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