aboutsummaryrefslogtreecommitdiffstats
path: root/nametoucs.c
blob: eef76bd857be7336aeb3b8fd692165cf427f4feb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <stdlib.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>

#include "libucd_int.h"
#include "gen/nametoucs_hash.h"

static uint32_t prehash(const char *str)
{
  uint32_t hash = PHASHSALT;
  const uint8_t *p = (const uint8_t *)str;

  while ( *p )
    hash = (hash ^ *p++) + ((hash << 27)+(hash >> 5));

  return hash;
}

/* This returns a candidate UCS for a given name. */
static int32_t name_lookup(const char *name)
{
  int32_t ucs;
  uint32_t hash;

  if ( !strncmp(name, "CJK UNIFIED IDEOGRAPH-", 22) ) {
    char *q;

    ucs = strtol(name+22, &q, 16);
    if ( *q || q < name+26 || q > name+27 )
      return -1;
  } else {
    hash = _libucd_nametoucs_hash(prehash(name));
    if ( hash > PHASHNKEYS )
      return -1;
    ucs = getint24(_libucd_nametoucs_tab[hash].ucs);
  }

  return ucs;
}

const struct unicode_character_data *
unicode_character_lookup(const char *name)
{
  int32_t ucs = name_lookup(name);
  const struct unicode_character_data *ucd =
    unicode_character_data(ucs);

  if ( !ucd )
    return NULL;

  if ( !ucd->name || strcmp(name, ucd->name) ) {
    unicode_character_put(ucd);
    errno = EINVAL;
    return NULL;
  }
  
  return ucd;
}