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