@@ -31,24 +31,39 @@ typedef struct
3131
3232/** @brief Initialize buffer object from memory
3333 * @param[in] buffer Decompression buffer object
34- * @param[in] data Data to buffer
34+ * @param[in] data Data to emulate buffering
3535 * @param[in] size Data size
3636 */
3737static inline void
3838buffer_memory (buffer_t * buffer , const void * data , size_t size )
3939{
40- buffer -> data = (void * )data ;
41- buffer -> size = size ;
42- buffer -> pos = 0 ;
40+ buffer -> data = (void * )data ;
41+ buffer -> limit = size ;
42+ buffer -> size = size ;
43+ buffer -> pos = 0 ;
44+ }
45+
46+ /** @brief Initialize buffer object with static memory
47+ * @param[in] buffer Decompression buffer object
48+ * @param[in] data Data buffer
49+ * @param[in] size Data size
50+ */
51+ static inline void
52+ buffer_static (buffer_t * buffer , const void * data , size_t size )
53+ {
54+ buffer -> data = (void * )data ;
55+ buffer -> limit = size ;
56+ buffer -> size = 0 ;
57+ buffer -> pos = 0 ;
4358}
4459
45- /** @brief Initialize buffer object
60+ /** @brief Initialize buffer object with dynamic memory
4661 * @param[in] buffer Decompression buffer object
4762 * @param[in] size Buffer size limit
4863 * @returns Whether succeeded
4964 */
5065static inline bool
51- buffer_init (buffer_t * buffer , size_t size )
66+ buffer_dynamic (buffer_t * buffer , size_t size )
5267{
5368 buffer -> data = (uint8_t * )malloc (size );
5469 if (!buffer -> data )
@@ -498,6 +513,7 @@ decompress_lz11(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt,
498513}
499514
500515/** @brief Decompress Huffman
516+ * @param[in] bits Data size in bits (usually 4 or 8)
501517 * @param[in] buffer Decompression buffer object
502518 * @param[in] iov Output vector
503519 * @param[in] iovcnt Number of buffers
@@ -507,9 +523,13 @@ decompress_lz11(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt,
507523 * @returns Whether succeeded
508524 */
509525static bool
510- decompress_huff (buffer_t * buffer , const decompressIOVec * iov , size_t iovcnt ,
511- size_t size , decompressCallback callback , void * userdata )
526+ decompress_huff (const size_t bits , buffer_t * buffer , const decompressIOVec * iov ,
527+ size_t iovcnt , size_t size , decompressCallback callback ,
528+ void * userdata )
512529{
530+ if (bits < 1 || bits > 8 )
531+ return false;
532+
513533 uint8_t * tree = (uint8_t * )malloc (512 );
514534 if (!tree )
515535 return false;
@@ -528,14 +548,13 @@ decompress_huff(buffer_t *buffer, const decompressIOVec *iov, size_t iovcnt,
528548 return false;
529549 }
530550
531- iov_iter out = iov_begin (iov , iovcnt );
532- const size_t bits = 8 ;
533- uint32_t word = 0 ; // 32-bits of input bitstream
534- uint32_t mask = 0 ; // which bit we are reading
535- uint32_t dataMask = (1 <<bits )- 1 ; // mask to apply to data
536- size_t node ; // node in the huffman tree
537- size_t child ; // child of a node
538- uint32_t offset ; // offset from node to child
551+ iov_iter out = iov_begin (iov , iovcnt );
552+ uint32_t word = 0 ; // 32-bits of input bitstream
553+ uint32_t mask = 0 ; // which bit we are reading
554+ uint8_t dataMask = (1 <<bits )- 1 ; // mask to apply to data
555+ size_t node ; // node in the huffman tree
556+ size_t child ; // child of a node
557+ uint32_t offset ; // offset from node to child
539558
540559 // point to the root of the huffman tree
541560 node = 1 ;
@@ -686,45 +705,67 @@ decompressCallback_Stdio(void *userdata, void *buffer, size_t size)
686705 return fread (buffer , 1 , size , fp );
687706}
688707
689- bool
690- decompressV ( const decompressIOVec * iov , size_t iovcnt ,
691- decompressCallback callback , void * userdata , size_t usersize )
708+ ssize_t
709+ decompressHeader ( decompressType * type , size_t * size ,
710+ decompressCallback callback , void * userdata , size_t insize )
692711{
693- if (iovcnt == 0 )
694- return false;
695-
696712 buffer_t buffer ;
713+ uint8_t bufferdata [4 ];
697714 if (!callback )
698- buffer_memory (& buffer , userdata , usersize );
699- else if (! buffer_init ( & buffer , BUFFERSIZE ))
700- return false ;
715+ buffer_memory (& buffer , userdata , insize );
716+ else
717+ buffer_static ( & buffer , bufferdata , sizeof ( bufferdata )) ;
701718
702- uint8_t header [8 ];
719+ uint8_t header [4 ];
703720 if (!buffer_read (& buffer , header , 4 , callback , userdata ))
721+ return -1 ;
722+
723+ size_t bytes = 4 ;
724+
725+ decompressType outtype = header [0 ] & ~0x80 ;
726+ size_t outsize = (header [1 ] << 0 )
727+ | (header [2 ] << 8 )
728+ | (header [3 ] << 16 );
729+
730+ if (header [0 ] & 0x80 )
704731 {
705- if (callback )
706- buffer_destroy (& buffer );
707- return false;
732+ if (!buffer_read (& buffer , header , 4 , callback , userdata ))
733+ return -1 ;
734+
735+ bytes += 4 ;
736+ outsize |= header [0 ] << 24 ;
708737 }
709738
710- uint8_t type = header [ 0 ];
711- size_t size = ( header [ 1 ] << 0 )
712- | ( header [ 2 ] << 8 )
713- | ( header [ 3 ] << 16 ) ;
739+ if ( type )
740+ * type = outtype ;
741+ if ( size )
742+ * size = outsize ;
714743
715- if (type & 0x80 )
716- {
717- type &= ~0x80 ;
744+ return bytes ;
745+ }
718746
719- if (! buffer_read ( & buffer , & header [ 4 ], 4 , callback , userdata ))
720- {
721- if ( callback )
722- buffer_destroy ( & buffer );
723- return false;
724- }
747+ bool
748+ decompressV ( const decompressIOVec * iov , size_t iovcnt ,
749+ decompressCallback callback , void * userdata , size_t insize )
750+ {
751+ if ( iovcnt == 0 )
752+ return false;
725753
726- size |= header [4 ] << 24 ;
754+ decompressType type ;
755+ size_t size ;
756+ ssize_t bytes = decompressHeader (& type , & size , callback , userdata , insize );
757+ if (bytes < 0 )
758+ return false;
759+
760+ buffer_t buffer ;
761+ if (!callback )
762+ {
763+ userdata = (uint8_t * )userdata + bytes ;
764+ insize -= bytes ;
765+ buffer_memory (& buffer , userdata , insize );
727766 }
767+ else if (!buffer_dynamic (& buffer , BUFFERSIZE ))
768+ return false;
728769
729770 size_t iovsize = iov_size (iov , iovcnt );
730771 if (iovsize < size )
@@ -733,26 +774,34 @@ decompressV(const decompressIOVec *iov, size_t iovcnt,
733774 bool result = false;
734775 switch (type )
735776 {
736- case 0x00 :
777+ case DECOMPRESS_DUMMY :
737778 {
738779 iov_iter out = iov_begin (iov , iovcnt );
739780 result = iov_read (& buffer , & out , size , callback , userdata );
740781 break ;
741782 }
742783
743- case 0x10 :
784+ case DECOMPRESS_LZSS :
744785 result = decompress_lzss (& buffer , iov , iovcnt , size , callback , userdata );
745786 break ;
746787
747- case 0x11 :
788+ case DECOMPRESS_LZ11 :
748789 result = decompress_lz11 (& buffer , iov , iovcnt , size , callback , userdata );
749790 break ;
750791
751- case 0x28 :
752- result = decompress_huff (& buffer , iov , iovcnt , size , callback , userdata );
792+ case DECOMPRESS_HUFF1 :
793+ case DECOMPRESS_HUFF2 :
794+ case DECOMPRESS_HUFF3 :
795+ case DECOMPRESS_HUFF4 :
796+ case DECOMPRESS_HUFF5 :
797+ case DECOMPRESS_HUFF6 :
798+ case DECOMPRESS_HUFF7 :
799+ case DECOMPRESS_HUFF8 :
800+ result = decompress_huff (type & 0xF , & buffer , iov , iovcnt , size ,
801+ callback , userdata );
753802 break ;
754803
755- case 0x30 :
804+ case DECOMPRESS_RLE :
756805 result = decompress_rle (& buffer , iov , iovcnt , size , callback , userdata );
757806 break ;
758807 }
@@ -764,12 +813,12 @@ decompressV(const decompressIOVec *iov, size_t iovcnt,
764813
765814bool
766815decompressV_LZSS (const decompressIOVec * iov , size_t iovcnt ,
767- decompressCallback callback , void * userdata , size_t usersize )
816+ decompressCallback callback , void * userdata , size_t insize )
768817{
769818 buffer_t buffer ;
770819 if (!callback )
771- buffer_memory (& buffer , userdata , usersize );
772- else if (!buffer_init (& buffer , BUFFERSIZE ))
820+ buffer_memory (& buffer , userdata , insize );
821+ else if (!buffer_dynamic (& buffer , BUFFERSIZE ))
773822 return false;
774823
775824 size_t size = iov_size (iov , iovcnt );
@@ -782,12 +831,12 @@ decompressV_LZSS(const decompressIOVec *iov, size_t iovcnt,
782831
783832bool
784833decompressV_LZ11 (const decompressIOVec * iov , size_t iovcnt ,
785- decompressCallback callback , void * userdata , size_t usersize )
834+ decompressCallback callback , void * userdata , size_t insize )
786835{
787836 buffer_t buffer ;
788837 if (!callback )
789- buffer_memory (& buffer , userdata , usersize );
790- else if (!buffer_init (& buffer , BUFFERSIZE ))
838+ buffer_memory (& buffer , userdata , insize );
839+ else if (!buffer_dynamic (& buffer , BUFFERSIZE ))
791840 return false;
792841
793842 size_t size = iov_size (iov , iovcnt );
@@ -799,17 +848,17 @@ decompressV_LZ11(const decompressIOVec *iov, size_t iovcnt,
799848}
800849
801850bool
802- decompressV_Huff (const decompressIOVec * iov , size_t iovcnt ,
803- decompressCallback callback , void * userdata , size_t usersize )
851+ decompressV_Huff (size_t bits , const decompressIOVec * iov , size_t iovcnt ,
852+ decompressCallback callback , void * userdata , size_t insize )
804853{
805854 buffer_t buffer ;
806855 if (!callback )
807- buffer_memory (& buffer , userdata , usersize );
808- else if (!buffer_init (& buffer , BUFFERSIZE ))
856+ buffer_memory (& buffer , userdata , insize );
857+ else if (!buffer_dynamic (& buffer , BUFFERSIZE ))
809858 return false;
810859
811860 size_t size = iov_size (iov , iovcnt );
812- bool result = decompress_huff (& buffer , iov , iovcnt , size , callback , userdata );
861+ bool result = decompress_huff (bits , & buffer , iov , iovcnt , size , callback , userdata );
813862
814863 if (callback )
815864 buffer_destroy (& buffer );
@@ -818,12 +867,12 @@ decompressV_Huff(const decompressIOVec *iov, size_t iovcnt,
818867
819868bool
820869decompressV_RLE (const decompressIOVec * iov , size_t iovcnt ,
821- decompressCallback callback , void * userdata , size_t usersize )
870+ decompressCallback callback , void * userdata , size_t insize )
822871{
823872 buffer_t buffer ;
824873 if (!callback )
825- buffer_memory (& buffer , userdata , usersize );
826- else if (!buffer_init (& buffer , BUFFERSIZE ))
874+ buffer_memory (& buffer , userdata , insize );
875+ else if (!buffer_dynamic (& buffer , BUFFERSIZE ))
827876 return false;
828877
829878 size_t size = iov_size (iov , iovcnt );
0 commit comments