virtual void put(const char *key, ResourceValue &value, UBool, UErrorCode &errorCode) { ResourceTable dayPeriodData = value.getTable(errorCode); if (U_FAILURE(errorCode)) { return; } for (int32_t i = 0; dayPeriodData.getKeyAndValue(i, key, value); ++i) { if (uprv_strcmp(key, "locales") == 0) { ResourceTable locales = value.getTable(errorCode); if (U_FAILURE(errorCode)) { return; } for (int32_t j = 0; locales.getKeyAndValue(j, key, value); ++j) { UnicodeString setNum_str = value.getUnicodeString(errorCode); int32_t setNum = parseSetNum(setNum_str, errorCode); uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode); } } else if (uprv_strcmp(key, "rules") == 0) { // Allocate one more than needed to skip [0]. See comment in parseSetNum(). data->rules = new DayPeriodRules[data->maxRuleSetNum + 1]; if (data->rules == NULL) { errorCode = U_MEMORY_ALLOCATION_ERROR; return; } ResourceTable rules = value.getTable(errorCode); processRules(rules, key, value, errorCode); if (U_FAILURE(errorCode)) { return; } } } }
StringTrieBuilder::Node * StringTrieBuilder::registerFinalValue(int32_t value, UErrorCode &errorCode) { if(U_FAILURE(errorCode)) { return NULL; } FinalValueNode key(value); const UHashElement *old=uhash_find(nodes, &key); if(old!=NULL) { return (Node *)old->key.pointer; } Node *newNode=new FinalValueNode(value); if(newNode==NULL) { errorCode=U_MEMORY_ALLOCATION_ERROR; return NULL; } // If uhash_puti() returns a non-zero value from an equivalent, previously // registered node, then uhash_find() failed to find that and we will leak newNode. #if !U_RELEASE int32_t oldValue= // Only in debug mode to avoid a compiler warning about unused oldValue. #endif uhash_puti(nodes, newNode, 1, &errorCode); U_ASSERT(oldValue==0); if(U_FAILURE(errorCode)) { delete newNode; return NULL; } return newNode; }
virtual void put(const char *key, const ResourceValue &value, UErrorCode &errorCode) { if (U_FAILURE(errorCode)) { return; } UnicodeString setNum_str = value.getUnicodeString(errorCode); int32_t setNum = parseSetNum(setNum_str, errorCode); uhash_puti(data->localeToRuleSetNumMap, const_cast<char *>(key), setNum, &errorCode); }
static void _put(UHashtable* hash, const char* key, int32_t value, int32_t expectedOldValue) { UErrorCode status = U_ZERO_ERROR; int32_t oldValue = uhash_puti(hash, (void*) key, value, &status); if (U_FAILURE(status)) { log_err("FAIL: uhash_put(%s) failed with %s and returned %ld\n", key, u_errorName(status), oldValue); } else if (oldValue != expectedOldValue) { log_err("FAIL: uhash_put(%s) returned old value %ld; expected %ld\n", key, oldValue, expectedOldValue); } else { log_verbose("Ok: uhash_put(%s, %d) returned old value %ld\n", key, value, oldValue); } }
int32_t writeValueAliases(const Value &value, UErrorCode &errorCode) { int32_t nameOffset=uhash_geti(nameGroupToOffset, (void *)value.joinedAliases); if(nameOffset!=0) { // The same list of aliases has been written already. return nameOffset-1; // Was incremented to reserve 0 for "not found". } // Write this not-yet-seen list of aliases. nameOffset=nameGroups.length(); uhash_puti(nameGroupToOffset, (void *)value.joinedAliases, nameOffset+1, &errorCode); // The first byte tells us how many aliases there are. // We use only values 0..0x1f in the first byte because when we write // the name groups as an invariant-character string into a source file, // those values (C0 control codes) are written as numbers rather than as characters. int32_t count=value.count; if(count>=0x20) { fprintf(stderr, "Error: Too many aliases in \"%s\"\n", value.joinedAliases); exit(U_INDEX_OUTOFBOUNDS_ERROR); } nameGroups.append((char)count, errorCode); // There is at least a short name (sometimes empty) and a long name. (count>=2) // Note: Sometimes the short and long names are the same. // In such a case, we could set a flag and omit the duplicate, // but that would save only about 1.35% of total data size (Unicode 6.0/ICU 4.6) // which is not worth the trouble. // Note: In Unicode 6.1, there are more duplicates due to newly added // short names for blocks and other properties. // It might now be worth changing the data structure. for(int32_t i=0; i<count; ++i) { const char *s=value.aliases[i]; int32_t sLength=uprv_strlen(s)+1; if(sLength>maxNameLength) { maxNameLength=sLength; } nameGroups.append(s, sLength, errorCode); // including NUL } return nameOffset; }
IdentifierInfo &IdentifierInfo::setIdentifier(const UnicodeString &identifier, UErrorCode &status) { if (U_FAILURE(status)) { return *this; } *fIdentifier = identifier; clear(); ScriptSet scriptsForCP; UChar32 cp; for (int32_t i = 0; i < identifier.length(); i += U16_LENGTH(cp)) { cp = identifier.char32At(i); // Store a representative character for each kind of decimal digit if (u_charType(cp) == U_DECIMAL_DIGIT_NUMBER) { // Just store the zero character as a representative for comparison. Unicode guarantees it is cp - value fNumerics->add(cp - (UChar32)u_getNumericValue(cp)); } UScriptCode extensions[500]; int32_t extensionsCount = uscript_getScriptExtensions(cp, extensions, UPRV_LENGTHOF(extensions), &status); if (U_FAILURE(status)) { return *this; } scriptsForCP.resetAll(); for (int32_t j=0; j<extensionsCount; j++) { scriptsForCP.set(extensions[j], status); } scriptsForCP.reset(USCRIPT_COMMON, status); scriptsForCP.reset(USCRIPT_INHERITED, status); switch (scriptsForCP.countMembers()) { case 0: break; case 1: // Single script, record it. fRequiredScripts->Union(scriptsForCP); break; default: if (!fRequiredScripts->intersects(scriptsForCP) && !uhash_geti(fScriptSetSet, &scriptsForCP)) { // If the set hasn't been added already, add it // (Add a copy, fScriptSetSet takes ownership of the copy.) uhash_puti(fScriptSetSet, new ScriptSet(scriptsForCP), 1, &status); } break; } } // Now make a final pass through ScriptSetSet to remove alternates that came before singles. // [Kana], [Kana Hira] => [Kana] // This is relatively infrequent, so doesn't have to be optimized. // We also compute any commonalities among the alternates. if (uhash_count(fScriptSetSet) > 0) { fCommonAmongAlternates->setAll(); for (int32_t it = UHASH_FIRST;;) { const UHashElement *nextHashEl = uhash_nextElement(fScriptSetSet, &it); if (nextHashEl == NULL) { break; } ScriptSet *next = static_cast<ScriptSet *>(nextHashEl->key.pointer); // [Kana], [Kana Hira] => [Kana] if (fRequiredScripts->intersects(*next)) { uhash_removeElement(fScriptSetSet, nextHashEl); } else { fCommonAmongAlternates->intersect(*next); // [[Arab Syrc Thaa]; [Arab Syrc]] => [[Arab Syrc]] for (int32_t otherIt = UHASH_FIRST;;) { const UHashElement *otherHashEl = uhash_nextElement(fScriptSetSet, &otherIt); if (otherHashEl == NULL) { break; } ScriptSet *other = static_cast<ScriptSet *>(otherHashEl->key.pointer); if (next != other && next->contains(*other)) { uhash_removeElement(fScriptSetSet, nextHashEl); break; } } } } } if (uhash_count(fScriptSetSet) == 0) { fCommonAmongAlternates->resetAll(); } return *this; }
//-------------------------------------------------------------------------- // // Assignment Operator // //-------------------------------------------------------------------------- RegexPattern &RegexPattern::operator = (const RegexPattern &other) { if (this == &other) { // Source and destination are the same. Don't do anything. return *this; } // Clean out any previous contents of object being assigned to. zap(); // Give target object a default initialization init(); // Copy simple fields fDeferredStatus = other.fDeferredStatus; if (U_FAILURE(fDeferredStatus)) { return *this; } if (other.fPatternString == NULL) { fPatternString = NULL; fPattern = utext_clone(fPattern, other.fPattern, FALSE, TRUE, &fDeferredStatus); } else { fPatternString = new UnicodeString(*(other.fPatternString)); if (fPatternString == NULL) { fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; } else { fPattern = utext_openConstUnicodeString(NULL, fPatternString, &fDeferredStatus); } } if (U_FAILURE(fDeferredStatus)) { return *this; } fFlags = other.fFlags; fLiteralText = other.fLiteralText; fMinMatchLen = other.fMinMatchLen; fFrameSize = other.fFrameSize; fDataSize = other.fDataSize; fStaticSets = other.fStaticSets; fStaticSets8 = other.fStaticSets8; fStartType = other.fStartType; fInitialStringIdx = other.fInitialStringIdx; fInitialStringLen = other.fInitialStringLen; *fInitialChars = *other.fInitialChars; fInitialChar = other.fInitialChar; *fInitialChars8 = *other.fInitialChars8; fNeedsAltInput = other.fNeedsAltInput; // Copy the pattern. It's just values, nothing deep to copy. fCompiledPat->assign(*other.fCompiledPat, fDeferredStatus); fGroupMap->assign(*other.fGroupMap, fDeferredStatus); // Copy the Unicode Sets. // Could be made more efficient if the sets were reference counted and shared, // but I doubt that pattern copying will be particularly common. // Note: init() already added an empty element zero to fSets int32_t i; int32_t numSets = other.fSets->size(); fSets8 = new Regex8BitSet[numSets]; if (fSets8 == NULL) { fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; return *this; } for (i=1; i<numSets; i++) { if (U_FAILURE(fDeferredStatus)) { return *this; } UnicodeSet *sourceSet = (UnicodeSet *)other.fSets->elementAt(i); UnicodeSet *newSet = new UnicodeSet(*sourceSet); if (newSet == NULL) { fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; break; } fSets->addElement(newSet, fDeferredStatus); fSets8[i] = other.fSets8[i]; } // Copy the named capture group hash map. int32_t hashPos = UHASH_FIRST; while (const UHashElement *hashEl = uhash_nextElement(other.fNamedCaptureMap, &hashPos)) { if (U_FAILURE(fDeferredStatus)) { break; } const UnicodeString *name = (const UnicodeString *)hashEl->key.pointer; UnicodeString *key = new UnicodeString(*name); int32_t val = hashEl->value.integer; if (key == NULL) { fDeferredStatus = U_MEMORY_ALLOCATION_ERROR; } else { uhash_puti(fNamedCaptureMap, key, val, &fDeferredStatus); } } return *this; }
static void TestOtherAPI(void){ UErrorCode status = U_ZERO_ERROR; UHashtable *hash; /* Use the correct type when cast to void * */ const UChar one[4] = {0x006F, 0x006E, 0x0065, 0}; /* L"one" */ const UChar one2[4] = {0x006F, 0x006E, 0x0065, 0}; /* Get around compiler optimizations */ const UChar two[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */ const UChar two2[4] = {0x0074, 0x0077, 0x006F, 0}; /* L"two" */ const UChar three[6] = {0x0074, 0x0068, 0x0072, 0x0065, 0x0065, 0}; /* L"three" */ const UChar four[6] = {0x0066, 0x006F, 0x0075, 0x0072, 0}; /* L"four" */ const UChar five[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */ const UChar five2[6] = {0x0066, 0x0069, 0x0076, 0x0065, 0}; /* L"five" */ hash = uhash_open(uhash_hashUChars, uhash_compareUChars, &status); if (U_FAILURE(status)) { log_err("FAIL: uhash_open failed with %s and returned 0x%08x\n", u_errorName(status), hash); return; } if (hash == NULL) { log_err("FAIL: uhash_open returned NULL\n"); return; } log_verbose("Ok: uhash_open returned 0x%08X\n", hash); uhash_puti(hash, (void*)one, 1, &status); if(uhash_count(hash) != 1){ log_err("FAIL: uhas_count() failed. Expected: 1, Got: %d\n", uhash_count(hash)); } uhash_puti(hash, (void*)two, 2, &status); uhash_puti(hash, (void*)three, 3, &status); uhash_puti(hash, (void*)four, 4, &status); uhash_puti(hash, (void*)five, 5, &status); if(uhash_count(hash) != 5){ log_err("FAIL: uhas_count() failed. Expected: 5, Got: %d\n", uhash_count(hash)); } if(uhash_geti(hash, (void*)two2) != 2){ log_err("FAIL: uhash_geti failed\n"); } if(uhash_removei(hash, (void*)five2) != 5){ log_err("FAIL: uhash_remove() failed\n"); } if(uhash_count(hash) != 4){ log_err("FAIL: uhas_count() failed. Expected: 4, Got: %d\n", uhash_count(hash)); } uhash_put(hash, (void*)one, NULL, &status); if(uhash_count(hash) != 3){ log_err("FAIL: uhash_put() with value=NULL didn't remove the key value pair\n"); } status=U_ILLEGAL_ARGUMENT_ERROR; uhash_puti(hash, (void*)one, 1, &status); if(uhash_count(hash) != 3){ log_err("FAIL: uhash_put() with value!=NULL should fail when status != U_ZERO_ERROR \n"); } status=U_ZERO_ERROR; uhash_puti(hash, (void*)one, 1, &status); if(uhash_count(hash) != 4){ log_err("FAIL: uhash_put() with value!=NULL didn't replace the key value pair\n"); } if(_compareUChars((void*)one, (void*)two) == TRUE || _compareUChars((void*)one, (void*)one) != TRUE || _compareUChars((void*)one, (void*)one2) != TRUE || _compareUChars((void*)one, NULL) == TRUE ) { log_err("FAIL: compareUChars failed\n"); } uhash_removeAll(hash); if(uhash_count(hash) != 0){ log_err("FAIL: uhas_count() failed. Expected: 0, Got: %d\n", uhash_count(hash)); } uhash_setKeyComparator(hash, uhash_compareLong); uhash_setKeyHasher(hash, uhash_hashLong); uhash_iputi(hash, 1001, 1, &status); uhash_iputi(hash, 1002, 2, &status); uhash_iputi(hash, 1003, 3, &status); if(_compareLong(1001, 1002) == TRUE || _compareLong(1001, 1001) != TRUE || _compareLong(1001, 0) == TRUE ) { log_err("FAIL: compareLong failed\n"); } /*set the resize policy to just GROW and SHRINK*/ /*how to test this??*/ uhash_setResizePolicy(hash, U_GROW_AND_SHRINK); uhash_iputi(hash, 1004, 4, &status); uhash_iputi(hash, 1005, 5, &status); uhash_iputi(hash, 1006, 6, &status); if(uhash_count(hash) != 6){ log_err("FAIL: uhash_count() failed. Expected: 6, Got: %d\n", uhash_count(hash)); } if(uhash_iremovei(hash, 1004) != 4){ log_err("FAIL: uhash_remove failed\n"); } if(uhash_iremovei(hash, 1004) != 0){ log_err("FAIL: uhash_remove failed\n"); } uhash_close(hash); }
void PluralRulesTest::testAvailbleLocales() { // Hash set of (char *) strings. UErrorCode status = U_ZERO_ERROR; UHashtable *localeSet = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, uhash_compareLong, &status); uhash_setKeyDeleter(localeSet, uprv_deleteUObject); if (U_FAILURE(status)) { errln("file %s, line %d: Error status = %s", __FILE__, __LINE__, u_errorName(status)); return; } // Check that each locale returned by the iterator is unique. StringEnumeration *localesEnum = PluralRules::getAvailableLocales(status); int localeCount = 0; for (;;) { const char *locale = localesEnum->next(NULL, status); if (U_FAILURE(status)) { dataerrln("file %s, line %d: Error status = %s", __FILE__, __LINE__, u_errorName(status)); return; } if (locale == NULL) { break; } localeCount++; int32_t oldVal = uhash_puti(localeSet, new UnicodeString(locale), 1, &status); if (oldVal != 0) { errln("file %s, line %d: locale %s was seen before.", __FILE__, __LINE__, locale); } } // Reset the iterator, verify that we get the same count. localesEnum->reset(status); int32_t localeCount2 = 0; while (localesEnum->next(NULL, status) != NULL) { if (U_FAILURE(status)) { errln("file %s, line %d: Error status = %s", __FILE__, __LINE__, u_errorName(status)); break; } localeCount2++; } if (localeCount != localeCount2) { errln("file %s, line %d: locale counts differ. They are (%d, %d)", __FILE__, __LINE__, localeCount, localeCount2); } // Instantiate plural rules for each available locale. localesEnum->reset(status); for (;;) { status = U_ZERO_ERROR; const char *localeName = localesEnum->next(NULL, status); if (U_FAILURE(status)) { errln("file %s, line %d: Error status = %s, locale = %s", __FILE__, __LINE__, u_errorName(status), localeName); return; } if (localeName == NULL) { break; } Locale locale = Locale::createFromName(localeName); PluralRules *pr = PluralRules::forLocale(locale, status); if (U_FAILURE(status)) { errln("file %s, line %d: Error %s creating plural rules for locale %s", __FILE__, __LINE__, u_errorName(status), localeName); continue; } if (pr == NULL) { errln("file %s, line %d: Null plural rules for locale %s", __FILE__, __LINE__, localeName); continue; } // Pump some numbers through the plural rules. Can't check for correct results, // mostly this to tickle any asserts or crashes that may be lurking. for (double n=0; n<120.0; n+=0.5) { UnicodeString keyword = pr->select(n); if (keyword.length() == 0) { errln("file %s, line %d, empty keyword for n = %g, locale %s", __FILE__, __LINE__, n, localeName); } } delete pr; } uhash_close(localeSet); delete localesEnum; }