1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
|
// Copyright The OpenTelemetry Authors
// SPDX-License-Identifier: Apache-2.0
#pragma once
#if defined(OPENTELEMETRY_STL_VERSION)
# if OPENTELEMETRY_STL_VERSION >= 2017
# include "opentelemetry/std/string_view.h"
# define OPENTELEMETRY_HAVE_STD_STRING_VIEW
# endif
#endif
#if !defined(OPENTELEMETRY_HAVE_STD_STRING_VIEW)
# include <algorithm>
# include <cstring>
# include <functional>
# include <ostream>
# include <stdexcept>
# include <string>
# include <type_traits>
# include <utility>
# include "opentelemetry/version.h"
OPENTELEMETRY_BEGIN_NAMESPACE
namespace nostd
{
using Traits = std::char_traits<char>;
/**
* Back port of std::string_view to work with pre-cpp-17 compilers.
*
* Note: This provides a subset of the methods available on std::string_view but
* tries to be as compatible as possible with the std::string_view interface.
*/
class string_view
{
public:
typedef std::size_t size_type;
static constexpr size_type npos = static_cast<size_type>(-1);
string_view() noexcept : length_(0), data_(nullptr) {}
string_view(const char *str) noexcept : length_(std::strlen(str)), data_(str) {}
string_view(const std::basic_string<char> &str OPENTELEMETRY_ATTRIBUTE_LIFETIME_BOUND) noexcept
: length_(str.length()), data_(str.c_str())
{}
string_view(const char *str, size_type len) noexcept : length_(len), data_(str) {}
explicit operator std::string() const { return {data_, length_}; }
const char *data() const noexcept { return data_; }
bool empty() const noexcept { return length_ == 0; }
size_type length() const noexcept { return length_; }
size_type size() const noexcept { return length_; }
const char *begin() const noexcept { return data(); }
const char *end() const noexcept { return data() + length(); }
const char &operator[](size_type i) { return *(data() + i); }
string_view substr(size_type pos, size_type n = npos) const
{
if (pos > length_)
{
# if __EXCEPTIONS
throw std::out_of_range{"opentelemetry::nostd::string_view"};
# else
std::terminate();
# endif
}
n = (std::min)(n, length_ - pos);
return string_view(data_ + pos, n);
}
int compare(string_view v) const noexcept
{
size_type len = (std::min)(size(), v.size());
int result = Traits::compare(data(), v.data(), len);
if (result == 0)
result = size() == v.size() ? 0 : (size() < v.size() ? -1 : 1);
return result;
}
int compare(size_type pos1, size_type count1, string_view v) const
{
return substr(pos1, count1).compare(v);
}
int compare(size_type pos1,
size_type count1,
string_view v,
size_type pos2,
size_type count2) const
{
return substr(pos1, count1).compare(v.substr(pos2, count2));
}
int compare(const char *s) const { return compare(string_view(s)); }
int compare(size_type pos1, size_type count1, const char *s) const
{
return substr(pos1, count1).compare(string_view(s));
}
int compare(size_type pos1, size_type count1, const char *s, size_type count2) const
{
return substr(pos1, count1).compare(string_view(s, count2));
}
size_type find(char ch, size_type pos = 0) const noexcept
{
size_type res = npos;
if (pos < length())
{
auto found = Traits::find(data() + pos, length() - pos, ch);
if (found)
{
res = found - data();
}
}
return res;
}
bool operator<(const string_view v) const noexcept { return compare(v) < 0; }
bool operator>(const string_view v) const noexcept { return compare(v) > 0; }
private:
// Note: uses the same binary layout as libstdc++'s std::string_view
// See
// https://github.com/gcc-mirror/gcc/blob/e0c554e4da7310df83bb1dcc7b8e6c4c9c5a2a4f/libstdc%2B%2B-v3/include/std/string_view#L466-L467
size_type length_;
const char *data_;
};
inline bool operator==(string_view lhs, string_view rhs) noexcept
{
return lhs.length() == rhs.length() &&
# if defined(_MSC_VER)
# if _MSC_VER >= 1900 && _MSC_VER <= 1911
// Avoid SCL error in Visual Studio 2015, VS2017 update 1 to update 4
(std::memcmp(lhs.data(), rhs.data(), lhs.length()) == 0);
# else
std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data());
# endif
# else
std::equal(lhs.data(), lhs.data() + lhs.length(), rhs.data());
# endif
}
inline bool operator==(string_view lhs, const std::string &rhs) noexcept
{
return lhs == string_view(rhs);
}
inline bool operator==(const std::string &lhs, string_view rhs) noexcept
{
return string_view(lhs) == rhs;
}
inline bool operator==(string_view lhs, const char *rhs) noexcept
{
return lhs == string_view(rhs);
}
inline bool operator==(const char *lhs, string_view rhs) noexcept
{
return string_view(lhs) == rhs;
}
inline bool operator!=(string_view lhs, string_view rhs) noexcept
{
return !(lhs == rhs);
}
inline bool operator!=(string_view lhs, const std::string &rhs) noexcept
{
return !(lhs == rhs);
}
inline bool operator!=(const std::string &lhs, string_view rhs) noexcept
{
return !(lhs == rhs);
}
inline bool operator!=(string_view lhs, const char *rhs) noexcept
{
return !(lhs == rhs);
}
inline bool operator!=(const char *lhs, string_view rhs) noexcept
{
return !(lhs == rhs);
}
inline std::ostream &operator<<(std::ostream &os, string_view s)
{
return os.write(s.data(), static_cast<std::streamsize>(s.length()));
}
} // namespace nostd
OPENTELEMETRY_END_NAMESPACE
namespace std
{
template <>
struct hash<OPENTELEMETRY_NAMESPACE::nostd::string_view>
{
std::size_t operator()(const OPENTELEMETRY_NAMESPACE::nostd::string_view &k) const
{
// TODO: for C++17 that has native support for std::basic_string_view it would
// be more performance-efficient to provide a zero-copy hash.
auto s = std::string(k.data(), k.size());
return std::hash<std::string>{}(s);
}
};
} // namespace std
#endif /* OPENTELEMETRY_HAVE_STD_STRING_VIEW */
|