Coverage Report

Created: 2025-10-13 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libidn2/lib/tr46map.c
Line
Count
Source
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
40.2k
#define countof(a) (sizeof(a)/sizeof(*(a)))
39
40
static void
41
_fill_map (uint32_t c, const uint8_t *p, IDNAMap *map)
42
7.48M
{
43
7.48M
  uint32_t value;
44
45
7.48M
  if (c <= 0xFF)
46
3.74M
    {
47
3.74M
      map->cp1 = *p++;
48
3.74M
      map->range = *p++;
49
3.74M
    }
50
3.74M
  else if (c <= 0xFFFF)
51
3.56M
    {
52
3.56M
      map->cp1 = (p[0] << 8) | p[1];
53
3.56M
      map->range = (p[2] << 8) | p[3];
54
3.56M
      p += 4;
55
3.56M
    }
56
176k
  else
57
176k
    {
58
176k
      map->cp1 = (p[0] << 16) | (p[1] << 8) | p[2];
59
176k
      map->range = (p[3] << 8) | p[4];
60
176k
      p += 5;
61
176k
    }
62
63
7.48M
  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
7.48M
  map->flag_index = value & 0x7;
68
7.48M
  map->offset = (value >> 3) & 0x3FFF;
69
7.48M
  map->nmappings = (value >> 17) & 0x1F;
70
7.48M
}
71
72
static int
73
_compare_idna_map (const uint32_t *c, const uint8_t *p)
74
6.68M
{
75
6.68M
  IDNAMap map;
76
77
6.68M
  _fill_map (*c, p, &map);
78
79
6.68M
  if (*c < map.cp1)
80
3.84M
    return -1;
81
2.83M
  if (*c > map.cp1 + map.range)
82
2.02M
    return 1;
83
808k
  return 0;
84
2.83M
}
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
808k
{
107
808k
  uint8_t *p;
108
109
808k
  if (c <= 0xFF)
110
515k
    p =
111
515k
      (uint8_t *) bsearch (&c, idna_map_8, sizeof (idna_map_8) / 5, 5,
112
515k
         (int (*)(const void *, const void *))
113
515k
         _compare_idna_map);
114
292k
  else if (c <= 0xFFFF)
115
277k
    p =
116
277k
      (uint8_t *) bsearch (&c, idna_map_16, sizeof (idna_map_16) / 7, 7,
117
277k
         (int (*)(const void *, const void *))
118
277k
         _compare_idna_map);
119
15.3k
  else if (c <= 0xFFFFFF)
120
15.3k
    p =
121
15.3k
      (uint8_t *) bsearch (&c, idna_map_24, sizeof (idna_map_24) / 8, 8,
122
15.3k
         (int (*)(const void *, const void *))
123
15.3k
         _compare_idna_map);
124
0
  else
125
0
    p = NULL;
126
127
808k
  if (!p)
128
0
    {
129
0
      memset (map, 0, sizeof (IDNAMap));
130
0
      return -1;
131
0
    }
132
133
808k
  _fill_map (c, p, map);
134
808k
  return 0;
135
808k
}
136
137
int
138
map_is (const IDNAMap *map, unsigned flags)
139
2.13M
{
140
2.13M
  return (idna_flags[map->flag_index] & flags) == flags;
141
2.13M
}
142
143
static int G_GNUC_IDN2_ATTRIBUTE_PURE
144
_compare_nfcqc_map (uint32_t *c, NFCQCMap *m2)
145
275k
{
146
275k
  if (*c < m2->cp1)
147
184k
    return -1;
148
90.2k
  if (*c > m2->cp2)
149
89.5k
    return 1;
150
689
  return 0;
151
90.2k
}
152
153
NFCQCMap *
154
get_nfcqc_map (uint32_t c)
155
40.2k
{
156
40.2k
  return (NFCQCMap *) bsearch (&c, nfcqc_map, countof (nfcqc_map),
157
40.2k
             sizeof (NFCQCMap),
158
40.2k
             (int (*)(const void *, const void *))
159
40.2k
             _compare_nfcqc_map);
160
40.2k
}
161
162
/* copy 'n' codepoints from mapdata stream */
163
int
164
get_map_data (uint32_t *dst, const IDNAMap *map)
165
86.4k
{
166
86.4k
  int n = map->nmappings;
167
86.4k
  const uint8_t *src = mapdata + map->offset;
168
169
276k
  for (; n > 0; n--)
170
189k
    {
171
189k
      uint32_t cp = 0;
172
189k
      do
173
304k
  cp = (cp << 7) | (*src & 0x7F);
174
304k
      while (*src++ & 0x80);
175
189k
      *dst++ = cp;
176
189k
    }
177
178
86.4k
  return map->nmappings;
179
86.4k
}