activerecord-spatialite-adapter 0.2.3 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.rdoc +8 -0
- data/README.rdoc +97 -44
- data/Version +1 -1
- data/lib/active_record/connection_adapters/spatialite_adapter.rb +23 -426
- data/lib/active_record/connection_adapters/spatialite_adapter/arel_tosql.rb +61 -0
- data/lib/{rgeo/active_record → active_record/connection_adapters}/spatialite_adapter/databases.rake +1 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/main_adapter.rb +234 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/native_format_parser.rb +163 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/railtie.rb +64 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/spatial_column.rb +135 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/spatial_table_definition.rb +102 -0
- data/lib/active_record/connection_adapters/spatialite_adapter/version.rb +63 -0
- data/lib/rgeo/active_record/spatialite_adapter/railtie.rb +2 -21
- data/test/tc_basic.rb +55 -21
- data/test/tc_spatial_queries.rb +165 -0
- metadata +20 -11
@@ -0,0 +1,61 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# SpatiaLite adapter for ActiveRecord
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
# :stopdoc:
|
38
|
+
|
39
|
+
module Arel
|
40
|
+
module Visitors
|
41
|
+
|
42
|
+
class SpatiaLite < SQLite
|
43
|
+
|
44
|
+
FUNC_MAP = {
|
45
|
+
'st_wkttosql' => 'GeomFromText',
|
46
|
+
}
|
47
|
+
|
48
|
+
include ::RGeo::ActiveRecord::SpatialToSql
|
49
|
+
|
50
|
+
def st_func(standard_name_)
|
51
|
+
FUNC_MAP[standard_name_.downcase] || standard_name_
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
VISITORS['spatialite'] = ::Arel::Visitors::SpatiaLite
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# :startdoc:
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# SpatiaLite adapter for ActiveRecord
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
# :stopdoc:
|
38
|
+
|
39
|
+
module ActiveRecord
|
40
|
+
|
41
|
+
module ConnectionAdapters
|
42
|
+
|
43
|
+
module SpatiaLiteAdapter
|
44
|
+
|
45
|
+
|
46
|
+
class MainAdapter < SQLite3Adapter
|
47
|
+
|
48
|
+
|
49
|
+
@@native_database_types = nil
|
50
|
+
|
51
|
+
|
52
|
+
def adapter_name
|
53
|
+
SpatiaLiteAdapter::ADAPTER_NAME
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def spatial_column_constructor(name_)
|
58
|
+
::RGeo::ActiveRecord::DEFAULT_SPATIAL_COLUMN_CONSTRUCTORS[name_]
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
def native_database_types
|
63
|
+
@@native_database_types ||= super.merge(:spatial => {:name => 'geometry'})
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
def spatialite_version
|
68
|
+
@spatialite_version ||= SQLiteAdapter::Version.new(select_value('SELECT spatialite_version()'))
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def srs_database_columns
|
73
|
+
{:name_column => 'ref_sys_name', :proj4text_column => 'proj4text', :auth_name_column => 'auth_name', :auth_srid_column => 'auth_srid'}
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
def quote(value_, column_=nil)
|
78
|
+
if ::RGeo::Feature::Geometry.check_type(value_)
|
79
|
+
"GeomFromWKB(X'#{::RGeo::WKRep::WKBGenerator.new(:hex_format => true).generate(value_)}', #{value_.srid})"
|
80
|
+
else
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
def columns(table_name_, name_=nil) #:nodoc:
|
87
|
+
spatial_info_ = spatial_column_info(table_name_)
|
88
|
+
table_structure(table_name_).map do |field_|
|
89
|
+
col_ = SpatialColumn.new(field_['name'], field_['dflt_value'], field_['type'], field_['notnull'].to_i == 0)
|
90
|
+
info_ = spatial_info_[field_['name']]
|
91
|
+
if info_
|
92
|
+
col_.set_srid(info_[:srid])
|
93
|
+
end
|
94
|
+
col_
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def indexes(table_name_, name_=nil)
|
100
|
+
results_ = super.map do |index_|
|
101
|
+
::RGeo::ActiveRecord::SpatialIndexDefinition.new(index_.table, index_.name, index_.unique, index_.columns, index_.lengths)
|
102
|
+
end
|
103
|
+
table_name_ = table_name_.to_s
|
104
|
+
names_ = select_values("SELECT name FROM sqlite_master WHERE type='table' AND name LIKE 'idx_#{quote_string(table_name_)}_%' AND rootpage=0") || []
|
105
|
+
results_ + names_.map do |n_|
|
106
|
+
col_name_ = n_.sub("idx_#{table_name_}_", '')
|
107
|
+
::RGeo::ActiveRecord::SpatialIndexDefinition.new(table_name_, n_, false, [col_name_], [], true)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
def create_table(table_name_, options_={})
|
113
|
+
table_name_ = table_name_.to_s
|
114
|
+
table_definition_ = SpatialTableDefinition.new(self)
|
115
|
+
table_definition_.primary_key(options_[:primary_key] || ::ActiveRecord::Base.get_primary_key(table_name_.singularize)) unless options_[:id] == false
|
116
|
+
yield table_definition_ if block_given?
|
117
|
+
if options_[:force] && table_exists?(table_name_)
|
118
|
+
drop_table(table_name_, options_)
|
119
|
+
end
|
120
|
+
|
121
|
+
create_sql_ = "CREATE#{' TEMPORARY' if options_[:temporary]} TABLE "
|
122
|
+
create_sql_ << "#{quote_table_name(table_name_)} ("
|
123
|
+
create_sql_ << table_definition_.to_sql
|
124
|
+
create_sql_ << ") #{options_[:options]}"
|
125
|
+
execute create_sql_
|
126
|
+
|
127
|
+
table_definition_.spatial_columns.each do |col_|
|
128
|
+
execute("SELECT AddGeometryColumn('#{quote_string(table_name_)}', '#{quote_string(col_.name.to_s)}', #{col_.srid}, '#{quote_string(col_.spatial_type.gsub('_','').upcase)}', 'XY', #{col_.null ? 0 : 1})")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
def drop_table(table_name_, options_={})
|
134
|
+
indexes(table_name_).each do |index_|
|
135
|
+
remove_index(table_name_, :spatial => true, :column => index_.columns[0]) if index_.spatial
|
136
|
+
end
|
137
|
+
execute("DELETE from geometry_columns where f_table_name='#{quote_string(table_name_.to_s)}'")
|
138
|
+
super
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
def add_column(table_name_, column_name_, type_, options_={})
|
143
|
+
if (info_ = spatial_column_constructor(type_.to_sym))
|
144
|
+
limit_ = options_[:limit]
|
145
|
+
options_.merge!(limit_) if limit_.is_a?(::Hash)
|
146
|
+
type_ = (options_[:type] || info_[:type] || type_).to_s.gsub('_', '').upcase
|
147
|
+
execute("SELECT AddGeometryColumn('#{quote_string(table_name_.to_s)}', '#{quote_string(column_name_.to_s)}', #{options_[:srid].to_i}, '#{quote_string(type_.to_s)}', 'XY', #{options_[:null] == false ? 0 : 1})")
|
148
|
+
else
|
149
|
+
super
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
def add_index(table_name_, column_name_, options_={})
|
155
|
+
if options_[:spatial]
|
156
|
+
column_name_ = column_name_.first if column_name_.kind_of?(::Array) && column_name_.size == 1
|
157
|
+
table_name_ = table_name_.to_s
|
158
|
+
column_name_ = column_name_.to_s
|
159
|
+
spatial_info_ = spatial_column_info(table_name_)
|
160
|
+
unless spatial_info_[column_name_]
|
161
|
+
raise ::ArgumentError, "Can't create spatial index because column '#{column_name_}' in table '#{table_name_}' is not a geometry column"
|
162
|
+
end
|
163
|
+
result_ = select_value("SELECT CreateSpatialIndex('#{quote_string(table_name_)}', '#{quote_string(column_name_)}')").to_i
|
164
|
+
if result_ == 0
|
165
|
+
raise ::ArgumentError, "Spatial index already exists on table '#{table_name_}', column '#{column_name_}'"
|
166
|
+
end
|
167
|
+
result_
|
168
|
+
else
|
169
|
+
super
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
def remove_index(table_name_, options_={})
|
175
|
+
if options_[:spatial]
|
176
|
+
table_name_ = table_name_.to_s
|
177
|
+
column_ = options_[:column]
|
178
|
+
if column_
|
179
|
+
column_ = column_[0] if column_.kind_of?(::Array)
|
180
|
+
column_ = column_.to_s
|
181
|
+
else
|
182
|
+
index_name_ = options_[:name]
|
183
|
+
unless index_name_
|
184
|
+
raise ::ArgumentError, "You need to specify a column or index name to remove a spatial index."
|
185
|
+
end
|
186
|
+
if index_name_ =~ /^idx_#{table_name_}_(\w+)$/
|
187
|
+
column_ = $1
|
188
|
+
else
|
189
|
+
raise ::ArgumentError, "Unknown spatial index name: #{index_name_.inspect}."
|
190
|
+
end
|
191
|
+
end
|
192
|
+
spatial_info_ = spatial_column_info(table_name_)
|
193
|
+
unless spatial_info_[column_]
|
194
|
+
raise ::ArgumentError, "Can't remove spatial index because column '#{column_}' in table '#{table_name_}' is not a geometry column"
|
195
|
+
end
|
196
|
+
index_name_ = "idx_#{table_name_}_#{column_}"
|
197
|
+
has_index_ = select_value("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='#{quote_string(index_name_)}'").to_i > 0
|
198
|
+
unless has_index_
|
199
|
+
raise ::ArgumentError, "Spatial index not present on table '#{table_name_}', column '#{column_}'"
|
200
|
+
end
|
201
|
+
execute("SELECT DisableSpatialIndex('#{quote_string(table_name_)}', '#{quote_string(column_)}')")
|
202
|
+
execute("DROP TABLE #{quote_table_name(index_name_)}")
|
203
|
+
else
|
204
|
+
super
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
def spatial_column_info(table_name_)
|
210
|
+
info_ = execute("SELECT * FROM geometry_columns WHERE f_table_name='#{quote_string(table_name_.to_s)}'")
|
211
|
+
result_ = {}
|
212
|
+
info_.each do |row_|
|
213
|
+
result_[row_['f_geometry_column']] = {
|
214
|
+
:name => row_['f_geometry_column'],
|
215
|
+
:type => row_['type'],
|
216
|
+
:dimension => row_['coord_dimension'],
|
217
|
+
:srid => row_['srid'],
|
218
|
+
:has_index => row_['spatial_index_enabled'],
|
219
|
+
}
|
220
|
+
end
|
221
|
+
result_
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
# :startdoc:
|
@@ -0,0 +1,163 @@
|
|
1
|
+
# -----------------------------------------------------------------------------
|
2
|
+
#
|
3
|
+
# SpatiaLite adapter for ActiveRecord
|
4
|
+
#
|
5
|
+
# -----------------------------------------------------------------------------
|
6
|
+
# Copyright 2010 Daniel Azuma
|
7
|
+
#
|
8
|
+
# All rights reserved.
|
9
|
+
#
|
10
|
+
# Redistribution and use in source and binary forms, with or without
|
11
|
+
# modification, are permitted provided that the following conditions are met:
|
12
|
+
#
|
13
|
+
# * Redistributions of source code must retain the above copyright notice,
|
14
|
+
# this list of conditions and the following disclaimer.
|
15
|
+
# * Redistributions in binary form must reproduce the above copyright notice,
|
16
|
+
# this list of conditions and the following disclaimer in the documentation
|
17
|
+
# and/or other materials provided with the distribution.
|
18
|
+
# * Neither the name of the copyright holder, nor the names of any other
|
19
|
+
# contributors to this software, may be used to endorse or promote products
|
20
|
+
# derived from this software without specific prior written permission.
|
21
|
+
#
|
22
|
+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
23
|
+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
24
|
+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
25
|
+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
26
|
+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
27
|
+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
28
|
+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
29
|
+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
30
|
+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
31
|
+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
32
|
+
# POSSIBILITY OF SUCH DAMAGE.
|
33
|
+
# -----------------------------------------------------------------------------
|
34
|
+
;
|
35
|
+
|
36
|
+
|
37
|
+
module ActiveRecord
|
38
|
+
|
39
|
+
module ConnectionAdapters
|
40
|
+
|
41
|
+
module SpatiaLiteAdapter
|
42
|
+
|
43
|
+
|
44
|
+
# A utility class that parses the native (internal) SpatiaLite
|
45
|
+
# format. This is used to read and return an attribute value as an
|
46
|
+
# RGeo object.
|
47
|
+
|
48
|
+
class NativeFormatParser
|
49
|
+
|
50
|
+
|
51
|
+
# Create a parser that generates features using the given factory.
|
52
|
+
|
53
|
+
def initialize(factory_)
|
54
|
+
@factory = factory_
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
# Parse the given binary data and return an object.
|
59
|
+
# Raises ::RGeo::Error::ParseError on failure.
|
60
|
+
|
61
|
+
def parse(data_)
|
62
|
+
@little_endian = data_[1,1] == "\x01"
|
63
|
+
srid_ = data_[2,4].unpack(@little_endian ? 'V' : 'N').first
|
64
|
+
begin
|
65
|
+
_start_scanner(data_)
|
66
|
+
obj_ = _parse_object(false)
|
67
|
+
_get_byte(0xfe)
|
68
|
+
ensure
|
69
|
+
_clean_scanner
|
70
|
+
end
|
71
|
+
obj_
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
def _parse_object(contained_) # :nodoc:
|
76
|
+
_get_byte(contained_ ? 0x69 : 0x7c)
|
77
|
+
type_code_ = _get_integer
|
78
|
+
case type_code_
|
79
|
+
when 1
|
80
|
+
coords_ = _get_doubles(2)
|
81
|
+
@factory.point(*coords_)
|
82
|
+
when 2
|
83
|
+
_parse_line_string
|
84
|
+
when 3
|
85
|
+
interior_rings_ = (1.._get_integer).map{ _parse_line_string }
|
86
|
+
exterior_ring_ = interior_rings_.shift || @factory.linear_ring([])
|
87
|
+
@factory.polygon(exterior_ring_, interior_rings_)
|
88
|
+
when 4
|
89
|
+
@factory.multi_point((1.._get_integer).map{ _parse_object(1) })
|
90
|
+
when 5
|
91
|
+
@factory.multi_line_string((1.._get_integer).map{ _parse_object(2) })
|
92
|
+
when 6
|
93
|
+
@factory.multi_polygon((1.._get_integer).map{ _parse_object(3) })
|
94
|
+
when 7
|
95
|
+
@factory.collection((1.._get_integer).map{ _parse_object(true) })
|
96
|
+
else
|
97
|
+
raise ::RGeo::Error::ParseError, "Unknown type value: #{type_code_}."
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
def _parse_line_string # :nodoc:
|
103
|
+
count_ = _get_integer
|
104
|
+
coords_ = _get_doubles(2 * count_)
|
105
|
+
@factory.line_string((0...count_).map{ |i_| @factory.point(*coords_[2*i_,2]) })
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
def _start_scanner(data_) # :nodoc:
|
110
|
+
@_data = data_
|
111
|
+
@_len = data_.length
|
112
|
+
@_pos = 38
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
def _clean_scanner # :nodoc:
|
117
|
+
@_data = nil
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def _get_byte(expect_=nil) # :nodoc:
|
122
|
+
if @_pos + 1 > @_len
|
123
|
+
raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill 1 byte"
|
124
|
+
end
|
125
|
+
str_ = @_data[@_pos, 1]
|
126
|
+
@_pos += 1
|
127
|
+
val_ = str_.unpack("C").first
|
128
|
+
if expect_ && expect_ != val_
|
129
|
+
raise ::RGeo::Error::ParseError, "Expected byte 0x#{expect_.to_s(16)} but got 0x#{val_.to_s(16)}"
|
130
|
+
end
|
131
|
+
val_
|
132
|
+
end
|
133
|
+
|
134
|
+
|
135
|
+
def _get_integer # :nodoc:
|
136
|
+
if @_pos + 4 > @_len
|
137
|
+
raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill 1 integer"
|
138
|
+
end
|
139
|
+
str_ = @_data[@_pos, 4]
|
140
|
+
@_pos += 4
|
141
|
+
str_.unpack("#{@little_endian ? 'V' : 'N'}").first
|
142
|
+
end
|
143
|
+
|
144
|
+
|
145
|
+
def _get_doubles(count_) # :nodoc:
|
146
|
+
len_ = 8 * count_
|
147
|
+
if @_pos + len_ > @_len
|
148
|
+
raise ::RGeo::Error::ParseError, "Not enough bytes left to fulfill #{count_} doubles"
|
149
|
+
end
|
150
|
+
str_ = @_data[@_pos, len_]
|
151
|
+
@_pos += len_
|
152
|
+
str_.unpack("#{@little_endian ? 'E' : 'G'}*")
|
153
|
+
end
|
154
|
+
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
end
|
160
|
+
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|