Class: ActiveRecord::ConnectionAdapters::SpatiaLiteAdapter::NativeFormatParser
- Inherits:
-
Object
- Object
- ActiveRecord::ConnectionAdapters::SpatiaLiteAdapter::NativeFormatParser
- Defined in:
- lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb
Overview
A utility class that parses the native (internal) SpatiaLite format. This is used to read and return an attribute value as an RGeo object.
Instance Method Summary collapse
-
#_clean_scanner ⇒ Object
:nodoc:.
-
#_get_byte(expect_ = nil) ⇒ Object
:nodoc:.
-
#_get_doubles(count_) ⇒ Object
:nodoc:.
-
#_get_integer ⇒ Object
:nodoc:.
-
#_parse_line_string ⇒ Object
:nodoc:.
-
#_parse_object(contained_) ⇒ Object
:nodoc:.
-
#_start_scanner(data_) ⇒ Object
:nodoc:.
-
#initialize(factory_) ⇒ NativeFormatParser
constructor
Create a parser that generates features using the given factory.
-
#parse(data_) ⇒ Object
Parse the given binary data and return an object.
Constructor Details
#initialize(factory_) ⇒ NativeFormatParser
Create a parser that generates features using the given factory.
53 54 55 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 53 def initialize(factory_) @factory = factory_ end |
Instance Method Details
#_clean_scanner ⇒ Object
:nodoc:
119 120 121 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 119 def _clean_scanner # :nodoc: @_data = nil end |
#_get_byte(expect_ = nil) ⇒ Object
:nodoc:
124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 124 def _get_byte(expect_=nil) # :nodoc: if @_pos + 1 > @_len raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill 1 byte" end str_ = @_data[@_pos, 1] @_pos += 1 val_ = str_.unpack("C").first if expect_ && expect_ != val_ raise ::RGeo::Error::ParseError, "Expected byte 0x#{expect_.to_s(16)} but got 0x#{val_.to_s(16)}" end val_ end |
#_get_doubles(count_) ⇒ Object
:nodoc:
148 149 150 151 152 153 154 155 156 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 148 def _get_doubles(count_) # :nodoc: len_ = 8 * count_ if @_pos + len_ > @_len raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill #{count_} doubles" end str_ = @_data[@_pos, len_] @_pos += len_ str_.unpack("#{@little_endian ? 'E' : 'G'}*") end |
#_get_integer ⇒ Object
:nodoc:
138 139 140 141 142 143 144 145 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 138 def _get_integer # :nodoc: if @_pos + 4 > @_len raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill 1 integer" end str_ = @_data[@_pos, 4] @_pos += 4 str_.unpack("#{@little_endian ? 'V' : 'N'}").first end |
#_parse_line_string ⇒ Object
:nodoc:
105 106 107 108 109 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 105 def _parse_line_string # :nodoc: count_ = _get_integer coords_ = _get_doubles(2 * count_) @factory.line_string((0...count_).map{ |i_| @factory.point(*coords_[2*i_,2]) }) end |
#_parse_object(contained_) ⇒ Object
:nodoc:
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 78 def _parse_object(contained_) # :nodoc: _get_byte(contained_ ? 0x69 : 0x7c) type_code_ = _get_integer case type_code_ when 1 coords_ = _get_doubles(2) @factory.point(*coords_) when 2 _parse_line_string when 3 interior_rings_ = (1.._get_integer).map{ _parse_line_string } exterior_ring_ = interior_rings_.shift || @factory.linear_ring([]) @factory.polygon(exterior_ring_, interior_rings_) when 4 @factory.multi_point((1.._get_integer).map{ _parse_object(1) }) when 5 @factory.multi_line_string((1.._get_integer).map{ _parse_object(2) }) when 6 @factory.multi_polygon((1.._get_integer).map{ _parse_object(3) }) when 7 @factory.collection((1.._get_integer).map{ _parse_object(true) }) else raise ::RGeo::Error::ParseError, "Unknown type value: #{type_code_}." end end |
#_start_scanner(data_) ⇒ Object
:nodoc:
112 113 114 115 116 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 112 def _start_scanner(data_) # :nodoc: @_data = data_ @_len = data_.length @_pos = 38 end |
#parse(data_) ⇒ Object
Parse the given binary data and return an object. Raises ::RGeo::Error::ParseError on failure.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb', line 61 def parse(data_) if data_[0,1] =~ /[0-9a-fA-F]/ data_ = [data_].pack('H*') end @little_endian = data_[1,1] == "\x01" srid_ = data_[2,4].unpack(@little_endian ? 'V' : 'N').first begin _start_scanner(data_) obj_ = _parse_object(false) _get_byte(0xfe) ensure _clean_scanner end obj_ end |