Refactor int Encoders

Instead of Shifting bits and masking in order to extract a subset of
the bits Lisp provides the function LBD, which allows us to extract a
number of bits from an integer. This approach is more direct,
communicates the intent better and allows the compiler to do less work.
This commit is contained in:
Javier Olaechea 2019-03-24 16:00:00 -05:00
parent 55fa48658d
commit 5a1eaaebad

View file

@ -309,37 +309,23 @@
(elt s 3)))) (elt s 3))))
i)) i))
(defun encode-int32 (i) (defmacro defint-encoder (num-of-octets &optional docstring)
"convert an integer into a sequence of 4 bytes in network byte order." (let ((enc-name (intern (format nil "~:@(encode-int~)~D" (* 8 num-of-octets))))
(declare (type integer i)) (buf (gensym))
(let ((buf (make-sequence (int (gensym)))
'(vector (unsigned-byte 8)) 4))) `(defun ,enc-name (,int)
(macrolet ((set-byte (n) ,@(when docstring
`(setf (elt buf ,n) (list docstring))
(logand #xff (ash i ,(* 8 (- n 3))))))) (let ((,buf (make-array ,num-of-octets :element-type '(unsigned-byte 8))))
(set-byte 0) ,@(loop
(set-byte 1) for n below num-of-octets
(set-byte 2) collect `(setf (aref ,buf ,n)
(set-byte 3)) (ldb (byte 8 (* 8 (- (1- ,num-of-octets) ,n)))
buf)) ,int)))
,buf))))
(defun encode-int64 (i) (defint-encoder 4 "Convert an integer into a sequence of 4 bytes in network byte order.")
"convert an integer into a sequence of 8 bytes in network byte order." (defint-encoder 8 "Convert an integer into a sequence of 8 bytes in network byte order.")
(declare (type integer i))
(let ((buf (make-sequence
'(vector (unsigned-byte 8)) 8)))
(macrolet ((set-byte (n)
`(setf (elt buf ,n)
(logand #xff (ash i ,(* 8 (- n 7)))))))
(set-byte 0)
(set-byte 1)
(set-byte 2)
(set-byte 3)
(set-byte 4)
(set-byte 5)
(set-byte 6)
(set-byte 7))
buf))
(defun decode-uint64 (s) (defun decode-uint64 (s)
"8 byte -> 64 bit unsigned int" "8 byte -> 64 bit unsigned int"