LCOV - code coverage report
Current view: top level - src/backend/snowball/libstemmer - utilities.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 172 271 63.5 %
Date: 2017-09-29 15:12:54 Functions: 18 29 62.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : #include "header.h"
       2             : 
       3             : #define unless(C) if(!(C))
       4             : 
       5             : #define CREATE_SIZE 1
       6             : 
       7          12 : extern symbol * create_s(void) {
       8             :     symbol * p;
       9          12 :     void * mem = malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol));
      10          12 :     if (mem == NULL) return NULL;
      11          12 :     p = (symbol *) (HEAD + (char *) mem);
      12          12 :     CAPACITY(p) = CREATE_SIZE;
      13          12 :     SET_SIZE(p, CREATE_SIZE);
      14          12 :     return p;
      15             : }
      16             : 
      17           0 : extern void lose_s(symbol * p) {
      18           0 :     if (p == NULL) return;
      19           0 :     free((char *) p - HEAD);
      20             : }
      21             : 
      22             : /*
      23             :    new_p = skip_utf8(p, c, lb, l, n); skips n characters forwards from p + c
      24             :    if n +ve, or n characters backwards from p + c - 1 if n -ve. new_p is the new
      25             :    position, or 0 on failure.
      26             : 
      27             :    -- used to implement hop and next in the utf8 case.
      28             : */
      29             : 
      30        5100 : extern int skip_utf8(const symbol * p, int c, int lb, int l, int n) {
      31             :     int b;
      32        5100 :     if (n >= 0) {
      33       10797 :         for (; n > 0; n--) {
      34        6535 :             if (c >= l) return -1;
      35        5736 :             b = p[c++];
      36        5736 :             if (b >= 0xC0) {   /* 1100 0000 */
      37           0 :                 while (c < l) {
      38           0 :                     b = p[c];
      39           0 :                     if (b >= 0xC0 || b < 0x80) break;
      40             :                     /* break unless b is 10------ */
      41           0 :                     c++;
      42             :                 }
      43             :             }
      44             :         }
      45             :     } else {
      46          78 :         for (; n < 0; n++) {
      47          39 :             if (c <= lb) return -1;
      48          39 :             b = p[--c];
      49          39 :             if (b >= 0x80) {   /* 1000 0000 */
      50           0 :                 while (c > lb) {
      51           0 :                     b = p[c];
      52           0 :                     if (b >= 0xC0) break; /* 1100 0000 */
      53           0 :                     c--;
      54             :                 }
      55             :             }
      56             :         }
      57             :     }
      58        4301 :     return c;
      59             : }
      60             : 
      61             : /* Code for character groupings: utf8 cases */
      62             : 
      63        7728 : static int get_utf8(const symbol * p, int c, int l, int * slot) {
      64             :     int b0, b1;
      65        7728 :     if (c >= l) return 0;
      66        6559 :     b0 = p[c++];
      67        6559 :     if (b0 < 0xC0 || c == l) {   /* 1100 0000 */
      68        6559 :         * slot = b0; return 1;
      69             :     }
      70           0 :     b1 = p[c++];
      71           0 :     if (b0 < 0xE0 || c == l) {   /* 1110 0000 */
      72           0 :         * slot = (b0 & 0x1F) << 6 | (b1 & 0x3F); return 2;
      73             :     }
      74           0 :     * slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (p[c] & 0x3F); return 3;
      75             : }
      76             : 
      77         486 : static int get_b_utf8(const symbol * p, int c, int lb, int * slot) {
      78             :     int b0, b1;
      79         486 :     if (c <= lb) return 0;
      80         473 :     b0 = p[--c];
      81         473 :     if (b0 < 0x80 || c == lb) {   /* 1000 0000 */
      82         473 :         * slot = b0; return 1;
      83             :     }
      84           0 :     b1 = p[--c];
      85           0 :     if (b1 >= 0xC0 || c == lb) {   /* 1100 0000 */
      86           0 :         * slot = (b1 & 0x1F) << 6 | (b0 & 0x3F); return 2;
      87             :     }
      88           0 :     * slot = (p[c] & 0xF) << 12 | (b1 & 0x3F) << 6 | (b0 & 0x3F); return 3;
      89             : }
      90             : 
      91        5261 : extern int in_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
      92             :     do {
      93             :     int ch;
      94        5261 :     int w = get_utf8(z->p, z->c, z->l, & ch);
      95        9025 :     unless (w) return -1;
      96        4419 :     if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
      97        2922 :         return w;
      98        1497 :     z->c += w;
      99        1497 :     } while (repeat);
     100        1303 :     return 0;
     101             : }
     102             : 
     103          82 : extern int in_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     104             :     do {
     105             :     int ch;
     106          82 :     int w = get_b_utf8(z->p, z->c, z->lb, & ch);
     107         116 :     unless (w) return -1;
     108          82 :     if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     109          34 :         return w;
     110          48 :     z->c -= w;
     111          48 :     } while (repeat);
     112          48 :     return 0;
     113             : }
     114             : 
     115        2467 : extern int out_grouping_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     116             :     do {
     117             :     int ch;
     118        2467 :     int w = get_utf8(z->p, z->c, z->l, & ch);
     119        3732 :     unless (w) return -1;
     120        2140 :     unless (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     121         938 :         return w;
     122        1202 :     z->c += w;
     123        1202 :     } while (repeat);
     124           0 :     return 0;
     125             : }
     126             : 
     127         404 : extern int out_grouping_b_U(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     128             :     do {
     129             :     int ch;
     130         404 :     int w = get_b_utf8(z->p, z->c, z->lb, & ch);
     131         559 :     unless (w) return -1;
     132         391 :     unless (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     133         142 :         return w;
     134         249 :     z->c -= w;
     135         249 :     } while (repeat);
     136         137 :     return 0;
     137             : }
     138             : 
     139             : /* Code for character groupings: non-utf8 cases */
     140             : 
     141           0 : extern int in_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     142             :     do {
     143             :     int ch;
     144           0 :     if (z->c >= z->l) return -1;
     145           0 :     ch = z->p[z->c];
     146           0 :     if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     147           0 :         return 1;
     148           0 :     z->c++;
     149           0 :     } while (repeat);
     150           0 :     return 0;
     151             : }
     152             : 
     153           0 : extern int in_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     154             :     do {
     155             :     int ch;
     156           0 :     if (z->c <= z->lb) return -1;
     157           0 :     ch = z->p[z->c - 1];
     158           0 :     if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     159           0 :         return 1;
     160           0 :     z->c--;
     161           0 :     } while (repeat);
     162           0 :     return 0;
     163             : }
     164             : 
     165           0 : extern int out_grouping(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     166             :     do {
     167             :     int ch;
     168           0 :     if (z->c >= z->l) return -1;
     169           0 :     ch = z->p[z->c];
     170           0 :     unless (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     171           0 :         return 1;
     172           0 :     z->c++;
     173           0 :     } while (repeat);
     174           0 :     return 0;
     175             : }
     176             : 
     177           0 : extern int out_grouping_b(struct SN_env * z, const unsigned char * s, int min, int max, int repeat) {
     178             :     do {
     179             :     int ch;
     180           0 :     if (z->c <= z->lb) return -1;
     181           0 :     ch = z->p[z->c - 1];
     182           0 :     unless (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
     183           0 :         return 1;
     184           0 :     z->c--;
     185           0 :     } while (repeat);
     186           0 :     return 0;
     187             : }
     188             : 
     189        3041 : extern int eq_s(struct SN_env * z, int s_size, const symbol * s) {
     190        3041 :     if (z->l - z->c < s_size || memcmp(z->p + z->c, s, s_size * sizeof(symbol)) != 0) return 0;
     191         120 :     z->c += s_size; return 1;
     192             : }
     193             : 
     194        1386 : extern int eq_s_b(struct SN_env * z, int s_size, const symbol * s) {
     195        1386 :     if (z->c - z->lb < s_size || memcmp(z->p + z->c - s_size, s, s_size * sizeof(symbol)) != 0) return 0;
     196         100 :     z->c -= s_size; return 1;
     197             : }
     198             : 
     199           0 : extern int eq_v(struct SN_env * z, const symbol * p) {
     200           0 :     return eq_s(z, SIZE(p), p);
     201             : }
     202             : 
     203           0 : extern int eq_v_b(struct SN_env * z, const symbol * p) {
     204           0 :     return eq_s_b(z, SIZE(p), p);
     205             : }
     206             : 
     207         454 : extern int find_among(struct SN_env * z, const struct among * v, int v_size) {
     208             : 
     209         454 :     int i = 0;
     210         454 :     int j = v_size;
     211             : 
     212         454 :     int c = z->c; int l = z->l;
     213         454 :     symbol * q = z->p + c;
     214             : 
     215             :     const struct among * w;
     216             : 
     217         454 :     int common_i = 0;
     218         454 :     int common_j = 0;
     219             : 
     220         454 :     int first_key_inspected = 0;
     221             : 
     222             :     while(1) {
     223        1641 :         int k = i + ((j - i) >> 1);
     224        1641 :         int diff = 0;
     225        1641 :         int common = common_i < common_j ? common_i : common_j; /* smaller */
     226        1641 :         w = v + k;
     227             :         {
     228        2092 :             int i2; for (i2 = common; i2 < w->s_size; i2++) {
     229        2086 :                 if (c + common == l) { diff = -1; break; }
     230        2078 :                 diff = q[common] - w->s[i2];
     231        2078 :                 if (diff != 0) break;
     232         451 :                 common++;
     233             :             }
     234             :         }
     235        1641 :         if (diff < 0) { j = k; common_j = common; }
     236         912 :                  else { i = k; common_i = common; }
     237        1641 :         if (j - i <= 1) {
     238         489 :             if (i > 0) break; /* v->s has been inspected */
     239          70 :             if (j == i) break; /* only one item in v */
     240             : 
     241             :             /* - but now we need to go round once more to get
     242             :                v->s inspected. This looks messy, but is actually
     243             :                the optimal approach.  */
     244             : 
     245          58 :             if (first_key_inspected) break;
     246          35 :             first_key_inspected = 1;
     247             :         }
     248        1187 :     }
     249             :     while(1) {
     250         454 :         w = v + i;
     251         454 :         if (common_i >= w->s_size) {
     252           6 :             z->c = c + w->s_size;
     253           6 :             if (w->function == 0) return w->result;
     254             :             {
     255           0 :                 int res = w->function(z);
     256           0 :                 z->c = c + w->s_size;
     257           0 :                 if (res) return w->result;
     258             :             }
     259             :         }
     260         448 :         i = w->substring_i;
     261         448 :         if (i < 0) return 0;
     262           0 :     }
     263             : }
     264             : 
     265             : /* find_among_b is for backwards processing. Same comments apply */
     266             : 
     267        1248 : extern int find_among_b(struct SN_env * z, const struct among * v, int v_size) {
     268             : 
     269        1248 :     int i = 0;
     270        1248 :     int j = v_size;
     271             : 
     272        1248 :     int c = z->c; int lb = z->lb;
     273        1248 :     symbol * q = z->p + c - 1;
     274             : 
     275             :     const struct among * w;
     276             : 
     277        1248 :     int common_i = 0;
     278        1248 :     int common_j = 0;
     279             : 
     280        1248 :     int first_key_inspected = 0;
     281             : 
     282             :     while(1) {
     283        4525 :         int k = i + ((j - i) >> 1);
     284        4525 :         int diff = 0;
     285        4525 :         int common = common_i < common_j ? common_i : common_j;
     286        4525 :         w = v + k;
     287             :         {
     288        7224 :             int i2; for (i2 = w->s_size - 1 - common; i2 >= 0; i2--) {
     289        6977 :                 if (c - common == lb) { diff = -1; break; }
     290        6976 :                 diff = q[- common] - w->s[i2];
     291        6976 :                 if (diff != 0) break;
     292        2699 :                 common++;
     293             :             }
     294             :         }
     295        4525 :         if (diff < 0) { j = k; common_j = common; }
     296        2207 :                  else { i = k; common_i = common; }
     297        4525 :         if (j - i <= 1) {
     298        1513 :             if (i > 0) break;
     299         530 :             if (j == i) break;
     300         413 :             if (first_key_inspected) break;
     301         265 :             first_key_inspected = 1;
     302             :         }
     303        3277 :     }
     304             :     while(1) {
     305        1614 :         w = v + i;
     306        1614 :         if (common_i >= w->s_size) {
     307         331 :             z->c = c - w->s_size;
     308         331 :             if (w->function == 0) return w->result;
     309             :             {
     310           0 :                 int res = w->function(z);
     311           0 :                 z->c = c - w->s_size;
     312           0 :                 if (res) return w->result;
     313             :             }
     314             :         }
     315        1283 :         i = w->substring_i;
     316        1283 :         if (i < 0) return 0;
     317         366 :     }
     318             : }
     319             : 
     320             : 
     321             : /* Increase the size of the buffer pointed to by p to at least n symbols.
     322             :  * If insufficient memory, returns NULL and frees the old buffer.
     323             :  */
     324          12 : static symbol * increase_size(symbol * p, int n) {
     325             :     symbol * q;
     326          12 :     int new_size = n + 20;
     327          12 :     void * mem = realloc((char *) p - HEAD,
     328             :                          HEAD + (new_size + 1) * sizeof(symbol));
     329          12 :     if (mem == NULL) {
     330           0 :         lose_s(p);
     331           0 :         return NULL;
     332             :     }
     333          12 :     q = (symbol *) (HEAD + (char *)mem);
     334          12 :     CAPACITY(q) = new_size;
     335          12 :     return q;
     336             : }
     337             : 
     338             : /* to replace symbols between c_bra and c_ket in z->p by the
     339             :    s_size symbols at s.
     340             :    Returns 0 on success, -1 on error.
     341             :    Also, frees z->p (and sets it to NULL) on error.
     342             : */
     343        1070 : extern int replace_s(struct SN_env * z, int c_bra, int c_ket, int s_size, const symbol * s, int * adjptr)
     344             : {
     345             :     int adjustment;
     346             :     int len;
     347        1070 :     if (z->p == NULL) {
     348           0 :         z->p = create_s();
     349           0 :         if (z->p == NULL) return -1;
     350             :     }
     351        1070 :     adjustment = s_size - (c_ket - c_bra);
     352        1070 :     len = SIZE(z->p);
     353        1070 :     if (adjustment != 0) {
     354         546 :         if (adjustment + len > CAPACITY(z->p)) {
     355          12 :             z->p = increase_size(z->p, adjustment + len);
     356          12 :             if (z->p == NULL) return -1;
     357             :         }
     358        1092 :         memmove(z->p + c_ket + adjustment,
     359         546 :                 z->p + c_ket,
     360         546 :                 (len - c_ket) * sizeof(symbol));
     361         546 :         SET_SIZE(z->p, adjustment + len);
     362         546 :         z->l += adjustment;
     363         546 :         if (z->c >= c_ket)
     364          24 :             z->c += adjustment;
     365             :         else
     366         522 :             if (z->c > c_bra)
     367           0 :                 z->c = c_bra;
     368             :     }
     369        1070 :     unless (s_size == 0) memmove(z->p + c_bra, s, s_size * sizeof(symbol));
     370        1070 :     if (adjptr != NULL)
     371           1 :         *adjptr = adjustment;
     372        1070 :     return 0;
     373             : }
     374             : 
     375         324 : static int slice_check(struct SN_env * z) {
     376             : 
     377         648 :     if (z->bra < 0 ||
     378         648 :         z->bra > z->ket ||
     379         648 :         z->ket > z->l ||
     380         648 :         z->p == NULL ||
     381         324 :         z->l > SIZE(z->p)) /* this line could be removed */
     382             :     {
     383             : #if 0
     384             :         fprintf(stderr, "faulty slice operation:\n");
     385             :         debug(z, -1, 0);
     386             : #endif
     387           0 :         return -1;
     388             :     }
     389         324 :     return 0;
     390             : }
     391             : 
     392         324 : extern int slice_from_s(struct SN_env * z, int s_size, const symbol * s) {
     393         324 :     if (slice_check(z)) return -1;
     394         324 :     return replace_s(z, z->bra, z->ket, s_size, s, NULL);
     395             : }
     396             : 
     397           0 : extern int slice_from_v(struct SN_env * z, const symbol * p) {
     398           0 :     return slice_from_s(z, SIZE(p), p);
     399             : }
     400             : 
     401         142 : extern int slice_del(struct SN_env * z) {
     402         142 :     return slice_from_s(z, 0, 0);
     403             : }
     404             : 
     405           1 : extern int insert_s(struct SN_env * z, int bra, int ket, int s_size, const symbol * s) {
     406             :     int adjustment;
     407           1 :     if (replace_s(z, bra, ket, s_size, s, &adjustment))
     408           0 :         return -1;
     409           1 :     if (bra <= z->bra) z->bra += adjustment;
     410           1 :     if (bra <= z->ket) z->ket += adjustment;
     411           1 :     return 0;
     412             : }
     413             : 
     414           0 : extern int insert_v(struct SN_env * z, int bra, int ket, const symbol * p) {
     415             :     int adjustment;
     416           0 :     if (replace_s(z, bra, ket, SIZE(p), p, &adjustment))
     417           0 :         return -1;
     418           0 :     if (bra <= z->bra) z->bra += adjustment;
     419           0 :     if (bra <= z->ket) z->ket += adjustment;
     420           0 :     return 0;
     421             : }
     422             : 
     423           0 : extern symbol * slice_to(struct SN_env * z, symbol * p) {
     424           0 :     if (slice_check(z)) {
     425           0 :         lose_s(p);
     426           0 :         return NULL;
     427             :     }
     428             :     {
     429           0 :         int len = z->ket - z->bra;
     430           0 :         if (CAPACITY(p) < len) {
     431           0 :             p = increase_size(p, len);
     432           0 :             if (p == NULL)
     433           0 :                 return NULL;
     434             :         }
     435           0 :         memmove(p, z->p + z->bra, len * sizeof(symbol));
     436           0 :         SET_SIZE(p, len);
     437             :     }
     438           0 :     return p;
     439             : }
     440             : 
     441           0 : extern symbol * assign_to(struct SN_env * z, symbol * p) {
     442           0 :     int len = z->l;
     443           0 :     if (CAPACITY(p) < len) {
     444           0 :         p = increase_size(p, len);
     445           0 :         if (p == NULL)
     446           0 :             return NULL;
     447             :     }
     448           0 :     memmove(p, z->p, len * sizeof(symbol));
     449           0 :     SET_SIZE(p, len);
     450           0 :     return p;
     451             : }
     452             : 
     453             : #if 0
     454             : extern void debug(struct SN_env * z, int number, int line_count) {
     455             :     int i;
     456             :     int limit = SIZE(z->p);
     457             :     /*if (number >= 0) printf("%3d (line %4d): '", number, line_count);*/
     458             :     if (number >= 0) printf("%3d (line %4d): [%d]'", number, line_count,limit);
     459             :     for (i = 0; i <= limit; i++) {
     460             :         if (z->lb == i) printf("{");
     461             :         if (z->bra == i) printf("[");
     462             :         if (z->c == i) printf("|");
     463             :         if (z->ket == i) printf("]");
     464             :         if (z->l == i) printf("}");
     465             :         if (i < limit)
     466             :         {   int ch = z->p[i];
     467             :             if (ch == 0) ch = '#';
     468             :             printf("%c", ch);
     469             :         }
     470             :     }
     471             :     printf("'\n");
     472             : }
     473             : #endif

Generated by: LCOV version 1.11