#include "unicode/utypes.h"
#if !UCONFIG_NO_TRANSLITERATION
#include "unicode/rep.h"
#include "unicode/unifilt.h"
#include "unitohex.h"
U_NAMESPACE_BEGIN
const char UnicodeToHexTransliterator::fgClassID=0;
const char UnicodeToHexTransliterator::_ID[] = "Any-Hex";
const UChar UnicodeToHexTransliterator::HEX_DIGITS[32] = {
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, };
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
const UnicodeString& thePattern,
UBool isUppercase,
UnicodeFilter* adoptedFilter,
UErrorCode& status) :
Transliterator(_ID, adoptedFilter),
uppercase(isUppercase) {
if (U_FAILURE(status)) {
return;
}
applyPattern(thePattern, status);
}
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
const UnicodeString& thePattern,
UErrorCode& status) :
Transliterator(_ID, 0),
uppercase(TRUE) {
if (U_FAILURE(status)) {
return;
}
applyPattern(thePattern, status);
}
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
UnicodeFilter* adoptedFilter) :
Transliterator(_ID, adoptedFilter),
pattern("\\\\u0000", ""),
prefix("\\u", 2, ""),
suffix(),
minDigits(4),
uppercase(TRUE) {
}
UnicodeToHexTransliterator::UnicodeToHexTransliterator(
const UnicodeToHexTransliterator& other) :
Transliterator(other),
pattern(other.pattern),
prefix(other.prefix),
suffix(other.suffix),
minDigits(other.minDigits),
uppercase(other.uppercase) {
}
UnicodeToHexTransliterator&
UnicodeToHexTransliterator::operator=(const UnicodeToHexTransliterator& other) {
Transliterator::operator=(other);
pattern = other.pattern;
prefix = other.prefix;
suffix = other.suffix;
minDigits = other.minDigits;
uppercase = other.uppercase;
return *this;
}
Transliterator*
UnicodeToHexTransliterator::clone(void) const {
return new UnicodeToHexTransliterator(*this);
}
void UnicodeToHexTransliterator::applyPattern(const UnicodeString& thePattern,
UErrorCode& status) {
if (U_FAILURE(status)) {
return;
}
pattern = thePattern;
prefix.truncate(0);
suffix.truncate(0);
minDigits = 0;
int32_t maxDigits = 0;
int32_t mode = 0;
for (int32_t i=0; i<pattern.length(); ++i) {
UChar c = pattern.charAt(i);
UBool isLiteral = FALSE;
if (c == BACKSLASH) {
if ((i+1)<pattern.length()) {
isLiteral = TRUE;
c = pattern.charAt(++i);
} else {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
if (!isLiteral) {
switch (c) {
case POUND:
if (mode == 0) {
++mode;
} else if (mode != 1) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
++maxDigits;
break;
case ZERO:
if (mode < 2) {
mode = 2;
} else if (mode != 2) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
++minDigits;
++maxDigits;
break;
default:
isLiteral = TRUE;
break;
}
}
if (isLiteral) {
if (mode == 0) {
prefix.append(c);
} else {
mode = 3;
suffix.append(c);
}
}
}
if (minDigits < 1 || maxDigits > 4) {
status = U_ILLEGAL_ARGUMENT_ERROR;
return;
}
}
const UnicodeString& UnicodeToHexTransliterator::toPattern(void) const {
return pattern;
}
UBool UnicodeToHexTransliterator::isUppercase(void) const {
return uppercase;
}
void UnicodeToHexTransliterator::setUppercase(UBool outputUppercase) {
uppercase = outputUppercase;
}
void UnicodeToHexTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
UBool ) const {
int32_t cursor = offsets.start;
int32_t limit = offsets.limit;
UnicodeString hex;
while (cursor < limit) {
UChar c = text.charAt(cursor);
hex = prefix;
UBool showRest = FALSE;
for (int32_t i=3; i>=0; --i) {
int32_t d = (c >> (i<<2)) & 0xF;
if (showRest || (d != 0) || minDigits > i) {
hex.append(HEX_DIGITS[uppercase ? (d|16) : d]);
showRest = TRUE;
}
}
hex.append(suffix);
text.handleReplaceBetween(cursor, cursor+1, hex);
int32_t len = hex.length();
cursor += len; --len;
limit += len;
}
offsets.contextLimit += limit - offsets.limit;
offsets.limit = limit;
offsets.start = cursor;
}
U_NAMESPACE_END
#endif