Coverage Report

Created: 2021-08-22 09:07

/src/skia/third_party/externals/icu/source/common/propname.cpp
Line
Count
Source (jump to first uncovered line)
1
// © 2016 and later: Unicode, Inc. and others.
2
// License & terms of use: http://www.unicode.org/copyright.html
3
/*
4
**********************************************************************
5
* Copyright (c) 2002-2014, International Business Machines
6
* Corporation and others.  All Rights Reserved.
7
**********************************************************************
8
* Author: Alan Liu
9
* Created: October 30 2002
10
* Since: ICU 2.4
11
* 2010nov19 Markus Scherer  Rewrite for formatVersion 2.
12
**********************************************************************
13
*/
14
#include "propname.h"
15
#include "unicode/uchar.h"
16
#include "unicode/udata.h"
17
#include "unicode/uscript.h"
18
#include "umutex.h"
19
#include "cmemory.h"
20
#include "cstring.h"
21
#include "uarrsort.h"
22
#include "uinvchar.h"
23
24
#define INCLUDED_FROM_PROPNAME_CPP
25
#include "propname_data.h"
26
27
U_CDECL_BEGIN
28
29
/**
30
 * Get the next non-ignorable ASCII character from a property name
31
 * and lowercases it.
32
 * @return ((advance count for the name)<<8)|character
33
 */
34
static inline int32_t
35
0
getASCIIPropertyNameChar(const char *name) {
36
0
    int32_t i;
37
0
    char c;
38
39
    /* Ignore delimiters '-', '_', and ASCII White_Space */
40
0
    for(i=0;
41
0
        (c=name[i++])==0x2d || c==0x5f ||
42
0
        c==0x20 || (0x09<=c && c<=0x0d);
43
0
    ) {}
44
45
0
    if(c!=0) {
46
0
        return (i<<8)|(uint8_t)uprv_asciitolower((char)c);
47
0
    } else {
48
0
        return i<<8;
49
0
    }
50
0
}
51
52
/**
53
 * Get the next non-ignorable EBCDIC character from a property name
54
 * and lowercases it.
55
 * @return ((advance count for the name)<<8)|character
56
 */
57
static inline int32_t
58
0
getEBCDICPropertyNameChar(const char *name) {
59
0
    int32_t i;
60
0
    char c;
61
62
    /* Ignore delimiters '-', '_', and EBCDIC White_Space */
63
0
    for(i=0;
64
0
        (c=name[i++])==0x60 || c==0x6d ||
65
0
        c==0x40 || c==0x05 || c==0x15 || c==0x25 || c==0x0b || c==0x0c || c==0x0d;
66
0
    ) {}
67
68
0
    if(c!=0) {
69
0
        return (i<<8)|(uint8_t)uprv_ebcdictolower((char)c);
70
0
    } else {
71
0
        return i<<8;
72
0
    }
73
0
}
74
75
/**
76
 * Unicode property names and property value names are compared "loosely".
77
 *
78
 * UCD.html 4.0.1 says:
79
 *   For all property names, property value names, and for property values for
80
 *   Enumerated, Binary, or Catalog properties, use the following
81
 *   loose matching rule:
82
 *
83
 *   LM3. Ignore case, whitespace, underscore ('_'), and hyphens.
84
 *
85
 * This function does just that, for (char *) name strings.
86
 * It is almost identical to ucnv_compareNames() but also ignores
87
 * C0 White_Space characters (U+0009..U+000d, and U+0085 on EBCDIC).
88
 *
89
 * @internal
90
 */
91
92
U_CAPI int32_t U_EXPORT2
93
0
uprv_compareASCIIPropertyNames(const char *name1, const char *name2) {
94
0
    int32_t rc, r1, r2;
95
96
0
    for(;;) {
97
0
        r1=getASCIIPropertyNameChar(name1);
98
0
        r2=getASCIIPropertyNameChar(name2);
99
100
        /* If we reach the ends of both strings then they match */
101
0
        if(((r1|r2)&0xff)==0) {
102
0
            return 0;
103
0
        }
104
105
        /* Compare the lowercased characters */
106
0
        if(r1!=r2) {
107
0
            rc=(r1&0xff)-(r2&0xff);
108
0
            if(rc!=0) {
109
0
                return rc;
110
0
            }
111
0
        }
112
113
0
        name1+=r1>>8;
114
0
        name2+=r2>>8;
115
0
    }
116
0
}
117
118
U_CAPI int32_t U_EXPORT2
119
0
uprv_compareEBCDICPropertyNames(const char *name1, const char *name2) {
120
0
    int32_t rc, r1, r2;
121
122
0
    for(;;) {
123
0
        r1=getEBCDICPropertyNameChar(name1);
124
0
        r2=getEBCDICPropertyNameChar(name2);
125
126
        /* If we reach the ends of both strings then they match */
127
0
        if(((r1|r2)&0xff)==0) {
128
0
            return 0;
129
0
        }
130
131
        /* Compare the lowercased characters */
132
0
        if(r1!=r2) {
133
0
            rc=(r1&0xff)-(r2&0xff);
134
0
            if(rc!=0) {
135
0
                return rc;
136
0
            }
137
0
        }
138
139
0
        name1+=r1>>8;
140
0
        name2+=r2>>8;
141
0
    }
142
0
}
143
144
U_CDECL_END
145
146
U_NAMESPACE_BEGIN
147
148
7.99k
int32_t PropNameData::findProperty(int32_t property) {
149
7.99k
    int32_t i=1;  // valueMaps index, initially after numRanges
150
16.0k
    for(int32_t numRanges=valueMaps[0]; numRanges>0; --numRanges) {
151
        // Read and skip the start and limit of this range.
152
16.0k
        int32_t start=valueMaps[i];
153
16.0k
        int32_t limit=valueMaps[i+1];
154
16.0k
        i+=2;
155
16.0k
        if(property<start) {
156
0
            break;
157
0
        }
158
16.0k
        if(property<limit) {
159
7.99k
            return i+(property-start)*2;
160
7.99k
        }
161
8.01k
        i+=(limit-start)*2;  // Skip all entries for this range.
162
8.01k
    }
163
0
    return 0;
164
7.99k
}
165
166
7.93k
int32_t PropNameData::findPropertyValueNameGroup(int32_t valueMapIndex, int32_t value) {
167
7.93k
    if(valueMapIndex==0) {
168
0
        return 0;  // The property does not have named values.
169
0
    }
170
7.93k
    ++valueMapIndex;  // Skip the BytesTrie offset.
171
7.93k
    int32_t numRanges=valueMaps[valueMapIndex++];
172
7.93k
    if(numRanges<0x10) {
173
        // Ranges of values.
174
7.93k
        for(; numRanges>0; --numRanges) {
175
            // Read and skip the start and limit of this range.
176
7.93k
            int32_t start=valueMaps[valueMapIndex];
177
7.93k
            int32_t limit=valueMaps[valueMapIndex+1];
178
7.93k
            valueMapIndex+=2;
179
7.93k
            if(value<start) {
180
0
                break;
181
0
            }
182
7.93k
            if(value<limit) {
183
7.93k
                return valueMaps[valueMapIndex+value-start];
184
7.93k
            }
185
0
            valueMapIndex+=limit-start;  // Skip all entries for this range.
186
0
        }
187
0
    } else {
188
        // List of values.
189
0
        int32_t valuesStart=valueMapIndex;
190
0
        int32_t nameGroupOffsetsStart=valueMapIndex+numRanges-0x10;
191
0
        do {
192
0
            int32_t v=valueMaps[valueMapIndex];
193
0
            if(value<v) {
194
0
                break;
195
0
            }
196
0
            if(value==v) {
197
0
                return valueMaps[nameGroupOffsetsStart+valueMapIndex-valuesStart];
198
0
            }
199
0
        } while(++valueMapIndex<nameGroupOffsetsStart);
200
0
    }
201
0
    return 0;
202
7.93k
}
203
204
7.93k
const char *PropNameData::getName(const char *nameGroup, int32_t nameIndex) {
205
7.93k
    int32_t numNames=*nameGroup++;
206
7.93k
    if(nameIndex<0 || numNames<=nameIndex) {
207
0
        return NULL;
208
0
    }
209
    // Skip nameIndex names.
210
7.93k
    for(; nameIndex>0; --nameIndex) {
211
0
        nameGroup=uprv_strchr(nameGroup, 0)+1;
212
0
    }
213
7.93k
    if(*nameGroup==0) {
214
0
        return NULL;  // no name (Property[Value]Aliases.txt has "n/a")
215
0
    }
216
7.93k
    return nameGroup;
217
7.93k
}
218
219
72
UBool PropNameData::containsName(BytesTrie &trie, const char *name) {
220
72
    if(name==NULL) {
221
0
        return FALSE;
222
0
    }
223
72
    UStringTrieResult result=USTRINGTRIE_NO_VALUE;
224
72
    char c;
225
348
    while((c=*name++)!=0) {
226
292
        c=uprv_invCharToLowercaseAscii(c);
227
        // Ignore delimiters '-', '_', and ASCII White_Space.
228
292
        if(c==0x2d || c==0x5f || c==0x20 || (0x09<=c && c<=0x0d)) {
229
0
            continue;
230
0
        }
231
292
        if(!USTRINGTRIE_HAS_NEXT(result)) {
232
16
            return FALSE;
233
16
        }
234
276
        result=trie.next((uint8_t)c);
235
276
    }
236
56
    return USTRINGTRIE_HAS_VALUE(result);
237
72
}
238
239
0
const char *PropNameData::getPropertyName(int32_t property, int32_t nameChoice) {
240
0
    int32_t valueMapIndex=findProperty(property);
241
0
    if(valueMapIndex==0) {
242
0
        return NULL;  // Not a known property.
243
0
    }
244
0
    return getName(nameGroups+valueMaps[valueMapIndex], nameChoice);
245
0
}
246
247
7.93k
const char *PropNameData::getPropertyValueName(int32_t property, int32_t value, int32_t nameChoice) {
248
7.93k
    int32_t valueMapIndex=findProperty(property);
249
7.93k
    if(valueMapIndex==0) {
250
0
        return NULL;  // Not a known property.
251
0
    }
252
7.93k
    int32_t nameGroupOffset=findPropertyValueNameGroup(valueMaps[valueMapIndex+1], value);
253
7.93k
    if(nameGroupOffset==0) {
254
0
        return NULL;
255
0
    }
256
7.93k
    return getName(nameGroups+nameGroupOffset, nameChoice);
257
7.93k
}
258
259
72
int32_t PropNameData::getPropertyOrValueEnum(int32_t bytesTrieOffset, const char *alias) {
260
72
    BytesTrie trie(bytesTries+bytesTrieOffset);
261
72
    if(containsName(trie, alias)) {
262
56
        return trie.getValue();
263
16
    } else {
264
16
        return UCHAR_INVALID_CODE;
265
16
    }
266
72
}
267
268
16
int32_t PropNameData::getPropertyEnum(const char *alias) {
269
16
    return getPropertyOrValueEnum(0, alias);
270
16
}
271
272
56
int32_t PropNameData::getPropertyValueEnum(int32_t property, const char *alias) {
273
56
    int32_t valueMapIndex=findProperty(property);
274
56
    if(valueMapIndex==0) {
275
0
        return UCHAR_INVALID_CODE;  // Not a known property.
276
0
    }
277
56
    valueMapIndex=valueMaps[valueMapIndex+1];
278
56
    if(valueMapIndex==0) {
279
0
        return UCHAR_INVALID_CODE;  // The property does not have named values.
280
0
    }
281
    // valueMapIndex is the start of the property's valueMap,
282
    // where the first word is the BytesTrie offset.
283
56
    return getPropertyOrValueEnum(valueMaps[valueMapIndex], alias);
284
56
}
285
U_NAMESPACE_END
286
287
//----------------------------------------------------------------------
288
// Public API implementation
289
290
U_CAPI const char* U_EXPORT2
291
u_getPropertyName(UProperty property,
292
0
                  UPropertyNameChoice nameChoice) {
293
0
    U_NAMESPACE_USE
294
0
    return PropNameData::getPropertyName(property, nameChoice);
295
0
}
296
297
U_CAPI UProperty U_EXPORT2
298
16
u_getPropertyEnum(const char* alias) {
299
16
    U_NAMESPACE_USE
300
16
    return (UProperty)PropNameData::getPropertyEnum(alias);
301
16
}
302
303
U_CAPI const char* U_EXPORT2
304
u_getPropertyValueName(UProperty property,
305
                       int32_t value,
306
7.93k
                       UPropertyNameChoice nameChoice) {
307
7.93k
    U_NAMESPACE_USE
308
7.93k
    return PropNameData::getPropertyValueName(property, value, nameChoice);
309
7.93k
}
310
311
U_CAPI int32_t U_EXPORT2
312
u_getPropertyValueEnum(UProperty property,
313
56
                       const char* alias) {
314
56
    U_NAMESPACE_USE
315
56
    return PropNameData::getPropertyValueEnum(property, alias);
316
56
}
317
318
U_CAPI const char*  U_EXPORT2
319
0
uscript_getName(UScriptCode scriptCode){
320
0
    return u_getPropertyValueName(UCHAR_SCRIPT, scriptCode,
321
0
                                  U_LONG_PROPERTY_NAME);
322
0
}
323
324
U_CAPI const char*  U_EXPORT2
325
7.93k
uscript_getShortName(UScriptCode scriptCode){
326
7.93k
    return u_getPropertyValueName(UCHAR_SCRIPT, scriptCode,
327
7.93k
                                  U_SHORT_PROPERTY_NAME);
328
7.93k
}