1
/* $OpenLDAP: pkg/ldap/libraries/liblunicode/ucdata/ucdata.c,v 1.36 2008/01/07 23:20:05 kurt Exp $ */
2
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
4
* Copyright 1998-2008 The OpenLDAP Foundation.
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted only as authorized by the OpenLDAP
11
* A copy of this license is available in file LICENSE in the
12
* top-level directory of the distribution or, alternatively, at
13
* <http://www.OpenLDAP.org/license.html>.
15
/* Copyright 2001 Computing Research Labs, New Mexico State University
17
* Permission is hereby granted, free of charge, to any person obtaining a
18
* copy of this software and associated documentation files (the "Software"),
19
* to deal in the Software without restriction, including without limitation
20
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
21
* and/or sell copies of the Software, and to permit persons to whom the
22
* Software is furnished to do so, subject to the following conditions:
24
* The above copyright notice and this permission notice shall be included in
25
* all copies or substantial portions of the Software.
27
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
30
* THE COMPUTING RESEARCH LAB OR NEW MEXICO STATE UNIVERSITY BE LIABLE FOR ANY
31
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
32
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
33
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35
/* $Id: ucdata.c,v 1.4 2001/01/02 18:46:20 mleisher Exp $" */
39
#include "k5-unicode.h"
44
#define HARDCODE_DATA 1
51
/**************************************************************************
53
* Miscellaneous types, data, and support functions.
55
**************************************************************************/
67
* A simple array of 32-bit masks for lookup.
69
static krb5_ui_4 masks32[32] = {
70
0x00000001UL, 0x00000002UL, 0x00000004UL, 0x00000008UL,
71
0x00000010UL, 0x00000020UL, 0x00000040UL, 0x00000080UL,
72
0x00000100UL, 0x00000200UL, 0x00000400UL, 0x00000800UL,
73
0x00001000UL, 0x00002000UL, 0x00004000UL, 0x00008000UL,
74
0x00010000UL, 0x00020000UL, 0x00040000UL, 0x00080000UL,
75
0x00100000UL, 0x00200000UL, 0x00400000UL, 0x00800000UL,
76
0x01000000UL, 0x02000000UL, 0x04000000UL, 0x08000000UL,
77
0x10000000UL, 0x20000000UL, 0x40000000UL, 0x80000000UL
80
#define endian_short(cc) (((cc) >> 8) | (((cc) & 0xff) << 8))
81
#define endian_long(cc) ((((cc) & 0xff) << 24)|((((cc) >> 8) & 0xff) << 16)|\
82
((((cc) >> 16) & 0xff) << 8)|((cc) >> 24))
86
_ucopenfile(char *paths, char *filename, char *mode)
89
char *fp, *dp, *pp, path[BUFSIZ];
91
if (filename == 0 || *filename == 0)
97
while (*dp && *dp != ':')
106
if ((f = fopen(path, mode)) != 0)
117
/**************************************************************************
119
* Support for the character properties.
121
**************************************************************************/
125
static krb5_ui_4 _ucprop_size;
126
static krb5_ui_2 *_ucprop_offsets;
127
static krb5_ui_4 *_ucprop_ranges;
130
* Return -1 on error, 0 if okay
133
_ucprop_load(char *paths, int reload)
139
if (_ucprop_size > 0) {
142
* The character properties have already been loaded.
147
* Unload the current character property data in preparation for
148
* loading a new copy. Only the first array has to be deallocated
149
* because all the memory for the arrays is allocated as a single
152
free((char *) _ucprop_offsets);
156
if ((in = _ucopenfile(paths, "ctype.dat", "rb")) == 0)
162
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
164
if (hdr.bom == 0xfffe) {
165
hdr.cnt = endian_short(hdr.cnt);
166
hdr.size.bytes = endian_long(hdr.size.bytes);
169
if ((_ucprop_size = hdr.cnt) == 0) {
175
* Allocate all the storage needed for the lookup table.
177
_ucprop_offsets = (krb5_ui_2 *) malloc(hdr.size.bytes);
180
* Calculate the offset into the storage for the ranges. The offsets
181
* array is on a 4-byte boundary and one larger than the value provided in
182
* the header count field. This means the offset to the ranges must be
183
* calculated after aligning the count to a 4-byte boundary.
185
if ((size = ((hdr.cnt + 1) * sizeof(krb5_ui_2))) & 3)
186
size += 4 - (size & 3);
188
_ucprop_ranges = (krb5_ui_4 *) (_ucprop_offsets + size);
191
* Load the offset array.
193
fread((char *) _ucprop_offsets, sizeof(krb5_ui_2), size, in);
196
* Do an endian swap if necessary. Don't forget there is an extra node on
197
* the end with the final index.
199
if (hdr.bom == 0xfffe) {
200
for (i = 0; i <= _ucprop_size; i++)
201
_ucprop_offsets[i] = endian_short(_ucprop_offsets[i]);
205
* Load the ranges. The number of elements is in the last array position
208
fread((char *) _ucprop_ranges, sizeof(krb5_ui_4),
209
_ucprop_offsets[_ucprop_size], in);
214
* Do an endian swap if necessary.
216
if (hdr.bom == 0xfffe) {
217
for (i = 0; i < _ucprop_offsets[_ucprop_size]; i++)
218
_ucprop_ranges[i] = endian_long(_ucprop_ranges[i]);
226
if (_ucprop_size == 0)
230
* Only need to free the offsets because the memory is allocated as a
233
free((char *) _ucprop_offsets);
239
_ucprop_lookup(krb5_ui_4 code, krb5_ui_4 n)
243
if (_ucprop_size == 0)
247
* There is an extra node on the end of the offsets to allow this routine
248
* to work right. If the index is 0xffff, then there are no nodes for the
251
if ((l = _ucprop_offsets[n]) == 0xffff)
255
* Locate the next offset that is not 0xffff. The sentinel at the end of
256
* the array is the max index value.
259
n + m < _ucprop_size && _ucprop_offsets[n + m] == 0xffff; m++) ;
261
r = _ucprop_offsets[n + m] - 1;
265
* Determine a "mid" point and adjust to make sure the mid point is at
266
* the beginning of a range pair.
270
if (code > _ucprop_ranges[m + 1])
272
else if (code < _ucprop_ranges[m])
274
else if (code >= _ucprop_ranges[m] && code <= _ucprop_ranges[m + 1])
281
ucisprop(krb5_ui_4 code, krb5_ui_4 mask1, krb5_ui_4 mask2)
285
if (mask1 == 0 && mask2 == 0)
288
for (i = 0; mask1 && i < 32; i++) {
289
if ((mask1 & masks32[i]) && _ucprop_lookup(code, i))
293
for (i = 32; mask2 && i < _ucprop_size; i++) {
294
if ((mask2 & masks32[i & 31]) && _ucprop_lookup(code, i))
301
/**************************************************************************
303
* Support for case mapping.
305
**************************************************************************/
309
/* These record the number of slots in the map.
310
* There are 3 words per slot.
312
static krb5_ui_4 _uccase_size;
313
static krb5_ui_2 _uccase_len[2];
314
static krb5_ui_4 *_uccase_map;
317
* Return -1 on error, 0 if okay
320
_uccase_load(char *paths, int reload)
326
if (_uccase_size > 0) {
329
* The case mappings have already been loaded.
333
free((char *) _uccase_map);
337
if ((in = _ucopenfile(paths, "case.dat", "rb")) == 0)
343
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
345
if (hdr.bom == 0xfffe) {
346
hdr.cnt = endian_short(hdr.cnt);
347
hdr.size.len[0] = endian_short(hdr.size.len[0]);
348
hdr.size.len[1] = endian_short(hdr.size.len[1]);
352
* Set the node count and lengths of the upper and lower case mapping
355
_uccase_size = hdr.cnt;
356
_uccase_len[0] = hdr.size.len[0];
357
_uccase_len[1] = hdr.size.len[1];
359
_uccase_map = (krb5_ui_4 *)
360
malloc(_uccase_size * 3 * sizeof(krb5_ui_4));
363
* Load the case mapping table.
365
fread((char *) _uccase_map, sizeof(krb5_ui_4), _uccase_size * 3, in);
368
* Do an endian swap if necessary.
370
if (hdr.bom == 0xfffe) {
371
for (i = 0; i < _uccase_size * 3; i++)
372
_uccase_map[i] = endian_long(_uccase_map[i]);
381
if (_uccase_size == 0)
384
free((char *) _uccase_map);
390
_uccase_lookup(krb5_ui_4 code, long l, long r, int field)
393
const krb5_ui_4 *tmp;
396
* Do the binary search.
400
* Determine a "mid" point and adjust to make sure the mid point is at
401
* the beginning of a case mapping triple.
404
tmp = &_uccase_map[m*3];
407
else if (code < *tmp)
409
else if (code == *tmp)
417
uctoupper(krb5_ui_4 code)
425
if (ucislower(code)) {
427
* The character is lower case.
431
r = (l + _uccase_len[1]) - 1;
434
* The character is title case.
437
l = _uccase_len[0] + _uccase_len[1];
438
r = _uccase_size - 1;
440
return _uccase_lookup(code, l, r, field);
444
uctolower(krb5_ui_4 code)
452
if (ucisupper(code)) {
454
* The character is upper case.
458
r = _uccase_len[0] - 1;
461
* The character is title case.
464
l = _uccase_len[0] + _uccase_len[1];
465
r = _uccase_size - 1;
467
return _uccase_lookup(code, l, r, field);
471
uctotitle(krb5_ui_4 code)
480
* The offset will always be the same for converting to title case.
484
if (ucisupper(code)) {
486
* The character is upper case.
489
r = _uccase_len[0] - 1;
492
* The character is lower case.
495
r = (l + _uccase_len[1]) - 1;
497
return _uccase_lookup(code, l, r, field);
500
/**************************************************************************
502
* Support for compositions.
504
**************************************************************************/
508
static krb5_ui_4 _uccomp_size;
509
static krb5_ui_4 *_uccomp_data;
512
* Return -1 on error, 0 if okay
515
_uccomp_load(char *paths, int reload)
521
if (_uccomp_size > 0) {
524
* The compositions have already been loaded.
528
free((char *) _uccomp_data);
532
if ((in = _ucopenfile(paths, "comp.dat", "rb")) == 0)
538
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
540
if (hdr.bom == 0xfffe) {
541
hdr.cnt = endian_short(hdr.cnt);
542
hdr.size.bytes = endian_long(hdr.size.bytes);
545
_uccomp_size = hdr.cnt;
546
_uccomp_data = (krb5_ui_4 *) malloc(hdr.size.bytes);
549
* Read the composition data in.
551
size = hdr.size.bytes / sizeof(krb5_ui_4);
552
fread((char *) _uccomp_data, sizeof(krb5_ui_4), size, in);
555
* Do an endian swap if necessary.
557
if (hdr.bom == 0xfffe) {
558
for (i = 0; i < size; i++)
559
_uccomp_data[i] = endian_long(_uccomp_data[i]);
563
* Assume that the data is ordered on count, so that all compositions
564
* of length 2 come first. Only handling length 2 for now.
566
for (i = 1; i < size; i += 4)
567
if (_uccomp_data[i] != 2)
569
_uccomp_size = i - 1;
578
if (_uccomp_size == 0)
581
free((char *) _uccomp_data);
587
uccomp(krb5_ui_4 node1, krb5_ui_4 node2, krb5_ui_4 *comp)
592
r = _uccomp_size - 1;
597
if (node1 > _uccomp_data[m+2])
599
else if (node1 < _uccomp_data[m+2])
601
else if (node2 > _uccomp_data[m+3])
603
else if (node2 < _uccomp_data[m+3])
606
*comp = _uccomp_data[m];
614
uccomp_hangul(krb5_ui_4 *str, int len)
616
const int SBase = 0xAC00, LBase = 0x1100,
617
VBase = 0x1161, TBase = 0x11A7,
618
LCount = 19, VCount = 21, TCount = 28,
619
NCount = VCount * TCount, /* 588 */
620
SCount = LCount * NCount; /* 11172 */
623
krb5_ui_4 ch, last, lindex, sindex;
627
for ( i = 1; i < len; i++ ) {
630
/* check if two current characters are L and V */
631
lindex = last - LBase;
632
if (lindex < (krb5_ui_4) LCount) {
633
krb5_ui_4 vindex = ch - VBase;
634
if (vindex < (krb5_ui_4) VCount) {
635
/* make syllable of form LV */
636
last = SBase + (lindex * VCount + vindex) * TCount;
637
str[rlen-1] = last; /* reset last */
642
/* check if two current characters are LV and T */
643
sindex = last - SBase;
644
if (sindex < (krb5_ui_4) SCount
645
&& (sindex % TCount) == 0)
647
krb5_ui_4 tindex = ch - TBase;
648
if (tindex <= (krb5_ui_4) TCount) {
649
/* make syllable of form LVT */
651
str[rlen-1] = last; /* reset last */
656
/* if neither case was true, just add the character */
665
uccanoncomp(krb5_ui_4 *str, int len)
668
krb5_ui_4 cl, prevcl, st, ch, co;
673
prevcl = uccombining_class(st) == 0 ? 0 : 256;
675
for (i = 1; i < len; i++) {
677
cl = uccombining_class(ch);
678
if (uccomp(st, ch, &co) && (prevcl < cl || prevcl == 0))
679
st = str[stpos] = co;
690
return uccomp_hangul(str, copos);
693
/**************************************************************************
695
* Support for decompositions.
697
**************************************************************************/
701
static krb5_ui_4 _ucdcmp_size;
702
static krb5_ui_4 *_ucdcmp_nodes;
703
static krb5_ui_4 *_ucdcmp_decomp;
705
static krb5_ui_4 _uckdcmp_size;
706
static krb5_ui_4 *_uckdcmp_nodes;
707
static krb5_ui_4 *_uckdcmp_decomp;
710
* Return -1 on error, 0 if okay
713
_ucdcmp_load(char *paths, int reload)
719
if (_ucdcmp_size > 0) {
722
* The decompositions have already been loaded.
726
free((char *) _ucdcmp_nodes);
730
if ((in = _ucopenfile(paths, "decomp.dat", "rb")) == 0)
736
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
738
if (hdr.bom == 0xfffe) {
739
hdr.cnt = endian_short(hdr.cnt);
740
hdr.size.bytes = endian_long(hdr.size.bytes);
743
_ucdcmp_size = hdr.cnt << 1;
744
_ucdcmp_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
745
_ucdcmp_decomp = _ucdcmp_nodes + (_ucdcmp_size + 1);
748
* Read the decomposition data in.
750
size = hdr.size.bytes / sizeof(krb5_ui_4);
751
fread((char *) _ucdcmp_nodes, sizeof(krb5_ui_4), size, in);
754
* Do an endian swap if necessary.
756
if (hdr.bom == 0xfffe) {
757
for (i = 0; i < size; i++)
758
_ucdcmp_nodes[i] = endian_long(_ucdcmp_nodes[i]);
765
* Return -1 on error, 0 if okay
768
_uckdcmp_load(char *paths, int reload)
774
if (_uckdcmp_size > 0) {
777
* The decompositions have already been loaded.
781
free((char *) _uckdcmp_nodes);
785
if ((in = _ucopenfile(paths, "kdecomp.dat", "rb")) == 0)
791
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
793
if (hdr.bom == 0xfffe) {
794
hdr.cnt = endian_short(hdr.cnt);
795
hdr.size.bytes = endian_long(hdr.size.bytes);
798
_uckdcmp_size = hdr.cnt << 1;
799
_uckdcmp_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
800
_uckdcmp_decomp = _uckdcmp_nodes + (_uckdcmp_size + 1);
803
* Read the decomposition data in.
805
size = hdr.size.bytes / sizeof(krb5_ui_4);
806
fread((char *) _uckdcmp_nodes, sizeof(krb5_ui_4), size, in);
809
* Do an endian swap if necessary.
811
if (hdr.bom == 0xfffe) {
812
for (i = 0; i < size; i++)
813
_uckdcmp_nodes[i] = endian_long(_uckdcmp_nodes[i]);
822
if (_ucdcmp_size == 0)
826
* Only need to free the offsets because the memory is allocated as a
829
free((char *) _ucdcmp_nodes);
834
_uckdcmp_unload(void)
836
if (_uckdcmp_size == 0)
840
* Only need to free the offsets because the memory is allocated as a
843
free((char *) _uckdcmp_nodes);
849
ucdecomp(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 **decomp)
853
if (code < _ucdcmp_nodes[0]) {
858
r = _ucdcmp_nodes[_ucdcmp_size] - 1;
862
* Determine a "mid" point and adjust to make sure the mid point is at
863
* the beginning of a code+offset pair.
867
if (code > _ucdcmp_nodes[m])
869
else if (code < _ucdcmp_nodes[m])
871
else if (code == _ucdcmp_nodes[m]) {
872
*num = _ucdcmp_nodes[m + 3] - _ucdcmp_nodes[m + 1];
873
*decomp = (krb5_ui_4*)&_ucdcmp_decomp[_ucdcmp_nodes[m + 1]];
881
uckdecomp(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 **decomp)
885
if (code < _uckdcmp_nodes[0]) {
890
r = _uckdcmp_nodes[_uckdcmp_size] - 1;
894
* Determine a "mid" point and adjust to make sure the mid point is at
895
* the beginning of a code+offset pair.
899
if (code > _uckdcmp_nodes[m])
901
else if (code < _uckdcmp_nodes[m])
903
else if (code == _uckdcmp_nodes[m]) {
904
*num = _uckdcmp_nodes[m + 3] - _uckdcmp_nodes[m + 1];
905
*decomp = (krb5_ui_4*)&_uckdcmp_decomp[_uckdcmp_nodes[m + 1]];
913
ucdecomp_hangul(krb5_ui_4 code, krb5_ui_4 *num, krb5_ui_4 decomp[])
915
if (!ucishangul(code))
919
decomp[0] = 0x1100 + (krb5_ui_4) (code / 588);
920
decomp[1] = 0x1161 + (krb5_ui_4) ((code % 588) / 28);
921
decomp[2] = 0x11a7 + (krb5_ui_4) (code % 28);
922
*num = (decomp[2] != 0x11a7) ? 3 : 2;
927
/* mode == 0 for canonical, mode == 1 for compatibility */
929
uccanoncompatdecomp(const krb5_ui_4 *in, int inlen,
930
krb5_ui_4 **out, int *outlen, short mode)
934
krb5_ui_4 num, class, *decomp, hangdecomp[3];
937
*out = (krb5_ui_4 *) malloc(size * sizeof(**out));
942
for (j = 0; j < (unsigned) inlen; j++) {
943
if (mode ? uckdecomp(in[j], &num, &decomp) : ucdecomp(in[j], &num, &decomp)) {
944
if ( size - i < num) {
945
size = inlen + i - j + num - 1;
946
*out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
950
for (k = 0; k < num; k++) {
951
class = uccombining_class(decomp[k]);
953
(*out)[i] = decomp[k];
955
for (l = i; l > 0; l--)
956
if (class >= uccombining_class((*out)[l-1]))
958
memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out));
959
(*out)[l] = decomp[k];
963
} else if (ucdecomp_hangul(in[j], &num, hangdecomp)) {
964
if (size - i < num) {
965
size = inlen + i - j + num - 1;
966
*out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
970
for (k = 0; k < num; k++) {
971
(*out)[i] = hangdecomp[k];
976
size = inlen + i - j;
977
*out = (krb5_ui_4 *) realloc(*out, size * sizeof(**out));
981
class = uccombining_class(in[j]);
985
for (l = i; l > 0; l--)
986
if (class >= uccombining_class((*out)[l-1]))
988
memcpy(*out + l + 1, *out + l, (i - l) * sizeof(**out));
998
uccanondecomp(const krb5_ui_4 *in, int inlen,
999
krb5_ui_4 **out, int *outlen)
1001
return uccanoncompatdecomp(in, inlen, out, outlen, 0);
1005
uccompatdecomp(const krb5_ui_4 *in, int inlen,
1006
krb5_ui_4 **out, int *outlen)
1008
return uccanoncompatdecomp(in, inlen, out, outlen, 1);
1011
/**************************************************************************
1013
* Support for combining classes.
1015
**************************************************************************/
1018
static krb5_ui_4 _uccmcl_size;
1019
static krb5_ui_4 *_uccmcl_nodes;
1022
* Return -1 on error, 0 if okay
1025
_uccmcl_load(char *paths, int reload)
1031
if (_uccmcl_size > 0) {
1034
* The combining classes have already been loaded.
1038
free((char *) _uccmcl_nodes);
1042
if ((in = _ucopenfile(paths, "cmbcl.dat", "rb")) == 0)
1048
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
1050
if (hdr.bom == 0xfffe) {
1051
hdr.cnt = endian_short(hdr.cnt);
1052
hdr.size.bytes = endian_long(hdr.size.bytes);
1055
_uccmcl_size = hdr.cnt * 3;
1056
_uccmcl_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
1059
* Read the combining classes in.
1061
fread((char *) _uccmcl_nodes, sizeof(krb5_ui_4), _uccmcl_size, in);
1064
* Do an endian swap if necessary.
1066
if (hdr.bom == 0xfffe) {
1067
for (i = 0; i < _uccmcl_size; i++)
1068
_uccmcl_nodes[i] = endian_long(_uccmcl_nodes[i]);
1075
_uccmcl_unload(void)
1077
if (_uccmcl_size == 0)
1080
free((char *) _uccmcl_nodes);
1086
uccombining_class(krb5_ui_4 code)
1091
r = _uccmcl_size - 1;
1096
if (code > _uccmcl_nodes[m + 1])
1098
else if (code < _uccmcl_nodes[m])
1100
else if (code >= _uccmcl_nodes[m] && code <= _uccmcl_nodes[m + 1])
1101
return _uccmcl_nodes[m + 2];
1106
/**************************************************************************
1108
* Support for numeric values.
1110
**************************************************************************/
1113
static krb5_ui_4 *_ucnum_nodes;
1114
static krb5_ui_4 _ucnum_size;
1115
static short *_ucnum_vals;
1118
* Return -1 on error, 0 if okay
1121
_ucnumb_load(char *paths, int reload)
1127
if (_ucnum_size > 0) {
1130
* The numbers have already been loaded.
1134
free((char *) _ucnum_nodes);
1138
if ((in = _ucopenfile(paths, "num.dat", "rb")) == 0)
1144
fread((char *) &hdr, sizeof(_ucheader_t), 1, in);
1146
if (hdr.bom == 0xfffe) {
1147
hdr.cnt = endian_short(hdr.cnt);
1148
hdr.size.bytes = endian_long(hdr.size.bytes);
1151
_ucnum_size = hdr.cnt;
1152
_ucnum_nodes = (krb5_ui_4 *) malloc(hdr.size.bytes);
1153
_ucnum_vals = (short *) (_ucnum_nodes + _ucnum_size);
1156
* Read the combining classes in.
1158
fread((char *) _ucnum_nodes, sizeof(unsigned char), hdr.size.bytes, in);
1161
* Do an endian swap if necessary.
1163
if (hdr.bom == 0xfffe) {
1164
for (i = 0; i < _ucnum_size; i++)
1165
_ucnum_nodes[i] = endian_long(_ucnum_nodes[i]);
1168
* Determine the number of values that have to be adjusted.
1170
size = (hdr.size.bytes -
1171
(_ucnum_size * (sizeof(krb5_ui_4) << 1))) /
1174
for (i = 0; i < size; i++)
1175
_ucnum_vals[i] = endian_short(_ucnum_vals[i]);
1182
_ucnumb_unload(void)
1184
if (_ucnum_size == 0)
1187
free((char *) _ucnum_nodes);
1193
ucnumber_lookup(krb5_ui_4 code, struct ucnumber *num)
1199
r = _ucnum_size - 1;
1202
* Determine a "mid" point and adjust to make sure the mid point is at
1203
* the beginning of a code+offset pair.
1207
if (code > _ucnum_nodes[m])
1209
else if (code < _ucnum_nodes[m])
1212
vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1];
1213
num->numerator = (int) *vp++;
1214
num->denominator = (int) *vp;
1222
ucdigit_lookup(krb5_ui_4 code, int *digit)
1228
r = _ucnum_size - 1;
1231
* Determine a "mid" point and adjust to make sure the mid point is at
1232
* the beginning of a code+offset pair.
1236
if (code > _ucnum_nodes[m])
1238
else if (code < _ucnum_nodes[m])
1241
vp = (short *)_ucnum_vals + _ucnum_nodes[m + 1];
1242
if (*vp == *(vp + 1)) {
1253
ucgetnumber(krb5_ui_4 code)
1255
struct ucnumber num;
1258
* Initialize with some arbitrary value, because the caller simply cannot
1259
* tell for sure if the code is a number without calling the ucisnumber()
1260
* macro before calling this function.
1262
num.numerator = num.denominator = -111;
1264
(void) ucnumber_lookup(code, &num);
1270
ucgetdigit(krb5_ui_4 code)
1275
* Initialize with some arbitrary value, because the caller simply cannot
1276
* tell for sure if the code is a number without calling the ucisdigit()
1277
* macro before calling this function.
1281
(void) ucdigit_lookup(code, &dig);
1286
/**************************************************************************
1288
* Setup and cleanup routines.
1290
**************************************************************************/
1293
int ucdata_load(char *paths, int masks) { return 0; }
1294
void ucdata_unload(int masks) { }
1295
int ucdata_reload(char *paths, int masks) { return 0; }
1298
* Return 0 if okay, negative on error
1301
ucdata_load(char *paths, int masks)
1305
if (masks & UCDATA_CTYPE)
1306
error |= _ucprop_load(paths, 0) < 0 ? UCDATA_CTYPE : 0;
1307
if (masks & UCDATA_CASE)
1308
error |= _uccase_load(paths, 0) < 0 ? UCDATA_CASE : 0;
1309
if (masks & UCDATA_DECOMP)
1310
error |= _ucdcmp_load(paths, 0) < 0 ? UCDATA_DECOMP : 0;
1311
if (masks & UCDATA_CMBCL)
1312
error |= _uccmcl_load(paths, 0) < 0 ? UCDATA_CMBCL : 0;
1313
if (masks & UCDATA_NUM)
1314
error |= _ucnumb_load(paths, 0) < 0 ? UCDATA_NUM : 0;
1315
if (masks & UCDATA_COMP)
1316
error |= _uccomp_load(paths, 0) < 0 ? UCDATA_COMP : 0;
1317
if (masks & UCDATA_KDECOMP)
1318
error |= _uckdcmp_load(paths, 0) < 0 ? UCDATA_KDECOMP : 0;
1324
ucdata_unload(int masks)
1326
if (masks & UCDATA_CTYPE)
1328
if (masks & UCDATA_CASE)
1330
if (masks & UCDATA_DECOMP)
1332
if (masks & UCDATA_CMBCL)
1334
if (masks & UCDATA_NUM)
1336
if (masks & UCDATA_COMP)
1338
if (masks & UCDATA_KDECOMP)
1343
* Return 0 if okay, negative on error
1346
ucdata_reload(char *paths, int masks)
1350
if (masks & UCDATA_CTYPE)
1351
error |= _ucprop_load(paths, 1) < 0 ? UCDATA_CTYPE : 0;
1352
if (masks & UCDATA_CASE)
1353
error |= _uccase_load(paths, 1) < 0 ? UCDATA_CASE : 0;
1354
if (masks & UCDATA_DECOMP)
1355
error |= _ucdcmp_load(paths, 1) < 0 ? UCDATA_DECOMP : 0;
1356
if (masks & UCDATA_CMBCL)
1357
error |= _uccmcl_load(paths, 1) < 0 ? UCDATA_CMBCL : 0;
1358
if (masks & UCDATA_NUM)
1359
error |= _ucnumb_load(paths, 1) < 0 ? UCDATA_NUM : 0;
1360
if (masks & UCDATA_COMP)
1361
error |= _uccomp_load(paths, 1) < 0 ? UCDATA_COMP : 0;
1362
if (masks & UCDATA_KDECOMP)
1363
error |= _uckdcmp_load(paths, 1) < 0 ? UCDATA_KDECOMP : 0;
1375
krb5_ui_4 i, lo, *dec;
1376
struct ucnumber num;
1378
/* ucdata_setup("."); */
1383
printf("NOT WEAK\n");
1385
printf("LOWER 0x%04lX\n", uctolower(0xff3a));
1386
printf("UPPER 0x%04lX\n", uctoupper(0xff5a));
1388
if (ucisalpha(0x1d5))
1391
printf("NOT ALPHA\n");
1393
if (ucisupper(0x1d5)) {
1395
lo = uctolower(0x1d5);
1396
printf("0x%04lx\n", lo);
1397
lo = uctotitle(0x1d5);
1398
printf("0x%04lx\n", lo);
1400
printf("NOT UPPER\n");
1402
if (ucistitle(0x1d5))
1405
printf("NOT TITLE\n");
1407
if (uciscomposite(0x1d5))
1408
printf("COMPOSITE\n");
1410
printf("NOT COMPOSITE\n");
1412
if (ucdecomp(0x1d5, &lo, &dec)) {
1413
for (i = 0; i < lo; i++)
1414
printf("0x%04lx ", dec[i]);
1418
if ((lo = uccombining_class(0x41)) != 0)
1419
printf("0x41 CCL %ld\n", lo);
1421
if (ucisxdigit(0xfeff))
1422
printf("0xFEFF HEX DIGIT\n");
1424
printf("0xFEFF NOT HEX DIGIT\n");
1426
if (ucisdefined(0x10000))
1427
printf("0x10000 DEFINED\n");
1429
printf("0x10000 NOT DEFINED\n");
1431
if (ucnumber_lookup(0x30, &num)) {
1432
if (num.denominator != 1)
1433
printf("UCNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator);
1435
printf("UCNUMBER: 0x30 = %d\n", num.numerator);
1437
printf("UCNUMBER: 0x30 NOT A NUMBER\n");
1439
if (ucnumber_lookup(0xbc, &num)) {
1440
if (num.denominator != 1)
1441
printf("UCNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator);
1443
printf("UCNUMBER: 0xbc = %d\n", num.numerator);
1445
printf("UCNUMBER: 0xbc NOT A NUMBER\n");
1448
if (ucnumber_lookup(0xff19, &num)) {
1449
if (num.denominator != 1)
1450
printf("UCNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator);
1452
printf("UCNUMBER: 0xff19 = %d\n", num.numerator);
1454
printf("UCNUMBER: 0xff19 NOT A NUMBER\n");
1456
if (ucnumber_lookup(0x4e00, &num)) {
1457
if (num.denominator != 1)
1458
printf("UCNUMBER: 0x4e00 = %d/%d\n", num.numerator, num.denominator);
1460
printf("UCNUMBER: 0x4e00 = %d\n", num.numerator);
1462
printf("UCNUMBER: 0x4e00 NOT A NUMBER\n");
1464
if (ucdigit_lookup(0x06f9, &dig))
1465
printf("UCDIGIT: 0x6f9 = %d\n", dig);
1467
printf("UCDIGIT: 0x6f9 NOT A NUMBER\n");
1469
dig = ucgetdigit(0x0969);
1470
printf("UCGETDIGIT: 0x969 = %d\n", dig);
1472
num = ucgetnumber(0x30);
1473
if (num.denominator != 1)
1474
printf("UCGETNUMBER: 0x30 = %d/%d\n", num.numerator, num.denominator);
1476
printf("UCGETNUMBER: 0x30 = %d\n", num.numerator);
1478
num = ucgetnumber(0xbc);
1479
if (num.denominator != 1)
1480
printf("UCGETNUMBER: 0xbc = %d/%d\n", num.numerator, num.denominator);
1482
printf("UCGETNUMBER: 0xbc = %d\n", num.numerator);
1484
num = ucgetnumber(0xff19);
1485
if (num.denominator != 1)
1486
printf("UCGETNUMBER: 0xff19 = %d/%d\n", num.numerator, num.denominator);
1488
printf("UCGETNUMBER: 0xff19 = %d\n", num.numerator);
1490
/* ucdata_cleanup(); */