diff --git a/upb/base/BUILD b/upb/base/BUILD index 47b44a031d40..a2848eb7c4d4 100644 --- a/upb/base/BUILD +++ b/upb/base/BUILD @@ -39,6 +39,16 @@ cc_library( deps = ["//upb:port"], ) +cc_test( + name = "string_view_test", + srcs = ["string_view_test.cc"], + deps = [ + ":base", + "@com_google_googletest//:gtest", + "@com_google_googletest//:gtest_main", + ], +) + filegroup( name = "source_files", srcs = glob( diff --git a/upb/base/string_view.h b/upb/base/string_view.h index e4d79e680bc0..072f21722f3c 100644 --- a/upb/base/string_view.h +++ b/upb/base/string_view.h @@ -45,6 +45,16 @@ UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) { return (a.size == b.size) && (!a.size || !memcmp(a.data, b.data, a.size)); } +// Compares StringViews following strcmp rules. +// Please note this comparison is neither unicode nor locale aware. +UPB_INLINE int upb_StringView_Compare(upb_StringView a, upb_StringView b) { + int result = memcmp(a.data, b.data, UPB_MIN(a.size, b.size)); + if (result == 0) { + return a.size - b.size; + } + return result; +} + // LINT.ThenChange( // GoogleInternalName1, // //depot/google3/third_party/upb/bits/golang/accessor.go:map_go_string, diff --git a/upb/base/string_view_test.cc b/upb/base/string_view_test.cc new file mode 100644 index 000000000000..9b82903f3fff --- /dev/null +++ b/upb/base/string_view_test.cc @@ -0,0 +1,69 @@ +#include "upb/base/string_view.h" + +#include + +#include + +namespace { + +TEST(upb_StringView, Compare_Eq) { + std::string s1("12345"); + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_EQ(upb_StringView_Compare(h1, h2), 0); +} + +TEST(upb_StringView, Compare_Eq_Shorter) { + std::string s1("1234"); // s1 is shorter. + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_LT(upb_StringView_Compare(h1, h2), 0); +} + +TEST(upb_StringView, Compare_Eq_Longer) { + std::string s1("123456"); // s1 is longer. + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_GT(upb_StringView_Compare(h1, h2), 0); +} + +TEST(upb_StringView, Compare_Less) { + std::string s1("12245"); // 2 < 3 + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_LT(upb_StringView_Compare(h1, h2), 0); +} + +TEST(upb_StringView, Compare_Greater) { + std::string s1("12445"); // 4 > 3 + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_GT(upb_StringView_Compare(h1, h2), 0); +} + +TEST(upb_StringView, Compare_Greater_Shorter) { + std::string s1("1244"); // s1 is shorter but 4 > 3. + std::string s2("12345"); + + upb_StringView h1 = upb_StringView_FromDataAndSize(s1.data(), s1.size()); + upb_StringView h2 = upb_StringView_FromDataAndSize(s2.data(), s2.size()); + + ASSERT_GT(upb_StringView_Compare(h1, h2), 0); +} + +} // namespace