File: crc32.lisp

package info (click to toggle)
cl-chipz 20160318-1
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 260 kB
  • sloc: lisp: 2,515; makefile: 13
file content (88 lines) | stat: -rw-r--r-- 2,969 bytes parent folder | download | duplicates (3)
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
;;;; crc32.lisp -- implementation of the CRC32 checksum

(in-package :chipz)

#+sbcl
(progn
(defstruct (crc32
             (:copier copy-crc32))
  (crc #xffffffff :type (unsigned-byte 32)))

(defun update-crc32 (state vector start end)
  (declare (type simple-octet-vector vector))
  (declare (type index start end))
  (do ((crc (crc32-crc state))
       (i start (1+ i))
       (table +crc32-table+))
      ((>= i end)
       (setf (crc32-crc state) crc)
       state)
    (declare (type (unsigned-byte 32) crc))
    (setf crc (logxor (aref table
                            (logand (logxor crc (aref vector i)) #xff))
                      (ash crc -8)))))

(defun produce-crc32 (state)
  (logxor #xffffffff (crc32-crc state)))
)

;; An implementation that conses significantly less on most
;; implementations.  Credit to Zach Beane.
#-sbcl
(progn
(defstruct (crc32
             (:copier copy-crc32))
  (low #xffff)
  (high #xffff))

(defun crc32-table ()
  (let ((table (make-array 512 :element-type '(unsigned-byte 16))))
    (dotimes (n 256 table)
      (let ((c n))
        (declare (type (unsigned-byte 32) c))
        (dotimes (k 8)
          (if (logbitp 0 c)
              (setf c (logxor #xEDB88320 (ash c -1)))
              (setf c (ash c -1)))
          (setf (aref table (ash n 1)) (ldb (byte 16 16) c)
                (aref table (1+ (ash n 1))) (ldb (byte 16 0) c)))))))

(defvar *crc32-table* (crc32-table))

(defun crc32 (high low buf start count)
  (declare (type (unsigned-byte 16) high low)
           (type index start count)
           (type simple-octet-vector buf)
           (optimize speed))
  (let ((i start)
        (table *crc32-table*))
    (declare (type index i)
             (type (simple-array (unsigned-byte 16) (*)) table))
    (dotimes (j count (values high low))
      (let ((index (logxor (logand low #xFF) (aref buf i))))
        (declare (type (integer 0 255) index))
        (let ((high-index (ash index 1))
              (low-index (1+ (ash index 1))))
          (declare (type (integer 0 511) high-index low-index))
          (let ((t-high (aref table high-index))
                (t-low (aref table low-index)))
            (declare (type (unsigned-byte 16) t-high t-low))
            (incf i)
            (setf low (logxor (ash (logand high #xFF) 8)
                              (ash low -8)
                              t-low))
            (setf high (logxor (ash high -8) t-high))))))))

(defun update-crc32 (state vector start end)
  ;; ABCL used to miscompile (SETF (VALUES (ACCESSOR ...) ...) ...)
  ;; in case you were wondering why we take this route.
  (multiple-value-bind (high low) (crc32 (crc32-high state) (crc32-low state)
                                         vector start (- end start))
    (setf (crc32-high state) high
          (crc32-low state) low)
    (values high low)))

(defun produce-crc32 (state)
  (+ (ash (logxor (crc32-high state) #xFFFF) 16)
     (logxor (crc32-low state) #xFFFF)))
)