|
1 /* |
|
2 ******************************************************************************* |
|
3 * |
|
4 * Copyright (C) 2004-2013, International Business Machines |
|
5 * Corporation and others. All Rights Reserved. |
|
6 * |
|
7 ******************************************************************************* |
|
8 * file name: ubidi_props.c |
|
9 * encoding: US-ASCII |
|
10 * tab size: 8 (not used) |
|
11 * indentation:4 |
|
12 * |
|
13 * created on: 2004dec30 |
|
14 * created by: Markus W. Scherer |
|
15 * |
|
16 * Low-level Unicode bidi/shaping properties access. |
|
17 */ |
|
18 |
|
19 #include "unicode/utypes.h" |
|
20 #include "unicode/uset.h" |
|
21 #include "unicode/udata.h" /* UDataInfo */ |
|
22 #include "ucmndata.h" /* DataHeader */ |
|
23 #include "udatamem.h" |
|
24 #include "uassert.h" |
|
25 #include "cmemory.h" |
|
26 #include "utrie2.h" |
|
27 #include "ubidi_props.h" |
|
28 #include "ucln_cmn.h" |
|
29 |
|
30 struct UBiDiProps { |
|
31 UDataMemory *mem; |
|
32 const int32_t *indexes; |
|
33 const uint32_t *mirrors; |
|
34 const uint8_t *jgArray; |
|
35 |
|
36 UTrie2 trie; |
|
37 uint8_t formatVersion[4]; |
|
38 }; |
|
39 |
|
40 /* ubidi_props_data.h is machine-generated by genbidi --csource */ |
|
41 #define INCLUDED_FROM_UBIDI_PROPS_C |
|
42 #include "ubidi_props_data.h" |
|
43 |
|
44 /* UBiDiProps singleton ----------------------------------------------------- */ |
|
45 |
|
46 U_CFUNC const UBiDiProps * |
|
47 ubidi_getSingleton() { |
|
48 return &ubidi_props_singleton; |
|
49 } |
|
50 |
|
51 /* set of property starts for UnicodeSet ------------------------------------ */ |
|
52 |
|
53 static UBool U_CALLCONV |
|
54 _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { |
|
55 /* add the start code point to the USet */ |
|
56 const USetAdder *sa=(const USetAdder *)context; |
|
57 sa->add(sa->set, start); |
|
58 return TRUE; |
|
59 } |
|
60 |
|
61 U_CFUNC void |
|
62 ubidi_addPropertyStarts(const UBiDiProps *bdp, const USetAdder *sa, UErrorCode *pErrorCode) { |
|
63 int32_t i, length; |
|
64 UChar32 c, start, limit; |
|
65 |
|
66 const uint8_t *jgArray; |
|
67 uint8_t prev, jg; |
|
68 |
|
69 if(U_FAILURE(*pErrorCode)) { |
|
70 return; |
|
71 } |
|
72 |
|
73 /* add the start code point of each same-value range of the trie */ |
|
74 utrie2_enum(&bdp->trie, NULL, _enumPropertyStartsRange, sa); |
|
75 |
|
76 /* add the code points from the bidi mirroring table */ |
|
77 length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH]; |
|
78 for(i=0; i<length; ++i) { |
|
79 c=UBIDI_GET_MIRROR_CODE_POINT(bdp->mirrors[i]); |
|
80 sa->addRange(sa->set, c, c+1); |
|
81 } |
|
82 |
|
83 /* add the code points from the Joining_Group array where the value changes */ |
|
84 start=bdp->indexes[UBIDI_IX_JG_START]; |
|
85 limit=bdp->indexes[UBIDI_IX_JG_LIMIT]; |
|
86 jgArray=bdp->jgArray; |
|
87 prev=0; |
|
88 while(start<limit) { |
|
89 jg=*jgArray++; |
|
90 if(jg!=prev) { |
|
91 sa->add(sa->set, start); |
|
92 prev=jg; |
|
93 } |
|
94 ++start; |
|
95 } |
|
96 if(prev!=0) { |
|
97 /* add the limit code point if the last value was not 0 (it is now start==limit) */ |
|
98 sa->add(sa->set, limit); |
|
99 } |
|
100 |
|
101 /* add code points with hardcoded properties, plus the ones following them */ |
|
102 |
|
103 /* (none right now) */ |
|
104 } |
|
105 |
|
106 /* property access functions ------------------------------------------------ */ |
|
107 |
|
108 U_CFUNC int32_t |
|
109 ubidi_getMaxValue(const UBiDiProps *bdp, UProperty which) { |
|
110 int32_t max; |
|
111 |
|
112 if(bdp==NULL) { |
|
113 return -1; |
|
114 } |
|
115 |
|
116 max=bdp->indexes[UBIDI_MAX_VALUES_INDEX]; |
|
117 switch(which) { |
|
118 case UCHAR_BIDI_CLASS: |
|
119 return (max&UBIDI_CLASS_MASK); |
|
120 case UCHAR_JOINING_GROUP: |
|
121 return (max&UBIDI_MAX_JG_MASK)>>UBIDI_MAX_JG_SHIFT; |
|
122 case UCHAR_JOINING_TYPE: |
|
123 return (max&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT; |
|
124 case UCHAR_BIDI_PAIRED_BRACKET_TYPE: |
|
125 return (max&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT; |
|
126 default: |
|
127 return -1; /* undefined */ |
|
128 } |
|
129 } |
|
130 |
|
131 U_CAPI UCharDirection |
|
132 ubidi_getClass(const UBiDiProps *bdp, UChar32 c) { |
|
133 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
134 return (UCharDirection)UBIDI_GET_CLASS(props); |
|
135 } |
|
136 |
|
137 U_CFUNC UBool |
|
138 ubidi_isMirrored(const UBiDiProps *bdp, UChar32 c) { |
|
139 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
140 return (UBool)UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT); |
|
141 } |
|
142 |
|
143 static UChar32 |
|
144 getMirror(const UBiDiProps *bdp, UChar32 c, uint16_t props) { |
|
145 int32_t delta=UBIDI_GET_MIRROR_DELTA(props); |
|
146 if(delta!=UBIDI_ESC_MIRROR_DELTA) { |
|
147 return c+delta; |
|
148 } else { |
|
149 /* look for mirror code point in the mirrors[] table */ |
|
150 const uint32_t *mirrors; |
|
151 uint32_t m; |
|
152 int32_t i, length; |
|
153 UChar32 c2; |
|
154 |
|
155 mirrors=bdp->mirrors; |
|
156 length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH]; |
|
157 |
|
158 /* linear search */ |
|
159 for(i=0; i<length; ++i) { |
|
160 m=mirrors[i]; |
|
161 c2=UBIDI_GET_MIRROR_CODE_POINT(m); |
|
162 if(c==c2) { |
|
163 /* found c, return its mirror code point using the index in m */ |
|
164 return UBIDI_GET_MIRROR_CODE_POINT(mirrors[UBIDI_GET_MIRROR_INDEX(m)]); |
|
165 } else if(c<c2) { |
|
166 break; |
|
167 } |
|
168 } |
|
169 |
|
170 /* c not found, return it itself */ |
|
171 return c; |
|
172 } |
|
173 } |
|
174 |
|
175 U_CFUNC UChar32 |
|
176 ubidi_getMirror(const UBiDiProps *bdp, UChar32 c) { |
|
177 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
178 return getMirror(bdp, c, props); |
|
179 } |
|
180 |
|
181 U_CFUNC UBool |
|
182 ubidi_isBidiControl(const UBiDiProps *bdp, UChar32 c) { |
|
183 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
184 return (UBool)UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT); |
|
185 } |
|
186 |
|
187 U_CFUNC UBool |
|
188 ubidi_isJoinControl(const UBiDiProps *bdp, UChar32 c) { |
|
189 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
190 return (UBool)UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT); |
|
191 } |
|
192 |
|
193 U_CFUNC UJoiningType |
|
194 ubidi_getJoiningType(const UBiDiProps *bdp, UChar32 c) { |
|
195 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
196 return (UJoiningType)((props&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT); |
|
197 } |
|
198 |
|
199 U_CFUNC UJoiningGroup |
|
200 ubidi_getJoiningGroup(const UBiDiProps *bdp, UChar32 c) { |
|
201 UChar32 start, limit; |
|
202 |
|
203 start=bdp->indexes[UBIDI_IX_JG_START]; |
|
204 limit=bdp->indexes[UBIDI_IX_JG_LIMIT]; |
|
205 if(start<=c && c<limit) { |
|
206 return (UJoiningGroup)bdp->jgArray[c-start]; |
|
207 } else { |
|
208 return U_JG_NO_JOINING_GROUP; |
|
209 } |
|
210 } |
|
211 |
|
212 U_CFUNC UBidiPairedBracketType |
|
213 ubidi_getPairedBracketType(const UBiDiProps *bdp, UChar32 c) { |
|
214 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
215 return (UBidiPairedBracketType)((props&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT); |
|
216 } |
|
217 |
|
218 U_CFUNC UChar32 |
|
219 ubidi_getPairedBracket(const UBiDiProps *bdp, UChar32 c) { |
|
220 uint16_t props=UTRIE2_GET16(&bdp->trie, c); |
|
221 if((props&UBIDI_BPT_MASK)==0) { |
|
222 return c; |
|
223 } else { |
|
224 return getMirror(bdp, c, props); |
|
225 } |
|
226 } |
|
227 |
|
228 /* public API (see uchar.h) ------------------------------------------------- */ |
|
229 |
|
230 U_CFUNC UCharDirection |
|
231 u_charDirection(UChar32 c) { |
|
232 return ubidi_getClass(&ubidi_props_singleton, c); |
|
233 } |
|
234 |
|
235 U_CFUNC UBool |
|
236 u_isMirrored(UChar32 c) { |
|
237 return ubidi_isMirrored(&ubidi_props_singleton, c); |
|
238 } |
|
239 |
|
240 U_CFUNC UChar32 |
|
241 u_charMirror(UChar32 c) { |
|
242 return ubidi_getMirror(&ubidi_props_singleton, c); |
|
243 } |
|
244 |
|
245 U_STABLE UChar32 U_EXPORT2 |
|
246 u_getBidiPairedBracket(UChar32 c) { |
|
247 return ubidi_getPairedBracket(&ubidi_props_singleton, c); |
|
248 } |