locales, libconv: Sync with FreeBSD (extensive reach)
[dragonfly.git] / lib / libc / locale / nextwctype.c
1 /*-
2  * Copyright (c) 2004 Tim J. Robbins.
3  * All rights reserved.
4  *
5  * Copyright (c) 2011 The FreeBSD Foundation
6  * All rights reserved.
7  * Portions of this software were developed by David Chisnall
8  * under sponsorship from the FreeBSD Foundation.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  *
31  * $FreeBSD: head/lib/libc/locale/nextwctype.c 227753 2011-11-20 14:45:42Z theraven $
32  */
33
34
35 #include <runetype.h>
36 #include <wchar.h>
37 #include <wctype.h>
38 #include "mblocal.h"
39
40 wint_t
41 nextwctype_l(wint_t wc, wctype_t wct, locale_t locale)
42 {
43         size_t lim;
44         FIX_LOCALE(locale);
45         _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes;
46         _RuneRange *rr = &runes->__runetype_ext;
47         _RuneEntry *base, *re;
48         int noinc;
49
50         noinc = 0;
51         if (wc < _CACHED_RUNES) {
52                 wc++;
53                 while (wc < _CACHED_RUNES) {
54                         if (runes->__runetype[wc] & wct)
55                                 return (wc);
56                         wc++;
57                 }
58                 wc--;
59         }
60         if (rr->__ranges != NULL && wc < rr->__ranges[0].__min) {
61                 wc = rr->__ranges[0].__min;
62                 noinc = 1;
63         }
64
65         /* Binary search -- see bsearch.c for explanation. */
66         base = rr->__ranges;
67         for (lim = rr->__nranges; lim != 0; lim >>= 1) {
68                 re = base + (lim >> 1);
69                 if (re->__min <= wc && wc <= re->__max)
70                         goto found;
71                 else if (wc > re->__max) {
72                         base = re + 1;
73                         lim--;
74                 }
75         }
76         return (-1);
77 found:
78         if (!noinc)
79                 wc++;
80         if (re->__min <= wc && wc <= re->__max) {
81                 if (re->__types != NULL) {
82                         for (; wc <= re->__max; wc++)
83                                 if (re->__types[wc - re->__min] & wct)
84                                         return (wc);
85                 } else if (re->__map & wct)
86                         return (wc);
87         }
88         while (++re < rr->__ranges + rr->__nranges) {
89                 wc = re->__min;
90                 if (re->__types != NULL) {
91                         for (; wc <= re->__max; wc++)
92                                 if (re->__types[wc - re->__min] & wct)
93                                         return (wc);
94                 } else if (re->__map & wct)
95                         return (wc);
96         }
97         return (-1);
98 }
99 wint_t
100 nextwctype(wint_t wc, wctype_t wct)
101 {
102         return nextwctype_l(wc, wct, __get_locale());
103 }