Home | History | Annotate | Download | only in common
      1 /*
      2 *******************************************************************************
      3 *
      4 *   Copyright (C) 2004-2014, 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 
     30 struct UBiDiProps {
     31     UDataMemory *mem;
     32     const int32_t *indexes;
     33     const uint32_t *mirrors;
     34     const uint8_t *jgArray;
     35     const uint8_t *jgArray2;
     36 
     37     UTrie2 trie;
     38     uint8_t formatVersion[4];
     39 };
     40 
     41 /* ubidi_props_data.h is machine-generated by genbidi --csource */
     42 #define INCLUDED_FROM_UBIDI_PROPS_C
     43 #include "ubidi_props_data.h"
     44 
     45 /* UBiDiProps singleton ----------------------------------------------------- */
     46 
     47 U_CFUNC const UBiDiProps *
     48 ubidi_getSingleton() {
     49     return &ubidi_props_singleton;
     50 }
     51 
     52 /* set of property starts for UnicodeSet ------------------------------------ */
     53 
     54 static UBool U_CALLCONV
     55 _enumPropertyStartsRange(const void *context, UChar32 start, UChar32 end, uint32_t value) {
     56     /* add the start code point to the USet */
     57     const USetAdder *sa=(const USetAdder *)context;
     58     sa->add(sa->set, start);
     59     return TRUE;
     60 }
     61 
     62 U_CFUNC void
     63 ubidi_addPropertyStarts(const UBiDiProps *bdp, const USetAdder *sa, UErrorCode *pErrorCode) {
     64     int32_t i, length;
     65     UChar32 c, start, limit;
     66 
     67     const uint8_t *jgArray;
     68     uint8_t prev, jg;
     69 
     70     if(U_FAILURE(*pErrorCode)) {
     71         return;
     72     }
     73 
     74     /* add the start code point of each same-value range of the trie */
     75     utrie2_enum(&bdp->trie, NULL, _enumPropertyStartsRange, sa);
     76 
     77     /* add the code points from the bidi mirroring table */
     78     length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH];
     79     for(i=0; i<length; ++i) {
     80         c=UBIDI_GET_MIRROR_CODE_POINT(bdp->mirrors[i]);
     81         sa->addRange(sa->set, c, c+1);
     82     }
     83 
     84     /* add the code points from the Joining_Group array where the value changes */
     85     start=bdp->indexes[UBIDI_IX_JG_START];
     86     limit=bdp->indexes[UBIDI_IX_JG_LIMIT];
     87     jgArray=bdp->jgArray;
     88     for(;;) {
     89         prev=0;
     90         while(start<limit) {
     91             jg=*jgArray++;
     92             if(jg!=prev) {
     93                 sa->add(sa->set, start);
     94                 prev=jg;
     95             }
     96             ++start;
     97         }
     98         if(prev!=0) {
     99             /* add the limit code point if the last value was not 0 (it is now start==limit) */
    100             sa->add(sa->set, limit);
    101         }
    102         if(limit==bdp->indexes[UBIDI_IX_JG_LIMIT]) {
    103             /* switch to the second Joining_Group range */
    104             start=bdp->indexes[UBIDI_IX_JG_START2];
    105             limit=bdp->indexes[UBIDI_IX_JG_LIMIT2];
    106             jgArray=bdp->jgArray2;
    107         } else {
    108             break;
    109         }
    110     }
    111 
    112     /* add code points with hardcoded properties, plus the ones following them */
    113 
    114     /* (none right now) */
    115 }
    116 
    117 /* property access functions ------------------------------------------------ */
    118 
    119 U_CFUNC int32_t
    120 ubidi_getMaxValue(const UBiDiProps *bdp, UProperty which) {
    121     int32_t max;
    122 
    123     if(bdp==NULL) {
    124         return -1;
    125     }
    126 
    127     max=bdp->indexes[UBIDI_MAX_VALUES_INDEX];
    128     switch(which) {
    129     case UCHAR_BIDI_CLASS:
    130         return (max&UBIDI_CLASS_MASK);
    131     case UCHAR_JOINING_GROUP:
    132         return (max&UBIDI_MAX_JG_MASK)>>UBIDI_MAX_JG_SHIFT;
    133     case UCHAR_JOINING_TYPE:
    134         return (max&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT;
    135     case UCHAR_BIDI_PAIRED_BRACKET_TYPE:
    136         return (max&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT;
    137     default:
    138         return -1; /* undefined */
    139     }
    140 }
    141 
    142 U_CAPI UCharDirection
    143 ubidi_getClass(const UBiDiProps *bdp, UChar32 c) {
    144     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    145     return (UCharDirection)UBIDI_GET_CLASS(props);
    146 }
    147 
    148 U_CFUNC UBool
    149 ubidi_isMirrored(const UBiDiProps *bdp, UChar32 c) {
    150     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    151     return (UBool)UBIDI_GET_FLAG(props, UBIDI_IS_MIRRORED_SHIFT);
    152 }
    153 
    154 static UChar32
    155 getMirror(const UBiDiProps *bdp, UChar32 c, uint16_t props) {
    156     int32_t delta=UBIDI_GET_MIRROR_DELTA(props);
    157     if(delta!=UBIDI_ESC_MIRROR_DELTA) {
    158         return c+delta;
    159     } else {
    160         /* look for mirror code point in the mirrors[] table */
    161         const uint32_t *mirrors;
    162         uint32_t m;
    163         int32_t i, length;
    164         UChar32 c2;
    165 
    166         mirrors=bdp->mirrors;
    167         length=bdp->indexes[UBIDI_IX_MIRROR_LENGTH];
    168 
    169         /* linear search */
    170         for(i=0; i<length; ++i) {
    171             m=mirrors[i];
    172             c2=UBIDI_GET_MIRROR_CODE_POINT(m);
    173             if(c==c2) {
    174                 /* found c, return its mirror code point using the index in m */
    175                 return UBIDI_GET_MIRROR_CODE_POINT(mirrors[UBIDI_GET_MIRROR_INDEX(m)]);
    176             } else if(c<c2) {
    177                 break;
    178             }
    179         }
    180 
    181         /* c not found, return it itself */
    182         return c;
    183     }
    184 }
    185 
    186 U_CFUNC UChar32
    187 ubidi_getMirror(const UBiDiProps *bdp, UChar32 c) {
    188     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    189     return getMirror(bdp, c, props);
    190 }
    191 
    192 U_CFUNC UBool
    193 ubidi_isBidiControl(const UBiDiProps *bdp, UChar32 c) {
    194     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    195     return (UBool)UBIDI_GET_FLAG(props, UBIDI_BIDI_CONTROL_SHIFT);
    196 }
    197 
    198 U_CFUNC UBool
    199 ubidi_isJoinControl(const UBiDiProps *bdp, UChar32 c) {
    200     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    201     return (UBool)UBIDI_GET_FLAG(props, UBIDI_JOIN_CONTROL_SHIFT);
    202 }
    203 
    204 U_CFUNC UJoiningType
    205 ubidi_getJoiningType(const UBiDiProps *bdp, UChar32 c) {
    206     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    207     return (UJoiningType)((props&UBIDI_JT_MASK)>>UBIDI_JT_SHIFT);
    208 }
    209 
    210 U_CFUNC UJoiningGroup
    211 ubidi_getJoiningGroup(const UBiDiProps *bdp, UChar32 c) {
    212     UChar32 start, limit;
    213 
    214     start=bdp->indexes[UBIDI_IX_JG_START];
    215     limit=bdp->indexes[UBIDI_IX_JG_LIMIT];
    216     if(start<=c && c<limit) {
    217         return (UJoiningGroup)bdp->jgArray[c-start];
    218     }
    219     start=bdp->indexes[UBIDI_IX_JG_START2];
    220     limit=bdp->indexes[UBIDI_IX_JG_LIMIT2];
    221     if(start<=c && c<limit) {
    222         return (UJoiningGroup)bdp->jgArray2[c-start];
    223     }
    224     return U_JG_NO_JOINING_GROUP;
    225 }
    226 
    227 U_CFUNC UBidiPairedBracketType
    228 ubidi_getPairedBracketType(const UBiDiProps *bdp, UChar32 c) {
    229     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    230     return (UBidiPairedBracketType)((props&UBIDI_BPT_MASK)>>UBIDI_BPT_SHIFT);
    231 }
    232 
    233 U_CFUNC UChar32
    234 ubidi_getPairedBracket(const UBiDiProps *bdp, UChar32 c) {
    235     uint16_t props=UTRIE2_GET16(&bdp->trie, c);
    236     if((props&UBIDI_BPT_MASK)==0) {
    237         return c;
    238     } else {
    239         return getMirror(bdp, c, props);
    240     }
    241 }
    242 
    243 /* public API (see uchar.h) ------------------------------------------------- */
    244 
    245 U_CFUNC UCharDirection
    246 u_charDirection(UChar32 c) {
    247     return ubidi_getClass(&ubidi_props_singleton, c);
    248 }
    249 
    250 U_CFUNC UBool
    251 u_isMirrored(UChar32 c) {
    252     return ubidi_isMirrored(&ubidi_props_singleton, c);
    253 }
    254 
    255 U_CFUNC UChar32
    256 u_charMirror(UChar32 c) {
    257     return ubidi_getMirror(&ubidi_props_singleton, c);
    258 }
    259 
    260 U_STABLE UChar32 U_EXPORT2
    261 u_getBidiPairedBracket(UChar32 c) {
    262     return ubidi_getPairedBracket(&ubidi_props_singleton, c);
    263 }
    264