~ubuntu-branches/ubuntu/gutsy/icu/gutsy-updates

« back to all changes in this revision

Viewing changes to source/i18n/unitohex.cpp

  • Committer: Package Import Robot
  • Author(s): Jay Berkenbilt
  • Date: 2005-11-19 11:29:31 UTC
  • mfrom: (1.1.2)
  • Revision ID: package-import@ubuntu.com-20051119112931-vcizkrp10tli4enw
Tags: 3.4-3
Explicitly build with g++ 3.4.  The current ICU fails its test suite
with 4.0 but not with 3.4.  Future versions should work properly with
4.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
**********************************************************************
3
 
*   Copyright (C) 1999-2001, International Business Machines
4
 
*   Corporation and others.  All Rights Reserved.
5
 
**********************************************************************
6
 
*   Date        Name        Description
7
 
*   11/17/99    aliu        Creation.
8
 
**********************************************************************
9
 
*/
10
 
#include "unicode/unitohex.h"
11
 
#include "unicode/rep.h"
12
 
#include "unicode/unifilt.h"
13
 
 
14
 
U_NAMESPACE_BEGIN
15
 
 
16
 
/**
17
 
 * ID for this transliterator.
18
 
 */
19
 
const char UnicodeToHexTransliterator::_ID[] = "Any-Hex";
20
 
 
21
 
const UChar UnicodeToHexTransliterator::HEX_DIGITS[32] = {
22
 
    // Use Unicode hex values for EBCDIC compatibility
23
 
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 01234567
24
 
    0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, // 89abcdef
25
 
    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, // 01234567
26
 
    0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, // 89ABCDEF
27
 
};
28
 
 
29
 
/**
30
 
 * Constructs a transliterator.
31
 
 */
32
 
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
33
 
                                const UnicodeString& thePattern,
34
 
                                UBool isUppercase,
35
 
                                UnicodeFilter* adoptedFilter,
36
 
                                UErrorCode& status) :
37
 
    Transliterator(_ID, adoptedFilter),
38
 
    uppercase(isUppercase) {
39
 
 
40
 
    if (U_FAILURE(status)) {
41
 
        return;
42
 
    }
43
 
    applyPattern(thePattern, status);
44
 
}
45
 
 
46
 
/**
47
 
 * Constructs a transliterator.
48
 
 */
49
 
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
50
 
                                const UnicodeString& thePattern,
51
 
                                UErrorCode& status) :
52
 
    Transliterator(_ID, 0),
53
 
    uppercase(TRUE) {
54
 
 
55
 
    if (U_FAILURE(status)) {
56
 
        return;
57
 
    }
58
 
    applyPattern(thePattern, status);
59
 
}
60
 
 
61
 
/**
62
 
 * Constructs a transliterator with the default prefix "\u"
63
 
 * that outputs four uppercase hex digits.
64
 
 */
65
 
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
66
 
                                UnicodeFilter* adoptedFilter) :
67
 
    Transliterator(_ID, adoptedFilter),
68
 
    pattern("\\\\u0000", ""),
69
 
    prefix("\\u", 2, ""),
70
 
    suffix(),
71
 
    minDigits(4),
72
 
    uppercase(TRUE) {
73
 
}
74
 
 
75
 
/**
76
 
 * Copy constructor.
77
 
 */
78
 
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
79
 
                                const UnicodeToHexTransliterator& other) :
80
 
    Transliterator(other),
81
 
    pattern(other.pattern),
82
 
    prefix(other.prefix),
83
 
    suffix(other.suffix),
84
 
    minDigits(other.minDigits),
85
 
    uppercase(other.uppercase) {
86
 
}
87
 
 
88
 
/**
89
 
 * Assignment operator.
90
 
 */
91
 
UnicodeToHexTransliterator&
92
 
UnicodeToHexTransliterator::operator=(const UnicodeToHexTransliterator& other) {
93
 
    Transliterator::operator=(other);
94
 
    pattern = other.pattern;
95
 
    prefix = other.prefix;
96
 
    suffix = other.suffix;
97
 
    minDigits = other.minDigits;
98
 
    uppercase = other.uppercase;
99
 
    return *this;
100
 
}
101
 
 
102
 
Transliterator*
103
 
UnicodeToHexTransliterator::clone(void) const {
104
 
    return new UnicodeToHexTransliterator(*this);
105
 
}
106
 
 
107
 
void UnicodeToHexTransliterator::applyPattern(const UnicodeString& thePattern,
108
 
                                              UErrorCode& status) {
109
 
    if (U_FAILURE(status)) {
110
 
        return;
111
 
    }
112
 
 
113
 
    // POSSIBILE FUTURE MODIFICATION
114
 
    // Parse thePattern, and if this succeeds, set pattern to thePattern.
115
 
    // If it fails, call applyPattern(pattern) to restore the original
116
 
    // conditions.
117
 
 
118
 
    pattern = thePattern;
119
 
    prefix.truncate(0);
120
 
    suffix.truncate(0);
121
 
    minDigits = 0;
122
 
    int32_t maxDigits = 0;
123
 
 
124
 
    /* The mode specifies where we are in each spec.
125
 
     * mode 0 = in prefix
126
 
     * mode 1 = in optional digits (#)
127
 
     * mode 2 = in required digits (0)
128
 
     * mode 3 = in suffix
129
 
     */
130
 
    int32_t mode = 0;
131
 
 
132
 
    for (int32_t i=0; i<pattern.length(); ++i) {
133
 
        UChar c = pattern.charAt(i);
134
 
        UBool isLiteral = FALSE;
135
 
        if (c == BACKSLASH) {
136
 
            if ((i+1)<pattern.length()) {
137
 
                isLiteral = TRUE;
138
 
                c = pattern.charAt(++i);
139
 
            } else {
140
 
                // Trailing '\\'
141
 
                status = U_ILLEGAL_ARGUMENT_ERROR;
142
 
                return;
143
 
            }
144
 
        }
145
 
 
146
 
        if (!isLiteral) {
147
 
            switch (c) {
148
 
            case POUND:
149
 
                // Seeing a '#' moves us from mode 0 (prefix) to mode 1
150
 
                // (optional digits).
151
 
                if (mode == 0) {
152
 
                    ++mode;
153
 
                } else if (mode != 1) {
154
 
                    // Unquoted '#'
155
 
                    status = U_ILLEGAL_ARGUMENT_ERROR;
156
 
                    return;
157
 
                }
158
 
                ++maxDigits;
159
 
                break;
160
 
            case ZERO:
161
 
                // Seeing a '0' moves us to mode 2 (required digits)
162
 
                if (mode < 2) {
163
 
                    mode = 2;
164
 
                } else if (mode != 2) {
165
 
                    // Unquoted '0'
166
 
                    status = U_ILLEGAL_ARGUMENT_ERROR;
167
 
                    return;
168
 
                }
169
 
                ++minDigits;
170
 
                ++maxDigits;
171
 
                break;
172
 
            default:
173
 
                isLiteral = TRUE;
174
 
                break;
175
 
            }
176
 
        }
177
 
 
178
 
        if (isLiteral) {
179
 
            if (mode == 0) {
180
 
                prefix.append(c);
181
 
            } else {
182
 
                // Any literal outside the prefix moves us into mode 3
183
 
                // (suffix)
184
 
                mode = 3;
185
 
                suffix.append(c);
186
 
            }
187
 
        }
188
 
    }
189
 
 
190
 
    if (minDigits < 1 || maxDigits > 4) {
191
 
        // Invalid min/max digit count
192
 
        status = U_ILLEGAL_ARGUMENT_ERROR;
193
 
        return;
194
 
    }
195
 
}
196
 
 
197
 
const UnicodeString& UnicodeToHexTransliterator::toPattern(void) const {
198
 
    return pattern;
199
 
}
200
 
 
201
 
/**
202
 
 * Returns true if this transliterator outputs uppercase hex digits.
203
 
 */
204
 
UBool UnicodeToHexTransliterator::isUppercase(void) const {
205
 
    return uppercase;
206
 
}
207
 
 
208
 
/**
209
 
 * Sets if this transliterator outputs uppercase hex digits.
210
 
 *
211
 
 * <p>Callers must take care if a transliterator is in use by
212
 
 * multiple threads.  The uppercase mode should not be changed by
213
 
 * one thread while another thread may be transliterating.
214
 
 * @param outputUppercase if true, then this transliterator
215
 
 * outputs uppercase hex digits.
216
 
 */
217
 
void UnicodeToHexTransliterator::setUppercase(UBool outputUppercase) {
218
 
    uppercase = outputUppercase;
219
 
}
220
 
 
221
 
/**
222
 
 * Implements {@link Transliterator#handleTransliterate}.
223
 
 */
224
 
void UnicodeToHexTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
225
 
                                                     UBool /*isIncremental*/) const {
226
 
    /**
227
 
     * Performs transliteration changing all characters to
228
 
     * Unicode hexadecimal escapes.  For example, '@' -> "U+0040",
229
 
     * assuming the prefix is "U+". 
230
 
     */
231
 
    int32_t cursor = offsets.start;
232
 
    int32_t limit = offsets.limit;
233
 
 
234
 
    UnicodeString hex;
235
 
 
236
 
    while (cursor < limit) {
237
 
        UChar c = text.charAt(cursor);
238
 
 
239
 
        hex = prefix;
240
 
        UBool showRest = FALSE;
241
 
        for (int32_t i=3; i>=0; --i) {
242
 
            /* Get each nibble from left to right */
243
 
            int32_t d = (c >> (i<<2)) & 0xF;
244
 
            if (showRest || (d != 0) || minDigits > i) {
245
 
                hex.append(HEX_DIGITS[uppercase ? (d|16) : d]);
246
 
                showRest = TRUE;
247
 
            }
248
 
        }
249
 
        hex.append(suffix);
250
 
 
251
 
        text.handleReplaceBetween(cursor, cursor+1, hex);
252
 
        int32_t len = hex.length();
253
 
        cursor += len; // Advance cursor by 1 and adjust for new text
254
 
        --len;
255
 
        limit += len;
256
 
    }
257
 
 
258
 
    offsets.contextLimit += limit - offsets.limit;
259
 
    offsets.limit = limit;
260
 
    offsets.start = cursor;
261
 
}
262
 
 
263
 
U_NAMESPACE_END
264