From 0a08e81e3190f6e3a760efec80be8ab14ef27b1b Mon Sep 17 00:00:00 2001 From: Mikhail Korobov Date: Tue, 18 Feb 2014 04:39:01 +0600 Subject: [PATCH] update libdatrie C library to 0.2.8 --- libdatrie/ChangeLog | 282 +++++++++++++ libdatrie/Makefile.am | 2 +- libdatrie/NEWS | 33 ++ libdatrie/configure.ac | 24 +- libdatrie/datrie/Makefile.am | 2 +- libdatrie/datrie/alpha-map-private.h | 2 +- libdatrie/datrie/alpha-map.c | 48 ++- libdatrie/datrie/alpha-map.h | 20 + libdatrie/datrie/darray.c | 14 +- libdatrie/datrie/dstring.c | 8 +- libdatrie/datrie/libdatrie.def | 1 + libdatrie/datrie/libdatrie.map | 4 + libdatrie/datrie/trie-string.c | 3 +- libdatrie/datrie/trie.c | 79 ++-- libdatrie/datrie/trie.h | 40 ++ libdatrie/datrie/triedefs.h | 7 +- libdatrie/doc/Doxyfile.in | 236 +++++++---- libdatrie/tests/Makefile.am | 54 +++ libdatrie/tests/test_file.c | 131 ++++++ libdatrie/tests/test_iterator.c | 136 +++++++ libdatrie/tests/test_nonalpha.c | 92 +++++ libdatrie/tests/test_store-retrieve.c | 201 ++++++++++ libdatrie/tests/test_walk.c | 549 ++++++++++++++++++++++++++ libdatrie/tests/utils.c | 168 ++++++++ libdatrie/tests/utils.h | 59 +++ libdatrie/tools/Makefile.am | 2 +- 26 files changed, 2067 insertions(+), 130 deletions(-) create mode 100644 libdatrie/tests/Makefile.am create mode 100644 libdatrie/tests/test_file.c create mode 100644 libdatrie/tests/test_iterator.c create mode 100644 libdatrie/tests/test_nonalpha.c create mode 100644 libdatrie/tests/test_store-retrieve.c create mode 100644 libdatrie/tests/test_walk.c create mode 100644 libdatrie/tests/utils.c create mode 100644 libdatrie/tests/utils.h diff --git a/libdatrie/ChangeLog b/libdatrie/ChangeLog index a02f949..b37fa3d 100644 --- a/libdatrie/ChangeLog +++ b/libdatrie/ChangeLog @@ -1,3 +1,285 @@ +2014-01-10 Theppitak Karoonboonyanan + + * configure.ac: + - Bump library revision to reflect code changes. + + * NEWS, configure.ac: + === Version 0.2.8 === + +2014-01-09 Theppitak Karoonboonyanan + + Improve documentation. + + * datrie/triedefs.h: + - Refine descriptions of data types. + * datrie/trie.c (trie_iterator_new): + - Fix typo on trie_root() mentioning. + * datrie/trie.c (trie_store, trie_store_if_absent): + - Adjust wording. + * datrie/alpha-map.h, datrie/trie.h: + - Add detailed description of AlphaMap and Trie types. + +2014-01-08 Theppitak Karoonboonyanan + + Clarify message in test_nonalpha. + + * tests/test_nonalpha.c (main): + - Clarify message on false key duplication. + +2014-01-08 Theppitak Karoonboonyanan + + Add test on keys with non-alphabet input chars. + + * tests/Makefile.am, +tests/test_nonalpha.c: + - Add test to ensure that operations on keys with non-alphabet + input chars fail. + +2014-01-08 Theppitak Karoonboonyanan + + Fail trie operations on non-alphabet inputs. + + alpha_map_char_to_trie() tried to return TRIE_CHAR_MAX to indicate + out-of-range error. But this value is indeed valid in trie operations. + Doing so could allow false key duplication when different non-alphabet + chars and TRIE_CHAR_MAX itself were all mapped to TRIE_CHAR_MAX. + So, let's fail all trie operations on non-alphabet input chars. + + * datrie/alpha-map-private.h, datrie/alpha-map.c + (alpha_map_char_to_trie): + - Make alpha_map_char_to_trie return TrieIndex type, using + TRIE_INDEX_MAX to indicate out-of-range error. + This allows TRIE_CHAR_MAX to be returned as a valid output. + * datrie/alpha-map.c (alpha_map_char_to_trie_str): + - Fail if alpha_map_char_to_trie() returns error code. + * datrie/trie.c (trie_retrieve, trie_store_conditionally, trie_delete, + trie_state_walk, trie_state_is_walkable): + - Check return value from alpha_map_char_to_trie() and return + failure status on error. + - Also cast TrieIndex return values to TrieChar on function calls. + + Thanks Naoki Youshinaga for the suggestion. + +2014-01-07 Theppitak Karoonboonyanan + + Check for NULL result from AlphaMap string funcs. + + * datrie/trie.c (trie_store_conditionally): + - Return failure on NULL alpha_map_char_to_trie_str(). + +2014-01-07 Theppitak Karoonboonyanan + + Return NULL on allocation errors in AlphaMap funcs. + + * datrie/alpha-map.c + (alpha_map_char_to_trie_str, alpha_map_trie_to_char_str): + - Return NULL on malloc() error. + +2014-01-03 Theppitak Karoonboonyanan + + Fix edge case with TRIE_CHAR_MAX as TrieChar. + + The trie input char with value TRIE_CHAR_MAX (255), was always + skipped by double-array algorithms. Let's include it. + + * datrie/darray.c (da_has_children, da_output_symbols, + da_relocate_base, da_first_separate, da_next_separate): + - Include the last char in trie char iterations. + + * datrie/darray.c (da_first_separate, da_next_separate): + - Declare characters as TrieIndex type instead of TrieChar, + to prevent infinite loop due to unsigned char overflow. + + Thanks Naoki Youshinaga for the report, test case, and analysis. + +2013-10-25 Theppitak Karoonboonyanan + + Fix comiler warnings in tests. + + * tests/test_walk.c (main): + - Remove unused var i; + - Remove extra printf() args. + * tests/test_iterator.c: + - Add missing #include for free(). + * tests/test_walk.c (walk_dict), tests/utils.c (dict_src): + - Cast string literals to (AlphaChar *) to fix signedness + differences. + +2013-10-25 Theppitak Karoonboonyanan + + * configure.ac: Post-release version suffix added. + +2013-10-22 Theppitak Karoonboonyanan + + * NEWS, configure.ac: + === Version 0.2.7.1 === + +2013-10-21 Theppitak Karoonboonyanan + + * configure.ac: Bump library versioning to reflect API addition. + (Change missing in previous release) + +2013-10-21 Theppitak Karoonboonyanan + + * configure.ac: Post-release version suffix added. + +2013-10-21 Theppitak Karoonboonyanan + + * NEWS, configure.ac: + === Version 0.2.7 === + +2013-10-21 Theppitak Karoonboonyanan + + Add missing distributed file. + + * tests/Makefile.am: + - Add utils.h to distribution. + +2013-10-20 Theppitak Karoonboonyanan + + Reorder tests from primitive to applied. + + * tests/Makefile.am: + - Test walk & iterator before store-retrieve & file. + +2013-10-20 Theppitak Karoonboonyanan + + Write a test suite for trie walk. + + * tests/test_walk.c: + - Write test code. + +2013-10-18 Theppitak Karoonboonyanan + + Write a test suite for trie store/retrieval. + + * tests/utils.h, tests/utils.c (+dict_src_n_entries): + - Add function to get total entries in dict_src[]. + * tests/test_store-retrieve.c (main): + - Write test code. + +2013-10-18 Theppitak Karoonboonyanan + + Fix messages in test_iterator. + + * tests/test_iterator.c (main): + - s/file/trie/. No file is written or read in this test. + +2013-10-18 Theppitak Karoonboonyanan + + Skip further iteration tests if key is NULL. + + * tests/test_iterator.c (main): + - Insert 'continue' if trie_iterator_get_key() returns NULL. + +2013-10-17 Theppitak Karoonboonyanan + + Document availibility of alpha_char_strcmp() + + * datrie/alpha-map.c (alpha_char_strcmp): + - Document that it's available since 0.2.7. + +2013-10-17 Theppitak Karoonboonyanan + + Write a test for trie iterator. + + * tests/test_iterator.c: + - Write test suite for trie iterator. + +2013-10-17 Theppitak Karoonboonyanan + + Add skeleton test suites & a test for file I/O. + + * configure.ac, Makefile.am, +tests/, +tests/Makefile.am: + - Add tests/ dir to the build system. + * +tests/utils.h, +tests/utils.c: + * +tests/test_file.c: + * +tests/test_iterator.c: + * +tests/test_store-retrieve.c: + * +tests/test_walk.c: + - Add skeleton for test suites. + * tests/utils.h, tests/utils.c, tests/test_file.c: + - Write test suite for file I/O. + +2013-10-17 Theppitak Karoonboonyanan + + Add alpha_char_strcmp() API. + + * datrie/alpha-map.h, datrie/alpha-map.c (+alpha_char_strcmp): + - Add alpha_char_strcmp() declaration & body. + * datrie/libdatrie.def, datrie/libdatrie.map: + - Add alpha_char_strcmp symbols. + +2013-10-16 Theppitak Karoonboonyanan + + Add missing info in alpha_map_add_range() doc. + + * datrie/alpha-map.c (alpha_map_add_range): + - Add documentation on return value. + +2013-09-23 Theppitak Karoonboonyanan + + Fix build for Visual Studio on Windows. + + * datrie/dstring.c (dstring_append, dstring_append_string, + dstring_append_char, dstring_terminate): + - Cast (void *) pointers to (char *) before calculating offsets, + for portability. + + Thanks Gabi Davar for the report and fix (via Mikhail Korobov + ). + +2013-09-23 Theppitak Karoonboonyanan + + Check for doxygen required version. + + * configure.ac: + - When doxygen-doc is enabled, also check doxygen version. + +2013-09-23 Theppitak Karoonboonyanan + + Fix doxygen warning. + + * doc/Doxyfile.in: + - doxygen no longer ships with the FreeSans font. Just drop it. + +2013-09-23 Theppitak Karoonboonyanan + + Update Doxyfile. + + * doc/Doxyfile.in: + - Updated with 'doxygen -u'. + +2013-09-23 Theppitak Karoonboonyanan + + Fix compiler warnings. + * datrie/trie-string.c (trie_string_append_string): + * datrie/trie.c (trie_iterator_get_key): + - Cast strlen() args from (const TrieChar *) to (const char *), + to fix signedness mismatch warnings. + +2013-09-23 Theppitak Karoonboonyanan + + Fix automake warnings. + + * datrie/Makefile.am, tools/Makefile.am: + - Replace deprecated INCLUDES with AM_CPPFLAGS. + +2013-09-23 Theppitak Karoonboonyanan + + * configure.ac: Post-release version suffix added. + +2013-01-23 Theppitak Karoonboonyanan + + * NEWS, configure.ac: + === Version 0.2.6 === + +2013-01-22 Theppitak Karoonboonyanan + + Use xz compression for release tarball. + + * configure.ac: + - Specify "dist-xz no-dist-gzip" options to AM_INIT_AUTOMAKE. + 2012-08-06 Theppitak Karoonboonyanan Improve AlphaMap range merging. diff --git a/libdatrie/Makefile.am b/libdatrie/Makefile.am index cab7e26..09a70ee 100644 --- a/libdatrie/Makefile.am +++ b/libdatrie/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = datrie tools man doc +SUBDIRS = datrie tools man doc tests EXTRA_DIST = README.migration diff --git a/libdatrie/NEWS b/libdatrie/NEWS index 247907c..bc3b9e5 100644 --- a/libdatrie/NEWS +++ b/libdatrie/NEWS @@ -1,5 +1,38 @@ libdatrie +0.2.8 (2014-01-10) +===== +- Fix compiler warnings in test suites. +- Fix edge-case error on alphabet set of size 255. + (Thanks Naoki Youshinaga for the report, test case, and analysis.) +- Fail trie operations on non-alphabet inputs, rather than silently allowing + them to sneak in as false keys. + (Thanks Naoki Youshinaga for the suggestion.) +- Improved documentation. + +0.2.7.1 (2013-10-22) +======= +- Bump library versioning to reflect API addition. + (Change missing in previous release) + +0.2.7 (2013-10-21) +===== +- Fix portability issue with non-GCC compilers. + [Thanks Gabi Daver for the report and fix (via Mikhail Korobov).] +- Fix compiler warnings. +- New utility API for comparing AlphaChar strings. +- Add test suites. +- Update doxygen doc generation. + +0.2.6 (2013-01-23) +===== +- New API trie_state_walkable_chars() for breadth-first traversal. +- New class TrieIterator for callback-free enumeration. +- Improved performance on key enumeration. +- Improved AlphaMap range merging. +- Bug fixes. +[Many thanks to Mikhail Korobov for improvements in this version.] + 0.2.5 (2011-11-04) ===== - Fix missing 'extern "C"' in header file. [Patch from Aurimas Černius] diff --git a/libdatrie/configure.ac b/libdatrie/configure.ac index 5b81e5b..82d83d5 100644 --- a/libdatrie/configure.ac +++ b/libdatrie/configure.ac @@ -2,24 +2,26 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ(2.59) -AC_INIT(libdatrie, 0.2.5svn, thep@linux.thai.net) +AC_INIT(libdatrie, 0.2.8, thep@linux.thai.net) AC_CONFIG_SRCDIR([datrie/trie.h]) AC_CONFIG_HEADER([config.h]) AC_CONFIG_MACRO_DIR([m4]) -AM_INIT_AUTOMAKE +AM_INIT_AUTOMAKE(dist-xz no-dist-gzip) # Library versioning # Library code modified: REVISION++ # Interfaces added: CURRENT++ REVISION=0 AGE++ # Interfaces changed/removed: CURRENT++ REVISION=0 AGE=0 -LT_CURRENT=3 -LT_REVISION=0 -LT_AGE=2 +LT_CURRENT=4 +LT_REVISION=1 +LT_AGE=3 AC_SUBST(LT_CURRENT) AC_SUBST(LT_REVISION) AC_SUBST(LT_AGE) +DOXYGEN_REQ_VER=1.8.4 + # Checks for programs. AC_PROG_CC AC_PROG_INSTALL @@ -107,6 +109,15 @@ if test "x$enable_doxygen_doc" = "xyes"; then AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,no) if test "x$DOXYGEN" = "xno"; then enable_doxygen_doc="no" + else + AC_MSG_CHECKING([doxygen >= $DOXYGEN_REQ_VER]) + DOXYGEN_VER=$($DOXYGEN --version) + if expr $DOXYGEN_VER \< $DOXYGEN_REQ_VER > /dev/null; then + AC_MSG_RESULT([$DOXYGEN_VER, no, documentation disabled]) + enable_doxygen_doc="no" + else + AC_MSG_RESULT([$DOXYGEN_VER, yes]) + fi fi fi @@ -128,5 +139,6 @@ AC_CONFIG_FILES([Makefile tools/Makefile man/Makefile doc/Makefile - doc/Doxyfile]) + doc/Doxyfile + tests/Makefile]) AC_OUTPUT diff --git a/libdatrie/datrie/Makefile.am b/libdatrie/datrie/Makefile.am index 9d567ff..e46af46 100644 --- a/libdatrie/datrie/Makefile.am +++ b/libdatrie/datrie/Makefile.am @@ -8,7 +8,7 @@ pkginclude_HEADERS = \ EXTRA_DIST = libdatrie.map libdatrie.def -INCLUDES = -I$(top_srcdir) +AM_CPPFLAGS = -I$(top_srcdir) lib_LTLIBRARIES = libdatrie.la diff --git a/libdatrie/datrie/alpha-map-private.h b/libdatrie/datrie/alpha-map-private.h index d3aceb4..0848ad7 100644 --- a/libdatrie/datrie/alpha-map-private.h +++ b/libdatrie/datrie/alpha-map-private.h @@ -34,7 +34,7 @@ AlphaMap * alpha_map_fread_bin (FILE *file); int alpha_map_fwrite_bin (const AlphaMap *alpha_map, FILE *file); -TrieChar alpha_map_char_to_trie (const AlphaMap *alpha_map, +TrieIndex alpha_map_char_to_trie (const AlphaMap *alpha_map, AlphaChar ac); AlphaChar alpha_map_trie_to_char (const AlphaMap *alpha_map, diff --git a/libdatrie/datrie/alpha-map.c b/libdatrie/datrie/alpha-map.c index 86afdbc..1a8fae9 100644 --- a/libdatrie/datrie/alpha-map.c +++ b/libdatrie/datrie/alpha-map.c @@ -51,6 +51,31 @@ alpha_char_strlen (const AlphaChar *str) return p - str; } +/** + * @brief Compare alphabet strings + * + * @param str1, str2 : the arrays of null-terminated AlphaChar strings + * to compare + * + * @return negative if @a str1 < @a str2; + * 0 if @a str1 == @a str2; + * positive if @a str1 > @a str2 + * + * Available since: 0.2.7 + */ +int +alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2) +{ + while (*str1 && *str1 == *str2) { + str1++; str2++; + } + if (*str1 < *str2) + return -1; + if (*str1 > *str2) + return 1; + return 0; +} + /*------------------------------* * PRIVATE DATA DEFINITONS * *------------------------------*/ @@ -241,6 +266,8 @@ alpha_map_fwrite_bin (const AlphaMap *alpha_map, FILE *file) * @param begin : the first character of the range * @param end : the last character of the range * + * @return 0 on success, non-zero on failure + * * Add a range of character codes from @a begin to @a end to the * alphabet set. */ @@ -342,10 +369,10 @@ alpha_map_add_range (AlphaMap *alpha_map, AlphaChar begin, AlphaChar end) return 0; } -TrieChar +TrieIndex alpha_map_char_to_trie (const AlphaMap *alpha_map, AlphaChar ac) { - TrieChar alpha_begin; + TrieIndex alpha_begin; AlphaRange *range; if (0 == ac) @@ -359,7 +386,7 @@ alpha_map_char_to_trie (const AlphaMap *alpha_map, AlphaChar ac) alpha_begin += range->end - range->begin + 1; } - return TRIE_CHAR_MAX; + return TRIE_INDEX_MAX; } AlphaChar @@ -388,12 +415,22 @@ alpha_map_char_to_trie_str (const AlphaMap *alpha_map, const AlphaChar *str) TrieChar *trie_str, *p; trie_str = (TrieChar *) malloc (alpha_char_strlen (str) + 1); + if (!trie_str) + return NULL; + for (p = trie_str; *str; p++, str++) { - *p = alpha_map_char_to_trie (alpha_map, *str); + TrieIndex tc = alpha_map_char_to_trie (alpha_map, *str); + if (TRIE_INDEX_MAX == tc) + goto error_str_allocated; + *p = (TrieChar) tc; } *p = 0; return trie_str; + +error_str_allocated: + free (trie_str); + return NULL; } AlphaChar * @@ -403,6 +440,9 @@ alpha_map_trie_to_char_str (const AlphaMap *alpha_map, const TrieChar *str) alpha_str = (AlphaChar *) malloc ((strlen ((const char *)str) + 1) * sizeof (AlphaChar)); + if (!alpha_str) + return NULL; + for (p = alpha_str; *str; p++, str++) { *p = (AlphaChar) alpha_map_trie_to_char (alpha_map, *str); } diff --git a/libdatrie/datrie/alpha-map.h b/libdatrie/datrie/alpha-map.h index f6ec422..8c34ad5 100644 --- a/libdatrie/datrie/alpha-map.h +++ b/libdatrie/datrie/alpha-map.h @@ -39,6 +39,25 @@ extern "C" { /** * @file alpha-map.h * @brief AlphaMap data type and functions + * + * AlphaMap is a mapping between AlphaChar and TrieChar. AlphaChar is the + * alphabet character used in words of a target language, while TrieChar + * is a small integer with packed range of values and is actually used in + * trie state transition calculations. + * + * Since double-array trie relies on sparse state transition table, + * a small set of input characters can make the table small, i.e. with + * small number of columns. But in real life, alphabet characters can be + * of non-continuous range of values. The unused slots between them can + * waste the space in the table, and can increase the chance of unused + * array cells. + * + * AlphaMap is thus defined for mapping between non-continuous ranges of + * values of AlphaChar and packed and continuous range of Triechar. + * + * In this implementation, TrieChar is defined as a single-byte integer, + * which means the largest AlphaChar set that is supported is of 255 + * values, as the special value of 0 is reserved for null-termination code. */ /** @@ -57,6 +76,7 @@ int alpha_map_add_range (AlphaMap *alpha_map, AlphaChar end); int alpha_char_strlen (const AlphaChar *str); +int alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2); #ifdef __cplusplus } diff --git a/libdatrie/datrie/darray.c b/libdatrie/datrie/darray.c index 8d976a6..c07712a 100644 --- a/libdatrie/datrie/darray.c +++ b/libdatrie/datrie/darray.c @@ -499,7 +499,7 @@ da_has_children (const DArray *d, return FALSE; max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base); - for (c = 0; c < max_c; c++) { + for (c = 0; c <= max_c; c++) { if (da_get_check (d, base + c) == s) return TRUE; } @@ -519,7 +519,7 @@ da_output_symbols (const DArray *d, base = da_get_base (d, s); max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base); - for (c = 0; c < max_c; c++) { + for (c = 0; c <= max_c; c++) { if (da_get_check (d, base + c) == s) symbols_add_fast (syms, (TrieChar) c); } @@ -617,7 +617,7 @@ da_relocate_base (DArray *d, TrieIndex c, max_c; max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - old_next_base); - for (c = 0; c < max_c; c++) { + for (c = 0; c <= max_c; c++) { if (da_get_check (d, old_next_base + c) == old_next) da_set_check (d, old_next_base + c, new_next); } @@ -765,11 +765,11 @@ TrieIndex da_first_separate (DArray *d, TrieIndex root, TrieString *keybuff) { TrieIndex base; - TrieChar c, max_c; + TrieIndex c, max_c; while ((base = da_get_base (d, root)) >= 0) { max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base); - for (c = 0; c < max_c; c++) { + for (c = 0; c <= max_c; c++) { if (da_get_check (d, base + c) == root) break; } @@ -811,7 +811,7 @@ da_next_separate (DArray *d, TrieIndex root, TrieIndex sep, TrieString *keybuff) { TrieIndex parent; TrieIndex base; - TrieChar c, max_c; + TrieIndex c, max_c; while (sep != root) { parent = da_get_check (d, sep); @@ -822,7 +822,7 @@ da_next_separate (DArray *d, TrieIndex root, TrieIndex sep, TrieString *keybuff) /* find next sibling of sep */ max_c = MIN_VAL (TRIE_CHAR_MAX, d->num_cells - base); - while (++c < max_c) { + while (++c <= max_c) { if (da_get_check (d, base + c) == parent) { trie_string_append_char (keybuff, c); return da_first_separate (d, base + c, keybuff); diff --git a/libdatrie/datrie/dstring.c b/libdatrie/datrie/dstring.c index 4255aad..20d336f 100644 --- a/libdatrie/datrie/dstring.c +++ b/libdatrie/datrie/dstring.c @@ -126,7 +126,7 @@ dstring_append (DString *dst, const DString *src) return FALSE; } - memcpy ((char *)dst->val + (dst->char_size * dst->str_len), (char *)src->val, + memcpy ((char *)dst->val + (dst->char_size * dst->str_len), src->val, (src->str_len + 1) * dst->char_size); dst->str_len += src->str_len; @@ -140,7 +140,8 @@ dstring_append_string (DString *ds, const void *data, int len) if (!dstring_ensure_space (ds, (ds->str_len + len + 1) * ds->char_size)) return FALSE; - memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, ds->char_size * len); + memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, + ds->char_size * len); ds->str_len += len; @@ -153,7 +154,8 @@ dstring_append_char (DString *ds, const void *data) if (!dstring_ensure_space (ds, (ds->str_len + 2) * ds->char_size)) return FALSE; - memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, ds->char_size); + memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, + ds->char_size); ds->str_len++; diff --git a/libdatrie/datrie/libdatrie.def b/libdatrie/datrie/libdatrie.def index 19d4a87..185bda5 100644 --- a/libdatrie/datrie/libdatrie.def +++ b/libdatrie/datrie/libdatrie.def @@ -3,6 +3,7 @@ alpha_map_clone alpha_map_free alpha_map_add_range alpha_char_strlen +alpha_char_strcmp trie_new trie_new_from_file trie_fread diff --git a/libdatrie/datrie/libdatrie.map b/libdatrie/datrie/libdatrie.map index d6a518a..8c9a0da 100644 --- a/libdatrie/datrie/libdatrie.map +++ b/libdatrie/datrie/libdatrie.map @@ -41,3 +41,7 @@ DATRIE_0.2.6 { trie_iterator_get_data; } DATRIE_0.2.4; +DATRIE_0.2.7 { + alpha_char_strcmp; +} DATRIE_0.2.6; + diff --git a/libdatrie/datrie/trie-string.c b/libdatrie/datrie/trie-string.c index 7deddeb..069324a 100644 --- a/libdatrie/datrie/trie-string.c +++ b/libdatrie/datrie/trie-string.c @@ -87,7 +87,8 @@ trie_string_append (TrieString *dst, const TrieString *src) Bool trie_string_append_string (TrieString *ts, const TrieChar *str) { - return dstring_append_string ((DString *)ts, str, strlen (str)); + return dstring_append_string ((DString *)ts, + str, strlen ((const char *)str)); } Bool diff --git a/libdatrie/datrie/trie.c b/libdatrie/datrie/trie.c index e513e23..e5eef2b 100644 --- a/libdatrie/datrie/trie.c +++ b/libdatrie/datrie/trie.c @@ -333,11 +333,11 @@ trie_retrieve (const Trie *trie, const AlphaChar *key, TrieData *o_data) /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { - if (!da_walk (trie->da, &s, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!da_walk (trie->da, &s, (TrieChar) tc)) return FALSE; - } if (0 == *p) break; } @@ -346,11 +346,11 @@ trie_retrieve (const Trie *trie, const AlphaChar *key, TrieData *o_data) s = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { - if (!tail_walk_char (trie->tail, s, &suffix_idx, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!tail_walk_char (trie->tail, s, &suffix_idx, (TrieChar) tc)) return FALSE; - } if (0 == *p) break; } @@ -368,7 +368,7 @@ trie_retrieve (const Trie *trie, const AlphaChar *key, TrieData *o_data) * @param key : the key for the entry to retrieve * @param data : the data associated to the entry * - * @return boolean value indicating the success of the process + * @return boolean value indicating the success of the operation * * Store a @a data for the given @a key in @a trie. If @a key does not * exist in @a trie, it will be appended. If it does, its current data will @@ -387,7 +387,7 @@ trie_store (Trie *trie, const AlphaChar *key, TrieData data) * @param key : the key for the entry to retrieve * @param data : the data associated to the entry * - * @return boolean value indicating the success of the process + * @return boolean value indicating the success of the operation * * Store a @a data for the given @a key in @a trie. If @a key does not * exist in @a trie, it will be appended. If it does, the function will @@ -417,13 +417,16 @@ trie_store_conditionally (Trie *trie, /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { - if (!da_walk (trie->da, &s, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!da_walk (trie->da, &s, (TrieChar) tc)) { TrieChar *key_str; Bool res; key_str = alpha_map_char_to_trie_str (trie->alpha_map, p); + if (!key_str) + return FALSE; res = trie_branch_in_branch (trie, s, key_str, data); free (key_str); @@ -438,13 +441,16 @@ trie_store_conditionally (Trie *trie, t = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { - if (!tail_walk_char (trie->tail, t, &suffix_idx, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!tail_walk_char (trie->tail, t, &suffix_idx, (TrieChar) tc)) { TrieChar *tail_str; Bool res; tail_str = alpha_map_char_to_trie_str (trie->alpha_map, sep); + if (!tail_str) + return FALSE; res = trie_branch_in_tail (trie, s, tail_str, data); free (tail_str); @@ -547,11 +553,11 @@ trie_delete (Trie *trie, const AlphaChar *key) /* walk through branches */ s = da_get_root (trie->da); for (p = key; !trie_da_is_separate (trie->da, s); p++) { - if (!da_walk (trie->da, &s, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!da_walk (trie->da, &s, (TrieChar) tc)) return FALSE; - } if (0 == *p) break; } @@ -560,11 +566,11 @@ trie_delete (Trie *trie, const AlphaChar *key) t = trie_da_get_tail_index (trie->da, s); suffix_idx = 0; for ( ; ; p++) { - if (!tail_walk_char (trie->tail, t, &suffix_idx, - alpha_map_char_to_trie (trie->alpha_map, *p))) - { + TrieIndex tc = alpha_map_char_to_trie (trie->alpha_map, *p); + if (TRIE_INDEX_MAX == tc) + return FALSE; + if (!tail_walk_char (trie->tail, t, &suffix_idx, (TrieChar) tc)) return FALSE; - } if (0 == *p) break; } @@ -742,12 +748,14 @@ trie_state_rewind (TrieState *s) Bool trie_state_walk (TrieState *s, AlphaChar c) { - TrieChar tc = alpha_map_char_to_trie (s->trie->alpha_map, c); + TrieIndex tc = alpha_map_char_to_trie (s->trie->alpha_map, c); + if (TRIE_INDEX_MAX == tc) + return FALSE; if (!s->is_suffix) { Bool ret; - ret = da_walk (s->trie->da, &s->index, tc); + ret = da_walk (s->trie->da, &s->index, (TrieChar) tc); if (ret && trie_da_is_separate (s->trie->da, s->index)) { s->index = trie_da_get_tail_index (s->trie->da, s->index); @@ -757,7 +765,8 @@ trie_state_walk (TrieState *s, AlphaChar c) return ret; } else { - return tail_walk_char (s->trie->tail, s->index, &s->suffix_idx, tc); + return tail_walk_char (s->trie->tail, s->index, &s->suffix_idx, + (TrieChar) tc); } } @@ -774,13 +783,15 @@ trie_state_walk (TrieState *s, AlphaChar c) Bool trie_state_is_walkable (const TrieState *s, AlphaChar c) { - TrieChar tc = alpha_map_char_to_trie (s->trie->alpha_map, c); + TrieIndex tc = alpha_map_char_to_trie (s->trie->alpha_map, c); + if (TRIE_INDEX_MAX == tc) + return FALSE; if (!s->is_suffix) - return da_is_walkable (s->trie->da, s->index, tc); + return da_is_walkable (s->trie->da, s->index, (TrieChar) tc); else return tail_is_walkable_char (s->trie->tail, s->index, s->suffix_idx, - tc); + (TrieChar) tc); } /** @@ -913,7 +924,7 @@ trie_state_get_terminal_data (const TrieState *s) * Create a new trie iterator for iterating entries of a sub-trie rooted at * state @a s. * - * Use it with the result of trie_get_root() to iterate the whole trie. + * Use it with the result of trie_root() to iterate the whole trie. * * The created object must be freed with trie_iterator_free(). * @@ -1039,7 +1050,8 @@ trie_iterator_get_key (const TrieIterator *iter) tail_str += s->suffix_idx; alpha_key = (AlphaChar *) malloc (sizeof (AlphaChar) - * (strlen (tail_str) + 1)); + * (strlen ((const char *)tail_str) + + 1)); alpha_p = alpha_key; } else { TrieIndex tail_idx; @@ -1054,7 +1066,8 @@ trie_iterator_get_key (const TrieIterator *iter) key_len = trie_string_length (iter->key); key_p = trie_string_get_val (iter->key); alpha_key = (AlphaChar *) malloc ( - sizeof (AlphaChar) * (key_len + strlen (tail_str) + 1) + sizeof (AlphaChar) + * (key_len + strlen ((const char *)tail_str) + 1) ); alpha_p = alpha_key; for (i = key_len; i > 0; i--) { diff --git a/libdatrie/datrie/trie.h b/libdatrie/datrie/trie.h index ec48042..a4f7e16 100644 --- a/libdatrie/datrie/trie.h +++ b/libdatrie/datrie/trie.h @@ -37,6 +37,46 @@ extern "C" { /** * @file trie.h * @brief Trie data type and functions + * + * Trie is a kind of digital search tree, an efficient indexing method with + * O(1) time complexity for searching. Comparably as efficient as hashing, + * trie also provides flexibility on incremental matching and key spelling + * manipulation. This makes it ideal for lexical analyzers, as well as + * spelling dictionaries. + * + * This library is an implementation of double-array structure for representing + * trie, as proposed by Junichi Aoe. The details of the implementation can be + * found at http://linux.thai.net/~thep/datrie/datrie.html + * + * A Trie is associated with an AlphaMap, a map between actual alphabet + * characters and the raw character used to walk through trie. + * You can define the alphabet set by adding ranges of character codes + * to it before associating it to a trie. And the keys to be added to the trie + * must be only in such ranges. + * + * A new Trie can be created in memory using trie_new(), saved to file using + * trie_save(), and loaded later with trie_new_from_file(). + * It can even be embeded in another file using trie_fwrite() and read back + * using trie_fread(). + * After use, Trie objects must be freed using trie_free(). + * + * Operations on trie include: + * + * - Add/delete entries with trie_store() and trie_delete() + * - Retrieve entries with trie_retrieve() + * - Walk through trie stepwise with TrieState and its functions + * (trie_root(), trie_state_walk(), trie_state_rewind(), + * trie_state_clone(), trie_state_copy(), + * trie_state_is_walkable(), trie_state_walkable_chars(), + * trie_state_is_single(), trie_state_get_data(). + * And do not forget to free TrieState objects with trie_state_free() + * after use.) + * - Enumerate all keys using trie_enumerate() + * - Iterate entries using TrieIterator and its functions + * (trie_iterator_new(), trie_iterator_next(), trie_iterator_get_key(), + * trie_iterator_get_data(). + * And do not forget to free TrieIterator objects with trie_iterator_free() + * after use.) */ /** diff --git a/libdatrie/datrie/triedefs.h b/libdatrie/datrie/triedefs.h index 01a21cf..1579e2e 100644 --- a/libdatrie/datrie/triedefs.h +++ b/libdatrie/datrie/triedefs.h @@ -35,7 +35,7 @@ */ /** - * @brief Trie character type for alphabet + * @brief Alphabet character type for use as input/output strings of trie keys */ typedef uint32 AlphaChar; @@ -45,7 +45,8 @@ typedef uint32 AlphaChar; #define ALPHA_CHAR_ERROR (~(AlphaChar)0) /** - * @brief Trie character type for key + * @brief Raw character type mapped into packed set from AlphaChar, + * for use in actual trie transition calculations */ typedef unsigned char TrieChar; /** @@ -55,7 +56,7 @@ typedef unsigned char TrieChar; #define TRIE_CHAR_MAX 255 /** - * @brief Type of Trie index + * @brief Type of index into Trie double-array and tail structures */ typedef int32 TrieIndex; /** diff --git a/libdatrie/doc/Doxyfile.in b/libdatrie/doc/Doxyfile.in index 265a48c..1adbb20 100644 --- a/libdatrie/doc/Doxyfile.in +++ b/libdatrie/doc/Doxyfile.in @@ -1,8 +1,10 @@ -# Doxyfile 1.8.1.2 +# Doxyfile 1.8.4 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # +# All text after a double hash (##) is considered a comment and is placed +# in front of the TAG it is preceding . # All text after a hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] @@ -70,9 +72,9 @@ CREATE_SUBDIRS = NO # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# messages), Korean, Korean-en, Latvian, Lithuanian, Norwegian, Macedonian, +# Persian, Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, +# Slovak, Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English @@ -136,7 +138,9 @@ FULL_PATH_NAMES = YES # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the -# path to strip. +# path to strip. Note that you specify absolute paths here, but also +# relative paths, which will be relative from the directory where doxygen is +# started. STRIP_FROM_PATH = @top_srcdir@ @@ -239,14 +243,15 @@ OPTIMIZE_FOR_FORTRAN = NO OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, +# and language is one of the parsers supported by doxygen: IDL, Java, +# Javascript, CSharp, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, +# C++. For instance to make doxygen treat .inc files as Fortran files (default +# is PHP), and .f files as C (default is Fortran), use: inc=Fortran f=C. Note +# that for custom extensions you also need to set FILE_PATTERNS otherwise the +# files are not read by doxygen. EXTENSION_MAPPING = @@ -259,6 +264,13 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and @@ -279,10 +291,10 @@ CPP_CLI_SUPPORT = NO SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES (the +# default) will make doxygen replace the get and set methods by a property in +# the documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. @@ -311,11 +323,11 @@ SUBGROUPING = YES INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# unions with only public data fields or simple typedef fields will be shown +# inline in the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO (the default), structs, classes, and unions are shown on a separate +# page (for HTML and Man pages) or section (for LaTeX and RTF). INLINE_SIMPLE_STRUCTS = NO @@ -329,30 +341,14 @@ INLINE_SIMPLE_STRUCTS = NO TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can +# be an expensive process and often the same symbol appear multiple times in +# the code, doxygen keeps a cache of pre-resolved symbols. If the cache is too +# small doxygen will become slower. If the cache is too large, memory is wasted. +# The cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid +# range is 0..9, the default is 0, corresponding to a cache size of 2^16 = 65536 +# symbols. LOOKUP_CACHE_SIZE = 0 @@ -363,7 +359,7 @@ LOOKUP_CACHE_SIZE = 0 # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# the EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO @@ -372,7 +368,8 @@ EXTRACT_ALL = NO EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. EXTRACT_PACKAGE = NO @@ -543,7 +540,8 @@ GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# documentation sections, marked by \if section-label ... \endif +# and \cond section-label ... \endcond blocks. ENABLED_SECTIONS = @@ -601,7 +599,8 @@ LAYOUT_FILE = # requires the bibtex tool to be installed. See also # http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style # of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# feature you need bibtex and perl available in the search path. Do not use +# file names with spaces, bibtex cannot handle them. CITE_BIB_FILES = @@ -758,8 +757,10 @@ IMAGE_PATH = # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# If FILTER_PATTERNS is specified, this tag will be ignored. +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. INPUT_FILTER = @@ -788,6 +789,13 @@ FILTER_SOURCE_FILES = NO FILTER_SOURCE_PATTERNS = +# If the USE_MD_FILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- @@ -909,17 +917,27 @@ HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! +# fine-tune the look of the HTML output. If left blank doxygen will +# generate a default style sheet. Note that it is recommended to use +# HTML_EXTRA_STYLESHEET instead of this one, as it is more robust and this +# tag will in the future become obsolete. HTML_STYLESHEET = +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional +# user-defined cascading style sheet that is included after the standard +# style sheets created by doxygen. Using this option one can overrule +# certain style aspects. This is preferred over using HTML_STYLESHEET +# since it does not replace the standard style sheet and is therefor more +# robust against future updates. Doxygen will copy the style sheet file to +# the output directory. + +HTML_EXTRA_STYLESHEET = + # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that # the files will be copied as-is; there are no commands or markers available. @@ -1000,9 +1018,9 @@ DOCSET_FEEDNAME = "Doxygen generated docs" DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify -# the documentation publisher. This should be a reverse domain-name style -# string, e.g. com.mycompany.MyDocSet.documentation. +# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely +# identify the documentation publisher. This should be a reverse domain-name +# style string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher @@ -1187,6 +1205,13 @@ FORMULA_TRANSPARENT = YES USE_MATHJAX = NO +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. Supported types are HTML-CSS, NativeMML (i.e. MathML) and +# SVG. The default value is HTML-CSS, which is slower, but has the best +# compatibility. + +MATHJAX_FORMAT = HTML-CSS + # When MathJax is enabled you need to specify the location relative to the # HTML output directory using the MATHJAX_RELPATH option. The destination # directory should contain the MathJax.js script. For instance, if the mathjax @@ -1204,6 +1229,11 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest MATHJAX_EXTENSIONS = +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript +# pieces of code that will be used on startup of the MathJax code. + +MATHJAX_CODEFILE = + # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using @@ -1215,15 +1245,55 @@ MATHJAX_EXTENSIONS = SEARCHENGINE = NO # When the SERVER_BASED_SEARCH tag is enabled the search engine will be -# implemented using a PHP enabled web server instead of at the web client -# using Javascript. Doxygen will generate the search PHP script and index -# file to put on the web server. The advantage of the server -# based approach is that it scales better to large projects and allows -# full text search. The disadvantages are that it is more difficult to setup -# and does not have live searching capabilities. +# implemented using a web server instead of a web client using Javascript. +# There are two flavours of web server based search depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. +# See the manual for details. SERVER_BASED_SEARCH = NO +# When EXTERNAL_SEARCH is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain +# the search results. Doxygen ships with an example indexer (doxyindexer) and +# search engine (doxysearch.cgi) which are based on the open source search +# engine library Xapian. See the manual for configuration details. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will returned the search results when EXTERNAL_SEARCH is enabled. +# Doxygen ships with an example search engine (doxysearch) which is based on +# the open source search engine library Xapian. See the manual for configuration +# details. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH AND EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id +# of to a relative location where the documentation can be found. +# The format is: EXTRA_SEARCH_MAPPINGS = id1=loc1 id2=loc2 ... + +EXTRA_SEARCH_MAPPINGS = + #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- @@ -1261,7 +1331,7 @@ COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, letter, legal and -# executive. If left blank a4wide will be used. +# executive. If left blank a4 will be used. PAPER_TYPE = a4wide @@ -1284,6 +1354,13 @@ LATEX_HEADER = LATEX_FOOTER = +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images +# or other source files which should be copied to the LaTeX output directory. +# Note that the files will be copied as-is; there are no commands or markers +# available. + +LATEX_EXTRA_FILES = + # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references @@ -1428,6 +1505,21 @@ XML_DTD = XML_PROGRAMLISTING = YES +#--------------------------------------------------------------------------- +# configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES Doxygen will generate DOCBOOK files +# that can be used to generate PDF. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the DOCBOOK pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. If left blank docbook will be used as the default path. + +DOCBOOK_OUTPUT = docbook + #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- @@ -1577,6 +1669,12 @@ ALLEXTERNALS = NO EXTERNAL_GROUPS = YES +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed +# in the related pages index. If set to NO, only the current project's +# pages will be listed. + +EXTERNAL_PAGES = YES + # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). @@ -1631,7 +1729,7 @@ DOT_NUM_THREADS = 0 # the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the # directory containing the font. -DOT_FONTNAME = FreeSans +DOT_FONTNAME = # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. @@ -1673,7 +1771,7 @@ UML_LOOK = NO # the class node. If there are many fields or methods and many nodes the # graph may become too big to be useful. The UML_LIMIT_NUM_FIELDS # threshold limits the number of items for each type to make the size more -# managable. Set this to 0 for no limit. Note that the threshold may be +# manageable. Set this to 0 for no limit. Note that the threshold may be # exceeded by 50% before the limit is enforced. UML_LIMIT_NUM_FIELDS = 10 diff --git a/libdatrie/tests/Makefile.am b/libdatrie/tests/Makefile.am new file mode 100644 index 0000000..9720c3d --- /dev/null +++ b/libdatrie/tests/Makefile.am @@ -0,0 +1,54 @@ +AM_CPPFLAGS = -I$(top_srcdir) + +TESTS_ENVIRONMENT = top_builddir=$(top_builddir) + +TESTS = \ + test_walk \ + test_iterator \ + test_store-retrieve \ + test_file \ + test_nonalpha \ + $(NULL) + +check_PROGRAMS = \ + test_walk \ + test_iterator \ + test_store-retrieve \ + test_file \ + test_nonalpha \ + $(NULL) + +noinst_HEADERS = \ + utils.h \ + $(NULL) + +test_walk_SOURCES = \ + test_walk.c \ + utils.c \ + $(NULL) +test_walk_LDADD = $(top_builddir)/datrie/libdatrie.la + +test_iterator_SOURCES = \ + test_iterator.c \ + utils.c \ + $(NULL) +test_iterator_LDADD = $(top_builddir)/datrie/libdatrie.la + +test_store_retrieve_SOURCES = \ + test_store-retrieve.c \ + utils.c \ + $(NULL) +test_store_retrieve_LDADD = $(top_builddir)/datrie/libdatrie.la + +test_file_SOURCES = \ + test_file.c \ + utils.c \ + $(NULL) +test_file_LDADD = $(top_builddir)/datrie/libdatrie.la + +test_nonalpha_SOURCES = \ + test_nonalpha.c \ + utils.c \ + $(NULL) +test_nonalpha_LDADD = $(top_builddir)/datrie/libdatrie.la + diff --git a/libdatrie/tests/test_file.c b/libdatrie/tests/test_file.c new file mode 100644 index 0000000..3e5217c --- /dev/null +++ b/libdatrie/tests/test_file.c @@ -0,0 +1,131 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * test_file.c - Test for datrie file operations + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" +#include +#include + +#define TRIE_FILENAME "test.tri" + +static Bool +trie_enum_mark_rec (const AlphaChar *key, TrieData key_data, void *user_data) +{ + Bool *is_failed = (Bool *)user_data; + TrieData src_data; + + src_data = dict_src_get_data (key); + if (TRIE_DATA_ERROR == src_data) { + printf ("Extra entry in file: key '%ls', data %d.\n", key, key_data); + *is_failed = TRUE; + } else if (src_data != key_data) { + printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", + key, src_data, key_data); + *is_failed = TRUE; + } else { + dict_src_set_data (key, TRIE_DATA_READ); + } + + return TRUE; +} + +int +main () +{ + Trie *test_trie; + DictRec *dict_p; + Bool is_failed; + + msg_step ("Preparing trie"); + test_trie = en_trie_new (); + if (!test_trie) { + printf ("Failed to allocate test trie.\n"); + goto err_trie_not_created; + } + + /* add/remove some words */ + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (!trie_store (test_trie, dict_p->key, dict_p->data)) { + printf ("Failed to add key '%ls', data %d.\n", + dict_p->key, dict_p->data); + goto err_trie_created; + } + } + + /* save & close */ + msg_step ("Saving trie to file"); + unlink (TRIE_FILENAME); /* error ignored */ + if (trie_save (test_trie, TRIE_FILENAME) != 0) { + printf ("Failed to save trie to file '%s'.\n", TRIE_FILENAME); + goto err_trie_created; + } + trie_free (test_trie); + + /* reload from file */ + msg_step ("Reloading trie from the saved file"); + test_trie = trie_new_from_file (TRIE_FILENAME); + if (!test_trie) { + printf ("Failed to reload saved trie from '%s'.\n", + TRIE_FILENAME); + goto err_trie_saved; + } + + /* enumerate & check */ + msg_step ("Checking trie contents"); + is_failed = FALSE; + /* mark entries found in file */ + if (!trie_enumerate (test_trie, trie_enum_mark_rec, (void *)&is_failed)) { + printf ("Failed to enumerate trie file contents.\n"); + goto err_trie_saved; + } + /* check for unmarked entries, (i.e. missed in file) */ + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (dict_p->data != TRIE_DATA_READ) { + printf ("Entry missed in file: key '%ls', data %d.\n", + dict_p->key, dict_p->data); + is_failed = TRUE; + } + } + if (is_failed) { + printf ("Errors found in trie saved contents.\n"); + goto err_trie_saved; + } + + unlink (TRIE_FILENAME); + trie_free (test_trie); + return 0; + +err_trie_saved: + unlink (TRIE_FILENAME); +err_trie_created: + trie_free (test_trie); +err_trie_not_created: + return 1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/test_iterator.c b/libdatrie/tests/test_iterator.c new file mode 100644 index 0000000..03fc6ed --- /dev/null +++ b/libdatrie/tests/test_iterator.c @@ -0,0 +1,136 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * test_iterator.c - Test for datrie iterator operations + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" +#include +#include + +int +main () +{ + Trie *test_trie; + DictRec *dict_p; + TrieState *trie_root_state; + TrieIterator *trie_it; + Bool is_failed; + + msg_step ("Preparing trie"); + test_trie = en_trie_new (); + if (!test_trie) { + fprintf (stderr, "Fail to create test trie\n"); + goto err_trie_not_created; + } + + /* store */ + msg_step ("Adding data to trie"); + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (!trie_store (test_trie, dict_p->key, dict_p->data)) { + printf ("Failed to add key '%ls', data %d.\n", + dict_p->key, dict_p->data); + goto err_trie_created; + } + } + + /* iterate & check */ + msg_step ("Iterating and checking trie contents"); + trie_root_state = trie_root (test_trie); + if (!trie_root_state) { + printf ("Failed to get trie root state\n"); + goto err_trie_created; + } + trie_it = trie_iterator_new (trie_root_state); + if (!trie_it) { + printf ("Failed to get trie iterator\n"); + goto err_trie_root_created; + } + + is_failed = FALSE; + while (trie_iterator_next (trie_it)) { + AlphaChar *key; + TrieData key_data, src_data; + + key = trie_iterator_get_key (trie_it); + if (!key) { + printf ("Failed to get key from trie iterator\n"); + is_failed = TRUE; + continue; + } + key_data = trie_iterator_get_data (trie_it); + if (TRIE_DATA_ERROR == key_data) { + printf ("Failed to get data from trie iterator for key '%ls'\n", + key); + is_failed = TRUE; + } + /* mark entries found in trie */ + src_data = dict_src_get_data (key); + if (TRIE_DATA_ERROR == src_data) { + printf ("Extra entry in trie: key '%ls', data %d.\n", + key, key_data); + is_failed = TRUE; + } else if (src_data != key_data) { + printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", + key, src_data, key_data); + is_failed = TRUE; + } else { + dict_src_set_data (key, TRIE_DATA_READ); + } + + free (key); + } + + /* check for unmarked entries, (i.e. missed in trie) */ + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (dict_p->data != TRIE_DATA_READ) { + printf ("Entry missed in trie: key '%ls', data %d.\n", + dict_p->key, dict_p->data); + is_failed = TRUE; + } + } + + if (is_failed) { + printf ("Errors found in trie iteration.\n"); + goto err_trie_it_created; + } + + trie_iterator_free (trie_it); + trie_state_free (trie_root_state); + trie_free (test_trie); + return 0; + +err_trie_it_created: + trie_iterator_free (trie_it); +err_trie_root_created: + trie_state_free (trie_root_state); +err_trie_created: + trie_free (test_trie); +err_trie_not_created: + return 1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/test_nonalpha.c b/libdatrie/tests/test_nonalpha.c new file mode 100644 index 0000000..06f2f54 --- /dev/null +++ b/libdatrie/tests/test_nonalpha.c @@ -0,0 +1,92 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2014 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * test_nonalpha.c - Test for datrie behaviors on non-alphabet inputs + * Created: 2014-01-06 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" +#include + +const AlphaChar *nonalpha_src[] = { + (AlphaChar *)L"a6acus", + (AlphaChar *)L"a5acus", + NULL +}; + +int +main () +{ + Trie *test_trie; + DictRec *dict_p; + const AlphaChar **nonalpha_key; + TrieData trie_data; + Bool is_fail; + + msg_step ("Preparing trie"); + test_trie = en_trie_new (); + if (!test_trie) { + fprintf (stderr, "Fail to create test trie\n"); + goto err_trie_not_created; + } + + /* store */ + msg_step ("Adding data to trie"); + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (!trie_store (test_trie, dict_p->key, dict_p->data)) { + printf ("Failed to add key '%ls', data %d.\n", + dict_p->key, dict_p->data); + goto err_trie_created; + } + } + + /* test storing keys with non-alphabet chars */ + is_fail = FALSE; + for (nonalpha_key = nonalpha_src; *nonalpha_key; nonalpha_key++) { + if (trie_retrieve (test_trie, *nonalpha_key, &trie_data)) { + printf ("False duplication on key '%ls', with existing data %d.\n", + *nonalpha_key, trie_data); + is_fail = TRUE; + } + if (trie_store (test_trie, *nonalpha_key, TRIE_DATA_UNREAD)) { + printf ("Wrongly added key '%ls' containing non-alphanet char\n", + *nonalpha_key); + is_fail = TRUE; + } + } + + if (is_fail) + goto err_trie_created; + + trie_free (test_trie); + return 0; + +err_trie_created: + trie_free (test_trie); +err_trie_not_created: + return 1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/test_store-retrieve.c b/libdatrie/tests/test_store-retrieve.c new file mode 100644 index 0000000..28e5aef --- /dev/null +++ b/libdatrie/tests/test_store-retrieve.c @@ -0,0 +1,201 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * test_store-retrieve.c - Test for datrie store/retrieve operations + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" +#include +#include +#include + +int +main () +{ + Trie *test_trie; + DictRec *dict_p; + TrieData trie_data; + Bool is_failed; + int n_entries, n_dels, i; + TrieState *trie_root_state; + TrieIterator *trie_it; + + msg_step ("Preparing trie"); + test_trie = en_trie_new (); + if (!test_trie) { + fprintf (stderr, "Fail to create test trie\n"); + goto err_trie_not_created; + } + + /* store */ + msg_step ("Adding data to trie"); + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (!trie_store (test_trie, dict_p->key, dict_p->data)) { + printf ("Failed to add key '%ls', data %d.\n", + dict_p->key, dict_p->data); + goto err_trie_created; + } + } + + /* retrieve */ + msg_step ("Retrieving data from trie"); + is_failed = FALSE; + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (!trie_retrieve (test_trie, dict_p->key, &trie_data)) { + printf ("Failed to retrieve key '%ls'.\n", dict_p->key); + is_failed = TRUE; + } + if (trie_data != dict_p->data) { + printf ("Wrong data for key '%ls'; expected %d, got %d.\n", + dict_p->key, dict_p->data, trie_data); + is_failed = TRUE; + } + } + if (is_failed) { + printf ("Trie store/retrieval test failed.\n"); + goto err_trie_created; + } + + /* delete */ + msg_step ("Deleting some entries from trie"); + n_entries = dict_src_n_entries (); + srand (time (NULL)); + for (n_dels = n_entries/3 + 1; n_dels > 0; n_dels--) { + /* pick an undeleted entry */ + do { + i = rand () % n_entries; + } while (TRIE_DATA_READ == dict_src[i].data); + + printf ("Deleting '%ls'\n", dict_src[i].key); + if (!trie_delete (test_trie, dict_src[i].key)) { + printf ("Failed to delete '%ls'\n", dict_src[i].key); + is_failed = TRUE; + } + dict_src[i].data = TRIE_DATA_READ; + } + if (is_failed) { + printf ("Trie deletion test failed.\n"); + goto err_trie_created; + } + + /* retrieve */ + msg_step ("Retrieving data from trie again after deletions"); + for (dict_p = dict_src; dict_p->key; dict_p++) { + /* skip deleted entries */ + if (TRIE_DATA_READ == dict_p->data) + continue; + + if (!trie_retrieve (test_trie, dict_p->key, &trie_data)) { + printf ("Failed to retrieve key '%ls'.\n", dict_p->key); + is_failed = TRUE; + } + if (trie_data != dict_p->data) { + printf ("Wrong data for key '%ls'; expected %d, got %d.\n", + dict_p->key, dict_p->data, trie_data); + is_failed = TRUE; + } + } + if (is_failed) { + printf ("Trie retrival-after-deletion test failed.\n"); + goto err_trie_created; + } + + /* enumerate & check */ + msg_step ("Iterating trie contents after deletions"); + trie_root_state = trie_root (test_trie); + if (!trie_root_state) { + printf ("Failed to get trie root state\n"); + goto err_trie_created; + } + trie_it = trie_iterator_new (trie_root_state); + if (!trie_it) { + printf ("Failed to get trie iterator\n"); + goto err_trie_root_created; + } + + while (trie_iterator_next (trie_it)) { + AlphaChar *key; + TrieData key_data, src_data; + + key = trie_iterator_get_key (trie_it); + if (!key) { + printf ("Failed to get key from trie iterator\n"); + is_failed = TRUE; + continue; + } + key_data = trie_iterator_get_data (trie_it); + if (TRIE_DATA_ERROR == key_data) { + printf ("Failed to get data from trie iterator for key '%ls'\n", + key); + is_failed = TRUE; + } + /* mark entries found in trie */ + src_data = dict_src_get_data (key); + if (TRIE_DATA_ERROR == src_data) { + printf ("Extra entry in trie: key '%ls', data %d.\n", + key, key_data); + is_failed = TRUE; + } else if (src_data != key_data) { + printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", + key, src_data, key_data); + is_failed = TRUE; + } else { + dict_src_set_data (key, TRIE_DATA_READ); + } + + free (key); + } + + /* check for unmarked entries, (i.e. missed in trie) */ + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (dict_p->data != TRIE_DATA_READ) { + printf ("Entry missed in trie: key '%ls', data %d.\n", + dict_p->key, dict_p->data); + is_failed = TRUE; + } + } + + if (is_failed) { + printf ("Errors found in trie iteration after deletions.\n"); + goto err_trie_it_created; + } + + trie_iterator_free (trie_it); + trie_state_free (trie_root_state); + trie_free (test_trie); + return 0; + +err_trie_it_created: + trie_iterator_free (trie_it); +err_trie_root_created: + trie_state_free (trie_root_state); +err_trie_created: + trie_free (test_trie); +err_trie_not_created: + return 1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/test_walk.c b/libdatrie/tests/test_walk.c new file mode 100644 index 0000000..45f1119 --- /dev/null +++ b/libdatrie/tests/test_walk.c @@ -0,0 +1,549 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * test_walk.c - Test for datrie walking operations + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" +#include + +/* + * Sample trie in http://linux.thai.net/~thep/datrie/datrie.html + * + * +---o-> (3) -o-> (4) -l-> [5] + * | + * | +---i-> (7) -z-> (8) -e-> [9] + * | | + * (1) -p-> (2) -r-> (6) -e-> (10) -v-> (11) -i-> (12) -e-> (13) -w-> [14] + * | | + * | +---p-> (15) -a-> (16) -r-> (17) -e-> [18] + * | + * +---o-> (19) -d-> (20) -u-> (21) -c-> (22) -e-> [23] + * | + * +---g-> (24) -r-> (25) -e-> (26) -s-> (27) -s-> [28] + * + */ +DictRec walk_dict[] = { + {(AlphaChar *)L"pool", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"prize", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"preview", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"prepare", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"produce", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"progress", TRIE_DATA_UNREAD}, + {(AlphaChar *)NULL, TRIE_DATA_ERROR}, +}; + +static Bool +is_walkables_include (AlphaChar c, const AlphaChar *walkables, int n_elm) +{ + while (n_elm > 0) { + if (walkables[--n_elm] == c) + return TRUE; + } + return FALSE; +} + +static void +print_walkables (const AlphaChar *walkables, int n_elm) +{ + int i; + + printf ("{"); + for (i = 0; i < n_elm; i++) { + if (i > 0) { + printf (", "); + } + printf ("'%lc'", walkables[i]); + } + printf ("}"); +} + +#define ALPHABET_SIZE 256 + +int +main () +{ + Trie *test_trie; + DictRec *dict_p; + TrieState *s, *t, *u; + AlphaChar walkables[ALPHABET_SIZE]; + int n; + Bool is_failed; + TrieData data; + + msg_step ("Preparing trie"); + test_trie = en_trie_new (); + if (!test_trie) { + fprintf (stderr, "Fail to create test trie\n"); + goto err_trie_not_created; + } + + /* store */ + for (dict_p = walk_dict; dict_p->key; dict_p++) { + if (!trie_store (test_trie, dict_p->key, dict_p->data)) { + printf ("Failed to add key '%ls', data %d.\n", + dict_p->key, dict_p->data); + goto err_trie_created; + } + } + + printf ( + "Now the trie structure is supposed to be:\n" + "\n" + " +---o-> (3) -o-> (4) -l-> [5]\n" + " |\n" + " | +---i-> (7) -z-> (8) -e-> [9]\n" + " | |\n" + "(1) -p-> (2) -r-> (6) -e-> (10) -v-> (11) -i-> (12) -e-> (13) -w-> [14]\n" + " | |\n" + " | +---p-> (15) -a-> (16) -r-> (17) -e-> [18]\n" + " |\n" + " +---o-> (19) -d-> (20) -u-> (21) -c-> (22) -e-> [23]\n" + " |\n" + " +---g-> (24) -r-> (25) -e-> (26) -s-> (27) -s-> [28]\n" + "\n" + ); + + /* walk */ + msg_step ("Test walking"); + s = trie_root (test_trie); + if (!s) { + printf ("Failed to get trie root state\n"); + goto err_trie_created; + } + + msg_step ("Test walking with 'p'"); + if (!trie_state_is_walkable (s, L'p')) { + printf ("Trie state is not walkable with 'p'\n"); + goto err_trie_state_s_created; + } + if (!trie_state_walk (s, L'p')) { + printf ("Failed to walk with 'p'\n"); + goto err_trie_state_s_created; + } + + msg_step ("Now at (2), walkable chars should be {'o', 'r'}"); + is_failed = FALSE; + n = trie_state_walkable_chars (s, walkables, ALPHABET_SIZE); + if (2 != n) { + printf ("Walkable chars should be exactly 2, got %d\n", n); + is_failed = TRUE; + } + if (!is_walkables_include (L'o', walkables, n)) { + printf ("Walkable chars do not include 'o'\n"); + is_failed = TRUE; + } + if (!is_walkables_include (L'r', walkables, n)) { + printf ("Walkable chars do not include 'r'\n"); + is_failed = TRUE; + } + if (is_failed) { + printf ("Walkables = "); + print_walkables (walkables, n); + printf ("\n"); + goto err_trie_state_s_created; + } + + msg_step ("Try walking from (2) with 'o' to (3)"); + t = trie_state_clone (s); + if (!t) { + printf ("Failed to clone trie state\n"); + goto err_trie_state_s_created; + } + if (!trie_state_walk (t, L'o')) { + printf ("Failed to walk from (2) with 'o' to (3)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_single (t)) { + printf ("(3) should be single, but isn't.\n"); + goto err_trie_state_t_created; + } + + msg_step ("Try walking from (3) with 'o' to (4)"); + if (!trie_state_walk (t, L'o')) { + printf ("Failed to walk from (3) with 'o' to (4)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_single (t)) { + printf ("(4) should be single, but isn't.\n"); + goto err_trie_state_t_created; + } + + msg_step ("Try walking from (4) with 'l' to (5)"); + if (!trie_state_walk (t, L'l')) { + printf ("Failed to walk from (4) with 'l' to (5)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_terminal (t)) { + printf ("(5) should be terminal, but isn't.\n"); + goto err_trie_state_t_created; + } + + /* get key & data */ + msg_step ("Try getting data from (5)"); + data = trie_state_get_data (t); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (5)\n"); + goto err_trie_state_t_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (5), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_t_created; + } + + /* walk s from (2) with 'r' to (6) */ + msg_step ("Try walking from (2) with 'r' to (6)"); + if (!trie_state_walk (s, L'r')) { + printf ("Failed to walk from (2) with 'r' to (6)\n"); + goto err_trie_state_t_created; + } + + msg_step ("Now at (6), walkable chars should be {'e', 'i', 'o'}"); + is_failed = FALSE; + n = trie_state_walkable_chars (s, walkables, ALPHABET_SIZE); + if (3 != n) { + printf ("Walkable chars should be exactly 3, got %d\n", n); + is_failed = TRUE; + } + if (!is_walkables_include (L'e', walkables, n)) { + printf ("Walkable chars do not include 'e'\n"); + is_failed = TRUE; + } + if (!is_walkables_include (L'i', walkables, n)) { + printf ("Walkable chars do not include 'i'\n"); + is_failed = TRUE; + } + if (!is_walkables_include (L'o', walkables, n)) { + printf ("Walkable chars do not include 'o'\n"); + is_failed = TRUE; + } + if (is_failed) { + printf ("Walkables = "); + print_walkables (walkables, n); + printf ("\n"); + goto err_trie_state_t_created; + } + + /* walk from s (6) with "ize" */ + msg_step ("Try walking from (6) with 'i' to (7)"); + trie_state_copy (t, s); + if (!trie_state_walk (t, L'i')) { + printf ("Failed to walk from (6) with 'i' to (7)\n"); + goto err_trie_state_t_created; + } + msg_step ("Try walking from (7) with 'z' to (8)"); + if (!trie_state_walk (t, L'z')) { + printf ("Failed to walk from (7) with 'z' to (8)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_single (t)) { + printf ("(7) should be single, but isn't.\n"); + goto err_trie_state_t_created; + } + msg_step ("Try walking from (8) with 'e' to (9)"); + if (!trie_state_walk (t, L'e')) { + printf ("Failed to walk from (8) with 'e' to (9)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_terminal (t)) { + printf ("(9) should be terminal, but isn't.\n"); + goto err_trie_state_t_created; + } + + msg_step ("Try getting data from (9)"); + data = trie_state_get_data (t); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (9)\n"); + goto err_trie_state_t_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (9), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_t_created; + } + + /* walk from u = s (6) with 'e' to (10) */ + msg_step ("Try walking from (6) with 'e' to (10)"); + u = trie_state_clone (s); + if (!u) { + printf ("Failed to clone trie state\n"); + goto err_trie_state_t_created; + } + if (!trie_state_walk (u, L'e')) { + printf ("Failed to walk from (6) with 'e' to (10)\n"); + goto err_trie_state_u_created; + } + + /* walkable chars from (10) should be {'p', 'v'} */ + msg_step ("Now at (10), walkable chars should be {'p', 'v'}"); + is_failed = FALSE; + n = trie_state_walkable_chars (u, walkables, ALPHABET_SIZE); + if (2 != n) { + printf ("Walkable chars should be exactly 2, got %d\n", n); + is_failed = TRUE; + } + if (!is_walkables_include (L'p', walkables, n)) { + printf ("Walkable chars do not include 'p'\n"); + is_failed = TRUE; + } + if (!is_walkables_include (L'v', walkables, n)) { + printf ("Walkable chars do not include 'v'\n"); + is_failed = TRUE; + } + if (is_failed) { + printf ("Walkables = "); + print_walkables (walkables, n); + printf ("\n"); + goto err_trie_state_u_created; + } + + /* walk from u (10) with "view" */ + msg_step ("Try walking from (10) with 'v' to (11)"); + trie_state_copy (t, u); + if (!trie_state_walk (t, L'v')) { + printf ("Failed to walk from (10) with 'v' to (11)\n"); + goto err_trie_state_u_created; + } + if (!trie_state_is_single (t)) { + printf ("(11) should be single, but isn't.\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (11) with 'i' to (12)"); + if (!trie_state_walk (t, L'i')) { + printf ("Failed to walk from (11) with 'i' to (12)\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (12) with 'e' to (13)"); + if (!trie_state_walk (t, L'e')) { + printf ("Failed to walk from (12) with 'e' to (13)\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (13) with 'w' to (14)"); + if (!trie_state_walk (t, L'w')) { + printf ("Failed to walk from (13) with 'w' to (14)\n"); + goto err_trie_state_u_created; + } + if (!trie_state_is_terminal (t)) { + printf ("(14) should be terminal, but isn't.\n"); + goto err_trie_state_u_created; + } + + msg_step ("Try getting data from (14)"); + data = trie_state_get_data (t); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (14)\n"); + goto err_trie_state_u_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (14), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_u_created; + } + + /* walk from u (10) with "pare" */ + msg_step ("Try walking from (10) with 'p' to (15)"); + trie_state_copy (t, u); + if (!trie_state_walk (t, L'p')) { + printf ("Failed to walk from (10) with 'p' to (15)\n"); + goto err_trie_state_u_created; + } + if (!trie_state_is_single (t)) { + printf ("(15) should be single, but isn't.\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (15) with 'a' to (16)"); + if (!trie_state_walk (t, L'a')) { + printf ("Failed to walk from (15) with 'a' to (16)\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (16) with 'r' to (17)"); + if (!trie_state_walk (t, L'r')) { + printf ("Failed to walk from (16) with 'r' to (17)\n"); + goto err_trie_state_u_created; + } + msg_step ("Try walking from (17) with 'e' to (18)"); + if (!trie_state_walk (t, L'e')) { + printf ("Failed to walk from (17) with 'e' to (18)\n"); + goto err_trie_state_u_created; + } + if (!trie_state_is_terminal (t)) { + printf ("(18) should be terminal, but isn't.\n"); + goto err_trie_state_u_created; + } + + msg_step ("Try getting data from (18)"); + data = trie_state_get_data (t); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (18)\n"); + goto err_trie_state_u_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (18), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_u_created; + } + + trie_state_free (u); + + /* walk s from (6) with 'o' to (19) */ + msg_step ("Try walking from (6) with 'o' to (19)"); + if (!trie_state_walk (s, L'o')) { + printf ("Failed to walk from (6) with 'o' to (19)\n"); + goto err_trie_state_t_created; + } + + msg_step ("Now at (19), walkable chars should be {'d', 'g'}"); + is_failed = FALSE; + n = trie_state_walkable_chars (s, walkables, ALPHABET_SIZE); + if (2 != n) { + printf ("Walkable chars should be exactly 2, got %d\n", n); + is_failed = TRUE; + } + if (!is_walkables_include (L'd', walkables, n)) { + printf ("Walkable chars do not include 'd'\n"); + is_failed = TRUE; + } + if (!is_walkables_include (L'g', walkables, n)) { + printf ("Walkable chars do not include 'g'\n"); + is_failed = TRUE; + } + if (is_failed) { + printf ("Walkables = "); + print_walkables (walkables, n); + printf ("\n"); + goto err_trie_state_t_created; + } + + /* walk from s (19) with "duce" */ + msg_step ("Try walking from (19) with 'd' to (20)"); + trie_state_copy (t, s); + if (!trie_state_walk (t, L'd')) { + printf ("Failed to walk from (19) with 'd' to (20)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_single (t)) { + printf ("(20) should be single, but isn't.\n"); + goto err_trie_state_t_created; + } + msg_step ("Try walking from (20) with 'u' to (21)"); + if (!trie_state_walk (t, L'u')) { + printf ("Failed to walk from (20) with 'u' to (21)\n"); + goto err_trie_state_t_created; + } + msg_step ("Try walking from (21) with 'c' to (22)"); + if (!trie_state_walk (t, L'c')) { + printf ("Failed to walk from (21) with 'c' to (22)\n"); + goto err_trie_state_t_created; + } + msg_step ("Try walking from (22) with 'e' to (23)"); + if (!trie_state_walk (t, L'e')) { + printf ("Failed to walk from (22) with 'e' to (23)\n"); + goto err_trie_state_t_created; + } + if (!trie_state_is_terminal (t)) { + printf ("(23) should be terminal, but isn't.\n"); + goto err_trie_state_t_created; + } + + msg_step ("Try getting data from (23)"); + data = trie_state_get_data (t); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (23)\n"); + goto err_trie_state_t_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (23), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_t_created; + } + + trie_state_free (t); + + /* walk from s (19) with "gress" */ + msg_step ("Try walking from (19) with 'g' to (24)"); + if (!trie_state_walk (s, L'g')) { + printf ("Failed to walk from (19) with 'g' to (24)\n"); + goto err_trie_state_s_created; + } + if (!trie_state_is_single (s)) { + printf ("(24) should be single, but isn't.\n"); + goto err_trie_state_s_created; + } + msg_step ("Try walking from (24) with 'r' to (25)"); + if (!trie_state_walk (s, L'r')) { + printf ("Failed to walk from (24) with 'r' to (25)\n"); + goto err_trie_state_s_created; + } + msg_step ("Try walking from (25) with 'e' to (26)"); + if (!trie_state_walk (s, L'e')) { + printf ("Failed to walk from (25) with 'e' to (26)\n"); + goto err_trie_state_s_created; + } + msg_step ("Try walking from (26) with 's' to (27)"); + if (!trie_state_walk (s, L's')) { + printf ("Failed to walk from (26) with 's' to (27)\n"); + goto err_trie_state_s_created; + } + msg_step ("Try walking from (27) with 's' to (28)"); + if (!trie_state_walk (s, L's')) { + printf ("Failed to walk from (27) with 's' to (28)\n"); + goto err_trie_state_s_created; + } + if (!trie_state_is_terminal (s)) { + printf ("(28) should be terminal, but isn't.\n"); + goto err_trie_state_s_created; + } + + msg_step ("Try getting data from (28)"); + data = trie_state_get_data (s); + if (TRIE_DATA_ERROR == data) { + printf ("Failed to get data from (28)\n"); + goto err_trie_state_s_created; + } + if (TRIE_DATA_UNREAD != data) { + printf ("Mismatched data from (28), expected %d, got %d\n", + TRIE_DATA_UNREAD, data); + goto err_trie_state_s_created; + } + + trie_state_free (s); + trie_free (test_trie); + return 0; + +err_trie_state_u_created: + trie_state_free (u); +err_trie_state_t_created: + trie_state_free (t); +err_trie_state_s_created: + trie_state_free (s); +err_trie_created: + trie_free (test_trie); +err_trie_not_created: + return 1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/utils.c b/libdatrie/tests/utils.c new file mode 100644 index 0000000..fc421ea --- /dev/null +++ b/libdatrie/tests/utils.c @@ -0,0 +1,168 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * utils.c - Utility functions for datrie test cases + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include +#include "utils.h" + +/*---------------------* + * Debugging helpers * + *---------------------*/ +void +msg_step (const char *msg) +{ + printf ("=> %s...\n", msg); +} + +/*-------------------------* + * Trie creation helpers * + *-------------------------*/ +static AlphaMap * +en_alpha_map_new () +{ + AlphaMap *en_map; + + en_map = alpha_map_new (); + if (!en_map) + goto err_map_not_created; + + if (alpha_map_add_range (en_map, 0x0061, 0x007a) != 0) + goto err_map_created; + + return en_map; + +err_map_created: + alpha_map_free (en_map); +err_map_not_created: + return NULL; +} + +Trie * +en_trie_new () +{ + AlphaMap *en_map; + Trie *en_trie; + + en_map = en_alpha_map_new (); + if (!en_map) + goto err_map_not_created; + + en_trie = trie_new (en_map); + if (!en_trie) + goto err_map_created; + + alpha_map_free (en_map); + return en_trie; + +err_map_created: + alpha_map_free (en_map); +err_map_not_created: + return NULL; +} + +/*---------------------------* + * Dict source for testing * + *---------------------------*/ +DictRec dict_src[] = { + {(AlphaChar *)L"a", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"abacus", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"abandon", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"accident", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"accredit", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"algorithm", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"ammonia", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"angel", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"angle", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"azure", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"bat", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"bet", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"best", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"home", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"house", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"hut", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"king", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"kite", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"name", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"net", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"network", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"nut", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"nutshell", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quality", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quantum", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quantity", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quartz", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quick", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"quiz", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"run", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"tape", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"test", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"what", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"when", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"where", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"which", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"who", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"why", TRIE_DATA_UNREAD}, + {(AlphaChar *)L"zebra", TRIE_DATA_UNREAD}, + {(AlphaChar *)NULL, TRIE_DATA_ERROR}, +}; + +int +dict_src_n_entries () +{ + return sizeof (dict_src) / sizeof (dict_src[0]) - 1; +} + +TrieData +dict_src_get_data (const AlphaChar *key) +{ + const DictRec *dict_p; + + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (alpha_char_strcmp (dict_p->key, key) == 0) { + return dict_p->data; + } + } + + return TRIE_DATA_ERROR; +} + +int +dict_src_set_data (const AlphaChar *key, TrieData data) +{ + DictRec *dict_p; + + for (dict_p = dict_src; dict_p->key; dict_p++) { + if (alpha_char_strcmp (dict_p->key, key) == 0) { + dict_p->data = data; + return 0; + } + } + + return -1; +} + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tests/utils.h b/libdatrie/tests/utils.h new file mode 100644 index 0000000..2fc957c --- /dev/null +++ b/libdatrie/tests/utils.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * libdatrie - Double-Array Trie Library + * Copyright (C) 2013 Theppitak Karoonboonyanan + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * utils.h - Utility functions for datrie test cases + * Created: 2013-10-16 + * Author: Theppitak Karoonboonyanan + */ + +#include + +/*---------------------* + * Debugging helpers * + *---------------------*/ +void msg_step (const char *msg); + +/*-------------------------* + * Trie creation helpers * + *-------------------------*/ +Trie * en_trie_new (); + +/*---------------------------* + * Dict source for testing * + *---------------------------*/ +typedef struct _DictRec DictRec; +struct _DictRec { + AlphaChar *key; + TrieData data; +}; + +#define TRIE_DATA_UNREAD 1 +#define TRIE_DATA_READ 2 + +extern DictRec dict_src[]; + +int dict_src_n_entries (); +TrieData dict_src_get_data (const AlphaChar *key); +int dict_src_set_data (const AlphaChar *key, TrieData data); + +/* +vi:ts=4:ai:expandtab +*/ diff --git a/libdatrie/tools/Makefile.am b/libdatrie/tools/Makefile.am index 4f44b2f..8d30622 100644 --- a/libdatrie/tools/Makefile.am +++ b/libdatrie/tools/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES = -I$(top_srcdir) +AM_CPPFLAGS = -I$(top_srcdir) bin_PROGRAMS = trietool-0.2