173 n.ptr = NULL; |
174 n.ptr = NULL; |
174 n.length = 0; |
175 n.length = 0; |
175 return n; |
176 return n; |
176 } |
177 } |
177 |
178 |
|
179 typedef size_t(*prefix_table_rfun)(void*,size_t); |
|
180 typedef void(*prefix_table_wfun)(void*,size_t,size_t); |
|
181 |
|
182 static size_t s_prefix_table_r(void* table, size_t index) { |
|
183 return (size_t) ((uint8_t*)table)[index]; |
|
184 } |
|
185 static void s_prefix_table_w(void* table, size_t index, size_t value) { |
|
186 ((uint8_t*)table)[index] = (uint8_t) value; |
|
187 } |
|
188 static size_t h_prefix_table_r(void* table, size_t index) { |
|
189 return ((size_t*)table)[index]; |
|
190 } |
|
191 static void h_prefix_table_w(void* table, size_t index, size_t value) { |
|
192 ((size_t*)table)[index] = value; |
|
193 } |
|
194 |
178 sstr_t sstrstr(sstr_t string, sstr_t match) { |
195 sstr_t sstrstr(sstr_t string, sstr_t match) { |
179 if (match.length == 0) { |
196 if (match.length == 0) { |
180 return string; |
197 return string; |
181 } |
198 } |
182 |
199 |
183 for (size_t i = 0 ; i < string.length ; i++) { |
200 /* prepare default return value in case of no match */ |
184 sstr_t substr = sstrsubs(string, i); |
201 sstr_t result = sstrn(NULL, 0); |
185 if (sstrprefix(substr, match)) { |
202 |
186 return substr; |
203 /* |
187 } |
204 * IMPORTANT: |
188 } |
205 * our prefix table contains the prefix length PLUS ONE |
189 |
206 * this is our decision, because we want to use the full range of size_t |
190 sstr_t emptystr; |
207 * the original algorithm needs a (-1) at one single place |
191 emptystr.length = 0; |
208 * and we want to avoid that |
192 emptystr.ptr = NULL; |
209 */ |
193 return emptystr; |
210 |
|
211 /* static prefix table */ |
|
212 static uint8_t s_prefix_table[256]; |
|
213 |
|
214 /* check pattern length and use appropriate prefix table */ |
|
215 register void* ptable; |
|
216 prefix_table_rfun ptable_r; |
|
217 prefix_table_wfun ptable_w; |
|
218 if (match.length > 255) { |
|
219 /* pattern exceeds static prefix table, allocate on the heap */ |
|
220 ptable = calloc(match.length+1, sizeof(size_t)); |
|
221 ptable_r = h_prefix_table_r; |
|
222 ptable_w = h_prefix_table_w; |
|
223 } else { |
|
224 ptable = s_prefix_table; |
|
225 ptable_r = s_prefix_table_r; |
|
226 ptable_w = s_prefix_table_w; |
|
227 } |
|
228 |
|
229 /* keep counter in registers */ |
|
230 register size_t i, j; |
|
231 |
|
232 /* fill prefix table */ |
|
233 i = 0; j = 0; |
|
234 ptable_w(ptable, i, j); |
|
235 while (i < match.length) { |
|
236 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { |
|
237 j = ptable_r(ptable, j-i); |
|
238 } |
|
239 i++; j++; |
|
240 ptable_w(ptable, i, j); |
|
241 } |
|
242 |
|
243 /* search */ |
|
244 i = 0; j = 1; |
|
245 while (i < string.length) { |
|
246 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { |
|
247 j = ptable_r(ptable, j-1); |
|
248 } |
|
249 i++; j++; |
|
250 if (j-1 == match.length) { |
|
251 size_t start = i - match.length; |
|
252 result.ptr = string.ptr + start; |
|
253 result.length = string.length - start; |
|
254 break; |
|
255 } |
|
256 } |
|
257 |
|
258 /* if prefix table was allocated on the heap, free it */ |
|
259 if (ptable != s_prefix_table) { |
|
260 free(ptable); |
|
261 } |
|
262 |
|
263 return result; |
194 } |
264 } |
195 |
265 |
196 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { |
266 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { |
197 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
267 return sstrsplit_a(ucx_default_allocator(), s, d, n); |
198 } |
268 } |