LCOV - code coverage report
Current view: top level - src/backend/snowball/libstemmer - utilities.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 173 294 58.8 %
Date: 2024-11-21 08:14:44 Functions: 17 31 54.8 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.14