ICU 73.2  73.2
ucptrie.h
Go to the documentation of this file.
00001 // © 2017 and later: Unicode, Inc. and others.
00002 // License & terms of use: http://www.unicode.org/copyright.html
00003 
00004 // ucptrie.h (modified from utrie2.h)
00005 // created: 2017dec29 Markus W. Scherer
00006 
00007 #ifndef __UCPTRIE_H__
00008 #define __UCPTRIE_H__
00009 
00010 #include "unicode/utypes.h"
00011 #include "unicode/ucpmap.h"
00012 #include "unicode/utf8.h"
00013 
00014 #if U_SHOW_CPLUSPLUS_API
00015 #include "unicode/localpointer.h"
00016 #endif   // U_SHOW_CPLUSPLUS_API
00017 
00018 U_CDECL_BEGIN
00019 
00028 #ifndef U_IN_DOXYGEN
00029 
00030 typedef union UCPTrieData {
00032     const void *ptr0;
00034     const uint16_t *ptr16;
00036     const uint32_t *ptr32;
00038     const uint8_t *ptr8;
00039 } UCPTrieData;
00040 #endif
00041 
00059 struct UCPTrie {
00060 #ifndef U_IN_DOXYGEN
00061 
00062     const uint16_t *index;
00064     UCPTrieData data;
00065 
00067     int32_t indexLength;
00069     int32_t dataLength;
00071     UChar32 highStart;
00073     uint16_t shifted12HighStart;
00074 
00076     int8_t type;  // UCPTrieType
00078     int8_t valueWidth;  // UCPTrieValueWidth
00079 
00081     uint32_t reserved32;
00083     uint16_t reserved16;
00084 
00090     uint16_t index3NullOffset;
00096     int32_t dataNullOffset;
00098     uint32_t nullValue;
00099 
00100 #ifdef UCPTRIE_DEBUG
00101 
00102     const char *name;
00103 #endif
00104 #endif
00105 };
00106 #ifndef U_IN_DOXYGEN
00107 typedef struct UCPTrie UCPTrie;
00108 #endif
00109 
00119 enum UCPTrieType {
00125     UCPTRIE_TYPE_ANY = -1,
00130     UCPTRIE_TYPE_FAST,
00135     UCPTRIE_TYPE_SMALL
00136 };
00137 #ifndef U_IN_DOXYGEN
00138 typedef enum UCPTrieType UCPTrieType;
00139 #endif
00140 
00149 enum UCPTrieValueWidth {
00155     UCPTRIE_VALUE_BITS_ANY = -1,
00161     UCPTRIE_VALUE_BITS_16,
00166     UCPTRIE_VALUE_BITS_32,
00172     UCPTRIE_VALUE_BITS_8
00173 };
00174 #ifndef U_IN_DOXYGEN
00175 typedef enum UCPTrieValueWidth UCPTrieValueWidth;
00176 #endif
00177 
00204 U_CAPI UCPTrie * U_EXPORT2
00205 ucptrie_openFromBinary(UCPTrieType type, UCPTrieValueWidth valueWidth,
00206                        const void *data, int32_t length, int32_t *pActualLength,
00207                        UErrorCode *pErrorCode);
00208 
00215 U_CAPI void U_EXPORT2
00216 ucptrie_close(UCPTrie *trie);
00217 
00227 U_CAPI UCPTrieType U_EXPORT2
00228 ucptrie_getType(const UCPTrie *trie);
00229 
00239 U_CAPI UCPTrieValueWidth U_EXPORT2
00240 ucptrie_getValueWidth(const UCPTrie *trie);
00241 
00256 U_CAPI uint32_t U_EXPORT2
00257 ucptrie_get(const UCPTrie *trie, UChar32 c);
00258 
00295 U_CAPI UChar32 U_EXPORT2
00296 ucptrie_getRange(const UCPTrie *trie, UChar32 start,
00297                  UCPMapRangeOption option, uint32_t surrogateValue,
00298                  UCPMapValueFilter *filter, const void *context, uint32_t *pValue);
00299 
00315 U_CAPI int32_t U_EXPORT2
00316 ucptrie_toBinary(const UCPTrie *trie, void *data, int32_t capacity, UErrorCode *pErrorCode);
00317 
00326 #define UCPTRIE_16(trie, i) ((trie)->data.ptr16[i])
00327 
00336 #define UCPTRIE_32(trie, i) ((trie)->data.ptr32[i])
00337 
00346 #define UCPTRIE_8(trie, i) ((trie)->data.ptr8[i])
00347 
00358 #define UCPTRIE_FAST_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_CP_INDEX(trie, 0xffff, c))
00359 
00370 #define UCPTRIE_SMALL_GET(trie, dataAccess, c) \
00371     dataAccess(trie, _UCPTRIE_CP_INDEX(trie, UCPTRIE_SMALL_MAX, c))
00372 
00386 #define UCPTRIE_FAST_U16_NEXT(trie, dataAccess, src, limit, c, result) UPRV_BLOCK_MACRO_BEGIN { \
00387     (c) = *(src)++; \
00388     int32_t __index; \
00389     if (!U16_IS_SURROGATE(c)) { \
00390         __index = _UCPTRIE_FAST_INDEX(trie, c); \
00391     } else { \
00392         uint16_t __c2; \
00393         if (U16_IS_SURROGATE_LEAD(c) && (src) != (limit) && U16_IS_TRAIL(__c2 = *(src))) { \
00394             ++(src); \
00395             (c) = U16_GET_SUPPLEMENTARY((c), __c2); \
00396             __index = _UCPTRIE_SMALL_INDEX(trie, c); \
00397         } else { \
00398             __index = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET; \
00399         } \
00400     } \
00401     (result) = dataAccess(trie, __index); \
00402 } UPRV_BLOCK_MACRO_END
00403 
00417 #define UCPTRIE_FAST_U16_PREV(trie, dataAccess, start, src, c, result) UPRV_BLOCK_MACRO_BEGIN { \
00418     (c) = *--(src); \
00419     int32_t __index; \
00420     if (!U16_IS_SURROGATE(c)) { \
00421         __index = _UCPTRIE_FAST_INDEX(trie, c); \
00422     } else { \
00423         uint16_t __c2; \
00424         if (U16_IS_SURROGATE_TRAIL(c) && (src) != (start) && U16_IS_LEAD(__c2 = *((src) - 1))) { \
00425             --(src); \
00426             (c) = U16_GET_SUPPLEMENTARY(__c2, (c)); \
00427             __index = _UCPTRIE_SMALL_INDEX(trie, c); \
00428         } else { \
00429             __index = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET; \
00430         } \
00431     } \
00432     (result) = dataAccess(trie, __index); \
00433 } UPRV_BLOCK_MACRO_END
00434 
00451 #define UCPTRIE_FAST_U8_NEXT(trie, dataAccess, src, limit, result) UPRV_BLOCK_MACRO_BEGIN { \
00452     int32_t __lead = (uint8_t)*(src)++; \
00453     if (!U8_IS_SINGLE(__lead)) { \
00454         uint8_t __t1, __t2, __t3; \
00455         if ((src) != (limit) && \
00456             (__lead >= 0xe0 ? \
00457                 __lead < 0xf0 ?  /* U+0800..U+FFFF except surrogates */ \
00458                     U8_LEAD3_T1_BITS[__lead &= 0xf] & (1 << ((__t1 = *(src)) >> 5)) && \
00459                     ++(src) != (limit) && (__t2 = *(src) - 0x80) <= 0x3f && \
00460                     (__lead = ((int32_t)(trie)->index[(__lead << 6) + (__t1 & 0x3f)]) + __t2, 1) \
00461                 :  /* U+10000..U+10FFFF */ \
00462                     (__lead -= 0xf0) <= 4 && \
00463                     U8_LEAD4_T1_BITS[(__t1 = *(src)) >> 4] & (1 << __lead) && \
00464                     (__lead = (__lead << 6) | (__t1 & 0x3f), ++(src) != (limit)) && \
00465                     (__t2 = *(src) - 0x80) <= 0x3f && \
00466                     ++(src) != (limit) && (__t3 = *(src) - 0x80) <= 0x3f && \
00467                     (__lead = __lead >= (trie)->shifted12HighStart ? \
00468                         (trie)->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET : \
00469                         ucptrie_internalSmallU8Index((trie), __lead, __t2, __t3), 1) \
00470             :  /* U+0080..U+07FF */ \
00471                 __lead >= 0xc2 && (__t1 = *(src) - 0x80) <= 0x3f && \
00472                 (__lead = (int32_t)(trie)->index[__lead & 0x1f] + __t1, 1))) { \
00473             ++(src); \
00474         } else { \
00475             __lead = (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET;  /* ill-formed*/ \
00476         } \
00477     } \
00478     (result) = dataAccess(trie, __lead); \
00479 } UPRV_BLOCK_MACRO_END
00480 
00497 #define UCPTRIE_FAST_U8_PREV(trie, dataAccess, start, src, result) UPRV_BLOCK_MACRO_BEGIN { \
00498     int32_t __index = (uint8_t)*--(src); \
00499     if (!U8_IS_SINGLE(__index)) { \
00500         __index = ucptrie_internalU8PrevIndex((trie), __index, (const uint8_t *)(start), \
00501                                               (const uint8_t *)(src)); \
00502         (src) -= __index & 7; \
00503         __index >>= 3; \
00504     } \
00505     (result) = dataAccess(trie, __index); \
00506 } UPRV_BLOCK_MACRO_END
00507 
00517 #define UCPTRIE_ASCII_GET(trie, dataAccess, c) dataAccess(trie, c)
00518 
00530 #define UCPTRIE_FAST_BMP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_FAST_INDEX(trie, c))
00531 
00542 #define UCPTRIE_FAST_SUPP_GET(trie, dataAccess, c) dataAccess(trie, _UCPTRIE_SMALL_INDEX(trie, c))
00543 
00544 /* Internal definitions ----------------------------------------------------- */
00545 
00546 #ifndef U_IN_DOXYGEN
00547 
00553 enum {
00555     UCPTRIE_FAST_SHIFT = 6,
00556 
00558     UCPTRIE_FAST_DATA_BLOCK_LENGTH = 1 << UCPTRIE_FAST_SHIFT,
00559 
00561     UCPTRIE_FAST_DATA_MASK = UCPTRIE_FAST_DATA_BLOCK_LENGTH - 1,
00562 
00564     UCPTRIE_SMALL_MAX = 0xfff,
00565 
00571     UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET = 1,
00577     UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET = 2
00578 };
00579 
00580 /* Internal functions and macros -------------------------------------------- */
00581 // Do not conditionalize with #ifndef U_HIDE_INTERNAL_API, needed for public API
00582 
00584 U_CAPI int32_t U_EXPORT2
00585 ucptrie_internalSmallIndex(const UCPTrie *trie, UChar32 c);
00586 
00588 U_CAPI int32_t U_EXPORT2
00589 ucptrie_internalSmallU8Index(const UCPTrie *trie, int32_t lt1, uint8_t t2, uint8_t t3);
00590 
00596 U_CAPI int32_t U_EXPORT2
00597 ucptrie_internalU8PrevIndex(const UCPTrie *trie, UChar32 c,
00598                             const uint8_t *start, const uint8_t *src);
00599 
00601 #define _UCPTRIE_FAST_INDEX(trie, c) \
00602     ((int32_t)(trie)->index[(c) >> UCPTRIE_FAST_SHIFT] + ((c) & UCPTRIE_FAST_DATA_MASK))
00603 
00605 #define _UCPTRIE_SMALL_INDEX(trie, c) \
00606     ((c) >= (trie)->highStart ? \
00607         (trie)->dataLength - UCPTRIE_HIGH_VALUE_NEG_DATA_OFFSET : \
00608         ucptrie_internalSmallIndex(trie, c))
00609 
00615 #define _UCPTRIE_CP_INDEX(trie, fastMax, c) \
00616     ((uint32_t)(c) <= (uint32_t)(fastMax) ? \
00617         _UCPTRIE_FAST_INDEX(trie, c) : \
00618         (uint32_t)(c) <= 0x10ffff ? \
00619             _UCPTRIE_SMALL_INDEX(trie, c) : \
00620             (trie)->dataLength - UCPTRIE_ERROR_VALUE_NEG_DATA_OFFSET)
00621 
00622 U_CDECL_END
00623 
00624 #endif  // U_IN_DOXYGEN
00625 
00626 #if U_SHOW_CPLUSPLUS_API
00627 
00628 U_NAMESPACE_BEGIN
00629 
00639 U_DEFINE_LOCAL_OPEN_POINTER(LocalUCPTriePointer, UCPTrie, ucptrie_close);
00640 
00641 U_NAMESPACE_END
00642 
00643 #endif  // U_SHOW_CPLUSPLUS_API
00644 
00645 #endif