1 /* Ppmd8.h -- PPMdI codec
2 2011-01-27 : Igor Pavlov : Public domain
3 This code is based on:
4   PPMd var.I (2002): Dmitry Shkarin : Public domain
5   Carryless rangecoder (1999): Dmitry Subbotin : Public domain */
6 
7 #ifndef __PPMD8_H
8 #define __PPMD8_H
9 
10 #include "Ppmd.h"
11 
12 EXTERN_C_BEGIN
13 
14 #define PPMD8_MIN_ORDER 2
15 #define PPMD8_MAX_ORDER 16
16 
17 struct CPpmd8_Context_;
18 
19 typedef
20   #ifdef PPMD_32BIT
21     struct CPpmd8_Context_ *
22   #else
23     UInt32
24   #endif
25   CPpmd8_Context_Ref;
26 
27 #pragma pack(push, 1)
28 
29 typedef struct CPpmd8_Context_
30 {
31   Byte NumStats;
32   Byte Flags;
33   UInt16 SummFreq;
34   CPpmd_State_Ref Stats;
35   CPpmd8_Context_Ref Suffix;
36 } CPpmd8_Context;
37 
38 #pragma pack(pop)
39 
40 #define Ppmd8Context_OneState(p) ((CPpmd_State *)&(p)->SummFreq)
41 
42 /* The BUG in Shkarin's code for FREEZE mode was fixed, but that fixed
43    code is not compatible with original code for some files compressed
44    in FREEZE mode. So we disable FREEZE mode support. */
45 
46 enum
47 {
48   PPMD8_RESTORE_METHOD_RESTART,
49   PPMD8_RESTORE_METHOD_CUT_OFF
50   #ifdef PPMD8_FREEZE_SUPPORT
51   , PPMD8_RESTORE_METHOD_FREEZE
52   #endif
53 };
54 
55 typedef struct
56 {
57   CPpmd8_Context *MinContext, *MaxContext;
58   CPpmd_State *FoundState;
59   unsigned OrderFall, InitEsc, PrevSuccess, MaxOrder;
60   Int32 RunLength, InitRL; /* must be 32-bit at least */
61 
62   UInt32 Size;
63   UInt32 GlueCount;
64   Byte *Base, *LoUnit, *HiUnit, *Text, *UnitsStart;
65   UInt32 AlignOffset;
66   unsigned RestoreMethod;
67 
68   /* Range Coder */
69   UInt32 Range;
70   UInt32 Code;
71   UInt32 Low;
72   union
73   {
74     IByteIn *In;
75     IByteOut *Out;
76   } Stream;
77 
78   Byte Indx2Units[PPMD_NUM_INDEXES];
79   Byte Units2Indx[128];
80   CPpmd_Void_Ref FreeList[PPMD_NUM_INDEXES];
81   UInt32 Stamps[PPMD_NUM_INDEXES];
82 
83   Byte NS2BSIndx[256], NS2Indx[260];
84   CPpmd_See DummySee, See[24][32];
85   UInt16 BinSumm[25][64];
86 } CPpmd8;
87 
88 void Ppmd8_Construct(CPpmd8 *p);
89 Bool Ppmd8_Alloc(CPpmd8 *p, UInt32 size, ISzAlloc *alloc);
90 void Ppmd8_Free(CPpmd8 *p, ISzAlloc *alloc);
91 void Ppmd8_Init(CPpmd8 *p, unsigned maxOrder, unsigned restoreMethod);
92 #define Ppmd8_WasAllocated(p) ((p)->Base != NULL)
93 
94 
95 /* ---------- Internal Functions ---------- */
96 
97 extern const Byte PPMD8_kExpEscape[16];
98 
99 #ifdef PPMD_32BIT
100   #define Ppmd8_GetPtr(p, ptr) (ptr)
101   #define Ppmd8_GetContext(p, ptr) (ptr)
102   #define Ppmd8_GetStats(p, ctx) ((ctx)->Stats)
103 #else
104   #define Ppmd8_GetPtr(p, offs) ((void *)((p)->Base + (offs)))
105   #define Ppmd8_GetContext(p, offs) ((CPpmd8_Context *)Ppmd8_GetPtr((p), (offs)))
106   #define Ppmd8_GetStats(p, ctx) ((CPpmd_State *)Ppmd8_GetPtr((p), ((ctx)->Stats)))
107 #endif
108 
109 void Ppmd8_Update1(CPpmd8 *p);
110 void Ppmd8_Update1_0(CPpmd8 *p);
111 void Ppmd8_Update2(CPpmd8 *p);
112 void Ppmd8_UpdateBin(CPpmd8 *p);
113 
114 #define Ppmd8_GetBinSumm(p) \
115     &p->BinSumm[p->NS2Indx[Ppmd8Context_OneState(p->MinContext)->Freq - 1]][ \
116     p->NS2BSIndx[Ppmd8_GetContext(p, p->MinContext->Suffix)->NumStats] + \
117     p->PrevSuccess + p->MinContext->Flags + ((p->RunLength >> 26) & 0x20)]
118 
119 CPpmd_See *Ppmd8_MakeEscFreq(CPpmd8 *p, unsigned numMasked, UInt32 *scale);
120 
121 
122 /* ---------- Decode ---------- */
123 
124 Bool Ppmd8_RangeDec_Init(CPpmd8 *p);
125 #define Ppmd8_RangeDec_IsFinishedOK(p) ((p)->Code == 0)
126 int Ppmd8_DecodeSymbol(CPpmd8 *p); /* returns: -1 as EndMarker, -2 as DataError */
127 
128 
129 /* ---------- Encode ---------- */
130 
131 #define Ppmd8_RangeEnc_Init(p) { (p)->Low = 0; (p)->Range = 0xFFFFFFFF; }
132 void Ppmd8_RangeEnc_FlushData(CPpmd8 *p);
133 void Ppmd8_EncodeSymbol(CPpmd8 *p, int symbol); /* symbol = -1 means EndMarker */
134 
135 EXTERN_C_END
136 
137 #endif
138