Initial import.

This commit is contained in:
Kyle 2015-04-13 03:01:44 -07:00
commit 6f1edcb56b
4 changed files with 184 additions and 0 deletions

19
LICENSE Normal file
View File

@ -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.

26
README.txt Normal file
View File

@ -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

10
binary.asd Normal file
View File

@ -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")))

129
binary.lisp Normal file
View File

@ -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)