git.fiddlerwoaroof.com
Browse code

Add binary parsing library, rework .asd

Ed Langley authored on 09/07/2018 08:08:13
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,80 @@
1
+(uiop:define-package :fwoar.bin-parser
2
+    (:use :cl)
3
+    (:mix :fw.lu :alexandria :serapeum))
4
+
5
+(in-package :fwoar.bin-parser)
6
+
7
+(defun read-bytes (n s)
8
+  (with (seq (make-array n :element-type 'octet))
9
+    (values seq
10
+            (read-sequence seq s))))
11
+
12
+(defun calculate-sizes (desc)
13
+  (reduce #'+ desc
14
+          :key #'cadr
15
+          :initial-value 0))
16
+
17
+(defun le->int (bytes)
18
+  (cadr
19
+   (reduce (op (destructuring-bind (count val) _1
20
+                 (list (1+ count)
21
+                       (+ val
22
+                          (ash _2
23
+                               (* count 8))))))
24
+           bytes
25
+           :initial-value (list 0 0))))
26
+
27
+(defun get-extractable-bytes (desc &optional (bindings ()))
28
+  (loop for ((name size . other) . rest) on (resolve-sizes desc bindings)
29
+     until (symbolp size)
30
+     collect (list* name size other) into extractable
31
+     finally (return (values extractable
32
+                             (append (unsplice
33
+                                      (when (symbolp size)
34
+                                        (list* name size other)))
35
+                                     rest))))) 
36
+
37
+(defun resolve-sizes (desc extant-bindings)
38
+  (declare (optimize (debug 3)))
39
+  (loop with bindings = (copy-seq extant-bindings)
40
+     for (name size . rest) in desc
41
+     for resolved = (when (symbolp size)
42
+                      (cdr (assoc size bindings)))
43
+     when resolved do (push (cons name resolved)
44
+                            bindings)
45
+     if resolved collect (list* name resolved rest) into new-desc
46
+     else collect (list* name size rest) into new-desc
47
+     finally (return (values new-desc
48
+                             (remove-duplicates (append (mapcar (op (apply #'cons (subseq _ 0 2)))
49
+                                                                new-desc)
50
+                                                        bindings)
51
+                                                :key 'car
52
+                                                :from-end t)))))
53
+
54
+(defun extract-bytes (desc bytes)
55
+  (loop
56
+     with cur-idx = 0
57
+     for (name size . rest) in desc
58
+     for next-seq = (subseq bytes cur-idx
59
+                            (+ cur-idx size))
60
+     collect (cons name (if rest
61
+                            (funcall (car rest) next-seq)
62
+                            next-seq))
63
+     do (incf cur-idx size)))
64
+
65
+(defun parse-struct (desc s)
66
+  (let* ((struct-size (calculate-sizes desc))
67
+         (bytes (read-bytes struct-size s)))
68
+    (extract-bytes desc bytes)))
69
+
70
+(defun make-zipfile-stream (fn)
71
+  (open fn :element-type '(unsigned-byte 8)))
72
+
73
+
74
+(defun extract (raw-desc s &optional bindings)
75
+  (multiple-value-bind (desc remainder) (get-extractable-bytes raw-desc bindings)
76
+    (let ((next-segment (parse-struct desc s)))
77
+      (if remainder
78
+          (append next-segment
79
+                  (extract remainder s (append next-segment bindings)))
80
+          next-segment))))
... ...
@@ -1,5 +1,16 @@
1 1
 ;;;; fwoar.lisputils.asd
2 2
 (in-package :asdf-user)
3
+
4
+(defsystem #:fwoar.lisputils/string-utils
5
+  :description "A binary parser"
6
+  :author "fiddlerwoaroof <fiddlerwoaroof@gmail.com"
7
+  :license "MIT"
8
+  :depends-on (#:should-test)
9
+  :components ((:file "string-utils/package")
10
+               (:file "string-utils/string-utils" :depends-on ("string-utils/package"))
11
+               #-lispworks
12
+               (:file "string-utils/test" :depends-on ("string-utils/string-utils"))))
13
+
3 14
 (asdf:defsystem #:fwoar.lisputils
4 15
   :description "Some utilities common to other libraries I'm writing"
5 16
   :author "fiddlerwoaroof <fiddlerwoaroof@gmail.com"
... ...
@@ -13,6 +24,7 @@
13 24
                #:serapeum
14 25
                #:cl-containers
15 26
                #:iterate
27
+               #:fwoar.lisputils/string-utils
16 28
                #-lispworks #:plump
17 29
                #:positional-lambda
18 30
                #-lispworks #:should-test)
... ...
@@ -24,13 +36,17 @@
24 36
                (:file "clos-helpers")
25 37
                (:file "counter")
26 38
                (:file "vector-utils")
27
-               (:file "string-utils/package")
28
-               (:file "string-utils/string-utils")
29 39
                #-lispworks
30 40
                (:file "non-lispworks")
31 41
                #-lispworks
32
-               (:file "string-utils/test")
33
-               #-lispworks
34 42
                (:file "patmatch")
35 43
                (:file "glambda")))
36 44
 
45
+(defsystem #:fwoar.lisputils/bin-parser
46
+  :description "A binary parser"
47
+  :author "fiddlerwoaroof <fiddlerwoaroof@gmail.com"
48
+  :license "MIT"
49
+  :depends-on (:fwoar.lisputils
50
+               :alexandria
51
+               :serapeum)
52
+  :components ((:file "bin-parser")))