middlemac 3.1.0 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/ext/trie/darray.h ADDED
@@ -0,0 +1,233 @@
1
+ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
+ /*
3
+ * darray.h - Double-array trie structure
4
+ * Created: 2006-08-11
5
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
6
+ */
7
+
8
+ #ifndef __DARRAY_H
9
+ #define __DARRAY_H
10
+
11
+ #include "triedefs.h"
12
+
13
+ /**
14
+ * @file darray.h
15
+ * @brief Double-array trie structure
16
+ */
17
+
18
+ /**
19
+ * @brief Double-array structure type
20
+ */
21
+ typedef struct _DArray DArray;
22
+
23
+ /**
24
+ * @brief Double-array entry enumeration function
25
+ *
26
+ * @param key : the key of the entry, up to @a sep_node
27
+ * @param sep_node : the separate node of the entry
28
+ * @param user_data : user-supplied data
29
+ *
30
+ * @return TRUE to continue enumeration, FALSE to stop
31
+ */
32
+ typedef Bool (*DAEnumFunc) (const TrieChar *key,
33
+ TrieIndex sep_node,
34
+ void *user_data);
35
+
36
+
37
+ /**
38
+ * @brief Create a new double-array object
39
+ *
40
+ * Create a new empty doubla-array object.
41
+ */
42
+ DArray * da_new ();
43
+
44
+ /**
45
+ * @brief Read double-array data from file
46
+ *
47
+ * @param file : the file to read
48
+ *
49
+ * @return a pointer to the openned double-array, NULL on failure
50
+ *
51
+ * Read double-array data from the opened file, starting from the current
52
+ * file pointer until the end of double array data block. On return, the
53
+ * file pointer is left at the position after the read block.
54
+ */
55
+ DArray * da_read (FILE *file);
56
+
57
+ /**
58
+ * @brief Free double-array data
59
+ *
60
+ * @param d : the double-array data
61
+ *
62
+ * Free the given double-array data.
63
+ */
64
+ void da_free (DArray *d);
65
+
66
+ /**
67
+ * @brief Write double-array data
68
+ *
69
+ * @param d : the double-array data
70
+ * @param file : the file to write to
71
+ *
72
+ * @return 0 on success, non-zero on failure
73
+ *
74
+ * Write double-array data to the given @a file, starting from the current
75
+ * file pointer. On return, the file pointer is left after the double-array
76
+ * data block.
77
+ */
78
+ int da_write (const DArray *d, FILE *file);
79
+
80
+
81
+ /**
82
+ * @brief Get root state
83
+ *
84
+ * @param d : the double-array data
85
+ *
86
+ * @return root state of the @a index set, or TRIE_INDEX_ERROR on failure
87
+ *
88
+ * Get root state for stepwise walking.
89
+ */
90
+ TrieIndex da_get_root (const DArray *d);
91
+
92
+
93
+ /**
94
+ * @brief Get BASE cell
95
+ *
96
+ * @param d : the double-array data
97
+ * @param s : the double-array state to get data
98
+ *
99
+ * @return the BASE cell value for the given state
100
+ *
101
+ * Get BASE cell value for the given state.
102
+ */
103
+ TrieIndex da_get_base (const DArray *d, TrieIndex s);
104
+
105
+ /**
106
+ * @brief Get CHECK cell
107
+ *
108
+ * @param d : the double-array data
109
+ * @param s : the double-array state to get data
110
+ *
111
+ * @return the CHECK cell value for the given state
112
+ *
113
+ * Get CHECK cell value for the given state.
114
+ */
115
+ TrieIndex da_get_check (const DArray *d, TrieIndex s);
116
+
117
+
118
+ /**
119
+ * @brief Set BASE cell
120
+ *
121
+ * @param d : the double-array data
122
+ * @param s : the double-array state to get data
123
+ * @param val : the value to set
124
+ *
125
+ * Set BASE cell for the given state to the given value.
126
+ */
127
+ void da_set_base (DArray *d, TrieIndex s, TrieIndex val);
128
+
129
+ /**
130
+ * @brief Set CHECK cell
131
+ *
132
+ * @param d : the double-array data
133
+ * @param s : the double-array state to get data
134
+ * @param val : the value to set
135
+ *
136
+ * Set CHECK cell for the given state to the given value.
137
+ */
138
+ void da_set_check (DArray *d, TrieIndex s, TrieIndex val);
139
+
140
+ /**
141
+ * @brief Walk in double-array structure
142
+ *
143
+ * @param d : the double-array structure
144
+ * @param s : current state
145
+ * @param c : the input character
146
+ *
147
+ * @return boolean indicating success
148
+ *
149
+ * Walk the double-array trie from state @a *s, using input character @a c.
150
+ * If there exists an edge from @a *s with arc labeled @a c, this function
151
+ * returns TRUE and @a *s is updated to the new state. Otherwise, it returns
152
+ * FALSE and @a *s is left unchanged.
153
+ */
154
+ Bool da_walk (const DArray *d, TrieIndex *s, TrieChar c);
155
+
156
+ /**
157
+ * @brief Test walkability in double-array structure
158
+ *
159
+ * @param d : the double-array structure
160
+ * @param s : current state
161
+ * @param c : the input character
162
+ *
163
+ * @return boolean indicating walkability
164
+ *
165
+ * Test if there is a transition from state @a s with input character @a c.
166
+ */
167
+ /*
168
+ Bool da_is_walkable (DArray *d, TrieIndex s, TrieChar c);
169
+ */
170
+ #define da_is_walkable(d,s,c) \
171
+ (da_get_check ((d), da_get_base ((d), (s)) + (c)) == (s))
172
+
173
+ /**
174
+ * @brief Insert a branch from trie node
175
+ *
176
+ * @param d : the double-array structure
177
+ * @param s : the state to add branch to
178
+ * @param c : the character for the branch label
179
+ *
180
+ * @return the index of the new node
181
+ *
182
+ * Insert a new arc labelled with character @a c from the trie node
183
+ * represented by index @a s in double-array structure @a d.
184
+ * Note that it assumes that no such arc exists before inserting.
185
+ */
186
+ TrieIndex da_insert_branch (DArray *d, TrieIndex s, TrieChar c);
187
+
188
+ /**
189
+ * @brief Prune the single branch
190
+ *
191
+ * @param d : the double-array structure
192
+ * @param s : the dangling state to prune off
193
+ *
194
+ * Prune off a non-separate path up from the final state @a s.
195
+ * If @a s still has some children states, it does nothing. Otherwise,
196
+ * it deletes the node and all its parents which become non-separate.
197
+ */
198
+ void da_prune (DArray *d, TrieIndex s);
199
+
200
+ /**
201
+ * @brief Prune the single branch up to given parent
202
+ *
203
+ * @param d : the double-array structure
204
+ * @param p : the parent up to which to be pruned
205
+ * @param s : the dangling state to prune off
206
+ *
207
+ * Prune off a non-separate path up from the final state @a s to the
208
+ * given parent @a p. The prunning stop when either the parent @a p
209
+ * is met, or a first non-separate node is found.
210
+ */
211
+ void da_prune_upto (DArray *d, TrieIndex p, TrieIndex s);
212
+
213
+ /**
214
+ * @brief Enumerate entries stored in double-array structure
215
+ *
216
+ * @param d : the double-array structure
217
+ * @param enum_func : the callback function to be called on each separate node
218
+ * @param user_data : user-supplied data to send as an argument to @a enum_func
219
+ *
220
+ * @return boolean value indicating whether all the keys are visited
221
+ *
222
+ * Enumerate all keys stored in double-array structure. For each entry, the
223
+ * user-supplied @a enum_func callback function is called, with the entry key,
224
+ * the separate node, and user-supplied data. Returning FALSE from such
225
+ * callback will stop enumeration and return FALSE.
226
+ */
227
+ Bool da_enumerate (const DArray *d, DAEnumFunc enum_func, void *user_data);
228
+
229
+ #endif /* __DARRAY_H */
230
+
231
+ /*
232
+ vi:ts=4:ai:expandtab
233
+ */
@@ -0,0 +1,23 @@
1
+ require 'mkmf'
2
+
3
+ ##
4
+ ## Avoid warnings, since newer versions of Xcode by default try to make more and more
5
+ ## warnings.
6
+ ##
7
+ append_cflags("-Wno-missing-noreturn")
8
+ append_cflags("-Wno-shorten-64-to-32")
9
+ append_cflags("-Wno-return-type")
10
+ append_cflags("-Wno-sign-compare")
11
+ append_cflags("-Wno-unused-function")
12
+ append_cflags("-Wno-incompatible-pointer-types")
13
+ puts "=-=-=-=-=-=-"
14
+ puts $CFLAGS
15
+ puts "=-=-=-=-=-=-"
16
+
17
+
18
+ ##
19
+ ## If we want it to be installed in lib/trie, then we have to create the makefile
20
+ ## in this nested format, too, otherwise lib_dir works for rake compile, but not
21
+ ## for rake install.
22
+ ##
23
+ create_makefile 'trie/trie'
@@ -0,0 +1,151 @@
1
+ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
+ /*
3
+ * fileutils.h - File utility functions
4
+ * Created: 2006-08-15
5
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
6
+ */
7
+
8
+ #include <string.h>
9
+ #include <stdlib.h>
10
+
11
+ #include "fileutils.h"
12
+
13
+ /*--------------------------------------*
14
+ * INTERNAL FUNCTIONS DECLARATIONS *
15
+ *--------------------------------------*/
16
+
17
+ static char * make_full_path (const char *dir,
18
+ const char *name,
19
+ const char *ext);
20
+
21
+ /* ==================== BEGIN IMPLEMENTATION PART ==================== */
22
+
23
+ /*--------------------------------*
24
+ * FUNCTIONS IMPLEMENTATIONS *
25
+ *--------------------------------*/
26
+
27
+ static char *
28
+ make_full_path (const char *dir, const char *name, const char *ext)
29
+ {
30
+ char *path;
31
+
32
+ path = (char *) malloc (strlen (dir) + strlen (name) + strlen (ext) + 2);
33
+ sprintf (path, "%s/%s%s", dir, name, ext);
34
+
35
+ return path;
36
+ }
37
+
38
+ FILE *
39
+ file_open (const char *dir, const char *name, const char *ext, TrieIOMode mode)
40
+ {
41
+ const char *std_mode;
42
+ char *full_path;
43
+ FILE *file;
44
+
45
+ if (mode & TRIE_IO_WRITE)
46
+ std_mode = "r+";
47
+ else
48
+ std_mode = "r";
49
+
50
+ full_path = make_full_path (dir, name, ext);
51
+ file = fopen (full_path, std_mode);
52
+ if (!file && mode & TRIE_IO_CREATE)
53
+ file = fopen (full_path, "w+");
54
+ free (full_path);
55
+
56
+ return file;
57
+ }
58
+
59
+ long
60
+ file_length (FILE *file)
61
+ {
62
+ long cur_pos;
63
+ long size;
64
+
65
+ cur_pos = ftell (file);
66
+
67
+ fseek (file, 0L, SEEK_END);
68
+ size = ftell (file);
69
+
70
+ fseek (file, cur_pos, SEEK_SET);
71
+
72
+ return size;
73
+ }
74
+
75
+ Bool
76
+ file_read_int32 (FILE *file, int32 *o_val)
77
+ {
78
+ unsigned char buff[4];
79
+
80
+ if (fread (buff, 4, 1, file) == 1) {
81
+ *o_val = (buff[0] << 24) | (buff[1] << 16) | (buff[2] << 8) | buff[3];
82
+ return TRUE;
83
+ }
84
+
85
+ return FALSE;
86
+ }
87
+
88
+ Bool
89
+ file_write_int32 (FILE *file, int32 val)
90
+ {
91
+ unsigned char buff[4];
92
+
93
+ buff[0] = (val >> 24) & 0xff;
94
+ buff[1] = (val >> 16) & 0xff;
95
+ buff[2] = (val >> 8) & 0xff;
96
+ buff[3] = val & 0xff;
97
+
98
+ return (fwrite (buff, 4, 1, file) == 1);
99
+ }
100
+
101
+ Bool
102
+ file_read_int16 (FILE *file, int16 *o_val)
103
+ {
104
+ unsigned char buff[2];
105
+
106
+ if (fread (buff, 2, 1, file) == 1) {
107
+ *o_val = (buff[0] << 8) | buff[1];
108
+ return TRUE;
109
+ }
110
+
111
+ return FALSE;
112
+ }
113
+
114
+ Bool
115
+ file_write_int16 (FILE *file, int16 val)
116
+ {
117
+ unsigned char buff[2];
118
+
119
+ buff[0] = val >> 8;
120
+ buff[1] = val & 0xff;
121
+
122
+ return (fwrite (buff, 2, 1, file) == 1);
123
+ }
124
+
125
+ Bool
126
+ file_read_int8 (FILE *file, int8 *o_val)
127
+ {
128
+ return (fread (o_val, sizeof (int8), 1, file) == 1);
129
+ }
130
+
131
+ Bool
132
+ file_write_int8 (FILE *file, int8 val)
133
+ {
134
+ return (fwrite (&val, sizeof (int8), 1, file) == 1);
135
+ }
136
+
137
+ Bool
138
+ file_read_chars (FILE *file, char *buff, int len)
139
+ {
140
+ return (fread (buff, sizeof (char), len, file) == len);
141
+ }
142
+
143
+ Bool
144
+ file_write_chars (FILE *file, const char *buff, int len)
145
+ {
146
+ return (fwrite (buff, sizeof (char), len, file) == len);
147
+ }
148
+
149
+ /*
150
+ vi:ts=4:ai:expandtab
151
+ */
@@ -0,0 +1,36 @@
1
+ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
+ /*
3
+ * fileutils.h - File utility functions
4
+ * Created: 2006-08-14
5
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
6
+ */
7
+
8
+ #ifndef __FILEUTILS_H
9
+ #define __FILEUTILS_H
10
+
11
+ #include <stdio.h>
12
+
13
+ #include "triedefs.h"
14
+
15
+ FILE * file_open (const char *dir, const char *name, const char *ext,
16
+ TrieIOMode mode);
17
+
18
+ long file_length (FILE *file);
19
+
20
+ Bool file_read_int32 (FILE *file, int32 *o_val);
21
+ Bool file_write_int32 (FILE *file, int32 val);
22
+
23
+ Bool file_read_int16 (FILE *file, int16 *o_val);
24
+ Bool file_write_int16 (FILE *file, int16 val);
25
+
26
+ Bool file_read_int8 (FILE *file, int8 *o_val);
27
+ Bool file_write_int8 (FILE *file, int8 val);
28
+
29
+ Bool file_read_chars (FILE *file, char *buff, int len);
30
+ Bool file_write_chars (FILE *file, const char *buff, int len);
31
+
32
+ #endif /* __FILEUTILS_H */
33
+
34
+ /*
35
+ vi:ts=4:ai:expandtab
36
+ */
data/ext/trie/tail.c ADDED
@@ -0,0 +1,340 @@
1
+ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
+ /*
3
+ * tail.c - trie tail for keeping suffixes
4
+ * Created: 2006-08-15
5
+ * Author: Theppitak Karoonboonyanan <thep@linux.thai.net>
6
+ */
7
+
8
+ #include <string.h>
9
+ #include <stdlib.h>
10
+ #include <stdio.h>
11
+
12
+ #include "tail.h"
13
+ #include "fileutils.h"
14
+
15
+ /*----------------------------------*
16
+ * INTERNAL TYPES DECLARATIONS *
17
+ *----------------------------------*/
18
+
19
+ /*-----------------------------------*
20
+ * PRIVATE METHODS DECLARATIONS *
21
+ *-----------------------------------*/
22
+
23
+ static TrieIndex tail_alloc_block (Tail *t);
24
+ static void tail_free_block (Tail *t, TrieIndex block);
25
+
26
+ /* ==================== BEGIN IMPLEMENTATION PART ==================== */
27
+
28
+ /*------------------------------------*
29
+ * INTERNAL TYPES IMPLEMENTATIONS *
30
+ *------------------------------------*/
31
+
32
+ /*------------------------------*
33
+ * PRIVATE DATA DEFINITONS *
34
+ *------------------------------*/
35
+
36
+ typedef struct {
37
+ TrieIndex next_free;
38
+ TrieData data;
39
+ TrieChar *suffix;
40
+ } TailBlock;
41
+
42
+ struct _Tail {
43
+ TrieIndex num_tails;
44
+ TailBlock *tails;
45
+ TrieIndex first_free;
46
+ };
47
+
48
+ /*-----------------------------*
49
+ * METHODS IMPLEMENTAIONS *
50
+ *-----------------------------*/
51
+
52
+ #define TAIL_SIGNATURE 0xDFFCDFFC
53
+ #define TAIL_START_BLOCKNO 1
54
+
55
+ /* Tail Header:
56
+ * INT32: signature
57
+ * INT32: pointer to first free slot
58
+ * INT32: number of tail blocks
59
+ *
60
+ * Tail Blocks:
61
+ * INT32: pointer to next free block (-1 for allocated blocks)
62
+ * INT32: data for the key
63
+ * INT16: length
64
+ * BYTES[length]: suffix string (no terminating '\0')
65
+ */
66
+
67
+ Tail *
68
+ tail_new ()
69
+ {
70
+ Tail *t;
71
+
72
+ t = (Tail *) malloc (sizeof (Tail));
73
+ if (!t)
74
+ return NULL;
75
+
76
+ t->first_free = 0;
77
+ t->num_tails = 0;
78
+ t->tails = NULL;
79
+
80
+ return t;
81
+ }
82
+
83
+ Tail *
84
+ tail_read (FILE *file)
85
+ {
86
+ long save_pos;
87
+ Tail *t;
88
+ TrieIndex i;
89
+ uint32 sig;
90
+
91
+ /* check signature */
92
+ save_pos = ftell (file);
93
+ if (!file_read_int32 (file, (int32 *) &sig) || TAIL_SIGNATURE != sig) {
94
+ fseek (file, save_pos, SEEK_SET);
95
+ return NULL;
96
+ }
97
+
98
+ t = (Tail *) malloc (sizeof (Tail));
99
+ if (!t)
100
+ return NULL;
101
+
102
+ file_read_int32 (file, &t->first_free);
103
+ file_read_int32 (file, &t->num_tails);
104
+ t->tails = (TailBlock *) malloc (t->num_tails * sizeof (TailBlock));
105
+ if (!t->tails)
106
+ goto exit_tail_created;
107
+ for (i = 0; i < t->num_tails; i++) {
108
+ int16 length;
109
+
110
+ file_read_int32 (file, &t->tails[i].next_free);
111
+ file_read_int32 (file, &t->tails[i].data);
112
+
113
+ file_read_int16 (file, &length);
114
+ t->tails[i].suffix = (TrieChar *) malloc (length + 1);
115
+ if (length > 0)
116
+ file_read_chars (file, (char *)t->tails[i].suffix, length);
117
+ t->tails[i].suffix[length] = '\0';
118
+ }
119
+
120
+ return t;
121
+
122
+ exit_tail_created:
123
+ free (t);
124
+ return NULL;
125
+ }
126
+
127
+ void
128
+ tail_free (Tail *t)
129
+ {
130
+ TrieIndex i;
131
+
132
+ if (t->tails) {
133
+ for (i = 0; i < t->num_tails; i++)
134
+ if (t->tails[i].suffix)
135
+ free (t->tails[i].suffix);
136
+ free (t->tails);
137
+ }
138
+ free (t);
139
+ }
140
+
141
+ int
142
+ tail_write (const Tail *t, FILE *file)
143
+ {
144
+ TrieIndex i;
145
+
146
+ if (!file_write_int32 (file, TAIL_SIGNATURE) ||
147
+ !file_write_int32 (file, t->first_free) ||
148
+ !file_write_int32 (file, t->num_tails))
149
+ {
150
+ return -1;
151
+ }
152
+ for (i = 0; i < t->num_tails; i++) {
153
+ int16 length;
154
+
155
+ if (!file_write_int32 (file, t->tails[i].next_free) ||
156
+ !file_write_int32 (file, t->tails[i].data))
157
+ {
158
+ return -1;
159
+ }
160
+
161
+ length = t->tails[i].suffix ? strlen ((const char *)t->tails[i].suffix)
162
+ : 0;
163
+ if (!file_write_int16 (file, length))
164
+ return -1;
165
+ if (length > 0 &&
166
+ !file_write_chars (file, (char *)t->tails[i].suffix, length))
167
+ {
168
+ return -1;
169
+ }
170
+ }
171
+
172
+ return 0;
173
+ }
174
+
175
+
176
+ const TrieChar *
177
+ tail_get_suffix (const Tail *t, TrieIndex index)
178
+ {
179
+ index -= TAIL_START_BLOCKNO;
180
+ return (index < t->num_tails) ? t->tails[index].suffix : NULL;
181
+ }
182
+
183
+ Bool
184
+ tail_set_suffix (Tail *t, TrieIndex index, const TrieChar *suffix)
185
+ {
186
+ index -= TAIL_START_BLOCKNO;
187
+ if (index < t->num_tails) {
188
+ /* suffix and t->tails[index].suffix may overlap;
189
+ * so, dup it before it's overwritten
190
+ */
191
+ TrieChar *tmp = NULL;
192
+ if (suffix)
193
+ tmp = (TrieChar *) strdup ((const char *)suffix);
194
+ if (t->tails[index].suffix)
195
+ free (t->tails[index].suffix);
196
+ t->tails[index].suffix = tmp;
197
+
198
+ return TRUE;
199
+ }
200
+ return FALSE;
201
+ }
202
+
203
+ TrieIndex
204
+ tail_add_suffix (Tail *t, const TrieChar *suffix)
205
+ {
206
+ TrieIndex new_block;
207
+
208
+ new_block = tail_alloc_block (t);
209
+ tail_set_suffix (t, new_block, suffix);
210
+
211
+ return new_block;
212
+ }
213
+
214
+ static TrieIndex
215
+ tail_alloc_block (Tail *t)
216
+ {
217
+ TrieIndex block;
218
+
219
+ if (0 != t->first_free) {
220
+ block = t->first_free;
221
+ t->first_free = t->tails[block].next_free;
222
+ } else {
223
+ block = t->num_tails;
224
+ t->tails = (TailBlock *) realloc (t->tails,
225
+ ++t->num_tails * sizeof (TailBlock));
226
+ }
227
+ t->tails[block].next_free = -1;
228
+ t->tails[block].data = TRIE_DATA_ERROR;
229
+ t->tails[block].suffix = NULL;
230
+
231
+ return block + TAIL_START_BLOCKNO;
232
+ }
233
+
234
+ static void
235
+ tail_free_block (Tail *t, TrieIndex block)
236
+ {
237
+ TrieIndex i, j;
238
+
239
+ block -= TAIL_START_BLOCKNO;
240
+
241
+ if (block >= t->num_tails)
242
+ return;
243
+
244
+ t->tails[block].data = TRIE_DATA_ERROR;
245
+ if (NULL != t->tails[block].suffix) {
246
+ free (t->tails[block].suffix);
247
+ t->tails[block].suffix = NULL;
248
+ }
249
+
250
+ /* find insertion point */
251
+ j = 0;
252
+ for (i = t->first_free; i != 0 && i < block; i = t->tails[i].next_free)
253
+ j = i;
254
+
255
+ /* insert free block between j and i */
256
+ t->tails[block].next_free = i;
257
+ if (0 != j)
258
+ t->tails[j].next_free = block;
259
+ else
260
+ t->first_free = block;
261
+ }
262
+
263
+ TrieData
264
+ tail_get_data (const Tail *t, TrieIndex index)
265
+ {
266
+ index -= TAIL_START_BLOCKNO;
267
+ return (index < t->num_tails) ? t->tails[index].data : TRIE_DATA_ERROR;
268
+ }
269
+
270
+ Bool
271
+ tail_set_data (Tail *t, TrieIndex index, TrieData data)
272
+ {
273
+ index -= TAIL_START_BLOCKNO;
274
+ if (index < t->num_tails) {
275
+ t->tails[index].data = data;
276
+ return TRUE;
277
+ }
278
+ return FALSE;
279
+ }
280
+
281
+ void
282
+ tail_delete (Tail *t, TrieIndex index)
283
+ {
284
+ tail_free_block (t, index);
285
+ }
286
+
287
+ int
288
+ tail_walk_str (const Tail *t,
289
+ TrieIndex s,
290
+ short *suffix_idx,
291
+ const TrieChar *str,
292
+ int len)
293
+ {
294
+ const TrieChar *suffix;
295
+ int i;
296
+ short j;
297
+
298
+ suffix = tail_get_suffix (t, s);
299
+ if (!suffix)
300
+ return FALSE;
301
+
302
+ i = 0; j = *suffix_idx;
303
+ while (i < len) {
304
+ if (str[i] != suffix[j])
305
+ break;
306
+ ++i;
307
+ /* stop and stay at null-terminator */
308
+ if (0 == suffix[j])
309
+ break;
310
+ ++j;
311
+ }
312
+ *suffix_idx = j;
313
+ return i;
314
+ }
315
+
316
+ Bool
317
+ tail_walk_char (const Tail *t,
318
+ TrieIndex s,
319
+ short *suffix_idx,
320
+ TrieChar c)
321
+ {
322
+ const TrieChar *suffix;
323
+ TrieChar suffix_char;
324
+
325
+ suffix = tail_get_suffix (t, s);
326
+ if (!suffix)
327
+ return FALSE;
328
+
329
+ suffix_char = suffix[*suffix_idx];
330
+ if (suffix_char == c) {
331
+ if (0 != suffix_char)
332
+ ++*suffix_idx;
333
+ return TRUE;
334
+ }
335
+ return FALSE;
336
+ }
337
+
338
+ /*
339
+ vi:ts=4:ai:expandtab
340
+ */