aboutsummaryrefslogtreecommitdiffstats
path: root/geoip
diff options
context:
space:
mode:
Diffstat (limited to 'geoip')
-rw-r--r--geoip/ip.lisp37
1 files changed, 33 insertions, 4 deletions
diff --git a/geoip/ip.lisp b/geoip/ip.lisp
index 63c373f..7098c94 100644
--- a/geoip/ip.lisp
+++ b/geoip/ip.lisp
@@ -59,7 +59,9 @@
(data-offset -1 :type fixnum))
(defstruct db-reader
- (db-ptr))
+ (db-ptr)
+ (head-ptr)
+ (data-offset))
(defstruct maxmind-database-metadata
(node-count 0 :read-only t :type fixnum)
@@ -167,7 +169,10 @@
(setf type (+ 7 (read-db-char db-ptr))))
(list type
(cond
- ((or (= type 1) (< length 29))
+ ((= type 1)
+ (incf-pointer (db-reader-db-ptr db-ptr) -1)
+ (+ 2 (ash length -3)))
+ ((< length 29)
length)
((= length 29)
(+ 29 (read-db-char db-ptr)))
@@ -181,16 +186,38 @@
(loop repeat length
collect
(cons
- (substitute #\- #\_ (mread-data db-ptr))
+ (intern (string-upcase (substitute #\- #\_ (mread-data db-ptr))) :keyword)
(mread-data db-ptr))))
(defun mread-list (db-ptr length)
(loop repeat length collect (mread-data db-ptr)))
+(defun read-pointer (reader)
+ (let* ((control-byte (read-db-char reader))
+ (size-bits (ldb (byte 2 3) control-byte))
+ (value-bits (ldb (byte 3 0) control-byte)))
+ (ecase size-bits
+ (0 (+ (ash value-bits 8) (read-db-char reader)))
+ (1 (+ (ash value-bits 16) (mread-unsigned reader 2) 2048))
+ (2 (+ (ash value-bits 24) (mread-unsigned reader 3) 526336))
+ (3 (mread-unsigned reader 4)))))
+
+(defun mread-pointer (reader)
+ (with-slots (db-ptr head-ptr data-offset) reader
+ (let* ((target (+ (read-pointer reader) data-offset))
+ (curr-ptr db-ptr)
+ (result))
+ (setf db-ptr (inc-pointer head-ptr target))
+ (setf result (mread-data reader))
+ (setf db-ptr curr-ptr)
+ result)))
+
(defun mread-data (db-ptr)
(destructuring-bind (type length) (mread-datafield-metadata db-ptr)
(ecase type
+ (1 (mread-pointer db-ptr))
(2 (mread-uft8 db-ptr length))
+ (3 (cons 'double (mread-unsigned db-ptr 8)))
(4 (bytes-from-foreign db-ptr length))
((5 6 9 10) (mread-unsigned db-ptr length))
(7 (mread-map db-ptr length))
@@ -233,7 +260,9 @@
(with-slots (node-count) metadata
(mread-data
(make-db-reader
- :db-ptr (inc-pointer ptr (+ data-offset (- record node-count 16)))))))))
+ :db-ptr (inc-pointer ptr (+ data-offset (- record node-count 16)))
+ :head-ptr ptr
+ :data-offset data-offset))))))
(defun integer-to-bits (n bit-count)
"Convert integer to list of bits (MSB first)"