Reputation: 23
Im trying to implement base64 coding in a very simple way. In my approach (lets for a second put away whether its appropriate or not) I need to reverse strings and then concate them. After that this concated string is used in substring function. Strings are joined properly but when I use substring basex seems to lose it.
Funny thing is substring works for well for all indexes starting at 8. So substring($string, 1, 8) and higher gives correct output. But everything below that is messed up. Starting with one disappeared number: substring($string, 1, 7 (and below) ) results in 6 length string. Moreover substring can start only with 1st or 0 index. Anything greater results in empty return.
declare variable $array := []; declare function bs:encode ( $input as xs:string ) { bs:integer-to-binary(string-to-codepoints($input), "", $array) } ; declare function bs:integer-to-binary ( $input as xs:integer*, $string as xs:string, $array as array(xs:string) ) { let $strings := for $i in $input return if ($i != 0) then if ($i mod 2 = 0) then bs:integer-to-binary(xs:integer($i div 2), concat($string, 0), $array) else bs:integer-to-binary(xs:integer($i div 2), concat($string, 1), $array) else if ($i <= 0) then array:append($array, $string) return bs:check-if-eight($strings) } ; declare function bs:check-if-eight ( $strings as item()+ ) { let $fullBinary := for $string in $strings return if (string-length($string) < 8) then bs:check-if-eight(concat($string, 0)) else $string (: add as private below :) return bs:concat-strings($fullBinary) } ; declare function bs:concat-strings ( $strings as item()+ ) { let $firstStringToConcat := functx:reverse-string($strings[position() = 1]) let $secondStringToConcat := functx:reverse-string($strings[position() = 2]) let $thirdStringToConcat := functx:reverse-string($strings[position() = 3]) let $concat := concat ($firstStringToConcat, $secondStringToConcat, $thirdStringToConcat) (: this returns correct string of binary value for Cat word :) return bs:divide-into-six($concat) } ; declare function bs:divide-into-six ( $binaryString as xs:string) { let $sixBitString := substring($binaryString, 1, 6) (: this should return 010000 instead i get 000100 which is not even in $binaryString at all :) return $sixBitString } ; bs:encode("Cat")
I expect first six letters from string (010000) instead I get some random sequence I guess (00100). The whole module is meant to encode strings into base64 format but for now (the part i uploaded) should just throw first six bits for 'C'
Upvotes: 1
Views: 199
Reputation: 23
Alright so I figured it out I guess.
First of all in function concat-strings I changed concat to fn:string-join. It allowed me to pass as an argument symbol that separates joined strings.
declare function bs:concat-strings ( $strings as item()+ ) { let $firstStringToConcat := xs:string(functx:reverse-string($strings[position() = 1])) let $secondStringToConcat := xs:string(functx:reverse-string($strings[position() = 2])) let $thirdStringToConcat := xs:string(functx:reverse-string($strings[position() = 3])) let $concat := ****fn:string-join(**** ($firstStringToConcat, $secondStringToConcat, $thirdStringToConcat),****'X'****) return bs:divide-into-six($concat) } ;
I saw that my input looked like this: XXXXXXXX01000011XXXXXXXXXXXXXXXXX01100001XXXXXXXXXXXXXXXXX01110100XXXXXXXX
Obviously it had to looping somewhere without clear for loop and as I novice to Xquery i must have been missed that. And indeed. I found it in check-if-eight function:
> declare function bs:check-if-eight ( $strings as item()+ ) { > **let $fullBinary :=** > for $string in $strings > return if (string-length($string) < 8) > then bs:check-if-eight(concat($string, 0)) > else $string (: add as private below :) > **return bs:concat-strings($fullBinary)** } ;
Despite being above FOR keyword, $fullBinary variable was in a loop and produced empty spaces(?) and it was clearly shown when i used X as a separator. DISCLAIMER: I thought about this before and used functx:trim but for some reason it doesnt work like I expected. So it might not for you too if having similar issue.
At this point it was clear that let $fullBinary cannot be bided in FLWR statement at least can't trigger concat-strings function. I changed it and now it produces only string and now im trying to figure out new sequence of running whole module but I think the main problem here is solved.
Upvotes: 0