I'm currently writing a program where I'm using read-sequence to read in
blocks of data three (unsigned) bytes at a time. What I would like to be
able to do it to treat each 3 byte block as a single integer, instead of 3
individual bytes. Instead of writing a series of shift lefts and
additions (shift the first byte left 8 bits, add the second, shift that
result left 8 bits, add the third), is there an easier method of
converting this sequence to an integer value?
Thanks for any help,
Cory
In article <············@nntp.itservices.ubc.ca>, Cory Spencer wrote:
>I'm currently writing a program where I'm using read-sequence to read in
>blocks of data three (unsigned) bytes at a time. What I would like to be
>able to do it to treat each 3 byte block as a single integer, instead of 3
>individual bytes. Instead of writing a series of shift lefts and
>additions (shift the first byte left 8 bits, add the second, shift that
>result left 8 bits, add the third), is there an easier method of
>converting this sequence to an integer value?
How about:
(+ (* #x10000 octet1) (* #x100 octet2) octet3)
Assuming the three values are in the range 0 to 255, as implied
by their names.
Cory Spencer <········@interchange.ubc.ca> writes:
> I'm currently writing a program where I'm using read-sequence to read in
> blocks of data three (unsigned) bytes at a time. What I would like to be
> able to do it to treat each 3 byte block as a single integer, instead of 3
> individual bytes. Instead of writing a series of shift lefts and
> additions (shift the first byte left 8 bits, add the second, shift that
> result left 8 bits, add the third), is there an easier method of
> converting this sequence to an integer value?
Two suggestions:
;;; This does not appear to work in SBCL - I'm getting values that
;;; appear to be 32-bit instead of 24-bit.
(with-open-file (in ".bashrc" :direction :input
:element-type '(unsigned-byte 24))
(do ((elt (read-byte in nil) (read-byte in nil)))
((null elt))
(format t "Read ~a~%" elt)))
;;; This approach gives values that look more reasonable, but is a bit
;;; more convoluted :-)
(defun read-int8 (stream)
(read-byte stream nil))
(defmacro def-def-read-int-x (name numbytes)
(let ((res (gensym "RES-"))
(elt (gensym "ELT-"))
(i (gensym "I-")))
`(defun ,name (stream)
(let ((,res 0))
(dotimes (,i ,numbytes)
(let ((,elt (read-int8 stream)))
(if (null ,elt)
(return-from ,name nil)
(setf ,res (dpb ,elt (byte 8 (* (- 2 ,i) 8)) ,res)))))
,res))))
(def-def-read-int-x read-int16 2)
(def-def-read-int-x read-int24 3)
(def-def-read-int-x read-int32 4)
(with-open-file (in ".bashrc" :direction :input
:element-type '(unsigned-byte 8))
(do ((elt (read-int24 in) (read-int24 in)))
((null elt))
(format t "Read ~a~%" elt)))
--
Raymond Wiker Mail: ·············@fast.no
Senior Software Engineer Web: http://www.fast.no/
Fast Search & Transfer ASA Phone: +47 23 01 11 60
P.O. Box 1677 Vika Fax: +47 35 54 87 99
NO-0120 Oslo, NORWAY Mob: +47 48 01 11 60
Try FAST Search: http://alltheweb.com/
> * In message <············@nntp.itservices.ubc.ca>
> * On the subject of "Sequence question"
> * Sent on 19 Dec 2001 07:05:52 GMT
> * Honorable Cory Spencer <········@interchange.ubc.ca> writes:
>
> I'm currently writing a program where I'm using read-sequence to read
> in blocks of data three (unsigned) bytes at a time. What I would like
> to be able to do it to treat each 3 byte block as a single integer,
> instead of 3 individual bytes. Instead of writing a series of shift
> lefts and additions (shift the first byte left 8 bits, add the second,
> shift that result left 8 bits, add the third), is there an easier
> method of converting this sequence to an integer value?
if you are using CLISP, you can use READ-INTEGER
<http://clisp.cons.org/impnotes.html#d39e14329>
--
Sam Steingold (http://www.podval.org/~sds)
Keep Jerusalem united! <http://www.onejerusalem.org/Petition.asp>
Read, think and remember! <http://www.iris.org.il> <http://www.memri.org/>
NY survival guide: when crossing a street, mind cars, not streetlights.
In article <············@nntp.itservices.ubc.ca>, Cory Spencer
<········@interchange.ubc.ca> wrote:
> I'm currently writing a program where I'm using read-sequence to read in
> blocks of data three (unsigned) bytes at a time. What I would like to be
> able to do it to treat each 3 byte block as a single integer, instead of 3
> individual bytes. Instead of writing a series of shift lefts and
> additions (shift the first byte left 8 bits, add the second, shift that
> result left 8 bits, add the third), is there an easier method of
> converting this sequence to an integer value?
On modern CPUs with barrel shifters and several integer execution units
there is no faster portable way.
The only thing that has a chance of being faster is to read several
groups of 2, 4, or 8 bytes into an integer variable (or Altivec, or SSE
etc) and then use shifting and masking to extract the values. i.e. read
3 16 bit integers to produce 2 values, or read 3 32 bit integers to
produce 4 values, or read 3 64 bit integers to produce 8 values. But
this only works if your CPU has the same byte-endianess as the source
data, which is only a 50/50 chance.
-- Bruce