LCOV - code coverage report
Current view: top level - languages - steminternal.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 7822d31adece Lines: 212 223 95.1 %
Date: 2019-05-23 11:15:29 Functions: 22 23 95.7 %
Branches: 185 206 89.8 %

           Branch data     Line data    Source code
       1                 :            : /** @file steminternal.cc
       2                 :            :  *  @brief Base class for implementations of stemming algorithms
       3                 :            :  */
       4                 :            : /* Derived from snowball's runtime/api.c:
       5                 :            :  *
       6                 :            :  * Copyright (c) 2001, Dr Martin Porter
       7                 :            :  * Copyright (c) 2004,2005, Richard Boulton
       8                 :            :  * Copyright (c) 2006,2007,2008,2009,2016 Olly Betts
       9                 :            :  * All rights reserved.
      10                 :            :  *
      11                 :            :  * Redistribution and use in source and binary forms, with or without
      12                 :            :  * modification, are permitted provided that the following conditions are met:
      13                 :            :  *
      14                 :            :  *   * Redistributions of source code must retain the above copyright notice,
      15                 :            :  *     this list of conditions and the following disclaimer.
      16                 :            :  *
      17                 :            :  *   * Redistributions in binary form must reproduce the above copyright
      18                 :            :  *     notice, this list of conditions and the following disclaimer in the
      19                 :            :  *     documentation and/or other materials provided with the distribution.
      20                 :            :  *
      21                 :            :  *   * Neither the name of the <ORGANIZATION> nor the names of its contributors
      22                 :            :  *     may be used to endorse or promote products derived from this software
      23                 :            :  *     without specific prior written permission.
      24                 :            :  *
      25                 :            :  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
      26                 :            :  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27                 :            :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28                 :            :  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
      29                 :            :  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      30                 :            :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      31                 :            :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      32                 :            :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      33                 :            :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      34                 :            :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
      35                 :            :  * POSSIBILITY OF SUCH DAMAGE.
      36                 :            :  */
      37                 :            : /* Copyright (C) 2007,2010 Olly Betts
      38                 :            :  * Copyright (C) 2010 Evgeny Sizikov
      39                 :            :  *
      40                 :            :  * This program is free software; you can redistribute it and/or
      41                 :            :  * modify it under the terms of the GNU General Public License as
      42                 :            :  * published by the Free Software Foundation; either version 2 of the
      43                 :            :  * License, or (at your option) any later version.
      44                 :            :  *
      45                 :            :  * This program is distributed in the hope that it will be useful,
      46                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      47                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      48                 :            :  * GNU General Public License for more details.
      49                 :            :  *
      50                 :            :  * You should have received a copy of the GNU General Public License
      51                 :            :  * along with this program; if not, write to the Free Software
      52                 :            :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      53                 :            :  */
      54                 :            : 
      55                 :            : #include <config.h>
      56                 :            : 
      57                 :            : #include "steminternal.h"
      58                 :            : 
      59                 :            : #include <xapian/error.h>
      60                 :            : 
      61                 :            : #include "omassert.h"
      62                 :            : 
      63                 :            : #include <cstdlib>
      64                 :            : #include <cstring>
      65                 :            : 
      66                 :            : #include <string>
      67                 :            : 
      68                 :            : using namespace std;
      69                 :            : 
      70                 :            : namespace Xapian {
      71                 :            : 
      72                 :            : #define CREATE_SIZE 16
      73                 :            : 
      74                 :            : symbol *
      75                 :       1669 : SnowballStemImplementation::create_s()
      76                 :            : {
      77                 :       1669 :     void * mem = malloc(HEAD + (CREATE_SIZE + 1) * sizeof(symbol));
      78         [ -  + ]:       1669 :     if (mem == NULL) throw std::bad_alloc();
      79                 :       1669 :     symbol * p = reinterpret_cast<symbol*>(HEAD + static_cast<char *>(mem));
      80                 :       1669 :     SET_CAPACITY(p, CREATE_SIZE);
      81                 :       1669 :     SET_SIZE(p, 0);
      82                 :       1669 :     return p;
      83                 :            : }
      84                 :            : 
      85                 :            : /*
      86                 :            :    new_c = skip_utf8(p, c, lb, l, n); skips n characters forwards from p + c
      87                 :            :    if n +ve, or n characters backwards from p + c - 1 if n -ve. new_c is the new
      88                 :            :    value of the cursor c, or -1 on failure.
      89                 :            : 
      90                 :            :    -- used to implement hop and next in the utf8 case.
      91                 :            : */
      92                 :            : 
      93                 :            : int
      94                 :  140878865 : SnowballStemImplementation::skip_utf8(const symbol * p, int c, int lb, int l, int n)
      95                 :            : {
      96         [ +  + ]:  140878865 :     if (n >= 0) {
      97         [ +  + ]:  281712717 :         for (; n > 0; --n) {
      98         [ +  + ]:  146812403 :             if (c >= l) return -1;
      99         [ +  + ]:  141236654 :             if (p[c++] >= 0xC0) {   /* 1100 0000 */
     100         [ +  + ]:   35844352 :                 while (c < l) {
     101                 :            :                     /* break unless p[c] is 10------ */
     102         [ +  + ]:   20569448 :                     if (p[c] >> 6 != 2) break;
     103                 :    5436551 :                     c++;
     104                 :            :                 }
     105                 :            :             }
     106                 :            :         }
     107                 :            :     } else {
     108         [ +  + ]:     867507 :         for (; n < 0; ++n) {
     109         [ +  + ]:     467719 :             if (c <= lb) return -1;
     110         [ +  + ]:     464705 :             if (p[--c] >= 0x80) {   /* 1000 0000 */
     111         [ +  + ]:      28784 :                 while (c > lb) {
     112         [ +  + ]:      19293 :                     if (p[c] >= 0xC0) break; /* 1100 0000 */
     113                 :       9827 :                     c--;
     114                 :            :                 }
     115                 :            :             }
     116                 :            :         }
     117                 :            :     }
     118                 :  135300102 :     return c;
     119                 :            : }
     120                 :            : 
     121                 :            : 
     122                 :            : /* Increase the size of the buffer pointed to by p to at least n symbols.
     123                 :            :  * If insufficient memory, throw std::bad_alloc().
     124                 :            :  */
     125                 :            : symbol *
     126                 :        398 : SnowballStemImplementation::increase_size(symbol * p, int n)
     127                 :            : {
     128                 :        398 :     int new_size = n + 20;
     129                 :        398 :     void * mem = realloc(reinterpret_cast<char *>(p) - HEAD,
     130                 :        796 :                          HEAD + (new_size + 1) * sizeof(symbol));
     131         [ -  + ]:        398 :     if (mem == NULL) {
     132                 :          0 :         throw std::bad_alloc();
     133                 :            :     }
     134                 :        398 :     symbol * q = reinterpret_cast<symbol*>(HEAD + static_cast<char *>(mem));
     135                 :        398 :     SET_CAPACITY(q, new_size);
     136                 :        398 :     return q;
     137                 :            : }
     138                 :            : 
     139                 :            : 
     140         [ -  + ]:       3324 : StemImplementation::~StemImplementation() { }
     141                 :            : 
     142                 :       3320 : SnowballStemImplementation::~SnowballStemImplementation()
     143                 :            : {
     144                 :       1660 :     lose_s(p);
     145         [ -  + ]:       1660 : }
     146                 :            : 
     147                 :            : string
     148                 :    6231520 : SnowballStemImplementation::operator()(const string & word)
     149                 :            : {
     150                 :    6231520 :     const symbol * s = reinterpret_cast<const symbol *>(word.data());
     151                 :    6231520 :     replace_s(0, l, word.size(), s);
     152                 :    6231520 :     c = 0;
     153         [ -  + ]:    6231520 :     if (stem() < 0) {
     154                 :            :         // FIXME: Is there a better choice of exception class?
     155 [ #  # ][ #  # ]:          0 :         throw Xapian::InternalError("stemming exception!");
                 [ #  # ]
     156                 :            :     }
     157         [ +  - ]:    6231520 :     return string(reinterpret_cast<const char *>(p), l);
     158                 :            : }
     159                 :            : 
     160                 :            : /* Code for character groupings: utf8 cases */
     161                 :            : 
     162                 :  120456688 : int SnowballStemImplementation::get_utf8(int * slot) {
     163                 :            :     int b0, b1;
     164                 :  120456688 :     int tmp = c;
     165         [ +  + ]:  120456688 :     if (tmp >= l) return 0;
     166                 :  115007008 :     b0 = p[tmp++];
     167 [ +  + ][ +  + ]:  115007008 :     if (b0 < 0xC0 || tmp == l) {   /* 1100 0000 */
     168                 :  104409210 :         * slot = b0; return 1;
     169                 :            :     }
     170                 :   10597798 :     b1 = p[tmp++];
     171 [ +  + ][ +  + ]:   10597798 :     if (b0 < 0xE0 || tmp == l) {   /* 1110 0000 */
     172                 :    5675651 :         * slot = (b0 & 0x1F) << 6 | (b1 & 0x3F); return 2;
     173                 :            :     }
     174                 :    4922147 :     * slot = (b0 & 0xF) << 12 | (b1 & 0x3F) << 6 | (p[tmp] & 0x3F); return 3;
     175                 :            : }
     176                 :            : 
     177                 :   38772142 : int SnowballStemImplementation::get_b_utf8(int * slot) {
     178                 :            :     int b0, b1;
     179                 :   38772142 :     int tmp = c;
     180         [ +  + ]:   38772142 :     if (tmp <= lb) return 0;
     181                 :   38167257 :     b0 = p[--tmp];
     182 [ +  + ][ +  + ]:   38167257 :     if (b0 < 0x80 || tmp == lb) {   /* 1000 0000 */
     183                 :   31357950 :         * slot = b0; return 1;
     184                 :            :     }
     185                 :    6809307 :     b1 = p[--tmp];
     186 [ +  + ][ +  + ]:    6809307 :     if (b1 >= 0xC0 || tmp == lb) {   /* 1100 0000 */
     187                 :    2491346 :         * slot = (b1 & 0x1F) << 6 | (b0 & 0x3F); return 2;
     188                 :            :     }
     189                 :    4317961 :     * slot = (p[tmp] & 0xF) << 12 | (b1 & 0x3F) << 6 | (b0 & 0x3F); return 3;
     190                 :            : }
     191                 :            : 
     192                 :            : int
     193                 :   65432617 : SnowballStemImplementation::in_grouping_U(const unsigned char * s, int min,
     194                 :            :                                           int max, int repeat)
     195                 :            : {
     196         [ +  + ]:   11887664 :     do {
     197                 :            :         int ch;
     198                 :   66992212 :         int w = get_utf8(&ch);
     199         [ +  + ]:  118377784 :         if (!w) return -1;
     200 [ +  + ][ +  + ]:   63273236 :         if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
         [ +  + ][ +  + ]
     201                 :   51385572 :             return w;
     202                 :   11887664 :         c += w;
     203                 :            :     } while (repeat);
     204                 :   10328069 :     return 0;
     205                 :            : }
     206                 :            : 
     207                 :            : int
     208                 :    1194104 : SnowballStemImplementation::in_grouping_b_U(const unsigned char * s, int min,
     209                 :            :                                             int max, int repeat)
     210                 :            : {
     211         [ +  + ]:     600695 :     do {
     212                 :            :         int ch;
     213                 :    1222870 :         int w = get_b_utf8(&ch);
     214         [ +  + ]:    1827705 :         if (!w) return -1;
     215 [ +  + ][ +  + ]:    1205530 :         if (ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0)
         [ +  + ][ +  + ]
     216                 :     604835 :             return w;
     217                 :     600695 :         c -= w;
     218                 :            :     } while (repeat);
     219                 :     571929 :     return 0;
     220                 :            : }
     221                 :            : 
     222                 :            : int
     223                 :   12884547 : SnowballStemImplementation::out_grouping_U(const unsigned char * s, int min,
     224                 :            :                                            int max, int repeat)
     225                 :            : {
     226         [ +  + ]:   42756832 :     do {
     227                 :            :         int ch;
     228                 :   53464476 :         int w = get_utf8(&ch);
     229         [ +  + ]:   62441416 :         if (!w) return -1;
     230 [ +  + ][ +  + ]:   51733772 :         if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0))
         [ +  + ][ +  + ]
     231                 :    8976940 :             /* FIXME: try adding this so gopast in generated code is simpler: if (repeat == 2) c += w; */ return w;
     232                 :   42756832 :         c += w;
     233                 :            :     } while (repeat);
     234                 :    2176903 :     return 0;
     235                 :            : }
     236                 :            : 
     237                 :            : int
     238                 :    7620360 : SnowballStemImplementation::out_grouping_b_U(const unsigned char * s, int min,
     239                 :            :                                              int max, int repeat)
     240                 :            : {
     241         [ +  + ]:   31352808 :     do {
     242                 :            :         int ch;
     243                 :   37549272 :         int w = get_b_utf8(&ch);
     244         [ +  + ]:   43158191 :         if (!w) return -1;
     245 [ +  + ][ +  + ]:   36961727 :         if (!(ch > max || (ch -= min) < 0 || (s[ch >> 3] & (0X1 << (ch & 0X7))) == 0))
         [ +  + ][ +  + ]
     246                 :    5608919 :             return w;
     247                 :   31352808 :         c -= w;
     248                 :            :     } while (repeat);
     249                 :    1423896 :     return 0;
     250                 :            : }
     251                 :            : 
     252                 :   14541641 : int SnowballStemImplementation::eq_s(int s_size, const symbol * s) {
     253 [ +  + ][ +  + ]:   14541641 :     if (l - c < s_size || memcmp(p + c, s, s_size * sizeof(symbol)) != 0)
     254                 :   14507599 :         return 0;
     255                 :      34042 :     c += s_size;
     256                 :      34042 :     return 1;
     257                 :            : }
     258                 :            : 
     259                 :   76671256 : int SnowballStemImplementation::eq_s_b(int s_size, const symbol * s) {
     260 [ +  + ][ +  + ]:   76671256 :     if (c - lb < s_size || memcmp(p + c - s_size, s, s_size * sizeof(symbol)) != 0)
     261                 :   72453590 :         return 0;
     262                 :    4217666 :     c -= s_size;
     263                 :    4217666 :     return 1;
     264                 :            : }
     265                 :            : 
     266                 :            : int
     267                 :   23163398 : SnowballStemImplementation::find_among(const symbol * pool,
     268                 :            :                                        const struct among * v, int v_size,
     269                 :            :                                        const unsigned char * fnum,
     270                 :            :                                        const among_function * f)
     271                 :            : {
     272                 :   23163398 :     int i = 0;
     273                 :   23163398 :     int j = v_size;
     274                 :            : 
     275                 :   23163398 :     const symbol * q = p + c;
     276                 :   23163398 :     int c_orig = c;
     277                 :            : 
     278                 :   23163398 :     int common_i = 0;
     279                 :   23163398 :     int common_j = 0;
     280                 :            : 
     281                 :   23163398 :     int first_key_inspected = 0;
     282                 :            : 
     283                 :            :     while (1) {
     284                 :   88688678 :         int k = i + ((j - i) >> 1);
     285                 :   88688678 :         int diff = 0;
     286         [ +  + ]:   88688678 :         int common = common_i < common_j ? common_i : common_j; /* smaller */
     287                 :   88688678 :         const struct among * w = v + k;
     288         [ +  + ]:   91966880 :         for (int x = common; x < w->s_size; ++x) {
     289         [ +  + ]:   85222834 :             if (c_orig + common == l) { diff = -1; break; }
     290                 :   84276412 :             diff = q[common] - (pool + w->s)[x];
     291         [ +  + ]:   84276412 :             if (diff != 0) break;
     292                 :    3278202 :             ++common;
     293                 :            :         }
     294         [ +  + ]:   88688678 :         if (diff < 0) { j = k; common_j = common; }
     295                 :   33074082 :                  else { i = k; common_i = common; }
     296         [ +  + ]:   88688678 :         if (j - i <= 1) {
     297         [ +  + ]:   33214857 :             if (i > 0) break; /* v->s has been inspected */
     298         [ +  + ]:   20102918 :             if (j == i) break; /* only one item in v */
     299                 :            : 
     300                 :            :             /* - but now we need to go round once more to get
     301                 :            :                v->s inspected. This looks messy, but is actually
     302                 :            :                the optimal approach.  */
     303                 :            : 
     304         [ +  + ]:   16489320 :             if (first_key_inspected) break;
     305                 :   10051459 :             first_key_inspected = 1;
     306                 :            :         }
     307                 :            :     }
     308                 :            :     while (1) {
     309                 :   34338363 :         const struct among * w = v + i;
     310         [ +  + ]:   34338363 :         if (common_i >= w->s_size) {
     311                 :   17891667 :             c = c_orig + w->s_size;
     312 [ +  + ][ +  + ]:   17891667 :             if (!fnum || !fnum[i]) return w->result;
     313                 :            :             {
     314                 :       1074 :                 int res = f[fnum[i] - 1](this);
     315                 :       1074 :                 c = c_orig + w->s_size;
     316         [ +  + ]:       1074 :                 if (res) return w->result;
     317                 :            :             }
     318                 :            :         }
     319                 :   16447020 :         i = w->substring_i;
     320         [ +  + ]:   16447020 :         if (i < 0) return 0;
     321                 :   76700245 :     }
     322                 :            : }
     323                 :            : 
     324                 :            : /* find_among_b is for backwards processing. Same comments apply */
     325                 :            : int
     326                 :   20016215 : SnowballStemImplementation::find_among_b(const symbol * pool,
     327                 :            :                                          const struct among * v, int v_size,
     328                 :            :                                          const unsigned char * fnum,
     329                 :            :                                          const among_function * f)
     330                 :            : {
     331                 :   20016215 :     int i = 0;
     332                 :   20016215 :     int j = v_size;
     333                 :            : 
     334                 :   20016215 :     const symbol * q = p + c - 1;
     335                 :   20016215 :     int c_orig = c;
     336                 :            : 
     337                 :   20016215 :     int common_i = 0;
     338                 :   20016215 :     int common_j = 0;
     339                 :            : 
     340                 :   20016215 :     int first_key_inspected = 0;
     341                 :            : 
     342                 :            :     while (1) {
     343                 :   70830149 :         int k = i + ((j - i) >> 1);
     344                 :   70830149 :         int diff = 0;
     345         [ +  + ]:   70830149 :         int common = common_i < common_j ? common_i : common_j;
     346                 :   70830149 :         const struct among * w = v + k;
     347         [ +  + ]:  106164001 :         for (int x = w->s_size - 1 - common; x >= 0; --x) {
     348         [ +  + ]:  102853103 :             if (c_orig - common == lb) { diff = -1; break; }
     349                 :   98158349 :             diff = q[- common] - (pool + w->s)[x];
     350         [ +  + ]:   98158349 :             if (diff != 0) break;
     351                 :   35333852 :             ++common;
     352                 :            :         }
     353         [ +  + ]:   70830149 :         if (diff < 0) { j = k; common_j = common; }
     354                 :   32083412 :                  else { i = k; common_i = common; }
     355         [ +  + ]:   70830149 :         if (j - i <= 1) {
     356         [ +  + ]:   26395030 :             if (i > 0) break;
     357         [ +  + ]:   12759477 :             if (j == i) break;
     358         [ +  + ]:    8409795 :             if (first_key_inspected) break;
     359                 :    6378815 :             first_key_inspected = 1;
     360                 :            :         }
     361                 :            :     }
     362                 :            :     while (1) {
     363                 :   22594029 :         const struct among * w = v + i;
     364         [ +  + ]:   22594029 :         if (common_i >= w->s_size) {
     365                 :    3723142 :             c = c_orig - w->s_size;
     366 [ +  + ][ +  + ]:    3723142 :             if (!fnum || !fnum[i]) return w->result;
     367                 :            :             {
     368                 :      56694 :                 int res = f[fnum[i] - 1](this);
     369                 :      56694 :                 c = c_orig - w->s_size;
     370         [ +  + ]:      56694 :                 if (res) return w->result;
     371                 :            :             }
     372                 :            :         }
     373                 :   18878230 :         i = w->substring_i;
     374         [ +  + ]:   18878230 :         if (i < 0) return 0;
     375                 :   53391748 :     }
     376                 :            : }
     377                 :            : 
     378                 :            : int
     379                 :    9469907 : SnowballStemImplementation::replace_s(int c_bra, int c_ket, int s_size,
     380                 :            :                                       const symbol * s)
     381                 :            : {
     382                 :            :     int adjustment;
     383                 :            :     int len;
     384                 :            :     Assert(p);
     385                 :    9469907 :     adjustment = s_size - (c_ket - c_bra);
     386                 :    9469907 :     len = SIZE(p);
     387         [ +  + ]:    9469907 :     if (adjustment != 0) {
     388         [ +  + ]:    8223817 :         if (adjustment + len > CAPACITY(p)) {
     389                 :        398 :             p = increase_size(p, adjustment + len);
     390                 :            :         }
     391                 :    8223817 :         memmove(p + c_ket + adjustment,
     392                 :            :                 p + c_ket,
     393                 :   16447634 :                 (len - c_ket) * sizeof(symbol));
     394                 :    8223817 :         SET_SIZE(p, adjustment + len);
     395                 :    8223817 :         l += adjustment;
     396         [ +  + ]:    8223817 :         if (c >= c_ket)
     397                 :     162663 :             c += adjustment;
     398                 :            :         else
     399         [ +  + ]:    8061154 :             if (c > c_bra)
     400                 :      10813 :                 c = c_bra;
     401                 :            :     }
     402         [ +  + ]:    9469907 :     if (s_size != 0) memmove(p + c_bra, s, s_size * sizeof(symbol));
     403                 :    9469907 :     return adjustment;
     404                 :            : }
     405                 :            : 
     406                 :    3381491 : int SnowballStemImplementation::slice_check() {
     407                 :            :     Assert(p);
     408 [ +  - ][ +  - ]:    3381491 :     if (bra < 0 || bra > ket || ket > l) {
                 [ -  + ]
     409                 :            : #if 0
     410                 :            :         fprintf(stderr, "faulty slice operation:\n");
     411                 :            :         debug(z, -1, 0);
     412                 :            : #endif
     413                 :          0 :         return -1;
     414                 :            :     }
     415                 :    3381491 :     return 0;
     416                 :            : }
     417                 :            : 
     418                 :    3211243 : int SnowballStemImplementation::slice_from_s(int s_size, const symbol * s) {
     419         [ -  + ]:    3211243 :     if (slice_check()) return -1;
     420                 :    3211243 :     replace_s(bra, ket, s_size, s);
     421                 :    3211243 :     return 0;
     422                 :            : }
     423                 :            : 
     424                 :            : void
     425                 :      27144 : SnowballStemImplementation::insert_s(int c_bra, int c_ket, int s_size,
     426                 :            :                                      const symbol * s)
     427                 :            : {
     428                 :      27144 :     int adjustment = replace_s(c_bra, c_ket, s_size, s);
     429         [ +  + ]:      27144 :     if (c_bra <= bra) bra += adjustment;
     430         [ +  - ]:      27144 :     if (c_bra <= ket) ket += adjustment;
     431                 :      27144 : }
     432                 :            : 
     433                 :     170248 : symbol * SnowballStemImplementation::slice_to(symbol * v) {
     434         [ -  + ]:     170248 :     if (slice_check()) return NULL;
     435                 :            :     {
     436                 :     170248 :         int len = ket - bra;
     437         [ -  + ]:     170248 :         if (CAPACITY(v) < len) {
     438                 :          0 :             v = increase_size(v, len);
     439                 :            :         }
     440                 :     170248 :         memmove(v, p + bra, len * sizeof(symbol));
     441                 :     170248 :         SET_SIZE(v, len);
     442                 :            :     }
     443                 :     170248 :     return v;
     444                 :            : }
     445                 :            : 
     446                 :          0 : symbol * SnowballStemImplementation::assign_to(symbol * v) {
     447                 :          0 :     int len = l;
     448         [ #  # ]:          0 :     if (CAPACITY(v) < len) {
     449                 :          0 :         v = increase_size(v, len);
     450                 :            :     }
     451                 :          0 :     memmove(v, p, len * sizeof(symbol));
     452                 :          0 :     SET_SIZE(v, len);
     453                 :          0 :     return v;
     454                 :            : }
     455                 :            : 
     456                 :    6027278 : int SnowballStemImplementation::len_utf8(const symbol * v) {
     457                 :    6027278 :     int size = SIZE(v);
     458                 :    6027278 :     int len = 0;
     459         [ +  + ]:  204425456 :     while (size--) {
     460                 :  198398178 :         symbol b = *v++;
     461 [ +  + ][ +  + ]:  198398178 :         if (b >= 0xC0 || b < 0x80) ++len;
     462                 :            :     }
     463                 :    6027278 :     return len;
     464                 :            : }
     465                 :            : 
     466                 :            : #if 0
     467                 :            : void SnowballStemImplementation::debug(int number, int line_count) {
     468                 :            :     int i;
     469                 :            :     int limit = SIZE(p);
     470                 :            :     if (number >= 0) printf("%3d (line %4d): [%d]'", number, line_count, limit);
     471                 :            :     for (i = 0; i <= limit; ++i) {
     472                 :            :         if (lb == i) printf("{");
     473                 :            :         if (bra == i) printf("[");
     474                 :            :         if (c == i) printf("|");
     475                 :            :         if (ket == i) printf("]");
     476                 :            :         if (l == i) printf("}");
     477                 :            :         if (i < limit) {
     478                 :            :             int ch = p[i];
     479                 :            :             if (ch == 0) ch = '#';
     480                 :            :             printf("%c", ch);
     481                 :            :         }
     482                 :            :     }
     483                 :            :     printf("'\n");
     484                 :            : }
     485                 :            : #endif
     486                 :            : }

Generated by: LCOV version 1.11