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 mbrtoc16() 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	size_t len;
49	char16_t c16;
50
51	/*
52	 * C/POSIX locale.
53	 */
54
55	printf("1..1\n");
56
57	/* Null wide character, internal state. */
58	assert(mbrtoc16(&c16, "", 1, NULL) == 0);
59	assert(c16 == 0);
60
61	/* Null wide character. */
62	memset(&s, 0, sizeof(s));
63	assert(mbrtoc16(&c16, "", 1, &s) == 0);
64	assert(c16 == 0);
65
66	/* Latin letter A, internal state. */
67	assert(mbrtoc16(NULL, 0, 0, NULL) == 0);
68	assert(mbrtoc16(&c16, "A", 1, NULL) == 1);
69	assert(c16 == L'A');
70
71	/* Latin letter A. */
72	memset(&s, 0, sizeof(s));
73	assert(mbrtoc16(&c16, "A", 1, &s) == 1);
74	assert(c16 == L'A');
75
76	/* Incomplete character sequence. */
77	c16 = L'z';
78	memset(&s, 0, sizeof(s));
79	assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
80	assert(c16 == L'z');
81
82	/* Check that mbrtoc16() doesn't access the buffer when n == 0. */
83	c16 = L'z';
84	memset(&s, 0, sizeof(s));
85	assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
86	assert(c16 == L'z');
87
88	/* Check that mbrtoc16() doesn't read ahead too aggressively. */
89	memset(&s, 0, sizeof(s));
90	assert(mbrtoc16(&c16, "AB", 2, &s) == 1);
91	assert(c16 == L'A');
92	assert(mbrtoc16(&c16, "C", 1, &s) == 1);
93	assert(c16 == L'C');
94
95	/*
96	 * ISO-8859-1.
97	 */
98
99	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-1"),
100	    "en_US.ISO8859-1") == 0);
101
102	/* Currency sign. */
103	memset(&s, 0, sizeof(s));
104	assert(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
105	assert(c16 == 0xa4);
106
107	/*
108	 * ISO-8859-15.
109	 */
110
111	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-15"),
112	    "en_US.ISO8859-15") == 0);
113
114	/* Euro sign. */
115	memset(&s, 0, sizeof(s));
116	assert(mbrtoc16(&c16, "\xa4", 1, &s) == 1);
117	assert(c16 == 0x20ac);
118
119	/*
120	 * UTF-8.
121	 */
122
123	assert(strcmp(setlocale(LC_CTYPE, "en_US.UTF-8"), "en_US.UTF-8") == 0);
124
125	/* Null wide character, internal state. */
126	assert(mbrtoc16(NULL, 0, 0, NULL) == 0);
127	assert(mbrtoc16(&c16, "", 1, NULL) == 0);
128	assert(c16 == 0);
129
130	/* Null wide character. */
131	memset(&s, 0, sizeof(s));
132	assert(mbrtoc16(&c16, "", 1, &s) == 0);
133	assert(c16 == 0);
134
135	/* Latin letter A, internal state. */
136	assert(mbrtoc16(NULL, 0, 0, NULL) == 0);
137	assert(mbrtoc16(&c16, "A", 1, NULL) == 1);
138	assert(c16 == L'A');
139
140	/* Latin letter A. */
141	memset(&s, 0, sizeof(s));
142	assert(mbrtoc16(&c16, "A", 1, &s) == 1);
143	assert(c16 == L'A');
144
145	/* Incomplete character sequence (zero length). */
146	c16 = L'z';
147	memset(&s, 0, sizeof(s));
148	assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2);
149	assert(c16 == L'z');
150
151	/* Incomplete character sequence (truncated double-byte). */
152	memset(&s, 0, sizeof(s));
153	c16 = 0;
154	assert(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
155
156	/* Same as above, but complete. */
157	memset(&s, 0, sizeof(s));
158	c16 = 0;
159	assert(mbrtoc16(&c16, "\xc3\x84", 2, &s) == 2);
160	assert(c16 == 0xc4);
161
162	/* Test restarting behaviour. */
163	memset(&s, 0, sizeof(s));
164	c16 = 0;
165	assert(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2);
166	assert(c16 == 0);
167	assert(mbrtoc16(&c16, "\xb7", 1, &s) == 1);
168	assert(c16 == 0xf7);
169
170	/* Surrogate pair. */
171	memset(&s, 0, sizeof(s));
172	c16 = 0;
173	assert(mbrtoc16(&c16, "\xf0\x9f\x92\xa9", 4, &s) == 4);
174	assert(c16 == 0xd83d);
175	assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-3);
176	assert(c16 == 0xdca9);
177
178	/* Letter e with acute, precomposed. */
179	memset(&s, 0, sizeof(s));
180	c16 = 0;
181	assert(mbrtoc16(&c16, "\xc3\xa9", 2, &s) == 2);
182	assert(c16 == 0xe9);
183
184	/* Letter e with acute, combined. */
185	memset(&s, 0, sizeof(s));
186	c16 = 0;
187	assert(mbrtoc16(&c16, "\x65\xcc\x81", 3, &s) == 1);
188	assert(c16 == 0x65);
189	assert(mbrtoc16(&c16, "\xcc\x81", 2, &s) == 2);
190	assert(c16 == 0x301);
191
192	printf("ok 1 - mbrtoc16()\n");
193
194	return (0);
195}
196