blob: b03265a3804755164d2c74e5777548c4fde62d97 [file] [log] [blame]
b.liue9582032025-04-17 19:18:16 +08001--- a/jffsX-utils/Makemodule.am
2+++ b/jffsX-utils/Makemodule.am
3@@ -9,8 +9,9 @@ mkfs_jffs2_SOURCES = \
4 include/mtd/jffs2-user.h \
5 include/list.h \
6 include/rbtree.h
7+
8 mkfs_jffs2_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
9-mkfs_jffs2_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS)
10+mkfs_jffs2_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_CFLAGS) $(LZO_CFLAGS) -I./include/linux/lzma
11
12 jffs2reader_SOURCES = jffsX-utils/jffs2reader.c include/mtd/jffs2-user.h
13 jffs2reader_LDADD = libmtd.a $(ZLIB_LIBS) $(LZO_LIBS)
14@@ -32,6 +33,14 @@ if WITH_ZLIB
15 mkfs_jffs2_SOURCES += jffsX-utils/compr_zlib.c
16 endif
17
18+if WITH_LZMA
19+mkfs_jffs2_SOURCES += \
20+ jffsX-utils/compr_lzma.c \
21+ jffsX-utils/lzma/LzFind.c \
22+ jffsX-utils/lzma/LzmaEnc.c \
23+ jffsX-utils/lzma/LzmaDec.c
24+endif
25+
26 EXTRA_DIST += jffsX-utils/device_table.txt jffsX-utils/mkfs.jffs2.1
27
28 dist_man1_MANS += jffsX-utils/mkfs.jffs2.1
29--- a/jffsX-utils/compr.c
30+++ b/jffsX-utils/compr.c
31@@ -471,6 +471,9 @@ int jffs2_compressors_init(void)
32 #ifdef WITH_LZO
33 jffs2_lzo_init();
34 #endif
35+#ifdef WITH_LZMA
36+ jffs2_lzma_init();
37+#endif
38 return 0;
39 }
40
41@@ -485,5 +488,8 @@ int jffs2_compressors_exit(void)
42 #ifdef WITH_LZO
43 jffs2_lzo_exit();
44 #endif
45+#ifdef WITH_LZMA
46+ jffs2_lzma_exit();
47+#endif
48 return 0;
49 }
50--- a/jffsX-utils/compr.h
51+++ b/jffsX-utils/compr.h
52@@ -22,8 +22,9 @@
53 #define JFFS2_RUBINMIPS_PRIORITY 10
54 #define JFFS2_DYNRUBIN_PRIORITY 20
55 #define JFFS2_RTIME_PRIORITY 50
56-#define JFFS2_ZLIB_PRIORITY 60
57-#define JFFS2_LZO_PRIORITY 80
58+#define JFFS2_LZMA_PRIORITY 70
59+#define JFFS2_ZLIB_PRIORITY 80
60+#define JFFS2_LZO_PRIORITY 90
61
62 #define JFFS2_COMPR_MODE_NONE 0
63 #define JFFS2_COMPR_MODE_PRIORITY 1
64@@ -110,5 +111,10 @@ void jffs2_rtime_exit(void);
65 int jffs2_lzo_init(void);
66 void jffs2_lzo_exit(void);
67 #endif
68+#ifdef WITH_LZMA
69+int jffs2_lzma_init(void);
70+void jffs2_lzma_exit(void);
71+#endif
72+
73
74 #endif /* __JFFS2_COMPR_H__ */
75--- /dev/null
76+++ b/jffsX-utils/compr_lzma.c
77@@ -0,0 +1,128 @@
78+/*
79+ * JFFS2 -- Journalling Flash File System, Version 2.
80+ *
81+ * For licensing information, see the file 'LICENCE' in this directory.
82+ *
83+ * JFFS2 wrapper to the LZMA C SDK
84+ *
85+ */
86+
87+#include <linux/lzma.h>
88+#include "compr.h"
89+
90+#ifdef __KERNEL__
91+ static DEFINE_MUTEX(deflate_mutex);
92+#endif
93+
94+CLzmaEncHandle *p;
95+Byte propsEncoded[LZMA_PROPS_SIZE];
96+SizeT propsSize = sizeof(propsEncoded);
97+
98+STATIC void lzma_free_workspace(void)
99+{
100+ LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc);
101+}
102+
103+STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props)
104+{
105+ if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL)
106+ {
107+ PRINT_ERROR("Failed to allocate lzma deflate workspace\n");
108+ return -ENOMEM;
109+ }
110+
111+ if (LzmaEnc_SetProps(p, props) != SZ_OK)
112+ {
113+ lzma_free_workspace();
114+ return -1;
115+ }
116+
117+ if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK)
118+ {
119+ lzma_free_workspace();
120+ return -1;
121+ }
122+
123+ return 0;
124+}
125+
126+STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out,
127+ uint32_t *sourcelen, uint32_t *dstlen)
128+{
129+ SizeT compress_size = (SizeT)(*dstlen);
130+ int ret;
131+
132+ #ifdef __KERNEL__
133+ mutex_lock(&deflate_mutex);
134+ #endif
135+
136+ ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen,
137+ 0, NULL, &lzma_alloc, &lzma_alloc);
138+
139+ #ifdef __KERNEL__
140+ mutex_unlock(&deflate_mutex);
141+ #endif
142+
143+ if (ret != SZ_OK)
144+ return -1;
145+
146+ *dstlen = (uint32_t)compress_size;
147+
148+ return 0;
149+}
150+
151+STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out,
152+ uint32_t srclen, uint32_t destlen)
153+{
154+ int ret;
155+ SizeT dl = (SizeT)destlen;
156+ SizeT sl = (SizeT)srclen;
157+ ELzmaStatus status;
158+
159+ ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded,
160+ propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc);
161+
162+ if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen)
163+ return -1;
164+
165+ return 0;
166+}
167+
168+static struct jffs2_compressor jffs2_lzma_comp = {
169+ .priority = JFFS2_LZMA_PRIORITY,
170+ .name = "lzma",
171+ .compr = JFFS2_COMPR_LZMA,
172+ .compress = &jffs2_lzma_compress,
173+ .decompress = &jffs2_lzma_decompress,
174+ .disabled = 0,
175+};
176+
177+int INIT jffs2_lzma_init(void)
178+{
179+ int ret;
180+ CLzmaEncProps props;
181+ LzmaEncProps_Init(&props);
182+
183+ props.dictSize = LZMA_BEST_DICT(0x2000);
184+ props.level = LZMA_BEST_LEVEL;
185+ props.lc = LZMA_BEST_LC;
186+ props.lp = LZMA_BEST_LP;
187+ props.pb = LZMA_BEST_PB;
188+ props.fb = LZMA_BEST_FB;
189+
190+ ret = lzma_alloc_workspace(&props);
191+ if (ret < 0)
192+ return ret;
193+
194+ ret = jffs2_register_compressor(&jffs2_lzma_comp);
195+ if (ret)
196+ lzma_free_workspace();
197+
198+ return ret;
199+}
200+
201+void jffs2_lzma_exit(void)
202+{
203+ jffs2_unregister_compressor(&jffs2_lzma_comp);
204+ lzma_free_workspace();
205+}
206--- a/include/linux/jffs2.h
207+++ b/include/linux/jffs2.h
208@@ -47,6 +47,7 @@
209 #define JFFS2_COMPR_DYNRUBIN 0x05
210 #define JFFS2_COMPR_ZLIB 0x06
211 #define JFFS2_COMPR_LZO 0x07
212+#define JFFS2_COMPR_LZMA 0x08
213 /* Compatibility flags. */
214 #define JFFS2_COMPAT_MASK 0xc000 /* What do to if an unknown nodetype is found */
215 #define JFFS2_NODE_ACCURATE 0x2000
216--- /dev/null
217+++ b/include/linux/lzma.h
218@@ -0,0 +1,61 @@
219+#ifndef __LZMA_H__
220+#define __LZMA_H__
221+
222+#ifdef __KERNEL__
223+ #include <linux/kernel.h>
224+ #include <linux/sched.h>
225+ #include <linux/slab.h>
226+ #include <linux/vmalloc.h>
227+ #include <linux/init.h>
228+ #define LZMA_MALLOC vmalloc
229+ #define LZMA_FREE vfree
230+ #define PRINT_ERROR(msg) printk(KERN_WARNING #msg)
231+ #define INIT __init
232+ #define STATIC static
233+#else
234+ #include <stdint.h>
235+ #include <stdlib.h>
236+ #include <stdio.h>
237+ #include <unistd.h>
238+ #include <string.h>
239+ #include <errno.h>
240+ #include <linux/jffs2.h>
241+ #ifndef PAGE_SIZE
242+ extern int page_size;
243+ #define PAGE_SIZE page_size
244+ #endif
245+ #define LZMA_MALLOC malloc
246+ #define LZMA_FREE free
247+ #define PRINT_ERROR(msg) fprintf(stderr, msg)
248+ #define INIT
249+ #define STATIC static
250+#endif
251+
252+#include "lzma/LzmaDec.h"
253+#include "lzma/LzmaEnc.h"
254+
255+#define LZMA_BEST_LEVEL (9)
256+#define LZMA_BEST_LC (0)
257+#define LZMA_BEST_LP (0)
258+#define LZMA_BEST_PB (0)
259+#define LZMA_BEST_FB (273)
260+
261+#define LZMA_BEST_DICT(n) (((int)((n) / 2)) * 2)
262+
263+static void *p_lzma_malloc(void *p, size_t size)
264+{
265+ if (size == 0)
266+ return NULL;
267+
268+ return LZMA_MALLOC(size);
269+}
270+
271+static void p_lzma_free(void *p, void *address)
272+{
273+ if (address != NULL)
274+ LZMA_FREE(address);
275+}
276+
277+static ISzAlloc lzma_alloc = {p_lzma_malloc, p_lzma_free};
278+
279+#endif
280--- /dev/null
281+++ b/include/linux/lzma/LzFind.h
282@@ -0,0 +1,116 @@
283+/* LzFind.h -- Match finder for LZ algorithms
284+2008-04-04
285+Copyright (c) 1999-2008 Igor Pavlov
286+You can use any of the following license options:
287+ 1) GNU Lesser General Public License (GNU LGPL)
288+ 2) Common Public License (CPL)
289+ 3) Common Development and Distribution License (CDDL) Version 1.0
290+ 4) Igor Pavlov, as the author of this code, expressly permits you to
291+ statically or dynamically link your code (or bind by name) to this file,
292+ while you keep this file unmodified.
293+*/
294+
295+#ifndef __LZFIND_H
296+#define __LZFIND_H
297+
298+#include "Types.h"
299+
300+typedef UInt32 CLzRef;
301+
302+typedef struct _CMatchFinder
303+{
304+ Byte *buffer;
305+ UInt32 pos;
306+ UInt32 posLimit;
307+ UInt32 streamPos;
308+ UInt32 lenLimit;
309+
310+ UInt32 cyclicBufferPos;
311+ UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */
312+
313+ UInt32 matchMaxLen;
314+ CLzRef *hash;
315+ CLzRef *son;
316+ UInt32 hashMask;
317+ UInt32 cutValue;
318+
319+ Byte *bufferBase;
320+ ISeqInStream *stream;
321+ int streamEndWasReached;
322+
323+ UInt32 blockSize;
324+ UInt32 keepSizeBefore;
325+ UInt32 keepSizeAfter;
326+
327+ UInt32 numHashBytes;
328+ int directInput;
329+ int btMode;
330+ /* int skipModeBits; */
331+ int bigHash;
332+ UInt32 historySize;
333+ UInt32 fixedHashSize;
334+ UInt32 hashSizeSum;
335+ UInt32 numSons;
336+ SRes result;
337+ UInt32 crc[256];
338+} CMatchFinder;
339+
340+#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer)
341+#define Inline_MatchFinder_GetIndexByte(p, index) ((p)->buffer[(Int32)(index)])
342+
343+#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos)
344+
345+int MatchFinder_NeedMove(CMatchFinder *p);
346+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p);
347+void MatchFinder_MoveBlock(CMatchFinder *p);
348+void MatchFinder_ReadIfRequired(CMatchFinder *p);
349+
350+void MatchFinder_Construct(CMatchFinder *p);
351+
352+/* Conditions:
353+ historySize <= 3 GB
354+ keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB
355+*/
356+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
357+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
358+ ISzAlloc *alloc);
359+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc);
360+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems);
361+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue);
362+
363+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son,
364+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue,
365+ UInt32 *distances, UInt32 maxLen);
366+
367+/*
368+Conditions:
369+ Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func.
370+ Mf_GetPointerToCurrentPos_Func's result must be used only before any other function
371+*/
372+
373+typedef void (*Mf_Init_Func)(void *object);
374+typedef Byte (*Mf_GetIndexByte_Func)(void *object, Int32 index);
375+typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object);
376+typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object);
377+typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances);
378+typedef void (*Mf_Skip_Func)(void *object, UInt32);
379+
380+typedef struct _IMatchFinder
381+{
382+ Mf_Init_Func Init;
383+ Mf_GetIndexByte_Func GetIndexByte;
384+ Mf_GetNumAvailableBytes_Func GetNumAvailableBytes;
385+ Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos;
386+ Mf_GetMatches_Func GetMatches;
387+ Mf_Skip_Func Skip;
388+} IMatchFinder;
389+
390+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable);
391+
392+void MatchFinder_Init(CMatchFinder *p);
393+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
394+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances);
395+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
396+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num);
397+
398+#endif
399--- /dev/null
400+++ b/include/linux/lzma/LzHash.h
401@@ -0,0 +1,56 @@
402+/* LzHash.h -- HASH functions for LZ algorithms
403+2008-03-26
404+Copyright (c) 1999-2008 Igor Pavlov
405+Read LzFind.h for license options */
406+
407+#ifndef __LZHASH_H
408+#define __LZHASH_H
409+
410+#define kHash2Size (1 << 10)
411+#define kHash3Size (1 << 16)
412+#define kHash4Size (1 << 20)
413+
414+#define kFix3HashSize (kHash2Size)
415+#define kFix4HashSize (kHash2Size + kHash3Size)
416+#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size)
417+
418+#define HASH2_CALC hashValue = cur[0] | ((UInt32)cur[1] << 8);
419+
420+#define HASH3_CALC { \
421+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
422+ hash2Value = temp & (kHash2Size - 1); \
423+ hashValue = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; }
424+
425+#define HASH4_CALC { \
426+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
427+ hash2Value = temp & (kHash2Size - 1); \
428+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
429+ hashValue = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & p->hashMask; }
430+
431+#define HASH5_CALC { \
432+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
433+ hash2Value = temp & (kHash2Size - 1); \
434+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
435+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)); \
436+ hashValue = (hash4Value ^ (p->crc[cur[4]] << 3)) & p->hashMask; \
437+ hash4Value &= (kHash4Size - 1); }
438+
439+/* #define HASH_ZIP_CALC hashValue = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */
440+#define HASH_ZIP_CALC hashValue = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF;
441+
442+
443+#define MT_HASH2_CALC \
444+ hash2Value = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1);
445+
446+#define MT_HASH3_CALC { \
447+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
448+ hash2Value = temp & (kHash2Size - 1); \
449+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); }
450+
451+#define MT_HASH4_CALC { \
452+ UInt32 temp = p->crc[cur[0]] ^ cur[1]; \
453+ hash2Value = temp & (kHash2Size - 1); \
454+ hash3Value = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); \
455+ hash4Value = (temp ^ ((UInt32)cur[2] << 8) ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); }
456+
457+#endif
458--- /dev/null
459+++ b/include/linux/lzma/LzmaDec.h
460@@ -0,0 +1,232 @@
461+/* LzmaDec.h -- LZMA Decoder
462+2008-04-29
463+Copyright (c) 1999-2008 Igor Pavlov
464+You can use any of the following license options:
465+ 1) GNU Lesser General Public License (GNU LGPL)
466+ 2) Common Public License (CPL)
467+ 3) Common Development and Distribution License (CDDL) Version 1.0
468+ 4) Igor Pavlov, as the author of this code, expressly permits you to
469+ statically or dynamically link your code (or bind by name) to this file,
470+ while you keep this file unmodified.
471+*/
472+
473+#ifndef __LZMADEC_H
474+#define __LZMADEC_H
475+
476+#include "Types.h"
477+
478+/* #define _LZMA_PROB32 */
479+/* _LZMA_PROB32 can increase the speed on some CPUs,
480+ but memory usage for CLzmaDec::probs will be doubled in that case */
481+
482+#ifdef _LZMA_PROB32
483+#define CLzmaProb UInt32
484+#else
485+#define CLzmaProb UInt16
486+#endif
487+
488+
489+/* ---------- LZMA Properties ---------- */
490+
491+#define LZMA_PROPS_SIZE 5
492+
493+typedef struct _CLzmaProps
494+{
495+ unsigned lc, lp, pb;
496+ UInt32 dicSize;
497+} CLzmaProps;
498+
499+/* LzmaProps_Decode - decodes properties
500+Returns:
501+ SZ_OK
502+ SZ_ERROR_UNSUPPORTED - Unsupported properties
503+*/
504+
505+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
506+
507+
508+/* ---------- LZMA Decoder state ---------- */
509+
510+/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
511+ Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
512+
513+#define LZMA_REQUIRED_INPUT_MAX 20
514+
515+typedef struct
516+{
517+ CLzmaProps prop;
518+ CLzmaProb *probs;
519+ Byte *dic;
520+ const Byte *buf;
521+ UInt32 range, code;
522+ SizeT dicPos;
523+ SizeT dicBufSize;
524+ UInt32 processedPos;
525+ UInt32 checkDicSize;
526+ unsigned state;
527+ UInt32 reps[4];
528+ unsigned remainLen;
529+ int needFlush;
530+ int needInitState;
531+ UInt32 numProbs;
532+ unsigned tempBufSize;
533+ Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
534+} CLzmaDec;
535+
536+#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
537+
538+void LzmaDec_Init(CLzmaDec *p);
539+
540+/* There are two types of LZMA streams:
541+ 0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
542+ 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
543+
544+typedef enum
545+{
546+ LZMA_FINISH_ANY, /* finish at any point */
547+ LZMA_FINISH_END /* block must be finished at the end */
548+} ELzmaFinishMode;
549+
550+/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
551+
552+ You must use LZMA_FINISH_END, when you know that current output buffer
553+ covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
554+
555+ If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
556+ and output value of destLen will be less than output buffer size limit.
557+ You can check status result also.
558+
559+ You can use multiple checks to test data integrity after full decompression:
560+ 1) Check Result and "status" variable.
561+ 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
562+ 3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
563+ You must use correct finish mode in that case. */
564+
565+typedef enum
566+{
567+ LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
568+ LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
569+ LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
570+ LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
571+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
572+} ELzmaStatus;
573+
574+/* ELzmaStatus is used only as output value for function call */
575+
576+
577+/* ---------- Interfaces ---------- */
578+
579+/* There are 3 levels of interfaces:
580+ 1) Dictionary Interface
581+ 2) Buffer Interface
582+ 3) One Call Interface
583+ You can select any of these interfaces, but don't mix functions from different
584+ groups for same object. */
585+
586+
587+/* There are two variants to allocate state for Dictionary Interface:
588+ 1) LzmaDec_Allocate / LzmaDec_Free
589+ 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
590+ You can use variant 2, if you set dictionary buffer manually.
591+ For Buffer Interface you must always use variant 1.
592+
593+LzmaDec_Allocate* can return:
594+ SZ_OK
595+ SZ_ERROR_MEM - Memory allocation error
596+ SZ_ERROR_UNSUPPORTED - Unsupported properties
597+*/
598+
599+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
600+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
601+
602+SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
603+void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
604+
605+/* ---------- Dictionary Interface ---------- */
606+
607+/* You can use it, if you want to eliminate the overhead for data copying from
608+ dictionary to some other external buffer.
609+ You must work with CLzmaDec variables directly in this interface.
610+
611+ STEPS:
612+ LzmaDec_Constr()
613+ LzmaDec_Allocate()
614+ for (each new stream)
615+ {
616+ LzmaDec_Init()
617+ while (it needs more decompression)
618+ {
619+ LzmaDec_DecodeToDic()
620+ use data from CLzmaDec::dic and update CLzmaDec::dicPos
621+ }
622+ }
623+ LzmaDec_Free()
624+*/
625+
626+/* LzmaDec_DecodeToDic
627+
628+ The decoding to internal dictionary buffer (CLzmaDec::dic).
629+ You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
630+
631+finishMode:
632+ It has meaning only if the decoding reaches output limit (dicLimit).
633+ LZMA_FINISH_ANY - Decode just dicLimit bytes.
634+ LZMA_FINISH_END - Stream must be finished after dicLimit.
635+
636+Returns:
637+ SZ_OK
638+ status:
639+ LZMA_STATUS_FINISHED_WITH_MARK
640+ LZMA_STATUS_NOT_FINISHED
641+ LZMA_STATUS_NEEDS_MORE_INPUT
642+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
643+ SZ_ERROR_DATA - Data error
644+*/
645+
646+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
647+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
648+
649+
650+/* ---------- Buffer Interface ---------- */
651+
652+/* It's zlib-like interface.
653+ See LzmaDec_DecodeToDic description for information about STEPS and return results,
654+ but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
655+ to work with CLzmaDec variables manually.
656+
657+finishMode:
658+ It has meaning only if the decoding reaches output limit (*destLen).
659+ LZMA_FINISH_ANY - Decode just destLen bytes.
660+ LZMA_FINISH_END - Stream must be finished after (*destLen).
661+*/
662+
663+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
664+ const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
665+
666+
667+/* ---------- One Call Interface ---------- */
668+
669+/* LzmaDecode
670+
671+finishMode:
672+ It has meaning only if the decoding reaches output limit (*destLen).
673+ LZMA_FINISH_ANY - Decode just destLen bytes.
674+ LZMA_FINISH_END - Stream must be finished after (*destLen).
675+
676+Returns:
677+ SZ_OK
678+ status:
679+ LZMA_STATUS_FINISHED_WITH_MARK
680+ LZMA_STATUS_NOT_FINISHED
681+ LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
682+ SZ_ERROR_DATA - Data error
683+ SZ_ERROR_MEM - Memory allocation error
684+ SZ_ERROR_UNSUPPORTED - Unsupported properties
685+ SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
686+*/
687+
688+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
689+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
690+ ELzmaStatus *status, ISzAlloc *alloc);
691+
692+#endif
693--- /dev/null
694+++ b/include/linux/lzma/LzmaEnc.h
695@@ -0,0 +1,74 @@
696+/* LzmaEnc.h -- LZMA Encoder
697+2008-04-27
698+Copyright (c) 1999-2008 Igor Pavlov
699+Read LzFind.h for license options */
700+
701+#ifndef __LZMAENC_H
702+#define __LZMAENC_H
703+
704+#include "Types.h"
705+
706+#define LZMA_PROPS_SIZE 5
707+
708+typedef struct _CLzmaEncProps
709+{
710+ int level; /* 0 <= level <= 9 */
711+ UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version
712+ (1 << 12) <= dictSize <= (1 << 30) for 64-bit version
713+ default = (1 << 24) */
714+ int lc; /* 0 <= lc <= 8, default = 3 */
715+ int lp; /* 0 <= lp <= 4, default = 0 */
716+ int pb; /* 0 <= pb <= 4, default = 2 */
717+ int algo; /* 0 - fast, 1 - normal, default = 1 */
718+ int fb; /* 5 <= fb <= 273, default = 32 */
719+ int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */
720+ int numHashBytes; /* 2, 3 or 4, default = 4 */
721+ UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */
722+ unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */
723+ int numThreads; /* 1 or 2, default = 2 */
724+} CLzmaEncProps;
725+
726+void LzmaEncProps_Init(CLzmaEncProps *p);
727+void LzmaEncProps_Normalize(CLzmaEncProps *p);
728+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2);
729+
730+
731+/* ---------- CLzmaEncHandle Interface ---------- */
732+
733+/* LzmaEnc_* functions can return the following exit codes:
734+Returns:
735+ SZ_OK - OK
736+ SZ_ERROR_MEM - Memory allocation error
737+ SZ_ERROR_PARAM - Incorrect paramater in props
738+ SZ_ERROR_WRITE - Write callback error.
739+ SZ_ERROR_PROGRESS - some break from progress callback
740+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
741+*/
742+
743+typedef void * CLzmaEncHandle;
744+
745+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc);
746+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig);
747+SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props);
748+SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size);
749+SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream,
750+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
751+SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
752+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
753+
754+/* ---------- One Call Interface ---------- */
755+
756+/* LzmaEncode
757+Return code:
758+ SZ_OK - OK
759+ SZ_ERROR_MEM - Memory allocation error
760+ SZ_ERROR_PARAM - Incorrect paramater
761+ SZ_ERROR_OUTPUT_EOF - output buffer overflow
762+ SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
763+*/
764+
765+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
766+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
767+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
768+
769+#endif
770--- /dev/null
771+++ b/include/linux/lzma/Types.h
772@@ -0,0 +1,130 @@
773+/* Types.h -- Basic types
774+2008-04-11
775+Igor Pavlov
776+Public domain */
777+
778+#ifndef __7Z_TYPES_H
779+#define __7Z_TYPES_H
780+
781+#define SZ_OK 0
782+
783+#define SZ_ERROR_DATA 1
784+#define SZ_ERROR_MEM 2
785+#define SZ_ERROR_CRC 3
786+#define SZ_ERROR_UNSUPPORTED 4
787+#define SZ_ERROR_PARAM 5
788+#define SZ_ERROR_INPUT_EOF 6
789+#define SZ_ERROR_OUTPUT_EOF 7
790+#define SZ_ERROR_READ 8
791+#define SZ_ERROR_WRITE 9
792+#define SZ_ERROR_PROGRESS 10
793+#define SZ_ERROR_FAIL 11
794+#define SZ_ERROR_THREAD 12
795+
796+#define SZ_ERROR_ARCHIVE 16
797+#define SZ_ERROR_NO_ARCHIVE 17
798+
799+typedef int SRes;
800+
801+#ifndef RINOK
802+#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
803+#endif
804+
805+typedef unsigned char Byte;
806+typedef short Int16;
807+typedef unsigned short UInt16;
808+
809+#ifdef _LZMA_UINT32_IS_ULONG
810+typedef long Int32;
811+typedef unsigned long UInt32;
812+#else
813+typedef int Int32;
814+typedef unsigned int UInt32;
815+#endif
816+
817+/* #define _SZ_NO_INT_64 */
818+/* define it if your compiler doesn't support 64-bit integers */
819+
820+#ifdef _SZ_NO_INT_64
821+
822+typedef long Int64;
823+typedef unsigned long UInt64;
824+
825+#else
826+
827+#if defined(_MSC_VER) || defined(__BORLANDC__)
828+typedef __int64 Int64;
829+typedef unsigned __int64 UInt64;
830+#else
831+typedef long long int Int64;
832+typedef unsigned long long int UInt64;
833+#endif
834+
835+#endif
836+
837+#ifdef _LZMA_NO_SYSTEM_SIZE_T
838+typedef UInt32 SizeT;
839+#else
840+#include <stddef.h>
841+typedef size_t SizeT;
842+#endif
843+
844+typedef int Bool;
845+#define True 1
846+#define False 0
847+
848+
849+#ifdef _MSC_VER
850+
851+#if _MSC_VER >= 1300
852+#define MY_NO_INLINE __declspec(noinline)
853+#else
854+#define MY_NO_INLINE
855+#endif
856+
857+#define MY_CDECL __cdecl
858+#define MY_STD_CALL __stdcall
859+#define MY_FAST_CALL MY_NO_INLINE __fastcall
860+
861+#else
862+
863+#define MY_CDECL
864+#define MY_STD_CALL
865+#define MY_FAST_CALL
866+
867+#endif
868+
869+
870+/* The following interfaces use first parameter as pointer to structure */
871+
872+typedef struct
873+{
874+ SRes (*Read)(void *p, void *buf, size_t *size);
875+ /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
876+ (output(*size) < input(*size)) is allowed */
877+} ISeqInStream;
878+
879+typedef struct
880+{
881+ size_t (*Write)(void *p, const void *buf, size_t size);
882+ /* Returns: result - the number of actually written bytes.
883+ (result < size) means error */
884+} ISeqOutStream;
885+
886+typedef struct
887+{
888+ SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
889+ /* Returns: result. (result != SZ_OK) means break.
890+ Value (UInt64)(Int64)-1 for size means unknown value. */
891+} ICompressProgress;
892+
893+typedef struct
894+{
895+ void *(*Alloc)(void *p, size_t size);
896+ void (*Free)(void *p, void *address); /* address can be 0 */
897+} ISzAlloc;
898+
899+#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
900+#define IAlloc_Free(p, a) (p)->Free((p), a)
901+
902+#endif
903--- /dev/null
904+++ b/jffsX-utils/lzma/LzFind.c
905@@ -0,0 +1,753 @@
906+/* LzFind.c -- Match finder for LZ algorithms
907+2008-04-04
908+Copyright (c) 1999-2008 Igor Pavlov
909+Read LzFind.h for license options */
910+
911+#include <string.h>
912+
913+#include "LzFind.h"
914+#include "LzHash.h"
915+
916+#define kEmptyHashValue 0
917+#define kMaxValForNormalize ((UInt32)0xFFFFFFFF)
918+#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */
919+#define kNormalizeMask (~(kNormalizeStepMin - 1))
920+#define kMaxHistorySize ((UInt32)3 << 30)
921+
922+#define kStartMaxLen 3
923+
924+static void LzInWindow_Free(CMatchFinder *p, ISzAlloc *alloc)
925+{
926+ if (!p->directInput)
927+ {
928+ alloc->Free(alloc, p->bufferBase);
929+ p->bufferBase = 0;
930+ }
931+}
932+
933+/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */
934+
935+static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAlloc *alloc)
936+{
937+ UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv;
938+ if (p->directInput)
939+ {
940+ p->blockSize = blockSize;
941+ return 1;
942+ }
943+ if (p->bufferBase == 0 || p->blockSize != blockSize)
944+ {
945+ LzInWindow_Free(p, alloc);
946+ p->blockSize = blockSize;
947+ p->bufferBase = (Byte *)alloc->Alloc(alloc, (size_t)blockSize);
948+ }
949+ return (p->bufferBase != 0);
950+}
951+
952+Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; }
953+static Byte MatchFinder_GetIndexByte(CMatchFinder *p, Int32 index) { return p->buffer[index]; }
954+
955+static UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; }
956+
957+void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue)
958+{
959+ p->posLimit -= subValue;
960+ p->pos -= subValue;
961+ p->streamPos -= subValue;
962+}
963+
964+static void MatchFinder_ReadBlock(CMatchFinder *p)
965+{
966+ if (p->streamEndWasReached || p->result != SZ_OK)
967+ return;
968+ for (;;)
969+ {
970+ Byte *dest = p->buffer + (p->streamPos - p->pos);
971+ size_t size = (p->bufferBase + p->blockSize - dest);
972+ if (size == 0)
973+ return;
974+ p->result = p->stream->Read(p->stream, dest, &size);
975+ if (p->result != SZ_OK)
976+ return;
977+ if (size == 0)
978+ {
979+ p->streamEndWasReached = 1;
980+ return;
981+ }
982+ p->streamPos += (UInt32)size;
983+ if (p->streamPos - p->pos > p->keepSizeAfter)
984+ return;
985+ }
986+}
987+
988+void MatchFinder_MoveBlock(CMatchFinder *p)
989+{
990+ memmove(p->bufferBase,
991+ p->buffer - p->keepSizeBefore,
992+ (size_t)(p->streamPos - p->pos + p->keepSizeBefore));
993+ p->buffer = p->bufferBase + p->keepSizeBefore;
994+}
995+
996+int MatchFinder_NeedMove(CMatchFinder *p)
997+{
998+ /* if (p->streamEndWasReached) return 0; */
999+ return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter);
1000+}
1001+
1002+void MatchFinder_ReadIfRequired(CMatchFinder *p)
1003+{
1004+ if (p->streamEndWasReached)
1005+ return;
1006+ if (p->keepSizeAfter >= p->streamPos - p->pos)
1007+ MatchFinder_ReadBlock(p);
1008+}
1009+
1010+static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p)
1011+{
1012+ if (MatchFinder_NeedMove(p))
1013+ MatchFinder_MoveBlock(p);
1014+ MatchFinder_ReadBlock(p);
1015+}
1016+
1017+static void MatchFinder_SetDefaultSettings(CMatchFinder *p)
1018+{
1019+ p->cutValue = 32;
1020+ p->btMode = 1;
1021+ p->numHashBytes = 4;
1022+ /* p->skipModeBits = 0; */
1023+ p->directInput = 0;
1024+ p->bigHash = 0;
1025+}
1026+
1027+#define kCrcPoly 0xEDB88320
1028+
1029+void MatchFinder_Construct(CMatchFinder *p)
1030+{
1031+ UInt32 i;
1032+ p->bufferBase = 0;
1033+ p->directInput = 0;
1034+ p->hash = 0;
1035+ MatchFinder_SetDefaultSettings(p);
1036+
1037+ for (i = 0; i < 256; i++)
1038+ {
1039+ UInt32 r = i;
1040+ int j;
1041+ for (j = 0; j < 8; j++)
1042+ r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
1043+ p->crc[i] = r;
1044+ }
1045+}
1046+
1047+static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAlloc *alloc)
1048+{
1049+ alloc->Free(alloc, p->hash);
1050+ p->hash = 0;
1051+}
1052+
1053+void MatchFinder_Free(CMatchFinder *p, ISzAlloc *alloc)
1054+{
1055+ MatchFinder_FreeThisClassMemory(p, alloc);
1056+ LzInWindow_Free(p, alloc);
1057+}
1058+
1059+static CLzRef* AllocRefs(UInt32 num, ISzAlloc *alloc)
1060+{
1061+ size_t sizeInBytes = (size_t)num * sizeof(CLzRef);
1062+ if (sizeInBytes / sizeof(CLzRef) != num)
1063+ return 0;
1064+ return (CLzRef *)alloc->Alloc(alloc, sizeInBytes);
1065+}
1066+
1067+int MatchFinder_Create(CMatchFinder *p, UInt32 historySize,
1068+ UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter,
1069+ ISzAlloc *alloc)
1070+{
1071+ UInt32 sizeReserv;
1072+ if (historySize > kMaxHistorySize)
1073+ {
1074+ MatchFinder_Free(p, alloc);
1075+ return 0;
1076+ }
1077+ sizeReserv = historySize >> 1;
1078+ if (historySize > ((UInt32)2 << 30))
1079+ sizeReserv = historySize >> 2;
1080+ sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19);
1081+
1082+ p->keepSizeBefore = historySize + keepAddBufferBefore + 1;
1083+ p->keepSizeAfter = matchMaxLen + keepAddBufferAfter;
1084+ /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */
1085+ if (LzInWindow_Create(p, sizeReserv, alloc))
1086+ {
1087+ UInt32 newCyclicBufferSize = (historySize /* >> p->skipModeBits */) + 1;
1088+ UInt32 hs;
1089+ p->matchMaxLen = matchMaxLen;
1090+ {
1091+ p->fixedHashSize = 0;
1092+ if (p->numHashBytes == 2)
1093+ hs = (1 << 16) - 1;
1094+ else
1095+ {
1096+ hs = historySize - 1;
1097+ hs |= (hs >> 1);
1098+ hs |= (hs >> 2);
1099+ hs |= (hs >> 4);
1100+ hs |= (hs >> 8);
1101+ hs >>= 1;
1102+ /* hs >>= p->skipModeBits; */
1103+ hs |= 0xFFFF; /* don't change it! It's required for Deflate */
1104+ if (hs > (1 << 24))
1105+ {
1106+ if (p->numHashBytes == 3)
1107+ hs = (1 << 24) - 1;
1108+ else
1109+ hs >>= 1;
1110+ }
1111+ }
1112+ p->hashMask = hs;
1113+ hs++;
1114+ if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size;
1115+ if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size;
1116+ if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size;
1117+ hs += p->fixedHashSize;
1118+ }
1119+
1120+ {
1121+ UInt32 prevSize = p->hashSizeSum + p->numSons;
1122+ UInt32 newSize;
1123+ p->historySize = historySize;
1124+ p->hashSizeSum = hs;
1125+ p->cyclicBufferSize = newCyclicBufferSize;
1126+ p->numSons = (p->btMode ? newCyclicBufferSize * 2 : newCyclicBufferSize);
1127+ newSize = p->hashSizeSum + p->numSons;
1128+ if (p->hash != 0 && prevSize == newSize)
1129+ return 1;
1130+ MatchFinder_FreeThisClassMemory(p, alloc);
1131+ p->hash = AllocRefs(newSize, alloc);
1132+ if (p->hash != 0)
1133+ {
1134+ p->son = p->hash + p->hashSizeSum;
1135+ return 1;
1136+ }
1137+ }
1138+ }
1139+ MatchFinder_Free(p, alloc);
1140+ return 0;
1141+}
1142+
1143+static void MatchFinder_SetLimits(CMatchFinder *p)
1144+{
1145+ UInt32 limit = kMaxValForNormalize - p->pos;
1146+ UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos;
1147+ if (limit2 < limit)
1148+ limit = limit2;
1149+ limit2 = p->streamPos - p->pos;
1150+ if (limit2 <= p->keepSizeAfter)
1151+ {
1152+ if (limit2 > 0)
1153+ limit2 = 1;
1154+ }
1155+ else
1156+ limit2 -= p->keepSizeAfter;
1157+ if (limit2 < limit)
1158+ limit = limit2;
1159+ {
1160+ UInt32 lenLimit = p->streamPos - p->pos;
1161+ if (lenLimit > p->matchMaxLen)
1162+ lenLimit = p->matchMaxLen;
1163+ p->lenLimit = lenLimit;
1164+ }
1165+ p->posLimit = p->pos + limit;
1166+}
1167+
1168+void MatchFinder_Init(CMatchFinder *p)
1169+{
1170+ UInt32 i;
1171+ for(i = 0; i < p->hashSizeSum; i++)
1172+ p->hash[i] = kEmptyHashValue;
1173+ p->cyclicBufferPos = 0;
1174+ p->buffer = p->bufferBase;
1175+ p->pos = p->streamPos = p->cyclicBufferSize;
1176+ p->result = SZ_OK;
1177+ p->streamEndWasReached = 0;
1178+ MatchFinder_ReadBlock(p);
1179+ MatchFinder_SetLimits(p);
1180+}
1181+
1182+static UInt32 MatchFinder_GetSubValue(CMatchFinder *p)
1183+{
1184+ return (p->pos - p->historySize - 1) & kNormalizeMask;
1185+}
1186+
1187+void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, UInt32 numItems)
1188+{
1189+ UInt32 i;
1190+ for (i = 0; i < numItems; i++)
1191+ {
1192+ UInt32 value = items[i];
1193+ if (value <= subValue)
1194+ value = kEmptyHashValue;
1195+ else
1196+ value -= subValue;
1197+ items[i] = value;
1198+ }
1199+}
1200+
1201+static void MatchFinder_Normalize(CMatchFinder *p)
1202+{
1203+ UInt32 subValue = MatchFinder_GetSubValue(p);
1204+ MatchFinder_Normalize3(subValue, p->hash, p->hashSizeSum + p->numSons);
1205+ MatchFinder_ReduceOffsets(p, subValue);
1206+}
1207+
1208+static void MatchFinder_CheckLimits(CMatchFinder *p)
1209+{
1210+ if (p->pos == kMaxValForNormalize)
1211+ MatchFinder_Normalize(p);
1212+ if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos)
1213+ MatchFinder_CheckAndMoveAndRead(p);
1214+ if (p->cyclicBufferPos == p->cyclicBufferSize)
1215+ p->cyclicBufferPos = 0;
1216+ MatchFinder_SetLimits(p);
1217+}
1218+
1219+static UInt32 * Hc_GetMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
1220+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
1221+ UInt32 *distances, UInt32 maxLen)
1222+{
1223+ son[_cyclicBufferPos] = curMatch;
1224+ for (;;)
1225+ {
1226+ UInt32 delta = pos - curMatch;
1227+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
1228+ return distances;
1229+ {
1230+ const Byte *pb = cur - delta;
1231+ curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)];
1232+ if (pb[maxLen] == cur[maxLen] && *pb == *cur)
1233+ {
1234+ UInt32 len = 0;
1235+ while(++len != lenLimit)
1236+ if (pb[len] != cur[len])
1237+ break;
1238+ if (maxLen < len)
1239+ {
1240+ *distances++ = maxLen = len;
1241+ *distances++ = delta - 1;
1242+ if (len == lenLimit)
1243+ return distances;
1244+ }
1245+ }
1246+ }
1247+ }
1248+}
1249+
1250+UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
1251+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue,
1252+ UInt32 *distances, UInt32 maxLen)
1253+{
1254+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
1255+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
1256+ UInt32 len0 = 0, len1 = 0;
1257+ for (;;)
1258+ {
1259+ UInt32 delta = pos - curMatch;
1260+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
1261+ {
1262+ *ptr0 = *ptr1 = kEmptyHashValue;
1263+ return distances;
1264+ }
1265+ {
1266+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
1267+ const Byte *pb = cur - delta;
1268+ UInt32 len = (len0 < len1 ? len0 : len1);
1269+ if (pb[len] == cur[len])
1270+ {
1271+ if (++len != lenLimit && pb[len] == cur[len])
1272+ while(++len != lenLimit)
1273+ if (pb[len] != cur[len])
1274+ break;
1275+ if (maxLen < len)
1276+ {
1277+ *distances++ = maxLen = len;
1278+ *distances++ = delta - 1;
1279+ if (len == lenLimit)
1280+ {
1281+ *ptr1 = pair[0];
1282+ *ptr0 = pair[1];
1283+ return distances;
1284+ }
1285+ }
1286+ }
1287+ if (pb[len] < cur[len])
1288+ {
1289+ *ptr1 = curMatch;
1290+ ptr1 = pair + 1;
1291+ curMatch = *ptr1;
1292+ len1 = len;
1293+ }
1294+ else
1295+ {
1296+ *ptr0 = curMatch;
1297+ ptr0 = pair;
1298+ curMatch = *ptr0;
1299+ len0 = len;
1300+ }
1301+ }
1302+ }
1303+}
1304+
1305+static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son,
1306+ UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue)
1307+{
1308+ CLzRef *ptr0 = son + (_cyclicBufferPos << 1) + 1;
1309+ CLzRef *ptr1 = son + (_cyclicBufferPos << 1);
1310+ UInt32 len0 = 0, len1 = 0;
1311+ for (;;)
1312+ {
1313+ UInt32 delta = pos - curMatch;
1314+ if (cutValue-- == 0 || delta >= _cyclicBufferSize)
1315+ {
1316+ *ptr0 = *ptr1 = kEmptyHashValue;
1317+ return;
1318+ }
1319+ {
1320+ CLzRef *pair = son + ((_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1);
1321+ const Byte *pb = cur - delta;
1322+ UInt32 len = (len0 < len1 ? len0 : len1);
1323+ if (pb[len] == cur[len])
1324+ {
1325+ while(++len != lenLimit)
1326+ if (pb[len] != cur[len])
1327+ break;
1328+ {
1329+ if (len == lenLimit)
1330+ {
1331+ *ptr1 = pair[0];
1332+ *ptr0 = pair[1];
1333+ return;
1334+ }
1335+ }
1336+ }
1337+ if (pb[len] < cur[len])
1338+ {
1339+ *ptr1 = curMatch;
1340+ ptr1 = pair + 1;
1341+ curMatch = *ptr1;
1342+ len1 = len;
1343+ }
1344+ else
1345+ {
1346+ *ptr0 = curMatch;
1347+ ptr0 = pair;
1348+ curMatch = *ptr0;
1349+ len0 = len;
1350+ }
1351+ }
1352+ }
1353+}
1354+
1355+#define MOVE_POS \
1356+ ++p->cyclicBufferPos; \
1357+ p->buffer++; \
1358+ if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p);
1359+
1360+#define MOVE_POS_RET MOVE_POS return offset;
1361+
1362+static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; }
1363+
1364+#define GET_MATCHES_HEADER2(minLen, ret_op) \
1365+ UInt32 lenLimit; UInt32 hashValue; const Byte *cur; UInt32 curMatch; \
1366+ lenLimit = p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \
1367+ cur = p->buffer;
1368+
1369+#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0)
1370+#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue)
1371+
1372+#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue
1373+
1374+#define GET_MATCHES_FOOTER(offset, maxLen) \
1375+ offset = (UInt32)(GetMatchesSpec1(lenLimit, curMatch, MF_PARAMS(p), \
1376+ distances + offset, maxLen) - distances); MOVE_POS_RET;
1377+
1378+#define SKIP_FOOTER \
1379+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS;
1380+
1381+static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1382+{
1383+ UInt32 offset;
1384+ GET_MATCHES_HEADER(2)
1385+ HASH2_CALC;
1386+ curMatch = p->hash[hashValue];
1387+ p->hash[hashValue] = p->pos;
1388+ offset = 0;
1389+ GET_MATCHES_FOOTER(offset, 1)
1390+}
1391+
1392+UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1393+{
1394+ UInt32 offset;
1395+ GET_MATCHES_HEADER(3)
1396+ HASH_ZIP_CALC;
1397+ curMatch = p->hash[hashValue];
1398+ p->hash[hashValue] = p->pos;
1399+ offset = 0;
1400+ GET_MATCHES_FOOTER(offset, 2)
1401+}
1402+
1403+static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1404+{
1405+ UInt32 hash2Value, delta2, maxLen, offset;
1406+ GET_MATCHES_HEADER(3)
1407+
1408+ HASH3_CALC;
1409+
1410+ delta2 = p->pos - p->hash[hash2Value];
1411+ curMatch = p->hash[kFix3HashSize + hashValue];
1412+
1413+ p->hash[hash2Value] =
1414+ p->hash[kFix3HashSize + hashValue] = p->pos;
1415+
1416+
1417+ maxLen = 2;
1418+ offset = 0;
1419+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
1420+ {
1421+ for (; maxLen != lenLimit; maxLen++)
1422+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
1423+ break;
1424+ distances[0] = maxLen;
1425+ distances[1] = delta2 - 1;
1426+ offset = 2;
1427+ if (maxLen == lenLimit)
1428+ {
1429+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
1430+ MOVE_POS_RET;
1431+ }
1432+ }
1433+ GET_MATCHES_FOOTER(offset, maxLen)
1434+}
1435+
1436+static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1437+{
1438+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
1439+ GET_MATCHES_HEADER(4)
1440+
1441+ HASH4_CALC;
1442+
1443+ delta2 = p->pos - p->hash[ hash2Value];
1444+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
1445+ curMatch = p->hash[kFix4HashSize + hashValue];
1446+
1447+ p->hash[ hash2Value] =
1448+ p->hash[kFix3HashSize + hash3Value] =
1449+ p->hash[kFix4HashSize + hashValue] = p->pos;
1450+
1451+ maxLen = 1;
1452+ offset = 0;
1453+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
1454+ {
1455+ distances[0] = maxLen = 2;
1456+ distances[1] = delta2 - 1;
1457+ offset = 2;
1458+ }
1459+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
1460+ {
1461+ maxLen = 3;
1462+ distances[offset + 1] = delta3 - 1;
1463+ offset += 2;
1464+ delta2 = delta3;
1465+ }
1466+ if (offset != 0)
1467+ {
1468+ for (; maxLen != lenLimit; maxLen++)
1469+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
1470+ break;
1471+ distances[offset - 2] = maxLen;
1472+ if (maxLen == lenLimit)
1473+ {
1474+ SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p));
1475+ MOVE_POS_RET;
1476+ }
1477+ }
1478+ if (maxLen < 3)
1479+ maxLen = 3;
1480+ GET_MATCHES_FOOTER(offset, maxLen)
1481+}
1482+
1483+static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1484+{
1485+ UInt32 hash2Value, hash3Value, delta2, delta3, maxLen, offset;
1486+ GET_MATCHES_HEADER(4)
1487+
1488+ HASH4_CALC;
1489+
1490+ delta2 = p->pos - p->hash[ hash2Value];
1491+ delta3 = p->pos - p->hash[kFix3HashSize + hash3Value];
1492+ curMatch = p->hash[kFix4HashSize + hashValue];
1493+
1494+ p->hash[ hash2Value] =
1495+ p->hash[kFix3HashSize + hash3Value] =
1496+ p->hash[kFix4HashSize + hashValue] = p->pos;
1497+
1498+ maxLen = 1;
1499+ offset = 0;
1500+ if (delta2 < p->cyclicBufferSize && *(cur - delta2) == *cur)
1501+ {
1502+ distances[0] = maxLen = 2;
1503+ distances[1] = delta2 - 1;
1504+ offset = 2;
1505+ }
1506+ if (delta2 != delta3 && delta3 < p->cyclicBufferSize && *(cur - delta3) == *cur)
1507+ {
1508+ maxLen = 3;
1509+ distances[offset + 1] = delta3 - 1;
1510+ offset += 2;
1511+ delta2 = delta3;
1512+ }
1513+ if (offset != 0)
1514+ {
1515+ for (; maxLen != lenLimit; maxLen++)
1516+ if (cur[(ptrdiff_t)maxLen - delta2] != cur[maxLen])
1517+ break;
1518+ distances[offset - 2] = maxLen;
1519+ if (maxLen == lenLimit)
1520+ {
1521+ p->son[p->cyclicBufferPos] = curMatch;
1522+ MOVE_POS_RET;
1523+ }
1524+ }
1525+ if (maxLen < 3)
1526+ maxLen = 3;
1527+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
1528+ distances + offset, maxLen) - (distances));
1529+ MOVE_POS_RET
1530+}
1531+
1532+UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances)
1533+{
1534+ UInt32 offset;
1535+ GET_MATCHES_HEADER(3)
1536+ HASH_ZIP_CALC;
1537+ curMatch = p->hash[hashValue];
1538+ p->hash[hashValue] = p->pos;
1539+ offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p),
1540+ distances, 2) - (distances));
1541+ MOVE_POS_RET
1542+}
1543+
1544+static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1545+{
1546+ do
1547+ {
1548+ SKIP_HEADER(2)
1549+ HASH2_CALC;
1550+ curMatch = p->hash[hashValue];
1551+ p->hash[hashValue] = p->pos;
1552+ SKIP_FOOTER
1553+ }
1554+ while (--num != 0);
1555+}
1556+
1557+void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1558+{
1559+ do
1560+ {
1561+ SKIP_HEADER(3)
1562+ HASH_ZIP_CALC;
1563+ curMatch = p->hash[hashValue];
1564+ p->hash[hashValue] = p->pos;
1565+ SKIP_FOOTER
1566+ }
1567+ while (--num != 0);
1568+}
1569+
1570+static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1571+{
1572+ do
1573+ {
1574+ UInt32 hash2Value;
1575+ SKIP_HEADER(3)
1576+ HASH3_CALC;
1577+ curMatch = p->hash[kFix3HashSize + hashValue];
1578+ p->hash[hash2Value] =
1579+ p->hash[kFix3HashSize + hashValue] = p->pos;
1580+ SKIP_FOOTER
1581+ }
1582+ while (--num != 0);
1583+}
1584+
1585+static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1586+{
1587+ do
1588+ {
1589+ UInt32 hash2Value, hash3Value;
1590+ SKIP_HEADER(4)
1591+ HASH4_CALC;
1592+ curMatch = p->hash[kFix4HashSize + hashValue];
1593+ p->hash[ hash2Value] =
1594+ p->hash[kFix3HashSize + hash3Value] = p->pos;
1595+ p->hash[kFix4HashSize + hashValue] = p->pos;
1596+ SKIP_FOOTER
1597+ }
1598+ while (--num != 0);
1599+}
1600+
1601+static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1602+{
1603+ do
1604+ {
1605+ UInt32 hash2Value, hash3Value;
1606+ SKIP_HEADER(4)
1607+ HASH4_CALC;
1608+ curMatch = p->hash[kFix4HashSize + hashValue];
1609+ p->hash[ hash2Value] =
1610+ p->hash[kFix3HashSize + hash3Value] =
1611+ p->hash[kFix4HashSize + hashValue] = p->pos;
1612+ p->son[p->cyclicBufferPos] = curMatch;
1613+ MOVE_POS
1614+ }
1615+ while (--num != 0);
1616+}
1617+
1618+void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num)
1619+{
1620+ do
1621+ {
1622+ SKIP_HEADER(3)
1623+ HASH_ZIP_CALC;
1624+ curMatch = p->hash[hashValue];
1625+ p->hash[hashValue] = p->pos;
1626+ p->son[p->cyclicBufferPos] = curMatch;
1627+ MOVE_POS
1628+ }
1629+ while (--num != 0);
1630+}
1631+
1632+void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable)
1633+{
1634+ vTable->Init = (Mf_Init_Func)MatchFinder_Init;
1635+ vTable->GetIndexByte = (Mf_GetIndexByte_Func)MatchFinder_GetIndexByte;
1636+ vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes;
1637+ vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos;
1638+ if (!p->btMode)
1639+ {
1640+ vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches;
1641+ vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip;
1642+ }
1643+ else if (p->numHashBytes == 2)
1644+ {
1645+ vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches;
1646+ vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip;
1647+ }
1648+ else if (p->numHashBytes == 3)
1649+ {
1650+ vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches;
1651+ vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip;
1652+ }
1653+ else
1654+ {
1655+ vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches;
1656+ vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip;
1657+ }
1658+}
1659--- /dev/null
1660+++ b/jffsX-utils/lzma/LzmaDec.c
1661@@ -0,0 +1,1014 @@
1662+/* LzmaDec.c -- LZMA Decoder
1663+2008-04-29
1664+Copyright (c) 1999-2008 Igor Pavlov
1665+Read LzmaDec.h for license options */
1666+
1667+#include "LzmaDec.h"
1668+
1669+#include <string.h>
1670+
1671+#define kNumTopBits 24
1672+#define kTopValue ((UInt32)1 << kNumTopBits)
1673+
1674+#define kNumBitModelTotalBits 11
1675+#define kBitModelTotal (1 << kNumBitModelTotalBits)
1676+#define kNumMoveBits 5
1677+
1678+#define RC_INIT_SIZE 5
1679+
1680+#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); }
1681+
1682+#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
1683+#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits));
1684+#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits));
1685+#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \
1686+ { UPDATE_0(p); i = (i + i); A0; } else \
1687+ { UPDATE_1(p); i = (i + i) + 1; A1; }
1688+#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;)
1689+
1690+#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); }
1691+#define TREE_DECODE(probs, limit, i) \
1692+ { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; }
1693+
1694+/* #define _LZMA_SIZE_OPT */
1695+
1696+#ifdef _LZMA_SIZE_OPT
1697+#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i)
1698+#else
1699+#define TREE_6_DECODE(probs, i) \
1700+ { i = 1; \
1701+ TREE_GET_BIT(probs, i); \
1702+ TREE_GET_BIT(probs, i); \
1703+ TREE_GET_BIT(probs, i); \
1704+ TREE_GET_BIT(probs, i); \
1705+ TREE_GET_BIT(probs, i); \
1706+ TREE_GET_BIT(probs, i); \
1707+ i -= 0x40; }
1708+#endif
1709+
1710+#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); }
1711+
1712+#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
1713+#define UPDATE_0_CHECK range = bound;
1714+#define UPDATE_1_CHECK range -= bound; code -= bound;
1715+#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \
1716+ { UPDATE_0_CHECK; i = (i + i); A0; } else \
1717+ { UPDATE_1_CHECK; i = (i + i) + 1; A1; }
1718+#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;)
1719+#define TREE_DECODE_CHECK(probs, limit, i) \
1720+ { i = 1; do { GET_BIT_CHECK(probs + i, i) } while(i < limit); i -= limit; }
1721+
1722+
1723+#define kNumPosBitsMax 4
1724+#define kNumPosStatesMax (1 << kNumPosBitsMax)
1725+
1726+#define kLenNumLowBits 3
1727+#define kLenNumLowSymbols (1 << kLenNumLowBits)
1728+#define kLenNumMidBits 3
1729+#define kLenNumMidSymbols (1 << kLenNumMidBits)
1730+#define kLenNumHighBits 8
1731+#define kLenNumHighSymbols (1 << kLenNumHighBits)
1732+
1733+#define LenChoice 0
1734+#define LenChoice2 (LenChoice + 1)
1735+#define LenLow (LenChoice2 + 1)
1736+#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits))
1737+#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits))
1738+#define kNumLenProbs (LenHigh + kLenNumHighSymbols)
1739+
1740+
1741+#define kNumStates 12
1742+#define kNumLitStates 7
1743+
1744+#define kStartPosModelIndex 4
1745+#define kEndPosModelIndex 14
1746+#define kNumFullDistances (1 << (kEndPosModelIndex >> 1))
1747+
1748+#define kNumPosSlotBits 6
1749+#define kNumLenToPosStates 4
1750+
1751+#define kNumAlignBits 4
1752+#define kAlignTableSize (1 << kNumAlignBits)
1753+
1754+#define kMatchMinLen 2
1755+#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
1756+
1757+#define IsMatch 0
1758+#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax))
1759+#define IsRepG0 (IsRep + kNumStates)
1760+#define IsRepG1 (IsRepG0 + kNumStates)
1761+#define IsRepG2 (IsRepG1 + kNumStates)
1762+#define IsRep0Long (IsRepG2 + kNumStates)
1763+#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax))
1764+#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits))
1765+#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex)
1766+#define LenCoder (Align + kAlignTableSize)
1767+#define RepLenCoder (LenCoder + kNumLenProbs)
1768+#define Literal (RepLenCoder + kNumLenProbs)
1769+
1770+#define LZMA_BASE_SIZE 1846
1771+#define LZMA_LIT_SIZE 768
1772+
1773+#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp)))
1774+
1775+#if Literal != LZMA_BASE_SIZE
1776+StopCompilingDueBUG
1777+#endif
1778+
1779+/*
1780+#define LZMA_STREAM_WAS_FINISHED_ID (-1)
1781+#define LZMA_SPEC_LEN_OFFSET (-3)
1782+*/
1783+
1784+Byte kLiteralNextStates[kNumStates * 2] =
1785+{
1786+ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5,
1787+ 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10
1788+};
1789+
1790+#define LZMA_DIC_MIN (1 << 12)
1791+
1792+/* First LZMA-symbol is always decoded.
1793+And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization
1794+Out:
1795+ Result:
1796+ 0 - OK
1797+ 1 - Error
1798+ p->remainLen:
1799+ < kMatchSpecLenStart : normal remain
1800+ = kMatchSpecLenStart : finished
1801+ = kMatchSpecLenStart + 1 : Flush marker
1802+ = kMatchSpecLenStart + 2 : State Init Marker
1803+*/
1804+
1805+static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
1806+{
1807+ CLzmaProb *probs = p->probs;
1808+
1809+ unsigned state = p->state;
1810+ UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3];
1811+ unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1;
1812+ unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1;
1813+ unsigned lc = p->prop.lc;
1814+
1815+ Byte *dic = p->dic;
1816+ SizeT dicBufSize = p->dicBufSize;
1817+ SizeT dicPos = p->dicPos;
1818+
1819+ UInt32 processedPos = p->processedPos;
1820+ UInt32 checkDicSize = p->checkDicSize;
1821+ unsigned len = 0;
1822+
1823+ const Byte *buf = p->buf;
1824+ UInt32 range = p->range;
1825+ UInt32 code = p->code;
1826+
1827+ do
1828+ {
1829+ CLzmaProb *prob;
1830+ UInt32 bound;
1831+ unsigned ttt;
1832+ unsigned posState = processedPos & pbMask;
1833+
1834+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
1835+ IF_BIT_0(prob)
1836+ {
1837+ unsigned symbol;
1838+ UPDATE_0(prob);
1839+ prob = probs + Literal;
1840+ if (checkDicSize != 0 || processedPos != 0)
1841+ prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) +
1842+ (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc))));
1843+
1844+ if (state < kNumLitStates)
1845+ {
1846+ symbol = 1;
1847+ do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100);
1848+ }
1849+ else
1850+ {
1851+ unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
1852+ unsigned offs = 0x100;
1853+ symbol = 1;
1854+ do
1855+ {
1856+ unsigned bit;
1857+ CLzmaProb *probLit;
1858+ matchByte <<= 1;
1859+ bit = (matchByte & offs);
1860+ probLit = prob + offs + bit + symbol;
1861+ GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit)
1862+ }
1863+ while (symbol < 0x100);
1864+ }
1865+ dic[dicPos++] = (Byte)symbol;
1866+ processedPos++;
1867+
1868+ state = kLiteralNextStates[state];
1869+ /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */
1870+ continue;
1871+ }
1872+ else
1873+ {
1874+ UPDATE_1(prob);
1875+ prob = probs + IsRep + state;
1876+ IF_BIT_0(prob)
1877+ {
1878+ UPDATE_0(prob);
1879+ state += kNumStates;
1880+ prob = probs + LenCoder;
1881+ }
1882+ else
1883+ {
1884+ UPDATE_1(prob);
1885+ if (checkDicSize == 0 && processedPos == 0)
1886+ return SZ_ERROR_DATA;
1887+ prob = probs + IsRepG0 + state;
1888+ IF_BIT_0(prob)
1889+ {
1890+ UPDATE_0(prob);
1891+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
1892+ IF_BIT_0(prob)
1893+ {
1894+ UPDATE_0(prob);
1895+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
1896+ dicPos++;
1897+ processedPos++;
1898+ state = state < kNumLitStates ? 9 : 11;
1899+ continue;
1900+ }
1901+ UPDATE_1(prob);
1902+ }
1903+ else
1904+ {
1905+ UInt32 distance;
1906+ UPDATE_1(prob);
1907+ prob = probs + IsRepG1 + state;
1908+ IF_BIT_0(prob)
1909+ {
1910+ UPDATE_0(prob);
1911+ distance = rep1;
1912+ }
1913+ else
1914+ {
1915+ UPDATE_1(prob);
1916+ prob = probs + IsRepG2 + state;
1917+ IF_BIT_0(prob)
1918+ {
1919+ UPDATE_0(prob);
1920+ distance = rep2;
1921+ }
1922+ else
1923+ {
1924+ UPDATE_1(prob);
1925+ distance = rep3;
1926+ rep3 = rep2;
1927+ }
1928+ rep2 = rep1;
1929+ }
1930+ rep1 = rep0;
1931+ rep0 = distance;
1932+ }
1933+ state = state < kNumLitStates ? 8 : 11;
1934+ prob = probs + RepLenCoder;
1935+ }
1936+ {
1937+ unsigned limit, offset;
1938+ CLzmaProb *probLen = prob + LenChoice;
1939+ IF_BIT_0(probLen)
1940+ {
1941+ UPDATE_0(probLen);
1942+ probLen = prob + LenLow + (posState << kLenNumLowBits);
1943+ offset = 0;
1944+ limit = (1 << kLenNumLowBits);
1945+ }
1946+ else
1947+ {
1948+ UPDATE_1(probLen);
1949+ probLen = prob + LenChoice2;
1950+ IF_BIT_0(probLen)
1951+ {
1952+ UPDATE_0(probLen);
1953+ probLen = prob + LenMid + (posState << kLenNumMidBits);
1954+ offset = kLenNumLowSymbols;
1955+ limit = (1 << kLenNumMidBits);
1956+ }
1957+ else
1958+ {
1959+ UPDATE_1(probLen);
1960+ probLen = prob + LenHigh;
1961+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
1962+ limit = (1 << kLenNumHighBits);
1963+ }
1964+ }
1965+ TREE_DECODE(probLen, limit, len);
1966+ len += offset;
1967+ }
1968+
1969+ if (state >= kNumStates)
1970+ {
1971+ UInt32 distance;
1972+ prob = probs + PosSlot +
1973+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits);
1974+ TREE_6_DECODE(prob, distance);
1975+ if (distance >= kStartPosModelIndex)
1976+ {
1977+ unsigned posSlot = (unsigned)distance;
1978+ int numDirectBits = (int)(((distance >> 1) - 1));
1979+ distance = (2 | (distance & 1));
1980+ if (posSlot < kEndPosModelIndex)
1981+ {
1982+ distance <<= numDirectBits;
1983+ prob = probs + SpecPos + distance - posSlot - 1;
1984+ {
1985+ UInt32 mask = 1;
1986+ unsigned i = 1;
1987+ do
1988+ {
1989+ GET_BIT2(prob + i, i, ; , distance |= mask);
1990+ mask <<= 1;
1991+ }
1992+ while(--numDirectBits != 0);
1993+ }
1994+ }
1995+ else
1996+ {
1997+ numDirectBits -= kNumAlignBits;
1998+ do
1999+ {
2000+ NORMALIZE
2001+ range >>= 1;
2002+
2003+ {
2004+ UInt32 t;
2005+ code -= range;
2006+ t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */
2007+ distance = (distance << 1) + (t + 1);
2008+ code += range & t;
2009+ }
2010+ /*
2011+ distance <<= 1;
2012+ if (code >= range)
2013+ {
2014+ code -= range;
2015+ distance |= 1;
2016+ }
2017+ */
2018+ }
2019+ while (--numDirectBits != 0);
2020+ prob = probs + Align;
2021+ distance <<= kNumAlignBits;
2022+ {
2023+ unsigned i = 1;
2024+ GET_BIT2(prob + i, i, ; , distance |= 1);
2025+ GET_BIT2(prob + i, i, ; , distance |= 2);
2026+ GET_BIT2(prob + i, i, ; , distance |= 4);
2027+ GET_BIT2(prob + i, i, ; , distance |= 8);
2028+ }
2029+ if (distance == (UInt32)0xFFFFFFFF)
2030+ {
2031+ len += kMatchSpecLenStart;
2032+ state -= kNumStates;
2033+ break;
2034+ }
2035+ }
2036+ }
2037+ rep3 = rep2;
2038+ rep2 = rep1;
2039+ rep1 = rep0;
2040+ rep0 = distance + 1;
2041+ if (checkDicSize == 0)
2042+ {
2043+ if (distance >= processedPos)
2044+ return SZ_ERROR_DATA;
2045+ }
2046+ else if (distance >= checkDicSize)
2047+ return SZ_ERROR_DATA;
2048+ state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3;
2049+ /* state = kLiteralNextStates[state]; */
2050+ }
2051+
2052+ len += kMatchMinLen;
2053+
2054+ {
2055+ SizeT rem = limit - dicPos;
2056+ unsigned curLen = ((rem < len) ? (unsigned)rem : len);
2057+ SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0);
2058+
2059+ processedPos += curLen;
2060+
2061+ len -= curLen;
2062+ if (pos + curLen <= dicBufSize)
2063+ {
2064+ Byte *dest = dic + dicPos;
2065+ ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos;
2066+ const Byte *lim = dest + curLen;
2067+ dicPos += curLen;
2068+ do
2069+ *(dest) = (Byte)*(dest + src);
2070+ while (++dest != lim);
2071+ }
2072+ else
2073+ {
2074+ do
2075+ {
2076+ dic[dicPos++] = dic[pos];
2077+ if (++pos == dicBufSize)
2078+ pos = 0;
2079+ }
2080+ while (--curLen != 0);
2081+ }
2082+ }
2083+ }
2084+ }
2085+ while (dicPos < limit && buf < bufLimit);
2086+ NORMALIZE;
2087+ p->buf = buf;
2088+ p->range = range;
2089+ p->code = code;
2090+ p->remainLen = len;
2091+ p->dicPos = dicPos;
2092+ p->processedPos = processedPos;
2093+ p->reps[0] = rep0;
2094+ p->reps[1] = rep1;
2095+ p->reps[2] = rep2;
2096+ p->reps[3] = rep3;
2097+ p->state = state;
2098+
2099+ return SZ_OK;
2100+}
2101+
2102+static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit)
2103+{
2104+ if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart)
2105+ {
2106+ Byte *dic = p->dic;
2107+ SizeT dicPos = p->dicPos;
2108+ SizeT dicBufSize = p->dicBufSize;
2109+ unsigned len = p->remainLen;
2110+ UInt32 rep0 = p->reps[0];
2111+ if (limit - dicPos < len)
2112+ len = (unsigned)(limit - dicPos);
2113+
2114+ if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len)
2115+ p->checkDicSize = p->prop.dicSize;
2116+
2117+ p->processedPos += len;
2118+ p->remainLen -= len;
2119+ while (len-- != 0)
2120+ {
2121+ dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)];
2122+ dicPos++;
2123+ }
2124+ p->dicPos = dicPos;
2125+ }
2126+}
2127+
2128+/* LzmaDec_DecodeReal2 decodes LZMA-symbols and sets p->needFlush and p->needInit, if required. */
2129+
2130+static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit)
2131+{
2132+ do
2133+ {
2134+ SizeT limit2 = limit;
2135+ if (p->checkDicSize == 0)
2136+ {
2137+ UInt32 rem = p->prop.dicSize - p->processedPos;
2138+ if (limit - p->dicPos > rem)
2139+ limit2 = p->dicPos + rem;
2140+ }
2141+ RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit));
2142+ if (p->processedPos >= p->prop.dicSize)
2143+ p->checkDicSize = p->prop.dicSize;
2144+ LzmaDec_WriteRem(p, limit);
2145+ }
2146+ while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart);
2147+
2148+ if (p->remainLen > kMatchSpecLenStart)
2149+ {
2150+ p->remainLen = kMatchSpecLenStart;
2151+ }
2152+ return 0;
2153+}
2154+
2155+typedef enum
2156+{
2157+ DUMMY_ERROR, /* unexpected end of input stream */
2158+ DUMMY_LIT,
2159+ DUMMY_MATCH,
2160+ DUMMY_REP
2161+} ELzmaDummy;
2162+
2163+static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize)
2164+{
2165+ UInt32 range = p->range;
2166+ UInt32 code = p->code;
2167+ const Byte *bufLimit = buf + inSize;
2168+ CLzmaProb *probs = p->probs;
2169+ unsigned state = p->state;
2170+ ELzmaDummy res;
2171+
2172+ {
2173+ CLzmaProb *prob;
2174+ UInt32 bound;
2175+ unsigned ttt;
2176+ unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1);
2177+
2178+ prob = probs + IsMatch + (state << kNumPosBitsMax) + posState;
2179+ IF_BIT_0_CHECK(prob)
2180+ {
2181+ UPDATE_0_CHECK
2182+
2183+ /* if (bufLimit - buf >= 7) return DUMMY_LIT; */
2184+
2185+ prob = probs + Literal;
2186+ if (p->checkDicSize != 0 || p->processedPos != 0)
2187+ prob += (LZMA_LIT_SIZE *
2188+ ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) +
2189+ (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc))));
2190+
2191+ if (state < kNumLitStates)
2192+ {
2193+ unsigned symbol = 1;
2194+ do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100);
2195+ }
2196+ else
2197+ {
2198+ unsigned matchByte = p->dic[p->dicPos - p->reps[0] +
2199+ ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)];
2200+ unsigned offs = 0x100;
2201+ unsigned symbol = 1;
2202+ do
2203+ {
2204+ unsigned bit;
2205+ CLzmaProb *probLit;
2206+ matchByte <<= 1;
2207+ bit = (matchByte & offs);
2208+ probLit = prob + offs + bit + symbol;
2209+ GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit)
2210+ }
2211+ while (symbol < 0x100);
2212+ }
2213+ res = DUMMY_LIT;
2214+ }
2215+ else
2216+ {
2217+ unsigned len;
2218+ UPDATE_1_CHECK;
2219+
2220+ prob = probs + IsRep + state;
2221+ IF_BIT_0_CHECK(prob)
2222+ {
2223+ UPDATE_0_CHECK;
2224+ state = 0;
2225+ prob = probs + LenCoder;
2226+ res = DUMMY_MATCH;
2227+ }
2228+ else
2229+ {
2230+ UPDATE_1_CHECK;
2231+ res = DUMMY_REP;
2232+ prob = probs + IsRepG0 + state;
2233+ IF_BIT_0_CHECK(prob)
2234+ {
2235+ UPDATE_0_CHECK;
2236+ prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState;
2237+ IF_BIT_0_CHECK(prob)
2238+ {
2239+ UPDATE_0_CHECK;
2240+ NORMALIZE_CHECK;
2241+ return DUMMY_REP;
2242+ }
2243+ else
2244+ {
2245+ UPDATE_1_CHECK;
2246+ }
2247+ }
2248+ else
2249+ {
2250+ UPDATE_1_CHECK;
2251+ prob = probs + IsRepG1 + state;
2252+ IF_BIT_0_CHECK(prob)
2253+ {
2254+ UPDATE_0_CHECK;
2255+ }
2256+ else
2257+ {
2258+ UPDATE_1_CHECK;
2259+ prob = probs + IsRepG2 + state;
2260+ IF_BIT_0_CHECK(prob)
2261+ {
2262+ UPDATE_0_CHECK;
2263+ }
2264+ else
2265+ {
2266+ UPDATE_1_CHECK;
2267+ }
2268+ }
2269+ }
2270+ state = kNumStates;
2271+ prob = probs + RepLenCoder;
2272+ }
2273+ {
2274+ unsigned limit, offset;
2275+ CLzmaProb *probLen = prob + LenChoice;
2276+ IF_BIT_0_CHECK(probLen)
2277+ {
2278+ UPDATE_0_CHECK;
2279+ probLen = prob + LenLow + (posState << kLenNumLowBits);
2280+ offset = 0;
2281+ limit = 1 << kLenNumLowBits;
2282+ }
2283+ else
2284+ {
2285+ UPDATE_1_CHECK;
2286+ probLen = prob + LenChoice2;
2287+ IF_BIT_0_CHECK(probLen)
2288+ {
2289+ UPDATE_0_CHECK;
2290+ probLen = prob + LenMid + (posState << kLenNumMidBits);
2291+ offset = kLenNumLowSymbols;
2292+ limit = 1 << kLenNumMidBits;
2293+ }
2294+ else
2295+ {
2296+ UPDATE_1_CHECK;
2297+ probLen = prob + LenHigh;
2298+ offset = kLenNumLowSymbols + kLenNumMidSymbols;
2299+ limit = 1 << kLenNumHighBits;
2300+ }
2301+ }
2302+ TREE_DECODE_CHECK(probLen, limit, len);
2303+ len += offset;
2304+ }
2305+
2306+ if (state < 4)
2307+ {
2308+ unsigned posSlot;
2309+ prob = probs + PosSlot +
2310+ ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) <<
2311+ kNumPosSlotBits);
2312+ TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot);
2313+ if (posSlot >= kStartPosModelIndex)
2314+ {
2315+ int numDirectBits = ((posSlot >> 1) - 1);
2316+
2317+ /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */
2318+
2319+ if (posSlot < kEndPosModelIndex)
2320+ {
2321+ prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1;
2322+ }
2323+ else
2324+ {
2325+ numDirectBits -= kNumAlignBits;
2326+ do
2327+ {
2328+ NORMALIZE_CHECK
2329+ range >>= 1;
2330+ code -= range & (((code - range) >> 31) - 1);
2331+ /* if (code >= range) code -= range; */
2332+ }
2333+ while (--numDirectBits != 0);
2334+ prob = probs + Align;
2335+ numDirectBits = kNumAlignBits;
2336+ }
2337+ {
2338+ unsigned i = 1;
2339+ do
2340+ {
2341+ GET_BIT_CHECK(prob + i, i);
2342+ }
2343+ while(--numDirectBits != 0);
2344+ }
2345+ }
2346+ }
2347+ }
2348+ }
2349+ NORMALIZE_CHECK;
2350+ return res;
2351+}
2352+
2353+
2354+static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data)
2355+{
2356+ p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]);
2357+ p->range = 0xFFFFFFFF;
2358+ p->needFlush = 0;
2359+}
2360+
2361+static void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState)
2362+{
2363+ p->needFlush = 1;
2364+ p->remainLen = 0;
2365+ p->tempBufSize = 0;
2366+
2367+ if (initDic)
2368+ {
2369+ p->processedPos = 0;
2370+ p->checkDicSize = 0;
2371+ p->needInitState = 1;
2372+ }
2373+ if (initState)
2374+ p->needInitState = 1;
2375+}
2376+
2377+void LzmaDec_Init(CLzmaDec *p)
2378+{
2379+ p->dicPos = 0;
2380+ LzmaDec_InitDicAndState(p, True, True);
2381+}
2382+
2383+static void LzmaDec_InitStateReal(CLzmaDec *p)
2384+{
2385+ UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp));
2386+ UInt32 i;
2387+ CLzmaProb *probs = p->probs;
2388+ for (i = 0; i < numProbs; i++)
2389+ probs[i] = kBitModelTotal >> 1;
2390+ p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1;
2391+ p->state = 0;
2392+ p->needInitState = 0;
2393+}
2394+
2395+SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen,
2396+ ELzmaFinishMode finishMode, ELzmaStatus *status)
2397+{
2398+ SizeT inSize = *srcLen;
2399+ (*srcLen) = 0;
2400+ LzmaDec_WriteRem(p, dicLimit);
2401+
2402+ *status = LZMA_STATUS_NOT_SPECIFIED;
2403+
2404+ while (p->remainLen != kMatchSpecLenStart)
2405+ {
2406+ int checkEndMarkNow;
2407+
2408+ if (p->needFlush != 0)
2409+ {
2410+ for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--)
2411+ p->tempBuf[p->tempBufSize++] = *src++;
2412+ if (p->tempBufSize < RC_INIT_SIZE)
2413+ {
2414+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
2415+ return SZ_OK;
2416+ }
2417+ if (p->tempBuf[0] != 0)
2418+ return SZ_ERROR_DATA;
2419+
2420+ LzmaDec_InitRc(p, p->tempBuf);
2421+ p->tempBufSize = 0;
2422+ }
2423+
2424+ checkEndMarkNow = 0;
2425+ if (p->dicPos >= dicLimit)
2426+ {
2427+ if (p->remainLen == 0 && p->code == 0)
2428+ {
2429+ *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK;
2430+ return SZ_OK;
2431+ }
2432+ if (finishMode == LZMA_FINISH_ANY)
2433+ {
2434+ *status = LZMA_STATUS_NOT_FINISHED;
2435+ return SZ_OK;
2436+ }
2437+ if (p->remainLen != 0)
2438+ {
2439+ *status = LZMA_STATUS_NOT_FINISHED;
2440+ return SZ_ERROR_DATA;
2441+ }
2442+ checkEndMarkNow = 1;
2443+ }
2444+
2445+ if (p->needInitState)
2446+ LzmaDec_InitStateReal(p);
2447+
2448+ if (p->tempBufSize == 0)
2449+ {
2450+ SizeT processed;
2451+ const Byte *bufLimit;
2452+ if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
2453+ {
2454+ int dummyRes = LzmaDec_TryDummy(p, src, inSize);
2455+ if (dummyRes == DUMMY_ERROR)
2456+ {
2457+ memcpy(p->tempBuf, src, inSize);
2458+ p->tempBufSize = (unsigned)inSize;
2459+ (*srcLen) += inSize;
2460+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
2461+ return SZ_OK;
2462+ }
2463+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
2464+ {
2465+ *status = LZMA_STATUS_NOT_FINISHED;
2466+ return SZ_ERROR_DATA;
2467+ }
2468+ bufLimit = src;
2469+ }
2470+ else
2471+ bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX;
2472+ p->buf = src;
2473+ if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0)
2474+ return SZ_ERROR_DATA;
2475+ processed = p->buf - src;
2476+ (*srcLen) += processed;
2477+ src += processed;
2478+ inSize -= processed;
2479+ }
2480+ else
2481+ {
2482+ unsigned rem = p->tempBufSize, lookAhead = 0;
2483+ while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize)
2484+ p->tempBuf[rem++] = src[lookAhead++];
2485+ p->tempBufSize = rem;
2486+ if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow)
2487+ {
2488+ int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem);
2489+ if (dummyRes == DUMMY_ERROR)
2490+ {
2491+ (*srcLen) += lookAhead;
2492+ *status = LZMA_STATUS_NEEDS_MORE_INPUT;
2493+ return SZ_OK;
2494+ }
2495+ if (checkEndMarkNow && dummyRes != DUMMY_MATCH)
2496+ {
2497+ *status = LZMA_STATUS_NOT_FINISHED;
2498+ return SZ_ERROR_DATA;
2499+ }
2500+ }
2501+ p->buf = p->tempBuf;
2502+ if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0)
2503+ return SZ_ERROR_DATA;
2504+ lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf));
2505+ (*srcLen) += lookAhead;
2506+ src += lookAhead;
2507+ inSize -= lookAhead;
2508+ p->tempBufSize = 0;
2509+ }
2510+ }
2511+ if (p->code == 0)
2512+ *status = LZMA_STATUS_FINISHED_WITH_MARK;
2513+ return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA;
2514+}
2515+
2516+SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status)
2517+{
2518+ SizeT outSize = *destLen;
2519+ SizeT inSize = *srcLen;
2520+ *srcLen = *destLen = 0;
2521+ for (;;)
2522+ {
2523+ SizeT inSizeCur = inSize, outSizeCur, dicPos;
2524+ ELzmaFinishMode curFinishMode;
2525+ SRes res;
2526+ if (p->dicPos == p->dicBufSize)
2527+ p->dicPos = 0;
2528+ dicPos = p->dicPos;
2529+ if (outSize > p->dicBufSize - dicPos)
2530+ {
2531+ outSizeCur = p->dicBufSize;
2532+ curFinishMode = LZMA_FINISH_ANY;
2533+ }
2534+ else
2535+ {
2536+ outSizeCur = dicPos + outSize;
2537+ curFinishMode = finishMode;
2538+ }
2539+
2540+ res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status);
2541+ src += inSizeCur;
2542+ inSize -= inSizeCur;
2543+ *srcLen += inSizeCur;
2544+ outSizeCur = p->dicPos - dicPos;
2545+ memcpy(dest, p->dic + dicPos, outSizeCur);
2546+ dest += outSizeCur;
2547+ outSize -= outSizeCur;
2548+ *destLen += outSizeCur;
2549+ if (res != 0)
2550+ return res;
2551+ if (outSizeCur == 0 || outSize == 0)
2552+ return SZ_OK;
2553+ }
2554+}
2555+
2556+void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc)
2557+{
2558+ alloc->Free(alloc, p->probs);
2559+ p->probs = 0;
2560+}
2561+
2562+static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc)
2563+{
2564+ alloc->Free(alloc, p->dic);
2565+ p->dic = 0;
2566+}
2567+
2568+void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc)
2569+{
2570+ LzmaDec_FreeProbs(p, alloc);
2571+ LzmaDec_FreeDict(p, alloc);
2572+}
2573+
2574+SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size)
2575+{
2576+ UInt32 dicSize;
2577+ Byte d;
2578+
2579+ if (size < LZMA_PROPS_SIZE)
2580+ return SZ_ERROR_UNSUPPORTED;
2581+ else
2582+ dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24);
2583+
2584+ if (dicSize < LZMA_DIC_MIN)
2585+ dicSize = LZMA_DIC_MIN;
2586+ p->dicSize = dicSize;
2587+
2588+ d = data[0];
2589+ if (d >= (9 * 5 * 5))
2590+ return SZ_ERROR_UNSUPPORTED;
2591+
2592+ p->lc = d % 9;
2593+ d /= 9;
2594+ p->pb = d / 5;
2595+ p->lp = d % 5;
2596+
2597+ return SZ_OK;
2598+}
2599+
2600+static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc)
2601+{
2602+ UInt32 numProbs = LzmaProps_GetNumProbs(propNew);
2603+ if (p->probs == 0 || numProbs != p->numProbs)
2604+ {
2605+ LzmaDec_FreeProbs(p, alloc);
2606+ p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb));
2607+ p->numProbs = numProbs;
2608+ if (p->probs == 0)
2609+ return SZ_ERROR_MEM;
2610+ }
2611+ return SZ_OK;
2612+}
2613+
2614+SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
2615+{
2616+ CLzmaProps propNew;
2617+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
2618+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
2619+ p->prop = propNew;
2620+ return SZ_OK;
2621+}
2622+
2623+SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc)
2624+{
2625+ CLzmaProps propNew;
2626+ SizeT dicBufSize;
2627+ RINOK(LzmaProps_Decode(&propNew, props, propsSize));
2628+ RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc));
2629+ dicBufSize = propNew.dicSize;
2630+ if (p->dic == 0 || dicBufSize != p->dicBufSize)
2631+ {
2632+ LzmaDec_FreeDict(p, alloc);
2633+ p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize);
2634+ if (p->dic == 0)
2635+ {
2636+ LzmaDec_FreeProbs(p, alloc);
2637+ return SZ_ERROR_MEM;
2638+ }
2639+ }
2640+ p->dicBufSize = dicBufSize;
2641+ p->prop = propNew;
2642+ return SZ_OK;
2643+}
2644+
2645+SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
2646+ const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
2647+ ELzmaStatus *status, ISzAlloc *alloc)
2648+{
2649+ CLzmaDec p;
2650+ SRes res;
2651+ SizeT inSize = *srcLen;
2652+ SizeT outSize = *destLen;
2653+ *srcLen = *destLen = 0;
2654+ if (inSize < RC_INIT_SIZE)
2655+ return SZ_ERROR_INPUT_EOF;
2656+
2657+ LzmaDec_Construct(&p);
2658+ res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc);
2659+ if (res != 0)
2660+ return res;
2661+ p.dic = dest;
2662+ p.dicBufSize = outSize;
2663+
2664+ LzmaDec_Init(&p);
2665+
2666+ *srcLen = inSize;
2667+ res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status);
2668+
2669+ if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT)
2670+ res = SZ_ERROR_INPUT_EOF;
2671+
2672+ (*destLen) = p.dicPos;
2673+ LzmaDec_FreeProbs(&p, alloc);
2674+ return res;
2675+}
2676--- /dev/null
2677+++ b/jffsX-utils/lzma/LzmaEnc.c
2678@@ -0,0 +1,2335 @@
2679+/* LzmaEnc.c -- LZMA Encoder
2680+2008-04-28
2681+Copyright (c) 1999-2008 Igor Pavlov
2682+Read LzmaEnc.h for license options */
2683+
2684+#if defined(SHOW_STAT) || defined(SHOW_STAT2)
2685+#include <stdio.h>
2686+#endif
2687+
2688+#include <string.h>
2689+
2690+#include "LzmaEnc.h"
2691+
2692+#include "LzFind.h"
2693+#ifdef COMPRESS_MF_MT
2694+#include "LzFindMt.h"
2695+#endif
2696+
2697+/* #define SHOW_STAT */
2698+/* #define SHOW_STAT2 */
2699+
2700+#ifdef SHOW_STAT
2701+static int ttt = 0;
2702+#endif
2703+
2704+#define kBlockSizeMax ((1 << LZMA_NUM_BLOCK_SIZE_BITS) - 1)
2705+
2706+#define kBlockSize (9 << 10)
2707+#define kUnpackBlockSize (1 << 18)
2708+#define kMatchArraySize (1 << 21)
2709+#define kMatchRecordMaxSize ((LZMA_MATCH_LEN_MAX * 2 + 3) * LZMA_MATCH_LEN_MAX)
2710+
2711+#define kNumMaxDirectBits (31)
2712+
2713+#define kNumTopBits 24
2714+#define kTopValue ((UInt32)1 << kNumTopBits)
2715+
2716+#define kNumBitModelTotalBits 11
2717+#define kBitModelTotal (1 << kNumBitModelTotalBits)
2718+#define kNumMoveBits 5
2719+#define kProbInitValue (kBitModelTotal >> 1)
2720+
2721+#define kNumMoveReducingBits 4
2722+#define kNumBitPriceShiftBits 4
2723+#define kBitPrice (1 << kNumBitPriceShiftBits)
2724+
2725+void LzmaEncProps_Init(CLzmaEncProps *p)
2726+{
2727+ p->level = 5;
2728+ p->dictSize = p->mc = 0;
2729+ p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1;
2730+ p->writeEndMark = 0;
2731+}
2732+
2733+void LzmaEncProps_Normalize(CLzmaEncProps *p)
2734+{
2735+ int level = p->level;
2736+ if (level < 0) level = 5;
2737+ p->level = level;
2738+ if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level == 6 ? (1 << 25) : (1 << 26)));
2739+ if (p->lc < 0) p->lc = 3;
2740+ if (p->lp < 0) p->lp = 0;
2741+ if (p->pb < 0) p->pb = 2;
2742+ if (p->algo < 0) p->algo = (level < 5 ? 0 : 1);
2743+ if (p->fb < 0) p->fb = (level < 7 ? 32 : 64);
2744+ if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1);
2745+ if (p->numHashBytes < 0) p->numHashBytes = 4;
2746+ if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1);
2747+ if (p->numThreads < 0) p->numThreads = ((p->btMode && p->algo) ? 2 : 1);
2748+}
2749+
2750+UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2)
2751+{
2752+ CLzmaEncProps props = *props2;
2753+ LzmaEncProps_Normalize(&props);
2754+ return props.dictSize;
2755+}
2756+
2757+/* #define LZMA_LOG_BSR */
2758+/* Define it for Intel's CPU */
2759+
2760+
2761+#ifdef LZMA_LOG_BSR
2762+
2763+#define kDicLogSizeMaxCompress 30
2764+
2765+#define BSR2_RET(pos, res) { unsigned long i; _BitScanReverse(&i, (pos)); res = (i + i) + ((pos >> (i - 1)) & 1); }
2766+
2767+UInt32 GetPosSlot1(UInt32 pos)
2768+{
2769+ UInt32 res;
2770+ BSR2_RET(pos, res);
2771+ return res;
2772+}
2773+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
2774+#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); }
2775+
2776+#else
2777+
2778+#define kNumLogBits (9 + (int)sizeof(size_t) / 2)
2779+#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7)
2780+
2781+static void LzmaEnc_FastPosInit(Byte *g_FastPos)
2782+{
2783+ int c = 2, slotFast;
2784+ g_FastPos[0] = 0;
2785+ g_FastPos[1] = 1;
2786+
2787+ for (slotFast = 2; slotFast < kNumLogBits * 2; slotFast++)
2788+ {
2789+ UInt32 k = (1 << ((slotFast >> 1) - 1));
2790+ UInt32 j;
2791+ for (j = 0; j < k; j++, c++)
2792+ g_FastPos[c] = (Byte)slotFast;
2793+ }
2794+}
2795+
2796+#define BSR2_RET(pos, res) { UInt32 i = 6 + ((kNumLogBits - 1) & \
2797+ (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \
2798+ res = p->g_FastPos[pos >> i] + (i * 2); }
2799+/*
2800+#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \
2801+ p->g_FastPos[pos >> 6] + 12 : \
2802+ p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; }
2803+*/
2804+
2805+#define GetPosSlot1(pos) p->g_FastPos[pos]
2806+#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); }
2807+#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos]; else BSR2_RET(pos, res); }
2808+
2809+#endif
2810+
2811+
2812+#define LZMA_NUM_REPS 4
2813+
2814+typedef unsigned CState;
2815+
2816+typedef struct _COptimal
2817+{
2818+ UInt32 price;
2819+
2820+ CState state;
2821+ int prev1IsChar;
2822+ int prev2;
2823+
2824+ UInt32 posPrev2;
2825+ UInt32 backPrev2;
2826+
2827+ UInt32 posPrev;
2828+ UInt32 backPrev;
2829+ UInt32 backs[LZMA_NUM_REPS];
2830+} COptimal;
2831+
2832+#define kNumOpts (1 << 12)
2833+
2834+#define kNumLenToPosStates 4
2835+#define kNumPosSlotBits 6
2836+#define kDicLogSizeMin 0
2837+#define kDicLogSizeMax 32
2838+#define kDistTableSizeMax (kDicLogSizeMax * 2)
2839+
2840+
2841+#define kNumAlignBits 4
2842+#define kAlignTableSize (1 << kNumAlignBits)
2843+#define kAlignMask (kAlignTableSize - 1)
2844+
2845+#define kStartPosModelIndex 4
2846+#define kEndPosModelIndex 14
2847+#define kNumPosModels (kEndPosModelIndex - kStartPosModelIndex)
2848+
2849+#define kNumFullDistances (1 << (kEndPosModelIndex / 2))
2850+
2851+#ifdef _LZMA_PROB32
2852+#define CLzmaProb UInt32
2853+#else
2854+#define CLzmaProb UInt16
2855+#endif
2856+
2857+#define LZMA_PB_MAX 4
2858+#define LZMA_LC_MAX 8
2859+#define LZMA_LP_MAX 4
2860+
2861+#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX)
2862+
2863+
2864+#define kLenNumLowBits 3
2865+#define kLenNumLowSymbols (1 << kLenNumLowBits)
2866+#define kLenNumMidBits 3
2867+#define kLenNumMidSymbols (1 << kLenNumMidBits)
2868+#define kLenNumHighBits 8
2869+#define kLenNumHighSymbols (1 << kLenNumHighBits)
2870+
2871+#define kLenNumSymbolsTotal (kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols)
2872+
2873+#define LZMA_MATCH_LEN_MIN 2
2874+#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1)
2875+
2876+#define kNumStates 12
2877+
2878+typedef struct
2879+{
2880+ CLzmaProb choice;
2881+ CLzmaProb choice2;
2882+ CLzmaProb low[LZMA_NUM_PB_STATES_MAX << kLenNumLowBits];
2883+ CLzmaProb mid[LZMA_NUM_PB_STATES_MAX << kLenNumMidBits];
2884+ CLzmaProb high[kLenNumHighSymbols];
2885+} CLenEnc;
2886+
2887+typedef struct
2888+{
2889+ CLenEnc p;
2890+ UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal];
2891+ UInt32 tableSize;
2892+ UInt32 counters[LZMA_NUM_PB_STATES_MAX];
2893+} CLenPriceEnc;
2894+
2895+typedef struct _CRangeEnc
2896+{
2897+ UInt32 range;
2898+ Byte cache;
2899+ UInt64 low;
2900+ UInt64 cacheSize;
2901+ Byte *buf;
2902+ Byte *bufLim;
2903+ Byte *bufBase;
2904+ ISeqOutStream *outStream;
2905+ UInt64 processed;
2906+ SRes res;
2907+} CRangeEnc;
2908+
2909+typedef struct _CSeqInStreamBuf
2910+{
2911+ ISeqInStream funcTable;
2912+ const Byte *data;
2913+ SizeT rem;
2914+} CSeqInStreamBuf;
2915+
2916+static SRes MyRead(void *pp, void *data, size_t *size)
2917+{
2918+ size_t curSize = *size;
2919+ CSeqInStreamBuf *p = (CSeqInStreamBuf *)pp;
2920+ if (p->rem < curSize)
2921+ curSize = p->rem;
2922+ memcpy(data, p->data, curSize);
2923+ p->rem -= curSize;
2924+ p->data += curSize;
2925+ *size = curSize;
2926+ return SZ_OK;
2927+}
2928+
2929+typedef struct
2930+{
2931+ CLzmaProb *litProbs;
2932+
2933+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
2934+ CLzmaProb isRep[kNumStates];
2935+ CLzmaProb isRepG0[kNumStates];
2936+ CLzmaProb isRepG1[kNumStates];
2937+ CLzmaProb isRepG2[kNumStates];
2938+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
2939+
2940+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
2941+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
2942+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
2943+
2944+ CLenPriceEnc lenEnc;
2945+ CLenPriceEnc repLenEnc;
2946+
2947+ UInt32 reps[LZMA_NUM_REPS];
2948+ UInt32 state;
2949+} CSaveState;
2950+
2951+typedef struct _CLzmaEnc
2952+{
2953+ IMatchFinder matchFinder;
2954+ void *matchFinderObj;
2955+
2956+ #ifdef COMPRESS_MF_MT
2957+ Bool mtMode;
2958+ CMatchFinderMt matchFinderMt;
2959+ #endif
2960+
2961+ CMatchFinder matchFinderBase;
2962+
2963+ #ifdef COMPRESS_MF_MT
2964+ Byte pad[128];
2965+ #endif
2966+
2967+ UInt32 optimumEndIndex;
2968+ UInt32 optimumCurrentIndex;
2969+
2970+ Bool longestMatchWasFound;
2971+ UInt32 longestMatchLength;
2972+ UInt32 numDistancePairs;
2973+
2974+ COptimal opt[kNumOpts];
2975+
2976+ #ifndef LZMA_LOG_BSR
2977+ Byte g_FastPos[1 << kNumLogBits];
2978+ #endif
2979+
2980+ UInt32 ProbPrices[kBitModelTotal >> kNumMoveReducingBits];
2981+ UInt32 matchDistances[LZMA_MATCH_LEN_MAX * 2 + 2 + 1];
2982+ UInt32 numFastBytes;
2983+ UInt32 additionalOffset;
2984+ UInt32 reps[LZMA_NUM_REPS];
2985+ UInt32 state;
2986+
2987+ UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax];
2988+ UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances];
2989+ UInt32 alignPrices[kAlignTableSize];
2990+ UInt32 alignPriceCount;
2991+
2992+ UInt32 distTableSize;
2993+
2994+ unsigned lc, lp, pb;
2995+ unsigned lpMask, pbMask;
2996+
2997+ CLzmaProb *litProbs;
2998+
2999+ CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX];
3000+ CLzmaProb isRep[kNumStates];
3001+ CLzmaProb isRepG0[kNumStates];
3002+ CLzmaProb isRepG1[kNumStates];
3003+ CLzmaProb isRepG2[kNumStates];
3004+ CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX];
3005+
3006+ CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits];
3007+ CLzmaProb posEncoders[kNumFullDistances - kEndPosModelIndex];
3008+ CLzmaProb posAlignEncoder[1 << kNumAlignBits];
3009+
3010+ CLenPriceEnc lenEnc;
3011+ CLenPriceEnc repLenEnc;
3012+
3013+ unsigned lclp;
3014+
3015+ Bool fastMode;
3016+
3017+ CRangeEnc rc;
3018+
3019+ Bool writeEndMark;
3020+ UInt64 nowPos64;
3021+ UInt32 matchPriceCount;
3022+ Bool finished;
3023+ Bool multiThread;
3024+
3025+ SRes result;
3026+ UInt32 dictSize;
3027+ UInt32 matchFinderCycles;
3028+
3029+ ISeqInStream *inStream;
3030+ CSeqInStreamBuf seqBufInStream;
3031+
3032+ CSaveState saveState;
3033+} CLzmaEnc;
3034+
3035+static void LzmaEnc_SaveState(CLzmaEncHandle pp)
3036+{
3037+ CLzmaEnc *p = (CLzmaEnc *)pp;
3038+ CSaveState *dest = &p->saveState;
3039+ int i;
3040+ dest->lenEnc = p->lenEnc;
3041+ dest->repLenEnc = p->repLenEnc;
3042+ dest->state = p->state;
3043+
3044+ for (i = 0; i < kNumStates; i++)
3045+ {
3046+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
3047+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
3048+ }
3049+ for (i = 0; i < kNumLenToPosStates; i++)
3050+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
3051+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
3052+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
3053+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
3054+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
3055+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
3056+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
3057+ memcpy(dest->reps, p->reps, sizeof(p->reps));
3058+ memcpy(dest->litProbs, p->litProbs, (0x300 << p->lclp) * sizeof(CLzmaProb));
3059+}
3060+
3061+static void LzmaEnc_RestoreState(CLzmaEncHandle pp)
3062+{
3063+ CLzmaEnc *dest = (CLzmaEnc *)pp;
3064+ const CSaveState *p = &dest->saveState;
3065+ int i;
3066+ dest->lenEnc = p->lenEnc;
3067+ dest->repLenEnc = p->repLenEnc;
3068+ dest->state = p->state;
3069+
3070+ for (i = 0; i < kNumStates; i++)
3071+ {
3072+ memcpy(dest->isMatch[i], p->isMatch[i], sizeof(p->isMatch[i]));
3073+ memcpy(dest->isRep0Long[i], p->isRep0Long[i], sizeof(p->isRep0Long[i]));
3074+ }
3075+ for (i = 0; i < kNumLenToPosStates; i++)
3076+ memcpy(dest->posSlotEncoder[i], p->posSlotEncoder[i], sizeof(p->posSlotEncoder[i]));
3077+ memcpy(dest->isRep, p->isRep, sizeof(p->isRep));
3078+ memcpy(dest->isRepG0, p->isRepG0, sizeof(p->isRepG0));
3079+ memcpy(dest->isRepG1, p->isRepG1, sizeof(p->isRepG1));
3080+ memcpy(dest->isRepG2, p->isRepG2, sizeof(p->isRepG2));
3081+ memcpy(dest->posEncoders, p->posEncoders, sizeof(p->posEncoders));
3082+ memcpy(dest->posAlignEncoder, p->posAlignEncoder, sizeof(p->posAlignEncoder));
3083+ memcpy(dest->reps, p->reps, sizeof(p->reps));
3084+ memcpy(dest->litProbs, p->litProbs, (0x300 << dest->lclp) * sizeof(CLzmaProb));
3085+}
3086+
3087+SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2)
3088+{
3089+ CLzmaEnc *p = (CLzmaEnc *)pp;
3090+ CLzmaEncProps props = *props2;
3091+ LzmaEncProps_Normalize(&props);
3092+
3093+ if (props.lc > LZMA_LC_MAX || props.lp > LZMA_LP_MAX || props.pb > LZMA_PB_MAX ||
3094+ props.dictSize > (1 << kDicLogSizeMaxCompress) || props.dictSize > (1 << 30))
3095+ return SZ_ERROR_PARAM;
3096+ p->dictSize = props.dictSize;
3097+ p->matchFinderCycles = props.mc;
3098+ {
3099+ unsigned fb = props.fb;
3100+ if (fb < 5)
3101+ fb = 5;
3102+ if (fb > LZMA_MATCH_LEN_MAX)
3103+ fb = LZMA_MATCH_LEN_MAX;
3104+ p->numFastBytes = fb;
3105+ }
3106+ p->lc = props.lc;
3107+ p->lp = props.lp;
3108+ p->pb = props.pb;
3109+ p->fastMode = (props.algo == 0);
3110+ p->matchFinderBase.btMode = props.btMode;
3111+ {
3112+ UInt32 numHashBytes = 4;
3113+ if (props.btMode)
3114+ {
3115+ if (props.numHashBytes < 2)
3116+ numHashBytes = 2;
3117+ else if (props.numHashBytes < 4)
3118+ numHashBytes = props.numHashBytes;
3119+ }
3120+ p->matchFinderBase.numHashBytes = numHashBytes;
3121+ }
3122+
3123+ p->matchFinderBase.cutValue = props.mc;
3124+
3125+ p->writeEndMark = props.writeEndMark;
3126+
3127+ #ifdef COMPRESS_MF_MT
3128+ /*
3129+ if (newMultiThread != _multiThread)
3130+ {
3131+ ReleaseMatchFinder();
3132+ _multiThread = newMultiThread;
3133+ }
3134+ */
3135+ p->multiThread = (props.numThreads > 1);
3136+ #endif
3137+
3138+ return SZ_OK;
3139+}
3140+
3141+static const int kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
3142+static const int kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
3143+static const int kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
3144+static const int kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
3145+
3146+/*
3147+ void UpdateChar() { Index = kLiteralNextStates[Index]; }
3148+ void UpdateMatch() { Index = kMatchNextStates[Index]; }
3149+ void UpdateRep() { Index = kRepNextStates[Index]; }
3150+ void UpdateShortRep() { Index = kShortRepNextStates[Index]; }
3151+*/
3152+
3153+#define IsCharState(s) ((s) < 7)
3154+
3155+
3156+#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1)
3157+
3158+#define kInfinityPrice (1 << 30)
3159+
3160+static void RangeEnc_Construct(CRangeEnc *p)
3161+{
3162+ p->outStream = 0;
3163+ p->bufBase = 0;
3164+}
3165+
3166+#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize)
3167+
3168+#define RC_BUF_SIZE (1 << 16)
3169+static int RangeEnc_Alloc(CRangeEnc *p, ISzAlloc *alloc)
3170+{
3171+ if (p->bufBase == 0)
3172+ {
3173+ p->bufBase = (Byte *)alloc->Alloc(alloc, RC_BUF_SIZE);
3174+ if (p->bufBase == 0)
3175+ return 0;
3176+ p->bufLim = p->bufBase + RC_BUF_SIZE;
3177+ }
3178+ return 1;
3179+}
3180+
3181+static void RangeEnc_Free(CRangeEnc *p, ISzAlloc *alloc)
3182+{
3183+ alloc->Free(alloc, p->bufBase);
3184+ p->bufBase = 0;
3185+}
3186+
3187+static void RangeEnc_Init(CRangeEnc *p)
3188+{
3189+ /* Stream.Init(); */
3190+ p->low = 0;
3191+ p->range = 0xFFFFFFFF;
3192+ p->cacheSize = 1;
3193+ p->cache = 0;
3194+
3195+ p->buf = p->bufBase;
3196+
3197+ p->processed = 0;
3198+ p->res = SZ_OK;
3199+}
3200+
3201+static void RangeEnc_FlushStream(CRangeEnc *p)
3202+{
3203+ size_t num;
3204+ if (p->res != SZ_OK)
3205+ return;
3206+ num = p->buf - p->bufBase;
3207+ if (num != p->outStream->Write(p->outStream, p->bufBase, num))
3208+ p->res = SZ_ERROR_WRITE;
3209+ p->processed += num;
3210+ p->buf = p->bufBase;
3211+}
3212+
3213+static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p)
3214+{
3215+ if ((UInt32)p->low < (UInt32)0xFF000000 || (int)(p->low >> 32) != 0)
3216+ {
3217+ Byte temp = p->cache;
3218+ do
3219+ {
3220+ Byte *buf = p->buf;
3221+ *buf++ = (Byte)(temp + (Byte)(p->low >> 32));
3222+ p->buf = buf;
3223+ if (buf == p->bufLim)
3224+ RangeEnc_FlushStream(p);
3225+ temp = 0xFF;
3226+ }
3227+ while (--p->cacheSize != 0);
3228+ p->cache = (Byte)((UInt32)p->low >> 24);
3229+ }
3230+ p->cacheSize++;
3231+ p->low = (UInt32)p->low << 8;
3232+}
3233+
3234+static void RangeEnc_FlushData(CRangeEnc *p)
3235+{
3236+ int i;
3237+ for (i = 0; i < 5; i++)
3238+ RangeEnc_ShiftLow(p);
3239+}
3240+
3241+static void RangeEnc_EncodeDirectBits(CRangeEnc *p, UInt32 value, int numBits)
3242+{
3243+ do
3244+ {
3245+ p->range >>= 1;
3246+ p->low += p->range & (0 - ((value >> --numBits) & 1));
3247+ if (p->range < kTopValue)
3248+ {
3249+ p->range <<= 8;
3250+ RangeEnc_ShiftLow(p);
3251+ }
3252+ }
3253+ while (numBits != 0);
3254+}
3255+
3256+static void RangeEnc_EncodeBit(CRangeEnc *p, CLzmaProb *prob, UInt32 symbol)
3257+{
3258+ UInt32 ttt = *prob;
3259+ UInt32 newBound = (p->range >> kNumBitModelTotalBits) * ttt;
3260+ if (symbol == 0)
3261+ {
3262+ p->range = newBound;
3263+ ttt += (kBitModelTotal - ttt) >> kNumMoveBits;
3264+ }
3265+ else
3266+ {
3267+ p->low += newBound;
3268+ p->range -= newBound;
3269+ ttt -= ttt >> kNumMoveBits;
3270+ }
3271+ *prob = (CLzmaProb)ttt;
3272+ if (p->range < kTopValue)
3273+ {
3274+ p->range <<= 8;
3275+ RangeEnc_ShiftLow(p);
3276+ }
3277+}
3278+
3279+static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol)
3280+{
3281+ symbol |= 0x100;
3282+ do
3283+ {
3284+ RangeEnc_EncodeBit(p, probs + (symbol >> 8), (symbol >> 7) & 1);
3285+ symbol <<= 1;
3286+ }
3287+ while (symbol < 0x10000);
3288+}
3289+
3290+static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 symbol, UInt32 matchByte)
3291+{
3292+ UInt32 offs = 0x100;
3293+ symbol |= 0x100;
3294+ do
3295+ {
3296+ matchByte <<= 1;
3297+ RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (symbol >> 8)), (symbol >> 7) & 1);
3298+ symbol <<= 1;
3299+ offs &= ~(matchByte ^ symbol);
3300+ }
3301+ while (symbol < 0x10000);
3302+}
3303+
3304+static void LzmaEnc_InitPriceTables(UInt32 *ProbPrices)
3305+{
3306+ UInt32 i;
3307+ for (i = (1 << kNumMoveReducingBits) / 2; i < kBitModelTotal; i += (1 << kNumMoveReducingBits))
3308+ {
3309+ const int kCyclesBits = kNumBitPriceShiftBits;
3310+ UInt32 w = i;
3311+ UInt32 bitCount = 0;
3312+ int j;
3313+ for (j = 0; j < kCyclesBits; j++)
3314+ {
3315+ w = w * w;
3316+ bitCount <<= 1;
3317+ while (w >= ((UInt32)1 << 16))
3318+ {
3319+ w >>= 1;
3320+ bitCount++;
3321+ }
3322+ }
3323+ ProbPrices[i >> kNumMoveReducingBits] = ((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount);
3324+ }
3325+}
3326+
3327+
3328+#define GET_PRICE(prob, symbol) \
3329+ p->ProbPrices[((prob) ^ (((-(int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
3330+
3331+#define GET_PRICEa(prob, symbol) \
3332+ ProbPrices[((prob) ^ ((-((int)(symbol))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits];
3333+
3334+#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits]
3335+#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
3336+
3337+#define GET_PRICE_0a(prob) ProbPrices[(prob) >> kNumMoveReducingBits]
3338+#define GET_PRICE_1a(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits]
3339+
3340+static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 symbol, UInt32 *ProbPrices)
3341+{
3342+ UInt32 price = 0;
3343+ symbol |= 0x100;
3344+ do
3345+ {
3346+ price += GET_PRICEa(probs[symbol >> 8], (symbol >> 7) & 1);
3347+ symbol <<= 1;
3348+ }
3349+ while (symbol < 0x10000);
3350+ return price;
3351+};
3352+
3353+static UInt32 LitEnc_GetPriceMatched(const CLzmaProb *probs, UInt32 symbol, UInt32 matchByte, UInt32 *ProbPrices)
3354+{
3355+ UInt32 price = 0;
3356+ UInt32 offs = 0x100;
3357+ symbol |= 0x100;
3358+ do
3359+ {
3360+ matchByte <<= 1;
3361+ price += GET_PRICEa(probs[offs + (matchByte & offs) + (symbol >> 8)], (symbol >> 7) & 1);
3362+ symbol <<= 1;
3363+ offs &= ~(matchByte ^ symbol);
3364+ }
3365+ while (symbol < 0x10000);
3366+ return price;
3367+};
3368+
3369+
3370+static void RcTree_Encode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
3371+{
3372+ UInt32 m = 1;
3373+ int i;
3374+ for (i = numBitLevels; i != 0 ;)
3375+ {
3376+ UInt32 bit;
3377+ i--;
3378+ bit = (symbol >> i) & 1;
3379+ RangeEnc_EncodeBit(rc, probs + m, bit);
3380+ m = (m << 1) | bit;
3381+ }
3382+};
3383+
3384+static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, int numBitLevels, UInt32 symbol)
3385+{
3386+ UInt32 m = 1;
3387+ int i;
3388+ for (i = 0; i < numBitLevels; i++)
3389+ {
3390+ UInt32 bit = symbol & 1;
3391+ RangeEnc_EncodeBit(rc, probs + m, bit);
3392+ m = (m << 1) | bit;
3393+ symbol >>= 1;
3394+ }
3395+}
3396+
3397+static UInt32 RcTree_GetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
3398+{
3399+ UInt32 price = 0;
3400+ symbol |= (1 << numBitLevels);
3401+ while (symbol != 1)
3402+ {
3403+ price += GET_PRICEa(probs[symbol >> 1], symbol & 1);
3404+ symbol >>= 1;
3405+ }
3406+ return price;
3407+}
3408+
3409+static UInt32 RcTree_ReverseGetPrice(const CLzmaProb *probs, int numBitLevels, UInt32 symbol, UInt32 *ProbPrices)
3410+{
3411+ UInt32 price = 0;
3412+ UInt32 m = 1;
3413+ int i;
3414+ for (i = numBitLevels; i != 0; i--)
3415+ {
3416+ UInt32 bit = symbol & 1;
3417+ symbol >>= 1;
3418+ price += GET_PRICEa(probs[m], bit);
3419+ m = (m << 1) | bit;
3420+ }
3421+ return price;
3422+}
3423+
3424+
3425+static void LenEnc_Init(CLenEnc *p)
3426+{
3427+ unsigned i;
3428+ p->choice = p->choice2 = kProbInitValue;
3429+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumLowBits); i++)
3430+ p->low[i] = kProbInitValue;
3431+ for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << kLenNumMidBits); i++)
3432+ p->mid[i] = kProbInitValue;
3433+ for (i = 0; i < kLenNumHighSymbols; i++)
3434+ p->high[i] = kProbInitValue;
3435+}
3436+
3437+static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState)
3438+{
3439+ if (symbol < kLenNumLowSymbols)
3440+ {
3441+ RangeEnc_EncodeBit(rc, &p->choice, 0);
3442+ RcTree_Encode(rc, p->low + (posState << kLenNumLowBits), kLenNumLowBits, symbol);
3443+ }
3444+ else
3445+ {
3446+ RangeEnc_EncodeBit(rc, &p->choice, 1);
3447+ if (symbol < kLenNumLowSymbols + kLenNumMidSymbols)
3448+ {
3449+ RangeEnc_EncodeBit(rc, &p->choice2, 0);
3450+ RcTree_Encode(rc, p->mid + (posState << kLenNumMidBits), kLenNumMidBits, symbol - kLenNumLowSymbols);
3451+ }
3452+ else
3453+ {
3454+ RangeEnc_EncodeBit(rc, &p->choice2, 1);
3455+ RcTree_Encode(rc, p->high, kLenNumHighBits, symbol - kLenNumLowSymbols - kLenNumMidSymbols);
3456+ }
3457+ }
3458+}
3459+
3460+static void LenEnc_SetPrices(CLenEnc *p, UInt32 posState, UInt32 numSymbols, UInt32 *prices, UInt32 *ProbPrices)
3461+{
3462+ UInt32 a0 = GET_PRICE_0a(p->choice);
3463+ UInt32 a1 = GET_PRICE_1a(p->choice);
3464+ UInt32 b0 = a1 + GET_PRICE_0a(p->choice2);
3465+ UInt32 b1 = a1 + GET_PRICE_1a(p->choice2);
3466+ UInt32 i = 0;
3467+ for (i = 0; i < kLenNumLowSymbols; i++)
3468+ {
3469+ if (i >= numSymbols)
3470+ return;
3471+ prices[i] = a0 + RcTree_GetPrice(p->low + (posState << kLenNumLowBits), kLenNumLowBits, i, ProbPrices);
3472+ }
3473+ for (; i < kLenNumLowSymbols + kLenNumMidSymbols; i++)
3474+ {
3475+ if (i >= numSymbols)
3476+ return;
3477+ prices[i] = b0 + RcTree_GetPrice(p->mid + (posState << kLenNumMidBits), kLenNumMidBits, i - kLenNumLowSymbols, ProbPrices);
3478+ }
3479+ for (; i < numSymbols; i++)
3480+ prices[i] = b1 + RcTree_GetPrice(p->high, kLenNumHighBits, i - kLenNumLowSymbols - kLenNumMidSymbols, ProbPrices);
3481+}
3482+
3483+static void MY_FAST_CALL LenPriceEnc_UpdateTable(CLenPriceEnc *p, UInt32 posState, UInt32 *ProbPrices)
3484+{
3485+ LenEnc_SetPrices(&p->p, posState, p->tableSize, p->prices[posState], ProbPrices);
3486+ p->counters[posState] = p->tableSize;
3487+}
3488+
3489+static void LenPriceEnc_UpdateTables(CLenPriceEnc *p, UInt32 numPosStates, UInt32 *ProbPrices)
3490+{
3491+ UInt32 posState;
3492+ for (posState = 0; posState < numPosStates; posState++)
3493+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
3494+}
3495+
3496+static void LenEnc_Encode2(CLenPriceEnc *p, CRangeEnc *rc, UInt32 symbol, UInt32 posState, Bool updatePrice, UInt32 *ProbPrices)
3497+{
3498+ LenEnc_Encode(&p->p, rc, symbol, posState);
3499+ if (updatePrice)
3500+ if (--p->counters[posState] == 0)
3501+ LenPriceEnc_UpdateTable(p, posState, ProbPrices);
3502+}
3503+
3504+
3505+
3506+
3507+static void MovePos(CLzmaEnc *p, UInt32 num)
3508+{
3509+ #ifdef SHOW_STAT
3510+ ttt += num;
3511+ printf("\n MovePos %d", num);
3512+ #endif
3513+ if (num != 0)
3514+ {
3515+ p->additionalOffset += num;
3516+ p->matchFinder.Skip(p->matchFinderObj, num);
3517+ }
3518+}
3519+
3520+static UInt32 ReadMatchDistances(CLzmaEnc *p, UInt32 *numDistancePairsRes)
3521+{
3522+ UInt32 lenRes = 0, numDistancePairs;
3523+ numDistancePairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matchDistances);
3524+ #ifdef SHOW_STAT
3525+ printf("\n i = %d numPairs = %d ", ttt, numDistancePairs / 2);
3526+ if (ttt >= 61994)
3527+ ttt = ttt;
3528+
3529+ ttt++;
3530+ {
3531+ UInt32 i;
3532+ for (i = 0; i < numDistancePairs; i += 2)
3533+ printf("%2d %6d | ", p->matchDistances[i], p->matchDistances[i + 1]);
3534+ }
3535+ #endif
3536+ if (numDistancePairs > 0)
3537+ {
3538+ lenRes = p->matchDistances[numDistancePairs - 2];
3539+ if (lenRes == p->numFastBytes)
3540+ {
3541+ UInt32 numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) + 1;
3542+ const Byte *pby = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
3543+ UInt32 distance = p->matchDistances[numDistancePairs - 1] + 1;
3544+ if (numAvail > LZMA_MATCH_LEN_MAX)
3545+ numAvail = LZMA_MATCH_LEN_MAX;
3546+
3547+ {
3548+ const Byte *pby2 = pby - distance;
3549+ for (; lenRes < numAvail && pby[lenRes] == pby2[lenRes]; lenRes++);
3550+ }
3551+ }
3552+ }
3553+ p->additionalOffset++;
3554+ *numDistancePairsRes = numDistancePairs;
3555+ return lenRes;
3556+}
3557+
3558+
3559+#define MakeAsChar(p) (p)->backPrev = (UInt32)(-1); (p)->prev1IsChar = False;
3560+#define MakeAsShortRep(p) (p)->backPrev = 0; (p)->prev1IsChar = False;
3561+#define IsShortRep(p) ((p)->backPrev == 0)
3562+
3563+static UInt32 GetRepLen1Price(CLzmaEnc *p, UInt32 state, UInt32 posState)
3564+{
3565+ return
3566+ GET_PRICE_0(p->isRepG0[state]) +
3567+ GET_PRICE_0(p->isRep0Long[state][posState]);
3568+}
3569+
3570+static UInt32 GetPureRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 state, UInt32 posState)
3571+{
3572+ UInt32 price;
3573+ if (repIndex == 0)
3574+ {
3575+ price = GET_PRICE_0(p->isRepG0[state]);
3576+ price += GET_PRICE_1(p->isRep0Long[state][posState]);
3577+ }
3578+ else
3579+ {
3580+ price = GET_PRICE_1(p->isRepG0[state]);
3581+ if (repIndex == 1)
3582+ price += GET_PRICE_0(p->isRepG1[state]);
3583+ else
3584+ {
3585+ price += GET_PRICE_1(p->isRepG1[state]);
3586+ price += GET_PRICE(p->isRepG2[state], repIndex - 2);
3587+ }
3588+ }
3589+ return price;
3590+}
3591+
3592+static UInt32 GetRepPrice(CLzmaEnc *p, UInt32 repIndex, UInt32 len, UInt32 state, UInt32 posState)
3593+{
3594+ return p->repLenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN] +
3595+ GetPureRepPrice(p, repIndex, state, posState);
3596+}
3597+
3598+static UInt32 Backward(CLzmaEnc *p, UInt32 *backRes, UInt32 cur)
3599+{
3600+ UInt32 posMem = p->opt[cur].posPrev;
3601+ UInt32 backMem = p->opt[cur].backPrev;
3602+ p->optimumEndIndex = cur;
3603+ do
3604+ {
3605+ if (p->opt[cur].prev1IsChar)
3606+ {
3607+ MakeAsChar(&p->opt[posMem])
3608+ p->opt[posMem].posPrev = posMem - 1;
3609+ if (p->opt[cur].prev2)
3610+ {
3611+ p->opt[posMem - 1].prev1IsChar = False;
3612+ p->opt[posMem - 1].posPrev = p->opt[cur].posPrev2;
3613+ p->opt[posMem - 1].backPrev = p->opt[cur].backPrev2;
3614+ }
3615+ }
3616+ {
3617+ UInt32 posPrev = posMem;
3618+ UInt32 backCur = backMem;
3619+
3620+ backMem = p->opt[posPrev].backPrev;
3621+ posMem = p->opt[posPrev].posPrev;
3622+
3623+ p->opt[posPrev].backPrev = backCur;
3624+ p->opt[posPrev].posPrev = cur;
3625+ cur = posPrev;
3626+ }
3627+ }
3628+ while (cur != 0);
3629+ *backRes = p->opt[0].backPrev;
3630+ p->optimumCurrentIndex = p->opt[0].posPrev;
3631+ return p->optimumCurrentIndex;
3632+}
3633+
3634+#define LIT_PROBS(pos, prevByte) (p->litProbs + ((((pos) & p->lpMask) << p->lc) + ((prevByte) >> (8 - p->lc))) * 0x300)
3635+
3636+static UInt32 GetOptimum(CLzmaEnc *p, UInt32 position, UInt32 *backRes)
3637+{
3638+ UInt32 numAvailableBytes, lenMain, numDistancePairs;
3639+ const Byte *data;
3640+ UInt32 reps[LZMA_NUM_REPS];
3641+ UInt32 repLens[LZMA_NUM_REPS];
3642+ UInt32 repMaxIndex, i;
3643+ UInt32 *matchDistances;
3644+ Byte currentByte, matchByte;
3645+ UInt32 posState;
3646+ UInt32 matchPrice, repMatchPrice;
3647+ UInt32 lenEnd;
3648+ UInt32 len;
3649+ UInt32 normalMatchPrice;
3650+ UInt32 cur;
3651+ if (p->optimumEndIndex != p->optimumCurrentIndex)
3652+ {
3653+ const COptimal *opt = &p->opt[p->optimumCurrentIndex];
3654+ UInt32 lenRes = opt->posPrev - p->optimumCurrentIndex;
3655+ *backRes = opt->backPrev;
3656+ p->optimumCurrentIndex = opt->posPrev;
3657+ return lenRes;
3658+ }
3659+ p->optimumCurrentIndex = p->optimumEndIndex = 0;
3660+
3661+ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
3662+
3663+ if (!p->longestMatchWasFound)
3664+ {
3665+ lenMain = ReadMatchDistances(p, &numDistancePairs);
3666+ }
3667+ else
3668+ {
3669+ lenMain = p->longestMatchLength;
3670+ numDistancePairs = p->numDistancePairs;
3671+ p->longestMatchWasFound = False;
3672+ }
3673+
3674+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
3675+ if (numAvailableBytes < 2)
3676+ {
3677+ *backRes = (UInt32)(-1);
3678+ return 1;
3679+ }
3680+ if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
3681+ numAvailableBytes = LZMA_MATCH_LEN_MAX;
3682+
3683+ repMaxIndex = 0;
3684+ for (i = 0; i < LZMA_NUM_REPS; i++)
3685+ {
3686+ UInt32 lenTest;
3687+ const Byte *data2;
3688+ reps[i] = p->reps[i];
3689+ data2 = data - (reps[i] + 1);
3690+ if (data[0] != data2[0] || data[1] != data2[1])
3691+ {
3692+ repLens[i] = 0;
3693+ continue;
3694+ }
3695+ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
3696+ repLens[i] = lenTest;
3697+ if (lenTest > repLens[repMaxIndex])
3698+ repMaxIndex = i;
3699+ }
3700+ if (repLens[repMaxIndex] >= p->numFastBytes)
3701+ {
3702+ UInt32 lenRes;
3703+ *backRes = repMaxIndex;
3704+ lenRes = repLens[repMaxIndex];
3705+ MovePos(p, lenRes - 1);
3706+ return lenRes;
3707+ }
3708+
3709+ matchDistances = p->matchDistances;
3710+ if (lenMain >= p->numFastBytes)
3711+ {
3712+ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
3713+ MovePos(p, lenMain - 1);
3714+ return lenMain;
3715+ }
3716+ currentByte = *data;
3717+ matchByte = *(data - (reps[0] + 1));
3718+
3719+ if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2)
3720+ {
3721+ *backRes = (UInt32)-1;
3722+ return 1;
3723+ }
3724+
3725+ p->opt[0].state = (CState)p->state;
3726+
3727+ posState = (position & p->pbMask);
3728+
3729+ {
3730+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
3731+ p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) +
3732+ (!IsCharState(p->state) ?
3733+ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
3734+ LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
3735+ }
3736+
3737+ MakeAsChar(&p->opt[1]);
3738+
3739+ matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]);
3740+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]);
3741+
3742+ if (matchByte == currentByte)
3743+ {
3744+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, p->state, posState);
3745+ if (shortRepPrice < p->opt[1].price)
3746+ {
3747+ p->opt[1].price = shortRepPrice;
3748+ MakeAsShortRep(&p->opt[1]);
3749+ }
3750+ }
3751+ lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]);
3752+
3753+ if (lenEnd < 2)
3754+ {
3755+ *backRes = p->opt[1].backPrev;
3756+ return 1;
3757+ }
3758+
3759+ p->opt[1].posPrev = 0;
3760+ for (i = 0; i < LZMA_NUM_REPS; i++)
3761+ p->opt[0].backs[i] = reps[i];
3762+
3763+ len = lenEnd;
3764+ do
3765+ p->opt[len--].price = kInfinityPrice;
3766+ while (len >= 2);
3767+
3768+ for (i = 0; i < LZMA_NUM_REPS; i++)
3769+ {
3770+ UInt32 repLen = repLens[i];
3771+ UInt32 price;
3772+ if (repLen < 2)
3773+ continue;
3774+ price = repMatchPrice + GetPureRepPrice(p, i, p->state, posState);
3775+ do
3776+ {
3777+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][repLen - 2];
3778+ COptimal *opt = &p->opt[repLen];
3779+ if (curAndLenPrice < opt->price)
3780+ {
3781+ opt->price = curAndLenPrice;
3782+ opt->posPrev = 0;
3783+ opt->backPrev = i;
3784+ opt->prev1IsChar = False;
3785+ }
3786+ }
3787+ while (--repLen >= 2);
3788+ }
3789+
3790+ normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]);
3791+
3792+ len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2);
3793+ if (len <= lenMain)
3794+ {
3795+ UInt32 offs = 0;
3796+ while (len > matchDistances[offs])
3797+ offs += 2;
3798+ for (; ; len++)
3799+ {
3800+ COptimal *opt;
3801+ UInt32 distance = matchDistances[offs + 1];
3802+
3803+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][len - LZMA_MATCH_LEN_MIN];
3804+ UInt32 lenToPosState = GetLenToPosState(len);
3805+ if (distance < kNumFullDistances)
3806+ curAndLenPrice += p->distancesPrices[lenToPosState][distance];
3807+ else
3808+ {
3809+ UInt32 slot;
3810+ GetPosSlot2(distance, slot);
3811+ curAndLenPrice += p->alignPrices[distance & kAlignMask] + p->posSlotPrices[lenToPosState][slot];
3812+ }
3813+ opt = &p->opt[len];
3814+ if (curAndLenPrice < opt->price)
3815+ {
3816+ opt->price = curAndLenPrice;
3817+ opt->posPrev = 0;
3818+ opt->backPrev = distance + LZMA_NUM_REPS;
3819+ opt->prev1IsChar = False;
3820+ }
3821+ if (len == matchDistances[offs])
3822+ {
3823+ offs += 2;
3824+ if (offs == numDistancePairs)
3825+ break;
3826+ }
3827+ }
3828+ }
3829+
3830+ cur = 0;
3831+
3832+ #ifdef SHOW_STAT2
3833+ if (position >= 0)
3834+ {
3835+ unsigned i;
3836+ printf("\n pos = %4X", position);
3837+ for (i = cur; i <= lenEnd; i++)
3838+ printf("\nprice[%4X] = %d", position - cur + i, p->opt[i].price);
3839+ }
3840+ #endif
3841+
3842+ for (;;)
3843+ {
3844+ UInt32 numAvailableBytesFull, newLen, numDistancePairs;
3845+ COptimal *curOpt;
3846+ UInt32 posPrev;
3847+ UInt32 state;
3848+ UInt32 curPrice;
3849+ Bool nextIsChar;
3850+ const Byte *data;
3851+ Byte currentByte, matchByte;
3852+ UInt32 posState;
3853+ UInt32 curAnd1Price;
3854+ COptimal *nextOpt;
3855+ UInt32 matchPrice, repMatchPrice;
3856+ UInt32 numAvailableBytes;
3857+ UInt32 startLen;
3858+
3859+ cur++;
3860+ if (cur == lenEnd)
3861+ return Backward(p, backRes, cur);
3862+
3863+ numAvailableBytesFull = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
3864+ newLen = ReadMatchDistances(p, &numDistancePairs);
3865+ if (newLen >= p->numFastBytes)
3866+ {
3867+ p->numDistancePairs = numDistancePairs;
3868+ p->longestMatchLength = newLen;
3869+ p->longestMatchWasFound = True;
3870+ return Backward(p, backRes, cur);
3871+ }
3872+ position++;
3873+ curOpt = &p->opt[cur];
3874+ posPrev = curOpt->posPrev;
3875+ if (curOpt->prev1IsChar)
3876+ {
3877+ posPrev--;
3878+ if (curOpt->prev2)
3879+ {
3880+ state = p->opt[curOpt->posPrev2].state;
3881+ if (curOpt->backPrev2 < LZMA_NUM_REPS)
3882+ state = kRepNextStates[state];
3883+ else
3884+ state = kMatchNextStates[state];
3885+ }
3886+ else
3887+ state = p->opt[posPrev].state;
3888+ state = kLiteralNextStates[state];
3889+ }
3890+ else
3891+ state = p->opt[posPrev].state;
3892+ if (posPrev == cur - 1)
3893+ {
3894+ if (IsShortRep(curOpt))
3895+ state = kShortRepNextStates[state];
3896+ else
3897+ state = kLiteralNextStates[state];
3898+ }
3899+ else
3900+ {
3901+ UInt32 pos;
3902+ const COptimal *prevOpt;
3903+ if (curOpt->prev1IsChar && curOpt->prev2)
3904+ {
3905+ posPrev = curOpt->posPrev2;
3906+ pos = curOpt->backPrev2;
3907+ state = kRepNextStates[state];
3908+ }
3909+ else
3910+ {
3911+ pos = curOpt->backPrev;
3912+ if (pos < LZMA_NUM_REPS)
3913+ state = kRepNextStates[state];
3914+ else
3915+ state = kMatchNextStates[state];
3916+ }
3917+ prevOpt = &p->opt[posPrev];
3918+ if (pos < LZMA_NUM_REPS)
3919+ {
3920+ UInt32 i;
3921+ reps[0] = prevOpt->backs[pos];
3922+ for (i = 1; i <= pos; i++)
3923+ reps[i] = prevOpt->backs[i - 1];
3924+ for (; i < LZMA_NUM_REPS; i++)
3925+ reps[i] = prevOpt->backs[i];
3926+ }
3927+ else
3928+ {
3929+ UInt32 i;
3930+ reps[0] = (pos - LZMA_NUM_REPS);
3931+ for (i = 1; i < LZMA_NUM_REPS; i++)
3932+ reps[i] = prevOpt->backs[i - 1];
3933+ }
3934+ }
3935+ curOpt->state = (CState)state;
3936+
3937+ curOpt->backs[0] = reps[0];
3938+ curOpt->backs[1] = reps[1];
3939+ curOpt->backs[2] = reps[2];
3940+ curOpt->backs[3] = reps[3];
3941+
3942+ curPrice = curOpt->price;
3943+ nextIsChar = False;
3944+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
3945+ currentByte = *data;
3946+ matchByte = *(data - (reps[0] + 1));
3947+
3948+ posState = (position & p->pbMask);
3949+
3950+ curAnd1Price = curPrice + GET_PRICE_0(p->isMatch[state][posState]);
3951+ {
3952+ const CLzmaProb *probs = LIT_PROBS(position, *(data - 1));
3953+ curAnd1Price +=
3954+ (!IsCharState(state) ?
3955+ LitEnc_GetPriceMatched(probs, currentByte, matchByte, p->ProbPrices) :
3956+ LitEnc_GetPrice(probs, currentByte, p->ProbPrices));
3957+ }
3958+
3959+ nextOpt = &p->opt[cur + 1];
3960+
3961+ if (curAnd1Price < nextOpt->price)
3962+ {
3963+ nextOpt->price = curAnd1Price;
3964+ nextOpt->posPrev = cur;
3965+ MakeAsChar(nextOpt);
3966+ nextIsChar = True;
3967+ }
3968+
3969+ matchPrice = curPrice + GET_PRICE_1(p->isMatch[state][posState]);
3970+ repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]);
3971+
3972+ if (matchByte == currentByte && !(nextOpt->posPrev < cur && nextOpt->backPrev == 0))
3973+ {
3974+ UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(p, state, posState);
3975+ if (shortRepPrice <= nextOpt->price)
3976+ {
3977+ nextOpt->price = shortRepPrice;
3978+ nextOpt->posPrev = cur;
3979+ MakeAsShortRep(nextOpt);
3980+ nextIsChar = True;
3981+ }
3982+ }
3983+
3984+ {
3985+ UInt32 temp = kNumOpts - 1 - cur;
3986+ if (temp < numAvailableBytesFull)
3987+ numAvailableBytesFull = temp;
3988+ }
3989+ numAvailableBytes = numAvailableBytesFull;
3990+
3991+ if (numAvailableBytes < 2)
3992+ continue;
3993+ if (numAvailableBytes > p->numFastBytes)
3994+ numAvailableBytes = p->numFastBytes;
3995+ if (!nextIsChar && matchByte != currentByte) /* speed optimization */
3996+ {
3997+ /* try Literal + rep0 */
3998+ UInt32 temp;
3999+ UInt32 lenTest2;
4000+ const Byte *data2 = data - (reps[0] + 1);
4001+ UInt32 limit = p->numFastBytes + 1;
4002+ if (limit > numAvailableBytesFull)
4003+ limit = numAvailableBytesFull;
4004+
4005+ for (temp = 1; temp < limit && data[temp] == data2[temp]; temp++);
4006+ lenTest2 = temp - 1;
4007+ if (lenTest2 >= 2)
4008+ {
4009+ UInt32 state2 = kLiteralNextStates[state];
4010+ UInt32 posStateNext = (position + 1) & p->pbMask;
4011+ UInt32 nextRepMatchPrice = curAnd1Price +
4012+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
4013+ GET_PRICE_1(p->isRep[state2]);
4014+ /* for (; lenTest2 >= 2; lenTest2--) */
4015+ {
4016+ UInt32 curAndLenPrice;
4017+ COptimal *opt;
4018+ UInt32 offset = cur + 1 + lenTest2;
4019+ while (lenEnd < offset)
4020+ p->opt[++lenEnd].price = kInfinityPrice;
4021+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
4022+ opt = &p->opt[offset];
4023+ if (curAndLenPrice < opt->price)
4024+ {
4025+ opt->price = curAndLenPrice;
4026+ opt->posPrev = cur + 1;
4027+ opt->backPrev = 0;
4028+ opt->prev1IsChar = True;
4029+ opt->prev2 = False;
4030+ }
4031+ }
4032+ }
4033+ }
4034+
4035+ startLen = 2; /* speed optimization */
4036+ {
4037+ UInt32 repIndex;
4038+ for (repIndex = 0; repIndex < LZMA_NUM_REPS; repIndex++)
4039+ {
4040+ UInt32 lenTest;
4041+ UInt32 lenTestTemp;
4042+ UInt32 price;
4043+ const Byte *data2 = data - (reps[repIndex] + 1);
4044+ if (data[0] != data2[0] || data[1] != data2[1])
4045+ continue;
4046+ for (lenTest = 2; lenTest < numAvailableBytes && data[lenTest] == data2[lenTest]; lenTest++);
4047+ while (lenEnd < cur + lenTest)
4048+ p->opt[++lenEnd].price = kInfinityPrice;
4049+ lenTestTemp = lenTest;
4050+ price = repMatchPrice + GetPureRepPrice(p, repIndex, state, posState);
4051+ do
4052+ {
4053+ UInt32 curAndLenPrice = price + p->repLenEnc.prices[posState][lenTest - 2];
4054+ COptimal *opt = &p->opt[cur + lenTest];
4055+ if (curAndLenPrice < opt->price)
4056+ {
4057+ opt->price = curAndLenPrice;
4058+ opt->posPrev = cur;
4059+ opt->backPrev = repIndex;
4060+ opt->prev1IsChar = False;
4061+ }
4062+ }
4063+ while (--lenTest >= 2);
4064+ lenTest = lenTestTemp;
4065+
4066+ if (repIndex == 0)
4067+ startLen = lenTest + 1;
4068+
4069+ /* if (_maxMode) */
4070+ {
4071+ UInt32 lenTest2 = lenTest + 1;
4072+ UInt32 limit = lenTest2 + p->numFastBytes;
4073+ UInt32 nextRepMatchPrice;
4074+ if (limit > numAvailableBytesFull)
4075+ limit = numAvailableBytesFull;
4076+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
4077+ lenTest2 -= lenTest + 1;
4078+ if (lenTest2 >= 2)
4079+ {
4080+ UInt32 state2 = kRepNextStates[state];
4081+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
4082+ UInt32 curAndLenCharPrice =
4083+ price + p->repLenEnc.prices[posState][lenTest - 2] +
4084+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
4085+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
4086+ data[lenTest], data2[lenTest], p->ProbPrices);
4087+ state2 = kLiteralNextStates[state2];
4088+ posStateNext = (position + lenTest + 1) & p->pbMask;
4089+ nextRepMatchPrice = curAndLenCharPrice +
4090+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
4091+ GET_PRICE_1(p->isRep[state2]);
4092+
4093+ /* for (; lenTest2 >= 2; lenTest2--) */
4094+ {
4095+ UInt32 curAndLenPrice;
4096+ COptimal *opt;
4097+ UInt32 offset = cur + lenTest + 1 + lenTest2;
4098+ while (lenEnd < offset)
4099+ p->opt[++lenEnd].price = kInfinityPrice;
4100+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
4101+ opt = &p->opt[offset];
4102+ if (curAndLenPrice < opt->price)
4103+ {
4104+ opt->price = curAndLenPrice;
4105+ opt->posPrev = cur + lenTest + 1;
4106+ opt->backPrev = 0;
4107+ opt->prev1IsChar = True;
4108+ opt->prev2 = True;
4109+ opt->posPrev2 = cur;
4110+ opt->backPrev2 = repIndex;
4111+ }
4112+ }
4113+ }
4114+ }
4115+ }
4116+ }
4117+ /* for (UInt32 lenTest = 2; lenTest <= newLen; lenTest++) */
4118+ if (newLen > numAvailableBytes)
4119+ {
4120+ newLen = numAvailableBytes;
4121+ for (numDistancePairs = 0; newLen > matchDistances[numDistancePairs]; numDistancePairs += 2);
4122+ matchDistances[numDistancePairs] = newLen;
4123+ numDistancePairs += 2;
4124+ }
4125+ if (newLen >= startLen)
4126+ {
4127+ UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]);
4128+ UInt32 offs, curBack, posSlot;
4129+ UInt32 lenTest;
4130+ while (lenEnd < cur + newLen)
4131+ p->opt[++lenEnd].price = kInfinityPrice;
4132+
4133+ offs = 0;
4134+ while (startLen > matchDistances[offs])
4135+ offs += 2;
4136+ curBack = matchDistances[offs + 1];
4137+ GetPosSlot2(curBack, posSlot);
4138+ for (lenTest = /*2*/ startLen; ; lenTest++)
4139+ {
4140+ UInt32 curAndLenPrice = normalMatchPrice + p->lenEnc.prices[posState][lenTest - LZMA_MATCH_LEN_MIN];
4141+ UInt32 lenToPosState = GetLenToPosState(lenTest);
4142+ COptimal *opt;
4143+ if (curBack < kNumFullDistances)
4144+ curAndLenPrice += p->distancesPrices[lenToPosState][curBack];
4145+ else
4146+ curAndLenPrice += p->posSlotPrices[lenToPosState][posSlot] + p->alignPrices[curBack & kAlignMask];
4147+
4148+ opt = &p->opt[cur + lenTest];
4149+ if (curAndLenPrice < opt->price)
4150+ {
4151+ opt->price = curAndLenPrice;
4152+ opt->posPrev = cur;
4153+ opt->backPrev = curBack + LZMA_NUM_REPS;
4154+ opt->prev1IsChar = False;
4155+ }
4156+
4157+ if (/*_maxMode && */lenTest == matchDistances[offs])
4158+ {
4159+ /* Try Match + Literal + Rep0 */
4160+ const Byte *data2 = data - (curBack + 1);
4161+ UInt32 lenTest2 = lenTest + 1;
4162+ UInt32 limit = lenTest2 + p->numFastBytes;
4163+ UInt32 nextRepMatchPrice;
4164+ if (limit > numAvailableBytesFull)
4165+ limit = numAvailableBytesFull;
4166+ for (; lenTest2 < limit && data[lenTest2] == data2[lenTest2]; lenTest2++);
4167+ lenTest2 -= lenTest + 1;
4168+ if (lenTest2 >= 2)
4169+ {
4170+ UInt32 state2 = kMatchNextStates[state];
4171+ UInt32 posStateNext = (position + lenTest) & p->pbMask;
4172+ UInt32 curAndLenCharPrice = curAndLenPrice +
4173+ GET_PRICE_0(p->isMatch[state2][posStateNext]) +
4174+ LitEnc_GetPriceMatched(LIT_PROBS(position + lenTest, data[lenTest - 1]),
4175+ data[lenTest], data2[lenTest], p->ProbPrices);
4176+ state2 = kLiteralNextStates[state2];
4177+ posStateNext = (posStateNext + 1) & p->pbMask;
4178+ nextRepMatchPrice = curAndLenCharPrice +
4179+ GET_PRICE_1(p->isMatch[state2][posStateNext]) +
4180+ GET_PRICE_1(p->isRep[state2]);
4181+
4182+ /* for (; lenTest2 >= 2; lenTest2--) */
4183+ {
4184+ UInt32 offset = cur + lenTest + 1 + lenTest2;
4185+ UInt32 curAndLenPrice;
4186+ COptimal *opt;
4187+ while (lenEnd < offset)
4188+ p->opt[++lenEnd].price = kInfinityPrice;
4189+ curAndLenPrice = nextRepMatchPrice + GetRepPrice(p, 0, lenTest2, state2, posStateNext);
4190+ opt = &p->opt[offset];
4191+ if (curAndLenPrice < opt->price)
4192+ {
4193+ opt->price = curAndLenPrice;
4194+ opt->posPrev = cur + lenTest + 1;
4195+ opt->backPrev = 0;
4196+ opt->prev1IsChar = True;
4197+ opt->prev2 = True;
4198+ opt->posPrev2 = cur;
4199+ opt->backPrev2 = curBack + LZMA_NUM_REPS;
4200+ }
4201+ }
4202+ }
4203+ offs += 2;
4204+ if (offs == numDistancePairs)
4205+ break;
4206+ curBack = matchDistances[offs + 1];
4207+ if (curBack >= kNumFullDistances)
4208+ GetPosSlot2(curBack, posSlot);
4209+ }
4210+ }
4211+ }
4212+ }
4213+}
4214+
4215+#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist))
4216+
4217+static UInt32 GetOptimumFast(CLzmaEnc *p, UInt32 *backRes)
4218+{
4219+ UInt32 numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
4220+ UInt32 lenMain, numDistancePairs;
4221+ const Byte *data;
4222+ UInt32 repLens[LZMA_NUM_REPS];
4223+ UInt32 repMaxIndex, i;
4224+ UInt32 *matchDistances;
4225+ UInt32 backMain;
4226+
4227+ if (!p->longestMatchWasFound)
4228+ {
4229+ lenMain = ReadMatchDistances(p, &numDistancePairs);
4230+ }
4231+ else
4232+ {
4233+ lenMain = p->longestMatchLength;
4234+ numDistancePairs = p->numDistancePairs;
4235+ p->longestMatchWasFound = False;
4236+ }
4237+
4238+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
4239+ if (numAvailableBytes > LZMA_MATCH_LEN_MAX)
4240+ numAvailableBytes = LZMA_MATCH_LEN_MAX;
4241+ if (numAvailableBytes < 2)
4242+ {
4243+ *backRes = (UInt32)(-1);
4244+ return 1;
4245+ }
4246+
4247+ repMaxIndex = 0;
4248+
4249+ for (i = 0; i < LZMA_NUM_REPS; i++)
4250+ {
4251+ const Byte *data2 = data - (p->reps[i] + 1);
4252+ UInt32 len;
4253+ if (data[0] != data2[0] || data[1] != data2[1])
4254+ {
4255+ repLens[i] = 0;
4256+ continue;
4257+ }
4258+ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
4259+ if (len >= p->numFastBytes)
4260+ {
4261+ *backRes = i;
4262+ MovePos(p, len - 1);
4263+ return len;
4264+ }
4265+ repLens[i] = len;
4266+ if (len > repLens[repMaxIndex])
4267+ repMaxIndex = i;
4268+ }
4269+ matchDistances = p->matchDistances;
4270+ if (lenMain >= p->numFastBytes)
4271+ {
4272+ *backRes = matchDistances[numDistancePairs - 1] + LZMA_NUM_REPS;
4273+ MovePos(p, lenMain - 1);
4274+ return lenMain;
4275+ }
4276+
4277+ backMain = 0; /* for GCC */
4278+ if (lenMain >= 2)
4279+ {
4280+ backMain = matchDistances[numDistancePairs - 1];
4281+ while (numDistancePairs > 2 && lenMain == matchDistances[numDistancePairs - 4] + 1)
4282+ {
4283+ if (!ChangePair(matchDistances[numDistancePairs - 3], backMain))
4284+ break;
4285+ numDistancePairs -= 2;
4286+ lenMain = matchDistances[numDistancePairs - 2];
4287+ backMain = matchDistances[numDistancePairs - 1];
4288+ }
4289+ if (lenMain == 2 && backMain >= 0x80)
4290+ lenMain = 1;
4291+ }
4292+
4293+ if (repLens[repMaxIndex] >= 2)
4294+ {
4295+ if (repLens[repMaxIndex] + 1 >= lenMain ||
4296+ (repLens[repMaxIndex] + 2 >= lenMain && (backMain > (1 << 9))) ||
4297+ (repLens[repMaxIndex] + 3 >= lenMain && (backMain > (1 << 15))))
4298+ {
4299+ UInt32 lenRes;
4300+ *backRes = repMaxIndex;
4301+ lenRes = repLens[repMaxIndex];
4302+ MovePos(p, lenRes - 1);
4303+ return lenRes;
4304+ }
4305+ }
4306+
4307+ if (lenMain >= 2 && numAvailableBytes > 2)
4308+ {
4309+ UInt32 i;
4310+ numAvailableBytes = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
4311+ p->longestMatchLength = ReadMatchDistances(p, &p->numDistancePairs);
4312+ if (p->longestMatchLength >= 2)
4313+ {
4314+ UInt32 newDistance = matchDistances[p->numDistancePairs - 1];
4315+ if ((p->longestMatchLength >= lenMain && newDistance < backMain) ||
4316+ (p->longestMatchLength == lenMain + 1 && !ChangePair(backMain, newDistance)) ||
4317+ (p->longestMatchLength > lenMain + 1) ||
4318+ (p->longestMatchLength + 1 >= lenMain && lenMain >= 3 && ChangePair(newDistance, backMain)))
4319+ {
4320+ p->longestMatchWasFound = True;
4321+ *backRes = (UInt32)(-1);
4322+ return 1;
4323+ }
4324+ }
4325+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1;
4326+ for (i = 0; i < LZMA_NUM_REPS; i++)
4327+ {
4328+ UInt32 len;
4329+ const Byte *data2 = data - (p->reps[i] + 1);
4330+ if (data[1] != data2[1] || data[2] != data2[2])
4331+ {
4332+ repLens[i] = 0;
4333+ continue;
4334+ }
4335+ for (len = 2; len < numAvailableBytes && data[len] == data2[len]; len++);
4336+ if (len + 1 >= lenMain)
4337+ {
4338+ p->longestMatchWasFound = True;
4339+ *backRes = (UInt32)(-1);
4340+ return 1;
4341+ }
4342+ }
4343+ *backRes = backMain + LZMA_NUM_REPS;
4344+ MovePos(p, lenMain - 2);
4345+ return lenMain;
4346+ }
4347+ *backRes = (UInt32)(-1);
4348+ return 1;
4349+}
4350+
4351+static void WriteEndMarker(CLzmaEnc *p, UInt32 posState)
4352+{
4353+ UInt32 len;
4354+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
4355+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
4356+ p->state = kMatchNextStates[p->state];
4357+ len = LZMA_MATCH_LEN_MIN;
4358+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
4359+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, (1 << kNumPosSlotBits) - 1);
4360+ RangeEnc_EncodeDirectBits(&p->rc, (((UInt32)1 << 30) - 1) >> kNumAlignBits, 30 - kNumAlignBits);
4361+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask);
4362+}
4363+
4364+static SRes CheckErrors(CLzmaEnc *p)
4365+{
4366+ if (p->result != SZ_OK)
4367+ return p->result;
4368+ if (p->rc.res != SZ_OK)
4369+ p->result = SZ_ERROR_WRITE;
4370+ if (p->matchFinderBase.result != SZ_OK)
4371+ p->result = SZ_ERROR_READ;
4372+ if (p->result != SZ_OK)
4373+ p->finished = True;
4374+ return p->result;
4375+}
4376+
4377+static SRes Flush(CLzmaEnc *p, UInt32 nowPos)
4378+{
4379+ /* ReleaseMFStream(); */
4380+ p->finished = True;
4381+ if (p->writeEndMark)
4382+ WriteEndMarker(p, nowPos & p->pbMask);
4383+ RangeEnc_FlushData(&p->rc);
4384+ RangeEnc_FlushStream(&p->rc);
4385+ return CheckErrors(p);
4386+}
4387+
4388+static void FillAlignPrices(CLzmaEnc *p)
4389+{
4390+ UInt32 i;
4391+ for (i = 0; i < kAlignTableSize; i++)
4392+ p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices);
4393+ p->alignPriceCount = 0;
4394+}
4395+
4396+static void FillDistancesPrices(CLzmaEnc *p)
4397+{
4398+ UInt32 tempPrices[kNumFullDistances];
4399+ UInt32 i, lenToPosState;
4400+ for (i = kStartPosModelIndex; i < kNumFullDistances; i++)
4401+ {
4402+ UInt32 posSlot = GetPosSlot1(i);
4403+ UInt32 footerBits = ((posSlot >> 1) - 1);
4404+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
4405+ tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base - posSlot - 1, footerBits, i - base, p->ProbPrices);
4406+ }
4407+
4408+ for (lenToPosState = 0; lenToPosState < kNumLenToPosStates; lenToPosState++)
4409+ {
4410+ UInt32 posSlot;
4411+ const CLzmaProb *encoder = p->posSlotEncoder[lenToPosState];
4412+ UInt32 *posSlotPrices = p->posSlotPrices[lenToPosState];
4413+ for (posSlot = 0; posSlot < p->distTableSize; posSlot++)
4414+ posSlotPrices[posSlot] = RcTree_GetPrice(encoder, kNumPosSlotBits, posSlot, p->ProbPrices);
4415+ for (posSlot = kEndPosModelIndex; posSlot < p->distTableSize; posSlot++)
4416+ posSlotPrices[posSlot] += ((((posSlot >> 1) - 1) - kNumAlignBits) << kNumBitPriceShiftBits);
4417+
4418+ {
4419+ UInt32 *distancesPrices = p->distancesPrices[lenToPosState];
4420+ UInt32 i;
4421+ for (i = 0; i < kStartPosModelIndex; i++)
4422+ distancesPrices[i] = posSlotPrices[i];
4423+ for (; i < kNumFullDistances; i++)
4424+ distancesPrices[i] = posSlotPrices[GetPosSlot1(i)] + tempPrices[i];
4425+ }
4426+ }
4427+ p->matchPriceCount = 0;
4428+}
4429+
4430+static void LzmaEnc_Construct(CLzmaEnc *p)
4431+{
4432+ RangeEnc_Construct(&p->rc);
4433+ MatchFinder_Construct(&p->matchFinderBase);
4434+ #ifdef COMPRESS_MF_MT
4435+ MatchFinderMt_Construct(&p->matchFinderMt);
4436+ p->matchFinderMt.MatchFinder = &p->matchFinderBase;
4437+ #endif
4438+
4439+ {
4440+ CLzmaEncProps props;
4441+ LzmaEncProps_Init(&props);
4442+ LzmaEnc_SetProps(p, &props);
4443+ }
4444+
4445+ #ifndef LZMA_LOG_BSR
4446+ LzmaEnc_FastPosInit(p->g_FastPos);
4447+ #endif
4448+
4449+ LzmaEnc_InitPriceTables(p->ProbPrices);
4450+ p->litProbs = 0;
4451+ p->saveState.litProbs = 0;
4452+}
4453+
4454+CLzmaEncHandle LzmaEnc_Create(ISzAlloc *alloc)
4455+{
4456+ void *p;
4457+ p = alloc->Alloc(alloc, sizeof(CLzmaEnc));
4458+ if (p != 0)
4459+ LzmaEnc_Construct((CLzmaEnc *)p);
4460+ return p;
4461+}
4462+
4463+static void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAlloc *alloc)
4464+{
4465+ alloc->Free(alloc, p->litProbs);
4466+ alloc->Free(alloc, p->saveState.litProbs);
4467+ p->litProbs = 0;
4468+ p->saveState.litProbs = 0;
4469+}
4470+
4471+static void LzmaEnc_Destruct(CLzmaEnc *p, ISzAlloc *alloc, ISzAlloc *allocBig)
4472+{
4473+ #ifdef COMPRESS_MF_MT
4474+ MatchFinderMt_Destruct(&p->matchFinderMt, allocBig);
4475+ #endif
4476+ MatchFinder_Free(&p->matchFinderBase, allocBig);
4477+ LzmaEnc_FreeLits(p, alloc);
4478+ RangeEnc_Free(&p->rc, alloc);
4479+}
4480+
4481+void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAlloc *alloc, ISzAlloc *allocBig)
4482+{
4483+ LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig);
4484+ alloc->Free(alloc, p);
4485+}
4486+
4487+static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, Bool useLimits, UInt32 maxPackSize, UInt32 maxUnpackSize)
4488+{
4489+ UInt32 nowPos32, startPos32;
4490+ if (p->inStream != 0)
4491+ {
4492+ p->matchFinderBase.stream = p->inStream;
4493+ p->matchFinder.Init(p->matchFinderObj);
4494+ p->inStream = 0;
4495+ }
4496+
4497+ if (p->finished)
4498+ return p->result;
4499+ RINOK(CheckErrors(p));
4500+
4501+ nowPos32 = (UInt32)p->nowPos64;
4502+ startPos32 = nowPos32;
4503+
4504+ if (p->nowPos64 == 0)
4505+ {
4506+ UInt32 numDistancePairs;
4507+ Byte curByte;
4508+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
4509+ return Flush(p, nowPos32);
4510+ ReadMatchDistances(p, &numDistancePairs);
4511+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][0], 0);
4512+ p->state = kLiteralNextStates[p->state];
4513+ curByte = p->matchFinder.GetIndexByte(p->matchFinderObj, 0 - p->additionalOffset);
4514+ LitEnc_Encode(&p->rc, p->litProbs, curByte);
4515+ p->additionalOffset--;
4516+ nowPos32++;
4517+ }
4518+
4519+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0)
4520+ for (;;)
4521+ {
4522+ UInt32 pos, len, posState;
4523+
4524+ if (p->fastMode)
4525+ len = GetOptimumFast(p, &pos);
4526+ else
4527+ len = GetOptimum(p, nowPos32, &pos);
4528+
4529+ #ifdef SHOW_STAT2
4530+ printf("\n pos = %4X, len = %d pos = %d", nowPos32, len, pos);
4531+ #endif
4532+
4533+ posState = nowPos32 & p->pbMask;
4534+ if (len == 1 && pos == 0xFFFFFFFF)
4535+ {
4536+ Byte curByte;
4537+ CLzmaProb *probs;
4538+ const Byte *data;
4539+
4540+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 0);
4541+ data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
4542+ curByte = *data;
4543+ probs = LIT_PROBS(nowPos32, *(data - 1));
4544+ if (IsCharState(p->state))
4545+ LitEnc_Encode(&p->rc, probs, curByte);
4546+ else
4547+ LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0] - 1));
4548+ p->state = kLiteralNextStates[p->state];
4549+ }
4550+ else
4551+ {
4552+ RangeEnc_EncodeBit(&p->rc, &p->isMatch[p->state][posState], 1);
4553+ if (pos < LZMA_NUM_REPS)
4554+ {
4555+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 1);
4556+ if (pos == 0)
4557+ {
4558+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 0);
4559+ RangeEnc_EncodeBit(&p->rc, &p->isRep0Long[p->state][posState], ((len == 1) ? 0 : 1));
4560+ }
4561+ else
4562+ {
4563+ UInt32 distance = p->reps[pos];
4564+ RangeEnc_EncodeBit(&p->rc, &p->isRepG0[p->state], 1);
4565+ if (pos == 1)
4566+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 0);
4567+ else
4568+ {
4569+ RangeEnc_EncodeBit(&p->rc, &p->isRepG1[p->state], 1);
4570+ RangeEnc_EncodeBit(&p->rc, &p->isRepG2[p->state], pos - 2);
4571+ if (pos == 3)
4572+ p->reps[3] = p->reps[2];
4573+ p->reps[2] = p->reps[1];
4574+ }
4575+ p->reps[1] = p->reps[0];
4576+ p->reps[0] = distance;
4577+ }
4578+ if (len == 1)
4579+ p->state = kShortRepNextStates[p->state];
4580+ else
4581+ {
4582+ LenEnc_Encode2(&p->repLenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
4583+ p->state = kRepNextStates[p->state];
4584+ }
4585+ }
4586+ else
4587+ {
4588+ UInt32 posSlot;
4589+ RangeEnc_EncodeBit(&p->rc, &p->isRep[p->state], 0);
4590+ p->state = kMatchNextStates[p->state];
4591+ LenEnc_Encode2(&p->lenEnc, &p->rc, len - LZMA_MATCH_LEN_MIN, posState, !p->fastMode, p->ProbPrices);
4592+ pos -= LZMA_NUM_REPS;
4593+ GetPosSlot(pos, posSlot);
4594+ RcTree_Encode(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], kNumPosSlotBits, posSlot);
4595+
4596+ if (posSlot >= kStartPosModelIndex)
4597+ {
4598+ UInt32 footerBits = ((posSlot >> 1) - 1);
4599+ UInt32 base = ((2 | (posSlot & 1)) << footerBits);
4600+ UInt32 posReduced = pos - base;
4601+
4602+ if (posSlot < kEndPosModelIndex)
4603+ RcTree_ReverseEncode(&p->rc, p->posEncoders + base - posSlot - 1, footerBits, posReduced);
4604+ else
4605+ {
4606+ RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits);
4607+ RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask);
4608+ p->alignPriceCount++;
4609+ }
4610+ }
4611+ p->reps[3] = p->reps[2];
4612+ p->reps[2] = p->reps[1];
4613+ p->reps[1] = p->reps[0];
4614+ p->reps[0] = pos;
4615+ p->matchPriceCount++;
4616+ }
4617+ }
4618+ p->additionalOffset -= len;
4619+ nowPos32 += len;
4620+ if (p->additionalOffset == 0)
4621+ {
4622+ UInt32 processed;
4623+ if (!p->fastMode)
4624+ {
4625+ if (p->matchPriceCount >= (1 << 7))
4626+ FillDistancesPrices(p);
4627+ if (p->alignPriceCount >= kAlignTableSize)
4628+ FillAlignPrices(p);
4629+ }
4630+ if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0)
4631+ break;
4632+ processed = nowPos32 - startPos32;
4633+ if (useLimits)
4634+ {
4635+ if (processed + kNumOpts + 300 >= maxUnpackSize ||
4636+ RangeEnc_GetProcessed(&p->rc) + kNumOpts * 2 >= maxPackSize)
4637+ break;
4638+ }
4639+ else if (processed >= (1 << 15))
4640+ {
4641+ p->nowPos64 += nowPos32 - startPos32;
4642+ return CheckErrors(p);
4643+ }
4644+ }
4645+ }
4646+ p->nowPos64 += nowPos32 - startPos32;
4647+ return Flush(p, nowPos32);
4648+}
4649+
4650+#define kBigHashDicLimit ((UInt32)1 << 24)
4651+
4652+static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
4653+{
4654+ UInt32 beforeSize = kNumOpts;
4655+ Bool btMode;
4656+ if (!RangeEnc_Alloc(&p->rc, alloc))
4657+ return SZ_ERROR_MEM;
4658+ btMode = (p->matchFinderBase.btMode != 0);
4659+ #ifdef COMPRESS_MF_MT
4660+ p->mtMode = (p->multiThread && !p->fastMode && btMode);
4661+ #endif
4662+
4663+ {
4664+ unsigned lclp = p->lc + p->lp;
4665+ if (p->litProbs == 0 || p->saveState.litProbs == 0 || p->lclp != lclp)
4666+ {
4667+ LzmaEnc_FreeLits(p, alloc);
4668+ p->litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
4669+ p->saveState.litProbs = (CLzmaProb *)alloc->Alloc(alloc, (0x300 << lclp) * sizeof(CLzmaProb));
4670+ if (p->litProbs == 0 || p->saveState.litProbs == 0)
4671+ {
4672+ LzmaEnc_FreeLits(p, alloc);
4673+ return SZ_ERROR_MEM;
4674+ }
4675+ p->lclp = lclp;
4676+ }
4677+ }
4678+
4679+ p->matchFinderBase.bigHash = (p->dictSize > kBigHashDicLimit);
4680+
4681+ if (beforeSize + p->dictSize < keepWindowSize)
4682+ beforeSize = keepWindowSize - p->dictSize;
4683+
4684+ #ifdef COMPRESS_MF_MT
4685+ if (p->mtMode)
4686+ {
4687+ RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig));
4688+ p->matchFinderObj = &p->matchFinderMt;
4689+ MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder);
4690+ }
4691+ else
4692+ #endif
4693+ {
4694+ if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig))
4695+ return SZ_ERROR_MEM;
4696+ p->matchFinderObj = &p->matchFinderBase;
4697+ MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder);
4698+ }
4699+ return SZ_OK;
4700+}
4701+
4702+static void LzmaEnc_Init(CLzmaEnc *p)
4703+{
4704+ UInt32 i;
4705+ p->state = 0;
4706+ for(i = 0 ; i < LZMA_NUM_REPS; i++)
4707+ p->reps[i] = 0;
4708+
4709+ RangeEnc_Init(&p->rc);
4710+
4711+
4712+ for (i = 0; i < kNumStates; i++)
4713+ {
4714+ UInt32 j;
4715+ for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++)
4716+ {
4717+ p->isMatch[i][j] = kProbInitValue;
4718+ p->isRep0Long[i][j] = kProbInitValue;
4719+ }
4720+ p->isRep[i] = kProbInitValue;
4721+ p->isRepG0[i] = kProbInitValue;
4722+ p->isRepG1[i] = kProbInitValue;
4723+ p->isRepG2[i] = kProbInitValue;
4724+ }
4725+
4726+ {
4727+ UInt32 num = 0x300 << (p->lp + p->lc);
4728+ for (i = 0; i < num; i++)
4729+ p->litProbs[i] = kProbInitValue;
4730+ }
4731+
4732+ {
4733+ for (i = 0; i < kNumLenToPosStates; i++)
4734+ {
4735+ CLzmaProb *probs = p->posSlotEncoder[i];
4736+ UInt32 j;
4737+ for (j = 0; j < (1 << kNumPosSlotBits); j++)
4738+ probs[j] = kProbInitValue;
4739+ }
4740+ }
4741+ {
4742+ for(i = 0; i < kNumFullDistances - kEndPosModelIndex; i++)
4743+ p->posEncoders[i] = kProbInitValue;
4744+ }
4745+
4746+ LenEnc_Init(&p->lenEnc.p);
4747+ LenEnc_Init(&p->repLenEnc.p);
4748+
4749+ for (i = 0; i < (1 << kNumAlignBits); i++)
4750+ p->posAlignEncoder[i] = kProbInitValue;
4751+
4752+ p->longestMatchWasFound = False;
4753+ p->optimumEndIndex = 0;
4754+ p->optimumCurrentIndex = 0;
4755+ p->additionalOffset = 0;
4756+
4757+ p->pbMask = (1 << p->pb) - 1;
4758+ p->lpMask = (1 << p->lp) - 1;
4759+}
4760+
4761+static void LzmaEnc_InitPrices(CLzmaEnc *p)
4762+{
4763+ if (!p->fastMode)
4764+ {
4765+ FillDistancesPrices(p);
4766+ FillAlignPrices(p);
4767+ }
4768+
4769+ p->lenEnc.tableSize =
4770+ p->repLenEnc.tableSize =
4771+ p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN;
4772+ LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, p->ProbPrices);
4773+ LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, p->ProbPrices);
4774+}
4775+
4776+static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
4777+{
4778+ UInt32 i;
4779+ for (i = 0; i < (UInt32)kDicLogSizeMaxCompress; i++)
4780+ if (p->dictSize <= ((UInt32)1 << i))
4781+ break;
4782+ p->distTableSize = i * 2;
4783+
4784+ p->finished = False;
4785+ p->result = SZ_OK;
4786+ RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig));
4787+ LzmaEnc_Init(p);
4788+ LzmaEnc_InitPrices(p);
4789+ p->nowPos64 = 0;
4790+ return SZ_OK;
4791+}
4792+
4793+static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqInStream *inStream, ISeqOutStream *outStream,
4794+ ISzAlloc *alloc, ISzAlloc *allocBig)
4795+{
4796+ CLzmaEnc *p = (CLzmaEnc *)pp;
4797+ p->inStream = inStream;
4798+ p->rc.outStream = outStream;
4799+ return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig);
4800+}
4801+
4802+static SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp,
4803+ ISeqInStream *inStream, UInt32 keepWindowSize,
4804+ ISzAlloc *alloc, ISzAlloc *allocBig)
4805+{
4806+ CLzmaEnc *p = (CLzmaEnc *)pp;
4807+ p->inStream = inStream;
4808+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
4809+}
4810+
4811+static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen)
4812+{
4813+ p->seqBufInStream.funcTable.Read = MyRead;
4814+ p->seqBufInStream.data = src;
4815+ p->seqBufInStream.rem = srcLen;
4816+}
4817+
4818+static SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen,
4819+ UInt32 keepWindowSize, ISzAlloc *alloc, ISzAlloc *allocBig)
4820+{
4821+ CLzmaEnc *p = (CLzmaEnc *)pp;
4822+ LzmaEnc_SetInputBuf(p, src, srcLen);
4823+ p->inStream = &p->seqBufInStream.funcTable;
4824+ return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig);
4825+}
4826+
4827+static void LzmaEnc_Finish(CLzmaEncHandle pp)
4828+{
4829+ #ifdef COMPRESS_MF_MT
4830+ CLzmaEnc *p = (CLzmaEnc *)pp;
4831+ if (p->mtMode)
4832+ MatchFinderMt_ReleaseStream(&p->matchFinderMt);
4833+ #endif
4834+}
4835+
4836+typedef struct _CSeqOutStreamBuf
4837+{
4838+ ISeqOutStream funcTable;
4839+ Byte *data;
4840+ SizeT rem;
4841+ Bool overflow;
4842+} CSeqOutStreamBuf;
4843+
4844+static size_t MyWrite(void *pp, const void *data, size_t size)
4845+{
4846+ CSeqOutStreamBuf *p = (CSeqOutStreamBuf *)pp;
4847+ if (p->rem < size)
4848+ {
4849+ size = p->rem;
4850+ p->overflow = True;
4851+ }
4852+ memcpy(p->data, data, size);
4853+ p->rem -= size;
4854+ p->data += size;
4855+ return size;
4856+}
4857+
4858+
4859+static UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp)
4860+{
4861+ const CLzmaEnc *p = (CLzmaEnc *)pp;
4862+ return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj);
4863+}
4864+
4865+static const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp)
4866+{
4867+ const CLzmaEnc *p = (CLzmaEnc *)pp;
4868+ return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset;
4869+}
4870+
4871+static SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, Bool reInit,
4872+ Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize)
4873+{
4874+ CLzmaEnc *p = (CLzmaEnc *)pp;
4875+ UInt64 nowPos64;
4876+ SRes res;
4877+ CSeqOutStreamBuf outStream;
4878+
4879+ outStream.funcTable.Write = MyWrite;
4880+ outStream.data = dest;
4881+ outStream.rem = *destLen;
4882+ outStream.overflow = False;
4883+
4884+ p->writeEndMark = False;
4885+ p->finished = False;
4886+ p->result = SZ_OK;
4887+
4888+ if (reInit)
4889+ LzmaEnc_Init(p);
4890+ LzmaEnc_InitPrices(p);
4891+ nowPos64 = p->nowPos64;
4892+ RangeEnc_Init(&p->rc);
4893+ p->rc.outStream = &outStream.funcTable;
4894+
4895+ res = LzmaEnc_CodeOneBlock(pp, True, desiredPackSize, *unpackSize);
4896+
4897+ *unpackSize = (UInt32)(p->nowPos64 - nowPos64);
4898+ *destLen -= outStream.rem;
4899+ if (outStream.overflow)
4900+ return SZ_ERROR_OUTPUT_EOF;
4901+
4902+ return res;
4903+}
4904+
4905+SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress,
4906+ ISzAlloc *alloc, ISzAlloc *allocBig)
4907+{
4908+ CLzmaEnc *p = (CLzmaEnc *)pp;
4909+ SRes res = SZ_OK;
4910+
4911+ #ifdef COMPRESS_MF_MT
4912+ Byte allocaDummy[0x300];
4913+ int i = 0;
4914+ for (i = 0; i < 16; i++)
4915+ allocaDummy[i] = (Byte)i;
4916+ #endif
4917+
4918+ RINOK(LzmaEnc_Prepare(pp, inStream, outStream, alloc, allocBig));
4919+
4920+ for (;;)
4921+ {
4922+ res = LzmaEnc_CodeOneBlock(pp, False, 0, 0);
4923+ if (res != SZ_OK || p->finished != 0)
4924+ break;
4925+ if (progress != 0)
4926+ {
4927+ res = progress->Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc));
4928+ if (res != SZ_OK)
4929+ {
4930+ res = SZ_ERROR_PROGRESS;
4931+ break;
4932+ }
4933+ }
4934+ }
4935+ LzmaEnc_Finish(pp);
4936+ return res;
4937+}
4938+
4939+SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size)
4940+{
4941+ CLzmaEnc *p = (CLzmaEnc *)pp;
4942+ int i;
4943+ UInt32 dictSize = p->dictSize;
4944+ if (*size < LZMA_PROPS_SIZE)
4945+ return SZ_ERROR_PARAM;
4946+ *size = LZMA_PROPS_SIZE;
4947+ props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc);
4948+
4949+ for (i = 11; i <= 30; i++)
4950+ {
4951+ if (dictSize <= ((UInt32)2 << i))
4952+ {
4953+ dictSize = (2 << i);
4954+ break;
4955+ }
4956+ if (dictSize <= ((UInt32)3 << i))
4957+ {
4958+ dictSize = (3 << i);
4959+ break;
4960+ }
4961+ }
4962+
4963+ for (i = 0; i < 4; i++)
4964+ props[1 + i] = (Byte)(dictSize >> (8 * i));
4965+ return SZ_OK;
4966+}
4967+
4968+SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
4969+ int writeEndMark, ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
4970+{
4971+ SRes res;
4972+ CLzmaEnc *p = (CLzmaEnc *)pp;
4973+
4974+ CSeqOutStreamBuf outStream;
4975+
4976+ LzmaEnc_SetInputBuf(p, src, srcLen);
4977+
4978+ outStream.funcTable.Write = MyWrite;
4979+ outStream.data = dest;
4980+ outStream.rem = *destLen;
4981+ outStream.overflow = False;
4982+
4983+ p->writeEndMark = writeEndMark;
4984+ res = LzmaEnc_Encode(pp, &outStream.funcTable, &p->seqBufInStream.funcTable,
4985+ progress, alloc, allocBig);
4986+
4987+ *destLen -= outStream.rem;
4988+ if (outStream.overflow)
4989+ return SZ_ERROR_OUTPUT_EOF;
4990+ return res;
4991+}
4992+
4993+SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
4994+ const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
4995+ ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig)
4996+{
4997+ CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc);
4998+ SRes res;
4999+ if (p == 0)
5000+ return SZ_ERROR_MEM;
5001+
5002+ res = LzmaEnc_SetProps(p, props);
5003+ if (res == SZ_OK)
5004+ {
5005+ res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize);
5006+ if (res == SZ_OK)
5007+ res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen,
5008+ writeEndMark, progress, alloc, allocBig);
5009+ }
5010+
5011+ LzmaEnc_Destroy(p, alloc, allocBig);
5012+ return res;
5013+}
5014--- a/jffsX-utils/mkfs.jffs2.c
5015+++ b/jffsX-utils/mkfs.jffs2.c
5016@@ -1668,11 +1668,11 @@ int main(int argc, char **argv)
5017 }
5018 erase_block_size *= units;
5019
5020- /* If it's less than 8KiB, they're not allowed */
5021- if (erase_block_size < 0x2000) {
5022- fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
5023+ /* If it's less than 4KiB, they're not allowed */
5024+ if (erase_block_size < 0x1000) {
5025+ fprintf(stderr, "Erase size 0x%x too small. Increasing to 4KiB minimum\n",
5026 erase_block_size);
5027- erase_block_size = 0x2000;
5028+ erase_block_size = 0x1000;
5029 }
5030 break;
5031 }
5032--- a/Makefile.am
5033+++ b/Makefile.am
5034@@ -19,6 +19,10 @@ if WITH_ZSTD
5035 AM_CPPFLAGS += -DWITH_ZSTD
5036 endif
5037
5038+if WITH_LZMA
5039+AM_CPPFLAGS += -DWITH_LZMA
5040+endif
5041+
5042 if WITH_SELINUX
5043 AM_CPPFLAGS += -DWITH_SELINUX
5044 endif
5045--- a/configure.ac
5046+++ b/configure.ac
5047@@ -96,6 +96,10 @@ AC_ARG_WITH([zstd],
5048 [AS_HELP_STRING([--with-zstd], [Support for ZSTD compression])],
5049 [], [with_zstd="check"])
5050
5051+AC_ARG_WITH([lzma],
5052+ [AS_HELP_STRING([--with-lzma], [Support for LZMA compression])],
5053+ [], [with_lzma="check"])
5054+
5055 AC_ARG_WITH([selinux],
5056 [AS_HELP_STRING([--with-selinux],
5057 [Support for selinux extended attributes])],
5058@@ -269,6 +273,7 @@ fi
5059 AM_CONDITIONAL([WITH_LZO], [test "x$with_lzo" = "xyes"])
5060 AM_CONDITIONAL([WITH_ZLIB], [test "x$with_zlib" = "xyes"])
5061 AM_CONDITIONAL([WITH_ZSTD], [test "x$with_zstd" = "xyes"])
5062+AM_CONDITIONAL([WITH_LZMA], [test "x$with_lzma" = "xyes"])
5063 AM_CONDITIONAL([WITH_XATTR], [test "x$with_xattr" = "xyes"])
5064 AM_CONDITIONAL([WITH_SELINUX], [test "x$with_selinux" = "xyes"])
5065 AM_CONDITIONAL([WITH_CRYPTO], [test "x$with_crypto" = "xyes"])
5066@@ -313,6 +318,7 @@ AC_MSG_RESULT([
5067 lzo support: ${with_lzo}
5068 zlib support: ${with_zlib}
5069 zstd support: ${with_zstd}
5070+ lzma support: ${with_lzma}
5071 xattr/acl support: ${with_xattr}
5072 SELinux support: ${with_selinux}
5073 fscrypt support: ${with_crypto}