home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-03-14 | 7.8 KB | 297 lines | [TEXT/MPS ] |
- unit bitpackunit;
- {
- Copyright ⌐ 1989 Albert Lunde, Northwestern University
- All Rights Reserved
- }
-
- {pack and unpack streams of bits}
- interface
- uses memtypes,quickdraw,osintf,toolintf,packintf;
-
- procedure longtohex(ll:longint;var hex:str255);
-
- procedure dumphex(ll:longint); {write longint as hex for debug}
-
- procedure stripbits(source:ptr;
- source_bits_per_item:integer;
- source_bytesize:longint;
- dest:ptr;
- dest_bits_per_item:integer;
- dest_bytesize:longint;
- first_item:longint;
- last_item:longint;
- invert:boolean);
-
-
- procedure bitstream_unpack( source:ptr;{input bytes}
- source_item_count:longint;
- source_bits_per_item:integer;{24 or less}
- dest:ptr;{output bytes,words, or longwords}
- dest_max_bytes:longint;
- var dest_item_count:longint;
- dest_bytes_per_item:integer;{1,2,4}
- dest_low_bit_alignment:integer);
-
- procedure bitstream_pack( source:ptr;{input bytes}
- source_item_count:longint;
- source_bytes_per_item:integer;{1,2,4}
- source_low_bit_alignment:integer;
- dest:ptr;{output bytes,words, or longwords}
- dest_max_bytes:longint;
- dest_bits_per_item:integer;{24 or less}
- var dest_item_count:longint);
- implementation
-
- procedure longtohex(ll:longint;var hex:str255);
- const mask=$0000000F;
- var i,dd:integer;
- begin
- hex:='';
- for i:=1 to 8 do
- begin
- dd:=integer(bitand(ll,mask));
- hex:=concat(Copy('0123456789ABCDEF',dd+1,1),hex);
- ll:=bitshift(ll,-4);
- end;
- end;{longtohex}
-
- procedure dumphex{(ll:longint)};
- var ss:str255;
- begin
- longtohex(ll,ss);
- write(ss,' ');
- end;{dumphex}
-
- procedure stripbits(* (source:ptr;
- source_bits_per_item:integer;
- source_bytesize:longint;
- dest:ptr;
- dest_bits_per_item:integer;
- dest_bytesize:longint;
- first_item:longint;
- last_item:longint;
- invert:boolean) *);
-
- {truncate or pad a stream of bits}
- label 99;
- var sbit,dbit:longint;
- sourcebyte:longint;
- destbyte:longint;
- soff,doff:integer;
- i,j,di:longint;
- minbits:integer;
- bit:boolean;
- begin
- if source_bits_per_item<dest_bits_per_item then
- minbits:=source_bits_per_item
- else
- minbits:=dest_bits_per_item;
- minbits:=minbits-1;
- di:=0;{destination item count}
- for i:=first_item-1 to last_item-1 do
- begin
- for j:=0 to minbits do
- begin
- sbit:=j+i*source_bits_per_item;
- dbit:=j+di*dest_bits_per_item;
- sourcebyte:=bsr(sbit,3);
- destbyte:=bsr(dbit,3);
- if sourcebyte<source_bytesize then
- begin
- bit:=bittst(source,sbit);
- if invert then bit:=not bit;
- end
- else
- begin
- bit:=false;
- end;
- if destbyte<dest_bytesize then
- begin
- if bit then
- bitset(dest,dbit)
- else
- bitclr(dest,dbit);
- end
- else
- begin
- goto 99;
- end;
- end;{bit copy loop}
-
- for j:=minbits+1 to dest_bits_per_item-1 do
- begin
- {clear unused bits in destination}
- dbit:=j+di*dest_bits_per_item;
- destbyte:=bsr(dbit,3);
- if destbyte<dest_bytesize then
- begin
- bitclr(dest,dbit);
- end
- else
- begin
- goto 99;
- end;
- end;{bit fill loop}
-
- di:=di+1;{destination item count}
- end;{item loop}
- 99:
- end;
-
-
- procedure bitstream_unpack(*( source:ptr;{input bytes}
- source_item_count:longint;
- source_bits_per_item:integer;{24 or less}
- dest:ptr;{output bytes,words, or longwords}
- dest_max_bytes:longint;
- var dest_item_count:longint;
- dest_bytes_per_item:integer;{1,2,4}
- dest_low_bit_alignment:integer)*);
- {unpack a stream of bits into an array of bytes,words or longint}
- {use high to low left to right coodinates for bits and bytes
- except for dest_low_bit_alignment which is an offset from the right}
- var item:longint;
- startbit,endbit:longint;
- startbyte,endbyte,bytecount:longint;
- destbyte:longint;
- endphase:integer;
- work,destmask:longint;
- sourcestrip,deststrip:longint;{address for pointer arithmetic}
- wptr,outptr:ptr;
- i:longint;
- morephase:integer;
- begin
- destbyte:=0;
-
- {strip address to allow pointer arithmetic}
- sourcestrip:=ord4(stripaddress(source));
- deststrip:=ord4(stripaddress(dest));
-
- {make destination mask}
- destmask:=bsr($FFFFFFFF,32-source_bits_per_item);
- outptr:=pointer(ord(@work)+4-dest_bytes_per_item);{pointer to item to output}
- if source_bits_per_item>1 then
- begin
- {multi bit unpack loop}
- for i:=1 to source_item_count do
- begin
- work:=0;
- {0123456789012345678901234567890123456789 bit count
- 0123456701234567012345670123456701234567 bit from left in byte
- 7654321076543210765432107654321076543210 bit from right in byte
- 0000000011111111222222223333333344444444 byte count
- 111222333444555666777888999000111222333 item count (3 bits per item)
- }
- startbit:=source_bits_per_item*(i-1);
- endbit:=(source_bits_per_item*i)-1;
- startbyte:=bsr(startbit,3);
- { div 8 (round down to byte)}
- endbyte:=bsr(endbit,3);
- {div 8 (round down to byte)}
- endphase:=(bsl(endbyte,3)+7)-endbit;
- {amount needed to right justify to a byte}
- bytecount:=endbyte-startbyte+1;
- morephase:=bsl(4-bytecount,3);
- {amount needed to right justify in longint}
- (* writeln('startbit=',startbit);
- writeln('endbit=',endbit);
- writeln('startbyte=',startbyte);
- writeln('endbyte=',endbyte);
- writeln('bytecount=',bytecount);
- writeln('phase=',endphase,' + ',morephase);*)
-
- wptr:=pointer(sourcestrip+startbyte);
- blockmove(wptr,@work,bytecount);
- (*dumphex(work);
- writeln(work);*)
- work:=bsl(band(bsr(work,endphase+morephase),destmask),dest_low_bit_alignment);
- (*dumphex(work);
- writeln(work);*)
- if destbyte+dest_bytes_per_item<=dest_max_bytes then {??????}
- begin
- dest_item_count:=dest_item_count+1;
- (*writeln('destbyte=',destbyte);*)
- wptr:=pointer(deststrip+destbyte);
- blockmove(outptr,wptr,dest_bytes_per_item);
- end;
- destbyte:=destbyte+dest_bytes_per_item;
- end;{for}
- end{multibit}
- else
- begin
- {single bit unpack loop}
- for i:=1 to source_item_count do
- begin
- startbit:=(i-1);
- if bittst(source,startbit) then work:=1 else work:=0;
- work:=bsl(work,dest_low_bit_alignment);
- {this is a clone of code above:}
- if destbyte+dest_bytes_per_item<=dest_max_bytes then {??????}
- begin
- dest_item_count:=dest_item_count+1;
- wptr:=pointer(deststrip+destbyte);
- blockmove(outptr,wptr,dest_bytes_per_item);
- end;
- destbyte:=destbyte+dest_bytes_per_item;
-
- end;{for}
- end;{singlebit}
- end;{proc bitstream_unpack}
-
- procedure bitstream_pack (*( source:ptr;{input bytes}
- source_item_count:longint;
- source_bytes_per_item:integer;{1,2,4}
- source_low_bit_alignment:integer;
- dest:ptr;{output bytes,words, or longwords}
- dest_max_bytes:longint;
- dest_bits_per_item:integer;{24 or less}
- var dest_item_count:longint) *);
- {quick and dirty version based on the toolbox bit testing routines}
- label 99;
- var item:longint;
- sourcebit,sb,db:longint;
- startoffset,endoffset,source_bits_per_unit:integer;
- destbyte:longint;
- i:longint;
- begin
- dest_item_count:=0;
- {compute offsets within the source units(bytes,words,longwrds)
- for the block of bits to be copied}
-
- source_bits_per_unit:=8*source_bytes_per_item;
- endoffset:=source_bits_per_unit-1-source_low_bit_alignment;
- startoffset:=endoffset-dest_bits_per_item+1;
-
- for i:=1 to source_item_count do
- begin
- (*writeln('item=',i);*)
- sourcebit:=(i-1)*source_bits_per_unit;
- db:=(i-1)*dest_bits_per_item;
- for sb:=sourcebit+startoffset to sourcebit+endoffset do
- begin
- destbyte:=BSR(db,3);
- (*writeln('sb=',sb);
- writeln('db=',db);*)
- if(db<=dest_max_bytes)then
- begin
- if bittst(source,sb) then
- begin
- bitset(dest,db);
- end
- else
- begin
- bitclr(dest,db);
- end
- end
- else
- begin
- goto 99;
- end;
- db:=db+1;
- end;
- dest_item_count:=dest_item_count+1;
- end;
- 99:{breakout}
- end;{proc bitstream_pack}
-
- end.