ICU-11058 support nested collation rule imports; make the importer stateless

X-SVN-Rev: 36157
This commit is contained in:
Markus Scherer 2014-08-13 22:58:14 +00:00
parent 40682975b0
commit 435623bc05
7 changed files with 35 additions and 147 deletions

View File

@ -14,117 +14,7 @@ es{
collations{ collations{
search{ search{
Sequence{ Sequence{
"[normalization on][suppressContractions [เ-ไ ເ-ໄ ꪵ ꪶ ꪹ ꪻ ꪼ]]" "[import und-u-co-search]"
"&'='<'≠'"
"&ا"
"<<<<<<"
"<<آ"
"<<<ﺂ<<<ﺁ"
"<<أ"
"<<<ﺄ<<<ﺃ"
"<<إ"
"<<<ﺈ<<<ﺇ"
"&و"
"<<<ۥ"
"<<<ﻮ<<<ﻭ"
"<<ؤ"
"<<<ﺆ<<<ﺅ"
"&ي"
"<<<ۦ"
"<<<ﻳ<<<ﻴ<<<ﻲ<<<ﻱ"
"<<ئ"
"<<<ﺋ<<<ﺌ<<<ﺊ<<<ﺉ"
"<<ى"
"<<<ﯨ<<<ﯩ"
"<<<ﻰ<<<ﻯ"
"&ه"
"<<<<<<<<<<<<"
"<<ة"
"<<<ﺔ<<<ﺓ"
"&[last primary ignorable]<<׳"
"<<״"
"<<ـ"
"<<ฺ"
"&ᄀ"
"=ᆨ"
"&ᄀᄀ"
"=ᄁ=ᆩ"
"&ᄀᄉ"
"=ᆪ"
"&ᄂ"
"=ᆫ"
"&ᄂᄌ"
"=ᆬ"
"&ᄂᄒ"
"=ᆭ"
"&ᄃ"
"=ᆮ"
"&ᄃᄃ"
"=ᄄ"
"&ᄅ"
"=ᆯ"
"&ᄅᄀ"
"=ᆰ"
"&ᄅᄆ"
"=ᆱ"
"&ᄅᄇ"
"=ᆲ"
"&ᄅᄉ"
"=ᆳ"
"&ᄅᄐ"
"=ᆴ"
"&ᄅᄑ"
"=ᆵ"
"&ᄅᄒ"
"=ᆶ"
"&ᄆ"
"=ᆷ"
"&ᄇ"
"=ᆸ"
"&ᄇᄇ"
"=ᄈ"
"&ᄇᄉ"
"=ᆹ"
"&ᄉ"
"=ᆺ"
"&ᄉᄉ"
"=ᄊ=ᆻ"
"&ᄋ"
"=ᆼ"
"&ᄌ"
"=ᆽ"
"&ᄌᄌ"
"=ᄍ"
"&ᄎ"
"=ᆾ"
"&ᄏ"
"=ᆿ"
"&ᄐ"
"=ᇀ"
"&ᄑ"
"=ᇁ"
"&ᄒ"
"=ᇂ"
"&ᅡᅵ"
"=ᅢ"
"&ᅣᅵ"
"=ᅤ"
"&ᅥᅵ"
"=ᅦ"
"&ᅧᅵ"
"=ᅨ"
"&ᅩᅡ"
"=ᅪ"
"&ᅩᅡᅵ"
"=ᅫ"
"&ᅩᅵ"
"=ᅬ"
"&ᅮᅴ"
"=ᅯ"
"&ᅮᅴᅵ"
"=ᅰ"
"&ᅮᅵ"
"=ᅱ"
"&N<ñ<<<Ñ" "&N<ñ<<<Ñ"
} }
Version{"25"} Version{"25"}

View File

@ -54,26 +54,22 @@ namespace {
class BundleImporter : public CollationRuleParser::Importer { class BundleImporter : public CollationRuleParser::Importer {
public: public:
BundleImporter() : rules(NULL) {} BundleImporter() {}
virtual ~BundleImporter(); virtual ~BundleImporter();
virtual const UnicodeString *getRules( virtual void getRules(
const char *localeID, const char *collationType, const char *localeID, const char *collationType,
UnicodeString &rules,
const char *&errorReason, UErrorCode &errorCode); const char *&errorReason, UErrorCode &errorCode);
private:
UnicodeString *rules;
}; };
BundleImporter::~BundleImporter() { BundleImporter::~BundleImporter() {}
delete rules;
}
const UnicodeString * void
BundleImporter::getRules( BundleImporter::getRules(
const char *localeID, const char *collationType, const char *localeID, const char *collationType,
UnicodeString &rules,
const char *& /*errorReason*/, UErrorCode &errorCode) { const char *& /*errorReason*/, UErrorCode &errorCode) {
delete rules; CollationLoader::loadRules(localeID, collationType, rules, errorCode);
return rules = CollationLoader::loadRules(localeID, collationType, errorCode);
} }
} // namespace } // namespace

View File

@ -638,10 +638,9 @@ CollationRuleParser::parseSetting(UErrorCode &errorCode) {
if(importer == NULL) { if(importer == NULL) {
setParseError("[import langTag] is not supported", errorCode); setParseError("[import langTag] is not supported", errorCode);
} else { } else {
const UnicodeString *importedRules = UnicodeString importedRules;
importer->getRules(baseID, importer->getRules(baseID, length > 0 ? collationType : "standard",
length > 0 ? collationType : "standard", importedRules, errorReason, errorCode);
errorReason, errorCode);
if(U_FAILURE(errorCode)) { if(U_FAILURE(errorCode)) {
if(errorReason == NULL) { if(errorReason == NULL) {
errorReason = "[import langTag] failed"; errorReason = "[import langTag] failed";
@ -651,7 +650,7 @@ CollationRuleParser::parseSetting(UErrorCode &errorCode) {
} }
const UnicodeString *outerRules = rules; const UnicodeString *outerRules = rules;
int32_t outerRuleIndex = ruleIndex; int32_t outerRuleIndex = ruleIndex;
parse(*importedRules, errorCode); parse(importedRules, errorCode);
if(U_FAILURE(errorCode)) { if(U_FAILURE(errorCode)) {
if(parseError != NULL) { if(parseError != NULL) {
parseError->offset = outerRuleIndex; parseError->offset = outerRuleIndex;

View File

@ -93,8 +93,9 @@ public:
class U_I18N_API Importer : public UObject { class U_I18N_API Importer : public UObject {
public: public:
virtual ~Importer(); virtual ~Importer();
virtual const UnicodeString *getRules( virtual void getRules(
const char *localeID, const char *collationType, const char *localeID, const char *collationType,
UnicodeString &rules,
const char *&errorReason, UErrorCode &errorCode) = 0; const char *&errorReason, UErrorCode &errorCode) = 0;
}; };

View File

@ -61,8 +61,8 @@ class UnicodeString;
class CollationLoader { class CollationLoader {
public: public:
static void appendRootRules(UnicodeString &s); static void appendRootRules(UnicodeString &s);
static UnicodeString *loadRules(const char *localeID, const char *collationType, static void loadRules(const char *localeID, const char *collationType,
UErrorCode &errorCode); UnicodeString &rules, UErrorCode &errorCode);
static const CollationTailoring *loadTailoring(const Locale &locale, Locale &validLocale, static const CollationTailoring *loadTailoring(const Locale &locale, Locale &validLocale,
UErrorCode &errorCode); UErrorCode &errorCode);

View File

@ -100,16 +100,17 @@ CollationLoader::appendRootRules(UnicodeString &s) {
} }
} }
UnicodeString * void
CollationLoader::loadRules(const char *localeID, const char *collationType, UErrorCode &errorCode) { CollationLoader::loadRules(const char *localeID, const char *collationType,
if(U_FAILURE(errorCode)) { return NULL; } UnicodeString &rules, UErrorCode &errorCode) {
if(U_FAILURE(errorCode)) { return; }
U_ASSERT(collationType != NULL && *collationType != 0); U_ASSERT(collationType != NULL && *collationType != 0);
// Copy the type for lowercasing. // Copy the type for lowercasing.
char type[16]; char type[16];
int32_t typeLength = uprv_strlen(collationType); int32_t typeLength = uprv_strlen(collationType);
if(typeLength >= LENGTHOF(type)) { if(typeLength >= LENGTHOF(type)) {
errorCode = U_ILLEGAL_ARGUMENT_ERROR; errorCode = U_ILLEGAL_ARGUMENT_ERROR;
return NULL; return;
} }
uprv_memcpy(type, collationType, typeLength + 1); uprv_memcpy(type, collationType, typeLength + 1);
T_CString_toLowerCase(type); T_CString_toLowerCase(type);
@ -121,15 +122,13 @@ CollationLoader::loadRules(const char *localeID, const char *collationType, UErr
ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode)); ures_getByKeyWithFallback(collations.getAlias(), type, NULL, &errorCode));
int32_t length; int32_t length;
const UChar *s = ures_getStringByKey(data.getAlias(), "Sequence", &length, &errorCode); const UChar *s = ures_getStringByKey(data.getAlias(), "Sequence", &length, &errorCode);
if(U_FAILURE(errorCode)) { return NULL; } if(U_FAILURE(errorCode)) { return; }
// No string pointer aliasing so that we need not hold onto the resource bundle. // No string pointer aliasing so that we need not hold onto the resource bundle.
UnicodeString *rules = new UnicodeString(s, length); rules.setTo(s, length);
if(rules == NULL) { if(rules.isBogus()) {
errorCode = U_MEMORY_ALLOCATION_ERROR; errorCode = U_MEMORY_ALLOCATION_ERROR;
return NULL;
} }
return rules;
} }
const CollationTailoring * const CollationTailoring *

View File

@ -673,21 +673,22 @@ class GenrbImporter : public icu::CollationRuleParser::Importer {
public: public:
GenrbImporter(const char *in, const char *out) : inputDir(in), outputDir(out) {} GenrbImporter(const char *in, const char *out) : inputDir(in), outputDir(out) {}
virtual ~GenrbImporter(); virtual ~GenrbImporter();
virtual const UnicodeString *getRules( virtual void getRules(
const char *localeID, const char *collationType, const char *localeID, const char *collationType,
UnicodeString &rules,
const char *&errorReason, UErrorCode &errorCode); const char *&errorReason, UErrorCode &errorCode);
private: private:
const char *inputDir; const char *inputDir;
const char *outputDir; const char *outputDir;
UnicodeString rules;
}; };
GenrbImporter::~GenrbImporter() {} GenrbImporter::~GenrbImporter() {}
const UnicodeString * void
GenrbImporter::getRules( GenrbImporter::getRules(
const char *localeID, const char *collationType, const char *localeID, const char *collationType,
UnicodeString &rules,
const char *& /*errorReason*/, UErrorCode &errorCode) { const char *& /*errorReason*/, UErrorCode &errorCode) {
struct SRBRoot *data = NULL; struct SRBRoot *data = NULL;
UCHARBUF *ucbuf = NULL; UCHARBUF *ucbuf = NULL;
@ -718,11 +719,11 @@ GenrbImporter::getRules(
if (U_FAILURE(errorCode)) { if (U_FAILURE(errorCode)) {
return NULL; return;
} }
if(filename==NULL){ if(filename==NULL){
errorCode=U_ILLEGAL_ARGUMENT_ERROR; errorCode=U_ILLEGAL_ARGUMENT_ERROR;
return NULL; return;
}else{ }else{
filelen = (int32_t)uprv_strlen(filename); filelen = (int32_t)uprv_strlen(filename);
} }
@ -810,6 +811,9 @@ GenrbImporter::getRules(
/* Parse the data into an SRBRoot */ /* Parse the data into an SRBRoot */
data = parse(ucbuf, inputDir, outputDir, filename, FALSE, FALSE, &errorCode); data = parse(ucbuf, inputDir, outputDir, filename, FALSE, FALSE, &errorCode);
if (U_FAILURE(errorCode)) {
goto finish;
}
root = data->fRoot; root = data->fRoot;
collations = resLookup(root, "collations"); collations = resLookup(root, "collations");
@ -818,7 +822,8 @@ GenrbImporter::getRules(
if (collation != NULL) { if (collation != NULL) {
sequence = resLookup(collation, "Sequence"); sequence = resLookup(collation, "Sequence");
if (sequence != NULL) { if (sequence != NULL) {
rules.setTo(FALSE, sequence->u.fString.fChars, sequence->u.fString.fLength); // No string pointer aliasing so that we need not hold onto the resource bundle.
rules.setTo(sequence->u.fString.fChars, sequence->u.fString.fLength);
} }
} }
} }
@ -835,8 +840,6 @@ finish:
if(ucbuf) { if(ucbuf) {
ucbuf_close(ucbuf); ucbuf_close(ucbuf);
} }
return &rules;
} }
// Quick-and-dirty escaping function. // Quick-and-dirty escaping function.