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 31struct 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 46U_CFUNC const UBiDiProps * 47ubidi_getSingleton() { 48 return &ubidi_props_singleton; 49} 50 51/* set of property starts for UnicodeSet ------------------------------------ */ 52 53static 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 61U_CFUNC void 62ubidi_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 108U_CFUNC int32_t 109ubidi_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 129U_CAPI UCharDirection 130ubidi_getClass(const UBiDiProps *bdp, UChar32 c) { 131 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 132 return (UCharDirection)UBIDI_GET_CLASS(props); 133} 134 135U_CFUNC UBool 136ubidi_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 141U_CFUNC UChar32 142ubidi_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 174U_CFUNC UBool 175ubidi_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 180U_CFUNC UBool 181ubidi_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 186U_CFUNC UJoiningType 187ubidi_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 192U_CFUNC UJoiningGroup 193ubidi_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 207U_CFUNC UCharDirection 208u_charDirection(UChar32 c) { 209 return ubidi_getClass(&ubidi_props_singleton, c); 210} 211 212U_CFUNC UBool 213u_isMirrored(UChar32 c) { 214 return ubidi_isMirrored(&ubidi_props_singleton, c); 215} 216 217U_CFUNC UChar32 218u_charMirror(UChar32 c) { 219 return ubidi_getMirror(&ubidi_props_singleton, c); 220} 221