string_view.hpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684
  1. // Copyright 2017-2020 by Martin Moene
  2. //
  3. // string-view lite, a C++17-like string_view for C++98 and later.
  4. // For more information see https://github.com/martinmoene/string-view-lite
  5. //
  6. // Distributed under the Boost Software License, Version 1.0.
  7. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  8. #pragma once
  9. #ifndef NONSTD_SV_LITE_H_INCLUDED
  10. #define NONSTD_SV_LITE_H_INCLUDED
  11. #define string_view_lite_MAJOR 1
  12. #define string_view_lite_MINOR 7
  13. #define string_view_lite_PATCH 0
  14. #define string_view_lite_VERSION nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY(string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
  15. #define nssv_STRINGIFY( x ) nssv_STRINGIFY_( x )
  16. #define nssv_STRINGIFY_( x ) #x
  17. // string-view lite configuration:
  18. #define nssv_STRING_VIEW_DEFAULT 0
  19. #define nssv_STRING_VIEW_NONSTD 1
  20. #define nssv_STRING_VIEW_STD 2
  21. // tweak header support:
  22. #ifdef __has_include
  23. # if __has_include(<nonstd/string_view.tweak.hpp>)
  24. # include <nonstd/string_view.tweak.hpp>
  25. # endif
  26. #define nssv_HAVE_TWEAK_HEADER 1
  27. #else
  28. #define nssv_HAVE_TWEAK_HEADER 0
  29. //# pragma message("string_view.hpp: Note: Tweak header not supported.")
  30. #endif
  31. // string_view selection and configuration:
  32. #if !defined( nssv_CONFIG_SELECT_STRING_VIEW )
  33. # define nssv_CONFIG_SELECT_STRING_VIEW ( nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD )
  34. #endif
  35. #ifndef nssv_CONFIG_STD_SV_OPERATOR
  36. # define nssv_CONFIG_STD_SV_OPERATOR 0
  37. #endif
  38. #ifndef nssv_CONFIG_USR_SV_OPERATOR
  39. # define nssv_CONFIG_USR_SV_OPERATOR 1
  40. #endif
  41. #ifdef nssv_CONFIG_CONVERSION_STD_STRING
  42. # define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS nssv_CONFIG_CONVERSION_STD_STRING
  43. # define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS nssv_CONFIG_CONVERSION_STD_STRING
  44. #endif
  45. #ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  46. # define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
  47. #endif
  48. #ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  49. # define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
  50. #endif
  51. #ifndef nssv_CONFIG_NO_STREAM_INSERTION
  52. # define nssv_CONFIG_NO_STREAM_INSERTION 0
  53. #endif
  54. // Control presence of exception handling (try and auto discover):
  55. #ifndef nssv_CONFIG_NO_EXCEPTIONS
  56. # if defined(_MSC_VER)
  57. # include <cstddef> // for _HAS_EXCEPTIONS
  58. # endif
  59. # if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
  60. # define nssv_CONFIG_NO_EXCEPTIONS 0
  61. # else
  62. # define nssv_CONFIG_NO_EXCEPTIONS 1
  63. # endif
  64. #endif
  65. // C++ language version detection (C++23 is speculative):
  66. // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
  67. #ifndef nssv_CPLUSPLUS
  68. # if defined(_MSVC_LANG ) && !defined(__clang__)
  69. # define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
  70. # else
  71. # define nssv_CPLUSPLUS __cplusplus
  72. # endif
  73. #endif
  74. #define nssv_CPP98_OR_GREATER ( nssv_CPLUSPLUS >= 199711L )
  75. #define nssv_CPP11_OR_GREATER ( nssv_CPLUSPLUS >= 201103L )
  76. #define nssv_CPP11_OR_GREATER_ ( nssv_CPLUSPLUS >= 201103L )
  77. #define nssv_CPP14_OR_GREATER ( nssv_CPLUSPLUS >= 201402L )
  78. #define nssv_CPP17_OR_GREATER ( nssv_CPLUSPLUS >= 201703L )
  79. #define nssv_CPP20_OR_GREATER ( nssv_CPLUSPLUS >= 202002L )
  80. #define nssv_CPP23_OR_GREATER ( nssv_CPLUSPLUS >= 202300L )
  81. // use C++17 std::string_view if available and requested:
  82. #if nssv_CPP17_OR_GREATER && defined(__has_include )
  83. # if __has_include( <string_view> )
  84. # define nssv_HAVE_STD_STRING_VIEW 1
  85. # else
  86. # define nssv_HAVE_STD_STRING_VIEW 0
  87. # endif
  88. #else
  89. # define nssv_HAVE_STD_STRING_VIEW 0
  90. #endif
  91. #define nssv_USES_STD_STRING_VIEW ( (nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && nssv_HAVE_STD_STRING_VIEW) )
  92. #define nssv_HAVE_STARTS_WITH ( nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW )
  93. #define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
  94. //
  95. // Use C++17 std::string_view:
  96. //
  97. #if nssv_USES_STD_STRING_VIEW
  98. #include <string_view>
  99. // Extensions for std::string:
  100. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  101. namespace nonstd {
  102. template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
  103. std::basic_string<CharT, Traits, Allocator>
  104. to_string( std::basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
  105. {
  106. return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
  107. }
  108. template< class CharT, class Traits, class Allocator >
  109. std::basic_string_view<CharT, Traits>
  110. to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
  111. {
  112. return std::basic_string_view<CharT, Traits>( s.data(), s.size() );
  113. }
  114. // Literal operators sv and _sv:
  115. #if nssv_CONFIG_STD_SV_OPERATOR
  116. using namespace std::literals::string_view_literals;
  117. #endif
  118. #if nssv_CONFIG_USR_SV_OPERATOR
  119. inline namespace literals {
  120. inline namespace string_view_literals {
  121. constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1)
  122. {
  123. return std::string_view{ str, len };
  124. }
  125. constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2)
  126. {
  127. return std::u16string_view{ str, len };
  128. }
  129. constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3)
  130. {
  131. return std::u32string_view{ str, len };
  132. }
  133. constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4)
  134. {
  135. return std::wstring_view{ str, len };
  136. }
  137. }} // namespace literals::string_view_literals
  138. #endif // nssv_CONFIG_USR_SV_OPERATOR
  139. } // namespace nonstd
  140. #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  141. namespace nonstd {
  142. using std::string_view;
  143. using std::wstring_view;
  144. using std::u16string_view;
  145. using std::u32string_view;
  146. using std::basic_string_view;
  147. // literal "sv" and "_sv", see above
  148. using std::operator==;
  149. using std::operator!=;
  150. using std::operator<;
  151. using std::operator<=;
  152. using std::operator>;
  153. using std::operator>=;
  154. using std::operator<<;
  155. } // namespace nonstd
  156. #else // nssv_HAVE_STD_STRING_VIEW
  157. //
  158. // Before C++17: use string_view lite:
  159. //
  160. // Compiler versions:
  161. //
  162. // MSVC++ 6.0 _MSC_VER == 1200 nssv_COMPILER_MSVC_VERSION == 60 (Visual Studio 6.0)
  163. // MSVC++ 7.0 _MSC_VER == 1300 nssv_COMPILER_MSVC_VERSION == 70 (Visual Studio .NET 2002)
  164. // MSVC++ 7.1 _MSC_VER == 1310 nssv_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003)
  165. // MSVC++ 8.0 _MSC_VER == 1400 nssv_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
  166. // MSVC++ 9.0 _MSC_VER == 1500 nssv_COMPILER_MSVC_VERSION == 90 (Visual Studio 2008)
  167. // MSVC++ 10.0 _MSC_VER == 1600 nssv_COMPILER_MSVC_VERSION == 100 (Visual Studio 2010)
  168. // MSVC++ 11.0 _MSC_VER == 1700 nssv_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012)
  169. // MSVC++ 12.0 _MSC_VER == 1800 nssv_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
  170. // MSVC++ 14.0 _MSC_VER == 1900 nssv_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015)
  171. // MSVC++ 14.1 _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
  172. // MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
  173. #if defined(_MSC_VER ) && !defined(__clang__)
  174. # define nssv_COMPILER_MSVC_VER (_MSC_VER )
  175. # define nssv_COMPILER_MSVC_VERSION (_MSC_VER / 10 - 10 * ( 5 + (_MSC_VER < 1900 ) ) )
  176. #else
  177. # define nssv_COMPILER_MSVC_VER 0
  178. # define nssv_COMPILER_MSVC_VERSION 0
  179. #endif
  180. #define nssv_COMPILER_VERSION( major, minor, patch ) ( 10 * ( 10 * (major) + (minor) ) + (patch) )
  181. #if defined( __apple_build_version__ )
  182. # define nssv_COMPILER_APPLECLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
  183. # define nssv_COMPILER_CLANG_VERSION 0
  184. #elif defined( __clang__ )
  185. # define nssv_COMPILER_APPLECLANG_VERSION 0
  186. # define nssv_COMPILER_CLANG_VERSION nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
  187. #else
  188. # define nssv_COMPILER_APPLECLANG_VERSION 0
  189. # define nssv_COMPILER_CLANG_VERSION 0
  190. #endif
  191. #if defined(__GNUC__) && !defined(__clang__)
  192. # define nssv_COMPILER_GNUC_VERSION nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
  193. #else
  194. # define nssv_COMPILER_GNUC_VERSION 0
  195. #endif
  196. // half-open range [lo..hi):
  197. #define nssv_BETWEEN( v, lo, hi ) ( (lo) <= (v) && (v) < (hi) )
  198. // Presence of language and library features:
  199. #ifdef _HAS_CPP0X
  200. # define nssv_HAS_CPP0X _HAS_CPP0X
  201. #else
  202. # define nssv_HAS_CPP0X 0
  203. #endif
  204. // Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
  205. #if nssv_COMPILER_MSVC_VER >= 1900
  206. # undef nssv_CPP11_OR_GREATER
  207. # define nssv_CPP11_OR_GREATER 1
  208. #endif
  209. #define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
  210. #define nssv_CPP11_100 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
  211. #define nssv_CPP11_110 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
  212. #define nssv_CPP11_120 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
  213. #define nssv_CPP11_140 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
  214. #define nssv_CPP11_141 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
  215. #define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
  216. #define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
  217. // Presence of C++11 language features:
  218. #define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
  219. #define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
  220. #define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
  221. #define nssv_HAVE_IS_DEFAULT nssv_CPP11_140
  222. #define nssv_HAVE_IS_DELETE nssv_CPP11_140
  223. #define nssv_HAVE_NOEXCEPT nssv_CPP11_140
  224. #define nssv_HAVE_NULLPTR nssv_CPP11_100
  225. #define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
  226. #define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
  227. #define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
  228. #define nssv_HAVE_WCHAR16_T nssv_CPP11_100
  229. #define nssv_HAVE_WCHAR32_T nssv_CPP11_100
  230. #if ! ( ( nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION ) || nssv_BETWEEN( nssv_COMPILER_CLANG_VERSION, 300, 400 ) )
  231. # define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
  232. #else
  233. # define nssv_HAVE_STD_DEFINED_LITERALS 0
  234. #endif
  235. // Presence of C++14 language features:
  236. #define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
  237. // Presence of C++17 language features:
  238. #define nssv_HAVE_NODISCARD nssv_CPP17_000
  239. // Presence of C++ library features:
  240. #define nssv_HAVE_STD_HASH nssv_CPP11_120
  241. // Presence of compiler intrinsics:
  242. // Providing char-type specializations for compare() and length() that
  243. // use compiler intrinsics can improve compile- and run-time performance.
  244. //
  245. // The challenge is in using the right combinations of builtin availability
  246. // and its constexpr-ness.
  247. //
  248. // | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) |
  249. // |----------|------------------------------|---------------------|
  250. // | clang | 4.0 (>= 4.0 ) | any (? ) |
  251. // | clang-a | 9.0 (>= 9.0 ) | any (? ) |
  252. // | gcc | any (constexpr) | any (? ) |
  253. // | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) |
  254. #define nssv_HAVE_BUILTIN_VER ( (nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || nssv_COMPILER_APPLECLANG_VERSION >= 900 )
  255. #define nssv_HAVE_BUILTIN_CE ( nssv_HAVE_BUILTIN_VER )
  256. #define nssv_HAVE_BUILTIN_MEMCMP ( (nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_14 )
  257. #define nssv_HAVE_BUILTIN_STRLEN ( (nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || !nssv_HAVE_CONSTEXPR_11 )
  258. #ifdef __has_builtin
  259. # define nssv_HAVE_BUILTIN( x ) __has_builtin( x )
  260. #else
  261. # define nssv_HAVE_BUILTIN( x ) 0
  262. #endif
  263. #if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
  264. # define nssv_BUILTIN_MEMCMP __builtin_memcmp
  265. #else
  266. # define nssv_BUILTIN_MEMCMP memcmp
  267. #endif
  268. #if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
  269. # define nssv_BUILTIN_STRLEN __builtin_strlen
  270. #else
  271. # define nssv_BUILTIN_STRLEN strlen
  272. #endif
  273. // C++ feature usage:
  274. #if nssv_HAVE_CONSTEXPR_11
  275. # define nssv_constexpr constexpr
  276. #else
  277. # define nssv_constexpr /*constexpr*/
  278. #endif
  279. #if nssv_HAVE_CONSTEXPR_14
  280. # define nssv_constexpr14 constexpr
  281. #else
  282. # define nssv_constexpr14 /*constexpr*/
  283. #endif
  284. #if nssv_HAVE_EXPLICIT_CONVERSION
  285. # define nssv_explicit explicit
  286. #else
  287. # define nssv_explicit /*explicit*/
  288. #endif
  289. #if nssv_HAVE_INLINE_NAMESPACE
  290. # define nssv_inline_ns inline
  291. #else
  292. # define nssv_inline_ns /*inline*/
  293. #endif
  294. #if nssv_HAVE_NOEXCEPT
  295. # define nssv_noexcept noexcept
  296. #else
  297. # define nssv_noexcept /*noexcept*/
  298. #endif
  299. //#if nssv_HAVE_REF_QUALIFIER
  300. //# define nssv_ref_qual &
  301. //# define nssv_refref_qual &&
  302. //#else
  303. //# define nssv_ref_qual /*&*/
  304. //# define nssv_refref_qual /*&&*/
  305. //#endif
  306. #if nssv_HAVE_NULLPTR
  307. # define nssv_nullptr nullptr
  308. #else
  309. # define nssv_nullptr NULL
  310. #endif
  311. #if nssv_HAVE_NODISCARD
  312. # define nssv_nodiscard [[nodiscard]]
  313. #else
  314. # define nssv_nodiscard /*[[nodiscard]]*/
  315. #endif
  316. // Additional includes:
  317. #include <algorithm>
  318. #include <cassert>
  319. #include <iterator>
  320. #include <limits>
  321. #include <string> // std::char_traits<>
  322. #if ! nssv_CONFIG_NO_STREAM_INSERTION
  323. # include <ostream>
  324. #endif
  325. #if ! nssv_CONFIG_NO_EXCEPTIONS
  326. # include <stdexcept>
  327. #endif
  328. #if nssv_CPP11_OR_GREATER
  329. # include <type_traits>
  330. #endif
  331. // Clang, GNUC, MSVC warning suppression macros:
  332. #if defined(__clang__)
  333. # pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
  334. # pragma clang diagnostic push
  335. # pragma clang diagnostic ignored "-Wuser-defined-literals"
  336. #elif defined(__GNUC__)
  337. # pragma GCC diagnostic push
  338. # pragma GCC diagnostic ignored "-Wliteral-suffix"
  339. #endif // __clang__
  340. #if nssv_COMPILER_MSVC_VERSION >= 140
  341. # define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
  342. # define nssv_SUPPRESS_MSVC_WARNING(code, descr) __pragma(warning(suppress: code) )
  343. # define nssv_DISABLE_MSVC_WARNINGS(codes) __pragma(warning(push)) __pragma(warning(disable: codes))
  344. #else
  345. # define nssv_SUPPRESS_MSGSL_WARNING(expr)
  346. # define nssv_SUPPRESS_MSVC_WARNING(code, descr)
  347. # define nssv_DISABLE_MSVC_WARNINGS(codes)
  348. #endif
  349. #if defined(__clang__)
  350. # define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
  351. #elif defined(__GNUC__)
  352. # define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
  353. #elif nssv_COMPILER_MSVC_VERSION >= 140
  354. # define nssv_RESTORE_WARNINGS() __pragma(warning(pop ))
  355. #else
  356. # define nssv_RESTORE_WARNINGS()
  357. #endif
  358. // Suppress the following MSVC (GSL) warnings:
  359. // - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
  360. // start with an underscore are reserved
  361. // - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
  362. // use brace initialization, gsl::narrow_cast or gsl::narow
  363. // - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
  364. nssv_DISABLE_MSVC_WARNINGS( 4455 26481 26472 )
  365. //nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
  366. //nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
  367. namespace nonstd { namespace sv_lite {
  368. //
  369. // basic_string_view declaration:
  370. //
  371. template
  372. <
  373. class CharT,
  374. class Traits = std::char_traits<CharT>
  375. >
  376. class basic_string_view;
  377. namespace detail {
  378. // support constexpr comparison in C++14;
  379. // for C++17 and later, use provided traits:
  380. template< typename CharT >
  381. inline nssv_constexpr14 int compare( CharT const * s1, CharT const * s2, std::size_t count )
  382. {
  383. while ( count-- != 0 )
  384. {
  385. if ( *s1 < *s2 ) return -1;
  386. if ( *s1 > *s2 ) return +1;
  387. ++s1; ++s2;
  388. }
  389. return 0;
  390. }
  391. #if nssv_HAVE_BUILTIN_MEMCMP
  392. // specialization of compare() for char, see also generic compare() above:
  393. inline nssv_constexpr14 int compare( char const * s1, char const * s2, std::size_t count )
  394. {
  395. return nssv_BUILTIN_MEMCMP( s1, s2, count );
  396. }
  397. #endif
  398. #if nssv_HAVE_BUILTIN_STRLEN
  399. // specialization of length() for char, see also generic length() further below:
  400. inline nssv_constexpr std::size_t length( char const * s )
  401. {
  402. return nssv_BUILTIN_STRLEN( s );
  403. }
  404. #endif
  405. #if defined(__OPTIMIZE__)
  406. // gcc, clang provide __OPTIMIZE__
  407. // Expect tail call optimization to make length() non-recursive:
  408. template< typename CharT >
  409. inline nssv_constexpr std::size_t length( CharT * s, std::size_t result = 0 )
  410. {
  411. return *s == '\0' ? result : length( s + 1, result + 1 );
  412. }
  413. #else // OPTIMIZE
  414. // non-recursive:
  415. template< typename CharT >
  416. inline nssv_constexpr14 std::size_t length( CharT * s )
  417. {
  418. std::size_t result = 0;
  419. while ( *s++ != '\0' )
  420. {
  421. ++result;
  422. }
  423. return result;
  424. }
  425. #endif // OPTIMIZE
  426. #if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
  427. #if defined(__OPTIMIZE__)
  428. // gcc, clang provide __OPTIMIZE__
  429. // Expect tail call optimization to make search() non-recursive:
  430. template< class CharT, class Traits = std::char_traits<CharT> >
  431. constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
  432. {
  433. return haystack.starts_with( needle ) ? haystack.begin() :
  434. haystack.empty() ? haystack.end() : search( haystack.substr(1), needle );
  435. }
  436. #else // OPTIMIZE
  437. // non-recursive:
  438. template< class CharT, class Traits = std::char_traits<CharT> >
  439. constexpr const CharT* search( basic_string_view<CharT, Traits> haystack, basic_string_view<CharT, Traits> needle )
  440. {
  441. return std::search( haystack.begin(), haystack.end(), needle.begin(), needle.end() );
  442. }
  443. #endif // OPTIMIZE
  444. #endif // nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
  445. } // namespace detail
  446. //
  447. // basic_string_view:
  448. //
  449. template
  450. <
  451. class CharT,
  452. class Traits /* = std::char_traits<CharT> */
  453. >
  454. class basic_string_view
  455. {
  456. public:
  457. // Member types:
  458. typedef Traits traits_type;
  459. typedef CharT value_type;
  460. typedef CharT * pointer;
  461. typedef CharT const * const_pointer;
  462. typedef CharT & reference;
  463. typedef CharT const & const_reference;
  464. typedef const_pointer iterator;
  465. typedef const_pointer const_iterator;
  466. typedef std::reverse_iterator< const_iterator > reverse_iterator;
  467. typedef std::reverse_iterator< const_iterator > const_reverse_iterator;
  468. typedef std::size_t size_type;
  469. typedef std::ptrdiff_t difference_type;
  470. // 24.4.2.1 Construction and assignment:
  471. nssv_constexpr basic_string_view() nssv_noexcept
  472. : data_( nssv_nullptr )
  473. , size_( 0 )
  474. {}
  475. #if nssv_CPP11_OR_GREATER
  476. nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept = default;
  477. #else
  478. nssv_constexpr basic_string_view( basic_string_view const & other ) nssv_noexcept
  479. : data_( other.data_)
  480. , size_( other.size_)
  481. {}
  482. #endif
  483. nssv_constexpr basic_string_view( CharT const * s, size_type count ) nssv_noexcept // non-standard noexcept
  484. : data_( s )
  485. , size_( count )
  486. {}
  487. nssv_constexpr basic_string_view( CharT const * s) nssv_noexcept // non-standard noexcept
  488. : data_( s )
  489. #if nssv_CPP17_OR_GREATER
  490. , size_( Traits::length(s) )
  491. #elif nssv_CPP11_OR_GREATER
  492. , size_( detail::length(s) )
  493. #else
  494. , size_( Traits::length(s) )
  495. #endif
  496. {}
  497. #if nssv_HAVE_NULLPTR
  498. # if nssv_HAVE_IS_DELETE
  499. nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept = delete;
  500. # else
  501. private: nssv_constexpr basic_string_view( std::nullptr_t ) nssv_noexcept; public:
  502. # endif
  503. #endif
  504. // Assignment:
  505. #if nssv_CPP11_OR_GREATER
  506. nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept = default;
  507. #else
  508. nssv_constexpr14 basic_string_view & operator=( basic_string_view const & other ) nssv_noexcept
  509. {
  510. data_ = other.data_;
  511. size_ = other.size_;
  512. return *this;
  513. }
  514. #endif
  515. // 24.4.2.2 Iterator support:
  516. nssv_constexpr const_iterator begin() const nssv_noexcept { return data_; }
  517. nssv_constexpr const_iterator end() const nssv_noexcept { return data_ + size_; }
  518. nssv_constexpr const_iterator cbegin() const nssv_noexcept { return begin(); }
  519. nssv_constexpr const_iterator cend() const nssv_noexcept { return end(); }
  520. nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept { return const_reverse_iterator( end() ); }
  521. nssv_constexpr const_reverse_iterator rend() const nssv_noexcept { return const_reverse_iterator( begin() ); }
  522. nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept { return rbegin(); }
  523. nssv_constexpr const_reverse_iterator crend() const nssv_noexcept { return rend(); }
  524. // 24.4.2.3 Capacity:
  525. nssv_constexpr size_type size() const nssv_noexcept { return size_; }
  526. nssv_constexpr size_type length() const nssv_noexcept { return size_; }
  527. nssv_constexpr size_type max_size() const nssv_noexcept { return (std::numeric_limits< size_type >::max)(); }
  528. // since C++20
  529. nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept
  530. {
  531. return 0 == size_;
  532. }
  533. // 24.4.2.4 Element access:
  534. nssv_constexpr const_reference operator[]( size_type pos ) const
  535. {
  536. return data_at( pos );
  537. }
  538. nssv_constexpr14 const_reference at( size_type pos ) const
  539. {
  540. #if nssv_CONFIG_NO_EXCEPTIONS
  541. assert( pos < size() );
  542. #else
  543. if ( pos >= size() )
  544. {
  545. throw std::out_of_range("nonstd::string_view::at()");
  546. }
  547. #endif
  548. return data_at( pos );
  549. }
  550. nssv_constexpr const_reference front() const { return data_at( 0 ); }
  551. nssv_constexpr const_reference back() const { return data_at( size() - 1 ); }
  552. nssv_constexpr const_pointer data() const nssv_noexcept { return data_; }
  553. // 24.4.2.5 Modifiers:
  554. nssv_constexpr14 void remove_prefix( size_type n )
  555. {
  556. assert( n <= size() );
  557. data_ += n;
  558. size_ -= n;
  559. }
  560. nssv_constexpr14 void remove_suffix( size_type n )
  561. {
  562. assert( n <= size() );
  563. size_ -= n;
  564. }
  565. nssv_constexpr14 void swap( basic_string_view & other ) nssv_noexcept
  566. {
  567. const basic_string_view tmp(other);
  568. other = *this;
  569. *this = tmp;
  570. }
  571. // 24.4.2.6 String operations:
  572. size_type copy( CharT * dest, size_type n, size_type pos = 0 ) const
  573. {
  574. #if nssv_CONFIG_NO_EXCEPTIONS
  575. assert( pos <= size() );
  576. #else
  577. if ( pos > size() )
  578. {
  579. throw std::out_of_range("nonstd::string_view::copy()");
  580. }
  581. #endif
  582. const size_type rlen = (std::min)( n, size() - pos );
  583. (void) Traits::copy( dest, data() + pos, rlen );
  584. return rlen;
  585. }
  586. nssv_constexpr14 basic_string_view substr( size_type pos = 0, size_type n = npos ) const
  587. {
  588. #if nssv_CONFIG_NO_EXCEPTIONS
  589. assert( pos <= size() );
  590. #else
  591. if ( pos > size() )
  592. {
  593. throw std::out_of_range("nonstd::string_view::substr()");
  594. }
  595. #endif
  596. return basic_string_view( data() + pos, (std::min)( n, size() - pos ) );
  597. }
  598. // compare(), 6x:
  599. nssv_constexpr14 int compare( basic_string_view other ) const nssv_noexcept // (1)
  600. {
  601. #if nssv_CPP17_OR_GREATER
  602. if ( const int result = Traits::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
  603. #else
  604. if ( const int result = detail::compare( data(), other.data(), (std::min)( size(), other.size() ) ) )
  605. #endif
  606. {
  607. return result;
  608. }
  609. return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
  610. }
  611. nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other ) const // (2)
  612. {
  613. return substr( pos1, n1 ).compare( other );
  614. }
  615. nssv_constexpr int compare( size_type pos1, size_type n1, basic_string_view other, size_type pos2, size_type n2 ) const // (3)
  616. {
  617. return substr( pos1, n1 ).compare( other.substr( pos2, n2 ) );
  618. }
  619. nssv_constexpr int compare( CharT const * s ) const // (4)
  620. {
  621. return compare( basic_string_view( s ) );
  622. }
  623. nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s ) const // (5)
  624. {
  625. return substr( pos1, n1 ).compare( basic_string_view( s ) );
  626. }
  627. nssv_constexpr int compare( size_type pos1, size_type n1, CharT const * s, size_type n2 ) const // (6)
  628. {
  629. return substr( pos1, n1 ).compare( basic_string_view( s, n2 ) );
  630. }
  631. // 24.4.2.7 Searching:
  632. // starts_with(), 3x, since C++20:
  633. nssv_constexpr bool starts_with( basic_string_view v ) const nssv_noexcept // (1)
  634. {
  635. return size() >= v.size() && compare( 0, v.size(), v ) == 0;
  636. }
  637. nssv_constexpr bool starts_with( CharT c ) const nssv_noexcept // (2)
  638. {
  639. return starts_with( basic_string_view( &c, 1 ) );
  640. }
  641. nssv_constexpr bool starts_with( CharT const * s ) const // (3)
  642. {
  643. return starts_with( basic_string_view( s ) );
  644. }
  645. // ends_with(), 3x, since C++20:
  646. nssv_constexpr bool ends_with( basic_string_view v ) const nssv_noexcept // (1)
  647. {
  648. return size() >= v.size() && compare( size() - v.size(), npos, v ) == 0;
  649. }
  650. nssv_constexpr bool ends_with( CharT c ) const nssv_noexcept // (2)
  651. {
  652. return ends_with( basic_string_view( &c, 1 ) );
  653. }
  654. nssv_constexpr bool ends_with( CharT const * s ) const // (3)
  655. {
  656. return ends_with( basic_string_view( s ) );
  657. }
  658. // find(), 4x:
  659. nssv_constexpr size_type find( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
  660. {
  661. return assert( v.size() == 0 || v.data() != nssv_nullptr )
  662. , pos >= size()
  663. ? npos : to_pos(
  664. #if nssv_CPP11_OR_GREATER && ! nssv_CPP17_OR_GREATER
  665. detail::search( substr(pos), v )
  666. #else
  667. std::search( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq )
  668. #endif
  669. );
  670. }
  671. nssv_constexpr size_type find( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
  672. {
  673. return find( basic_string_view( &c, 1 ), pos );
  674. }
  675. nssv_constexpr size_type find( CharT const * s, size_type pos, size_type n ) const // (3)
  676. {
  677. return find( basic_string_view( s, n ), pos );
  678. }
  679. nssv_constexpr size_type find( CharT const * s, size_type pos = 0 ) const // (4)
  680. {
  681. return find( basic_string_view( s ), pos );
  682. }
  683. // rfind(), 4x:
  684. nssv_constexpr14 size_type rfind( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
  685. {
  686. if ( size() < v.size() )
  687. {
  688. return npos;
  689. }
  690. if ( v.empty() )
  691. {
  692. return (std::min)( size(), pos );
  693. }
  694. const_iterator last = cbegin() + (std::min)( size() - v.size(), pos ) + v.size();
  695. const_iterator result = std::find_end( cbegin(), last, v.cbegin(), v.cend(), Traits::eq );
  696. return result != last ? size_type( result - cbegin() ) : npos;
  697. }
  698. nssv_constexpr14 size_type rfind( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
  699. {
  700. return rfind( basic_string_view( &c, 1 ), pos );
  701. }
  702. nssv_constexpr14 size_type rfind( CharT const * s, size_type pos, size_type n ) const // (3)
  703. {
  704. return rfind( basic_string_view( s, n ), pos );
  705. }
  706. nssv_constexpr14 size_type rfind( CharT const * s, size_type pos = npos ) const // (4)
  707. {
  708. return rfind( basic_string_view( s ), pos );
  709. }
  710. // find_first_of(), 4x:
  711. nssv_constexpr size_type find_first_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
  712. {
  713. return pos >= size()
  714. ? npos
  715. : to_pos( std::find_first_of( cbegin() + pos, cend(), v.cbegin(), v.cend(), Traits::eq ) );
  716. }
  717. nssv_constexpr size_type find_first_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
  718. {
  719. return find_first_of( basic_string_view( &c, 1 ), pos );
  720. }
  721. nssv_constexpr size_type find_first_of( CharT const * s, size_type pos, size_type n ) const // (3)
  722. {
  723. return find_first_of( basic_string_view( s, n ), pos );
  724. }
  725. nssv_constexpr size_type find_first_of( CharT const * s, size_type pos = 0 ) const // (4)
  726. {
  727. return find_first_of( basic_string_view( s ), pos );
  728. }
  729. // find_last_of(), 4x:
  730. nssv_constexpr size_type find_last_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
  731. {
  732. return empty()
  733. ? npos
  734. : pos >= size()
  735. ? find_last_of( v, size() - 1 )
  736. : to_pos( std::find_first_of( const_reverse_iterator( cbegin() + pos + 1 ), crend(), v.cbegin(), v.cend(), Traits::eq ) );
  737. }
  738. nssv_constexpr size_type find_last_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
  739. {
  740. return find_last_of( basic_string_view( &c, 1 ), pos );
  741. }
  742. nssv_constexpr size_type find_last_of( CharT const * s, size_type pos, size_type count ) const // (3)
  743. {
  744. return find_last_of( basic_string_view( s, count ), pos );
  745. }
  746. nssv_constexpr size_type find_last_of( CharT const * s, size_type pos = npos ) const // (4)
  747. {
  748. return find_last_of( basic_string_view( s ), pos );
  749. }
  750. // find_first_not_of(), 4x:
  751. nssv_constexpr size_type find_first_not_of( basic_string_view v, size_type pos = 0 ) const nssv_noexcept // (1)
  752. {
  753. return pos >= size()
  754. ? npos
  755. : to_pos( std::find_if( cbegin() + pos, cend(), not_in_view( v ) ) );
  756. }
  757. nssv_constexpr size_type find_first_not_of( CharT c, size_type pos = 0 ) const nssv_noexcept // (2)
  758. {
  759. return find_first_not_of( basic_string_view( &c, 1 ), pos );
  760. }
  761. nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
  762. {
  763. return find_first_not_of( basic_string_view( s, count ), pos );
  764. }
  765. nssv_constexpr size_type find_first_not_of( CharT const * s, size_type pos = 0 ) const // (4)
  766. {
  767. return find_first_not_of( basic_string_view( s ), pos );
  768. }
  769. // find_last_not_of(), 4x:
  770. nssv_constexpr size_type find_last_not_of( basic_string_view v, size_type pos = npos ) const nssv_noexcept // (1)
  771. {
  772. return empty()
  773. ? npos
  774. : pos >= size()
  775. ? find_last_not_of( v, size() - 1 )
  776. : to_pos( std::find_if( const_reverse_iterator( cbegin() + pos + 1 ), crend(), not_in_view( v ) ) );
  777. }
  778. nssv_constexpr size_type find_last_not_of( CharT c, size_type pos = npos ) const nssv_noexcept // (2)
  779. {
  780. return find_last_not_of( basic_string_view( &c, 1 ), pos );
  781. }
  782. nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos, size_type count ) const // (3)
  783. {
  784. return find_last_not_of( basic_string_view( s, count ), pos );
  785. }
  786. nssv_constexpr size_type find_last_not_of( CharT const * s, size_type pos = npos ) const // (4)
  787. {
  788. return find_last_not_of( basic_string_view( s ), pos );
  789. }
  790. // Constants:
  791. #if nssv_CPP17_OR_GREATER
  792. static nssv_constexpr size_type npos = size_type(-1);
  793. #elif nssv_CPP11_OR_GREATER
  794. enum : size_type { npos = size_type(-1) };
  795. #else
  796. enum { npos = size_type(-1) };
  797. #endif
  798. private:
  799. struct not_in_view
  800. {
  801. const basic_string_view v;
  802. nssv_constexpr explicit not_in_view( basic_string_view v_ ) : v( v_ ) {}
  803. nssv_constexpr bool operator()( CharT c ) const
  804. {
  805. return npos == v.find_first_of( c );
  806. }
  807. };
  808. nssv_constexpr size_type to_pos( const_iterator it ) const
  809. {
  810. return it == cend() ? npos : size_type( it - cbegin() );
  811. }
  812. nssv_constexpr size_type to_pos( const_reverse_iterator it ) const
  813. {
  814. return it == crend() ? npos : size_type( crend() - it - 1 );
  815. }
  816. nssv_constexpr const_reference data_at( size_type pos ) const
  817. {
  818. #if nssv_BETWEEN( nssv_COMPILER_GNUC_VERSION, 1, 500 )
  819. return data_[pos];
  820. #else
  821. return assert( pos < size() ), data_[pos];
  822. #endif
  823. }
  824. private:
  825. const_pointer data_;
  826. size_type size_;
  827. public:
  828. #if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  829. template< class Allocator >
  830. basic_string_view( std::basic_string<CharT, Traits, Allocator> const & s ) nssv_noexcept
  831. : data_( s.data() )
  832. , size_( s.size() )
  833. {}
  834. #if nssv_HAVE_EXPLICIT_CONVERSION
  835. template< class Allocator >
  836. explicit operator std::basic_string<CharT, Traits, Allocator>() const
  837. {
  838. return to_string( Allocator() );
  839. }
  840. #endif // nssv_HAVE_EXPLICIT_CONVERSION
  841. #if nssv_CPP11_OR_GREATER
  842. template< class Allocator = std::allocator<CharT> >
  843. std::basic_string<CharT, Traits, Allocator>
  844. to_string( Allocator const & a = Allocator() ) const
  845. {
  846. return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
  847. }
  848. #else
  849. std::basic_string<CharT, Traits>
  850. to_string() const
  851. {
  852. return std::basic_string<CharT, Traits>( begin(), end() );
  853. }
  854. template< class Allocator >
  855. std::basic_string<CharT, Traits, Allocator>
  856. to_string( Allocator const & a ) const
  857. {
  858. return std::basic_string<CharT, Traits, Allocator>( begin(), end(), a );
  859. }
  860. #endif // nssv_CPP11_OR_GREATER
  861. #endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
  862. };
  863. //
  864. // Non-member functions:
  865. //
  866. // 24.4.3 Non-member comparison functions:
  867. // lexicographically compare two string views (function template):
  868. template< class CharT, class Traits >
  869. nssv_constexpr bool operator== (
  870. basic_string_view <CharT, Traits> lhs,
  871. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  872. { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
  873. template< class CharT, class Traits >
  874. nssv_constexpr bool operator!= (
  875. basic_string_view <CharT, Traits> lhs,
  876. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  877. { return !( lhs == rhs ); }
  878. template< class CharT, class Traits >
  879. nssv_constexpr bool operator< (
  880. basic_string_view <CharT, Traits> lhs,
  881. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  882. { return lhs.compare( rhs ) < 0; }
  883. template< class CharT, class Traits >
  884. nssv_constexpr bool operator<= (
  885. basic_string_view <CharT, Traits> lhs,
  886. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  887. { return lhs.compare( rhs ) <= 0; }
  888. template< class CharT, class Traits >
  889. nssv_constexpr bool operator> (
  890. basic_string_view <CharT, Traits> lhs,
  891. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  892. { return lhs.compare( rhs ) > 0; }
  893. template< class CharT, class Traits >
  894. nssv_constexpr bool operator>= (
  895. basic_string_view <CharT, Traits> lhs,
  896. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  897. { return lhs.compare( rhs ) >= 0; }
  898. // Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
  899. // Implementations shall provide sufficient additional overloads marked
  900. // constexpr and noexcept so that an object t with an implicit conversion
  901. // to S can be compared according to Table 67.
  902. #if ! nssv_CPP11_OR_GREATER || nssv_BETWEEN( nssv_COMPILER_MSVC_VERSION, 100, 141 )
  903. // accommodate for older compilers:
  904. // ==
  905. template< class CharT, class Traits>
  906. nssv_constexpr bool operator==(
  907. basic_string_view<CharT, Traits> lhs,
  908. CharT const * rhs ) nssv_noexcept
  909. { return lhs.size() == detail::length( rhs ) && lhs.compare( rhs ) == 0; }
  910. template< class CharT, class Traits>
  911. nssv_constexpr bool operator==(
  912. CharT const * lhs,
  913. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  914. { return detail::length( lhs ) == rhs.size() && rhs.compare( lhs ) == 0; }
  915. template< class CharT, class Traits>
  916. nssv_constexpr bool operator==(
  917. basic_string_view<CharT, Traits> lhs,
  918. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  919. { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
  920. template< class CharT, class Traits>
  921. nssv_constexpr bool operator==(
  922. std::basic_string<CharT, Traits> rhs,
  923. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  924. { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
  925. // !=
  926. template< class CharT, class Traits>
  927. nssv_constexpr bool operator!=(
  928. basic_string_view<CharT, Traits> lhs,
  929. CharT const * rhs ) nssv_noexcept
  930. { return !( lhs == rhs ); }
  931. template< class CharT, class Traits>
  932. nssv_constexpr bool operator!=(
  933. CharT const * lhs,
  934. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  935. { return !( lhs == rhs ); }
  936. template< class CharT, class Traits>
  937. nssv_constexpr bool operator!=(
  938. basic_string_view<CharT, Traits> lhs,
  939. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  940. { return !( lhs == rhs ); }
  941. template< class CharT, class Traits>
  942. nssv_constexpr bool operator!=(
  943. std::basic_string<CharT, Traits> rhs,
  944. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  945. { return !( lhs == rhs ); }
  946. // <
  947. template< class CharT, class Traits>
  948. nssv_constexpr bool operator<(
  949. basic_string_view<CharT, Traits> lhs,
  950. CharT const * rhs ) nssv_noexcept
  951. { return lhs.compare( rhs ) < 0; }
  952. template< class CharT, class Traits>
  953. nssv_constexpr bool operator<(
  954. CharT const * lhs,
  955. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  956. { return rhs.compare( lhs ) > 0; }
  957. template< class CharT, class Traits>
  958. nssv_constexpr bool operator<(
  959. basic_string_view<CharT, Traits> lhs,
  960. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  961. { return lhs.compare( rhs ) < 0; }
  962. template< class CharT, class Traits>
  963. nssv_constexpr bool operator<(
  964. std::basic_string<CharT, Traits> rhs,
  965. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  966. { return rhs.compare( lhs ) > 0; }
  967. // <=
  968. template< class CharT, class Traits>
  969. nssv_constexpr bool operator<=(
  970. basic_string_view<CharT, Traits> lhs,
  971. CharT const * rhs ) nssv_noexcept
  972. { return lhs.compare( rhs ) <= 0; }
  973. template< class CharT, class Traits>
  974. nssv_constexpr bool operator<=(
  975. CharT const * lhs,
  976. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  977. { return rhs.compare( lhs ) >= 0; }
  978. template< class CharT, class Traits>
  979. nssv_constexpr bool operator<=(
  980. basic_string_view<CharT, Traits> lhs,
  981. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  982. { return lhs.compare( rhs ) <= 0; }
  983. template< class CharT, class Traits>
  984. nssv_constexpr bool operator<=(
  985. std::basic_string<CharT, Traits> rhs,
  986. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  987. { return rhs.compare( lhs ) >= 0; }
  988. // >
  989. template< class CharT, class Traits>
  990. nssv_constexpr bool operator>(
  991. basic_string_view<CharT, Traits> lhs,
  992. CharT const * rhs ) nssv_noexcept
  993. { return lhs.compare( rhs ) > 0; }
  994. template< class CharT, class Traits>
  995. nssv_constexpr bool operator>(
  996. CharT const * lhs,
  997. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  998. { return rhs.compare( lhs ) < 0; }
  999. template< class CharT, class Traits>
  1000. nssv_constexpr bool operator>(
  1001. basic_string_view<CharT, Traits> lhs,
  1002. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  1003. { return lhs.compare( rhs ) > 0; }
  1004. template< class CharT, class Traits>
  1005. nssv_constexpr bool operator>(
  1006. std::basic_string<CharT, Traits> rhs,
  1007. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  1008. { return rhs.compare( lhs ) < 0; }
  1009. // >=
  1010. template< class CharT, class Traits>
  1011. nssv_constexpr bool operator>=(
  1012. basic_string_view<CharT, Traits> lhs,
  1013. CharT const * rhs ) nssv_noexcept
  1014. { return lhs.compare( rhs ) >= 0; }
  1015. template< class CharT, class Traits>
  1016. nssv_constexpr bool operator>=(
  1017. CharT const * lhs,
  1018. basic_string_view<CharT, Traits> rhs ) nssv_noexcept
  1019. { return rhs.compare( lhs ) <= 0; }
  1020. template< class CharT, class Traits>
  1021. nssv_constexpr bool operator>=(
  1022. basic_string_view<CharT, Traits> lhs,
  1023. std::basic_string<CharT, Traits> rhs ) nssv_noexcept
  1024. { return lhs.compare( rhs ) >= 0; }
  1025. template< class CharT, class Traits>
  1026. nssv_constexpr bool operator>=(
  1027. std::basic_string<CharT, Traits> rhs,
  1028. basic_string_view<CharT, Traits> lhs ) nssv_noexcept
  1029. { return rhs.compare( lhs ) <= 0; }
  1030. #else // newer compilers:
  1031. #define nssv_BASIC_STRING_VIEW_I(T,U) typename std::decay< basic_string_view<T,U> >::type
  1032. #if defined(_MSC_VER) // issue 40
  1033. # define nssv_MSVC_ORDER(x) , int=x
  1034. #else
  1035. # define nssv_MSVC_ORDER(x) /*, int=x*/
  1036. #endif
  1037. // ==
  1038. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1039. nssv_constexpr bool operator==(
  1040. basic_string_view <CharT, Traits> lhs,
  1041. nssv_BASIC_STRING_VIEW_I(CharT, Traits) rhs ) nssv_noexcept
  1042. { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
  1043. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1044. nssv_constexpr bool operator==(
  1045. nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
  1046. basic_string_view <CharT, Traits> rhs ) nssv_noexcept
  1047. { return lhs.size() == rhs.size() && lhs.compare( rhs ) == 0; }
  1048. // !=
  1049. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1050. nssv_constexpr bool operator!= (
  1051. basic_string_view < CharT, Traits > lhs,
  1052. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
  1053. { return !( lhs == rhs ); }
  1054. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1055. nssv_constexpr bool operator!= (
  1056. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
  1057. basic_string_view < CharT, Traits > rhs ) nssv_noexcept
  1058. { return !( lhs == rhs ); }
  1059. // <
  1060. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1061. nssv_constexpr bool operator< (
  1062. basic_string_view < CharT, Traits > lhs,
  1063. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
  1064. { return lhs.compare( rhs ) < 0; }
  1065. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1066. nssv_constexpr bool operator< (
  1067. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
  1068. basic_string_view < CharT, Traits > rhs ) nssv_noexcept
  1069. { return lhs.compare( rhs ) < 0; }
  1070. // <=
  1071. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1072. nssv_constexpr bool operator<= (
  1073. basic_string_view < CharT, Traits > lhs,
  1074. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
  1075. { return lhs.compare( rhs ) <= 0; }
  1076. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1077. nssv_constexpr bool operator<= (
  1078. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
  1079. basic_string_view < CharT, Traits > rhs ) nssv_noexcept
  1080. { return lhs.compare( rhs ) <= 0; }
  1081. // >
  1082. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1083. nssv_constexpr bool operator> (
  1084. basic_string_view < CharT, Traits > lhs,
  1085. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
  1086. { return lhs.compare( rhs ) > 0; }
  1087. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1088. nssv_constexpr bool operator> (
  1089. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
  1090. basic_string_view < CharT, Traits > rhs ) nssv_noexcept
  1091. { return lhs.compare( rhs ) > 0; }
  1092. // >=
  1093. template< class CharT, class Traits nssv_MSVC_ORDER(1) >
  1094. nssv_constexpr bool operator>= (
  1095. basic_string_view < CharT, Traits > lhs,
  1096. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) rhs ) nssv_noexcept
  1097. { return lhs.compare( rhs ) >= 0; }
  1098. template< class CharT, class Traits nssv_MSVC_ORDER(2) >
  1099. nssv_constexpr bool operator>= (
  1100. nssv_BASIC_STRING_VIEW_I( CharT, Traits ) lhs,
  1101. basic_string_view < CharT, Traits > rhs ) nssv_noexcept
  1102. { return lhs.compare( rhs ) >= 0; }
  1103. #undef nssv_MSVC_ORDER
  1104. #undef nssv_BASIC_STRING_VIEW_I
  1105. #endif // compiler-dependent approach to comparisons
  1106. // 24.4.4 Inserters and extractors:
  1107. #if ! nssv_CONFIG_NO_STREAM_INSERTION
  1108. namespace detail {
  1109. template< class Stream >
  1110. void write_padding( Stream & os, std::streamsize n )
  1111. {
  1112. for ( std::streamsize i = 0; i < n; ++i )
  1113. os.rdbuf()->sputc( os.fill() );
  1114. }
  1115. template< class Stream, class View >
  1116. Stream & write_to_stream( Stream & os, View const & sv )
  1117. {
  1118. typename Stream::sentry sentry( os );
  1119. if ( !sentry )
  1120. return os;
  1121. const std::streamsize length = static_cast<std::streamsize>( sv.length() );
  1122. // Whether, and how, to pad:
  1123. const bool pad = ( length < os.width() );
  1124. const bool left_pad = pad && ( os.flags() & std::ios_base::adjustfield ) == std::ios_base::right;
  1125. if ( left_pad )
  1126. write_padding( os, os.width() - length );
  1127. // Write span characters:
  1128. os.rdbuf()->sputn( sv.begin(), length );
  1129. if ( pad && !left_pad )
  1130. write_padding( os, os.width() - length );
  1131. // Reset output stream width:
  1132. os.width( 0 );
  1133. return os;
  1134. }
  1135. } // namespace detail
  1136. template< class CharT, class Traits >
  1137. std::basic_ostream<CharT, Traits> &
  1138. operator<<(
  1139. std::basic_ostream<CharT, Traits>& os,
  1140. basic_string_view <CharT, Traits> sv )
  1141. {
  1142. return detail::write_to_stream( os, sv );
  1143. }
  1144. #endif // nssv_CONFIG_NO_STREAM_INSERTION
  1145. // Several typedefs for common character types are provided:
  1146. typedef basic_string_view<char> string_view;
  1147. typedef basic_string_view<wchar_t> wstring_view;
  1148. #if nssv_HAVE_WCHAR16_T
  1149. typedef basic_string_view<char16_t> u16string_view;
  1150. typedef basic_string_view<char32_t> u32string_view;
  1151. #endif
  1152. }} // namespace nonstd::sv_lite
  1153. //
  1154. // 24.4.6 Suffix for basic_string_view literals:
  1155. //
  1156. #if nssv_HAVE_USER_DEFINED_LITERALS
  1157. namespace nonstd {
  1158. nssv_inline_ns namespace literals {
  1159. nssv_inline_ns namespace string_view_literals {
  1160. #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
  1161. nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1)
  1162. {
  1163. return nonstd::sv_lite::string_view{ str, len };
  1164. }
  1165. nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
  1166. {
  1167. return nonstd::sv_lite::u16string_view{ str, len };
  1168. }
  1169. nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
  1170. {
  1171. return nonstd::sv_lite::u32string_view{ str, len };
  1172. }
  1173. nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
  1174. {
  1175. return nonstd::sv_lite::wstring_view{ str, len };
  1176. }
  1177. #endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
  1178. #if nssv_CONFIG_USR_SV_OPERATOR
  1179. nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1)
  1180. {
  1181. return nonstd::sv_lite::string_view{ str, len };
  1182. }
  1183. nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2)
  1184. {
  1185. return nonstd::sv_lite::u16string_view{ str, len };
  1186. }
  1187. nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3)
  1188. {
  1189. return nonstd::sv_lite::u32string_view{ str, len };
  1190. }
  1191. nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4)
  1192. {
  1193. return nonstd::sv_lite::wstring_view{ str, len };
  1194. }
  1195. #endif // nssv_CONFIG_USR_SV_OPERATOR
  1196. }}} // namespace nonstd::literals::string_view_literals
  1197. #endif
  1198. //
  1199. // Extensions for std::string:
  1200. //
  1201. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1202. namespace nonstd {
  1203. namespace sv_lite {
  1204. // Exclude MSVC 14 (19.00): it yields ambiguous to_string():
  1205. #if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
  1206. template< class CharT, class Traits, class Allocator = std::allocator<CharT> >
  1207. std::basic_string<CharT, Traits, Allocator>
  1208. to_string( basic_string_view<CharT, Traits> v, Allocator const & a = Allocator() )
  1209. {
  1210. return std::basic_string<CharT,Traits, Allocator>( v.begin(), v.end(), a );
  1211. }
  1212. #else
  1213. template< class CharT, class Traits >
  1214. std::basic_string<CharT, Traits>
  1215. to_string( basic_string_view<CharT, Traits> v )
  1216. {
  1217. return std::basic_string<CharT, Traits>( v.begin(), v.end() );
  1218. }
  1219. template< class CharT, class Traits, class Allocator >
  1220. std::basic_string<CharT, Traits, Allocator>
  1221. to_string( basic_string_view<CharT, Traits> v, Allocator const & a )
  1222. {
  1223. return std::basic_string<CharT, Traits, Allocator>( v.begin(), v.end(), a );
  1224. }
  1225. #endif // nssv_CPP11_OR_GREATER
  1226. template< class CharT, class Traits, class Allocator >
  1227. basic_string_view<CharT, Traits>
  1228. to_string_view( std::basic_string<CharT, Traits, Allocator> const & s )
  1229. {
  1230. return basic_string_view<CharT, Traits>( s.data(), s.size() );
  1231. }
  1232. }} // namespace nonstd::sv_lite
  1233. #endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1234. //
  1235. // make types and algorithms available in namespace nonstd:
  1236. //
  1237. namespace nonstd {
  1238. using sv_lite::basic_string_view;
  1239. using sv_lite::string_view;
  1240. using sv_lite::wstring_view;
  1241. #if nssv_HAVE_WCHAR16_T
  1242. using sv_lite::u16string_view;
  1243. #endif
  1244. #if nssv_HAVE_WCHAR32_T
  1245. using sv_lite::u32string_view;
  1246. #endif
  1247. // literal "sv"
  1248. using sv_lite::operator==;
  1249. using sv_lite::operator!=;
  1250. using sv_lite::operator<;
  1251. using sv_lite::operator<=;
  1252. using sv_lite::operator>;
  1253. using sv_lite::operator>=;
  1254. #if ! nssv_CONFIG_NO_STREAM_INSERTION
  1255. using sv_lite::operator<<;
  1256. #endif
  1257. #if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
  1258. using sv_lite::to_string;
  1259. using sv_lite::to_string_view;
  1260. #endif
  1261. } // namespace nonstd
  1262. // 24.4.5 Hash support (C++11):
  1263. // Note: The hash value of a string view object is equal to the hash value of
  1264. // the corresponding string object.
  1265. #if nssv_HAVE_STD_HASH
  1266. #include <functional>
  1267. namespace std {
  1268. template<>
  1269. struct hash< nonstd::string_view >
  1270. {
  1271. public:
  1272. std::size_t operator()( nonstd::string_view v ) const nssv_noexcept
  1273. {
  1274. return std::hash<std::string>()( std::string( v.data(), v.size() ) );
  1275. }
  1276. };
  1277. template<>
  1278. struct hash< nonstd::wstring_view >
  1279. {
  1280. public:
  1281. std::size_t operator()( nonstd::wstring_view v ) const nssv_noexcept
  1282. {
  1283. return std::hash<std::wstring>()( std::wstring( v.data(), v.size() ) );
  1284. }
  1285. };
  1286. template<>
  1287. struct hash< nonstd::u16string_view >
  1288. {
  1289. public:
  1290. std::size_t operator()( nonstd::u16string_view v ) const nssv_noexcept
  1291. {
  1292. return std::hash<std::u16string>()( std::u16string( v.data(), v.size() ) );
  1293. }
  1294. };
  1295. template<>
  1296. struct hash< nonstd::u32string_view >
  1297. {
  1298. public:
  1299. std::size_t operator()( nonstd::u32string_view v ) const nssv_noexcept
  1300. {
  1301. return std::hash<std::u32string>()( std::u32string( v.data(), v.size() ) );
  1302. }
  1303. };
  1304. } // namespace std
  1305. #endif // nssv_HAVE_STD_HASH
  1306. nssv_RESTORE_WARNINGS()
  1307. #endif // nssv_HAVE_STD_STRING_VIEW
  1308. #endif // NONSTD_SV_LITE_H_INCLUDED