11 #ifndef NONSTD_SV_LITE_H_INCLUDED
12 #define NONSTD_SV_LITE_H_INCLUDED
14 #define string_view_lite_MAJOR 1
15 #define string_view_lite_MINOR 1
16 #define string_view_lite_PATCH 0
18 #define string_view_lite_VERSION \
19 nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY( \
20 string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
22 #define nssv_STRINGIFY(x) nssv_STRINGIFY_(x)
23 #define nssv_STRINGIFY_(x) #x
27 #define nssv_STRING_VIEW_DEFAULT 0
28 #define nssv_STRING_VIEW_NONSTD 1
29 #define nssv_STRING_VIEW_STD 2
31 #if !defined(nssv_CONFIG_SELECT_STRING_VIEW)
32 #define nssv_CONFIG_SELECT_STRING_VIEW \
33 (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD)
36 #if defined(nssv_CONFIG_SELECT_STD_STRING_VIEW) || \
37 defined(nssv_CONFIG_SELECT_NONSTD_STRING_VIEW)
38 #error nssv_CONFIG_SELECT_STD_STRING_VIEW and nssv_CONFIG_SELECT_NONSTD_STRING_VIEW are deprecated and removed, please use nssv_CONFIG_SELECT_STRING_VIEW=nssv_STRING_VIEW_...
41 #ifndef nssv_CONFIG_STD_SV_OPERATOR
42 #define nssv_CONFIG_STD_SV_OPERATOR 0
45 #ifndef nssv_CONFIG_USR_SV_OPERATOR
46 #define nssv_CONFIG_USR_SV_OPERATOR 1
49 #ifdef nssv_CONFIG_CONVERSION_STD_STRING
50 #define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
51 #define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
54 #ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
55 #define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
58 #ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
59 #define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
65 #ifndef nssv_CPLUSPLUS
66 #if defined(_MSVC_LANG) && !defined(__clang__)
67 #define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
69 #define nssv_CPLUSPLUS __cplusplus
73 #define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L)
74 #define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L)
75 #define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L)
76 #define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L)
77 #define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L)
78 #define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202000L)
80 #define nssv_HAVE_STD_STRING_VIEW 0
82 #define nssv_USES_STD_STRING_VIEW \
83 ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \
84 ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && \
85 nssv_HAVE_STD_STRING_VIEW))
87 #define nssv_HAVE_STARTS_WITH (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW)
88 #define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
94 #if nssv_USES_STD_STRING_VIEW
96 #include <string_view>
100 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
105 template <
class CharT,
class Traits,
class Allocator = std::allocator<CharT> >
106 std::basic_string<CharT, Traits, Allocator>
107 to_string(std::basic_string_view<CharT, Traits> v, Allocator
const& a = Allocator())
109 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
112 template <
class CharT,
class Traits,
class Allocator>
113 std::basic_string_view<CharT, Traits>
116 return std::basic_string_view<CharT, Traits>(
s.data(),
s.size());
121 #if nssv_CONFIG_STD_SV_OPERATOR
123 using namespace std::literals::string_view_literals;
127 #if nssv_CONFIG_USR_SV_OPERATOR
131 inline namespace string_view_literals
134 constexpr
std::string_view operator"" _sv(
const char* str,
size_t len) noexcept
160 #endif // nssv_CONFIG_USR_SV_OPERATOR
164 #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
177 using std::operator==;
178 using std::operator!=;
179 using std::operator<;
180 using std::operator<=;
181 using std::operator>;
182 using std::operator>=;
184 using std::operator<<;
188 #else // nssv_HAVE_STD_STRING_VIEW
207 #if defined(_MSC_VER) && !defined(__clang__)
208 #define nssv_COMPILER_MSVC_VER (_MSC_VER)
209 #define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
211 #define nssv_COMPILER_MSVC_VER 0
212 #define nssv_COMPILER_MSVC_VERSION 0
215 #define nssv_COMPILER_VERSION(major, minor, patch) (10 * (10 * major + minor) + patch)
217 #if defined(__clang__)
218 #define nssv_COMPILER_CLANG_VERSION \
219 nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
221 #define nssv_COMPILER_CLANG_VERSION 0
224 #if defined(__GNUC__) && !defined(__clang__)
225 #define nssv_COMPILER_GNUC_VERSION \
226 nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
228 #define nssv_COMPILER_GNUC_VERSION 0
232 #define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
237 #define nssv_HAS_CPP0X _HAS_CPP0X
239 #define nssv_HAS_CPP0X 0
244 #if nssv_COMPILER_MSVC_VER >= 1900
245 #undef nssv_CPP11_OR_GREATER
246 #define nssv_CPP11_OR_GREATER 1
249 #define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
250 #define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
251 #define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
252 #define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
253 #define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
254 #define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
256 #define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
257 #define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
261 #define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
262 #define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
263 #define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
264 #define nssv_HAVE_NOEXCEPT nssv_CPP11_140
265 #define nssv_HAVE_NULLPTR nssv_CPP11_100
266 #define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
267 #define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
268 #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
269 #define nssv_HAVE_WCHAR16_T nssv_CPP11_100
270 #define nssv_HAVE_WCHAR32_T nssv_CPP11_100
272 #if !((nssv_CPP11 && nssv_COMPILER_CLANG_VERSION) || \
273 nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400))
274 #define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
279 #define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
283 #define nssv_HAVE_NODISCARD nssv_CPP17_000
287 #define nssv_HAVE_STD_HASH nssv_CPP11_120
291 #if nssv_HAVE_CONSTEXPR_11
292 #define nssv_constexpr constexpr
294 #define nssv_constexpr
297 #if nssv_HAVE_CONSTEXPR_14
298 #define nssv_constexpr14 constexpr
300 #define nssv_constexpr14
303 #if nssv_HAVE_EXPLICIT_CONVERSION
304 #define nssv_explicit explicit
306 #define nssv_explicit
309 #if nssv_HAVE_INLINE_NAMESPACE
310 #define nssv_inline_ns inline
312 #define nssv_inline_ns
315 #if nssv_HAVE_NOEXCEPT
316 #define nssv_noexcept noexcept
318 #define nssv_noexcept
329 #if nssv_HAVE_NULLPTR
330 #define nssv_nullptr nullptr
332 #define nssv_nullptr NULL
335 #if nssv_HAVE_NODISCARD
336 #define nssv_nodiscard [[nodiscard]]
338 #define nssv_nodiscard
351 #if nssv_CPP11_OR_GREATER
352 #include <type_traits>
357 #if defined(__clang__)
358 #pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
359 #pragma clang diagnostic push
360 #pragma clang diagnostic ignored "-Wuser-defined-literals"
361 #elif defined(__GNUC__)
362 #pragma GCC diagnostic push
363 #pragma GCC diagnostic ignored "-Wliteral-suffix"
366 #if nssv_COMPILER_MSVC_VERSION >= 140
367 #define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
368 #define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress : code))
369 #define nssv_DISABLE_MSVC_WARNINGS(codes) \
370 __pragma(warning(push)) __pragma(warning(disable : codes))
372 #define nssv_SUPPRESS_MSGSL_WARNING(expr)
373 #define nssv_SUPPRESS_MSVC_WARNING(code, descr)
374 #define nssv_DISABLE_MSVC_WARNINGS(codes)
377 #if defined(__clang__)
378 #define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
379 #elif defined(__GNUC__)
380 #define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
381 #elif nssv_COMPILER_MSVC_VERSION >= 140
382 #define nssv_RESTORE_WARNINGS() __pragma(warning(pop))
384 #define nssv_RESTORE_WARNINGS()
403 template <
class CharT,
class Traits = std::
char_traits<CharT> >
410 template <
class CharT,
class Traits
417 typedef Traits traits_type;
418 typedef CharT value_type;
421 typedef CharT
const* const_pointer;
422 typedef CharT& reference;
423 typedef CharT
const& const_reference;
425 typedef const_pointer iterator;
426 typedef const_pointer const_iterator;
427 typedef std::reverse_iterator<const_iterator> reverse_iterator;
428 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
431 typedef std::ptrdiff_t difference_type;
439 #if nssv_CPP11_OR_GREATER
444 : data_(other.
data_),
451 : data_(
s), size_(count)
461 #if nssv_CPP11_OR_GREATER
482 return data_ + size_;
496 return const_reverse_iterator(end());
500 return const_reverse_iterator(begin());
524 return (std::numeric_limits<size_type>::max)();
547 throw std::out_of_range(
"nonst::string_view::at()");
556 return data_at(
size() - 1);
588 size_type
copy(CharT*
dest, size_type n, size_type pos = 0)
const
591 throw std::out_of_range(
"nonst::string_view::copy()");
593 const size_type rlen = (std::min)(n,
size() - pos);
603 throw std::out_of_range(
"nonst::string_view::substr()");
612 if (
const int result =
622 return substr(pos1, n1).compare(other);
626 size_type pos2, size_type n2)
const
628 return substr(pos1, n1).compare(other.substr(pos2, n2));
636 nssv_constexpr int compare(size_type pos1, size_type n1, CharT
const*
s)
const
641 nssv_constexpr int compare(size_type pos1, size_type n1, CharT
const*
s,
653 return size() >= v.
size() && compare(0, v.
size(), v) == 0;
689 pos >=
size() ? npos :
690 to_pos(std::search(cbegin() + pos, cend(), v.cbegin(),
691 v.cend(), Traits::eq));
720 return (std::min)(
size(), pos);
722 const_iterator last = cbegin() + (std::min)(
size() - v.
size(), pos) + v.
size();
723 const_iterator result =
724 std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq);
726 return result != last ? size_type(result - cbegin()) : npos;
751 return pos >=
size() ? npos :
752 to_pos(std::find_first_of(cbegin() + pos, cend(), v.cbegin(),
753 v.cend(), Traits::eq));
769 size_type pos = 0)
const
782 find_last_of(v,
size() - 1) :
783 to_pos(std::find_first_of(const_reverse_iterator(cbegin() + pos + 1),
784 crend(), v.cbegin(), v.cend(), Traits::eq));
788 find_last_of(CharT c, size_type pos = npos)
const nssv_noexcept
794 size_type count)
const
800 size_type pos = npos)
const
810 return pos >=
size() ? npos :
811 to_pos(std::find_if(cbegin() + pos, cend(), not_in_view(v)));
815 find_first_not_of(CharT c, size_type pos = 0)
const nssv_noexcept
820 nssv_constexpr size_type find_first_not_of(CharT
const*
s, size_type pos,
821 size_type count)
const
827 size_type pos = 0)
const
837 return empty() ? npos :
839 find_last_not_of(v,
size() - 1) :
840 to_pos(std::find_if(const_reverse_iterator(cbegin() + pos + 1),
841 crend(), not_in_view(v)));
845 find_last_not_of(CharT c, size_type pos = npos)
const nssv_noexcept
850 nssv_constexpr size_type find_last_not_of(CharT
const*
s, size_type pos,
851 size_type count)
const
857 size_type pos = npos)
const
864 #if nssv_CPP17_OR_GREATER
866 #elif nssv_CPP11_OR_GREATER
889 return npos == v.find_first_of(c);
895 return it == cend() ? npos : size_type(it - cbegin());
900 return it == crend() ? npos : size_type(crend() - it - 1);
905 #if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500)
917 #if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
919 template <
class Allocator>
926 #if nssv_HAVE_EXPLICIT_CONVERSION
928 template <
class Allocator>
929 explicit operator std::basic_string<CharT, Traits, Allocator>()
const
934 #endif // nssv_HAVE_EXPLICIT_CONVERSION
936 #if nssv_CPP11_OR_GREATER
938 template <
class Allocator = std::allocator<CharT> >
939 std::basic_string<CharT, Traits, Allocator>
940 to_string(Allocator
const& a = Allocator())
const
942 return std::basic_string<CharT, Traits, Allocator>(begin(), end(), a);
947 std::basic_string<CharT, Traits>
to_string()
const
949 return std::basic_string<CharT, Traits>(begin(), end());
952 template <
class Allocator>
953 std::basic_string<CharT, Traits, Allocator>
to_string(Allocator
const& a)
const
955 return std::basic_string<CharT, Traits, Allocator>(begin(), end(), a);
958 #endif // nssv_CPP11_OR_GREATER
960 #endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
970 template <
class CharT,
class Traits>
977 template <
class CharT,
class Traits>
984 template <
class CharT,
class Traits>
991 template <
class CharT,
class Traits>
998 template <
class CharT,
class Traits>
1005 template <
class CharT,
class Traits>
1017 #if nssv_CPP11_OR_GREATER && !nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141)
1019 #define nssv_BASIC_STRING_VIEW_I(T, U) typename std::decay<basic_string_view<T, U> >::type
1021 #if nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 140, 150)
1022 #define nssv_MSVC_ORDER(x) , int = x
1024 #define nssv_MSVC_ORDER(x)
1029 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1031 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
1037 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1041 return lhs.size() == rhs.
size() && lhs.compare(rhs) == 0;
1046 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1048 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
1051 return lhs.
size() != rhs.size() || lhs.
compare(rhs) != 0;
1054 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1058 return lhs.compare(rhs) != 0;
1063 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1070 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1074 return lhs.compare(rhs) < 0;
1079 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1081 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
1087 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1091 return lhs.compare(rhs) <= 0;
1096 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1103 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1107 return lhs.compare(rhs) > 0;
1112 template <
class CharT,
class Traits nssv_MSVC_ORDER(1)>
1114 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
1120 template <
class CharT,
class Traits nssv_MSVC_ORDER(2)>
1124 return lhs.compare(rhs) >= 0;
1127 #undef nssv_MSVC_ORDER
1128 #undef nssv_BASIC_STRING_VIEW_I
1130 #endif // nssv_CPP11_OR_GREATER
1137 template <
class Stream>
1140 for (std::streamsize i = 0; i < n; ++i)
1141 os.rdbuf()->sputc(os.fill());
1144 template <
class Stream,
class View>
1145 Stream& write_to_stream(Stream& os, View
const& sv)
1147 typename Stream::sentry sentry(os);
1152 const std::streamsize length =
static_cast<std::streamsize
>(sv.length());
1155 const bool pad = (length < os.width());
1156 const bool left_pad =
1163 os.rdbuf()->sputn(sv.begin(), length);
1165 if (pad && !left_pad)
1176 template <
class CharT,
class Traits>
1177 std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
1180 return detail::write_to_stream(os, sv);
1187 #if nssv_HAVE_WCHAR16_T
1199 #if nssv_HAVE_USER_DEFINED_LITERALS
1208 #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
1234 #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
1236 #if nssv_CONFIG_USR_SV_OPERATOR
1262 #endif // nssv_CONFIG_USR_SV_OPERATOR
1273 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1282 #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
1284 template <
class CharT,
class Traits,
class Allocator = std::allocator<CharT> >
1285 std::basic_string<CharT, Traits, Allocator>
to_string(basic_string_view<CharT, Traits> v,
1286 Allocator
const& a = Allocator())
1288 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
1293 template <
class CharT,
class Traits>
1294 std::basic_string<CharT, Traits>
to_string(basic_string_view<CharT, Traits> v)
1296 return std::basic_string<CharT, Traits>(v.begin(), v.end());
1299 template <
class CharT,
class Traits,
class Allocator>
1300 std::basic_string<CharT, Traits, Allocator>
to_string(basic_string_view<CharT, Traits> v,
1303 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
1306 #endif // nssv_CPP11_OR_GREATER
1308 template <
class CharT,
class Traits,
class Allocator>
1309 basic_string_view<CharT, Traits>
1312 return basic_string_view<CharT, Traits>(
s.data(),
s.size());
1318 #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1331 #if nssv_HAVE_WCHAR16_T
1334 #if nssv_HAVE_WCHAR32_T
1340 using sv_lite::operator==;
1341 using sv_lite::operator!=;
1342 using sv_lite::operator<;
1343 using sv_lite::operator<=;
1344 using sv_lite::operator>;
1345 using sv_lite::operator>=;
1347 using sv_lite::operator<<;
1349 #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
1361 #if nssv_HAVE_STD_HASH
1363 #include <functional>
1374 return std::hash<std::string>()(std::string(v.data(), v.size()));
1384 return std::hash<std::wstring>()(std::wstring(v.data(), v.size()));
1394 return std::hash<std::u16string>()(std::u16string(v.data(), v.size()));
1404 return std::hash<std::u32string>()(std::u32string(v.data(), v.size()));
1410 #endif // nssv_HAVE_STD_HASH
1414 #endif // nssv_HAVE_STD_STRING_VIEW
1415 #endif // NONSTD_SV_LITE_H_INCLUDED