Integer doesn't grow in size when left-shifted?
Posted: Sat Mar 26, 2011 6:48 am
Hello.
In attempt to teach myself the language, I'm writing a library to read and write AMF format. The documentation is here: http://opensource.adobe.com/wiki/downlo ... _05_08.pdf
In a nutshell, this format is a "native" for Flash object encoding, which Flash can use for client-server communication, saving persistent data on disc and serializing objects when communicating from one Flash to another. Several implementations exist in other languages (FluorineFX in C#, BlazeDS in Java, Zend_Amf in PHP and pyamf in Python, and there may be more). I'm trying to write one in CL.
Below is my attempt to rewrite a function that reads UI29 records (that is an unsigned variable length integer of maximum 29 significant bits). The algorithm is quite simple: read 8 bits, if first is 1, then take the rest 7 bits and combine them with the result, however, the bits in result must be shifted 7 spaces to the left, so that the new 7 bits will exactly follow the rest of the already written bits. Repeat the process either until you encounter first 0 bit, or until 4 whole octets are read.
The code in comment is in AS3, but I think I can rewrite it in Java or C# if that will make it easier to understand. Something peculiar to AS3 - >>> is the right unsigned shift (i.e. it doesn't preserve the sign in the first bit, instead it moves the first bit with the rest). Assignment, or any variant of assignment returns the new assigned value, that is (a = 42) == 42.
What happens is that it looks like the "total" variable won't grow when it's bits are shifted to the right (as if it had fixed number of bits of 8).
Now, my questions are: does my code actually do what I believe it does?
Are the functions and data types correct for what I'm trying to do? (I saw different manuals suggesting that I use boole and bit-prefixed functions - I don't know what is the difference, and I can't figure out how would I cast a list of bits to integer. I'm less bothered with efficiency, but if I'm doing something outrageous, please tell! 
Thanks.
In attempt to teach myself the language, I'm writing a library to read and write AMF format. The documentation is here: http://opensource.adobe.com/wiki/downlo ... _05_08.pdf
In a nutshell, this format is a "native" for Flash object encoding, which Flash can use for client-server communication, saving persistent data on disc and serializing objects when communicating from one Flash to another. Several implementations exist in other languages (FluorineFX in C#, BlazeDS in Java, Zend_Amf in PHP and pyamf in Python, and there may be more). I'm trying to write one in CL.
Below is my attempt to rewrite a function that reads UI29 records (that is an unsigned variable length integer of maximum 29 significant bits). The algorithm is quite simple: read 8 bits, if first is 1, then take the rest 7 bits and combine them with the result, however, the bits in result must be shifted 7 spaces to the left, so that the new 7 bits will exactly follow the rest of the already written bits. Repeat the process either until you encounter first 0 bit, or until 4 whole octets are read.
The code in comment is in AS3, but I think I can rewrite it in Java or C# if that will make it easier to understand. Something peculiar to AS3 - >>> is the right unsigned shift (i.e. it doesn't preserve the sign in the first bit, instead it moves the first bit with the rest). Assignment, or any variant of assignment returns the new assigned value, that is (a = 42) == 42.
Code: Select all
;private function encodeUI29(bytes:ByteArray):uint
;{
; var byte:uint;
; var total:uint;
; var bytesRead:int;
; var shift:int = 7;
;
; do
; {
; byte = bytes.readUnsignedByte();
; bytesRead++;
; total |= int(byte & 0x7F);
; shift += int(bytesRead == 4);
; trace("total:", total, "byte", byte, "shift", shift);
; }
; while ((bytesRead < 4) && (byte >>> 7 > 0) && ((total <<= shift) > 0));
;
; return total;
;}
; ---- calling encodeUI29() ---
; -----------------------------
; bytes.writeByte(0x80 | 0x12);
; bytes.writeByte(0x80 | 0x34);
; bytes.writeByte(0x80 | 0x56);
; bytes.writeByte(0x80 | 0x01);
; bytes.position = 0;
; this.encodeUI29(bytes);
; ---- results: --------------
; total: 18 byte 146 shift 7
; total: 2356 byte 180 shift 7
; total: 301654 byte 214 shift 7
; total: 38611713 byte 129 shift 8
(defun encode-ui29 (bytes)
(let ((total 0) (shift -7))
(loop
for the-byte in bytes
for bytes-read from 0
do (setf total (logior total (logand the-byte #x7F)))
do (setf shift (- shift (if (= bytes-read 4) 1 0)))
do (format t "total: ~a, the-byte: ~a, shift: ~a~%" total the-byte shift)
when (and (< bytes-read 4)
(= 0 (ash the-byte 7))
(> (setf total (ash total shift)) 0))
return total)))
(encode-ui29 (list (logior #x80 #x12) (logior #x80 #x34) (logior #x80 #x56) (logior #x80 #x01)))
; ---- results ---------------
; total: 18, the-byte: 146, shift: -7
; total: 54, the-byte: 180, shift: -7
; total: 118, the-byte: 214, shift: -7
; total: 119, the-byte: 129, shift: -8
Now, my questions are: does my code actually do what I believe it does?


Thanks.