diff --git a/contrib/unaccent/unaccent.c b/contrib/unaccent/unaccent.c new file mode 100644 index 4182376..8caa7c2 *** a/contrib/unaccent/unaccent.c --- b/contrib/unaccent/unaccent.c *************** *** 23,52 **** PG_MODULE_MAGIC; /* ! * Unaccent dictionary uses uncompressed suffix tree to find a ! * character to replace. Each node of tree is an array of ! * SuffixChar struct with length = 256 (n-th element of array * corresponds to byte) */ ! typedef struct SuffixChar { ! struct SuffixChar *nextChar; char *replaceTo; int replacelen; ! } SuffixChar; /* ! * placeChar - put str into tree's structure, byte by byte. */ ! static SuffixChar * ! placeChar(SuffixChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen) { ! SuffixChar *curnode; if (!node) { ! node = palloc(sizeof(SuffixChar) * 256); ! memset(node, 0, sizeof(SuffixChar) * 256); } curnode = node + *str; --- 23,51 ---- PG_MODULE_MAGIC; /* ! * Unaccent dictionary uses trie to find a character to replace. Each node of ! * trie is an array of TrieChar struct with length = 256 (n-th element of array * corresponds to byte) */ ! typedef struct TrieChar { ! struct TrieChar *nextChar; char *replaceTo; int replacelen; ! } TrieChar; /* ! * placeChar - put str into trie's structure, byte by byte. */ ! static TrieChar * ! placeChar(TrieChar *node, unsigned char *str, int lenstr, char *replaceTo, int replacelen) { ! TrieChar *curnode; if (!node) { ! node = palloc(sizeof(TrieChar) * 256); ! memset(node, 0, sizeof(TrieChar) * 256); } curnode = node + *str; *************** placeChar(SuffixChar *node, unsigned cha *** 71,83 **** } /* ! * initSuffixTree - create suffix tree from file. Function converts * UTF8-encoded file into current encoding. */ ! static SuffixChar * ! initSuffixTree(char *filename) { ! SuffixChar *volatile rootSuffixTree = NULL; MemoryContext ccxt = CurrentMemoryContext; tsearch_readline_state trst; volatile bool skip; --- 70,82 ---- } /* ! * initTrie - create trie from file. Function converts * UTF8-encoded file into current encoding. */ ! static TrieChar * ! initTrie(char *filename) { ! TrieChar *volatile rootTrie = NULL; MemoryContext ccxt = CurrentMemoryContext; tsearch_readline_state trst; volatile bool skip; *************** initSuffixTree(char *filename) *** 161,167 **** } if (state >= 3) ! rootSuffixTree = placeChar(rootSuffixTree, (unsigned char *) src, srclen, trg, trglen); --- 160,166 ---- } if (state >= 3) ! rootTrie = placeChar(rootTrie, (unsigned char *) src, srclen, trg, trglen); *************** initSuffixTree(char *filename) *** 192,205 **** tsearch_readline_end(&trst); ! return rootSuffixTree; } /* ! * findReplaceTo - find multibyte character in tree */ ! static SuffixChar * ! findReplaceTo(SuffixChar *node, unsigned char *src, int srclen) { while (node) { --- 191,204 ---- tsearch_readline_end(&trst); ! return rootTrie; } /* ! * findReplaceTo - find multibyte character in trie */ ! static TrieChar * ! findReplaceTo(TrieChar *node, unsigned char *src, int srclen) { while (node) { *************** Datum *** 221,227 **** unaccent_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); ! SuffixChar *rootSuffixTree = NULL; bool fileloaded = false; ListCell *l; --- 220,226 ---- unaccent_init(PG_FUNCTION_ARGS) { List *dictoptions = (List *) PG_GETARG_POINTER(0); ! TrieChar *rootTrie = NULL; bool fileloaded = false; ListCell *l; *************** unaccent_init(PG_FUNCTION_ARGS) *** 235,241 **** ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Rules parameters"))); ! rootSuffixTree = initSuffixTree(defGetString(defel)); fileloaded = true; } else --- 234,240 ---- ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("multiple Rules parameters"))); ! rootTrie = initTrie(defGetString(defel)); fileloaded = true; } else *************** unaccent_init(PG_FUNCTION_ARGS) *** 254,260 **** errmsg("missing Rules parameter"))); } ! PG_RETURN_POINTER(rootSuffixTree); } PG_FUNCTION_INFO_V1(unaccent_lexize); --- 253,259 ---- errmsg("missing Rules parameter"))); } ! PG_RETURN_POINTER(rootTrie); } PG_FUNCTION_INFO_V1(unaccent_lexize); *************** Datum unaccent_lexize(PG_FUNCTION_ARGS) *** 262,282 **** Datum unaccent_lexize(PG_FUNCTION_ARGS) { ! SuffixChar *rootSuffixTree = (SuffixChar *) PG_GETARG_POINTER(0); char *srcchar = (char *) PG_GETARG_POINTER(1); int32 len = PG_GETARG_INT32(2); char *srcstart, *trgchar = NULL; int charlen; TSLexeme *res = NULL; ! SuffixChar *node; srcstart = srcchar; while (srcchar - srcstart < len) { charlen = pg_mblen(srcchar); ! node = findReplaceTo(rootSuffixTree, (unsigned char *) srcchar, charlen); if (node && node->replaceTo) { if (!res) --- 261,281 ---- Datum unaccent_lexize(PG_FUNCTION_ARGS) { ! TrieChar *rootTrie = (TrieChar *) PG_GETARG_POINTER(0); char *srcchar = (char *) PG_GETARG_POINTER(1); int32 len = PG_GETARG_INT32(2); char *srcstart, *trgchar = NULL; int charlen; TSLexeme *res = NULL; ! TrieChar *node; srcstart = srcchar; while (srcchar - srcstart < len) { charlen = pg_mblen(srcchar); ! node = findReplaceTo(rootTrie, (unsigned char *) srcchar, charlen); if (node && node->replaceTo) { if (!res)