LCOV - code coverage report
Current view: top level - src/backend/snowball/libstemmer - utilities.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 60.3 % 373 225
Test Date: 2026-01-26 10:56:24 Functions: 54.8 % 31 17
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 44.4 % 306 136

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

Generated by: LCOV version 2.3.2-1