]> granicus.if.org Git - icu/commitdiff
ICU-20698 C++ Hashtable allow integer value zero
authorMarkus Scherer <markus.icu@gmail.com>
Tue, 29 Dec 2020 19:16:09 +0000 (11:16 -0800)
committerMarkus Scherer <markus.icu@gmail.com>
Tue, 29 Dec 2020 21:47:17 +0000 (13:47 -0800)
icu4c/source/common/hash.h
icu4c/source/common/localeprioritylist.cpp
icu4c/source/tools/gennorm2/extradata.cpp

index f02cb7087a508b014e51cd1fd0385b895af6543d..b927ddb3c365af50474cb3bfbdcf389324af5d7b 100644 (file)
@@ -85,16 +85,22 @@ public:
 
     inline int32_t puti(const UnicodeString& key, int32_t value, UErrorCode& status);
 
+    inline int32_t putiAllowZero(const UnicodeString& key, int32_t value, UErrorCode& status);
+
     inline void* get(const UnicodeString& key) const;
 
     inline int32_t geti(const UnicodeString& key) const;
 
+    inline int32_t getiAndFound(const UnicodeString& key, UBool &found) const;
+
     inline void* remove(const UnicodeString& key);
 
     inline int32_t removei(const UnicodeString& key);
 
     inline void removeAll(void);
 
+    inline UBool containsKey(const UnicodeString& key) const;
+
     inline const UHashElement* find(const UnicodeString& key) const;
 
     /**
@@ -203,6 +209,11 @@ inline int32_t Hashtable::puti(const UnicodeString& key, int32_t value, UErrorCo
     return uhash_puti(hash, new UnicodeString(key), value, &status);
 }
 
+inline int32_t Hashtable::putiAllowZero(const UnicodeString& key, int32_t value,
+                                        UErrorCode& status) {
+    return uhash_putiAllowZero(hash, new UnicodeString(key), value, &status);
+}
+
 inline void* Hashtable::get(const UnicodeString& key) const {
     return uhash_get(hash, &key);
 }
@@ -211,6 +222,10 @@ inline int32_t Hashtable::geti(const UnicodeString& key) const {
     return uhash_geti(hash, &key);
 }
 
+inline int32_t Hashtable::getiAndFound(const UnicodeString& key, UBool &found) const {
+    return uhash_getiAndFound(hash, &key, &found);
+}
+
 inline void* Hashtable::remove(const UnicodeString& key) {
     return uhash_remove(hash, &key);
 }
@@ -219,6 +234,10 @@ inline int32_t Hashtable::removei(const UnicodeString& key) {
     return uhash_removei(hash, &key);
 }
 
+inline UBool Hashtable::containsKey(const UnicodeString& key) const {
+    return uhash_containsKey(hash, &key);
+}
+
 inline const UHashElement* Hashtable::find(const UnicodeString& key) const {
     return uhash_find(hash, &key);
 }
index 8916b121be305754742e213ca15258d07172d633..4455eedb75e67c0b1ea6d2aa45bd5b73d5ecdae9 100644 (file)
@@ -187,17 +187,18 @@ bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &e
         if (U_FAILURE(errorCode)) { return false; }
     }
     LocalPointer<Locale> clone;
-    int32_t index = uhash_geti(map, &locale);
-    if (index != 0) {
+    UBool found = false;
+    int32_t index = uhash_getiAndFound(map, &locale, &found);
+    if (found) {
         // Duplicate: Remove the old item and append it anew.
-        LocaleAndWeight &lw = list->array[index - 1];
+        LocaleAndWeight &lw = list->array[index];
         clone.adoptInstead(lw.locale);
         lw.locale = nullptr;
         lw.weight = 0;
         ++numRemoved;
     }
     if (weight <= 0) {  // do not add q=0
-        if (index != 0) {
+        if (found) {
             // Not strictly necessary but cleaner.
             uhash_removei(map, &locale);
         }
@@ -217,7 +218,7 @@ bool LocalePriorityList::add(const Locale &locale, int32_t weight, UErrorCode &e
             return false;
         }
     }
-    uhash_puti(map, clone.getAlias(), listLength + 1, &errorCode);
+    uhash_putiAllowZero(map, clone.getAlias(), listLength, &errorCode);
     if (U_FAILURE(errorCode)) { return false; }
     LocaleAndWeight &lw = list->array[listLength];
     lw.locale = clone.orphan();
index b6c15adc7ab33980943788d1d89e28928b8deede..bb5512a8b16bcde9baf08ed61ef70f0c38df19b6 100644 (file)
@@ -92,17 +92,18 @@ int32_t ExtraData::writeNoNoMapping(UChar32 c, const Norm &norm,
                                     Hashtable &previousMappings) {
     UnicodeString newMapping;
     int32_t offset=writeMapping(c, norm, newMapping);
-    int32_t previousOffset=previousMappings.geti(newMapping);
-    if(previousOffset!=0) {
+    UBool found=false;
+    int32_t previousOffset=previousMappings.getiAndFound(newMapping, found);
+    if(found) {
         // Duplicate, point to the identical mapping that has already been stored.
-        offset=previousOffset-1;
+        offset=previousOffset;
     } else {
         // Append this new mapping and
         // enter it into the hashtable, avoiding value 0 which is "not found".
         offset=dataString.length()+offset;
         dataString.append(newMapping);
-        IcuToolErrorCode errorCode("gennorm2/writeExtraData()/Hashtable.puti()");
-        previousMappings.puti(newMapping, offset+1, errorCode);
+        IcuToolErrorCode errorCode("gennorm2/writeExtraData()/Hashtable.putiAllowZero()");
+        previousMappings.putiAllowZero(newMapping, offset, errorCode);
     }
     return offset;
 }