1/* $NetBSD: iswctype_mb.c,v 1.10 2010/06/12 05:54:05 tnozaki Exp $ */
2
3/*-
4 * Copyright (c)2008 Citrus Project,
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30#if defined(LIBC_SCCS) && !defined(lint)
31__RCSID("$NetBSD: iswctype_mb.c,v 1.10 2010/06/12 05:54:05 tnozaki Exp $");
32#endif /* LIBC_SCCS and not lint */
33
34#include "namespace.h"
35#include <sys/types.h>
36#include <assert.h>
37#include <errno.h>
38#define __SETLOCALE_SOURCE__
39#include <locale.h>
40#include <string.h>
41#include <wchar.h>
42#include <wctype.h>
43
44#include "setlocale_local.h"
45
46#include "runetype_local.h"
47#include "_wctype_local.h"
48#include "_wctrans_local.h"
49
50#define _RUNE_LOCALE() ((_RuneLocale const *) \
51    (*_current_locale())->part_impl[(size_t)LC_CTYPE])
52
53#define _ISWCTYPE_FUNC(name, index)			\
54int							\
55isw##name(wint_t wc)					\
56{							\
57	_RuneLocale const *rl;				\
58	_WCTypeEntry const *te;				\
59							\
60	rl = _RUNE_LOCALE();				\
61	te = &rl->rl_wctype[index];			\
62	return _iswctype_priv(rl, wc, te);		\
63}
64_ISWCTYPE_FUNC(alnum,  _WCTYPE_INDEX_ALNUM)
65_ISWCTYPE_FUNC(alpha,  _WCTYPE_INDEX_ALPHA)
66_ISWCTYPE_FUNC(blank,  _WCTYPE_INDEX_BLANK)
67_ISWCTYPE_FUNC(cntrl,  _WCTYPE_INDEX_CNTRL)
68_ISWCTYPE_FUNC(digit,  _WCTYPE_INDEX_DIGIT)
69_ISWCTYPE_FUNC(graph,  _WCTYPE_INDEX_GRAPH)
70_ISWCTYPE_FUNC(lower,  _WCTYPE_INDEX_LOWER)
71_ISWCTYPE_FUNC(print,  _WCTYPE_INDEX_PRINT)
72_ISWCTYPE_FUNC(punct,  _WCTYPE_INDEX_PUNCT)
73_ISWCTYPE_FUNC(space,  _WCTYPE_INDEX_SPACE)
74_ISWCTYPE_FUNC(upper,  _WCTYPE_INDEX_UPPER)
75_ISWCTYPE_FUNC(xdigit, _WCTYPE_INDEX_XDIGIT)
76
77#define _TOWCTRANS_FUNC(name, index)			\
78wint_t							\
79tow##name(wint_t wc)					\
80{							\
81	_RuneLocale const *rl;				\
82	_WCTransEntry const *te;			\
83							\
84	rl = _RUNE_LOCALE();				\
85	te = &rl->rl_wctrans[index];			\
86	return _towctrans_priv(wc, te);			\
87}
88_TOWCTRANS_FUNC(upper, _WCTRANS_INDEX_UPPER)
89_TOWCTRANS_FUNC(lower, _WCTRANS_INDEX_LOWER)
90
91wctype_t
92wctype(const char *charclass)
93{
94	_RuneLocale const *rl;
95	size_t i;
96
97	rl = _RUNE_LOCALE();
98	for (i = 0; i < _WCTYPE_NINDEXES; ++i) {
99		if (!strcmp(rl->rl_wctype[i].te_name, charclass))
100			return (wctype_t)__UNCONST(&rl->rl_wctype[i]);
101	}
102	return (wctype_t)NULL;
103}
104
105wctrans_t
106wctrans(const char *charmap)
107{
108	_RuneLocale const *rl;
109	size_t i;
110
111	rl = _RUNE_LOCALE();
112	for (i = 0; i < _WCTRANS_NINDEXES; ++i) {
113		_DIAGASSERT(rl->rl_wctrans[i].te_name != NULL);
114		if (!strcmp(rl->rl_wctrans[i].te_name, charmap))
115			return (wctrans_t)__UNCONST(&rl->rl_wctype[i]);
116	}
117	return (wctrans_t)NULL;
118}
119
120int
121iswctype(wint_t wc, wctype_t charclass)
122{
123	_RuneLocale const *rl;
124	_WCTypeEntry const *te;
125
126	if (charclass == NULL) {
127		errno = EINVAL;
128		return 0;
129	}
130	rl = _RUNE_LOCALE();
131	te = (_WCTypeEntry const *)(void *)charclass;
132	return _iswctype_priv(rl, wc, te);
133}
134
135wint_t
136towctrans(wint_t wc, wctrans_t charmap)
137{
138	_WCTransEntry const *te;
139
140	if (charmap == NULL) {
141		errno = EINVAL;
142		return wc;
143	}
144	te = (_WCTransEntry const *)(void *)charmap;
145	return _towctrans_priv(wc, te);
146}
147
148__weak_alias(wcwidth,_wcwidth)
149
150int
151wcwidth(wchar_t wc)
152{
153	_RuneLocale const *rl;
154	_RuneType x;
155
156	if (wc == L'\0')
157		return 0;
158	rl = _RUNE_LOCALE();
159	x = _runetype_priv(rl, wc);
160	if (x & _RUNETYPE_R)
161		return ((unsigned)x & _RUNETYPE_SWM) >> _RUNETYPE_SWS;
162	return -1;
163}
164
165int
166wcswidth(const wchar_t * __restrict ws, size_t wn)
167{
168	_RuneLocale const *rl;
169	_RuneType x;
170	int width;
171
172	_DIAGASSERT(ws != NULL);
173
174	rl = _RUNE_LOCALE();
175	width = 0;
176	while (wn > 0 && *ws != L'\0') {
177		x = _runetype_priv(rl, *ws);
178		if ((x & _RUNETYPE_R) == 0)
179			return -1;
180		width += ((unsigned)x & _RUNETYPE_SWM) >> _RUNETYPE_SWS;
181		++ws, --wn;
182	}
183	return width;
184}
185