~ubuntu-branches/ubuntu/utopic/gettext/utopic

« back to all changes in this revision

Viewing changes to gettext-tools/gnulib-lib/uniname/uniname.c

  • Committer: Colin Watson
  • Date: 2010-08-01 21:36:08 UTC
  • mfrom: (2.1.10 sid)
  • Revision ID: cjwatson@canonical.com-20100801213608-yy7vkm8lpatep3ci
merge from Debian 0.18.1.1-1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* Association between Unicode characters and their names.
2
 
   Copyright (C) 2000-2002, 2005-2007 Free Software Foundation, Inc.
 
2
   Copyright (C) 2000-2002, 2005-2007, 2009-2010 Free Software Foundation, Inc.
3
3
 
4
4
   This program is free software: you can redistribute it and/or modify it
5
5
   under the terms of the GNU General Public License as published
73
73
    {
74
74
      unsigned int i = (i1 + i2) >> 1;
75
75
      if (unicode_name_by_length[i].ind_offset <= index)
76
 
        i1 = i;
 
76
        i1 = i;
77
77
      else
78
 
        i2 = i;
 
78
        i2 = i;
79
79
    }
80
80
  i = i1;
81
81
  assert (unicode_name_by_length[i].ind_offset <= index
82
 
          && index < unicode_name_by_length[i+1].ind_offset);
 
82
          && index < unicode_name_by_length[i+1].ind_offset);
83
83
  *lengthp = i;
84
84
  return &unicode_name_words[unicode_name_by_length[i].extra_offset
85
 
                             + (index-unicode_name_by_length[i].ind_offset)*i];
 
85
                             + (index-unicode_name_by_length[i].ind_offset)*i];
86
86
}
87
87
 
88
88
/* Looks up the index of a word.  */
97
97
      unsigned int i1 = i0;
98
98
      unsigned int i2 = unicode_name_by_length[length+1].ind_offset;
99
99
      while (i2 - i1 > 0)
100
 
        {
101
 
          unsigned int i = (i1 + i2) >> 1;
102
 
          const char *p = &unicode_name_words[extra_offset + (i-i0)*length];
103
 
          const char *w = word;
104
 
          unsigned int n = length;
105
 
          for (;;)
106
 
            {
107
 
              if (*p < *w)
108
 
                {
109
 
                  if (i1 == i)
110
 
                    return -1;
111
 
                  /* Note here: i1 < i < i2.  */
112
 
                  i1 = i;
113
 
                  break;
114
 
                }
115
 
              if (*p > *w)
116
 
                {
117
 
                  /* Note here: i1 <= i < i2.  */
118
 
                  i2 = i;
119
 
                  break;
120
 
                }
121
 
              p++; w++; n--;
122
 
              if (n == 0)
123
 
                return i;
124
 
            }
125
 
        }
 
100
        {
 
101
          unsigned int i = (i1 + i2) >> 1;
 
102
          const char *p = &unicode_name_words[extra_offset + (i-i0)*length];
 
103
          const char *w = word;
 
104
          unsigned int n = length;
 
105
          for (;;)
 
106
            {
 
107
              if (*p < *w)
 
108
                {
 
109
                  if (i1 == i)
 
110
                    return -1;
 
111
                  /* Note here: i1 < i < i2.  */
 
112
                  i1 = i;
 
113
                  break;
 
114
                }
 
115
              if (*p > *w)
 
116
                {
 
117
                  /* Note here: i1 <= i < i2.  */
 
118
                  i2 = i;
 
119
                  break;
 
120
                }
 
121
              p++; w++; n--;
 
122
              if (n == 0)
 
123
                return i;
 
124
            }
 
125
        }
126
126
    }
127
127
  return -1;
128
128
}
171
171
 
172
172
      q = jamo_initial_short_name[index1];
173
173
      while (*q != '\0')
174
 
        *ptr++ = *q++;
 
174
        *ptr++ = *q++;
175
175
      q = jamo_medial_short_name[index2];
176
176
      while (*q != '\0')
177
 
        *ptr++ = *q++;
 
177
        *ptr++ = *q++;
178
178
      q = jamo_final_short_name[index3];
179
179
      while (*q != '\0')
180
 
        *ptr++ = *q++;
 
180
        *ptr++ = *q++;
181
181
      *ptr = '\0';
182
182
      return buf;
183
183
    }
184
184
  else if ((c >= 0xF900 && c <= 0xFA2D) || (c >= 0xFA30 && c <= 0xFA6A)
185
 
           || (c >= 0xFA70 && c <= 0xFAD9) || (c >= 0x2F800 && c <= 0x2FA1D))
 
185
           || (c >= 0xFA70 && c <= 0xFAD9) || (c >= 0x2F800 && c <= 0x2FA1D))
186
186
    {
187
187
      /* Special case for CJK compatibility ideographs. Keeps the tables
188
 
         small.  */
 
188
         small.  */
189
189
      char *ptr;
190
190
      int i;
191
191
 
194
194
      ptr = buf + 28;
195
195
 
196
196
      for (i = (c < 0x10000 ? 12 : 16); i >= 0; i -= 4)
197
 
        {
198
 
          unsigned int x = (c >> i) & 0xf;
199
 
          *ptr++ = (x < 10 ? '0' : 'A' - 10) + x;
200
 
        }
 
197
        {
 
198
          unsigned int x = (c >> i) & 0xf;
 
199
          *ptr++ = (x < 10 ? '0' : 'A' - 10) + x;
 
200
        }
201
201
      *ptr = '\0';
202
202
      return buf;
203
203
    }
207
207
 
208
208
      /* Transform the code so that it fits in 16 bits.  */
209
209
      switch (c >> 12)
210
 
        {
211
 
        case 0x00: case 0x01: case 0x02: case 0x03: case 0x04:
212
 
          break;
213
 
        case 0x0A:
214
 
          c -= 0x05000;
215
 
          break;
216
 
        case 0x0F:
217
 
          c -= 0x09000;
218
 
          break;
219
 
        case 0x10:
220
 
          c -= 0x09000;
221
 
          break;
222
 
        case 0x12:
223
 
          c -= 0x0A000;
224
 
          break;
225
 
        case 0x1D:
226
 
          c -= 0x14000;
227
 
          break;
228
 
        case 0x2F:
229
 
          c -= 0x25000;
230
 
          break;
231
 
        case 0xE0:
232
 
          c -= 0xD5000;
233
 
          break;
234
 
        default:
235
 
          return NULL;
236
 
        }
 
210
        {
 
211
        case 0x00: case 0x01: case 0x02: case 0x03: case 0x04:
 
212
          break;
 
213
        case 0x0A:
 
214
          c -= 0x05000;
 
215
          break;
 
216
        case 0x0F:
 
217
          c -= 0x09000;
 
218
          break;
 
219
        case 0x10:
 
220
          c -= 0x09000;
 
221
          break;
 
222
        case 0x12:
 
223
          c -= 0x0A000;
 
224
          break;
 
225
        case 0x1D:
 
226
          c -= 0x14000;
 
227
          break;
 
228
        case 0x1F:
 
229
          c -= 0x15000;
 
230
          break;
 
231
        case 0x2F:
 
232
          c -= 0x24000;
 
233
          break;
 
234
        case 0xE0:
 
235
          c -= 0xD4000;
 
236
          break;
 
237
        default:
 
238
          return NULL;
 
239
        }
237
240
 
238
241
      {
239
 
        /* Binary search in unicode_code_to_name.  */
240
 
        unsigned int i1 = 0;
241
 
        unsigned int i2 = SIZEOF (unicode_code_to_name);
242
 
        for (;;)
243
 
          {
244
 
            unsigned int i = (i1 + i2) >> 1;
245
 
            if (unicode_code_to_name[i].code == c)
246
 
              {
247
 
                words = &unicode_names[unicode_code_to_name[i].name];
248
 
                break;
249
 
              }
250
 
            else if (unicode_code_to_name[i].code < c)
251
 
              {
252
 
                if (i1 == i)
253
 
                  {
254
 
                    words = NULL;
255
 
                    break;
256
 
                  }
257
 
                /* Note here: i1 < i < i2.  */
258
 
                i1 = i;
259
 
              }
260
 
            else if (unicode_code_to_name[i].code > c)
261
 
              {
262
 
                if (i2 == i)
263
 
                  {
264
 
                    words = NULL;
265
 
                    break;
266
 
                  }
267
 
                /* Note here: i1 <= i < i2.  */
268
 
                i2 = i;
269
 
              }
270
 
          }
 
242
        /* Binary search in unicode_code_to_name.  */
 
243
        unsigned int i1 = 0;
 
244
        unsigned int i2 = SIZEOF (unicode_code_to_name);
 
245
        for (;;)
 
246
          {
 
247
            unsigned int i = (i1 + i2) >> 1;
 
248
            if (unicode_code_to_name[i].code == c)
 
249
              {
 
250
                words = &unicode_names[unicode_code_to_name[i].name];
 
251
                break;
 
252
              }
 
253
            else if (unicode_code_to_name[i].code < c)
 
254
              {
 
255
                if (i1 == i)
 
256
                  {
 
257
                    words = NULL;
 
258
                    break;
 
259
                  }
 
260
                /* Note here: i1 < i < i2.  */
 
261
                i1 = i;
 
262
              }
 
263
            else if (unicode_code_to_name[i].code > c)
 
264
              {
 
265
                if (i2 == i)
 
266
                  {
 
267
                    words = NULL;
 
268
                    break;
 
269
                  }
 
270
                /* Note here: i1 <= i < i2.  */
 
271
                i2 = i;
 
272
              }
 
273
          }
271
274
      }
272
275
      if (words != NULL)
273
 
        {
274
 
          /* Found it in unicode_code_to_name. Now concatenate the words.  */
275
 
          /* buf needs to have at least UNICODE_CHARNAME_MAX_LENGTH bytes.  */
276
 
          char *ptr = buf;
277
 
          for (;;)
278
 
            {
279
 
              unsigned int wordlen;
280
 
              const char *word = unicode_name_word (*words>>1, &wordlen);
281
 
              do
282
 
                *ptr++ = *word++;
283
 
              while (--wordlen > 0);
284
 
              if ((*words & 1) == 0)
285
 
                break;
286
 
              *ptr++ = ' ';
287
 
              words++;
288
 
            }
289
 
          *ptr = '\0';
290
 
          return buf;
291
 
        }
 
276
        {
 
277
          /* Found it in unicode_code_to_name. Now concatenate the words.  */
 
278
          /* buf needs to have at least UNICODE_CHARNAME_MAX_LENGTH bytes.  */
 
279
          char *ptr = buf;
 
280
          for (;;)
 
281
            {
 
282
              unsigned int wordlen;
 
283
              const char *word = unicode_name_word (*words>>1, &wordlen);
 
284
              do
 
285
                *ptr++ = *word++;
 
286
              while (--wordlen > 0);
 
287
              if ((*words & 1) == 0)
 
288
                break;
 
289
              *ptr++ = ' ';
 
290
              words++;
 
291
            }
 
292
          *ptr = '\0';
 
293
          return buf;
 
294
        }
292
295
      return NULL;
293
296
    }
294
297
}
305
308
      char buf[UNICODE_CHARNAME_MAX_LENGTH];
306
309
      char *ptr = buf;
307
310
      for (;;)
308
 
        {
309
 
          char c = *name++;
310
 
          if (!(c >= ' ' && c <= '~'))
311
 
            break;
312
 
          *ptr++ = (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
313
 
          if (--len == 0)
314
 
            goto filled_buf;
315
 
        }
 
311
        {
 
312
          char c = *name++;
 
313
          if (!(c >= ' ' && c <= '~'))
 
314
            break;
 
315
          *ptr++ = (c >= 'a' && c <= 'z' ? c - 'a' + 'A' : c);
 
316
          if (--len == 0)
 
317
            goto filled_buf;
 
318
        }
316
319
      if (false)
317
320
      filled_buf:
318
 
        {
319
 
          /* Convert the constituents to uint16_t words.  */
320
 
          uint16_t words[UNICODE_CHARNAME_MAX_WORDS];
321
 
          uint16_t *wordptr = words;
322
 
          {
323
 
            const char *p1 = buf;
324
 
            for (;;)
325
 
              {
326
 
                {
327
 
                  int word;
328
 
                  const char *p2 = p1;
329
 
                  while (p2 < ptr && *p2 != ' ')
330
 
                    p2++;
331
 
                  word = unicode_name_word_lookup (p1, p2 - p1);
332
 
                  if (word < 0)
333
 
                    break;
334
 
                  if (wordptr == &words[UNICODE_CHARNAME_MAX_WORDS])
335
 
                    break;
336
 
                  *wordptr++ = word;
337
 
                  if (p2 == ptr)
338
 
                    goto filled_words;
339
 
                  p1 = p2 + 1;
340
 
                }
341
 
                /* Special case for Hangul syllables. Keeps the tables small. */
342
 
                if (wordptr == &words[2]
343
 
                    && words[0] == UNICODE_CHARNAME_WORD_HANGUL
344
 
                    && words[1] == UNICODE_CHARNAME_WORD_SYLLABLE)
345
 
                  {
346
 
                    /* Split the last word [p1..ptr) into three parts:
347
 
                         1) [BCDGHJKMNPRST]
348
 
                         2) [AEIOUWY]
349
 
                         3) [BCDGHIJKLMNPST]
350
 
                     */
351
 
                    const char *p2;
352
 
                    const char *p3;
353
 
                    const char *p4;
354
 
 
355
 
                    p2 = p1;
356
 
                    while (p2 < ptr
357
 
                           && (*p2 == 'B' || *p2 == 'C' || *p2 == 'D'
358
 
                               || *p2 == 'G' || *p2 == 'H' || *p2 == 'J'
359
 
                               || *p2 == 'K' || *p2 == 'M' || *p2 == 'N'
360
 
                               || *p2 == 'P' || *p2 == 'R' || *p2 == 'S'
361
 
                               || *p2 == 'T'))
362
 
                      p2++;
363
 
                    p3 = p2;
364
 
                    while (p3 < ptr
365
 
                           && (*p3 == 'A' || *p3 == 'E' || *p3 == 'I'
366
 
                               || *p3 == 'O' || *p3 == 'U' || *p3 == 'W'
367
 
                               || *p3 == 'Y'))
368
 
                      p3++;
369
 
                    p4 = p3;
370
 
                    while (p4 < ptr
371
 
                           && (*p4 == 'B' || *p4 == 'C' || *p4 == 'D'
372
 
                               || *p4 == 'G' || *p4 == 'H' || *p4 == 'I'
373
 
                               || *p4 == 'J' || *p4 == 'K' || *p4 == 'L'
374
 
                               || *p4 == 'M' || *p4 == 'N' || *p4 == 'P'
375
 
                               || *p4 == 'S' || *p4 == 'T'))
376
 
                      p4++;
377
 
                    if (p4 == ptr)
378
 
                      {
379
 
                        unsigned int n1 = p2 - p1;
380
 
                        unsigned int n2 = p3 - p2;
381
 
                        unsigned int n3 = p4 - p3;
382
 
 
383
 
                        if (n1 <= 2 && (n2 >= 1 && n2 <= 3) && n3 <= 2)
384
 
                          {
385
 
                            unsigned int index1;
386
 
 
387
 
                            for (index1 = 0; index1 < 19; index1++)
388
 
                              if (memcmp(jamo_initial_short_name[index1], p1, n1) == 0
389
 
                                  && jamo_initial_short_name[index1][n1] == '\0')
390
 
                                {
391
 
                                  unsigned int index2;
392
 
 
393
 
                                  for (index2 = 0; index2 < 21; index2++)
394
 
                                    if (memcmp(jamo_medial_short_name[index2], p2, n2) == 0
395
 
                                        && jamo_medial_short_name[index2][n2] == '\0')
396
 
                                      {
397
 
                                        unsigned int index3;
398
 
 
399
 
                                        for (index3 = 0; index3 < 28; index3++)
400
 
                                          if (memcmp(jamo_final_short_name[index3], p3, n3) == 0
401
 
                                              && jamo_final_short_name[index3][n3] == '\0')
402
 
                                            {
403
 
                                              return 0xAC00 + (index1 * 21 + index2) * 28 + index3;
404
 
                                            }
405
 
                                        break;
406
 
                                      }
407
 
                                  break;
408
 
                                }
409
 
                          }
410
 
                      }
411
 
                  }
412
 
                /* Special case for CJK compatibility ideographs. Keeps the
413
 
                   tables small.  */
414
 
                if (wordptr == &words[2]
415
 
                    && words[0] == UNICODE_CHARNAME_WORD_CJK
416
 
                    && words[1] == UNICODE_CHARNAME_WORD_COMPATIBILITY
417
 
                    && p1 + 14 <= ptr
418
 
                    && p1 + 15 >= ptr
419
 
                    && memcmp (p1, "IDEOGRAPH-", 10) == 0)
420
 
                  {
421
 
                    const char *p2 = p1 + 10;
422
 
 
423
 
                    if (*p2 != '0')
424
 
                      {
425
 
                        unsigned int c = 0;
426
 
 
427
 
                        for (;;)
428
 
                          {
429
 
                            if (*p2 >= '0' && *p2 <= '9')
430
 
                              c += (*p2 - '0');
431
 
                            else if (*p2 >= 'A' && *p2 <= 'F')
432
 
                              c += (*p2 - 'A' + 10);
433
 
                            else
434
 
                              break;
435
 
                            p2++;
436
 
                            if (p2 == ptr)
437
 
                              {
438
 
                                if ((c >= 0xF900 && c <= 0xFA2D)
439
 
                                    || (c >= 0xFA30 && c <= 0xFA6A)
440
 
                                    || (c >= 0xFA70 && c <= 0xFAD9)
441
 
                                    || (c >= 0x2F800 && c <= 0x2FA1D))
442
 
                                  return c;
443
 
                                else
444
 
                                  break;
445
 
                              }
446
 
                            c = c << 4;
447
 
                          }
448
 
                      }
449
 
                  }
450
 
              }
451
 
          }
452
 
          if (false)
453
 
          filled_words:
454
 
            {
455
 
              /* Multiply by 2, to simplify later comparisons.  */
456
 
              unsigned int words_length = wordptr - words;
457
 
              {
458
 
                int i = words_length - 1;
459
 
                words[i] = 2 * words[i];
460
 
                for (; --i >= 0; )
461
 
                  words[i] = 2 * words[i] + 1;
462
 
              }
463
 
              /* Binary search in unicode_name_to_code.  */
464
 
              {
465
 
                unsigned int i1 = 0;
466
 
                unsigned int i2 = SIZEOF (unicode_name_to_code);
467
 
                for (;;)
468
 
                  {
469
 
                    unsigned int i = (i1 + i2) >> 1;
470
 
                    const uint16_t *w = words;
471
 
                    const uint16_t *p = &unicode_names[unicode_name_to_code[i].name];
472
 
                    unsigned int n = words_length;
473
 
                    for (;;)
474
 
                      {
475
 
                        if (*p < *w)
476
 
                          {
477
 
                            if (i1 == i)
478
 
                              goto name_not_found;
479
 
                            /* Note here: i1 < i < i2.  */
480
 
                            i1 = i;
481
 
                            break;
482
 
                          }
483
 
                        else if (*p > *w)
484
 
                          {
485
 
                            if (i2 == i)
486
 
                              goto name_not_found;
487
 
                            /* Note here: i1 <= i < i2.  */
488
 
                            i2 = i;
489
 
                            break;
490
 
                          }
491
 
                        p++; w++; n--;
492
 
                        if (n == 0)
493
 
                          {
494
 
                            unsigned int c = unicode_name_to_code[i].code;
495
 
 
496
 
                            /* Undo the transformation to 16-bit space.  */
497
 
                            static const unsigned int offset[12] =
498
 
                              {
499
 
                                0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
500
 
                                0x05000, 0x09000, 0x09000, 0x0A000, 0x14000,
501
 
                                0x25000, 0xD5000
502
 
                              };
503
 
                            return c + offset[c >> 12];
504
 
                          }
505
 
                      }
506
 
                  }
507
 
              }
508
 
            name_not_found: ;
509
 
            }
510
 
        }
 
321
        {
 
322
          /* Convert the constituents to uint16_t words.  */
 
323
          uint16_t words[UNICODE_CHARNAME_MAX_WORDS];
 
324
          uint16_t *wordptr = words;
 
325
          {
 
326
            const char *p1 = buf;
 
327
            for (;;)
 
328
              {
 
329
                {
 
330
                  int word;
 
331
                  const char *p2 = p1;
 
332
                  while (p2 < ptr && *p2 != ' ')
 
333
                    p2++;
 
334
                  word = unicode_name_word_lookup (p1, p2 - p1);
 
335
                  if (word < 0)
 
336
                    break;
 
337
                  if (wordptr == &words[UNICODE_CHARNAME_MAX_WORDS])
 
338
                    break;
 
339
                  *wordptr++ = word;
 
340
                  if (p2 == ptr)
 
341
                    goto filled_words;
 
342
                  p1 = p2 + 1;
 
343
                }
 
344
                /* Special case for Hangul syllables. Keeps the tables small. */
 
345
                if (wordptr == &words[2]
 
346
                    && words[0] == UNICODE_CHARNAME_WORD_HANGUL
 
347
                    && words[1] == UNICODE_CHARNAME_WORD_SYLLABLE)
 
348
                  {
 
349
                    /* Split the last word [p1..ptr) into three parts:
 
350
                         1) [BCDGHJKMNPRST]
 
351
                         2) [AEIOUWY]
 
352
                         3) [BCDGHIJKLMNPST]
 
353
                     */
 
354
                    const char *p2;
 
355
                    const char *p3;
 
356
                    const char *p4;
 
357
 
 
358
                    p2 = p1;
 
359
                    while (p2 < ptr
 
360
                           && (*p2 == 'B' || *p2 == 'C' || *p2 == 'D'
 
361
                               || *p2 == 'G' || *p2 == 'H' || *p2 == 'J'
 
362
                               || *p2 == 'K' || *p2 == 'M' || *p2 == 'N'
 
363
                               || *p2 == 'P' || *p2 == 'R' || *p2 == 'S'
 
364
                               || *p2 == 'T'))
 
365
                      p2++;
 
366
                    p3 = p2;
 
367
                    while (p3 < ptr
 
368
                           && (*p3 == 'A' || *p3 == 'E' || *p3 == 'I'
 
369
                               || *p3 == 'O' || *p3 == 'U' || *p3 == 'W'
 
370
                               || *p3 == 'Y'))
 
371
                      p3++;
 
372
                    p4 = p3;
 
373
                    while (p4 < ptr
 
374
                           && (*p4 == 'B' || *p4 == 'C' || *p4 == 'D'
 
375
                               || *p4 == 'G' || *p4 == 'H' || *p4 == 'I'
 
376
                               || *p4 == 'J' || *p4 == 'K' || *p4 == 'L'
 
377
                               || *p4 == 'M' || *p4 == 'N' || *p4 == 'P'
 
378
                               || *p4 == 'S' || *p4 == 'T'))
 
379
                      p4++;
 
380
                    if (p4 == ptr)
 
381
                      {
 
382
                        unsigned int n1 = p2 - p1;
 
383
                        unsigned int n2 = p3 - p2;
 
384
                        unsigned int n3 = p4 - p3;
 
385
 
 
386
                        if (n1 <= 2 && (n2 >= 1 && n2 <= 3) && n3 <= 2)
 
387
                          {
 
388
                            unsigned int index1;
 
389
 
 
390
                            for (index1 = 0; index1 < 19; index1++)
 
391
                              if (memcmp (jamo_initial_short_name[index1], p1, n1) == 0
 
392
                                  && jamo_initial_short_name[index1][n1] == '\0')
 
393
                                {
 
394
                                  unsigned int index2;
 
395
 
 
396
                                  for (index2 = 0; index2 < 21; index2++)
 
397
                                    if (memcmp (jamo_medial_short_name[index2], p2, n2) == 0
 
398
                                        && jamo_medial_short_name[index2][n2] == '\0')
 
399
                                      {
 
400
                                        unsigned int index3;
 
401
 
 
402
                                        for (index3 = 0; index3 < 28; index3++)
 
403
                                          if (memcmp (jamo_final_short_name[index3], p3, n3) == 0
 
404
                                              && jamo_final_short_name[index3][n3] == '\0')
 
405
                                            {
 
406
                                              return 0xAC00 + (index1 * 21 + index2) * 28 + index3;
 
407
                                            }
 
408
                                        break;
 
409
                                      }
 
410
                                  break;
 
411
                                }
 
412
                          }
 
413
                      }
 
414
                  }
 
415
                /* Special case for CJK compatibility ideographs. Keeps the
 
416
                   tables small.  */
 
417
                if (wordptr == &words[2]
 
418
                    && words[0] == UNICODE_CHARNAME_WORD_CJK
 
419
                    && words[1] == UNICODE_CHARNAME_WORD_COMPATIBILITY
 
420
                    && p1 + 14 <= ptr
 
421
                    && p1 + 15 >= ptr
 
422
                    && memcmp (p1, "IDEOGRAPH-", 10) == 0)
 
423
                  {
 
424
                    const char *p2 = p1 + 10;
 
425
 
 
426
                    if (*p2 != '0')
 
427
                      {
 
428
                        unsigned int c = 0;
 
429
 
 
430
                        for (;;)
 
431
                          {
 
432
                            if (*p2 >= '0' && *p2 <= '9')
 
433
                              c += (*p2 - '0');
 
434
                            else if (*p2 >= 'A' && *p2 <= 'F')
 
435
                              c += (*p2 - 'A' + 10);
 
436
                            else
 
437
                              break;
 
438
                            p2++;
 
439
                            if (p2 == ptr)
 
440
                              {
 
441
                                if ((c >= 0xF900 && c <= 0xFA2D)
 
442
                                    || (c >= 0xFA30 && c <= 0xFA6A)
 
443
                                    || (c >= 0xFA70 && c <= 0xFAD9)
 
444
                                    || (c >= 0x2F800 && c <= 0x2FA1D))
 
445
                                  return c;
 
446
                                else
 
447
                                  break;
 
448
                              }
 
449
                            c = c << 4;
 
450
                          }
 
451
                      }
 
452
                  }
 
453
              }
 
454
          }
 
455
          if (false)
 
456
          filled_words:
 
457
            {
 
458
              /* Multiply by 2, to simplify later comparisons.  */
 
459
              unsigned int words_length = wordptr - words;
 
460
              {
 
461
                int i = words_length - 1;
 
462
                words[i] = 2 * words[i];
 
463
                for (; --i >= 0; )
 
464
                  words[i] = 2 * words[i] + 1;
 
465
              }
 
466
              /* Binary search in unicode_name_to_code.  */
 
467
              {
 
468
                unsigned int i1 = 0;
 
469
                unsigned int i2 = SIZEOF (unicode_name_to_code);
 
470
                for (;;)
 
471
                  {
 
472
                    unsigned int i = (i1 + i2) >> 1;
 
473
                    const uint16_t *w = words;
 
474
                    const uint16_t *p = &unicode_names[unicode_name_to_code[i].name];
 
475
                    unsigned int n = words_length;
 
476
                    for (;;)
 
477
                      {
 
478
                        if (*p < *w)
 
479
                          {
 
480
                            if (i1 == i)
 
481
                              goto name_not_found;
 
482
                            /* Note here: i1 < i < i2.  */
 
483
                            i1 = i;
 
484
                            break;
 
485
                          }
 
486
                        else if (*p > *w)
 
487
                          {
 
488
                            if (i2 == i)
 
489
                              goto name_not_found;
 
490
                            /* Note here: i1 <= i < i2.  */
 
491
                            i2 = i;
 
492
                            break;
 
493
                          }
 
494
                        p++; w++; n--;
 
495
                        if (n == 0)
 
496
                          {
 
497
                            unsigned int c = unicode_name_to_code[i].code;
 
498
 
 
499
                            /* Undo the transformation to 16-bit space.  */
 
500
                            static const unsigned int offset[13] =
 
501
                              {
 
502
                                0x00000, 0x00000, 0x00000, 0x00000, 0x00000,
 
503
                                0x05000, 0x09000, 0x09000, 0x0A000, 0x14000,
 
504
                                0x15000, 0x24000, 0xD4000
 
505
                              };
 
506
                            return c + offset[c >> 12];
 
507
                          }
 
508
                      }
 
509
                  }
 
510
              }
 
511
            name_not_found: ;
 
512
            }
 
513
        }
511
514
    }
512
515
  return UNINAME_INVALID;
513
516
}