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