diff --git a/tools/inspector_protocol/encoding/encoding.h b/tools/inspector_protocol/encoding/encoding.h index 14432484d55b9d..a1bcfc4be3db4a 100644 --- a/tools/inspector_protocol/encoding/encoding.h +++ b/tools/inspector_protocol/encoding/encoding.h @@ -5,6 +5,7 @@ #ifndef V8_INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_ #define V8_INSPECTOR_PROTOCOL_ENCODING_ENCODING_H_ +#include #include #include #include @@ -14,6 +15,19 @@ #include namespace v8_inspector_protocol_encoding { +// This library is designed to be portable. The only allowed dependency +// are the C/C++ standard libraries, up to C++11. We support both 32 bit +// and 64 architectures. +// +// Types used below: +// uint8_t: a byte, e.g. for raw bytes or UTF8 characters +// uint16_t: two bytes, e.g. for UTF16 characters +// For input parameters: +// span: pointer to bytes and length +// span: pointer to UTF16 chars and length +// For output parameters: +// std::vector - Owned segment of bytes / utf8 characters and length. +// std::string - Same, for compatibility, even though char is signed. // ============================================================================= // span - sequence of bytes @@ -72,6 +86,22 @@ inline span SpanFrom(const std::string& v) { return span(reinterpret_cast(v.data()), v.size()); } +// Less than / equality comparison functions for sorting / searching for byte +// spans. These are similar to absl::string_view's < and == operators. +inline bool SpanLessThan(span x, span y) noexcept { + auto min_size = std::min(x.size(), y.size()); + const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool SpanEquals(span x, span y) noexcept { + auto len = x.size(); + if (len != y.size()) + return false; + return x.data() == y.data() || len == 0 || + std::memcmp(x.data(), y.data(), len) == 0; +} + // ============================================================================= // Status and Error codes // ============================================================================= diff --git a/tools/inspector_protocol/encoding/encoding_test.cc b/tools/inspector_protocol/encoding/encoding_test.cc index 554aa1b2cbaedb..f6b40dfcefe2df 100644 --- a/tools/inspector_protocol/encoding/encoding_test.cc +++ b/tools/inspector_protocol/encoding/encoding_test.cc @@ -121,6 +121,28 @@ TEST(SpanFromTest, FromConstCharAndLiteral) { EXPECT_EQ(3u, SpanFrom("foo").size()); } +TEST(SpanComparisons, ByteWiseLexicographicalOrder) { + // Compare the empty span. + EXPECT_FALSE(SpanLessThan(span(), span())); + EXPECT_TRUE(SpanEquals(span(), span())); + + // Compare message with itself. + std::string msg = "Hello, world"; + EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(msg))); + EXPECT_TRUE(SpanEquals(SpanFrom(msg), SpanFrom(msg))); + + // Compare message and copy. + EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(std::string(msg)))); + EXPECT_TRUE(SpanEquals(SpanFrom(msg), SpanFrom(std::string(msg)))); + + // Compare two messages. |lesser_msg| < |msg| because of the first + // byte ('A' < 'H'). + std::string lesser_msg = "A lesser message."; + EXPECT_TRUE(SpanLessThan(SpanFrom(lesser_msg), SpanFrom(msg))); + EXPECT_FALSE(SpanLessThan(SpanFrom(msg), SpanFrom(lesser_msg))); + EXPECT_FALSE(SpanEquals(SpanFrom(msg), SpanFrom(lesser_msg))); +} + // ============================================================================= // Status and Error codes // ============================================================================= diff --git a/tools/inspector_protocol/lib/encoding_h.template b/tools/inspector_protocol/lib/encoding_h.template index 4d9874bfbd5cb4..2601192e160543 100644 --- a/tools/inspector_protocol/lib/encoding_h.template +++ b/tools/inspector_protocol/lib/encoding_h.template @@ -9,6 +9,7 @@ #ifndef {{"_".join(config.protocol.namespace)}}_encoding_h #define {{"_".join(config.protocol.namespace)}}_encoding_h +#include #include #include #include @@ -23,6 +24,19 @@ namespace {{namespace}} { // ===== encoding/encoding.h ===== +// This library is designed to be portable. The only allowed dependency +// are the C/C++ standard libraries, up to C++11. We support both 32 bit +// and 64 architectures. +// +// Types used below: +// uint8_t: a byte, e.g. for raw bytes or UTF8 characters +// uint16_t: two bytes, e.g. for UTF16 characters +// For input parameters: +// span: pointer to bytes and length +// span: pointer to UTF16 chars and length +// For output parameters: +// std::vector - Owned segment of bytes / utf8 characters and length. +// std::string - Same, for compatibility, even though char is signed. // ============================================================================= // span - sequence of bytes @@ -81,6 +95,22 @@ inline span SpanFrom(const std::string& v) { return span(reinterpret_cast(v.data()), v.size()); } +// Less than / equality comparison functions for sorting / searching for byte +// spans. These are similar to absl::string_view's < and == operators. +inline bool SpanLessThan(span x, span y) noexcept { + auto min_size = std::min(x.size(), y.size()); + const int r = min_size == 0 ? 0 : memcmp(x.data(), y.data(), min_size); + return (r < 0) || (r == 0 && x.size() < y.size()); +} + +inline bool SpanEquals(span x, span y) noexcept { + auto len = x.size(); + if (len != y.size()) + return false; + return x.data() == y.data() || len == 0 || + std::memcmp(x.data(), y.data(), len) == 0; +} + // ============================================================================= // Status and Error codes // =============================================================================