1 // © 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