]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/propname.cpp
ICU-3.13.tar.gz
[apple/icu.git] / icuSources / common / propname.cpp
CommitLineData
b75a7d8f
A
1/*
2**********************************************************************
3* Copyright (c) 2002-2003, International Business Machines
4* Corporation and others. All Rights Reserved.
5**********************************************************************
6* Author: Alan Liu
7* Created: October 30 2002
8* Since: ICU 2.4
9**********************************************************************
10*/
11#include "propname.h"
12#include "unicode/uchar.h"
13#include "unicode/udata.h"
14#include "umutex.h"
15
16U_NAMESPACE_BEGIN
17
18//----------------------------------------------------------------------
19// PropertyAliases implementation
20
21const char*
22PropertyAliases::chooseNameInGroup(Offset offset,
23 UPropertyNameChoice choice) const {
24 int32_t c = choice;
25 if (!offset || c < 0) {
26 return NULL;
27 }
28 const Offset* p = (const Offset*) getPointer(offset);
29 while (c-- > 0) {
30 if (*p++ < 0) return NULL;
31 }
32 Offset a = *p;
33 if (a < 0) a = -a;
34 return (const char*) getPointerNull(a);
35}
36
37const ValueMap*
38PropertyAliases::getValueMap(EnumValue prop) const {
39 NonContiguousEnumToOffset* e2o = (NonContiguousEnumToOffset*) getPointer(enumToValue_offset);
40 Offset a = e2o->getOffset(prop);
41 return (const ValueMap*) (a ? getPointerNull(a) : NULL);
42}
43
44inline const char*
45PropertyAliases::getPropertyName(EnumValue prop,
46 UPropertyNameChoice choice) const {
47 NonContiguousEnumToOffset* e2n = (NonContiguousEnumToOffset*) getPointer(enumToName_offset);
48 return chooseNameInGroup(e2n->getOffset(prop), choice);
49}
50
51inline EnumValue
52PropertyAliases::getPropertyEnum(const char* alias) const {
53 NameToEnum* n2e = (NameToEnum*) getPointer(nameToEnum_offset);
54 return n2e->getEnum(alias, *this);
55}
56
57inline const char*
58PropertyAliases::getPropertyValueName(EnumValue prop,
59 EnumValue value,
60 UPropertyNameChoice choice) const {
61 const ValueMap* vm = getValueMap(prop);
62 if (!vm) return NULL;
63 Offset a;
64 if (vm->enumToName_offset) {
65 a = ((EnumToOffset*) getPointer(vm->enumToName_offset))->
66 getOffset(value);
67 } else {
68 a = ((NonContiguousEnumToOffset*) getPointer(vm->ncEnumToName_offset))->
69 getOffset(value);
70 }
71 return chooseNameInGroup(a, choice);
72}
73
74inline EnumValue
75PropertyAliases::getPropertyValueEnum(EnumValue prop,
76 const char* alias) const {
77 const ValueMap* vm = getValueMap(prop);
78 if (!vm) return UCHAR_INVALID_CODE;
79 NameToEnum* n2e = (NameToEnum*) getPointer(vm->nameToEnum_offset);
80 return n2e->getEnum(alias, *this);
81}
82
83U_NAMESPACE_END
84
85//----------------------------------------------------------------------
86// UDataMemory structures
87
88static const PropertyAliases* PNAME = NULL;
89static UDataMemory* UDATA = NULL;
90
91//----------------------------------------------------------------------
92// UDataMemory loading/unloading
93
94/**
95 * udata callback to verify the zone data.
96 */
97U_CDECL_BEGIN
98static UBool U_CALLCONV
99isAcceptable(void* /*context*/,
100 const char* /*type*/, const char* /*name*/,
101 const UDataInfo* info) {
102 return
103 info->size >= sizeof(UDataInfo) &&
104 info->isBigEndian == U_IS_BIG_ENDIAN &&
105 info->charsetFamily == U_CHARSET_FAMILY &&
106 info->dataFormat[0] == PNAME_SIG_0 &&
107 info->dataFormat[1] == PNAME_SIG_1 &&
108 info->dataFormat[2] == PNAME_SIG_2 &&
109 info->dataFormat[3] == PNAME_SIG_3 &&
110 info->formatVersion[0] == PNAME_FORMAT_VERSION;
111}
112
113UBool
114pname_cleanup() {
115 if (UDATA) {
116 udata_close(UDATA);
117 UDATA = NULL;
118 }
119 PNAME = NULL;
120 return TRUE;
121}
122U_CDECL_END
123
124/**
125 * Load the property names data. Caller should check that data is
126 * not loaded BEFORE calling this function. Returns TRUE if the load
127 * succeeds.
128 */
129static UBool _load() {
130 UErrorCode ec = U_ZERO_ERROR;
131 UDataMemory* data =
132 udata_openChoice(0, PNAME_DATA_TYPE, PNAME_DATA_NAME,
133 isAcceptable, 0, &ec);
134 if (U_SUCCESS(ec)) {
135 umtx_lock(NULL);
136 if (UDATA == NULL) {
137 UDATA = data;
138 PNAME = (const PropertyAliases*) udata_getMemory(UDATA);
139 data = NULL;
140 }
141 umtx_unlock(NULL);
142 }
143 if (data) {
144 udata_close(data);
145 }
146 return PNAME!=NULL;
147}
148
149/**
150 * Inline function that expands to code that does a lazy load of the
151 * property names data. If the data is already loaded, avoids an
152 * unnecessary function call. If the data is not loaded, call _load()
153 * to load it, and return TRUE if the load succeeds.
154 */
155static inline UBool load() {
156 umtx_lock(NULL);
157 UBool f = (PNAME!=NULL);
158 umtx_unlock(NULL);
159 return f || _load();
160}
161
162//----------------------------------------------------------------------
163// Public API implementation
164
165// The C API is just a thin wrapper. Each function obtains a pointer
166// to the singleton PropertyAliases, and calls the appropriate method
167// on it. If it cannot obtain a pointer, because valid data is not
168// available, then it returns NULL or UCHAR_INVALID_CODE.
169
170U_CAPI const char* U_EXPORT2
171u_getPropertyName(UProperty property,
172 UPropertyNameChoice nameChoice) {
173 return load() ? PNAME->getPropertyName(property, nameChoice)
174 : NULL;
175}
176
177U_CAPI UProperty U_EXPORT2
178u_getPropertyEnum(const char* alias) {
179 UProperty p = load() ? (UProperty) PNAME->getPropertyEnum(alias)
180 : UCHAR_INVALID_CODE;
181 return p;
182}
183
184U_CAPI const char* U_EXPORT2
185u_getPropertyValueName(UProperty property,
186 int32_t value,
187 UPropertyNameChoice nameChoice) {
188 return load() ? PNAME->getPropertyValueName(property, value, nameChoice)
189 : NULL;
190}
191
192U_CAPI int32_t U_EXPORT2
193u_getPropertyValueEnum(UProperty property,
194 const char* alias) {
195 return load() ? PNAME->getPropertyValueEnum(property, alias)
196 : UCHAR_INVALID_CODE;
197}
198
199//eof