/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "base/polygraph.h"
#include "xstd/h/iostream.h"
#include "xstd/h/sstream.h"
#include "runtime/IOBuf.h"
#include "csm/CdbBodyIter.h"
#include "csm/TextDbase.h"
#include "csm/InjectIter.h"
#include "base/RndPermut.h"
#include "xstd/gadgets.h"
void InjectIter::reset() {
theCreator = 0;
theTdb = 0;
theBodyIter = 0;
theInjGap = 0;
theInjOff = Size();
theTdbPos = -1;
incInjOff = true;
}
void InjectIter::start(CdbBodyIter *aBodyIter) {
Assert(theTdb && theTdb->count());
Assert(!theBodyIter && aBodyIter);
theBodyIter = aBodyIter;
theTdbPosGen.seed(GlbPermut(theBodyIter->contentHash(), rndInjTbdPos));
theInjGap->rndGen()->seed(GlbPermut(theBodyIter->contentHash(), rndInjOff));
theInjOff = 0;
}
void InjectIter::inject(WrBuf &buf, Size areaOff, Size areaLen) {
do {
// get next injection position if needed
if (incInjOff) {
// XXX: this may overflow, borrow from SrvXact
theInjOff += (Size)(int)rint(theInjGap->trial());
incInjOff = false;
}
// get next injection text if needed
if (theTdbPos < 0)
theTdbPos = theTdbPosGen(0, theTdb->count());
const Size injLen = theTdb->len(theTdbPos);
// will it fit?
if (injLen <= areaLen) {
const Size bufEnd = theBodyIter->builtSize() + areaOff + areaLen;
const Size offMax = bufEnd - injLen;
// is it time to inject?
if (theInjOff <= offMax) {
const Size bufOff = Min(areaLen, bufEnd - theInjOff);
Assert(buf.contSize() >= bufOff);
buf.overwrite(buf.contSize() - bufOff,
theTdb->str(theTdbPos), injLen);
// reset cache after we used up the values
incInjOff = true;
theTdbPos = -1;
// prevent injections from overlapping
theInjOff = bufEnd - bufOff + injLen;
}
}
} while (incInjOff);
}
syntax highlighted by Code2HTML, v. 0.9.1