Coverage Report

Created: 2024-03-08 06:32

/src/libidn2/lib/tr46map.c
Line
Count
Source (jump to first uncovered line)
1
/* tr46map.c - implementation of IDNA2008 TR46 functions
2
   Copyright (C) 2016-2017 Tim Rühsen
3
4
   Libidn2 is free software: you can redistribute it and/or modify it
5
   under the terms of either:
6
7
     * the GNU Lesser General Public License as published by the Free
8
       Software Foundation; either version 3 of the License, or (at
9
       your option) any later version.
10
11
   or
12
13
     * the GNU General Public License as published by the Free
14
       Software Foundation; either version 2 of the License, or (at
15
       your option) any later version.
16
17
   or both in parallel, as here.
18
19
   This program is distributed in the hope that it will be useful,
20
   but WITHOUT ANY WARRANTY; without even the implied warranty of
21
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
   GNU General Public License for more details.
23
24
   You should have received copies of the GNU General Public License and
25
   the GNU Lesser General Public License along with this program.  If
26
   not, see <http://www.gnu.org/licenses/>.
27
*/
28
29
#include <config.h>
30
31
#include <stdint.h>
32
#include <stdlib.h>   /* bsearch */
33
#include <string.h>   /* memset */
34
35
#include "tr46map.h"
36
#include "tr46map_data.c"
37
38
0
#define countof(a) (sizeof(a)/sizeof(*(a)))
39
40
static void
41
_fill_map (uint32_t c, const uint8_t *p, IDNAMap *map)
42
8.56M
{
43
8.56M
  uint32_t value;
44
45
8.56M
  if (c <= 0xFF)
46
3.67M
    {
47
3.67M
      map->cp1 = *p++;
48
3.67M
      map->range = *p++;
49
3.67M
    }
50
4.89M
  else if (c <= 0xFFFF)
51
4.78M
    {
52
4.78M
      map->cp1 = (p[0] << 8) | p[1];
53
4.78M
      map->range = (p[2] << 8) | p[3];
54
4.78M
      p += 4;
55
4.78M
    }
56
113k
  else
57
113k
    {
58
113k
      map->cp1 = (p[0] << 16) | (p[1] << 8) | p[2];
59
113k
      map->range = (p[3] << 8) | p[4];
60
113k
      p += 5;
61
113k
    }
62
63
8.56M
  value = (p[0] << 16) | (p[1] << 8) | p[2];
64
65
  /* deconstruct value, construction was
66
   *   value = (((map->nmappings << 14) | map->offset) << 3) | map->flag_index; */
67
8.56M
  map->flag_index = value & 0x7;
68
8.56M
  map->offset = (value >> 3) & 0x3FFF;
69
8.56M
  map->nmappings = (value >> 17) & 0x1F;
70
8.56M
}
71
72
static int
73
_compare_idna_map (const uint32_t *c, const uint8_t *p)
74
7.70M
{
75
7.70M
  IDNAMap map;
76
77
7.70M
  _fill_map (*c, p, &map);
78
79
7.70M
  if (*c < map.cp1)
80
4.24M
    return -1;
81
3.46M
  if (*c > map.cp1 + map.range)
82
2.59M
    return 1;
83
866k
  return 0;
84
3.46M
}
85
86
/*
87
static int
88
_compare_idna_map(uint32_t *c, IDNAMap *m2)
89
{
90
  if (*c < m2->cp1)
91
    return -1;
92
  if (*c > m2->cp1 + m2->range)
93
    return 1;
94
  return 0;
95
}
96
97
IDNAMap
98
*get_idna_map(uint32_t c)
99
{
100
  return bsearch(&c, idna_map, countof(idna_map), sizeof(IDNAMap), (int(*)(const void *, const void *))_compare_idna_map);
101
}
102
*/
103
104
int
105
get_idna_map (uint32_t c, IDNAMap *map)
106
866k
{
107
866k
  uint8_t *p;
108
109
866k
  if (c <= 0xFF)
110
485k
    p =
111
485k
      (uint8_t *) bsearch (&c, idna_map_8, sizeof (idna_map_8) / 5, 5,
112
485k
         (int (*)(const void *, const void *))
113
485k
         _compare_idna_map);
114
381k
  else if (c <= 0xFFFF)
115
371k
    p =
116
371k
      (uint8_t *) bsearch (&c, idna_map_16, sizeof (idna_map_16) / 7, 7,
117
371k
         (int (*)(const void *, const void *))
118
371k
         _compare_idna_map);
119
9.77k
  else if (c <= 0xFFFFFF)
120
9.77k
    p =
121
9.77k
      (uint8_t *) bsearch (&c, idna_map_24, sizeof (idna_map_24) / 8, 8,
122
9.77k
         (int (*)(const void *, const void *))
123
9.77k
         _compare_idna_map);
124
0
  else
125
0
    p = NULL;
126
127
866k
  if (!p)
128
0
    {
129
0
      memset (map, 0, sizeof (IDNAMap));
130
0
      return -1;
131
0
    }
132
133
866k
  _fill_map (c, p, map);
134
866k
  return 0;
135
866k
}
136
137
int
138
map_is (const IDNAMap *map, unsigned flags)
139
1.87M
{
140
1.87M
  return (idna_flags[map->flag_index] & flags) == flags;
141
1.87M
}
142
143
static int G_GNUC_IDN2_ATTRIBUTE_PURE
144
_compare_nfcqc_map (uint32_t *c, NFCQCMap *m2)
145
0
{
146
0
  if (*c < m2->cp1)
147
0
    return -1;
148
0
  if (*c > m2->cp2)
149
0
    return 1;
150
0
  return 0;
151
0
}
152
153
NFCQCMap *
154
get_nfcqc_map (uint32_t c)
155
0
{
156
0
  return (NFCQCMap *) bsearch (&c, nfcqc_map, countof (nfcqc_map),
157
0
             sizeof (NFCQCMap),
158
0
             (int (*)(const void *, const void *))
159
0
             _compare_nfcqc_map);
160
0
}
161
162
/* copy 'n' codepoints from mapdata stream */
163
int
164
get_map_data (uint32_t *dst, const IDNAMap *map)
165
94.3k
{
166
94.3k
  int n = map->nmappings;
167
94.3k
  const uint8_t *src = mapdata + map->offset;
168
169
307k
  for (; n > 0; n--)
170
212k
    {
171
212k
      uint32_t cp = 0;
172
212k
      do
173
361k
  cp = (cp << 7) | (*src & 0x7F);
174
361k
      while (*src++ & 0x80);
175
212k
      *dst++ = cp;
176
212k
    }
177
178
94.3k
  return map->nmappings;
179
94.3k
}