cpp-common/bt2c: add CStringView equality and non-equality operators
authorSimon Marchi <simon.marchi@efficios.com>
Mon, 15 Jan 2024 21:25:29 +0000 (16:25 -0500)
committerSimon Marchi <simon.marchi@efficios.com>
Mon, 29 Jan 2024 16:38:19 +0000 (11:38 -0500)
Add `operator==` and `operator!=` functions to check equality or
non-equality between `CStringView` and another `CStringView`,
`const char *` and `std::string`.

Add a test to exercise those.

Change-Id: I2463966aae50792bb3e21ae65f9f124b08114499
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.lttng.org/c/babeltrace/+/11681
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
src/cpp-common/bt2c/c-string-view.hpp
tests/Makefile.am
tests/cpp-common/test-c-string-view.cpp [new file with mode: 0644]

index a7b54e70651fa271c3cc1dc71793a9ae044e19dd..54c87de9f1df581541e6eec5b9af40e3155bcd1a 100644 (file)
@@ -15,6 +15,8 @@
 #include "cpp-common/bt2s/string-view.hpp"
 #include "cpp-common/vendor/fmt/format.h"
 
+#include "type-traits.hpp"
+
 namespace bt2c {
 
 /*
@@ -183,6 +185,67 @@ static inline const char *format_as(const CStringView& str)
     return str ? *str : "(null)";
 }
 
+namespace internal {
+
+template <typename StrT>
+const char *asConstCharPtr(StrT&& val) noexcept
+{
+    return val.data();
+}
+
+inline const char *asConstCharPtr(const char * const val) noexcept
+{
+    return val;
+}
+
+template <typename StrT>
+using ComparableWithCStringView =
+    IsOneOf<typename std::decay<StrT>::type, CStringView, std::string, const char *>;
+
+} /* namespace internal */
+
+/*
+ * Returns true if `lhs` is equal to `rhs`.
+ *
+ * `LhsT` and `RhsT` may be any of:
+ *
+ * • `const char *`
+ * • `std::string`
+ * • `CStringView`
+ *
+ * Both `lhs` and `rhs` must not have an underlying `nullptr` raw data.
+ */
+template <
+    typename LhsT, typename RhsT,
+    typename = typename std::enable_if<internal::ComparableWithCStringView<LhsT>::value>::type,
+    typename = typename std::enable_if<internal::ComparableWithCStringView<RhsT>::value>::type>
+bool operator==(LhsT&& lhs, RhsT&& rhs) noexcept
+{
+    const auto rawLhs = internal::asConstCharPtr(lhs);
+    const auto rawRhs = internal::asConstCharPtr(rhs);
+
+    BT_ASSERT_DBG(rawLhs);
+    BT_ASSERT_DBG(rawRhs);
+    return std::strcmp(rawLhs, rawRhs) == 0;
+}
+
+/*
+ * Returns true if `lhs` is not equal to `rhs`.
+ *
+ * `LhsT` and `RhsT` may be any of:
+ *
+ * • `const char *`
+ * • `std::string`
+ * • `CStringView`
+ *
+ * Both `lhs` and `rhs` must not have an underlying `nullptr` raw data.
+ */
+template <typename LhsT, typename RhsT>
+bool operator!=(LhsT&& lhs, RhsT&& rhs) noexcept
+{
+    return !(std::forward<LhsT>(lhs) == std::forward<RhsT>(rhs));
+}
+
 } /* namespace bt2c */
 
 #endif /* BABELTRACE_CPP_COMMON_BT2C_C_STRING_VIEW_HPP */
index 90382fb429ae20fce5f151155fea9d8f97a85851..a24f32083ae536fe26c904e94e46bc2a79ae5925 100644 (file)
@@ -8,6 +8,13 @@ SUBDIRS = \
        plugins \
        param-validation
 
+AM_CPPFLAGS += -I$(top_srcdir)/tests/utils
+
+COMMON_TEST_LDADD = \
+       $(top_builddir)/tests/utils/tap/libtap.la \
+       $(top_builddir)/src/common/libcommon.la \
+       $(top_builddir)/src/logging/liblogging.la
+
 # Directories added to EXTRA_DIST will be recursively copied to the distribution.
 EXTRA_DIST = $(srcdir)/data \
             bindings/python/bt2/.coveragerc
@@ -63,6 +70,8 @@ dist_check_SCRIPTS = \
        python-plugin-provider/test-python-plugin-provider.sh \
        python-plugin-provider/test_python_plugin_provider.py
 
+noinst_PROGRAMS =
+
 TESTS_BINDINGS =
 
 if ENABLE_PYTHON_BINDINGS
@@ -80,6 +89,18 @@ TESTS_CLI = \
        cli/test-trace-read.sh \
        cli/test-trimmer.sh
 
+noinst_PROGRAMS += \
+       cpp-common/test-c-string-view
+
+cpp_common_test_c_string_view_SOURCES = \
+       cpp-common/test-c-string-view.cpp
+
+cpp_common_test_c_string_view_LDADD = \
+       $(COMMON_TEST_LDADD)
+
+TESTS_CPP_COMMON = \
+       cpp-common/test-c-string-view
+
 TESTS_LIB = \
        lib/test-bt-uuid \
        lib/test-bt-values \
@@ -176,6 +197,7 @@ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' \
 TESTS_NO_BITFIELD = \
        $(TESTS_BINDINGS) \
        $(TESTS_CLI) \
+       $(TESTS_CPP_COMMON) \
        $(TESTS_CTF_WRITER) \
        $(TESTS_LIB) \
        $(TESTS_PARAM_VALIDATION) \
@@ -192,6 +214,7 @@ endef
 $(eval $(call check_target,bindings,$(TESTS_BINDINGS)))
 $(eval $(call check_target,bitfield,$(TESTS_BITFIELD)))
 $(eval $(call check_target,cli,$(TESTS_CLI)))
+$(eval $(call check_target,cpp-common,$(TESTS_CPP_COMMON)))
 $(eval $(call check_target,ctf-writer,$(TESTS_CTF_WRITER)))
 $(eval $(call check_target,lib,$(TESTS_LIB)))
 $(eval $(call check_target,plugins,$(TESTS_PLUGINS)))
diff --git a/tests/cpp-common/test-c-string-view.cpp b/tests/cpp-common/test-c-string-view.cpp
new file mode 100644 (file)
index 0000000..d137763
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * Copyright (C) 2024 EfficiOS, Inc.
+ */
+
+#include <string>
+
+#include "cpp-common/bt2c/c-string-view.hpp"
+
+#include "tap/tap.h"
+
+namespace {
+
+template <typename StrT>
+const char *asConstCharPtr(StrT&& val)
+{
+    return val.data();
+}
+
+const char *asConstCharPtr(const char * const val)
+{
+    return val;
+}
+
+const char *typeName(bt2c::CStringView)
+{
+    return "bt2c::CStringView";
+}
+
+const char *typeName(const char *)
+{
+    return "const char *";
+}
+
+const char *typeName(const std::string&)
+{
+    return "std::string";
+}
+
+template <typename Str1T, typename Str2T>
+void testEq(Str1T&& lhs, Str2T&& rhs)
+{
+    BT_ASSERT(asConstCharPtr(lhs) != asConstCharPtr(rhs));
+    ok(lhs == rhs, "`%s` == `%s`", typeName(lhs), typeName(rhs));
+}
+
+template <typename Str1T, typename Str2T>
+void testNe(Str1T&& lhs, Str2T&& rhs)
+{
+    BT_ASSERT(asConstCharPtr(lhs) != asConstCharPtr(rhs));
+    ok(lhs != rhs, "`%s` != `%s`", typeName(lhs), typeName(rhs));
+}
+
+void testEquality()
+{
+    const std::string foo1 = "foo", foo2 = "foo";
+    const std::string bar = "bar";
+
+    /* `CStringView` vs `CStringView` */
+    testEq(bt2c::CStringView {foo1}, bt2c::CStringView {foo2});
+    testNe(bt2c::CStringView {foo1}, bt2c::CStringView {bar});
+
+    /* `CStringView` vs `const char *` */
+    testEq(bt2c::CStringView {foo1}, foo2.c_str());
+    testNe(bt2c::CStringView {foo1}, bar.c_str());
+    testEq(foo1.c_str(), bt2c::CStringView {foo2});
+    testNe(foo1.c_str(), bt2c::CStringView {bar});
+
+    /* `StringView` vs `std::string` */
+    testEq(bt2c::CStringView {foo1}, foo2);
+    testNe(bt2c::CStringView {foo1}, bar);
+    testEq(foo1, bt2c::CStringView {foo2});
+    testNe(foo1, bt2c::CStringView {bar});
+}
+
+} // namespace
+
+int main()
+{
+    plan_tests(10);
+    testEquality();
+    return exit_status();
+}
This page took 0.027141 seconds and 4 git commands to generate.