Class: Sequel::Postgres::PGArray::Parser
- Defined in:
- lib/sequel/extensions/pg_array.rb
Overview
PostgreSQL array parser that handles both text and numeric input. Because PostgreSQL arrays can contain objects that can be literalized in any number of ways, it is not possible to make a fully generic parser.
This parser is very simple and unoptimized, but should still be O(n) where n is the length of the input string.
Instance Attribute Summary collapse
-
#pos ⇒ Object
readonly
Returns the value of attribute pos.
Instance Method Summary collapse
-
#initialize(source, converter = nil) ⇒ Parser
constructor
Set the source for the input, and any converter callable to call with objects to be created.
-
#new_entry(include_empty = false) ⇒ Object
Take the buffer of recorded characters and add it to the array of entries, and use a new buffer for recorded characters.
-
#next_char ⇒ Object
Return 2 objects, whether the next character in the input was escaped with a backslash, and what the next character is.
-
#parse(nested = false) ⇒ Object
Parse the input character by character, returning an array of parsed (and potentially converted) objects.
-
#record(c) ⇒ Object
Add a new character to the buffer of recorded characters.
Constructor Details
#initialize(source, converter = nil) ⇒ Parser
Set the source for the input, and any converter callable to call with objects to be created. For nested parsers the source may contain text after the end current parse, which will be ignored.
187 188 189 190 191 192 193 194 195 |
# File 'lib/sequel/extensions/pg_array.rb', line 187 def initialize(source, converter=nil) @source = source @source_length = source.length @converter = converter @pos = -1 @entries = [] @recorded = "" @dimension = 0 end |
Instance Attribute Details
#pos ⇒ Object (readonly)
Returns the value of attribute pos.
181 182 183 |
# File 'lib/sequel/extensions/pg_array.rb', line 181 def pos @pos end |
Instance Method Details
#new_entry(include_empty = false) ⇒ Object
Take the buffer of recorded characters and add it to the array of entries, and use a new buffer for recorded characters.
216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/sequel/extensions/pg_array.rb', line 216 def new_entry(include_empty=false) if !@recorded.empty? || include_empty entry = @recorded if entry == NULL && !include_empty entry = nil elsif @converter entry = @converter.call(entry) end @entries.push(entry) @recorded = "" end end |
#next_char ⇒ Object
Return 2 objects, whether the next character in the input was escaped with a backslash, and what the next character is.
199 200 201 202 203 204 205 206 207 |
# File 'lib/sequel/extensions/pg_array.rb', line 199 def next_char @pos += 1 if (c = @source[@pos..@pos]) == BACKSLASH @pos += 1 [true, @source[@pos..@pos]] else [false, c] end end |
#parse(nested = false) ⇒ Object
Parse the input character by character, returning an array of parsed (and potentially converted) objects.
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/sequel/extensions/pg_array.rb', line 231 def parse(nested=false) # quote sets whether we are inside of a quoted string. quote = false until @pos >= @source_length escaped, char = next_char if char == OPEN_BRACE && !quote @dimension += 1 if (@dimension > 1) # Multi-dimensional array encounter, use a subparser # to parse the next level down. subparser = self.class.new(@source[@pos..-1], @converter) @entries.push(subparser.parse(true)) @pos += subparser.pos - 1 end elsif char == CLOSE_BRACE && !quote @dimension -= 1 if (@dimension == 0) new_entry # Exit early if inside a subparser, since the # text after parsing the current level should be # ignored as it is handled by the parent parser. return @entries if nested end elsif char == QUOTE && !escaped # If already inside the quoted string, this is the # ending quote, so add the entry. Otherwise, this # is the opening quote, so set the quote flag. new_entry(true) if quote quote = !quote elsif char == COMMA && !quote # If not inside a string and a comma occurs, it indicates # the end of the entry, so add the entry. new_entry else # Add the character to the recorded character buffer. record(char) end end raise Sequel::Error, "array dimensions not balanced" unless @dimension == 0 @entries end |
#record(c) ⇒ Object
Add a new character to the buffer of recorded characters.
210 211 212 |
# File 'lib/sequel/extensions/pg_array.rb', line 210 def record(c) @recorded << c end |