source: rtems/cpukit/libmisc/utf8proc/utf8proc.c @ f666fc59

5
Last change on this file since f666fc59 was f666fc59, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 13, 2017 at 7:29:51 AM

utf8proc: Include <utf8proc/utf8proc.h>

Prepare for header file move to common include directory.

Update #3254.

  • Property mode set to 100644
File size: 20.0 KB
Line 
1/*
2 *  Copyright (c) 2009 Public Software Group e. V., Berlin, Germany
3 *
4 *  Permission is hereby granted, free of charge, to any person obtaining a
5 *  copy of this software and associated documentation files (the "Software"),
6 *  to deal in the Software without restriction, including without limitation
7 *  the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 *  and/or sell copies of the Software, and to permit persons to whom the
9 *  Software is furnished to do so, subject to the following conditions:
10 *
11 *  The above copyright notice and this permission notice shall be included in
12 *  all copies or substantial portions of the Software.
13 *
14 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 *  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 *  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 *  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 *  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 *  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20 *  DEALINGS IN THE SOFTWARE.
21 */
22
23/*
24 *  This library contains derived data from a modified version of the
25 *  Unicode data files.
26 *
27 *  The original data files are available at
28 *  http://www.unicode.org/Public/UNIDATA/
29 *
30 *  Please notice the copyright statement in the file "utf8proc_data.c".
31 */
32
33
34/*
35 *  File name:    utf8proc.c
36 *
37 *  Description:
38 *  Implementation of libutf8proc.
39 */
40
41
42#include <utf8proc/utf8proc.h>
43#include "utf8proc_data.c"
44
45
46const int8_t utf8proc_utf8class[256] = {
47  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
48  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
49  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
50  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
51  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
52  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
53  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
54  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
55  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
57  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
58  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
59  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
60  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
61  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
62  4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0 };
63
64#define UTF8PROC_HANGUL_SBASE 0xAC00
65#define UTF8PROC_HANGUL_LBASE 0x1100
66#define UTF8PROC_HANGUL_VBASE 0x1161
67#define UTF8PROC_HANGUL_TBASE 0x11A7
68#define UTF8PROC_HANGUL_LCOUNT 19
69#define UTF8PROC_HANGUL_VCOUNT 21
70#define UTF8PROC_HANGUL_TCOUNT 28
71#define UTF8PROC_HANGUL_NCOUNT 588
72#define UTF8PROC_HANGUL_SCOUNT 11172
73/* END is exclusive */
74#define UTF8PROC_HANGUL_L_START  0x1100
75#define UTF8PROC_HANGUL_L_END    0x115A
76#define UTF8PROC_HANGUL_L_FILLER 0x115F
77#define UTF8PROC_HANGUL_V_START  0x1160
78#define UTF8PROC_HANGUL_V_END    0x11A3
79#define UTF8PROC_HANGUL_T_START  0x11A8
80#define UTF8PROC_HANGUL_T_END    0x11FA
81#define UTF8PROC_HANGUL_S_START  0xAC00
82#define UTF8PROC_HANGUL_S_END    0xD7A4
83
84
85#define UTF8PROC_BOUNDCLASS_START    0
86#define UTF8PROC_BOUNDCLASS_OTHER    1
87#define UTF8PROC_BOUNDCLASS_CR       2
88#define UTF8PROC_BOUNDCLASS_LF       3
89#define UTF8PROC_BOUNDCLASS_CONTROL  4
90#define UTF8PROC_BOUNDCLASS_EXTEND   5
91#define UTF8PROC_BOUNDCLASS_L        6
92#define UTF8PROC_BOUNDCLASS_V        7
93#define UTF8PROC_BOUNDCLASS_T        8
94#define UTF8PROC_BOUNDCLASS_LV       9
95#define UTF8PROC_BOUNDCLASS_LVT     10
96
97
98const char *utf8proc_version(void) {
99  return "1.1.5";
100}
101
102const char *utf8proc_errmsg(ssize_t errcode) {
103  switch (errcode) {
104    case UTF8PROC_ERROR_NOMEM:
105    return "Memory for processing UTF-8 data could not be allocated.";
106    case UTF8PROC_ERROR_OVERFLOW:
107    return "UTF-8 string is too long to be processed.";
108    case UTF8PROC_ERROR_INVALIDUTF8:
109    return "Invalid UTF-8 string";
110    case UTF8PROC_ERROR_NOTASSIGNED:
111    return "Unassigned Unicode code point found in UTF-8 string.";
112    case UTF8PROC_ERROR_INVALIDOPTS:
113    return "Invalid options for UTF-8 processing chosen.";
114    default:
115    return "An unknown error occured while processing UTF-8 data.";
116  }
117}
118
119ssize_t utf8proc_iterate(
120  const uint8_t *str, ssize_t strlen, int32_t *dst
121) {
122  int length;
123  int i;
124  int32_t uc = -1;
125  *dst = -1;
126  if (!strlen) return 0;
127  length = utf8proc_utf8class[str[0]];
128  if (!length) return UTF8PROC_ERROR_INVALIDUTF8;
129  if (strlen >= 0 && length > strlen) return UTF8PROC_ERROR_INVALIDUTF8;
130  for (i=1; i<length; i++) {
131    if ((str[i] & 0xC0) != 0x80) return UTF8PROC_ERROR_INVALIDUTF8;
132  }
133  switch (length) {
134    case 1:
135    uc = str[0];
136    break;
137    case 2:
138    uc = ((str[0] & 0x1F) <<  6) + (str[1] & 0x3F);
139    if (uc < 0x80) uc = -1;
140    break;
141    case 3:
142    uc = ((str[0] & 0x0F) << 12) + ((str[1] & 0x3F) <<  6)
143      + (str[2] & 0x3F);
144    if (uc < 0x800 || (uc >= 0xD800 && uc < 0xE000) ||
145      (uc >= 0xFDD0 && uc < 0xFDF0)) uc = -1;
146    break;
147    case 4:
148#if defined(__rtems__)
149    uc = (((int32_t)str[0] & 0x07) << 18) + (((int32_t)str[1] & 0x3F) << 12)
150      + (((int32_t)str[2] & 0x3F) <<  6) + (str[3] & 0x3F);
151#else
152    uc = ((str[0] & 0x07) << 18) + ((str[1] & 0x3F) << 12)
153      + ((str[2] & 0x3F) <<  6) + (str[3] & 0x3F);
154#endif
155    if (uc < 0x10000 || uc >= 0x110000) uc = -1;
156    break;
157  }
158  if (uc < 0 || ((uc & 0xFFFF) >= 0xFFFE))
159    return UTF8PROC_ERROR_INVALIDUTF8;
160  *dst = uc;
161  return length;
162}
163
164bool utf8proc_codepoint_valid(int32_t uc) {
165  if (uc < 0 || uc >= 0x110000 ||
166    ((uc & 0xFFFF) >= 0xFFFE) || (uc >= 0xD800 && uc < 0xE000) ||
167    (uc >= 0xFDD0 && uc < 0xFDF0)) return false;
168  else return true;
169}
170
171ssize_t utf8proc_encode_char(int32_t uc, uint8_t *dst) {
172  if (uc < 0x00) {
173    return 0;
174  } else if (uc < 0x80) {
175    dst[0] = uc;
176    return 1;
177  } else if (uc < 0x800) {
178    dst[0] = 0xC0 + (uc >> 6);
179    dst[1] = 0x80 + (uc & 0x3F);
180    return 2;
181  } else if (uc == 0xFFFF) {
182    dst[0] = 0xFF;
183    return 1;
184  } else if (uc == 0xFFFE) {
185    dst[0] = 0xFE;
186    return 1;
187  } else if (uc < 0x10000) {
188    dst[0] = 0xE0 + (uc >> 12);
189    dst[1] = 0x80 + ((uc >> 6) & 0x3F);
190    dst[2] = 0x80 + (uc & 0x3F);
191    return 3;
192  } else if (uc < 0x110000) {
193    dst[0] = 0xF0 + (uc >> 18);
194    dst[1] = 0x80 + ((uc >> 12) & 0x3F);
195    dst[2] = 0x80 + ((uc >> 6) & 0x3F);
196    dst[3] = 0x80 + (uc & 0x3F);
197    return 4;
198  } else return 0;
199}
200
201const utf8proc_property_t *utf8proc_get_property(int32_t uc) {
202  /* ASSERT: uc >= 0 && uc < 0x110000 */
203  return utf8proc_properties + (
204    utf8proc_stage2table[
205      utf8proc_stage1table[uc >> 8] + (uc & 0xFF)
206    ]
207  );
208}
209
210#define utf8proc_decompose_lump(replacement_uc) \
211  return utf8proc_decompose_char((replacement_uc), dst, bufsize, \
212  options & ~UTF8PROC_LUMP, last_boundclass)
213
214ssize_t utf8proc_decompose_char(int32_t uc, int32_t *dst, ssize_t bufsize,
215    int options, int *last_boundclass) {
216  /* ASSERT: uc >= 0 && uc < 0x110000 */
217  const utf8proc_property_t *property;
218  utf8proc_propval_t category;
219  int32_t hangul_sindex;
220  property = utf8proc_get_property(uc);
221  category = property->category;
222  hangul_sindex = uc - UTF8PROC_HANGUL_SBASE;
223  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
224    if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT) {
225      int32_t hangul_tindex;
226      if (bufsize >= 1) {
227        dst[0] = UTF8PROC_HANGUL_LBASE +
228          hangul_sindex / UTF8PROC_HANGUL_NCOUNT;
229        if (bufsize >= 2) dst[1] = UTF8PROC_HANGUL_VBASE +
230          (hangul_sindex % UTF8PROC_HANGUL_NCOUNT) / UTF8PROC_HANGUL_TCOUNT;
231      }
232      hangul_tindex = hangul_sindex % UTF8PROC_HANGUL_TCOUNT;
233      if (!hangul_tindex) return 2;
234      if (bufsize >= 3) dst[2] = UTF8PROC_HANGUL_TBASE + hangul_tindex;
235      return 3;
236    }
237  }
238  if (options & UTF8PROC_REJECTNA) {
239    if (!category) return UTF8PROC_ERROR_NOTASSIGNED;
240  }
241  if (options & UTF8PROC_IGNORE) {
242    if (property->ignorable) return 0;
243  }
244  if (options & UTF8PROC_LUMP) {
245    if (category == UTF8PROC_CATEGORY_ZS) utf8proc_decompose_lump(0x0020);
246    if (uc == 0x2018 || uc == 0x2019 || uc == 0x02BC || uc == 0x02C8)
247      utf8proc_decompose_lump(0x0027);
248    if (category == UTF8PROC_CATEGORY_PD || uc == 0x2212)
249      utf8proc_decompose_lump(0x002D);
250    if (uc == 0x2044 || uc == 0x2215) utf8proc_decompose_lump(0x002F);
251    if (uc == 0x2236) utf8proc_decompose_lump(0x003A);
252    if (uc == 0x2039 || uc == 0x2329 || uc == 0x3008)
253      utf8proc_decompose_lump(0x003C);
254    if (uc == 0x203A || uc == 0x232A || uc == 0x3009)
255      utf8proc_decompose_lump(0x003E);
256    if (uc == 0x2216) utf8proc_decompose_lump(0x005C);
257    if (uc == 0x02C4 || uc == 0x02C6 || uc == 0x2038 || uc == 0x2303)
258      utf8proc_decompose_lump(0x005E);
259    if (category == UTF8PROC_CATEGORY_PC || uc == 0x02CD)
260      utf8proc_decompose_lump(0x005F);
261    if (uc == 0x02CB) utf8proc_decompose_lump(0x0060);
262    if (uc == 0x2223) utf8proc_decompose_lump(0x007C);
263    if (uc == 0x223C) utf8proc_decompose_lump(0x007E);
264    if ((options & UTF8PROC_NLF2LS) && (options & UTF8PROC_NLF2PS)) {
265      if (category == UTF8PROC_CATEGORY_ZL ||
266          category == UTF8PROC_CATEGORY_ZP)
267        utf8proc_decompose_lump(0x000A);
268    }
269  }
270  if (options & UTF8PROC_STRIPMARK) {
271    if (category == UTF8PROC_CATEGORY_MN ||
272      category == UTF8PROC_CATEGORY_MC ||
273      category == UTF8PROC_CATEGORY_ME) return 0;
274  }
275  if (options & UTF8PROC_CASEFOLD) {
276    if (property->casefold_mapping) {
277      const int32_t *casefold_entry;
278      ssize_t written = 0;
279      for (casefold_entry = property->casefold_mapping;
280          *casefold_entry >= 0; casefold_entry++) {
281        written += utf8proc_decompose_char(*casefold_entry, dst+written,
282          (bufsize > written) ? (bufsize - written) : 0, options,
283          last_boundclass);
284        if (written < 0) return UTF8PROC_ERROR_OVERFLOW;
285      }
286      return written;
287    }
288  }
289  if (options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) {
290    if (property->decomp_mapping &&
291        (!property->decomp_type || (options & UTF8PROC_COMPAT))) {
292      const int32_t *decomp_entry;
293      ssize_t written = 0;
294      for (decomp_entry = property->decomp_mapping;
295          *decomp_entry >= 0; decomp_entry++) {
296        written += utf8proc_decompose_char(*decomp_entry, dst+written,
297          (bufsize > written) ? (bufsize - written) : 0, options,
298        last_boundclass);
299        if (written < 0) return UTF8PROC_ERROR_OVERFLOW;
300      }
301      return written;
302    }
303  }
304  if (options & UTF8PROC_CHARBOUND) {
305    bool boundary;
306    int tbc, lbc;
307    tbc =
308      (uc == 0x000D) ? UTF8PROC_BOUNDCLASS_CR :
309      (uc == 0x000A) ? UTF8PROC_BOUNDCLASS_LF :
310      ((category == UTF8PROC_CATEGORY_ZL ||
311        category == UTF8PROC_CATEGORY_ZP ||
312        category == UTF8PROC_CATEGORY_CC ||
313        category == UTF8PROC_CATEGORY_CF) &&
314        !(uc == 0x200C || uc == 0x200D)) ? UTF8PROC_BOUNDCLASS_CONTROL :
315      property->extend ? UTF8PROC_BOUNDCLASS_EXTEND :
316      ((uc >= UTF8PROC_HANGUL_L_START && uc < UTF8PROC_HANGUL_L_END) ||
317        uc == UTF8PROC_HANGUL_L_FILLER) ? UTF8PROC_BOUNDCLASS_L :
318      (uc >= UTF8PROC_HANGUL_V_START && uc < UTF8PROC_HANGUL_V_END) ?
319        UTF8PROC_BOUNDCLASS_V :
320      (uc >= UTF8PROC_HANGUL_T_START && uc < UTF8PROC_HANGUL_T_END) ?
321        UTF8PROC_BOUNDCLASS_T :
322      (uc >= UTF8PROC_HANGUL_S_START && uc < UTF8PROC_HANGUL_S_END) ? (
323        ((uc-UTF8PROC_HANGUL_SBASE) % UTF8PROC_HANGUL_TCOUNT == 0) ?
324          UTF8PROC_BOUNDCLASS_LV : UTF8PROC_BOUNDCLASS_LVT
325      ) :
326      UTF8PROC_BOUNDCLASS_OTHER;
327    lbc = *last_boundclass;
328    boundary =
329      (tbc == UTF8PROC_BOUNDCLASS_EXTEND) ? false :
330      (lbc == UTF8PROC_BOUNDCLASS_START) ? true :
331      (lbc == UTF8PROC_BOUNDCLASS_CR &&
332       tbc == UTF8PROC_BOUNDCLASS_LF) ? false :
333      (lbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true :
334      (tbc == UTF8PROC_BOUNDCLASS_CONTROL) ? true :
335      (lbc == UTF8PROC_BOUNDCLASS_L &&
336       (tbc == UTF8PROC_BOUNDCLASS_L ||
337        tbc == UTF8PROC_BOUNDCLASS_V ||
338        tbc == UTF8PROC_BOUNDCLASS_LV ||
339        tbc == UTF8PROC_BOUNDCLASS_LVT)) ? false :
340      ((lbc == UTF8PROC_BOUNDCLASS_LV ||
341        lbc == UTF8PROC_BOUNDCLASS_V) &&
342       (tbc == UTF8PROC_BOUNDCLASS_V ||
343        tbc == UTF8PROC_BOUNDCLASS_T)) ? false :
344      ((lbc == UTF8PROC_BOUNDCLASS_LVT ||
345        lbc == UTF8PROC_BOUNDCLASS_T) &&
346       tbc == UTF8PROC_BOUNDCLASS_T) ? false :
347       true;
348    *last_boundclass = tbc;
349    if (boundary) {
350      if (bufsize >= 1) dst[0] = 0xFFFF;
351      if (bufsize >= 2) dst[1] = uc;
352      return 2;
353    }
354  }
355  if (bufsize >= 1) *dst = uc;
356  return 1;
357}
358
359ssize_t utf8proc_decompose(
360  const uint8_t *str, ssize_t strlen,
361  int32_t *buffer, ssize_t bufsize, int options
362) {
363  /* strlen will be ignored, if UTF8PROC_NULLTERM is set in options */
364  ssize_t wpos = 0;
365  if ((options & UTF8PROC_COMPOSE) && (options & UTF8PROC_DECOMPOSE))
366    return UTF8PROC_ERROR_INVALIDOPTS;
367  if ((options & UTF8PROC_STRIPMARK) &&
368      !(options & UTF8PROC_COMPOSE) && !(options & UTF8PROC_DECOMPOSE))
369    return UTF8PROC_ERROR_INVALIDOPTS;
370  {
371    int32_t uc;
372    ssize_t rpos = 0;
373    ssize_t decomp_result;
374    int boundclass = UTF8PROC_BOUNDCLASS_START;
375    while (1) {
376      if (options & UTF8PROC_NULLTERM) {
377        rpos += utf8proc_iterate(str + rpos, -1, &uc);
378        /* checking of return value is not neccessary,
379           as 'uc' is < 0 in case of error */
380        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
381        if (rpos < 0) return UTF8PROC_ERROR_OVERFLOW;
382        if (uc == 0) break;
383      } else {
384        if (rpos >= strlen) break;
385        rpos += utf8proc_iterate(str + rpos, strlen - rpos, &uc);
386        if (uc < 0) return UTF8PROC_ERROR_INVALIDUTF8;
387      }
388      decomp_result = utf8proc_decompose_char(
389        uc, buffer + wpos, (bufsize > wpos) ? (bufsize - wpos) : 0, options,
390        &boundclass
391      );
392      if (decomp_result < 0) return decomp_result;
393      wpos += decomp_result;
394      /* prohibiting integer overflows due to too long strings: */
395      if (wpos < 0 || wpos > SSIZE_MAX/sizeof(int32_t)/2)
396        return UTF8PROC_ERROR_OVERFLOW;
397    }
398  }
399  if ((options & (UTF8PROC_COMPOSE|UTF8PROC_DECOMPOSE)) && bufsize >= wpos) {
400    ssize_t pos = 0;
401    while (pos < wpos-1) {
402      int32_t uc1, uc2;
403      const utf8proc_property_t *property1, *property2;
404      uc1 = buffer[pos];
405      uc2 = buffer[pos+1];
406      property1 = utf8proc_get_property(uc1);
407      property2 = utf8proc_get_property(uc2);
408      if (property1->combining_class > property2->combining_class &&
409          property2->combining_class > 0) {
410        buffer[pos] = uc2;
411        buffer[pos+1] = uc1;
412        if (pos > 0) pos--; else pos++;
413      } else {
414        pos++;
415      }
416    }
417  }
418  return wpos;
419}
420
421ssize_t utf8proc_reencode(int32_t *buffer, ssize_t length, int options) {
422  /* UTF8PROC_NULLTERM option will be ignored, 'length' is never ignored
423     ASSERT: 'buffer' has one spare byte of free space at the end! */
424  if (options & (UTF8PROC_NLF2LS | UTF8PROC_NLF2PS | UTF8PROC_STRIPCC)) {
425    ssize_t rpos;
426    ssize_t wpos = 0;
427    int32_t uc;
428    for (rpos = 0; rpos < length; rpos++) {
429      uc = buffer[rpos];
430      if (uc == 0x000D && rpos < length-1 && buffer[rpos+1] == 0x000A) rpos++;
431      if (uc == 0x000A || uc == 0x000D || uc == 0x0085 ||
432          ((options & UTF8PROC_STRIPCC) && (uc == 0x000B || uc == 0x000C))) {
433        if (options & UTF8PROC_NLF2LS) {
434          if (options & UTF8PROC_NLF2PS) {
435            buffer[wpos++] = 0x000A;
436          } else {
437            buffer[wpos++] = 0x2028;
438          }
439        } else {
440          if (options & UTF8PROC_NLF2PS) {
441            buffer[wpos++] = 0x2029;
442          } else {
443            buffer[wpos++] = 0x0020;
444          }
445        }
446      } else if ((options & UTF8PROC_STRIPCC) &&
447          (uc < 0x0020 || (uc >= 0x007F && uc < 0x00A0))) {
448        if (uc == 0x0009) buffer[wpos++] = 0x0020;
449      } else {
450        buffer[wpos++] = uc;
451      }
452    }
453    length = wpos;
454  }
455  if (options & UTF8PROC_COMPOSE) {
456    int32_t *starter = NULL;
457    int32_t current_char;
458    const utf8proc_property_t *starter_property = NULL, *current_property;
459    utf8proc_propval_t max_combining_class = -1;
460    ssize_t rpos;
461    ssize_t wpos = 0;
462    int32_t composition;
463    for (rpos = 0; rpos < length; rpos++) {
464      current_char = buffer[rpos];
465      current_property = utf8proc_get_property(current_char);
466      if (starter && current_property->combining_class > max_combining_class) {
467        /* combination perhaps possible */
468        int32_t hangul_lindex;
469        int32_t hangul_sindex;
470        hangul_lindex = *starter - UTF8PROC_HANGUL_LBASE;
471        if (hangul_lindex >= 0 && hangul_lindex < UTF8PROC_HANGUL_LCOUNT) {
472          int32_t hangul_vindex;
473          hangul_vindex = current_char - UTF8PROC_HANGUL_VBASE;
474          if (hangul_vindex >= 0 && hangul_vindex < UTF8PROC_HANGUL_VCOUNT) {
475            *starter = UTF8PROC_HANGUL_SBASE +
476              (hangul_lindex * UTF8PROC_HANGUL_VCOUNT + hangul_vindex) *
477              UTF8PROC_HANGUL_TCOUNT;
478            starter_property = NULL;
479            continue;
480          }
481        }
482        hangul_sindex = *starter - UTF8PROC_HANGUL_SBASE;
483        if (hangul_sindex >= 0 && hangul_sindex < UTF8PROC_HANGUL_SCOUNT &&
484            (hangul_sindex % UTF8PROC_HANGUL_TCOUNT) == 0) {
485          int32_t hangul_tindex;
486          hangul_tindex = current_char - UTF8PROC_HANGUL_TBASE;
487          if (hangul_tindex >= 0 && hangul_tindex < UTF8PROC_HANGUL_TCOUNT) {
488            *starter += hangul_tindex;
489            starter_property = NULL;
490            continue;
491          }
492        }
493        if (!starter_property) {
494          starter_property = utf8proc_get_property(*starter);
495        }
496        if (starter_property->comb1st_index >= 0 &&
497            current_property->comb2nd_index >= 0) {
498          composition = utf8proc_combinations[
499            starter_property->comb1st_index +
500            current_property->comb2nd_index
501          ];
502          if (composition >= 0 && (!(options & UTF8PROC_STABLE) ||
503              !(utf8proc_get_property(composition)->comp_exclusion))) {
504            *starter = composition;
505            starter_property = NULL;
506            continue;
507          }
508        }
509      }
510      buffer[wpos] = current_char;
511      if (current_property->combining_class) {
512        if (current_property->combining_class > max_combining_class) {
513          max_combining_class = current_property->combining_class;
514        }
515      } else {
516        starter = buffer + wpos;
517        starter_property = NULL;
518        max_combining_class = -1;
519      }
520      wpos++;
521    }
522    length = wpos;
523  }
524  {
525    ssize_t rpos, wpos = 0;
526    int32_t uc;
527    for (rpos = 0; rpos < length; rpos++) {
528      uc = buffer[rpos];
529      wpos += utf8proc_encode_char(uc, ((uint8_t *)buffer) + wpos);
530    }
531    ((uint8_t *)buffer)[wpos] = 0;
532    return wpos;
533  }
534}
535
536ssize_t utf8proc_map(
537  const uint8_t *str, ssize_t strlen, uint8_t **dstptr, int options
538) {
539  int32_t *buffer;
540  ssize_t result;
541  *dstptr = NULL;
542  result = utf8proc_decompose(str, strlen, NULL, 0, options);
543  if (result < 0) return result;
544  buffer = malloc(result * sizeof(int32_t) + 1);
545  if (!buffer) return UTF8PROC_ERROR_NOMEM;
546  result = utf8proc_decompose(str, strlen, buffer, result, options);
547  if (result < 0) {
548    free(buffer);
549    return result;
550  }
551  result = utf8proc_reencode(buffer, result, options);
552  if (result < 0) {
553    free(buffer);
554    return result;
555  }
556  {
557    int32_t *newptr;
558    newptr = realloc(buffer, (size_t)result+1);
559    if (newptr) buffer = newptr;
560  }
561  *dstptr = (uint8_t *)buffer;
562  return result;
563}
564
565uint8_t *utf8proc_NFD(const uint8_t *str) {
566  uint8_t *retval;
567  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
568    UTF8PROC_DECOMPOSE);
569  return retval;
570}
571
572uint8_t *utf8proc_NFC(const uint8_t *str) {
573  uint8_t *retval;
574  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
575    UTF8PROC_COMPOSE);
576  return retval;
577}
578
579uint8_t *utf8proc_NFKD(const uint8_t *str) {
580  uint8_t *retval;
581  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
582    UTF8PROC_DECOMPOSE | UTF8PROC_COMPAT);
583  return retval;
584}
585
586uint8_t *utf8proc_NFKC(const uint8_t *str) {
587  uint8_t *retval;
588  utf8proc_map(str, 0, &retval, UTF8PROC_NULLTERM | UTF8PROC_STABLE |
589    UTF8PROC_COMPOSE | UTF8PROC_COMPAT);
590  return retval;
591}
592
Note: See TracBrowser for help on using the repository browser.