1*f6dc9357SAndroid Build Coastguard Worker /* Bcj2.h -- BCJ2 converter for x86 code (Branch CALL/JUMP variant2) 2*f6dc9357SAndroid Build Coastguard Worker 2023-03-02 : Igor Pavlov : Public domain */ 3*f6dc9357SAndroid Build Coastguard Worker 4*f6dc9357SAndroid Build Coastguard Worker #ifndef ZIP7_INC_BCJ2_H 5*f6dc9357SAndroid Build Coastguard Worker #define ZIP7_INC_BCJ2_H 6*f6dc9357SAndroid Build Coastguard Worker 7*f6dc9357SAndroid Build Coastguard Worker #include "7zTypes.h" 8*f6dc9357SAndroid Build Coastguard Worker 9*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_BEGIN 10*f6dc9357SAndroid Build Coastguard Worker 11*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_NUM_STREAMS 4 12*f6dc9357SAndroid Build Coastguard Worker 13*f6dc9357SAndroid Build Coastguard Worker enum 14*f6dc9357SAndroid Build Coastguard Worker { 15*f6dc9357SAndroid Build Coastguard Worker BCJ2_STREAM_MAIN, 16*f6dc9357SAndroid Build Coastguard Worker BCJ2_STREAM_CALL, 17*f6dc9357SAndroid Build Coastguard Worker BCJ2_STREAM_JUMP, 18*f6dc9357SAndroid Build Coastguard Worker BCJ2_STREAM_RC 19*f6dc9357SAndroid Build Coastguard Worker }; 20*f6dc9357SAndroid Build Coastguard Worker 21*f6dc9357SAndroid Build Coastguard Worker enum 22*f6dc9357SAndroid Build Coastguard Worker { 23*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ORIG_0 = BCJ2_NUM_STREAMS, 24*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ORIG_1, 25*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ORIG_2, 26*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ORIG_3, 27*f6dc9357SAndroid Build Coastguard Worker 28*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ORIG, 29*f6dc9357SAndroid Build Coastguard Worker BCJ2_DEC_STATE_ERROR /* after detected data error */ 30*f6dc9357SAndroid Build Coastguard Worker }; 31*f6dc9357SAndroid Build Coastguard Worker 32*f6dc9357SAndroid Build Coastguard Worker enum 33*f6dc9357SAndroid Build Coastguard Worker { 34*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_STATE_ORIG = BCJ2_NUM_STREAMS, 35*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_STATE_FINISHED /* it's state after fully encoded stream */ 36*f6dc9357SAndroid Build Coastguard Worker }; 37*f6dc9357SAndroid Build Coastguard Worker 38*f6dc9357SAndroid Build Coastguard Worker 39*f6dc9357SAndroid Build Coastguard Worker /* #define BCJ2_IS_32BIT_STREAM(s) ((s) == BCJ2_STREAM_CALL || (s) == BCJ2_STREAM_JUMP) */ 40*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_IS_32BIT_STREAM(s) ((unsigned)((unsigned)(s) - (unsigned)BCJ2_STREAM_CALL) < 2) 41*f6dc9357SAndroid Build Coastguard Worker 42*f6dc9357SAndroid Build Coastguard Worker /* 43*f6dc9357SAndroid Build Coastguard Worker CBcj2Dec / CBcj2Enc 44*f6dc9357SAndroid Build Coastguard Worker bufs sizes: 45*f6dc9357SAndroid Build Coastguard Worker BUF_SIZE(n) = lims[n] - bufs[n] 46*f6dc9357SAndroid Build Coastguard Worker bufs sizes for BCJ2_STREAM_CALL and BCJ2_STREAM_JUMP must be multiply of 4: 47*f6dc9357SAndroid Build Coastguard Worker (BUF_SIZE(BCJ2_STREAM_CALL) & 3) == 0 48*f6dc9357SAndroid Build Coastguard Worker (BUF_SIZE(BCJ2_STREAM_JUMP) & 3) == 0 49*f6dc9357SAndroid Build Coastguard Worker */ 50*f6dc9357SAndroid Build Coastguard Worker 51*f6dc9357SAndroid Build Coastguard Worker // typedef UInt32 CBcj2Prob; 52*f6dc9357SAndroid Build Coastguard Worker typedef UInt16 CBcj2Prob; 53*f6dc9357SAndroid Build Coastguard Worker 54*f6dc9357SAndroid Build Coastguard Worker /* 55*f6dc9357SAndroid Build Coastguard Worker BCJ2 encoder / decoder internal requirements: 56*f6dc9357SAndroid Build Coastguard Worker - If last bytes of stream contain marker (e8/e8/0f8x), then 57*f6dc9357SAndroid Build Coastguard Worker there is also encoded symbol (0 : no conversion) in RC stream. 58*f6dc9357SAndroid Build Coastguard Worker - One case of overlapped instructions is supported, 59*f6dc9357SAndroid Build Coastguard Worker if last byte of converted instruction is (0f) and next byte is (8x): 60*f6dc9357SAndroid Build Coastguard Worker marker [xx xx xx 0f] 8x 61*f6dc9357SAndroid Build Coastguard Worker then the pair (0f 8x) is treated as marker. 62*f6dc9357SAndroid Build Coastguard Worker */ 63*f6dc9357SAndroid Build Coastguard Worker 64*f6dc9357SAndroid Build Coastguard Worker /* ---------- BCJ2 Decoder ---------- */ 65*f6dc9357SAndroid Build Coastguard Worker 66*f6dc9357SAndroid Build Coastguard Worker /* 67*f6dc9357SAndroid Build Coastguard Worker CBcj2Dec: 68*f6dc9357SAndroid Build Coastguard Worker (dest) is allowed to overlap with bufs[BCJ2_STREAM_MAIN], with the following conditions: 69*f6dc9357SAndroid Build Coastguard Worker bufs[BCJ2_STREAM_MAIN] >= dest && 70*f6dc9357SAndroid Build Coastguard Worker bufs[BCJ2_STREAM_MAIN] - dest >= 71*f6dc9357SAndroid Build Coastguard Worker BUF_SIZE(BCJ2_STREAM_CALL) + 72*f6dc9357SAndroid Build Coastguard Worker BUF_SIZE(BCJ2_STREAM_JUMP) 73*f6dc9357SAndroid Build Coastguard Worker reserve = bufs[BCJ2_STREAM_MAIN] - dest - 74*f6dc9357SAndroid Build Coastguard Worker ( BUF_SIZE(BCJ2_STREAM_CALL) + 75*f6dc9357SAndroid Build Coastguard Worker BUF_SIZE(BCJ2_STREAM_JUMP) ) 76*f6dc9357SAndroid Build Coastguard Worker and additional conditions: 77*f6dc9357SAndroid Build Coastguard Worker if (it's first call of Bcj2Dec_Decode() after Bcj2Dec_Init()) 78*f6dc9357SAndroid Build Coastguard Worker { 79*f6dc9357SAndroid Build Coastguard Worker (reserve != 1) : if (ver < v23.00) 80*f6dc9357SAndroid Build Coastguard Worker } 81*f6dc9357SAndroid Build Coastguard Worker else // if there are more than one calls of Bcj2Dec_Decode() after Bcj2Dec_Init()) 82*f6dc9357SAndroid Build Coastguard Worker { 83*f6dc9357SAndroid Build Coastguard Worker (reserve >= 6) : if (ver < v23.00) 84*f6dc9357SAndroid Build Coastguard Worker (reserve >= 4) : if (ver >= v23.00) 85*f6dc9357SAndroid Build Coastguard Worker We need that (reserve) because after first call of Bcj2Dec_Decode(), 86*f6dc9357SAndroid Build Coastguard Worker CBcj2Dec::temp can contain up to 4 bytes for writing to (dest). 87*f6dc9357SAndroid Build Coastguard Worker } 88*f6dc9357SAndroid Build Coastguard Worker (reserve == 0) is allowed, if we decode full stream via single call of Bcj2Dec_Decode(). 89*f6dc9357SAndroid Build Coastguard Worker (reserve == 0) also is allowed in case of multi-call, if we use fixed buffers, 90*f6dc9357SAndroid Build Coastguard Worker and (reserve) is calculated from full (final) sizes of all streams before first call. 91*f6dc9357SAndroid Build Coastguard Worker */ 92*f6dc9357SAndroid Build Coastguard Worker 93*f6dc9357SAndroid Build Coastguard Worker typedef struct 94*f6dc9357SAndroid Build Coastguard Worker { 95*f6dc9357SAndroid Build Coastguard Worker const Byte *bufs[BCJ2_NUM_STREAMS]; 96*f6dc9357SAndroid Build Coastguard Worker const Byte *lims[BCJ2_NUM_STREAMS]; 97*f6dc9357SAndroid Build Coastguard Worker Byte *dest; 98*f6dc9357SAndroid Build Coastguard Worker const Byte *destLim; 99*f6dc9357SAndroid Build Coastguard Worker 100*f6dc9357SAndroid Build Coastguard Worker unsigned state; /* BCJ2_STREAM_MAIN has more priority than BCJ2_STATE_ORIG */ 101*f6dc9357SAndroid Build Coastguard Worker 102*f6dc9357SAndroid Build Coastguard Worker UInt32 ip; /* property of starting base for decoding */ 103*f6dc9357SAndroid Build Coastguard Worker UInt32 temp; /* Byte temp[4]; */ 104*f6dc9357SAndroid Build Coastguard Worker UInt32 range; 105*f6dc9357SAndroid Build Coastguard Worker UInt32 code; 106*f6dc9357SAndroid Build Coastguard Worker CBcj2Prob probs[2 + 256]; 107*f6dc9357SAndroid Build Coastguard Worker } CBcj2Dec; 108*f6dc9357SAndroid Build Coastguard Worker 109*f6dc9357SAndroid Build Coastguard Worker 110*f6dc9357SAndroid Build Coastguard Worker /* Note: 111*f6dc9357SAndroid Build Coastguard Worker Bcj2Dec_Init() sets (CBcj2Dec::ip = 0) 112*f6dc9357SAndroid Build Coastguard Worker if (ip != 0) property is required, the caller must set CBcj2Dec::ip after Bcj2Dec_Init() 113*f6dc9357SAndroid Build Coastguard Worker */ 114*f6dc9357SAndroid Build Coastguard Worker void Bcj2Dec_Init(CBcj2Dec *p); 115*f6dc9357SAndroid Build Coastguard Worker 116*f6dc9357SAndroid Build Coastguard Worker 117*f6dc9357SAndroid Build Coastguard Worker /* Bcj2Dec_Decode(): 118*f6dc9357SAndroid Build Coastguard Worker returns: 119*f6dc9357SAndroid Build Coastguard Worker SZ_OK 120*f6dc9357SAndroid Build Coastguard Worker SZ_ERROR_DATA : if data in 5 starting bytes of BCJ2_STREAM_RC stream are not correct 121*f6dc9357SAndroid Build Coastguard Worker */ 122*f6dc9357SAndroid Build Coastguard Worker SRes Bcj2Dec_Decode(CBcj2Dec *p); 123*f6dc9357SAndroid Build Coastguard Worker 124*f6dc9357SAndroid Build Coastguard Worker /* To check that decoding was finished you can compare 125*f6dc9357SAndroid Build Coastguard Worker sizes of processed streams with sizes known from another sources. 126*f6dc9357SAndroid Build Coastguard Worker You must do at least one mandatory check from the two following options: 127*f6dc9357SAndroid Build Coastguard Worker - the check for size of processed output (ORIG) stream. 128*f6dc9357SAndroid Build Coastguard Worker - the check for size of processed input (MAIN) stream. 129*f6dc9357SAndroid Build Coastguard Worker additional optional checks: 130*f6dc9357SAndroid Build Coastguard Worker - the checks for processed sizes of all input streams (MAIN, CALL, JUMP, RC) 131*f6dc9357SAndroid Build Coastguard Worker - the checks Bcj2Dec_IsMaybeFinished*() 132*f6dc9357SAndroid Build Coastguard Worker also before actual decoding you can check that the 133*f6dc9357SAndroid Build Coastguard Worker following condition is met for stream sizes: 134*f6dc9357SAndroid Build Coastguard Worker ( size(ORIG) == size(MAIN) + size(CALL) + size(JUMP) ) 135*f6dc9357SAndroid Build Coastguard Worker */ 136*f6dc9357SAndroid Build Coastguard Worker 137*f6dc9357SAndroid Build Coastguard Worker /* (state == BCJ2_STREAM_MAIN) means that decoder is ready for 138*f6dc9357SAndroid Build Coastguard Worker additional input data in BCJ2_STREAM_MAIN stream. 139*f6dc9357SAndroid Build Coastguard Worker Note that (state == BCJ2_STREAM_MAIN) is allowed for non-finished decoding. 140*f6dc9357SAndroid Build Coastguard Worker */ 141*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) ((_p_)->state == BCJ2_STREAM_MAIN) 142*f6dc9357SAndroid Build Coastguard Worker 143*f6dc9357SAndroid Build Coastguard Worker /* if the stream decoding was finished correctly, then range decoder 144*f6dc9357SAndroid Build Coastguard Worker part of CBcj2Dec also was finished, and then (CBcj2Dec::code == 0). 145*f6dc9357SAndroid Build Coastguard Worker Note that (CBcj2Dec::code == 0) is allowed for non-finished decoding. 146*f6dc9357SAndroid Build Coastguard Worker */ 147*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Dec_IsMaybeFinished_code(_p_) ((_p_)->code == 0) 148*f6dc9357SAndroid Build Coastguard Worker 149*f6dc9357SAndroid Build Coastguard Worker /* use Bcj2Dec_IsMaybeFinished() only as additional check 150*f6dc9357SAndroid Build Coastguard Worker after at least one mandatory check from the two following options: 151*f6dc9357SAndroid Build Coastguard Worker - the check for size of processed output (ORIG) stream. 152*f6dc9357SAndroid Build Coastguard Worker - the check for size of processed input (MAIN) stream. 153*f6dc9357SAndroid Build Coastguard Worker */ 154*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Dec_IsMaybeFinished(_p_) ( \ 155*f6dc9357SAndroid Build Coastguard Worker Bcj2Dec_IsMaybeFinished_state_MAIN(_p_) && \ 156*f6dc9357SAndroid Build Coastguard Worker Bcj2Dec_IsMaybeFinished_code(_p_)) 157*f6dc9357SAndroid Build Coastguard Worker 158*f6dc9357SAndroid Build Coastguard Worker 159*f6dc9357SAndroid Build Coastguard Worker 160*f6dc9357SAndroid Build Coastguard Worker /* ---------- BCJ2 Encoder ---------- */ 161*f6dc9357SAndroid Build Coastguard Worker 162*f6dc9357SAndroid Build Coastguard Worker typedef enum 163*f6dc9357SAndroid Build Coastguard Worker { 164*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_CONTINUE, 165*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_END_BLOCK, 166*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_END_STREAM 167*f6dc9357SAndroid Build Coastguard Worker } EBcj2Enc_FinishMode; 168*f6dc9357SAndroid Build Coastguard Worker 169*f6dc9357SAndroid Build Coastguard Worker /* 170*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_CONTINUE: 171*f6dc9357SAndroid Build Coastguard Worker process non finished encoding. 172*f6dc9357SAndroid Build Coastguard Worker It notifies the encoder that additional further calls 173*f6dc9357SAndroid Build Coastguard Worker can provide more input data (src) than provided by current call. 174*f6dc9357SAndroid Build Coastguard Worker In that case the CBcj2Enc encoder still can move (src) pointer 175*f6dc9357SAndroid Build Coastguard Worker up to (srcLim), but CBcj2Enc encoder can store some of the last 176*f6dc9357SAndroid Build Coastguard Worker processed bytes (up to 4 bytes) from src to internal CBcj2Enc::temp[] buffer. 177*f6dc9357SAndroid Build Coastguard Worker at return: 178*f6dc9357SAndroid Build Coastguard Worker (CBcj2Enc::src will point to position that includes 179*f6dc9357SAndroid Build Coastguard Worker processed data and data copied to (temp[]) buffer) 180*f6dc9357SAndroid Build Coastguard Worker That data from (temp[]) buffer will be used in further calls. 181*f6dc9357SAndroid Build Coastguard Worker 182*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_END_BLOCK: 183*f6dc9357SAndroid Build Coastguard Worker finish encoding of current block (ended at srcLim) without RC flushing. 184*f6dc9357SAndroid Build Coastguard Worker at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_ORIG) && 185*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc::src == CBcj2Enc::srcLim) 186*f6dc9357SAndroid Build Coastguard Worker : it shows that block encoding was finished. And the encoder is 187*f6dc9357SAndroid Build Coastguard Worker ready for new (src) data or for stream finish operation. 188*f6dc9357SAndroid Build Coastguard Worker finished block means 189*f6dc9357SAndroid Build Coastguard Worker { 190*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc has completed block encoding up to (srcLim). 191*f6dc9357SAndroid Build Coastguard Worker (1 + 4 bytes) or (2 + 4 bytes) CALL/JUMP cortages will 192*f6dc9357SAndroid Build Coastguard Worker not cross block boundary at (srcLim). 193*f6dc9357SAndroid Build Coastguard Worker temporary CBcj2Enc buffer for (ORIG) src data is empty. 194*f6dc9357SAndroid Build Coastguard Worker 3 output uncompressed streams (MAIN, CALL, JUMP) were flushed. 195*f6dc9357SAndroid Build Coastguard Worker RC stream was not flushed. And RC stream will cross block boundary. 196*f6dc9357SAndroid Build Coastguard Worker } 197*f6dc9357SAndroid Build Coastguard Worker Note: some possible implementation of BCJ2 encoder could 198*f6dc9357SAndroid Build Coastguard Worker write branch marker (e8/e8/0f8x) in one call of Bcj2Enc_Encode(), 199*f6dc9357SAndroid Build Coastguard Worker and it could calculate symbol for RC in another call of Bcj2Enc_Encode(). 200*f6dc9357SAndroid Build Coastguard Worker BCJ2 encoder uses ip/fileIp/fileSize/relatLimit values to calculate RC symbol. 201*f6dc9357SAndroid Build Coastguard Worker And these CBcj2Enc variables can have different values in different Bcj2Enc_Encode() calls. 202*f6dc9357SAndroid Build Coastguard Worker So caller must finish each block with BCJ2_ENC_FINISH_MODE_END_BLOCK 203*f6dc9357SAndroid Build Coastguard Worker to ensure that RC symbol is calculated and written in proper block. 204*f6dc9357SAndroid Build Coastguard Worker 205*f6dc9357SAndroid Build Coastguard Worker BCJ2_ENC_FINISH_MODE_END_STREAM 206*f6dc9357SAndroid Build Coastguard Worker finish encoding of stream (ended at srcLim) fully including RC flushing. 207*f6dc9357SAndroid Build Coastguard Worker at return: if (CBcj2Enc::state == BCJ2_ENC_STATE_FINISHED) 208*f6dc9357SAndroid Build Coastguard Worker : it shows that stream encoding was finished fully, 209*f6dc9357SAndroid Build Coastguard Worker and all output streams were flushed fully. 210*f6dc9357SAndroid Build Coastguard Worker also Bcj2Enc_IsFinished() can be called. 211*f6dc9357SAndroid Build Coastguard Worker */ 212*f6dc9357SAndroid Build Coastguard Worker 213*f6dc9357SAndroid Build Coastguard Worker 214*f6dc9357SAndroid Build Coastguard Worker /* 215*f6dc9357SAndroid Build Coastguard Worker 32-bit relative offset in JUMP/CALL commands is 216*f6dc9357SAndroid Build Coastguard Worker - (mod 4 GiB) for 32-bit x86 code 217*f6dc9357SAndroid Build Coastguard Worker - signed Int32 for 64-bit x86-64 code 218*f6dc9357SAndroid Build Coastguard Worker BCJ2 encoder also does internal relative to absolute address conversions. 219*f6dc9357SAndroid Build Coastguard Worker And there are 2 possible ways to do it: 220*f6dc9357SAndroid Build Coastguard Worker before v23: we used 32-bit variables and (mod 4 GiB) conversion 221*f6dc9357SAndroid Build Coastguard Worker since v23: we use 64-bit variables and (signed Int32 offset) conversion. 222*f6dc9357SAndroid Build Coastguard Worker The absolute address condition for conversion in v23: 223*f6dc9357SAndroid Build Coastguard Worker ((UInt64)((Int64)ip64 - (Int64)fileIp64 + 5 + (Int32)offset) < (UInt64)fileSize64) 224*f6dc9357SAndroid Build Coastguard Worker note that if (fileSize64 > 2 GiB). there is difference between 225*f6dc9357SAndroid Build Coastguard Worker old (mod 4 GiB) way (v22) and new (signed Int32 offset) way (v23). 226*f6dc9357SAndroid Build Coastguard Worker And new (v23) way is more suitable to encode 64-bit x86-64 code for (fileSize64 > 2 GiB) cases. 227*f6dc9357SAndroid Build Coastguard Worker */ 228*f6dc9357SAndroid Build Coastguard Worker 229*f6dc9357SAndroid Build Coastguard Worker /* 230*f6dc9357SAndroid Build Coastguard Worker // for old (v22) way for conversion: 231*f6dc9357SAndroid Build Coastguard Worker typedef UInt32 CBcj2Enc_ip_unsigned; 232*f6dc9357SAndroid Build Coastguard Worker typedef Int32 CBcj2Enc_ip_signed; 233*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_FileSize_MAX ((UInt32)1 << 31) 234*f6dc9357SAndroid Build Coastguard Worker */ 235*f6dc9357SAndroid Build Coastguard Worker typedef UInt64 CBcj2Enc_ip_unsigned; 236*f6dc9357SAndroid Build Coastguard Worker typedef Int64 CBcj2Enc_ip_signed; 237*f6dc9357SAndroid Build Coastguard Worker 238*f6dc9357SAndroid Build Coastguard Worker /* maximum size of file that can be used for conversion condition */ 239*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_FileSize_MAX ((CBcj2Enc_ip_unsigned)0 - 2) 240*f6dc9357SAndroid Build Coastguard Worker 241*f6dc9357SAndroid Build Coastguard Worker /* default value of fileSize64_minus1 variable that means 242*f6dc9357SAndroid Build Coastguard Worker that absolute address limitation will not be used */ 243*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_FileSizeField_UNLIMITED ((CBcj2Enc_ip_unsigned)0 - 1) 244*f6dc9357SAndroid Build Coastguard Worker 245*f6dc9357SAndroid Build Coastguard Worker /* calculate value that later can be set to CBcj2Enc::fileSize64_minus1 */ 246*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize) \ 247*f6dc9357SAndroid Build Coastguard Worker ((CBcj2Enc_ip_unsigned)(fileSize) - 1) 248*f6dc9357SAndroid Build Coastguard Worker 249*f6dc9357SAndroid Build Coastguard Worker /* set CBcj2Enc::fileSize64_minus1 variable from size of file */ 250*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Enc_SET_FileSize(p, fileSize) \ 251*f6dc9357SAndroid Build Coastguard Worker (p)->fileSize64_minus1 = BCJ2_ENC_GET_FileSizeField_VAL_FROM_FileSize(fileSize); 252*f6dc9357SAndroid Build Coastguard Worker 253*f6dc9357SAndroid Build Coastguard Worker 254*f6dc9357SAndroid Build Coastguard Worker typedef struct 255*f6dc9357SAndroid Build Coastguard Worker { 256*f6dc9357SAndroid Build Coastguard Worker Byte *bufs[BCJ2_NUM_STREAMS]; 257*f6dc9357SAndroid Build Coastguard Worker const Byte *lims[BCJ2_NUM_STREAMS]; 258*f6dc9357SAndroid Build Coastguard Worker const Byte *src; 259*f6dc9357SAndroid Build Coastguard Worker const Byte *srcLim; 260*f6dc9357SAndroid Build Coastguard Worker 261*f6dc9357SAndroid Build Coastguard Worker unsigned state; 262*f6dc9357SAndroid Build Coastguard Worker EBcj2Enc_FinishMode finishMode; 263*f6dc9357SAndroid Build Coastguard Worker 264*f6dc9357SAndroid Build Coastguard Worker Byte context; 265*f6dc9357SAndroid Build Coastguard Worker Byte flushRem; 266*f6dc9357SAndroid Build Coastguard Worker Byte isFlushState; 267*f6dc9357SAndroid Build Coastguard Worker 268*f6dc9357SAndroid Build Coastguard Worker Byte cache; 269*f6dc9357SAndroid Build Coastguard Worker UInt32 range; 270*f6dc9357SAndroid Build Coastguard Worker UInt64 low; 271*f6dc9357SAndroid Build Coastguard Worker UInt64 cacheSize; 272*f6dc9357SAndroid Build Coastguard Worker 273*f6dc9357SAndroid Build Coastguard Worker // UInt32 context; // for marker version, it can include marker flag. 274*f6dc9357SAndroid Build Coastguard Worker 275*f6dc9357SAndroid Build Coastguard Worker /* (ip64) and (fileIp64) correspond to virtual source stream position 276*f6dc9357SAndroid Build Coastguard Worker that doesn't include data in temp[] */ 277*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc_ip_unsigned ip64; /* current (ip) position */ 278*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc_ip_unsigned fileIp64; /* start (ip) position of current file */ 279*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc_ip_unsigned fileSize64_minus1; /* size of current file (for conversion limitation) */ 280*f6dc9357SAndroid Build Coastguard Worker UInt32 relatLimit; /* (relatLimit <= ((UInt32)1 << 31)) : 0 means disable_conversion */ 281*f6dc9357SAndroid Build Coastguard Worker // UInt32 relatExcludeBits; 282*f6dc9357SAndroid Build Coastguard Worker 283*f6dc9357SAndroid Build Coastguard Worker UInt32 tempTarget; 284*f6dc9357SAndroid Build Coastguard Worker unsigned tempPos; /* the number of bytes that were copied to temp[] buffer 285*f6dc9357SAndroid Build Coastguard Worker (tempPos <= 4) outside of Bcj2Enc_Encode() */ 286*f6dc9357SAndroid Build Coastguard Worker // Byte temp[4]; // for marker version 287*f6dc9357SAndroid Build Coastguard Worker Byte temp[8]; 288*f6dc9357SAndroid Build Coastguard Worker CBcj2Prob probs[2 + 256]; 289*f6dc9357SAndroid Build Coastguard Worker } CBcj2Enc; 290*f6dc9357SAndroid Build Coastguard Worker 291*f6dc9357SAndroid Build Coastguard Worker void Bcj2Enc_Init(CBcj2Enc *p); 292*f6dc9357SAndroid Build Coastguard Worker 293*f6dc9357SAndroid Build Coastguard Worker 294*f6dc9357SAndroid Build Coastguard Worker /* 295*f6dc9357SAndroid Build Coastguard Worker Bcj2Enc_Encode(): at exit: 296*f6dc9357SAndroid Build Coastguard Worker p->State < BCJ2_NUM_STREAMS : we need more buffer space for output stream 297*f6dc9357SAndroid Build Coastguard Worker (bufs[p->State] == lims[p->State]) 298*f6dc9357SAndroid Build Coastguard Worker p->State == BCJ2_ENC_STATE_ORIG : we need more data in input src stream 299*f6dc9357SAndroid Build Coastguard Worker (src == srcLim) 300*f6dc9357SAndroid Build Coastguard Worker p->State == BCJ2_ENC_STATE_FINISHED : after fully encoded stream 301*f6dc9357SAndroid Build Coastguard Worker */ 302*f6dc9357SAndroid Build Coastguard Worker void Bcj2Enc_Encode(CBcj2Enc *p); 303*f6dc9357SAndroid Build Coastguard Worker 304*f6dc9357SAndroid Build Coastguard Worker /* Bcj2Enc encoder can look ahead for up 4 bytes of source stream. 305*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc::tempPos : is the number of bytes that were copied from input stream to temp[] buffer. 306*f6dc9357SAndroid Build Coastguard Worker (CBcj2Enc::src) after Bcj2Enc_Encode() is starting position after 307*f6dc9357SAndroid Build Coastguard Worker fully processed data and after data copied to temp buffer. 308*f6dc9357SAndroid Build Coastguard Worker So if the caller needs to get real number of fully processed input 309*f6dc9357SAndroid Build Coastguard Worker bytes (without look ahead data in temp buffer), 310*f6dc9357SAndroid Build Coastguard Worker the caller must subtruct (CBcj2Enc::tempPos) value from processed size 311*f6dc9357SAndroid Build Coastguard Worker value that is calculated based on current (CBcj2Enc::src): 312*f6dc9357SAndroid Build Coastguard Worker cur_processed_pos = Calc_Big_Processed_Pos(enc.src)) - 313*f6dc9357SAndroid Build Coastguard Worker Bcj2Enc_Get_AvailInputSize_in_Temp(&enc); 314*f6dc9357SAndroid Build Coastguard Worker */ 315*f6dc9357SAndroid Build Coastguard Worker /* get the size of input data that was stored in temp[] buffer: */ 316*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Enc_Get_AvailInputSize_in_Temp(p) ((p)->tempPos) 317*f6dc9357SAndroid Build Coastguard Worker 318*f6dc9357SAndroid Build Coastguard Worker #define Bcj2Enc_IsFinished(p) ((p)->flushRem == 0) 319*f6dc9357SAndroid Build Coastguard Worker 320*f6dc9357SAndroid Build Coastguard Worker /* Note : the decoder supports overlapping of marker (0f 80). 321*f6dc9357SAndroid Build Coastguard Worker But we can eliminate such overlapping cases by setting 322*f6dc9357SAndroid Build Coastguard Worker the limit for relative offset conversion as 323*f6dc9357SAndroid Build Coastguard Worker CBcj2Enc::relatLimit <= (0x0f << 24) == (240 MiB) 324*f6dc9357SAndroid Build Coastguard Worker */ 325*f6dc9357SAndroid Build Coastguard Worker /* default value for CBcj2Enc::relatLimit */ 326*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_RELAT_LIMIT_DEFAULT ((UInt32)0x0f << 24) 327*f6dc9357SAndroid Build Coastguard Worker #define BCJ2_ENC_RELAT_LIMIT_MAX ((UInt32)1 << 31) 328*f6dc9357SAndroid Build Coastguard Worker // #define BCJ2_RELAT_EXCLUDE_NUM_BITS 5 329*f6dc9357SAndroid Build Coastguard Worker 330*f6dc9357SAndroid Build Coastguard Worker EXTERN_C_END 331*f6dc9357SAndroid Build Coastguard Worker 332*f6dc9357SAndroid Build Coastguard Worker #endif 333