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