]>
Commit | Line | Data |
---|---|---|
f67539c2 TL |
1 | #ifndef OPENTRACING_STRING_VIEW_H |
2 | #define OPENTRACING_STRING_VIEW_H | |
3 | ||
4 | #include <opentracing/version.h> | |
5 | #include <algorithm> | |
6 | #include <cstring> | |
7 | #include <ostream> | |
8 | #include <string> | |
9 | ||
10 | // =========== | |
11 | // string_view.h | |
12 | // =========== | |
13 | // class string_view - Constant reference to an external string | |
14 | // | |
15 | // ----------------- | |
16 | // String References | |
17 | // ----------------- | |
18 | // This string references is a simplified version of the boost::string_ref. | |
19 | // Its purpose is to avoid a number of efficiency problems that appear | |
20 | // commonly when interacting with 'std::string' and c-strings. | |
21 | // | |
22 | // See the boost documentation for more background: | |
23 | // http://www.boost.org/doc/libs/master/libs/utility/doc/html/string_ref.html | |
24 | // | |
25 | // ----- | |
26 | // Note: | |
27 | // ----- | |
28 | // Although we have the ability to use wide string refs, there are side | |
29 | // effects in exposing an OpenTracing interface that works with narrow and wide | |
30 | // strings at the same time. Storage on the implementation will have a 'native' | |
31 | // format. | |
32 | // | |
33 | // Exposing references to that format avoid copies means clients would be | |
34 | // dependent on that format. If they're dependent on that detail and then switch | |
35 | // out the implementation to a different format, there would be lots of code | |
36 | // that breaks if it was expecting wstring and starts receiving string all of a | |
37 | // sudden. That design issue still needs to be addressed. | |
38 | ||
39 | namespace opentracing { | |
40 | BEGIN_OPENTRACING_ABI_NAMESPACE | |
41 | // =============== | |
42 | // class string_view | |
43 | // =============== | |
44 | // Represent a constant reference to an external character array. The external | |
45 | // array need not be null-terminated, if explicitly created with a known length. | |
46 | // | |
47 | // This class does not own the data. It is expected to be used in situations | |
48 | // where the character data resides in some other buffer, whose lifetime extends | |
49 | // past that of the string_view. For this reason, it is not in general safe to | |
50 | // store a string_view. | |
51 | ||
52 | class string_view { | |
53 | public: | |
54 | // Construct an empty string_view | |
55 | string_view() noexcept : data_(nullptr), length_(0) {} | |
56 | ||
57 | // create string reference from const character pointer | |
58 | string_view(const char* str) noexcept | |
59 | : data_(str), length_(std::strlen(str)) {} | |
60 | ||
61 | // Create constant string reference from pointer and length | |
62 | string_view(const std::basic_string<char>& str) noexcept | |
63 | : data_(str.c_str()), length_(str.length()) {} | |
64 | ||
65 | // Create constant string reference from pointer and length | |
66 | string_view(const char* str, size_t len) noexcept | |
67 | : data_(str), length_(len) {} | |
68 | ||
69 | // Implicit conversion to std::string | |
70 | operator std::string() const { return {data_, length_}; } | |
71 | ||
72 | // Return address of the referenced string | |
73 | const char* data() const noexcept { return data_; } | |
74 | ||
75 | // Returns true if `length_` == 0 | |
76 | bool empty() const noexcept { return length_ == 0; } | |
77 | ||
78 | // Return the length of the referenced string | |
79 | size_t length() const noexcept { return length_; } | |
80 | size_t size() const noexcept { return length_; } | |
81 | ||
82 | // Returns a RandomAccessIterator to the first element. | |
83 | const char* begin() const noexcept { return data(); } | |
84 | ||
85 | // Returns a RandomAccessIterator for the last element. | |
86 | const char* end() const noexcept { return data() + length(); } | |
87 | ||
88 | // Returns the character in the i-th position. | |
89 | const char& operator[](std::size_t i) { return *(data() + i); } | |
90 | ||
91 | private: | |
92 | const char* data_; // Pointer to external storage | |
93 | size_t length_; // Length of data pointed to by 'data_' | |
94 | }; | |
95 | ||
96 | inline bool operator==(string_view lhs, string_view rhs) noexcept { | |
97 | return lhs.length() == rhs.length() && | |
98 | std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data()); | |
99 | } | |
100 | ||
101 | inline bool operator==(string_view lhs, const std::string& rhs) noexcept { | |
102 | return lhs == string_view(rhs); | |
103 | } | |
104 | ||
105 | inline bool operator==(const std::string& lhs, string_view rhs) noexcept { | |
106 | return string_view(lhs) == rhs; | |
107 | } | |
108 | ||
109 | inline bool operator==(string_view lhs, const char* rhs) noexcept { | |
110 | return lhs == string_view(rhs); | |
111 | } | |
112 | ||
113 | inline bool operator==(const char* lhs, string_view rhs) noexcept { | |
114 | return string_view(lhs) == rhs; | |
115 | } | |
116 | ||
117 | inline bool operator!=(string_view lhs, string_view rhs) noexcept { | |
118 | return !(lhs == rhs); | |
119 | } | |
120 | ||
121 | inline bool operator!=(string_view lhs, const std::string& rhs) noexcept { | |
122 | return !(lhs == rhs); | |
123 | } | |
124 | ||
125 | inline bool operator!=(const std::string& lhs, string_view rhs) noexcept { | |
126 | return !(lhs == rhs); | |
127 | } | |
128 | ||
129 | inline bool operator!=(string_view lhs, const char* rhs) noexcept { | |
130 | return !(lhs == rhs); | |
131 | } | |
132 | ||
133 | inline bool operator!=(const char* lhs, string_view rhs) noexcept { | |
134 | return !(lhs == rhs); | |
135 | } | |
136 | ||
137 | inline std::ostream& operator<<(std::ostream& os, | |
138 | const opentracing::string_view& ref) { | |
139 | return os.write(ref.data(), static_cast<std::streamsize>(ref.length())); | |
140 | } | |
141 | END_OPENTRACING_ABI_NAMESPACE | |
142 | } // namespace opentracing | |
143 | ||
144 | #endif // OPENTRACING_STRING_VIEW_H |