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