middlemac 3.1.0 → 3.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ */