#include "unicode/utypes.h"
#if !UCONFIG_NO_TRANSLITERATION
#include "unicode/uniset.h"
#include "unicode/uiter.h"
#include "nortrans.h"
#include "unormimp.h"
#include "mutex.h"
#include "ucln_in.h"
U_NAMESPACE_BEGIN
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(NormalizationTransliterator)
void NormalizationTransliterator::registerIDs() {
UErrorCode errorCode = U_ZERO_ERROR;
if(!unorm_haveData(&errorCode)) {
return;
}
Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFC"),
_create, integerToken(UNORM_NFC));
Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFKC"),
_create, integerToken(UNORM_NFKC));
Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFD"),
_create, integerToken(UNORM_NFD));
Transliterator::_registerFactory(UNICODE_STRING_SIMPLE("Any-NFKD"),
_create, integerToken(UNORM_NFKD));
Transliterator::_registerSpecialInverse(UNICODE_STRING_SIMPLE("NFC"),
UNICODE_STRING_SIMPLE("NFD"), TRUE);
Transliterator::_registerSpecialInverse(UNICODE_STRING_SIMPLE("NFKC"),
UNICODE_STRING_SIMPLE("NFKD"), TRUE);
}
Transliterator* NormalizationTransliterator::_create(const UnicodeString& ID,
Token context) {
return new NormalizationTransliterator(ID, (UNormalizationMode) context.integer, 0);
}
NormalizationTransliterator::NormalizationTransliterator(
const UnicodeString& id,
UNormalizationMode mode, int32_t opt) :
Transliterator(id, 0) {
fMode = mode;
options = opt;
}
NormalizationTransliterator::~NormalizationTransliterator() {
}
NormalizationTransliterator::NormalizationTransliterator(const NormalizationTransliterator& o) :
Transliterator(o) {
fMode = o.fMode;
options = o.options;
}
NormalizationTransliterator& NormalizationTransliterator::operator=(const NormalizationTransliterator& o) {
Transliterator::operator=(o);
fMode = o.fMode;
options = o.options;
return *this;
}
Transliterator* NormalizationTransliterator::clone(void) const {
return new NormalizationTransliterator(*this);
}
void NormalizationTransliterator::handleTransliterate(Replaceable& text, UTransPosition& offsets,
UBool isIncremental) const {
int32_t start = offsets.start;
int32_t limit = offsets.limit;
int32_t length, delta;
if(start >= limit) {
return;
}
UCharIterator iter;
uiter_setReplaceable(&iter, &text);
UnicodeString output;
UChar *buffer;
UBool neededToNormalize;
UErrorCode errorCode;
while(start < limit) {
iter.start = iter.index = start;
iter.limit = limit;
buffer = output.getBuffer(-1);
errorCode = U_ZERO_ERROR;
length = unorm_next(&iter, buffer, output.getCapacity(),
fMode, 0,
TRUE, &neededToNormalize,
&errorCode);
output.releaseBuffer(length);
if(errorCode == U_BUFFER_OVERFLOW_ERROR) {
iter.index = start;
buffer = output.getBuffer(length);
errorCode = U_ZERO_ERROR;
length = unorm_next(&iter, buffer, output.getCapacity(),
fMode, 0,
TRUE, &neededToNormalize,
&errorCode);
output.releaseBuffer(length);
}
if(U_FAILURE(errorCode)) {
break;
}
limit = iter.index;
if(isIncremental && limit == iter.limit) {
const UChar *s=output.getBuffer();
int32_t i=0, outLength=output.length();
UChar32 c;
while(i<outLength) {
U16_NEXT(s, i, outLength, c);
if(!unorm_isNFSkippable(c, fMode)) {
outLength=-1; break;
}
}
if (outLength<0) {
break;
}
}
if(neededToNormalize) {
text.handleReplaceBetween(start, limit, output);
delta = length - (limit - start); start = limit += delta; limit = offsets.limit += delta; offsets.contextLimit += delta;
} else {
start = limit;
limit = offsets.limit;
}
}
offsets.start = start;
}
U_NAMESPACE_END
#endif