Branch data Line data Source code
1 : : /* bidi.c - IDNA right to left checking functions
2 : : Copyright (C) 2011 Simon Josefsson
3 : :
4 : : This program is free software: you can redistribute it and/or modify
5 : : it under the terms of the GNU General Public License as published by
6 : : the Free Software Foundation, either version 3 of the License, or
7 : : (at your option) any later version.
8 : :
9 : : This program is distributed in the hope that it will be useful,
10 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : GNU General Public License for more details.
13 : :
14 : : You should have received a copy of the GNU General Public License
15 : : along with this program. If not, see <http://www.gnu.org/licenses/>.
16 : : */
17 : :
18 : : #include <config.h>
19 : :
20 : : #include "idn2.h"
21 : :
22 : : #include <stdbool.h>
23 : :
24 : : #include "bidi.h"
25 : :
26 : : #include "unictype.h"
27 : :
28 : : /* The entire bidi rule could be rewritten into an one-pass approach;
29 : : the implementation below may in the worse case iterate through the
30 : : string a few times. However, recall Knuth and premature
31 : : optimization is the root of all evil. */
32 : :
33 : : static bool
34 : 164 : rtl_ralanenescsetonbnnsm_ok (const uint32_t * label, size_t llen)
35 : : {
36 : : int bc;
37 : :
38 [ + + ]: 1489 : for (; llen > 0; label++, llen--)
39 : : {
40 : 1329 : bc = uc_bidi_class (*label);
41 : :
42 [ + + ]: 1329 : switch (bc)
43 : : {
44 : : case UC_BIDI_R:
45 : : case UC_BIDI_AL:
46 : : case UC_BIDI_AN:
47 : : case UC_BIDI_EN:
48 : : case UC_BIDI_ES:
49 : : case UC_BIDI_CS:
50 : : case UC_BIDI_ET:
51 : : case UC_BIDI_ON:
52 : : case UC_BIDI_BN:
53 : : case UC_BIDI_NSM:
54 : : break;
55 : :
56 : : default:
57 : 4 : return false;
58 : : }
59 : : }
60 : :
61 : 164 : return true;
62 : : }
63 : :
64 : : static bool
65 : 160 : rtl_ends_ok (const uint32_t * label, size_t llen)
66 : : {
67 : : const uint32_t *p;
68 : : int bc;
69 : :
70 [ + - ]: 172 : for (p = label + llen - 1; llen > 0; llen--, p--)
71 : : {
72 : 172 : bc = uc_bidi_class (*p);
73 [ + + - ]: 172 : switch (bc)
74 : : {
75 : : case UC_BIDI_NSM:
76 : 12 : continue;
77 : :
78 : : case UC_BIDI_R:
79 : : case UC_BIDI_AL:
80 : : case UC_BIDI_EN:
81 : : case UC_BIDI_AN:
82 : 160 : return true;
83 : :
84 : : default:
85 : 0 : return false;
86 : : }
87 : : }
88 : :
89 : 160 : return false;
90 : : }
91 : :
92 : : static bool
93 : 160 : rtl_enan_ok (const uint32_t * label, size_t llen)
94 : : {
95 : 160 : bool en = false;
96 : 160 : bool an = false;
97 : : const uint32_t *p;
98 : : int bc;
99 : :
100 [ + + ]: 1479 : for (p = label + llen - 1; llen > 0; llen--, p--)
101 : : {
102 : 1319 : bc = uc_bidi_class (*p);
103 [ + + + ]: 1319 : switch (bc)
104 : : {
105 : : case UC_BIDI_EN:
106 : 9 : en = true;
107 : 9 : break;
108 : :
109 : : case UC_BIDI_AN:
110 : 5 : an = true;
111 : : break;
112 : : }
113 : : }
114 : :
115 [ + + ][ + - ]: 160 : return !(en && an);
116 : : }
117 : :
118 : : static int
119 : 164 : rtl (const uint32_t * label, size_t llen)
120 : : {
121 [ + + ][ + - ]: 164 : if (rtl_ralanenescsetonbnnsm_ok (label, llen)
[ + - ]
122 : : && rtl_ends_ok (label, llen) && rtl_enan_ok (label, llen))
123 : 160 : return IDN2_OK;
124 : 164 : return IDN2_BIDI;
125 : : }
126 : :
127 : : static bool
128 : 3 : ltr_lenescsetonbnnsm_ok (const uint32_t * label, size_t llen)
129 : : {
130 : : int bc;
131 : :
132 [ + - ]: 6 : for (; llen > 0; label++, llen--)
133 : : {
134 : 6 : bc = uc_bidi_class (*label);
135 [ + + ]: 6 : switch (bc)
136 : : {
137 : : case UC_BIDI_L:
138 : : case UC_BIDI_EN:
139 : : case UC_BIDI_ES:
140 : : case UC_BIDI_CS:
141 : : case UC_BIDI_ET:
142 : : case UC_BIDI_ON:
143 : : case UC_BIDI_BN:
144 : : case UC_BIDI_NSM:
145 : : break;
146 : :
147 : : default:
148 : 3 : return false;
149 : : }
150 : : }
151 : :
152 : 3 : return true;
153 : : }
154 : :
155 : : static bool
156 : 0 : ltr_ends_ok (const uint32_t * label, size_t llen)
157 : : {
158 : : const uint32_t *p;
159 : : int bc;
160 : :
161 [ # # ]: 0 : for (p = label + llen - 1; llen > 0; llen--, p--)
162 : : {
163 : 0 : bc = uc_bidi_class (*p);
164 [ # # # ]: 0 : switch (bc)
165 : : {
166 : : case UC_BIDI_NSM:
167 : 0 : continue;
168 : :
169 : : case UC_BIDI_L:
170 : : case UC_BIDI_EN:
171 : 0 : return true;
172 : :
173 : : default:
174 : 0 : return false;
175 : : }
176 : : }
177 : :
178 : 0 : return false;
179 : : }
180 : :
181 : : static int
182 : 3 : ltr (const uint32_t * label, size_t llen)
183 : : {
184 [ - + ][ # # ]: 3 : if (ltr_lenescsetonbnnsm_ok (label, llen) && ltr_ends_ok (label, llen))
185 : 0 : return IDN2_OK;
186 : 3 : return IDN2_BIDI;
187 : : }
188 : :
189 : : static bool
190 : 373 : bidi_p (const uint32_t * label, size_t llen)
191 : : {
192 : : int bc;
193 : :
194 [ + + ]: 1573 : for (; llen > 0; label++, llen--)
195 : : {
196 : 1369 : bc = uc_bidi_class (*label);
197 : :
198 [ + + ]: 1369 : switch (bc)
199 : : {
200 : : case UC_BIDI_R:
201 : : case UC_BIDI_AL:
202 : : case UC_BIDI_AN:
203 : 169 : return true;
204 : : }
205 : : }
206 : :
207 : 373 : return false;
208 : : }
209 : :
210 : : int
211 : 373 : _idn2_bidi (const uint32_t * label, size_t llen)
212 : : {
213 : : int bc;
214 : :
215 [ + + ]: 373 : if (!bidi_p (label, llen))
216 : 204 : return IDN2_OK;
217 : :
218 : 169 : bc = uc_bidi_class (*label);
219 [ + + + ]: 169 : switch (bc)
220 : : {
221 : : case UC_BIDI_L:
222 : 3 : return ltr (label, llen);
223 : :
224 : : case UC_BIDI_R:
225 : : case UC_BIDI_AL:
226 : 164 : return rtl (label, llen);
227 : : }
228 : :
229 : 373 : return IDN2_BIDI;
230 : : }
|