xref: /minix3/external/bsd/bind/dist/contrib/idn/idnkit-1.0-src/lib/ucsset.c (revision 00b67f09dd46474d133c95011a48590a8e8f94c7)
1*00b67f09SDavid van Moolenbroek /*	$NetBSD: ucsset.c,v 1.4 2014/12/10 04:37:55 christos Exp $	*/
2*00b67f09SDavid van Moolenbroek 
3*00b67f09SDavid van Moolenbroek #ifndef lint
4*00b67f09SDavid van Moolenbroek static char *rcsid = "Id: ucsset.c,v 1.1 2003/06/04 00:26:15 marka Exp ";
5*00b67f09SDavid van Moolenbroek #endif
6*00b67f09SDavid van Moolenbroek 
7*00b67f09SDavid van Moolenbroek /*
8*00b67f09SDavid van Moolenbroek  * Copyright (c) 2001 Japan Network Information Center.  All rights reserved.
9*00b67f09SDavid van Moolenbroek  *
10*00b67f09SDavid van Moolenbroek  * By using this file, you agree to the terms and conditions set forth bellow.
11*00b67f09SDavid van Moolenbroek  *
12*00b67f09SDavid van Moolenbroek  * 			LICENSE TERMS AND CONDITIONS
13*00b67f09SDavid van Moolenbroek  *
14*00b67f09SDavid van Moolenbroek  * The following License Terms and Conditions apply, unless a different
15*00b67f09SDavid van Moolenbroek  * license is obtained from Japan Network Information Center ("JPNIC"),
16*00b67f09SDavid van Moolenbroek  * a Japanese association, Kokusai-Kougyou-Kanda Bldg 6F, 2-3-4 Uchi-Kanda,
17*00b67f09SDavid van Moolenbroek  * Chiyoda-ku, Tokyo 101-0047, Japan.
18*00b67f09SDavid van Moolenbroek  *
19*00b67f09SDavid van Moolenbroek  * 1. Use, Modification and Redistribution (including distribution of any
20*00b67f09SDavid van Moolenbroek  *    modified or derived work) in source and/or binary forms is permitted
21*00b67f09SDavid van Moolenbroek  *    under this License Terms and Conditions.
22*00b67f09SDavid van Moolenbroek  *
23*00b67f09SDavid van Moolenbroek  * 2. Redistribution of source code must retain the copyright notices as they
24*00b67f09SDavid van Moolenbroek  *    appear in each source code file, this License Terms and Conditions.
25*00b67f09SDavid van Moolenbroek  *
26*00b67f09SDavid van Moolenbroek  * 3. Redistribution in binary form must reproduce the Copyright Notice,
27*00b67f09SDavid van Moolenbroek  *    this License Terms and Conditions, in the documentation and/or other
28*00b67f09SDavid van Moolenbroek  *    materials provided with the distribution.  For the purposes of binary
29*00b67f09SDavid van Moolenbroek  *    distribution the "Copyright Notice" refers to the following language:
30*00b67f09SDavid van Moolenbroek  *    "Copyright (c) 2000-2002 Japan Network Information Center.  All rights reserved."
31*00b67f09SDavid van Moolenbroek  *
32*00b67f09SDavid van Moolenbroek  * 4. The name of JPNIC may not be used to endorse or promote products
33*00b67f09SDavid van Moolenbroek  *    derived from this Software without specific prior written approval of
34*00b67f09SDavid van Moolenbroek  *    JPNIC.
35*00b67f09SDavid van Moolenbroek  *
36*00b67f09SDavid van Moolenbroek  * 5. Disclaimer/Limitation of Liability: THIS SOFTWARE IS PROVIDED BY JPNIC
37*00b67f09SDavid van Moolenbroek  *    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
38*00b67f09SDavid van Moolenbroek  *    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
39*00b67f09SDavid van Moolenbroek  *    PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL JPNIC BE LIABLE
40*00b67f09SDavid van Moolenbroek  *    FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41*00b67f09SDavid van Moolenbroek  *    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42*00b67f09SDavid van Moolenbroek  *    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43*00b67f09SDavid van Moolenbroek  *    BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44*00b67f09SDavid van Moolenbroek  *    WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
45*00b67f09SDavid van Moolenbroek  *    OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
46*00b67f09SDavid van Moolenbroek  *    ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
47*00b67f09SDavid van Moolenbroek  */
48*00b67f09SDavid van Moolenbroek 
49*00b67f09SDavid van Moolenbroek #include <config.h>
50*00b67f09SDavid van Moolenbroek 
51*00b67f09SDavid van Moolenbroek #include <stdlib.h>
52*00b67f09SDavid van Moolenbroek #include <stdio.h>
53*00b67f09SDavid van Moolenbroek #include <string.h>
54*00b67f09SDavid van Moolenbroek 
55*00b67f09SDavid van Moolenbroek #include <idn/result.h>
56*00b67f09SDavid van Moolenbroek #include <idn/assert.h>
57*00b67f09SDavid van Moolenbroek #include <idn/logmacro.h>
58*00b67f09SDavid van Moolenbroek #include <idn/ucsset.h>
59*00b67f09SDavid van Moolenbroek 
60*00b67f09SDavid van Moolenbroek #define UCS_MAX		0x80000000UL
61*00b67f09SDavid van Moolenbroek 
62*00b67f09SDavid van Moolenbroek #define INIT_SIZE	50
63*00b67f09SDavid van Moolenbroek 
64*00b67f09SDavid van Moolenbroek /*
65*00b67f09SDavid van Moolenbroek  * Code point range.
66*00b67f09SDavid van Moolenbroek  *
67*00b67f09SDavid van Moolenbroek  * The set of code points is represented by an array of code point ranges.
68*00b67f09SDavid van Moolenbroek  * In the building phase, specified ranges by 'idn_ucsset_add' or
69*00b67f09SDavid van Moolenbroek  * 'idn_ucsset_addrange' are simply appended to the array.
70*00b67f09SDavid van Moolenbroek  * And 'idn_ucsset_fix' sorts the array by the code point value, and also
71*00b67f09SDavid van Moolenbroek  * merges any intersecting ranges.  Since the array is sorted, a binary
72*00b67f09SDavid van Moolenbroek  * search can be used for looking up.
73*00b67f09SDavid van Moolenbroek  */
74*00b67f09SDavid van Moolenbroek typedef struct {
75*00b67f09SDavid van Moolenbroek 	unsigned long from;
76*00b67f09SDavid van Moolenbroek 	unsigned long to;
77*00b67f09SDavid van Moolenbroek } range_t;
78*00b67f09SDavid van Moolenbroek 
79*00b67f09SDavid van Moolenbroek /*
80*00b67f09SDavid van Moolenbroek  * Code point segment.
81*00b67f09SDavid van Moolenbroek  *
82*00b67f09SDavid van Moolenbroek  * To speed up searching further, the entire region of UCS-4 code points
83*00b67f09SDavid van Moolenbroek  * (U+0000 - U+7FFFFFFF) are divided into segments. For each segment,
84*00b67f09SDavid van Moolenbroek  * the first and last element of the range array corresponding to the
85*00b67f09SDavid van Moolenbroek  * segment are computed by 'idn_ucsset_fix'.  This narrows down the
86*00b67f09SDavid van Moolenbroek  * (initial) search range.
87*00b67f09SDavid van Moolenbroek  */
88*00b67f09SDavid van Moolenbroek typedef struct {
89*00b67f09SDavid van Moolenbroek 	int range_start;	/* index of ucsset.ranges */
90*00b67f09SDavid van Moolenbroek 	int range_end;		/* ditto */
91*00b67f09SDavid van Moolenbroek } segment_t;
92*00b67f09SDavid van Moolenbroek 
93*00b67f09SDavid van Moolenbroek /*
94*00b67f09SDavid van Moolenbroek  * Code point to segment index conversion.
95*00b67f09SDavid van Moolenbroek  *
96*00b67f09SDavid van Moolenbroek  * Below is the function that maps a code point to the corresponding segment.
97*00b67f09SDavid van Moolenbroek  * The mapping is non-uniform, so that BMP, the following 16 planes that
98*00b67f09SDavid van Moolenbroek  * comprise Unicode code points together with BMP, and other planes
99*00b67f09SDavid van Moolenbroek  * have different granularity.
100*00b67f09SDavid van Moolenbroek  */
101*00b67f09SDavid van Moolenbroek #define SEG_THLD1	0x10000		/* BMP */
102*00b67f09SDavid van Moolenbroek #define SEG_THLD2	0x110000	/* Unicode (BMP+16planes) */
103*00b67f09SDavid van Moolenbroek #define SEG_SFT1	10		/* BMP: 1K code points/segment */
104*00b67f09SDavid van Moolenbroek #define SEG_SFT2	14		/* following 16 planes: 16K cp/seg */
105*00b67f09SDavid van Moolenbroek #define SEG_SFT3	24		/* rest: 16M cp/seg */
106*00b67f09SDavid van Moolenbroek #define SEG_OFF1	(SEG_THLD1 >> SEG_SFT1)
107*00b67f09SDavid van Moolenbroek #define SEG_OFF2	(((SEG_THLD2 - SEG_THLD1) >> SEG_SFT2) + SEG_OFF1)
108*00b67f09SDavid van Moolenbroek #define SEG_INDEX(v) \
109*00b67f09SDavid van Moolenbroek 	(((v) < SEG_THLD1) ? ((v) >> SEG_SFT1) : \
110*00b67f09SDavid van Moolenbroek 	 ((v) < SEG_THLD2) ? ((((v) - SEG_THLD1) >> SEG_SFT2) + SEG_OFF1) : \
111*00b67f09SDavid van Moolenbroek 	 ((((v) - SEG_THLD2) >> SEG_SFT3) + SEG_OFF2))
112*00b67f09SDavid van Moolenbroek #define SEG_LEN	(SEG_INDEX(UCS_MAX - 1) + 1)
113*00b67f09SDavid van Moolenbroek 
114*00b67f09SDavid van Moolenbroek /*
115*00b67f09SDavid van Moolenbroek  * Representation of set of UCS code points.
116*00b67f09SDavid van Moolenbroek  */
117*00b67f09SDavid van Moolenbroek typedef struct idn_ucsset {
118*00b67f09SDavid van Moolenbroek 	segment_t segments[SEG_LEN];
119*00b67f09SDavid van Moolenbroek 	int fixed;
120*00b67f09SDavid van Moolenbroek 	int size;			/* allocated size of 'ranges' */
121*00b67f09SDavid van Moolenbroek 	int nranges;			/* num of ranges */
122*00b67f09SDavid van Moolenbroek 	range_t *ranges;
123*00b67f09SDavid van Moolenbroek 	int refcnt;			/* reference count */
124*00b67f09SDavid van Moolenbroek } ucsset;
125*00b67f09SDavid van Moolenbroek 
126*00b67f09SDavid van Moolenbroek static idn_result_t	addrange(idn_ucsset_t ctx, unsigned long from,
127*00b67f09SDavid van Moolenbroek 				 unsigned long to, char *func_name);
128*00b67f09SDavid van Moolenbroek static int		comp_range(const void *v1, const void *v2);
129*00b67f09SDavid van Moolenbroek 
130*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsset_create(idn_ucsset_t * ctx)131*00b67f09SDavid van Moolenbroek idn_ucsset_create(idn_ucsset_t *ctx) {
132*00b67f09SDavid van Moolenbroek 	idn_ucsset_t bm;
133*00b67f09SDavid van Moolenbroek 
134*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL);
135*00b67f09SDavid van Moolenbroek 
136*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_create()\n"));
137*00b67f09SDavid van Moolenbroek 
138*00b67f09SDavid van Moolenbroek 	if ((bm = malloc(sizeof(ucsset))) == NULL) {
139*00b67f09SDavid van Moolenbroek 		WARNING(("idn_ucsset_create: malloc failed\n"));
140*00b67f09SDavid van Moolenbroek 		return idn_nomemory;
141*00b67f09SDavid van Moolenbroek 	}
142*00b67f09SDavid van Moolenbroek 	bm->size = bm->nranges = 0;
143*00b67f09SDavid van Moolenbroek 	bm->ranges = NULL;
144*00b67f09SDavid van Moolenbroek 	bm->fixed = 0;
145*00b67f09SDavid van Moolenbroek 	bm->refcnt = 1;
146*00b67f09SDavid van Moolenbroek 	*ctx = bm;
147*00b67f09SDavid van Moolenbroek 	return (idn_success);
148*00b67f09SDavid van Moolenbroek }
149*00b67f09SDavid van Moolenbroek 
150*00b67f09SDavid van Moolenbroek void
idn_ucsset_destroy(idn_ucsset_t ctx)151*00b67f09SDavid van Moolenbroek idn_ucsset_destroy(idn_ucsset_t ctx) {
152*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0);
153*00b67f09SDavid van Moolenbroek 
154*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_destroy()\n"));
155*00b67f09SDavid van Moolenbroek 
156*00b67f09SDavid van Moolenbroek 	if (--ctx->refcnt == 0) {
157*00b67f09SDavid van Moolenbroek 		if (ctx->ranges != NULL)
158*00b67f09SDavid van Moolenbroek 			free(ctx->ranges);
159*00b67f09SDavid van Moolenbroek 		free(ctx);
160*00b67f09SDavid van Moolenbroek 	}
161*00b67f09SDavid van Moolenbroek }
162*00b67f09SDavid van Moolenbroek 
163*00b67f09SDavid van Moolenbroek void
idn_ucsset_incrref(idn_ucsset_t ctx)164*00b67f09SDavid van Moolenbroek idn_ucsset_incrref(idn_ucsset_t ctx) {
165*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0);
166*00b67f09SDavid van Moolenbroek 
167*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_incrref()\n"));
168*00b67f09SDavid van Moolenbroek 
169*00b67f09SDavid van Moolenbroek 	ctx->refcnt++;
170*00b67f09SDavid van Moolenbroek }
171*00b67f09SDavid van Moolenbroek 
172*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsset_add(idn_ucsset_t ctx,unsigned long v)173*00b67f09SDavid van Moolenbroek idn_ucsset_add(idn_ucsset_t ctx, unsigned long v) {
174*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0);
175*00b67f09SDavid van Moolenbroek 
176*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_add(v=U+%lX)\n", v));
177*00b67f09SDavid van Moolenbroek 
178*00b67f09SDavid van Moolenbroek 	return (addrange(ctx, v, v, "idn_ucsset_add"));
179*00b67f09SDavid van Moolenbroek }
180*00b67f09SDavid van Moolenbroek 
181*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsset_addrange(idn_ucsset_t ctx,unsigned long from,unsigned long to)182*00b67f09SDavid van Moolenbroek idn_ucsset_addrange(idn_ucsset_t ctx, unsigned long from,
183*00b67f09SDavid van Moolenbroek 			 unsigned long to)
184*00b67f09SDavid van Moolenbroek {
185*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0);
186*00b67f09SDavid van Moolenbroek 
187*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_addrange(from=U+%lX, to=U+%lX)\n",
188*00b67f09SDavid van Moolenbroek 	       from, to));
189*00b67f09SDavid van Moolenbroek 
190*00b67f09SDavid van Moolenbroek 	return (addrange(ctx, from, to, "idn_ucsset_addrange"));
191*00b67f09SDavid van Moolenbroek }
192*00b67f09SDavid van Moolenbroek 
193*00b67f09SDavid van Moolenbroek void
idn_ucsset_fix(idn_ucsset_t ctx)194*00b67f09SDavid van Moolenbroek idn_ucsset_fix(idn_ucsset_t ctx) {
195*00b67f09SDavid van Moolenbroek 	int nranges;
196*00b67f09SDavid van Moolenbroek 	range_t *ranges;
197*00b67f09SDavid van Moolenbroek 	segment_t *segments;
198*00b67f09SDavid van Moolenbroek 	int i, j;
199*00b67f09SDavid van Moolenbroek 
200*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0);
201*00b67f09SDavid van Moolenbroek 
202*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_fix()\n"));
203*00b67f09SDavid van Moolenbroek 
204*00b67f09SDavid van Moolenbroek 	nranges = ctx->nranges;
205*00b67f09SDavid van Moolenbroek 	ranges = ctx->ranges;
206*00b67f09SDavid van Moolenbroek 	segments = ctx->segments;
207*00b67f09SDavid van Moolenbroek 
208*00b67f09SDavid van Moolenbroek 	if (ctx->fixed)
209*00b67f09SDavid van Moolenbroek 		return;
210*00b67f09SDavid van Moolenbroek 
211*00b67f09SDavid van Moolenbroek 	ctx->fixed = 1;
212*00b67f09SDavid van Moolenbroek 
213*00b67f09SDavid van Moolenbroek 	/* Initialize segment array */
214*00b67f09SDavid van Moolenbroek 	for (i = 0; i < SEG_LEN; i++) {
215*00b67f09SDavid van Moolenbroek 		segments[i].range_start = -1;
216*00b67f09SDavid van Moolenbroek 		segments[i].range_end = -1;
217*00b67f09SDavid van Moolenbroek 	}
218*00b67f09SDavid van Moolenbroek 
219*00b67f09SDavid van Moolenbroek 	/* If the set is empty, there's nothing to be done. */
220*00b67f09SDavid van Moolenbroek 	if (nranges == 0)
221*00b67f09SDavid van Moolenbroek 		return;
222*00b67f09SDavid van Moolenbroek 
223*00b67f09SDavid van Moolenbroek 	/* Sort ranges. */
224*00b67f09SDavid van Moolenbroek 	qsort(ranges, nranges, sizeof(range_t), comp_range);
225*00b67f09SDavid van Moolenbroek 
226*00b67f09SDavid van Moolenbroek 	/* Merge overlapped/continuous ranges. */
227*00b67f09SDavid van Moolenbroek 	for (i = 0, j = 1; j < nranges; j++) {
228*00b67f09SDavid van Moolenbroek 		if (ranges[i].to + 1 >= ranges[j].from) {
229*00b67f09SDavid van Moolenbroek 			/* can be merged */
230*00b67f09SDavid van Moolenbroek 			if (ranges[i].to < ranges[j].to) {
231*00b67f09SDavid van Moolenbroek 				ranges[i].to = ranges[j].to;
232*00b67f09SDavid van Moolenbroek 			}
233*00b67f09SDavid van Moolenbroek 		} else {
234*00b67f09SDavid van Moolenbroek 			i++;
235*00b67f09SDavid van Moolenbroek 			if (i < j)
236*00b67f09SDavid van Moolenbroek 				ranges[i] = ranges[j];
237*00b67f09SDavid van Moolenbroek 		}
238*00b67f09SDavid van Moolenbroek 	}
239*00b67f09SDavid van Moolenbroek 	/* 'i' points the last range in the array. */
240*00b67f09SDavid van Moolenbroek 	ctx->nranges = nranges = ++i;
241*00b67f09SDavid van Moolenbroek 
242*00b67f09SDavid van Moolenbroek 	/* Create segment array. */
243*00b67f09SDavid van Moolenbroek 	for (i = 0; i < nranges; i++) {
244*00b67f09SDavid van Moolenbroek 		int fidx = SEG_INDEX(ranges[i].from);
245*00b67f09SDavid van Moolenbroek 		int tidx = SEG_INDEX(ranges[i].to);
246*00b67f09SDavid van Moolenbroek 
247*00b67f09SDavid van Moolenbroek 		for (j = fidx; j <= tidx; j++) {
248*00b67f09SDavid van Moolenbroek 			if (segments[j].range_start < 0)
249*00b67f09SDavid van Moolenbroek 				segments[j].range_start = i;
250*00b67f09SDavid van Moolenbroek 			segments[j].range_end = i;
251*00b67f09SDavid van Moolenbroek 		}
252*00b67f09SDavid van Moolenbroek 	}
253*00b67f09SDavid van Moolenbroek 
254*00b67f09SDavid van Moolenbroek #if 0
255*00b67f09SDavid van Moolenbroek 	/*
256*00b67f09SDavid van Moolenbroek 	 * Does the standard guarantee realloc() always succeeds
257*00b67f09SDavid van Moolenbroek 	 * when shrinking?
258*00b67f09SDavid van Moolenbroek 	 */
259*00b67f09SDavid van Moolenbroek 	/* Shrink malloc'ed space if possible. */
260*00b67f09SDavid van Moolenbroek 	ctx->ranges = realloc(ctx->ranges, ctx->nranges * sizeof(range_t));
261*00b67f09SDavid van Moolenbroek #endif
262*00b67f09SDavid van Moolenbroek }
263*00b67f09SDavid van Moolenbroek 
264*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsset_lookup(idn_ucsset_t ctx,unsigned long v,int * found)265*00b67f09SDavid van Moolenbroek idn_ucsset_lookup(idn_ucsset_t ctx, unsigned long v, int *found) {
266*00b67f09SDavid van Moolenbroek 	int idx;
267*00b67f09SDavid van Moolenbroek 	segment_t *segments;
268*00b67f09SDavid van Moolenbroek 
269*00b67f09SDavid van Moolenbroek 	assert(ctx != NULL && ctx->refcnt > 0 && found != NULL);
270*00b67f09SDavid van Moolenbroek 
271*00b67f09SDavid van Moolenbroek 	TRACE(("idn_ucsset_lookup(v=U+%lX)\n", v));
272*00b67f09SDavid van Moolenbroek 
273*00b67f09SDavid van Moolenbroek 	/* Make sure it is fixed. */
274*00b67f09SDavid van Moolenbroek 	if (!ctx->fixed) {
275*00b67f09SDavid van Moolenbroek 		WARNING(("idn_ucsset_lookup: not fixed yet\n"));
276*00b67f09SDavid van Moolenbroek 		return (idn_failure);
277*00b67f09SDavid van Moolenbroek 	}
278*00b67f09SDavid van Moolenbroek 
279*00b67f09SDavid van Moolenbroek 	/* Check the given code point. */
280*00b67f09SDavid van Moolenbroek 	if (v >= UCS_MAX)
281*00b67f09SDavid van Moolenbroek 		return (idn_invalid_codepoint);
282*00b67f09SDavid van Moolenbroek 
283*00b67f09SDavid van Moolenbroek 	/* Get the segment 'v' belongs to. */
284*00b67f09SDavid van Moolenbroek 	segments = ctx->segments;
285*00b67f09SDavid van Moolenbroek 	idx = SEG_INDEX(v);
286*00b67f09SDavid van Moolenbroek 
287*00b67f09SDavid van Moolenbroek 	/* Do binary search. */
288*00b67f09SDavid van Moolenbroek 	*found = 0;
289*00b67f09SDavid van Moolenbroek 	if (segments[idx].range_start >= 0) {
290*00b67f09SDavid van Moolenbroek 		int lo = segments[idx].range_start;
291*00b67f09SDavid van Moolenbroek 		int hi = segments[idx].range_end;
292*00b67f09SDavid van Moolenbroek 		range_t *ranges = ctx->ranges;
293*00b67f09SDavid van Moolenbroek 
294*00b67f09SDavid van Moolenbroek 		while (lo <= hi) {
295*00b67f09SDavid van Moolenbroek 			int mid = (lo + hi) / 2;
296*00b67f09SDavid van Moolenbroek 			if (v < ranges[mid].from) {
297*00b67f09SDavid van Moolenbroek 				hi = mid - 1;
298*00b67f09SDavid van Moolenbroek 			} else if (v > ranges[mid].to) {
299*00b67f09SDavid van Moolenbroek 				lo = mid + 1;
300*00b67f09SDavid van Moolenbroek 			} else {
301*00b67f09SDavid van Moolenbroek 				*found = 1;
302*00b67f09SDavid van Moolenbroek 				break;
303*00b67f09SDavid van Moolenbroek 			}
304*00b67f09SDavid van Moolenbroek 		}
305*00b67f09SDavid van Moolenbroek 	}
306*00b67f09SDavid van Moolenbroek 	return (idn_success);
307*00b67f09SDavid van Moolenbroek }
308*00b67f09SDavid van Moolenbroek 
309*00b67f09SDavid van Moolenbroek static idn_result_t
addrange(idn_ucsset_t ctx,unsigned long from,unsigned long to,char * func_name)310*00b67f09SDavid van Moolenbroek addrange(idn_ucsset_t ctx, unsigned long from, unsigned long to,
311*00b67f09SDavid van Moolenbroek 	 char *func_name)
312*00b67f09SDavid van Moolenbroek {
313*00b67f09SDavid van Moolenbroek 	range_t *newbuf;
314*00b67f09SDavid van Moolenbroek 
315*00b67f09SDavid van Moolenbroek 	/* Check the given code points. */
316*00b67f09SDavid van Moolenbroek 	if (from > UCS_MAX) {
317*00b67f09SDavid van Moolenbroek 		WARNING(("%s: code point out of range (U+%lX)\n",
318*00b67f09SDavid van Moolenbroek 			 func_name, from));
319*00b67f09SDavid van Moolenbroek 		return (idn_invalid_codepoint);
320*00b67f09SDavid van Moolenbroek 	} else if (to > UCS_MAX) {
321*00b67f09SDavid van Moolenbroek 		WARNING(("%s: code point out of range (U+%lX)\n",
322*00b67f09SDavid van Moolenbroek 			 func_name, to));
323*00b67f09SDavid van Moolenbroek 		return (idn_invalid_codepoint);
324*00b67f09SDavid van Moolenbroek 	} else if (from > to) {
325*00b67f09SDavid van Moolenbroek 		WARNING(("%s: invalid range spec (U+%lX-U+%lX)\n",
326*00b67f09SDavid van Moolenbroek 			 func_name, from, to));
327*00b67f09SDavid van Moolenbroek 		return (idn_invalid_codepoint);
328*00b67f09SDavid van Moolenbroek 	}
329*00b67f09SDavid van Moolenbroek 
330*00b67f09SDavid van Moolenbroek 	/* Make sure it is not fixed yet. */
331*00b67f09SDavid van Moolenbroek 	if (ctx->fixed) {
332*00b67f09SDavid van Moolenbroek 		WARNING(("%s: attempt to add to already fixed object\n",
333*00b67f09SDavid van Moolenbroek 			 func_name));
334*00b67f09SDavid van Moolenbroek 		return (idn_failure);
335*00b67f09SDavid van Moolenbroek 	}
336*00b67f09SDavid van Moolenbroek 
337*00b67f09SDavid van Moolenbroek 	/* Append the specified range to the 'ranges' array. */
338*00b67f09SDavid van Moolenbroek 	if (ctx->nranges >= ctx->size) {
339*00b67f09SDavid van Moolenbroek 		/* Make it bigger. */
340*00b67f09SDavid van Moolenbroek 		if (ctx->size == 0)
341*00b67f09SDavid van Moolenbroek 			ctx->size = INIT_SIZE;
342*00b67f09SDavid van Moolenbroek 		else
343*00b67f09SDavid van Moolenbroek 			ctx->size *= 2;
344*00b67f09SDavid van Moolenbroek 		newbuf = realloc(ctx->ranges, ctx->size * sizeof(range_t));
345*00b67f09SDavid van Moolenbroek 		if (newbuf == NULL)
346*00b67f09SDavid van Moolenbroek 			return (idn_nomemory);
347*00b67f09SDavid van Moolenbroek 		ctx->ranges = newbuf;
348*00b67f09SDavid van Moolenbroek 	}
349*00b67f09SDavid van Moolenbroek 	ctx->ranges[ctx->nranges].from = from;
350*00b67f09SDavid van Moolenbroek 	ctx->ranges[ctx->nranges].to = to;
351*00b67f09SDavid van Moolenbroek 	ctx->nranges++;
352*00b67f09SDavid van Moolenbroek 
353*00b67f09SDavid van Moolenbroek 	return (idn_success);
354*00b67f09SDavid van Moolenbroek }
355*00b67f09SDavid van Moolenbroek 
356*00b67f09SDavid van Moolenbroek static int
comp_range(const void * v1,const void * v2)357*00b67f09SDavid van Moolenbroek comp_range(const void *v1, const void *v2) {
358*00b67f09SDavid van Moolenbroek 	/*
359*00b67f09SDavid van Moolenbroek 	 * Range comparation function suitable for qsort().
360*00b67f09SDavid van Moolenbroek 	 */
361*00b67f09SDavid van Moolenbroek 	const range_t *r1 = v1;
362*00b67f09SDavid van Moolenbroek 	const range_t *r2 = v2;
363*00b67f09SDavid van Moolenbroek 
364*00b67f09SDavid van Moolenbroek 	if (r1->from < r2->from)
365*00b67f09SDavid van Moolenbroek 		return (-1);
366*00b67f09SDavid van Moolenbroek 	else if (r1->from > r2->from)
367*00b67f09SDavid van Moolenbroek 		return (1);
368*00b67f09SDavid van Moolenbroek 	else
369*00b67f09SDavid van Moolenbroek 		return (0);
370*00b67f09SDavid van Moolenbroek }
371