namespace {
+/**
+ * Copy bytes from src to somewhere in the buffer referenced by dst. The
+ * actual starting position of the copy will be the first address in the
+ * destination buffer whose address mod 8 is equal to the src address mod 8.
+ * The caller is responsible for ensuring that the destination buffer has
+ * enough extra space to accommodate the shifted copy.
+ */
+char* copyWithSameAlignment(char* dst, const char* src, size_t length) {
+ const char* originalDst = dst;
+ size_t dstOffset = size_t(dst) & 0x7;
+ size_t srcOffset = size_t(src) & 0x7;
+ while (dstOffset != srcOffset) {
+ dst++;
+ dstOffset++;
+ dstOffset &= 0x7;
+ }
+ CHECK(dst <= originalDst + 7);
+ CHECK((size_t(dst) & 0x7) == (size_t(src) & 0x7));
+ memcpy(dst, src, length);
+ return dst;
+}
+
void testToLowerAscii(Range<const char*> src) {
- char control[src.size()];
- memcpy(control, src.begin(), src.size());
- char test[src.size()];
- memcpy(test, src.begin(), src.size());
+ // Allocate extra space so we can make copies that start at the
+ // same alignment (byte, word, quadword, etc) as the source buffer.
+ char controlBuf[src.size() + 7];
+ char* control = copyWithSameAlignment(controlBuf, src.begin(), src.size());
+
+ char testBuf[src.size() + 7];
+ char* test = copyWithSameAlignment(testBuf, src.begin(), src.size());
+
for (size_t i = 0; i < src.size(); i++) {
control[i] = tolower(control[i]);
}
}
// Test input buffers of several lengths to exercise all the
// cases: buffer at the start/middle/end of an aligned block, plus
- // buffers that span multiple aligned blocks.
- for (size_t length = 1; length < 11; length++) {
+ // buffers that span multiple aligned blocks. The longest test input
+ // is 3 unaligned bytes + 4 32-bit aligned bytes + 8 64-bit aligned
+ // + 4 32-bit aligned + 3 unaligned = 22 bytes.
+ for (size_t length = 1; length < 23; length++) {
for (size_t offset = 0; offset + length <= kSize; offset++) {
testToLowerAscii(Range<const char*>(input + offset, length));
}