File: io.lisp

package info (click to toggle)
acl2 8.6%2Bdfsg-3
  • links: PTS
  • area: main
  • in suites: sid
  • size: 1,138,276 kB
  • sloc: lisp: 17,818,294; java: 125,359; python: 28,122; javascript: 23,458; cpp: 18,851; ansic: 11,569; perl: 7,678; xml: 5,591; sh: 3,978; makefile: 3,840; ruby: 2,633; yacc: 1,126; ml: 763; awk: 295; csh: 233; lex: 197; php: 178; tcl: 49; asm: 23; haskell: 17
file content (125 lines) | stat: -rw-r--r-- 3,847 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
(in-package #:org.shirakumo.zippy)

(deftype io ()
  `(or stream vector-input directory-input))

(defstruct (vector-input (:constructor make-vector-input (vector index start end)))
  (vector NIL :type (simple-array (unsigned-byte 8) (*)) :read-only T)
  (start 0 :type fixnum :read-only T)
  (end 0 :type fixnum :read-only T)
  (index 0 :type fixnum))

(defstruct directory-input)

(defun seek (io target)
  (etypecase io
    (vector-input
     (if (<= (vector-input-start io) target (1- (vector-input-end io)))
         (setf (vector-input-index io) target)
         (error 'out-of-bounds-seek :target target)))
    (stream
     (file-position io target))))

(defun has-more (io)
  (etypecase io
    (vector-input
     (< (vector-input-index io) (vector-input-end io)))
    (stream
     (< (file-position io) (file-length io)))))

(defun index (io)
  (etypecase io
    (vector-input
     (vector-input-index io))
    (stream ; works for e.g. flexi-stream:in-memory-*-stream
     (file-position io))))

(defun start (io)
  (etypecase io
    (vector-input
     (vector-input-start io))
    (stream
     0)))

(defun end (io)
  (etypecase io
    (vector-input
     (vector-input-end io))
    (stream
     (file-length io))))

(defmethod size ((io vector-input))
  (- (vector-input-end io) (vector-input-start io)))

(defmethod size ((io stream))
  (file-length io))

(defun ub32 (io)
  (etypecase io
    (vector-input
     (prog1 (nibbles:ub32ref/le (vector-input-vector io) (vector-input-index io))
       (incf (vector-input-index io) 4)))
    (stream
     (nibbles:read-ub32/le io))))

(defun output (io array start end)
  (etypecase io
    (vector-input
     (when (<= (vector-input-end io) (+ (vector-input-index io) (- end start)))
       (error 'out-of-bounds-seek :target (+ (vector-input-index io) (- end start))))
     (loop with vector = (vector-input-vector io)
           for i from start below end
           for j from (vector-input-index io)
           do (setf (aref vector j) (aref array i)))
     (incf (vector-input-index io) (- end start)))
    (stream
     (write-sequence array io :start start :end end))))

(defun parse-structure* (io)
  (etypecase io
    (vector-input
     (multiple-value-bind (value index)
         (decode-structure (vector-input-vector io) (vector-input-index io))
       (setf (vector-input-index io) index)
       value))
    (stream
     (read-structure io))))

(defun write-structure* (structure io)
  (etypecase io
    (vector-input
     (setf (vector-input-index io)
           (encode-structure structure (vector-input-vector io) (vector-input-index io))))
    (stream
     (write-structure structure io)))
  io)

(defmacro parse-structure (structure-type io-var)
  (let ((io (gensym "IO")))
    `(let ((,io ,io-var))
       (etypecase ,io
         (vector-input
          (multiple-value-bind (value index)
              (,(intern (format NIL "~a-~a" 'decode structure-type))
               (vector-input-vector ,io) (vector-input-index ,io))
            (setf (vector-input-index ,io) index)
            value))
         (stream
          (,(intern (format NIL "~a-~a" 'read structure-type)) ,io))))))

(defun call-with-io (function io &key (start 0) end (if-exists :error) (direction :input))
  (etypecase io
    ((or string pathname)
     (if (pathname-utils:directory-p io)
         (funcall function (make-directory-input))
         (with-open-file (stream io :direction direction
                                    :element-type '(unsigned-byte 8)
                                    :if-exists if-exists)
           (funcall function stream))))
    (io
     (funcall function io))
    (vector
     (funcall function (make-vector-input io start start (or end (length io)))))))

(defmacro with-io ((io target &rest args) &body body)
  `(call-with-io (lambda (,io) ,@body) ,target ,@args))