Coverage Report

Created: 2025-07-11 06:34

/src/aspell/modules/speller/default/phonetic.cpp
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2000 by Kevin Atkinson under the terms of the LGPL
2
3
#include "language.hpp"
4
#include "phonetic.hpp"
5
#include "phonet.hpp"
6
7
#include "file_util.hpp"
8
#include "file_data_util.hpp"
9
#include "clone_ptr-t.hpp"
10
11
namespace aspeller {
12
  
13
  class SimpileSoundslike : public Soundslike {
14
  private:
15
    const Language * lang;
16
    char first[256];
17
    char rest[256];
18
  public:
19
27
    SimpileSoundslike(const Language * l) : lang(l) {}
20
21
27
    PosibErr<void> setup(Conv &) {
22
27
      memcpy(first, lang->sl_first_, 256);
23
27
      memcpy(rest,  lang->sl_rest_, 256);
24
27
      return no_err;
25
27
    }
26
    
27
27
    String soundslike_chars() const {
28
27
      bool chars_set[256] = {0};
29
6.93k
      for (int i = 0; i != 256; ++i) 
30
6.91k
      {
31
6.91k
        char c = first[i];
32
6.91k
        if (c) chars_set[static_cast<unsigned char>(c)] = true;
33
6.91k
        c = rest[i];
34
6.91k
        if (c) chars_set[static_cast<unsigned char>(c)] = true;
35
6.91k
      }
36
27
      String     chars_list;
37
6.93k
      for (int i = 0; i != 256; ++i) 
38
6.91k
      {
39
6.91k
        if (chars_set[i]) 
40
675
          chars_list += static_cast<char>(i);
41
6.91k
      }
42
27
      return chars_list;
43
27
    }
44
    
45
    char * to_soundslike(char * res, const char * str, int size) const 
46
696k
    {
47
696k
      char prev, cur = '\0';
48
49
696k
      const char * i = str;
50
700k
      while (*i) {
51
700k
        cur = first[static_cast<unsigned char>(*i++)];
52
700k
        if (cur) {*res++ = cur; break;}
53
700k
      }
54
696k
      prev = cur;
55
      
56
5.00M
      while (*i) {
57
4.30M
  cur = rest[static_cast<unsigned char>(*i++)];
58
4.30M
  if (cur && cur != prev) *res++ = cur;
59
4.30M
  prev = cur;
60
4.30M
      }
61
696k
      *res = '\0';
62
696k
      return res;
63
696k
    }
64
65
54
    const char * name () const {
66
54
      return "simple";
67
54
    }
68
27
    const char * version() const {
69
27
      return "2.0";
70
27
    }
71
  };
72
73
  class NoSoundslike : public Soundslike {
74
  private:
75
    const Language * lang;
76
  public:
77
0
    NoSoundslike(const Language * l) : lang(l) {}
78
79
0
    PosibErr<void> setup(Conv &) {return no_err;}
80
    
81
0
    String soundslike_chars() const {
82
0
      return get_clean_chars(*lang);
83
0
    }
84
85
    char * to_soundslike(char * res, const char * str, int size) const 
86
0
    {
87
0
      return lang->LangImpl::to_clean(res, str);
88
0
    }
89
90
0
    const char * name() const {
91
0
      return "none";
92
0
    }
93
0
    const char * version() const {
94
0
      return "1.0";
95
0
    }
96
  };
97
98
  class StrippedSoundslike : public Soundslike {
99
  private:
100
    const Language * lang;
101
  public:
102
0
    StrippedSoundslike(const Language * l) : lang(l) {}
103
104
0
    PosibErr<void> setup(Conv &) {return no_err;}
105
    
106
0
    String soundslike_chars() const {
107
0
      return get_stripped_chars(*lang);
108
0
    }
109
110
    char * to_soundslike(char * res, const char * str, int size) const 
111
0
    {
112
0
      return lang->LangImpl::to_stripped(res, str);
113
0
    }
114
115
0
    const char * name() const {
116
0
      return "stripped";
117
0
    }
118
0
    const char * version() const {
119
0
      return "1.0";
120
0
    }
121
  };
122
123
  class PhonetSoundslike : public Soundslike {
124
125
    const Language * lang;
126
    StackPtr<PhonetParms> phonet_parms;
127
    
128
  public:
129
130
1.00k
    PhonetSoundslike(const Language * l) : lang(l) {}
131
132
1.00k
    PosibErr<void> setup(Conv & iconv) {
133
1.00k
      String file;
134
1.00k
      file += lang->data_dir();
135
1.00k
      file += '/';
136
1.00k
      file += lang->name();
137
1.00k
      file += "_phonet.dat";
138
1.00k
      PosibErr<PhonetParms *> pe = new_phonet(file, iconv, lang);
139
1.00k
      if (pe.has_err()) return pe;
140
1.00k
      phonet_parms.reset(pe);
141
1.00k
      return no_err;
142
1.00k
    }
143
144
145
    String soundslike_chars() const 
146
1.00k
    {
147
1.00k
      bool chars_set[256] = {0};
148
1.00k
      String     chars_list;
149
1.00k
      for (const char * * i = phonet_parms->rules + 1; 
150
106k
     *(i-1) != PhonetParms::rules_end;
151
105k
     i += 2) 
152
105k
      {
153
211k
        for (const char * j = *i; *j; ++j) 
154
105k
        {
155
105k
          chars_set[static_cast<unsigned char>(*j)] = true;
156
105k
        }
157
105k
      }
158
258k
      for (int i = 0; i != 256; ++i) 
159
257k
      {
160
257k
        if (chars_set[i]) 
161
18.1k
          chars_list += static_cast<char>(i);
162
257k
      }
163
1.00k
      return chars_list;
164
1.00k
    }
165
    
166
    char * to_soundslike(char * res, const char * str, int size) const 
167
321k
    {
168
321k
      int new_size = phonet(str, res, size, *phonet_parms);
169
321k
      return res + new_size;
170
321k
    }
171
    
172
    const char * name() const
173
3.02k
    {
174
3.02k
      return "phonet";
175
3.02k
    }
176
    const char * version() const 
177
2.01k
    {
178
2.01k
      return phonet_parms->version.c_str();
179
2.01k
    }
180
  };
181
  
182
  
183
  PosibErr<Soundslike *> new_soundslike(ParmString name, 
184
                                        Conv & iconv,
185
                                        const Language * lang)
186
1.03k
  {
187
1.03k
    Soundslike * sl;
188
1.03k
    if (name == "simple" || name == "generic") {
189
27
      sl = new SimpileSoundslike(lang);
190
1.00k
    } else if (name == "stripped") {
191
0
      sl = new StrippedSoundslike(lang);
192
1.00k
    } else if (name == "none") {
193
0
      sl = new NoSoundslike(lang);
194
1.00k
    } else if (name == lang->name()) {
195
1.00k
      sl = new PhonetSoundslike(lang);
196
1.00k
    } else {
197
0
      abort(); // FIXME
198
0
    }
199
1.03k
    PosibErrBase pe = sl->setup(iconv);
200
1.03k
    if (pe.has_err()) {
201
0
      delete sl;
202
0
      return pe;
203
1.03k
    } else {
204
1.03k
      return sl;
205
1.03k
    }
206
1.03k
  }
207
}
208