TinyLzmaCompress.c 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984
  1. // TinyLZMA
  2. // Source from https://github.com/WangXuan95/TinyLzma
  3. #include <stdlib.h> // this code only use malloc and free
  4. #include "TinyLzmaCompress.h"
  5. // the code only use these basic types :
  6. // int : as return code
  7. // uint8_t : as compressed and uncompressed data, as LZMA state
  8. // uint16_t : as probabilities of range coder
  9. // uint32_t : as generic integers
  10. // size_t : as data length
  11. #define RET_IF_ERROR(expression) { \
  12. int res = (expression); \
  13. if (res != R_OK) \
  14. return res; \
  15. }
  16. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  17. // common useful functions
  18. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  19. static uint32_t bitsReverse (uint32_t bits, uint32_t bit_count) {
  20. uint32_t revbits = 0;
  21. for (; bit_count>0; bit_count--) {
  22. revbits <<= 1;
  23. revbits |= (bits & 1);
  24. bits >>= 1;
  25. }
  26. return revbits;
  27. }
  28. static uint32_t countBit (uint32_t val) { // count bits after the highest bit '1'
  29. uint32_t count = 0;
  30. for (; val!=0; val>>=1)
  31. count ++;
  32. return count;
  33. }
  34. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  35. // Range Encoder
  36. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  37. #define RANGE_CODE_NORMALIZE_THRESHOLD (1 << 24)
  38. #define RANGE_CODE_MOVE_BITS 5
  39. #define RANGE_CODE_N_BIT_MODEL_TOTAL_BITS 11
  40. #define RANGE_CODE_BIT_MODEL_TOTAL (1 << RANGE_CODE_N_BIT_MODEL_TOTAL_BITS)
  41. #define RANGE_CODE_HALF_PROBABILITY (RANGE_CODE_BIT_MODEL_TOTAL >> 1)
  42. #define RANGE_CODE_CACHE_SIZE_MAX (~((size_t)0))
  43. typedef struct {
  44. uint8_t overflow;
  45. uint8_t cache;
  46. uint8_t low_msb; // the 32th bit (high 1 bit) of "low"
  47. uint32_t low_lsb; // the 31~0th bit (low 32 bits) of "low". Note that ((low_msb<<32) | low_lsb) forms a 33-bit unsigned integer. The goal is to avoid using 64-bit integer type.
  48. uint32_t range;
  49. size_t cache_size;
  50. uint8_t *p_dst;
  51. uint8_t *p_dst_limit;
  52. } RangeEncoder_t;
  53. static RangeEncoder_t newRangeEncoder (uint8_t *p_dst, size_t dst_len) {
  54. RangeEncoder_t coder;
  55. coder.cache = 0;
  56. coder.low_msb = 0;
  57. coder.low_lsb = 0;
  58. coder.range = 0xFFFFFFFF;
  59. coder.cache_size = 1;
  60. coder.p_dst = p_dst;
  61. coder.p_dst_limit = p_dst + dst_len;
  62. coder.overflow = 0;
  63. return coder;
  64. }
  65. static void rangeEncodeOutByte (RangeEncoder_t *e, uint8_t byte) {
  66. if (e->p_dst != e->p_dst_limit)
  67. *(e->p_dst++) = byte;
  68. else
  69. e->overflow = 1;
  70. }
  71. static void rangeEncodeNormalize (RangeEncoder_t *e) {
  72. if (e->range < RANGE_CODE_NORMALIZE_THRESHOLD) {
  73. if (e->low_msb) { // if "low" is greater than or equal to (1<<32)
  74. rangeEncodeOutByte(e, e->cache+1);
  75. for (; e->cache_size>1; e->cache_size--)
  76. rangeEncodeOutByte(e, 0x00);
  77. e->cache = (uint8_t)((e->low_lsb) >> 24);
  78. e->cache_size = 0;
  79. } else if (e->low_lsb < 0xFF000000) { // if "low" is less than ((1<<32)-(1<<24))
  80. rangeEncodeOutByte(e, e->cache);
  81. for (; e->cache_size>1; e->cache_size--)
  82. rangeEncodeOutByte(e, 0xFF);
  83. e->cache = (uint8_t)((e->low_lsb) >> 24);
  84. e->cache_size = 0;
  85. }
  86. if (e->cache_size < RANGE_CODE_CACHE_SIZE_MAX)
  87. e->cache_size ++;
  88. e->low_msb = 0;
  89. e->low_lsb <<= 8;
  90. e->range <<= 8;
  91. }
  92. }
  93. static void rangeEncodeTerminate (RangeEncoder_t *e) {
  94. e->range = 0;
  95. rangeEncodeNormalize(e);
  96. rangeEncodeNormalize(e);
  97. rangeEncodeNormalize(e);
  98. rangeEncodeNormalize(e);
  99. rangeEncodeNormalize(e);
  100. rangeEncodeNormalize(e);
  101. }
  102. static void rangeEncodeIntByFixedProb (RangeEncoder_t *e, uint32_t val, uint32_t bit_count) {
  103. for (; bit_count>0; bit_count--) {
  104. uint8_t bit = 1 & (val >> (bit_count-1));
  105. rangeEncodeNormalize(e);
  106. e->range >>= 1;
  107. if (bit) {
  108. if ((e->low_lsb + e->range) < e->low_lsb) // if low_lsb + range overflow from 32-bit unsigned integer
  109. e->low_msb = 1;
  110. e->low_lsb += e->range;
  111. }
  112. }
  113. }
  114. static void rangeEncodeBit (RangeEncoder_t *e, uint16_t *p_prob, uint8_t bit) {
  115. uint32_t prob = *p_prob;
  116. uint32_t bound;
  117. rangeEncodeNormalize(e);
  118. bound = (e->range >> RANGE_CODE_N_BIT_MODEL_TOTAL_BITS) * prob;
  119. if (!bit) { // encode bit 0
  120. e->range = bound;
  121. *p_prob = (uint16_t)(prob + ((RANGE_CODE_BIT_MODEL_TOTAL - prob) >> RANGE_CODE_MOVE_BITS));
  122. } else { // encode bit 1
  123. e->range -= bound;
  124. if ((e->low_lsb + bound) < e->low_lsb) // if low_lsb + bound overflow from 32-bit unsigned integer
  125. e->low_msb = 1;
  126. e->low_lsb += bound;
  127. *p_prob = (uint16_t)(prob - (prob >> RANGE_CODE_MOVE_BITS));
  128. }
  129. }
  130. static void rangeEncodeInt (RangeEncoder_t *e, uint16_t *p_prob, uint32_t val, uint32_t bit_count) {
  131. uint32_t treepos = 1;
  132. for (; bit_count>0; bit_count--) {
  133. uint8_t bit = (uint8_t)(1 & (val >> (bit_count-1)));
  134. rangeEncodeBit(e, p_prob+(treepos-1), bit);
  135. treepos <<= 1;
  136. if (bit)
  137. treepos |= 1;
  138. }
  139. }
  140. static void rangeEncodeByteMatched (RangeEncoder_t *e, uint16_t *p_prob, uint32_t byte, uint32_t match_byte) {
  141. uint32_t i, treepos = 1, off0 = 0x100, off1;
  142. for (i=0; i<8; i++) {
  143. uint8_t bit = (uint8_t)(1 & (byte >> 7));
  144. byte <<= 1;
  145. match_byte <<= 1;
  146. off1 = off0;
  147. off0 &= match_byte;
  148. rangeEncodeBit(e, p_prob+(off0+off1+treepos-1), bit);
  149. treepos <<= 1;
  150. if (bit)
  151. treepos |= 1;
  152. else
  153. off0 ^= off1;
  154. }
  155. }
  156. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  157. // LZ {length, distance} searching algorithm
  158. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  159. #define LZ_LEN_MAX 273
  160. //#define LZ_DIST_MAX_PLUS1 0xFFFFFFFF
  161. #define LZ_DIST_MAX_PLUS1 0x40000000
  162. #define HASH_LEVEL 16
  163. #define HASH_N 21
  164. #define HASH_SIZE (1<<HASH_N)
  165. #define HASH_MASK ((1<<HASH_N)-1)
  166. #define INVALID_HASH_ITEM (~((size_t)0)) // use maximum value of size_t as invalid hash entry
  167. #define INIT_HASH_TABLE(hash_table) { \
  168. uint32_t i, j; \
  169. for (i=0; i<HASH_SIZE; i++) \
  170. for (j=0; j<HASH_LEVEL; j++) \
  171. hash_table[i][j] = INVALID_HASH_ITEM; \
  172. }
  173. static uint32_t getHash (const uint8_t *p_src, size_t src_len, size_t pos) {
  174. if (pos >= src_len || pos+1 == src_len || pos+2 == src_len)
  175. return 0 ;
  176. else
  177. #if HASH_N < 24
  178. return ((p_src[pos+2]<<16) + (p_src[pos+1]<<8) + p_src[pos]) & HASH_MASK;
  179. #else
  180. return ((p_src[pos+2]<<16) + (p_src[pos+1]<<8) + p_src[pos]);
  181. #endif
  182. }
  183. static void updateHashTable (const uint8_t *p_src, size_t src_len, size_t pos, size_t hash_table [][HASH_LEVEL]) {
  184. const uint32_t hash = getHash(p_src, src_len, pos);
  185. uint32_t i, oldest_i = 0;
  186. size_t oldest_pos = INVALID_HASH_ITEM;
  187. if (pos >= src_len)
  188. return;
  189. for (i=0; i<HASH_LEVEL; i++) {
  190. if (hash_table[hash][i] == INVALID_HASH_ITEM) { // find a invalid (empty) hash item
  191. hash_table[hash][i] = pos; // fill it
  192. return; // return immediently
  193. }
  194. if (oldest_pos > hash_table[hash][i]) { // search the oldest hash item
  195. oldest_pos = hash_table[hash][i];
  196. oldest_i = i;
  197. }
  198. }
  199. hash_table[hash][oldest_i] = pos;
  200. }
  201. static uint32_t lenDistScore (uint32_t len, uint32_t dist, uint32_t rep0, uint32_t rep1, uint32_t rep2, uint32_t rep3) {
  202. #define D 12
  203. static const uint32_t TABLE_THRESHOLDS [] = {D*D*D*D*D*5, D*D*D*D*4, D*D*D*3, D*D*2, D};
  204. uint32_t score;
  205. if (dist == rep0 || dist == rep1 || dist == rep2 || dist == rep3) {
  206. score = 5;
  207. } else {
  208. for (score=4; score>0; score--)
  209. if (dist <= TABLE_THRESHOLDS[score])
  210. break;
  211. }
  212. if (len < 2)
  213. return 8 + 5;
  214. else if (len == 2)
  215. return 8 + score + 1;
  216. else
  217. return 8 + score + len;
  218. }
  219. static void lzSearchMatch (const uint8_t *p_src, size_t src_len, size_t pos, size_t hash_table [][HASH_LEVEL], uint32_t *p_len, uint32_t *p_dist) {
  220. const uint32_t len_max = ((src_len-pos) < LZ_LEN_MAX) ? (src_len-pos) : LZ_LEN_MAX;
  221. const uint32_t hash = getHash(p_src, src_len, pos);
  222. uint32_t i, j, score1, score2;
  223. *p_len = 0;
  224. *p_dist = 0;
  225. score1 = lenDistScore(0, 0xFFFFFFFF, 0, 0, 0, 0);
  226. for (i=0; i<HASH_LEVEL+2; i++) {
  227. size_t ppos = (i<HASH_LEVEL) ? hash_table[hash][i] : (pos-1-(i-HASH_LEVEL));
  228. if (ppos != INVALID_HASH_ITEM && ppos < pos && (pos - ppos) < LZ_DIST_MAX_PLUS1) {
  229. for (j=0; j<len_max; j++)
  230. if (p_src[pos+j] != p_src[ppos+j])
  231. break;
  232. score2 = lenDistScore(j, (pos-ppos), 0, 0, 0, 0);
  233. if (j >= 2 && score1 < score2) {
  234. score1 = score2;
  235. *p_len = j;
  236. *p_dist = pos - ppos;
  237. }
  238. }
  239. }
  240. }
  241. static void lzSearchRep (const uint8_t *p_src, size_t src_len, size_t pos, uint32_t rep0, uint32_t rep1, uint32_t rep2, uint32_t rep3, uint32_t len_limit, uint32_t *p_len, uint32_t *p_dist) {
  242. uint32_t len_max = ((src_len-pos) < LZ_LEN_MAX) ? (src_len-pos) : LZ_LEN_MAX;
  243. uint32_t reps [4];
  244. uint32_t i, j;
  245. if (len_max > len_limit)
  246. len_max = len_limit;
  247. reps[0] = rep0; reps[1] = rep1; reps[2] = rep2; reps[3] = rep3;
  248. *p_len = 0;
  249. *p_dist = 0;
  250. for (i=0; i<4; i++) {
  251. if (reps[i] <= pos) {
  252. size_t ppos = pos - reps[i];
  253. for (j=0; j<len_max; j++)
  254. if (p_src[pos+j] != p_src[ppos+j])
  255. break;
  256. if (j >= 2 && j > *p_len) {
  257. *p_len = j;
  258. *p_dist = reps[i];
  259. }
  260. }
  261. }
  262. }
  263. static void lzSearch (const uint8_t *p_src, size_t src_len, size_t pos, uint32_t rep0, uint32_t rep1, uint32_t rep2, uint32_t rep3, size_t hash_table [][HASH_LEVEL], uint32_t *p_len, uint32_t *p_dist) {
  264. uint32_t rlen, rdist;
  265. uint32_t mlen, mdist;
  266. lzSearchRep(p_src, src_len, pos, rep0, rep1, rep2, rep3, 0xFFFFFFFF, &rlen, &rdist);
  267. lzSearchMatch(p_src, src_len, pos, hash_table, &mlen, &mdist);
  268. if ( lenDistScore(rlen, rdist, rep0, rep1, rep2, rep3) >= lenDistScore(mlen, mdist, rep0, rep1, rep2, rep3) ) {
  269. *p_len = rlen;
  270. *p_dist = rdist;
  271. } else {
  272. *p_len = mlen;
  273. *p_dist = mdist;
  274. }
  275. }
  276. static uint8_t isShortRep (const uint8_t *p_src, size_t src_len, size_t pos, uint32_t rep0) {
  277. return (pos >= rep0 && (p_src[pos] == p_src[pos-rep0])) ? 1 : 0;
  278. }
  279. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  280. // LZMA Encoder
  281. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  282. typedef enum { // packet_type
  283. PKT_LIT,
  284. PKT_MATCH,
  285. PKT_SHORTREP,
  286. PKT_REP0, // LONGREP0
  287. PKT_REP1, // LONGREP1
  288. PKT_REP2, // LONGREP2
  289. PKT_REP3 // LONGREP3
  290. } PACKET_t;
  291. static uint8_t stateTransition (uint8_t state, PACKET_t type) {
  292. switch (state) {
  293. case 0 : return (type==PKT_LIT) ? 0 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  294. case 1 : return (type==PKT_LIT) ? 0 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  295. case 2 : return (type==PKT_LIT) ? 0 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  296. case 3 : return (type==PKT_LIT) ? 0 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  297. case 4 : return (type==PKT_LIT) ? 1 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  298. case 5 : return (type==PKT_LIT) ? 2 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  299. case 6 : return (type==PKT_LIT) ? 3 : (type==PKT_MATCH) ? 7 : (type==PKT_SHORTREP) ? 9 : 8;
  300. case 7 : return (type==PKT_LIT) ? 4 : (type==PKT_MATCH) ? 10 : (type==PKT_SHORTREP) ? 11 : 11;
  301. case 8 : return (type==PKT_LIT) ? 5 : (type==PKT_MATCH) ? 10 : (type==PKT_SHORTREP) ? 11 : 11;
  302. case 9 : return (type==PKT_LIT) ? 6 : (type==PKT_MATCH) ? 10 : (type==PKT_SHORTREP) ? 11 : 11;
  303. case 10 : return (type==PKT_LIT) ? 4 : (type==PKT_MATCH) ? 10 : (type==PKT_SHORTREP) ? 11 : 11;
  304. case 11 : return (type==PKT_LIT) ? 5 : (type==PKT_MATCH) ? 10 : (type==PKT_SHORTREP) ? 11 : 11;
  305. default : return 0xFF; // 0xFF is invalid state which will never appear
  306. }
  307. }
  308. #define N_STATES 12
  309. #define N_LIT_STATES 7
  310. #define LC 3 // valid range : 0~8
  311. #define N_PREV_BYTE_LC_MSBS (1 << LC)
  312. #define LC_SHIFT (8 - LC)
  313. #define LC_MASK ((1 << LC) - 1)
  314. #define LP 0 // valid range : 0~4
  315. #define N_LIT_POS_STATES (1 << LP)
  316. #define LP_MASK ((1 << LP) - 1)
  317. #define PB 3 // valid range : 0~4
  318. #define N_POS_STATES (1 << PB)
  319. #define PB_MASK ((1 << PB) - 1)
  320. #define LCLPPB_BYTE ((uint8_t)( (PB * 5 + LP) * 9 + LC ))
  321. #define INIT_PROBS(probs) { \
  322. uint16_t *p = (uint16_t*)(probs); \
  323. uint16_t *q = p + (sizeof(probs) / sizeof(uint16_t)); \
  324. for (; p<q; p++) \
  325. *p = RANGE_CODE_HALF_PROBABILITY; \
  326. } // all probabilities are init to 50% (half probability)
  327. static int lzmaEncode (const uint8_t *p_src, size_t src_len, uint8_t *p_dst, size_t *p_dst_len, uint8_t with_end_mark) {
  328. uint8_t state = 0; // valid value : 0~12
  329. size_t pos = 0; // position of uncompressed data (p_dst)
  330. uint32_t rep0 = 1;
  331. uint32_t rep1 = 1;
  332. uint32_t rep2 = 1;
  333. uint32_t rep3 = 1;
  334. uint32_t n_bypass=0, len_bypass=0, dist_bypass=0;
  335. RangeEncoder_t coder = newRangeEncoder(p_dst, *p_dst_len);
  336. // probability arrays ---------------------------------------
  337. uint16_t probs_is_match [N_STATES] [N_POS_STATES] ;
  338. uint16_t probs_is_rep [N_STATES] ;
  339. uint16_t probs_is_rep0 [N_STATES] ;
  340. uint16_t probs_is_rep0_long [N_STATES] [N_POS_STATES] ;
  341. uint16_t probs_is_rep1 [N_STATES] ;
  342. uint16_t probs_is_rep2 [N_STATES] ;
  343. uint16_t probs_literal [N_LIT_POS_STATES] [N_PREV_BYTE_LC_MSBS] [3*(1<<8)];
  344. uint16_t probs_dist_slot [4] [(1<<6)-1];
  345. uint16_t probs_dist_special [10] [(1<<5)-1];
  346. uint16_t probs_dist_align [(1<<4)-1];
  347. uint16_t probs_len_choice [2];
  348. uint16_t probs_len_choice2 [2];
  349. uint16_t probs_len_low [2] [N_POS_STATES] [(1<<3)-1];
  350. uint16_t probs_len_mid [2] [N_POS_STATES] [(1<<3)-1];
  351. uint16_t probs_len_high [2] [(1<<8)-1];
  352. // size_t hash_table [HASH_SIZE][HASH_LEVEL]; // if HASH_LEVEL and HASH_SIZE is small, you can use this instead of malloc
  353. size_t (*hash_table) [HASH_LEVEL];
  354. hash_table = (size_t (*) [HASH_LEVEL]) malloc (sizeof(size_t) * HASH_SIZE * HASH_LEVEL); // if HASH_LEVEL and HASH_SIZE is large, we must use malloc instead of local variables to prevent stack-overflow
  355. if (hash_table == 0)
  356. return R_ERR_MEMORY_RUNOUT;
  357. INIT_HASH_TABLE(hash_table);
  358. INIT_PROBS(probs_is_match);
  359. INIT_PROBS(probs_is_rep);
  360. INIT_PROBS(probs_is_rep0);
  361. INIT_PROBS(probs_is_rep0_long);
  362. INIT_PROBS(probs_is_rep1);
  363. INIT_PROBS(probs_is_rep2);
  364. INIT_PROBS(probs_literal);
  365. INIT_PROBS(probs_dist_slot);
  366. INIT_PROBS(probs_dist_special);
  367. INIT_PROBS(probs_dist_align);
  368. INIT_PROBS(probs_len_choice);
  369. INIT_PROBS(probs_len_choice2);
  370. INIT_PROBS(probs_len_low);
  371. INIT_PROBS(probs_len_mid);
  372. INIT_PROBS(probs_len_high);
  373. while (!coder.overflow) {
  374. const uint32_t lit_pos_state = LP_MASK & (uint32_t)pos;
  375. const uint32_t pos_state = PB_MASK & (uint32_t)pos;
  376. uint32_t curr_byte=0, match_byte=0, prev_byte_lc_msbs=0;
  377. uint32_t dist=0, len=0;
  378. PACKET_t type;
  379. if (pos < src_len)
  380. curr_byte = p_src[pos];
  381. if (pos > 0) {
  382. match_byte = p_src[pos-rep0];
  383. prev_byte_lc_msbs = (p_src[pos-1] >> LC_SHIFT) & LC_MASK;
  384. }
  385. if (pos >= src_len) { // input end (no more data to be encoded)
  386. if (!with_end_mark) // if user dont want to encode end marker
  387. break; // finish immediently
  388. with_end_mark = 0; // clear with_end_mark. we will finish at the next loop
  389. type = PKT_MATCH; // the end marker is regarded as a MATCH packet
  390. len = 2; // this MATCH packet's len = 2
  391. dist = 0; // this MATCH packet's dist = 0, in next steps, we will encode dist-1 (0xFFFFFFFF), aka end marker
  392. } else { // there are still data need to be encoded
  393. if (n_bypass > 0) {
  394. len = 0;
  395. dist = 0;
  396. n_bypass --;
  397. } else if (len_bypass > 0) {
  398. len = len_bypass;
  399. dist = dist_bypass;
  400. len_bypass = 0;
  401. dist_bypass = 0;
  402. } else {
  403. lzSearch(p_src, src_len, pos, rep0, rep1, rep2, rep3, hash_table, &len, &dist);
  404. if ((src_len-pos)>8 && len>=2) {
  405. const uint32_t score0 = lenDistScore(len, dist, rep0, rep1, rep2, rep3);
  406. uint32_t len1=0, dist1=0, score1=0;
  407. uint32_t len2=0, dist2=0, score2=0;
  408. lzSearch(p_src, src_len, pos+1, rep0, rep1, rep2, rep3, hash_table, &len1, &dist1);
  409. score1 = lenDistScore(len1, dist1, rep0, rep1, rep2, rep3);
  410. if (len >= 3) {
  411. lzSearch(p_src, src_len, pos+2, rep0, rep1, rep2, rep3, hash_table, &len2, &dist2);
  412. score2 = lenDistScore(len2, dist2, rep0, rep1, rep2, rep3) - 1;
  413. }
  414. if (score2 > score0 && score2 > score1) {
  415. len = 0;
  416. dist = 0;
  417. lzSearchRep(p_src, src_len, pos, rep0, rep1, rep2, rep3, 2, &len, &dist);
  418. len_bypass = len2;
  419. dist_bypass = dist2;
  420. n_bypass = (len<2) ? 1 : 0;
  421. } else if (score1 > score0) {
  422. len = 0;
  423. dist = 0;
  424. len_bypass = len1;
  425. dist_bypass = dist1;
  426. n_bypass = 0;
  427. }
  428. }
  429. }
  430. if (len < 2) {
  431. type = isShortRep(p_src, src_len, pos, rep0) ? PKT_SHORTREP : PKT_LIT;
  432. } else if (dist == rep0) {
  433. type = PKT_REP0;
  434. } else if (dist == rep1) {
  435. type = PKT_REP1;
  436. rep1 = rep0;
  437. rep0 = dist;
  438. } else if (dist == rep2) {
  439. type = PKT_REP2;
  440. rep2 = rep1;
  441. rep1 = rep0;
  442. rep0 = dist;
  443. } else if (dist == rep3) {
  444. type = PKT_REP3;
  445. rep3 = rep2;
  446. rep2 = rep1;
  447. rep1 = rep0;
  448. rep0 = dist;
  449. } else {
  450. type = PKT_MATCH;
  451. rep3 = rep2;
  452. rep2 = rep1;
  453. rep1 = rep0;
  454. rep0 = dist;
  455. }
  456. {
  457. const size_t pos2 = pos + ((type==PKT_LIT || type==PKT_SHORTREP) ? 1 : len);
  458. for (; pos<pos2; pos++)
  459. updateHashTable(p_src, src_len, pos, hash_table);
  460. }
  461. }
  462. switch (type) {
  463. case PKT_LIT :
  464. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 0);
  465. break;
  466. case PKT_MATCH :
  467. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  468. rangeEncodeBit(&coder, &probs_is_rep [state] , 0);
  469. break;
  470. case PKT_SHORTREP :
  471. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  472. rangeEncodeBit(&coder, &probs_is_rep [state] , 1);
  473. rangeEncodeBit(&coder, &probs_is_rep0 [state] , 0);
  474. rangeEncodeBit(&coder, &probs_is_rep0_long[state][pos_state], 0);
  475. break;
  476. case PKT_REP0 :
  477. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  478. rangeEncodeBit(&coder, &probs_is_rep [state] , 1);
  479. rangeEncodeBit(&coder, &probs_is_rep0 [state] , 0);
  480. rangeEncodeBit(&coder, &probs_is_rep0_long[state][pos_state], 1);
  481. break;
  482. case PKT_REP1 :
  483. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  484. rangeEncodeBit(&coder, &probs_is_rep [state] , 1);
  485. rangeEncodeBit(&coder, &probs_is_rep0 [state] , 1);
  486. rangeEncodeBit(&coder, &probs_is_rep1 [state] , 0);
  487. break;
  488. case PKT_REP2 :
  489. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  490. rangeEncodeBit(&coder, &probs_is_rep [state] , 1);
  491. rangeEncodeBit(&coder, &probs_is_rep0 [state] , 1);
  492. rangeEncodeBit(&coder, &probs_is_rep1 [state] , 1);
  493. rangeEncodeBit(&coder, &probs_is_rep2 [state] , 0);
  494. break;
  495. default : // PKT_REP3
  496. rangeEncodeBit(&coder, &probs_is_match [state][pos_state], 1);
  497. rangeEncodeBit(&coder, &probs_is_rep [state] , 1);
  498. rangeEncodeBit(&coder, &probs_is_rep0 [state] , 1);
  499. rangeEncodeBit(&coder, &probs_is_rep1 [state] , 1);
  500. rangeEncodeBit(&coder, &probs_is_rep2 [state] , 1);
  501. break;
  502. }
  503. if (type == PKT_LIT) {
  504. if (state < N_LIT_STATES)
  505. rangeEncodeInt (&coder, probs_literal[lit_pos_state][prev_byte_lc_msbs], curr_byte, 8);
  506. else
  507. rangeEncodeByteMatched(&coder, probs_literal[lit_pos_state][prev_byte_lc_msbs], curr_byte, match_byte);
  508. }
  509. if (type == PKT_MATCH || type == PKT_REP0 || type == PKT_REP1 || type == PKT_REP2 || type == PKT_REP3) {
  510. const uint8_t isrep = (type != PKT_MATCH);
  511. if (len < 10) { // len = 2~9
  512. rangeEncodeBit(&coder, &probs_len_choice [isrep], 0);
  513. rangeEncodeInt(&coder, probs_len_low [isrep][pos_state], len-2 , 3);
  514. } else if (len < 18) { // len = 10~17
  515. rangeEncodeBit(&coder, &probs_len_choice [isrep], 1);
  516. rangeEncodeBit(&coder, &probs_len_choice2[isrep], 0);
  517. rangeEncodeInt(&coder, probs_len_mid [isrep][pos_state], len-10, 3);
  518. } else { // len = 18~273
  519. rangeEncodeBit(&coder, &probs_len_choice [isrep], 1);
  520. rangeEncodeBit(&coder, &probs_len_choice2[isrep], 1);
  521. rangeEncodeInt(&coder, probs_len_high [isrep], len-18, 8);
  522. }
  523. }
  524. if (type == PKT_MATCH) {
  525. const uint32_t len_min5_minus2 = (len>5) ? 3 : (len-2);
  526. uint32_t dist_slot, bcnt, bits;
  527. dist --;
  528. if (dist < 4) {
  529. dist_slot = dist;
  530. } else {
  531. dist_slot = countBit(dist) - 1;
  532. dist_slot = (dist_slot<<1) | ((dist>>(dist_slot-1)) & 1);
  533. }
  534. rangeEncodeInt(&coder, probs_dist_slot[len_min5_minus2], dist_slot, 6);
  535. if (dist_slot >= 14) { // dist slot = 14~63
  536. bcnt = (dist_slot >> 1) - 5;
  537. bits = (dist>>4) & ((1<<bcnt)-1);
  538. rangeEncodeIntByFixedProb(&coder, bits, bcnt);
  539. bcnt = 4;
  540. bits = dist & ((1<<bcnt)-1);
  541. bits = bitsReverse(bits, bcnt);
  542. rangeEncodeInt(&coder, probs_dist_align, bits, bcnt);
  543. } else if (dist_slot >= 4) { // dist slot = 4~13
  544. bcnt = (dist_slot >> 1) - 1;
  545. bits = dist & ((1<<bcnt)-1);
  546. bits = bitsReverse(bits, bcnt);
  547. rangeEncodeInt(&coder, probs_dist_special[dist_slot-4], bits, bcnt);
  548. }
  549. }
  550. state = stateTransition(state, type);
  551. }
  552. free(hash_table);
  553. rangeEncodeTerminate(&coder);
  554. if (coder.overflow)
  555. return R_ERR_OUTPUT_OVERFLOW;
  556. *p_dst_len = coder.p_dst - p_dst;
  557. return R_OK;
  558. }
  559. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  560. // LZMA compress function, output data is packed in ".lzma" format
  561. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  562. #define LZMA_DIC_MIN 4096
  563. #define LZMA_DIC_LEN ((LZ_DIST_MAX_PLUS1>LZMA_DIC_MIN) ? LZ_DIST_MAX_PLUS1 : LZMA_DIC_MIN)
  564. #define LZMA_HEADER_LEN 13
  565. static int writeLzmaHeader (uint8_t *p_dst, size_t *p_dst_len, size_t uncompressed_len, uint8_t uncompressed_len_known) {
  566. uint32_t i;
  567. if (*p_dst_len < LZMA_HEADER_LEN)
  568. return R_ERR_OUTPUT_OVERFLOW;
  569. *p_dst_len = LZMA_HEADER_LEN;
  570. *(p_dst++) = LCLPPB_BYTE;
  571. for (i=0; i<4; i++)
  572. *(p_dst++) = (uint8_t)(LZMA_DIC_LEN >> (i*8));
  573. for (i=0; i<8; i++) {
  574. if (uncompressed_len_known) {
  575. *(p_dst++) = (uint8_t)uncompressed_len;
  576. uncompressed_len >>= 8;
  577. } else {
  578. *(p_dst++) = 0xFF;
  579. }
  580. }
  581. return R_OK;
  582. }
  583. int tinyLzmaCompress (const uint8_t *p_src, size_t src_len, uint8_t *p_dst, size_t *p_dst_len) {
  584. size_t hdr_len, cmprs_len;
  585. hdr_len = *p_dst_len; // set available space for header length
  586. RET_IF_ERROR( writeLzmaHeader(p_dst, &hdr_len, src_len, 1) ); //
  587. cmprs_len = *p_dst_len - hdr_len; // set available space for compressed data length
  588. RET_IF_ERROR( lzmaEncode(p_src, src_len, p_dst+hdr_len, &cmprs_len, 1) ); // do compression
  589. *p_dst_len = hdr_len + cmprs_len; // the final output data length = LZMA file header len + compressed data len
  590. return R_OK;
  591. }
  592. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  593. // LZMA compress function, output data is packed in ".zip" format, with a single file in this zip package
  594. /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  595. static size_t getStringLength (const char *string) {
  596. size_t i;
  597. for (i=0; *string; string++, i++);
  598. return i;
  599. }
  600. #define ZIP_LZMA_PROPERTY_LEN 9
  601. #define ZIP_HEADER_LEN_EXCLUDE_FILENAME 30
  602. #define ZIP_FOOTER_LEN_EXCLUDE_FILENAME (46 + 22)
  603. #define FILE_NAME_IN_ZIP_MAX_LEN ((size_t)0xFF00)
  604. #define ZIP_UNCOMPRESSED_MAX_LEN ((size_t)0xFFFF0000)
  605. #define ZIP_COMPRESSED_MAX_LEN ((size_t)0xFFFF0000)
  606. static int writeZipHeader (uint8_t *p_dst, size_t *p_dst_len, uint32_t crc, size_t compressed_len, size_t uncompressed_len, const char *file_name) {
  607. size_t i;
  608. const size_t file_name_len = getStringLength(file_name);
  609. if (file_name_len > FILE_NAME_IN_ZIP_MAX_LEN)
  610. return R_ERR_UNSUPPORTED;
  611. if (uncompressed_len > ZIP_UNCOMPRESSED_MAX_LEN) // ".zip" format don't support uncompressed size > 32-bit integer
  612. return R_ERR_UNSUPPORTED;
  613. if (compressed_len > ZIP_COMPRESSED_MAX_LEN) // ".zip" format don't support compressed size > 32-bit integer
  614. return R_ERR_UNSUPPORTED;
  615. if (*p_dst_len < ZIP_HEADER_LEN_EXCLUDE_FILENAME + file_name_len) // no enough space for writing ZIP header
  616. return R_ERR_OUTPUT_OVERFLOW;
  617. *p_dst_len = ZIP_HEADER_LEN_EXCLUDE_FILENAME + file_name_len;
  618. // Local File Header ----------------------------------------------------
  619. *(p_dst++) = 0x50; // 0~3 Local file header signature # 0x04034b50 (read as a little-endian number)
  620. *(p_dst++) = 0x4B;
  621. *(p_dst++) = 0x03;
  622. *(p_dst++) = 0x04;
  623. *(p_dst++) = 0x3F; // 4~5 Version needed to extract (minimum)
  624. *(p_dst++) = 0x00;
  625. *(p_dst++) = 0x00; // 6~7 General purpose bit flag
  626. *(p_dst++) = 0x00;
  627. *(p_dst++) = 0x0E; // 8~9 Compression method (0x0E = LZMA)
  628. *(p_dst++) = 0x00;
  629. *(p_dst++) = 0x00; // 10~11 File last modification time
  630. *(p_dst++) = 0x00;
  631. *(p_dst++) = 0x00; // 12~13 File last modification date
  632. *(p_dst++) = 0x00;
  633. *(p_dst++) = (uint8_t)(crc >> 0); // 14~17 CRC-32
  634. *(p_dst++) = (uint8_t)(crc >> 8);
  635. *(p_dst++) = (uint8_t)(crc >>16);
  636. *(p_dst++) = (uint8_t)(crc >>24);
  637. *(p_dst++) = (uint8_t)(compressed_len >> 0); // 18~21 Compressed size
  638. *(p_dst++) = (uint8_t)(compressed_len >> 8);
  639. *(p_dst++) = (uint8_t)(compressed_len >>16);
  640. *(p_dst++) = (uint8_t)(compressed_len >>24);
  641. *(p_dst++) = (uint8_t)(uncompressed_len >> 0); // 22~25 Uncompressed size
  642. *(p_dst++) = (uint8_t)(uncompressed_len >> 8);
  643. *(p_dst++) = (uint8_t)(uncompressed_len >>16);
  644. *(p_dst++) = (uint8_t)(uncompressed_len >>24);
  645. *(p_dst++) = (uint8_t)(file_name_len >> 0); // 26~27 File name length (n)
  646. *(p_dst++) = (uint8_t)(file_name_len >> 8);
  647. *(p_dst++) = 0x00; // 28~29 Extra field length (m)
  648. *(p_dst++) = 0x00;
  649. for (i=0; i<file_name_len; i++) // 46~46+file_name_len-1 : File Name
  650. *(p_dst++) = file_name[i];
  651. return R_OK;
  652. }
  653. static int writeZipLzmaProperty (uint8_t *p_dst, size_t *p_dst_len) {
  654. if (*p_dst_len < ZIP_LZMA_PROPERTY_LEN) // no enough space for writing ZIP's LZMA property
  655. return R_ERR_OUTPUT_OVERFLOW;
  656. *p_dst_len = ZIP_LZMA_PROPERTY_LEN;
  657. *(p_dst++) = 0x10;
  658. *(p_dst++) = 0x02;
  659. *(p_dst++) = 0x05;
  660. *(p_dst++) = 0x00;
  661. *(p_dst++) = LCLPPB_BYTE;
  662. *(p_dst++) = (uint8_t)(LZMA_DIC_LEN >> 0);
  663. *(p_dst++) = (uint8_t)(LZMA_DIC_LEN >> 8);
  664. *(p_dst++) = (uint8_t)(LZMA_DIC_LEN >>16);
  665. *(p_dst++) = (uint8_t)(LZMA_DIC_LEN >>24);
  666. return R_OK;
  667. }
  668. static int writeZipFooter (uint8_t *p_dst, size_t *p_dst_len, uint32_t crc, size_t compressed_len, size_t uncompressed_len, const char *file_name, size_t offset) {
  669. size_t i;
  670. const size_t file_name_len = getStringLength(file_name);
  671. if (*p_dst_len < ZIP_FOOTER_LEN_EXCLUDE_FILENAME + file_name_len) // no enough space for writing ZIP footer
  672. return R_ERR_OUTPUT_OVERFLOW;
  673. *p_dst_len = ZIP_FOOTER_LEN_EXCLUDE_FILENAME + file_name_len;
  674. // Central Directory File Header ----------------------------------------------------
  675. *(p_dst++) = 0x50; // 0~3 Central directory file header signature # 0x02014b50
  676. *(p_dst++) = 0x4B;
  677. *(p_dst++) = 0x01;
  678. *(p_dst++) = 0x02;
  679. *(p_dst++) = 0x1E; // 4~5 Version made by
  680. *(p_dst++) = 0x03;
  681. *(p_dst++) = 0x3F; // 6~7 Version needed to extract (minimum)
  682. *(p_dst++) = 0x00;
  683. *(p_dst++) = 0x00; // 8~9 General purpose bit flag
  684. *(p_dst++) = 0x00;
  685. *(p_dst++) = 0x0E; // 10~11 Compression method : 14 = LZMA
  686. *(p_dst++) = 0x00;
  687. *(p_dst++) = 0x00; // 12~13 File last modification time
  688. *(p_dst++) = 0x00;
  689. *(p_dst++) = 0x00; // 14~15 File last modification date
  690. *(p_dst++) = 0x00;
  691. *(p_dst++) = (uint8_t)(crc >> 0); // 16~19 CRC-32
  692. *(p_dst++) = (uint8_t)(crc >> 8);
  693. *(p_dst++) = (uint8_t)(crc >>16);
  694. *(p_dst++) = (uint8_t)(crc >>24);
  695. *(p_dst++) = (uint8_t)(compressed_len >> 0); // 20~23 Compressed size
  696. *(p_dst++) = (uint8_t)(compressed_len >> 8);
  697. *(p_dst++) = (uint8_t)(compressed_len >>16);
  698. *(p_dst++) = (uint8_t)(compressed_len >>24);
  699. *(p_dst++) = (uint8_t)(uncompressed_len >> 0); // 24~27 Uncompressed size
  700. *(p_dst++) = (uint8_t)(uncompressed_len >> 8);
  701. *(p_dst++) = (uint8_t)(uncompressed_len >>16);
  702. *(p_dst++) = (uint8_t)(uncompressed_len >>24);
  703. *(p_dst++) = (uint8_t)(file_name_len >> 0); // 28~29 File name length (n)
  704. *(p_dst++) = (uint8_t)(file_name_len >> 8);
  705. *(p_dst++) = 0x00; // 30~31 Extra field length (m)
  706. *(p_dst++) = 0x00;
  707. *(p_dst++) = 0x00; // 32~33 File comment length (k)
  708. *(p_dst++) = 0x00;
  709. *(p_dst++) = 0x00; // 34~35 Disk number where file starts
  710. *(p_dst++) = 0x00;
  711. *(p_dst++) = 0x00; // 36~37 Internal file attributes
  712. *(p_dst++) = 0x00;
  713. *(p_dst++) = 0x00; // 38~41 External file attributes
  714. *(p_dst++) = 0x00;
  715. *(p_dst++) = 0x00;
  716. *(p_dst++) = 0x00;
  717. *(p_dst++) = 0x00; // 42~45 Relative offset of local file header.
  718. *(p_dst++) = 0x00;
  719. *(p_dst++) = 0x00;
  720. *(p_dst++) = 0x00;
  721. for (i=0; i<file_name_len; i++) // 46~46+file_name_len-1 : File Name
  722. *(p_dst++) = file_name[i];
  723. // End of Central Directory Record ----------------------------------------------------
  724. *(p_dst++) = 0x50; // 0~3 End of central directory signature # 0x06054b50
  725. *(p_dst++) = 0x4B;
  726. *(p_dst++) = 0x05;
  727. *(p_dst++) = 0x06;
  728. *(p_dst++) = 0x00; // 4~5 Number of this disk
  729. *(p_dst++) = 0x00;
  730. *(p_dst++) = 0x00; // 6~7 Disk where central directory starts
  731. *(p_dst++) = 0x00;
  732. *(p_dst++) = 0x01; // 8~9 Number of central directory records on this disk
  733. *(p_dst++) = 0x00;
  734. *(p_dst++) = 0x01; // 10~11 Total number of central directory records
  735. *(p_dst++) = 0x00;
  736. *(p_dst++) = (uint8_t)((46+file_name_len) >> 0); // 12~15 Size of central directory (bytes)
  737. *(p_dst++) = (uint8_t)((46+file_name_len) >> 8);
  738. *(p_dst++) = (uint8_t)((46+file_name_len) >>16);
  739. *(p_dst++) = (uint8_t)((46+file_name_len) >>24);
  740. *(p_dst++) = (uint8_t)(offset >> 0); // 16~19 Offset of start of central directory, relative to start of archive (pos of p_dst)
  741. *(p_dst++) = (uint8_t)(offset >> 8);
  742. *(p_dst++) = (uint8_t)(offset >>16);
  743. *(p_dst++) = (uint8_t)(offset >>24);
  744. *(p_dst++) = 0x00; // 20~21 Comment length (n)
  745. *(p_dst++) = 0x00;
  746. return R_OK;
  747. }
  748. static uint32_t calcCrc32 (const uint8_t *p_src, size_t src_len) {
  749. static const uint32_t TABLE_CRC32 [] = { 0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac, 0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c, 0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c, 0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c };
  750. uint32_t crc = 0xFFFFFFFF;
  751. const uint8_t *p_end = p_src + src_len;
  752. for (; p_src<p_end; p_src++) {
  753. crc ^= *p_src;
  754. crc = TABLE_CRC32[crc & 0x0f] ^ (crc >> 4);
  755. crc = TABLE_CRC32[crc & 0x0f] ^ (crc >> 4);
  756. }
  757. return ~crc;
  758. }
  759. int tinyLzmaCompressToZipContainer (const uint8_t *p_src, size_t src_len, uint8_t *p_dst, size_t *p_dst_len, const char *file_name_in_zip) {
  760. size_t zip_hdr_len, lzma_prop_len, cmprs_len, zip_ftr_len; // there are 4 parts of the final output data : ZIP header, ZIP LZMA property, LZMA compressed data, and ZIP footer
  761. uint32_t crc;
  762. zip_hdr_len = *p_dst_len; // set available space for ZIP header
  763. RET_IF_ERROR( writeZipHeader(p_dst, &zip_hdr_len, 0, 0, src_len, file_name_in_zip) ); // note that some fields are unknown and filled using "0", we should rewrite it later
  764. lzma_prop_len = *p_dst_len - zip_hdr_len; // set available space for ZIP LZMA property
  765. RET_IF_ERROR( writeZipLzmaProperty(p_dst+zip_hdr_len, &lzma_prop_len) );
  766. cmprs_len = *p_dst_len - zip_hdr_len - lzma_prop_len; // set available space for LZMA compressed data
  767. RET_IF_ERROR( lzmaEncode(p_src, src_len, p_dst+zip_hdr_len+lzma_prop_len, &cmprs_len, 1) );
  768. if (cmprs_len > ZIP_COMPRESSED_MAX_LEN)
  769. return R_ERR_UNSUPPORTED;
  770. cmprs_len += lzma_prop_len; // ZIP's LZMA property is actually a part of compressed data
  771. crc = calcCrc32(p_src, src_len);
  772. zip_ftr_len = *p_dst_len - zip_hdr_len - cmprs_len; // set available space for ZIP footer
  773. RET_IF_ERROR( writeZipFooter(p_dst+zip_hdr_len+cmprs_len, &zip_ftr_len, crc, cmprs_len, src_len, file_name_in_zip, zip_hdr_len+cmprs_len) );
  774. RET_IF_ERROR( writeZipHeader(p_dst, &zip_hdr_len, crc, cmprs_len, src_len, file_name_in_zip) ); // rewrite ZIP header, since some fields are not writed previously.
  775. *p_dst_len = zip_hdr_len + cmprs_len + zip_ftr_len; // the total output length = ZIP header length + compressed data length (include ZIP LZMA property) + ZIP footer length
  776. return R_OK;
  777. }