*/
#include <algorithm>
+#include <cassert>
#include "base/intmath.hh"
#include "base/types.hh"
Addr nextAddr;
/** The size of the current chunk (in bytes). */
Addr curSize;
+ /** The size of the next chunk (in bytes). */
+ Addr nextSize;
/** The number of bytes remaining in the region after the current chunk. */
Addr sizeLeft;
/** The start address so we can calculate offset in writing block. */
// ... even if startAddr is already chunk-aligned
nextAddr += chunkSize;
}
+ nextAddr = std::min(nextAddr, startAddr + totalSize);
}
// How many bytes are left between curAddr and the end of this chunk?
- Addr left_in_chunk = nextAddr - curAddr;
- curSize = std::min(totalSize, left_in_chunk);
+ curSize = nextAddr - curAddr;
sizeLeft = totalSize - curSize;
+ nextSize = std::min(sizeLeft, chunkSize);
}
/**
*/
bool last() const { return sizeLeft == 0; }
+ /**
+ * Grow this chunk to cover additional bytes which are already handled.
+ * @param next The first byte of the next chunk.
+ *
+ * @ingroup api_chunk_generator
+ */
+ void
+ setNext(Addr next)
+ {
+ assert(next >= nextAddr);
+
+ const Addr skipping = std::min(next - nextAddr, sizeLeft);
+
+ sizeLeft -= skipping;
+ curSize += skipping;
+ nextAddr = next;
+
+ assert(chunkSize);
+
+ // nextSize will be enough to get to an alignment boundary,
+ nextSize = roundUp(next, chunkSize) - next;
+ // or if it's already aligned, to the following boundary or the end.
+ if (!nextSize)
+ nextSize = std::min(sizeLeft, chunkSize);
+ }
+
/**
* Advance generator to next chunk.
* @return True if successful, false if unsuccessful
}
curAddr = nextAddr;
- curSize = std::min(sizeLeft, chunkSize);
+ curSize = nextSize;
sizeLeft -= curSize;
nextAddr += curSize;
+ nextSize = std::min(sizeLeft, chunkSize);
return true;
}
};
EXPECT_FALSE(chunk_generator.last());
}
+/*
+ * A test to check skipping over bytes.
+ */
+TEST(ChunkGeneratorTest, SkipBytes)
+{
+ ChunkGenerator chunk_generator(0, 1024, 8);
+ EXPECT_EQ(0, chunk_generator.addr());
+ EXPECT_TRUE(chunk_generator.next());
+ EXPECT_EQ(8, chunk_generator.addr());
+
+ chunk_generator.setNext(23);
+ EXPECT_EQ(23 - 8, chunk_generator.size());
+ EXPECT_TRUE(chunk_generator.next());
+ EXPECT_EQ(23, chunk_generator.addr());
+ EXPECT_EQ(1, chunk_generator.size());
+ EXPECT_TRUE(chunk_generator.next());
+ EXPECT_EQ(24, chunk_generator.addr());
+ EXPECT_EQ(8, chunk_generator.size());
+
+ chunk_generator.setNext(32);
+ EXPECT_EQ(32 - 24, chunk_generator.size());
+ EXPECT_TRUE(chunk_generator.next());
+ EXPECT_EQ(32, chunk_generator.addr());
+ EXPECT_EQ(8, chunk_generator.size());
+
+ chunk_generator.setNext(64);
+ EXPECT_EQ(64 - 32, chunk_generator.size());
+ EXPECT_TRUE(chunk_generator.next());
+ EXPECT_EQ(64, chunk_generator.addr());
+ EXPECT_EQ(8, chunk_generator.size());
+
+ chunk_generator.setNext(2048);
+ EXPECT_EQ(1024 - 64, chunk_generator.size());
+ EXPECT_TRUE(chunk_generator.last());
+ EXPECT_FALSE(chunk_generator.next());
+ EXPECT_TRUE(chunk_generator.done());
+}
+
/*
* A test to consume chunks until the last chunk.
*/