Skip to content

Commit

Permalink
ICU-22696 Add uhash support for std::string_view.
Browse files Browse the repository at this point in the history
  • Loading branch information
roubert committed Jul 30, 2024
1 parent 8891c07 commit 10fe2a6
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 0 deletions.
31 changes: 31 additions & 0 deletions icu4c/source/common/uhash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
******************************************************************************
*/

#include <string_view>

#include "uhash.h"
#include "unicode/ustring.h"
#include "cstring.h"
Expand Down Expand Up @@ -944,6 +946,12 @@ uhash_hashIChars(const UHashTok key) {
return s == nullptr ? 0 : ustr_hashICharsN(s, static_cast<int32_t>(uprv_strlen(s)));
}

U_CAPI int32_t U_EXPORT2
uhash_hashIStringView(const UHashTok key) {
const std::string_view* s = static_cast<std::string_view*>(key.pointer);
return s == nullptr ? 0 : ustr_hashICharsN(s->data(), static_cast<int32_t>(s->size()));
}

U_CAPI UBool U_EXPORT2
uhash_equals(const UHashtable* hash1, const UHashtable* hash2){
int32_t count1, count2, pos, i;
Expand Down Expand Up @@ -1051,6 +1059,29 @@ uhash_compareIChars(const UHashTok key1, const UHashTok key2) {
return (UBool)(*p1 == *p2);
}

U_CAPI UBool U_EXPORT2
uhash_compareIStringView(const UHashTok key1, const UHashTok key2) {
const std::string_view* p1 = static_cast<std::string_view*>(key1.pointer);
const std::string_view* p2 = static_cast<std::string_view*>(key2.pointer);
if (p1 == p2) {
return true;
}
if (p1 == nullptr || p2 == nullptr) {
return false;
}
const std::string_view& v1 = *p1;
const std::string_view& v2 = *p2;
if (v1.size() != v2.size()) {
return false;
}
for (size_t i = 0; i < v1.size(); ++i) {
if (uprv_tolower(v1[i]) != uprv_tolower(v2[i])) {
return false;
}
}
return true;
}

/********************************************************************
* PUBLIC int32_t Support Functions
********************************************************************/
Expand Down
19 changes: 19 additions & 0 deletions icu4c/source/common/uhash.h
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,15 @@ uhash_hashChars(const UHashTok key);
U_CAPI int32_t U_EXPORT2
uhash_hashIChars(const UHashTok key);

/**
* Generate a case-insensitive hash code for a std::string_view.
* Use together with uhash_compareIStringView.
* @param key A pointer to the std::string_view to hash.
* @return A hash code for the key.
*/
U_CAPI int32_t U_EXPORT2
uhash_hashIStringView(const UHashTok key);

/**
* Comparator for null-terminated UChar* strings. Use together with
* uhash_hashUChars.
Expand Down Expand Up @@ -724,6 +733,16 @@ uhash_compareChars(const UHashTok key1, const UHashTok key2);
U_CAPI UBool U_EXPORT2
uhash_compareIChars(const UHashTok key1, const UHashTok key2);

/**
* Case-insensitive comparator for std::string_view.
* Use together with uhash_hashIStringView.
* @param key1 A pointer to the std::string_view for comparison
* @param key2 A pointer to the std::string_view for comparison
* @return true if key1 and key2 are equal, return false otherwise.
*/
U_CAPI UBool U_EXPORT2
uhash_compareIStringView(const UHashTok key1, const UHashTok key2);

/********************************************************************
* UnicodeString Support Functions
********************************************************************/
Expand Down
2 changes: 2 additions & 0 deletions icu4c/source/common/unicode/urename.h
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@
#define uhash_compareCaselessUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_compareCaselessUnicodeString)
#define uhash_compareChars U_ICU_ENTRY_POINT_RENAME(uhash_compareChars)
#define uhash_compareIChars U_ICU_ENTRY_POINT_RENAME(uhash_compareIChars)
#define uhash_compareIStringView U_ICU_ENTRY_POINT_RENAME(uhash_compareIStringView)
#define uhash_compareLong U_ICU_ENTRY_POINT_RENAME(uhash_compareLong)
#define uhash_compareScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_compareScriptSet)
#define uhash_compareUChars U_ICU_ENTRY_POINT_RENAME(uhash_compareUChars)
Expand All @@ -1008,6 +1009,7 @@
#define uhash_hashCaselessUnicodeString U_ICU_ENTRY_POINT_RENAME(uhash_hashCaselessUnicodeString)
#define uhash_hashChars U_ICU_ENTRY_POINT_RENAME(uhash_hashChars)
#define uhash_hashIChars U_ICU_ENTRY_POINT_RENAME(uhash_hashIChars)
#define uhash_hashIStringView U_ICU_ENTRY_POINT_RENAME(uhash_hashIStringView)
#define uhash_hashLong U_ICU_ENTRY_POINT_RENAME(uhash_hashLong)
#define uhash_hashScriptSet U_ICU_ENTRY_POINT_RENAME(uhash_hashScriptSet)
#define uhash_hashUChars U_ICU_ENTRY_POINT_RENAME(uhash_hashUChars)
Expand Down
44 changes: 44 additions & 0 deletions icu4c/source/test/intltest/itutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ extern IntlTest *createPluralMapTest();
#if !UCONFIG_NO_FORMATTING
extern IntlTest *createStaticUnicodeSetsTest();
#endif
static IntlTest *createUHashTest();

void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* &name, char* par )
{
Expand Down Expand Up @@ -80,6 +81,7 @@ void IntlTestUtilities::runIndexedTest( int32_t index, UBool exec, const char* &
#endif
TESTCASE_AUTO_CLASS(LocaleBuilderTest);
TESTCASE_AUTO_CREATE_CLASS(LocaleMatcherTest);
TESTCASE_AUTO_CREATE_CLASS(UHashTest);
TESTCASE_AUTO_END;
}

Expand Down Expand Up @@ -905,3 +907,45 @@ void EnumSetTest::TestEnumSet() {
assertFalse(WHERE, flags.get(THING2));
assertFalse(WHERE, flags.get(THING3));
}

/** UHashTest **/
#include "uhash.h"
#include <string_view>

class UHashTest : public IntlTest {
public:
UHashTest() = default;
virtual void runIndexedTest(int32_t index, UBool exec, const char*& name, char* par = nullptr) override;
void TestStringView();
};

static IntlTest* createUHashTest() {
return new UHashTest();
}

void UHashTest::runIndexedTest(int32_t index, UBool exec, const char*& name, char* /*par*/) {
TESTCASE_AUTO_BEGIN;
TESTCASE_AUTO(TestStringView);
TESTCASE_AUTO_END;
}

void UHashTest::TestStringView() {
IcuTestErrorCode status(*this, "TestStringView");
LocalUHashtablePointer table(
uhash_open(uhash_hashIStringView, uhash_compareIStringView, nullptr, status));
if (status.errIfFailureAndReset("uhash_open") ||
!assertTrue("uhash_open", table.isValid())) {
return;
}

std::string_view key("aaa");
std::string_view value("bbb");

uhash_put(table.getAlias(), &key, &value, status);
if (status.errIfFailureAndReset("uhash_put")) return;

std::string_view lookup("AAA");

auto* result = static_cast<std::string_view*>(uhash_get(table.getAlias(), &lookup));
assertTrue("uhash_get", result == &value);
}

0 comments on commit 10fe2a6

Please sign in to comment.