michael@0: /* michael@0: ******************************************************************************* michael@0: * michael@0: * Copyright (C) 2004-2013, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: * michael@0: ******************************************************************************* michael@0: * file name: ubidi_props.c michael@0: * encoding: US-ASCII michael@0: * tab size: 8 (not used) michael@0: * indentation:4 michael@0: * michael@0: * created on: 2004dec30 michael@0: * created by: Markus W. Scherer michael@0: * michael@0: * Low-level Unicode bidi/shaping properties access. michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "unicode/uset.h" michael@0: #include "unicode/udata.h" /* UDataInfo */ michael@0: #include "ucmndata.h" /* DataHeader */ michael@0: #include "udatamem.h" michael@0: #include "uassert.h" michael@0: #include "cmemory.h" michael@0: #include "utrie2.h" michael@0: #include "ubidi_props.h" michael@0: #include "ucln_cmn.h" michael@0: michael@0: struct UBiDiProps { michael@0: UDataMemory *mem; michael@0: const int32_t *indexes; michael@0: const uint32_t *mirrors; michael@0: const uint8_t *jgArray; michael@0: michael@0: UTrie2 trie; michael@0: uint8_t formatVersion[4]; michael@0: }; michael@0: michael@0: /* ubidi_props_data.h is machine-generated by genbidi --csource */ michael@0: #define INCLUDED_FROM_UBIDI_PROPS_C michael@0: #include "ubidi_props_data.h" michael@0: michael@0: /* UBiDiProps singleton ----------------------------------------------------- */ michael@0: michael@0: U_CFUNC const UBiDiProps * michael@0: ubidi_getSingleton() { michael@0: return &ubidi_props_singleton; michael@0: } michael@0: michael@0: /* set of property starts for UnicodeSet ------------------------------------ */ michael@0: michael@0: static UBool U_CALLCONV michael@0: _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) { michael@0: /* add the start code point to the USet */ michael@0: const USetAdder *sa=(const USetAdder *)context; michael@0: sa->add(sa->set, start); michael@0: return TRUE; michael@0: } michael@0: michael@0: U_CFUNC void michael@0: ubidi_addPropertyStarts(const UBiDiProps *bdp, const USetAdder *sa, UErrorCode *pErrorCode) { michael@0: int32_t i, length; michael@0: UChar32 c, start, limit; michael@0: michael@0: const uint8_t *jgArray; michael@0: uint8_t prev, jg; michael@0: michael@0: if(U_FAILURE(*pErrorCode)) { michael@0: return; michael@0: } michael@0: michael@0: /* add the start code point of each same-value range of the trie */ michael@0: utrie2_enum(&bdp->trie, NULL, _enumPropertyStartsRange, sa); michael@0: michael@0: /* add the code points from the bidi mirroring table */ michael@0: length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH]; michael@0: for(i=0; imirrors[i]); michael@0: sa->addRange(sa->set, c, c+1); michael@0: } michael@0: michael@0: /* add the code points from the Joining_Group array where the value changes */ michael@0: start=bdp->indexes[UBIDI_IX_JG_START]; michael@0: limit=bdp->indexes[UBIDI_IX_JG_LIMIT]; michael@0: jgArray=bdp->jgArray; michael@0: prev=0; michael@0: while(startadd(sa->set, start); michael@0: prev=jg; michael@0: } michael@0: ++start; michael@0: } michael@0: if(prev!=0) { michael@0: /* add the limit code point if the last value was not 0 (it is now start==limit) */ michael@0: sa->add(sa->set, limit); michael@0: } michael@0: michael@0: /* add code points with hardcoded properties, plus the ones following them */ michael@0: michael@0: /* (none right now) */ michael@0: } michael@0: michael@0: /* property access functions ------------------------------------------------ */ michael@0: michael@0: U_CFUNC int32_t michael@0: ubidi_getMaxValue(const UBiDiProps *bdp, UProperty which) { michael@0: int32_t max; michael@0: michael@0: if(bdp==NULL) { michael@0: return -1; michael@0: } michael@0: michael@0: max=bdp->indexes[UBIDI_MAX_VALUES_INDEX]; michael@0: switch(which) { michael@0: case UCHAR_BIDI_CLASS: michael@0: return (max&UBIDI_CLASS_MASK); michael@0: case UCHAR_JOINING_GROUP: michael@0: return (max&UBIDI_MAX_JG_MASK)>>UBIDI_MAX_JG_SHIFT; michael@0: case UCHAR_JOINING_TYPE: michael@0: return (max&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT; michael@0: case UCHAR_BIDI_PAIRED_BRACKET_TYPE: michael@0: return (max&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT; michael@0: default: michael@0: return -1; /* undefined */ michael@0: } michael@0: } michael@0: michael@0: U_CAPI UCharDirection michael@0: ubidi_getClass(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UCharDirection)UBIDI_GET_CLASS(props); michael@0: } michael@0: michael@0: U_CFUNC UBool michael@0: ubidi_isMirrored(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UBool)UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT); michael@0: } michael@0: michael@0: static UChar32 michael@0: getMirror(const UBiDiProps *bdp, UChar32 c, uint16_t props) { michael@0: int32_t delta=UBIDI_GET_MIRROR_DELTA(props); michael@0: if(delta!=UBIDI_ESC_MIRROR_DELTA) { michael@0: return c+delta; michael@0: } else { michael@0: /* look for mirror code point in the mirrors[] table */ michael@0: const uint32_t *mirrors; michael@0: uint32_t m; michael@0: int32_t i, length; michael@0: UChar32 c2; michael@0: michael@0: mirrors=bdp->mirrors; michael@0: length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH]; michael@0: michael@0: /* linear search */ michael@0: for(i=0; itrie, c); michael@0: return getMirror(bdp, c, props); michael@0: } michael@0: michael@0: U_CFUNC UBool michael@0: ubidi_isBidiControl(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UBool)UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT); michael@0: } michael@0: michael@0: U_CFUNC UBool michael@0: ubidi_isJoinControl(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UBool)UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT); michael@0: } michael@0: michael@0: U_CFUNC UJoiningType michael@0: ubidi_getJoiningType(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UJoiningType)((props&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT); michael@0: } michael@0: michael@0: U_CFUNC UJoiningGroup michael@0: ubidi_getJoiningGroup(const UBiDiProps *bdp, UChar32 c) { michael@0: UChar32 start, limit; michael@0: michael@0: start=bdp->indexes[UBIDI_IX_JG_START]; michael@0: limit=bdp->indexes[UBIDI_IX_JG_LIMIT]; michael@0: if(start<=c && cjgArray[c-start]; michael@0: } else { michael@0: return U_JG_NO_JOINING_GROUP; michael@0: } michael@0: } michael@0: michael@0: U_CFUNC UBidiPairedBracketType michael@0: ubidi_getPairedBracketType(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: return (UBidiPairedBracketType)((props&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT); michael@0: } michael@0: michael@0: U_CFUNC UChar32 michael@0: ubidi_getPairedBracket(const UBiDiProps *bdp, UChar32 c) { michael@0: uint16_t props=UTRIE2_GET16(&bdp->trie, c); michael@0: if((props&UBIDI_BPT_MASK)==0) { michael@0: return c; michael@0: } else { michael@0: return getMirror(bdp, c, props); michael@0: } michael@0: } michael@0: michael@0: /* public API (see uchar.h) ------------------------------------------------- */ michael@0: michael@0: U_CFUNC UCharDirection michael@0: u_charDirection(UChar32 c) { michael@0: return ubidi_getClass(&ubidi_props_singleton, c); michael@0: } michael@0: michael@0: U_CFUNC UBool michael@0: u_isMirrored(UChar32 c) { michael@0: return ubidi_isMirrored(&ubidi_props_singleton, c); michael@0: } michael@0: michael@0: U_CFUNC UChar32 michael@0: u_charMirror(UChar32 c) { michael@0: return ubidi_getMirror(&ubidi_props_singleton, c); michael@0: } michael@0: michael@0: U_STABLE UChar32 U_EXPORT2 michael@0: u_getBidiPairedBracket(UChar32 c) { michael@0: return ubidi_getPairedBracket(&ubidi_props_singleton, c); michael@0: }