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