|
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 */ |