| 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=(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, NULL, _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 (UBool)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 (UBool)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 (UBool)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_STABLE UChar32 U_EXPORT2 |
| 252 | u_getBidiPairedBracket(UChar32 c) { |
| 253 | return ubidi_getPairedBracket(c); |
| 254 | } |
| 255 | |