2 * Copyright (c) 2023 Philippe Proulx <pproulx@efficios.com>
4 * SPDX-License-Identifier: MIT
7 #ifndef LTTNG_C_STRING_VIEW_HPP
8 #define LTTNG_C_STRING_VIEW_HPP
10 #include <common/format.hpp>
11 #include <common/type-traits.hpp>
21 * A view on a constant null-terminated C string.
23 class c_string_view final {
26 * Builds an empty view (data() returns `nullptr`).
28 * Intentionally not explicit.
30 constexpr c_string_view() noexcept = default;
33 * Builds a view of the C string `str` (may be `nullptr`).
35 * Intentionally not explicit.
37 /* NOLINTBEGIN(google-explicit-constructor) */
38 constexpr c_string_view(const char *const str) noexcept : _str{ str }
41 /* NOLINTEND(google-explicit-constructor) */
44 * Builds a view of the string `str`.
46 /* NOLINTBEGIN(google-explicit-constructor) */
47 c_string_view(const std::string& str) noexcept : _str{ str.c_str() }
53 * Makes this view view the C string `str` (may be `nullptr`).
55 c_string_view& operator=(const char *const str) noexcept
62 * Viewed null-terminated C string (may be `nullptr`).
64 const char *data() const noexcept
72 operator const char *() const noexcept /* NOLINT(google-explicit-constructor) */
78 * Evaluate as boolean (false means an empty string).
80 operator bool() const noexcept /* NOLINT(google-explicit-constructor) */
88 const char *operator*() const noexcept
96 * data() must not return `nullptr`.
98 const char *begin() const noexcept
104 * Pointer to the null character of the viewed C string.
106 * data() must not return `nullptr`.
108 const char *end() const noexcept
110 return _str + this->len();
114 * Length of the viewed C string, excluding the null character.
116 * data() must not return `nullptr`.
118 std::size_t len() const noexcept
120 return std::strlen(_str);
124 * Returns an `std::string` instance containing a copy of the viewed
127 * data() must not return `nullptr`.
129 std::string str() const
131 return std::string{ _str };
137 operator std::string() const /* NOLINT(google-explicit-constructor) */
143 * Returns the character at index `i`.
145 * `i` must be less than what len() returns.
147 * data() must not return `nullptr`.
149 char operator[](const std::size_t i) const noexcept
154 bool startsWith(const lttng::c_string_view prefix) const noexcept
156 return std::strncmp(_str, (const char *) prefix, prefix.len()) == 0;
160 const char *_str = nullptr;
163 inline const char *format_as(const c_string_view& str)
165 return str ? *str : "(null)";
170 template <typename StrT>
171 const char *as_const_char_ptr(StrT&& val) noexcept
176 inline const char *as_const_char_ptr(const char *const val) noexcept
181 template <typename StrT>
182 using comparable_with_c_string_view = lttng::traits::
183 is_one_of<typename std::decay<StrT>::type, c_string_view, std::string, const char *>;
185 } /* namespace internal */
188 * Returns true if `lhs` is equal to `rhs`.
190 * `LhsT` and `RhsT` may be any of:
196 * Both `lhs` and `rhs` must not have an underlying `nullptr` raw data.
202 typename std::enable_if<internal::comparable_with_c_string_view<LhsT>::value>::type,
204 typename std::enable_if<internal::comparable_with_c_string_view<RhsT>::value>::type>
205 bool operator==(LhsT&& lhs, RhsT&& rhs) noexcept
207 const auto raw_lhs = internal::as_const_char_ptr(lhs);
208 const auto raw_rhs = internal::as_const_char_ptr(rhs);
210 return std::strcmp(raw_lhs, raw_rhs) == 0;
214 * Returns true if `lhs` is not equal to `rhs`.
216 * `LhsT` and `RhsT` may be any of:
222 * Both `lhs` and `rhs` must not have an underlying `nullptr` raw data.
228 typename std::enable_if<internal::comparable_with_c_string_view<LhsT>::value>::type,
230 typename std::enable_if<internal::comparable_with_c_string_view<RhsT>::value>::type>
231 bool operator!=(LhsT&& lhs, RhsT&& rhs) noexcept
233 return !(std::forward<LhsT>(lhs) == std::forward<RhsT>(rhs));
236 } /* namespace lttng */
239 * Appends `rhs` to `lhs`.
241 inline void operator+=(std::string& lhs, lttng::c_string_view rhs)
248 struct hash<lttng::c_string_view> {
249 std::size_t operator()(const lttng::c_string_view& str) const
251 auto hash_value = std::hash<char>{}('\0');
253 for (auto character : str) {
254 hash_value ^= std::hash<decltype(character)>{}(character);
260 } /* namespace std */
262 #endif /* LTTNG_C_STRING_VIEW_HPP */