intl/icu/source/i18n/name2uni.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /*
     2 **********************************************************************
     3 *   Copyright (C) 2001-2011, International Business Machines
     4 *   Corporation and others.  All Rights Reserved.
     5 **********************************************************************
     6 *   Date        Name        Description
     7 *   06/07/01    aliu        Creation.
     8 **********************************************************************
     9 */
    11 #include "unicode/utypes.h"
    13 #if !UCONFIG_NO_TRANSLITERATION
    15 #include "unicode/unifilt.h"
    16 #include "unicode/uchar.h"
    17 #include "unicode/uniset.h"
    18 #include "unicode/utf16.h"
    19 #include "cmemory.h"
    20 #include "name2uni.h"
    21 #include "patternprops.h"
    22 #include "uprops.h"
    23 #include "uinvchar.h"
    24 #include "util.h"
    26 U_NAMESPACE_BEGIN
    28 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NameUnicodeTransliterator)
    30 static const UChar OPEN[] = {92,78,126,123,126,0}; // "\N~{~"
    31 static const UChar OPEN_DELIM  = 92;  // '\\' first char of OPEN
    32 static const UChar CLOSE_DELIM = 125; // '}'
    33 static const UChar SPACE       = 32;  // ' '
    35 U_CDECL_BEGIN
    37 // USetAdder implementation
    38 // Does not use uset.h to reduce code dependencies
    39 static void U_CALLCONV
    40 _set_add(USet *set, UChar32 c) {
    41     uset_add(set, c);
    42 }
    44 // These functions aren't used.
    45 /*static void U_CALLCONV
    46 _set_addRange(USet *set, UChar32 start, UChar32 end) {
    47     ((UnicodeSet *)set)->add(start, end);
    48 }
    50 static void U_CALLCONV
    51 _set_addString(USet *set, const UChar *str, int32_t length) {
    52     ((UnicodeSet *)set)->add(UnicodeString((UBool)(length<0), str, length));
    53 }*/
    55 U_CDECL_END
    57 /**
    58  * Constructs a transliterator with the default delimiters '{' and
    59  * '}'.
    60  */
    61 NameUnicodeTransliterator::NameUnicodeTransliterator(UnicodeFilter* adoptedFilter) :
    62     Transliterator(UNICODE_STRING("Name-Any", 8), adoptedFilter) {
    64     UnicodeSet *legalPtr = &legal;
    65     // Get the legal character set
    66     USetAdder sa = {
    67         (USet *)legalPtr, // USet* == UnicodeSet*
    68         _set_add,
    69         NULL, // Don't need _set_addRange
    70         NULL, // Don't need _set_addString
    71         NULL, // Don't need remove()
    72         NULL
    73     };
    74     uprv_getCharNameCharacters(&sa);
    75 }
    77 /**
    78  * Destructor.
    79  */
    80 NameUnicodeTransliterator::~NameUnicodeTransliterator() {}
    82 /**
    83  * Copy constructor.
    84  */
    85 NameUnicodeTransliterator::NameUnicodeTransliterator(const NameUnicodeTransliterator& o) :
    86     Transliterator(o), legal(o.legal) {}
    88 /**
    89  * Assignment operator.
    90  */
    91 /*NameUnicodeTransliterator& NameUnicodeTransliterator::operator=(
    92                              const NameUnicodeTransliterator& o) {
    93     Transliterator::operator=(o);
    94     // not necessary: the legal sets should all be the same -- legal=o.legal;
    95     return *this;
    96 }*/
    98 /**
    99  * Transliterator API.
   100  */
   101 Transliterator* NameUnicodeTransliterator::clone(void) const {
   102     return new NameUnicodeTransliterator(*this);
   103 }
   105 /**
   106  * Implements {@link Transliterator#handleTransliterate}.
   107  */
   108 void NameUnicodeTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
   109                                                     UBool isIncremental) const {
   110     // The failure mode, here and below, is to behave like Any-Null,
   111     // if either there is no name data (max len == 0) or there is no
   112     // memory (malloc() => NULL).
   114     int32_t maxLen = uprv_getMaxCharNameLength();
   115     if (maxLen == 0) {
   116         offsets.start = offsets.limit;
   117         return;
   118     }
   120     // Accomodate the longest possible name
   121     ++maxLen; // allow for temporary trailing space
   122     char* cbuf = (char*) uprv_malloc(maxLen);
   123     if (cbuf == NULL) {
   124         offsets.start = offsets.limit;
   125         return;
   126     }
   128     UnicodeString openPat(TRUE, OPEN, -1);
   129     UnicodeString str, name;
   131     int32_t cursor = offsets.start;
   132     int32_t limit = offsets.limit;
   134     // Modes:
   135     // 0 - looking for open delimiter
   136     // 1 - after open delimiter
   137     int32_t mode = 0;
   138     int32_t openPos = -1; // open delim candidate pos
   140     UChar32 c;
   141     while (cursor < limit) {
   142         c = text.char32At(cursor);
   144         switch (mode) {
   145         case 0: // looking for open delimiter
   146             if (c == OPEN_DELIM) { // quick check first
   147                 openPos = cursor;
   148                 int32_t i =
   149                     ICU_Utility::parsePattern(openPat, text, cursor, limit);
   150                 if (i >= 0 && i < limit) {
   151                     mode = 1;
   152                     name.truncate(0);
   153                     cursor = i;
   154                     continue; // *** reprocess char32At(cursor)
   155                 }
   156             }
   157             break;
   159         case 1: // after open delimiter
   160             // Look for legal chars.  If \s+ is found, convert it
   161             // to a single space.  If closeDelimiter is found, exit
   162             // the loop.  If any other character is found, exit the
   163             // loop.  If the limit is reached, exit the loop.
   165             // Convert \s+ => SPACE.  This assumes there are no
   166             // runs of >1 space characters in names.
   167             if (PatternProps::isWhiteSpace(c)) {
   168                 // Ignore leading whitespace
   169                 if (name.length() > 0 &&
   170                     name.charAt(name.length()-1) != SPACE) {
   171                     name.append(SPACE);
   172                     // If we are too long then abort.  maxLen includes
   173                     // temporary trailing space, so use '>'.
   174                     if (name.length() > maxLen) {
   175                         mode = 0;
   176                     }
   177                 }
   178                 break;
   179             }
   181             if (c == CLOSE_DELIM) {
   182                 int32_t len = name.length();
   184                 // Delete trailing space, if any
   185                 if (len > 0 &&
   186                     name.charAt(len-1) == SPACE) {
   187                     --len;
   188                 }
   190                 if (uprv_isInvariantUString(name.getBuffer(), len)) {
   191                     name.extract(0, len, cbuf, maxLen, US_INV);
   193                     UErrorCode status = U_ZERO_ERROR;
   194                     c = u_charFromName(U_EXTENDED_CHAR_NAME, cbuf, &status);
   195                     if (U_SUCCESS(status)) {
   196                         // Lookup succeeded
   198                         // assert(U16_LENGTH(CLOSE_DELIM) == 1);
   199                         cursor++; // advance over CLOSE_DELIM
   201                         str.truncate(0);
   202                         str.append(c);
   203                         text.handleReplaceBetween(openPos, cursor, str);
   205                         // Adjust indices for the change in the length of
   206                         // the string.  Do not assume that str.length() ==
   207                         // 1, in case of surrogates.
   208                         int32_t delta = cursor - openPos - str.length();
   209                         cursor -= delta;
   210                         limit -= delta;
   211                         // assert(cursor == openPos + str.length());
   212                     }
   213                 }
   214                 // If the lookup failed, we leave things as-is and
   215                 // still switch to mode 0 and continue.
   216                 mode = 0;
   217                 openPos = -1; // close off candidate
   218                 continue; // *** reprocess char32At(cursor)
   219             }
   221             // Check if c is a legal char.  We assume here that
   222             // legal.contains(OPEN_DELIM) is FALSE, so when we abort a
   223             // name, we don't have to go back to openPos+1.
   224             if (legal.contains(c)) {
   225                 name.append(c);
   226                 // If we go past the longest possible name then abort.
   227                 // maxLen includes temporary trailing space, so use '>='.
   228                 if (name.length() >= maxLen) {
   229                     mode = 0;
   230                 }
   231             }
   233             // Invalid character
   234             else {
   235                 --cursor; // Backup and reprocess this character
   236                 mode = 0;
   237             }
   239             break;
   240         }
   242         cursor += U16_LENGTH(c);
   243     }
   245     offsets.contextLimit += limit - offsets.limit;
   246     offsets.limit = limit;
   247     // In incremental mode, only advance the cursor up to the last
   248     // open delimiter candidate.
   249     offsets.start = (isIncremental && openPos >= 0) ? openPos : cursor;
   251     uprv_free(cbuf);
   252 }
   254 U_NAMESPACE_END
   256 #endif /* #if !UCONFIG_NO_TRANSLITERATION */

mercurial