1250883Sed/*-
2250883Sed * Copyright (c) 2002 Tim J. Robbins
3250883Sed * All rights reserved.
4250883Sed *
5250883Sed * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org>
6250883Sed * All rights reserved.
7250883Sed *
8250883Sed * Redistribution and use in source and binary forms, with or without
9250883Sed * modification, are permitted provided that the following conditions
10250883Sed * are met:
11250883Sed * 1. Redistributions of source code must retain the above copyright
12250883Sed *    notice, this list of conditions and the following disclaimer.
13250883Sed * 2. Redistributions in binary form must reproduce the above copyright
14250883Sed *    notice, this list of conditions and the following disclaimer in the
15250883Sed *    documentation and/or other materials provided with the distribution.
16250883Sed *
17250883Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18250883Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19250883Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20250883Sed * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21250883Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22250883Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23250883Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24250883Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25250883Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26250883Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27250883Sed * SUCH DAMAGE.
28250883Sed */
29250883Sed/*
30250883Sed * Test program for c16rtomb() as specified by ISO/IEC 9899:2011.
31250883Sed */
32250883Sed
33250883Sed#include <sys/cdefs.h>
34250883Sed__FBSDID("$FreeBSD$");
35250883Sed
36250883Sed#include <assert.h>
37250883Sed#include <errno.h>
38250883Sed#include <limits.h>
39250883Sed#include <locale.h>
40250883Sed#include <stdio.h>
41250883Sed#include <string.h>
42250883Sed#include <uchar.h>
43250883Sed
44250883Sedint
45250883Sedmain(int argc, char *argv[])
46250883Sed{
47250883Sed	mbstate_t s;
48250883Sed	char buf[MB_LEN_MAX + 1];
49250883Sed
50250883Sed	/*
51250883Sed	 * C/POSIX locale.
52250883Sed	 */
53250883Sed
54250883Sed	printf("1..1\n");
55250883Sed
56250883Sed	/*
57250883Sed	 * If the buffer argument is NULL, c16 is implicitly 0,
58250883Sed	 * c16rtomb() resets its internal state.
59250883Sed	 */
60250883Sed	assert(c16rtomb(NULL, L'\0', NULL) == 1);
61250883Sed	assert(c16rtomb(NULL, 0xdc00, NULL) == 1);
62250883Sed
63250883Sed	/* Null wide character. */
64250883Sed	memset(&s, 0, sizeof(s));
65250883Sed	memset(buf, 0xcc, sizeof(buf));
66250883Sed	assert(c16rtomb(buf, 0, &s) == 1);
67250883Sed	assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc);
68250883Sed
69250883Sed	/* Latin letter A, internal state. */
70250883Sed	assert(c16rtomb(NULL, L'\0', NULL) == 1);
71250883Sed	assert(c16rtomb(NULL, L'A', NULL) == 1);
72250883Sed
73250883Sed	/* Latin letter A. */
74250883Sed	memset(&s, 0, sizeof(s));
75250883Sed	memset(buf, 0xcc, sizeof(buf));
76250883Sed	assert(c16rtomb(buf, L'A', &s) == 1);
77250883Sed	assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc);
78250883Sed
79250883Sed	/* Unicode character 'Pile of poo'. */
80250883Sed	memset(&s, 0, sizeof(s));
81250883Sed	memset(buf, 0xcc, sizeof(buf));
82250883Sed	assert(c16rtomb(buf, 0xd83d, &s) == 0);
83250883Sed	assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
84250883Sed	assert(errno == EILSEQ);
85251314Sed	assert((unsigned char)buf[0] == 0xcc);
86250883Sed
87250883Sed	/*
88251314Sed	 * ISO8859-1.
89251314Sed	 */
90251314Sed
91251314Sed	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-1"),
92251314Sed	    "en_US.ISO8859-1") == 0);
93251314Sed
94251314Sed	/* Unicode character 'Euro sign'. */
95251314Sed	memset(&s, 0, sizeof(s));
96251314Sed	memset(buf, 0xcc, sizeof(buf));
97251314Sed	assert(c16rtomb(buf, 0x20ac, &s) == (size_t)-1);
98251314Sed	assert(errno == EILSEQ);
99251314Sed	assert((unsigned char)buf[0] == 0xcc);
100251314Sed
101251314Sed	/*
102251314Sed	 * ISO8859-15.
103251314Sed	 */
104251314Sed
105251314Sed	assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-15"),
106251314Sed	    "en_US.ISO8859-15") == 0);
107251314Sed
108251314Sed	/* Unicode character 'Euro sign'. */
109251314Sed	memset(&s, 0, sizeof(s));
110251314Sed	memset(buf, 0xcc, sizeof(buf));
111251314Sed	assert(c16rtomb(buf, 0x20ac, &s) == 1);
112251314Sed	assert((unsigned char)buf[0] == 0xa4 && (unsigned char)buf[1] == 0xcc);
113251314Sed
114251314Sed	/*
115250883Sed	 * UTF-8.
116250883Sed	 */
117250883Sed
118250883Sed	assert(strcmp(setlocale(LC_CTYPE, "en_US.UTF-8"), "en_US.UTF-8") == 0);
119250883Sed
120250883Sed	/* Unicode character 'Pile of poo'. */
121250883Sed	memset(&s, 0, sizeof(s));
122250883Sed	memset(buf, 0xcc, sizeof(buf));
123250883Sed	assert(c16rtomb(buf, 0xd83d, &s) == 0);
124250883Sed	assert(c16rtomb(buf, 0xdca9, &s) == 4);
125250883Sed	assert((unsigned char)buf[0] == 0xf0 && (unsigned char)buf[1] == 0x9f &&
126250883Sed	    (unsigned char)buf[2] == 0x92 && (unsigned char)buf[3] == 0xa9 &&
127250883Sed	    (unsigned char)buf[4] == 0xcc);
128250883Sed
129250883Sed	/* Invalid code; 'Pile of poo' without the trail surrogate. */
130250883Sed	memset(&s, 0, sizeof(s));
131250883Sed	memset(buf, 0xcc, sizeof(buf));
132250883Sed	assert(c16rtomb(buf, 0xd83d, &s) == 0);
133250883Sed	assert(c16rtomb(buf, L'A', &s) == (size_t)-1);
134250883Sed	assert(errno == EILSEQ);
135251314Sed	assert((unsigned char)buf[0] == 0xcc);
136250883Sed
137250883Sed	/* Invalid code; 'Pile of poo' without the lead surrogate. */
138250883Sed	memset(&s, 0, sizeof(s));
139250883Sed	memset(buf, 0xcc, sizeof(buf));
140250883Sed	assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1);
141250883Sed	assert(errno == EILSEQ);
142251314Sed	assert((unsigned char)buf[0] == 0xcc);
143250883Sed
144250883Sed	printf("ok 1 - c16rtomb()\n");
145250883Sed}
146