From: Bob Felts
Subject: Reading Binary Files: Best Practices?
Date: 
Message-ID: <1irwxg6.14vwqbobbbm70N%wrf3@stablecross.com>
Seibel's book, PCL, has a section on parsing binary files.  He gives an
example of reading an unsigned 16-bit thing:

   (defun read-ui16 (stream)
     (let ((ui16 0))
     (setf (ldb (byte 8 8) ui16) (read-byte stream))
     (setf (ldb (byte 8 0) ui16) (read-byte stream))
     ui16))

So far, so good.  How would a Lisp expert read a signed 16-bit thing?

One might, for example, write (sign-ui16 (read-ui16 stream)), where
sign-ui16 is defined as follows:

   (defun sign-ui16 (n)
     (if (zerop (ldb (byte 1 15) n))
       n
       (- (1+ (logxor #xffff n)))))

If the sign-bit is zero, return the number.  If it's set, return -(~n +
1).  (Note: lognot doesn't work - it has to be logxor).

Any suggestions on a better way to do this?

From: Zach Beane
Subject: Re: Reading Binary Files: Best Practices?
Date: 
Message-ID: <m363lmu8mv.fsf@unnamed.xach.com>
····@stablecross.com (Bob Felts) writes:

> So far, so good.  How would a Lisp expert read a signed 16-bit thing?
>
> One might, for example, write (sign-ui16 (read-ui16 stream)), where
> sign-ui16 is defined as follows:
>
>    (defun sign-ui16 (n)
>      (if (zerop (ldb (byte 1 15) n))
>        n
>        (- (1+ (logxor #xffff n)))))
>
> If the sign-bit is zero, return the number.  If it's set, return -(~n +
> 1).  (Note: lognot doesn't work - it has to be logxor).
>
> Any suggestions on a better way to do this?

Christophe Rhodes showed me this general idea:

  (defun sign-sized (n size)
    (if (logbitp (1- size) n)
        (dpb n (byte size 0) -1)
        n))

So:

  (defun sign-ui16 (n)
    (sign-sized n 16))

Zach
From: Madhu
Subject: Re: Reading Binary Files: Best Practices?
Date: 
Message-ID: <m3ej0b8eud.fsf@moon.robolove.meer.net>
* (Bob Felts) <···························@stablecross.com> :
Wrote on Sun, 14 Dec 2008 00:38:13 -0500:

|    (defun sign-ui16 (n)
|      (if (zerop (ldb (byte 1 15) n))
|        n
|        (- (1+ (logxor #xffff n)))))
|
| If the sign-bit is zero, return the number.  If it's set, return -(~n +
| 1).  (Note: lognot doesn't work - it has to be logxor).
|
| Any suggestions on a better way to do this?

Here is general code from Pascal Bourguignon

  (defun unsigned-to-signed/2-complement (x width) 
    (declare (integer x width))
    (let ((maxpos+1 (expt 2 (1- width))))
	 (if (< x maxpos+1) x (- x (* 2 maxpos+1)))))

Most of the code I've seen which reads signed 16bit words is along these
lines: declare the variable to be an unsigned-byte 16, check and
subtract 65536, or just return n.

This does not address how n was read from the external file, endianness
in which the file was stored.  For parsing binary files I've been using
frodef's excellent

	<URL:http://www.cs.uit.no/~frodef/sw/binary-types/>  

(from even before PCL came out.) There you'd do 

(read-binary 's16 stream)

--
Madhu
From: Bob Felts
Subject: Re: Reading Binary Files: Best Practices?
Date: 
Message-ID: <1iry1x0.kukbaikjzmwwN%wrf3@stablecross.com>
Madhu <·······@meer.net> wrote:

> * (Bob Felts) <···························@stablecross.com> :
> Wrote on Sun, 14 Dec 2008 00:38:13 -0500:
> 
> |    (defun sign-ui16 (n)
> |      (if (zerop (ldb (byte 1 15) n))
> |        n
> |        (- (1+ (logxor #xffff n)))))
> |
> | If the sign-bit is zero, return the number.  If it's set, return -(~n +
> | 1).  (Note: lognot doesn't work - it has to be logxor).
> |
> | Any suggestions on a better way to do this?
> 
> Here is general code from Pascal Bourguignon
> 
>   (defun unsigned-to-signed/2-complement (x width) 
>     (declare (integer x width))
>     (let ((maxpos+1 (expt 2 (1- width))))
>   (if (< x maxpos+1) x (- x (* 2 maxpos+1)))))
> 
> Most of the code I've seen which reads signed 16bit words is along these
> lines: declare the variable to be an unsigned-byte 16, check and
> subtract 65536, or just return n.
> 
> This does not address how n was read from the external file, endianness
> in which the file was stored.  For parsing binary files I've been using
> frodef's excellent
> 
>  <URL:http://www.cs.uit.no/~frodef/sw/binary-types/>  
> 
> (from even before PCL came out.) There you'd do 
> 
> (read-binary 's16 stream)
> 

Thanks.   Excellent information.