Advertisement
Guest User

mini deflate

a guest
Aug 21st, 2015
174
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 31.42 KB | None | 0 0
  1. /*
  2. Copyright (c) 2015, Ralf Willenbacher
  3. All rights reserved.
  4.  
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions
  7. are met:
  8.  
  9. 1. Redistributions of source code must retain the above copyright
  10.    notice, this list of conditions and the following disclaimer.
  11.  
  12. 2. Redistributions in binary form must reproduce the above copyright
  13.    notice, this list of conditions and the following disclaimer in
  14.    the documentation and/or other materials provided with the
  15.    distribution.
  16.  
  17. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  23. BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25. CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26. LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  27. ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  28. POSSIBILITY OF SUCH DAMAGE.
  29. */
  30.  
  31. #include <stdlib.h>
  32. #include <stdio.h>
  33. #include <stdint.h>
  34. #include <memory.h>
  35.  
  36. #define MDEFLATE_DEBUG_PRINTF 0
  37. #define WITH_LITERAL_ONLY_TREE 1
  38.  
  39. #define MDEFLATE_MAX_LITERAL_NODE   15
  40. #define MDEFLATE_MAX_LITERAL_NODES  16
  41. #define MDEFLATE_END_OF_BLOCK_NODE  16
  42. #define MDEFLATE_LENGTH_NODES_OFFSET ( MDEFLATE_END_OF_BLOCK_NODE + 1 )
  43. #define MDEFLATE_MAX_LENGTH_NODES    8
  44. #define MDEFLATE_MATCH_LENGTH_OFFSET 3
  45. #define MDEFLATE_MAX_MATCH_LENGTH  256
  46. #define MDEFLATE_MAX_SYMBOL_NODES ( MDEFLATE_END_OF_BLOCK_NODE + MDEFLATE_MAX_LENGTH_NODES + 1 )
  47. #define MDEFLATE_MAX_OFFSET_NODES  32
  48. #define MDEFLATE_MAX_CODEBOOK_BACK ( 1 << 14 )
  49.  
  50. #define MDEFLATE_BLOCK_SIZE ( 1 << 14 )
  51. #define MDEFLATE_MAX_CW_LENGTH 8
  52.  
  53. #define MDEFLATE_MAX_BL_NODES ( MDEFLATE_MAX_CW_LENGTH + 1 )
  54. #define MDEFLATE_MAX_BL_CW_LENGTH 7
  55.  
  56.  
  57. /* ------------------------ COMPRESS ------------------------ */
  58.  
  59.  
  60. typedef struct {
  61.     int32_t i_cw;
  62.     int32_t i_cw_length;
  63.     int32_t i_count;
  64.     int32_t i_order;
  65. } encnode_t;
  66.  
  67. typedef struct treenode_s {
  68.     int32_t i_order;
  69.     int32_t i_count;
  70.     struct treenode_s *ps_parent;
  71.     struct treenode_s *rgps_children[ 2 ];
  72. } treenode_t;
  73.  
  74. typedef struct {
  75.     int32_t i_max_codebook_back;
  76.     int32_t i_codebook_back;
  77.     int32_t i_max_match_length;
  78.     encnode_t rgs_symbol_nodes[ MDEFLATE_MAX_SYMBOL_NODES ];
  79. #if WITH_LITERAL_ONLY_TREE
  80.     encnode_t rgs_literal_nodes[ MDEFLATE_MAX_LITERAL_NODES ];
  81. #endif
  82.     encnode_t rgs_offset_nodes[ MDEFLATE_MAX_OFFSET_NODES ];
  83.     encnode_t rgs_bl_nodes[ MDEFLATE_MAX_BL_NODES ];
  84.     int32_t i_treenode_alloc;
  85.     treenode_t s_headnode;
  86.     treenode_t rgs_treenodes[ 64 * 2 ];
  87.     int32_t i_max_depth;
  88.  
  89.     int32_t i_num_overflow;
  90.     int32_t rgi_cw_length_counts[ MDEFLATE_MAX_CW_LENGTH + 1 ];
  91.  
  92.     int32_t i_symbol_count;
  93.     uint8_t rgui8_symbols[ MDEFLATE_BLOCK_SIZE + 1 ];
  94.     int32_t i_length_and_offset_count;
  95.     int32_t rgi_length_and_offset[ MDEFLATE_BLOCK_SIZE + 1 ];
  96.  
  97.     uint32_t ui_cw;
  98.     int32_t i_cw_bits;
  99.     int32_t i_bitstream_size;
  100.     uint8_t *pui8_bitstream;
  101.  
  102.     uint8_t rgui8_offset_lut[ MDEFLATE_MAX_CODEBOOK_BACK ];
  103.     uint32_t rgui_offset_offset[ MDEFLATE_MAX_CODEBOOK_BACK ];
  104.     uint8_t rgui8_length_lut[ MDEFLATE_MAX_MATCH_LENGTH ];
  105.     uint32_t rgui_length_offset[ MDEFLATE_MAX_MATCH_LENGTH ];
  106. } mdeflate_compress_t;
  107.  
  108. const int32_t rgi_length_extra[ MDEFLATE_MAX_LENGTH_NODES ] = { 0, 1, 2, 3, 4, 5, 6, 7 };
  109. const int32_t rgi_offset_extra[ MDEFLATE_MAX_OFFSET_NODES ] = { 0, 1, 2, 4, 6, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
  110.  
  111.  
  112. void mdeflate_write_bits( mdeflate_compress_t *ps_compress, int32_t i_cw, int32_t i_cw_length )
  113. {
  114.     ps_compress->ui_cw |= i_cw << ( 32 - i_cw_length - ps_compress->i_cw_bits );
  115.     ps_compress->i_cw_bits += i_cw_length;
  116.  
  117.     while( ps_compress->i_cw_bits >= 8 )
  118.     {
  119.         ps_compress->pui8_bitstream[ ps_compress->i_bitstream_size++ ] = ps_compress->ui_cw >> 24;
  120.         ps_compress->ui_cw <<= 8;
  121.         ps_compress->i_cw_bits -= 8;
  122.     }
  123. }
  124.  
  125.  
  126. void mdeflate_init_length_and_offset_table( mdeflate_compress_t *ps_compress )
  127. {
  128.     int32_t i_offset_symbol_idx, i_offset, i_idx, i_offset_size, i_length, i_length_size, i_length_symbol_idx;
  129.  
  130.     i_offset = 0;
  131.     for( i_offset_symbol_idx = 0; i_offset_symbol_idx < MDEFLATE_MAX_OFFSET_NODES; i_offset_symbol_idx++ )
  132.     {
  133.         ps_compress->rgui_offset_offset[ i_offset_symbol_idx ] = i_offset;
  134.         i_offset_size = 1 << rgi_offset_extra[ i_offset_symbol_idx ];
  135.         for( i_idx = 0; i_idx < i_offset_size; i_idx++ )
  136.         {
  137.             ps_compress->rgui8_offset_lut[ i_offset++ ] = i_offset_symbol_idx;
  138.         }
  139.     }
  140.  
  141.     i_length = 0;
  142.     for( i_length_symbol_idx = 0; i_length_symbol_idx < MDEFLATE_MAX_LENGTH_NODES; i_length_symbol_idx++ )
  143.     {
  144.         ps_compress->rgui_length_offset[ i_length_symbol_idx ] = i_length;
  145.         i_length_size = 1 << rgi_length_extra[ i_length_symbol_idx ];
  146.         for( i_idx = 0; i_idx < i_length_size; i_idx++ )
  147.         {
  148.             ps_compress->rgui8_length_lut[ i_length++ ] = i_length_symbol_idx;
  149.         }
  150.     }
  151.  
  152.     ps_compress->i_max_codebook_back = i_offset - 1;
  153.     ps_compress->i_max_match_length = i_length - 1;
  154. #if MDEFLATE_DEBUG_PRINTF > 0
  155.     printf("max codebook back: %d, max match length: %d\n", ps_compress->i_max_codebook_back, ps_compress->i_max_match_length );
  156. #endif
  157. }
  158.  
  159.  
  160. void mdeflate_assign_cw_r( mdeflate_compress_t *ps_compress, treenode_t *ps_treenode, int32_t i_depth )
  161. {
  162.     if( i_depth > ps_compress->i_max_depth )
  163.     {
  164.         ps_compress->i_num_overflow++;
  165.     }
  166.  
  167.     if( ps_treenode->i_order >= 0 )
  168.     {
  169.         if( i_depth > ps_compress->i_max_depth )
  170.         {
  171.             ps_compress->rgi_cw_length_counts[ ps_compress->i_max_depth ]++;
  172.         }
  173.         else
  174.         {
  175.             ps_compress->rgi_cw_length_counts[ i_depth ]++;
  176.         }
  177.     }
  178.     else
  179.     {
  180.         mdeflate_assign_cw_r( ps_compress, ps_treenode->rgps_children[ 0 ], i_depth + 1 );
  181.         mdeflate_assign_cw_r( ps_compress, ps_treenode->rgps_children[ 1 ], i_depth + 1 );
  182.     }
  183. }
  184.  
  185. int32_t mdeflate_construct_tree( mdeflate_compress_t *ps_compress, encnode_t *ps_nodes, int32_t i_num_nodes, int32_t i_max_cw_length )
  186. {
  187.     int32_t i_node, i_non_zero, i_last_non_zero, i_highest, i_highest_count, i_order_zero, i_idx, i_osearch, i_order;
  188.  
  189.     i_non_zero = 0;
  190.     for( i_node = 0; i_node < i_num_nodes; i_node++ )
  191.     {
  192.         ps_nodes[ i_node ].i_cw = 0;
  193.         ps_nodes[ i_node ].i_cw_length = 0;
  194.         ps_nodes[ i_node ].i_order = -1;
  195.         if( ps_nodes[ i_node ].i_count > 0 )
  196.         {
  197.             i_non_zero++;
  198.             i_last_non_zero = i_node;
  199.         }
  200.     }
  201.     for( i_idx = 0; i_idx <= ps_compress->i_max_depth; i_idx++ )
  202.     {
  203.         ps_compress->rgi_cw_length_counts[ i_idx ] = 0;
  204.     }
  205.  
  206.     memset( ps_compress->rgs_treenodes, 0, sizeof( ps_compress->rgs_treenodes ) );
  207.    
  208.     ps_compress->i_max_depth = i_max_cw_length;
  209.  
  210.     if( i_non_zero == 0 )
  211.     {
  212.         return 0; /* offset nodes without match */
  213.     }
  214.  
  215.     if( i_non_zero == 1 ) /* force at least 2 nodes */
  216.     {
  217.         if( i_last_non_zero < i_num_nodes - 1 )
  218.         {
  219.             ps_nodes[ i_num_nodes - 1 ].i_count = 1;
  220.         }
  221.         else
  222.         {
  223.             ps_nodes[ i_num_nodes - 2 ].i_count = 1;
  224.         }
  225.         i_non_zero++;
  226.     }
  227.    
  228.     for( i_idx = 0; i_idx < i_non_zero; i_idx++ )
  229.     {
  230.         i_highest = -1;
  231.         i_highest_count = 0;
  232.         for( i_node = 0; i_node < i_num_nodes; i_node++ )
  233.         {
  234.             if( ps_nodes[ i_node ].i_order < 0 && ps_nodes[ i_node ].i_count > i_highest_count )
  235.             {
  236.                 i_highest_count = ps_nodes[ i_node ].i_count;
  237.                 i_highest = i_node;
  238.             }
  239.         }
  240.         if( i_highest < 0 )
  241.         {
  242.             fprintf( stderr, "order sorting failure\n");
  243.             exit( -1 );
  244.         }
  245.         ps_nodes[ i_highest ].i_order = i_idx;
  246.         if( i_idx == 0 )
  247.         {
  248.             i_order_zero = i_highest;
  249.         }
  250.     }
  251.  
  252.     ps_compress->s_headnode.rgps_children[ 0 ] = &ps_compress->rgs_treenodes[ 0 ];
  253.     ps_compress->s_headnode.rgps_children[ 1 ] = NULL;
  254.     ps_compress->rgs_treenodes[ 0 ].i_order = 0;
  255.     ps_compress->rgs_treenodes[ 0 ].i_count = ps_nodes[ i_order_zero ].i_count;
  256.     ps_compress->rgs_treenodes[ 0 ].ps_parent = &ps_compress->s_headnode;
  257.     ps_compress->i_treenode_alloc = 1;
  258.  
  259.     for( i_idx = 1; i_idx < i_non_zero; i_idx++ )
  260.     {
  261.         treenode_t *ps_treenode, *ps_new_branch, *ps_tree, *ps_parent;
  262.         for( i_node = 0; i_node < i_num_nodes; i_node++ )
  263.         {
  264.             if( ps_nodes[ i_node ].i_order == i_idx )
  265.             {
  266.                 break;
  267.             }
  268.         }
  269.  
  270.         ps_treenode = &ps_compress->rgs_treenodes[ ps_compress->i_treenode_alloc++ ];
  271.         ps_new_branch = &ps_compress->rgs_treenodes[ ps_compress->i_treenode_alloc++ ];
  272.  
  273.         ps_treenode->i_order = i_idx;
  274.         ps_treenode->i_count = ps_nodes[ i_node ].i_count;
  275.         ps_new_branch->i_order = -1;
  276.         ps_new_branch->rgps_children[ 1 ] = ps_treenode;
  277.         ps_treenode->ps_parent = ps_new_branch;
  278.  
  279.         ps_tree = ps_compress->s_headnode.rgps_children[ 0 ];
  280.         while( ps_tree->i_order < 0 && ps_tree->i_count > ps_treenode->i_count )
  281.         {
  282.             ps_tree = ps_tree->rgps_children[ 1 ];
  283.         }
  284.         ps_new_branch->ps_parent = ps_tree->ps_parent;
  285.         ps_new_branch->rgps_children[ 0 ] = ps_tree;
  286.         ps_tree->ps_parent = ps_new_branch;
  287.  
  288.         if( ps_new_branch->ps_parent->rgps_children[ 0 ] == ps_tree )
  289.         {
  290.             ps_new_branch->ps_parent->rgps_children[ 0 ] = ps_new_branch;
  291.         }
  292.         else
  293.         {
  294.             ps_new_branch->ps_parent->rgps_children[ 1 ] = ps_new_branch;
  295.         }
  296.         ps_new_branch->i_count += ps_tree->i_count;
  297.        
  298.         ps_tree = ps_new_branch;
  299.         while( ps_tree->ps_parent != &ps_compress->s_headnode )
  300.         {
  301.             treenode_t *ps_swap;
  302.  
  303.             ps_tree->i_count += ps_treenode->i_count;
  304.  
  305.             ps_parent = ps_tree->ps_parent;
  306.             if( ps_parent->rgps_children[ 0 ]->i_count < ps_parent->rgps_children[ 1 ]->i_count )
  307.             {
  308.                 ps_swap = ps_parent->rgps_children[ 0 ];
  309.                 ps_parent->rgps_children[ 0 ] = ps_parent->rgps_children[ 1 ];
  310.                 ps_parent->rgps_children[ 1 ] = ps_swap;
  311.             }
  312.             ps_tree = ps_parent;
  313.         }
  314.     }
  315.  
  316.     mdeflate_assign_cw_r( ps_compress, ps_compress->s_headnode.rgps_children[ 0 ], 0 );
  317.  
  318.     if( ps_compress->i_num_overflow != 0 )
  319.     {
  320.         while( ps_compress->i_num_overflow )
  321.         {
  322.             for( i_idx = ps_compress->i_max_depth - 1; i_idx > 0; i_idx-- )
  323.             {
  324.                 if( ps_compress->rgi_cw_length_counts[ i_idx ] > 0 )
  325.                 {
  326.                     ps_compress->rgi_cw_length_counts[ i_idx ]--;
  327.                     ps_compress->rgi_cw_length_counts[ i_idx + 1 ] += 2;
  328.                     ps_compress->rgi_cw_length_counts[ ps_compress->i_max_depth ]--;
  329.                     ps_compress->i_num_overflow -= 2;
  330.                     break;
  331.                 }
  332.             }
  333.         }
  334.     }
  335.  
  336.     i_order = 0;
  337.     for( i_idx = 1; i_idx <= ps_compress->i_max_depth; i_idx++ )
  338.     {
  339.         for( i_node = 0; i_node < ps_compress->rgi_cw_length_counts[ i_idx ]; i_node++ )
  340.         {
  341.             for( i_osearch = 0; i_osearch < i_num_nodes; i_osearch++ )
  342.             {
  343.                 if( ps_nodes[ i_osearch ].i_order == i_order )
  344.                 {
  345.                     ps_nodes[ i_osearch ].i_cw_length = i_idx;
  346.                     i_order++;
  347.                     break;
  348.                 }
  349.             }
  350.         }
  351.     }
  352.     return i_non_zero;
  353. }
  354.  
  355.  
  356.  
  357. void mdeflate_assign_cw( mdeflate_compress_t *ps_compress, encnode_t *ps_nodes, int32_t i_num_nodes, treenode_t *ps_treenode )
  358. {
  359.     int32_t i_cw_length, i_cw, i_node;
  360.  
  361.     i_cw = 0;
  362.     for( i_cw_length = 1; i_cw_length <= ps_compress->i_max_depth; i_cw_length++ )
  363.     {
  364.         i_cw <<= 1;
  365.         for( i_node = 0; i_node < i_num_nodes; i_node++ )
  366.         {
  367.             if( ps_nodes[ i_node ].i_cw_length == i_cw_length )
  368.             {
  369. #if MDEFLATE_DEBUG_PRINTF > 1
  370.                 int32_t i_idx;
  371.                 for( i_idx = 0; i_idx < i_cw_length; i_idx++ )
  372.                 {
  373.                     printf("%d", i_cw & ( 1 << ( i_cw_length - i_idx - 1 ) ) ? 1 : 0 );
  374.                 }
  375.                 printf(" - %d ( %d )\n", i_node, ps_nodes[ i_node ].i_count );
  376. #endif
  377.  
  378.                 ps_nodes[ i_node ].i_cw = i_cw++;
  379.             }
  380.         }
  381.     }
  382.     if( i_cw != ( ( 1 << ps_compress->i_max_depth ) ) )
  383.     {
  384.         fprintf( stderr, "codeword assignment failure ! ( %d %d)\n", i_cw, 1 << ps_compress->i_max_depth );
  385.         exit( -1 );
  386.     }
  387. }
  388.  
  389.  
  390. int32_t mdeflate_find_match( mdeflate_compress_t *ps_compress, uint8_t *pui8_search, int32_t i_offset_from_start, int32_t i_search_end, int32_t *pi_offset )
  391. {
  392.     int32_t i_max_match_length, i_max_back, i_offset, i_best_offset, i_best_match_length, i_match;
  393.  
  394.  
  395.     i_max_match_length = i_search_end - i_offset_from_start;
  396.     if( i_max_match_length > ps_compress->i_max_match_length )
  397.     {
  398.         i_max_match_length = ps_compress->i_max_match_length;
  399.     }
  400.     i_max_back = i_offset_from_start + ps_compress->i_codebook_back;
  401.     if( i_max_back > ps_compress->i_max_codebook_back )
  402.     {
  403.         i_max_back = ps_compress->i_max_codebook_back;
  404.     }
  405.     i_offset = 1;
  406.    
  407.     i_best_offset = i_best_match_length = 0;
  408.     *pi_offset = 0;
  409.    
  410.     while( i_offset < i_max_back )
  411.     {
  412.         i_match = 0;
  413.         if( pui8_search[ -i_offset ] == pui8_search[ 0 ] && pui8_search[ -i_offset + i_best_match_length ] == pui8_search[ i_best_match_length ] )
  414.         {
  415.             i_match = 1;
  416.             while( pui8_search[ -i_offset + i_match ] == pui8_search[ i_match ] && i_match < i_max_match_length )
  417.             {
  418.                 i_match++;
  419.             }  
  420.         }
  421.         if( i_match > i_best_match_length )
  422.         {
  423.             i_best_match_length = i_match;
  424.             i_best_offset = i_offset;
  425.         }
  426.         i_offset++;
  427.     }
  428.  
  429.     if( i_best_match_length == MDEFLATE_MATCH_LENGTH_OFFSET ) /* sanity */
  430.     {
  431.         int32_t i_offset_symbol, i_offset_size;
  432.         i_offset_symbol = ps_compress->rgui8_offset_lut[ i_offset - 1 ];
  433.         i_offset_size = rgi_offset_extra[ i_offset_symbol ];
  434.         if( ( i_offset_size + 14 ) > ( i_best_match_length * 8 ) )
  435.         {
  436.             i_best_match_length = 0;
  437.         }
  438.     }
  439.  
  440.     if( i_best_match_length >= MDEFLATE_MATCH_LENGTH_OFFSET )
  441.     {
  442.         *pi_offset = i_best_offset;
  443.         return i_best_match_length;
  444.     }
  445.     return 0;
  446. }
  447.  
  448.  
  449. int32_t mdeflate_enc_block( uint8_t *pui8_in_data, int32_t i_in_data_length, uint8_t *pui8_out_data, int32_t i_cb_back )
  450. {
  451.     int32_t i_idx, i_length_and_offset_idx, i_length_literal, i_length_bcopy, i_next_match_length, i_next_offset;
  452.    
  453.     mdeflate_compress_t s_compress;
  454.  
  455.     memset( &s_compress, 0, sizeof( s_compress ) );
  456.  
  457.     s_compress.pui8_bitstream = pui8_out_data;
  458.     mdeflate_init_length_and_offset_table( &s_compress );
  459.     s_compress.i_codebook_back = i_cb_back;
  460.  
  461.     i_length_literal = i_length_bcopy = 0;
  462.  
  463.     i_next_match_length = -1;
  464.     for( i_idx = 0; i_idx < i_in_data_length; )
  465.     {
  466.         int32_t i_symbol, i_offset_symbol, i_length, i_offset;
  467.  
  468.         if( i_next_match_length < 0 )
  469.         {
  470.             i_length = mdeflate_find_match( &s_compress, &pui8_in_data[ i_idx ], i_idx, i_in_data_length, &i_offset );
  471.             if( i_length > 0 && ( i_idx + 1 ) < i_in_data_length )
  472.             {
  473.                 i_next_match_length = mdeflate_find_match( &s_compress, &pui8_in_data[ i_idx + 1 ], i_idx + 1, i_in_data_length, &i_next_offset );
  474.             }
  475.             if( i_next_match_length > i_length )
  476.             {
  477.                 i_length = 0;
  478.             }
  479.             else
  480.             {
  481.                 i_next_match_length = -1;
  482.             }
  483.         }
  484.         else
  485.         {
  486.             i_length = i_next_match_length;
  487.             i_offset = i_next_offset;
  488.             i_next_match_length = -1;
  489.         }
  490.         if( i_length > 0 )
  491.         {
  492.             i_idx += i_length;
  493.             i_length_bcopy += i_length;
  494.  
  495. #if MDEFLATE_DEBUG_PRINTF > 1
  496.             printf("match %d %d\n", i_length, i_offset );
  497. #endif
  498.  
  499.             i_length -= MDEFLATE_MATCH_LENGTH_OFFSET;
  500.             i_symbol = s_compress.rgui8_length_lut[ i_length ];
  501.             i_length -= s_compress.rgui_length_offset[ i_symbol ];
  502.             i_symbol += MDEFLATE_LENGTH_NODES_OFFSET;
  503.  
  504.             i_offset -= 1;
  505.             i_offset_symbol = s_compress.rgui8_offset_lut[ i_offset ];
  506.             i_offset -= s_compress.rgui_offset_offset[ i_offset_symbol ];
  507.            
  508.             s_compress.rgs_symbol_nodes[ i_symbol ].i_count++;
  509.             s_compress.rgui8_symbols[ s_compress.i_symbol_count++ ] = i_symbol;
  510.  
  511.             s_compress.rgs_offset_nodes[ i_offset_symbol ].i_count++;
  512.             s_compress.rgui8_symbols[ s_compress.i_symbol_count++ ] = i_offset_symbol;
  513.             s_compress.rgi_length_and_offset[ s_compress.i_length_and_offset_count++ ] = i_length;
  514.             s_compress.rgi_length_and_offset[ s_compress.i_length_and_offset_count++ ] = i_offset;         
  515.         }
  516.         else
  517.         {
  518.             i_symbol = pui8_in_data[ i_idx ] & 0xf;
  519.             s_compress.rgs_symbol_nodes[ i_symbol ].i_count++;
  520.             s_compress.rgui8_symbols[ s_compress.i_symbol_count++ ] = i_symbol;
  521.  
  522.             i_symbol = ( pui8_in_data[ i_idx ] >> 4 ) & 0xf;
  523. #if !WITH_LITERAL_ONLY_TREE
  524.             s_compress.rgs_symbol_nodes[ i_symbol ].i_count++;
  525. #else
  526.             s_compress.rgs_literal_nodes[ i_symbol ].i_count++;
  527. #endif
  528.             s_compress.rgui8_symbols[ s_compress.i_symbol_count++ ] = i_symbol;
  529.  
  530.             i_idx += 1;
  531.             i_length_literal += 1;
  532.         }
  533.     }
  534.     s_compress.rgs_symbol_nodes[ MDEFLATE_END_OF_BLOCK_NODE ].i_count++;
  535.     s_compress.rgui8_symbols[ s_compress.i_symbol_count++ ] = MDEFLATE_END_OF_BLOCK_NODE;
  536.  
  537.     mdeflate_construct_tree( &s_compress, &s_compress.rgs_symbol_nodes[ 0 ], MDEFLATE_MAX_SYMBOL_NODES, MDEFLATE_MAX_CW_LENGTH );
  538.     mdeflate_assign_cw( &s_compress, &s_compress.rgs_symbol_nodes[ 0 ], MDEFLATE_MAX_SYMBOL_NODES, s_compress.s_headnode.rgps_children[ 0 ] );
  539. #if WITH_LITERAL_ONLY_TREE
  540.     if( mdeflate_construct_tree( &s_compress, &s_compress.rgs_literal_nodes[ 0 ], MDEFLATE_MAX_LITERAL_NODES, MDEFLATE_MAX_CW_LENGTH ) )
  541.     {
  542.         mdeflate_assign_cw( &s_compress, &s_compress.rgs_literal_nodes[ 0 ], MDEFLATE_MAX_LITERAL_NODES, s_compress.s_headnode.rgps_children[ 0 ] );
  543.     }
  544. #endif
  545.     if( mdeflate_construct_tree( &s_compress, &s_compress.rgs_offset_nodes[ 0 ], MDEFLATE_MAX_OFFSET_NODES, MDEFLATE_MAX_CW_LENGTH ) )
  546.     {
  547.         mdeflate_assign_cw( &s_compress, &s_compress.rgs_offset_nodes[ 0 ], MDEFLATE_MAX_OFFSET_NODES, s_compress.s_headnode.rgps_children[ 0 ] );
  548.     }
  549.  
  550.  
  551.     for( i_idx = 0; i_idx < MDEFLATE_MAX_SYMBOL_NODES; i_idx++ )
  552.     {
  553.         s_compress.rgs_bl_nodes[ s_compress.rgs_symbol_nodes[ i_idx ].i_cw_length ].i_count++;
  554.     }
  555. #if WITH_LITERAL_ONLY_TREE
  556.     for( i_idx = 0; i_idx < MDEFLATE_MAX_LITERAL_NODES; i_idx++ )
  557.     {
  558.         s_compress.rgs_bl_nodes[ s_compress.rgs_literal_nodes[ i_idx ].i_cw_length ].i_count++;
  559.     }
  560. #endif
  561.     for( i_idx = 0; i_idx < MDEFLATE_MAX_OFFSET_NODES; i_idx++ )
  562.     {
  563.         s_compress.rgs_bl_nodes[ s_compress.rgs_offset_nodes[ i_idx ].i_cw_length ].i_count++;
  564.     }
  565.  
  566.     mdeflate_construct_tree( &s_compress, &s_compress.rgs_bl_nodes[ 0 ], MDEFLATE_MAX_BL_NODES, MDEFLATE_MAX_BL_CW_LENGTH );
  567.     mdeflate_assign_cw( &s_compress, &s_compress.rgs_bl_nodes[ 0 ], MDEFLATE_MAX_BL_NODES, s_compress.s_headnode.rgps_children[ 0 ] );
  568.  
  569.    
  570.     for( i_idx = 0; i_idx < MDEFLATE_MAX_BL_NODES; i_idx++ )
  571.     {
  572.         mdeflate_write_bits( &s_compress, s_compress.rgs_bl_nodes[ i_idx ].i_cw_length, 3 );
  573.     }
  574.    
  575.  
  576.     for( i_idx = 0; i_idx < MDEFLATE_MAX_SYMBOL_NODES; i_idx++ )
  577.     {
  578.         int32_t i_bl_idx = s_compress.rgs_symbol_nodes[ i_idx ].i_cw_length;
  579.         mdeflate_write_bits( &s_compress, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw_length );
  580.     }
  581. #if WITH_LITERAL_ONLY_TREE
  582.     for( i_idx = 0; i_idx < MDEFLATE_MAX_LITERAL_NODES; i_idx++ )
  583.     {
  584.         int32_t i_bl_idx = s_compress.rgs_literal_nodes[ i_idx ].i_cw_length;
  585.         mdeflate_write_bits( &s_compress, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw_length );
  586.     }
  587. #endif
  588.     for( i_idx = 0; i_idx < MDEFLATE_MAX_OFFSET_NODES; i_idx++ )
  589.     {
  590.         int32_t i_bl_idx = s_compress.rgs_offset_nodes[ i_idx ].i_cw_length;
  591.         mdeflate_write_bits( &s_compress, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw, s_compress.rgs_bl_nodes[ i_bl_idx ].i_cw_length );
  592.     }
  593.  
  594. #if MDEFLATE_DEBUG_PRINTF > 0
  595.     printf( "stats: literal: %db, bcopy: %db, tot: %d\n", i_length_literal, i_length_bcopy, i_length_literal + i_length_bcopy );
  596. #endif
  597.  
  598.     i_length_and_offset_idx = 0;
  599.     for( i_idx = 0; i_idx < s_compress.i_symbol_count; i_idx++ )
  600.     {
  601.         int32_t i_symbol, i_offset_symbol;
  602.         i_symbol = s_compress.rgui8_symbols[ i_idx ];
  603. #if MDEFLATE_DEBUG_PRINTF > 2
  604.         printf("esym %d\n", i_symbol );
  605. #endif
  606.         mdeflate_write_bits( &s_compress, s_compress.rgs_symbol_nodes[ i_symbol ].i_cw, s_compress.rgs_symbol_nodes[ i_symbol ].i_cw_length );
  607.         if( i_symbol > MDEFLATE_END_OF_BLOCK_NODE )
  608.         {
  609.             mdeflate_write_bits( &s_compress, s_compress.rgi_length_and_offset[ i_length_and_offset_idx++ ], rgi_length_extra[ i_symbol - MDEFLATE_LENGTH_NODES_OFFSET ] );
  610.             i_offset_symbol = s_compress.rgui8_symbols[ ++i_idx ];
  611.             mdeflate_write_bits( &s_compress, s_compress.rgs_offset_nodes[ i_offset_symbol ].i_cw, s_compress.rgs_offset_nodes[ i_offset_symbol ].i_cw_length );
  612.             mdeflate_write_bits( &s_compress, s_compress.rgi_length_and_offset[ i_length_and_offset_idx++ ], rgi_offset_extra[ i_offset_symbol ] );
  613. #if MDEFLATE_DEBUG_PRINTF > 2
  614.             printf("eoff %d\n", i_offset_symbol );
  615. #endif
  616.         }
  617.         else if( i_symbol <= MDEFLATE_MAX_LITERAL_NODE )
  618.         {
  619.             i_symbol = s_compress.rgui8_symbols[ ++i_idx ];
  620. #if MDEFLATE_DEBUG_PRINTF > 2
  621.         printf("esym2 %d\n", i_symbol );
  622. #endif
  623.             if( i_symbol > MDEFLATE_MAX_LITERAL_NODE )
  624.             {
  625.                 fprintf( stderr, "compression error, second literal symbol is no literal symbol\n");
  626.                 exit( 1 );
  627.             }
  628. #if !WITH_LITERAL_ONLY_TREE
  629.             mdeflate_write_bits( &s_compress, s_compress.rgs_symbol_nodes[ i_symbol ].i_cw, s_compress.rgs_symbol_nodes[ i_symbol ].i_cw_length );
  630. #else
  631.             mdeflate_write_bits( &s_compress, s_compress.rgs_literal_nodes[ i_symbol ].i_cw, s_compress.rgs_literal_nodes[ i_symbol ].i_cw_length );
  632. #endif
  633.         }
  634.     }
  635.     if( s_compress.i_cw_bits > 0 )
  636.     {
  637.         s_compress.pui8_bitstream[ s_compress.i_bitstream_size++ ] = s_compress.ui_cw >> 24;
  638.     }
  639.     return s_compress.i_bitstream_size;
  640. }
  641.  
  642.  
  643.  
  644. /* ------------------------ UNCOMPRESS ------------------------ */
  645.  
  646. typedef struct {
  647.     int8_t i8_bits;
  648.     uint16_t ui16_cw;
  649.     uint8_t *pui8_bitstream;
  650.  
  651.     uint8_t ui8_out_slot;
  652.     uint8_t *pui8_out;
  653.  
  654.     uint8_t rgui8_symbol_lut[ 1 << MDEFLATE_MAX_CW_LENGTH ];
  655.     uint8_t rgui8_symbol_length_lut[ MDEFLATE_MAX_SYMBOL_NODES ];
  656. #if WITH_LITERAL_ONLY_TREE
  657.     uint8_t rgui8_literal_lut[ 1 << MDEFLATE_MAX_CW_LENGTH ];
  658.     uint8_t rgui8_literal_length_lut[ MDEFLATE_MAX_LITERAL_NODES ];
  659. #endif
  660.     uint8_t rgui8_offset_lut[ 1 << MDEFLATE_MAX_CW_LENGTH ];
  661.     uint8_t rgui8_offset_length_lut[ MDEFLATE_MAX_OFFSET_NODES ];
  662.  
  663.     uint16_t rgui16_offset_offset[ MDEFLATE_MAX_OFFSET_NODES ];
  664.     uint8_t rgui8_length_offset[ MDEFLATE_MAX_SYMBOL_NODES ];
  665. } minflate_uncompress_t;
  666.  
  667.  
  668. uint8_t minflate_read_bits( minflate_uncompress_t *ps_uncompress, uint8_t ui8_length )
  669. {
  670.     uint8_t ui8_cw;
  671.     ui8_cw = ps_uncompress->ui16_cw >> ( 16 - ui8_length );
  672.     ps_uncompress->ui16_cw <<= ui8_length;
  673.     ps_uncompress->i8_bits -= ui8_length;
  674.     if( ps_uncompress->i8_bits < 0 )
  675.     {
  676.         ps_uncompress->ui16_cw |= ( *( ps_uncompress->pui8_bitstream++ ) ) << ( -ps_uncompress->i8_bits );
  677.         ps_uncompress->i8_bits += 8;
  678.     }
  679.     return ui8_cw;
  680. }
  681.  
  682.  
  683. void minflate_init_length_and_offset_table( minflate_uncompress_t *ps_uncompress )
  684. {
  685.     int32_t i_symbol_idx, i_symbol_offset;
  686.  
  687.     i_symbol_offset = 0;
  688.     for( i_symbol_idx = 0; i_symbol_idx < MDEFLATE_MAX_OFFSET_NODES; i_symbol_idx++ )
  689.     {
  690.         ps_uncompress->rgui16_offset_offset[ i_symbol_idx ] = i_symbol_offset;
  691.         i_symbol_offset += 1 << rgi_offset_extra[ i_symbol_idx ];
  692.     }
  693.  
  694.     i_symbol_offset = 0;
  695.     for( i_symbol_idx = 0; i_symbol_idx < MDEFLATE_MAX_LENGTH_NODES; i_symbol_idx++ )
  696.     {
  697.         ps_uncompress->rgui8_length_offset[ i_symbol_idx ] = i_symbol_offset;
  698.         i_symbol_offset += 1 << rgi_length_extra[ i_symbol_idx ];
  699.     }
  700. }
  701.  
  702.  
  703. void minflate_assign_cw( minflate_uncompress_t *ps_uncompress, int8_t i8_num_nodes, uint8_t *pui8_length_lut, uint8_t *pui8_lut )
  704. {
  705.     int8_t i8_cw_length, i8_node;
  706.     uint8_t ui8_cw, ui8_idx;
  707.    
  708.     ui8_cw = 0;
  709.     for( i8_cw_length = 1; i8_cw_length <= MDEFLATE_MAX_CW_LENGTH; i8_cw_length++ )
  710.     {
  711.         for( i8_node = 0; i8_node < i8_num_nodes; i8_node++ )
  712.         {
  713.             if( pui8_length_lut[ i8_node ] == i8_cw_length )
  714.             {
  715.                 uint8_t ui8_dim = 1 << ( 8 - i8_cw_length );
  716.                 for( ui8_idx = 0; ui8_idx < ui8_dim; ui8_idx++ )
  717.                 {
  718.                     pui8_lut[ ui8_cw++ ] = i8_node;
  719.                 }
  720.             }
  721.         }
  722.     }
  723. }
  724.  
  725.  
  726. void minflate_read_and_assign_bl_cw( minflate_uncompress_t *ps_uncompress, int8_t i8_num_nodes, uint8_t *pui8_length_lut, uint8_t *pui8_lut )
  727. {
  728.     int8_t i8_node;
  729.  
  730.     for( i8_node = 0; i8_node < i8_num_nodes; i8_node++ )
  731.     {
  732.         pui8_length_lut[ i8_node ] = minflate_read_bits( ps_uncompress, 3 );
  733. #if MDEFLATE_DEBUG_PRINTF > 1
  734.         printf("node %d, l %d\n", i8_node, pui8_length_lut[ i8_node ] );
  735. #endif
  736.     }
  737.  
  738.     minflate_assign_cw( ps_uncompress, i8_num_nodes, pui8_length_lut, pui8_lut );
  739. }
  740.  
  741. uint8_t minflate_read_symbol( minflate_uncompress_t *ps_uncompress, uint8_t *pui8_node_lut, uint8_t *pui8_node_length_lut )
  742. {
  743.     uint8_t ui8_sym, ui8_len;
  744.  
  745.     ui8_sym = pui8_node_lut[ ps_uncompress->ui16_cw >> 8 ];
  746.     ui8_len = pui8_node_length_lut[ ui8_sym ];
  747.  
  748.     ps_uncompress->ui16_cw <<= ui8_len;
  749.     ps_uncompress->i8_bits -= ui8_len;
  750.     if( ps_uncompress->i8_bits < 0 )
  751.     {
  752.         ps_uncompress->ui16_cw |= ( *( ps_uncompress->pui8_bitstream++ ) ) << ( -ps_uncompress->i8_bits );
  753.         ps_uncompress->i8_bits += 8;
  754.     }
  755.  
  756.     return ui8_sym;
  757. }
  758.  
  759. void minflate_read_lengths( minflate_uncompress_t *ps_uncompress, int8_t i8_num_nodes, uint8_t *pui8_bl_length_lut, uint8_t *pui8_bl_lut, uint8_t *pui8_length_lut )
  760. {
  761.     int8_t i8_idx;
  762.  
  763.     for( i8_idx = 0; i8_idx < i8_num_nodes; i8_idx++ )
  764.     {
  765.         pui8_length_lut[ i8_idx ] = minflate_read_symbol( ps_uncompress, pui8_bl_lut, pui8_bl_length_lut );
  766.     }
  767. }
  768.  
  769.  
  770. int32_t minflate_dec_block( uint8_t *pui8_in_data, int32_t i_in_data_length, uint8_t *pui8_out_data )
  771. {
  772.     minflate_uncompress_t s_uncompress;
  773.     uint8_t ui8_sym;
  774.     int32_t i_length_literal, i_length_bcopy;
  775.  
  776.     memset( &s_uncompress, 0, sizeof( s_uncompress ) );
  777.  
  778.     minflate_init_length_and_offset_table( &s_uncompress );
  779.  
  780.     s_uncompress.i8_bits = 8;
  781.     s_uncompress.ui16_cw = ( pui8_in_data[ 0 ] << 8 ) | pui8_in_data[ 1 ];
  782.     s_uncompress.pui8_bitstream = pui8_in_data + 2;
  783.  
  784.     s_uncompress.ui8_out_slot = 0;
  785.     s_uncompress.pui8_out = pui8_out_data;
  786.  
  787.     minflate_read_and_assign_bl_cw( &s_uncompress, MDEFLATE_MAX_BL_NODES, &s_uncompress.rgui8_symbol_lut[ 0 ], &s_uncompress.rgui8_offset_lut[ 0 ] );
  788.  
  789.     minflate_read_lengths( &s_uncompress, MDEFLATE_MAX_SYMBOL_NODES, &s_uncompress.rgui8_symbol_lut[ 0 ], &s_uncompress.rgui8_offset_lut[ 0 ], &s_uncompress.rgui8_symbol_length_lut[ 0 ] );
  790. #if WITH_LITERAL_ONLY_TREE
  791.     minflate_read_lengths( &s_uncompress, MDEFLATE_MAX_LITERAL_NODES, &s_uncompress.rgui8_symbol_lut[ 0 ], &s_uncompress.rgui8_offset_lut[ 0 ], &s_uncompress.rgui8_literal_length_lut[ 0 ] );
  792. #endif
  793.     minflate_read_lengths( &s_uncompress, MDEFLATE_MAX_OFFSET_NODES, &s_uncompress.rgui8_symbol_lut[ 0 ], &s_uncompress.rgui8_offset_lut[ 0 ], &s_uncompress.rgui8_offset_length_lut[ 0 ] );
  794.  
  795.     minflate_assign_cw( &s_uncompress, MDEFLATE_MAX_SYMBOL_NODES, &s_uncompress.rgui8_symbol_length_lut[ 0 ], &s_uncompress.rgui8_symbol_lut[ 0 ] );
  796. #if WITH_LITERAL_ONLY_TREE
  797.     minflate_assign_cw( &s_uncompress, MDEFLATE_MAX_LITERAL_NODES, &s_uncompress.rgui8_literal_length_lut[ 0 ], &s_uncompress.rgui8_literal_lut[ 0 ] );
  798. #endif
  799.     minflate_assign_cw( &s_uncompress, MDEFLATE_MAX_OFFSET_NODES, &s_uncompress.rgui8_offset_length_lut[ 0 ], &s_uncompress.rgui8_offset_lut[ 0 ] );
  800.  
  801.  
  802.     i_length_literal = i_length_bcopy = 0;
  803.  
  804.     do {
  805.         ui8_sym = minflate_read_symbol( &s_uncompress, s_uncompress.rgui8_symbol_lut, s_uncompress.rgui8_symbol_length_lut );
  806.         if( ui8_sym <= MDEFLATE_MAX_LITERAL_NODE )
  807.         {
  808. #if !WITH_LITERAL_ONLY_TREE
  809.             ui8_sym |= ( minflate_read_symbol( &s_uncompress, s_uncompress.rgui8_symbol_lut, s_uncompress.rgui8_symbol_length_lut ) ) << 4;
  810. #else
  811.             ui8_sym |= ( minflate_read_symbol( &s_uncompress, s_uncompress.rgui8_literal_lut, s_uncompress.rgui8_literal_length_lut ) ) << 4;
  812. #endif
  813.             *( s_uncompress.pui8_out++ ) = ui8_sym;
  814.             ui8_sym = 0;
  815.             i_length_literal++;
  816.         }
  817.         else if( ui8_sym >= MDEFLATE_LENGTH_NODES_OFFSET )
  818.         {
  819.             uint8_t ui8_length_sym, ui8_offset_sym, ui8_length, *pui8_bcopy, ui8_length_extra;
  820.             int16_t i16_offset, i16_offset_extra;
  821.  
  822.             ui8_length_sym = ui8_sym - MDEFLATE_LENGTH_NODES_OFFSET;
  823.             ui8_length = s_uncompress.rgui8_length_offset[ ui8_length_sym ];
  824.             ui8_length_extra = minflate_read_bits( &s_uncompress, rgi_length_extra[ ui8_length_sym ] );
  825.             ui8_length += ui8_length_extra;
  826.             ui8_length += MDEFLATE_MATCH_LENGTH_OFFSET;
  827.             ui8_offset_sym = minflate_read_symbol( &s_uncompress, s_uncompress.rgui8_offset_lut, s_uncompress.rgui8_offset_length_lut );
  828.             i16_offset = s_uncompress.rgui16_offset_offset[ ui8_offset_sym ];
  829.             i16_offset_extra = minflate_read_bits( &s_uncompress, rgi_offset_extra[ ui8_offset_sym ] );
  830.             i16_offset += i16_offset_extra;
  831.             i16_offset += 1;
  832.  
  833. #if MDEFLATE_DEBUG_PRINTF > 1
  834.             printf("bcopy %d %d (%d %d )\n", ui8_length, i16_offset, ui8_length_extra, i16_offset_extra );
  835. #endif
  836.             i_length_bcopy += ui8_length;
  837.  
  838.             pui8_bcopy = s_uncompress.pui8_out - i16_offset;
  839.             while( ui8_length > 0 )
  840.             {
  841.                 *( s_uncompress.pui8_out++ ) = *( pui8_bcopy++ );
  842.                 ui8_length--;
  843.             }
  844.         }
  845.     } while( ui8_sym != MDEFLATE_END_OF_BLOCK_NODE );
  846.  
  847. #if MDEFLATE_DEBUG_PRINTF > 0
  848.     printf("ustats: %d %d %d\n", i_length_literal, i_length_bcopy, i_length_literal + i_length_bcopy );
  849. #endif
  850.  
  851.     return ( int32_t ) ( s_uncompress.pui8_out - pui8_out_data );
  852. }
  853.  
  854.  
  855. /* ------------------------ MAIN ------------------------ */
  856.  
  857.  
  858. int main( int i_argc, char *argv[ ] )
  859. {
  860.     FILE *f_in, *f_out;
  861.     uint8_t rgui8_data[ MDEFLATE_BLOCK_SIZE ];
  862.     uint8_t rgui8_edata[ MDEFLATE_BLOCK_SIZE + MDEFLATE_BLOCK_SIZE / 5 ];
  863.     uint8_t rgui8_ddata[ MDEFLATE_BLOCK_SIZE ];
  864.     int32_t i_data_size, i_edata_size, i_ddata_size, i_ret, i_cb_size;
  865.  
  866.     if( i_argc < 3 )
  867.     {
  868.         printf("usage: <option> infile outfile\nwhere option is either 'c' for compress or 'd' for decompress\n");
  869.         exit( 1 );
  870.     }
  871.    
  872.     if( argv[ 1 ][ 0 ] == 'c' && argv[ 1 ][ 1 ] == 0 )
  873.     {
  874.         f_in = fopen( argv[ 2 ], "rb" );
  875.         if( f_in == NULL )
  876.         {
  877.             printf("unable to open \"%s\" for reading\n", argv[ 2 ] );
  878.             exit( 1 );
  879.         }
  880.         f_out = fopen( argv[ 3 ], "wb" );
  881.         if( f_out == NULL )
  882.         {
  883.             printf("unable to open \"%s\" for writing\n", argv[ 3 ] );
  884.             exit( 1 );
  885.         }
  886.  
  887.         i_cb_size = 0;
  888.         while( 1 )
  889.         {
  890.             i_ret = fread( &rgui8_data[ MDEFLATE_BLOCK_SIZE / 2 ], sizeof( uint8_t ), MDEFLATE_BLOCK_SIZE / 2, f_in ); /* / 2 because of nibbles */
  891. #if MDEFLATE_DEBUG_PRINTF > 0
  892.             printf("block, %d bytes\n", i_ret );
  893. #endif
  894.             if( i_ret > 0 )
  895.             {
  896.                 i_data_size = i_ret;
  897.                 i_edata_size = mdeflate_enc_block( &rgui8_data[ MDEFLATE_BLOCK_SIZE / 2 ], i_data_size, &rgui8_edata[ 2 ], i_cb_size );
  898.                 rgui8_edata[ 0 ] = ( i_edata_size >> 8 ) & 0xff;
  899.                 rgui8_edata[ 1 ] = ( i_edata_size      ) & 0xff;
  900.                 i_ret = fwrite( rgui8_edata, i_edata_size + 2, sizeof( uint8_t ), f_out );
  901.                 printf( "%d %d ( %.2f )\n", i_data_size, i_edata_size, ( ( float ) i_edata_size ) / ( ( float )i_data_size ) );
  902.                 memcpy( &rgui8_data[ ( MDEFLATE_BLOCK_SIZE / 2 ) - i_data_size ], &rgui8_data[ MDEFLATE_BLOCK_SIZE / 2 ], sizeof( uint8_t ) * i_data_size );
  903.                 i_cb_size = i_data_size;
  904.             }
  905.             else
  906.             {
  907.                 rgui8_edata[ 0 ] = 0;
  908.                 rgui8_edata[ 1 ] = 0;
  909.                 i_edata_size = 2;
  910.                 i_ret = fwrite( rgui8_edata, i_edata_size, sizeof( uint8_t ), f_out );
  911.                 break;
  912.             }
  913.         }
  914.     }
  915.     else if( argv[ 1 ][ 0 ] == 'd' && argv[ 1 ][ 1 ] == 0 )
  916.     {
  917.         uint16_t ui16_blocksize;
  918.  
  919.         f_in = fopen( argv[ 2 ], "rb" );
  920.         if( f_in == NULL )
  921.         {
  922.             printf("unable to open \"%s\" for reading\n", argv[ 2 ] );
  923.             exit( 1 );
  924.         }
  925.         f_out = fopen( argv[ 3 ], "wb" );
  926.         if( f_out == NULL )
  927.         {
  928.             printf("unable to open \"%s\" for writing\n", argv[ 3 ] );
  929.             exit( 1 );
  930.         }
  931.        
  932.         while( 1 )
  933.         {
  934.             ui16_blocksize = fgetc( f_in ) << 8;
  935.             ui16_blocksize |= fgetc( f_in );
  936.             if( ui16_blocksize > 0 )
  937.             {
  938.                 i_ret = fread( &rgui8_edata[ 0 ], ui16_blocksize, 1, f_in );
  939.                 i_ddata_size = minflate_dec_block( rgui8_edata, ui16_blocksize * sizeof( uint8_t ), &rgui8_ddata[ MDEFLATE_BLOCK_SIZE / 2 ] );
  940.                 printf( "%d -> %d ( %.2f )\n", ui16_blocksize + 2, i_ddata_size, ( ( float ) ui16_blocksize ) / ( ( float ) i_ddata_size ) );
  941.                 fwrite( &rgui8_ddata[ MDEFLATE_BLOCK_SIZE / 2 ], i_ddata_size  * sizeof( uint8_t ), 1, f_out );
  942.                 memcpy( &rgui8_ddata[ ( MDEFLATE_BLOCK_SIZE / 2 ) - ( int32_t )i_ddata_size ], &rgui8_ddata[ MDEFLATE_BLOCK_SIZE / 2 ], i_ddata_size * sizeof( uint8_t ) );
  943.             }
  944.             else
  945.             {
  946.                 break;
  947.             }
  948.         }
  949.     }
  950.     return 0;
  951. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement