From: Alex Drummond
Subject: Converting numbers into sequences of bytes
Date: 
Message-ID: <c3eemb$2556$1@uns-a.ucl.ac.uk>
Hello,

I want to convert a number into a sequence of bytes so that I can send it
through a pipe (there is a C program listening at the other end). I would
prefer to have a direct binary representation of the number rather than an
ASCII one, but one which is independent of the particular Lisp
implementation I'm using. So for example I would like to be able to take an
integer and convert it into a raw representation of its value (e.g. a
vector of four bytes or something like that). I realise that this would be
considerably more difficult for floating point numbers, but I really only
need to do it with integers. I'd be grateful for any help :)

-- 

Alex

From: Edi Weitz
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <m3hdwl6us7.fsf@bird.agharta.de>
> I want to convert a number into a sequence of bytes so that I can
> send it through a pipe (there is a C program listening at the other
> end). I would prefer to have a direct binary representation of the
> number rather than an ASCII one, but one which is independent of the
> particular Lisp implementation I'm using. So for example I would
> like to be able to take an integer and convert it into a raw
> representation of its value (e.g. a vector of four bytes or
> something like that). I realise that this would be considerably more
> difficult for floating point numbers, but I really only need to do
> it with integers. I'd be grateful for any help :)

Have you looked at <http://www.cliki.net/Binary-types>?

I haven't used it myself and in the intro it only talks about
"accessing binary files" but at the end of the text you'll find a
mention of the CVS version and "specialized reader and writer
functions." Maybe that'll help.

Cheers,
Edi.
From: Björn Lindberg
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <hcsad2dm5uz.fsf@tjatte.nada.kth.se>
Alex Drummond <············@foo.com> writes:

> Hello,
> 
> I want to convert a number into a sequence of bytes so that I can send it
> through a pipe (there is a C program listening at the other end). I would
> prefer to have a direct binary representation of the number rather than an
> ASCII one, but one which is independent of the particular Lisp
> implementation I'm using. So for example I would like to be able to take an
> integer and convert it into a raw representation of its value (e.g. a
> vector of four bytes or something like that). I realise that this would be
> considerably more difficult for floating point numbers, but I really only
> need to do it with integers. I'd be grateful for any help :)

Here is a function to turn an integer into an array of high-to-low
order bytes:

(defun integer->bytes (n)
  (loop for i = n then quot
	for (quot rem) = (multiple-value-list (floor i 256))
	collect rem into result
	while (> quot 0)
	finally (return (make-array (length result)
				    :element-type '(unsigned-byte 8)
				    :initial-contents (nreverse result)))))

(integer->bytes (expt 2 32))
==> #(1 0 0 0 0)
(integer->bytes (1- (expt 2 32)))
==> #(255 255 255 255)

I *think* you could then just use WRITE-SEQUENCE to write it to a
stream, and get the raw bytes output. The C program would have to
assemble it similarly.

If instead you would like to read the result directly as a C int, you
have to figure out the endian-ness of your platform first.


Bj�rn
From: Alex Drummond
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <c3emdm$fnq$1@uns-a.ucl.ac.uk>
That works nicely, thanks :)

Bj�rn Lindberg wrote:

> Alex Drummond <············@foo.com> writes:
> 
>> Hello,
>> 
>> I want to convert a number into a sequence of bytes so that I can send it
>> through a pipe (there is a C program listening at the other end). I would
>> prefer to have a direct binary representation of the number rather than
>> an ASCII one, but one which is independent of the particular Lisp
>> implementation I'm using. So for example I would like to be able to take
>> an integer and convert it into a raw representation of its value (e.g. a
>> vector of four bytes or something like that). I realise that this would
>> be considerably more difficult for floating point numbers, but I really
>> only need to do it with integers. I'd be grateful for any help :)
> 
> Here is a function to turn an integer into an array of high-to-low
> order bytes:
> 
> (defun integer->bytes (n)
>   (loop for i = n then quot
> for (quot rem) = (multiple-value-list (floor i 256))
> collect rem into result
> while (> quot 0)
> finally (return (make-array (length result)
> :element-type '(unsigned-byte 8)
> :initial-contents (nreverse result)))))
> 
> (integer->bytes (expt 2 32))
> ==> #(1 0 0 0 0)
> (integer->bytes (1- (expt 2 32)))
> ==> #(255 255 255 255)
> 
> I *think* you could then just use WRITE-SEQUENCE to write it to a
> stream, and get the raw bytes output. The C program would have to
> assemble it similarly.
> 
> If instead you would like to read the result directly as a C int, you
> have to figure out the endian-ness of your platform first.
> 
> 
> Bj�rn

-- 

Alex
From: Wade Humeniuk
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <mWE6c.95943$Ff2.81058@clgrps12>
Alex Drummond wrote:
> Hello,
> 
> I want to convert a number into a sequence of bytes so that I can send it
> through a pipe (there is a C program listening at the other end). I would
> prefer to have a direct binary representation of the number rather than an
> ASCII one, but one which is independent of the particular Lisp
> implementation I'm using. So for example I would like to be able to take an
> integer and convert it into a raw representation of its value (e.g. a
> vector of four bytes or something like that). I realise that this would be
> considerably more difficult for floating point numbers, but I really only
> need to do it with integers. I'd be grateful for any help :)
> 


(defun integers-bytes-32 (integer)
   (values (ldb (byte 8 24) integer)
           (ldb (byte 8 16) integer)
           (ldb (byte 8 8) integer)
           (ldb (byte 8 0) integer)))

CL-USER 3 > (integers-bytes-32 #x0f657a21)
15
101
122
33

CL-USER 4 >

Wade
From: Wade Humeniuk
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <3dF6c.95946$Ff2.88087@clgrps12>
Wade Humeniuk wrote:


> 
> (defun integers-bytes-32 (integer)
>   (values (ldb (byte 8 24) integer)
>           (ldb (byte 8 16) integer)
>           (ldb (byte 8 8) integer)
>           (ldb (byte 8 0) integer)))
> 
> CL-USER 3 > (integers-bytes-32 #x0f657a21)
> 15
> 101
> 122
> 33
> 
> CL-USER 4 >

And of course the inverse

(defun bytes-integer-32 (b24 b16 b8 b0)
   (let ((integer 0))
     (setf (ldb (byte 8 24) integer) b24
           (ldb (byte 8 16) integer) b16
           (ldb (byte 8 8) integer) b8
           (ldb (byte 8 0) integer) b0)
     integer))

CL-USER 1 > (format t "~X" (bytes-integer-32 #x0f #xe5 #x11 #x3d))
FE5113D
NIL

And maybe a stream writing function

(defun write-integer-32 (integer stream &optional (endian :big))
   (assert (typep (stream-element-type stream) '(unsigned-byte 8)))
   (multiple-value-bind (b24 b16 b8 b0)
       (integers-bytes-32 integer)
     (ecase endian
       (:big
        (write-byte b24 stream)
        (write-byte b16 stream)
        (write-byte b8 stream)
        (write-byte b0 stream))
       (:little
        (write-byte b0 stream)
        (write-byte b8 stream)
        (write-byte b16 stream)
        (write-byte b24 stream)))))

Untested.

Wade
From: Wade Humeniuk
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <rIG6c.95949$Ff2.27211@clgrps12>
On reflection it might be better to bite the bullet and implement
a more declarative wrapper around byte based protocols.  Something
like:

(defbyteprotocol :little-endian message1
   (id :type '(unsigned-byte 8))
   (size :type '(unsigned-byte 32) :reader #'read-integer-32
         :writer #'write-integer-32)
   (array :type '(vector (unsigned-byte 32) *)))

Having readers and writers for different types (of course defaulting the reader or
writer based on type).  It would also be possible to use the FFI to define the
protocols and use

Then have general purpose functions to write and read byteprotocols.

(write-byteprotocol (make-message1 :id blob :size 4 :array #(1234 651 900 1000)) stream)

(read-byteprotocol 'message1 stream)

Wade
From: Alex Drummond
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <c3gav9$mka$1@uns-a.ucl.ac.uk>
Again, this was very helpful, thanks :)

Wade Humeniuk wrote:

> Alex Drummond wrote:
>> Hello,
>> 
>> I want to convert a number into a sequence of bytes so that I can send it
>> through a pipe (there is a C program listening at the other end). I would
>> prefer to have a direct binary representation of the number rather than
>> an ASCII one, but one which is independent of the particular Lisp
>> implementation I'm using. So for example I would like to be able to take
>> an integer and convert it into a raw representation of its value (e.g. a
>> vector of four bytes or something like that). I realise that this would
>> be considerably more difficult for floating point numbers, but I really
>> only need to do it with integers. I'd be grateful for any help :)
>> 
> 
> 
> (defun integers-bytes-32 (integer)
>    (values (ldb (byte 8 24) integer)
>            (ldb (byte 8 16) integer)
>            (ldb (byte 8 8) integer)
>            (ldb (byte 8 0) integer)))
> 
> CL-USER 3 > (integers-bytes-32 #x0f657a21)
> 15
> 101
> 122
> 33
> 
> CL-USER 4 >
> 
> Wade

-- 

Alex
From: Joseph Oswald
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <e86bd0ec.0403200703.3a89035a@posting.google.com>
Alex Drummond <············@foo.com> wrote in message news:<·············@uns-a.ucl.ac.uk>...

> implementation I'm using. So for example I would like to be able to take an
> integer and convert it into a raw representation of its value (e.g. a
> vector of four bytes or something like that). I realise that this would be
> considerably more difficult for floating point numbers,

Alex--

  Others have pointed you to ldb, dpb, and friends (see
http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/sec_the_numbers_dictionary.html
for details.) Those work very well for integers.

  The corresponding functions for floating point numbers are
decode-float, integer-decode-float, and scale-float. They are handy
for converting floating point numbers from the Lisp representation 
(which in almost all modern cases will be IEEE format) into other
formats, or IEEE format, if you wish.

http://users.rcn.com/jaoswald/lisp/calma/calma-float.lisp

is an example of some code I wrote to generate and interpret
Calma-format floating point numbers, used for the GDS-II photomask
data stream format. It assumes the Lisp floats use radix 2, but could
be generalized. It's not the most elegant code, but it worked.

I feel that these features are much, much, more flexible and powerful
than the corresponding facilities in C, once you understand them.
From: Alex Drummond
Subject: Re: Converting numbers into sequences of bytes
Date: 
Message-ID: <c3j8u3$2jhm$1@uns-a.ucl.ac.uk>
> I feel that these features are much, much, more flexible and powerful
> than the corresponding facilities in C, once you understand them.

I agree. It would definitely be easier to do this badly in C, but it looks
like CL lets you to do it right.

Joseph Oswald wrote:

> Alex Drummond <············@foo.com> wrote in message
> news:<·············@uns-a.ucl.ac.uk>...
> 
>> implementation I'm using. So for example I would like to be able to take
>> an integer and convert it into a raw representation of its value (e.g. a
>> vector of four bytes or something like that). I realise that this would
>> be considerably more difficult for floating point numbers,
> 
> Alex--
> 
>   Others have pointed you to ldb, dpb, and friends (see
>
http://www-2.cs.cmu.edu/Groups/AI/html/hyperspec/HyperSpec/Body/sec_the_numbers_dictionary.html
> for details.) Those work very well for integers.
> 
>   The corresponding functions for floating point numbers are
> decode-float, integer-decode-float, and scale-float. They are handy
> for converting floating point numbers from the Lisp representation
> (which in almost all modern cases will be IEEE format) into other
> formats, or IEEE format, if you wish.
> 
> http://users.rcn.com/jaoswald/lisp/calma/calma-float.lisp
> 
> is an example of some code I wrote to generate and interpret
> Calma-format floating point numbers, used for the GDS-II photomask
> data stream format. It assumes the Lisp floats use radix 2, but could
> be generalized. It's not the most elegant code, but it worked.
> 
> I feel that these features are much, much, more flexible and powerful
> than the corresponding facilities in C, once you understand them.

-- 

Alex