if (U_FAILURE(status)) { return;
} // Do range checks only when warranted to save time if (anteContextPos < 0) {
anteContextLength = 0;
} else { if (anteContextPos > input.length()) { // throw new IllegalArgumentException("Invalid ante context");
status = U_ILLEGAL_ARGUMENT_ERROR; return;
}
anteContextLength = anteContextPos;
} if (postContextPos < 0) {
keyLength = input.length() - anteContextLength;
} else { if (postContextPos < anteContextLength ||
postContextPos > input.length()) { // throw new IllegalArgumentException("Invalid post context");
status = U_ILLEGAL_ARGUMENT_ERROR; return;
}
keyLength = postContextPos - anteContextLength;
} if (cursorPosition < 0) {
cursorPosition = outputStr.length();
} elseif (cursorPosition > outputStr.length()) { // throw new IllegalArgumentException("Invalid cursor position");
status = U_ILLEGAL_ARGUMENT_ERROR; return;
} // We don't validate the segments array. The caller must // guarantee that the segments are well-formed (that is, that // all $n references in the output refer to indices of this // array, and that no array elements are null).
this->segments = segs;
this->segmentsCount = segsCount;
pattern = input;
flags = 0; if (anchorStart) {
flags |= ANCHOR_START;
} if (anchorEnd) {
flags |= ANCHOR_END;
}
anteContext = nullptr; if (anteContextLength > 0) {
anteContext = new StringMatcher(pattern, 0, anteContextLength, false, *data); /* test for nullptr */ if (anteContext == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
}
key = nullptr; if (keyLength > 0) {
key = new StringMatcher(pattern, anteContextLength, anteContextLength + keyLength, false, *data); /* test for nullptr */ if (key == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
}
int32_t postContextLength = pattern.length() - keyLength - anteContextLength;
postContext = nullptr; if (postContextLength > 0) {
postContext = new StringMatcher(pattern, anteContextLength + keyLength, pattern.length(), false, *data); /* test for nullptr */ if (postContext == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
}
this->output = new StringReplacer(outputStr, cursorPosition + cursorOffset, data); /* test for nullptr */ if (this->output == nullptr) {
status = U_MEMORY_ALLOCATION_ERROR; return;
}
}
/** *Internalmethod.Returns8-bitindexvalueforthisrule. *Thisisthelowbyteofthefirstcharacterofthekey, *unlessthefirstcharacterofthekeyisaset.Ifit'sa *set,orotherwisecanmatchmultiplekeys,theindexvalueis-1.
*/
int16_t TransliterationRule::getIndexValue() const { if (anteContextLength == pattern.length()) { // A pattern with just ante context {such as foo)>bar} can // match any key. return -1;
}
UChar32 c = pattern.char32At(anteContextLength); return static_cast<int16_t>(data->lookupMatcher(c) == nullptr ? (c & 0xFF) : -1);
}
/** *Internalmethod.Returnstrueifthisrulematchesthegiven *indexvalue.Theindexvalueisan8-bitinteger,0..255, *representingthelowbyteofthefirstcharacterofthekey. *Itmatchesthisruleifitmatchesthefirstcharacterofthe *key,orifthefirstcharacterofthekeyisaset,andtheset *containsanycharacterwithalowbyteequaltotheindex *value.Iftherulecontainsonlyantecontext,asinfoo)>bar, *thenitwillmatchanykey.
*/
UBool TransliterationRule::matchesIndexValue(uint8_t v) const { // Delegate to the key, or if there is none, to the postContext. // If there is neither then we match any key; return true.
UnicodeMatcher *m = (key != nullptr) ? key : postContext; return (m != nullptr) ? m->matchesIndexValue(v) : true;
}
/* LIMITATION of the current mask algorithm: Some rule *maskingsarecurrentlynotdetected.Forexample, *"{Lu}]a>x"masks"A]a>y".Thiscanbeaddedlater.TODO
*/
int32_t len = pattern.length();
int32_t left = anteContextLength;
int32_t left2 = r2.anteContextLength;
int32_t right = len - left;
int32_t right2 = r2.pattern.length() - left2;
int32_t cachedCompare = r2.pattern.compare(left2 - left, len, pattern);
// TODO Clean this up -- some logic might be combinable with the // next statement.
// Test for anchor masking if (left == left2 && right == right2 &&
keyLength <= r2.keyLength && 0 == cachedCompare) { // The following boolean logic implements the table above return (flags == r2.flags) ||
(!(flags & ANCHOR_START) && !(flags & ANCHOR_END)) ||
((r2.flags & ANCHOR_START) && (r2.flags & ANCHOR_END));
}
/** *Attemptamatchandreplacementatthegivenposition.Return *thedegreeofmatchbetweenthisruleandthegiventext.The *degreeofmatchmaybemismatch,apartialmatch,orafull *match.Amismatchmeansatleastonecharacterofthetext *doesnotmatchthecontextorkey.Apartialmatchmeanssome *contextandkeycharactersmatch,butthetextisnotlong *enoughtomatchallofthem.Afullmatchmeansallcontext *andkeycharactersmatch. * *Ifafullmatchisobtained,performareplacement,updatepos, *andreturnU_MATCH.Otherwisebothtextandposareunchanged. * *@paramtextthetext *@paramposthepositionindices *@paramincrementaliftrue,testforpartialmatchesthatmay *becompletedbyadditionaltextinsertedatpos.limit. *@returnoneof<code>U_MISMATCH</code>, *<code>U_PARTIAL_MATCH</code>,or<code>U_MATCH</code>.If *incrementalisfalsethenU_PARTIAL_MATCHwillnotbereturned.
*/
UMatchDegree TransliterationRule::matchAndReplace(Replaceable& text,
UTransPosition& pos,
UBool incremental) const { // Matching and replacing are done in one method because the // replacement operation needs information obtained during the // match. Another way to do this is to have the match method // create a match result struct with relevant offsets, and to pass // this into the replace method.
// ============================ MATCH ===========================
// Reset segment match data if (segments != nullptr) { for (int32_t i=0; i<segmentsCount; ++i) {
((StringMatcher*) segments[i])->resetMatch();
}
}
// int32_t lenDelta, keyLimit;
int32_t keyLimit;
// ------------------------ Ante Context ------------------------
// A mismatch in the ante context, or with the start anchor, // is an outright U_MISMATCH regardless of whether we are // incremental or not.
int32_t oText; // offset into 'text' // int32_t newStart = 0;
int32_t minOText;
// Note (1): We process text in 16-bit code units, rather than // 32-bit code points. This works because stand-ins are // always in the BMP and because we are doing a literal match // operation, which can be done 16-bits at a time.
// -------------------- Key and Post Context --------------------
oText = pos.start;
if (key != nullptr) {
match = key->matches(text, oText, pos.limit, incremental); if (match != U_MATCH) { return match;
}
}
keyLimit = oText;
if (postContext != nullptr) { if (incremental && keyLimit == pos.limit) { // The key matches just before pos.limit, and there is // a postContext. Since we are in incremental mode, // we must assume more characters may be inserted at // pos.limit -- this is a partial match. return U_PARTIAL_MATCH;
}
match = postContext->matches(text, oText, pos.contextLimit, incremental); if (match != U_MATCH) { return match;
}
}
// Accumulate special characters (and non-specials following them) // into quoteBuf. Append quoteBuf, within single quotes, when // a non-quoted element must be inserted.
UnicodeString str, quoteBuf;
// Do not emit the braces '{' '}' around the pattern if there // is neither anteContext nor postContext.
UBool emitBraces =
(anteContext != nullptr) || (postContext != nullptr);
void TransliterationRule::setData(const TransliterationRuleData* d) {
data = d; if (anteContext != nullptr) anteContext->setData(d); if (postContext != nullptr) postContext->setData(d); if (key != nullptr) key->setData(d); // assert(output != nullptr);
output->setData(d); // Don't have to do segments since they are in the context or key
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.