1*f6dc9357SAndroid Build Coastguard Worker // Mtf8.h 2*f6dc9357SAndroid Build Coastguard Worker 3*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_COMPRESS_MTF8_H 4*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_COMPRESS_MTF8_H 5*f6dc9357SAndroid Build Coastguard Worker 6*f6dc9357SAndroid Build Coastguard Worker #include "../../../C/CpuArch.h" 7*f6dc9357SAndroid Build Coastguard Worker 8*f6dc9357SAndroid Build Coastguard Worker namespace NCompress { 9*f6dc9357SAndroid Build Coastguard Worker 10*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Encoder 11*f6dc9357SAndroid Build Coastguard Worker { 12*f6dc9357SAndroid Build Coastguard Worker Byte Buf[256]; 13*f6dc9357SAndroid Build Coastguard Worker FindAndMoveCMtf8Encoder14*f6dc9357SAndroid Build Coastguard Worker unsigned FindAndMove(Byte v) throw() 15*f6dc9357SAndroid Build Coastguard Worker { 16*f6dc9357SAndroid Build Coastguard Worker size_t pos; 17*f6dc9357SAndroid Build Coastguard Worker for (pos = 0; Buf[pos] != v; pos++); 18*f6dc9357SAndroid Build Coastguard Worker const unsigned resPos = (unsigned)pos; 19*f6dc9357SAndroid Build Coastguard Worker for (; pos >= 8; pos -= 8) 20*f6dc9357SAndroid Build Coastguard Worker { 21*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = Buf[pos - 1]; 22*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 1] = Buf[pos - 2]; 23*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 2] = Buf[pos - 3]; 24*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 3] = Buf[pos - 4]; 25*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 4] = Buf[pos - 5]; 26*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 5] = Buf[pos - 6]; 27*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 6] = Buf[pos - 7]; 28*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 7] = Buf[pos - 8]; 29*f6dc9357SAndroid Build Coastguard Worker } 30*f6dc9357SAndroid Build Coastguard Worker for (; pos != 0; pos--) 31*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = Buf[pos - 1]; 32*f6dc9357SAndroid Build Coastguard Worker Buf[0] = v; 33*f6dc9357SAndroid Build Coastguard Worker return resPos; 34*f6dc9357SAndroid Build Coastguard Worker } 35*f6dc9357SAndroid Build Coastguard Worker }; 36*f6dc9357SAndroid Build Coastguard Worker 37*f6dc9357SAndroid Build Coastguard Worker /* 38*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Decoder 39*f6dc9357SAndroid Build Coastguard Worker { 40*f6dc9357SAndroid Build Coastguard Worker Byte Buf[256]; 41*f6dc9357SAndroid Build Coastguard Worker 42*f6dc9357SAndroid Build Coastguard Worker void StartInit() { memset(Buf, 0, sizeof(Buf)); } 43*f6dc9357SAndroid Build Coastguard Worker void Add(unsigned pos, Byte val) { Buf[pos] = val; } 44*f6dc9357SAndroid Build Coastguard Worker Byte GetHead() const { return Buf[0]; } 45*f6dc9357SAndroid Build Coastguard Worker Byte GetAndMove(unsigned pos) 46*f6dc9357SAndroid Build Coastguard Worker { 47*f6dc9357SAndroid Build Coastguard Worker Byte res = Buf[pos]; 48*f6dc9357SAndroid Build Coastguard Worker for (; pos >= 8; pos -= 8) 49*f6dc9357SAndroid Build Coastguard Worker { 50*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = Buf[pos - 1]; 51*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 1] = Buf[pos - 2]; 52*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 2] = Buf[pos - 3]; 53*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 3] = Buf[pos - 4]; 54*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 4] = Buf[pos - 5]; 55*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 5] = Buf[pos - 6]; 56*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 6] = Buf[pos - 7]; 57*f6dc9357SAndroid Build Coastguard Worker Buf[pos - 7] = Buf[pos - 8]; 58*f6dc9357SAndroid Build Coastguard Worker } 59*f6dc9357SAndroid Build Coastguard Worker for (; pos > 0; pos--) 60*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = Buf[pos - 1]; 61*f6dc9357SAndroid Build Coastguard Worker Buf[0] = res; 62*f6dc9357SAndroid Build Coastguard Worker return res; 63*f6dc9357SAndroid Build Coastguard Worker } 64*f6dc9357SAndroid Build Coastguard Worker }; 65*f6dc9357SAndroid Build Coastguard Worker */ 66*f6dc9357SAndroid Build Coastguard Worker 67*f6dc9357SAndroid Build Coastguard Worker #ifdef MY_CPU_64BIT 68*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CMtfVar; 69*f6dc9357SAndroid Build Coastguard Worker #define Z7_MTF_MOVS 3 70*f6dc9357SAndroid Build Coastguard Worker #else 71*f6dc9357SAndroid Build Coastguard Worker typedef UInt32 CMtfVar; 72*f6dc9357SAndroid Build Coastguard Worker #define Z7_MTF_MOVS 2 73*f6dc9357SAndroid Build Coastguard Worker #endif 74*f6dc9357SAndroid Build Coastguard Worker 75*f6dc9357SAndroid Build Coastguard Worker #define Z7_MTF_MASK ((1 << Z7_MTF_MOVS) - 1) 76*f6dc9357SAndroid Build Coastguard Worker 77*f6dc9357SAndroid Build Coastguard Worker 78*f6dc9357SAndroid Build Coastguard Worker struct CMtf8Decoder 79*f6dc9357SAndroid Build Coastguard Worker { 80*f6dc9357SAndroid Build Coastguard Worker CMtfVar Buf[256 >> Z7_MTF_MOVS]; 81*f6dc9357SAndroid Build Coastguard Worker StartInitCMtf8Decoder82*f6dc9357SAndroid Build Coastguard Worker void StartInit() { memset(Buf, 0, sizeof(Buf)); } AddCMtf8Decoder83*f6dc9357SAndroid Build Coastguard Worker void Add(unsigned pos, Byte val) { Buf[pos >> Z7_MTF_MOVS] |= ((CMtfVar)val << ((pos & Z7_MTF_MASK) << 3)); } GetHeadCMtf8Decoder84*f6dc9357SAndroid Build Coastguard Worker Byte GetHead() const { return (Byte)Buf[0]; } 85*f6dc9357SAndroid Build Coastguard Worker 86*f6dc9357SAndroid Build Coastguard Worker Z7_FORCE_INLINE GetAndMoveCMtf8Decoder87*f6dc9357SAndroid Build Coastguard Worker Byte GetAndMove(unsigned pos) throw() 88*f6dc9357SAndroid Build Coastguard Worker { 89*f6dc9357SAndroid Build Coastguard Worker const UInt32 lim = ((UInt32)pos >> Z7_MTF_MOVS); 90*f6dc9357SAndroid Build Coastguard Worker pos = (pos & Z7_MTF_MASK) << 3; 91*f6dc9357SAndroid Build Coastguard Worker CMtfVar prev = (Buf[lim] >> pos) & 0xFF; 92*f6dc9357SAndroid Build Coastguard Worker 93*f6dc9357SAndroid Build Coastguard Worker UInt32 i = 0; 94*f6dc9357SAndroid Build Coastguard Worker 95*f6dc9357SAndroid Build Coastguard Worker 96*f6dc9357SAndroid Build Coastguard Worker /* 97*f6dc9357SAndroid Build Coastguard Worker if ((lim & 1) != 0) 98*f6dc9357SAndroid Build Coastguard Worker { 99*f6dc9357SAndroid Build Coastguard Worker CMtfVar next = Buf[0]; 100*f6dc9357SAndroid Build Coastguard Worker Buf[0] = (next << 8) | prev; 101*f6dc9357SAndroid Build Coastguard Worker prev = (next >> (Z7_MTF_MASK << 3)); 102*f6dc9357SAndroid Build Coastguard Worker i = 1; 103*f6dc9357SAndroid Build Coastguard Worker lim -= 1; 104*f6dc9357SAndroid Build Coastguard Worker } 105*f6dc9357SAndroid Build Coastguard Worker for (; i < lim; i += 2) 106*f6dc9357SAndroid Build Coastguard Worker { 107*f6dc9357SAndroid Build Coastguard Worker CMtfVar n0 = Buf[i]; 108*f6dc9357SAndroid Build Coastguard Worker CMtfVar n1 = Buf[i + 1]; 109*f6dc9357SAndroid Build Coastguard Worker Buf[i ] = (n0 << 8) | prev; 110*f6dc9357SAndroid Build Coastguard Worker Buf[i + 1] = (n1 << 8) | (n0 >> (Z7_MTF_MASK << 3)); 111*f6dc9357SAndroid Build Coastguard Worker prev = (n1 >> (Z7_MTF_MASK << 3)); 112*f6dc9357SAndroid Build Coastguard Worker } 113*f6dc9357SAndroid Build Coastguard Worker */ 114*f6dc9357SAndroid Build Coastguard Worker 115*f6dc9357SAndroid Build Coastguard Worker for (; i < lim; i++) 116*f6dc9357SAndroid Build Coastguard Worker { 117*f6dc9357SAndroid Build Coastguard Worker const CMtfVar n0 = Buf[i]; 118*f6dc9357SAndroid Build Coastguard Worker Buf[i ] = (n0 << 8) | prev; 119*f6dc9357SAndroid Build Coastguard Worker prev = (n0 >> (Z7_MTF_MASK << 3)); 120*f6dc9357SAndroid Build Coastguard Worker } 121*f6dc9357SAndroid Build Coastguard Worker 122*f6dc9357SAndroid Build Coastguard Worker 123*f6dc9357SAndroid Build Coastguard Worker const CMtfVar next = Buf[i]; 124*f6dc9357SAndroid Build Coastguard Worker const CMtfVar mask = (((CMtfVar)0x100 << pos) - 1); 125*f6dc9357SAndroid Build Coastguard Worker Buf[i] = (next & ~mask) | (((next << 8) | prev) & mask); 126*f6dc9357SAndroid Build Coastguard Worker return (Byte)Buf[0]; 127*f6dc9357SAndroid Build Coastguard Worker } 128*f6dc9357SAndroid Build Coastguard Worker }; 129*f6dc9357SAndroid Build Coastguard Worker 130*f6dc9357SAndroid Build Coastguard Worker /* 131*f6dc9357SAndroid Build Coastguard Worker const int kSmallSize = 64; 132*f6dc9357SAndroid Build Coastguard Worker class CMtf8Decoder 133*f6dc9357SAndroid Build Coastguard Worker { 134*f6dc9357SAndroid Build Coastguard Worker Byte SmallBuffer[kSmallSize]; 135*f6dc9357SAndroid Build Coastguard Worker int SmallSize; 136*f6dc9357SAndroid Build Coastguard Worker int Counts[16]; 137*f6dc9357SAndroid Build Coastguard Worker int Size; 138*f6dc9357SAndroid Build Coastguard Worker public: 139*f6dc9357SAndroid Build Coastguard Worker Byte Buf[256]; 140*f6dc9357SAndroid Build Coastguard Worker 141*f6dc9357SAndroid Build Coastguard Worker Byte GetHead() const 142*f6dc9357SAndroid Build Coastguard Worker { 143*f6dc9357SAndroid Build Coastguard Worker if (SmallSize > 0) 144*f6dc9357SAndroid Build Coastguard Worker return SmallBuffer[kSmallSize - SmallSize]; 145*f6dc9357SAndroid Build Coastguard Worker return Buf[0]; 146*f6dc9357SAndroid Build Coastguard Worker } 147*f6dc9357SAndroid Build Coastguard Worker 148*f6dc9357SAndroid Build Coastguard Worker void Init(int size) 149*f6dc9357SAndroid Build Coastguard Worker { 150*f6dc9357SAndroid Build Coastguard Worker Size = size; 151*f6dc9357SAndroid Build Coastguard Worker SmallSize = 0; 152*f6dc9357SAndroid Build Coastguard Worker for (int i = 0; i < 16; i++) 153*f6dc9357SAndroid Build Coastguard Worker { 154*f6dc9357SAndroid Build Coastguard Worker Counts[i] = ((size >= 16) ? 16 : size); 155*f6dc9357SAndroid Build Coastguard Worker size -= Counts[i]; 156*f6dc9357SAndroid Build Coastguard Worker } 157*f6dc9357SAndroid Build Coastguard Worker } 158*f6dc9357SAndroid Build Coastguard Worker 159*f6dc9357SAndroid Build Coastguard Worker void Add(unsigned pos, Byte val) 160*f6dc9357SAndroid Build Coastguard Worker { 161*f6dc9357SAndroid Build Coastguard Worker Buf[pos] = val; 162*f6dc9357SAndroid Build Coastguard Worker } 163*f6dc9357SAndroid Build Coastguard Worker 164*f6dc9357SAndroid Build Coastguard Worker Byte GetAndMove(int pos) 165*f6dc9357SAndroid Build Coastguard Worker { 166*f6dc9357SAndroid Build Coastguard Worker if (pos < SmallSize) 167*f6dc9357SAndroid Build Coastguard Worker { 168*f6dc9357SAndroid Build Coastguard Worker Byte *p = SmallBuffer + kSmallSize - SmallSize; 169*f6dc9357SAndroid Build Coastguard Worker Byte res = p[pos]; 170*f6dc9357SAndroid Build Coastguard Worker for (; pos > 0; pos--) 171*f6dc9357SAndroid Build Coastguard Worker p[pos] = p[pos - 1]; 172*f6dc9357SAndroid Build Coastguard Worker SmallBuffer[kSmallSize - SmallSize] = res; 173*f6dc9357SAndroid Build Coastguard Worker return res; 174*f6dc9357SAndroid Build Coastguard Worker } 175*f6dc9357SAndroid Build Coastguard Worker if (SmallSize == kSmallSize) 176*f6dc9357SAndroid Build Coastguard Worker { 177*f6dc9357SAndroid Build Coastguard Worker int i = Size - 1; 178*f6dc9357SAndroid Build Coastguard Worker int g = 16; 179*f6dc9357SAndroid Build Coastguard Worker do 180*f6dc9357SAndroid Build Coastguard Worker { 181*f6dc9357SAndroid Build Coastguard Worker g--; 182*f6dc9357SAndroid Build Coastguard Worker int offset = (g << 4); 183*f6dc9357SAndroid Build Coastguard Worker for (int t = Counts[g] - 1; t >= 0; t--, i--) 184*f6dc9357SAndroid Build Coastguard Worker Buf[i] = Buf[offset + t]; 185*f6dc9357SAndroid Build Coastguard Worker } 186*f6dc9357SAndroid Build Coastguard Worker while (g != 0); 187*f6dc9357SAndroid Build Coastguard Worker 188*f6dc9357SAndroid Build Coastguard Worker for (i = kSmallSize - 1; i >= 0; i--) 189*f6dc9357SAndroid Build Coastguard Worker Buf[i] = SmallBuffer[i]; 190*f6dc9357SAndroid Build Coastguard Worker Init(Size); 191*f6dc9357SAndroid Build Coastguard Worker } 192*f6dc9357SAndroid Build Coastguard Worker pos -= SmallSize; 193*f6dc9357SAndroid Build Coastguard Worker int g; 194*f6dc9357SAndroid Build Coastguard Worker for (g = 0; pos >= Counts[g]; g++) 195*f6dc9357SAndroid Build Coastguard Worker pos -= Counts[g]; 196*f6dc9357SAndroid Build Coastguard Worker int offset = (g << 4); 197*f6dc9357SAndroid Build Coastguard Worker Byte res = Buf[offset + pos]; 198*f6dc9357SAndroid Build Coastguard Worker for (pos; pos < 16 - 1; pos++) 199*f6dc9357SAndroid Build Coastguard Worker Buf[offset + pos] = Buf[offset + pos + 1]; 200*f6dc9357SAndroid Build Coastguard Worker 201*f6dc9357SAndroid Build Coastguard Worker SmallSize++; 202*f6dc9357SAndroid Build Coastguard Worker SmallBuffer[kSmallSize - SmallSize] = res; 203*f6dc9357SAndroid Build Coastguard Worker 204*f6dc9357SAndroid Build Coastguard Worker Counts[g]--; 205*f6dc9357SAndroid Build Coastguard Worker return res; 206*f6dc9357SAndroid Build Coastguard Worker } 207*f6dc9357SAndroid Build Coastguard Worker }; 208*f6dc9357SAndroid Build Coastguard Worker */ 209*f6dc9357SAndroid Build Coastguard Worker 210*f6dc9357SAndroid Build Coastguard Worker } 211*f6dc9357SAndroid Build Coastguard Worker 212*f6dc9357SAndroid Build Coastguard Worker #endif 213