void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double matchProba, void* litTable, unsigned* seedPtr) { BYTE* buffPtr = (BYTE*)buffer; const U32 matchProba32 = (U32)(32768 * matchProba); size_t pos = prefixSize; void* ldctx = litTable; U32* seed = seedPtr; /* special case */ while (matchProba >= 1.0) { size_t size0 = RDG_rand(seed) & 3; size0 = (size_t)1 << (16 + size0 * 2); size0 += RDG_rand(seed) & (size0-1); /* because size0 is power of 2*/ if (buffSize < pos + size0) { memset(buffPtr+pos, 0, buffSize-pos); return; } memset(buffPtr+pos, 0, size0); pos += size0; buffPtr[pos-1] = RDG_genChar(seed, ldctx); } /* init */ if (pos==0) buffPtr[0] = RDG_genChar(seed, ldctx), pos=1; /* Generate compressible data */ while (pos < buffSize) { /* Select : Literal (char) or Match (within 32K) */ if (RDG_RAND15BITS < matchProba32) { /* Copy (within 32K) */ size_t match; size_t d; int length = RDG_RANDLENGTH + 4; U32 offset = RDG_RAND15BITS + 1; if (offset > pos) offset = (U32)pos; match = pos - offset; d = pos + length; if (d > buffSize) d = buffSize; while (pos < d) buffPtr[pos++] = buffPtr[match++]; } else { /* Literal (noise) */ size_t d; size_t length = RDG_RANDLENGTH; d = pos + length; if (d > buffSize) d = buffSize; while (pos < d) buffPtr[pos++] = RDG_genChar(seed, ldctx); } } }
static BYTE RDG_genChar(U32* seed, const BYTE* ldt) { U32 const id = RDG_rand(seed) & LTMASK; //TRACE(" %u : \n", id); //TRACE(" %4u [%4u] ; val : %4u \n", id, id&255, ldt[id]); return ldt[id]; /* memory-sanitizer fails here, stating "uninitialized value" when table initialized with P==0.0. Checked : table is fully initialized */ }
void RDG_genBlock(void* buffer, size_t buffSize, size_t prefixSize, double matchProba, const BYTE* ldt, unsigned* seedPtr) { BYTE* const buffPtr = (BYTE*)buffer; U32 const matchProba32 = (U32)(32768 * matchProba); size_t pos = prefixSize; U32 prevOffset = 1; /* special case : sparse content */ while (matchProba >= 1.0) { size_t size0 = RDG_rand(seedPtr) & 3; size0 = (size_t)1 << (16 + size0 * 2); size0 += RDG_rand(seedPtr) & (size0-1); /* because size0 is power of 2*/ if (buffSize < pos + size0) { memset(buffPtr+pos, 0, buffSize-pos); return; } memset(buffPtr+pos, 0, size0); pos += size0; buffPtr[pos-1] = RDG_genChar(seedPtr, ldt); continue; } /* init */ if (pos==0) buffPtr[0] = RDG_genChar(seedPtr, ldt), pos=1; /* Generate compressible data */ while (pos < buffSize) { /* Select : Literal (char) or Match (within 32K) */ if (RDG_rand15Bits(seedPtr) < matchProba32) { /* Copy (within 32K) */ U32 const length = RDG_randLength(seedPtr) + 4; U32 const d = (U32) MIN(pos + length , buffSize); U32 const repeatOffset = (RDG_rand(seedPtr) & 15) == 2; U32 const randOffset = RDG_rand15Bits(seedPtr) + 1; U32 const offset = repeatOffset ? prevOffset : (U32) MIN(randOffset , pos); size_t match = pos - offset; //TRACE("pos : %u; offset: %u ; length : %u \n", (U32)pos, offset, length); while (pos < d) buffPtr[pos++] = buffPtr[match++]; /* correctly manages overlaps */ prevOffset = offset; } else { /* Literal (noise) */ U32 const length = RDG_randLength(seedPtr); U32 const d = (U32) MIN(pos + length, buffSize); while (pos < d) buffPtr[pos++] = RDG_genChar(seedPtr, ldt); } } }
static U32 RDG_randLength(unsigned* seedPtr) { if (RDG_rand(seedPtr) & 7) return (RDG_rand(seedPtr) & 0xF); /* small length */ return (RDG_rand(seedPtr) & 0x1FF) + 0xF; }
static U32 RDG_rand15Bits (unsigned* seedPtr) { return RDG_rand(seedPtr) & 0x7FFF; }
static char RDG_genChar(U32* seed, const void* ltctx) { const BYTE* lt = (const BYTE*)ltctx; U32 id = RDG_rand(seed) & LTMASK; return lt[id]; }
static BYTE RDG_genChar(U32* seed, const litDistribTable lt) { U32 id = RDG_rand(seed) & LTMASK; return (lt[id]); }