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