| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | ! Copyright (C) 2009 Doug Coleman. | 
					
						
							|  |  |  | ! See http://factorcode.org/license.txt for BSD license. | 
					
						
							|  |  |  | USING: accessors byte-arrays destructors fry io kernel locals | 
					
						
							|  |  |  | math sequences ;
 | 
					
						
							|  |  |  | IN: bitstreams | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  | TUPLE: bitstream stream end-of-stream? current-bits #bits disposed ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | TUPLE: bitstream-reader < bitstream ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : reset-bitstream ( stream -- stream )
 | 
					
						
							|  |  |  |     0 >>#bits 0 >>current-bits ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : new-bitstream ( stream class -- bitstream )
 | 
					
						
							|  |  |  |     new
 | 
					
						
							|  |  |  |         swap >>stream | 
					
						
							|  |  |  |         reset-bitstream ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | M: bitstream-reader dispose ( stream -- )
 | 
					
						
							|  |  |  |     stream>> dispose ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <bitstream-reader> ( stream -- bitstream )
 | 
					
						
							|  |  |  |     bitstream-reader new-bitstream ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : read-next-byte ( bitstream -- bitstream )
 | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  |     dup stream>> stream-read1 [ | 
					
						
							|  |  |  |         >>current-bits 8 >>#bits | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         0 >>#bits | 
					
						
							|  |  |  |         t >>end-of-stream? | 
					
						
							|  |  |  |     ] if* ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | : maybe-read-next-byte ( bitstream -- bitstream )
 | 
					
						
							|  |  |  |     dup #bits>> 0 = [ read-next-byte ] when ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : shift-one-bit ( bitstream -- n )
 | 
					
						
							|  |  |  |     [ current-bits>> ] [ #bits>> ] bi 1- neg shift 1 bitand ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  | : next-bit ( bitstream -- n/f ? )
 | 
					
						
							|  |  |  |     maybe-read-next-byte | 
					
						
							|  |  |  |     dup end-of-stream?>> [ | 
					
						
							|  |  |  |         drop f
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  |     ] [ | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  |         [ shift-one-bit ] | 
					
						
							|  |  |  |         [ [ 1- ] change-#bits maybe-read-next-byte drop ] bi
 | 
					
						
							|  |  |  |     ] if dup >boolean ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  | : read-bit ( bitstream -- n ? )
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  |     dup #bits>> 1 = [ | 
					
						
							|  |  |  |         [ current-bits>> 1 bitand ] | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  |         [ read-next-byte drop ] bi t
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  |     ] [ | 
					
						
							|  |  |  |         next-bit | 
					
						
							|  |  |  |     ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : bits>integer ( seq -- n )
 | 
					
						
							|  |  |  |     0 [ [ 1 shift ] dip bitor ] reduce ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-12 23:10:32 -05:00
										 |  |  | : read-bits ( width bitstream -- n width ? )
 | 
					
						
							|  |  |  |     [ | 
					
						
							|  |  |  |         '[ _ read-bit drop ] replicate
 | 
					
						
							|  |  |  |         [ f = ] trim-tail
 | 
					
						
							|  |  |  |         [ bits>integer ] [ length ] bi
 | 
					
						
							|  |  |  |     ] 2keep drop over = ;
 | 
					
						
							| 
									
										
										
										
											2009-02-12 18:44:43 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | TUPLE: bitstream-writer < bitstream ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : <bitstream-writer> ( stream -- bitstream )
 | 
					
						
							|  |  |  |     bitstream-writer new-bitstream ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : write-bit ( n bitstream -- )
 | 
					
						
							|  |  |  |     [ 1 shift bitor ] change-current-bits | 
					
						
							|  |  |  |     [ 1+ ] change-#bits | 
					
						
							|  |  |  |     dup #bits>> 8 = [ | 
					
						
							|  |  |  |         [ [ current-bits>> ] [ stream>> stream-write1 ] bi ] | 
					
						
							|  |  |  |         [ reset-bitstream drop ] bi
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         drop
 | 
					
						
							|  |  |  |     ] if ; inline
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | ERROR: invalid-bit-width n ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :: write-bits ( n width bitstream -- )
 | 
					
						
							|  |  |  |     n 0 < [ n invalid-bit-width ] when
 | 
					
						
							|  |  |  |     n 0 = [ | 
					
						
							|  |  |  |         width [ 0 bitstream write-bit ] times
 | 
					
						
							|  |  |  |     ] [ | 
					
						
							|  |  |  |         width n log2 1+ dup :> n-length - [ 0 bitstream write-bit ] times
 | 
					
						
							|  |  |  |         n-length [ | 
					
						
							|  |  |  |             n-length swap - 1- neg n swap shift 1 bitand
 | 
					
						
							|  |  |  |             bitstream write-bit | 
					
						
							|  |  |  |         ] each
 | 
					
						
							|  |  |  |     ] if ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : flush-bits ( bitstream -- ) stream>> stream-flush ;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | : bitstream-output ( bitstream -- bytes ) stream>> >byte-array ;
 |