| 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 |  | 
|---|