ucx/string.c

changeset 237
5ba9de6361ff
parent 236
ffc6d0910342
child 238
27b31c2c959c
equal deleted inserted replaced
236:ffc6d0910342 237:5ba9de6361ff
174 n.ptr = NULL; 174 n.ptr = NULL;
175 n.length = 0; 175 n.length = 0;
176 return n; 176 return n;
177 } 177 }
178 178
179 typedef size_t(*prefix_table_rfun)(void*,size_t); 179 #define ptable_r(dest, useheap, ptable, index) (dest = useheap ? \
180 typedef void(*prefix_table_wfun)(void*,size_t,size_t); 180 ((size_t*)ptable)[index] : (size_t) ((uint8_t*)ptable)[index])
181 181
182 static size_t s_prefix_table_r(void* table, size_t index) { 182 #define ptable_w(useheap, ptable, index, src) do {\
183 return (size_t) ((uint8_t*)table)[index]; 183 if (!useheap) ((uint8_t*)ptable)[index] = (uint8_t) src;\
184 } 184 else ((size_t*)ptable)[index] = src;\
185 static void s_prefix_table_w(void* table, size_t index, size_t value) { 185 } while (0);
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 186
195 sstr_t sstrstr(sstr_t string, sstr_t match) { 187 sstr_t sstrstr(sstr_t string, sstr_t match) {
196 if (match.length == 0) { 188 if (match.length == 0) {
197 return string; 189 return string;
198 } 190 }
210 202
211 /* static prefix table */ 203 /* static prefix table */
212 static uint8_t s_prefix_table[256]; 204 static uint8_t s_prefix_table[256];
213 205
214 /* check pattern length and use appropriate prefix table */ 206 /* check pattern length and use appropriate prefix table */
215 register void* ptable; 207 /* if the pattern exceeds static prefix table, allocate on the heap */
216 prefix_table_rfun ptable_r; 208 register int useheap = match.length > 255;
217 prefix_table_wfun ptable_w; 209 register void* ptable = useheap ?
218 if (match.length > 255) { 210 calloc(match.length+1, sizeof(size_t)): s_prefix_table;
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 211
229 /* keep counter in registers */ 212 /* keep counter in registers */
230 register size_t i, j; 213 register size_t i, j;
231 214
232 /* fill prefix table */ 215 /* fill prefix table */
233 i = 0; j = 0; 216 i = 0; j = 0;
234 ptable_w(ptable, i, j); 217 ptable_w(useheap, ptable, i, j);
235 while (i < match.length) { 218 while (i < match.length) {
236 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) { 219 while (j >= 1 && match.ptr[j-1] != match.ptr[i]) {
237 j = ptable_r(ptable, j-i); 220 ptable_r(j, useheap, ptable, j-i);
238 } 221 }
239 i++; j++; 222 i++; j++;
240 ptable_w(ptable, i, j); 223 ptable_w(useheap, ptable, i, j);
241 } 224 }
242 225
243 /* search */ 226 /* search */
244 i = 0; j = 1; 227 i = 0; j = 1;
245 while (i < string.length) { 228 while (i < string.length) {
246 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) { 229 while (j >= 1 && string.ptr[i] != match.ptr[j-1]) {
247 j = ptable_r(ptable, j-1); 230 ptable_r(j, useheap, ptable, j-1);
248 } 231 }
249 i++; j++; 232 i++; j++;
250 if (j-1 == match.length) { 233 if (j-1 == match.length) {
251 size_t start = i - match.length; 234 size_t start = i - match.length;
252 result.ptr = string.ptr + start; 235 result.ptr = string.ptr + start;
260 free(ptable); 243 free(ptable);
261 } 244 }
262 245
263 return result; 246 return result;
264 } 247 }
248
249 #undef ptable_r
250 #undef ptable_w
265 251
266 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) { 252 sstr_t* sstrsplit(sstr_t s, sstr_t d, ssize_t *n) {
267 return sstrsplit_a(ucx_default_allocator(), s, d, n); 253 return sstrsplit_a(ucx_default_allocator(), s, d, n);
268 } 254 }
269 255

mercurial