1*00b67f09SDavid van Moolenbroek /* $NetBSD: ucsmap.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: ucsmap.c,v 1.1 2003/06/04 00:26:14 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 <string.h>
53*00b67f09SDavid van Moolenbroek
54*00b67f09SDavid van Moolenbroek #include <idn/result.h>
55*00b67f09SDavid van Moolenbroek #include <idn/assert.h>
56*00b67f09SDavid van Moolenbroek #include <idn/log.h>
57*00b67f09SDavid van Moolenbroek #include <idn/logmacro.h>
58*00b67f09SDavid van Moolenbroek #include <idn/ucsmap.h>
59*00b67f09SDavid van Moolenbroek
60*00b67f09SDavid van Moolenbroek #define INIT_SIZE 50
61*00b67f09SDavid van Moolenbroek #define DEFAULT_BUF_SIZE 500
62*00b67f09SDavid van Moolenbroek #define UCSMAP_HASH_SIZE 103
63*00b67f09SDavid van Moolenbroek #define MAX_MAPLEN 0xffff
64*00b67f09SDavid van Moolenbroek
65*00b67f09SDavid van Moolenbroek /*
66*00b67f09SDavid van Moolenbroek * This module implements UCS 1-to-N mapping.
67*00b67f09SDavid van Moolenbroek * To speed up mapping table lookup, a combination of hash and
68*00b67f09SDavid van Moolenbroek * binary search is used.
69*00b67f09SDavid van Moolenbroek */
70*00b67f09SDavid van Moolenbroek
71*00b67f09SDavid van Moolenbroek /*
72*00b67f09SDavid van Moolenbroek * Mapping entry.
73*00b67f09SDavid van Moolenbroek * Entries are sorted by its hash index and code point.
74*00b67f09SDavid van Moolenbroek */
75*00b67f09SDavid van Moolenbroek typedef struct {
76*00b67f09SDavid van Moolenbroek short hidx; /* hash index */
77*00b67f09SDavid van Moolenbroek unsigned short len; /* length of mapped sequence */
78*00b67f09SDavid van Moolenbroek unsigned long ucs; /* code point to be mapped */
79*00b67f09SDavid van Moolenbroek unsigned long *map; /* mapped sequence of code points */
80*00b67f09SDavid van Moolenbroek } ucsmap_entry_t;
81*00b67f09SDavid van Moolenbroek
82*00b67f09SDavid van Moolenbroek /*
83*00b67f09SDavid van Moolenbroek * Hash table entry.
84*00b67f09SDavid van Moolenbroek * Since the entries pointed by ucsmap_hash_t.entry are sorted,
85*00b67f09SDavid van Moolenbroek * binary search can be used.
86*00b67f09SDavid van Moolenbroek */
87*00b67f09SDavid van Moolenbroek typedef struct {
88*00b67f09SDavid van Moolenbroek ucsmap_entry_t *entry; /* sorted by code point */
89*00b67f09SDavid van Moolenbroek int n; /* length of 'entry' */
90*00b67f09SDavid van Moolenbroek } ucsmap_hash_t;
91*00b67f09SDavid van Moolenbroek
92*00b67f09SDavid van Moolenbroek /*
93*00b67f09SDavid van Moolenbroek * UCS character buffer for storing target character sequence.
94*00b67f09SDavid van Moolenbroek */
95*00b67f09SDavid van Moolenbroek typedef struct ucsmap_buf {
96*00b67f09SDavid van Moolenbroek struct ucsmap_buf *next;
97*00b67f09SDavid van Moolenbroek unsigned long buf[1]; /* actually a variable length array */
98*00b67f09SDavid van Moolenbroek } ucsmap_buf_t;
99*00b67f09SDavid van Moolenbroek
100*00b67f09SDavid van Moolenbroek /*
101*00b67f09SDavid van Moolenbroek * Mapping object.
102*00b67f09SDavid van Moolenbroek */
103*00b67f09SDavid van Moolenbroek typedef struct idn_ucsmap {
104*00b67f09SDavid van Moolenbroek ucsmap_hash_t hash[UCSMAP_HASH_SIZE];
105*00b67f09SDavid van Moolenbroek ucsmap_entry_t *entries; /* array of entries */
106*00b67f09SDavid van Moolenbroek size_t entry_size; /* allocated size */
107*00b67f09SDavid van Moolenbroek size_t nentries; /* # of entries in use */
108*00b67f09SDavid van Moolenbroek ucsmap_buf_t *mapdata; /* list of character buffers */
109*00b67f09SDavid van Moolenbroek size_t mapdata_size; /* allocated size of current buffer */
110*00b67f09SDavid van Moolenbroek size_t mapdata_used; /* # of chars in use */
111*00b67f09SDavid van Moolenbroek int fixed; /* already fixed? */
112*00b67f09SDavid van Moolenbroek int refcnt; /* reference count */
113*00b67f09SDavid van Moolenbroek } ucsmap_t;
114*00b67f09SDavid van Moolenbroek
115*00b67f09SDavid van Moolenbroek static int ucsmap_hash(unsigned long v);
116*00b67f09SDavid van Moolenbroek static unsigned long *save_mapped_sequence(idn_ucsmap_t ctx,
117*00b67f09SDavid van Moolenbroek unsigned long *map,
118*00b67f09SDavid van Moolenbroek size_t maplen);
119*00b67f09SDavid van Moolenbroek static void free_mapbuf(ucsmap_buf_t *buf);
120*00b67f09SDavid van Moolenbroek static int comp_entry(const void *v1, const void *v2);
121*00b67f09SDavid van Moolenbroek
122*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsmap_create(idn_ucsmap_t * ctxp)123*00b67f09SDavid van Moolenbroek idn_ucsmap_create(idn_ucsmap_t *ctxp) {
124*00b67f09SDavid van Moolenbroek idn_ucsmap_t ctx;
125*00b67f09SDavid van Moolenbroek
126*00b67f09SDavid van Moolenbroek assert(ctxp != NULL);
127*00b67f09SDavid van Moolenbroek
128*00b67f09SDavid van Moolenbroek TRACE(("idn_ucsmap_create()\n"));
129*00b67f09SDavid van Moolenbroek
130*00b67f09SDavid van Moolenbroek if ((ctx = malloc(sizeof(*ctx))) == NULL) {
131*00b67f09SDavid van Moolenbroek WARNING(("idn_ucsmap_create: malloc failed\n"));
132*00b67f09SDavid van Moolenbroek return (idn_nomemory);
133*00b67f09SDavid van Moolenbroek }
134*00b67f09SDavid van Moolenbroek
135*00b67f09SDavid van Moolenbroek ctx->entry_size = 0;
136*00b67f09SDavid van Moolenbroek ctx->nentries = 0;
137*00b67f09SDavid van Moolenbroek ctx->entries = NULL;
138*00b67f09SDavid van Moolenbroek ctx->mapdata = NULL;
139*00b67f09SDavid van Moolenbroek ctx->mapdata_size = 0;
140*00b67f09SDavid van Moolenbroek ctx->mapdata_used = 0;
141*00b67f09SDavid van Moolenbroek ctx->fixed = 0;
142*00b67f09SDavid van Moolenbroek ctx->refcnt = 1;
143*00b67f09SDavid van Moolenbroek *ctxp = ctx;
144*00b67f09SDavid van Moolenbroek return (idn_success);
145*00b67f09SDavid van Moolenbroek }
146*00b67f09SDavid van Moolenbroek
147*00b67f09SDavid van Moolenbroek void
idn_ucsmap_destroy(idn_ucsmap_t ctx)148*00b67f09SDavid van Moolenbroek idn_ucsmap_destroy(idn_ucsmap_t ctx) {
149*00b67f09SDavid van Moolenbroek assert(ctx != NULL && ctx->refcnt > 0);
150*00b67f09SDavid van Moolenbroek
151*00b67f09SDavid van Moolenbroek TRACE(("idn_ucsmap_destroy()\n"));
152*00b67f09SDavid van Moolenbroek
153*00b67f09SDavid van Moolenbroek if (--ctx->refcnt == 0) {
154*00b67f09SDavid van Moolenbroek if (ctx->entries != NULL)
155*00b67f09SDavid van Moolenbroek free(ctx->entries);
156*00b67f09SDavid van Moolenbroek if (ctx->mapdata != NULL)
157*00b67f09SDavid van Moolenbroek free_mapbuf(ctx->mapdata);
158*00b67f09SDavid van Moolenbroek free(ctx);
159*00b67f09SDavid van Moolenbroek }
160*00b67f09SDavid van Moolenbroek }
161*00b67f09SDavid van Moolenbroek
162*00b67f09SDavid van Moolenbroek void
idn_ucsmap_incrref(idn_ucsmap_t ctx)163*00b67f09SDavid van Moolenbroek idn_ucsmap_incrref(idn_ucsmap_t ctx) {
164*00b67f09SDavid van Moolenbroek assert(ctx != NULL && ctx->refcnt > 0);
165*00b67f09SDavid van Moolenbroek
166*00b67f09SDavid van Moolenbroek ctx->refcnt++;
167*00b67f09SDavid van Moolenbroek }
168*00b67f09SDavid van Moolenbroek
169*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsmap_add(idn_ucsmap_t ctx,unsigned long ucs,unsigned long * map,size_t maplen)170*00b67f09SDavid van Moolenbroek idn_ucsmap_add(idn_ucsmap_t ctx, unsigned long ucs,
171*00b67f09SDavid van Moolenbroek unsigned long *map, size_t maplen)
172*00b67f09SDavid van Moolenbroek {
173*00b67f09SDavid van Moolenbroek ucsmap_entry_t *e;
174*00b67f09SDavid van Moolenbroek ucsmap_entry_t *newbuf;
175*00b67f09SDavid van Moolenbroek
176*00b67f09SDavid van Moolenbroek assert(ctx != NULL && ctx->refcnt > 0);
177*00b67f09SDavid van Moolenbroek
178*00b67f09SDavid van Moolenbroek TRACE(("idn_ucsmap_add(ucs=U+%lX, maplen=%u)\n", ucs, maplen));
179*00b67f09SDavid van Moolenbroek
180*00b67f09SDavid van Moolenbroek /* Make sure it is not fixed yet. */
181*00b67f09SDavid van Moolenbroek if (ctx->fixed) {
182*00b67f09SDavid van Moolenbroek WARNING(("idn_ucsmap_add: attempt to add to fixed map\n"));
183*00b67f09SDavid van Moolenbroek return (idn_failure);
184*00b67f09SDavid van Moolenbroek }
185*00b67f09SDavid van Moolenbroek
186*00b67f09SDavid van Moolenbroek if (maplen > MAX_MAPLEN) {
187*00b67f09SDavid van Moolenbroek WARNING(("idn_ucsmap_add: maplen too large (> %d)\n",
188*00b67f09SDavid van Moolenbroek MAX_MAPLEN));
189*00b67f09SDavid van Moolenbroek return (idn_failure);
190*00b67f09SDavid van Moolenbroek }
191*00b67f09SDavid van Moolenbroek
192*00b67f09SDavid van Moolenbroek /* Append an entry. */
193*00b67f09SDavid van Moolenbroek if (ctx->nentries >= ctx->entry_size) {
194*00b67f09SDavid van Moolenbroek if (ctx->entry_size == 0)
195*00b67f09SDavid van Moolenbroek ctx->entry_size = INIT_SIZE;
196*00b67f09SDavid van Moolenbroek else
197*00b67f09SDavid van Moolenbroek ctx->entry_size *= 2;
198*00b67f09SDavid van Moolenbroek newbuf = realloc(ctx->entries, sizeof(*e) * ctx->entry_size);
199*00b67f09SDavid van Moolenbroek if (newbuf == NULL)
200*00b67f09SDavid van Moolenbroek return (idn_nomemory);
201*00b67f09SDavid van Moolenbroek ctx->entries = newbuf;
202*00b67f09SDavid van Moolenbroek }
203*00b67f09SDavid van Moolenbroek e = &ctx->entries[ctx->nentries];
204*00b67f09SDavid van Moolenbroek e->hidx = ucsmap_hash(ucs);
205*00b67f09SDavid van Moolenbroek e->len = maplen;
206*00b67f09SDavid van Moolenbroek e->ucs = ucs;
207*00b67f09SDavid van Moolenbroek if (maplen > 0) {
208*00b67f09SDavid van Moolenbroek /* Save mapped sequence in the buffer. */
209*00b67f09SDavid van Moolenbroek e->map = save_mapped_sequence(ctx, map, maplen);
210*00b67f09SDavid van Moolenbroek if (e->map == NULL)
211*00b67f09SDavid van Moolenbroek return (idn_nomemory);
212*00b67f09SDavid van Moolenbroek } else {
213*00b67f09SDavid van Moolenbroek /*
214*00b67f09SDavid van Moolenbroek * Zero 'maplen' is perfectly valid meaning one-to-zero
215*00b67f09SDavid van Moolenbroek * mapping.
216*00b67f09SDavid van Moolenbroek */
217*00b67f09SDavid van Moolenbroek e->map = NULL;
218*00b67f09SDavid van Moolenbroek }
219*00b67f09SDavid van Moolenbroek ctx->nentries++;
220*00b67f09SDavid van Moolenbroek
221*00b67f09SDavid van Moolenbroek return (idn_success);
222*00b67f09SDavid van Moolenbroek }
223*00b67f09SDavid van Moolenbroek
224*00b67f09SDavid van Moolenbroek void
idn_ucsmap_fix(idn_ucsmap_t ctx)225*00b67f09SDavid van Moolenbroek idn_ucsmap_fix(idn_ucsmap_t ctx) {
226*00b67f09SDavid van Moolenbroek ucsmap_entry_t *e;
227*00b67f09SDavid van Moolenbroek int last_hidx;
228*00b67f09SDavid van Moolenbroek int i;
229*00b67f09SDavid van Moolenbroek
230*00b67f09SDavid van Moolenbroek assert(ctx != NULL && ctx->refcnt > 0);
231*00b67f09SDavid van Moolenbroek
232*00b67f09SDavid van Moolenbroek TRACE(("idn_ucsmap_fix()\n"));
233*00b67f09SDavid van Moolenbroek
234*00b67f09SDavid van Moolenbroek if (ctx->fixed)
235*00b67f09SDavid van Moolenbroek return;
236*00b67f09SDavid van Moolenbroek
237*00b67f09SDavid van Moolenbroek ctx->fixed = 1;
238*00b67f09SDavid van Moolenbroek
239*00b67f09SDavid van Moolenbroek /* Initialize hash. */
240*00b67f09SDavid van Moolenbroek for (i = 0; i < UCSMAP_HASH_SIZE; i++) {
241*00b67f09SDavid van Moolenbroek ctx->hash[i].entry = NULL;
242*00b67f09SDavid van Moolenbroek ctx->hash[i].n = 0;
243*00b67f09SDavid van Moolenbroek }
244*00b67f09SDavid van Moolenbroek
245*00b67f09SDavid van Moolenbroek if (ctx->nentries == 0)
246*00b67f09SDavid van Moolenbroek return;
247*00b67f09SDavid van Moolenbroek
248*00b67f09SDavid van Moolenbroek /* Sort entries by the hash value and code point. */
249*00b67f09SDavid van Moolenbroek qsort(ctx->entries, ctx->nentries, sizeof(ucsmap_entry_t), comp_entry);
250*00b67f09SDavid van Moolenbroek
251*00b67f09SDavid van Moolenbroek /*
252*00b67f09SDavid van Moolenbroek * Now the entries are sorted by their hash value, and
253*00b67f09SDavid van Moolenbroek * sorted by its code point among the ones with the same hash value.
254*00b67f09SDavid van Moolenbroek */
255*00b67f09SDavid van Moolenbroek
256*00b67f09SDavid van Moolenbroek /* Build hash table. */
257*00b67f09SDavid van Moolenbroek last_hidx = -1;
258*00b67f09SDavid van Moolenbroek for (i = 0, e = ctx->entries; i < ctx->nentries; i++, e++) {
259*00b67f09SDavid van Moolenbroek if (e->hidx != last_hidx) {
260*00b67f09SDavid van Moolenbroek ctx->hash[e->hidx].entry = e;
261*00b67f09SDavid van Moolenbroek last_hidx = e->hidx;
262*00b67f09SDavid van Moolenbroek }
263*00b67f09SDavid van Moolenbroek ctx->hash[last_hidx].n++;
264*00b67f09SDavid van Moolenbroek }
265*00b67f09SDavid van Moolenbroek }
266*00b67f09SDavid van Moolenbroek
267*00b67f09SDavid van Moolenbroek idn_result_t
idn_ucsmap_map(idn_ucsmap_t ctx,unsigned long v,unsigned long * to,size_t tolen,size_t * maplenp)268*00b67f09SDavid van Moolenbroek idn_ucsmap_map(idn_ucsmap_t ctx, unsigned long v, unsigned long *to,
269*00b67f09SDavid van Moolenbroek size_t tolen, size_t *maplenp) {
270*00b67f09SDavid van Moolenbroek int hash;
271*00b67f09SDavid van Moolenbroek ucsmap_entry_t *e;
272*00b67f09SDavid van Moolenbroek int n;
273*00b67f09SDavid van Moolenbroek int hi, lo, mid;
274*00b67f09SDavid van Moolenbroek
275*00b67f09SDavid van Moolenbroek assert(ctx != NULL && ctx->refcnt > 0 && to != NULL &&
276*00b67f09SDavid van Moolenbroek maplenp != NULL);
277*00b67f09SDavid van Moolenbroek
278*00b67f09SDavid van Moolenbroek TRACE(("idn_ucsmap_map(v=U+%lX)\n", v));
279*00b67f09SDavid van Moolenbroek
280*00b67f09SDavid van Moolenbroek if (!ctx->fixed) {
281*00b67f09SDavid van Moolenbroek WARNING(("idn_ucsmap_map: not fixed yet\n"));
282*00b67f09SDavid van Moolenbroek return (idn_failure);
283*00b67f09SDavid van Moolenbroek }
284*00b67f09SDavid van Moolenbroek
285*00b67f09SDavid van Moolenbroek /* First, look up hash table. */
286*00b67f09SDavid van Moolenbroek hash = ucsmap_hash(v);
287*00b67f09SDavid van Moolenbroek if ((n = ctx->hash[hash].n) == 0)
288*00b67f09SDavid van Moolenbroek goto nomap;
289*00b67f09SDavid van Moolenbroek
290*00b67f09SDavid van Moolenbroek /* Then do binary search. */
291*00b67f09SDavid van Moolenbroek e = ctx->hash[hash].entry;
292*00b67f09SDavid van Moolenbroek lo = 0;
293*00b67f09SDavid van Moolenbroek hi = n - 1;
294*00b67f09SDavid van Moolenbroek while (lo <= hi) {
295*00b67f09SDavid van Moolenbroek mid = (lo + hi) / 2;
296*00b67f09SDavid van Moolenbroek if (v < e[mid].ucs)
297*00b67f09SDavid van Moolenbroek hi = mid - 1;
298*00b67f09SDavid van Moolenbroek else if (v > e[mid].ucs)
299*00b67f09SDavid van Moolenbroek lo = mid + 1;
300*00b67f09SDavid van Moolenbroek else {
301*00b67f09SDavid van Moolenbroek /* Found. */
302*00b67f09SDavid van Moolenbroek if (tolen < e[mid].len)
303*00b67f09SDavid van Moolenbroek return (idn_buffer_overflow);
304*00b67f09SDavid van Moolenbroek memcpy(to, e[mid].map, sizeof(*to) * e[mid].len);
305*00b67f09SDavid van Moolenbroek *maplenp = e[mid].len;
306*00b67f09SDavid van Moolenbroek return (idn_success);
307*00b67f09SDavid van Moolenbroek }
308*00b67f09SDavid van Moolenbroek }
309*00b67f09SDavid van Moolenbroek
310*00b67f09SDavid van Moolenbroek /*
311*00b67f09SDavid van Moolenbroek * Not found. Put the original character to 'to'
312*00b67f09SDavid van Moolenbroek * just for convenience.
313*00b67f09SDavid van Moolenbroek */
314*00b67f09SDavid van Moolenbroek nomap:
315*00b67f09SDavid van Moolenbroek if (tolen < 1)
316*00b67f09SDavid van Moolenbroek return (idn_buffer_overflow);
317*00b67f09SDavid van Moolenbroek *to = v;
318*00b67f09SDavid van Moolenbroek *maplenp = 1;
319*00b67f09SDavid van Moolenbroek return (idn_nomapping);
320*00b67f09SDavid van Moolenbroek }
321*00b67f09SDavid van Moolenbroek
322*00b67f09SDavid van Moolenbroek static int
ucsmap_hash(unsigned long v)323*00b67f09SDavid van Moolenbroek ucsmap_hash(unsigned long v) {
324*00b67f09SDavid van Moolenbroek return (v % UCSMAP_HASH_SIZE);
325*00b67f09SDavid van Moolenbroek }
326*00b67f09SDavid van Moolenbroek
327*00b67f09SDavid van Moolenbroek static unsigned long *
save_mapped_sequence(idn_ucsmap_t ctx,unsigned long * map,size_t maplen)328*00b67f09SDavid van Moolenbroek save_mapped_sequence(idn_ucsmap_t ctx, unsigned long *map, size_t maplen) {
329*00b67f09SDavid van Moolenbroek ucsmap_buf_t *buf;
330*00b67f09SDavid van Moolenbroek unsigned long *p;
331*00b67f09SDavid van Moolenbroek size_t allocsize;
332*00b67f09SDavid van Moolenbroek
333*00b67f09SDavid van Moolenbroek /*
334*00b67f09SDavid van Moolenbroek * If the current buffer (the first one in the ctx->mapdata list)
335*00b67f09SDavid van Moolenbroek * has enough space, use it. Otherwise, allocate a new buffer and
336*00b67f09SDavid van Moolenbroek * insert it at the beginning of the list.
337*00b67f09SDavid van Moolenbroek */
338*00b67f09SDavid van Moolenbroek if (ctx->mapdata_used + maplen > ctx->mapdata_size) {
339*00b67f09SDavid van Moolenbroek if (maplen > DEFAULT_BUF_SIZE)
340*00b67f09SDavid van Moolenbroek allocsize = maplen * 2;
341*00b67f09SDavid van Moolenbroek else
342*00b67f09SDavid van Moolenbroek allocsize = DEFAULT_BUF_SIZE;
343*00b67f09SDavid van Moolenbroek buf = malloc(sizeof(ucsmap_hash_t) +
344*00b67f09SDavid van Moolenbroek sizeof(unsigned long) * allocsize);
345*00b67f09SDavid van Moolenbroek if (buf == NULL)
346*00b67f09SDavid van Moolenbroek return (NULL);
347*00b67f09SDavid van Moolenbroek buf->next = ctx->mapdata;
348*00b67f09SDavid van Moolenbroek ctx->mapdata = buf;
349*00b67f09SDavid van Moolenbroek ctx->mapdata_size = allocsize;
350*00b67f09SDavid van Moolenbroek ctx->mapdata_used = 0;
351*00b67f09SDavid van Moolenbroek }
352*00b67f09SDavid van Moolenbroek p = ctx->mapdata->buf + ctx->mapdata_used;
353*00b67f09SDavid van Moolenbroek memcpy(p, map, sizeof(unsigned long) * maplen);
354*00b67f09SDavid van Moolenbroek ctx->mapdata_used += maplen;
355*00b67f09SDavid van Moolenbroek return (p);
356*00b67f09SDavid van Moolenbroek }
357*00b67f09SDavid van Moolenbroek
358*00b67f09SDavid van Moolenbroek static void
free_mapbuf(ucsmap_buf_t * buf)359*00b67f09SDavid van Moolenbroek free_mapbuf(ucsmap_buf_t *buf) {
360*00b67f09SDavid van Moolenbroek while (buf != NULL) {
361*00b67f09SDavid van Moolenbroek ucsmap_buf_t *next = buf->next;
362*00b67f09SDavid van Moolenbroek free(buf);
363*00b67f09SDavid van Moolenbroek buf = next;
364*00b67f09SDavid van Moolenbroek }
365*00b67f09SDavid van Moolenbroek }
366*00b67f09SDavid van Moolenbroek
367*00b67f09SDavid van Moolenbroek static int
comp_entry(const void * v1,const void * v2)368*00b67f09SDavid van Moolenbroek comp_entry(const void *v1, const void *v2) {
369*00b67f09SDavid van Moolenbroek const ucsmap_entry_t *e1 = v1;
370*00b67f09SDavid van Moolenbroek const ucsmap_entry_t *e2 = v2;
371*00b67f09SDavid van Moolenbroek
372*00b67f09SDavid van Moolenbroek if (e1->hidx < e2->hidx)
373*00b67f09SDavid van Moolenbroek return (-1);
374*00b67f09SDavid van Moolenbroek else if (e1->hidx > e2->hidx)
375*00b67f09SDavid van Moolenbroek return (1);
376*00b67f09SDavid van Moolenbroek else if (e1->ucs < e2->ucs)
377*00b67f09SDavid van Moolenbroek return (-1);
378*00b67f09SDavid van Moolenbroek else if (e1->ucs > e2->ucs)
379*00b67f09SDavid van Moolenbroek return (1);
380*00b67f09SDavid van Moolenbroek else
381*00b67f09SDavid van Moolenbroek return (0);
382*00b67f09SDavid van Moolenbroek }
383