1999-11-20 00:40:50 +00:00
|
|
|
/*
|
|
|
|
**********************************************************************
|
|
|
|
* Copyright (C) 1999, International Business Machines
|
|
|
|
* Corporation and others. All Rights Reserved.
|
|
|
|
**********************************************************************
|
|
|
|
* Date Name Description
|
|
|
|
* 11/17/99 aliu Creation.
|
|
|
|
**********************************************************************
|
|
|
|
*/
|
1999-12-28 23:57:50 +00:00
|
|
|
#include "unicode/rbt.h"
|
1999-11-20 00:40:50 +00:00
|
|
|
#include "rbt_pars.h"
|
|
|
|
#include "rbt_data.h"
|
|
|
|
#include "rbt_rule.h"
|
1999-12-28 23:57:50 +00:00
|
|
|
#include "unicode/rep.h"
|
1999-11-20 00:40:50 +00:00
|
|
|
|
2001-10-08 23:26:58 +00:00
|
|
|
U_NAMESPACE_BEGIN
|
|
|
|
|
2001-10-11 23:54:55 +00:00
|
|
|
const char RuleBasedTransliterator::fgClassID = 0; // Value is irrelevant
|
2001-06-12 17:35:03 +00:00
|
|
|
|
1999-11-20 00:40:50 +00:00
|
|
|
void RuleBasedTransliterator::_construct(const UnicodeString& rules,
|
2000-06-27 19:00:38 +00:00
|
|
|
UTransDirection direction,
|
2001-08-31 03:23:39 +00:00
|
|
|
UParseError& parseError,
|
|
|
|
UErrorCode& status) {
|
1999-11-20 00:40:50 +00:00
|
|
|
data = 0;
|
|
|
|
isDataOwned = TRUE;
|
2001-10-10 19:29:45 +00:00
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return;
|
1999-11-20 00:40:50 +00:00
|
|
|
}
|
2001-10-10 19:29:45 +00:00
|
|
|
|
|
|
|
TransliteratorParser parser;
|
|
|
|
parser.parse(rules, direction, parseError, status);
|
|
|
|
if (U_FAILURE(status)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parser.idBlock.length() != 0 ||
|
|
|
|
parser.compoundFilter != NULL) {
|
|
|
|
status = U_INVALID_RBT_SYNTAX; // ::ID blocks disallowed in RBT
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
data = parser.orphanData();
|
|
|
|
setMaximumContextLength(data->ruleSet.getMaximumContextLength());
|
1999-11-20 00:40:50 +00:00
|
|
|
}
|
|
|
|
|
2000-09-30 00:06:54 +00:00
|
|
|
RuleBasedTransliterator::RuleBasedTransliterator(const UnicodeString& id,
|
1999-11-20 00:40:50 +00:00
|
|
|
const TransliterationRuleData* theData,
|
|
|
|
UnicodeFilter* adoptedFilter) :
|
2000-09-30 00:06:54 +00:00
|
|
|
Transliterator(id, adoptedFilter),
|
1999-11-20 01:04:34 +00:00
|
|
|
data((TransliterationRuleData*)theData), // cast away const
|
2000-01-18 18:27:27 +00:00
|
|
|
isDataOwned(FALSE) {
|
|
|
|
setMaximumContextLength(data->ruleSet.getMaximumContextLength());
|
|
|
|
}
|
1999-11-20 00:40:50 +00:00
|
|
|
|
2001-07-13 21:09:41 +00:00
|
|
|
/**
|
|
|
|
* Internal constructor.
|
|
|
|
*/
|
|
|
|
RuleBasedTransliterator::RuleBasedTransliterator(const UnicodeString& id,
|
|
|
|
TransliterationRuleData* theData,
|
|
|
|
UBool isDataAdopted) :
|
|
|
|
Transliterator(id, 0),
|
|
|
|
data(theData),
|
|
|
|
isDataOwned(isDataAdopted) {
|
|
|
|
setMaximumContextLength(data->ruleSet.getMaximumContextLength());
|
|
|
|
}
|
|
|
|
|
1999-11-20 00:40:50 +00:00
|
|
|
/**
|
|
|
|
* Copy constructor. Since the data object is immutable, we can share
|
|
|
|
* it with other objects -- no need to clone it.
|
|
|
|
*/
|
|
|
|
RuleBasedTransliterator::RuleBasedTransliterator(
|
|
|
|
const RuleBasedTransliterator& other) :
|
2000-06-30 23:26:07 +00:00
|
|
|
Transliterator(other), data(other.data),
|
|
|
|
isDataOwned(other.isDataOwned) {
|
|
|
|
|
|
|
|
// Only do a deep copy if this is non-owned data, that is,
|
|
|
|
// data that will be later deleted. System transliterators
|
|
|
|
// contain owned data.
|
|
|
|
if (isDataOwned) {
|
|
|
|
data = new TransliterationRuleData(*other.data);
|
2000-01-18 18:27:27 +00:00
|
|
|
}
|
1999-11-20 01:04:34 +00:00
|
|
|
}
|
1999-11-20 00:40:50 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Destructor. We do NOT own the data object, so we do not delete it.
|
|
|
|
*/
|
1999-11-20 01:04:34 +00:00
|
|
|
RuleBasedTransliterator::~RuleBasedTransliterator() {
|
|
|
|
if (isDataOwned) {
|
|
|
|
delete data;
|
|
|
|
}
|
|
|
|
}
|
1999-11-20 00:40:50 +00:00
|
|
|
|
|
|
|
Transliterator* // Covariant return NOT ALLOWED (for portability)
|
1999-12-22 22:57:04 +00:00
|
|
|
RuleBasedTransliterator::clone(void) const {
|
1999-11-20 00:40:50 +00:00
|
|
|
return new RuleBasedTransliterator(*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2000-01-19 19:12:42 +00:00
|
|
|
* Implements {@link Transliterator#handleTransliterate}.
|
1999-11-20 00:40:50 +00:00
|
|
|
*/
|
2000-01-19 19:12:42 +00:00
|
|
|
void
|
2000-06-27 19:00:38 +00:00
|
|
|
RuleBasedTransliterator::handleTransliterate(Replaceable& text, UTransPosition& index,
|
2000-05-18 22:08:39 +00:00
|
|
|
UBool isIncremental) const {
|
2001-07-25 19:11:02 +00:00
|
|
|
/* We keep contextStart and contextLimit fixed the entire time,
|
|
|
|
* relative to the text -- contextLimit may move numerically if
|
|
|
|
* text is inserted or removed. The start offset moves toward
|
|
|
|
* limit, with replacements happening under it.
|
1999-11-20 00:40:50 +00:00
|
|
|
*
|
|
|
|
* Example: rules 1. ab>x|y
|
|
|
|
* 2. yc>z
|
|
|
|
*
|
2001-07-25 19:11:02 +00:00
|
|
|
* |eabcd begin - no match, advance start
|
|
|
|
* e|abcd match rule 1 - change text & adjust start
|
|
|
|
* ex|ycd match rule 2 - change text & adjust start
|
|
|
|
* exz|d no match, advance start
|
1999-11-20 00:40:50 +00:00
|
|
|
* exzd| done
|
|
|
|
*/
|
|
|
|
|
2000-02-12 02:05:36 +00:00
|
|
|
/* A rule like
|
|
|
|
* a>b|a
|
|
|
|
* creates an infinite loop. To prevent that, we put an arbitrary
|
|
|
|
* limit on the number of iterations that we take, one that is
|
|
|
|
* high enough that any reasonable rules are ok, but low enough to
|
|
|
|
* prevent a server from hanging. The limit is 16 times the
|
|
|
|
* number of characters n, unless n is so large that 16n exceeds a
|
|
|
|
* uint32_t.
|
|
|
|
*/
|
|
|
|
uint32_t loopCount = 0;
|
2000-06-29 00:18:43 +00:00
|
|
|
uint32_t loopLimit = index.limit - index.start;
|
2000-02-12 02:05:36 +00:00
|
|
|
if (loopLimit >= 0x10000000) {
|
|
|
|
loopLimit = 0xFFFFFFFF;
|
|
|
|
} else {
|
|
|
|
loopLimit <<= 4;
|
|
|
|
}
|
|
|
|
|
2001-07-25 19:11:02 +00:00
|
|
|
while (index.start < index.limit &&
|
|
|
|
loopCount <= loopLimit &&
|
|
|
|
data->ruleSet.transliterate(text, index, isIncremental)) {
|
|
|
|
++loopCount;
|
1999-11-20 00:40:50 +00:00
|
|
|
}
|
|
|
|
}
|
2001-06-12 17:35:03 +00:00
|
|
|
|
|
|
|
UnicodeString& RuleBasedTransliterator::toRules(UnicodeString& rulesSource,
|
|
|
|
UBool escapeUnprintable) const {
|
2001-07-25 19:11:02 +00:00
|
|
|
return data->ruleSet.toRules(rulesSource, escapeUnprintable);
|
2001-06-12 17:35:03 +00:00
|
|
|
}
|
2001-10-08 23:26:58 +00:00
|
|
|
|
|
|
|
U_NAMESPACE_END
|
|
|
|
|