diff --git a/include/xo/object2/DString.hpp b/include/xo/object2/DString.hpp index da891e7..fb23672 100644 --- a/include/xo/object2/DString.hpp +++ b/include/xo/object2/DString.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include //#include @@ -169,6 +170,11 @@ namespace xo { **/ static int compare(const DString & lhs, const DString & rhs) noexcept; + /** compute hash of string contents **/ + std::size_t hash() const noexcept { + return std::hash{}(std::string_view(chars_, size_)); + } + // TODO - behave like std::string, to the extent feasible // insert // insert_range @@ -273,4 +279,13 @@ namespace xo { } /*namespace scm*/ } /*namespace xo*/ +namespace std { + template <> + struct hash { + std::size_t operator()(const xo::scm::DString & x) const noexcept { + return x.hash(); + } + }; +} /*namespace std*/ + /* end DString.hpp */ diff --git a/utest/DString.test.cpp b/utest/DString.test.cpp index 19ade04..21f33bd 100644 --- a/utest/DString.test.cpp +++ b/utest/DString.test.cpp @@ -358,6 +358,35 @@ namespace xo { REQUIRE(*apple1 >= *apple2); REQUIRE_FALSE(*apple1 >= *banana); } + + TEST_CASE("DString-hash", "[object2][DString]") + { + ArenaConfig cfg { .name_ = "testarena", + .size_ = 4*1024 }; + DArena arena = DArena::map(cfg); + auto alloc = with_facet::mkobj(&arena); + + DString * s1 = DString::from_cstr(alloc, "hello"); + DString * s2 = DString::from_cstr(alloc, "hello"); + DString * s3 = DString::from_cstr(alloc, "world"); + DString * empty1 = DString::empty(alloc, 16); + DString * empty2 = DString::empty(alloc, 32); + + // same content produces same hash + REQUIRE(s1->hash() == s2->hash()); + + // empty strings have same hash + REQUIRE(empty1->hash() == empty2->hash()); + + // different content produces different hash (not guaranteed, but highly likely) + REQUIRE(s1->hash() != s3->hash()); + + // std::hash specialization works + std::hash hasher; + REQUIRE(hasher(*s1) == s1->hash()); + REQUIRE(hasher(*s2) == s2->hash()); + REQUIRE(hasher(*s1) == hasher(*s2)); + } } /*namespace ut*/ } /*namespace xo*/