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