Files
findcrcs/crcutil-1.0/examples/usage.cc

210 lines
6.2 KiB
C++

// Copyright 2010 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "std_headers.h"
#include "interface.h"
static const size_t kRollWindow = 4;
static const unsigned char kTestData[] = "abcdefgh";
static const int kTestDataHead =
static_cast<size_t>((sizeof(kTestData) - 1) / 4);
static const int kTestDataTail =
static_cast<size_t>(sizeof(kTestData) - 1 - kTestDataHead);
typedef crcutil_interface::UINT64 uint64;
// GCC -- up to 4.5.0 inclusively -- is not aware that the right format
// to print "long long" is "%ll[oudx]". Such nonsense does not prevent
// it from complaining about format mismatch, though. Here is the cure.
void xprintf(const char *format, ...) {
va_list va;
va_start(va, format);
vprintf(format, va);
va_end(va);
fflush(stdout);
}
//
// Please notice that when working with 64-bit and smaller CRCs,
// the use of "hi" part of CRC value is unnecessary.
//
void Show(const crcutil_interface::CRC *crc) {
char buffer[sizeof(kTestData) + 32];
//
// Access CRC properties.
//
uint64 lo;
crc->GeneratingPolynomial(&lo);
xprintf("Generating polynomial 0x%llx, degree %llu",
lo,
static_cast<uint64>(crc->Degree()));
crc->CanonizeValue(&lo);
xprintf(", canonize_value=0x%llx", lo);
crc->RollStartValue(&lo);
xprintf(", roll start value=0x%llx, roll window=%llu",
lo,
static_cast<uint64>(crc->RollWindowBytes()));
//
// Check integrity of CRC tables.
//
crc->SelfCheckValue(&lo);
xprintf(", self check value 0x%llx\n", lo);
//
// Compute CRC.
//
lo = 0;
crc->Compute(kTestData, sizeof(kTestData) - 1, &lo);
xprintf("CRC32C(\"%s\") = 0x%llx\n", kTestData, lo);
//
// Compute CRC (incrementally).
//
lo = 0;
crc->Compute(kTestData, kTestDataHead, &lo);
xprintf("CRC32C(\"%.*s\", 0) = 0x%llx, ", kTestDataHead, kTestData, lo);
crc->Compute(kTestData + kTestDataHead, kTestDataTail, &lo);
xprintf("CRC32C(\"%s\", CRC32(\"%.*s\", 0)) = 0x%llx = CRC32(\"%s\")\n",
kTestData + kTestDataHead, kTestDataHead, kTestData, lo, kTestData);
//
// Compute CRC of a message filled with 0s.
//
lo = 1;
crc->CrcOfZeroes(sizeof(buffer), &lo);
uint64 lo1 = 1;
memset(buffer, 0, sizeof(buffer));
crc->Compute(buffer, sizeof(buffer), &lo1);
xprintf("CRC of %d zeroes = %llx, expected %llx\n",
static_cast<int>(sizeof(buffer)),
lo,
lo1);
//
// Use rolling CRC.
//
xprintf("RollingCrc expected =");
for (size_t i = 0; i <= kRollWindow; ++i) {
crc->RollStartValue(&lo);
crc->Compute(kTestData + i, kRollWindow, &lo);
xprintf(" 0x%llx", lo);
}
xprintf("\n");
crc->RollStart(kTestData, &lo, NULL);
xprintf("RollingCrc actual = 0x%llx", lo);
for (size_t i = 1; i <= kRollWindow; ++i) {
crc->Roll(kTestData[i - 1], kTestData[i - 1 + kRollWindow], &lo, NULL);
xprintf(" 0x%llx", lo);
}
xprintf("\n");
//
// Change initial value.
//
lo = 0;
crc->Compute(kTestData, sizeof(kTestData) - 1, &lo);
uint64 lo1_expected = 1;
crc->Compute(kTestData, sizeof(kTestData) - 1, &lo1_expected);
lo1 = lo;
crc->ChangeStartValue(0, 0, // old start value
1, 0, // new start value
sizeof(kTestData) - 1,
&lo1);
xprintf("CRC(\"%s\", 0) = 0x%llx, CRC(\"%s\", 1)=0x%llx, expected 0x%llx\n",
kTestData, lo, kTestData, lo1, lo1_expected);
//
// Concatenate CRCs.
//
uint64 start_value = 1;
lo = start_value;
crc->Compute(kTestData, kTestDataHead, &lo);
lo1 = 0;
crc->Compute(kTestData + kTestDataHead, kTestDataTail, &lo1);
uint64 lo2 = lo;
crc->Concatenate(lo1, 0, kTestDataTail, &lo2);
uint64 lo2_expected = start_value;
crc->Compute(kTestData, sizeof(kTestData) - 1, &lo2_expected);
xprintf("CRC(\"%.*s\", 1) = 0x%llx, CRC(\"%s\", 0)=0x%llx, "
"CRC(\"%s\", 1) = 0x%llx, expected 0x%llx\n",
kTestDataHead, kTestData, lo,
kTestData + kTestDataHead, lo1,
kTestData, lo2,
lo2_expected);
//
// Store complementary CRC so that CRC of a message followed
// by complementary CRC value produces predefined result (e.g. 0).
//
memcpy(buffer, kTestData, sizeof(kTestData) - 1);
lo = 1;
crc->Compute(buffer, sizeof(kTestData) - 1, &lo);
size_t stored_crc_bytes = crc->StoreComplementaryCrc(
buffer + sizeof(kTestData) - 1,
lo, 0,
0);
// Compute CRC of message + complementary CRC using the same start value
// (start value could be changed via ChangeStartValue()).
lo1 = 1;
crc->Compute(buffer, sizeof(kTestData) - 1 + stored_crc_bytes, &lo1);
xprintf("Crc of message + complementary CRC = %llx, expected 0\n", lo1);
//
// Store CRC after the message and ensure that CRC of message + its
// CRC produces constant result irrespective of message data.
//
memcpy(buffer, kTestData, sizeof(kTestData) - 1);
lo = 1;
crc->Compute(buffer, sizeof(kTestData) - 1, &lo);
stored_crc_bytes = crc->StoreCrc(buffer + sizeof(kTestData) - 1, lo);
// Compute CRC of message + its CRC using start value of 0.
lo1 = 1;
crc->Compute(buffer, sizeof(kTestData) - 1 + stored_crc_bytes, &lo1);
// Ensure that it matches "predicted" constant value, irrespective
// of a message or CRC start value.
crc->CrcOfCrc(&lo2);
xprintf("CrcOfCrc=%llx, expected %llx\n", lo1, lo2);
xprintf("\n");
}
void ShowAndDelete(crcutil_interface::CRC *crc) {
Show(crc);
crc->Delete();
}
int main() {
ShowAndDelete(crcutil_interface::CRC::Create(
0xEB31D82E, 0, 32, true, 0x1111, 0, kRollWindow,
crcutil_interface::CRC::IsSSE42Available(), NULL));
ShowAndDelete(crcutil_interface::CRC::Create(
0x82f63b78, 0, 32, true, 0x2222, 0, kRollWindow,
crcutil_interface::CRC::IsSSE42Available(), NULL));
return 0;
}