1/*-
2 * Copyright (c) 2002 Tim J. Robbins
3 * All rights reserved.
4 *
5 * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org>
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29/*
30 * Test program for c16rtomb() as specified by ISO/IEC 9899:2011.
31 */
32
33#include <sys/cdefs.h>
34__FBSDID("$FreeBSD$");
35
36#include <assert.h>
37#include <errno.h>
38#include <limits.h>
39#include <locale.h>
40#include <stdio.h>
41#include <string.h>
42#include <uchar.h>
43
44int
45main(int argc, char *argv[])
46{
47	mbstate_t s;
48	char buf[MB_LEN_MAX + 1];
49
50	/*
51	 * C/POSIX locale.
52	 */
53
54	printf("1..1\n");
55
56	/*
57	 * If the buffer argument is NULL, c16 is implicitly 0,
58	 * c16rtomb() resets its internal state.
59	 */
60	assert(c16rtomb(NULL, L'\0', NULL) == 1);
61	assert(c16rtomb(NULL, 0xdc00, NULL) == 1);
62
63	/* Null wide character. */
64	memset(&s, 0, sizeof(s));
65	memset(buf, 0xcc, sizeof(buf));
66	assert(c16rtomb(buf, 0, &s) == 1);
67	assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
68
69	/* Latin letter A, internal state. */
70	assert(c16rtomb(NULL, L'\0', NULL) == 1);
71	assert(c16rtomb(NULL, L'A', NULL) == 1);
72
73	/* Latin letter A. */
74	memset(&s, 0, sizeof(s));
75	memset(buf, 0xcc, sizeof(buf));
76	assert(c16rtomb(buf, L'A', &s) == 1);
77	assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
78
79	/* Unicode character 'Pile of poo'. */
80	memset(&s, 0, sizeof(s));
81	memset(buf, 0xcc, sizeof(buf));
82	assert(c16rtomb(buf, 0xd83d, &s) == 0);
83	assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
84	assert(errno == EILSEQ);
85	assert((unsigned char)buf[0] == 0xcc);
86
87	/*
88	 * ISO8859-1.
89	 */
90
91	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-1"),
92	    "en_US.ISO8859-1") == 0);
93
94	/* Unicode character 'Euro sign'. */
95	memset(&s, 0, sizeof(s));
96	memset(buf, 0xcc, sizeof(buf));
97	assert(c16rtomb(buf, 0x20ac, &s) == (size_t)-1);
98	assert(errno == EILSEQ);
99	assert((unsigned char)buf[0] == 0xcc);
100
101	/*
102	 * ISO8859-15.
103	 */
104
105	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-15"),
106	    "en_US.ISO8859-15") == 0);
107
108	/* Unicode character 'Euro sign'. */
109	memset(&s, 0, sizeof(s));
110	memset(buf, 0xcc, sizeof(buf));
111	assert(c16rtomb(buf, 0x20ac, &s) == 1);
112	assert((unsigned char)buf[0] == 0xa4 && (unsigned char)buf[1] == 0xcc);
113
114	/*
115	 * UTF-8.
116	 */
117
118	assert(strcmp(setlocale(LC_CTYPE, "en_US.UTF-8"), "en_US.UTF-8") == 0);
119
120	/* Unicode character 'Pile of poo'. */
121	memset(&s, 0, sizeof(s));
122	memset(buf, 0xcc, sizeof(buf));
123	assert(c16rtomb(buf, 0xd83d, &s) == 0);
124	assert(c16rtomb(buf, 0xdca9, &s) == 4);
125	assert((unsigned char)buf[0] == 0xf0 && (unsigned char)buf[1] == 0x9f &&
126	    (unsigned char)buf[2] == 0x92 && (unsigned char)buf[3] == 0xa9 &&
127	    (unsigned char)buf[4] == 0xcc);
128
129	/* Invalid code; 'Pile of poo' without the trail surrogate. */
130	memset(&s, 0, sizeof(s));
131	memset(buf, 0xcc, sizeof(buf));
132	assert(c16rtomb(buf, 0xd83d, &s) == 0);
133	assert(c16rtomb(buf, L'A', &s) == (size_t)-1);
134	assert(errno == EILSEQ);
135	assert((unsigned char)buf[0] == 0xcc);
136
137	/* Invalid code; 'Pile of poo' without the lead surrogate. */
138	memset(&s, 0, sizeof(s));
139	memset(buf, 0xcc, sizeof(buf));
140	assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
141	assert(errno == EILSEQ);
142	assert((unsigned char)buf[0] == 0xcc);
143
144	printf("ok 1 - c16rtomb()\n");
145}
146