This function searches for a repetition (a previous occurence of the current byte sequence) Returns length of the repetition, and stores the backward distance to pWork structure.
| 245 | // Returns length of the repetition, and stores the backward distance |
| 246 | // to pWork structure. |
| 247 | static unsigned int PKWAREAPI FindRep(TCmpStruct * pWork, unsigned char * input_data) |
| 248 | { |
| 249 | unsigned short * phash_to_index; // Pointer into pWork->phash_to_index table |
| 250 | unsigned short * phash_offs; // Pointer to the table containing offsets of each PAIR_HASH |
| 251 | unsigned char * repetition_limit; // An eventual repetition must be at position below this pointer |
| 252 | unsigned char * prev_repetition; // Pointer to the previous occurence of the current PAIR_HASH |
| 253 | unsigned char * prev_rep_end; // End of the previous repetition |
| 254 | unsigned char * input_data_ptr; |
| 255 | unsigned short phash_offs_index; // Index to the table with PAIR_HASH positions |
| 256 | unsigned short min_phash_offs; // The lowest allowed hash offset |
| 257 | unsigned short offs_in_rep; // Offset within found repetition |
| 258 | unsigned int equal_byte_count; // Number of bytes that are equal to the previous occurence |
| 259 | unsigned int rep_length = 1; // Length of the found repetition |
| 260 | unsigned int rep_length2; // Secondary repetition |
| 261 | unsigned char pre_last_byte; // Last but one byte from a repetion |
| 262 | unsigned short di_val; |
| 263 | |
| 264 | // Calculate the previous position of the PAIR_HASH |
| 265 | phash_to_index = pWork->phash_to_index + BYTE_PAIR_HASH(input_data); |
| 266 | min_phash_offs = (unsigned short)((input_data - pWork->work_buff) - pWork->dsize_bytes + 1); |
| 267 | phash_offs_index = phash_to_index[0]; |
| 268 | |
| 269 | // If the PAIR_HASH offset is below the limit, find a next one |
| 270 | phash_offs = pWork->phash_offs + phash_offs_index; |
| 271 | if(*phash_offs < min_phash_offs) |
| 272 | { |
| 273 | while(*phash_offs < min_phash_offs) |
| 274 | { |
| 275 | phash_offs_index++; |
| 276 | phash_offs++; |
| 277 | } |
| 278 | *phash_to_index = phash_offs_index; |
| 279 | } |
| 280 | |
| 281 | // Get the first location of the PAIR_HASH, |
| 282 | // and thus the first eventual location of byte repetition |
| 283 | phash_offs = pWork->phash_offs + phash_offs_index; |
| 284 | prev_repetition = pWork->work_buff + phash_offs[0]; |
| 285 | repetition_limit = input_data - 1; |
| 286 | |
| 287 | // If the current PAIR_HASH was not encountered before, |
| 288 | // we haven't found a repetition. |
| 289 | if(prev_repetition >= repetition_limit) |
| 290 | return 0; |
| 291 | |
| 292 | // We have found a match of a PAIR_HASH. Now we have to make sure |
| 293 | // that it is also a byte match, because PAIR_HASH is not unique. |
| 294 | // We compare the bytes and count the length of the repetition |
| 295 | input_data_ptr = input_data; |
| 296 | for(;;) |
| 297 | { |
| 298 | // If the first byte of the repetition and the so-far-last byte |
| 299 | // of the repetition are equal, we will compare the blocks. |
| 300 | if(*input_data_ptr == *prev_repetition && input_data_ptr[rep_length-1] == prev_repetition[rep_length-1]) |
| 301 | { |
| 302 | // Skip the current byte |
| 303 | prev_repetition++; |
| 304 | input_data_ptr++; |