diff --git a/.gitignore b/.gitignore index 57fd4c6d..5c0c2bac 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ data/ucd src/libucd.la tests/printucddata +tests/printucddata_cpp # test output: diff --git a/Makefile.am b/Makefile.am index 74c11df6..787b967f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -6,6 +6,7 @@ mimedir = $(xdgdatadir)/mime xmldir = $(mimedir)/packages AM_LDFLAGS = ${LTLIBINTL} +AM_CFLAGS = -Isrc/include -Isrc AM_CXXFLAGS = -Isrc/include -Isrc ACLOCAL_AMFLAGS = -I m4 @@ -113,19 +114,29 @@ src_libucd_la_SOURCES = \ ############################# tests ########################################### noinst_bin_PROGRAMS += tests/printucddata -tests_printucddata_SOURCES = tests/printucddata.cpp +tests_printucddata_SOURCES = tests/printucddata.c tests_printucddata_LDADD = src/libucd.la +noinst_bin_PROGRAMS += tests/printucddata_cpp +tests_printucddata_cpp_SOURCES = tests/printucddata_cpp.cpp +tests_printucddata_cpp_LDADD = src/libucd.la + tests/unicode-data.expected: tools/printdata.py tools/ucd.py \ data/ucd/UnicodeData.txt \ data/ucd/PropList.txt \ data/ucd/Scripts.txt tools/printdata.py ${UCD_ROOTDIR} ${UCD_FLAGS} > $@ -tests/unicode-data.actual: tests/printucddata +tests/unicode-data-capi.actual: tests/printucddata tests/printucddata > $@ -tests/unicode-data.diff: tests/unicode-data.expected tests/unicode-data.actual - diff -U0 tests/unicode-data.expected tests/unicode-data.actual > tests/unicode-data.diff +tests/unicode-data-cppapi.actual: tests/printucddata_cpp + tests/printucddata_cpp > $@ -check: tests/unicode-data.diff +tests/unicode-data-capi.diff: tests/unicode-data.expected tests/unicode-data-capi.actual + diff -U0 tests/unicode-data.expected tests/unicode-data-capi.actual > tests/unicode-data-capi.diff + +tests/unicode-data-cppapi.diff: tests/unicode-data.expected tests/unicode-data-cppapi.actual + diff -U0 tests/unicode-data.expected tests/unicode-data-cppapi.actual > tests/unicode-data-cppapi.diff + +check: tests/unicode-data-capi.diff tests/unicode-data-cppapi.diff diff --git a/tests/printucddata.c b/tests/printucddata.c new file mode 100644 index 00000000..09b5f03a --- /dev/null +++ b/tests/printucddata.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2012-2016 Reece H. Dunn + * + * This file is part of ucd-tools. + * + * ucd-tools is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * ucd-tools is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with ucd-tools. If not, see . + */ + +#include "ucd/ucd.h" + +#include +#include + +void fput_utf8c(FILE *out, codepoint_t c) +{ + if (c < 0x80) + fputc((uint8_t)c, out); + else if (c < 0x800) + { + fputc(0xC0 | (c >> 6), out); + fputc(0x80 + (c & 0x3F), out); + } + else if (c < 0x10000) + { + fputc(0xE0 | (c >> 12), out); + fputc(0x80 + ((c >> 6) & 0x3F), out); + fputc(0x80 + (c & 0x3F), out); + } + else if (c < 0x200000) + { + fputc(0xF0 | (c >> 18), out); + fputc(0x80 + ((c >> 12) & 0x3F), out); + fputc(0x80 + ((c >> 6) & 0x3F), out); + fputc(0x80 + (c & 0x3F), out); + } +} + +int fget_utf8c(FILE *in, codepoint_t *c) +{ + int ch = EOF; + if ((ch = fgetc(in)) == EOF) return 0; + if ((uint8_t)ch < 0x80) + *c = (uint8_t)ch; + else switch ((uint8_t)ch & 0xF0) + { + default: + *c = (uint8_t)ch & 0x1F; + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + break; + case 0xE0: + *c = (uint8_t)ch & 0x0F; + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + break; + case 0xF0: + *c = (uint8_t)ch & 0x07; + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + if ((ch = fgetc(in)) == EOF) return 0; + *c = (*c << 6) + ((uint8_t)ch & 0x3F); + break; + } + return 1; +} + +void uprintf_codepoint(FILE *out, codepoint_t c, char mode) +{ + switch (mode) + { + case 'c': // character + switch (c) + { + case '\t': fputs("\\t", out); break; + case '\r': fputs("\\r", out); break; + case '\n': fputs("\\n", out); break; + default: fput_utf8c(out, c); break; + } + break; + case 'h': // hexadecimal (lower) + fprintf(out, "%06x", c); + break; + case 'H': // hexadecimal (upper) + fprintf(out, "%06X", c); + break; + } +} + +void uprintf(FILE *out, codepoint_t c, const char *format) +{ + while (*format) switch (*format) + { + case '%': + switch (*++format) + { + case 'c': // category + fputs(ucd_get_category_string(ucd_lookup_category(c)), out); + break; + case 'C': // category group + fputs(ucd_get_category_group_string(ucd_lookup_category_group(c)), out); + break; + case 'p': // codepoint + uprintf_codepoint(out, c, *++format); + break; + case 'L': // lowercase + uprintf_codepoint(out, ucd_tolower(c), *++format); + break; + case 's': // script + fputs(ucd_get_script_string(ucd_lookup_script(c)), out); + break; + case 'T': // titlecase + uprintf_codepoint(out, ucd_totitle(c), *++format); + break; + case 'U': // uppercase + uprintf_codepoint(out, ucd_toupper(c), *++format); + break; + case 'W': // whitespace + if (ucd_isspace(c)) + fputs("White_Space", out); + break; + } + ++format; + break; + default: + fputc(*format, out); + ++format; + break; + } +} + +void print_file(FILE *in) +{ + codepoint_t c = 0; + while (fget_utf8c(in, &c)) + uprintf(stdout, c, "%pc\t%pH\t%s\t%c\t%Uc\t%Lc\t%Tc\t%W\n"); +} + +int main(int argc, char **argv) +{ + if (argc == 2) + { + if (!strcmp(argv[1], "--stdin") || !strcmp(argv[1], "-")) + print_file(stdin); + else + { + FILE *in = fopen(argv[1], "r"); + if (in) + { + print_file(in); + fclose(in); + } + else + fprintf(stdout, "cannot open `%s`\n", argv[1]); + } + } + else + { + for (codepoint_t c = 0; c <= 0x10FFFF; ++c) + uprintf(stdout, c, "%pH %s %C %c %UH %LH %TH %W\n"); + } + return 0; +} diff --git a/tests/printucddata.cpp b/tests/printucddata_cpp.cpp similarity index 99% rename from tests/printucddata.cpp rename to tests/printucddata_cpp.cpp index 7263e54d..60a2b04f 100644 --- a/tests/printucddata.cpp +++ b/tests/printucddata_cpp.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2015 Reece H. Dunn + * Copyright (C) 2012-2016 Reece H. Dunn * * This file is part of ucd-tools. *