userver: userver/utils/zstring_view.hpp Source File
Loading...
Searching...
No Matches
zstring_view.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file
4/// @brief @copybrief utils::zstring_view
5/// @ingroup userver_universal
6
7#include <string>
8#include <string_view>
9#include <type_traits>
10
11#include <fmt/format.h>
12
13#include <userver/formats/serialize/to.hpp>
14
15USERVER_NAMESPACE_BEGIN
16
17namespace utils {
18
19// Forward declaration
20[[noreturn]] void AbortWithStacktrace(std::string_view message) noexcept;
21
22/// @ingroup userver_containers
23///
24/// @brief Non-empty string view type that guarantees null-termination and has a `c_str()` member function.
25class zstring_view : public std::string_view { // NOLINT(readability-identifier-naming)
26public:
27 zstring_view() = delete;
28 zstring_view(const zstring_view& str) = default;
29
30 constexpr zstring_view(const char* str) noexcept : std::string_view{str} {
31 // data()[size()] == '\0' is guaranteed by std::string_view that calls std::strlen(str)
32 }
33
34 zstring_view(const std::string& str) noexcept : std::string_view{str} {}
35
36 zstring_view& operator=(std::string_view) = delete;
37 zstring_view& operator=(const zstring_view&) = default;
38
39 void remove_suffix(std::size_t) = delete; // zstring_view becomes not null-terminated after that function call
40 void swap(std::string_view&) = delete; // zstring_view may become not null-terminated after that function call
41 void swap(zstring_view& other) noexcept { std::string_view::swap(other); }
42
43 constexpr const char* c_str() const noexcept { return std::string_view::data(); }
44
45 /// Constructs a zstring_view from a pointer and size.
46 /// @warning `str[len]` should be '\0'.
47 static constexpr zstring_view UnsafeMake(const char* str, std::size_t len) noexcept {
48 return zstring_view{str, len};
49 }
50
51private:
52 constexpr zstring_view(const char* str, std::size_t len) noexcept : std::string_view{str, len} {
53#ifndef NDEBUG
54 if (!str || str[len] != 0) {
55 USERVER_NAMESPACE::utils::AbortWithStacktrace("`str` should be not null and should be null terminated");
56 }
57#endif
58 }
59};
60
61template <class Value>
62Value Serialize(zstring_view view, formats::serialize::To<Value>) {
63 return typename Value::Builder(std::string_view{view}).ExtractValue();
64}
65
66} // namespace utils
67
68USERVER_NAMESPACE_END
69
70template <>
71struct fmt::formatter<USERVER_NAMESPACE::utils::zstring_view, char> : fmt::formatter<std::string_view> {};
72
73namespace fmt {
74
75// Allow fmt::runtime() to work with utils::zstring_view
76template <class... NotUsed>
77inline auto runtime(USERVER_NAMESPACE::utils::zstring_view s, NotUsed...) // NOLINT(readability-identifier-naming)
78 -> decltype(fmt::runtime(std::string_view{s})) {
79 static_assert(sizeof...(NotUsed) == 0);
80 return fmt::runtime(std::string_view{s});
81}
82
83} // namespace fmt