| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | ! Copyright (C) 2009 Doug Coleman. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | USING: accessors byte-arrays byte-vectors | 
					
						
							|  |  |  | combinators.short-circuit fry io.binary kernel locals math | 
					
						
							|  |  |  | math.bitwise sequences sequences.private ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | IN: bitstreams | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | TUPLE: widthed | 
					
						
							|  |  |  | { bits integer read-only } | 
					
						
							|  |  |  | { #bits integer read-only } ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | ERROR: invalid-widthed bits #bits ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : check-widthed ( bits #bits -- bits #bits )
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  |     2dup { | 
					
						
							|  |  |  |         [ nip 0 < ] | 
					
						
							|  |  |  |         [ { [ nip 0 = ] [ drop 0 = not ] } 2&& ] | 
					
						
							|  |  |  |         [ | 
					
						
							|  |  |  |             swap [ drop f ] [ | 
					
						
							|  |  |  |                 dup 0 < [ neg ] when log2 <=
 | 
					
						
							|  |  |  |             ] if-zero
 | 
					
						
							|  |  |  |         ] | 
					
						
							| 
									
										
										
										
											2015-08-13 19:13:05 -04:00
										 |  |  |     } 2|| [ invalid-widthed ] when ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : <widthed> ( bits #bits -- widthed )
 | 
					
						
							|  |  |  |     check-widthed | 
					
						
							|  |  |  |     widthed boa ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : zero-widthed ( -- widthed ) 0 0 <widthed> ;
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | : zero-widthed? ( widthed -- ? ) zero-widthed = ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | TUPLE: bit-reader | 
					
						
							|  |  |  |     { bytes byte-array } | 
					
						
							|  |  |  |     { byte-pos array-capacity initial: 0 } | 
					
						
							|  |  |  |     { bit-pos array-capacity initial: 0 } ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | TUPLE: msb0-bit-reader < bit-reader ;
 | 
					
						
							|  |  |  | TUPLE: lsb0-bit-reader < bit-reader ;
 | 
					
						
							| 
									
										
										
										
											2009-06-13 19:47:19 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <msb0-bit-reader> ( bytes -- bs )
 | 
					
						
							|  |  |  |     msb0-bit-reader new swap >>bytes ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <lsb0-bit-reader> ( bytes -- bs )
 | 
					
						
							|  |  |  |     lsb0-bit-reader new swap >>bytes ; inline
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | TUPLE: bit-writer | 
					
						
							|  |  |  |     { bytes byte-vector } | 
					
						
							|  |  |  |     { widthed widthed } ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | TUPLE: msb0-bit-writer < bit-writer ;
 | 
					
						
							|  |  |  | TUPLE: lsb0-bit-writer < bit-writer ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | : new-bit-writer ( class -- bs )
 | 
					
						
							|  |  |  |     new
 | 
					
						
							|  |  |  |         BV{ } clone >>bytes | 
					
						
							| 
									
										
										
										
											2011-10-14 15:31:06 -04:00
										 |  |  |         zero-widthed >>widthed ; inline
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : <msb0-bit-writer> ( -- bs )
 | 
					
						
							|  |  |  |     msb0-bit-writer new-bit-writer ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <lsb0-bit-writer> ( -- bs )
 | 
					
						
							|  |  |  |     lsb0-bit-writer new-bit-writer ;
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | GENERIC: peek ( n bitstream -- value )
 | 
					
						
							|  |  |  | GENERIC: poke ( value n bitstream -- )
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | : get-abp ( bitstream -- abp )
 | 
					
						
							| 
									
										
										
										
											2009-06-05 06:26:50 -04:00
										 |  |  |     [ byte-pos>> 8 * ] [ bit-pos>> + ] bi ; inline
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : set-abp ( abp bitstream -- )
 | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |     [ 8 /mod ] dip [ bit-pos<< ] [ byte-pos<< ] bi ; inline
 | 
					
						
							| 
									
										
										
										
											2009-06-05 06:26:50 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : seek ( n bitstream -- )
 | 
					
						
							| 
									
										
										
										
											2009-06-05 06:26:50 -04:00
										 |  |  |     [ get-abp + ] [ set-abp ] bi ; inline
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 06:26:50 -04:00
										 |  |  | : (align) ( n m -- n' )
 | 
					
						
							| 
									
										
										
										
											2009-08-13 20:21:44 -04:00
										 |  |  |     [ /mod 0 > [ 1 + ] when ] [ * ] bi ; inline
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-06-05 06:26:50 -04:00
										 |  |  | : align ( n bitstream -- )
 | 
					
						
							|  |  |  |     [ get-abp swap (align) ] [ set-abp ] bi ; inline
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : read ( n bitstream -- value )
 | 
					
						
							|  |  |  |     [ peek ] [ seek ] 2bi ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | <PRIVATE
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-08-13 06:20:39 -04:00
										 |  |  | ERROR: not-enough-widthed-bits widthed n ;
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | : check-widthed-bits ( widthed n -- widthed n )
 | 
					
						
							|  |  |  |     2dup { [ nip 0 < ] [ [ #bits>> ] dip < ] } 2|| | 
					
						
							| 
									
										
										
										
											2015-08-13 19:13:05 -04:00
										 |  |  |     [ not-enough-widthed-bits ] when ;
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : widthed-bits ( widthed n -- bits )
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  |     check-widthed-bits | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  |     [ [ bits>> ] [ #bits>> ] bi ] dip
 | 
					
						
							|  |  |  |     [ - neg shift ] keep <widthed> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : split-widthed ( widthed n -- widthed1 widthed2 )
 | 
					
						
							|  |  |  |     2dup [ #bits>> ] dip < [ | 
					
						
							|  |  |  |         drop zero-widthed | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  |         [ widthed-bits ] | 
					
						
							|  |  |  |         [ [ [ bits>> ] [ #bits>> ] bi ] dip - [ bits ] keep <widthed> ] 2bi
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | : widthed>bytes ( widthed -- bytes widthed )
 | 
					
						
							|  |  |  |     [ 8 split-widthed dup zero-widthed? not ] | 
					
						
							|  |  |  |     [ swap bits>> ] B{ } produce-as nip swap ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | :: |widthed ( widthed1 widthed2 -- widthed3 )
 | 
					
						
							|  |  |  |     widthed1 bits>> :> bits1 | 
					
						
							|  |  |  |     widthed1 #bits>> :> #bits1 | 
					
						
							|  |  |  |     widthed2 bits>> :> bits2 | 
					
						
							|  |  |  |     widthed2 #bits>> :> #bits2 | 
					
						
							|  |  |  |     bits1 #bits2 shift bits2 bitor
 | 
					
						
							|  |  |  |     #bits1 #bits2 + <widthed> ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | PRIVATE>
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  | M:: lsb0-bit-writer poke ( value n bs -- )
 | 
					
						
							|  |  |  |     value n <widthed> :> widthed | 
					
						
							|  |  |  |     widthed | 
					
						
							| 
									
										
										
										
											2009-10-28 17:11:33 -04:00
										 |  |  |     bs widthed>> #bits>> 8 swap - split-widthed :> ( byte remainder )
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     byte bs widthed>> |widthed :> new-byte | 
					
						
							| 
									
										
										
										
											2009-05-15 15:59:26 -04:00
										 |  |  |     new-byte #bits>> 8 = [ | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |         new-byte bits>> bs bytes>> push
 | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         zero-widthed bs widthed<< | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  |         remainder widthed>bytes | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         [ bs bytes>> push-all ] [ bs widthed<< ] bi*
 | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         byte bs widthed<< | 
					
						
							| 
									
										
										
										
											2009-05-14 16:44:57 -04:00
										 |  |  |     ] if ;
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | : enough-bits? ( n bs -- ? )
 | 
					
						
							|  |  |  |     [ bytes>> length ] | 
					
						
							|  |  |  |     [ byte-pos>> - 8 * ] | 
					
						
							|  |  |  |     [ bit-pos>> - ] tri <= ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERROR: not-enough-bits n bit-reader ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : #bits>#bytes ( #bits -- #bytes )
 | 
					
						
							|  |  |  |     8 /mod 0 = [ 1 + ] unless ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 15:08:56 -04:00
										 |  |  | :: subseq>bits-le ( bignum n bs -- bits )
 | 
					
						
							|  |  |  |     bignum bs bit-pos>> neg shift n bits ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: subseq>bits-be ( bignum n bs -- bits )
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  |     bignum
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     8 bs bit-pos>> - n - 8 mod dup 0 < [ 8 + ] when
 | 
					
						
							|  |  |  |     neg shift n bits ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: adjust-bits ( n bs -- )
 | 
					
						
							| 
									
										
										
										
											2009-10-28 17:11:33 -04:00
										 |  |  |     n 8 /mod :> ( #bytes #bits )
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     bs [ #bytes + ] change-byte-pos | 
					
						
							|  |  |  |     bit-pos>> #bits + dup 8 >= [ | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         8 - bs bit-pos<< | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |         bs [ 1 + ] change-byte-pos drop
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2010-05-05 16:52:54 -04:00
										 |  |  |         bs bit-pos<< | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-05-15 15:08:56 -04:00
										 |  |  | :: (peek) ( n bs endian> subseq-endian -- bits )
 | 
					
						
							| 
									
										
										
										
											2015-08-13 19:13:05 -04:00
										 |  |  |     n bs enough-bits? [ n bs not-enough-bits ] unless
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     bs [ byte-pos>> ] [ bit-pos>> n + ] bi #bits>#bytes dupd +
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  |     bs bytes>> subseq endian> execute( seq -- x ) | 
					
						
							|  |  |  |     n bs subseq-endian execute( bignum n bs -- bits ) ;
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | M: lsb0-bit-reader peek ( n bs -- bits )
 | 
					
						
							|  |  |  |     \ le> \ subseq>bits-le (peek) ;
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  | M: msb0-bit-reader peek ( n bs -- bits )
 | 
					
						
							|  |  |  |     \ be> \ subseq>bits-be (peek) ;
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  | :: bit-writer-bytes ( writer -- bytes )
 | 
					
						
							|  |  |  |     writer widthed>> #bits>> :> n | 
					
						
							|  |  |  |     n 0 = [ | 
					
						
							|  |  |  |         writer widthed>> bits>> 8 n - shift
 | 
					
						
							| 
									
										
										
										
											2014-12-15 22:28:24 -05:00
										 |  |  |         writer bytes>> push
 | 
					
						
							| 
									
										
										
										
											2009-05-15 00:33:00 -04:00
										 |  |  |     ] unless
 | 
					
						
							|  |  |  |     writer bytes>> ;
 | 
					
						
							| 
									
										
										
										
											2009-06-03 22:21:51 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-24 00:28:38 -04:00
										 |  |  | :: byte-array-n>sequence ( byte-array n -- seq )
 | 
					
						
							| 
									
										
										
										
											2017-06-01 17:59:35 -04:00
										 |  |  |     byte-array length 8 * n / <iota> | 
					
						
							| 
									
										
										
										
											2009-06-03 22:21:51 -04:00
										 |  |  |     byte-array <msb0-bit-reader> '[ | 
					
						
							|  |  |  |         drop n _ read
 | 
					
						
							|  |  |  |     ] { } map-as ;
 |