--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include "common.h"
+#include "../qrspec.h"
+
+void print_eccTable(void)
+{
+ int i, j;
+ int ecc;
+ int data;
+ int spec[5];
+
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ printf("Version %2d\n", i);
+ for(j=0; j<4; j++) {
+ QRspec_getEccSpec(i, (QRecLevel)j, spec);
+ data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
+ ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
+ printf("%3d\t", ecc);
+ printf("%2d\t", QRspec_rsBlockNum1(spec));
+ printf("(%3d, %3d, %3d)\n",
+ QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec),
+ QRspec_rsDataCodes1(spec),
+ QRspec_rsEccCodes1(spec));
+ if(QRspec_rsBlockNum2(spec) > 0) {
+ printf("\t%2d\t", QRspec_rsBlockNum2(spec));
+ printf("(%3d, %3d, %3d)\n",
+ QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec),
+ QRspec_rsDataCodes2(spec),
+ QRspec_rsEccCodes2(spec));
+ }
+ }
+ }
+}
+
+void test_eccTable(void)
+{
+ int i, j;
+ int ecc;
+ int data;
+ int err = 0;
+ int spec[5];
+
+ testStart("Checking ECC table.");
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ for(j=0; j<4; j++) {
+ QRspec_getEccSpec(i, (QRecLevel)j, spec);
+ data = QRspec_rsBlockNum1(spec) * QRspec_rsDataCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsDataCodes2(spec);
+ ecc = QRspec_rsBlockNum1(spec) * QRspec_rsEccCodes1(spec)
+ + QRspec_rsBlockNum2(spec) * QRspec_rsEccCodes2(spec);
+ if(data + ecc != QRspec_getDataLength(i, (QRecLevel)j) + QRspec_getECCLength(i, (QRecLevel)j)) {
+ printf("Error in version %d, level %d: invalid size\n", i, j);
+ printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
+ err++;
+ }
+ if(ecc != QRspec_getECCLength(i, (QRecLevel)j)) {
+ printf("Error in version %d, level %d: invalid data\n", i, j);
+ printf("%d %d %d %d %d %d\n", spec[0], spec[1], spec[2], spec[3], spec[4], spec[2]);
+ err++;
+ }
+ }
+ }
+ testEnd(err);
+}
+
+void test_eccTable2(void)
+{
+ int i;
+ int spec[5];
+
+ const int correct[7][6] = {
+ { 8, 1, 0, 2, 60, 38},
+ { 8, 1, 1, 2, 61, 39},
+ {24, 2, 0, 11, 54, 24},
+ {24, 2, 1, 16, 55, 25},
+ {32, 0, 0, 17, 145, 115},
+ {40, 3, 0, 20, 45, 15},
+ {40, 3, 1, 61, 46, 16},
+ };
+
+ testStart("Checking ECC table(2)");
+ for(i=0; i<7; i++) {
+ QRspec_getEccSpec(correct[i][0], (QRecLevel)correct[i][1], spec);
+ if(correct[i][2] == 0) {
+ assert_equal(QRspec_rsBlockNum1(spec), correct[i][3],
+ "Error in version %d, level %d. rsBlockNum1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsBlockNum1(spec), correct[i][3]);
+ assert_equal(QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4],
+ "Error in version %d, level %d. rsDataCodes1 + rsEccCodes1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes1(spec) + QRspec_rsEccCodes1(spec), correct[i][4]);
+ assert_equal(QRspec_rsDataCodes1(spec), correct[i][5],
+ "Error in version %d, level %d. rsDataCodes1 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes1(spec), correct[i][5]);
+ } else {
+ assert_equal(QRspec_rsBlockNum2(spec), correct[i][3],
+ "Error in version %d, level %d. rsBlockNum2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsBlockNum2(spec), correct[i][3]);
+ assert_equal(QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4],
+ "Error in version %d, level %d. rsDataCodes2 + rsEccCodes2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes2(spec) + QRspec_rsEccCodes2(spec), correct[i][4]);
+ assert_equal(QRspec_rsDataCodes2(spec), correct[i][5],
+ "Error in version %d, level %d. rsDataCodes2 was %d, expected %d.\n",
+ correct[i][0], correct[i][1],
+ QRspec_rsDataCodes2(spec), correct[i][5]);
+ }
+ }
+ testFinish();
+}
+
+void test_newframe(void)
+{
+ unsigned char buf[QRSPEC_WIDTH_MAX * QRSPEC_WIDTH_MAX];
+ int i, width;
+ size_t len;
+ FILE *fp;
+ unsigned char *frame;
+
+ testStart("Checking newly created frame.");
+ fp = fopen("frame", "rb");
+ if(fp == NULL) {
+ perror("Failed to open \"frame\":");
+ abort();
+ }
+ for(i=1; i<=QRSPEC_VERSION_MAX; i++) {
+ frame = QRspec_newFrame(i);
+ width = QRspec_getWidth(i);
+ len = fread(buf, 1, width * width, fp);
+ if((int)len != width * width) {
+ perror("Failed to read the pattern file:");
+ abort();
+ }
+ assert_zero(memcmp(frame, buf, len), "frame pattern mismatch (version %d)\n", i);
+ free(frame);
+ }
+
+ testFinish();
+ fclose(fp);
+}
+
+#if 0
+/* This test is used to check positions of alignment pattern. See Appendix E
+ * (pp.71) of JIS X0510:2004 and compare to the output. Before comment out
+ * this test, change the value of the pattern marker's center dot from 0xa1
+ * to 0xb1 (QRspec_putAlignmentMarker() : finder).
+ */
+void test_alignment(void)
+{
+ unsigned char *frame;
+ int i, x, y, width, c;
+
+ testStart("Checking alignment pattern.");
+ for(i=2; i<=QRSPEC_VERSION_MAX; i++) {
+ printf("%2d", i);
+ frame = QRspec_newFrame(i);
+ width = QRspec_getWidth(i);
+ c = 0;
+ for(x=0; x<width * width; x++) {
+ if(frame[x] == 0xb1) {
+ c++;
+ }
+ }
+ printf("|%2d| 6", c);
+ y = width - 7;
+ for(x=0; x < width; x++) {
+ if(frame[y * width + x] == 0xb1) {
+ printf(", %3d", x);
+ }
+ }
+ printf("\n");
+ free(frame);
+ }
+ testFinish();
+}
+#endif
+
+void test_verpat(void)
+{
+ int version;
+ unsigned int pattern;
+ int err = 0;
+ unsigned int data;
+ unsigned int code;
+ int i, c;
+ unsigned int mask;
+
+ for(version=7; version <= QRSPEC_VERSION_MAX; version++) {
+ pattern = QRspec_getVersionPattern(version);
+ if((pattern >> 12) != (unsigned int)version) {
+ printf("Error in version %d.\n", version);
+ err++;
+ continue;
+ }
+ mask = 0x40;
+ for(i=0; mask != 0; i++) {
+ if(version & mask) break;
+ mask = mask >> 1;
+ }
+ c = 6 - i;
+ data = version << 12;
+ code = 0x1f25 << c;
+ mask = 0x40000 >> (6 - c);
+ for(i=0; i<=c; i++) {
+ if(mask & data) {
+ data ^= code;
+ }
+ code = code >> 1;
+ mask = mask >> 1;
+ }
+ data = (version << 12) | (data & 0xfff);
+ if(data != pattern) {
+ printf("Error in version %d\n", version);
+ err++;
+ }
+ }
+}
+
+void print_newFrame(void)
+{
+ int width;
+ int x, y;
+ unsigned char *frame;
+
+ frame = QRspec_newFrame(7);
+ width = QRspec_getWidth(7);
+ for(y=0; y<width; y++) {
+ for(x=0; x<width; x++) {
+ printf("%02x ", frame[y * width + x]);
+ }
+ printf("\n");
+ }
+ free(frame);
+}
+
+/* See Table 22 (pp.45) and Appendix C (pp. 65) of JIS X0510:2004 */
+static unsigned int levelIndicator[4] = {1, 0, 3, 2};
+static unsigned int calcFormatInfo(int mask, QRecLevel level)
+{
+ unsigned int data, ecc, b, code;
+ int i, c;
+
+ data = (levelIndicator[level] << 13) | (mask << 10);
+ ecc = data;
+ b = 1 << 14;
+ for(i=0; b != 0; i++) {
+ if(ecc & b) break;
+ b = b >> 1;
+ }
+ c = 4 - i;
+ code = 0x537 << c ; //10100110111
+ b = 1 << (10 + c);
+ for(i=0; i<=c; i++) {
+ if(b & ecc) {
+ ecc ^= code;
+ }
+ code = code >> 1;
+ b = b >> 1;
+ }
+
+ return (data | ecc) ^ 0x5412;
+}
+
+void test_format(void)
+{
+ unsigned int format;
+ int i, j;
+ int err = 0;
+
+ testStart("Format info test");
+ for(i=0; i<4; i++) {
+ for(j=0; j<8; j++) {
+ format = calcFormatInfo(j, (QRecLevel)i);
+// printf("0x%04x, ", format);
+ if(format != QRspec_getFormatInfo(j, (QRecLevel)i)) {
+ printf("Level %d, mask %x\n", i, j);
+ err++;
+ }
+ }
+// printf("\n");
+ }
+ testEnd(err);
+}
+
+int main(int argc, char **argv)
+{
+ test_eccTable();
+ test_eccTable2();
+ //print_eccTable();
+ test_newframe();
+ //test_alignment();
+ test_verpat();
+ //print_newFrame();
+ test_format();
+
+ QRspec_clearCache();
+
+ report();
+
+ return 0;
+}