Here is a RubyLanguage version of the QueryStringParserTranslations. (See also CommentingChallengeResponsePartTwo).
There are some minor interface changes in the Ruby version. The public methods are parse_stream(input_stream) and parse_string(string) with the obvious semantics. Since we don't require the use of a stream, we can toss out the initialization. It also means the parser object can be reused to parse multiple strings or streams.
This code was written from scratch, rather than trying to translate either the Java or Python versions. I did use the unit tests from CommentingChallengeResponse. With the exception of one of the degenerate cases, this parser passes all the unit tests found there. The one exception is that I chose to parse "name%=value" as {'name' => 'value'} rather than {'namealue' => ''} in the testDegenerate_MissingHexDigitsBeforeValue test.
-- JimWeirich
Here is the code.
class QueryStringParser def parse_stream(input) lines = input.readlines.collect { |line| line.chomp } parse_string(lines.join('&')) end def parse_string(string) hash = Hash.new string.split('&').each { |pair| key, value = pair.split('=', 2) hash[normalize(key)] = normalize(value) } hash end private def normalize(str) return "" if str.nil? str = replace_pluses_with_spaces(str) return replace_hex_encodings(str) end def replace_pluses_with_spaces(str) str.gsub(/\+/, ' ') end def replace_hex_encodings(str) str.gsub(/%(.{0,2})/) { |hex| digits = $1 if digits =~ /[0-9A-Fa-f]{2}/ digits.hex.chr else '' end } end end
Jim,
What do the ||| characters mean? e.g. |hex| |line| |pair|
-- SteveHowell
Ruby syntax for parameters to a block.
{ |a, b| self.doSomethingWith(a, b) }would be not-quite-equivalent-but-pretty-close to Python's
lambda a, b: self.doSomethingWith(a, b)