1 /*
2  * Copyright 2013 Garrett D'Amore <garrett@damore.org>
3  * Copyright (c) 2004 Tim J. Robbins.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27 
28 #include "lint.h"
29 #include "runetype.h"
30 #include <wchar.h>
31 #include <wctype.h>
32 #include "localeimpl.h"
33 
34 /*
35  * nextwctype, while exposed on *BSD/MacOS X, is considered "consolidation
36  * private" for illumos.  Hence, we keep the _l version static for now.
37  * If we decide to make this public, just remove the static keyword and
38  * put it in the headers and mapfile.  (Should fix up the underscore prefix
39  * to __nextwctype() as well.)
40  */
41 static wint_t
nextwctype_l(wint_t wc,wctype_t wct,locale_t loc)42 nextwctype_l(wint_t wc, wctype_t wct, locale_t loc)
43 {
44 	size_t lim;
45 	const _RuneLocale *rl;
46 	const _RuneRange *rr;
47 	const _RuneEntry *base, *re;
48 	int noinc;
49 
50 	rl = loc->runelocale;
51 	rr = &rl->__runetype_ext;
52 
53 	noinc = 0;
54 	if (wc < _CACHED_RUNES) {
55 		wc++;
56 		while (wc < _CACHED_RUNES) {
57 			if (rl->__runetype[wc] & wct)
58 				return (wc);
59 			wc++;
60 		}
61 		wc--;
62 	}
63 	if (rr->__ranges != NULL && wc < rr->__ranges[0].__min) {
64 		wc = rr->__ranges[0].__min;
65 		noinc = 1;
66 	}
67 
68 	/* Binary search -- see bsearch.c for explanation. */
69 	base = rr->__ranges;
70 	for (lim = rr->__nranges; lim != 0; lim >>= 1) {
71 		re = base + (lim >> 1);
72 		if (re->__min <= wc && wc <= re->__max)
73 			goto found;
74 		else if (wc > re->__max) {
75 			base = re + 1;
76 			lim--;
77 		}
78 	}
79 	return (-1);
80 found:
81 	if (!noinc)
82 		wc++;
83 	if (re->__min <= wc && wc <= re->__max) {
84 		if (re->__types != NULL) {
85 			for (; wc <= re->__max; wc++)
86 				if (re->__types[wc - re->__min] & wct)
87 					return (wc);
88 		} else if (re->__map & wct)
89 			return (wc);
90 	}
91 	while (++re < rr->__ranges + rr->__nranges) {
92 		wc = re->__min;
93 		if (re->__types != NULL) {
94 			for (; wc <= re->__max; wc++)
95 				if (re->__types[wc - re->__min] & wct)
96 					return (wc);
97 		} else if (re->__map & wct)
98 			return (wc);
99 	}
100 	return (-1);
101 }
102 
103 /*
104  * External, but consolidation private routine.
105  */
106 wint_t
__nextwctype(wint_t wc,wctype_t wct)107 __nextwctype(wint_t wc, wctype_t wct)
108 {
109 	return (nextwctype_l(wc, wct, uselocale(NULL)));
110 }
111