├── man ├── .cvsignore ├── Makefile.am └── trietool.1 ├── AUTHORS ├── datrie ├── .cvsignore ├── libdatrie.def ├── libdatrie.map ├── Makefile.am ├── dstring-private.h ├── fileutils.h ├── dstring.h ├── trie-private.h ├── alpha-map-private.h ├── triedefs.h ├── trie-string.h ├── alpha-map.h ├── tail.h ├── darray.h ├── fileutils.c ├── typedefs.h ├── trie-string.c ├── dstring.c ├── trie.h ├── tail.c └── alpha-map.c ├── tools ├── .cvsignore └── Makefile.am ├── doc ├── .cvsignore └── Makefile.am ├── datrie-0.2.pc.in ├── .cvsignore ├── Makefile.am ├── autogen.sh ├── INSTALL ├── nsis ├── README ├── contrib │ └── libdatrienv.sh ├── make-nsis ├── ChangeLog ├── SearchReplace.nsh ├── WriteEnvStr.nsh ├── WritePathStr.nsh └── libdatrie.nsi ├── README ├── tests ├── utils.h ├── Makefile.am ├── test_null_trie.c ├── test_byte_alpha.c ├── test_nonalpha.c ├── test_term_state.c ├── test_file.c ├── test_serialization.c ├── test_iterator.c ├── test_byte_list.c ├── utils.c └── test_store-retrieve.c ├── configure.ac ├── NEWS └── README.migration /man/.cvsignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | Makefile 3 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Theppitak Karoonboonyanan 2 | -------------------------------------------------------------------------------- /datrie/.cvsignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | Makefile 3 | *.o 4 | *.lo 5 | *.la 6 | -------------------------------------------------------------------------------- /tools/.cvsignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | Makefile 3 | *.o 4 | *.lo 5 | *.la 6 | -------------------------------------------------------------------------------- /doc/.cvsignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | Makefile 3 | Doxyfile 4 | doxygen.stamp 5 | html 6 | -------------------------------------------------------------------------------- /datrie-0.2.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: datrie 7 | Description: Double-array trie library 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -ldatrie 10 | Cflags: -I${includedir} 11 | -------------------------------------------------------------------------------- /.cvsignore: -------------------------------------------------------------------------------- 1 | Makefile.in 2 | aclocal.m4 3 | autom4te.cache 4 | m4 5 | depcomp 6 | config.h.in 7 | configure 8 | config.h 9 | config.log 10 | config.status 11 | config.guess 12 | config.sub 13 | INSTALL 14 | install-sh 15 | missing 16 | libtool 17 | ltmain.sh 18 | Makefile 19 | stamp-h1 20 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | 3 | SUBDIRS = datrie tools man doc tests 4 | 5 | EXTRA_DIST = \ 6 | README.migration \ 7 | build-aux/git-version-gen \ 8 | $(NULL) 9 | 10 | pkgconfigdir = $(libdir)/pkgconfig 11 | pkgconfig_DATA = datrie-0.2.pc 12 | 13 | dist-hook: 14 | echo $(VERSION) > $(distdir)/VERSION 15 | -------------------------------------------------------------------------------- /man/Makefile.am: -------------------------------------------------------------------------------- 1 | EXTRA_DIST = trietool.1 2 | 3 | man_MANS = trietool.1 4 | 5 | OLD_MAN_NAME=trietool-0.2.1 6 | 7 | install-data-hook: 8 | rm -f $(DESTDIR)$(mandir)/man1/$(OLD_MAN_NAME) 9 | $(LN_S) trietool.1 $(DESTDIR)$(mandir)/man1/$(OLD_MAN_NAME) 10 | 11 | uninstall-hook: 12 | rm -f $(DESTDIR)$(mandir)/man1/$(OLD_MAN_NAME) 13 | 14 | -------------------------------------------------------------------------------- /tools/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -I$(top_srcdir) 2 | 3 | bin_PROGRAMS = trietool 4 | 5 | trietool_SOURCES = trietool.c 6 | trietool_LDADD = \ 7 | $(top_builddir)/datrie/libdatrie.la \ 8 | $(ICONV_LIBS) 9 | 10 | OLD_PROG_NAME=trietool-0.2 11 | 12 | install-data-hook: 13 | $(MKDIR_P) $(DESTDIR)$(bindir) 14 | rm -f $(DESTDIR)$(bindir)/$(OLD_PROG_NAME) 15 | $(LN_S) trietool $(DESTDIR)$(bindir)/$(OLD_PROG_NAME) 16 | 17 | uninstall-hook: 18 | rm -f $(DESTDIR)$(bindir)/$(OLD_PROG_NAME) 19 | 20 | -------------------------------------------------------------------------------- /autogen.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -x 4 | 5 | DIE=0 6 | 7 | # Detect [g]libtoolize 8 | if libtoolize --version > /dev/null 2>&1; then 9 | LIBTOOLIZE=libtoolize 10 | elif glibtoolize --version > /dev/null 2>&1; then 11 | LIBTOOLIZE=glibtoolize 12 | else 13 | echo "**Error**: Missing 'libtoolize'" 14 | DIE=1 15 | fi 16 | 17 | if [ $DIE -eq 1 ]; then 18 | exit 1 19 | fi 20 | 21 | autoheader 22 | ${LIBTOOLIZE} --force 23 | aclocal 24 | automake --add-missing 25 | # Use -f so git-version-gen does refresh 26 | autoconf -f 27 | 28 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Basic Installation 2 | ================== 3 | 4 | # Build requirements: 5 | # - libtool 6 | # - iconv support (normally from glibc on GNU systems; some systems might 7 | # provide libiconv) 8 | # - doxygen (optional, for documentation generation) 9 | 10 | # When downloaded from the Github repo (Skip for released tarballs) 11 | ./autogen.sh 12 | 13 | ./configure 14 | # Or to install elsewhere: ./configure --prefix=... 15 | 16 | make 17 | 18 | # Recommended 19 | make check 20 | 21 | # With elevated permissions if required 22 | make install 23 | 24 | # In order to uninstall 25 | make uninstall 26 | 27 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | if ENABLE_DOXYGEN_DOC 2 | 3 | all-local: doxygen.stamp 4 | 5 | doxygen.stamp: $(top_srcdir)/datrie/*.h $(top_srcdir)/datrie/*.c 6 | $(DOXYGEN) 7 | touch doxygen.stamp 8 | 9 | install-data-local: install-html 10 | 11 | install-html: 12 | $(INSTALL) -d $(DESTDIR)$(htmldocdir) 13 | $(INSTALL_DATA) html/* $(DESTDIR)$(htmldocdir) 14 | 15 | uninstall-local: 16 | rm -rf $(DESTDIR)$(htmldocdir) 17 | 18 | clean-local: 19 | rm -rf html man 20 | rm -f doxygen.stamp 21 | rm -f doxygen_sqlite3.db 22 | 23 | else 24 | 25 | install-data-local: 26 | uninstall-local: 27 | clean-local: 28 | 29 | endif 30 | 31 | -------------------------------------------------------------------------------- /datrie/libdatrie.def: -------------------------------------------------------------------------------- 1 | alpha_map_new 2 | alpha_map_clone 3 | alpha_map_free 4 | alpha_map_add_range 5 | alpha_char_strlen 6 | alpha_char_strcmp 7 | trie_new 8 | trie_new_from_file 9 | trie_fread 10 | trie_free 11 | trie_get_serialized_size 12 | trie_serialize 13 | trie_save 14 | trie_fwrite 15 | trie_is_dirty 16 | trie_retrieve 17 | trie_store 18 | trie_store_if_absent 19 | trie_delete 20 | trie_enumerate 21 | trie_root 22 | trie_state_clone 23 | trie_state_copy 24 | trie_state_free 25 | trie_state_rewind 26 | trie_state_walk 27 | trie_state_is_walkable 28 | trie_state_walkable_chars 29 | trie_state_is_single 30 | trie_state_get_data 31 | trie_iterator_new 32 | trie_iterator_free 33 | trie_iterator_next 34 | trie_iterator_get_key 35 | trie_iterator_get_data 36 | -------------------------------------------------------------------------------- /nsis/README: -------------------------------------------------------------------------------- 1 | NSIS installer for Windows 2 | ========================== 3 | 4 | This directory contains scripts and resources for building installer for 5 | Windows based on NSIS (Nullsoft Scriptable Install System). The make script 6 | is provided for cross-compiling from a GNU/Linux system using mingw32 and nsis. 7 | 8 | Requirements 9 | ------------ 10 | 11 | In addition to normal build-essential tools, GNU autotools, and pkg-config, 12 | you will need the following packages to cross-build the installer from 13 | GNU//Linux: 14 | 15 | - mingw32 16 | - nsis 17 | - tofrodos 18 | 19 | On Debian GNU/Linux, you can just apt-get the named packages. 20 | 21 | Building 22 | -------- 23 | 24 | In this `installer' directory, just type: 25 | 26 | $ ./make-nsis 27 | 28 | The generated installer will be libdatrie.v{version}.exe. 29 | 30 | The script is actually a make file. You can see build stages in the file, 31 | such as configure, build, install, binary. 32 | 33 | To clean everything, for example, you can type: 34 | 35 | $ ./make-nsis distclean 36 | 37 | -------------------------------------------------------------------------------- /datrie/libdatrie.map: -------------------------------------------------------------------------------- 1 | DATRIE_0.2 { 2 | global: 3 | alpha_map_new; 4 | alpha_map_clone; 5 | alpha_map_free; 6 | alpha_map_add_range; 7 | alpha_char_strlen; 8 | trie_new; 9 | trie_new_from_file; 10 | trie_free; 11 | trie_save; 12 | trie_is_dirty; 13 | trie_retrieve; 14 | trie_store; 15 | trie_delete; 16 | trie_enumerate; 17 | trie_root; 18 | trie_state_clone; 19 | trie_state_copy; 20 | trie_state_free; 21 | trie_state_rewind; 22 | trie_state_walk; 23 | trie_state_is_walkable; 24 | trie_state_is_single; 25 | trie_state_get_data; 26 | local: *; 27 | }; 28 | 29 | DATRIE_0.2.4 { 30 | trie_store_if_absent; 31 | trie_fread; 32 | trie_fwrite; 33 | } DATRIE_0.2; 34 | 35 | DATRIE_0.2.6 { 36 | trie_state_walkable_chars; 37 | trie_iterator_new; 38 | trie_iterator_free; 39 | trie_iterator_next; 40 | trie_iterator_get_key; 41 | trie_iterator_get_data; 42 | } DATRIE_0.2.4; 43 | 44 | DATRIE_0.2.7 { 45 | alpha_char_strcmp; 46 | } DATRIE_0.2.6; 47 | 48 | DATRIE_0.2.13 { 49 | trie_get_serialized_size; 50 | trie_serialize; 51 | } DATRIE_0.2.7; 52 | -------------------------------------------------------------------------------- /datrie/Makefile.am: -------------------------------------------------------------------------------- 1 | pkgincludedir = $(includedir)/datrie 2 | 3 | pkginclude_HEADERS = \ 4 | typedefs.h \ 5 | triedefs.h \ 6 | alpha-map.h \ 7 | trie.h 8 | 9 | EXTRA_DIST = libdatrie.map libdatrie.def 10 | 11 | AM_CPPFLAGS = -I$(top_srcdir) 12 | 13 | lib_LTLIBRARIES = libdatrie.la 14 | 15 | libdatrie_la_SOURCES = \ 16 | typedefs.h \ 17 | triedefs.h \ 18 | trie-private.h \ 19 | dstring.h \ 20 | dstring-private.h \ 21 | dstring.c \ 22 | trie-string.h \ 23 | trie-string.c \ 24 | fileutils.h \ 25 | fileutils.c \ 26 | darray.h \ 27 | darray.c \ 28 | tail.h \ 29 | tail.c \ 30 | trie.h \ 31 | trie.c \ 32 | alpha-map.h \ 33 | alpha-map-private.h \ 34 | alpha-map.c 35 | 36 | if LD_HAS_VERSION_SCRIPT 37 | EXPORTS_FLAGS = -Wl,-version-script -Wl,$(srcdir)/libdatrie.map 38 | EXPORTS_DEPS = libdatrie.map 39 | else 40 | EXPORTS_FLAGS = -export-symbols $(srcdir)/libdatrie.def 41 | EXPORTS_DEPS = libdatrie.def 42 | endif 43 | 44 | libdatrie_la_LDFLAGS = -no-undefined \ 45 | -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \ 46 | $(EXPORTS_FLAGS) 47 | libdatrie_la_DEPENDENCIES = $(EXPORTS_DEPS) 48 | 49 | -------------------------------------------------------------------------------- /nsis/contrib/libdatrienv.sh: -------------------------------------------------------------------------------- 1 | if test -n "$DATRIE_BASEPATH"; then 2 | case `uname -a` in 3 | CYGWIN*) 4 | DATRIE_BASEPATH=`echo $DATRIE_BASEPATH | sed -e 's/\"//g'` 5 | DATRIE_BASEPATH=`cygpath $DATRIE_BASEPATH`;; 6 | MINGW32*) 7 | DATRIE_BASEPATH=`echo $DATRIE_BASEPATH | sed -e 's/\"//g' -e 's/\\\\/\\//g' -e 's/^\\([a-zA-Z]\\):/\\/\\1/g'` 8 | esac 9 | export DATRIE_BASEPATH=$DATRIE_BASEPATH 10 | export PATH=$DATRIE_BASEPATH/bin:$PATH 11 | # export ACLOCAL_FLAGS="-I $DATRIE_BASEPATH/share/aclocal $ACLOCAL_FLAGS" 12 | 13 | if test "x$C_INCLUDE_PATH" = x; then 14 | APPEND= 15 | else 16 | APPEND=":$C_INCLUDE_PATH" 17 | fi 18 | export C_INCLUDE_PATH=$DATRIE_BASEPATH/include$APPEND 19 | 20 | if test "x$LIBRARY_PATH" = x; then 21 | APPEND= 22 | else 23 | APPEND=":$LIBRARY_PATH" 24 | fi 25 | export LIBRARY_PATH=$DATRIE_BASEPATH/lib:/lib/w32api$APPEND 26 | 27 | if test "x$PKG_CONFIG_PATH" = x; then 28 | APPEND= 29 | else 30 | APPEND=":$PKG_CONFIG_PATH" 31 | fi 32 | export PKG_CONFIG_PATH=$DATRIE_BASEPATH/lib/pkgconfig$APPEND 33 | 34 | if test "x$MANPATH" = x; then 35 | APPEND= 36 | else 37 | APPEND=":$MANPATH" 38 | fi 39 | export MANPATH=$DATRIE_BASEPATH/share/man$APPEND 40 | fi 41 | -------------------------------------------------------------------------------- /nsis/make-nsis: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | CURDIR = $(shell pwd) 4 | INSTALL_DOCS = \ 5 | $(CURDIR)/../AUTHORS \ 6 | $(CURDIR)/../ChangeLog \ 7 | $(CURDIR)/../COPYING \ 8 | $(CURDIR)/../INSTALL \ 9 | $(CURDIR)/../NEWS \ 10 | $(CURDIR)/../README 11 | 12 | all: binary 13 | 14 | distclean: 15 | make distclean 16 | rm -rf datrie doc man tools 17 | rm -rf libdatrie 18 | rm -f configure-stamp 19 | rm -f *.exe 20 | 21 | configure: configure-stamp 22 | configure-stamp: 23 | ../configure --prefix=/ --host=i586-mingw32msvc 24 | touch $@ 25 | 26 | build: configure 27 | make 28 | 29 | install: 30 | make install DESTDIR=$(CURDIR)/libdatrie 31 | 32 | # install docs 33 | if [ ! -e $(CURDIR)/libdatrie/doc ]; then \ 34 | mkdir $(CURDIR)/libdatrie/doc; \ 35 | fi 36 | for file in $(INSTALL_DOCS); do \ 37 | cp $$file $(CURDIR)/libdatrie/doc/`basename $$file`.txt; \ 38 | todos $(CURDIR)/libdatrie/doc/$$file.txt; \ 39 | done 40 | 41 | # install contrib files 42 | if [ ! -e $(CURDIR)/libdatrie/contrib ]; then \ 43 | mkdir $(CURDIR)/libdatrie/contrib; \ 44 | fi 45 | cp contrib/libdatrienv.sh $(CURDIR)/libdatrie/contrib 46 | 47 | binary: build install 48 | makensis libdatrie.nsi 49 | 50 | .PHONY: all distclean configure build install binary 51 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | datrie - Double-Array Trie Library 2 | ================================== 3 | 4 | This is an implementation of double-array structure for representing trie, 5 | as proposed by Junichi Aoe [1]. 6 | 7 | Trie is a kind of digital search tree, an efficient indexing method in which 8 | search time is independent of database size. It only takes O(m) search time, 9 | where m is the length of the search string. Comparably as efficient as hashing, 10 | trie also provides flexibility on incremental matching and key spelling 11 | manipulation. This makes it ideal for lexical analyzers, as well as spelling 12 | dictionaries. 13 | 14 | See the details of the implementation at [2]: 15 | https://linux.thai.net/~thep/datrie/datrie.html 16 | 17 | Historically, this was first implemented as C++ classes in a library called 18 | midatrie [2], but later simplified and rewritten from scratch in C. 19 | 20 | -- 21 | Theppitak Karoonboonyanan. 22 | September 2006. 23 | 24 | References 25 | ---------- 26 | 27 | [1] Aoe, J. "An Efficient Digital Search Algorithm by Using a Double-Array 28 | Structure". IEEE Transactions on Software Engineering. Vol. 15, 9 29 | (Sep 1989). pp. 1066-1077. 30 | 31 | [2] Karoonboonyanan, T. "An Implementation of Double-Array Trie". 32 | https://linux.thai.net/~thep/datrie/datrie.html 33 | 34 | -------------------------------------------------------------------------------- /nsis/ChangeLog: -------------------------------------------------------------------------------- 1 | 2009-04-14 Theppitak Karoonboonyanan 2 | 3 | * libdatrie.nsi: Do not install obsolete man3/* for -devel subpackage. 4 | 5 | 2007-04-06 Theppitak Karoonboonyanan 6 | 7 | Incorporate changes for componentized installation by Taniya Supasin 8 | . 9 | 10 | * libdatrie.nsi: Split section into runtime, devel, doc components. 11 | Handle component dependency in UI. Set default directory to 12 | c:\libdatrie. 13 | 14 | * contrib/libdatrienv.sh: Set $MANPAGE env. 15 | 16 | * make-nsis: Append '.txt' extension to package docs. 17 | 18 | 2007-03-27 Theppitak Karoonboonyanan 19 | 20 | * make-nsis: 21 | Explicitly list files to copy from contrib, to prevent failure on 22 | presence of the extra CVS directory. 23 | 24 | 2007-03-27 Theppitak Karoonboonyanan 25 | 26 | First import NSIS-based installer by Taniya Supasin 27 | . 28 | 29 | * libdatrie.nsi, SearchReplace.nsh, WriteEnvStr.nsh, WritePathStr.nsh: 30 | Import Taniya's NSIS scripts. 31 | 32 | * contrib/libdatrienv.sh: 33 | Import Taniya's shell profile for building environment. 34 | 35 | * make-nsis: 36 | Write make rules for building the installer using mingw32 37 | cross-compilation and nsis. 38 | 39 | * README: 40 | Document the build process. 41 | 42 | -------------------------------------------------------------------------------- /datrie/dstring-private.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * dstring-private.h - Dynamic string type 23 | * Created: 2012-08-02 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __DSTRING_PRIVATE_H 28 | #define __DSTRING_PRIVATE_H 29 | 30 | #include "typedefs.h" 31 | 32 | 33 | struct _DString { 34 | int char_size; 35 | int str_len; 36 | int alloc_size; 37 | void * val; 38 | }; 39 | 40 | 41 | #endif /* __DSTRING_PRIVATE_H */ 42 | 43 | /* 44 | vi:ts=4:ai:expandtab 45 | */ 46 | -------------------------------------------------------------------------------- /datrie/fileutils.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * fileutils.h - File utility functions 23 | * Created: 2006-08-14 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __FILEUTILS_H 28 | #define __FILEUTILS_H 29 | 30 | #include 31 | #include 32 | 33 | void serialize_int32_be_incr (uint8 **buff, int32 val); 34 | Bool file_read_int32 (FILE *file, int32 *o_val); 35 | Bool file_write_int32 (FILE *file, int32 val); 36 | 37 | void serialize_int16_be_incr (uint8 **buff, int16 val); 38 | Bool file_read_int16 (FILE *file, int16 *o_val); 39 | Bool file_write_int16 (FILE *file, int16 val); 40 | 41 | Bool file_read_int8 (FILE *file, int8 *o_val); 42 | Bool file_write_int8 (FILE *file, int8 val); 43 | 44 | Bool file_read_chars (FILE *file, char *buff, int len); 45 | Bool file_write_chars (FILE *file, const char *buff, int len); 46 | 47 | #endif /* __FILEUTILS_H */ 48 | 49 | /* 50 | vi:ts=4:ai:expandtab 51 | */ 52 | -------------------------------------------------------------------------------- /tests/utils.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * utils.h - Utility functions for datrie test cases 23 | * Created: 2013-10-16 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | 29 | /*---------------------* 30 | * Debugging helpers * 31 | *---------------------*/ 32 | void msg_step (const char *msg); 33 | 34 | /*-------------------------* 35 | * Trie creation helpers * 36 | *-------------------------*/ 37 | Trie * en_trie_new (void); 38 | 39 | /*---------------------------* 40 | * Dict source for testing * 41 | *---------------------------*/ 42 | typedef struct _DictRec DictRec; 43 | struct _DictRec { 44 | AlphaChar *key; 45 | TrieData data; 46 | }; 47 | 48 | #define TRIE_DATA_UNREAD 1 49 | #define TRIE_DATA_READ 2 50 | 51 | extern DictRec dict_src[]; 52 | 53 | int dict_src_n_entries (void); 54 | TrieData dict_src_get_data (const AlphaChar *key); 55 | int dict_src_set_data (const AlphaChar *key, TrieData data); 56 | 57 | /* 58 | vi:ts=4:ai:expandtab 59 | */ 60 | -------------------------------------------------------------------------------- /datrie/dstring.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * dstring.h - Dynamic string type 23 | * Created: 2012-08-01 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __DSTRING_H 28 | #define __DSTRING_H 29 | 30 | #include "typedefs.h" 31 | 32 | typedef struct _DString DString; 33 | 34 | DString * dstring_new (int char_size, int n_elm); 35 | 36 | void dstring_free (DString *ds); 37 | 38 | int dstring_length (const DString *ds); 39 | 40 | const void * dstring_get_val (const DString *ds); 41 | 42 | void * dstring_get_val_rw (DString *ds); 43 | 44 | void dstring_clear (DString *ds); 45 | 46 | Bool dstring_copy (DString *dst, const DString *src); 47 | 48 | Bool dstring_append (DString *dst, const DString *src); 49 | 50 | Bool dstring_append_string (DString *ds, const void *data, int len); 51 | 52 | Bool dstring_append_char (DString *ds, const void *data); 53 | 54 | Bool dstring_terminate (DString *ds); 55 | 56 | Bool dstring_cut_last (DString *ds); 57 | 58 | #endif /* __DSTRING_H */ 59 | 60 | /* 61 | vi:ts=4:ai:expandtab 62 | */ 63 | -------------------------------------------------------------------------------- /datrie/trie-private.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * trie-private.h - Private utilities for trie implementation 23 | * Created: 2007-08-25 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TRIE_PRIVATE_H 28 | #define __TRIE_PRIVATE_H 29 | 30 | #include 31 | 32 | /** 33 | * @file trie-private.h 34 | * @brief Private utilities for trie implementation 35 | */ 36 | 37 | /** 38 | * @brief LIKELY and UNLIKELY macros for hinting the compiler 39 | * about the expected result of a Boolean expression, for the sake of 40 | * optimization 41 | */ 42 | #if defined(__GNUC__) && (__GNUC__ > 2) && defined(__OPTIMIZE__) 43 | #define LIKELY(expr) (__builtin_expect (!!(expr), 1)) 44 | #define UNLIKELY(expr) (__builtin_expect (!!(expr), 0)) 45 | #else 46 | #define LIKELY(expr) (expr) 47 | #define UNLIKELY(expr) (expr) 48 | #endif 49 | 50 | /** 51 | * @brief Minimum value macro 52 | */ 53 | #define MIN_VAL(a,b) ((a)<(b)?(a):(b)) 54 | /** 55 | * @brief Maximum value macro 56 | */ 57 | #define MAX_VAL(a,b) ((a)>(b)?(a):(b)) 58 | 59 | #endif /* __TRIE_PRIVATE_H */ 60 | 61 | /* 62 | vi:ts=4:ai:expandtab 63 | */ 64 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | AM_CPPFLAGS = -I$(top_srcdir) 2 | 3 | TESTS_ENVIRONMENT = top_builddir=$(top_builddir) 4 | 5 | TESTS = \ 6 | test_walk \ 7 | test_iterator \ 8 | test_store-retrieve \ 9 | test_file \ 10 | test_serialization \ 11 | test_nonalpha \ 12 | test_null_trie \ 13 | test_term_state \ 14 | test_byte_alpha \ 15 | test_byte_list \ 16 | $(NULL) 17 | 18 | check_PROGRAMS = \ 19 | test_walk \ 20 | test_iterator \ 21 | test_store-retrieve \ 22 | test_file \ 23 | test_serialization \ 24 | test_nonalpha \ 25 | test_null_trie \ 26 | test_term_state \ 27 | test_byte_alpha \ 28 | test_byte_list \ 29 | $(NULL) 30 | 31 | noinst_HEADERS = \ 32 | utils.h \ 33 | $(NULL) 34 | 35 | test_walk_SOURCES = \ 36 | test_walk.c \ 37 | utils.c \ 38 | $(NULL) 39 | test_walk_LDADD = $(top_builddir)/datrie/libdatrie.la 40 | 41 | test_iterator_SOURCES = \ 42 | test_iterator.c \ 43 | utils.c \ 44 | $(NULL) 45 | test_iterator_LDADD = $(top_builddir)/datrie/libdatrie.la 46 | 47 | test_store_retrieve_SOURCES = \ 48 | test_store-retrieve.c \ 49 | utils.c \ 50 | $(NULL) 51 | test_store_retrieve_LDADD = $(top_builddir)/datrie/libdatrie.la 52 | 53 | test_file_SOURCES = \ 54 | test_file.c \ 55 | utils.c \ 56 | $(NULL) 57 | test_file_LDADD = $(top_builddir)/datrie/libdatrie.la 58 | 59 | test_serialization_SOURCES = \ 60 | test_serialization.c \ 61 | utils.c \ 62 | $(NULL) 63 | test_serialization_LDADD = $(top_builddir)/datrie/libdatrie.la 64 | 65 | test_nonalpha_SOURCES = \ 66 | test_nonalpha.c \ 67 | utils.c \ 68 | $(NULL) 69 | test_nonalpha_LDADD = $(top_builddir)/datrie/libdatrie.la 70 | 71 | test_null_trie_SOURCES = \ 72 | test_null_trie.c \ 73 | utils.c \ 74 | $(NULL) 75 | test_null_trie_LDADD = $(top_builddir)/datrie/libdatrie.la 76 | 77 | test_term_state_SOURCES = \ 78 | test_term_state.c \ 79 | utils.c \ 80 | $(NULL) 81 | test_term_state_LDADD = $(top_builddir)/datrie/libdatrie.la 82 | 83 | test_byte_alpha_SOURCES = \ 84 | test_byte_alpha.c \ 85 | utils.c \ 86 | $(NULL) 87 | test_byte_alpha_LDADD = $(top_builddir)/datrie/libdatrie.la 88 | 89 | test_byte_list_SOURCES = \ 90 | test_byte_list.c \ 91 | utils.c \ 92 | $(NULL) 93 | test_byte_list_LDADD = $(top_builddir)/datrie/libdatrie.la 94 | 95 | -------------------------------------------------------------------------------- /datrie/alpha-map-private.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * alpha-map-private.h - private APIs for alpha-map 23 | * Created: 2008-12-04 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __ALPHA_MAP_PRIVATE_H 28 | #define __ALPHA_MAP_PRIVATE_H 29 | 30 | #include 31 | #include "alpha-map.h" 32 | 33 | AlphaMap * alpha_map_fread_bin (FILE *file); 34 | 35 | int alpha_map_fwrite_bin (const AlphaMap *alpha_map, FILE *file); 36 | 37 | size_t alpha_map_get_serialized_size (const AlphaMap *alpha_map); 38 | 39 | void alpha_map_serialize_bin (const AlphaMap *alpha_map, uint8 **ptr); 40 | 41 | 42 | TrieIndex alpha_map_char_to_trie (const AlphaMap *alpha_map, 43 | AlphaChar ac); 44 | 45 | AlphaChar alpha_map_trie_to_char (const AlphaMap *alpha_map, 46 | TrieChar tc); 47 | 48 | TrieChar * alpha_map_char_to_trie_str (const AlphaMap *alpha_map, 49 | const AlphaChar *str); 50 | 51 | AlphaChar * alpha_map_trie_to_char_str (const AlphaMap *alpha_map, 52 | const TrieChar *str); 53 | 54 | 55 | #endif /* __ALPHA_MAP_PRIVATE_H */ 56 | 57 | 58 | /* 59 | vi:ts=4:ai:expandtab 60 | */ 61 | 62 | -------------------------------------------------------------------------------- /datrie/triedefs.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * triedefs.h - General typedefs for trie 23 | * Created: 2006-08-11 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TRIEDEFS_H 28 | #define __TRIEDEFS_H 29 | 30 | #include 31 | 32 | /** 33 | * @file triedefs.h 34 | * @brief General typedefs for trie 35 | */ 36 | 37 | /** 38 | * @brief Alphabet character type for use as input/output strings of trie keys 39 | */ 40 | typedef uint32 AlphaChar; 41 | 42 | /** 43 | * @brief Error value for alphabet character 44 | */ 45 | #define ALPHA_CHAR_ERROR (~(AlphaChar)0) 46 | 47 | /** 48 | * @brief Raw character type mapped into packed set from AlphaChar, 49 | * for use in actual trie transition calculations 50 | */ 51 | typedef unsigned char TrieChar; 52 | /** 53 | * @brief Trie terminator character 54 | */ 55 | #define TRIE_CHAR_TERM '\0' 56 | #define TRIE_CHAR_MAX 255 57 | 58 | /** 59 | * @brief Type of index into Trie double-array and tail structures 60 | */ 61 | typedef int32 TrieIndex; 62 | /** 63 | * @brief Trie error index 64 | */ 65 | #define TRIE_INDEX_ERROR 0 66 | /** 67 | * @brief Maximum trie index value 68 | */ 69 | #define TRIE_INDEX_MAX 0x7fffffff 70 | 71 | /** 72 | * @brief Type of value associated to trie entries 73 | */ 74 | typedef int32 TrieData; 75 | /** 76 | * @brief Trie error data 77 | */ 78 | #define TRIE_DATA_ERROR -1 79 | 80 | #endif /* __TRIEDEFS_H */ 81 | 82 | /* 83 | vi:ts=4:ai:expandtab 84 | */ 85 | -------------------------------------------------------------------------------- /datrie/trie-string.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * trie-string.h - Dynamic string type for Trie alphabets 23 | * Created: 2012-08-02 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TRIE_STRING_H 28 | #define __TRIE_STRING_H 29 | 30 | #include "dstring.h" 31 | #include "triedefs.h" 32 | 33 | #include 34 | 35 | /*----------------------------* 36 | * STATIC TRIECHAR STRING * 37 | *----------------------------*/ 38 | 39 | size_t trie_char_strlen (const TrieChar *str); 40 | 41 | size_t trie_char_strsize (const TrieChar *str); 42 | 43 | TrieChar * trie_char_strdup (const TrieChar *str); 44 | 45 | /*-----------------------------* 46 | * DYNAMIC TRIECHAR STRING * 47 | *-----------------------------*/ 48 | 49 | typedef struct _TrieString TrieString; 50 | 51 | TrieString * trie_string_new (int n_elm); 52 | 53 | void trie_string_free (TrieString *ts); 54 | 55 | int trie_string_length (const TrieString *ts); 56 | 57 | const void * trie_string_get_val (const TrieString *ts); 58 | 59 | void * trie_string_get_val_rw (TrieString *ts); 60 | 61 | void trie_string_clear (TrieString *ts); 62 | 63 | Bool trie_string_copy (TrieString *dst, const TrieString *src); 64 | 65 | Bool trie_string_append (TrieString *dst, const TrieString *src); 66 | 67 | Bool trie_string_append_string (TrieString *ts, const TrieChar *str); 68 | 69 | Bool trie_string_append_char (TrieString *ts, TrieChar tc); 70 | 71 | Bool trie_string_terminate (TrieString *ts); 72 | 73 | Bool trie_string_cut_last (TrieString *ts); 74 | 75 | 76 | #endif /* __TRIE_STRING_H */ 77 | 78 | /* 79 | vi:ts=4:ai:expandtab 80 | */ 81 | 82 | -------------------------------------------------------------------------------- /tests/test_null_trie.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2015 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_null_trie.c - Test for datrie iteration on empty trie 23 | * Created: 2015-04-21 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | #include 32 | 33 | int 34 | main (void) 35 | { 36 | Trie *test_trie; 37 | TrieState *trie_root_state; 38 | TrieIterator *trie_it; 39 | Bool is_failed; 40 | 41 | msg_step ("Preparing empty trie"); 42 | test_trie = en_trie_new (); 43 | if (!test_trie) { 44 | fprintf (stderr, "Fail to create test trie\n"); 45 | goto err_trie_not_created; 46 | } 47 | 48 | /* iterate & check */ 49 | msg_step ("Iterating"); 50 | trie_root_state = trie_root (test_trie); 51 | if (!trie_root_state) { 52 | printf ("Failed to get trie root state\n"); 53 | goto err_trie_created; 54 | } 55 | trie_it = trie_iterator_new (trie_root_state); 56 | if (!trie_it) { 57 | printf ("Failed to get trie iterator\n"); 58 | goto err_trie_root_created; 59 | } 60 | 61 | is_failed = FALSE; 62 | while (trie_iterator_next (trie_it)) { 63 | AlphaChar *key; 64 | 65 | printf ("Got entry from empty trie, which is weird!\n"); 66 | 67 | key = trie_iterator_get_key (trie_it); 68 | if (key) { 69 | printf ("Got key from empty trie, which is weird! (key='%ls')\n", 70 | (wchar_t *)key); 71 | is_failed = TRUE; 72 | free (key); 73 | } 74 | } 75 | 76 | if (is_failed) { 77 | printf ("Errors found in empty trie iteration.\n"); 78 | goto err_trie_it_created; 79 | } 80 | 81 | trie_iterator_free (trie_it); 82 | trie_state_free (trie_root_state); 83 | trie_free (test_trie); 84 | return 0; 85 | 86 | err_trie_it_created: 87 | trie_iterator_free (trie_it); 88 | err_trie_root_created: 89 | trie_state_free (trie_root_state); 90 | err_trie_created: 91 | trie_free (test_trie); 92 | err_trie_not_created: 93 | return 1; 94 | } 95 | 96 | /* 97 | vi:ts=4:ai:expandtab 98 | */ 99 | -------------------------------------------------------------------------------- /tests/test_byte_alpha.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2018 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_byte_alpha.c - Test byte stream (full-range 0..255) alpha map 23 | * Created: 2018-04-21 24 | * Author: Theppitak Karoonboonyanan 25 | * Based on test case in issue #6 26 | * https://github.com/tlwg/libdatrie/issues/6 27 | */ 28 | 29 | #include 30 | #include "utils.h" 31 | #include 32 | #include 33 | 34 | #define TEST_DATA 255 35 | int 36 | main (void) 37 | { 38 | AlphaMap *alpha_map; 39 | Trie *test_trie; 40 | AlphaChar key[3]; 41 | TrieData data; 42 | 43 | msg_step ("Preparing alpha map"); 44 | alpha_map = alpha_map_new (); 45 | if (!alpha_map) { 46 | printf ("Fail to allocate alpha map\n"); 47 | goto err_alpha_map_not_created; 48 | } 49 | if (alpha_map_add_range (alpha_map, 0x00, 0xff) != 0) { 50 | printf ("Fail to add full alpha map range\n"); 51 | goto err_alpha_map_created; 52 | } 53 | 54 | msg_step ("Preparing trie"); 55 | test_trie = trie_new (alpha_map); 56 | alpha_map_free (alpha_map); 57 | if (!test_trie) { 58 | printf ("Fail to create test trie\n"); 59 | goto err_alpha_map_created; 60 | } 61 | 62 | msg_step ("Storing key to test trie"); 63 | key[0] = 0xff; 64 | key[1] = 0xff; 65 | key[2] = 0; 66 | if (!trie_store (test_trie, key, TEST_DATA)) { 67 | printf ("Fail to store key to test trie\n"); 68 | goto err_trie_created; 69 | } 70 | 71 | msg_step ("Retrieving data from test trie"); 72 | if (!trie_retrieve (test_trie, key, &data)) { 73 | printf ("Fail to retrieve key from test trie\n"); 74 | goto err_trie_created; 75 | } 76 | if (TEST_DATA != data) { 77 | printf ("Retrieved data = %d, not %d\n", data, TEST_DATA); 78 | goto err_trie_created; 79 | } 80 | 81 | msg_step ("Freeing test trie"); 82 | trie_free (test_trie); 83 | return 0; 84 | 85 | err_trie_created: 86 | trie_free (test_trie); 87 | err_alpha_map_created: 88 | alpha_map_free (alpha_map); 89 | err_alpha_map_not_created: 90 | return 1; 91 | } 92 | 93 | /* 94 | vi:ts=4:ai:expandtab 95 | */ 96 | -------------------------------------------------------------------------------- /tests/test_nonalpha.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2014 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_nonalpha.c - Test for datrie behaviors on non-alphabet inputs 23 | * Created: 2014-01-06 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | 32 | const AlphaChar *nonalpha_src[] = { 33 | (AlphaChar *)L"a6acus", 34 | (AlphaChar *)L"a5acus", 35 | NULL 36 | }; 37 | 38 | int 39 | main (void) 40 | { 41 | Trie *test_trie; 42 | DictRec *dict_p; 43 | const AlphaChar **nonalpha_key; 44 | TrieData trie_data; 45 | Bool is_fail; 46 | 47 | msg_step ("Preparing trie"); 48 | test_trie = en_trie_new (); 49 | if (!test_trie) { 50 | fprintf (stderr, "Fail to create test trie\n"); 51 | goto err_trie_not_created; 52 | } 53 | 54 | /* store */ 55 | msg_step ("Adding data to trie"); 56 | for (dict_p = dict_src; dict_p->key; dict_p++) { 57 | if (!trie_store (test_trie, dict_p->key, dict_p->data)) { 58 | printf ("Failed to add key '%ls', data %d.\n", 59 | (wchar_t *)dict_p->key, dict_p->data); 60 | goto err_trie_created; 61 | } 62 | } 63 | 64 | /* test storing keys with non-alphabet chars */ 65 | is_fail = FALSE; 66 | for (nonalpha_key = nonalpha_src; *nonalpha_key; nonalpha_key++) { 67 | if (trie_retrieve (test_trie, *nonalpha_key, &trie_data)) { 68 | printf ("False duplication on key '%ls', with existing data %d.\n", 69 | (wchar_t *)*nonalpha_key, trie_data); 70 | is_fail = TRUE; 71 | } 72 | if (trie_store (test_trie, *nonalpha_key, TRIE_DATA_UNREAD)) { 73 | printf ("Wrongly added key '%ls' containing non-alphanet char\n", 74 | (wchar_t *)*nonalpha_key); 75 | is_fail = TRUE; 76 | } 77 | } 78 | 79 | if (is_fail) 80 | goto err_trie_created; 81 | 82 | trie_free (test_trie); 83 | return 0; 84 | 85 | err_trie_created: 86 | trie_free (test_trie); 87 | err_trie_not_created: 88 | return 1; 89 | } 90 | 91 | /* 92 | vi:ts=4:ai:expandtab 93 | */ 94 | -------------------------------------------------------------------------------- /datrie/alpha-map.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * alpha-map.h - map between character codes and trie alphabet 23 | * Created: 2006-08-19 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __ALPHA_MAP_H 28 | #define __ALPHA_MAP_H 29 | 30 | #include 31 | 32 | #include 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | 38 | /** 39 | * @file alpha-map.h 40 | * @brief AlphaMap data type and functions 41 | * 42 | * AlphaMap is a mapping between AlphaChar and TrieChar. AlphaChar is the 43 | * alphabet character used in words of a target language, while TrieChar 44 | * is a small integer with packed range of values and is actually used in 45 | * trie state transition calculations. 46 | * 47 | * Since double-array trie relies on sparse state transition table, 48 | * a small set of input characters can make the table small, i.e. with 49 | * small number of columns. But in real life, alphabet characters can be 50 | * of non-continuous range of values. The unused slots between them can 51 | * waste the space in the table, and can increase the chance of unused 52 | * array cells. 53 | * 54 | * AlphaMap is thus defined for mapping between non-continuous ranges of 55 | * values of AlphaChar and packed and continuous range of Triechar. 56 | * 57 | * In this implementation, TrieChar is defined as a single-byte integer, 58 | * which means the largest AlphaChar set that is supported is of 255 59 | * values, as the special value of 0 is reserved for null-termination code. 60 | */ 61 | 62 | /** 63 | * @brief AlphaMap data type 64 | */ 65 | typedef struct _AlphaMap AlphaMap; 66 | 67 | AlphaMap * alpha_map_new (void); 68 | 69 | AlphaMap * alpha_map_clone (const AlphaMap *a_map); 70 | 71 | void alpha_map_free (AlphaMap *alpha_map); 72 | 73 | int alpha_map_add_range (AlphaMap *alpha_map, 74 | AlphaChar begin, 75 | AlphaChar end); 76 | 77 | int alpha_char_strlen (const AlphaChar *str); 78 | int alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2); 79 | 80 | #ifdef __cplusplus 81 | } 82 | #endif 83 | 84 | #endif /* __ALPHA_MAP_H */ 85 | 86 | 87 | /* 88 | vi:ts=4:ai:expandtab 89 | */ 90 | -------------------------------------------------------------------------------- /nsis/SearchReplace.nsh: -------------------------------------------------------------------------------- 1 | ; search & replace line in file. 2 | ;------------------------- 3 | ; parameter description 4 | ; $9 is filename to search 5 | ; $8 is string to search 6 | ; $7 is string to replace 7 | ;------------------------ 8 | ; How to call function: 9 | ; Push "filename.txt" 10 | ; Push "the string to search" 11 | ; Push "the string to replace" 12 | ; Call un.ReplaceLine 13 | ;----------------------- 14 | Function un.ReplaceLine 15 | 16 | Pop $7 17 | Pop $8 18 | Pop $9 19 | 20 | ClearErrors 21 | FileOpen $0 $9 "r" ; open target file for reading 22 | GetTempFileName $R0 ; get new temp file name 23 | FileOpen $1 $R0 "w" ; open temp file for writing 24 | loop: 25 | FileRead $0 $2 ; read line from target file 26 | IfErrors done ; check if end of file reached 27 | StrCmp $2 "$8$\r$\n" 0 +2 ; compare line with search string with CR/LF 28 | StrCpy $2 "$7$\r$\n" ; change line 29 | StrCmp $2 "$8" 0 +2 ; compare line with search string without CR/LF (at the end of the file) 30 | StrCpy $2 "$7" ; change line 31 | FileWrite $1 $2 ; write changed or unchanged line to temp file 32 | Goto loop 33 | 34 | done: 35 | FileClose $0 ; close target file 36 | FileClose $1 ; close temp file 37 | Delete $9 ; delete target file 38 | CopyFiles /SILENT $R0 $9 ; copy temp file to target file 39 | Delete $R0 ; delete temp file 40 | 41 | FunctionEnd 42 | 43 | ;--------- 44 | 45 | 46 | ; search & delete line in file. 47 | ;------------------------- 48 | ; parameter description 49 | ; $9 is filename to search 50 | ; $8 is string to search and delete 51 | ; 52 | ;------------------------ 53 | ; How to call function: 54 | ; 55 | ; Push "filename.txt" 56 | ; Push "the string to search and delete" 57 | ; Call un.DeleteLine 58 | ; 59 | ;----------------------- 60 | Function un.DeleteLine 61 | 62 | Pop $8 63 | Pop $9 64 | 65 | ClearErrors 66 | FileOpen $0 $9 "r" ; open target file for reading 67 | GetTempFileName $R0 ; get new temp file name 68 | FileOpen $1 $R0 "w" ; open temp file for writing 69 | loop: 70 | FileRead $0 $2 ; read line from target file 71 | IfErrors done ; check if end of file reached 72 | StrCmp $2 "$8$\r$\n" loop 0 ; if search string (with CR/LF) is found, goto loop 73 | StrCmp $2 "$8" loop 0 ; if search string is found at the end of the file, goto loop 74 | FileWrite $1 $2 ; write changed or unchanged line to temp file 75 | Goto loop 76 | 77 | done: 78 | FileClose $0 ; close target file 79 | FileClose $1 ; close temp file 80 | Delete $9 ; delete target file 81 | CopyFiles /SILENT $R0 $9 ; copy temp file to target file 82 | Delete $R0 ; delete temp file 83 | 84 | FunctionEnd 85 | 86 | ;--------- -------------------------------------------------------------------------------- /datrie/tail.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * tail.h - trie tail for keeping suffixes 23 | * Created: 2006-08-12 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TAIL_H 28 | #define __TAIL_H 29 | 30 | #include "triedefs.h" 31 | 32 | /** 33 | * @file tail.h 34 | * @brief trie tail for keeping suffixes 35 | */ 36 | 37 | /** 38 | * @brief Tail structure type 39 | */ 40 | typedef struct _Tail Tail; 41 | 42 | Tail * tail_new (void); 43 | 44 | Tail * tail_fread (FILE *file); 45 | 46 | void tail_free (Tail *t); 47 | 48 | size_t tail_get_serialized_size (const Tail *t); 49 | 50 | int tail_serialize (const Tail *t, uint8 **ptr); 51 | 52 | int tail_fwrite (const Tail *t, FILE *file); 53 | 54 | 55 | const TrieChar * tail_get_suffix (const Tail *t, TrieIndex index); 56 | 57 | Bool tail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix); 58 | 59 | TrieIndex tail_add_suffix (Tail *t, const TrieChar *suffix); 60 | 61 | TrieData tail_get_data (const Tail *t, TrieIndex index); 62 | 63 | Bool tail_set_data (Tail *t, TrieIndex index, TrieData data); 64 | 65 | void tail_delete (Tail *t, TrieIndex index); 66 | 67 | int tail_walk_str (const Tail *t, 68 | TrieIndex s, 69 | short *suffix_idx, 70 | const TrieChar *str, 71 | int len); 72 | 73 | Bool tail_walk_char (const Tail *t, 74 | TrieIndex s, 75 | short *suffix_idx, 76 | TrieChar c); 77 | 78 | /** 79 | * @brief Test walkability in tail with a character 80 | * 81 | * @param t : the tail data 82 | * @param s : the tail data index 83 | * @param suffix_idx : current character index in suffix 84 | * @param c : the character to test walkability 85 | * 86 | * @return boolean indicating walkability 87 | * 88 | * Test if the character @a c can be used to walk from given character 89 | * position @a suffix_idx of entry @a s of the tail data @a t. 90 | */ 91 | /* 92 | Bool tail_is_walkable_char (Tail *t, 93 | TrieIndex s, 94 | short suffix_idx, 95 | const TrieChar c); 96 | */ 97 | #define tail_is_walkable_char(t,s,suffix_idx,c) \ 98 | (tail_get_suffix ((t), (s)) [suffix_idx] == (c)) 99 | 100 | #endif /* __TAIL_H */ 101 | 102 | /* 103 | vi:ts=4:ai:expandtab 104 | */ 105 | -------------------------------------------------------------------------------- /datrie/darray.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * darray.h - Double-array trie structure 23 | * Created: 2006-08-11 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __DARRAY_H 28 | #define __DARRAY_H 29 | 30 | #include "triedefs.h" 31 | #include "trie-string.h" 32 | 33 | /** 34 | * @file darray.h 35 | * @brief Double-array trie structure 36 | */ 37 | 38 | /** 39 | * @brief Symbol set structure type 40 | */ 41 | typedef struct _Symbols Symbols; 42 | 43 | void symbols_free (Symbols *syms); 44 | int symbols_num (const Symbols *syms); 45 | TrieChar symbols_get (const Symbols *syms, int index); 46 | 47 | /** 48 | * @brief Double-array structure type 49 | */ 50 | typedef struct _DArray DArray; 51 | 52 | 53 | DArray * da_new (void); 54 | 55 | DArray * da_fread (FILE *file); 56 | 57 | void da_free (DArray *d); 58 | 59 | size_t da_get_serialized_size (const DArray *d); 60 | 61 | void da_serialize (const DArray *d, uint8 **ptr); 62 | 63 | int da_fwrite (const DArray *d, FILE *file); 64 | 65 | 66 | TrieIndex da_get_root (const DArray *d); 67 | 68 | 69 | TrieIndex da_get_base (const DArray *d, TrieIndex s); 70 | 71 | TrieIndex da_get_check (const DArray *d, TrieIndex s); 72 | 73 | 74 | void da_set_base (DArray *d, TrieIndex s, TrieIndex val); 75 | 76 | void da_set_check (DArray *d, TrieIndex s, TrieIndex val); 77 | 78 | Bool da_walk (const DArray *d, TrieIndex *s, TrieChar c); 79 | 80 | Symbols * da_output_symbols (const DArray *d, TrieIndex s); 81 | 82 | /** 83 | * @brief Test walkability in double-array structure 84 | * 85 | * @param d : the double-array structure 86 | * @param s : current state 87 | * @param c : the input character 88 | * 89 | * @return boolean indicating walkability 90 | * 91 | * Test if there is a transition from state @a s with input character @a c. 92 | */ 93 | /* 94 | Bool da_is_walkable (DArray *d, TrieIndex s, TrieChar c); 95 | */ 96 | #define da_is_walkable(d,s,c) \ 97 | (da_get_check ((d), da_get_base ((d), (s)) + (c)) == (s)) 98 | 99 | TrieIndex da_insert_branch (DArray *d, TrieIndex s, TrieChar c); 100 | 101 | void da_prune (DArray *d, TrieIndex s); 102 | 103 | void da_prune_upto (DArray *d, TrieIndex p, TrieIndex s); 104 | 105 | TrieIndex da_first_separate (DArray *d, TrieIndex root, TrieString *keybuff); 106 | 107 | TrieIndex da_next_separate (DArray *d, 108 | TrieIndex root, 109 | TrieIndex sep, 110 | TrieString *keybuff); 111 | 112 | #endif /* __DARRAY_H */ 113 | 114 | /* 115 | vi:ts=4:ai:expandtab 116 | */ 117 | -------------------------------------------------------------------------------- /nsis/WriteEnvStr.nsh: -------------------------------------------------------------------------------- 1 | !ifndef _WriteEnvStr_nsh 2 | !define _WriteEnvStr_nsh 3 | 4 | !include WinMessages.nsh 5 | 6 | !ifndef WriteEnvStr_RegKey 7 | !ifdef ALL_USERS 8 | !define WriteEnvStr_RegKey \ 9 | 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' 10 | !else 11 | !define WriteEnvStr_RegKey 'HKCU "Environment"' 12 | !endif 13 | !endif 14 | 15 | # 16 | # WriteEnvStr - Writes an environment variable 17 | # Note: Win9x systems requires reboot 18 | # 19 | # Example: 20 | # Push "HOMEDIR" # name 21 | # Push "C:\New Home Dir\" # value 22 | # Call WriteEnvStr 23 | # 24 | Function WriteEnvStr 25 | Exch $1 ; $1 has environment variable value 26 | Exch 27 | Exch $0 ; $0 has environment variable name 28 | Push $2 29 | 30 | Call IsNT 31 | Pop $2 32 | StrCmp $2 1 WriteEnvStr_NT 33 | ; Not on NT 34 | StrCpy $2 $WINDIR 2 ; Copy drive of windows (c:) 35 | FileOpen $2 "$2\autoexec.bat" a 36 | FileSeek $2 0 END 37 | FileWrite $2 "$\r$\nSET $0=$1$\r$\n" 38 | FileClose $2 39 | SetRebootFlag true 40 | Goto WriteEnvStr_done 41 | 42 | WriteEnvStr_NT: 43 | WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1 44 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} \ 45 | 0 "STR:Environment" /TIMEOUT=5000 46 | 47 | WriteEnvStr_done: 48 | Pop $2 49 | Pop $0 50 | Pop $1 51 | FunctionEnd 52 | 53 | # 54 | # un.DeleteEnvStr - Removes an environment variable 55 | # Note: Win9x systems requires reboot 56 | # 57 | # Example: 58 | # Push "HOMEDIR" # name 59 | # Call un.DeleteEnvStr 60 | # 61 | Function un.DeleteEnvStr 62 | Exch $0 ; $0 now has the name of the variable 63 | Push $1 64 | Push $2 65 | Push $3 66 | Push $4 67 | Push $5 68 | 69 | Call un.IsNT 70 | Pop $1 71 | StrCmp $1 1 DeleteEnvStr_NT 72 | ; Not on NT 73 | StrCpy $1 $WINDIR 2 74 | FileOpen $1 "$1\autoexec.bat" r 75 | GetTempFileName $4 76 | FileOpen $2 $4 w 77 | StrCpy $0 "SET $0=" 78 | SetRebootFlag true 79 | 80 | DeleteEnvStr_dosLoop: 81 | FileRead $1 $3 82 | StrLen $5 $0 83 | StrCpy $5 $3 $5 84 | StrCmp $5 $0 DeleteEnvStr_dosLoop 85 | StrCmp $5 "" DeleteEnvStr_dosLoopEnd 86 | FileWrite $2 $3 87 | Goto DeleteEnvStr_dosLoop 88 | 89 | DeleteEnvStr_dosLoopEnd: 90 | FileClose $2 91 | FileClose $1 92 | StrCpy $1 $WINDIR 2 93 | Delete "$1\autoexec.bat" 94 | CopyFiles /SILENT $4 "$1\autoexec.bat" 95 | Delete $4 96 | Goto DeleteEnvStr_done 97 | 98 | DeleteEnvStr_NT: 99 | DeleteRegValue ${WriteEnvStr_RegKey} $0 100 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} \ 101 | 0 "STR:Environment" /TIMEOUT=5000 102 | 103 | DeleteEnvStr_done: 104 | Pop $5 105 | Pop $4 106 | Pop $3 107 | Pop $2 108 | Pop $1 109 | Pop $0 110 | FunctionEnd 111 | 112 | !ifndef IsNT_KiCHiK 113 | !define IsNT_KiCHiK 114 | 115 | # 116 | # [un.]IsNT - Pushes 1 if running on NT, 0 if not 117 | # 118 | # Example: 119 | # Call IsNT 120 | # Pop $0 121 | # StrCmp $0 1 +3 122 | # MessageBox MB_OK "Not running on NT!" 123 | # Goto +2 124 | # MessageBox MB_OK "Running on NT!" 125 | # 126 | !macro IsNT UN 127 | Function ${UN}IsNT 128 | Push $0 129 | ReadRegStr $0 HKLM \ 130 | "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 131 | StrCmp $0 "" 0 IsNT_yes 132 | ; we are not NT. 133 | Pop $0 134 | Push 0 135 | Return 136 | 137 | IsNT_yes: 138 | ; NT!!! 139 | Pop $0 140 | Push 1 141 | FunctionEnd 142 | !macroend 143 | !insertmacro IsNT "" 144 | !insertmacro IsNT "un." 145 | 146 | !endif ; IsNT_KiCHiK 147 | 148 | !endif ; _WriteEnvStr_nsh 149 | 150 | -------------------------------------------------------------------------------- /datrie/fileutils.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * fileutils.h - File utility functions 23 | * Created: 2006-08-15 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include 29 | 30 | #include "fileutils.h" 31 | 32 | /* ==================== BEGIN IMPLEMENTATION PART ==================== */ 33 | 34 | /*--------------------------------* 35 | * FUNCTIONS IMPLEMENTATIONS * 36 | *--------------------------------*/ 37 | 38 | static int32 39 | parse_int32_be (const uint8 *buff) 40 | { 41 | return (buff[0] << 24) | (buff[1] << 16) | (buff[2] << 8) | buff[3]; 42 | } 43 | 44 | Bool 45 | file_read_int32 (FILE *file, int32 *o_val) 46 | { 47 | uint8 buff[4]; 48 | 49 | if (fread (buff, 4, 1, file) == 1) { 50 | *o_val = parse_int32_be (buff); 51 | return TRUE; 52 | } 53 | 54 | return FALSE; 55 | } 56 | 57 | static void 58 | serialize_int32_be (uint8 *buff, int32 val) 59 | { 60 | buff[0] = (val >> 24) & 0xff; 61 | buff[1] = (val >> 16) & 0xff; 62 | buff[2] = (val >> 8) & 0xff; 63 | buff[3] = val & 0xff; 64 | } 65 | 66 | 67 | void 68 | serialize_int32_be_incr (uint8 **buff, int32 val) 69 | { 70 | serialize_int32_be (*buff, val); 71 | *buff += 4; /* don't sizeof! */ 72 | } 73 | 74 | Bool 75 | file_write_int32 (FILE *file, int32 val) 76 | { 77 | uint8 buff[4]; 78 | serialize_int32_be (buff, val); 79 | return (fwrite (buff, 4, 1, file) == 1); 80 | } 81 | 82 | static int16 83 | parse_int16_be (const uint8 *buff) 84 | { 85 | return (buff[0] << 8) | buff[1]; 86 | } 87 | 88 | Bool 89 | file_read_int16 (FILE *file, int16 *o_val) 90 | { 91 | uint8 buff[2]; 92 | 93 | if (fread (buff, 2, 1, file) == 1) { 94 | *o_val = parse_int16_be (buff); 95 | return TRUE; 96 | } 97 | 98 | return FALSE; 99 | } 100 | 101 | static void 102 | serialize_int16_be (uint8 *buff, int16 val) 103 | { 104 | buff[0] = val >> 8; 105 | buff[1] = val & 0xff; 106 | } 107 | 108 | void 109 | serialize_int16_be_incr (uint8 **buff, int16 val) 110 | { 111 | serialize_int16_be (*buff, val); 112 | *buff += 2; /* don't sizeof! */ 113 | } 114 | 115 | Bool 116 | file_write_int16 (FILE *file, int16 val) 117 | { 118 | uint8 buff[2]; 119 | serialize_int16_be (buff, val); 120 | return (fwrite (buff, 2, 1, file) == 1); 121 | } 122 | 123 | Bool 124 | file_read_int8 (FILE *file, int8 *o_val) 125 | { 126 | return (fread (o_val, sizeof (int8), 1, file) == 1); 127 | } 128 | 129 | Bool 130 | file_write_int8 (FILE *file, int8 val) 131 | { 132 | return (fwrite (&val, sizeof (int8), 1, file) == 1); 133 | } 134 | 135 | Bool 136 | file_read_chars (FILE *file, char *buff, int len) 137 | { 138 | return (fread (buff, sizeof (char), len, file) == len); 139 | } 140 | 141 | Bool 142 | file_write_chars (FILE *file, const char *buff, int len) 143 | { 144 | return (fwrite (buff, sizeof (char), len, file) == len); 145 | } 146 | 147 | /* 148 | vi:ts=4:ai:expandtab 149 | */ 150 | -------------------------------------------------------------------------------- /datrie/typedefs.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * typedefs.h - general types 23 | * Created : 11 Aug 2006 24 | * Author : Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TYPEDEFS_H 28 | #define __TYPEDEFS_H 29 | 30 | #include 31 | 32 | typedef enum { DA_FALSE = 0, DA_TRUE = 1 } Bool; 33 | #ifndef FALSE 34 | # define FALSE DA_FALSE 35 | #endif 36 | #ifndef TRUE 37 | # define TRUE DA_TRUE 38 | #endif 39 | 40 | # if UCHAR_MAX == 0xff 41 | # ifndef UINT8_TYPEDEF 42 | # define UINT8_TYPEDEF 43 | typedef unsigned char uint8; 44 | # endif /* UINT8_TYPEDEF */ 45 | # endif /* UCHAR_MAX */ 46 | 47 | # if SCHAR_MAX == 0x7f 48 | # ifndef INT8_TYPEDEF 49 | # define INT8_TYPEDEF 50 | typedef signed char int8; 51 | # endif /* INT8_TYPEDEF */ 52 | # endif /* SCHAR_MAX */ 53 | 54 | # if UINT_MAX == 0xffff 55 | # ifndef UINT16_TYPEDEF 56 | # define UINT16_TYPEDEF 57 | typedef unsigned int uint16; 58 | # endif /* UINT16_TYPEDEF */ 59 | # endif /* UINT_MAX */ 60 | 61 | # if INT_MAX == 0x7fff 62 | # ifndef INT16_TYPEDEF 63 | # define INT16_TYPEDEF 64 | typedef int int16; 65 | # endif /* INT16_TYPEDEF */ 66 | # endif /* INT_MAX */ 67 | 68 | # if USHRT_MAX == 0xffff 69 | # ifndef UINT16_TYPEDEF 70 | # define UINT16_TYPEDEF 71 | typedef unsigned short uint16; 72 | # endif /* UINT16_TYPEDEF */ 73 | # endif /* USHRT_MAX */ 74 | 75 | # if SHRT_MAX == 0x7fff 76 | # ifndef INT16_TYPEDEF 77 | # define INT16_TYPEDEF 78 | typedef short int16; 79 | # endif /* INT16_TYPEDEF */ 80 | # endif /* SHRT_MAX */ 81 | 82 | # if UINT_MAX == 0xffffffff 83 | # ifndef UINT32_TYPEDEF 84 | # define UINT32_TYPEDEF 85 | typedef unsigned int uint32; 86 | # endif /* UINT32_TYPEDEF */ 87 | # endif /* UINT_MAX */ 88 | 89 | # if INT_MAX == 0x7fffffff 90 | # ifndef INT32_TYPEDEF 91 | # define INT32_TYPEDEF 92 | typedef int int32; 93 | # endif /* INT32_TYPEDEF */ 94 | # endif /* INT_MAX */ 95 | 96 | # if ULONG_MAX == 0xffffffff 97 | # ifndef UINT32_TYPEDEF 98 | # define UINT32_TYPEDEF 99 | typedef unsigned long uint32; 100 | # endif /* UINT32_TYPEDEF */ 101 | # endif /* ULONG_MAX */ 102 | 103 | # if LONG_MAX == 0x7fffffff 104 | # ifndef INT32_TYPEDEF 105 | # define INT32_TYPEDEF 106 | typedef long int32; 107 | # endif /* INT32_TYPEDEF */ 108 | # endif /* LONG_MAX */ 109 | 110 | # ifndef UINT8_TYPEDEF 111 | # error "uint8 type is undefined!" 112 | # endif 113 | # ifndef INT8_TYPEDEF 114 | # error "int8 type is undefined!" 115 | # endif 116 | # ifndef UINT16_TYPEDEF 117 | # error "uint16 type is undefined!" 118 | # endif 119 | # ifndef INT16_TYPEDEF 120 | # error "int16 type is undefined!" 121 | # endif 122 | # ifndef UINT32_TYPEDEF 123 | # error "uint32 type is undefined!" 124 | # endif 125 | # ifndef INT32_TYPEDEF 126 | # error "int32 type is undefined!" 127 | # endif 128 | 129 | 130 | #endif /* __TYPEDEFS_H */ 131 | 132 | /* 133 | vi:ts=4:ai:expandtab 134 | */ 135 | -------------------------------------------------------------------------------- /datrie/trie-string.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * trie-string.c - Dynamic string type for Trie alphabets 23 | * Created: 2012-08-02 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include "trie-string.h" 28 | #include "dstring-private.h" 29 | #include "triedefs.h" 30 | #include "trie-private.h" 31 | 32 | #include 33 | #include 34 | 35 | /*----------------------------* 36 | * STATIC TRIECHAR STRING * 37 | *----------------------------*/ 38 | 39 | size_t 40 | trie_char_strlen (const TrieChar *str) 41 | { 42 | size_t len = 0; 43 | while (*str++ != TRIE_CHAR_TERM) { 44 | ++len; 45 | } 46 | return len; 47 | } 48 | 49 | size_t 50 | trie_char_strsize (const TrieChar *str) 51 | { 52 | return trie_char_strlen (str) * sizeof (TrieChar); 53 | } 54 | 55 | TrieChar * 56 | trie_char_strdup (const TrieChar *str) 57 | { 58 | TrieChar *dup 59 | = (TrieChar *) malloc (sizeof (TrieChar) * (trie_char_strlen (str) + 1)); 60 | if (UNLIKELY (!dup)) 61 | return NULL; 62 | TrieChar *p = dup; 63 | 64 | while (*str != TRIE_CHAR_TERM) { 65 | *p++ = *str++; 66 | } 67 | *p = TRIE_CHAR_TERM; 68 | 69 | return dup; 70 | } 71 | 72 | /*-----------------------------* 73 | * DYNAMIC TRIECHAR STRING * 74 | *-----------------------------*/ 75 | 76 | struct _TrieString { 77 | DString ds; 78 | }; 79 | 80 | 81 | TrieString * 82 | trie_string_new (int n_elm) 83 | { 84 | return (TrieString *) dstring_new (sizeof (TrieChar), n_elm); 85 | } 86 | 87 | void 88 | trie_string_free (TrieString *ts) 89 | { 90 | dstring_free ((DString *)ts); 91 | } 92 | 93 | int 94 | trie_string_length (const TrieString *ts) 95 | { 96 | return dstring_length ((DString *)ts); 97 | } 98 | 99 | const void * 100 | trie_string_get_val (const TrieString *ts) 101 | { 102 | return dstring_get_val ((DString *)ts); 103 | } 104 | 105 | void * 106 | trie_string_get_val_rw (TrieString *ts) 107 | { 108 | return dstring_get_val_rw ((DString *)ts); 109 | } 110 | 111 | void 112 | trie_string_clear (TrieString *ts) 113 | { 114 | dstring_clear ((DString *)ts); 115 | } 116 | 117 | Bool 118 | trie_string_copy (TrieString *dst, const TrieString *src) 119 | { 120 | return dstring_copy ((DString *)dst, (const DString *)src); 121 | } 122 | 123 | Bool 124 | trie_string_append (TrieString *dst, const TrieString *src) 125 | { 126 | return dstring_append ((DString *)dst, (const DString *)src); 127 | } 128 | 129 | Bool 130 | trie_string_append_string (TrieString *ts, const TrieChar *str) 131 | { 132 | return dstring_append_string ((DString *)ts, 133 | str, strlen ((const char *)str)); 134 | } 135 | 136 | Bool 137 | trie_string_append_char (TrieString *ts, TrieChar tc) 138 | { 139 | return dstring_append_char ((DString *)ts, &tc); 140 | } 141 | 142 | Bool 143 | trie_string_terminate (TrieString *ts) 144 | { 145 | static const TrieChar term = TRIE_CHAR_TERM; 146 | return dstring_append_char ((DString *)ts, &term); 147 | } 148 | 149 | Bool 150 | trie_string_cut_last (TrieString *ts) 151 | { 152 | return dstring_cut_last ((DString *)ts); 153 | } 154 | 155 | /* 156 | vi:ts=4:ai:expandtab 157 | */ 158 | -------------------------------------------------------------------------------- /tests/test_term_state.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2018 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_term_state.c - Test data retrieval from terminal state 23 | * Created: 2018-03-29 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | 32 | /* 33 | * Test trie 34 | * 35 | * (1) -a-> (2) -b-> (3) -#-> [4] {data=1} 36 | * | 37 | * +---c-> (5) -#-> [6] {data=2} 38 | * 39 | */ 40 | int 41 | main (void) 42 | { 43 | Trie *test_trie; 44 | TrieState *trie_state; 45 | TrieData data; 46 | Bool is_failed; 47 | 48 | msg_step ("Preparing trie"); 49 | test_trie = en_trie_new (); 50 | if (!test_trie) { 51 | printf ("Fail to create test trie\n"); 52 | goto err_trie_not_created; 53 | } 54 | 55 | /* populate trie */ 56 | msg_step ("Populating trie with test set"); 57 | if (!trie_store (test_trie, (AlphaChar *)L"ab", 1)) { 58 | printf ("Failed to add key 'ab', data 1.\n"); 59 | goto err_trie_created; 60 | } 61 | if (!trie_store (test_trie, (AlphaChar *)L"abc", 2)) { 62 | printf ("Failed to add key 'abc', data 2.\n"); 63 | goto err_trie_created; 64 | } 65 | 66 | is_failed = FALSE; 67 | 68 | /* try retrieving data */ 69 | msg_step ("Preparing root state"); 70 | trie_state = trie_root (test_trie); 71 | if (!trie_state) { 72 | printf ("Failed to get trie root state\n"); 73 | goto err_trie_created; 74 | } 75 | 76 | msg_step ("Try walking from root with 'a'"); 77 | if (!trie_state_walk (trie_state, (AlphaChar)L'a')) { 78 | printf ("Failed to walk from root with 'a'.\n"); 79 | is_failed = TRUE; 80 | } 81 | 82 | data = trie_state_get_data (trie_state); 83 | if (data != TRIE_DATA_ERROR) { 84 | printf ("Retrieved data at 'a' is %d, not %d.\n", 85 | data, TRIE_DATA_ERROR); 86 | is_failed = TRUE; 87 | } 88 | 89 | msg_step ("Try walking further with 'b'"); 90 | if (!trie_state_walk (trie_state, (AlphaChar)L'b')) { 91 | printf ("Failed to continue walking with 'b'.\n"); 92 | is_failed = TRUE; 93 | } 94 | 95 | data = trie_state_get_data (trie_state); 96 | if (data != 1) { 97 | printf ("Retrieved data for key 'ab' is %d, not 1.\n", data); 98 | is_failed = TRUE; 99 | } 100 | 101 | msg_step ("Try walking further with 'c'"); 102 | if (!trie_state_walk (trie_state, (AlphaChar)L'c')) { 103 | printf ("Failed to continue walking with 'c'.\n"); 104 | is_failed = TRUE; 105 | } 106 | 107 | data = trie_state_get_data (trie_state); 108 | if (data != 2) { 109 | printf ("Retrieved data for key 'abc' is %d, not 2.\n", data); 110 | is_failed = TRUE; 111 | } 112 | 113 | trie_state_free (trie_state); 114 | 115 | if (is_failed) { 116 | printf ("Errors found in terminal state data retrieval.\n"); 117 | goto err_trie_created; 118 | } 119 | 120 | trie_free (test_trie); 121 | return 0; 122 | 123 | err_trie_created: 124 | trie_free (test_trie); 125 | err_trie_not_created: 126 | return 1; 127 | } 128 | 129 | /* 130 | vi:ts=4:ai:expandtab 131 | */ 132 | -------------------------------------------------------------------------------- /tests/test_file.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_file.c - Test for datrie file operations 23 | * Created: 2013-10-16 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | 32 | #define TRIE_FILENAME "test_file.tri" 33 | 34 | static Bool 35 | trie_enum_mark_rec (const AlphaChar *key, TrieData key_data, void *user_data) 36 | { 37 | Bool *is_failed = (Bool *)user_data; 38 | TrieData src_data; 39 | 40 | src_data = dict_src_get_data (key); 41 | if (TRIE_DATA_ERROR == src_data) { 42 | printf ("Extra entry in file: key '%ls', data %d.\n", 43 | (wchar_t *)key, key_data); 44 | *is_failed = TRUE; 45 | } else if (src_data != key_data) { 46 | printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", 47 | (wchar_t *)key, src_data, key_data); 48 | *is_failed = TRUE; 49 | } else { 50 | dict_src_set_data (key, TRIE_DATA_READ); 51 | } 52 | 53 | return TRUE; 54 | } 55 | 56 | int 57 | main (void) 58 | { 59 | Trie *test_trie; 60 | DictRec *dict_p; 61 | Bool is_failed; 62 | 63 | msg_step ("Preparing trie"); 64 | test_trie = en_trie_new (); 65 | if (!test_trie) { 66 | printf ("Failed to allocate test trie.\n"); 67 | goto err_trie_not_created; 68 | } 69 | 70 | /* add/remove some words */ 71 | for (dict_p = dict_src; dict_p->key; dict_p++) { 72 | if (!trie_store (test_trie, dict_p->key, dict_p->data)) { 73 | printf ("Failed to add key '%ls', data %d.\n", 74 | (wchar_t *)dict_p->key, dict_p->data); 75 | goto err_trie_created; 76 | } 77 | } 78 | 79 | /* save & close */ 80 | msg_step ("Saving trie to file"); 81 | remove (TRIE_FILENAME); /* error ignored */ 82 | if (trie_save (test_trie, TRIE_FILENAME) != 0) { 83 | printf ("Failed to save trie to file '%s'.\n", TRIE_FILENAME); 84 | goto err_trie_created; 85 | } 86 | trie_free (test_trie); 87 | 88 | /* reload from file */ 89 | msg_step ("Reloading trie from the saved file"); 90 | test_trie = trie_new_from_file (TRIE_FILENAME); 91 | if (!test_trie) { 92 | printf ("Failed to reload saved trie from '%s'.\n", 93 | TRIE_FILENAME); 94 | goto err_trie_saved; 95 | } 96 | 97 | /* enumerate & check */ 98 | msg_step ("Checking trie contents"); 99 | is_failed = FALSE; 100 | /* mark entries found in file */ 101 | if (!trie_enumerate (test_trie, trie_enum_mark_rec, (void *)&is_failed)) { 102 | printf ("Failed to enumerate trie file contents.\n"); 103 | goto err_trie_saved; 104 | } 105 | /* check for unmarked entries, (i.e. missed in file) */ 106 | for (dict_p = dict_src; dict_p->key; dict_p++) { 107 | if (dict_p->data != TRIE_DATA_READ) { 108 | printf ("Entry missed in file: key '%ls', data %d.\n", 109 | (wchar_t *)dict_p->key, dict_p->data); 110 | is_failed = TRUE; 111 | } 112 | } 113 | if (is_failed) { 114 | printf ("Errors found in trie saved contents.\n"); 115 | goto err_trie_saved; 116 | } 117 | 118 | remove (TRIE_FILENAME); 119 | trie_free (test_trie); 120 | return 0; 121 | 122 | err_trie_saved: 123 | remove (TRIE_FILENAME); 124 | err_trie_created: 125 | trie_free (test_trie); 126 | err_trie_not_created: 127 | return 1; 128 | } 129 | 130 | /* 131 | vi:ts=4:ai:expandtab 132 | */ 133 | -------------------------------------------------------------------------------- /tests/test_serialization.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_serialization.c - Test for datrie file and in-memory blob operations 23 | * Created: 2019-11-11 24 | * Author: Theppitak Karoonboonyanan and KOLANICH 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #define TRIE_FILENAME "test_serialization.tri" 35 | 36 | int 37 | main (void) 38 | { 39 | Trie *test_trie; 40 | DictRec *dict_p; 41 | 42 | msg_step ("Preparing trie"); 43 | test_trie = en_trie_new (); 44 | if (!test_trie) { 45 | printf ("Failed to allocate test trie.\n"); 46 | goto err_trie_not_created; 47 | } 48 | 49 | /* add/remove some words */ 50 | for (dict_p = dict_src; dict_p->key; dict_p++) { 51 | if (!trie_store (test_trie, dict_p->key, dict_p->data)) { 52 | printf ("Failed to add key '%ls', data %d.\n", 53 | (wchar_t *)dict_p->key, dict_p->data); 54 | goto err_trie_created; 55 | } 56 | } 57 | 58 | /* save & close */ 59 | msg_step ("Saving trie to file"); 60 | remove (TRIE_FILENAME); /* error ignored */ 61 | if (trie_save (test_trie, TRIE_FILENAME) != 0) { 62 | printf ("Failed to save trie to file '%s'.\n", TRIE_FILENAME); 63 | goto err_trie_created; 64 | } 65 | 66 | msg_step ("Getting serialized trie size"); 67 | size_t size = trie_get_serialized_size (test_trie); 68 | printf ("serialized trie size %lu\n", size); 69 | msg_step ("Allocating"); 70 | uint8 *trieSerializedData = malloc (size); 71 | if (!trieSerializedData) { 72 | printf ("Failed to allocate trieSerializedData.\n"); 73 | goto err_trie_saved; 74 | } 75 | printf ("allocated %p\n", trieSerializedData); 76 | msg_step ("Serializing"); 77 | trie_serialize (test_trie, trieSerializedData); 78 | msg_step ("Serialized"); 79 | 80 | FILE *f = fopen (TRIE_FILENAME, "rb"); 81 | if (!f) { 82 | printf ("Failed to reopen trie file " TRIE_FILENAME ".\n"); 83 | goto err_serial_data_allocated; 84 | } 85 | fseek (f, 0, SEEK_END); 86 | size_t file_size = ftell (f); 87 | fseek (f, 0, SEEK_SET); 88 | 89 | if (size != file_size) { 90 | printf ("Trie serialized data doesn't match size of the file.\n"); 91 | goto err_file_reopened; 92 | } 93 | 94 | unsigned char *trieFileData = malloc (size); 95 | if (!trieFileData) { 96 | printf ("Failed to allocate trieFileData.\n"); 97 | goto err_file_reopened; 98 | } 99 | if (fread (trieFileData, 1, size, f) != size) { 100 | printf ("Failed to read back the serialized trie file.\n"); 101 | goto err_file_data_allocated; 102 | } 103 | if (memcmp (trieSerializedData, trieFileData, size) != 0) { 104 | printf ("Trie serialized data doesn't match contents of the file.\n"); 105 | goto err_file_data_allocated; 106 | } 107 | printf ("PASS!\n"); 108 | 109 | free (trieFileData); 110 | fclose (f); 111 | free (trieSerializedData); 112 | remove (TRIE_FILENAME); 113 | trie_free (test_trie); 114 | return 0; 115 | 116 | err_file_data_allocated: 117 | free (trieFileData); 118 | err_file_reopened: 119 | fclose (f); 120 | err_serial_data_allocated: 121 | free (trieSerializedData); 122 | err_trie_saved: 123 | remove (TRIE_FILENAME); 124 | err_trie_created: 125 | trie_free (test_trie); 126 | err_trie_not_created: 127 | return 1; 128 | } 129 | 130 | /* 131 | vi:ts=4:ai:expandtab 132 | */ 133 | -------------------------------------------------------------------------------- /tests/test_iterator.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_iterator.c - Test for datrie iterator operations 23 | * Created: 2013-10-16 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | #include 32 | 33 | int 34 | main (void) 35 | { 36 | Trie *test_trie; 37 | DictRec *dict_p; 38 | TrieState *trie_root_state; 39 | TrieIterator *trie_it; 40 | Bool is_failed; 41 | 42 | msg_step ("Preparing trie"); 43 | test_trie = en_trie_new (); 44 | if (!test_trie) { 45 | fprintf (stderr, "Fail to create test trie\n"); 46 | goto err_trie_not_created; 47 | } 48 | 49 | /* store */ 50 | msg_step ("Adding data to trie"); 51 | for (dict_p = dict_src; dict_p->key; dict_p++) { 52 | if (!trie_store (test_trie, dict_p->key, dict_p->data)) { 53 | printf ("Failed to add key '%ls', data %d.\n", 54 | (wchar_t *)dict_p->key, dict_p->data); 55 | goto err_trie_created; 56 | } 57 | } 58 | 59 | /* iterate & check */ 60 | msg_step ("Iterating and checking trie contents"); 61 | trie_root_state = trie_root (test_trie); 62 | if (!trie_root_state) { 63 | printf ("Failed to get trie root state\n"); 64 | goto err_trie_created; 65 | } 66 | trie_it = trie_iterator_new (trie_root_state); 67 | if (!trie_it) { 68 | printf ("Failed to get trie iterator\n"); 69 | goto err_trie_root_created; 70 | } 71 | 72 | is_failed = FALSE; 73 | while (trie_iterator_next (trie_it)) { 74 | AlphaChar *key; 75 | TrieData key_data, src_data; 76 | 77 | key = trie_iterator_get_key (trie_it); 78 | if (!key) { 79 | printf ("Failed to get key from trie iterator\n"); 80 | is_failed = TRUE; 81 | continue; 82 | } 83 | key_data = trie_iterator_get_data (trie_it); 84 | if (TRIE_DATA_ERROR == key_data) { 85 | printf ("Failed to get data from trie iterator for key '%ls'\n", 86 | (wchar_t *)key); 87 | is_failed = TRUE; 88 | } 89 | /* mark entries found in trie */ 90 | src_data = dict_src_get_data (key); 91 | if (TRIE_DATA_ERROR == src_data) { 92 | printf ("Extra entry in trie: key '%ls', data %d.\n", 93 | (wchar_t *)key, key_data); 94 | is_failed = TRUE; 95 | } else if (src_data != key_data) { 96 | printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", 97 | (wchar_t *)key, src_data, key_data); 98 | is_failed = TRUE; 99 | } else { 100 | dict_src_set_data (key, TRIE_DATA_READ); 101 | } 102 | 103 | free (key); 104 | } 105 | 106 | /* check for unmarked entries, (i.e. missed in trie) */ 107 | for (dict_p = dict_src; dict_p->key; dict_p++) { 108 | if (dict_p->data != TRIE_DATA_READ) { 109 | printf ("Entry missed in trie: key '%ls', data %d.\n", 110 | (wchar_t *)dict_p->key, dict_p->data); 111 | is_failed = TRUE; 112 | } 113 | } 114 | 115 | if (is_failed) { 116 | printf ("Errors found in trie iteration.\n"); 117 | goto err_trie_it_created; 118 | } 119 | 120 | trie_iterator_free (trie_it); 121 | trie_state_free (trie_root_state); 122 | trie_free (test_trie); 123 | return 0; 124 | 125 | err_trie_it_created: 126 | trie_iterator_free (trie_it); 127 | err_trie_root_created: 128 | trie_state_free (trie_root_state); 129 | err_trie_created: 130 | trie_free (test_trie); 131 | err_trie_not_created: 132 | return 1; 133 | } 134 | 135 | /* 136 | vi:ts=4:ai:expandtab 137 | */ 138 | -------------------------------------------------------------------------------- /datrie/dstring.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * dstring.c - Dynamic string type 23 | * Created: 2012-08-01 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include "dstring.h" 28 | #include "dstring-private.h" 29 | 30 | #include "trie-private.h" 31 | #include 32 | #include 33 | 34 | 35 | DString * 36 | dstring_new (int char_size, int n_elm) 37 | { 38 | DString *ds; 39 | 40 | ds = (DString *) malloc (sizeof (DString)); 41 | if (UNLIKELY (!ds)) 42 | return NULL; 43 | 44 | ds->alloc_size = char_size * n_elm; 45 | ds->val = malloc (ds->alloc_size); 46 | if (UNLIKELY (!ds->val)) { 47 | free (ds); 48 | return NULL; 49 | } 50 | 51 | ds->char_size = char_size; 52 | ds->str_len = 0; 53 | 54 | return ds; 55 | } 56 | 57 | void 58 | dstring_free (DString *ds) 59 | { 60 | free (ds->val); 61 | free (ds); 62 | } 63 | 64 | int 65 | dstring_length (const DString *ds) 66 | { 67 | return ds->str_len; 68 | } 69 | 70 | const void * 71 | dstring_get_val (const DString *ds) 72 | { 73 | return ds->val; 74 | } 75 | 76 | void * 77 | dstring_get_val_rw (DString *ds) 78 | { 79 | return ds->val; 80 | } 81 | 82 | void 83 | dstring_clear (DString *ds) 84 | { 85 | ds->str_len = 0; 86 | } 87 | 88 | static Bool 89 | dstring_ensure_space (DString *ds, int size) 90 | { 91 | if (ds->alloc_size < size) { 92 | int re_size = MAX_VAL (ds->alloc_size * 2, size); 93 | void *re_ptr = realloc (ds->val, re_size); 94 | if (UNLIKELY (!re_ptr)) 95 | return FALSE; 96 | ds->val = re_ptr; 97 | ds->alloc_size = re_size; 98 | } 99 | 100 | return TRUE; 101 | } 102 | 103 | Bool 104 | dstring_copy (DString *dst, const DString *src) 105 | { 106 | if (!dstring_ensure_space (dst, (src->str_len + 1) * src->char_size)) 107 | return FALSE; 108 | 109 | memcpy (dst->val, src->val, (src->str_len + 1) * src->char_size); 110 | 111 | dst->char_size = src->char_size; 112 | dst->str_len = src->str_len; 113 | 114 | return TRUE; 115 | } 116 | 117 | Bool 118 | dstring_append (DString *dst, const DString *src) 119 | { 120 | if (dst->char_size != src->char_size) 121 | return FALSE; 122 | 123 | if (!dstring_ensure_space (dst, (dst->str_len + src->str_len + 1) 124 | * dst->char_size)) 125 | { 126 | return FALSE; 127 | } 128 | 129 | memcpy ((char *)dst->val + (dst->char_size * dst->str_len), src->val, 130 | (src->str_len + 1) * dst->char_size); 131 | 132 | dst->str_len += src->str_len; 133 | 134 | return TRUE; 135 | } 136 | 137 | Bool 138 | dstring_append_string (DString *ds, const void *data, int len) 139 | { 140 | if (!dstring_ensure_space (ds, (ds->str_len + len + 1) * ds->char_size)) 141 | return FALSE; 142 | 143 | memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, 144 | ds->char_size * len); 145 | 146 | ds->str_len += len; 147 | 148 | return TRUE; 149 | } 150 | 151 | Bool 152 | dstring_append_char (DString *ds, const void *data) 153 | { 154 | if (!dstring_ensure_space (ds, (ds->str_len + 2) * ds->char_size)) 155 | return FALSE; 156 | 157 | memcpy ((char *)ds->val + (ds->char_size * ds->str_len), data, 158 | ds->char_size); 159 | 160 | ds->str_len++; 161 | 162 | return TRUE; 163 | } 164 | 165 | Bool 166 | dstring_terminate (DString *ds) 167 | { 168 | if (!dstring_ensure_space (ds, (ds->str_len + 2) * ds->char_size)) 169 | return FALSE; 170 | 171 | memset ((char *)ds->val + (ds->char_size * ds->str_len), 0, ds->char_size); 172 | 173 | return TRUE; 174 | } 175 | 176 | Bool 177 | dstring_cut_last (DString *ds) 178 | { 179 | if (0 == ds->str_len) 180 | return FALSE; 181 | 182 | ds->str_len--; 183 | 184 | return TRUE; 185 | } 186 | 187 | /* 188 | vi:ts=4:ai:expandtab 189 | */ 190 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.71]) 5 | AC_INIT([libdatrie], 6 | [m4_esyscmd(build-aux/git-version-gen)], 7 | [https://github.com/tlwg/libdatrie/issues]) 8 | AC_CONFIG_SRCDIR([datrie/trie.h]) 9 | AC_CONFIG_HEADERS([config.h]) 10 | AC_CONFIG_AUX_DIR(build-aux) 11 | AC_CONFIG_MACRO_DIR([m4]) 12 | 13 | AM_INIT_AUTOMAKE(dist-xz no-dist-gzip) 14 | 15 | # Library versioning 16 | # Library code modified: REVISION++ 17 | # Interfaces added: CURRENT++ REVISION=0 AGE++ 18 | # Interfaces changed/removed: CURRENT++ REVISION=0 AGE=0 19 | LT_CURRENT=5 20 | LT_REVISION=1 21 | LT_AGE=4 22 | AC_SUBST(LT_CURRENT) 23 | AC_SUBST(LT_REVISION) 24 | AC_SUBST(LT_AGE) 25 | 26 | DOXYGEN_REQ_VER=1.9.8 27 | 28 | # Checks for programs. 29 | AC_PROG_CC 30 | AC_PROG_INSTALL 31 | AC_PROG_LN_S 32 | AC_PROG_MAKE_SET 33 | LT_INIT 34 | 35 | # Whether linker support --version-script option 36 | echo '{global:hello; local:*;};' > conftest.ver 37 | _LT_LINKER_OPTION( 38 | [whether linker supports -version-script], 39 | [datrie_cv_have_version_script], 40 | [-Wl,-version-script -Wl,conftest.ver]) 41 | 42 | AM_CONDITIONAL(LD_HAS_VERSION_SCRIPT, 43 | test "$datrie_cv_have_version_script" = "yes") 44 | 45 | # Checks for libraries. 46 | 47 | # 48 | # Checks for iconv 49 | # 50 | found_iconv=no 51 | # Check in the C library first 52 | AC_CHECK_FUNC(iconv_open, [with_libiconv=no; found_iconv=yes]) 53 | # Check if we have GNU libiconv 54 | if test $found_iconv = "no"; then 55 | AC_CHECK_LIB(iconv, libiconv_open, [with_libiconv=gnu; found_iconv=yes]) 56 | fi 57 | # Check if we have a iconv in -liconv, possibly from vendor 58 | if test $found_iconv = "no"; then 59 | AC_CHECK_LIB(iconv, iconv_open, [with_libiconv=native; found_iconv=yes]) 60 | fi 61 | if test $found_iconv = "no"; then 62 | AC_MSG_ERROR([*** No usable iconv() implementation found]) 63 | fi 64 | 65 | # 66 | # Checks for locale_charset() and nl_langinfo(CODESET) 67 | # 68 | AC_CHECK_LIB(iconv, locale_charset, 69 | [have_locale_charset=yes], [have_locale_charset=no]) 70 | if test x$have_locale_charset = xyes; then 71 | AC_DEFINE(HAVE_LOCALE_CHARSET,1,[Have locale_charset()]) 72 | with_libiconv=yes 73 | fi 74 | AC_CACHE_CHECK( 75 | [for nl_langinfo (CODESET)], datrie_cv_langinfo_codeset, 76 | [AC_COMPILE_IFELSE( 77 | [AC_LANG_PROGRAM( 78 | [[#include ]], 79 | [[char *codeset = nl_langinfo (CODESET);]] 80 | )], 81 | [datrie_cv_langinfo_codeset=yes], 82 | [datrie_cv_langinfo_codeset=no])] 83 | ) 84 | if test x$datrie_cv_langinfo_codeset = xyes; then 85 | AC_DEFINE(HAVE_LANGINFO_CODESET,1,[Have nl_langinfo (CODESET)]) 86 | fi 87 | if test x$have_locale_charset = xno && test x$datrie_cv_langinfo_codeset = xno 88 | then 89 | AC_MSG_ERROR([*** No locale_charset() nor nl_langinfo(CODESET) found. 90 | Please consider installing GNU libiconv.]) 91 | fi 92 | 93 | case $with_libiconv in 94 | gnu|native|yes) 95 | ICONV_LIBS="-liconv" 96 | ;; 97 | esac 98 | AC_SUBST(ICONV_LIBS) 99 | 100 | 101 | # Checks for header files. 102 | AC_CHECK_HEADERS([limits.h stdlib.h stdio.h string.h]) 103 | 104 | # Checks for typedefs, structures, and compiler characteristics. 105 | AC_C_CONST 106 | AC_TYPE_SIZE_T 107 | 108 | dnl Disable doc generation with doxygen option 109 | AC_ARG_ENABLE(doxygen-doc, 110 | [AS_HELP_STRING([--disable-doxygen-doc], 111 | [disable document generation with doxygen])], 112 | , enable_doxygen_doc="yes") 113 | 114 | if test "x$enable_doxygen_doc" = "xyes"; then 115 | AC_CHECK_PROG(DOXYGEN,doxygen,doxygen,no) 116 | if test "x$DOXYGEN" = "xno"; then 117 | enable_doxygen_doc="no" 118 | else 119 | AC_MSG_CHECKING([doxygen >= $DOXYGEN_REQ_VER]) 120 | DOXYGEN_VER=$($DOXYGEN --version) 121 | AS_VERSION_COMPARE([$DOXYGEN_VER],[$DOXYGEN_REQ_VER], 122 | [enable_doxygen_doc="no"]) 123 | if test x"$enable_doxygen_doc" = "xyes"; then 124 | AC_MSG_RESULT([$DOXYGEN_VER, yes]) 125 | else 126 | AC_MSG_RESULT([$DOXYGEN_VER, no, documentation disabled]) 127 | fi 128 | fi 129 | fi 130 | 131 | dnl where to install the doxygen-generated HTML doc 132 | AC_ARG_WITH(html-docdir, 133 | [AS_HELP_STRING([--with-html-docdir=DIR], 134 | [where to install the doxyten-generated HTML doc [PREFIX/share/doc/datrie/html]])], 135 | [htmldocdir="$withval"], [htmldocdir=\$\{prefix\}/share/doc/datrie/html]) 136 | AC_SUBST(htmldocdir) 137 | 138 | AM_CONDITIONAL(ENABLE_DOXYGEN_DOC,test "x$enable_doxygen_doc" = "xyes") 139 | 140 | # Checks for library functions. 141 | AC_CHECK_FUNCS([malloc]) 142 | 143 | AC_CONFIG_FILES([Makefile 144 | datrie-0.2.pc 145 | datrie/Makefile 146 | tools/Makefile 147 | man/Makefile 148 | doc/Makefile 149 | doc/Doxyfile 150 | tests/Makefile]) 151 | AC_OUTPUT 152 | -------------------------------------------------------------------------------- /man/trietool.1: -------------------------------------------------------------------------------- 1 | .\" Hey, EMACS: -*- nroff -*- 2 | .\" First parameter, NAME, should be all caps 3 | .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection 4 | .\" other parameters are allowed: see man(7), man(1) 5 | .TH TRIETOOL 1 "DECEMBER 2008" 6 | .\" Please adjust this date whenever revising the manpage. 7 | .\" 8 | .\" Some roff macros, for reference: 9 | .\" .nh disable hyphenation 10 | .\" .hy enable hyphenation 11 | .\" .ad l left justify 12 | .\" .ad b justify to both left and right margins 13 | .\" .nf disable filling 14 | .\" .fi enable filling 15 | .\" .br insert line break 16 | .\" .sp insert n+1 empty lines 17 | .\" for manpage-specific macros, see man(7) 18 | .SH NAME 19 | trietool \- trie manipulation tool 20 | .SH SYNOPSIS 21 | \fBtrietool\fP [ \fIoptions\fP ] \fItrie command arg\fP ... 22 | .SH DESCRIPTION 23 | \fBtrietool\fP is the command-line tool for manipulating double-array trie 24 | data. It can be used to query, add and remove words in a trie. 25 | .P 26 | .SS The Trie 27 | The \fItrie\fP argument specifies the name of the trie to manipulate. 28 | A trie is stored in a file with `.tri' extension. However, to create a new 29 | trie, one needs to prepare a file with `.abm' extension, describing the 30 | Unicode ranges of alphabet set of the trie. The ABM defines a set of 31 | vectors that map Unicode characters into a continuous range of integers. 32 | The mapped integers will be used as internal alphabet for the trie. 33 | Such mapping can improve the space allocation within the trie data, regardless 34 | of non-continuity of the character set being used, as the mapped range is 35 | always continuous. 36 | .P 37 | The ABM file is a plain text file, with each line listing a range of 32-bit 38 | Unicodes to be added to the alphabet set, in the format: 39 | .IP 40 | [0xSSSS,0xTTTT] 41 | .P 42 | where `0xSSSS' and `0xTTTT' are hexadecimal values of starting and ending 43 | character code for the range, respectively. 44 | .P 45 | For example, for a dictionary that contains only English words witout any 46 | punctuations, one may prepare `\fItrie\fP.abm' as: 47 | .IP 48 | [0x0041,0x005a] 49 | .br 50 | [0x0061,0x007a] 51 | .P 52 | The first line lists the ASCII codes for A-Z, and the second for a-z. 53 | .P 54 | No more than 255 alphabets are allowed in a trie. 55 | .P 56 | The created `.tri' file will incorporate the ABM data. So, the `.abm' file 57 | is not required after the first creation, and will be ignored. 58 | .SH COMMANDS 59 | Available commands are: 60 | .TP 61 | \fBadd\fP \fIword data\fP ... 62 | Add \fIword\fP to trie, associated with integer \fIdata\fP. Arbitrary number of 63 | words-data pairs can be given. Two arguments will be read at a time, the first 64 | will be treated as \fIword\fP, and the second as \fIdata\fP. 65 | .TP 66 | \fBadd-list\fP [ \fIoptions\fP ] \fIlist-file\fP 67 | Add words with associated data listed in \fIlist-file\fP to trie. The 68 | \fIlist-file\fP must be a text file listing one word per line. The associated 69 | data can be put after the word in the same line, separated with tab (`\\t') 70 | character. If the data field is omitted, a default value (\-1) will be used 71 | instead. 72 | .TP 73 | .B " " 74 | \fIOptions\fP are available for this command: 75 | .RS 76 | .TP 77 | .B \-e, \-\-encoding \fIenc\fP 78 | Specify character encoding of the \fIlist-file\fP contents, such as `UTF-8'. 79 | If omitted, current locale codeset is assumed. 80 | .RE 81 | .TP 82 | \fBdelete\fP \fIword\fP ... 83 | Delete \fIword\fP from trie. Arbitrary number of words to delete can be given. 84 | .TP 85 | \fBdelete-list\fP [ \fIoptions\fP ] \fIlist-file\fP 86 | Delete words listed in \fIlist-file\fP from trie. The \fIlist-file\fP must be 87 | a text file listing one word per line. 88 | .TP 89 | .B " " 90 | \fIOptions\fP are available for this command: 91 | .RS 92 | .TP 93 | .B \-e, \-\-encoding \fIenc\fP 94 | Specify character encoding of the \fIlist-file\fP contents, such as `UTF-8'. 95 | If omitted, current locale codeset is assumed. 96 | .RE 97 | .TP 98 | \fBquery\fP \fIword\fP 99 | Search for \fIword\fP in trie. If \fIword\fP exists, its associated data 100 | is printed to standard output. Otherwise, error message is printed to standard 101 | error, with nothing printed to standard output. 102 | .TP 103 | \fBlist\fP 104 | List all words in trie to standard output. The output lists one word-data pair 105 | per line, separated with tab (`\\t') character, the format appropriate for 106 | being \fIlist-file\fP for the \fBadd-list\fP command. 107 | .SH OPTIONS 108 | This program follows the usual GNU command line syntax, with long 109 | options starting with two dashes (`\-\-'). 110 | A summary of options is included below. 111 | .TP 112 | .B \-p, \-\-path \fIdir\fP 113 | Set trie directory to \fIdir\fP [default=`.'] 114 | .TP 115 | .B \-h, \-\-help 116 | Show summary of options. 117 | .TP 118 | .B \-V, \-\-version 119 | Show version of program. 120 | .SH AUTHOR 121 | libdatrie was written by Theppitak Karoonboonyanan. 122 | .PP 123 | This manual page was written by Theppitak Karoonboonyanan . 124 | -------------------------------------------------------------------------------- /tests/test_byte_list.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2018 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_byte_list.c - Test byte trie enumeration 23 | * Created: 2018-11-20 24 | * Author: Theppitak Karoonboonyanan 25 | * Based on test case in issue #9 26 | * https://github.com/tlwg/libdatrie/issues/9 27 | */ 28 | 29 | #include 30 | #include "utils.h" 31 | #include 32 | #include 33 | 34 | typedef struct _DictEntry DictEntry; 35 | struct _DictEntry { 36 | AlphaChar key[4]; 37 | TrieData data; 38 | int is_checked; 39 | }; 40 | 41 | #define N_ELM(v) (sizeof(v)/sizeof(v[0])) 42 | 43 | /* Dictionary source */ 44 | static DictEntry Source[] = { 45 | { { '1', '2', 0 }, 1, 0 }, 46 | { { '1', '2', '3', 0 }, 2, 0 }, 47 | }; 48 | 49 | static void 50 | dump_key_data (const AlphaChar *key, TrieData data) 51 | { 52 | const AlphaChar *p; 53 | 54 | printf ("["); 55 | for (p = key; *p; ++p) { 56 | if (p != key) { 57 | printf (", "); 58 | } 59 | printf ("%04x", *p); 60 | } 61 | printf ("] : %d\n", data); 62 | } 63 | 64 | static void 65 | dump_entry (const TrieIterator *iter) 66 | { 67 | AlphaChar *key = trie_iterator_get_key (iter); 68 | dump_key_data (key, trie_iterator_get_data (iter)); 69 | free (key); 70 | } 71 | 72 | /* 73 | * Check if the trie entry referenced by iter match any Source[] element 74 | * and mark the matched element as checked. 75 | * Return: 1 if matched, 0 otherwise 76 | */ 77 | static int 78 | validate_entry (const TrieIterator *iter) 79 | { 80 | AlphaChar *key = trie_iterator_get_key (iter); 81 | TrieData data = trie_iterator_get_data (iter); 82 | int i; 83 | 84 | for (i = 0; i < N_ELM (Source); i++) { 85 | if (alpha_char_strcmp (Source[i].key, key) == 0 86 | && Source[i].data == data) 87 | { 88 | Source[i].is_checked = 1; 89 | free (key); 90 | return 1; 91 | } 92 | } 93 | free (key); 94 | return 0; 95 | } 96 | 97 | /* 98 | * Check if all Source[] elements are checked and reported unchecked one. 99 | * Return: 1 if all are checked, 0 otherwise. 100 | */ 101 | static int 102 | is_all_checked() 103 | { 104 | int i; 105 | int ret = 1; 106 | 107 | for (i = 0; i < N_ELM (Source); i++) { 108 | if (!Source[i].is_checked) { 109 | printf ("Not visited Source entry: "); 110 | dump_key_data (Source[i].key, Source[i].data); 111 | ret = 0; 112 | } 113 | } 114 | 115 | return ret; 116 | } 117 | 118 | int 119 | main (void) 120 | { 121 | AlphaMap *alpha_map; 122 | Trie *test_trie; 123 | int i; 124 | TrieState *root; 125 | TrieIterator *iter; 126 | int ret = 0; 127 | 128 | msg_step ("Preparing alpha map"); 129 | alpha_map = alpha_map_new (); 130 | if (!alpha_map) { 131 | printf ("Fail to allocate alpha map\n"); 132 | goto err_alpha_map_not_created; 133 | } 134 | if (alpha_map_add_range (alpha_map, 0x00, 0xff) != 0) { 135 | printf ("Fail to add full alpha map range\n"); 136 | goto err_alpha_map_created; 137 | } 138 | 139 | msg_step ("Preparing trie"); 140 | test_trie = trie_new (alpha_map); 141 | alpha_map_free (alpha_map); 142 | if (!test_trie) { 143 | printf ("Fail to create test trie\n"); 144 | goto err_alpha_map_created; 145 | } 146 | 147 | msg_step ("Storing entries to test trie"); 148 | for (i = 0; i < N_ELM (Source); i++) { 149 | if (!trie_store (test_trie, Source[i].key, Source[i].data)) { 150 | printf ("Fail to store entry %d to test trie:\n", i); 151 | dump_key_data (Source[i].key, Source[i].data); 152 | goto err_trie_created; 153 | } 154 | } 155 | 156 | msg_step ("Iterating trie"); 157 | root = trie_root (test_trie); 158 | iter = trie_iterator_new (root); 159 | while (trie_iterator_next (iter)) { 160 | if (!validate_entry (iter)) { 161 | printf ("Fail to validate trie entry:\n"); 162 | dump_entry (iter); 163 | ret = 1; 164 | } 165 | } 166 | if (!is_all_checked()) { 167 | ret = 1; 168 | } 169 | trie_iterator_free (iter); 170 | trie_state_free (root); 171 | 172 | msg_step ("Freeing test trie"); 173 | trie_free (test_trie); 174 | return ret; 175 | 176 | err_trie_created: 177 | trie_free (test_trie); 178 | err_alpha_map_created: 179 | alpha_map_free (alpha_map); 180 | err_alpha_map_not_created: 181 | return 1; 182 | } 183 | 184 | /* 185 | vi:ts=4:ai:expandtab 186 | */ 187 | -------------------------------------------------------------------------------- /tests/utils.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * utils.c - Utility functions for datrie test cases 23 | * Created: 2013-10-16 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | 30 | /*---------------------* 31 | * Debugging helpers * 32 | *---------------------*/ 33 | void 34 | msg_step (const char *msg) 35 | { 36 | printf ("=> %s...\n", msg); 37 | } 38 | 39 | /*-------------------------* 40 | * Trie creation helpers * 41 | *-------------------------*/ 42 | static AlphaMap * 43 | en_alpha_map_new (void) 44 | { 45 | AlphaMap *en_map; 46 | 47 | en_map = alpha_map_new (); 48 | if (!en_map) 49 | goto err_map_not_created; 50 | 51 | if (alpha_map_add_range (en_map, 0x0061, 0x007a) != 0) 52 | goto err_map_created; 53 | 54 | return en_map; 55 | 56 | err_map_created: 57 | alpha_map_free (en_map); 58 | err_map_not_created: 59 | return NULL; 60 | } 61 | 62 | Trie * 63 | en_trie_new (void) 64 | { 65 | AlphaMap *en_map; 66 | Trie *en_trie; 67 | 68 | en_map = en_alpha_map_new (); 69 | if (!en_map) 70 | goto err_map_not_created; 71 | 72 | en_trie = trie_new (en_map); 73 | if (!en_trie) 74 | goto err_map_created; 75 | 76 | alpha_map_free (en_map); 77 | return en_trie; 78 | 79 | err_map_created: 80 | alpha_map_free (en_map); 81 | err_map_not_created: 82 | return NULL; 83 | } 84 | 85 | /*---------------------------* 86 | * Dict source for testing * 87 | *---------------------------*/ 88 | DictRec dict_src[] = { 89 | {(AlphaChar *)L"a", TRIE_DATA_UNREAD}, 90 | {(AlphaChar *)L"abacus", TRIE_DATA_UNREAD}, 91 | {(AlphaChar *)L"abandon", TRIE_DATA_UNREAD}, 92 | {(AlphaChar *)L"accident", TRIE_DATA_UNREAD}, 93 | {(AlphaChar *)L"accredit", TRIE_DATA_UNREAD}, 94 | {(AlphaChar *)L"algorithm", TRIE_DATA_UNREAD}, 95 | {(AlphaChar *)L"ammonia", TRIE_DATA_UNREAD}, 96 | {(AlphaChar *)L"angel", TRIE_DATA_UNREAD}, 97 | {(AlphaChar *)L"angle", TRIE_DATA_UNREAD}, 98 | {(AlphaChar *)L"azure", TRIE_DATA_UNREAD}, 99 | {(AlphaChar *)L"bat", TRIE_DATA_UNREAD}, 100 | {(AlphaChar *)L"bet", TRIE_DATA_UNREAD}, 101 | {(AlphaChar *)L"best", TRIE_DATA_UNREAD}, 102 | {(AlphaChar *)L"home", TRIE_DATA_UNREAD}, 103 | {(AlphaChar *)L"house", TRIE_DATA_UNREAD}, 104 | {(AlphaChar *)L"hut", TRIE_DATA_UNREAD}, 105 | {(AlphaChar *)L"king", TRIE_DATA_UNREAD}, 106 | {(AlphaChar *)L"kite", TRIE_DATA_UNREAD}, 107 | {(AlphaChar *)L"name", TRIE_DATA_UNREAD}, 108 | {(AlphaChar *)L"net", TRIE_DATA_UNREAD}, 109 | {(AlphaChar *)L"network", TRIE_DATA_UNREAD}, 110 | {(AlphaChar *)L"nut", TRIE_DATA_UNREAD}, 111 | {(AlphaChar *)L"nutshell", TRIE_DATA_UNREAD}, 112 | {(AlphaChar *)L"quality", TRIE_DATA_UNREAD}, 113 | {(AlphaChar *)L"quantum", TRIE_DATA_UNREAD}, 114 | {(AlphaChar *)L"quantity", TRIE_DATA_UNREAD}, 115 | {(AlphaChar *)L"quartz", TRIE_DATA_UNREAD}, 116 | {(AlphaChar *)L"quick", TRIE_DATA_UNREAD}, 117 | {(AlphaChar *)L"quiz", TRIE_DATA_UNREAD}, 118 | {(AlphaChar *)L"run", TRIE_DATA_UNREAD}, 119 | {(AlphaChar *)L"tape", TRIE_DATA_UNREAD}, 120 | {(AlphaChar *)L"test", TRIE_DATA_UNREAD}, 121 | {(AlphaChar *)L"what", TRIE_DATA_UNREAD}, 122 | {(AlphaChar *)L"when", TRIE_DATA_UNREAD}, 123 | {(AlphaChar *)L"where", TRIE_DATA_UNREAD}, 124 | {(AlphaChar *)L"which", TRIE_DATA_UNREAD}, 125 | {(AlphaChar *)L"who", TRIE_DATA_UNREAD}, 126 | {(AlphaChar *)L"why", TRIE_DATA_UNREAD}, 127 | {(AlphaChar *)L"zebra", TRIE_DATA_UNREAD}, 128 | {(AlphaChar *)NULL, TRIE_DATA_ERROR}, 129 | }; 130 | 131 | int 132 | dict_src_n_entries (void) 133 | { 134 | return sizeof (dict_src) / sizeof (dict_src[0]) - 1; 135 | } 136 | 137 | TrieData 138 | dict_src_get_data (const AlphaChar *key) 139 | { 140 | const DictRec *dict_p; 141 | 142 | for (dict_p = dict_src; dict_p->key; dict_p++) { 143 | if (alpha_char_strcmp (dict_p->key, key) == 0) { 144 | return dict_p->data; 145 | } 146 | } 147 | 148 | return TRIE_DATA_ERROR; 149 | } 150 | 151 | int 152 | dict_src_set_data (const AlphaChar *key, TrieData data) 153 | { 154 | DictRec *dict_p; 155 | 156 | for (dict_p = dict_src; dict_p->key; dict_p++) { 157 | if (alpha_char_strcmp (dict_p->key, key) == 0) { 158 | dict_p->data = data; 159 | return 0; 160 | } 161 | } 162 | 163 | return -1; 164 | } 165 | 166 | /* 167 | vi:ts=4:ai:expandtab 168 | */ 169 | -------------------------------------------------------------------------------- /NEWS: -------------------------------------------------------------------------------- 1 | libdatrie 2 | 3 | 0.2.14 (2025-11-25) 4 | ====== 5 | - No more dependency on autoconf-archive when building from Git. 6 | - Check and link to locale_charset() available in libiconv 1.17. 7 | - Issue #25, PR #27, reported and fixed by John Hein. 8 | - Problem fixes for parallel build. 9 | - Debian #1105545, "make --shuffle=reverse", reported by Lucas Nussbaum. 10 | - Issue #28, writing to the same file, reported by 11 | @enter-github-username@github.com. 12 | - Catch more malloc() failures caught by Coverity Scan 13 | - Issue #20, reported by Peng Wu. 14 | - Updated build scripts to latest toolchain. 15 | - Minor documentation fix. 16 | - Minor error handling improvement in tests. 17 | 18 | 0.2.13 (2021-01-29) 19 | ====== 20 | - Fix wrong key listing in byte trie 21 | (Issue #9, Thanks @legale for the report.) 22 | - Fix cross-compiling issue caused by AC_FUNC_MALLOC 23 | (Issue #11, Thanks Vanessa McHale for the report.) 24 | - Fix isspace() arg problem on NetBSD. 25 | (Personal mail, Thanks Sean for the report; 26 | PR #8, Thanks OBATA Akio for an individual pull request.) 27 | - Fix some documentations. 28 | - Really use TRIE_CHAR_TERM in TrieChar string termination. 29 | Changing TRIE_CHAR_TERM definition now won't break the code. 30 | - Fix Windows build issue by avoiding include. 31 | (Partially addressing PR #15, Thanks @fanc999 for first raising this.) 32 | - [New APIs] Add serialization of the trie into memory buffer. 33 | (PR #12, Thanks KOLANICH for the contribution.) 34 | 35 | 0.2.12 (2018-06-19) 36 | ====== 37 | - More C90 (ANSI C) compliance. 38 | (Thanks Peter Moulder for the patch) 39 | - Prevent some compiling conflicts with other sources. 40 | (Thanks Peter Moulder for the patch) 41 | - Fix miscellaneous compiler warnings. 42 | - Prevent trimming on extremely long dictionary path names. 43 | 44 | 0.2.11 (2018-04-23) 45 | ====== 46 | - Detect iconv() error more correctly in trietool. 47 | (Thanks Daniel Macks for the report on Issue #3) 48 | - Clarify package description that search time is O(m), where m is 49 | key length, not O(1), while still claiming that it's independent 50 | of database size. 51 | (Thanks @flackbash for the report on Issue #4) 52 | - Fix trie_state_get_data() on a prefix key. 53 | (Thanks Filip Pytloun from the pytries project for the initial patch) 54 | - Fix reported segfault on full-range alpha map. 55 | (Thanks Xiao Wang for the report on Issue #6, 56 | and @nevermatch for the analysis.) 57 | 58 | 0.2.10 (2015-10-20) 59 | ====== 60 | - Correctly check doxygen version on configure. 61 | (Thanks Petr Gajdos for the patch.) 62 | - Optimization on AlphaMap mapping. 63 | (contributing to 0.2% less run time for LibThai word breaking) 64 | 65 | 0.2.9 (2015-05-03) 66 | ===== 67 | - Fix binary file opening on Windows 68 | (Thanks phongphan.p for the report and initial patch.) 69 | - Fix infinite loop on empty trie iteration. 70 | (Thanks Sergei Lebedev for the report and analysis.) 71 | - Micro-optimization with LIKELY/UNLIKELY hints. 72 | (contributing to 4.76% faster dictionary loading, 1.95% faster 73 | word breaking for LibThai) 74 | - Improved error handling 75 | - 'trietool-0.2' utility is renamed to just 'trietool' 76 | - Improved documentation 77 | (Thanks edgehogapp for the suggestion.) 78 | - No timestamp on Doxygen-generated doc 79 | (Thanks Debian Reproducible) 80 | 81 | 0.2.8 (2014-01-10) 82 | ===== 83 | - Fix compiler warnings in test suites. 84 | - Fix edge-case error on alphabet set of size 255. 85 | (Thanks Naoki Youshinaga for the report, test case, and analysis.) 86 | - Fail trie operations on non-alphabet inputs, rather than silently allowing 87 | them to sneak in as false keys. 88 | (Thanks Naoki Youshinaga for the suggestion.) 89 | - Improved documentation. 90 | 91 | 0.2.7.1 (2013-10-22) 92 | ======= 93 | - Bump library versioning to reflect API addition. 94 | (Change missing in previous release) 95 | 96 | 0.2.7 (2013-10-21) 97 | ===== 98 | - Fix portability issue with non-GCC compilers. 99 | [Thanks Gabi Daver for the report and fix (via Mikhail Korobov).] 100 | - Fix compiler warnings. 101 | - New utility API for comparing AlphaChar strings. 102 | - Add test suites. 103 | - Update doxygen doc generation. 104 | 105 | 0.2.6 (2013-01-23) 106 | ===== 107 | - New API trie_state_walkable_chars() for breadth-first traversal. 108 | - New class TrieIterator for callback-free enumeration. 109 | - Improved performance on key enumeration. 110 | - Improved AlphaMap range merging. 111 | - Bug fixes. 112 | [Many thanks to Mikhail Korobov for improvements in this version.] 113 | 114 | 0.2.5 (2011-11-04) 115 | ===== 116 | - Fix missing 'extern "C"' in header file. [Patch from Aurimas Černius] 117 | - Minor documentation fix. 118 | 119 | 0.2.4 (2010-06-30) 120 | ===== 121 | - Close file on saving trie. [Bug report from Xu Jiandong] 122 | - Add trie_store_if_absent() API which fails on adding duplicated key. 123 | This is useful for preventing race condition in multi-thread applications. 124 | [Suggestion from Dan Searle] 125 | - Add trie_fread() and trie_fwrite() APIs for reading/writing trie data in 126 | an open file, allowing trie to be embeded as part of a bigger file. 127 | [Suggestion from NIIBE Yutaka] 128 | 129 | 0.2.3 (2010-02-27) 130 | ===== 131 | - More robustness against corrupted trie files. 132 | - License clarification in individual source files. 133 | 134 | 0.2.2 (2009-04-29) 135 | ===== 136 | - Support building with linkers without symbol versioning supports, 137 | including Mac, Cygwin, MinGW. 138 | - Support other iconv implementations than that's in glibc, for Mac and MinGW. 139 | 140 | 0.2.1 (2009-04-05) 141 | ===== 142 | - Fix errors in documentation 143 | - Symbol versioning to ease upgrade across SONAME 144 | - Minor cleanups 145 | 146 | 0.2.0 (2009-03-24) 147 | ===== 148 | - New APIs for performance: trie_state_copy(), trie_state_is_single() 149 | - Clean-ups 150 | 151 | 0.1.99.2 (2008-12-15) 152 | ======== 153 | - More robust handling of alphabet ranges 154 | - Allow co-existence with libdatrie0 155 | 156 | 0.1.99.1 (2008-12-12) 157 | ======== 158 | - Breaking ABI with libdatrie0 159 | - More capacity with 32-bit node index 160 | - Adjusted API for non-file trie usage 161 | - All data in one file, no more *.br and *.tl split 162 | - Drop SBTrie wrapper; all features are merged into Trie 163 | - Domain characters are now Unicode 164 | 165 | 0.1.3 (2008-01-28) 166 | ===== 167 | - Fix memory bug which can crash on some platforms, reportedly win32. 168 | (shepmaster) 169 | - Fix symbols exporting, so it builds on Mac. (Vee Satayamas) 170 | - Remove excessive documentation for private API's. 171 | - Add the SBM file format documentation frequently asked for 172 | 173 | 0.1.2 (2007-08-25) 174 | ===== 175 | - Limited symbols export, to avoid name clashing 176 | - Improved error handling for edge cases 177 | - Fix crashes 178 | 179 | 0.1.1 (2006-10-12) 180 | ===== 181 | - Fix compiler warnings 182 | - Man page for trietool 183 | 184 | 0.1.0 (2006-09-18) 185 | ===== 186 | - Initial release 187 | - BASE-TAIL Double-array trie structure 188 | - Single-byte character map support 189 | 190 | -------------------------------------------------------------------------------- /tests/test_store-retrieve.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2013 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * test_store-retrieve.c - Test for datrie store/retrieve operations 23 | * Created: 2013-10-16 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include "utils.h" 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | int 35 | main (void) 36 | { 37 | Trie *test_trie; 38 | DictRec *dict_p; 39 | TrieData trie_data; 40 | Bool is_failed; 41 | int n_entries, n_dels, i; 42 | TrieState *trie_root_state; 43 | TrieIterator *trie_it; 44 | 45 | msg_step ("Preparing trie"); 46 | test_trie = en_trie_new (); 47 | if (!test_trie) { 48 | fprintf (stderr, "Fail to create test trie\n"); 49 | goto err_trie_not_created; 50 | } 51 | 52 | /* store */ 53 | msg_step ("Adding data to trie"); 54 | for (dict_p = dict_src; dict_p->key; dict_p++) { 55 | if (!trie_store (test_trie, dict_p->key, dict_p->data)) { 56 | printf ("Failed to add key '%ls', data %d.\n", 57 | (wchar_t *)dict_p->key, dict_p->data); 58 | goto err_trie_created; 59 | } 60 | } 61 | 62 | /* retrieve */ 63 | msg_step ("Retrieving data from trie"); 64 | is_failed = FALSE; 65 | for (dict_p = dict_src; dict_p->key; dict_p++) { 66 | if (!trie_retrieve (test_trie, dict_p->key, &trie_data)) { 67 | printf ("Failed to retrieve key '%ls'.\n", (wchar_t *)dict_p->key); 68 | is_failed = TRUE; 69 | } 70 | if (trie_data != dict_p->data) { 71 | printf ("Wrong data for key '%ls'; expected %d, got %d.\n", 72 | (wchar_t *)dict_p->key, dict_p->data, trie_data); 73 | is_failed = TRUE; 74 | } 75 | } 76 | if (is_failed) { 77 | printf ("Trie store/retrieval test failed.\n"); 78 | goto err_trie_created; 79 | } 80 | 81 | /* delete */ 82 | msg_step ("Deleting some entries from trie"); 83 | n_entries = dict_src_n_entries (); 84 | srand (time (NULL)); 85 | for (n_dels = n_entries/3 + 1; n_dels > 0; n_dels--) { 86 | /* pick an undeleted entry */ 87 | do { 88 | i = rand () % n_entries; 89 | } while (TRIE_DATA_READ == dict_src[i].data); 90 | 91 | printf ("Deleting '%ls'\n", (wchar_t *)dict_src[i].key); 92 | if (!trie_delete (test_trie, dict_src[i].key)) { 93 | printf ("Failed to delete '%ls'\n", (wchar_t *)dict_src[i].key); 94 | is_failed = TRUE; 95 | } 96 | dict_src[i].data = TRIE_DATA_READ; 97 | } 98 | if (is_failed) { 99 | printf ("Trie deletion test failed.\n"); 100 | goto err_trie_created; 101 | } 102 | 103 | /* retrieve */ 104 | msg_step ("Retrieving data from trie again after deletions"); 105 | for (dict_p = dict_src; dict_p->key; dict_p++) { 106 | /* skip deleted entries */ 107 | if (TRIE_DATA_READ == dict_p->data) 108 | continue; 109 | 110 | if (!trie_retrieve (test_trie, dict_p->key, &trie_data)) { 111 | printf ("Failed to retrieve key '%ls'.\n", (wchar_t *)dict_p->key); 112 | is_failed = TRUE; 113 | } 114 | if (trie_data != dict_p->data) { 115 | printf ("Wrong data for key '%ls'; expected %d, got %d.\n", 116 | (wchar_t *)dict_p->key, dict_p->data, trie_data); 117 | is_failed = TRUE; 118 | } 119 | } 120 | if (is_failed) { 121 | printf ("Trie retrival-after-deletion test failed.\n"); 122 | goto err_trie_created; 123 | } 124 | 125 | /* enumerate & check */ 126 | msg_step ("Iterating trie contents after deletions"); 127 | trie_root_state = trie_root (test_trie); 128 | if (!trie_root_state) { 129 | printf ("Failed to get trie root state\n"); 130 | goto err_trie_created; 131 | } 132 | trie_it = trie_iterator_new (trie_root_state); 133 | if (!trie_it) { 134 | printf ("Failed to get trie iterator\n"); 135 | goto err_trie_root_created; 136 | } 137 | 138 | while (trie_iterator_next (trie_it)) { 139 | AlphaChar *key; 140 | TrieData key_data, src_data; 141 | 142 | key = trie_iterator_get_key (trie_it); 143 | if (!key) { 144 | printf ("Failed to get key from trie iterator\n"); 145 | is_failed = TRUE; 146 | continue; 147 | } 148 | key_data = trie_iterator_get_data (trie_it); 149 | if (TRIE_DATA_ERROR == key_data) { 150 | printf ("Failed to get data from trie iterator for key '%ls'\n", 151 | (wchar_t *)key); 152 | is_failed = TRUE; 153 | } 154 | /* mark entries found in trie */ 155 | src_data = dict_src_get_data (key); 156 | if (TRIE_DATA_ERROR == src_data) { 157 | printf ("Extra entry in trie: key '%ls', data %d.\n", 158 | (wchar_t *)key, key_data); 159 | is_failed = TRUE; 160 | } else if (src_data != key_data) { 161 | printf ("Data mismatch for: key '%ls', expected %d, got %d.\n", 162 | (wchar_t *)key, src_data, key_data); 163 | is_failed = TRUE; 164 | } else { 165 | dict_src_set_data (key, TRIE_DATA_READ); 166 | } 167 | 168 | free (key); 169 | } 170 | 171 | /* check for unmarked entries, (i.e. missed in trie) */ 172 | for (dict_p = dict_src; dict_p->key; dict_p++) { 173 | if (dict_p->data != TRIE_DATA_READ) { 174 | printf ("Entry missed in trie: key '%ls', data %d.\n", 175 | (wchar_t *)dict_p->key, dict_p->data); 176 | is_failed = TRUE; 177 | } 178 | } 179 | 180 | if (is_failed) { 181 | printf ("Errors found in trie iteration after deletions.\n"); 182 | goto err_trie_it_created; 183 | } 184 | 185 | trie_iterator_free (trie_it); 186 | trie_state_free (trie_root_state); 187 | trie_free (test_trie); 188 | return 0; 189 | 190 | err_trie_it_created: 191 | trie_iterator_free (trie_it); 192 | err_trie_root_created: 193 | trie_state_free (trie_root_state); 194 | err_trie_created: 195 | trie_free (test_trie); 196 | err_trie_not_created: 197 | return 1; 198 | } 199 | 200 | /* 201 | vi:ts=4:ai:expandtab 202 | */ 203 | -------------------------------------------------------------------------------- /README.migration: -------------------------------------------------------------------------------- 1 | MIGRATION FROM 0.1.X TO 0.2.X 2 | 3 | 0.2.x breaks 0.1.x interoperability in many ways, to allow more use cases, and 4 | to provide more storage capacity. 5 | 6 | 1. Binary Data Changes 7 | 8 | 1.1 All Trie Data in Single File 9 | 10 | No more splitting of a trie into '{trie-name}.sbm', '{trie-name}.br' and 11 | '{trie-name}.tl'. All parts are now stored in a single file, '{trie-name}.tri'. 12 | 13 | Note, however, that a '{trie-name}.abm' (a renamed version of '{trie-name}.sbm' 14 | after Unicode support) is still needed on first creation. But once created, 15 | the '{trie-name}.tri' will incorporate the alphabet map data, and no 16 | '{trie-name}.abm' is required in later uses. It will even be ignored if exists. 17 | 18 | 1.2 32-Bit Node Index 19 | 20 | To accommodate larger word lists, trie node indices are now 32 bits, instead of 21 | 16 bits. This means 32,767 times capacity compared to the old format. 22 | Therefore, the data size are doubled in general when migrating from old format, 23 | but it can now hold exponentially more entries. 24 | 25 | In addition, the tail block lengths are now 16 bits, instead of 8 bits, making 26 | it possible to store longer suffixes, for dictionaries of extremely long words. 27 | 28 | 1.3 No Backward Compatibility 29 | 30 | For simplicity of the code, it was decided not to read/write old format files. 31 | If you still prefer using the old format, just stay with the old version. If 32 | you like to gain more support from the new version, you can migrate your old 33 | data by first dumping your dictionary with 0.1.x trietool into text file and 34 | then creating the new dictionary with the dumped word list. Or if you already 35 | have the word list, that makes things a lot easier. Just create the dictionary 36 | with the new trietool. 37 | 38 | Data Migration Steps: 39 | 40 | a. If you have the word list source, just skip to next step. Otherwise, you 41 | can dump the old data with 0.1.x trietool: 42 | 43 | $ trietool {trie-name} list > words.lst 44 | 45 | b. Prepare '{trie-name}.abm', listing ranges of characters used in the word 46 | list, in terms of Unicode values. For example, for an English and Thai 47 | dictionary: 48 | 49 | [0x0041,0x005a] 50 | [0x0061,0x007a] 51 | [0x0e01,0x0e3a] 52 | [0x0e40,0x0e4e] 53 | 54 | c. Generate new trie with 0.2.x trietool-0.2. For example: 55 | 56 | $ trietool-0.2 {trie-name} add-list -e TIS-620 words.lst 57 | 58 | In this example, the '-e TIS-620' indicates that the 'words.lst' file 59 | contains TIS-620 encoded text, which is most likely for word lists dumped 60 | from the old trie with 8-bit Thai character code as the key encoding. 61 | Replace it with your old encoding as necessary, such as ISO-8859-1 or the 62 | like. If '-e' option is omitted, current locale encoding is assumed. 63 | See trietool-0.2 man page for details. 64 | 65 | 2. API Changes 66 | 67 | 2.1 Non-File Trie Usage 68 | 69 | In datrie 0.1.x, every trie was associated with a set of files. Now, this is 70 | not only reduced to a single file, but zero file is also possible. That is, a 71 | new trie can be created in memory, added words, removed words, queried words, 72 | and then disposed without writing data to any file. Meanwhile, saving to file 73 | is still possible. 74 | 75 | Scenario 1: Loading trie from file, using it read-only. 76 | 1a. Open trie with trie_new_from_file(path). 77 | 1b. Use it. 78 | 1c. On exit: 79 | - Close it with trie_free(). 80 | 81 | Scenario 2: Loading trie from file, updating file when finished. 82 | 2a. Open trie with trie_new_from_file(path). 83 | 2b. Use/update it. 84 | 2c. On exit: 85 | - If trie_is_dirty(), then trie_save(). 86 | - Close it with trie_free(). 87 | 88 | Scenario 3: Create a new trie, saving it when finished. 89 | 3a. Prepare an alphabet map: 90 | - Create new alphabet map with alpha_map_new(). 91 | - Add ranges with alpha_map_add_range(). 92 | 3b. Create new trie with trie_new(alpha_map). 93 | 3c. Free the alphabet map with alpha_map_free(). 94 | 3d. Use/update the trie. 95 | 3e. On exit: 96 | - If trie_is_dirty(), then trie_save(). 97 | - Close the trie with trie_free(). 98 | 99 | Scenario 4: Create temporary trie, disposing it when finished. 100 | 4a. Prepare an alphabet map: 101 | - Create new alphabet map with alpha_map_new(). 102 | - Add ranges with alpha_map_add_range(). 103 | 4b. Create new trie with trie_new(alpha_map). 104 | 4c. Free the alphabet map with alpha_map_free(). 105 | 4d. Use/update the trie. 106 | 4e. On exit: 107 | - Close the trie with trie_free(). 108 | 109 | 2.2 No More SBTrie 110 | 111 | In datrie 0.1.x, SBTrie provided a wrapper to Trie implementation, converting 112 | between real character codes and trie internal codes. This was for compactness, 113 | as continuous character code range can cause more compact sparse table 114 | allocation, while the real alphabet set needs not be continuous. However, in 115 | datrie 0.2.x, this mapping feature has been merged into Trie class, to reduce 116 | call layers. So, there is no SBTrie any more. You can call Trie directly in the 117 | same way you called SBTrie in 0.1.x. 118 | 119 | 2.3 Characters are Now Unicode 120 | 121 | datrie was previously planned to support multiple kinds of character encodings, 122 | with only single-byte encoding as the available implementation for the time 123 | being. 124 | 125 | However, as there have been many requests for Unicode support, it seems to be 126 | the most useful choice, into which all other encodings can be converted. 127 | 128 | Furthermore, as datrie is mostly used in program's critical path, having too 129 | many layers can contribute to being a bottleneck. So, only Unicode is accepted 130 | in this version. It's now the application's duty to convert its keys into 131 | Unicode before passing them to datrie. This should also allow any kind of 132 | possible caching. 133 | 134 | 2.4 New Public APIs for Alphabet Map 135 | 136 | As AlphaMap (alphabet map) is now necessary for creating a new empty trie, the 137 | APIs for manipulating this data is now exposed to the public scope. See 138 | for the details. 139 | 140 | 2.5 Extensions to TrieState 141 | 142 | trie_state_copy() 143 | 144 | As part of performance profiling, allocating and freeing TrieState is found 145 | to eat up CPU time at some degree. So, reusing existing TrieState where 146 | possible does help. This function is added for copying TrieState data, as a 147 | better alternative than trie_state_clone(). 148 | 149 | trie_state_is_single() 150 | 151 | Sometimes, checking if a TrieState is a leaf state is too expensive for 152 | program's critical path. It needs to check both whether the state is in a 153 | non-branching path, that is, whether it is in a suffix node, and whether it 154 | can be walked by a terminator. When a program only needs to check for the 155 | former fact and not the latter, this method is at disposal. 156 | 157 | 3. Changes to TrieTool 158 | 159 | 3.1 Renaming 160 | 161 | To allow co-existence with 0.1.x trietool, 0.2.x trietool is named 162 | trietool-0.2. 163 | 164 | 3.2 '*.abm' Instead of '*.sbm' 165 | 166 | As SBTrie has been eliminated in datrie 0.2.x, the corresponding '*.sbm' 167 | (single-byte map) input file is also obsoleted. It is now renamed to '*.abm' 168 | (alphabet map). Its format is also redefined to be Unicode-based. All alphabet 169 | character ranges are defined in Unicode. 170 | 171 | Besides, the '*.abm' file is required only once at trie creation time. It is 172 | not needed at deployment, as the alphabet map is already included in the single 173 | trie file. 174 | 175 | 3.3 Encoding Conversion Support 176 | 177 | As datrie is now Unicode-based, conversion from other encodings can be useful. 178 | This is possible for word list operations, namely add-list and delete-list, by 179 | the additional '-e {enc}' or '--encoding {enc}' option. This option specifies 180 | the character encoding of the word list file. And trietool-0.2 will convert the 181 | contents to Unicode on-the-fly. 182 | 183 | -------------------------------------------------------------------------------- /datrie/trie.h: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * trie.h - Trie data type and functions 23 | * Created: 2006-08-11 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #ifndef __TRIE_H 28 | #define __TRIE_H 29 | 30 | #include 31 | #include 32 | 33 | #ifdef __cplusplus 34 | extern "C" { 35 | #endif 36 | 37 | /** 38 | * @file trie.h 39 | * @brief Trie data type and functions 40 | * 41 | * Trie is a kind of digital search tree, an efficient indexing method with 42 | * O(1) time complexity for searching. Comparably as efficient as hashing, 43 | * trie also provides flexibility on incremental matching and key spelling 44 | * manipulation. This makes it ideal for lexical analyzers, as well as 45 | * spelling dictionaries. 46 | * 47 | * This library is an implementation of double-array structure for representing 48 | * trie, as proposed by Junichi Aoe. The details of the implementation can be 49 | * found at http://linux.thai.net/~thep/datrie/datrie.html 50 | * 51 | * A Trie is associated with an AlphaMap, a map between actual alphabet 52 | * characters and the raw characters used to walk through trie. 53 | * You can define the alphabet set by adding ranges of character codes 54 | * to it before associating it to a trie. And the keys to be added to the trie 55 | * must comprise only characters in such ranges. Note that the size of the 56 | * alphabet set is limited to 256 (TRIE_CHAR_MAX + 1), and the AlphaMap 57 | * will map the alphabet characters to raw codes in the range 0..255 58 | * (0..TRIE_CHAR_MAX). The alphabet character ranges need not be continuous, 59 | * but the mapped raw codes will be continuous, for the sake of compactness 60 | * of the trie. 61 | * 62 | * A new Trie can be created in memory using trie_new(), saved to file using 63 | * trie_save(), and loaded later with trie_new_from_file(). 64 | * It can even be embeded in another file using trie_fwrite() and read back 65 | * using trie_fread(). 66 | * After use, Trie objects must be freed using trie_free(). 67 | * 68 | * Operations on trie include: 69 | * 70 | * - Add/delete entries with trie_store() and trie_delete() 71 | * - Retrieve entries with trie_retrieve() 72 | * - Walk through trie stepwise with TrieState and its functions 73 | * (trie_root(), trie_state_walk(), trie_state_rewind(), 74 | * trie_state_clone(), trie_state_copy(), 75 | * trie_state_is_walkable(), trie_state_walkable_chars(), 76 | * trie_state_is_single(), trie_state_get_data(). 77 | * And do not forget to free TrieState objects with trie_state_free() 78 | * after use.) 79 | * - Enumerate all keys using trie_enumerate() 80 | * - Iterate entries using TrieIterator and its functions 81 | * (trie_iterator_new(), trie_iterator_next(), trie_iterator_get_key(), 82 | * trie_iterator_get_data(). 83 | * And do not forget to free TrieIterator objects with trie_iterator_free() 84 | * after use.) 85 | */ 86 | 87 | /** 88 | * @brief Trie data type 89 | */ 90 | typedef struct _Trie Trie; 91 | 92 | /** 93 | * @brief Trie enumeration function 94 | * 95 | * @param key : the key of the entry 96 | * @param key_data : the data of the entry 97 | * @param user_data : the user-supplied data on enumerate call 98 | * 99 | * @return TRUE to continue enumeration, FALSE to stop 100 | */ 101 | typedef Bool (*TrieEnumFunc) (const AlphaChar *key, 102 | TrieData key_data, 103 | void *user_data); 104 | 105 | /** 106 | * @brief Trie walking state 107 | */ 108 | typedef struct _TrieState TrieState; 109 | 110 | 111 | /** 112 | * @brief Trie iteration state 113 | */ 114 | typedef struct _TrieIterator TrieIterator; 115 | 116 | /*-----------------------* 117 | * GENERAL FUNCTIONS * 118 | *-----------------------*/ 119 | 120 | Trie * trie_new (const AlphaMap *alpha_map); 121 | 122 | Trie * trie_new_from_file (const char *path); 123 | 124 | Trie * trie_fread (FILE *file); 125 | 126 | void trie_free (Trie *trie); 127 | 128 | size_t trie_get_serialized_size (Trie *trie); 129 | 130 | void trie_serialize (Trie *trie, uint8 *ptr); 131 | 132 | int trie_save (Trie *trie, const char *path); 133 | 134 | int trie_fwrite (Trie *trie, FILE *file); 135 | 136 | Bool trie_is_dirty (const Trie *trie); 137 | 138 | 139 | /*------------------------------* 140 | * GENERAL QUERY OPERATIONS * 141 | *------------------------------*/ 142 | 143 | Bool trie_retrieve (const Trie *trie, 144 | const AlphaChar *key, 145 | TrieData *o_data); 146 | 147 | Bool trie_store (Trie *trie, const AlphaChar *key, TrieData data); 148 | 149 | Bool trie_store_if_absent (Trie *trie, const AlphaChar *key, TrieData data); 150 | 151 | Bool trie_delete (Trie *trie, const AlphaChar *key); 152 | 153 | Bool trie_enumerate (const Trie *trie, 154 | TrieEnumFunc enum_func, 155 | void *user_data); 156 | 157 | 158 | /*-------------------------------* 159 | * STEPWISE QUERY OPERATIONS * 160 | *-------------------------------*/ 161 | 162 | TrieState * trie_root (const Trie *trie); 163 | 164 | 165 | /*----------------* 166 | * TRIE STATE * 167 | *----------------*/ 168 | 169 | TrieState * trie_state_clone (const TrieState *s); 170 | 171 | void trie_state_copy (TrieState *dst, const TrieState *src); 172 | 173 | void trie_state_free (TrieState *s); 174 | 175 | void trie_state_rewind (TrieState *s); 176 | 177 | Bool trie_state_walk (TrieState *s, AlphaChar c); 178 | 179 | Bool trie_state_is_walkable (const TrieState *s, AlphaChar c); 180 | 181 | int trie_state_walkable_chars (const TrieState *s, 182 | AlphaChar chars[], 183 | int chars_nelm); 184 | 185 | /** 186 | * @brief Check for terminal state 187 | * 188 | * @param s : the state to check 189 | * 190 | * @return boolean value indicating whether it is a terminal state 191 | * 192 | * Check if the given state is a terminal state. A terminal state is a trie 193 | * state that terminates a key, and stores a value associated with it. 194 | */ 195 | #define trie_state_is_terminal(s) trie_state_is_walkable((s),0) 196 | 197 | Bool trie_state_is_single (const TrieState *s); 198 | 199 | /** 200 | * @brief Check for leaf state 201 | * 202 | * @param s : the state to check 203 | * 204 | * @return boolean value indicating whether it is a leaf state 205 | * 206 | * Check if the given state is a leaf state. A leaf state is a terminal state 207 | * that has no other branch. 208 | */ 209 | #define trie_state_is_leaf(s) \ 210 | (trie_state_is_single(s) && trie_state_is_terminal(s)) 211 | 212 | TrieData trie_state_get_data (const TrieState *s); 213 | 214 | 215 | /*----------------------* 216 | * ENTRY ITERATION * 217 | *----------------------*/ 218 | 219 | TrieIterator * trie_iterator_new (TrieState *s); 220 | 221 | void trie_iterator_free (TrieIterator *iter); 222 | 223 | Bool trie_iterator_next (TrieIterator *iter); 224 | 225 | AlphaChar * trie_iterator_get_key (const TrieIterator *iter); 226 | 227 | TrieData trie_iterator_get_data (const TrieIterator *iter); 228 | 229 | 230 | #ifdef __cplusplus 231 | } 232 | #endif 233 | 234 | #endif /* __TRIE_H */ 235 | 236 | /* 237 | vi:ts=4:ai:expandtab 238 | */ 239 | -------------------------------------------------------------------------------- /nsis/WritePathStr.nsh: -------------------------------------------------------------------------------- 1 | !ifndef _AddToPath_nsh 2 | !define _AddToPath_nsh 3 | 4 | !verbose 3 5 | !include "WinMessages.NSH" 6 | !verbose 4 7 | 8 | !ifndef WriteEnvStr_RegKey 9 | !ifdef ALL_USERS 10 | !define WriteEnvStr_RegKey \ 11 | 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' 12 | !else 13 | !define WriteEnvStr_RegKey 'HKCU "Environment"' 14 | !endif 15 | !endif 16 | 17 | ; AddToPath - Adds the given dir to the search path. 18 | ; Input - head of the stack 19 | ; Note - Win9x systems requires reboot 20 | 21 | Function AddToPath 22 | Exch $0 23 | Push $1 24 | Push $2 25 | Push $3 26 | 27 | # don't add if the path doesn't exist 28 | IfFileExists "$0\*.*" "" AddToPath_done 29 | 30 | ReadEnvStr $1 PATH 31 | Push "$1;" 32 | Push "$0;" 33 | Call StrStr 34 | Pop $2 35 | StrCmp $2 "" "" AddToPath_done 36 | Push "$1;" 37 | Push "$0\;" 38 | Call StrStr 39 | Pop $2 40 | StrCmp $2 "" "" AddToPath_done 41 | GetFullPathName /SHORT $3 $0 42 | Push "$1;" 43 | Push "$3;" 44 | Call StrStr 45 | Pop $2 46 | StrCmp $2 "" "" AddToPath_done 47 | Push "$1;" 48 | Push "$3\;" 49 | Call StrStr 50 | Pop $2 51 | StrCmp $2 "" "" AddToPath_done 52 | 53 | Call IsNT 54 | Pop $1 55 | StrCmp $1 1 AddToPath_NT 56 | ; Not on NT 57 | StrCpy $1 $WINDIR 2 58 | FileOpen $1 "$1\autoexec.bat" a 59 | FileSeek $1 -1 END 60 | FileReadByte $1 $2 61 | IntCmp $2 26 0 +2 +2 # DOS EOF 62 | FileSeek $1 -1 END # write over EOF 63 | FileWrite $1 "$\r$\nSET PATH=%PATH%;$3$\r$\n" 64 | FileClose $1 65 | SetRebootFlag true 66 | Goto AddToPath_done 67 | 68 | AddToPath_NT: 69 | ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" 70 | StrCmp $1 "" AddToPath_NTdoIt 71 | Push $1 72 | Call Trim 73 | Pop $1 74 | StrCpy $0 "$1;$0" 75 | AddToPath_NTdoIt: 76 | WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $0 77 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 78 | 79 | AddToPath_done: 80 | Pop $3 81 | Pop $2 82 | Pop $1 83 | Pop $0 84 | FunctionEnd 85 | 86 | ; RemoveFromPath - Remove a given dir from the path 87 | ; Input: head of the stack 88 | 89 | Function un.RemoveFromPath 90 | Exch $0 91 | Push $1 92 | Push $2 93 | Push $3 94 | Push $4 95 | Push $5 96 | Push $6 97 | 98 | IntFmt $6 "%c" 26 # DOS EOF 99 | 100 | Call un.IsNT 101 | Pop $1 102 | StrCmp $1 1 unRemoveFromPath_NT 103 | ; Not on NT 104 | StrCpy $1 $WINDIR 2 105 | FileOpen $1 "$1\autoexec.bat" r 106 | GetTempFileName $4 107 | FileOpen $2 $4 w 108 | GetFullPathName /SHORT $0 $0 109 | StrCpy $0 "SET PATH=%PATH%;$0" 110 | Goto unRemoveFromPath_dosLoop 111 | 112 | unRemoveFromPath_dosLoop: 113 | FileRead $1 $3 114 | StrCpy $5 $3 1 -1 # read last char 115 | StrCmp $5 $6 0 +2 # if DOS EOF 116 | StrCpy $3 $3 -1 # remove DOS EOF so we can compare 117 | StrCmp $3 "$0$\r$\n" unRemoveFromPath_dosLoopRemoveLine 118 | StrCmp $3 "$0$\n" unRemoveFromPath_dosLoopRemoveLine 119 | StrCmp $3 "$0" unRemoveFromPath_dosLoopRemoveLine 120 | StrCmp $3 "" unRemoveFromPath_dosLoopEnd 121 | FileWrite $2 $3 122 | Goto unRemoveFromPath_dosLoop 123 | unRemoveFromPath_dosLoopRemoveLine: 124 | SetRebootFlag true 125 | Goto unRemoveFromPath_dosLoop 126 | 127 | unRemoveFromPath_dosLoopEnd: 128 | FileClose $2 129 | FileClose $1 130 | StrCpy $1 $WINDIR 2 131 | Delete "$1\autoexec.bat" 132 | CopyFiles /SILENT $4 "$1\autoexec.bat" 133 | Delete $4 134 | Goto unRemoveFromPath_done 135 | 136 | unRemoveFromPath_NT: 137 | ReadRegStr $1 ${WriteEnvStr_RegKey} "PATH" 138 | StrCpy $5 $1 1 -1 # copy last char 139 | StrCmp $5 ";" +2 # if last char != ; 140 | StrCpy $1 "$1;" # append ; 141 | Push $1 142 | Push "$0;" 143 | Call un.StrStr ; Find `$0;` in $1 144 | Pop $2 ; pos of our dir 145 | StrCmp $2 "" unRemoveFromPath_done 146 | ; else, it is in path 147 | # $0 - path to add 148 | # $1 - path var 149 | StrLen $3 "$0;" 150 | StrLen $4 $2 151 | StrCpy $5 $1 -$4 # $5 is now the part before the path to remove 152 | StrCpy $6 $2 "" $3 # $6 is now the part after the path to remove 153 | StrCpy $3 $5$6 154 | 155 | StrCpy $5 $3 1 -1 # copy last char 156 | StrCmp $5 ";" 0 +2 # if last char == ; 157 | StrCpy $3 $3 -1 # remove last char 158 | 159 | WriteRegExpandStr ${WriteEnvStr_RegKey} "PATH" $3 160 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 161 | 162 | unRemoveFromPath_done: 163 | Pop $6 164 | Pop $5 165 | Pop $4 166 | Pop $3 167 | Pop $2 168 | Pop $1 169 | Pop $0 170 | FunctionEnd 171 | 172 | 173 | 174 | ; AddToEnvVar - Adds the given value to the given environment var 175 | ; Input - head of the stack $0 environement variable $1=value to add 176 | ; Note - Win9x systems requires reboot 177 | 178 | Function AddToEnvVar 179 | 180 | Exch $1 ; $1 has environment variable value 181 | Exch 182 | Exch $0 ; $0 has environment variable name 183 | 184 | DetailPrint "Adding $1 to $0" 185 | Push $2 186 | Push $3 187 | Push $4 188 | 189 | 190 | ReadEnvStr $2 $0 191 | Push "$2;" 192 | Push "$1;" 193 | Call StrStr 194 | Pop $3 195 | StrCmp $3 "" "" AddToEnvVar_done 196 | 197 | Push "$2;" 198 | Push "$1\;" 199 | Call StrStr 200 | Pop $3 201 | StrCmp $3 "" "" AddToEnvVar_done 202 | 203 | 204 | Call IsNT 205 | Pop $2 206 | StrCmp $2 1 AddToEnvVar_NT 207 | ; Not on NT 208 | StrCpy $2 $WINDIR 2 209 | FileOpen $2 "$2\autoexec.bat" a 210 | FileSeek $2 -1 END 211 | FileReadByte $2 $3 212 | IntCmp $3 26 0 +2 +2 # DOS EOF 213 | FileSeek $2 -1 END # write over EOF 214 | FileWrite $2 "$\r$\nSET $0=%$0%;$4$\r$\n" 215 | FileClose $2 216 | SetRebootFlag true 217 | Goto AddToEnvVar_done 218 | 219 | AddToEnvVar_NT: 220 | ReadRegStr $2 ${WriteEnvStr_RegKey} $0 221 | StrCpy $3 $2 1 -1 # copy last char 222 | StrCmp $3 ";" 0 +2 # if last char == ; 223 | StrCpy $2 $2 -1 # remove last char 224 | StrCmp $2 "" AddToEnvVar_NTdoIt 225 | StrCpy $1 "$2;$1" 226 | AddToEnvVar_NTdoIt: 227 | WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $1 228 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 229 | 230 | AddToEnvVar_done: 231 | Pop $4 232 | Pop $3 233 | Pop $2 234 | Pop $0 235 | Pop $1 236 | 237 | FunctionEnd 238 | 239 | ; RemoveFromEnvVar - Remove a given value from a environment var 240 | ; Input: head of the stack 241 | 242 | Function un.RemoveFromEnvVar 243 | 244 | Exch $1 ; $1 has environment variable value 245 | Exch 246 | Exch $0 ; $0 has environment variable name 247 | 248 | DetailPrint "Removing $1 from $0" 249 | Push $2 250 | Push $3 251 | Push $4 252 | Push $5 253 | Push $6 254 | Push $7 255 | 256 | IntFmt $7 "%c" 26 # DOS EOF 257 | 258 | Call un.IsNT 259 | Pop $2 260 | StrCmp $2 1 unRemoveFromEnvVar_NT 261 | ; Not on NT 262 | StrCpy $2 $WINDIR 2 263 | FileOpen $2 "$2\autoexec.bat" r 264 | GetTempFileName $5 265 | FileOpen $3 $5 w 266 | GetFullPathName /SHORT $1 $1 267 | StrCpy $1 "SET $0=%$0%;$1" 268 | Goto unRemoveFromEnvVar_dosLoop 269 | 270 | unRemoveFromEnvVar_dosLoop: 271 | FileRead $2 $4 272 | StrCpy $6 $4 1 -1 # read last char 273 | StrCmp $6 $7 0 +2 # if DOS EOF 274 | StrCpy $4 $4 -1 # remove DOS EOF so we can compare 275 | StrCmp $4 "$1$\r$\n" unRemoveFromEnvVar_dosLoopRemoveLine 276 | StrCmp $4 "$1$\n" unRemoveFromEnvVar_dosLoopRemoveLine 277 | StrCmp $4 "$1" unRemoveFromEnvVar_dosLoopRemoveLine 278 | StrCmp $4 "" unRemoveFromEnvVar_dosLoopEnd 279 | FileWrite $3 $4 280 | Goto unRemoveFromEnvVar_dosLoop 281 | unRemoveFromEnvVar_dosLoopRemoveLine: 282 | SetRebootFlag true 283 | Goto unRemoveFromEnvVar_dosLoop 284 | 285 | unRemoveFromEnvVar_dosLoopEnd: 286 | FileClose $3 287 | FileClose $2 288 | StrCpy $2 $WINDIR 2 289 | Delete "$2\autoexec.bat" 290 | CopyFiles /SILENT $5 "$2\autoexec.bat" 291 | Delete $5 292 | Goto unRemoveFromEnvVar_done 293 | 294 | unRemoveFromEnvVar_NT: 295 | ReadRegStr $2 ${WriteEnvStr_RegKey} $0 296 | StrCpy $6 $2 1 -1 # copy last char 297 | StrCmp $6 ";" +2 # if last char != ; 298 | StrCpy $2 "$2;" # append ; 299 | Push $2 300 | Push "$1;" 301 | Call un.StrStr ; Find `$1;` in $2 302 | Pop $3 ; pos of our dir 303 | StrCmp $3 "" unRemoveFromEnvVar_done 304 | ; else, it is in path 305 | # $1 - path to add 306 | # $2 - path var 307 | StrLen $4 "$1;" 308 | StrLen $5 $3 309 | StrCpy $6 $2 -$5 # $6 is now the part before the path to remove 310 | StrCpy $7 $3 "" $4 # $7 is now the part after the path to remove 311 | StrCpy $4 $6$7 312 | 313 | StrCpy $6 $4 1 -1 # copy last char 314 | StrCmp $6 ";" 0 +2 # if last char == ; 315 | StrCpy $4 $4 -1 # remove last char 316 | 317 | WriteRegExpandStr ${WriteEnvStr_RegKey} $0 $4 318 | 319 | ; delete reg value if null 320 | StrCmp $4 "" 0 +2 # if null delete reg 321 | DeleteRegValue ${WriteEnvStr_RegKey} $0 322 | 323 | SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 324 | 325 | unRemoveFromEnvVar_done: 326 | Pop $7 327 | Pop $6 328 | Pop $5 329 | Pop $4 330 | Pop $3 331 | Pop $2 332 | Pop $1 333 | Pop $0 334 | FunctionEnd 335 | 336 | 337 | 338 | 339 | !ifndef IsNT_KiCHiK 340 | !define IsNT_KiCHiK 341 | 342 | ########################################### 343 | # Utility Functions # 344 | ########################################### 345 | 346 | ; IsNT 347 | ; no input 348 | ; output, top of the stack = 1 if NT or 0 if not 349 | ; 350 | ; Usage: 351 | ; Call IsNT 352 | ; Pop $R0 353 | ; ($R0 at this point is 1 or 0) 354 | 355 | !macro IsNT un 356 | Function ${un}IsNT 357 | Push $0 358 | ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 359 | StrCmp $0 "" 0 IsNT_yes 360 | ; we are not NT. 361 | Pop $0 362 | Push 0 363 | Return 364 | 365 | IsNT_yes: 366 | ; NT!!! 367 | Pop $0 368 | Push 1 369 | FunctionEnd 370 | !macroend 371 | !insertmacro IsNT "" 372 | !insertmacro IsNT "un." 373 | 374 | !endif ; IsNT_KiCHiK 375 | 376 | ; StrStr 377 | ; input, top of stack = string to search for 378 | ; top of stack-1 = string to search in 379 | ; output, top of stack (replaces with the portion of the string remaining) 380 | ; modifies no other variables. 381 | ; 382 | ; Usage: 383 | ; Push "this is a long ass string" 384 | ; Push "ass" 385 | ; Call StrStr 386 | ; Pop $R0 387 | ; ($R0 at this point is "ass string") 388 | 389 | !macro StrStr un 390 | Function ${un}StrStr 391 | Exch $R1 ; st=haystack,old$R1, $R1=needle 392 | Exch ; st=old$R1,haystack 393 | Exch $R2 ; st=old$R1,old$R2, $R2=haystack 394 | Push $R3 395 | Push $R4 396 | Push $R5 397 | StrLen $R3 $R1 398 | StrCpy $R4 0 399 | ; $R1=needle 400 | ; $R2=haystack 401 | ; $R3=len(needle) 402 | ; $R4=cnt 403 | ; $R5=tmp 404 | loop: 405 | StrCpy $R5 $R2 $R3 $R4 406 | StrCmp $R5 $R1 done 407 | StrCmp $R5 "" done 408 | IntOp $R4 $R4 + 1 409 | Goto loop 410 | done: 411 | StrCpy $R1 $R2 "" $R4 412 | Pop $R5 413 | Pop $R4 414 | Pop $R3 415 | Pop $R2 416 | Exch $R1 417 | FunctionEnd 418 | !macroend 419 | !insertmacro StrStr "" 420 | !insertmacro StrStr "un." 421 | 422 | !endif ; _AddToPath_nsh 423 | 424 | Function Trim ; Added by Pelaca 425 | Exch $R1 426 | Push $R2 427 | Loop: 428 | StrCpy $R2 "$R1" 1 -1 429 | StrCmp "$R2" " " RTrim 430 | StrCmp "$R2" "$\n" RTrim 431 | StrCmp "$R2" "$\r" RTrim 432 | StrCmp "$R2" ";" RTrim 433 | GoTo Done 434 | RTrim: 435 | StrCpy $R1 "$R1" -1 436 | Goto Loop 437 | Done: 438 | Pop $R2 439 | Exch $R1 440 | FunctionEnd 441 | 442 | -------------------------------------------------------------------------------- /nsis/libdatrie.nsi: -------------------------------------------------------------------------------- 1 | ; NSIS installer 2 | !include "MUI.nsh" 3 | !include "Sections.nsh" 4 | !include "logiclib.nsh" 5 | 6 | ;environment variable manipulation functions header 7 | !include "WriteEnvStr.nsh" 8 | !include "WritePathStr.nsh" 9 | !include "SearchReplace.nsh" 10 | ;------------------------------- 11 | ; change below variables. 12 | ;------------------------------- 13 | 14 | !define PROGNAME "libdatrie" 15 | !define VERSION "0.1.1" 16 | 17 | ;NSIS will add file(s) from this directory 18 | !define BINSRCDIR "${PROGNAME}" 19 | 20 | !define EULAFILE "${BINSRCDIR}\doc\COPYING.txt" 21 | 22 | ;set env shell-script to store in /etc/profile.d (msys and cygwin) 23 | !define ENV_SETFILE "libdatrienv.sh" 24 | 25 | ;set BASEPATH variable name 26 | !define BASEPATH "DATRIE_BASEPATH" 27 | ;-------------------------------- 28 | 29 | ; The name of the installer 30 | Name "${PROGNAME} v.${VERSION}" 31 | 32 | ; The file to write 33 | OutFile "${PROGNAME}.v${VERSION}.exe" 34 | 35 | ShowInstDetails show 36 | ShowUninstDetails show 37 | 38 | ;-------------------------------- 39 | ; additional variable for dependency checking. 40 | Var IndependentSectionState 41 | 42 | ;-------------------------------- 43 | 44 | ;Interface Settings 45 | 46 | !define MUI_ABORTWARNING 47 | !define MUI_COMPONENTSPAGE_NODESC 48 | ;-------------------------------- 49 | 50 | ;Pages 51 | ;Page EULA 52 | ;Page components 53 | ;Page directory 54 | ;Page instfiles 55 | 56 | !insertmacro MUI_PAGE_LICENSE "${EULAFILE}" 57 | !insertmacro MUI_PAGE_COMPONENTS 58 | !insertmacro MUI_PAGE_DIRECTORY 59 | !insertmacro MUI_PAGE_INSTFILES 60 | 61 | ;UninstPage components 62 | ;UninstPage uninstConfirm 63 | ;UninstPage instfiles 64 | ; !insertmacro MUI_UNPAGE_COMPONENTS 65 | !insertmacro MUI_UNPAGE_CONFIRM 66 | !insertmacro MUI_UNPAGE_INSTFILES 67 | ;-------------------------------- 68 | 69 | ;Languages 70 | 71 | !insertmacro MUI_LANGUAGE "English" 72 | 73 | ;-------------------------------- 74 | 75 | ; Section install mainfiles 76 | 77 | SectionGroup /e "${PROGNAME}-components" 78 | ;The stuff to install 79 | 80 | Section "-write information to registry" 81 | ;Write the installation path into the registry 82 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" "$INSTDIR" 83 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}" "Version" "${VERSION}" 84 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}" "BaseVar" "${BASEPATH}" 85 | SectionEnd 86 | 87 | Section "${PROGNAME}-runtime" runtimesec 88 | ;SectionIn RO 89 | ;Set output path to the installation directory. 90 | SetOutPath "$INSTDIR\bin" 91 | ;Put file there 92 | File "${BINSRCDIR}\bin\*.dll" 93 | 94 | SetOutPath "$INSTDIR\doc" 95 | File "${BINSRCDIR}\doc\*.*" 96 | ;Write component info. 97 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}\components" "runtime" "1" 98 | SectionEnd 99 | 100 | Section /o "trietool" binsec 101 | ;SectionIn RO 102 | ;Set output path to the installation directory. 103 | SetOutPath "$INSTDIR\bin" 104 | ;Put file there 105 | File "${BINSRCDIR}\bin\*.exe" 106 | SetOutPath "$INSTDIR\share\man\man1" 107 | File "${BINSRCDIR}\share\man\man1\*.*" 108 | ;Write component info. 109 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}\components" "trietool" "1" 110 | SectionEnd 111 | 112 | 113 | Section /o "${PROGNAME}-devel" develsec 114 | ;SectionIn RO 115 | ;Set output path to the installation directory. 116 | SetOutPath $INSTDIR 117 | ;Put file there 118 | File /r "${BINSRCDIR}\include" 119 | 120 | SetOutPath "$INSTDIR\lib" 121 | File "${BINSRCDIR}\lib\*.*" 122 | 123 | SetOutPath "$INSTDIR\lib\pkgconfig" 124 | File "${BINSRCDIR}\lib\pkgconfig\*.*" 125 | 126 | ;Write component info. 127 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}\components" "devel" "1" 128 | SectionEnd 129 | 130 | Section /o "${PROGNAME}-doc" docsec 131 | ;SectionIn RO 132 | ;Set output path to the installation directory. 133 | SetOutPath "$INSTDIR\share" 134 | ;Put file there 135 | File /r "${BINSRCDIR}\share\doc" 136 | ;Write component info. 137 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}\components" "doc" "1" 138 | SectionEnd 139 | 140 | Section "-Write Uninstaller" 141 | ;Write the uninstall keys for Windows 142 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGNAME}" "DisplayName" "${PROGNAME} v.${VERSION}" 143 | WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGNAME}" "UninstallString" '"$INSTDIR\uninstall.exe"' 144 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGNAME}" "NoModify" 1 145 | WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGNAME}" "NoRepair" 1 146 | ;create uninstaller 147 | SetOutPath $INSTDIR 148 | WriteUninstaller "$INSTDIR\uninstall.exe" 149 | SectionEnd 150 | 151 | Section "Start Menu Shortcuts" 152 | SetShellVarContext current 153 | CreateDirectory "$STARTMENU\Programs\${PROGNAME}" 154 | ; Create link to docs if runtime section is selected 155 | ${If} ${SectionIsSelected} ${runtimesec} 156 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\AUTHORS.lnk" "$INSTDIR\doc\AUTHORS.txt" 157 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\COPYING.lnk" "$INSTDIR\doc\COPYING.txt" 158 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\INSTALL.lnk" "$INSTDIR\doc\INSTALL.txt" 159 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\NEWS.lnk" "$INSTDIR\doc\NEWS.txt" 160 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\README.lnk" "$INSTDIR\doc\README.txt" 161 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\Changelog.lnk" "$INSTDIR\doc\Changelog.txt" 162 | ${EndIf} 163 | CreateShortCut "$STARTMENU\Programs\${PROGNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" 164 | ;Write component info. 165 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}\components" "startmenu" "1" 166 | SectionEnd 167 | 168 | SectionGroupEnd 169 | 170 | ;------------------------------------------------------------- 171 | ; Section set environment 172 | 173 | SectionGroup /e "Set environment for toolchains" 174 | 175 | Section "-set base path" 176 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "BaseVar" 177 | ReadRegStr $1 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 178 | Push $0 179 | Push '"$1"' 180 | Call WriteEnvStr 181 | SectionEnd 182 | 183 | Section "-set bin path" 184 | ; check if runtime section is selected. 185 | ${If} ${SectionIsSelected} ${runtimesec} 186 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 187 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 188 | StrCmp $1 "" noNT isNT 189 | noNT: 190 | Push "PATH" 191 | Push '"$0\bin";%PATH%' 192 | Call WriteEnvStr 193 | goto done 194 | isNT: 195 | Push "PATH" 196 | Push '"$0\bin"' 197 | Call AddToEnvVar 198 | goto done 199 | done: 200 | ${EndIf} 201 | SectionEnd 202 | 203 | Section "MSYS/mingw" 204 | ;where is MSYS/mingw 205 | ReadRegStr $0 HKLM "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\MSYS-1.0_is1" "Inno Setup: App Path" 206 | StrCmp $0 "" nomsys ismsys 207 | nomsys: 208 | goto done 209 | ismsys: 210 | SetOutPath "$0\etc\profile.d" 211 | File /oname=${ENV_SETFILE} "${BINSRCDIR}\contrib\${ENV_SETFILE}" 212 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}" "msys-env" "$0\etc\profile.d\${ENV_SETFILE}" 213 | goto done 214 | done: 215 | SectionEnd 216 | 217 | Section "Cygwin" 218 | ;where is Cygwin 219 | ReadRegStr $0 HKLM "Software\Cygnus Solutions\Cygwin\mounts v2\/" "native" 220 | StrCmp $0 "" nocygwin iscygwin 221 | nocygwin: 222 | goto done 223 | iscygwin: 224 | SetOutPath "$0\etc\profile.d" 225 | File /oname=${ENV_SETFILE} "${BINSRCDIR}\contrib\${ENV_SETFILE}" 226 | WriteRegStr HKLM "SOFTWARE\${PROGNAME}" "cygwin-env" "$0\etc\profile.d\${ENV_SETFILE}" 227 | goto done 228 | done: 229 | SectionEnd 230 | 231 | Section "MSVC" 232 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 233 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 234 | StrCmp $1 "" noNT0 isNT0 235 | noNT0: 236 | Push "INCLUDE" 237 | Push '"$0\include";%INCLUDE%' 238 | Call WriteEnvStr 239 | goto inc_done 240 | isNT0: 241 | Push "INCLUDE" 242 | Push '"$0\include"' 243 | Call AddToEnvVar 244 | goto inc_done 245 | inc_done: 246 | 247 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 248 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 249 | StrCmp $1 "" noNT1 isNT1 250 | noNT1: 251 | Push "LIB" 252 | Push '"$0\lib";%LIB%' 253 | Call WriteEnvStr 254 | goto lib_done 255 | isNT1: 256 | Push "LIB" 257 | Push '"$0\lib"' 258 | Call AddToEnvVar 259 | goto lib_done 260 | lib_done: 261 | 262 | SectionEnd 263 | 264 | SectionGroupEnd 265 | 266 | ;-------------------------------- 267 | ; Uninstall Sections. 268 | Section "-un.Uninstall" 269 | ;Get installation folder from registry if available 270 | ; Remove files and uninstaller 271 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 272 | RMDir /r "$0" 273 | 274 | ; Remove environment Variables 275 | ; Remove BASEPATH 276 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "BaseVar" 277 | Push $0 278 | Call un.DeleteEnvStr 279 | 280 | ; Remove bin path 281 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 282 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 283 | StrCmp $1 "" noNT0 isNT0 284 | noNT0: 285 | StrCpy $2 $WINDIR 2 286 | Push "$2\autoexec.bat" 287 | Push 'SET PATH="$0\bin";%PATH%' 288 | Call un.DeleteLine 289 | goto bin_done 290 | isNT0: 291 | Push "PATH" 292 | Push '"$0\bin"' 293 | Call un.RemoveFromEnvVar 294 | goto bin_done 295 | bin_done: 296 | 297 | ; Remove include path 298 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 299 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 300 | StrCmp $1 "" noNT1 isNT1 301 | noNT1: 302 | StrCpy $2 $WINDIR 2 303 | Push "$2\autoexec.bat" 304 | Push 'SET INCLUDE="$0\include";%INCLUDE%' 305 | Call un.DeleteLine 306 | goto inc_done 307 | isNT1: 308 | Push "INCLUDE" 309 | Push '"$0\include"' 310 | Call un.RemoveFromEnvVar 311 | goto inc_done 312 | inc_done: 313 | 314 | ; Remove lib path 315 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "Install_Dir" 316 | ReadRegStr $1 HKLM "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion 317 | StrCmp $1 "" noNT2 isNT2 318 | noNT2: 319 | StrCpy $2 $WINDIR 2 320 | Push "$2\autoexec.bat" 321 | Push 'SET LIB="$0\lib";%LIB%' 322 | Call un.DeleteLine 323 | goto lib_done 324 | isNT2: 325 | Push "LIB" 326 | Push '"$0\lib"' 327 | Call un.RemoveFromEnvVar 328 | goto lib_done 329 | lib_done: 330 | 331 | ; Remove shell-script in /etc/profile.d (msys/cygwin) 332 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "msys-env" 333 | Delete $0 334 | ReadRegStr $0 HKLM "SOFTWARE\${PROGNAME}" "cygwin-env" 335 | Delete $0 336 | 337 | ; Remove shortcuts, if any 338 | SetShellVarContext current 339 | RMDir /r "$STARTMENU\Programs\${PROGNAME}" 340 | 341 | ; Remove registry keys 342 | DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PROGNAME}" 343 | DeleteRegKey HKLM "SOFTWARE\${PROGNAME}" 344 | SectionEnd 345 | 346 | ;--------------------------------------- 347 | 348 | Function .onInit 349 | ; The default installation directory is "systemdrive:\(program's name)" 350 | ; for example : "C:\${PROGNAME}, D:$\{PROGNAME}" 351 | StrCpy $R9 $WINDIR 2 352 | StrCpy $INSTDIR "$R9\${PROGNAME}" 353 | 354 | ; Dependency Checking's variable setting. 355 | ;This is first time setting. 356 | SectionGetFlags ${runtimesec} $R0 357 | IntOp $R0 $R0 & ${SF_SELECTED} 358 | StrCpy $IndependentSectionState $R0 359 | 360 | FunctionEnd 361 | 362 | 363 | ;------------------------------------------------------------- 364 | ; use callback function .onSelChange for dependency checking. 365 | ;------------------------------------------------------------- 366 | Function .onSelChange 367 | 368 | ;================================== 369 | ; start checking dependcy routine. 370 | ;================================== 371 | Push $R0 372 | Push $R1 373 | 374 | # Check if runtimesec was just selected then select binsec and develsec. 375 | SectionGetFlags ${runtimesec} $R0 376 | IntOp $R0 $R0 & ${SF_SELECTED} 377 | StrCmp $R0 $IndependentSectionState +3 378 | StrCpy $IndependentSectionState $R0 379 | Goto UnselectDependentSections 380 | StrCpy $IndependentSectionState $R0 381 | 382 | Goto CheckDependentSections 383 | 384 | # Select runtimesec if binsec or develsec was selected. 385 | SelectIndependentSection: 386 | 387 | SectionGetFlags ${runtimesec} $R0 388 | IntOp $R1 $R0 & ${SF_SELECTED} 389 | StrCmp $R1 ${SF_SELECTED} +3 390 | 391 | IntOp $R0 $R0 | ${SF_SELECTED} 392 | SectionSetFlags ${runtimesec} $R0 393 | 394 | StrCpy $IndependentSectionState ${SF_SELECTED} 395 | 396 | Goto End 397 | 398 | # Were binsec or develsec just unselected? 399 | CheckDependentSections: 400 | 401 | SectionGetFlags ${binsec} $R0 402 | IntOp $R0 $R0 & ${SF_SELECTED} 403 | StrCmp $R0 ${SF_SELECTED} SelectIndependentSection 404 | 405 | SectionGetFlags ${develsec} $R0 406 | IntOp $R0 $R0 & ${SF_SELECTED} 407 | StrCmp $R0 ${SF_SELECTED} SelectIndependentSection 408 | 409 | Goto End 410 | 411 | # Unselect binsec and develsec if runtimesec was unselected. 412 | UnselectDependentSections: 413 | 414 | SectionGetFlags ${binsec} $R0 415 | IntOp $R1 $R0 & ${SF_SELECTED} 416 | StrCmp $R1 ${SF_SELECTED} 0 +3 417 | 418 | IntOp $R0 $R0 ^ ${SF_SELECTED} 419 | SectionSetFlags ${binsec} $R0 420 | 421 | SectionGetFlags ${develsec} $R0 422 | IntOp $R1 $R0 & ${SF_SELECTED} 423 | StrCmp $R1 ${SF_SELECTED} 0 +3 424 | 425 | IntOp $R0 $R0 ^ ${SF_SELECTED} 426 | SectionSetFlags ${develsec} $R0 427 | 428 | End: 429 | 430 | Pop $R1 431 | Pop $R0 432 | ;================================== 433 | ; End of checking dependcy routine. 434 | ;================================== 435 | 436 | FunctionEnd 437 | ;----------------------------- 438 | -------------------------------------------------------------------------------- /datrie/tail.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * tail.c - trie tail for keeping suffixes 23 | * Created: 2006-08-15 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include 29 | #ifndef _MSC_VER /* for SIZE_MAX */ 30 | # include 31 | #endif 32 | #include 33 | 34 | #include "tail.h" 35 | #include "trie-private.h" 36 | #include "fileutils.h" 37 | #include "trie-string.h" 38 | 39 | /*----------------------------------* 40 | * INTERNAL TYPES DECLARATIONS * 41 | *----------------------------------*/ 42 | 43 | /*-----------------------------------* 44 | * PRIVATE METHODS DECLARATIONS * 45 | *-----------------------------------*/ 46 | 47 | static TrieIndex tail_alloc_block (Tail *t); 48 | static void tail_free_block (Tail *t, TrieIndex block); 49 | 50 | /* ==================== BEGIN IMPLEMENTATION PART ==================== */ 51 | 52 | /*------------------------------------* 53 | * INTERNAL TYPES IMPLEMENTATIONS * 54 | *------------------------------------*/ 55 | 56 | /*------------------------------* 57 | * PRIVATE DATA DEFINITONS * 58 | *------------------------------*/ 59 | 60 | typedef struct { 61 | TrieIndex next_free; 62 | TrieData data; 63 | TrieChar *suffix; 64 | } TailBlock; 65 | 66 | struct _Tail { 67 | TrieIndex num_tails; 68 | TailBlock *tails; 69 | TrieIndex first_free; 70 | }; 71 | 72 | /*-----------------------------* 73 | * METHODS IMPLEMENTAIONS * 74 | *-----------------------------*/ 75 | 76 | #define TAIL_SIGNATURE 0xDFFCDFFC 77 | #define TAIL_START_BLOCKNO 1 78 | 79 | /* Tail Header: 80 | * INT32: signature 81 | * INT32: pointer to first free slot 82 | * INT32: number of tail blocks 83 | * 84 | * Tail Blocks: 85 | * INT32: pointer to next free block (-1 for allocated blocks) 86 | * INT32: data for the key 87 | * INT16: length 88 | * BYTES[length]: suffix string (no terminating '\0') 89 | */ 90 | 91 | /** 92 | * @brief Create a new tail object 93 | * 94 | * Create a new empty tail object. 95 | */ 96 | Tail * 97 | tail_new (void) 98 | { 99 | Tail *t; 100 | 101 | t = (Tail *) malloc (sizeof (Tail)); 102 | if (UNLIKELY (!t)) 103 | return NULL; 104 | 105 | t->first_free = 0; 106 | t->num_tails = 0; 107 | t->tails = NULL; 108 | 109 | return t; 110 | } 111 | 112 | /** 113 | * @brief Read tail data from file 114 | * 115 | * @param file : the file to read 116 | * 117 | * @return a pointer to the openned tail data, NULL on failure 118 | * 119 | * Read tail data from the opened file, starting from the current 120 | * file pointer until the end of tail data block. On return, the 121 | * file pointer is left at the position after the read block. 122 | */ 123 | Tail * 124 | tail_fread (FILE *file) 125 | { 126 | long save_pos; 127 | Tail *t; 128 | TrieIndex i; 129 | uint32 sig; 130 | 131 | /* check signature */ 132 | save_pos = ftell (file); 133 | if (!file_read_int32 (file, (int32 *) &sig) || TAIL_SIGNATURE != sig) 134 | goto exit_file_read; 135 | 136 | t = (Tail *) malloc (sizeof (Tail)); 137 | if (UNLIKELY (!t)) 138 | goto exit_file_read; 139 | 140 | if (!file_read_int32 (file, &t->first_free) || 141 | !file_read_int32 (file, &t->num_tails)) 142 | { 143 | goto exit_tail_created; 144 | } 145 | if (t->num_tails > SIZE_MAX / sizeof (TailBlock)) 146 | goto exit_tail_created; 147 | t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock)); 148 | if (UNLIKELY (!t->tails)) 149 | goto exit_tail_created; 150 | for (i = 0; i < t->num_tails; i++) { 151 | int16 length; 152 | 153 | if (!file_read_int32 (file, &t->tails[i].next_free) || 154 | !file_read_int32 (file, &t->tails[i].data) || 155 | !file_read_int16 (file, &length)) 156 | { 157 | goto exit_in_loop; 158 | } 159 | 160 | t->tails[i].suffix = (TrieChar *) malloc (length + 1); 161 | if (UNLIKELY (!t->tails[i].suffix)) 162 | goto exit_in_loop; 163 | if (length > 0) { 164 | if (!file_read_chars (file, (char *)t->tails[i].suffix, length)) { 165 | free (t->tails[i].suffix); 166 | goto exit_in_loop; 167 | } 168 | } 169 | t->tails[i].suffix[length] = TRIE_CHAR_TERM; 170 | } 171 | 172 | return t; 173 | 174 | exit_in_loop: 175 | while (i > 0) { 176 | free (t->tails[--i].suffix); 177 | } 178 | free (t->tails); 179 | exit_tail_created: 180 | free (t); 181 | exit_file_read: 182 | fseek (file, save_pos, SEEK_SET); 183 | return NULL; 184 | } 185 | 186 | /** 187 | * @brief Free tail data 188 | * 189 | * @param t : the tail data 190 | * 191 | * @return 0 on success, non-zero on failure 192 | * 193 | * Free the given tail data. 194 | */ 195 | void 196 | tail_free (Tail *t) 197 | { 198 | TrieIndex i; 199 | 200 | if (t->tails) { 201 | for (i = 0; i < t->num_tails; i++) 202 | if (t->tails[i].suffix) 203 | free (t->tails[i].suffix); 204 | free (t->tails); 205 | } 206 | free (t); 207 | } 208 | 209 | /** 210 | * @brief Write tail data 211 | * 212 | * @param t : the tail data 213 | * @param file : the file to write to 214 | * 215 | * @return 0 on success, non-zero on failure 216 | * 217 | * Write tail data to the given @a file, starting from the current file 218 | * pointer. On return, the file pointer is left after the tail data block. 219 | */ 220 | int 221 | tail_fwrite (const Tail *t, FILE *file) 222 | { 223 | TrieIndex i; 224 | 225 | if (!file_write_int32 (file, TAIL_SIGNATURE) || 226 | !file_write_int32 (file, t->first_free) || 227 | !file_write_int32 (file, t->num_tails)) 228 | { 229 | return -1; 230 | } 231 | for (i = 0; i < t->num_tails; i++) { 232 | int16 length; 233 | 234 | if (!file_write_int32 (file, t->tails[i].next_free) || 235 | !file_write_int32 (file, t->tails[i].data)) 236 | { 237 | return -1; 238 | } 239 | 240 | length = t->tails[i].suffix ? trie_char_strlen (t->tails[i].suffix) 241 | : 0; 242 | if (!file_write_int16 (file, length)) 243 | return -1; 244 | if (length > 0 && 245 | !file_write_chars (file, (char *)t->tails[i].suffix, length)) 246 | { 247 | return -1; 248 | } 249 | } 250 | 251 | return 0; 252 | } 253 | 254 | 255 | size_t 256 | tail_get_serialized_size (const Tail *t) 257 | { 258 | size_t static_count = ( 259 | sizeof (int32) /* sizeof (TAIL_SIGNATURE) */ 260 | + sizeof (t->first_free) 261 | + sizeof (t->num_tails) 262 | ); 263 | size_t dynamic_count = 0u; 264 | if (t->num_tails > 0) { 265 | TrieIndex i = 0; 266 | dynamic_count += ( 267 | sizeof (t->tails[i].next_free) + sizeof (t->tails[i].data) 268 | + sizeof (int16) /* length */ 269 | ) * t->num_tails; 270 | for (; i < t->num_tails; i++) { 271 | if (t->tails[i].suffix) 272 | { 273 | dynamic_count += trie_char_strsize (t->tails[i].suffix); 274 | } 275 | } 276 | } 277 | return static_count + dynamic_count; 278 | } 279 | 280 | 281 | int 282 | tail_serialize (const Tail *t, uint8 **ptr) 283 | { 284 | TrieIndex i; 285 | 286 | serialize_int32_be_incr (ptr, TAIL_SIGNATURE); 287 | serialize_int32_be_incr (ptr, t->first_free); 288 | serialize_int32_be_incr (ptr, t->num_tails); 289 | 290 | for (i = 0; i < t->num_tails; i++) { 291 | int16 length; 292 | serialize_int32_be_incr (ptr, t->tails[i].next_free); 293 | serialize_int32_be_incr (ptr, t->tails[i].data); 294 | 295 | length = t->tails[i].suffix ? trie_char_strsize (t->tails[i].suffix) 296 | : 0; 297 | serialize_int16_be_incr (ptr, length); 298 | if (length) 299 | { 300 | memcpy (*ptr, (char *)t->tails[i].suffix, length); 301 | *ptr += length; 302 | } 303 | } 304 | 305 | return 0; 306 | } 307 | 308 | 309 | /** 310 | * @brief Get suffix 311 | * 312 | * @param t : the tail data 313 | * @param index : the index of the suffix 314 | * 315 | * @return pointer to the indexed suffix string. 316 | * 317 | * Get suffix from tail with given @a index. The returned string is a pointer 318 | * to internal storage, which should be accessed read-only by the caller. 319 | * No need to free() it. 320 | */ 321 | const TrieChar * 322 | tail_get_suffix (const Tail *t, TrieIndex index) 323 | { 324 | index -= TAIL_START_BLOCKNO; 325 | return LIKELY (index < t->num_tails) ? t->tails[index].suffix : NULL; 326 | } 327 | 328 | /** 329 | * @brief Set suffix of existing entry 330 | * 331 | * @param t : the tail data 332 | * @param index : the index of the suffix 333 | * @param suffix : the new suffix 334 | * 335 | * Set suffix of existing entry of given @a index in tail. 336 | */ 337 | Bool 338 | tail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix) 339 | { 340 | index -= TAIL_START_BLOCKNO; 341 | if (LIKELY (index < t->num_tails)) { 342 | /* suffix and t->tails[index].suffix may overlap; 343 | * so, dup it before it's overwritten 344 | */ 345 | TrieChar *tmp = NULL; 346 | if (suffix) { 347 | tmp = trie_char_strdup (suffix); 348 | if (UNLIKELY (!tmp)) 349 | return FALSE; 350 | } 351 | if (t->tails[index].suffix) 352 | free (t->tails[index].suffix); 353 | t->tails[index].suffix = tmp; 354 | 355 | return TRUE; 356 | } 357 | return FALSE; 358 | } 359 | 360 | /** 361 | * @brief Add a new suffix 362 | * 363 | * @param t : the tail data 364 | * @param suffix : the new suffix 365 | * 366 | * @return the index of the newly added suffix, 367 | * or TRIE_INDEX_ERROR on failure. 368 | * 369 | * Add a new suffix entry to tail. 370 | */ 371 | TrieIndex 372 | tail_add_suffix (Tail *t, const TrieChar *suffix) 373 | { 374 | TrieIndex new_block; 375 | 376 | new_block = tail_alloc_block (t); 377 | if (UNLIKELY (TRIE_INDEX_ERROR == new_block)) 378 | return TRIE_INDEX_ERROR; 379 | 380 | tail_set_suffix (t, new_block, suffix); 381 | 382 | return new_block; 383 | } 384 | 385 | static TrieIndex 386 | tail_alloc_block (Tail *t) 387 | { 388 | TrieIndex block; 389 | 390 | if (0 != t->first_free) { 391 | block = t->first_free; 392 | t->first_free = t->tails[block].next_free; 393 | } else { 394 | void *new_block; 395 | 396 | block = t->num_tails; 397 | 398 | new_block = realloc (t->tails, (t->num_tails + 1) * sizeof (TailBlock)); 399 | if (UNLIKELY (!new_block)) 400 | return TRIE_INDEX_ERROR; 401 | 402 | t->tails = (TailBlock *) new_block; 403 | ++t->num_tails; 404 | } 405 | t->tails[block].next_free = -1; 406 | t->tails[block].data = TRIE_DATA_ERROR; 407 | t->tails[block].suffix = NULL; 408 | 409 | return block + TAIL_START_BLOCKNO; 410 | } 411 | 412 | static void 413 | tail_free_block (Tail *t, TrieIndex block) 414 | { 415 | TrieIndex i, j; 416 | 417 | block -= TAIL_START_BLOCKNO; 418 | 419 | if (block >= t->num_tails) 420 | return; 421 | 422 | t->tails[block].data = TRIE_DATA_ERROR; 423 | if (NULL != t->tails[block].suffix) { 424 | free (t->tails[block].suffix); 425 | t->tails[block].suffix = NULL; 426 | } 427 | 428 | /* find insertion point */ 429 | j = 0; 430 | for (i = t->first_free; i != 0 && i < block; i = t->tails[i].next_free) 431 | j = i; 432 | 433 | /* insert free block between j and i */ 434 | t->tails[block].next_free = i; 435 | if (0 != j) 436 | t->tails[j].next_free = block; 437 | else 438 | t->first_free = block; 439 | } 440 | 441 | /** 442 | * @brief Get data associated to suffix entry 443 | * 444 | * @param t : the tail data 445 | * @param index : the index of the suffix 446 | * 447 | * @return the data associated to the suffix entry 448 | * 449 | * Get data associated to suffix entry @a index in tail data. 450 | */ 451 | TrieData 452 | tail_get_data (const Tail *t, TrieIndex index) 453 | { 454 | index -= TAIL_START_BLOCKNO; 455 | return LIKELY (index < t->num_tails) 456 | ? t->tails[index].data : TRIE_DATA_ERROR; 457 | } 458 | 459 | /** 460 | * @brief Set data associated to suffix entry 461 | * 462 | * @param t : the tail data 463 | * @param index : the index of the suffix 464 | * @param data : the data to set 465 | * 466 | * @return boolean indicating success 467 | * 468 | * Set data associated to suffix entry @a index in tail data. 469 | */ 470 | Bool 471 | tail_set_data (Tail *t, TrieIndex index, TrieData data) 472 | { 473 | index -= TAIL_START_BLOCKNO; 474 | if (LIKELY (index < t->num_tails)) { 475 | t->tails[index].data = data; 476 | return TRUE; 477 | } 478 | return FALSE; 479 | } 480 | 481 | /** 482 | * @brief Delete suffix entry 483 | * 484 | * @param t : the tail data 485 | * @param index : the index of the suffix to delete 486 | * 487 | * Delete suffix entry from the tail data. 488 | */ 489 | void 490 | tail_delete (Tail *t, TrieIndex index) 491 | { 492 | tail_free_block (t, index); 493 | } 494 | 495 | /** 496 | * @brief Walk in tail with a string 497 | * 498 | * @param t : the tail data 499 | * @param s : the tail data index 500 | * @param suffix_idx : pointer to current character index in suffix 501 | * @param str : the string to use in walking 502 | * @param len : total characters in @a str to walk 503 | * 504 | * @return total number of characters successfully walked 505 | * 506 | * Walk in the tail data @a t at entry @a s, from given character position 507 | * @a *suffix_idx, using @a len characters of given string @a str. On return, 508 | * @a *suffix_idx is updated to the position after the last successful walk, 509 | * and the function returns the total number of character succesfully walked. 510 | */ 511 | int 512 | tail_walk_str (const Tail *t, 513 | TrieIndex s, 514 | short *suffix_idx, 515 | const TrieChar *str, 516 | int len) 517 | { 518 | const TrieChar *suffix; 519 | int i; 520 | short j; 521 | 522 | suffix = tail_get_suffix (t, s); 523 | if (UNLIKELY (!suffix)) 524 | return FALSE; 525 | 526 | i = 0; j = *suffix_idx; 527 | while (i < len) { 528 | if (str[i] != suffix[j]) 529 | break; 530 | ++i; 531 | /* stop and stay at null-terminator */ 532 | if (TRIE_CHAR_TERM == suffix[j]) 533 | break; 534 | ++j; 535 | } 536 | *suffix_idx = j; 537 | return i; 538 | } 539 | 540 | /** 541 | * @brief Walk in tail with a character 542 | * 543 | * @param t : the tail data 544 | * @param s : the tail data index 545 | * @param suffix_idx : pointer to current character index in suffix 546 | * @param c : the character to use in walking 547 | * 548 | * @return boolean indicating success 549 | * 550 | * Walk in the tail data @a t at entry @a s, from given character position 551 | * @a *suffix_idx, using given character @a c. If the walk is successful, 552 | * it returns TRUE, and @a *suffix_idx is updated to the next character. 553 | * Otherwise, it returns FALSE, and @a *suffix_idx is left unchanged. 554 | */ 555 | Bool 556 | tail_walk_char (const Tail *t, 557 | TrieIndex s, 558 | short *suffix_idx, 559 | TrieChar c) 560 | { 561 | const TrieChar *suffix; 562 | TrieChar suffix_char; 563 | 564 | suffix = tail_get_suffix (t, s); 565 | if (UNLIKELY (!suffix)) 566 | return FALSE; 567 | 568 | suffix_char = suffix[*suffix_idx]; 569 | if (suffix_char == c) { 570 | if (TRIE_CHAR_TERM != suffix_char) 571 | ++*suffix_idx; 572 | return TRUE; 573 | } 574 | return FALSE; 575 | } 576 | 577 | /* 578 | vi:ts=4:ai:expandtab 579 | */ 580 | -------------------------------------------------------------------------------- /datrie/alpha-map.c: -------------------------------------------------------------------------------- 1 | /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 2 | /* 3 | * libdatrie - Double-Array Trie Library 4 | * Copyright (C) 2006 Theppitak Karoonboonyanan 5 | * 6 | * This library is free software; you can redistribute it and/or 7 | * modify it under the terms of the GNU Lesser General Public 8 | * License as published by the Free Software Foundation; either 9 | * version 2.1 of the License, or (at your option) any later version. 10 | * 11 | * This library is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 | * Lesser General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Lesser General Public 17 | * License along with this library; if not, write to the Free Software 18 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 | */ 20 | 21 | /* 22 | * alpha-map.c - map between character codes and trie alphabet 23 | * Created: 2006-08-19 24 | * Author: Theppitak Karoonboonyanan 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | #include "alpha-map.h" 34 | #include "alpha-map-private.h" 35 | #include "trie-private.h" 36 | #include "fileutils.h" 37 | #include "trie-string.h" 38 | 39 | /** 40 | * @brief Alphabet string length 41 | * 42 | * @param str : the array of null-terminated AlphaChar string to measure 43 | * 44 | * @return the total characters in @a str. 45 | */ 46 | int 47 | alpha_char_strlen (const AlphaChar *str) 48 | { 49 | const AlphaChar *p; 50 | 51 | for (p = str; *p; p++) 52 | ; 53 | return p - str; 54 | } 55 | 56 | /** 57 | * @brief Compare alphabet strings 58 | * 59 | * @param str1, str2 : the arrays of null-terminated AlphaChar strings 60 | * to compare 61 | * 62 | * @return negative if @a str1 < @a str2; 63 | * 0 if @a str1 == @a str2; 64 | * positive if @a str1 > @a str2 65 | * 66 | * Available since: 0.2.7 67 | */ 68 | int 69 | alpha_char_strcmp (const AlphaChar *str1, const AlphaChar *str2) 70 | { 71 | while (*str1 && *str1 == *str2) { 72 | str1++; str2++; 73 | } 74 | if (*str1 < *str2) 75 | return -1; 76 | if (*str1 > *str2) 77 | return 1; 78 | return 0; 79 | } 80 | 81 | /*------------------------------* 82 | * PRIVATE DATA DEFINITONS * 83 | *------------------------------*/ 84 | 85 | typedef struct _AlphaRange { 86 | struct _AlphaRange *next; 87 | 88 | AlphaChar begin; 89 | AlphaChar end; 90 | } AlphaRange; 91 | 92 | struct _AlphaMap { 93 | AlphaRange *first_range; 94 | 95 | /* work area */ 96 | /* alpha-to-trie map */ 97 | AlphaChar alpha_begin; 98 | AlphaChar alpha_end; 99 | int alpha_map_sz; 100 | TrieIndex *alpha_to_trie_map; 101 | 102 | /* trie-to-alpha map */ 103 | int trie_map_sz; 104 | AlphaChar *trie_to_alpha_map; 105 | }; 106 | 107 | /*-----------------------------------* 108 | * PRIVATE METHODS DECLARATIONS * 109 | *-----------------------------------*/ 110 | static int alpha_map_get_total_ranges (const AlphaMap *alpha_map); 111 | static int alpha_map_add_range_only (AlphaMap *alpha_map, 112 | AlphaChar begin, AlphaChar end); 113 | static int alpha_map_recalc_work_area (AlphaMap *alpha_map); 114 | 115 | /*-----------------------------* 116 | * METHODS IMPLEMENTAIONS * 117 | *-----------------------------*/ 118 | 119 | #define ALPHAMAP_SIGNATURE 0xD9FCD9FC 120 | 121 | /* AlphaMap Header: 122 | * - INT32: signature 123 | * - INT32: total ranges 124 | * 125 | * Ranges: 126 | * - INT32: range begin 127 | * - INT32: range end 128 | */ 129 | 130 | /** 131 | * @brief Create new alphabet map 132 | * 133 | * @return a pointer to the newly created alphabet map, NULL on failure 134 | * 135 | * Create a new empty alphabet map. The map contents can then be added with 136 | * alpha_map_add_range(). 137 | * 138 | * The created object must be freed with alpha_map_free(). 139 | */ 140 | AlphaMap * 141 | alpha_map_new (void) 142 | { 143 | AlphaMap *alpha_map; 144 | 145 | alpha_map = (AlphaMap *) malloc (sizeof (AlphaMap)); 146 | if (UNLIKELY (!alpha_map)) 147 | return NULL; 148 | 149 | alpha_map->first_range = NULL; 150 | 151 | /* work area */ 152 | alpha_map->alpha_begin = 0; 153 | alpha_map->alpha_end = 0; 154 | alpha_map->alpha_map_sz = 0; 155 | alpha_map->alpha_to_trie_map = NULL; 156 | 157 | alpha_map->trie_map_sz = 0; 158 | alpha_map->trie_to_alpha_map = NULL; 159 | 160 | return alpha_map; 161 | } 162 | 163 | /** 164 | * @brief Create a clone of alphabet map 165 | * 166 | * @param a_map : the source alphabet map to clone 167 | * 168 | * @return a pointer to the alphabet map clone, NULL on failure 169 | * 170 | * The created object must be freed with alpha_map_free(). 171 | */ 172 | AlphaMap * 173 | alpha_map_clone (const AlphaMap *a_map) 174 | { 175 | AlphaMap *alpha_map; 176 | AlphaRange *range; 177 | 178 | alpha_map = alpha_map_new (); 179 | if (UNLIKELY (!alpha_map)) 180 | return NULL; 181 | 182 | for (range = a_map->first_range; range; range = range->next) { 183 | if (alpha_map_add_range_only (alpha_map, range->begin, range->end) != 0) 184 | goto exit_map_created; 185 | } 186 | 187 | if (alpha_map_recalc_work_area (alpha_map) != 0) 188 | goto exit_map_created; 189 | 190 | return alpha_map; 191 | 192 | exit_map_created: 193 | alpha_map_free (alpha_map); 194 | return NULL; 195 | } 196 | 197 | /** 198 | * @brief Free an alphabet map object 199 | * 200 | * @param alpha_map : the alphabet map object to free 201 | * 202 | * Destruct the @a alpha_map and free its allocated memory. 203 | */ 204 | void 205 | alpha_map_free (AlphaMap *alpha_map) 206 | { 207 | AlphaRange *p, *q; 208 | 209 | p = alpha_map->first_range; 210 | while (p) { 211 | q = p->next; 212 | free (p); 213 | p = q; 214 | } 215 | 216 | /* work area */ 217 | if (alpha_map->alpha_to_trie_map) 218 | free (alpha_map->alpha_to_trie_map); 219 | if (alpha_map->trie_to_alpha_map) 220 | free (alpha_map->trie_to_alpha_map); 221 | 222 | free (alpha_map); 223 | } 224 | 225 | AlphaMap * 226 | alpha_map_fread_bin (FILE *file) 227 | { 228 | long save_pos; 229 | uint32 sig; 230 | int32 total, i; 231 | AlphaMap *alpha_map; 232 | 233 | /* check signature */ 234 | save_pos = ftell (file); 235 | if (!file_read_int32 (file, (int32 *) &sig) || ALPHAMAP_SIGNATURE != sig) 236 | goto exit_file_read; 237 | 238 | alpha_map = alpha_map_new (); 239 | if (UNLIKELY (!alpha_map)) 240 | goto exit_file_read; 241 | 242 | /* read number of ranges */ 243 | if (!file_read_int32 (file, &total)) 244 | goto exit_map_created; 245 | 246 | /* read character ranges */ 247 | for (i = 0; i < total; i++) { 248 | int32 b, e; 249 | 250 | if (!file_read_int32 (file, &b) || !file_read_int32 (file, &e)) 251 | goto exit_map_created; 252 | alpha_map_add_range_only (alpha_map, b, e); 253 | } 254 | 255 | /* work area */ 256 | if (UNLIKELY (alpha_map_recalc_work_area (alpha_map) != 0)) 257 | goto exit_map_created; 258 | 259 | return alpha_map; 260 | 261 | exit_map_created: 262 | alpha_map_free (alpha_map); 263 | exit_file_read: 264 | fseek (file, save_pos, SEEK_SET); 265 | return NULL; 266 | } 267 | 268 | static int 269 | alpha_map_get_total_ranges (const AlphaMap *alpha_map) 270 | { 271 | int n; 272 | AlphaRange *range; 273 | 274 | for (n = 0, range = alpha_map->first_range; range; range = range->next) { 275 | ++n; 276 | } 277 | 278 | return n; 279 | } 280 | 281 | int 282 | alpha_map_fwrite_bin (const AlphaMap *alpha_map, FILE *file) 283 | { 284 | AlphaRange *range; 285 | 286 | if (!file_write_int32 (file, ALPHAMAP_SIGNATURE) || 287 | !file_write_int32 (file, alpha_map_get_total_ranges (alpha_map))) 288 | { 289 | return -1; 290 | } 291 | 292 | for (range = alpha_map->first_range; range; range = range->next) { 293 | if (!file_write_int32 (file, range->begin) || 294 | !file_write_int32 (file, range->end)) 295 | { 296 | return -1; 297 | } 298 | } 299 | 300 | return 0; 301 | } 302 | 303 | size_t 304 | alpha_map_get_serialized_size (const AlphaMap *alpha_map) 305 | { 306 | int32 ranges_count = alpha_map_get_total_ranges (alpha_map); 307 | return ( 308 | 4 /* ALPHAMAP_SIGNATURE */ 309 | + sizeof (ranges_count) 310 | + (sizeof (AlphaChar) * 2) * ranges_count /* range->begin, range->end */ 311 | ); 312 | } 313 | 314 | void 315 | alpha_map_serialize_bin (const AlphaMap *alpha_map, uint8 **ptr) 316 | { 317 | AlphaRange *range; 318 | serialize_int32_be_incr (ptr, ALPHAMAP_SIGNATURE); 319 | serialize_int32_be_incr (ptr, alpha_map_get_total_ranges (alpha_map)); 320 | 321 | for (range = alpha_map->first_range; range; range = range->next) { 322 | serialize_int32_be_incr (ptr, range->begin); 323 | serialize_int32_be_incr (ptr, range->end); 324 | } 325 | } 326 | 327 | static int 328 | alpha_map_add_range_only (AlphaMap *alpha_map, AlphaChar begin, AlphaChar end) 329 | { 330 | AlphaRange *q, *r, *begin_node, *end_node; 331 | 332 | if (begin > end) 333 | return -1; 334 | 335 | begin_node = end_node = 0; 336 | 337 | /* Skip first ranges till 'begin' is covered */ 338 | for (q = 0, r = alpha_map->first_range; 339 | r && r->begin <= begin; 340 | q = r, r = r->next) 341 | { 342 | if (begin <= r->end) { 343 | /* 'r' covers 'begin' -> take 'r' as beginning point */ 344 | begin_node = r; 345 | break; 346 | } 347 | if (r->end + 1 == begin) { 348 | /* 'begin' is next to 'r'-end 349 | * -> extend 'r'-end to cover 'begin' 350 | */ 351 | r->end = begin; 352 | begin_node = r; 353 | break; 354 | } 355 | } 356 | if (!begin_node && r && r->begin <= end + 1) { 357 | /* ['begin', 'end'] overlaps into 'r'-begin 358 | * or 'r' is next to 'end' if r->begin == end + 1 359 | * -> extend 'r'-begin to include the range 360 | */ 361 | r->begin = begin; 362 | begin_node = r; 363 | } 364 | /* Run upto the first range that exceeds 'end' */ 365 | while (r && r->begin <= end + 1) { 366 | if (end <= r->end) { 367 | /* 'r' covers 'end' -> take 'r' as ending point */ 368 | end_node = r; 369 | } else if (r != begin_node) { 370 | /* ['begin', 'end'] covers the whole 'r' -> remove 'r' */ 371 | if (q) { 372 | q->next = r->next; 373 | free (r); 374 | r = q->next; 375 | } else { 376 | alpha_map->first_range = r->next; 377 | free (r); 378 | r = alpha_map->first_range; 379 | } 380 | continue; 381 | } 382 | q = r; 383 | r = r->next; 384 | } 385 | if (!end_node && q && begin <= q->end) { 386 | /* ['begin', 'end'] overlaps 'q' at the end 387 | * -> extend 'q'-end to include the range 388 | */ 389 | q->end = end; 390 | end_node = q; 391 | } 392 | 393 | if (begin_node && end_node) { 394 | if (begin_node != end_node) { 395 | /* Merge begin_node and end_node ranges together */ 396 | assert (begin_node->next == end_node); 397 | begin_node->end = end_node->end; 398 | begin_node->next = end_node->next; 399 | free (end_node); 400 | } 401 | } else if (!begin_node && !end_node) { 402 | /* ['begin', 'end'] overlaps with none of the ranges 403 | * -> insert a new range 404 | */ 405 | AlphaRange *range = (AlphaRange *) malloc (sizeof (AlphaRange)); 406 | 407 | if (UNLIKELY (!range)) 408 | return -1; 409 | 410 | range->begin = begin; 411 | range->end = end; 412 | 413 | /* insert it between 'q' and 'r' */ 414 | if (q) { 415 | q->next = range; 416 | } else { 417 | alpha_map->first_range = range; 418 | } 419 | range->next = r; 420 | } 421 | 422 | return 0; 423 | } 424 | 425 | static int 426 | alpha_map_recalc_work_area (AlphaMap *alpha_map) 427 | { 428 | AlphaRange *range; 429 | 430 | /* free old existing map */ 431 | if (alpha_map->alpha_to_trie_map) { 432 | free (alpha_map->alpha_to_trie_map); 433 | alpha_map->alpha_to_trie_map = NULL; 434 | } 435 | if (alpha_map->trie_to_alpha_map) { 436 | free (alpha_map->trie_to_alpha_map); 437 | alpha_map->trie_to_alpha_map = NULL; 438 | } 439 | 440 | range = alpha_map->first_range; 441 | if (range) { 442 | const AlphaChar alpha_begin = range->begin; 443 | int n_alpha, n_trie, i; 444 | AlphaChar a; 445 | TrieIndex trie_char; 446 | 447 | alpha_map->alpha_begin = alpha_begin; 448 | n_trie = 0; 449 | for ( ;; ) { 450 | n_trie += range->end - range->begin + 1; 451 | if (!range->next) 452 | break; 453 | range = range->next; 454 | } 455 | if (n_trie < TRIE_CHAR_TERM) { 456 | n_trie = TRIE_CHAR_TERM + 1; 457 | } else { 458 | n_trie++; 459 | } 460 | alpha_map->alpha_end = range->end; 461 | 462 | alpha_map->alpha_map_sz = n_alpha = range->end - alpha_begin + 1; 463 | alpha_map->alpha_to_trie_map 464 | = (TrieIndex *) malloc (n_alpha * sizeof (TrieIndex)); 465 | if (UNLIKELY (!alpha_map->alpha_to_trie_map)) 466 | goto error_alpha_map_not_created; 467 | for (i = 0; i < n_alpha; i++) { 468 | alpha_map->alpha_to_trie_map[i] = TRIE_INDEX_MAX; 469 | } 470 | 471 | alpha_map->trie_map_sz = n_trie; 472 | alpha_map->trie_to_alpha_map 473 | = (AlphaChar *) malloc (n_trie * sizeof (AlphaChar)); 474 | if (UNLIKELY (!alpha_map->trie_to_alpha_map)) 475 | goto error_alpha_map_created; 476 | 477 | trie_char = 0; 478 | for (range = alpha_map->first_range; range; range = range->next) { 479 | for (a = range->begin; a <= range->end; a++) { 480 | if (TRIE_CHAR_TERM == trie_char) 481 | trie_char++; 482 | alpha_map->alpha_to_trie_map[a - alpha_begin] = trie_char; 483 | alpha_map->trie_to_alpha_map[trie_char] = a; 484 | trie_char++; 485 | } 486 | } 487 | while (trie_char < n_trie) { 488 | alpha_map->trie_to_alpha_map[trie_char++] = ALPHA_CHAR_ERROR; 489 | } 490 | alpha_map->trie_to_alpha_map[TRIE_CHAR_TERM] = 0; 491 | } 492 | 493 | return 0; 494 | 495 | error_alpha_map_created: 496 | free (alpha_map->alpha_to_trie_map); 497 | alpha_map->alpha_to_trie_map = NULL; 498 | error_alpha_map_not_created: 499 | return -1; 500 | } 501 | 502 | /** 503 | * @brief Add a range to alphabet map 504 | * 505 | * @param alpha_map : the alphabet map object 506 | * @param begin : the first character of the range 507 | * @param end : the last character of the range 508 | * 509 | * @return 0 on success, non-zero on failure 510 | * 511 | * Add a range of character codes from @a begin to @a end to the 512 | * alphabet set. 513 | */ 514 | int 515 | alpha_map_add_range (AlphaMap *alpha_map, AlphaChar begin, AlphaChar end) 516 | { 517 | int res = alpha_map_add_range_only (alpha_map, begin, end); 518 | if (res != 0) 519 | return res; 520 | return alpha_map_recalc_work_area (alpha_map); 521 | } 522 | 523 | TrieIndex 524 | alpha_map_char_to_trie (const AlphaMap *alpha_map, AlphaChar ac) 525 | { 526 | TrieIndex alpha_begin; 527 | 528 | if (UNLIKELY (0 == ac)) 529 | return TRIE_CHAR_TERM; 530 | 531 | if (UNLIKELY (!alpha_map->alpha_to_trie_map)) 532 | return TRIE_INDEX_MAX; 533 | 534 | alpha_begin = alpha_map->alpha_begin; 535 | if (alpha_begin <= ac && ac <= alpha_map->alpha_end) 536 | { 537 | return alpha_map->alpha_to_trie_map[ac - alpha_begin]; 538 | } 539 | 540 | return TRIE_INDEX_MAX; 541 | } 542 | 543 | AlphaChar 544 | alpha_map_trie_to_char (const AlphaMap *alpha_map, TrieChar tc) 545 | { 546 | if (tc < alpha_map->trie_map_sz) 547 | return alpha_map->trie_to_alpha_map[tc]; 548 | 549 | return ALPHA_CHAR_ERROR; 550 | } 551 | 552 | TrieChar * 553 | alpha_map_char_to_trie_str (const AlphaMap *alpha_map, const AlphaChar *str) 554 | { 555 | TrieChar *trie_str, *p; 556 | 557 | trie_str = (TrieChar *) malloc (alpha_char_strlen (str) + 1); 558 | if (UNLIKELY (!trie_str)) 559 | return NULL; 560 | 561 | for (p = trie_str; *str; p++, str++) { 562 | TrieIndex tc = alpha_map_char_to_trie (alpha_map, *str); 563 | if (TRIE_INDEX_MAX == tc) 564 | goto error_str_allocated; 565 | *p = (TrieChar) tc; 566 | } 567 | *p = TRIE_CHAR_TERM; 568 | 569 | return trie_str; 570 | 571 | error_str_allocated: 572 | free (trie_str); 573 | return NULL; 574 | } 575 | 576 | AlphaChar * 577 | alpha_map_trie_to_char_str (const AlphaMap *alpha_map, const TrieChar *str) 578 | { 579 | AlphaChar *alpha_str, *p; 580 | 581 | alpha_str = (AlphaChar *) malloc ((trie_char_strlen (str) + 1) 582 | * sizeof (AlphaChar)); 583 | if (UNLIKELY (!alpha_str)) 584 | return NULL; 585 | 586 | for (p = alpha_str; *str; p++, str++) { 587 | *p = (AlphaChar) alpha_map_trie_to_char (alpha_map, *str); 588 | } 589 | *p = 0; 590 | 591 | return alpha_str; 592 | } 593 | 594 | /* 595 | vi:ts=4:ai:expandtab 596 | */ 597 | --------------------------------------------------------------------------------