sypex_geo 0.0.1 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0b509a171c46e45958ffd1cd999fd539e7d307e0
4
- data.tar.gz: 876b33e9d0a53db5826f9b7850dbdc66b5d616cd
3
+ metadata.gz: bb5f6cd269004ce0ac3ef7c190008ca0341cb219
4
+ data.tar.gz: b1fbd13bb57fc6fb0fff8c118d77719f5856ee38
5
5
  SHA512:
6
- metadata.gz: 2c6922ee63332e359bde80669f918627dfe196aa8cdf4a7b44c9014eaba363dcc6ae1a9e457e9313f0048ead8cd0b7f365f9ea0adf2b2b436eaa47a30daf308b
7
- data.tar.gz: 20b94c1123899ced1bbe980ed16cd9e3493237d1741957ae688f988db9e69b477898e4f28ad563f36fd5a0aaf07a9f1b265781a397a3f51ad49ad7ca244bf815
6
+ metadata.gz: 12c16308ea7729916da8279fa967669a6b9083b9c4d352e7156ca1aa36a13a64d1b23ca4fe80ca166f544e6195510cf31144046038255df078d71ca922a0be08
7
+ data.tar.gz: 9fac5ecb9febc9751efb7892a469ba92c0c2b97ab5839c60548cd2cc2fc5b833148408b7999861e88cf7bdd0dd20c865d580ea19cf891d7f5696a3e0d1e205b2
data/.gitignore CHANGED
@@ -1,8 +1,6 @@
1
1
  *.gem
2
- pkg/
3
- .bundle
4
- .config
5
- Gemfile.lock
6
- coverage
7
- tmp
8
- *.bundle
2
+ /.bundle
3
+ /Gemfile.lock
4
+ /pkg
5
+ /tmp
6
+ /coverage
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
7
+
8
+ env:
9
+ - SYPEXGEO_CITY_MAX_DB=sypexgeo_city_max.dat
10
+
11
+ before_script:
12
+ - '[ -f sypexgeo_city_max.dat ] || (wget http://sypexgeo.net/files/SxGeoCityMax_utf8.zip && unzip SxGeoCityMax_utf8.zip && mv SxGeoCityMax.dat sypexgeo_city_max.dat)'
13
+
14
+ addons:
15
+ code_climate:
16
+ repo_token: 15e49d47a87a130d4a3cde0bb2ce14fe9053f525e92495a215027aff3e552368
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Gem Version](https://badge.fury.io/rb/sypex_geo.svg)](http://badge.fury.io/rb/sypex_geo)
2
+
1
3
  # SypexGeo
2
4
 
3
5
  [Sypex Geo IP database](http://sypexgeo.net) adapter for Ruby.
@@ -12,19 +14,92 @@ And then execute:
12
14
 
13
15
  $ bundle
14
16
 
15
- Or install it yourself as:
17
+ ## Usage
16
18
 
17
- $ gem install sypex_geo
19
+ ```ruby
20
+ require 'sypex_geo'
18
21
 
19
- ## Usage
22
+ db = SypexGeo::Database.new('./sypex_geo_city_max.dat')
23
+ db.lookup(<IPv4 address>)
24
+ # => {
25
+ # city: {
26
+ # id: 524901,
27
+ # lat: 55,
28
+ # lon: 37,
29
+ # name_ru: 'Москва',
30
+ # name_en: 'Moscow',
31
+ # okato: '45'
32
+ # },
33
+ # country: {
34
+ # id: 185,
35
+ # iso: 'RU'
36
+ # },
37
+ # region: nil
38
+ # }
20
39
 
21
- require 'sypex_geo'
40
+ # Query details.
41
+ db.lookup(<IPv4 address>, true)
42
+ # => {
43
+ # city: {
44
+ # id: 524901,
45
+ # lat: 55,
46
+ # lon: 37,
47
+ # name_ru: 'Москва',
48
+ # name_en: 'Moscow',
49
+ # okato: '45'
50
+ # },
51
+ # region: {
52
+ # id: 524894,
53
+ # name_ru: 'Москва',
54
+ # name_en: 'Moskva',
55
+ # lat: 55,
56
+ # lon: 37,
57
+ # iso: 'RU-MOW',
58
+ # timezone: 'Europe/Moscow',
59
+ # okato: '45'
60
+ # },
61
+ # country: {
62
+ # id: 185,
63
+ # iso: 'RU',
64
+ # continent: 'EU',
65
+ # lat: 60,
66
+ # lon: 100,
67
+ # name_ru: 'Россия',
68
+ # name_en: 'Russia',
69
+ # timezone: 'Europe/Moscow'
70
+ # }
71
+ # }
22
72
 
23
- db = SypexGeo::Database.new('./sypex_geo_city_max.dat')
24
- db.lookup(<IPv4 address>)
73
+ # "memory_mode"
74
+ db = SypexGeo::MemoryDatabase.new('./sypex_geo_city_max.dat')
75
+ db.lookup(<IPv4 address>)
76
+ ```
25
77
 
26
- ## License
78
+ ## Testing
79
+
80
+ $ SYPEXGEO_CITY_MAX_DB=./sypexgeo_city_max.dat rspec
27
81
 
28
- Licensed under the MIT License
82
+ ## License
29
83
 
30
84
  Copyright (c) 2014 Kolesnikov Danil
85
+
86
+ MIT License
87
+
88
+ Permission is hereby granted, free of charge, to any person obtaining
89
+ a copy of this software and associated documentation files (the
90
+ "Software"), to deal in the Software without restriction, including
91
+ without limitation the rights to use, copy, modify, merge, publish,
92
+ distribute, sublicense, and/or sell copies of the Software, and to
93
+ permit persons to whom the Software is furnished to do so, subject to
94
+ the following conditions:
95
+
96
+ The above copyright notice and this permission notice shall be
97
+ included in all copies or substantial portions of the Software.
98
+
99
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
100
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
101
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
102
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
103
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
104
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
105
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,163 @@
1
+ require 'ipaddr'
2
+
3
+ module SypexGeo
4
+ class DatabaseError < StandardError
5
+ end
6
+
7
+ class Database
8
+ attr_reader :version
9
+
10
+ def initialize(path)
11
+ @file = File.open(path, 'rb')
12
+
13
+ setup!
14
+ end
15
+
16
+ def lookup(ip, full = false)
17
+ if seek = search(ip)
18
+ read_location(seek, full)
19
+ end
20
+ end
21
+
22
+ def inspect
23
+ "#<#{self.class}:0x#{object_id} @version=#{@version}>"
24
+ end
25
+
26
+ protected
27
+
28
+ def setup!
29
+ if header = @file.read(40)
30
+ id, @version, @time, @type, @charset,
31
+ @b_idx_len, @m_idx_len, @range, @db_items, @id_len,
32
+ @max_region, @max_city, @region_size, @city_size,
33
+ @max_country, @country_size,
34
+ @pack_size = header.unpack('a3CNCCCnnNCnnNNnNn')
35
+ end
36
+
37
+ raise DatabaseError.new, 'Wrong file format' unless id == 'SxG'
38
+
39
+ @pack = @file.read(@pack_size).split("\0")
40
+ @b_idx_arr = @file.read(@b_idx_len * 4).unpack('N*')
41
+ @m_idx_arr = @file.read(@m_idx_len * 4).scan(/.{1,4}/m)
42
+
43
+ @block_len = 3 + @id_len
44
+ @db_begin = @file.tell
45
+ @regions_begin = @db_begin + @db_items * @block_len
46
+ @cities_begin = @regions_begin + @region_size
47
+ end
48
+
49
+ def search(ip)
50
+ ip1n = ip.to_i
51
+
52
+ return if ip1n == 0 or ip1n == 127 or ip1n >= 224
53
+
54
+ ipn = IPAddr.new(ip).hton
55
+ blocks_min, blocks_max = @b_idx_arr[ip1n - 1], @b_idx_arr[ip1n]
56
+
57
+ if blocks_max - blocks_min > @range
58
+ part = search_idx(ipn, blocks_min / @range, (blocks_max / @range) - 1)
59
+ min = part > 0 ? part * @range : 0
60
+ max = part > @m_idx_len ? @db_items : (part + 1) * @range
61
+ min = blocks_min if min < blocks_min
62
+ max = blocks_max if max > blocks_max
63
+ else
64
+ min = blocks_min
65
+ max = blocks_max
66
+ end
67
+
68
+ search_db(ipn, min, max)
69
+ end
70
+
71
+ def search_idx(ipn, min, max)
72
+ idx = @m_idx_arr
73
+
74
+ while max - min > 8
75
+ offset = (min + max) >> 1
76
+
77
+ if ipn > idx[offset]
78
+ min = offset
79
+ else
80
+ max = offset
81
+ end
82
+ end
83
+
84
+ while ipn > idx[min]
85
+ break if min >= max
86
+ min += 1
87
+ end
88
+
89
+ min
90
+ end
91
+
92
+ def search_db(ipn, min, max)
93
+ len = max - min
94
+ @file.pos = @db_begin + min * @block_len
95
+ search_db_chunk(@file.read(len * @block_len), ipn, 0, len - 1)
96
+ end
97
+
98
+ def search_db_chunk(data, ipn, min, max)
99
+ block_len = @block_len
100
+
101
+ if max - min > 1
102
+ ipn = ipn[1, 3]
103
+
104
+ while max - min > 8
105
+ offset = (min + max) >> 1
106
+
107
+ if ipn > data[offset * block_len, 3]
108
+ min = offset
109
+ else
110
+ max = offset
111
+ end
112
+ end
113
+
114
+ while ipn >= data[min * block_len, 3]
115
+ min += 1
116
+ break if min >= max
117
+ end
118
+ else
119
+ min += 1
120
+ end
121
+
122
+ data[min * block_len - @id_len, @id_len].unpack('H*').first.hex
123
+ end
124
+
125
+ def read_data(seek, limit, type)
126
+ @file.pos = (type == TYPE_REGION ? @regions_begin : @cities_begin) + seek
127
+ Pack.parse(@pack[type], @file.read(limit))
128
+ end
129
+
130
+ def read_country(seek)
131
+ read_data(seek, @max_country, TYPE_COUNTRY)
132
+ end
133
+
134
+ def read_region(seek)
135
+ read_data(seek, @max_region, TYPE_REGION)
136
+ end
137
+
138
+ def read_city(seek)
139
+ read_data(seek, @max_city, TYPE_CITY)
140
+ end
141
+
142
+ def read_location(seek, full = false)
143
+ region = nil
144
+ city = nil
145
+ country = nil
146
+
147
+ if seek < @country_size
148
+ country = read_country(seek)
149
+ elsif city = read_city(seek)
150
+ region_seek = city.delete(:region_seek)
151
+ country_id = city.delete(:country_id)
152
+ country = { id: country_id, iso: COUNTRY_CODES[country_id - 1] }
153
+ end
154
+
155
+ if full and region_seek
156
+ region = read_region(region_seek)
157
+ country = read_country(region.delete(:country_seek))
158
+ end
159
+
160
+ { city: city, region: region, country: country }
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,20 @@
1
+ module SypexGeo
2
+ class MemoryDatabase < Database
3
+ def setup!
4
+ super
5
+
6
+ @db = @file.read(@db_items * @block_len)
7
+ @regions_db = @file.read(@region_size) if @region_size > 0
8
+ @cities_db = @file.read(@city_size) if @city_size > 0
9
+ end
10
+
11
+ def search_db(ipn, min, max)
12
+ search_db_chunk(@db, ipn, min, max)
13
+ end
14
+
15
+ def read_data(seek, limit, type)
16
+ raw = (type == TYPE_REGION ? @regions_db : @cities_db)[seek, limit]
17
+ Pack.parse(@pack[type], raw)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ module SypexGeo
2
+ module Pack
3
+ def self.parse(pack, data)
4
+ result = {}
5
+ pos = 0
6
+
7
+ pack.split('/').each do |p|
8
+ type, name = p.split(':')
9
+
10
+ if data.nil? or data.empty?
11
+ val = type[0] =~ /b|c/ ? '' : 0
12
+ else
13
+ if type[0] == 'b'
14
+ len = data.index("\0", pos) - pos + 1
15
+ val = data[pos, len - 1].force_encoding('UTF-8')
16
+ else
17
+ len = type_length(type)
18
+ val = unpack(type, data[pos, len])
19
+ val = val[0] if val.is_a?(Array)
20
+ end
21
+
22
+ pos += len
23
+ end
24
+
25
+ result[name.to_sym] = val
26
+ end
27
+
28
+ result
29
+ end
30
+
31
+ protected
32
+
33
+ def self.type_length(type)
34
+ case type[0]
35
+ when /t|T/ then 1
36
+ when /s|S|n/ then 2
37
+ when /m|M/ then 3
38
+ when 'd' then 8
39
+ when 'c' then type[1..-1].to_i
40
+ else 4
41
+ end
42
+ end
43
+
44
+ def self.unpack(type, val)
45
+ case type[0]
46
+ when 't' then val.unpack('c')
47
+ when 'T' then val.unpack('C')
48
+ when 's' then val.unpack('s')
49
+ when 'S' then val.unpack('S')
50
+ when 'm' then (val + (val[2].ord >> 7) > 0 ? "\xFF" : "\0").unpack('l')
51
+ when 'M' then (val + "\0").unpack('L')
52
+ when 'i' then val.unpack('l')
53
+ when 'I' then val.unpack('L')
54
+ when 'f' then val.unpack('f')
55
+ when 'd' then val.unpack('d')
56
+ when 'n' then val.unpack('s')[0] / (10 ** type[1].to_i)
57
+ when 'N' then val.unpack('l')[0] / (10 ** type[1].to_i)
58
+ when 'c' then val.rstrip
59
+ end
60
+ end
61
+ end
62
+ end
@@ -1,3 +1,3 @@
1
1
  module SypexGeo
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
data/lib/sypex_geo.rb CHANGED
@@ -1,4 +1,6 @@
1
- require 'ipaddr'
1
+ require 'sypex_geo/database'
2
+ require 'sypex_geo/memory_database'
3
+ require 'sypex_geo/pack'
2
4
  require 'sypex_geo/version'
3
5
 
4
6
  module SypexGeo
@@ -19,243 +21,4 @@ module SypexGeo
19
21
  TR TT TV TW TZ UA UG UM US UY UZ VA VC VE VG VI VN VU WF WS YE YT RS ZA
20
22
  ZM ME ZW A1 A2 O1 AX GG IM JE BL MF
21
23
  ]
22
-
23
- class DatabaseError < StandardError
24
- end
25
-
26
- class Database
27
- attr_reader :version
28
-
29
- def initialize(path)
30
- @file = File.open(path, 'rb')
31
-
32
- setup!
33
- end
34
-
35
- def lookup(ip, full = false)
36
- if seek = search(ip)
37
- read_location(seek, full)
38
- end
39
- end
40
-
41
- def inspect
42
- "#<#{self.class}:0x#{object_id} @version=#{@version}>"
43
- end
44
-
45
- protected
46
-
47
- def setup!
48
- if header = @file.read(40)
49
- id, @version, @time, @type, @charset,
50
- @b_idx_len, @m_idx_len, @range, @db_items, @id_len,
51
- @max_region, @max_city, @region_size, @city_size,
52
- @max_country, @country_size,
53
- @pack_size = header.unpack('a3CNCCCnnNCnnNNnNn')
54
- end
55
-
56
- raise DatabaseError.new, 'Wrong file format' unless id == 'SxG'
57
-
58
- @pack = @file.read(@pack_size).split("\0")
59
- @b_idx_arr = @file.read(@b_idx_len * 4).unpack('N*')
60
- @m_idx_arr = @file.read(@m_idx_len * 4).scan(/.{1,4}/m)
61
-
62
- @block_len = 3 + @id_len
63
- @db_begin = @file.tell
64
- @regions_begin = @db_begin + @db_items * @block_len
65
- @cities_begin = @regions_begin + @region_size
66
- end
67
-
68
- def search(ip)
69
- ip1n = ip.to_i
70
-
71
- return if ip1n == 0 or ip1n == 127 or ip1n >= 224
72
-
73
- ipn = IPAddr.new(ip).hton
74
- blocks_min, blocks_max = @b_idx_arr[ip1n - 1], @b_idx_arr[ip1n]
75
-
76
- if blocks_max - blocks_min > @range
77
- part = search_idx(ipn, blocks_min / @range, (blocks_max / @range) - 1)
78
- min = part > 0 ? part * @range : 0
79
- max = part > @m_idx_len ? @db_items : (part + 1) * @range
80
- min = blocks_min if min < blocks_min
81
- max = blocks_max if max > blocks_max
82
- else
83
- min = blocks_min
84
- max = blocks_max
85
- end
86
-
87
- search_db(ipn, min, max)
88
- end
89
-
90
- def search_idx(ipn, min, max)
91
- idx = @m_idx_arr
92
-
93
- while max - min > 8
94
- offset = (min + max) >> 1
95
-
96
- if ipn > idx[offset]
97
- min = offset
98
- else
99
- max = offset
100
- end
101
- end
102
-
103
- while ipn > idx[min]
104
- break if min >= max
105
- min += 1
106
- end
107
-
108
- min
109
- end
110
-
111
- def search_db(ipn, min, max)
112
- len = max - min
113
- @file.pos = @db_begin + min * @block_len
114
- search_db_chunk(@file.read(len * @block_len), ipn, 0, len - 1)
115
- end
116
-
117
- def search_db_chunk(data, ipn, min, max)
118
- block_len = @block_len
119
-
120
- if max - min > 1
121
- ipn = ipn[1, 3]
122
-
123
- while max - min > 8
124
- offset = (min + max) >> 1
125
-
126
- if ipn > data[offset * block_len, 3]
127
- min = offset
128
- else
129
- max = offset
130
- end
131
- end
132
-
133
- while ipn >= data[min * block_len, 3]
134
- min += 1
135
- break if min >= max
136
- end
137
- else
138
- min += 1
139
- end
140
-
141
- data[min * block_len - @id_len, @id_len].unpack('H*').first.hex
142
- end
143
-
144
- def read_data(seek, limit, type)
145
- @file.pos = (type == TYPE_REGION ? @regions_begin : @cities_begin) + seek
146
- Pack.parse(@pack[type], @file.read(limit))
147
- end
148
-
149
- def read_country(seek)
150
- read_data(seek, @max_country, TYPE_COUNTRY)
151
- end
152
-
153
- def read_region(seek)
154
- read_data(seek, @max_region, TYPE_REGION)
155
- end
156
-
157
- def read_city(seek)
158
- read_data(seek, @max_city, TYPE_CITY)
159
- end
160
-
161
- def read_location(seek, full = false)
162
- region = nil
163
- city = nil
164
- country = nil
165
-
166
- if seek < @country_size
167
- country = read_country(seek)
168
- elsif city = read_city(seek)
169
- region_seek = city.delete(:region_seek)
170
- country_id = city.delete(:country_id)
171
- country = { id: country_id, iso: COUNTRY_CODES[country_id - 1] }
172
- end
173
-
174
- if full and region_seek
175
- region = read_region(region_seek)
176
- country = read_country(region.delete(:country_seek))
177
- end
178
-
179
- { city: city, region: region, country: country }
180
- end
181
- end
182
-
183
- class MemoryDatabase < Database
184
- def setup!
185
- super
186
-
187
- @db = @file.read(@db_items * @block_len)
188
- @regions_db = @file.read(@region_size) if @region_size > 0
189
- @cities_db = @file.read(@city_size) if @city_size > 0
190
- end
191
-
192
- def search_db(ipn, min, max)
193
- search_db_chunk(@db, ipn, min, max)
194
- end
195
-
196
- def read_data(seek, limit, type)
197
- raw = (type == TYPE_REGION ? @regions_db : @cities_db)[seek, limit]
198
- Pack.parse(@pack[type], raw)
199
- end
200
- end
201
-
202
- module Pack
203
- def self.parse(pack, data)
204
- result = {}
205
- pos = 0
206
-
207
- pack.split('/').each do |p|
208
- type, name = p.split(':')
209
-
210
- if data.nil? or data.empty?
211
- result[name] = type[0] =~ /b|c/ ? '' : 0
212
- else
213
- if type[0] == 'b'
214
- len = data.index("\0", pos) - pos
215
- val = data[pos, len].force_encoding('UTF-8')
216
- len += 1
217
- else
218
- len = type_length(type)
219
- val = unpack(type, data[pos, len])
220
- end
221
-
222
- result[name] = val.is_a?(Array) ? val[0] : val
223
- pos += len
224
- end
225
- end
226
-
227
- Hash[result.map{ |k, v| [ k.to_sym, v ] }]
228
- end
229
-
230
- protected
231
-
232
- def self.type_length(type)
233
- case type[0]
234
- when /t|T/ then 1
235
- when /s|S|n/ then 2
236
- when /m|M/ then 3
237
- when 'd' then 8
238
- when 'c' then type[1..-1].to_i
239
- else 4
240
- end
241
- end
242
-
243
- def self.unpack(type, val)
244
- case type[0]
245
- when 't' then val.unpack('c')
246
- when 'T' then val.unpack('C')
247
- when 's' then val.unpack('s')
248
- when 'S' then val.unpack('S')
249
- when 'm' then (val + (val[2].ord >> 7) > 0 ? "\xFF" : "\0").unpack('l')
250
- when 'M' then (val + "\0").unpack('L')
251
- when 'i' then val.unpack('l')
252
- when 'I' then val.unpack('L')
253
- when 'f' then val.unpack('f')
254
- when 'd' then val.unpack('d')
255
- when 'n' then val.unpack('s')[0] / (10 ** type[1].to_i)
256
- when 'N' then val.unpack('l')[0] / (10 ** type[1].to_i)
257
- when 'c' then val.rstrip
258
- end
259
- end
260
- end
261
24
  end
data/spec/spec_helper.rb CHANGED
@@ -1,7 +1,5 @@
1
- if ENV['SIMPLECOV']
2
- require 'simplecov'
3
- SimpleCov.start
4
- end
1
+ require 'codeclimate-test-reporter'
2
+ CodeClimate::TestReporter.start
5
3
 
6
4
  RSpec.configure do |config|
7
5
  config.order = 'random'
@@ -1,3 +1,4 @@
1
+ require './spec/spec_helper'
1
2
  require 'sypex_geo'
2
3
 
3
4
  describe SypexGeo do
data/sypex_geo.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ['kolesnikovde@gmail.com']
11
11
  spec.summary = 'Sypex Geo IP database adapter for Ruby.'
12
12
  spec.description = 'Sypex Geo IP database adapter for Ruby.'
13
- spec.homepage = ''
13
+ spec.homepage = 'https://github.com/kolesnikovde/sypex_geo'
14
14
  spec.license = 'MIT'
15
15
 
16
16
  spec.files = `git ls-files -z`.split("\x0")
@@ -18,6 +18,8 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^spec/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_development_dependency 'bundler', '~> 1.6'
22
- spec.add_development_dependency 'rake'
21
+ spec.add_development_dependency 'bundler', '~> 1'
22
+ spec.add_development_dependency 'rake', '~> 10'
23
+ spec.add_development_dependency 'rspec', '~> 3'
24
+ spec.add_development_dependency 'codeclimate-test-reporter'
23
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sypex_geo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kolesnikov Danil
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-08-14 00:00:00.000000000 Z
11
+ date: 2014-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,16 +16,44 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '1.6'
19
+ version: '1'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '1.6'
26
+ version: '1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: codeclimate-test-reporter
29
57
  requirement: !ruby/object:Gem::Requirement
30
58
  requirements:
31
59
  - - ">="
@@ -48,17 +76,20 @@ files:
48
76
  - ".editorconfig"
49
77
  - ".gitignore"
50
78
  - ".rspec"
79
+ - ".travis.yml"
51
80
  - Gemfile
52
- - LICENSE
53
81
  - README.md
54
82
  - Rakefile
55
83
  - lib/sypex_geo.rb
84
+ - lib/sypex_geo/database.rb
85
+ - lib/sypex_geo/memory_database.rb
86
+ - lib/sypex_geo/pack.rb
56
87
  - lib/sypex_geo/version.rb
57
88
  - spec/spec_helper.rb
58
89
  - spec/support/invalid.dat
59
90
  - spec/sypex_geo_spec.rb
60
91
  - sypex_geo.gemspec
61
- homepage: ''
92
+ homepage: https://github.com/kolesnikovde/sypex_geo
62
93
  licenses:
63
94
  - MIT
64
95
  metadata: {}
data/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2014 Kolesnikov Danil
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.