Coverage Report

Created: 2026-11-12 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libunistring/lib/uninorm/u-normalize-internal.h
Line
Count
Source
1
/* Decomposition and composition of Unicode strings.
2
   Copyright (C) 2009-2026 Free Software Foundation, Inc.
3
   Written by Bruno Haible <bruno@clisp.org>, 2009.
4
5
   This file is free software: you can redistribute it and/or modify
6
   it under the terms of the GNU Lesser General Public License as
7
   published by the Free Software Foundation; either version 2.1 of the
8
   License, or (at your option) any later version.
9
10
   This file is distributed in the hope that it will be useful,
11
   but WITHOUT ANY WARRANTY; without even the implied warranty of
12
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
   GNU Lesser General Public License for more details.
14
15
   You should have received a copy of the GNU Lesser General Public License
16
   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
17
18
UNIT *
19
FUNC (uninorm_t nf, const UNIT *s, size_t n,
20
      UNIT *resultbuf, size_t *lengthp)
21
38.5k
{
22
38.5k
  int (*decomposer) (ucs4_t uc, ucs4_t *decomposition) = nf->decomposer;
23
38.5k
  ucs4_t (*composer) (ucs4_t uc1, ucs4_t uc2) = nf->composer;
24
25
  /* The result being accumulated.  */
26
38.5k
  UNIT *result;
27
38.5k
  size_t allocated;
28
38.5k
  if (resultbuf == NULL)
29
38.5k
    {
30
38.5k
      result = NULL;
31
38.5k
      allocated = 0;
32
38.5k
    }
33
0
  else
34
0
    {
35
0
      result = resultbuf;
36
0
      allocated = *lengthp;
37
0
    }
38
38.5k
  size_t length = 0;
39
40
  /* The buffer for sorting.  */
41
38.5k
  #define SORTBUF_PREALLOCATED 64
42
38.5k
  struct ucs4_with_ccc sortbuf_preallocated[2 * SORTBUF_PREALLOCATED];
43
38.5k
  struct ucs4_with_ccc *sortbuf = /* array of size 2 * sortbuf_allocated */
44
38.5k
    sortbuf_preallocated;
45
38.5k
  size_t sortbuf_allocated = SORTBUF_PREALLOCATED;
46
38.5k
  size_t sortbuf_count = 0;
47
48
38.5k
  {
49
38.5k
    const UNIT *s_end = s + n;
50
51
38.5k
    for (;;)
52
369k
      {
53
369k
        int count;
54
369k
        ucs4_t decomposed[UC_DECOMPOSITION_MAX_LENGTH];
55
369k
        int decomposed_count;
56
57
369k
        if (s < s_end)
58
330k
          {
59
            /* Fetch the next character.  */
60
330k
            count = U_MBTOUC_UNSAFE (&decomposed[0], s, s_end - s);
61
330k
            decomposed_count = 1;
62
63
            /* Decompose it, recursively.
64
               It would be possible to precompute the recursive decomposition
65
               and store it in a table.  But this would significantly increase
66
               the size of the decomposition tables, because for example for
67
               U+1FC1 the recursive canonical decomposition and the recursive
68
               compatibility decomposition are different.  */
69
688k
            for (int curr = 0; curr < decomposed_count; )
70
358k
              {
71
                /* Invariant: decomposed[0..curr-1] is fully decomposed, i.e.
72
                   all elements are atomic.  */
73
358k
                ucs4_t curr_decomposed[UC_DECOMPOSITION_MAX_LENGTH];
74
358k
                int curr_decomposed_count;
75
76
358k
                curr_decomposed_count = decomposer (decomposed[curr], curr_decomposed);
77
358k
                if (curr_decomposed_count >= 0)
78
13.8k
                  {
79
                    /* Move curr_decomposed[0..curr_decomposed_count-1] over
80
                       decomposed[curr], making room.  It's not worth using
81
                       memcpy() here, since the counts are so small.  */
82
13.8k
                    int shift = curr_decomposed_count - 1;
83
84
13.8k
                    if (shift < 0)
85
0
                      abort ();
86
13.8k
                    if (shift > 0)
87
13.6k
                      {
88
13.6k
                        decomposed_count += shift;
89
13.6k
                        if (decomposed_count > UC_DECOMPOSITION_MAX_LENGTH)
90
0
                          abort ();
91
19.2k
                        for (int j = decomposed_count - 1 - shift; j > curr; j--)
92
5.61k
                          decomposed[j + shift] = decomposed[j];
93
13.6k
                      }
94
41.4k
                    for (; shift >= 0; shift--)
95
27.5k
                      decomposed[curr + shift] = curr_decomposed[shift];
96
13.8k
                  }
97
344k
                else
98
344k
                  {
99
                    /* decomposed[curr] is atomic.  */
100
344k
                    curr++;
101
344k
                  }
102
358k
              }
103
330k
          }
104
38.5k
        else
105
38.5k
          {
106
38.5k
            count = 0;
107
38.5k
            decomposed_count = 0;
108
38.5k
          }
109
110
369k
        int i = 0;
111
369k
        for (;;)
112
713k
          {
113
713k
            ucs4_t uc;
114
713k
            int ccc;
115
116
713k
            if (s < s_end)
117
674k
              {
118
                /* Fetch the next character from the decomposition.  */
119
674k
                if (i == decomposed_count)
120
330k
                  break;
121
344k
                uc = decomposed[i];
122
344k
                ccc = uc_combining_class (uc);
123
344k
              }
124
38.5k
            else
125
38.5k
              {
126
                /* End of string reached.  */
127
38.5k
                uc = 0;
128
38.5k
                ccc = 0;
129
38.5k
              }
130
131
382k
            if (ccc == 0)
132
328k
              {
133
                /* Apply the canonical ordering algorithm to the accumulated
134
                   sequence of characters.  */
135
328k
                if (sortbuf_count > 1)
136
11.6k
                  gl_uninorm_decompose_merge_sort_inplace (sortbuf, sortbuf_count,
137
11.6k
                                                           sortbuf + sortbuf_count);
138
139
328k
                if (composer != NULL)
140
328k
                  {
141
                    /* Attempt to combine decomposed characters, as specified
142
                       in the Unicode Standard Annex #15 "Unicode Normalization
143
                       Forms".  We need to check
144
                         1. whether the first accumulated character is a
145
                            "starter" (i.e. has ccc = 0).  This is usually the
146
                            case.  But when the string starts with a
147
                            non-starter, the sortbuf also starts with a
148
                            non-starter.  Btw, this check could also be
149
                            omitted, because the composition table has only
150
                            entries (code1, code2) for which code1 is a
151
                            starter; if the first accumulated character is not
152
                            a starter, no lookup will succeed.
153
                         2. If the sortbuf has more than one character, check
154
                            for each of these characters that are not "blocked"
155
                            from the starter (i.e. have a ccc that is higher
156
                            than the ccc of the previous character) whether it
157
                            can be combined with the first character.
158
                         3. If only one character is left in sortbuf, check
159
                            whether it can be combined with the next character
160
                            (also a starter).  */
161
328k
                    if (sortbuf_count > 0 && sortbuf[0].ccc == 0)
162
290k
                      {
163
342k
                        for (size_t j = 1; j < sortbuf_count; )
164
52.4k
                          {
165
52.4k
                            if (sortbuf[j].ccc > sortbuf[j - 1].ccc)
166
25.1k
                              {
167
25.1k
                                ucs4_t combined =
168
25.1k
                                  composer (sortbuf[0].code, sortbuf[j].code);
169
25.1k
                                if (combined)
170
9.78k
                                  {
171
9.78k
                                    sortbuf[0].code = combined;
172
                                    /* sortbuf[0].ccc = 0, still valid.  */
173
34.4k
                                    for (size_t k = j + 1; k < sortbuf_count; k++)
174
24.6k
                                      sortbuf[k - 1] = sortbuf[k];
175
9.78k
                                    sortbuf_count--;
176
9.78k
                                    continue;
177
9.78k
                                  }
178
25.1k
                              }
179
42.6k
                            j++;
180
42.6k
                          }
181
290k
                        if (s < s_end && sortbuf_count == 1)
182
245k
                          {
183
245k
                            ucs4_t combined =
184
245k
                              composer (sortbuf[0].code, uc);
185
245k
                            if (combined)
186
3.14k
                              {
187
3.14k
                                uc = combined;
188
3.14k
                                ccc = 0;
189
                                /* uc could be further combined with subsequent
190
                                   characters.  So don't put it into sortbuf[0] in
191
                                   this round, only in the next round.  */
192
3.14k
                                sortbuf_count = 0;
193
3.14k
                              }
194
245k
                          }
195
290k
                      }
196
328k
                  }
197
198
660k
                for (size_t j = 0; j < sortbuf_count; j++)
199
331k
                  {
200
331k
                    ucs4_t muc = sortbuf[j].code;
201
202
                    /* Append muc to the result accumulator.  */
203
331k
                    if (length < allocated)
204
292k
                      {
205
292k
                        int ret =
206
292k
                          U_UCTOMB (result + length, muc, allocated - length);
207
292k
                        if (ret == -1)
208
0
                          {
209
0
                            errno = EINVAL;
210
0
                            goto fail;
211
0
                          }
212
292k
                        if (ret >= 0)
213
292k
                          {
214
292k
                            length += ret;
215
292k
                            goto done_appending;
216
292k
                          }
217
292k
                      }
218
39.0k
                    {
219
39.0k
                      size_t old_allocated = allocated;
220
39.0k
                      size_t new_allocated = 2 * old_allocated;
221
39.0k
                      if (new_allocated < 64)
222
37.9k
                        new_allocated = 64;
223
39.0k
                      if (new_allocated < old_allocated) /* integer overflow? */
224
0
                        abort ();
225
39.0k
                      {
226
39.0k
                        UNIT *larger_result;
227
39.0k
                        if (result == NULL)
228
37.9k
                          {
229
37.9k
                            larger_result =
230
37.9k
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
231
37.9k
                            if (larger_result == NULL)
232
0
                              {
233
0
                                errno = ENOMEM;
234
0
                                goto fail;
235
0
                              }
236
37.9k
                          }
237
1.05k
                        else if (result == resultbuf)
238
0
                          {
239
0
                            larger_result =
240
0
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
241
0
                            if (larger_result == NULL)
242
0
                              {
243
0
                                errno = ENOMEM;
244
0
                                goto fail;
245
0
                              }
246
0
                            U_CPY (larger_result, resultbuf, length);
247
0
                          }
248
1.05k
                        else
249
1.05k
                          {
250
1.05k
                            larger_result =
251
1.05k
                              (UNIT *) realloc (result, new_allocated * sizeof (UNIT));
252
1.05k
                            if (larger_result == NULL)
253
0
                              {
254
0
                                errno = ENOMEM;
255
0
                                goto fail;
256
0
                              }
257
1.05k
                          }
258
39.0k
                        result = larger_result;
259
39.0k
                        allocated = new_allocated;
260
39.0k
                        {
261
39.0k
                          int ret =
262
39.0k
                            U_UCTOMB (result + length, muc, allocated - length);
263
39.0k
                          if (ret == -1)
264
0
                            {
265
0
                              errno = EINVAL;
266
0
                              goto fail;
267
0
                            }
268
39.0k
                          if (ret < 0)
269
0
                            abort ();
270
39.0k
                          length += ret;
271
39.0k
                          goto done_appending;
272
39.0k
                        }
273
39.0k
                      }
274
39.0k
                    }
275
331k
                   done_appending: ;
276
331k
                  }
277
278
                /* sortbuf is now empty.  */
279
328k
                sortbuf_count = 0;
280
328k
              }
281
282
382k
            if (!(s < s_end))
283
              /* End of string reached.  */
284
38.5k
              break;
285
286
            /* Append (uc, ccc) to sortbuf.  */
287
344k
            if (sortbuf_count == sortbuf_allocated)
288
175
              {
289
175
                sortbuf_allocated = 2 * sortbuf_allocated;
290
175
                if (sortbuf_allocated < sortbuf_count) /* integer overflow? */
291
0
                  abort ();
292
175
                struct ucs4_with_ccc *new_sortbuf =
293
175
                  (struct ucs4_with_ccc *) malloc (2 * sortbuf_allocated * sizeof (struct ucs4_with_ccc));
294
175
                if (new_sortbuf == NULL)
295
0
                  {
296
0
                    errno = ENOMEM;
297
0
                    goto fail;
298
0
                  }
299
175
                memcpy (new_sortbuf, sortbuf,
300
175
                        sortbuf_count * sizeof (struct ucs4_with_ccc));
301
175
                if (sortbuf != sortbuf_preallocated)
302
175
                  free (sortbuf);
303
175
                sortbuf = new_sortbuf;
304
175
              }
305
344k
            sortbuf[sortbuf_count].code = uc;
306
344k
            sortbuf[sortbuf_count].ccc = ccc;
307
344k
            sortbuf_count++;
308
309
344k
            i++;
310
344k
          }
311
312
369k
        if (!(s < s_end))
313
          /* End of string reached.  */
314
38.5k
          break;
315
316
330k
        s += count;
317
330k
      }
318
38.5k
  }
319
320
38.5k
  if (length == 0)
321
587
    {
322
587
      if (result == NULL)
323
587
        {
324
          /* Return a non-NULL value.  NULL means error.  */
325
587
          result = (UNIT *) malloc (1);
326
587
          if (result == NULL)
327
0
            {
328
0
              errno = ENOMEM;
329
0
              goto fail;
330
0
            }
331
587
        }
332
587
    }
333
37.9k
  else if (result != resultbuf && length < allocated)
334
37.8k
    {
335
      /* Shrink the allocated memory if possible.  */
336
37.8k
      UNIT *memory = (UNIT *) realloc (result, length * sizeof (UNIT));
337
37.8k
      if (memory != NULL)
338
37.8k
        result = memory;
339
37.8k
    }
340
341
38.5k
  if (sortbuf_count > 0)
342
0
    abort ();
343
38.5k
  if (sortbuf != sortbuf_preallocated)
344
38.5k
    free (sortbuf);
345
346
38.5k
  *lengthp = length;
347
38.5k
  return result;
348
349
0
 fail:
350
0
  {
351
0
    int saved_errno = errno;
352
0
    if (sortbuf != sortbuf_preallocated)
353
0
      free (sortbuf);
354
0
    if (result != resultbuf)
355
0
      free (result);
356
0
    errno = saved_errno;
357
0
  }
358
  return NULL;
359
38.5k
}
u16_normalize
Line
Count
Source
21
10.1k
{
22
10.1k
  int (*decomposer) (ucs4_t uc, ucs4_t *decomposition) = nf->decomposer;
23
10.1k
  ucs4_t (*composer) (ucs4_t uc1, ucs4_t uc2) = nf->composer;
24
25
  /* The result being accumulated.  */
26
10.1k
  UNIT *result;
27
10.1k
  size_t allocated;
28
10.1k
  if (resultbuf == NULL)
29
10.1k
    {
30
10.1k
      result = NULL;
31
10.1k
      allocated = 0;
32
10.1k
    }
33
0
  else
34
0
    {
35
0
      result = resultbuf;
36
0
      allocated = *lengthp;
37
0
    }
38
10.1k
  size_t length = 0;
39
40
  /* The buffer for sorting.  */
41
10.1k
  #define SORTBUF_PREALLOCATED 64
42
10.1k
  struct ucs4_with_ccc sortbuf_preallocated[2 * SORTBUF_PREALLOCATED];
43
10.1k
  struct ucs4_with_ccc *sortbuf = /* array of size 2 * sortbuf_allocated */
44
10.1k
    sortbuf_preallocated;
45
10.1k
  size_t sortbuf_allocated = SORTBUF_PREALLOCATED;
46
10.1k
  size_t sortbuf_count = 0;
47
48
10.1k
  {
49
10.1k
    const UNIT *s_end = s + n;
50
51
10.1k
    for (;;)
52
55.9k
      {
53
55.9k
        int count;
54
55.9k
        ucs4_t decomposed[UC_DECOMPOSITION_MAX_LENGTH];
55
55.9k
        int decomposed_count;
56
57
55.9k
        if (s < s_end)
58
45.8k
          {
59
            /* Fetch the next character.  */
60
45.8k
            count = U_MBTOUC_UNSAFE (&decomposed[0], s, s_end - s);
61
45.8k
            decomposed_count = 1;
62
63
            /* Decompose it, recursively.
64
               It would be possible to precompute the recursive decomposition
65
               and store it in a table.  But this would significantly increase
66
               the size of the decomposition tables, because for example for
67
               U+1FC1 the recursive canonical decomposition and the recursive
68
               compatibility decomposition are different.  */
69
91.6k
            for (int curr = 0; curr < decomposed_count; )
70
45.8k
              {
71
                /* Invariant: decomposed[0..curr-1] is fully decomposed, i.e.
72
                   all elements are atomic.  */
73
45.8k
                ucs4_t curr_decomposed[UC_DECOMPOSITION_MAX_LENGTH];
74
45.8k
                int curr_decomposed_count;
75
76
45.8k
                curr_decomposed_count = decomposer (decomposed[curr], curr_decomposed);
77
45.8k
                if (curr_decomposed_count >= 0)
78
0
                  {
79
                    /* Move curr_decomposed[0..curr_decomposed_count-1] over
80
                       decomposed[curr], making room.  It's not worth using
81
                       memcpy() here, since the counts are so small.  */
82
0
                    int shift = curr_decomposed_count - 1;
83
84
0
                    if (shift < 0)
85
0
                      abort ();
86
0
                    if (shift > 0)
87
0
                      {
88
0
                        decomposed_count += shift;
89
0
                        if (decomposed_count > UC_DECOMPOSITION_MAX_LENGTH)
90
0
                          abort ();
91
0
                        for (int j = decomposed_count - 1 - shift; j > curr; j--)
92
0
                          decomposed[j + shift] = decomposed[j];
93
0
                      }
94
0
                    for (; shift >= 0; shift--)
95
0
                      decomposed[curr + shift] = curr_decomposed[shift];
96
0
                  }
97
45.8k
                else
98
45.8k
                  {
99
                    /* decomposed[curr] is atomic.  */
100
45.8k
                    curr++;
101
45.8k
                  }
102
45.8k
              }
103
45.8k
          }
104
10.1k
        else
105
10.1k
          {
106
10.1k
            count = 0;
107
10.1k
            decomposed_count = 0;
108
10.1k
          }
109
110
55.9k
        int i = 0;
111
55.9k
        for (;;)
112
101k
          {
113
101k
            ucs4_t uc;
114
101k
            int ccc;
115
116
101k
            if (s < s_end)
117
91.6k
              {
118
                /* Fetch the next character from the decomposition.  */
119
91.6k
                if (i == decomposed_count)
120
45.8k
                  break;
121
45.8k
                uc = decomposed[i];
122
45.8k
                ccc = uc_combining_class (uc);
123
45.8k
              }
124
10.1k
            else
125
10.1k
              {
126
                /* End of string reached.  */
127
10.1k
                uc = 0;
128
10.1k
                ccc = 0;
129
10.1k
              }
130
131
55.9k
            if (ccc == 0)
132
55.9k
              {
133
                /* Apply the canonical ordering algorithm to the accumulated
134
                   sequence of characters.  */
135
55.9k
                if (sortbuf_count > 1)
136
0
                  gl_uninorm_decompose_merge_sort_inplace (sortbuf, sortbuf_count,
137
0
                                                           sortbuf + sortbuf_count);
138
139
55.9k
                if (composer != NULL)
140
55.9k
                  {
141
                    /* Attempt to combine decomposed characters, as specified
142
                       in the Unicode Standard Annex #15 "Unicode Normalization
143
                       Forms".  We need to check
144
                         1. whether the first accumulated character is a
145
                            "starter" (i.e. has ccc = 0).  This is usually the
146
                            case.  But when the string starts with a
147
                            non-starter, the sortbuf also starts with a
148
                            non-starter.  Btw, this check could also be
149
                            omitted, because the composition table has only
150
                            entries (code1, code2) for which code1 is a
151
                            starter; if the first accumulated character is not
152
                            a starter, no lookup will succeed.
153
                         2. If the sortbuf has more than one character, check
154
                            for each of these characters that are not "blocked"
155
                            from the starter (i.e. have a ccc that is higher
156
                            than the ccc of the previous character) whether it
157
                            can be combined with the first character.
158
                         3. If only one character is left in sortbuf, check
159
                            whether it can be combined with the next character
160
                            (also a starter).  */
161
55.9k
                    if (sortbuf_count > 0 && sortbuf[0].ccc == 0)
162
45.8k
                      {
163
45.8k
                        for (size_t j = 1; j < sortbuf_count; )
164
0
                          {
165
0
                            if (sortbuf[j].ccc > sortbuf[j - 1].ccc)
166
0
                              {
167
0
                                ucs4_t combined =
168
0
                                  composer (sortbuf[0].code, sortbuf[j].code);
169
0
                                if (combined)
170
0
                                  {
171
0
                                    sortbuf[0].code = combined;
172
                                    /* sortbuf[0].ccc = 0, still valid.  */
173
0
                                    for (size_t k = j + 1; k < sortbuf_count; k++)
174
0
                                      sortbuf[k - 1] = sortbuf[k];
175
0
                                    sortbuf_count--;
176
0
                                    continue;
177
0
                                  }
178
0
                              }
179
0
                            j++;
180
0
                          }
181
45.8k
                        if (s < s_end && sortbuf_count == 1)
182
35.7k
                          {
183
35.7k
                            ucs4_t combined =
184
35.7k
                              composer (sortbuf[0].code, uc);
185
35.7k
                            if (combined)
186
0
                              {
187
0
                                uc = combined;
188
0
                                ccc = 0;
189
                                /* uc could be further combined with subsequent
190
                                   characters.  So don't put it into sortbuf[0] in
191
                                   this round, only in the next round.  */
192
0
                                sortbuf_count = 0;
193
0
                              }
194
35.7k
                          }
195
45.8k
                      }
196
55.9k
                  }
197
198
101k
                for (size_t j = 0; j < sortbuf_count; j++)
199
45.8k
                  {
200
45.8k
                    ucs4_t muc = sortbuf[j].code;
201
202
                    /* Append muc to the result accumulator.  */
203
45.8k
                    if (length < allocated)
204
35.7k
                      {
205
35.7k
                        int ret =
206
35.7k
                          U_UCTOMB (result + length, muc, allocated - length);
207
35.7k
                        if (ret == -1)
208
0
                          {
209
0
                            errno = EINVAL;
210
0
                            goto fail;
211
0
                          }
212
35.7k
                        if (ret >= 0)
213
35.7k
                          {
214
35.7k
                            length += ret;
215
35.7k
                            goto done_appending;
216
35.7k
                          }
217
35.7k
                      }
218
10.1k
                    {
219
10.1k
                      size_t old_allocated = allocated;
220
10.1k
                      size_t new_allocated = 2 * old_allocated;
221
10.1k
                      if (new_allocated < 64)
222
10.1k
                        new_allocated = 64;
223
10.1k
                      if (new_allocated < old_allocated) /* integer overflow? */
224
0
                        abort ();
225
10.1k
                      {
226
10.1k
                        UNIT *larger_result;
227
10.1k
                        if (result == NULL)
228
10.1k
                          {
229
10.1k
                            larger_result =
230
10.1k
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
231
10.1k
                            if (larger_result == NULL)
232
0
                              {
233
0
                                errno = ENOMEM;
234
0
                                goto fail;
235
0
                              }
236
10.1k
                          }
237
0
                        else if (result == resultbuf)
238
0
                          {
239
0
                            larger_result =
240
0
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
241
0
                            if (larger_result == NULL)
242
0
                              {
243
0
                                errno = ENOMEM;
244
0
                                goto fail;
245
0
                              }
246
0
                            U_CPY (larger_result, resultbuf, length);
247
0
                          }
248
0
                        else
249
0
                          {
250
0
                            larger_result =
251
0
                              (UNIT *) realloc (result, new_allocated * sizeof (UNIT));
252
0
                            if (larger_result == NULL)
253
0
                              {
254
0
                                errno = ENOMEM;
255
0
                                goto fail;
256
0
                              }
257
0
                          }
258
10.1k
                        result = larger_result;
259
10.1k
                        allocated = new_allocated;
260
10.1k
                        {
261
10.1k
                          int ret =
262
10.1k
                            U_UCTOMB (result + length, muc, allocated - length);
263
10.1k
                          if (ret == -1)
264
0
                            {
265
0
                              errno = EINVAL;
266
0
                              goto fail;
267
0
                            }
268
10.1k
                          if (ret < 0)
269
0
                            abort ();
270
10.1k
                          length += ret;
271
10.1k
                          goto done_appending;
272
10.1k
                        }
273
10.1k
                      }
274
10.1k
                    }
275
45.8k
                   done_appending: ;
276
45.8k
                  }
277
278
                /* sortbuf is now empty.  */
279
55.9k
                sortbuf_count = 0;
280
55.9k
              }
281
282
55.9k
            if (!(s < s_end))
283
              /* End of string reached.  */
284
10.1k
              break;
285
286
            /* Append (uc, ccc) to sortbuf.  */
287
45.8k
            if (sortbuf_count == sortbuf_allocated)
288
0
              {
289
0
                sortbuf_allocated = 2 * sortbuf_allocated;
290
0
                if (sortbuf_allocated < sortbuf_count) /* integer overflow? */
291
0
                  abort ();
292
0
                struct ucs4_with_ccc *new_sortbuf =
293
0
                  (struct ucs4_with_ccc *) malloc (2 * sortbuf_allocated * sizeof (struct ucs4_with_ccc));
294
0
                if (new_sortbuf == NULL)
295
0
                  {
296
0
                    errno = ENOMEM;
297
0
                    goto fail;
298
0
                  }
299
0
                memcpy (new_sortbuf, sortbuf,
300
0
                        sortbuf_count * sizeof (struct ucs4_with_ccc));
301
0
                if (sortbuf != sortbuf_preallocated)
302
0
                  free (sortbuf);
303
0
                sortbuf = new_sortbuf;
304
0
              }
305
45.8k
            sortbuf[sortbuf_count].code = uc;
306
45.8k
            sortbuf[sortbuf_count].ccc = ccc;
307
45.8k
            sortbuf_count++;
308
309
45.8k
            i++;
310
45.8k
          }
311
312
55.9k
        if (!(s < s_end))
313
          /* End of string reached.  */
314
10.1k
          break;
315
316
45.8k
        s += count;
317
45.8k
      }
318
10.1k
  }
319
320
10.1k
  if (length == 0)
321
0
    {
322
0
      if (result == NULL)
323
0
        {
324
          /* Return a non-NULL value.  NULL means error.  */
325
0
          result = (UNIT *) malloc (1);
326
0
          if (result == NULL)
327
0
            {
328
0
              errno = ENOMEM;
329
0
              goto fail;
330
0
            }
331
0
        }
332
0
    }
333
10.1k
  else if (result != resultbuf && length < allocated)
334
10.1k
    {
335
      /* Shrink the allocated memory if possible.  */
336
10.1k
      UNIT *memory = (UNIT *) realloc (result, length * sizeof (UNIT));
337
10.1k
      if (memory != NULL)
338
10.1k
        result = memory;
339
10.1k
    }
340
341
10.1k
  if (sortbuf_count > 0)
342
0
    abort ();
343
10.1k
  if (sortbuf != sortbuf_preallocated)
344
10.1k
    free (sortbuf);
345
346
10.1k
  *lengthp = length;
347
10.1k
  return result;
348
349
0
 fail:
350
0
  {
351
0
    int saved_errno = errno;
352
0
    if (sortbuf != sortbuf_preallocated)
353
0
      free (sortbuf);
354
0
    if (result != resultbuf)
355
0
      free (result);
356
0
    errno = saved_errno;
357
0
  }
358
  return NULL;
359
10.1k
}
u32_normalize
Line
Count
Source
21
28.4k
{
22
28.4k
  int (*decomposer) (ucs4_t uc, ucs4_t *decomposition) = nf->decomposer;
23
28.4k
  ucs4_t (*composer) (ucs4_t uc1, ucs4_t uc2) = nf->composer;
24
25
  /* The result being accumulated.  */
26
28.4k
  UNIT *result;
27
28.4k
  size_t allocated;
28
28.4k
  if (resultbuf == NULL)
29
28.4k
    {
30
28.4k
      result = NULL;
31
28.4k
      allocated = 0;
32
28.4k
    }
33
0
  else
34
0
    {
35
0
      result = resultbuf;
36
0
      allocated = *lengthp;
37
0
    }
38
28.4k
  size_t length = 0;
39
40
  /* The buffer for sorting.  */
41
28.4k
  #define SORTBUF_PREALLOCATED 64
42
28.4k
  struct ucs4_with_ccc sortbuf_preallocated[2 * SORTBUF_PREALLOCATED];
43
28.4k
  struct ucs4_with_ccc *sortbuf = /* array of size 2 * sortbuf_allocated */
44
28.4k
    sortbuf_preallocated;
45
28.4k
  size_t sortbuf_allocated = SORTBUF_PREALLOCATED;
46
28.4k
  size_t sortbuf_count = 0;
47
48
28.4k
  {
49
28.4k
    const UNIT *s_end = s + n;
50
51
28.4k
    for (;;)
52
313k
      {
53
313k
        int count;
54
313k
        ucs4_t decomposed[UC_DECOMPOSITION_MAX_LENGTH];
55
313k
        int decomposed_count;
56
57
313k
        if (s < s_end)
58
284k
          {
59
            /* Fetch the next character.  */
60
284k
            count = U_MBTOUC_UNSAFE (&decomposed[0], s, s_end - s);
61
284k
            decomposed_count = 1;
62
63
            /* Decompose it, recursively.
64
               It would be possible to precompute the recursive decomposition
65
               and store it in a table.  But this would significantly increase
66
               the size of the decomposition tables, because for example for
67
               U+1FC1 the recursive canonical decomposition and the recursive
68
               compatibility decomposition are different.  */
69
597k
            for (int curr = 0; curr < decomposed_count; )
70
312k
              {
71
                /* Invariant: decomposed[0..curr-1] is fully decomposed, i.e.
72
                   all elements are atomic.  */
73
312k
                ucs4_t curr_decomposed[UC_DECOMPOSITION_MAX_LENGTH];
74
312k
                int curr_decomposed_count;
75
76
312k
                curr_decomposed_count = decomposer (decomposed[curr], curr_decomposed);
77
312k
                if (curr_decomposed_count >= 0)
78
13.8k
                  {
79
                    /* Move curr_decomposed[0..curr_decomposed_count-1] over
80
                       decomposed[curr], making room.  It's not worth using
81
                       memcpy() here, since the counts are so small.  */
82
13.8k
                    int shift = curr_decomposed_count - 1;
83
84
13.8k
                    if (shift < 0)
85
0
                      abort ();
86
13.8k
                    if (shift > 0)
87
13.6k
                      {
88
13.6k
                        decomposed_count += shift;
89
13.6k
                        if (decomposed_count > UC_DECOMPOSITION_MAX_LENGTH)
90
0
                          abort ();
91
19.2k
                        for (int j = decomposed_count - 1 - shift; j > curr; j--)
92
5.61k
                          decomposed[j + shift] = decomposed[j];
93
13.6k
                      }
94
41.4k
                    for (; shift >= 0; shift--)
95
27.5k
                      decomposed[curr + shift] = curr_decomposed[shift];
96
13.8k
                  }
97
298k
                else
98
298k
                  {
99
                    /* decomposed[curr] is atomic.  */
100
298k
                    curr++;
101
298k
                  }
102
312k
              }
103
284k
          }
104
28.4k
        else
105
28.4k
          {
106
28.4k
            count = 0;
107
28.4k
            decomposed_count = 0;
108
28.4k
          }
109
110
313k
        int i = 0;
111
313k
        for (;;)
112
611k
          {
113
611k
            ucs4_t uc;
114
611k
            int ccc;
115
116
611k
            if (s < s_end)
117
583k
              {
118
                /* Fetch the next character from the decomposition.  */
119
583k
                if (i == decomposed_count)
120
284k
                  break;
121
298k
                uc = decomposed[i];
122
298k
                ccc = uc_combining_class (uc);
123
298k
              }
124
28.4k
            else
125
28.4k
              {
126
                /* End of string reached.  */
127
28.4k
                uc = 0;
128
28.4k
                ccc = 0;
129
28.4k
              }
130
131
326k
            if (ccc == 0)
132
272k
              {
133
                /* Apply the canonical ordering algorithm to the accumulated
134
                   sequence of characters.  */
135
272k
                if (sortbuf_count > 1)
136
11.6k
                  gl_uninorm_decompose_merge_sort_inplace (sortbuf, sortbuf_count,
137
11.6k
                                                           sortbuf + sortbuf_count);
138
139
272k
                if (composer != NULL)
140
272k
                  {
141
                    /* Attempt to combine decomposed characters, as specified
142
                       in the Unicode Standard Annex #15 "Unicode Normalization
143
                       Forms".  We need to check
144
                         1. whether the first accumulated character is a
145
                            "starter" (i.e. has ccc = 0).  This is usually the
146
                            case.  But when the string starts with a
147
                            non-starter, the sortbuf also starts with a
148
                            non-starter.  Btw, this check could also be
149
                            omitted, because the composition table has only
150
                            entries (code1, code2) for which code1 is a
151
                            starter; if the first accumulated character is not
152
                            a starter, no lookup will succeed.
153
                         2. If the sortbuf has more than one character, check
154
                            for each of these characters that are not "blocked"
155
                            from the starter (i.e. have a ccc that is higher
156
                            than the ccc of the previous character) whether it
157
                            can be combined with the first character.
158
                         3. If only one character is left in sortbuf, check
159
                            whether it can be combined with the next character
160
                            (also a starter).  */
161
272k
                    if (sortbuf_count > 0 && sortbuf[0].ccc == 0)
162
244k
                      {
163
296k
                        for (size_t j = 1; j < sortbuf_count; )
164
52.4k
                          {
165
52.4k
                            if (sortbuf[j].ccc > sortbuf[j - 1].ccc)
166
25.1k
                              {
167
25.1k
                                ucs4_t combined =
168
25.1k
                                  composer (sortbuf[0].code, sortbuf[j].code);
169
25.1k
                                if (combined)
170
9.78k
                                  {
171
9.78k
                                    sortbuf[0].code = combined;
172
                                    /* sortbuf[0].ccc = 0, still valid.  */
173
34.4k
                                    for (size_t k = j + 1; k < sortbuf_count; k++)
174
24.6k
                                      sortbuf[k - 1] = sortbuf[k];
175
9.78k
                                    sortbuf_count--;
176
9.78k
                                    continue;
177
9.78k
                                  }
178
25.1k
                              }
179
42.6k
                            j++;
180
42.6k
                          }
181
244k
                        if (s < s_end && sortbuf_count == 1)
182
209k
                          {
183
209k
                            ucs4_t combined =
184
209k
                              composer (sortbuf[0].code, uc);
185
209k
                            if (combined)
186
3.14k
                              {
187
3.14k
                                uc = combined;
188
3.14k
                                ccc = 0;
189
                                /* uc could be further combined with subsequent
190
                                   characters.  So don't put it into sortbuf[0] in
191
                                   this round, only in the next round.  */
192
3.14k
                                sortbuf_count = 0;
193
3.14k
                              }
194
209k
                          }
195
244k
                      }
196
272k
                  }
197
198
558k
                for (size_t j = 0; j < sortbuf_count; j++)
199
285k
                  {
200
285k
                    ucs4_t muc = sortbuf[j].code;
201
202
                    /* Append muc to the result accumulator.  */
203
285k
                    if (length < allocated)
204
256k
                      {
205
256k
                        int ret =
206
256k
                          U_UCTOMB (result + length, muc, allocated - length);
207
256k
                        if (ret == -1)
208
0
                          {
209
0
                            errno = EINVAL;
210
0
                            goto fail;
211
0
                          }
212
256k
                        if (ret >= 0)
213
256k
                          {
214
256k
                            length += ret;
215
256k
                            goto done_appending;
216
256k
                          }
217
256k
                      }
218
28.9k
                    {
219
28.9k
                      size_t old_allocated = allocated;
220
28.9k
                      size_t new_allocated = 2 * old_allocated;
221
28.9k
                      if (new_allocated < 64)
222
27.8k
                        new_allocated = 64;
223
28.9k
                      if (new_allocated < old_allocated) /* integer overflow? */
224
0
                        abort ();
225
28.9k
                      {
226
28.9k
                        UNIT *larger_result;
227
28.9k
                        if (result == NULL)
228
27.8k
                          {
229
27.8k
                            larger_result =
230
27.8k
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
231
27.8k
                            if (larger_result == NULL)
232
0
                              {
233
0
                                errno = ENOMEM;
234
0
                                goto fail;
235
0
                              }
236
27.8k
                          }
237
1.05k
                        else if (result == resultbuf)
238
0
                          {
239
0
                            larger_result =
240
0
                              (UNIT *) malloc (new_allocated * sizeof (UNIT));
241
0
                            if (larger_result == NULL)
242
0
                              {
243
0
                                errno = ENOMEM;
244
0
                                goto fail;
245
0
                              }
246
0
                            U_CPY (larger_result, resultbuf, length);
247
0
                          }
248
1.05k
                        else
249
1.05k
                          {
250
1.05k
                            larger_result =
251
1.05k
                              (UNIT *) realloc (result, new_allocated * sizeof (UNIT));
252
1.05k
                            if (larger_result == NULL)
253
0
                              {
254
0
                                errno = ENOMEM;
255
0
                                goto fail;
256
0
                              }
257
1.05k
                          }
258
28.9k
                        result = larger_result;
259
28.9k
                        allocated = new_allocated;
260
28.9k
                        {
261
28.9k
                          int ret =
262
28.9k
                            U_UCTOMB (result + length, muc, allocated - length);
263
28.9k
                          if (ret == -1)
264
0
                            {
265
0
                              errno = EINVAL;
266
0
                              goto fail;
267
0
                            }
268
28.9k
                          if (ret < 0)
269
0
                            abort ();
270
28.9k
                          length += ret;
271
28.9k
                          goto done_appending;
272
28.9k
                        }
273
28.9k
                      }
274
28.9k
                    }
275
285k
                   done_appending: ;
276
285k
                  }
277
278
                /* sortbuf is now empty.  */
279
272k
                sortbuf_count = 0;
280
272k
              }
281
282
326k
            if (!(s < s_end))
283
              /* End of string reached.  */
284
28.4k
              break;
285
286
            /* Append (uc, ccc) to sortbuf.  */
287
298k
            if (sortbuf_count == sortbuf_allocated)
288
175
              {
289
175
                sortbuf_allocated = 2 * sortbuf_allocated;
290
175
                if (sortbuf_allocated < sortbuf_count) /* integer overflow? */
291
0
                  abort ();
292
175
                struct ucs4_with_ccc *new_sortbuf =
293
175
                  (struct ucs4_with_ccc *) malloc (2 * sortbuf_allocated * sizeof (struct ucs4_with_ccc));
294
175
                if (new_sortbuf == NULL)
295
0
                  {
296
0
                    errno = ENOMEM;
297
0
                    goto fail;
298
0
                  }
299
175
                memcpy (new_sortbuf, sortbuf,
300
175
                        sortbuf_count * sizeof (struct ucs4_with_ccc));
301
175
                if (sortbuf != sortbuf_preallocated)
302
175
                  free (sortbuf);
303
175
                sortbuf = new_sortbuf;
304
175
              }
305
298k
            sortbuf[sortbuf_count].code = uc;
306
298k
            sortbuf[sortbuf_count].ccc = ccc;
307
298k
            sortbuf_count++;
308
309
298k
            i++;
310
298k
          }
311
312
313k
        if (!(s < s_end))
313
          /* End of string reached.  */
314
28.4k
          break;
315
316
284k
        s += count;
317
284k
      }
318
28.4k
  }
319
320
28.4k
  if (length == 0)
321
587
    {
322
587
      if (result == NULL)
323
587
        {
324
          /* Return a non-NULL value.  NULL means error.  */
325
587
          result = (UNIT *) malloc (1);
326
587
          if (result == NULL)
327
0
            {
328
0
              errno = ENOMEM;
329
0
              goto fail;
330
0
            }
331
587
        }
332
587
    }
333
27.8k
  else if (result != resultbuf && length < allocated)
334
27.7k
    {
335
      /* Shrink the allocated memory if possible.  */
336
27.7k
      UNIT *memory = (UNIT *) realloc (result, length * sizeof (UNIT));
337
27.7k
      if (memory != NULL)
338
27.7k
        result = memory;
339
27.7k
    }
340
341
28.4k
  if (sortbuf_count > 0)
342
0
    abort ();
343
28.4k
  if (sortbuf != sortbuf_preallocated)
344
28.4k
    free (sortbuf);
345
346
28.4k
  *lengthp = length;
347
28.4k
  return result;
348
349
0
 fail:
350
0
  {
351
0
    int saved_errno = errno;
352
0
    if (sortbuf != sortbuf_preallocated)
353
0
      free (sortbuf);
354
0
    if (result != resultbuf)
355
0
      free (result);
356
0
    errno = saved_errno;
357
0
  }
358
  return NULL;
359
28.4k
}