Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/archival/libunarchive/decompress_unlzma.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 12  Line 12 
12  #include "libbb.h"  #include "libbb.h"
13  #include "unarchive.h"  #include "unarchive.h"
14    
15  #ifdef CONFIG_FEATURE_LZMA_FAST  #if ENABLE_FEATURE_LZMA_FAST
16  #  define speed_inline ATTRIBUTE_ALWAYS_INLINE  #  define speed_inline ALWAYS_INLINE
17  #else  #else
18  #  define speed_inline  #  define speed_inline
19  #endif  #endif
# Line 45  typedef struct { Line 45  typedef struct {
45    
46    
47  /* Called twice: once at startup and once in rc_normalize() */  /* Called twice: once at startup and once in rc_normalize() */
48  static void rc_read(rc_t * rc)  static void rc_read(rc_t *rc)
49  {  {
50   int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE);   int buffer_size = safe_read(rc->fd, RC_BUFFER, RC_BUFFER_SIZE);
51   if (buffer_size <= 0)   if (buffer_size <= 0)
# Line 58  static void rc_read(rc_t * rc) Line 58  static void rc_read(rc_t * rc)
58  static rc_t* rc_init(int fd) /*, int buffer_size) */  static rc_t* rc_init(int fd) /*, int buffer_size) */
59  {  {
60   int i;   int i;
61   rc_t* rc;   rc_t *rc;
62    
63   rc = xmalloc(sizeof(rc_t) + RC_BUFFER_SIZE);   rc = xmalloc(sizeof(*rc) + RC_BUFFER_SIZE);
64    
65   rc->fd = fd;   rc->fd = fd;
66   /* rc->buffer_size = buffer_size; */   /* rc->buffer_size = buffer_size; */
# Line 78  static rc_t* rc_init(int fd) /*, int buf Line 78  static rc_t* rc_init(int fd) /*, int buf
78  }  }
79    
80  /* Called once  */  /* Called once  */
81  static ATTRIBUTE_ALWAYS_INLINE void rc_free(rc_t * rc)  static ALWAYS_INLINE void rc_free(rc_t *rc)
82  {  {
83   if (ENABLE_FEATURE_CLEAN_UP)   free(rc);
  free(rc);  
84  }  }
85    
86  /* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */  /* Called twice, but one callsite is in speed_inline'd rc_is_bit_0_helper() */
87  static void rc_do_normalize(rc_t * rc)  static void rc_do_normalize(rc_t *rc)
88  {  {
89   if (rc->ptr >= rc->buffer_end)   if (rc->ptr >= rc->buffer_end)
90   rc_read(rc);   rc_read(rc);
91   rc->range <<= 8;   rc->range <<= 8;
92   rc->code = (rc->code << 8) | *rc->ptr++;   rc->code = (rc->code << 8) | *rc->ptr++;
93  }  }
94  static ATTRIBUTE_ALWAYS_INLINE void rc_normalize(rc_t * rc)  static ALWAYS_INLINE void rc_normalize(rc_t *rc)
95  {  {
96   if (rc->range < (1 << RC_TOP_BITS)) {   if (rc->range < (1 << RC_TOP_BITS)) {
97   rc_do_normalize(rc);   rc_do_normalize(rc);
98   }   }
99  }  }
100    
101  /* Called 9 times */  /* rc_is_bit_0 is called 9 times */
102  /* Why rc_is_bit_0_helper exists?  /* Why rc_is_bit_0_helper exists?
103   * Because we want to always expose (rc->code < rc->bound) to optimizer   * Because we want to always expose (rc->code < rc->bound) to optimizer.
104     * Thus rc_is_bit_0 is always inlined, and rc_is_bit_0_helper is inlined
105     * only if we compile for speed.
106   */   */
107  static speed_inline uint32_t rc_is_bit_0_helper(rc_t * rc, uint16_t * p)  static speed_inline uint32_t rc_is_bit_0_helper(rc_t *rc, uint16_t *p)
108  {  {
109   rc_normalize(rc);   rc_normalize(rc);
110   rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);   rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
111   return rc->bound;   return rc->bound;
112  }  }
113  static ATTRIBUTE_ALWAYS_INLINE int rc_is_bit_0(rc_t * rc, uint16_t * p)  static ALWAYS_INLINE int rc_is_bit_0(rc_t *rc, uint16_t *p)
114  {  {
115   uint32_t t = rc_is_bit_0_helper(rc, p);   uint32_t t = rc_is_bit_0_helper(rc, p);
116   return rc->code < t;   return rc->code < t;
117  }  }
118    
119  /* Called ~10 times, but very small, thus inlined */  /* Called ~10 times, but very small, thus inlined */
120  static speed_inline void rc_update_bit_0(rc_t * rc, uint16_t * p)  static speed_inline void rc_update_bit_0(rc_t *rc, uint16_t *p)
121  {  {
122   rc->range = rc->bound;   rc->range = rc->bound;
123   *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;   *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
124  }  }
125  static speed_inline void rc_update_bit_1(rc_t * rc, uint16_t * p)  static speed_inline void rc_update_bit_1(rc_t *rc, uint16_t *p)
126  {  {
127   rc->range -= rc->bound;   rc->range -= rc->bound;
128   rc->code -= rc->bound;   rc->code -= rc->bound;
# Line 129  static speed_inline void rc_update_bit_1 Line 130  static speed_inline void rc_update_bit_1
130  }  }
131    
132  /* Called 4 times in unlzma loop */  /* Called 4 times in unlzma loop */
133  static int rc_get_bit(rc_t * rc, uint16_t * p, int *symbol)  static int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
134  {  {
135   if (rc_is_bit_0(rc, p)) {   if (rc_is_bit_0(rc, p)) {
136   rc_update_bit_0(rc, p);   rc_update_bit_0(rc, p);
# Line 143  static int rc_get_bit(rc_t * rc, uint16_ Line 144  static int rc_get_bit(rc_t * rc, uint16_
144  }  }
145    
146  /* Called once */  /* Called once */
147  static ATTRIBUTE_ALWAYS_INLINE int rc_direct_bit(rc_t * rc)  static ALWAYS_INLINE int rc_direct_bit(rc_t *rc)
148  {  {
149   rc_normalize(rc);   rc_normalize(rc);
150   rc->range >>= 1;   rc->range >>= 1;
# Line 156  static ATTRIBUTE_ALWAYS_INLINE int rc_di Line 157  static ATTRIBUTE_ALWAYS_INLINE int rc_di
157    
158  /* Called twice */  /* Called twice */
159  static speed_inline void  static speed_inline void
160  rc_bit_tree_decode(rc_t * rc, uint16_t * p, int num_levels, int *symbol)  rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol)
161  {  {
162   int i = num_levels;   int i = num_levels;
163    
# Line 227  enum { Line 228  enum {
228  };  };
229    
230    
231  USE_DESKTOP(long long) int  USE_DESKTOP(long long) int FAST_FUNC
232  unlzma(int src_fd, int dst_fd)  unpack_lzma_stream(int src_fd, int dst_fd)
233  {  {
234   USE_DESKTOP(long long total_written = 0;)   USE_DESKTOP(long long total_written = 0;)
235   lzma_header_t header;   lzma_header_t header;
# Line 280  unlzma(int src_fd, int dst_fd) Line 281  unlzma(int src_fd, int dst_fd)
281   while (global_pos + buffer_pos < header.dst_size) {   while (global_pos + buffer_pos < header.dst_size) {
282   int pos_state = (buffer_pos + global_pos) & pos_state_mask;   int pos_state = (buffer_pos + global_pos) & pos_state_mask;
283    
284   prob =   prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
  p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;  
285   if (rc_is_bit_0(rc, prob)) {   if (rc_is_bit_0(rc, prob)) {
286   mi = 1;   mi = 1;
287   rc_update_bit_0(rc, prob);   rc_update_bit_0(rc, prob);
288   prob = (p + LZMA_LITERAL + (LZMA_LIT_SIZE   prob = (p + LZMA_LITERAL
289   * ((((buffer_pos + global_pos) & literal_pos_mask) << lc)          + (LZMA_LIT_SIZE * ((((buffer_pos + global_pos) & literal_pos_mask) << lc)
290   + (previous_byte >> (8 - lc)))));                              + (previous_byte >> (8 - lc))
291                               )
292              )
293     );
294    
295   if (state >= LZMA_NUM_LIT_STATES) {   if (state >= LZMA_NUM_LIT_STATES) {
296   int match_byte;   int match_byte;
# Line 302  unlzma(int src_fd, int dst_fd) Line 305  unlzma(int src_fd, int dst_fd)
305   match_byte <<= 1;   match_byte <<= 1;
306   bit = match_byte & 0x100;   bit = match_byte & 0x100;
307   prob_lit = prob + 0x100 + bit + mi;   prob_lit = prob + 0x100 + bit + mi;
308   if (rc_get_bit(rc, prob_lit, &mi)) {   bit ^= (rc_get_bit(rc, prob_lit, &mi) << 8); /* 0x100 or 0 */
309   if (!bit)   if (bit)
310   break;   break;
  } else {  
  if (bit)  
  break;  
  }  
311   } while (mi < 0x100);   } while (mi < 0x100);
312   }   }
313   while (mi < 0x100) {   while (mi < 0x100) {
314   prob_lit = prob + mi;   prob_lit = prob + mi;
315   rc_get_bit(rc, prob_lit, &mi);   rc_get_bit(rc, prob_lit, &mi);
316   }   }
  previous_byte = (uint8_t) mi;  
317    
318     state -= 3;
319     if (state < 4-3)
320     state = 0;
321     if (state >= 10-3)
322     state -= 6-3;
323    
324     previous_byte = (uint8_t) mi;
325    #if ENABLE_FEATURE_LZMA_FAST
326     one_byte1:
327   buffer[buffer_pos++] = previous_byte;   buffer[buffer_pos++] = previous_byte;
328   if (buffer_pos == header.dict_size) {   if (buffer_pos == header.dict_size) {
329   buffer_pos = 0;   buffer_pos = 0;
330   global_pos += header.dict_size;   global_pos += header.dict_size;
331   if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)   if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
332   goto bad;   goto bad;
333   USE_DESKTOP(total_written += header.dict_size;)   USE_DESKTOP(total_written += header.dict_size;)
334   }   }
335   if (state < 4)  #else
336   state = 0;   len = 1;
337   else if (state < 10)   goto one_byte2;
338   state -= 3;  #endif
  else  
  state -= 6;  
339   } else {   } else {
340   int offset;   int offset;
341   uint16_t *prob_len;   uint16_t *prob_len;
# Line 350  unlzma(int src_fd, int dst_fd) Line 355  unlzma(int src_fd, int dst_fd)
355   if (rc_is_bit_0(rc, prob)) {   if (rc_is_bit_0(rc, prob)) {
356   rc_update_bit_0(rc, prob);   rc_update_bit_0(rc, prob);
357   prob = (p + LZMA_IS_REP_0_LONG   prob = (p + LZMA_IS_REP_0_LONG
358   + (state << LZMA_NUM_POS_BITS_MAX) + pos_state);          + (state << LZMA_NUM_POS_BITS_MAX)
359            + pos_state
360     );
361   if (rc_is_bit_0(rc, prob)) {   if (rc_is_bit_0(rc, prob)) {
362   rc_update_bit_0(rc, prob);   rc_update_bit_0(rc, prob);
363    
364   state = state < LZMA_NUM_LIT_STATES ? 9 : 11;   state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
365    #if ENABLE_FEATURE_LZMA_FAST
366   pos = buffer_pos - rep0;   pos = buffer_pos - rep0;
367   while (pos >= header.dict_size)   while (pos >= header.dict_size)
368   pos += header.dict_size;   pos += header.dict_size;
369   previous_byte = buffer[pos];   previous_byte = buffer[pos];
370   buffer[buffer_pos++] = previous_byte;   goto one_byte1;
371   if (buffer_pos == header.dict_size) {  #else
372   buffer_pos = 0;   len = 1;
373   global_pos += header.dict_size;   goto string;
374   if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)  #endif
  goto bad;  
  USE_DESKTOP(total_written += header.dict_size;)  
  }  
  continue;  
375   } else {   } else {
376   rc_update_bit_1(rc, prob);   rc_update_bit_1(rc, prob);
377   }   }
# Line 403  unlzma(int src_fd, int dst_fd) Line 407  unlzma(int src_fd, int dst_fd)
407   if (rc_is_bit_0(rc, prob_len)) {   if (rc_is_bit_0(rc, prob_len)) {
408   rc_update_bit_0(rc, prob_len);   rc_update_bit_0(rc, prob_len);
409   prob_len = (prob + LZMA_LEN_LOW   prob_len = (prob + LZMA_LEN_LOW
410   + (pos_state << LZMA_LEN_NUM_LOW_BITS));              + (pos_state << LZMA_LEN_NUM_LOW_BITS));
411   offset = 0;   offset = 0;
412   num_bits = LZMA_LEN_NUM_LOW_BITS;   num_bits = LZMA_LEN_NUM_LOW_BITS;
413   } else {   } else {
# Line 412  unlzma(int src_fd, int dst_fd) Line 416  unlzma(int src_fd, int dst_fd)
416   if (rc_is_bit_0(rc, prob_len)) {   if (rc_is_bit_0(rc, prob_len)) {
417   rc_update_bit_0(rc, prob_len);   rc_update_bit_0(rc, prob_len);
418   prob_len = (prob + LZMA_LEN_MID   prob_len = (prob + LZMA_LEN_MID
419   + (pos_state << LZMA_LEN_NUM_MID_BITS));              + (pos_state << LZMA_LEN_NUM_MID_BITS));
420   offset = 1 << LZMA_LEN_NUM_LOW_BITS;   offset = 1 << LZMA_LEN_NUM_LOW_BITS;
421   num_bits = LZMA_LEN_NUM_MID_BITS;   num_bits = LZMA_LEN_NUM_MID_BITS;
422   } else {   } else {
423   rc_update_bit_1(rc, prob_len);   rc_update_bit_1(rc, prob_len);
424   prob_len = prob + LZMA_LEN_HIGH;   prob_len = prob + LZMA_LEN_HIGH;
425   offset = ((1 << LZMA_LEN_NUM_LOW_BITS)   offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
426    + (1 << LZMA_LEN_NUM_MID_BITS));            + (1 << LZMA_LEN_NUM_MID_BITS));
427   num_bits = LZMA_LEN_NUM_HIGH_BITS;   num_bits = LZMA_LEN_NUM_HIGH_BITS;
428   }   }
429   }   }
# Line 430  unlzma(int src_fd, int dst_fd) Line 434  unlzma(int src_fd, int dst_fd)
434   int pos_slot;   int pos_slot;
435    
436   state += LZMA_NUM_LIT_STATES;   state += LZMA_NUM_LIT_STATES;
437   prob =   prob = p + LZMA_POS_SLOT +
438   p + LZMA_POS_SLOT +         ((len < LZMA_NUM_LEN_TO_POS_STATES ? len :
439   ((len <           LZMA_NUM_LEN_TO_POS_STATES - 1)
440    LZMA_NUM_LEN_TO_POS_STATES ? len :           << LZMA_NUM_POS_SLOT_BITS);
   LZMA_NUM_LEN_TO_POS_STATES - 1)  
  << LZMA_NUM_POS_SLOT_BITS);  
441   rc_bit_tree_decode(rc, prob, LZMA_NUM_POS_SLOT_BITS,   rc_bit_tree_decode(rc, prob, LZMA_NUM_POS_SLOT_BITS,
442     &pos_slot);     &pos_slot);
443   if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {   if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
# Line 466  unlzma(int src_fd, int dst_fd) Line 468  unlzma(int src_fd, int dst_fd)
468   }   }
469    
470   len += LZMA_MATCH_MIN_LEN;   len += LZMA_MATCH_MIN_LEN;
471     SKIP_FEATURE_LZMA_FAST(string:)
472   do {   do {
473   pos = buffer_pos - rep0;   pos = buffer_pos - rep0;
474   while (pos >= header.dict_size)   while (pos >= header.dict_size)
475   pos += header.dict_size;   pos += header.dict_size;
476   previous_byte = buffer[pos];   previous_byte = buffer[pos];
477     SKIP_FEATURE_LZMA_FAST(one_byte2:)
478   buffer[buffer_pos++] = previous_byte;   buffer[buffer_pos++] = previous_byte;
479   if (buffer_pos == header.dict_size) {   if (buffer_pos == header.dict_size) {
480   buffer_pos = 0;   buffer_pos = 0;
481   global_pos += header.dict_size;   global_pos += header.dict_size;
482   if (full_write(dst_fd, buffer, header.dict_size) != header.dict_size)   if (full_write(dst_fd, buffer, header.dict_size) != (ssize_t)header.dict_size)
483   goto bad;   goto bad;
484   USE_DESKTOP(total_written += header.dict_size;)   USE_DESKTOP(total_written += header.dict_size;)
485   }   }
# Line 485  unlzma(int src_fd, int dst_fd) Line 488  unlzma(int src_fd, int dst_fd)
488   }   }
489   }   }
490    
491     {
492   if (full_write(dst_fd, buffer, buffer_pos) != buffer_pos) {   SKIP_DESKTOP(int total_written = 0; /* success */)
493     USE_DESKTOP(total_written += buffer_pos;)
494     if (full_write(dst_fd, buffer, buffer_pos) != (ssize_t)buffer_pos) {
495   bad:   bad:
496     total_written = -1; /* failure */
497     }
498   rc_free(rc);   rc_free(rc);
499   return -1;   free(p);
500     free(buffer);
501     return total_written;
502   }   }
  rc_free(rc);  
  USE_DESKTOP(total_written += buffer_pos;)  
  return USE_DESKTOP(total_written) + 0;  
503  }  }

Legend:
Removed from v.815  
changed lines
  Added in v.816