1/* 2******************************************************************************* 3* 4* Copyright (C) 2004-2013, 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 "uassert.h" 25#include "cmemory.h" 26#include "utrie2.h" 27#include "ubidi_props.h" 28#include "ucln_cmn.h" 29 30struct UBiDiProps { 31 UDataMemory *mem; 32 const int32_t *indexes; 33 const uint32_t *mirrors; 34 const uint8_t *jgArray; 35 36 UTrie2 trie; 37 uint8_t formatVersion[4]; 38}; 39 40/* ubidi_props_data.h is machine-generated by genbidi --csource */ 41#define INCLUDED_FROM_UBIDI_PROPS_C 42#include "ubidi_props_data.h" 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 case UCHAR_BIDI_PAIRED_BRACKET_TYPE: 125 return (max&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT; 126 default: 127 return -1; /* undefined */ 128 } 129} 130 131U_CAPI UCharDirection 132ubidi_getClass(const UBiDiProps *bdp, UChar32 c) { 133 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 134 return (UCharDirection)UBIDI_GET_CLASS(props); 135} 136 137U_CFUNC UBool 138ubidi_isMirrored(const UBiDiProps *bdp, UChar32 c) { 139 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 140 return (UBool)UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT); 141} 142 143static UChar32 144getMirror(const UBiDiProps *bdp, UChar32 c, uint16_t props) { 145 int32_t delta=UBIDI_GET_MIRROR_DELTA(props); 146 if(delta!=UBIDI_ESC_MIRROR_DELTA) { 147 return c+delta; 148 } else { 149 /* look for mirror code point in the mirrors[] table */ 150 const uint32_t *mirrors; 151 uint32_t m; 152 int32_t i, length; 153 UChar32 c2; 154 155 mirrors=bdp->mirrors; 156 length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH]; 157 158 /* linear search */ 159 for(i=0; i<length; ++i) { 160 m=mirrors[i]; 161 c2=UBIDI_GET_MIRROR_CODE_POINT(m); 162 if(c==c2) { 163 /* found c, return its mirror code point using the index in m */ 164 return UBIDI_GET_MIRROR_CODE_POINT(mirrors[UBIDI_GET_MIRROR_INDEX(m)]); 165 } else if(c<c2) { 166 break; 167 } 168 } 169 170 /* c not found, return it itself */ 171 return c; 172 } 173} 174 175U_CFUNC UChar32 176ubidi_getMirror(const UBiDiProps *bdp, UChar32 c) { 177 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 178 return getMirror(bdp, c, props); 179} 180 181U_CFUNC UBool 182ubidi_isBidiControl(const UBiDiProps *bdp, UChar32 c) { 183 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 184 return (UBool)UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT); 185} 186 187U_CFUNC UBool 188ubidi_isJoinControl(const UBiDiProps *bdp, UChar32 c) { 189 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 190 return (UBool)UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT); 191} 192 193U_CFUNC UJoiningType 194ubidi_getJoiningType(const UBiDiProps *bdp, UChar32 c) { 195 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 196 return (UJoiningType)((props&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT); 197} 198 199U_CFUNC UJoiningGroup 200ubidi_getJoiningGroup(const UBiDiProps *bdp, UChar32 c) { 201 UChar32 start, limit; 202 203 start=bdp->indexes[UBIDI_IX_JG_START]; 204 limit=bdp->indexes[UBIDI_IX_JG_LIMIT]; 205 if(start<=c && c<limit) { 206 return (UJoiningGroup)bdp->jgArray[c-start]; 207 } else { 208 return U_JG_NO_JOINING_GROUP; 209 } 210} 211 212U_CFUNC UBidiPairedBracketType 213ubidi_getPairedBracketType(const UBiDiProps *bdp, UChar32 c) { 214 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 215 return (UBidiPairedBracketType)((props&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT); 216} 217 218U_CFUNC UChar32 219ubidi_getPairedBracket(const UBiDiProps *bdp, UChar32 c) { 220 uint16_t props=UTRIE2_GET16(&bdp->trie, c); 221 if((props&UBIDI_BPT_MASK)==0) { 222 return c; 223 } else { 224 return getMirror(bdp, c, props); 225 } 226} 227 228/* public API (see uchar.h) ------------------------------------------------- */ 229 230U_CFUNC UCharDirection 231u_charDirection(UChar32 c) { 232 return ubidi_getClass(&ubidi_props_singleton, c); 233} 234 235U_CFUNC UBool 236u_isMirrored(UChar32 c) { 237 return ubidi_isMirrored(&ubidi_props_singleton, c); 238} 239 240U_CFUNC UChar32 241u_charMirror(UChar32 c) { 242 return ubidi_getMirror(&ubidi_props_singleton, c); 243} 244 245U_STABLE UChar32 U_EXPORT2 246u_getBidiPairedBracket(UChar32 c) { 247 return ubidi_getPairedBracket(&ubidi_props_singleton, c); 248} 249