Initial import.
This commit is contained in:
		
						commit
						6f1edcb56b
					
				| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
Copyright (c) 2015 Kyle Isom <kyle@metacircular.net>
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in
 | 
			
		||||
all copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 | 
			
		||||
THE SOFTWARE.
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
#:BINARY
 | 
			
		||||
 | 
			
		||||
These are various utilities I wrote to read and write integers from
 | 
			
		||||
binary streams while working on a common lisp interface to the 9P
 | 
			
		||||
protocol. The following sets of functions are provided:
 | 
			
		||||
 | 
			
		||||
    - read-{u32,u16,u8}: read unsigned 32-, 16-, and 8-bit integers
 | 
			
		||||
      from a stream.
 | 
			
		||||
    - write-{u32,u16,u8}: write unsigned 32-, 16-, and 8-bit integers
 | 
			
		||||
      from a stream.
 | 
			
		||||
    - read-{i32,i16,i8}: read signed 32-, 16-, and 8-bit integers
 | 
			
		||||
      from a stream.
 | 
			
		||||
    - write-{i32,i16,u8}: write signed 32-, 16-, and 8-bit integers
 | 
			
		||||
      from a stream.
 | 
			
		||||
 | 
			
		||||
    - octets: read binary data from a stream
 | 
			
		||||
    - {int,uint}-from-bytes: read a signed or unsigned integer from
 | 
			
		||||
      a byte array.
 | 
			
		||||
    - {int,uint}-to-bytes: produce a byte array from a signed or
 | 
			
		||||
      unsigned integer.
 | 
			
		||||
 | 
			
		||||
Most of these functions take an endian specifier. Valid endians are
 | 
			
		||||
:little for little endian (the default) and :big for big endian.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
kyle@metacircular.net
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
;;;; binary.asd
 | 
			
		||||
 | 
			
		||||
(asdf:defsystem #:binary
 | 
			
		||||
  :description "Describe binary here"
 | 
			
		||||
  :author "Kyle Isom <kyle@metacircular.net>"
 | 
			
		||||
  :license "MIT License"
 | 
			
		||||
  :serial t
 | 
			
		||||
  :components ((:file "package")
 | 
			
		||||
               (:file "binary")))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,129 @@
 | 
			
		|||
;;;; binary.lisp
 | 
			
		||||
 | 
			
		||||
(in-package #:binary)
 | 
			
		||||
 | 
			
		||||
;;; "binary" goes here. Hacks and glory await!
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
(defconstant U32 4)
 | 
			
		||||
(defconstant I32 4)
 | 
			
		||||
(defconstant U16 2)
 | 
			
		||||
(defconstant I16 2)
 | 
			
		||||
(defconstant U8  1)
 | 
			
		||||
(defconstant I8  1)
 | 
			
		||||
 | 
			
		||||
(defun octets (stream length)
 | 
			
		||||
  "Read length bytes from the stream."
 | 
			
		||||
  (let ((bin (make-array length :element-type '(unsigned-byte 8))))
 | 
			
		||||
    (read-sequence bin stream)
 | 
			
		||||
    bin))
 | 
			
		||||
 | 
			
		||||
(defun uint-from-bytes (bin &key (endian :little))
 | 
			
		||||
  "Produce an unsigned integer from the binary array input."
 | 
			
		||||
  (let ((bin (cond
 | 
			
		||||
	       ((eql endian :little) bin)
 | 
			
		||||
	       ((eql endian :big)    (reverse bin))
 | 
			
		||||
	       (t (error "Invalid endian specification."))))
 | 
			
		||||
	(n 0))
 | 
			
		||||
    (dotimes (i (length bin))
 | 
			
		||||
      (setf n (+ n (ash (aref bin i) (* i 8)))))
 | 
			
		||||
    n))
 | 
			
		||||
 | 
			
		||||
(defun uint-to-bytes (n size &key (endian :little))
 | 
			
		||||
  "Produce a binary array of size bytes from the unsigned integer
 | 
			
		||||
provided."
 | 
			
		||||
  (let ((bin (make-array size :element-type '(unsigned-byte 8))))
 | 
			
		||||
    (dotimes (i size)
 | 
			
		||||
      (setf (aref bin i)
 | 
			
		||||
	    (logand 255 (ash n (- 0 (* i 8))))))
 | 
			
		||||
    (cond
 | 
			
		||||
      ((eql endian :little) bin)
 | 
			
		||||
      ((eql endian :big)    (nreverse bin))
 | 
			
		||||
      (t (error "Invalid endian specification.")))))
 | 
			
		||||
 | 
			
		||||
(defun read-uint (stream size &key (endian :little))
 | 
			
		||||
  (uint-from-bytes (octets stream size) :endian endian))
 | 
			
		||||
 | 
			
		||||
(defun write-uint (stream n size &key (endian :little))
 | 
			
		||||
  (write-sequence (uint-to-bytes n size :endian endian) stream))
 | 
			
		||||
 | 
			
		||||
(defmacro define-unsigned-reader (const-name)
 | 
			
		||||
  (let ((docstring
 | 
			
		||||
	 (format nil
 | 
			
		||||
		 "Read an unsigned ~A-bit integer from a stream."
 | 
			
		||||
		 (subseq  (format nil "~A" const-name) 1))))
 | 
			
		||||
    `(defun ,(intern (format nil "READ-~A" const-name))
 | 
			
		||||
	 (stream &key (endian :little))
 | 
			
		||||
       ,docstring
 | 
			
		||||
       (read-uint stream ,const-name :endian endian))))
 | 
			
		||||
 | 
			
		||||
(defmacro define-unsigned-writer (const-name)
 | 
			
		||||
  (let ((docstring
 | 
			
		||||
	 (format nil
 | 
			
		||||
		 "Write an unsigned ~A-bit integer to a stream."
 | 
			
		||||
		 (subseq  (format nil "~A" const-name) 1))))
 | 
			
		||||
    `(defun ,(intern (format nil "WRITE-~A" const-name))
 | 
			
		||||
	 (stream n &key (endian :little))
 | 
			
		||||
       ,docstring
 | 
			
		||||
       (write-uint stream n ,const-name :endian endian))))
 | 
			
		||||
 | 
			
		||||
(defmacro defunsigned (const-name)
 | 
			
		||||
  `(progn
 | 
			
		||||
     (define-unsigned-reader ,const-name)
 | 
			
		||||
     (define-unsigned-writer ,const-name)))
 | 
			
		||||
 | 
			
		||||
(defunsigned U32)
 | 
			
		||||
(defunsigned U16)
 | 
			
		||||
(defunsigned U8)
 | 
			
		||||
 | 
			
		||||
(defun twos-complement (n size)
 | 
			
		||||
  (if (zerop (logand (ash 1 (* (- size 1) 8)) n))
 | 
			
		||||
      n
 | 
			
		||||
      (- n (ash 1 (* size 8)))))
 | 
			
		||||
 | 
			
		||||
(defun int-from-bytes (bin &key (endian :little))
 | 
			
		||||
  "Produce a signed integer from the binary array input."
 | 
			
		||||
  (twos-complement (uint-from-bytes bin :endian endian)
 | 
			
		||||
		   (length bin)))
 | 
			
		||||
 | 
			
		||||
(defun int-to-bytes (n size &key (endian :little))
 | 
			
		||||
  "Produce a binary array of size bytes from the provided signed
 | 
			
		||||
integer."
 | 
			
		||||
  (uint-to-bytes (twos-complement n size) size :endian endian))
 | 
			
		||||
 | 
			
		||||
(defun read-int (stream size &key (endian :little))
 | 
			
		||||
  (int-from-bytes (octets stream size)
 | 
			
		||||
		  :endian endian))
 | 
			
		||||
 | 
			
		||||
(defun write-int (stream n size &key (endian :little))
 | 
			
		||||
  (write-sequence (int-to-bytes n size :endian endian)
 | 
			
		||||
		  stream))
 | 
			
		||||
 | 
			
		||||
(defmacro define-signed-reader (const-name)
 | 
			
		||||
  (let ((docstring
 | 
			
		||||
	 (format nil
 | 
			
		||||
		 "Read a signed ~A-bit integer from a stream."
 | 
			
		||||
		 (subseq  (format nil "~A" const-name) 1))))
 | 
			
		||||
    `(defun ,(intern (format nil "READ-~A" const-name))
 | 
			
		||||
	 (stream &key (endian :little))
 | 
			
		||||
       ,docstring
 | 
			
		||||
       (read-int stream ,const-name :endian endian))))
 | 
			
		||||
 | 
			
		||||
(defmacro define-signed-writer (const-name)
 | 
			
		||||
  (let ((docstring
 | 
			
		||||
	 (format nil
 | 
			
		||||
		 "Write a signed ~A-bit integer to a stream."
 | 
			
		||||
		 (subseq  (format nil "~A" const-name) 1))))
 | 
			
		||||
    `(defun ,(intern (format nil "WRITE-~A" const-name))
 | 
			
		||||
	 (stream n &key (endian :little))
 | 
			
		||||
       ,docstring
 | 
			
		||||
       (write-int stream n ,const-name :endian endian))))
 | 
			
		||||
 | 
			
		||||
(defmacro defsigned (const-name)
 | 
			
		||||
  `(progn
 | 
			
		||||
     (define-signed-reader ,const-name)
 | 
			
		||||
     (define-signed-writer ,const-name)))
 | 
			
		||||
 | 
			
		||||
(defsigned I32)
 | 
			
		||||
(defsigned I16)
 | 
			
		||||
(defsigned I8)
 | 
			
		||||
		Loading…
	
		Reference in New Issue