michael@0: /* michael@0: ********************************************************************** michael@0: * Copyright (C) 2001-2011, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ********************************************************************** michael@0: * Date Name Description michael@0: * 06/06/01 aliu Creation. michael@0: ********************************************************************** michael@0: */ michael@0: michael@0: #include "unicode/utypes.h" michael@0: michael@0: #if !UCONFIG_NO_TRANSLITERATION michael@0: michael@0: #include "unicode/unifilt.h" michael@0: #include "unicode/uchar.h" michael@0: #include "unicode/utf16.h" michael@0: #include "uni2name.h" michael@0: #include "cstring.h" michael@0: #include "cmemory.h" michael@0: #include "uprops.h" michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UnicodeNameTransliterator) michael@0: michael@0: static const UChar OPEN_DELIM[] = {92,78,123,0}; // "\N{" michael@0: static const UChar CLOSE_DELIM = 125; // "}" michael@0: #define OPEN_DELIM_LEN 3 michael@0: michael@0: /** michael@0: * Constructs a transliterator. michael@0: */ michael@0: UnicodeNameTransliterator::UnicodeNameTransliterator(UnicodeFilter* adoptedFilter) : michael@0: Transliterator(UNICODE_STRING("Any-Name", 8), adoptedFilter) { michael@0: } michael@0: michael@0: /** michael@0: * Destructor. michael@0: */ michael@0: UnicodeNameTransliterator::~UnicodeNameTransliterator() {} michael@0: michael@0: /** michael@0: * Copy constructor. michael@0: */ michael@0: UnicodeNameTransliterator::UnicodeNameTransliterator(const UnicodeNameTransliterator& o) : michael@0: Transliterator(o) {} michael@0: michael@0: /** michael@0: * Assignment operator. michael@0: */ michael@0: /*UnicodeNameTransliterator& UnicodeNameTransliterator::operator=( michael@0: const UnicodeNameTransliterator& o) { michael@0: Transliterator::operator=(o); michael@0: return *this; michael@0: }*/ michael@0: michael@0: /** michael@0: * Transliterator API. michael@0: */ michael@0: Transliterator* UnicodeNameTransliterator::clone(void) const { michael@0: return new UnicodeNameTransliterator(*this); michael@0: } michael@0: michael@0: /** michael@0: * Implements {@link Transliterator#handleTransliterate}. michael@0: * Ignore isIncremental since we don't need the context, and michael@0: * we work on codepoints. michael@0: */ michael@0: void UnicodeNameTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets, michael@0: UBool /*isIncremental*/) const { michael@0: // The failure mode, here and below, is to behave like Any-Null, michael@0: // if either there is no name data (max len == 0) or there is no michael@0: // memory (malloc() => NULL). michael@0: michael@0: int32_t maxLen = uprv_getMaxCharNameLength(); michael@0: if (maxLen == 0) { michael@0: offsets.start = offsets.limit; michael@0: return; michael@0: } michael@0: michael@0: // Accomodate the longest possible name plus padding michael@0: char* buf = (char*) uprv_malloc(maxLen); michael@0: if (buf == NULL) { michael@0: offsets.start = offsets.limit; michael@0: return; michael@0: } michael@0: michael@0: int32_t cursor = offsets.start; michael@0: int32_t limit = offsets.limit; michael@0: michael@0: UnicodeString str(FALSE, OPEN_DELIM, OPEN_DELIM_LEN); michael@0: UErrorCode status; michael@0: int32_t len; michael@0: michael@0: while (cursor < limit) { michael@0: UChar32 c = text.char32At(cursor); michael@0: int32_t clen = U16_LENGTH(c); michael@0: status = U_ZERO_ERROR; michael@0: if ((len = u_charName(c, U_EXTENDED_CHAR_NAME, buf, maxLen, &status)) >0 && !U_FAILURE(status)) { michael@0: str.truncate(OPEN_DELIM_LEN); michael@0: str.append(UnicodeString(buf, len, US_INV)).append(CLOSE_DELIM); michael@0: text.handleReplaceBetween(cursor, cursor+clen, str); michael@0: len += OPEN_DELIM_LEN + 1; // adjust for delimiters michael@0: cursor += len; // advance cursor and adjust for new text michael@0: limit += len-clen; // change in length michael@0: } else { michael@0: cursor += clen; michael@0: } michael@0: } michael@0: michael@0: offsets.contextLimit += limit - offsets.limit; michael@0: offsets.limit = limit; michael@0: offsets.start = cursor; michael@0: michael@0: uprv_free(buf); michael@0: } michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: #endif /* #if !UCONFIG_NO_TRANSLITERATION */