File indexing completed on 2025-02-02 04:26:01
0001 /* Copyright 2015 the unarr project authors (see AUTHORS file). 0002 License: LGPLv3 */ 0003 0004 /* adapted from https://code.google.com/p/theunarchiver/source/browse/XADMaster/XADPrefixCode.m */ 0005 0006 #include "rar.h" 0007 0008 bool rar_new_node(struct huffman_code *code) 0009 { 0010 if (!code->tree) { 0011 code->minlength = INT_MAX; 0012 code->maxlength = INT_MIN; 0013 } 0014 if (code->numentries + 1 >= code->capacity) { 0015 /* in my small file sample, 1024 is the value needed most often */ 0016 int new_capacity = code->capacity ? code->capacity * 2 : 1024; 0017 void *new_tree = calloc(new_capacity, sizeof(*code->tree)); 0018 if (!new_tree) { 0019 warn("OOM during decompression"); 0020 return false; 0021 } 0022 memcpy(new_tree, code->tree, code->capacity * sizeof(*code->tree)); 0023 free(code->tree); 0024 code->tree = new_tree; 0025 code->capacity = new_capacity; 0026 } 0027 code->tree[code->numentries].branches[0] = -1; 0028 code->tree[code->numentries].branches[1] = -2; 0029 code->numentries++; 0030 return true; 0031 } 0032 0033 bool rar_add_value(struct huffman_code *code, int value, int codebits, int length) 0034 { 0035 int lastnode, bitpos, bit; 0036 0037 free(code->table); 0038 code->table = NULL; 0039 0040 if (length > code->maxlength) 0041 code->maxlength = length; 0042 if (length < code->minlength) 0043 code->minlength = length; 0044 0045 lastnode = 0; 0046 for (bitpos = length - 1; bitpos >= 0; bitpos--) { 0047 bit = (codebits >> bitpos) & 1; 0048 if (rar_is_leaf_node(code, lastnode)) { 0049 warn("Invalid data in bitstream"); /* prefix found */ 0050 return false; 0051 } 0052 if (code->tree[lastnode].branches[bit] < 0) { 0053 if (!rar_new_node(code)) 0054 return false; 0055 code->tree[lastnode].branches[bit] = code->numentries - 1; 0056 } 0057 lastnode = code->tree[lastnode].branches[bit]; 0058 } 0059 0060 if (code->tree[lastnode].branches[0] != -1 || code->tree[lastnode].branches[1] != -2) { 0061 warn("Invalid data in bitstream"); /* prefix found */ 0062 return false; 0063 } 0064 code->tree[lastnode].branches[0] = code->tree[lastnode].branches[1] = value; 0065 return true; 0066 } 0067 0068 bool rar_create_code(struct huffman_code *code, uint8_t *lengths, int numsymbols) 0069 { 0070 int symbolsleft = numsymbols; 0071 int codebits = 0; 0072 int i, j; 0073 0074 if (!rar_new_node(code)) 0075 return false; 0076 0077 for (i = 1; i <= 0x0F; i++) { 0078 for (j = 0; j < numsymbols; j++) { 0079 if (lengths[j] != i) 0080 continue; 0081 if (!rar_add_value(code, j, codebits, i)) 0082 return false; 0083 if (--symbolsleft <= 0) 0084 return true; 0085 codebits++; 0086 } 0087 codebits <<= 1; 0088 } 0089 return true; 0090 } 0091 0092 static bool rar_make_table_rec(struct huffman_code *code, int node, int offset, int depth, int maxdepth) 0093 { 0094 int currtablesize = 1 << (maxdepth - depth); 0095 0096 if (node < 0 || code->numentries <= node) { 0097 warn("Invalid data in bitstream"); /* invalid location to Huffman tree specified */ 0098 return false; 0099 } 0100 0101 if (rar_is_leaf_node(code, node)) { 0102 int i; 0103 for (i = 0; i < currtablesize; i++) { 0104 code->table[offset + i].length = depth; 0105 code->table[offset + i].value = code->tree[node].branches[0]; 0106 } 0107 } 0108 else if (depth == maxdepth) { 0109 code->table[offset].length = maxdepth + 1; 0110 code->table[offset].value = node; 0111 } 0112 else { 0113 if (!rar_make_table_rec(code, code->tree[node].branches[0], offset, depth + 1, maxdepth)) 0114 return false; 0115 if (!rar_make_table_rec(code, code->tree[node].branches[1], offset + currtablesize / 2, depth + 1, maxdepth)) 0116 return false; 0117 } 0118 return true; 0119 } 0120 0121 bool rar_make_table(struct huffman_code *code) 0122 { 0123 if (code->minlength <= code->maxlength && code->maxlength <= 10) 0124 code->tablesize = code->maxlength; 0125 else 0126 code->tablesize = 10; 0127 0128 code->table = calloc(1ULL << code->tablesize, sizeof(*code->table)); 0129 if (!code->table) { 0130 warn("OOM during decompression"); 0131 return false; 0132 } 0133 0134 return rar_make_table_rec(code, 0, 0, 0, code->tablesize); 0135 } 0136 0137 void rar_free_code(struct huffman_code *code) 0138 { 0139 free(code->tree); 0140 free(code->table); 0141 memset(code, 0, sizeof(*code)); 0142 }