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