File: api.lisp

package info (click to toggle)
acl2 8.5dfsg-5
  • links: PTS
  • area: main
  • in suites: bookworm
  • size: 991,452 kB
  • sloc: lisp: 15,567,759; javascript: 22,820; cpp: 13,929; ansic: 12,092; perl: 7,150; java: 4,405; xml: 3,884; makefile: 3,507; sh: 3,187; ruby: 2,633; ml: 763; python: 746; yacc: 723; awk: 295; csh: 186; php: 171; lex: 154; tcl: 49; asm: 23; haskell: 17
file content (71 lines) | stat: -rw-r--r-- 2,809 bytes parent folder | download
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
(in-package 3bz)

(defun decompress (context state)
  (etypecase state
    (gzip-state
     (decompress-gzip context state))
    (zlib-state
     (decompress-zlib context state))
    (deflate-state
     (decompress-deflate context state))))

(defun replace-output-buffer (state buffer)
  (unless (or (zerop (ds-output-offset state))
              (ds-output-overflow state))
    ;; we don't create/fill window until output buffer overflows, so
    ;; would need to do that here. error for now until someone needs
    ;; that ability...
    (error "can't switch buffers without filling old one yet."))
  (setf (ds-output-buffer state) buffer)
  (setf (ds-output-offset state) 0)
  (setf (ds-output-overflow state) nil))

(defun decompress-vector (compressed &key (format :zlib) (start 0) (end (length compressed)) output)
  "decompress octet-vector COMPRESSED using
FORMAT (:deflate,:zlib,:gzip). If output is supplied, it should be an
octet-vector large enough to hold entire uncompressed output.

Returns buffer containing decompressed data (OUTPUT if supplied) and #
of octets decompressed."
  (let ((parts nil)
        (state (ecase format
                 (:gzip (make-gzip-state))
                 (:zlib (make-zlib-state))
                 (:deflate (make-deflate-state))))
        (rc (make-octet-vector-context compressed :start start :end end)))
    (if output
        (progn
          (setf (ds-output-buffer state) output)
          (setf (ds-output-offset state) 0)
          (let ((c (decompress rc state)))
            (unless (ds-finished state)
              (cond
                ((ds-input-underrun state)
                 (error "incomplete ~a stream" format))
                ((ds-output-overflow state)
                 (error "not enough space to decompress ~a stream" format))
                (t (error "?"))))
            (values output c)))
        (progn
          (loop for out = (make-array (min (- end start) 32768)
                                      :element-type 'octet)
                  then (make-array (* 2 (length out)) :element-type 'octet)
                do (replace-output-buffer state out)
                   (let ((c (decompress rc state)))
                     (push (cons out c) parts))
                   (assert (not (ds-input-underrun state)))
                until (ds-finished state))
          (let* ((s (reduce '+ parts :key 'cdr))
                 (b (make-array s :element-type 'octet)))
            (loop for start = 0 then (+ start c)
                  for (p . c) in (nreverse parts)
                  do (replace b p :start1 start :end2 c))
            (values b (length b)))))))

(defun finished (state)
  (ds-finished state))
(defun input-underrun (state)
  (ds-input-underrun state))
(defun output-overflow (state)
  (ds-output-overflow state))