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