Home | History | Annotate | Download | only in i18n
      1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 **********************************************************************
      5 *   Copyright (C) 2001-2011, International Business Machines
      6 *   Corporation and others.  All Rights Reserved.
      7 **********************************************************************
      8 *   Date        Name        Description
      9 *   06/06/01    aliu        Creation.
     10 **********************************************************************
     11 */
     12 
     13 #include "unicode/utypes.h"
     14 
     15 #if !UCONFIG_NO_TRANSLITERATION
     16 
     17 #include "unicode/unifilt.h"
     18 #include "unicode/uchar.h"
     19 #include "unicode/utf16.h"
     20 #include "uni2name.h"
     21 #include "cstring.h"
     22 #include "cmemory.h"
     23 #include "uprops.h"
     24 
     25 U_NAMESPACE_BEGIN
     26 
     27 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeNameTransliterator)
     28 
     29 static const UChar OPEN_DELIM[] = {92,78,123,0}; // "\N{"
     30 static const UChar CLOSE_DELIM  = 125; // "}"
     31 #define OPEN_DELIM_LEN 3
     32 
     33 /**
     34  * Constructs a transliterator.
     35  */
     36 UnicodeNameTransliterator::UnicodeNameTransliterator(UnicodeFilter* adoptedFilter) :
     37     Transliterator(UNICODE_STRING("Any-Name", 8), adoptedFilter) {
     38 }
     39 
     40 /**
     41  * Destructor.
     42  */
     43 UnicodeNameTransliterator::~UnicodeNameTransliterator() {}
     44 
     45 /**
     46  * Copy constructor.
     47  */
     48 UnicodeNameTransliterator::UnicodeNameTransliterator(const UnicodeNameTransliterator& o) :
     49     Transliterator(o) {}
     50 
     51 /**
     52  * Assignment operator.
     53  */
     54 /*UnicodeNameTransliterator& UnicodeNameTransliterator::operator=(
     55                              const UnicodeNameTransliterator& o) {
     56     Transliterator::operator=(o);
     57     return *this;
     58 }*/
     59 
     60 /**
     61  * Transliterator API.
     62  */
     63 Transliterator* UnicodeNameTransliterator::clone(void) const {
     64     return new UnicodeNameTransliterator(*this);
     65 }
     66 
     67 /**
     68  * Implements {@link Transliterator#handleTransliterate}.
     69  * Ignore isIncremental since we don't need the context, and
     70  * we work on codepoints.
     71  */
     72 void UnicodeNameTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
     73                                                     UBool /*isIncremental*/) const {
     74     // The failure mode, here and below, is to behave like Any-Null,
     75     // if either there is no name data (max len == 0) or there is no
     76     // memory (malloc() => NULL).
     77 
     78     int32_t maxLen = uprv_getMaxCharNameLength();
     79     if (maxLen == 0) {
     80         offsets.start = offsets.limit;
     81         return;
     82     }
     83 
     84     // Accomodate the longest possible name plus padding
     85     char* buf = (char*) uprv_malloc(maxLen);
     86     if (buf == NULL) {
     87         offsets.start = offsets.limit;
     88         return;
     89     }
     90 
     91     int32_t cursor = offsets.start;
     92     int32_t limit = offsets.limit;
     93 
     94     UnicodeString str(FALSE, OPEN_DELIM, OPEN_DELIM_LEN);
     95     UErrorCode status;
     96     int32_t len;
     97 
     98     while (cursor < limit) {
     99         UChar32 c = text.char32At(cursor);
    100         int32_t clen = U16_LENGTH(c);
    101         status = U_ZERO_ERROR;
    102         if ((len = u_charName(c, U_EXTENDED_CHAR_NAME, buf, maxLen, &status)) >0 && !U_FAILURE(status)) {
    103             str.truncate(OPEN_DELIM_LEN);
    104             str.append(UnicodeString(buf, len, US_INV)).append(CLOSE_DELIM);
    105             text.handleReplaceBetween(cursor, cursor+clen, str);
    106             len += OPEN_DELIM_LEN + 1; // adjust for delimiters
    107             cursor += len; // advance cursor and adjust for new text
    108             limit += len-clen; // change in length
    109         } else {
    110             cursor += clen;
    111         }
    112     }
    113 
    114     offsets.contextLimit += limit - offsets.limit;
    115     offsets.limit = limit;
    116     offsets.start = cursor;
    117 
    118     uprv_free(buf);
    119 }
    120 
    121 U_NAMESPACE_END
    122 
    123 #endif /* #if !UCONFIG_NO_TRANSLITERATION */
    124