ICU-770 Rewrote the memory logic (constructors, destructors, copy constructors, freeze, addRule) to make TransliterationRuleSet more flexible and to eliminate an obscure copy-constructore related leak.

X-SVN-Rev: 5992
This commit is contained in:
Alan Liu 2001-10-02 05:53:25 +00:00
parent 6637d7f8b3
commit 107a86f928
2 changed files with 39 additions and 22 deletions

View file

@ -45,28 +45,36 @@ static void maskingError(const TransliterationRule& rule1,
* Construct a new empty rule set.
*/
TransliterationRuleSet::TransliterationRuleSet(UErrorCode& status) {
maxContextLength = 0;
ruleVector = new UVector(status);
ruleVector->setDeleter(&_deleteRule);
ruleVector = new UVector(&_deleteRule, NULL, status);
rules = NULL;
maxContextLength = 0;
if (ruleVector == NULL) {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
/**
* Copy constructor. We assume that the ruleset being copied
* has already been frozen.
* Copy constructor.
*/
TransliterationRuleSet::TransliterationRuleSet(const TransliterationRuleSet& other) :
ruleVector(0),
rules(0),
maxContextLength(other.maxContextLength) {
int32_t i, len;
uprv_memcpy(index, other.index, sizeof(index));
int32_t len = index[256]; // see freeze()
rules = new TransliterationRule*[len];
for (int32_t i=0; i<len; ++i) {
rules[i] = new TransliterationRule(*other.rules[i]);
UErrorCode status = U_ZERO_ERROR;
ruleVector = new UVector(&_deleteRule, NULL, status);
if (other.ruleVector != 0 && ruleVector != 0 && U_SUCCESS(status)) {
len = other.ruleVector->size();
for (i=0; i<len && U_SUCCESS(status); ++i) {
ruleVector->addElement(new TransliterationRule(
*(TransliterationRule*)other.ruleVector->elementAt(i)), status);
}
}
if (other.rules != 0) {
UParseError p;
freeze(p, status);
}
}
@ -74,7 +82,7 @@ TransliterationRuleSet::TransliterationRuleSet(const TransliterationRuleSet& oth
* Destructor.
*/
TransliterationRuleSet::~TransliterationRuleSet() {
delete ruleVector;
delete ruleVector; // This deletes the contained rules
delete[] rules;
}
@ -101,6 +109,9 @@ int32_t TransliterationRuleSet::getMaximumContextLength(void) const {
* significant. The last call to this method must be followed by
* a call to <code>freeze()</code> before the rule set is used.
*
* <p>If freeze() has already been called, calling addRule()
* unfreezes the rules, and freeze() must be called again.
*
* @param adoptedRule the rule to add
*/
void TransliterationRuleSet::addRule(TransliterationRule* adoptedRule,
@ -116,7 +127,7 @@ void TransliterationRuleSet::addRule(TransliterationRule* adoptedRule,
maxContextLength = len;
}
delete[] rules; // Contains alias pointers
delete rules;
rules = 0;
}

View file

@ -23,30 +23,34 @@ class UnicodeString;
*/
class TransliterationRuleSet {
/**
* Vector of rules, in the order added. This is only used while the rule
* set is getting built. After that, freeze() reorders and indexes the
* rules into rules[]. However, the vector is kept until destruction.
* Vector of rules, in the order added. This is used while the
* rule set is getting built. After that, freeze() reorders and
* indexes the rules into rules[]. Any given rule is stored once
* in ruleVector, and one or more times in rules[]. ruleVector
* owns and deletes the rules.
*/
UVector* ruleVector;
/**
* Length of the longest preceding context
*/
int32_t maxContextLength;
/**
* Sorted and indexed table of rules. This is created by freeze() from
* the rules in ruleVector.
* Sorted and indexed table of rules. This is created by freeze()
* from the rules in ruleVector. It contains alias pointers to
* the rules in ruleVector. It is zero before freeze() is called
* and non-zero thereafter.
*/
TransliterationRule** rules;
/**
* Index table. For text having a first character c, compute x = c&0xFF.
* Now use rules[index[x]..index[x+1]-1]. This index table is created by
* freeze().
* freeze(). Before freeze() is called it contains garbage.
*/
int32_t index[257];
/**
* Length of the longest preceding context
*/
int32_t maxContextLength;
public:
/**
@ -80,6 +84,8 @@ public:
* Add a rule to this set. Rules are added in order, and order is
* significant. The last call to this method must be followed by
* a call to <code>freeze()</code> before the rule set is used.
* This method must <em>not</em> be called after freeze() has been
* called.
*
* @param adoptedRule the rule to add
*/