From: Philippe Proulx Date: Tue, 5 Dec 2023 07:00:28 +0000 (-0500) Subject: cpp-common/bt2c: add `bt2c::CStringView` X-Git-Url: https://git.efficios.com/?a=commitdiff_plain;h=339e8bc45d45a998c7d530ebe8d2bf0d579aa60a;p=babeltrace.git cpp-common/bt2c: add `bt2c::CStringView` A `bt2c::CStringView` is like a `bt2s::string_view`, but specialized for strings that are known to be null-terminated (C strings). This is useful when wrapping an existing API which has functions returning `const char *`: return `bt2c::CStringView` from the wrappers at no cost, but with improved usability: if (myObj.name().len() >= 16) { // ... } vs. if (std::strlen(myObj.name()) >= 16) { // ... } A `bt2c::CStringView` only computes the length of the underlying C string with std::strlen() when needed. It can convert to `std::string` and `bt2s::string_view`. `c-string-view.hpp` includes an {fmt} formatter for convenience. It writes `(null)` when the underlying pointer is null, just like the glibc printf() does. Signed-off-by: Philippe Proulx Change-Id: I522ce586e9966736dadeeabf30f02da5dc62c80c Reviewed-on: https://review.lttng.org/c/babeltrace/+/11485 CI-Build: Simon Marchi Reviewed-by: Simon Marchi Tested-by: jenkins --- diff --git a/src/Makefile.am b/src/Makefile.am index f158fe27..6bb2269b 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,6 +44,7 @@ noinst_HEADERS = \ cpp-common/bt2/value.hpp \ cpp-common/bt2/wrap.hpp \ cpp-common/bt2c/align.hpp \ + cpp-common/bt2c/c-string-view.hpp \ cpp-common/bt2c/call.hpp \ cpp-common/bt2c/endian.hpp \ cpp-common/bt2c/exc.hpp \ diff --git a/src/cpp-common/bt2c/c-string-view.hpp b/src/cpp-common/bt2c/c-string-view.hpp new file mode 100644 index 00000000..ddcf36c6 --- /dev/null +++ b/src/cpp-common/bt2c/c-string-view.hpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2023 Philippe Proulx + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BABELTRACE_CPP_COMMON_BT2C_C_STRING_VIEW_HPP +#define BABELTRACE_CPP_COMMON_BT2C_C_STRING_VIEW_HPP + +#include +#include +#include + +#include "common/assert.h" +#include "cpp-common/bt2s/string-view.hpp" +#include "cpp-common/vendor/fmt/core.h" + +namespace bt2c { + +/* + * A view on a constant null-terminated C string. + * + * Similar to `bt2s::string_view`, but len() and end() compute the + * length on demand. + */ +class CStringView final +{ +public: + /* + * Builds an empty view (data() returns `nullptr`). + * + * Intentionally not explicit. + */ + CStringView() noexcept = default; + + /* + * Builds a view of the C string `str` (may be `nullptr`). + * + * Intentionally not explicit. + */ + CStringView(const char * const str) noexcept : _mStr {str} + { + } + + /* + * Makes this view view the C string `str` (may be `nullptr`). + * + * Intentionally not explicit. + */ + CStringView& operator=(const char * const str) noexcept + { + _mStr = str; + return *this; + } + + /* + * Viewed null-terminated C string (may be `nullptr`). + */ + const char *data() const noexcept + { + return _mStr; + } + + /* + * Alias of data(). + */ + operator const char *() const noexcept + { + return this->data(); + } + + /* + * Alias of data(). + */ + const char *operator*() const noexcept + { + return this->data(); + } + + /* + * Alias of data(). + * + * data() must not return `nullptr`. + */ + const char *begin() const noexcept + { + BT_ASSERT_DBG(_mStr); + return this->data(); + } + + /* + * Pointer to the null character of the viewed C string. + * + * data() must not return `nullptr`. + */ + const char *end() const noexcept + { + BT_ASSERT_DBG(_mStr); + return _mStr + this->len(); + } + + /* + * Length of the viewed C string, excluding the null character. + * + * data() must not return `nullptr`. + */ + std::size_t len() const noexcept + { + BT_ASSERT_DBG(_mStr); + return std::strlen(_mStr); + } + + /* + * Returns an `std::string` instance containing a copy of the viewed + * C string. + * + * data() must not return `nullptr`. + */ + std::string str() const + { + BT_ASSERT_DBG(_mStr); + return std::string {_mStr}; + } + + /* + * Alias of str(). + */ + operator std::string() const + { + return this->str(); + } + + /* + * Returns a `bt2s::string_view` instance to view the contents, + * excluding the null character, of the viewed C string. + */ + bt2s::string_view strView() const noexcept + { + if (_mStr) { + return bt2s::string_view {this->begin(), this->len()}; + } else { + return {}; + } + } + + /* + * Alias of strView(). + */ + operator bt2s::string_view() const noexcept + { + return this->strView(); + } + + /* + * Returns the character at index `i`. + * + * `i` must be less than what len() returns. + * + * data() must not return `nullptr`. + */ + char operator[](const std::size_t i) const noexcept + { + BT_ASSERT_DBG(_mStr); + BT_ASSERT_DBG(i < this->len()); + return _mStr[i]; + } + +private: + const char *_mStr = nullptr; +}; + +} /* namespace bt2c */ + +namespace fmt { + +template <> +struct formatter +{ + constexpr auto parse(format_parse_context& ctx) const -> format_parse_context::iterator + { + return ctx.end(); + } + + auto format(const bt2c::CStringView& str, format_context& ctx) const -> format_context::iterator + { + return str ? fmt::format_to(ctx.out(), "{}", *str) : fmt::format_to(ctx.out(), "(null)"); + } +}; + +} /* namespace fmt */ + +#endif /* BABELTRACE_CPP_COMMON_BT2C_C_STRING_VIEW_HPP */