1 /*
2 * TERMS AND CONDITIONS
3 * FOR
4 * OPEN SOURCE CODE LICENSE
5 * Version 1.1
6 *
7 * Japan Registry Services Co., Ltd. ("JPRS"), a Japanese corporation
8 * having its head office at Chiyoda First Bldg. East 13F 3-8-1 Nishi-Kanda,
9 * Chiyoda-ku, Tokyo 101-0065, Japan, grants you the license for open source
10 * code specified in EXHIBIT A the "Code" subject to the following Terms and
11 * Conditions ("OSCL").
12 *
13 * 1. License Grant.
14 * JPRS hereby grants you a worldwide, royalty-free, non-exclusive
15 * license, subject to third party intellectual property claims:
16 * (a) under intellectual property rights (other than patent or
17 * trademark) licensable by JPRS to use, reproduce, modify, display,
18 * perform, sublicense and distribute the Code (or portions thereof)
19 * with or without modifications, and/or as part of a derivative work;
20 * or
21 * (b) under claims of the infringement through the making, using,
22 * offering to sell and/or otherwise disposing the JPRS Revised Code
23 * (or portions thereof);
24 * (c) the licenses granted in this Section 1(a) and (b) are effective on
25 * the date JPRS first distributes the Code to you under the terms of
26 * this OSCL;
27 * (d) Notwithstanding the above stated terms, no patent license is
28 * granted:
29 * 1) for a code that you delete from the Code;
30 * 2) separate from the Code; or
31 * 3) for infringements caused by:
32 * i) modification of the Code; or
33 * ii) combination of the Code with other software or devices.
34 *
35 * 2. Consents.
36 * You agree that:
37 * (a) you must include a copy of this OSCL and the notice set forth in
38 * EXHIBIT A with every copy of the Code you distribute;
39 * (b) you must include a copy of this OSCL and the notice set forth in
40 * EXHIBIT A with every copy of binary form of the Code in the
41 * documentation and/or other materials provided with the distribution;
42 * (c) you may not offer or impose any terms on any source code version
43 * that alters or restricts the applicable version of this OSCL or
44 * the recipients' rights hereunder.
45 * (d) If the terms and conditions are set forth in EXHIBIT A, you must
46 * comply with those terms and conditions.
47 *
48 * 3. Proprietary Information.
49 * All trademarks, service marks, patents, copyrights, trade secrets, and
50 * other proprietary rights in or related to the Code are and will remain
51 * the exclusive property of JPRS or its licensors, whether or not
52 * specifically recognized or perfected under local law except specified
53 * in this OSCL; provided however you agree and understand that the JPRS
54 * name may not be used to endorse or promote this Code without prior
55 * written approval of JPRS.
56 *
57 * 4. WARRANTY DISCLAIMER.
58 * JPRS MAKES NO REPRESENTATIONS AND WARRANTIES REGARDING THE USE OF THE
59 * CODE, NOR DOES JPRS MAKE ANY REPRESENTATIONS THAT THE CODE WILL BECOME
60 * COMMERCIALLY AVAILABLE. JPRS, ITS AFFILIATES, AND ITS SUPPLIERS DO NOT
61 * WARRANT OR REPRESENT THAT THE CODE IS FREE OF ERRORS OR THAT THE CODE
62 * IS SUITABLE FOR TRANSLATION AND/OR LOCALIZATION. THE CODE IS PROVIDED
63 * ON AN "AS IS" BASIS AND JPRS AND ITS SUPPLIERS HAVE NO OBLIGATION TO
64 * CORRECT ERRORS OR TO SUPPORT THE CODE UNDER THIS OSCL FOR ANY REASON.
65 * TO THE FULL EXTENT PERMITTED BY LAW, ALL OBLIGATIONS ARE HEREBY
66 * EXCLUDED WHETHER EXPRESS, STATUTORY OR IMPLIED UNDER LAW, COURSE OF
67 * DEALING, CUSTOM, TRADE USAGE, ORAL OR WRITTEN STATEMENT OR OTHERWISE,
68 * INCLUDING BUT NOT LIMITED TO ANY IMPLIED WARRANTIES OF MERCHANTABILITY
69 * OR FITNESS FOR A PARTICULAR PURPOSE CONCERNING THE CODE.
70 *
71 * 5. NO LIABILITY.
72 * UNDER NO CIRCUMSTANCES SHALL JPRS AND/OR ITS AFFILIATES, LICENSORS, OR
73 * REPRESENTATIVES BE LIABLE FOR ANY DAMAGES INCLUDING BUT NOT LIMITED TO
74 * CONSEQUENTIAL, INDIRECT, SPECIAL, PUNITIVE OR INCIDENTAL DAMAGES,
75 * WHETHER FORESEEABLE OR UNFORESEEABLE, BASED ON YOUR CLAIMS, INCLUDING,
76 * BUT NOT LIMITED TO, CLAIMS FOR LOSS OF DATA, GOODWILL, PROFITS, USE OF
77 * MONEY, INTERRUPTION IN USE OR AVAILABILITY OF DATA, STOPPAGE, IMPLIED
78 * WARRANTY, BREACH OF CONTRACT, MISREPRESENTATION, NEGLIGENCE, STRICT
79 * LIABILITY IN TORT, OR OTHERWISE.
80 *
81 * 6. Indemnification.
82 * You hereby agree to indemnify, defend, and hold harmless JPRS for any
83 * liability incurred by JRPS due to your terms of warranty, support,
84 * indemnity, or liability offered by you to any third party.
85 *
86 * 7. Termination.
87 * 7.1 This OSCL shall be automatically terminated in the events that:
88 * (a) You fail to comply with the terms herein and fail to cure such
89 * breach within 30 days of becoming aware of the breach;
90 * (b) You initiate patent or copyright infringement litigation against
91 * any party (including a cross-claim or counterclaim in a lawsuit)
92 * alleging that the Code constitutes a direct or indirect patent or
93 * copyright infringement, in such case, this OSCL to you shall
94 * terminate as of the date such litigation is filed;
95 * 7.2 In the event of termination under Sections 7.1(a) or 7.1(b) above,
96 * all end user license agreements (excluding distributors and
97 * resellers) which have been validly granted by You or any distributor
98 * hereunder prior to termination shall survive termination.
99 *
100 *
101 * 8. General.
102 * This OSCL shall be governed by, and construed and enforced in
103 * accordance with, the laws of Japan. Any litigation or arbitration
104 * between the parties shall be conducted exclusively in Tokyo, Japan
105 * except written consent of JPRS provides other venue.
106 *
107 *
108 * EXHIBIT A
109 *
110 * The original open source code of idnkit-2 is idnkit-1.0 developed and
111 * conceived by Japan Network Information Center ("JPNIC"), a Japanese
112 * association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
113 * Chiyoda-ku, Tokyo 101-0047, Japan, and JPRS modifies above original code
114 * under following Terms and Conditions set forth by JPNIC.
115 *
116 * JPNIC
117 *
118 * Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved.
119 *
120 * By using this file, you agree to the terms and conditions set forth bellow.
121 *
122 * LICENSE TERMS AND CONDITIONS
123 *
124 * The following License Terms and Conditions apply, unless a different
125 * license is obtained from Japan Network Information Center ("JPNIC"),
126 * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
127 * Chiyoda-ku, Tokyo 101-0047, Japan.
128 *
129 * 1. Use, Modification and Redistribution (including distribution of any
130 * modified or derived work) in source and/or binary forms is permitted
131 * under this License Terms and Conditions.
132 *
133 * 2. Redistribution of source code must retain the copyright notices as they
134 * appear in each source code file, this License Terms and Conditions.
135 *
136 * 3. Redistribution in binary form must reproduce the Copyright Notice,
137 * this License Terms and Conditions, in the documentation and/or other
138 * materials provided with the distribution. For the purposes of binary
139 * distribution the "Copyright Notice" refers to the following language:
140 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
141 *
142 * 4. The name of JPNIC may not be used to endorse or promote products
143 * derived from this Software without specific prior written approval of
144 * JPNIC.
145 *
146 * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
147 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
148 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
149 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JPNIC BE LIABLE
150 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
151 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
152 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
153 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
154 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
155 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
156 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
157 *
158 *
159 * JPRS Public License Notice
160 * For
161 * idnkit-2.
162 *
163 * The contents of this file are subject to the Terms and Conditions for
164 * the Open Source Code License (the "OSCL"). You may not use this file
165 * except in compliance with above terms and conditions. A copy of the OSCL
166 * is available at <http://jprs.co.jp/idn/>.
167 * The JPRS Revised Code is idnkit-2.
168 * The Initial Developer of the JPRS Revised Code is Japan Network
169 * Information Center ("JPNIC"), a Japanese association,
170 * Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda, Chiyoda-ku, Tokyo
171 * 101-0047, Japan.
172 * "Copyright (c) 2000-2002 Japan Network Information Center. All rights reserved."
173 * "Copyright (c) 2010-2012 Japan Registry Services Co., Ltd. All rights reserved."
174 * Contributor(s): ______________________________________.
175 *
176 * If you wish to allow use of your version of this file only under the
177 * above License(s) and not to allow others to use your version of this
178 * file, please indicate your decision by deleting the relevant provisions
179 * above and replacing them with the notice and other provisions required
180 * by the above License(s). If you do not delete the relevant provisions,
181 * a recipient may use your version of this file under either the above
182 * License(s).
183 */
184
185 #include <config.h>
186
187 #include <stddef.h>
188 #include <stdlib.h>
189 #include <string.h>
190
191 #include <idn/assert.h>
192 #include <idn/debug.h>
193 #include <idn/logmacro.h>
194 #include <idn/result.h>
195 #include <idn/utf32.h>
196
197 /*
198 * Unicode surrogate pair.
199 */
200 #define SURROGATE_HIGH(v) (SURROGATE_H_OFF + (((v) - 0x10000) >> 10))
201 #define SURROGATE_LOW(v) (SURROGATE_L_OFF + ((v) & 0x3ff))
202 #define SURROGATE_BASE 0x10000
203 #define SURROGATE_H_OFF 0xd800
204 #define SURROGATE_L_OFF 0xdc00
205 #define COMBINE_SURROGATE(h, l) \
206 (SURROGATE_BASE + (((h)-SURROGATE_H_OFF)<<10) + ((l)-SURROGATE_L_OFF))
207
208 /*
209 * ASCII ctype macros.
210 * Note that these macros evaluate the argument multiple times. Be careful.
211 */
212 #define ASCII_TOUPPER(c) \
213 (('a' <= (c) && (c) <= 'z') ? ((c) - 'a' + 'A') : (c))
214 #define ASCII_TOLOWER(c) \
215 (('A' <= (c) && (c) <= 'Z') ? ((c) - 'A' + 'a') : (c))
216
217 /*
218 * Convert an UTF-32 character to a multibyte UTF-16 sequence.
219 */
220 idn_result_t
idn__utf32_toutf16(const unsigned long * utf32,unsigned short * utf16,size_t tolen)221 idn__utf32_toutf16(const unsigned long *utf32, unsigned short *utf16,
222 size_t tolen) {
223 idn_result_t r = idn_success;
224 unsigned short *utf16p = utf16;
225 unsigned long v;
226
227 TRACE(("idn__utf32_toutf16(utf32=\"%s\", tolen=%d)\n",
228 idn__debug_utf32xstring(utf32), (int)tolen));
229
230 while (*utf32 != '\0') {
231 v = *utf32++;
232
233 if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
234 WARNING(("idn__utf32_utf32toutf16: UTF-32 string "
235 "contains surrogate pair\n"));
236 r = idn_invalid_encoding;
237 goto ret;
238 } else if (v > 0xffff) {
239 /* Convert to surrogate pair */
240 if (v >= 0x110000) {
241 r = idn_invalid_encoding;
242 goto ret;
243 }
244 if (tolen < 2) {
245 r = idn_buffer_overflow;
246 goto ret;
247 }
248 *utf16p++ = SURROGATE_HIGH(v);
249 *utf16p++ = SURROGATE_LOW(v);
250 tolen -= 2;
251 } else {
252 if (tolen < 1) {
253 r = idn_buffer_overflow;
254 goto ret;
255 }
256 *utf16p++ = v;
257 tolen--;
258 }
259 }
260
261 if (tolen < 1) {
262 r = idn_buffer_overflow;
263 goto ret;
264 }
265 *utf16p = '\0';
266
267 ret:
268 if (r == idn_success) {
269 TRACE(("idn__utf32_toutf16(): success (utf16=\"%s\")\n",
270 idn__debug_utf16xstring(utf16)));
271 } else {
272 TRACE(("idn__utf32_toutf16(): %s\n", idn_result_tostring(r)));
273 }
274 return (r);
275 }
276
277 /*
278 * Convert a multibyte UTF-16 sequence to an UTF-32 character.
279 */
280 idn_result_t
idn__utf32_fromutf16(const unsigned short * utf16,unsigned long * utf32,size_t tolen)281 idn__utf32_fromutf16(const unsigned short *utf16, unsigned long *utf32,
282 size_t tolen) {
283 idn_result_t r = idn_success;
284 unsigned long *utf32p = utf32;
285 unsigned short v0, v1;
286
287 TRACE(("idn__utf32_fromutf16(utf16=\"%s\", tolen=%d)\n",
288 idn__debug_utf16xstring(utf16), (int)tolen));
289
290 while (*utf16 != '\0') {
291 v0 = *utf16;
292
293 if (tolen < 1) {
294 r = idn_buffer_overflow;
295 goto ret;
296 }
297
298 if (IS_SURROGATE_HIGH(v0)) {
299 v1 = *(utf16 + 1);
300 if (!IS_SURROGATE_LOW(v1)) {
301 WARNING(("idn__utf32_utf16toutf32: "
302 "corrupted surrogate pair\n"));
303 r = idn_invalid_encoding;
304 goto ret;
305 }
306 *utf32p++ = COMBINE_SURROGATE(v0, v1);
307 tolen--;
308 utf16 += 2;
309
310 } else {
311 *utf32p++ = v0;
312 tolen--;
313 utf16++;
314
315 }
316 }
317
318 if (tolen < 1) {
319 r = idn_buffer_overflow;
320 goto ret;
321 }
322 *utf32p = '\0';
323
324 ret:
325 if (r == idn_success) {
326 TRACE(("idn__utf32_fromutf16(): success (utf32=\"%s\")\n",
327 idn__debug_utf32xstring(utf32)));
328 } else {
329 TRACE(("idn__utf32_fromutf16(): %s\n",
330 idn_result_tostring(r)));
331 }
332 return (r);
333 }
334
335 /*
336 * Convert a multibyte UTF-8 sequence to an UTF-32 character.
337 */
338 idn_result_t
idn__utf32_fromutf8(const char * utf8,unsigned long * utf32,size_t tolen)339 idn__utf32_fromutf8(const char *utf8, unsigned long *utf32, size_t tolen) {
340 idn_result_t r = idn_success;
341 const unsigned char *utf8p = (const unsigned char *)utf8;
342 unsigned long *utf32p = utf32;
343 unsigned long v, min;
344 unsigned char c;
345 int width;
346 int i;
347
348 TRACE(("idn__utf32_fromutf8(utf8=\"%s\", tolen=%d)\n",
349 idn__debug_xstring(utf8), (int)tolen));
350
351 while(*utf8p != '\0') {
352 c = *utf8p++;
353 if (c < 0x80) {
354 v = c;
355 min = 0;
356 width = 1;
357 } else if (c < 0xc0) {
358 WARNING(("idn__utf32_fromutf8: invalid character\n"));
359 r = idn_invalid_encoding;
360 goto ret;
361 } else if (c < 0xe0) {
362 v = c & 0x1f;
363 min = 0x80;
364 width = 2;
365 } else if (c < 0xf0) {
366 v = c & 0x0f;
367 min = 0x800;
368 width = 3;
369 } else if (c < 0xf8) {
370 v = c & 0x07;
371 min = 0x10000;
372 width = 4;
373 } else if (c < 0xfc) {
374 v = c & 0x03;
375 min = 0x200000;
376 width = 5;
377 } else if (c < 0xfe) {
378 v = c & 0x01;
379 min = 0x4000000;
380 width = 6;
381 } else {
382 WARNING(("idn__utf32_fromutf8: invalid character\n"));
383 r = idn_invalid_encoding;
384 goto ret;
385 }
386
387 for (i = width - 1; i > 0; i--) {
388 c = *utf8p++;
389 if (c < 0x80 || 0xc0 <= c) {
390 WARNING(("idn__utf32_fromutf8: "
391 "invalid character\n"));
392 r = idn_invalid_encoding;
393 goto ret;
394 }
395 v = (v << 6) | (c & 0x3f);
396 }
397
398 if (v < min || v > UTF32_MAX) {
399 WARNING(("idn__utf32_fromutf8: invalid character\n"));
400 r = idn_invalid_encoding;
401 goto ret;
402 }
403 if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
404 WARNING(("idn__utf32_fromutf8: UTF-8 string contains "
405 "surrogate pair\n"));
406 r = idn_invalid_encoding;
407 goto ret;
408 }
409 if (tolen < 1) {
410 r = idn_buffer_overflow;
411 goto ret;
412 }
413 tolen--;
414 *utf32p++ = v;
415 }
416
417 if (tolen < 1) {
418 r = idn_buffer_overflow;
419 goto ret;
420 }
421 *utf32p = '\0';
422
423 ret:
424 if (r == idn_success) {
425 TRACE(("idn__utf32_fromutf8(): success (utf32=\"%s\")\n",
426 idn__debug_utf32xstring(utf32)));
427 } else {
428 TRACE(("idn__utf32_fromutf8(): %s\n",
429 idn_result_tostring(r)));
430 }
431 return (r);
432 }
433
434 /*
435 * Convert an UTF-32 character to a multibyte UTF-8 sequence.
436 */
437 idn_result_t
idn__utf32_toutf8(const unsigned long * utf32,char * utf8,size_t tolen)438 idn__utf32_toutf8(const unsigned long *utf32, char *utf8, size_t tolen) {
439 idn_result_t r = idn_success;
440 unsigned char *utf8p = (unsigned char *)utf8;
441 unsigned long v;
442 int width;
443 int mask;
444 int offset;
445
446 TRACE(("idn__utf32_toutf8(utf32=\"%s\", tolen=%d)\n",
447 idn__debug_utf32xstring(utf32), (int)tolen));
448
449 while (*utf32 != '\0') {
450 v = *utf32++;
451 if (IS_SURROGATE_LOW(v) || IS_SURROGATE_HIGH(v)) {
452 WARNING(("idn__utf32_toutf8: UTF-32 string contains "
453 "surrogate pair\n"));
454 r = idn_invalid_encoding;
455 goto ret;
456 }
457 if (v < 0x80) {
458 mask = 0;
459 width = 1;
460 } else if (v < 0x800) {
461 mask = 0xc0;
462 width = 2;
463 } else if (v < 0x10000) {
464 mask = 0xe0;
465 width = 3;
466 } else if (v < 0x200000) {
467 mask = 0xf0;
468 width = 4;
469 } else if (v < 0x4000000) {
470 mask = 0xf8;
471 width = 5;
472 } else if (v < 0x80000000) {
473 mask = 0xfc;
474 width = 6;
475 } else {
476 WARNING(("idn__utf32_toutf8: invalid character\n"));
477 r = idn_invalid_encoding;
478 goto ret;
479 }
480
481 if (tolen < width) {
482 r = idn_buffer_overflow;
483 goto ret;
484 }
485 offset = 6 * (width - 1);
486 *utf8p++ = (v >> offset) | mask;
487 mask = 0x80;
488 while (offset > 0) {
489 offset -= 6;
490 *utf8p++ = ((v >> offset) & 0x3f) | mask;
491 }
492 tolen -= width;
493 }
494
495 if (tolen < 1) {
496 r = idn_buffer_overflow;
497 goto ret;
498 }
499 *utf8p = '\0';
500
501 ret:
502 if (r == idn_success) {
503 TRACE(("idn__utf32_toutf8(): success (utf8=\"%s\")\n",
504 idn__debug_xstring(utf8)));
505 } else {
506 TRACE(("idn__utf32_toutf8(): %s\n",
507 idn_result_tostring(r)));
508 }
509 return (r);
510 }
511
512 /*
513 * UTF-32 string version of strlen().
514 * It returns the number of characters in a string.
515 */
516 size_t
idn__utf32_strlen(const unsigned long * utf32)517 idn__utf32_strlen(const unsigned long *utf32) {
518 size_t len;
519
520 for (len = 0; *utf32 != '\0'; utf32++, len++)
521 /* nothing to do */ ;
522
523 return (len);
524 }
525
526 /*
527 * UTF-32 string version of strnlen().
528 * It returns the number of characters in a string, but at most 'n'.
529 */
530 size_t
idn__utf32_strnlen(const unsigned long * utf32,size_t n)531 idn__utf32_strnlen(const unsigned long *utf32, size_t n) {
532 size_t len;
533
534 for (len = 0; n > 0 && *utf32 != '\0'; n--, utf32++, len++)
535 /* nothing to do */ ;
536
537 return (len);
538 }
539
540
541 /*
542 * UTF-32 string version of strchr().
543 */
544 unsigned long *
idn__utf32_strchr(const unsigned long * s,unsigned long c)545 idn__utf32_strchr(const unsigned long *s, unsigned long c) {
546 unsigned long *p = (unsigned long *)s;
547
548 for (;;) {
549 if (*p == c)
550 return (p);
551 if (*p == '\0')
552 return (NULL);
553 p++;
554 }
555
556 return (NULL); /* not reached */
557 }
558
559 /*
560 * UTF-32 string version of strrchr().
561 */
562 unsigned long *
idn__utf32_strrchr(const unsigned long * s,unsigned long c)563 idn__utf32_strrchr(const unsigned long *s, unsigned long c) {
564 unsigned long *p = (unsigned long *)s;
565 unsigned long *result = NULL;
566
567 for (;;) {
568 if (*p == c)
569 result = p;
570 if (*p == '\0')
571 return (result);
572 p++;
573 }
574
575 return (NULL); /* not reached */
576 }
577
578 /*
579 * UTF-32 string version of strcpy().
580 */
581 idn_result_t
idn__utf32_strcpy(unsigned long * to,size_t tolen,const unsigned long * from)582 idn__utf32_strcpy(unsigned long *to, size_t tolen, const unsigned long *from) {
583 while (*from != '\0') {
584 if (tolen <= 0)
585 return (idn_buffer_overflow);
586 *to++ = *from++;
587 tolen--;
588 }
589
590 if (tolen <= 0)
591 return (idn_buffer_overflow);
592 *to = '\0';
593
594 return (idn_success);
595 }
596
597 /*
598 * UTF-32 string version of strncpy().
599 */
600 idn_result_t
idn__utf32_strncpy(unsigned long * to,size_t tolen,const unsigned long * from,size_t n)601 idn__utf32_strncpy(unsigned long *to, size_t tolen,
602 const unsigned long *from, size_t n) {
603 while (n > 0 && *from != '\0') {
604 if (tolen <= 0)
605 return (idn_buffer_overflow);
606 *to++ = *from++;
607 tolen--;
608 n--;
609 }
610
611 if (tolen <= 0)
612 return (idn_buffer_overflow);
613 *to = '\0';
614
615 return (idn_success);
616 }
617
618 /*
619 * UTF-32 string version of strcat().
620 */
621 idn_result_t
idn__utf32_strcat(unsigned long * to,size_t tolen,const unsigned long * from)622 idn__utf32_strcat(unsigned long *to, size_t tolen, const unsigned long *from) {
623 while (*to != '\0') {
624 if (tolen <= 0)
625 return (idn_buffer_overflow);
626 to++;
627 tolen--;
628 }
629
630 while (*from != '\0') {
631 if (tolen <= 0)
632 return (idn_buffer_overflow);
633 *to++ = *from++;
634 tolen--;
635 }
636
637 if (tolen <= 0)
638 return (idn_buffer_overflow);
639 *to = '\0';
640
641 return (idn_success);
642 }
643
644 /*
645 * UTF-32 string version of strncat().
646 */
647 idn_result_t
idn__utf32_strncat(unsigned long * to,size_t tolen,const unsigned long * from,size_t n)648 idn__utf32_strncat(unsigned long *to, size_t tolen,
649 const unsigned long *from, size_t n) {
650 while (*to != '\0') {
651 if (tolen <= 0)
652 return (idn_buffer_overflow);
653 to++;
654 tolen--;
655 }
656
657 while (n > 0 && *from != '\0') {
658 if (tolen <= 0)
659 return (idn_buffer_overflow);
660 *to++ = *from++;
661 tolen--;
662 n--;
663 }
664
665 if (tolen <= 0)
666 return (idn_buffer_overflow);
667 *to = '\0';
668
669 return (idn_success);
670 }
671
672 /*
673 * UTF-32 string version of strcmp().
674 */
675 int
idn__utf32_strcmp(const unsigned long * str1,const unsigned long * str2)676 idn__utf32_strcmp(const unsigned long *str1, const unsigned long *str2) {
677 while (*str1 != '\0') {
678 if (*str1 > *str2)
679 return (1);
680 else if (*str1 < *str2)
681 return (-1);
682 str1++;
683 str2++;
684 }
685
686 if (*str1 > *str2)
687 return (1);
688 else if (*str1 < *str2)
689 return (-1);
690
691 return (0);
692 }
693
694 /*
695 * UTF-32 string version of strncmp().
696 */
697 int
idn__utf32_strncmp(const unsigned long * str1,const unsigned long * str2,size_t n)698 idn__utf32_strncmp(const unsigned long *str1, const unsigned long *str2,
699 size_t n) {
700 while (n > 0 && *str1 != '\0') {
701 if (*str1 > *str2)
702 return (1);
703 else if (*str1 < *str2)
704 return (-1);
705 str1++;
706 str2++;
707 n--;
708 }
709
710 if (n > 0) {
711 if (*str1 > *str2)
712 return (1);
713 else if (*str1 < *str2)
714 return (-1);
715 }
716
717 return (0);
718 }
719
720 /*
721 * UTF-32 string version of strcasecmp().
722 */
723 int
idn__utf32_strcasecmp(const unsigned long * str1,const unsigned long * str2)724 idn__utf32_strcasecmp(const unsigned long *str1, const unsigned long *str2) {
725 unsigned long c1, c2;
726
727 while (*str1 != '\0') {
728 c1 = ASCII_TOLOWER(*str1);
729 c2 = ASCII_TOLOWER(*str2);
730 if (c1 > c2)
731 return (1);
732 else if (c1 < c2)
733 return (-1);
734 str1++;
735 str2++;
736 }
737
738 c1 = ASCII_TOLOWER(*str1);
739 c2 = ASCII_TOLOWER(*str2);
740 if (c1 > c2)
741 return (1);
742 else if (c1 < c2)
743 return (-1);
744
745 return (0);
746 }
747
748 /*
749 * UTF-32 string version of strncasecmp().
750 */
751 int
idn__utf32_strncasecmp(const unsigned long * str1,const unsigned long * str2,size_t n)752 idn__utf32_strncasecmp(const unsigned long *str1, const unsigned long *str2,
753 size_t n) {
754 unsigned long c1, c2;
755
756 while (n > 0 && *str1 != '\0') {
757 c1 = ASCII_TOLOWER(*str1);
758 c2 = ASCII_TOLOWER(*str2);
759 if (c1 > c2)
760 return (1);
761 else if (c1 < c2)
762 return (-1);
763 str1++;
764 str2++;
765 n--;
766 }
767
768 if (n > 0) {
769 c1 = ASCII_TOLOWER(*str1);
770 c2 = ASCII_TOLOWER(*str2);
771 if (c1 > c2)
772 return (1);
773 else if (c1 < c2)
774 return (-1);
775 }
776
777 return (0);
778 }
779
780 /*
781 * UTF-32 string version of strdup().
782 */
783 unsigned long *
idn__utf32_strdup(const unsigned long * str)784 idn__utf32_strdup(const unsigned long *str) {
785 size_t length = idn__utf32_strlen(str);
786 unsigned long *dupstr;
787
788 dupstr = (unsigned long *)malloc(sizeof(*str) * (length + 1));
789 if (dupstr == NULL)
790 return (NULL);
791 memcpy(dupstr, str, sizeof(*str) * (length + 1));
792
793 return (dupstr);
794 }
795
796 /*
797 * UTF-32 string version of strndup().
798 */
799 unsigned long *
idn__utf32_strndup(const unsigned long * str,size_t n)800 idn__utf32_strndup(const unsigned long *str, size_t n) {
801 size_t length = idn__utf32_strnlen(str, n);
802 unsigned long *dupstr;
803
804 dupstr = (unsigned long *)malloc(sizeof(*str) * (length + 1));
805 if (dupstr == NULL)
806 return (NULL);
807 memcpy(dupstr, str, sizeof(*str) * (length + 1));
808 *(dupstr + length) = '\0';
809
810 return (dupstr);
811 }
812
813 /*
814 * Convert ASCII uppercase letters ('A'..'Z') in 's' to lowercase.
815 */
816 void
idn__utf32_asclower(unsigned long * s)817 idn__utf32_asclower(unsigned long *s) {
818 unsigned long *p;
819
820 for (p = s; *p != '\0'; p++) {
821 if ('A' <= *p && *p <= 'Z')
822 *p += 'a' - 'A';
823 }
824 }
825
826