@@ -23,6 +23,7 @@ var metadataStartMarker = []byte("\xAB\xCD\xEFMaxMind.com")
23
23
type Reader struct {
24
24
hasMappedFile bool
25
25
buffer []byte
26
+ nodeReader nodeReader
26
27
decoder decoder
27
28
Metadata Metadata
28
29
ipv4Start uint
@@ -75,37 +76,46 @@ func FromBytes(buffer []byte) (*Reader, error) {
75
76
buffer [searchTreeSize + dataSectionSeparatorSize : metadataStart - len (metadataStartMarker )],
76
77
}
77
78
79
+ nodeBuffer := buffer [:searchTreeSize ]
80
+ var nodeReader nodeReader
81
+ switch metadata .RecordSize {
82
+ case 24 :
83
+ nodeReader = nodeReader24 {buffer : nodeBuffer }
84
+ case 28 :
85
+ nodeReader = nodeReader28 {buffer : nodeBuffer }
86
+ case 32 :
87
+ nodeReader = nodeReader32 {buffer : nodeBuffer }
88
+ default :
89
+ return nil , newInvalidDatabaseError ("unknown record size: %d" , metadata .RecordSize )
90
+ }
91
+
78
92
reader := & Reader {
79
- buffer : buffer ,
80
- decoder : d ,
81
- Metadata : metadata ,
82
- ipv4Start : 0 ,
93
+ buffer : buffer ,
94
+ nodeReader : nodeReader ,
95
+ decoder : d ,
96
+ Metadata : metadata ,
97
+ ipv4Start : 0 ,
83
98
}
84
99
85
- err = reader .setIPv4Start ()
100
+ reader .setIPv4Start ()
86
101
87
102
return reader , err
88
103
}
89
104
90
- func (r * Reader ) setIPv4Start () error {
105
+ func (r * Reader ) setIPv4Start () {
91
106
if r .Metadata .IPVersion != 6 {
92
- return nil
107
+ return
93
108
}
94
109
95
110
nodeCount := r .Metadata .NodeCount
96
111
97
112
node := uint (0 )
98
- var err error
99
113
i := 0
100
114
for ; i < 96 && node < nodeCount ; i ++ {
101
- node , err = r .readNode (node , 0 )
102
- if err != nil {
103
- return err
104
- }
115
+ node = r .nodeReader .readLeft (r .nodeOffset (node ))
105
116
}
106
117
r .ipv4Start = node
107
118
r .ipv4StartBitDepth = i
108
- return err
109
119
}
110
120
111
121
// Lookup retrieves the database record for ip and stores it in the value
@@ -241,10 +251,11 @@ func (r *Reader) lookupPointer(ip net.IP) (uint, int, net.IP, error) {
241
251
for ; i < bitCount && node < nodeCount ; i ++ {
242
252
bit := uint (1 ) & (uint (ip [i >> 3 ]) >> (7 - (i % 8 )))
243
253
244
- var err error
245
- node , err = r .readNode (node , bit )
246
- if err != nil {
247
- return 0 , int (i ), ip , err
254
+ offset := r .nodeOffset (node )
255
+ if bit == 0 {
256
+ node = r .nodeReader .readLeft (offset )
257
+ } else {
258
+ node = r .nodeReader .readRight (offset )
248
259
}
249
260
}
250
261
if node == nodeCount {
@@ -257,33 +268,8 @@ func (r *Reader) lookupPointer(ip net.IP) (uint, int, net.IP, error) {
257
268
return 0 , int (i ), ip , newInvalidDatabaseError ("invalid node in search tree" )
258
269
}
259
270
260
- func (r * Reader ) readNode (nodeNumber uint , index uint ) (uint , error ) {
261
- RecordSize := r .Metadata .RecordSize
262
-
263
- baseOffset := nodeNumber * RecordSize / 4
264
-
265
- var nodeBytes []byte
266
- var prefix uint
267
- switch RecordSize {
268
- case 24 :
269
- offset := baseOffset + index * 3
270
- nodeBytes = r .buffer [offset : offset + 3 ]
271
- case 28 :
272
- prefix = uint (r .buffer [baseOffset + 3 ])
273
- if index != 0 {
274
- prefix &= 0x0F
275
- } else {
276
- prefix = (0xF0 & prefix ) >> 4
277
- }
278
- offset := baseOffset + index * 4
279
- nodeBytes = r .buffer [offset : offset + 3 ]
280
- case 32 :
281
- offset := baseOffset + index * 4
282
- nodeBytes = r .buffer [offset : offset + 4 ]
283
- default :
284
- return 0 , newInvalidDatabaseError ("unknown record size: %d" , RecordSize )
285
- }
286
- return uintFromBytes (prefix , nodeBytes ), nil
271
+ func (r * Reader ) nodeOffset (node uint ) uint {
272
+ return node * r .Metadata .RecordSize / 4
287
273
}
288
274
289
275
func (r * Reader ) retrieveData (pointer uint , result interface {}) error {
0 commit comments