xapian-core  2.1.0
snowball_runtime.cc
Go to the documentation of this file.
1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 
6 #define SNOWBALL_RUNTIME_THROW_EXCEPTIONS
7 
8 #include "snowball_runtime.h"
9 
10 #ifdef SNOWBALL_RUNTIME_THROW_EXCEPTIONS
11 # include <new>
12 # include <stdexcept>
13 # define SNOWBALL_RETURN_OK return
14 # define SNOWBALL_RETURN_OR_THROW(R, E) throw E
15 # define SNOWBALL_PROPAGATE_ERR(F) F
16 #else
17 # define SNOWBALL_RETURN_OK return 0
18 # define SNOWBALL_RETURN_OR_THROW(R, E) return R
19 # define SNOWBALL_PROPAGATE_ERR(F) do { \
20  int snowball_err = F; \
21  if (snowball_err < 0) return snowball_err; \
22  } while (0)
23 #endif
24 
25 #define HEAD (2 * sizeof(int))
26 
27 /* Note that sizeof(symbol) should divide HEAD without remainder, otherwise
28  * there is an alignment problem.
29  *
30  * We support C90 here so use a typedef trick instead of static_assert.
31  */
32 typedef int sizeof_symbol_divides_head[(HEAD % sizeof(symbol) == 0) ? 1 : -1];
33 
34 #define CREATE_SIZE 31
35 
36 extern symbol * create_s(void) {
37  symbol * p;
38  void * mem = malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol));
39  if (mem == NULL)
40  SNOWBALL_RETURN_OR_THROW(NULL, std::bad_alloc());
41  p = (symbol *) (HEAD + (char *) mem);
43  SET_SIZE(p, 0);
44  return p;
45 }
46 
47 extern void lose_s(symbol * p) {
48  if (p == NULL) return;
49  free((char *) p - HEAD);
50 }
51 
52 /*
53  new_p = skip_utf8(p, c, l, n); skips n characters forwards from p + c.
54  new_p is the new position, or -1 on failure (if c would be > l).
55 
56  Caller ensures n >= 0.
57 
58  -- used to implement hop and next in the utf8 case.
59 */
60 
61 extern int skip_utf8(const symbol * p, int c, int limit, int n) {
62  int b;
63  for (; n > 0; n--) {
64  if (c >= limit) return -1;
65  b = p[c++];
66  if (b >= 0xC0) { /* 1100 0000 */
67  while (c < limit) {
68  b = p[c];
69  if (b >= 0xC0 || b < 0x80) break;
70  /* break unless b is 10------ */
71  c++;
72  }
73  }
74  }
75  return c;
76 }
77 
78 /*
79  new_p = skip_b_utf8(p, c, lb, n); skips n characters backwards from p + c - 1
80  new_p is the new position, or -1 on failure (if c would be < lb).
81 
82  Caller ensures n >= 0.
83 
84  -- used to implement hop and next in the utf8 case.
85 */
86 
87 extern int skip_b_utf8(const symbol * p, int c, int limit, int n) {
88  int b;
89  for (; n > 0; n--) {
90  if (c <= limit) return -1;
91  b = p[--c];
92  if (b >= 0x80) { /* 1000 0000 */
93  while (c > limit) {
94  b = p[c];
95  if (b >= 0xC0) break; /* 1100 0000 */
96  c--;
97  }
98  }
99  }
100  return c;
101 }
102 
103 /* Code for character groupings: utf8 cases */
104 
105 static int get_utf8(const symbol * p, int c, int l, int * slot) {
106  int b0, b1, b2;
107  if (c >= l) return 0;
108  b0 = p[c++];
109  if (b0 < 0xC0 || c == l) { /* 1100 0000 */
110  *slot = b0;
111  return 1;
112  }
113  b1 = p[c++] & 0x3F;
114  if (b0 < 0xE0 || c == l) { /* 1110 0000 */
115  *slot = (b0 & 0x1F) << 6 | b1;
116  return 2;
117  }
118  b2 = p[c++] & 0x3F;
119  if (b0 < 0xF0 || c == l) { /* 1111 0000 */
120  *slot = (b0 & 0xF) << 12 | b1 << 6 | b2;
121  return 3;
122  }
123  *slot = (b0 & 0x7) << 18 | b1 << 12 | b2 << 6 | (p[c] & 0x3F);
124  return 4;
125 }
126 
127 static int get_b_utf8(const symbol * p, int c, int lb, int * slot) {
128  int a, b;
129  if (c <= lb) return 0;
130  b = p[--c];
131  if (b < 0x80 || c == lb) { /* 1000 0000 */
132  *slot = b;
133  return 1;
134  }
135  a = b & 0x3F;
136  b = p[--c];
137  if (b >= 0xC0 || c == lb) { /* 1100 0000 */
138  *slot = (b & 0x1F) << 6 | a;
139  return 2;
140  }
141  a |= (b & 0x3F) << 6;
142  b = p[--c];
143  if (b >= 0xE0 || c == lb) { /* 1110 0000 */
144  *slot = (b & 0xF) << 12 | a;
145  return 3;
146  }
147  *slot = (p[--c] & 0x7) << 18 | (b & 0x3F) << 12 | a;
148  return 4;
149 }
150 
151 #ifdef SNOWBALL_COVERAGE
152 /* The grouping number gets stored in a byte, clamped to 255. */
153 static char grouping_seen[255];
154 
155 static void report_coverage(const unsigned char * s, int min, int max, int ch, const unsigned char * p, int w) {
156  int i = 0;
157  int j;
158  int outof = 0;
159  const unsigned char * loc = s + (max - min + 8) / 8;
160  int grouping_number = *loc++;
161  /* Adjust ch be an offset from min if it's past the end of the range. If
162  * we already subtracted min then this will condition will be false. Only
163  * needed for the "out" case but the condition can never be true for the
164  * "in" case.
165  */
166  if (ch > max) ch -= min;
167  /* Find the index of this character in the grouping. */
168  for (j = 0; j != max - min; ++j) {
169  if (s[j >> 3] & (0X1 << (j & 0X7))) {
170  ++outof;
171  if (j < ch) ++i;
172  }
173  }
174  if (grouping_number < (int)sizeof(grouping_seen) &&
175  grouping_seen[grouping_number] == 0) {
176  /* Report every entry once, then unused cases will appear (and we can
177  * decrement each count when generating the coverage report).
178  */
179  int k = 0;
180  for (j = 0; j != max - min; ++j) {
181  if (s[j >> 3] & (0X1 << (j & 0X7))) {
182  fprintf(stderr, "%s index %d of %d '", loc, k, outof + 1);
183  int codepoint = j + min;
184  if (codepoint < 0x80) {
185  putc(codepoint, stderr);
186  } else if (codepoint < 0x800) {
187  putc((codepoint >> 6) | 0xC0, stderr);
188  putc((codepoint & 0x3F) | 0x80, stderr);
189  } else {
190  putc((codepoint >> 12) | 0xE0, stderr);
191  putc(((codepoint >> 6) & 0x3F) | 0x80, stderr);
192  putc((codepoint & 0x3F) | 0x80, stderr);
193  }
194  fprintf(stderr, "'\n");
195  ++k;
196  }
197  }
198  grouping_seen[grouping_number] = 1;
199  }
200  fprintf(stderr, "%s index %d of %d '%.*s'\n", loc, i, outof + 1, w, p);
201 }
202 
203 static void report_coverage_nomatch(const unsigned char * s, int min, int max) {
204  const unsigned char * loc = s + (max - min + 8) / 8;
205  ++loc;
206  fprintf(stderr, "%s no match\n", loc);
207 }
208 #endif
209 
210 extern int in_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
211  do {
212  int ch;
213  int w = get_utf8(z->p, z->c, z->l, & ch);
214  if (!w) return -1;
215  if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) {
216 #ifdef SNOWBALL_COVERAGE
217  report_coverage_nomatch(s, min, max);
218 #endif
219  return w;
220  }
221 #ifdef SNOWBALL_COVERAGE
222  report_coverage(s, min, max, ch, z->p + z->c, w);
223 #endif
224  z->c += w;
225  } while (repeat);
226  return 0;
227 }
228 
229 extern int in_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
230  do {
231  int ch;
232  int w = get_b_utf8(z->p, z->c, z->lb, & ch);
233  if (!w) return -1;
234  if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0) {
235 #ifdef SNOWBALL_COVERAGE
236  report_coverage_nomatch(s, min, max);
237 #endif
238  return w;
239  }
240 #ifdef SNOWBALL_COVERAGE
241  report_coverage(s, min, max, ch, z->p + z->c - w, w);
242 #endif
243  z->c -= w;
244  } while (repeat);
245  return 0;
246 }
247 
248 extern int out_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
249  do {
250  int ch;
251  int w = get_utf8(z->p, z->c, z->l, & ch);
252  if (!w) return -1;
253  if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)) {
254 #ifdef SNOWBALL_COVERAGE
255  report_coverage(s, min, max, ch, z->p + z->c, w);
256 #endif
257  return w;
258  }
259 #ifdef SNOWBALL_COVERAGE
260  report_coverage_nomatch(s, min, max);
261 #endif
262  z->c += w;
263  } while (repeat);
264  return 0;
265 }
266 
267 extern int out_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
268  do {
269  int ch;
270  int w = get_b_utf8(z->p, z->c, z->lb, & ch);
271  if (!w) return -1;
272  if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)) {
273 #ifdef SNOWBALL_COVERAGE
274  report_coverage(s, min, max, ch, z->p + z->c - w, w);
275 #endif
276  return w;
277  }
278 #ifdef SNOWBALL_COVERAGE
279  report_coverage_nomatch(s, min, max);
280 #endif
281  z->c -= w;
282  } while (repeat);
283  return 0;
284 }
285 
286 /* Code for character groupings: non-utf8 cases */
287 
288 extern int in_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
289  do {
290  int ch;
291  if (z->c >= z->l) return -1;
292  ch = z->p[z->c];
293  if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
294  return 1;
295  z->c++;
296  } while (repeat);
297  return 0;
298 }
299 
300 extern int in_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
301  do {
302  int ch;
303  if (z->c <= z->lb) return -1;
304  ch = z->p[z->c - 1];
305  if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
306  return 1;
307  z->c--;
308  } while (repeat);
309  return 0;
310 }
311 
312 extern int out_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
313  do {
314  int ch;
315  if (z->c >= z->l) return -1;
316  ch = z->p[z->c];
317  if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0))
318  return 1;
319  z->c++;
320  } while (repeat);
321  return 0;
322 }
323 
324 extern int out_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
325  do {
326  int ch;
327  if (z->c <= z->lb) return -1;
328  ch = z->p[z->c - 1];
329  if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0))
330  return 1;
331  z->c--;
332  } while (repeat);
333  return 0;
334 }
335 
336 extern int eq_s(struct SN_env * z, int s_size, const symbol * s) {
337  if (z->l - z->c < s_size || memcmp(z->p + z->c, s, s_size * sizeof(symbol)) != 0) return 0;
338  z->c += s_size; return 1;
339 }
340 
341 extern int eq_s_b(struct SN_env * z, int s_size, const symbol * s) {
342  if (z->c - z->lb < s_size || memcmp(z->p + z->c - s_size, s, s_size * sizeof(symbol)) != 0) return 0;
343  z->c -= s_size; return 1;
344 }
345 
346 extern int eq_v(struct SN_env * z, const symbol * p) {
347  return eq_s(z, SIZE(p), p);
348 }
349 
350 extern int eq_v_b(struct SN_env * z, const symbol * p) {
351  return eq_s_b(z, SIZE(p), p);
352 }
353 
354 #ifdef SNOWBALL_COVERAGE
355 /* Declare more entries than any real Snowball program will have. */
356 static char among_seen[4096];
357 #endif
358 
359 extern int find_among(struct SN_env * z, const struct among * v, int v_size,
360  int (*call_among_func)(struct SN_env*)) {
361 
362  int i = 0;
363  int j = v_size;
364 
365  int c = z->c; int l = z->l;
366  const symbol * q = z->p + c;
367 
368  const struct among * w;
369 
370  int common_i = 0;
371  int common_j = 0;
372 
373  int first_key_inspected = 0;
374 
375 #ifdef SNOWBALL_COVERAGE
376  int among_number = v[v_size].s_size;
377  if (among_number < (int)sizeof(among_seen) &&
378  among_seen[among_number] == 0) {
379  /* Report every entry once, then unused cases will appear (and we can
380  * decrement each count when generating the coverage report).
381  */
382  int k;
383  for (k = 0; k < v_size; ++k) {
384  w = v + k;
385  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
386  if (w->function) {
387  fprintf(stderr, "%s: among %d : %d of %d func-f '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
388  }
389  }
390  /* If the among matches the empty string without a gating function then
391  * the "no match" case is impossible and so not useful to include in a
392  * coverage report.
393  */
394  if (v[v_size * 2].s_size != -1) {
395  fprintf(stderr, "%s: among %d no match\n", v[v_size * 2].s, among_number);
396  }
397  among_seen[among_number] = 1;
398  }
399 #endif
400  while (1) {
401  int k = i + ((j - i) >> 1);
402  int diff = 0;
403  int common = common_i < common_j ? common_i : common_j; /* smaller */
404  w = v + k;
405  {
406  int i2; for (i2 = common; i2 < w->s_size; i2++) {
407  if (c + common == l) { diff = -1; break; }
408  diff = q[common] - w->s[i2];
409  if (diff != 0) break;
410  common++;
411  }
412  }
413  if (diff < 0) {
414  j = k;
415  common_j = common;
416  } else {
417  i = k;
418  common_i = common;
419  }
420  if (j - i <= 1) {
421  if (i > 0) break; /* v->s has been inspected */
422  if (j == i) break; /* only one item in v */
423 
424  /* - but now we need to go round once more to get
425  v->s inspected. This looks messy, but is actually
426  the optimal approach. */
427 
428  if (first_key_inspected) break;
429  first_key_inspected = 1;
430  }
431  }
432  w = v + i;
433  while (1) {
434  if (common_i >= w->s_size) {
435  z->c = c + w->s_size;
436  if (!w->function) {
437 #ifdef SNOWBALL_COVERAGE
438  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
439 #endif
440  return w->result;
441  }
442  z->af = w->function;
443  if (call_among_func(z)) {
444  z->c = c + w->s_size;
445 #ifdef SNOWBALL_COVERAGE
446  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
447 #endif
448  return w->result;
449  }
450 #ifdef SNOWBALL_COVERAGE
451  fprintf(stderr, "%s: among %d : %d of %d func-f '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
452 #endif
453  }
454  if (!w->substring_i) {
455 #ifdef SNOWBALL_COVERAGE
456  fprintf(stderr, "%s: among %d no match\n", v[v_size * 2].s, among_number);
457 #endif
458  return 0;
459  }
460  w += w->substring_i;
461  }
462 }
463 
464 /* find_among_b is for backwards processing. Same comments apply */
465 
466 extern int find_among_b(struct SN_env * z, const struct among * v, int v_size,
467  int (*call_among_func)(struct SN_env*)) {
468 
469  int i = 0;
470  int j = v_size;
471 
472  int c = z->c; int lb = z->lb;
473  const symbol * q = z->p + c - 1;
474 
475  const struct among * w;
476 
477  int common_i = 0;
478  int common_j = 0;
479 
480  int first_key_inspected = 0;
481 
482 #ifdef SNOWBALL_COVERAGE
483  int among_number = v[v_size].s_size;
484  if (among_number < (int)sizeof(among_seen) &&
485  among_seen[among_number] == 0) {
486  /* Report every entry once, then unused cases will appear (and we can
487  * decrement each count when generating the coverage report).
488  */
489  int k;
490  for (k = 0; k < v_size; ++k) {
491  w = v + k;
492  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
493  if (w->function) {
494  fprintf(stderr, "%s: among %d : %d of %d func-f '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
495  }
496  }
497  /* If the among matches the empty string without a gating function then
498  * the "no match" case is impossible and so not useful to include in a
499  * coverage report.
500  */
501  if (v[v_size * 2].s_size != -1) {
502  fprintf(stderr, "%s: among %d no match\n", v[v_size * 2].s, among_number);
503  }
504  among_seen[among_number] = 1;
505  }
506 #endif
507  while (1) {
508  int k = i + ((j - i) >> 1);
509  int diff = 0;
510  int common = common_i < common_j ? common_i : common_j;
511  w = v + k;
512  {
513  int i2; for (i2 = w->s_size - 1 - common; i2 >= 0; i2--) {
514  if (c - common == lb) { diff = -1; break; }
515  diff = q[- common] - w->s[i2];
516  if (diff != 0) break;
517  common++;
518  }
519  }
520  if (diff < 0) { j = k; common_j = common; }
521  else { i = k; common_i = common; }
522  if (j - i <= 1) {
523  if (i > 0) break;
524  if (j == i) break;
525  if (first_key_inspected) break;
526  first_key_inspected = 1;
527  }
528  }
529  w = v + i;
530  while (1) {
531  if (common_i >= w->s_size) {
532  z->c = c - w->s_size;
533  if (!w->function) {
534 #ifdef SNOWBALL_COVERAGE
535  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
536 #endif
537  return w->result;
538  }
539  z->af = w->function;
540  if (call_among_func(z)) {
541 #ifdef SNOWBALL_COVERAGE
542  fprintf(stderr, "%s: among %d : %d of %d string '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
543 #endif
544  z->c = c - w->s_size;
545  return w->result;
546  }
547 #ifdef SNOWBALL_COVERAGE
548  fprintf(stderr, "%s: among %d : %d of %d func-f '%.*s'\n", w[v_size].s, among_number, w[v_size].result, v_size, w->s_size, w->s);
549 #endif
550  }
551  if (!w->substring_i) {
552 #ifdef SNOWBALL_COVERAGE
553  fprintf(stderr, "%s: among %d no match\n", v[v_size * 2].s, among_number);
554 #endif
555  return 0;
556  }
557  w += w->substring_i;
558  }
559 }
560 
561 
562 /* Increase the size of the buffer pointed to by p to at least n symbols.
563  * On success, returns 0. If insufficient memory, returns -1.
564  */
565 static int increase_size(symbol ** p, int n) {
566  int new_size = n + 20;
567  void * mem = realloc((char *) *p - HEAD,
568  HEAD + (new_size + 1) * sizeof(symbol));
569  symbol * q;
570  if (mem == NULL) return -1;
571  q = (symbol *) (HEAD + (char *)mem);
572  CAPACITY(q) = new_size;
573  *p = q;
574  return 0;
575 }
576 
577 /* to replace symbols between c_bra and c_ket in z->p by the
578  s_size symbols at s.
579  Returns 0 on success, -1 on error.
580 */
581 extern SNOWBALL_ERR replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s)
582 {
583  int adjustment = s_size - (c_ket - c_bra);
584  if (adjustment != 0) {
585  int len = SIZE(z->p);
586  if (adjustment + len > CAPACITY(z->p)) {
587  SNOWBALL_PROPAGATE_ERR(increase_size(&z->p, adjustment + len));
588  }
589  memmove(z->p + c_ket + adjustment,
590  z->p + c_ket,
591  (len - c_ket) * sizeof(symbol));
592  SET_SIZE(z->p, adjustment + len);
593  z->l += adjustment;
594  if (z->c >= c_ket)
595  z->c += adjustment;
596  else if (z->c > c_bra)
597  z->c = c_bra;
598  }
599  if (s_size) memmove(z->p + c_bra, s, s_size * sizeof(symbol));
601 }
602 
603 # define REPLACE_S(Z, B, K, SIZE, S) \
604  SNOWBALL_PROPAGATE_ERR(replace_s(Z, B, K, SIZE, S))
605 
606 static SNOWBALL_ERR slice_check(struct SN_env * z) {
607 
608  if (z->bra < 0 ||
609  z->bra > z->ket ||
610  z->ket > z->l ||
611  z->l > SIZE(z->p)) /* this line could be removed */
612  {
613 #if 0
614  fprintf(stderr, "faulty slice operation:\n");
615  debug(z, -1, 0);
616 #endif
617  SNOWBALL_RETURN_OR_THROW(-1, std::logic_error("Snowball slice invalid"));
618  }
620 }
621 
622 # define SLICE_CHECK(Z) SNOWBALL_PROPAGATE_ERR(slice_check(Z))
623 
624 extern SNOWBALL_ERR slice_from_s(struct SN_env * z, int s_size, const symbol * s) {
625  SLICE_CHECK(z);
626  REPLACE_S(z, z->bra, z->ket, s_size, s);
627  z->ket = z->bra + s_size;
629 }
630 
631 extern SNOWBALL_ERR slice_from_v(struct SN_env * z, const symbol * p) {
632  return slice_from_s(z, SIZE(p), p);
633 }
634 
635 extern SNOWBALL_ERR slice_del(struct SN_env * z) {
636  SLICE_CHECK(z);
637  {
638  int slice_size = z->ket - z->bra;
639  if (slice_size != 0) {
640  int len = SIZE(z->p);
641  memmove(z->p + z->bra,
642  z->p + z->ket,
643  (len - z->ket) * sizeof(symbol));
644  SET_SIZE(z->p, len - slice_size);
645  z->l -= slice_size;
646  if (z->c >= z->ket)
647  z->c -= slice_size;
648  else if (z->c > z->bra)
649  z->c = z->bra;
650  z->ket = z->bra;
651  }
652  }
654 }
655 
656 extern SNOWBALL_ERR insert_s(struct SN_env * z, int bra, int ket, int s_size, const symbol * s) {
657  REPLACE_S(z, bra, ket, s_size, s);
658  if (bra <= z->ket) {
659  int adjustment = s_size - (ket - bra);
660  z->ket += adjustment;
661  if (bra <= z->bra) z->bra += adjustment;
662  }
664 }
665 
666 extern SNOWBALL_ERR insert_v(struct SN_env * z, int bra, int ket, const symbol * p) {
667  return insert_s(z, bra, ket, SIZE(p), p);
668 }
669 
670 extern SNOWBALL_ERR slice_to(struct SN_env * z, symbol ** p) {
671  SLICE_CHECK(z);
672  {
673  int len = z->ket - z->bra;
674  if (CAPACITY(*p) < len) {
676  }
677  memmove(*p, z->p + z->bra, len * sizeof(symbol));
678  SET_SIZE(*p, len);
679  }
681 }
682 
683 extern SNOWBALL_ERR assign_to(struct SN_env * z, symbol ** p) {
684  int len = z->l;
685  if (CAPACITY(*p) < len) {
687  }
688  memmove(*p, z->p, len * sizeof(symbol));
689  SET_SIZE(*p, len);
691 }
692 
693 extern int len_utf8(const symbol * p) {
694  int size = SIZE(p);
695  int len = 0;
696  while (size--) {
697  symbol b = *p++;
698  if (b >= 0xC0 || b < 0x80) ++len;
699  }
700  return len;
701 }
unsigned char symbol
Definition: api.h:4
PositionList * p
#define SIZE(p)
Definition: header.h:21
@ c_ket
Definition: header.h:140
@ c_bra
Definition: header.h:136
#define CAPACITY(p)
Definition: header.h:24
#define SET_SIZE(p, n)
Definition: header.h:22
#define REPLACE_S(Z, B, K, SIZE, S)
#define SNOWBALL_RETURN_OR_THROW(R, E)
#define SLICE_CHECK(Z)
#define HEAD
int out_grouping_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
#define CREATE_SIZE
int in_grouping_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
SNOWBALL_ERR insert_s(struct SN_env *z, int bra, int ket, int s_size, const symbol *s)
int eq_v_b(struct SN_env *z, const symbol *p)
SNOWBALL_ERR slice_from_s(struct SN_env *z, int s_size, const symbol *s)
int in_grouping(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
SNOWBALL_ERR slice_to(struct SN_env *z, symbol **p)
int sizeof_symbol_divides_head[(HEAD % sizeof(symbol)==0) ? 1 :-1]
SNOWBALL_ERR assign_to(struct SN_env *z, symbol **p)
SNOWBALL_ERR slice_from_v(struct SN_env *z, const symbol *p)
int eq_s(struct SN_env *z, int s_size, const symbol *s)
SNOWBALL_ERR insert_v(struct SN_env *z, int bra, int ket, const symbol *p)
#define SNOWBALL_PROPAGATE_ERR(F)
static SNOWBALL_ERR slice_check(struct SN_env *z)
int eq_v(struct SN_env *z, const symbol *p)
SNOWBALL_ERR replace_s(struct SN_env *z, int c_bra, int c_ket, int s_size, const symbol *s)
void lose_s(symbol *p)
static int get_utf8(const symbol *p, int c, int l, int *slot)
symbol * create_s(void)
int out_grouping_b(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
int find_among_b(struct SN_env *z, const struct among *v, int v_size, int(*call_among_func)(struct SN_env *))
#define SNOWBALL_RETURN_OK
int in_grouping_b_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
int skip_b_utf8(const symbol *p, int c, int limit, int n)
int eq_s_b(struct SN_env *z, int s_size, const symbol *s)
int out_grouping(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
SNOWBALL_ERR slice_del(struct SN_env *z)
int out_grouping_b_U(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
int skip_utf8(const symbol *p, int c, int limit, int n)
int in_grouping_b(struct SN_env *z, const unsigned char *s, int min, int max, int repeat)
int len_utf8(const symbol *p)
static int get_b_utf8(const symbol *p, int c, int lb, int *slot)
static int increase_size(symbol **p, int n)
int find_among(struct SN_env *z, const struct among *v, int v_size, int(*call_among_func)(struct SN_env *))
#define SNOWBALL_ERR
Definition: api.h:12
int af
Definition: api.h:15
int lb
Definition: api.h:14
symbol * p
Definition: api.h:13
int ket
Definition: api.h:14
int c
Definition: api.h:14
int bra
Definition: api.h:14
int l
Definition: api.h:14
Definition: header.h:295
struct amongvec * v
Definition: header.h:297
int substring_i
const symbol * s
int function