LL1Checker 2.0
“Tool for verifying LL(1) grammars and validating input strings.”
Loading...
Searching...
No Matches
tabulate.hpp
1// Copyright 2016-2018 by Martin Moene
2//
3// https://github.com/martinmoene/variant-lite
4//
5// Distributed under the Boost Software License, Version 1.0.
6// (See accompanying file LICENSE.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8
9#pragma once
10
11#ifndef NONSTD_VARIANT_LITE_HPP
12#define NONSTD_VARIANT_LITE_HPP
13
14#define variant_lite_MAJOR 1
15#define variant_lite_MINOR 2
16#define variant_lite_PATCH 2
17
18#define variant_lite_VERSION \
19 variant_STRINGIFY(variant_lite_MAJOR) "." variant_STRINGIFY( \
20 variant_lite_MINOR) "." variant_STRINGIFY(variant_lite_PATCH)
21
22#define variant_STRINGIFY(x) variant_STRINGIFY_(x)
23#define variant_STRINGIFY_(x) #x
24
25// variant-lite configuration:
26
27#define variant_VARIANT_DEFAULT 0
28#define variant_VARIANT_NONSTD 1
29#define variant_VARIANT_STD 2
30
31#if !defined(variant_CONFIG_SELECT_VARIANT)
32#define variant_CONFIG_SELECT_VARIANT \
33 (variant_HAVE_STD_VARIANT ? variant_VARIANT_STD : variant_VARIANT_NONSTD)
34#endif
35
36#ifndef variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
37#define variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO 0
38#endif
39
40#ifndef variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
41#define variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO 0
42#endif
43
44// Control presence of exception handling (try and auto discover):
45
46#ifndef variant_CONFIG_NO_EXCEPTIONS
47#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
48#define variant_CONFIG_NO_EXCEPTIONS 0
49#else
50#define variant_CONFIG_NO_EXCEPTIONS 1
51#endif
52#endif
53
54// C++ language version detection (C++20 is speculative):
55// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
56
57#ifndef variant_CPLUSPLUS
58#if defined(_MSVC_LANG) && !defined(__clang__)
59#define variant_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
60#else
61#define variant_CPLUSPLUS __cplusplus
62#endif
63#endif
64
65#define variant_CPP98_OR_GREATER (variant_CPLUSPLUS >= 199711L)
66#define variant_CPP11_OR_GREATER (variant_CPLUSPLUS >= 201103L)
67#define variant_CPP11_OR_GREATER_ (variant_CPLUSPLUS >= 201103L)
68#define variant_CPP14_OR_GREATER (variant_CPLUSPLUS >= 201402L)
69#define variant_CPP17_OR_GREATER (variant_CPLUSPLUS >= 201703L)
70#define variant_CPP20_OR_GREATER (variant_CPLUSPLUS >= 202000L)
71
72// Use C++17 std::variant if available and requested:
73
74#if variant_CPP17_OR_GREATER && defined(__has_include)
75#if __has_include(<variant> )
76#define variant_HAVE_STD_VARIANT 1
77#else
78#define variant_HAVE_STD_VARIANT 0
79#endif
80#else
81#define variant_HAVE_STD_VARIANT 0
82#endif
83
84#define variant_USES_STD_VARIANT \
85 ((variant_CONFIG_SELECT_VARIANT == variant_VARIANT_STD) || \
86 ((variant_CONFIG_SELECT_VARIANT == variant_VARIANT_DEFAULT) && \
87 variant_HAVE_STD_VARIANT))
88
89//
90// in_place: code duplicated in any-lite, expected-lite, optional-lite,
91// value-ptr-lite, variant-lite:
92//
93
94#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
95#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
96
97// C++17 std::in_place in <utility>:
98
99#if variant_CPP17_OR_GREATER
100
101#include <utility>
102
103namespace nonstd {
104
105using std::in_place;
106using std::in_place_index;
107using std::in_place_index_t;
108using std::in_place_t;
109using std::in_place_type;
110using std::in_place_type_t;
111
112#define nonstd_lite_in_place_t(T) std::in_place_t
113#define nonstd_lite_in_place_type_t(T) std::in_place_type_t<T>
114#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
115
116#define nonstd_lite_in_place(T) \
117 std::in_place_t {}
118#define nonstd_lite_in_place_type(T) \
119 std::in_place_type_t<T> {}
120#define nonstd_lite_in_place_index(K) \
121 std::in_place_index_t<K> {}
122
123} // namespace nonstd
124
125#else // variant_CPP17_OR_GREATER
126
127#include <cstddef>
128
129namespace nonstd {
130namespace detail {
131
132template <class T> struct in_place_type_tag {};
133
134template <std::size_t K> struct in_place_index_tag {};
135
136} // namespace detail
137
138struct in_place_t {};
139
140template <class T>
141inline in_place_t
143 return in_place_t();
144}
145
146template <std::size_t K>
147inline in_place_t
148in_place(detail::in_place_index_tag<K> = detail::in_place_index_tag<K>()) {
149 return in_place_t();
150}
151
152template <class T>
153inline in_place_t
155 return in_place_t();
156}
157
158template <std::size_t K>
159inline in_place_t in_place_index(
161 return in_place_t();
162}
163
164// mimic templated typedef:
165
166#define nonstd_lite_in_place_t(T) \
167 nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag<T>)
168#define nonstd_lite_in_place_type_t(T) \
169 nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag<T>)
170#define nonstd_lite_in_place_index_t(K) \
171 nonstd::in_place_t (&)(nonstd::detail::in_place_index_tag<K>)
172
173#define nonstd_lite_in_place(T) nonstd::in_place_type<T>
174#define nonstd_lite_in_place_type(T) nonstd::in_place_type<T>
175#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
176
177} // namespace nonstd
178
179#endif // variant_CPP17_OR_GREATER
180#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
181
182//
183// Use C++17 std::variant:
184//
185
186#if variant_USES_STD_VARIANT
187
188#include <functional> // std::hash<>
189#include <variant>
190
191#if !variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
192#define variant_size_V(T) nonstd::variant_size<T>::value
193#endif
194
195#if !variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
196#define variant_alternative_T(K, T) \
197 typename nonstd::variant_alternative<K, T>::type
198#endif
199
200namespace nonstd {
201
202using std::bad_variant_access;
203using std::hash;
204using std::monostate;
205using std::variant;
206using std::variant_alternative;
207using std::variant_alternative_t;
208using std::variant_size;
209using std::variant_size_v;
210
211using std::get;
212using std::get_if;
213using std::holds_alternative;
214using std::visit;
215using std::operator==;
216using std::operator!=;
217using std::operator<;
218using std::operator<=;
219using std::operator>;
220using std::operator>=;
221using std::swap;
222
223constexpr auto variant_npos = std::variant_npos;
224} // namespace nonstd
225
226#else // variant_USES_STD_VARIANT
227
228#include <cstddef>
229#include <limits>
230#include <new>
231#include <utility>
232
233#if variant_CONFIG_NO_EXCEPTIONS
234#include <cassert>
235#else
236#include <stdexcept>
237#endif
238
239// variant-lite type and visitor argument count configuration
240// (script/generate_header.py):
241
242#define variant_CONFIG_MAX_TYPE_COUNT 16
243#define variant_CONFIG_MAX_VISITOR_ARG_COUNT 5
244
245// variant-lite alignment configuration:
246
247#ifndef variant_CONFIG_MAX_ALIGN_HACK
248#define variant_CONFIG_MAX_ALIGN_HACK 0
249#endif
250
251#ifndef variant_CONFIG_ALIGN_AS
252// no default, used in #if defined()
253#endif
254
255#ifndef variant_CONFIG_ALIGN_AS_FALLBACK
256#define variant_CONFIG_ALIGN_AS_FALLBACK double
257#endif
258
259// half-open range [lo..hi):
260#define variant_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
261
262// Compiler versions:
263//
264// MSVC++ 6.0 _MSC_VER == 1200 variant_COMPILER_MSVC_VERSION == 60 (Visual
265// Studio 6.0) MSVC++ 7.0 _MSC_VER == 1300 variant_COMPILER_MSVC_VERSION ==
266// 70 (Visual Studio .NET 2002) MSVC++ 7.1 _MSC_VER == 1310
267// variant_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) MSVC++ 8.0
268// _MSC_VER == 1400 variant_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
269// MSVC++ 9.0 _MSC_VER == 1500 variant_COMPILER_MSVC_VERSION == 90 (Visual
270// Studio 2008) MSVC++ 10.0 _MSC_VER == 1600 variant_COMPILER_MSVC_VERSION ==
271// 100 (Visual Studio 2010) MSVC++ 11.0 _MSC_VER == 1700
272// variant_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) MSVC++ 12.0
273// _MSC_VER == 1800 variant_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
274// MSVC++ 14.0 _MSC_VER == 1900 variant_COMPILER_MSVC_VERSION == 140 (Visual
275// Studio 2015) MSVC++ 14.1 _MSC_VER >= 1910 variant_COMPILER_MSVC_VERSION ==
276// 141 (Visual Studio 2017) MSVC++ 14.2 _MSC_VER >= 1920
277// variant_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
278
279#if defined(_MSC_VER) && !defined(__clang__)
280#define variant_COMPILER_MSVC_VER (_MSC_VER)
281#define variant_COMPILER_MSVC_VERSION \
282 (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
283#else
284#define variant_COMPILER_MSVC_VER 0
285#define variant_COMPILER_MSVC_VERSION 0
286#endif
287
288#define variant_COMPILER_VERSION(major, minor, patch) \
289 (10 * (10 * (major) + (minor)) + (patch))
290
291#if defined(__clang__)
292#define variant_COMPILER_CLANG_VERSION \
293 variant_COMPILER_VERSION(__clang_major__, __clang_minor__, \
294 __clang_patchlevel__)
295#else
296#define variant_COMPILER_CLANG_VERSION 0
297#endif
298
299#if defined(__GNUC__) && !defined(__clang__)
300#define variant_COMPILER_GNUC_VERSION \
301 variant_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
302#else
303#define variant_COMPILER_GNUC_VERSION 0
304#endif
305
306#if variant_BETWEEN(variant_COMPILER_MSVC_VER, 1300, 1900)
307#pragma warning(push)
308#pragma warning(disable : 4345) // initialization behavior changed
309#endif
310
311// Presence of language and library features:
312
313#define variant_HAVE(feature) (variant_HAVE_##feature)
314
315#ifdef _HAS_CPP0X
316#define variant_HAS_CPP0X _HAS_CPP0X
317#else
318#define variant_HAS_CPP0X 0
319#endif
320
321// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
322
323#if variant_COMPILER_MSVC_VER >= 1900
324#undef variant_CPP11_OR_GREATER
325#define variant_CPP11_OR_GREATER 1
326#endif
327
328#define variant_CPP11_90 \
329 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1500)
330#define variant_CPP11_100 \
331 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1600)
332#define variant_CPP11_110 \
333 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1700)
334#define variant_CPP11_120 \
335 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1800)
336#define variant_CPP11_140 \
337 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1900)
338#define variant_CPP11_141 \
339 (variant_CPP11_OR_GREATER_ || variant_COMPILER_MSVC_VER >= 1910)
340
341#define variant_CPP14_000 (variant_CPP14_OR_GREATER)
342#define variant_CPP17_000 (variant_CPP17_OR_GREATER)
343
344// Presence of C++11 language features:
345
346#define variant_HAVE_CONSTEXPR_11 variant_CPP11_140
347#define variant_HAVE_INITIALIZER_LIST variant_CPP11_120
348#define variant_HAVE_NOEXCEPT variant_CPP11_140
349#define variant_HAVE_NULLPTR variant_CPP11_100
350#define variant_HAVE_OVERRIDE variant_CPP11_140
351
352// Presence of C++14 language features:
353
354#define variant_HAVE_CONSTEXPR_14 variant_CPP14_000
355
356// Presence of C++17 language features:
357
358// no flag
359
360// Presence of C++ library features:
361
362#define variant_HAVE_CONDITIONAL variant_CPP11_120
363#define variant_HAVE_REMOVE_CV variant_CPP11_120
364#define variant_HAVE_STD_ADD_POINTER variant_CPP11_90
365#define variant_HAVE_TYPE_TRAITS variant_CPP11_90
366
367#define variant_HAVE_TR1_TYPE_TRAITS (!!variant_COMPILER_GNUC_VERSION)
368#define variant_HAVE_TR1_ADD_POINTER (!!variant_COMPILER_GNUC_VERSION)
369
370// C++ feature usage:
371
372#if variant_HAVE_CONSTEXPR_11
373#define variant_constexpr constexpr
374#else
375#define variant_constexpr /*constexpr*/
376#endif
377
378#if variant_HAVE_CONSTEXPR_14
379#define variant_constexpr14 constexpr
380#else
381#define variant_constexpr14 /*constexpr*/
382#endif
383
384#if variant_HAVE_NOEXCEPT
385#define variant_noexcept noexcept
386#else
387#define variant_noexcept /*noexcept*/
388#endif
389
390#if variant_HAVE_NULLPTR
391#define variant_nullptr nullptr
392#else
393#define variant_nullptr NULL
394#endif
395
396#if variant_HAVE_OVERRIDE
397#define variant_override override
398#else
399#define variant_override /*override*/
400#endif
401
402// additional includes:
403
404#if variant_CPP11_OR_GREATER
405#include <functional> // std::hash
406#endif
407
408#if variant_HAVE_INITIALIZER_LIST
409#include <initializer_list>
410#endif
411
412#if variant_HAVE_TYPE_TRAITS
413#include <type_traits>
414#elif variant_HAVE_TR1_TYPE_TRAITS
415#include <tr1/type_traits>
416#endif
417
418// Method enabling
419
420#if variant_CPP11_OR_GREATER
421
422#define variant_REQUIRES_0(...) \
423 template <bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0>
424
425#define variant_REQUIRES_T(...) \
426 , typename std::enable_if<(__VA_ARGS__), int>::type = 0
427
428#define variant_REQUIRES_R(R, ...) \
429 typename std::enable_if<(__VA_ARGS__), R>::type
430
431#define variant_REQUIRES_A(...) \
432 , typename std::enable_if<(__VA_ARGS__), void*>::type = nullptr
433
434#endif
435
436//
437// variant:
438//
439
440namespace nonstd {
441namespace variants {
442
443// C++11 emulation:
444
445namespace std11 {
446
447#if variant_HAVE_STD_ADD_POINTER
448
449using std::add_pointer;
450
451#elif variant_HAVE_TR1_ADD_POINTER
452
453using std::tr1::add_pointer;
454
455#else
456
457template <class T> struct remove_reference {
458 typedef T type;
459};
460template <class T> struct remove_reference<T&> {
461 typedef T type;
462};
463
464template <class T> struct add_pointer {
465 typedef typename remove_reference<T>::type* type;
466};
467
468#endif // variant_HAVE_STD_ADD_POINTER
469
470#if variant_HAVE_REMOVE_CV
471
472using std::remove_cv;
473
474#else
475
476template <class T> struct remove_const {
477 typedef T type;
478};
479template <class T> struct remove_const<const T> {
480 typedef T type;
481};
482
483template <class T> struct remove_volatile {
484 typedef T type;
485};
486template <class T> struct remove_volatile<volatile T> {
487 typedef T type;
488};
489
490template <class T> struct remove_cv {
491 typedef typename remove_volatile<typename remove_const<T>::type>::type type;
492};
493
494#endif // variant_HAVE_REMOVE_CV
495
496#if variant_HAVE_CONDITIONAL
497
498using std::conditional;
499
500#else
501
502template <bool Cond, class Then, class Else> struct conditional;
503
504template <class Then, class Else> struct conditional<true, Then, Else> {
505 typedef Then type;
506};
507
508template <class Then, class Else> struct conditional<false, Then, Else> {
509 typedef Else type;
510};
511
512#endif // variant_HAVE_CONDITIONAL
513
514} // namespace std11
515
517
518namespace std17 {
519
520#if variant_CPP17_OR_GREATER
521
522using std::is_nothrow_swappable;
523using std::is_swappable;
524
525#elif variant_CPP11_OR_GREATER
526
527namespace detail {
528
529using std::swap;
530
531struct is_swappable {
532 template <typename T,
533 typename = decltype(swap(std::declval<T&>(), std::declval<T&>()))>
534 static std::true_type test(int);
535
536 template <typename> static std::false_type test(...);
537};
538
539struct is_nothrow_swappable {
540 // wrap noexcept(epr) in separate function as work-around for VC140
541 // (VS2015):
542
543 template <typename T> static constexpr bool test() {
544 return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
545 }
546
547 template <typename T>
548 static auto test(int) -> std::integral_constant<bool, test<T>()> {}
549
550 template <typename> static std::false_type test(...);
551};
552
553} // namespace detail
554
555// is [nothow] swappable:
556
557template <typename T>
558struct is_swappable : decltype(detail::is_swappable::test<T>(0)) {};
559
560template <typename T>
561struct is_nothrow_swappable
562 : decltype(detail::is_nothrow_swappable::test<T>(0)) {};
563
564#endif // variant_CPP17_OR_GREATER
565
566} // namespace std17
567
568// detail:
569
570namespace detail {
571
572// typelist:
573
574#define variant_TL1(T1) detail::typelist<T1, detail::nulltype>
575#define variant_TL2(T1, T2) detail::typelist<T1, variant_TL1(T2)>
576#define variant_TL3(T1, T2, T3) detail::typelist<T1, variant_TL2(T2, T3)>
577#define variant_TL4(T1, T2, T3, T4) \
578 detail::typelist<T1, variant_TL3(T2, T3, T4)>
579#define variant_TL5(T1, T2, T3, T4, T5) \
580 detail::typelist<T1, variant_TL4(T2, T3, T4, T5)>
581#define variant_TL6(T1, T2, T3, T4, T5, T6) \
582 detail::typelist<T1, variant_TL5(T2, T3, T4, T5, T6)>
583#define variant_TL7(T1, T2, T3, T4, T5, T6, T7) \
584 detail::typelist<T1, variant_TL6(T2, T3, T4, T5, T6, T7)>
585#define variant_TL8(T1, T2, T3, T4, T5, T6, T7, T8) \
586 detail::typelist<T1, variant_TL7(T2, T3, T4, T5, T6, T7, T8)>
587#define variant_TL9(T1, T2, T3, T4, T5, T6, T7, T8, T9) \
588 detail::typelist<T1, variant_TL8(T2, T3, T4, T5, T6, T7, T8, T9)>
589#define variant_TL10(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) \
590 detail::typelist<T1, variant_TL9(T2, T3, T4, T5, T6, T7, T8, T9, T10)>
591#define variant_TL11(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11) \
592 detail::typelist<T1, variant_TL10(T2, T3, T4, T5, T6, T7, T8, T9, T10, T11)>
593#define variant_TL12(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12) \
594 detail::typelist<T1, variant_TL11(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
595 T11, T12)>
596#define variant_TL13(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13) \
597 detail::typelist<T1, variant_TL12(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
598 T11, T12, T13)>
599#define variant_TL14(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, \
600 T14) \
601 detail::typelist<T1, variant_TL13(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
602 T11, T12, T13, T14)>
603#define variant_TL15(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, \
604 T14, T15) \
605 detail::typelist<T1, variant_TL14(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
606 T11, T12, T13, T14, T15)>
607#define variant_TL16(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, \
608 T14, T15, T16) \
609 detail::typelist<T1, variant_TL15(T2, T3, T4, T5, T6, T7, T8, T9, T10, \
610 T11, T12, T13, T14, T15, T16)>
611
612// variant parameter unused type tags:
613
614template <class T> struct TX : T {
615 inline TX<T> operator+() const { return TX<T>(); }
616 inline TX<T> operator-() const { return TX<T>(); }
617
618 inline TX<T> operator!() const { return TX<T>(); }
619 inline TX<T> operator~() const { return TX<T>(); }
620
621 inline TX<T>* operator&() const { return variant_nullptr; }
622
623 template <class U> inline TX<T> operator*(U const&) const {
624 return TX<T>();
625 }
626 template <class U> inline TX<T> operator/(U const&) const {
627 return TX<T>();
628 }
629
630 template <class U> inline TX<T> operator%(U const&) const {
631 return TX<T>();
632 }
633 template <class U> inline TX<T> operator+(U const&) const {
634 return TX<T>();
635 }
636 template <class U> inline TX<T> operator-(U const&) const {
637 return TX<T>();
638 }
639
640 template <class U> inline TX<T> operator<<(U const&) const {
641 return TX<T>();
642 }
643 template <class U> inline TX<T> operator>>(U const&) const {
644 return TX<T>();
645 }
646
647 inline bool operator==(T const&) const { return false; }
648 inline bool operator<(T const&) const { return false; }
649
650 template <class U> inline TX<T> operator&(U const&) const {
651 return TX<T>();
652 }
653 template <class U> inline TX<T> operator|(U const&) const {
654 return TX<T>();
655 }
656 template <class U> inline TX<T> operator^(U const&) const {
657 return TX<T>();
658 }
659
660 template <class U> inline TX<T> operator&&(U const&) const {
661 return TX<T>();
662 }
663 template <class U> inline TX<T> operator||(U const&) const {
664 return TX<T>();
665 }
666};
667
668struct S0 {};
669typedef TX<S0> T0;
670struct S1 {};
671typedef TX<S1> T1;
672struct S2 {};
673typedef TX<S2> T2;
674struct S3 {};
675typedef TX<S3> T3;
676struct S4 {};
677typedef TX<S4> T4;
678struct S5 {};
679typedef TX<S5> T5;
680struct S6 {};
681typedef TX<S6> T6;
682struct S7 {};
683typedef TX<S7> T7;
684struct S8 {};
685typedef TX<S8> T8;
686struct S9 {};
687typedef TX<S9> T9;
688struct S10 {};
689typedef TX<S10> T10;
690struct S11 {};
691typedef TX<S11> T11;
692struct S12 {};
693typedef TX<S12> T12;
694struct S13 {};
695typedef TX<S13> T13;
696struct S14 {};
697typedef TX<S14> T14;
698struct S15 {};
699typedef TX<S15> T15;
700
701struct nulltype {};
702
703template <class Head, class Tail> struct typelist {
704 typedef Head head;
705 typedef Tail tail;
706};
707
708// typelist max element size:
709
710template <class List> struct typelist_max;
711
712template <> struct typelist_max<nulltype> {
713 enum V { value = 0 };
714 typedef void type;
715};
716
717template <class Head, class Tail> struct typelist_max<typelist<Head, Tail>> {
718 private:
719 enum TV { tail_value = size_t(typelist_max<Tail>::value) };
720
721 typedef typename typelist_max<Tail>::type tail_type;
722
723 public:
724 enum V {
725 value =
726 (sizeof(Head) > tail_value) ? sizeof(Head) : std::size_t(tail_value)
727 };
728
729 typedef typename std11::conditional<(sizeof(Head) > tail_value), Head,
730 tail_type>::type type;
731};
732
733#if variant_CPP11_OR_GREATER
734
735// typelist max alignof element type:
736
737template <class List> struct typelist_max_alignof;
738
739template <> struct typelist_max_alignof<nulltype> {
740 enum V { value = 0 };
741};
742
743template <class Head, class Tail>
744struct typelist_max_alignof<typelist<Head, Tail>> {
745 private:
746 enum TV { tail_value = size_t(typelist_max_alignof<Tail>::value) };
747
748 public:
749 enum V {
750 value = (alignof(Head) > tail_value) ? alignof(Head)
751 : std::size_t(tail_value)
752 };
753};
754
755#endif
756
757// typelist size (length):
758
759template <class List> struct typelist_size {
760 enum V { value = 1 };
761};
762
763template <> struct typelist_size<T0> {
764 enum V { value = 0 };
765};
766template <> struct typelist_size<T1> {
767 enum V { value = 0 };
768};
769template <> struct typelist_size<T2> {
770 enum V { value = 0 };
771};
772template <> struct typelist_size<T3> {
773 enum V { value = 0 };
774};
775template <> struct typelist_size<T4> {
776 enum V { value = 0 };
777};
778template <> struct typelist_size<T5> {
779 enum V { value = 0 };
780};
781template <> struct typelist_size<T6> {
782 enum V { value = 0 };
783};
784template <> struct typelist_size<T7> {
785 enum V { value = 0 };
786};
787template <> struct typelist_size<T8> {
788 enum V { value = 0 };
789};
790template <> struct typelist_size<T9> {
791 enum V { value = 0 };
792};
793template <> struct typelist_size<T10> {
794 enum V { value = 0 };
795};
796template <> struct typelist_size<T11> {
797 enum V { value = 0 };
798};
799template <> struct typelist_size<T12> {
800 enum V { value = 0 };
801};
802template <> struct typelist_size<T13> {
803 enum V { value = 0 };
804};
805template <> struct typelist_size<T14> {
806 enum V { value = 0 };
807};
808template <> struct typelist_size<T15> {
809 enum V { value = 0 };
810};
811
812template <> struct typelist_size<nulltype> {
813 enum V { value = 0 };
814};
815
816template <class Head, class Tail> struct typelist_size<typelist<Head, Tail>> {
817 enum V { value = typelist_size<Head>::value + typelist_size<Tail>::value };
818};
819
820// typelist index of type:
821
822template <class List, class T> struct typelist_index_of;
823
824template <class T> struct typelist_index_of<nulltype, T> {
825 enum V { value = -1 };
826};
827
828template <class Tail, class T> struct typelist_index_of<typelist<T, Tail>, T> {
829 enum V { value = 0 };
830};
831
832template <class Head, class Tail, class T>
833struct typelist_index_of<typelist<Head, Tail>, T> {
834 private:
835 enum TV { nextVal = typelist_index_of<Tail, T>::value };
836
837 public:
838 enum V { value = nextVal == -1 ? -1 : 1 + nextVal };
839};
840
841// typelist type at index:
842
843template <class List, std::size_t i> struct typelist_type_at;
844
845template <class Head, class Tail>
846struct typelist_type_at<typelist<Head, Tail>, 0> {
847 typedef Head type;
848};
849
850template <class Head, class Tail, std::size_t i>
851struct typelist_type_at<typelist<Head, Tail>, i> {
852 typedef typename typelist_type_at<Tail, i - 1>::type type;
853};
854
855#if variant_CONFIG_MAX_ALIGN_HACK
856
857// Max align, use most restricted type for alignment:
858
859#define variant_UNIQUE(name) variant_UNIQUE2(name, __LINE__)
860#define variant_UNIQUE2(name, line) variant_UNIQUE3(name, line)
861#define variant_UNIQUE3(name, line) name##line
862
863#define variant_ALIGN_TYPE(type) \
864 type variant_UNIQUE(_t); \
865 struct_t<type> variant_UNIQUE(_st)
866
867template <class T> struct struct_t {
868 T _;
869};
870
871union max_align_t {
872 variant_ALIGN_TYPE(char);
873 variant_ALIGN_TYPE(short int);
874 variant_ALIGN_TYPE(int);
875 variant_ALIGN_TYPE(long int);
876 variant_ALIGN_TYPE(float);
877 variant_ALIGN_TYPE(double);
878 variant_ALIGN_TYPE(long double);
879 variant_ALIGN_TYPE(char*);
880 variant_ALIGN_TYPE(short int*);
881 variant_ALIGN_TYPE(int*);
882 variant_ALIGN_TYPE(long int*);
883 variant_ALIGN_TYPE(float*);
884 variant_ALIGN_TYPE(double*);
885 variant_ALIGN_TYPE(long double*);
886 variant_ALIGN_TYPE(void*);
887
888#ifdef HAVE_LONG_LONG
889 variant_ALIGN_TYPE(long long);
890#endif
891
892 struct Unknown;
893
894 Unknown (*variant_UNIQUE(_))(Unknown);
895 Unknown* Unknown::* variant_UNIQUE(_);
896 Unknown (Unknown::* variant_UNIQUE(_))(Unknown);
897
898 struct_t<Unknown (*)(Unknown)> variant_UNIQUE(_);
899 struct_t<Unknown * Unknown::*> variant_UNIQUE(_);
900 struct_t<Unknown (Unknown::*)(Unknown)> variant_UNIQUE(_);
901};
902
903#undef variant_UNIQUE
904#undef variant_UNIQUE2
905#undef variant_UNIQUE3
906
907#undef variant_ALIGN_TYPE
908
909#elif defined(variant_CONFIG_ALIGN_AS) // variant_CONFIG_MAX_ALIGN_HACK
910
911// Use user-specified type for alignment:
912
913#define variant_ALIGN_AS(unused) variant_CONFIG_ALIGN_AS
914
915#else // variant_CONFIG_MAX_ALIGN_HACK
916
917// Determine POD type to use for alignment:
918
919#define variant_ALIGN_AS(to_align) \
920 typename detail::type_of_size<detail::alignment_types, \
921 detail::alignment_of<to_align>::value>::type
922
923template <typename T> struct alignment_of;
924
925template <typename T> struct alignment_of_hack {
926 char c;
927 T t;
928 alignment_of_hack();
929};
930
931template <size_t A, size_t S> struct alignment_logic {
932 enum V { value = A < S ? A : S };
933};
934
935template <typename T> struct alignment_of {
936 enum V {
937 value = alignment_logic<sizeof(alignment_of_hack<T>) - sizeof(T),
938 sizeof(T)>::value
939 };
940};
941
942template <typename List, size_t N> struct type_of_size {
943 typedef typename std11::conditional<
944 N == sizeof(typename List::head), typename List::head,
945 typename type_of_size<typename List::tail, N>::type>::type type;
946};
947
948template <size_t N> struct type_of_size<nulltype, N> {
949 typedef variant_CONFIG_ALIGN_AS_FALLBACK type;
950};
951
952template <typename T> struct struct_t {
953 T _;
954};
955
956#define variant_ALIGN_TYPE(type) typelist < type, typelist < struct_t<type>
957
958struct Unknown;
959
960typedef variant_ALIGN_TYPE(char), variant_ALIGN_TYPE(short),
961 variant_ALIGN_TYPE(int), variant_ALIGN_TYPE(long),
962 variant_ALIGN_TYPE(float), variant_ALIGN_TYPE(double),
963 variant_ALIGN_TYPE(long double),
964
965 variant_ALIGN_TYPE(char*), variant_ALIGN_TYPE(short*),
966 variant_ALIGN_TYPE(int*), variant_ALIGN_TYPE(long*),
967 variant_ALIGN_TYPE(float*), variant_ALIGN_TYPE(double*),
968 variant_ALIGN_TYPE(long double*),
969
970 variant_ALIGN_TYPE(Unknown (*)(Unknown)),
971 variant_ALIGN_TYPE(Unknown* Unknown::*),
972 variant_ALIGN_TYPE(Unknown (Unknown::*)(Unknown)),
973
974 nulltype >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alignment_types;
975
976#undef variant_ALIGN_TYPE
977
978#endif // variant_CONFIG_MAX_ALIGN_HACK
979
980#if variant_CPP11_OR_GREATER
981
982template <typename T> inline std::size_t hash(T const& v) {
983 return std::hash<T>()(v);
984}
985
986inline std::size_t hash(T0 const&) {
987 return 0;
988}
989inline std::size_t hash(T1 const&) {
990 return 0;
991}
992inline std::size_t hash(T2 const&) {
993 return 0;
994}
995inline std::size_t hash(T3 const&) {
996 return 0;
997}
998inline std::size_t hash(T4 const&) {
999 return 0;
1000}
1001inline std::size_t hash(T5 const&) {
1002 return 0;
1003}
1004inline std::size_t hash(T6 const&) {
1005 return 0;
1006}
1007inline std::size_t hash(T7 const&) {
1008 return 0;
1009}
1010inline std::size_t hash(T8 const&) {
1011 return 0;
1012}
1013inline std::size_t hash(T9 const&) {
1014 return 0;
1015}
1016inline std::size_t hash(T10 const&) {
1017 return 0;
1018}
1019inline std::size_t hash(T11 const&) {
1020 return 0;
1021}
1022inline std::size_t hash(T12 const&) {
1023 return 0;
1024}
1025inline std::size_t hash(T13 const&) {
1026 return 0;
1027}
1028inline std::size_t hash(T14 const&) {
1029 return 0;
1030}
1031inline std::size_t hash(T15 const&) {
1032 return 0;
1033}
1034
1035#endif // variant_CPP11_OR_GREATER
1036
1037template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
1038 class T7, class T8, class T9, class T10, class T11, class T12,
1039 class T13, class T14, class T15>
1040struct helper {
1041 typedef signed char type_index_t;
1042 typedef variant_TL16(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
1043 T13, T14, T15) variant_types;
1044
1045 template <class U> static U* as(void* data) {
1046 return reinterpret_cast<U*>(data);
1047 }
1048
1049 template <class U> static U const* as(void const* data) {
1050 return reinterpret_cast<const U*>(data);
1051 }
1052
1053 static type_index_t to_index_t(std::size_t index) {
1054 return static_cast<type_index_t>(index);
1055 }
1056
1057 static void destroy(type_index_t index, void* data) {
1058 switch (index) {
1059 case 0:
1060 as<T0>(data)->~T0();
1061 break;
1062 case 1:
1063 as<T1>(data)->~T1();
1064 break;
1065 case 2:
1066 as<T2>(data)->~T2();
1067 break;
1068 case 3:
1069 as<T3>(data)->~T3();
1070 break;
1071 case 4:
1072 as<T4>(data)->~T4();
1073 break;
1074 case 5:
1075 as<T5>(data)->~T5();
1076 break;
1077 case 6:
1078 as<T6>(data)->~T6();
1079 break;
1080 case 7:
1081 as<T7>(data)->~T7();
1082 break;
1083 case 8:
1084 as<T8>(data)->~T8();
1085 break;
1086 case 9:
1087 as<T9>(data)->~T9();
1088 break;
1089 case 10:
1090 as<T10>(data)->~T10();
1091 break;
1092 case 11:
1093 as<T11>(data)->~T11();
1094 break;
1095 case 12:
1096 as<T12>(data)->~T12();
1097 break;
1098 case 13:
1099 as<T13>(data)->~T13();
1100 break;
1101 case 14:
1102 as<T14>(data)->~T14();
1103 break;
1104 case 15:
1105 as<T15>(data)->~T15();
1106 break;
1107 }
1108 }
1109
1110#if variant_CPP11_OR_GREATER
1111 template <class T, class... Args>
1112 static type_index_t construct_t(void* data, Args&&... args) {
1113 new (data) T(std::forward<Args>(args)...);
1114
1116 }
1117
1118 template <std::size_t K, class... Args>
1119 static type_index_t construct_i(void* data, Args&&... args) {
1121
1122 construct_t<type>(data, std::forward<Args>(args)...);
1123
1124 return to_index_t(K);
1125 }
1126
1127 static type_index_t move_construct(type_index_t const from_index,
1128 void* from_value, void* to_value) {
1129 switch (from_index) {
1130 case 0:
1131 new (to_value) T0(std::move(*as<T0>(from_value)));
1132 break;
1133 case 1:
1134 new (to_value) T1(std::move(*as<T1>(from_value)));
1135 break;
1136 case 2:
1137 new (to_value) T2(std::move(*as<T2>(from_value)));
1138 break;
1139 case 3:
1140 new (to_value) T3(std::move(*as<T3>(from_value)));
1141 break;
1142 case 4:
1143 new (to_value) T4(std::move(*as<T4>(from_value)));
1144 break;
1145 case 5:
1146 new (to_value) T5(std::move(*as<T5>(from_value)));
1147 break;
1148 case 6:
1149 new (to_value) T6(std::move(*as<T6>(from_value)));
1150 break;
1151 case 7:
1152 new (to_value) T7(std::move(*as<T7>(from_value)));
1153 break;
1154 case 8:
1155 new (to_value) T8(std::move(*as<T8>(from_value)));
1156 break;
1157 case 9:
1158 new (to_value) T9(std::move(*as<T9>(from_value)));
1159 break;
1160 case 10:
1161 new (to_value) T10(std::move(*as<T10>(from_value)));
1162 break;
1163 case 11:
1164 new (to_value) T11(std::move(*as<T11>(from_value)));
1165 break;
1166 case 12:
1167 new (to_value) T12(std::move(*as<T12>(from_value)));
1168 break;
1169 case 13:
1170 new (to_value) T13(std::move(*as<T13>(from_value)));
1171 break;
1172 case 14:
1173 new (to_value) T14(std::move(*as<T14>(from_value)));
1174 break;
1175 case 15:
1176 new (to_value) T15(std::move(*as<T15>(from_value)));
1177 break;
1178 }
1179 return from_index;
1180 }
1181
1182 static type_index_t move_assign(type_index_t const from_index,
1183 void* from_value, void* to_value) {
1184 switch (from_index) {
1185 case 0:
1186 *as<T0>(to_value) = std::move(*as<T0>(from_value));
1187 break;
1188 case 1:
1189 *as<T1>(to_value) = std::move(*as<T1>(from_value));
1190 break;
1191 case 2:
1192 *as<T2>(to_value) = std::move(*as<T2>(from_value));
1193 break;
1194 case 3:
1195 *as<T3>(to_value) = std::move(*as<T3>(from_value));
1196 break;
1197 case 4:
1198 *as<T4>(to_value) = std::move(*as<T4>(from_value));
1199 break;
1200 case 5:
1201 *as<T5>(to_value) = std::move(*as<T5>(from_value));
1202 break;
1203 case 6:
1204 *as<T6>(to_value) = std::move(*as<T6>(from_value));
1205 break;
1206 case 7:
1207 *as<T7>(to_value) = std::move(*as<T7>(from_value));
1208 break;
1209 case 8:
1210 *as<T8>(to_value) = std::move(*as<T8>(from_value));
1211 break;
1212 case 9:
1213 *as<T9>(to_value) = std::move(*as<T9>(from_value));
1214 break;
1215 case 10:
1216 *as<T10>(to_value) = std::move(*as<T10>(from_value));
1217 break;
1218 case 11:
1219 *as<T11>(to_value) = std::move(*as<T11>(from_value));
1220 break;
1221 case 12:
1222 *as<T12>(to_value) = std::move(*as<T12>(from_value));
1223 break;
1224 case 13:
1225 *as<T13>(to_value) = std::move(*as<T13>(from_value));
1226 break;
1227 case 14:
1228 *as<T14>(to_value) = std::move(*as<T14>(from_value));
1229 break;
1230 case 15:
1231 *as<T15>(to_value) = std::move(*as<T15>(from_value));
1232 break;
1233 }
1234 return from_index;
1235 }
1236#endif
1237
1238 static type_index_t copy_construct(type_index_t const from_index,
1239 const void* from_value, void* to_value) {
1240 switch (from_index) {
1241 case 0:
1242 new (to_value) T0(*as<T0>(from_value));
1243 break;
1244 case 1:
1245 new (to_value) T1(*as<T1>(from_value));
1246 break;
1247 case 2:
1248 new (to_value) T2(*as<T2>(from_value));
1249 break;
1250 case 3:
1251 new (to_value) T3(*as<T3>(from_value));
1252 break;
1253 case 4:
1254 new (to_value) T4(*as<T4>(from_value));
1255 break;
1256 case 5:
1257 new (to_value) T5(*as<T5>(from_value));
1258 break;
1259 case 6:
1260 new (to_value) T6(*as<T6>(from_value));
1261 break;
1262 case 7:
1263 new (to_value) T7(*as<T7>(from_value));
1264 break;
1265 case 8:
1266 new (to_value) T8(*as<T8>(from_value));
1267 break;
1268 case 9:
1269 new (to_value) T9(*as<T9>(from_value));
1270 break;
1271 case 10:
1272 new (to_value) T10(*as<T10>(from_value));
1273 break;
1274 case 11:
1275 new (to_value) T11(*as<T11>(from_value));
1276 break;
1277 case 12:
1278 new (to_value) T12(*as<T12>(from_value));
1279 break;
1280 case 13:
1281 new (to_value) T13(*as<T13>(from_value));
1282 break;
1283 case 14:
1284 new (to_value) T14(*as<T14>(from_value));
1285 break;
1286 case 15:
1287 new (to_value) T15(*as<T15>(from_value));
1288 break;
1289 }
1290 return from_index;
1291 }
1292
1293 static type_index_t copy_assign(type_index_t const from_index,
1294 const void* from_value, void* to_value) {
1295 switch (from_index) {
1296 case 0:
1297 *as<T0>(to_value) = *as<T0>(from_value);
1298 break;
1299 case 1:
1300 *as<T1>(to_value) = *as<T1>(from_value);
1301 break;
1302 case 2:
1303 *as<T2>(to_value) = *as<T2>(from_value);
1304 break;
1305 case 3:
1306 *as<T3>(to_value) = *as<T3>(from_value);
1307 break;
1308 case 4:
1309 *as<T4>(to_value) = *as<T4>(from_value);
1310 break;
1311 case 5:
1312 *as<T5>(to_value) = *as<T5>(from_value);
1313 break;
1314 case 6:
1315 *as<T6>(to_value) = *as<T6>(from_value);
1316 break;
1317 case 7:
1318 *as<T7>(to_value) = *as<T7>(from_value);
1319 break;
1320 case 8:
1321 *as<T8>(to_value) = *as<T8>(from_value);
1322 break;
1323 case 9:
1324 *as<T9>(to_value) = *as<T9>(from_value);
1325 break;
1326 case 10:
1327 *as<T10>(to_value) = *as<T10>(from_value);
1328 break;
1329 case 11:
1330 *as<T11>(to_value) = *as<T11>(from_value);
1331 break;
1332 case 12:
1333 *as<T12>(to_value) = *as<T12>(from_value);
1334 break;
1335 case 13:
1336 *as<T13>(to_value) = *as<T13>(from_value);
1337 break;
1338 case 14:
1339 *as<T14>(to_value) = *as<T14>(from_value);
1340 break;
1341 case 15:
1342 *as<T15>(to_value) = *as<T15>(from_value);
1343 break;
1344 }
1345 return from_index;
1346 }
1347};
1348
1349} // namespace detail
1350
1351//
1352// Variant:
1353//
1354
1355template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
1356 class T7, class T8, class T9, class T10, class T11, class T12,
1357 class T13, class T14, class T15>
1358class variant;
1359
1360// 19.7.8 Class monostate
1361
1362class monostate {};
1363
1364// 19.7.9 monostate relational operators
1365
1366inline variant_constexpr bool operator<(monostate, monostate) variant_noexcept {
1367 return false;
1368}
1369inline variant_constexpr bool operator>(monostate, monostate) variant_noexcept {
1370 return false;
1371}
1372inline variant_constexpr bool operator<=(monostate,
1373 monostate) variant_noexcept {
1374 return true;
1375}
1376inline variant_constexpr bool operator>=(monostate,
1377 monostate) variant_noexcept {
1378 return true;
1379}
1380inline variant_constexpr bool operator==(monostate,
1381 monostate) variant_noexcept {
1382 return true;
1383}
1384inline variant_constexpr bool operator!=(monostate,
1385 monostate) variant_noexcept {
1386 return false;
1387}
1388
1389// 19.7.4 variant helper classes
1390
1391// obtain the size of the variant's list of alternatives at compile time
1392
1393template <class T> struct variant_size; /* undefined */
1394
1395template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
1396 class T7, class T8, class T9, class T10, class T11, class T12,
1397 class T13, class T14, class T15>
1398struct variant_size<variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
1399 T12, T13, T14, T15>> {
1400 enum _ {
1401 value = detail::typelist_size<variant_TL16(T0, T1, T2, T3, T4, T5, T6,
1402 T7, T8, T9, T10, T11, T12,
1403 T13, T14, T15)>::value
1404 };
1405};
1406
1407#if variant_CPP14_OR_GREATER
1408template <class T>
1409constexpr std::size_t variant_size_v = variant_size<T>::value;
1410#endif
1411
1412#if !variant_CONFIG_OMIT_VARIANT_SIZE_V_MACRO
1413#define variant_size_V(T) nonstd::variant_size<T>::value
1414#endif
1415
1416// obtain the type of the alternative specified by its index, at compile time:
1417
1418template <std::size_t K, class T> struct variant_alternative; /* undefined */
1419
1420template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
1421 class T5, class T6, class T7, class T8, class T9, class T10,
1422 class T11, class T12, class T13, class T14, class T15>
1423struct variant_alternative<K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9,
1424 T10, T11, T12, T13, T14, T15>> {
1425 typedef
1426 typename detail::typelist_type_at<variant_TL16(T0, T1, T2, T3, T4, T5,
1427 T6, T7, T8, T9, T10, T11,
1428 T12, T13, T14, T15),
1429 K>::type type;
1430};
1431
1432#if variant_CPP11_OR_GREATER
1433template <std::size_t K, class T>
1434using variant_alternative_t = typename variant_alternative<K, T>::type;
1435#endif
1436
1437#if !variant_CONFIG_OMIT_VARIANT_ALTERNATIVE_T_MACRO
1438#define variant_alternative_T(K, T) \
1439 typename nonstd::variant_alternative<K, T>::type
1440#endif
1441
1442// NTS:implement specializes the std::uses_allocator type trait
1443// std::uses_allocator<nonstd::variant>
1444
1445// index of the variant in the invalid state (constant)
1446
1447#if variant_CPP11_OR_GREATER
1448variant_constexpr std::size_t variant_npos = static_cast<std::size_t>(-1);
1449#else
1450static const std::size_t variant_npos = static_cast<std::size_t>(-1);
1451#endif
1452
1453#if !variant_CONFIG_NO_EXCEPTIONS
1454
1455// 19.7.11 Class bad_variant_access
1456
1457class bad_variant_access : public std::exception {
1458 public:
1459#if variant_CPP11_OR_GREATER
1460 virtual const char* what() const variant_noexcept variant_override
1461#else
1462 virtual const char* what() const throw()
1463#endif
1464 {
1465 return "bad variant access";
1466 }
1467};
1468
1469#endif // variant_CONFIG_NO_EXCEPTIONS
1470
1471// 19.7.3 Class template variant
1472
1473template <class T0, class T1 = detail::T1, class T2 = detail::T2,
1474 class T3 = detail::T3, class T4 = detail::T4, class T5 = detail::T5,
1475 class T6 = detail::T6, class T7 = detail::T7, class T8 = detail::T8,
1476 class T9 = detail::T9, class T10 = detail::T10,
1477 class T11 = detail::T11, class T12 = detail::T12,
1478 class T13 = detail::T13, class T14 = detail::T14,
1479 class T15 = detail::T15>
1480class variant {
1481 typedef detail::helper<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
1482 T12, T13, T14, T15>
1483 helper_type;
1484 typedef variant_TL16(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
1485 T13, T14, T15) variant_types;
1486
1487 public:
1488 // 19.7.3.1 Constructors
1489
1490 variant() : type_index(0) { new (ptr()) T0(); }
1491
1492 variant(T0 const& t0) : type_index(0) { new (ptr()) T0(t0); }
1493 variant(T1 const& t1) : type_index(1) { new (ptr()) T1(t1); }
1494 variant(T2 const& t2) : type_index(2) { new (ptr()) T2(t2); }
1495 variant(T3 const& t3) : type_index(3) { new (ptr()) T3(t3); }
1496 variant(T4 const& t4) : type_index(4) { new (ptr()) T4(t4); }
1497 variant(T5 const& t5) : type_index(5) { new (ptr()) T5(t5); }
1498 variant(T6 const& t6) : type_index(6) { new (ptr()) T6(t6); }
1499 variant(T7 const& t7) : type_index(7) { new (ptr()) T7(t7); }
1500 variant(T8 const& t8) : type_index(8) { new (ptr()) T8(t8); }
1501 variant(T9 const& t9) : type_index(9) { new (ptr()) T9(t9); }
1502 variant(T10 const& t10) : type_index(10) { new (ptr()) T10(t10); }
1503 variant(T11 const& t11) : type_index(11) { new (ptr()) T11(t11); }
1504 variant(T12 const& t12) : type_index(12) { new (ptr()) T12(t12); }
1505 variant(T13 const& t13) : type_index(13) { new (ptr()) T13(t13); }
1506 variant(T14 const& t14) : type_index(14) { new (ptr()) T14(t14); }
1507 variant(T15 const& t15) : type_index(15) { new (ptr()) T15(t15); }
1508
1509#if variant_CPP11_OR_GREATER
1510 variant(T0&& t0) : type_index(0) { new (ptr()) T0(std::move(t0)); }
1511 variant(T1&& t1) : type_index(1) { new (ptr()) T1(std::move(t1)); }
1512 variant(T2&& t2) : type_index(2) { new (ptr()) T2(std::move(t2)); }
1513 variant(T3&& t3) : type_index(3) { new (ptr()) T3(std::move(t3)); }
1514 variant(T4&& t4) : type_index(4) { new (ptr()) T4(std::move(t4)); }
1515 variant(T5&& t5) : type_index(5) { new (ptr()) T5(std::move(t5)); }
1516 variant(T6&& t6) : type_index(6) { new (ptr()) T6(std::move(t6)); }
1517 variant(T7&& t7) : type_index(7) { new (ptr()) T7(std::move(t7)); }
1518 variant(T8&& t8) : type_index(8) { new (ptr()) T8(std::move(t8)); }
1519 variant(T9&& t9) : type_index(9) { new (ptr()) T9(std::move(t9)); }
1520 variant(T10&& t10) : type_index(10) { new (ptr()) T10(std::move(t10)); }
1521 variant(T11&& t11) : type_index(11) { new (ptr()) T11(std::move(t11)); }
1522 variant(T12&& t12) : type_index(12) { new (ptr()) T12(std::move(t12)); }
1523 variant(T13&& t13) : type_index(13) { new (ptr()) T13(std::move(t13)); }
1524 variant(T14&& t14) : type_index(14) { new (ptr()) T14(std::move(t14)); }
1525 variant(T15&& t15) : type_index(15) { new (ptr()) T15(std::move(t15)); }
1526
1527#endif
1528
1529 variant(variant const& other) : type_index(other.type_index) {
1530 (void) helper_type::copy_construct(other.type_index, other.ptr(),
1531 ptr());
1532 }
1533
1534#if variant_CPP11_OR_GREATER
1535
1536 variant(variant&& other) noexcept(
1537 std::is_nothrow_move_constructible<T0>::value &&
1538 std::is_nothrow_move_constructible<T1>::value &&
1539 std::is_nothrow_move_constructible<T2>::value &&
1540 std::is_nothrow_move_constructible<T3>::value &&
1541 std::is_nothrow_move_constructible<T4>::value &&
1542 std::is_nothrow_move_constructible<T5>::value &&
1543 std::is_nothrow_move_constructible<T6>::value &&
1544 std::is_nothrow_move_constructible<T7>::value &&
1545 std::is_nothrow_move_constructible<T8>::value &&
1546 std::is_nothrow_move_constructible<T9>::value &&
1547 std::is_nothrow_move_constructible<T10>::value &&
1548 std::is_nothrow_move_constructible<T11>::value &&
1549 std::is_nothrow_move_constructible<T12>::value &&
1550 std::is_nothrow_move_constructible<T13>::value &&
1551 std::is_nothrow_move_constructible<T14>::value &&
1552 std::is_nothrow_move_constructible<T15>::value)
1553 : type_index(other.type_index) {
1554 (void) helper_type::move_construct(other.type_index, other.ptr(),
1555 ptr());
1556 }
1557
1558 template <std::size_t K>
1559 using type_at_t = typename detail::typelist_type_at<variant_types, K>::type;
1560
1561 template <class T, class... Args variant_REQUIRES_T(
1562 std::is_constructible<T, Args...>::value)>
1563 explicit variant(nonstd_lite_in_place_type_t(T), Args&&... args) {
1564 type_index = variant_npos_internal();
1565 type_index = helper_type::template construct_t<T>(
1566 ptr(), std::forward<Args>(args)...);
1567 }
1568
1569 template <class T, class U,
1570 class... Args variant_REQUIRES_T(
1571 std::is_constructible<T, std::initializer_list<U>&,
1572 Args...>::value)>
1573 explicit variant(nonstd_lite_in_place_type_t(T),
1574 std::initializer_list<U> il, Args&&... args) {
1575 type_index = variant_npos_internal();
1576 type_index = helper_type::template construct_t<T>(
1577 ptr(), il, std::forward<Args>(args)...);
1578 }
1579
1580 template <std::size_t K,
1581 class... Args variant_REQUIRES_T(
1582 std::is_constructible<type_at_t<K>, Args...>::value)>
1583 explicit variant(nonstd_lite_in_place_index_t(K), Args&&... args) {
1584 type_index = variant_npos_internal();
1585 type_index = helper_type::template construct_i<K>(
1586 ptr(), std::forward<Args>(args)...);
1587 }
1588
1589 template <size_t K, class U,
1590 class... Args variant_REQUIRES_T(
1591 std::is_constructible<type_at_t<K>, std::initializer_list<U>&,
1592 Args...>::value)>
1593 explicit variant(nonstd_lite_in_place_index_t(K),
1594 std::initializer_list<U> il, Args&&... args) {
1595 type_index = variant_npos_internal();
1596 type_index = helper_type::template construct_i<K>(
1597 ptr(), il, std::forward<Args>(args)...);
1598 }
1599
1600#endif // variant_CPP11_OR_GREATER
1601
1602 // 19.7.3.2 Destructor
1603
1604 ~variant() {
1605 if (!valueless_by_exception()) {
1606 helper_type::destroy(type_index, ptr());
1607 }
1608 }
1609
1610 // 19.7.3.3 Assignment
1611
1612 variant& operator=(variant const& other) { return copy_assign(other); }
1613
1614#if variant_CPP11_OR_GREATER
1615
1616 variant& operator=(variant&& other) noexcept(
1617 std::is_nothrow_move_assignable<T0>::value &&
1618 std::is_nothrow_move_assignable<T1>::value &&
1619 std::is_nothrow_move_assignable<T2>::value &&
1620 std::is_nothrow_move_assignable<T3>::value &&
1621 std::is_nothrow_move_assignable<T4>::value &&
1622 std::is_nothrow_move_assignable<T5>::value &&
1623 std::is_nothrow_move_assignable<T6>::value &&
1624 std::is_nothrow_move_assignable<T7>::value &&
1625 std::is_nothrow_move_assignable<T8>::value &&
1626 std::is_nothrow_move_assignable<T9>::value &&
1627 std::is_nothrow_move_assignable<T10>::value &&
1628 std::is_nothrow_move_assignable<T11>::value &&
1629 std::is_nothrow_move_assignable<T12>::value &&
1630 std::is_nothrow_move_assignable<T13>::value &&
1631 std::is_nothrow_move_assignable<T14>::value &&
1632 std::is_nothrow_move_assignable<T15>::value) {
1633 return move_assign(std::move(other));
1634 }
1635
1636 variant& operator=(T0&& t0) { return assign_value<0>(std::move(t0)); }
1637 variant& operator=(T1&& t1) { return assign_value<1>(std::move(t1)); }
1638 variant& operator=(T2&& t2) { return assign_value<2>(std::move(t2)); }
1639 variant& operator=(T3&& t3) { return assign_value<3>(std::move(t3)); }
1640 variant& operator=(T4&& t4) { return assign_value<4>(std::move(t4)); }
1641 variant& operator=(T5&& t5) { return assign_value<5>(std::move(t5)); }
1642 variant& operator=(T6&& t6) { return assign_value<6>(std::move(t6)); }
1643 variant& operator=(T7&& t7) { return assign_value<7>(std::move(t7)); }
1644 variant& operator=(T8&& t8) { return assign_value<8>(std::move(t8)); }
1645 variant& operator=(T9&& t9) { return assign_value<9>(std::move(t9)); }
1646 variant& operator=(T10&& t10) { return assign_value<10>(std::move(t10)); }
1647 variant& operator=(T11&& t11) { return assign_value<11>(std::move(t11)); }
1648 variant& operator=(T12&& t12) { return assign_value<12>(std::move(t12)); }
1649 variant& operator=(T13&& t13) { return assign_value<13>(std::move(t13)); }
1650 variant& operator=(T14&& t14) { return assign_value<14>(std::move(t14)); }
1651 variant& operator=(T15&& t15) { return assign_value<15>(std::move(t15)); }
1652
1653#endif
1654
1655 variant& operator=(T0 const& t0) { return assign_value<0>(t0); }
1656 variant& operator=(T1 const& t1) { return assign_value<1>(t1); }
1657 variant& operator=(T2 const& t2) { return assign_value<2>(t2); }
1658 variant& operator=(T3 const& t3) { return assign_value<3>(t3); }
1659 variant& operator=(T4 const& t4) { return assign_value<4>(t4); }
1660 variant& operator=(T5 const& t5) { return assign_value<5>(t5); }
1661 variant& operator=(T6 const& t6) { return assign_value<6>(t6); }
1662 variant& operator=(T7 const& t7) { return assign_value<7>(t7); }
1663 variant& operator=(T8 const& t8) { return assign_value<8>(t8); }
1664 variant& operator=(T9 const& t9) { return assign_value<9>(t9); }
1665 variant& operator=(T10 const& t10) { return assign_value<10>(t10); }
1666 variant& operator=(T11 const& t11) { return assign_value<11>(t11); }
1667 variant& operator=(T12 const& t12) { return assign_value<12>(t12); }
1668 variant& operator=(T13 const& t13) { return assign_value<13>(t13); }
1669 variant& operator=(T14 const& t14) { return assign_value<14>(t14); }
1670 variant& operator=(T15 const& t15) { return assign_value<15>(t15); }
1671
1672 std::size_t index() const {
1673 return variant_npos_internal() == type_index
1674 ? variant_npos
1675 : static_cast<std::size_t>(type_index);
1676 }
1677
1678 // 19.7.3.4 Modifiers
1679
1680#if variant_CPP11_OR_GREATER
1681 template <class T, class... Args variant_REQUIRES_T(
1682 std::is_constructible<T, Args...>::value)>
1683 T& emplace(Args&&... args) {
1684 helper_type::destroy(type_index, ptr());
1685 type_index = variant_npos_internal();
1686 type_index = helper_type::template construct_t<T>(
1687 ptr(), std::forward<Args>(args)...);
1688
1689 return *as<T>();
1690 }
1691
1692 template <class T, class U,
1693 class... Args variant_REQUIRES_T(
1694 std::is_constructible<T, std::initializer_list<U>&,
1695 Args...>::value)>
1696 T& emplace(std::initializer_list<U> il, Args&&... args) {
1697 helper_type::destroy(type_index, ptr());
1698 type_index = variant_npos_internal();
1699 type_index = helper_type::template construct_t<T>(
1700 ptr(), il, std::forward<Args>(args)...);
1701
1702 return *as<T>();
1703 }
1704
1705 template <size_t K,
1706 class... Args variant_REQUIRES_T(
1707 std::is_constructible<type_at_t<K>, Args...>::value)>
1708 variant_alternative_t<K, variant>& emplace(Args&&... args) {
1709 return this->template emplace<type_at_t<K>>(
1710 std::forward<Args>(args)...);
1711 }
1712
1713 template <size_t K, class U,
1714 class... Args variant_REQUIRES_T(
1715 std::is_constructible<type_at_t<K>, std::initializer_list<U>&,
1716 Args...>::value)>
1717 variant_alternative_t<K, variant>& emplace(std::initializer_list<U> il,
1718 Args&&... args) {
1719 return this->template emplace<type_at_t<K>>(
1720 il, std::forward<Args>(args)...);
1721 }
1722
1723#endif // variant_CPP11_OR_GREATER
1724
1725 // 19.7.3.5 Value status
1726
1727 bool valueless_by_exception() const {
1728 return type_index == variant_npos_internal();
1729 }
1730
1731 // 19.7.3.6 Swap
1732
1733 void swap(variant& other)
1734#if variant_CPP11_OR_GREATER
1735 noexcept(std::is_nothrow_move_constructible<T0>::value &&
1736 std17::is_nothrow_swappable<T0>::value &&
1737 std::is_nothrow_move_constructible<T1>::value &&
1738 std17::is_nothrow_swappable<T1>::value &&
1739 std::is_nothrow_move_constructible<T2>::value &&
1740 std17::is_nothrow_swappable<T2>::value &&
1741 std::is_nothrow_move_constructible<T3>::value &&
1742 std17::is_nothrow_swappable<T3>::value &&
1743 std::is_nothrow_move_constructible<T4>::value &&
1744 std17::is_nothrow_swappable<T4>::value &&
1745 std::is_nothrow_move_constructible<T5>::value &&
1746 std17::is_nothrow_swappable<T5>::value &&
1747 std::is_nothrow_move_constructible<T6>::value &&
1748 std17::is_nothrow_swappable<T6>::value &&
1749 std::is_nothrow_move_constructible<T7>::value &&
1750 std17::is_nothrow_swappable<T7>::value &&
1751 std::is_nothrow_move_constructible<T8>::value &&
1752 std17::is_nothrow_swappable<T8>::value &&
1753 std::is_nothrow_move_constructible<T9>::value &&
1754 std17::is_nothrow_swappable<T9>::value &&
1755 std::is_nothrow_move_constructible<T10>::value &&
1756 std17::is_nothrow_swappable<T10>::value &&
1757 std::is_nothrow_move_constructible<T11>::value &&
1758 std17::is_nothrow_swappable<T11>::value &&
1759 std::is_nothrow_move_constructible<T12>::value &&
1760 std17::is_nothrow_swappable<T12>::value &&
1761 std::is_nothrow_move_constructible<T13>::value &&
1762 std17::is_nothrow_swappable<T13>::value &&
1763 std::is_nothrow_move_constructible<T14>::value &&
1764 std17::is_nothrow_swappable<T14>::value &&
1765 std::is_nothrow_move_constructible<T15>::value &&
1766 std17::is_nothrow_swappable<T15>::value
1767
1768 )
1769#endif
1770 {
1771 if (valueless_by_exception() && other.valueless_by_exception()) {
1772 // no effect
1773 } else if (type_index == other.type_index) {
1774 this->swap_value(type_index, other);
1775 } else {
1776#if variant_CPP11_OR_GREATER
1777 variant tmp(std::move(*this));
1778 *this = std::move(other);
1779 other = std::move(tmp);
1780#else
1781 variant tmp(*this);
1782 *this = other;
1783 other = tmp;
1784#endif
1785 }
1786 }
1787
1788 //
1789 // non-standard:
1790 //
1791
1792 template <class T>
1793 static variant_constexpr std::size_t index_of() variant_noexcept {
1794 return to_size_t(
1796 variant_types, typename std11::remove_cv<T>::type>::value);
1797 }
1798
1799 template <class T> T& get() {
1800#if variant_CONFIG_NO_EXCEPTIONS
1801 assert(index_of<T>() == index());
1802#else
1803 if (index_of<T>() != index()) {
1804 throw bad_variant_access();
1805 }
1806#endif
1807 return *as<T>();
1808 }
1809
1810 template <class T> T const& get() const {
1811#if variant_CONFIG_NO_EXCEPTIONS
1812 assert(index_of<T>() == index());
1813#else
1814 if (index_of<T>() != index()) {
1815 throw bad_variant_access();
1816 }
1817#endif
1818 return *as<const T>();
1819 }
1820
1821 template <std::size_t K>
1823 return this->template get<
1825 }
1826
1827 template <std::size_t K>
1828 typename variant_alternative<K, variant>::type const& get() const {
1829 return this->template get<
1831 }
1832
1833 private:
1834 typedef typename helper_type::type_index_t type_index_t;
1835
1836 void* ptr() variant_noexcept { return &data; }
1837
1838 void const* ptr() const variant_noexcept { return &data; }
1839
1840 template <class U> U* as() { return reinterpret_cast<U*>(ptr()); }
1841
1842 template <class U> U const* as() const {
1843 return reinterpret_cast<U const*>(ptr());
1844 }
1845
1846 template <class U> static variant_constexpr std::size_t to_size_t(U index) {
1847 return static_cast<std::size_t>(index);
1848 }
1849
1850 variant_constexpr type_index_t
1851 variant_npos_internal() const variant_noexcept {
1852 return static_cast<type_index_t>(-1);
1853 }
1854
1855 variant& copy_assign(variant const& other) {
1856 if (valueless_by_exception() && other.valueless_by_exception()) {
1857 // no effect
1858 } else if (!valueless_by_exception() &&
1859 other.valueless_by_exception()) {
1860 helper_type::destroy(type_index, ptr());
1861 type_index = variant_npos_internal();
1862 } else if (index() == other.index()) {
1863 type_index =
1864 helper_type::copy_assign(other.type_index, other.ptr(), ptr());
1865 } else {
1866 helper_type::destroy(type_index, ptr());
1867 type_index = variant_npos_internal();
1868 type_index = helper_type::copy_construct(other.type_index,
1869 other.ptr(), ptr());
1870 }
1871 return *this;
1872 }
1873
1874#if variant_CPP11_OR_GREATER
1875
1876 variant& move_assign(variant&& other) {
1877 if (valueless_by_exception() && other.valueless_by_exception()) {
1878 // no effect
1879 } else if (!valueless_by_exception() &&
1880 other.valueless_by_exception()) {
1881 helper_type::destroy(type_index, ptr());
1882 type_index = variant_npos_internal();
1883 } else if (index() == other.index()) {
1884 type_index =
1885 helper_type::move_assign(other.type_index, other.ptr(), ptr());
1886 } else {
1887 helper_type::destroy(type_index, ptr());
1888 type_index = variant_npos_internal();
1889 type_index = helper_type::move_construct(other.type_index,
1890 other.ptr(), ptr());
1891 }
1892 return *this;
1893 }
1894
1895 template <std::size_t K, class T> variant& assign_value(T&& value) {
1896 if (index() == K) {
1897 *as<T>() = std::forward<T>(value);
1898 } else {
1899 helper_type::destroy(type_index, ptr());
1900 type_index = variant_npos_internal();
1901 new (ptr()) T(std::forward<T>(value));
1902 type_index = K;
1903 }
1904 return *this;
1905 }
1906
1907#endif // variant_CPP11_OR_GREATER
1908
1909 template <std::size_t K, class T> variant& assign_value(T const& value) {
1910 if (index() == K) {
1911 *as<T>() = value;
1912 } else {
1913 helper_type::destroy(type_index, ptr());
1914 type_index = variant_npos_internal();
1915 new (ptr()) T(value);
1916 type_index = K;
1917 }
1918 return *this;
1919 }
1920
1921 void swap_value(type_index_t index, variant& other) {
1922 using std::swap;
1923 switch (index) {
1924 case 0:
1925 swap(this->get<0>(), other.get<0>());
1926 break;
1927 case 1:
1928 swap(this->get<1>(), other.get<1>());
1929 break;
1930 case 2:
1931 swap(this->get<2>(), other.get<2>());
1932 break;
1933 case 3:
1934 swap(this->get<3>(), other.get<3>());
1935 break;
1936 case 4:
1937 swap(this->get<4>(), other.get<4>());
1938 break;
1939 case 5:
1940 swap(this->get<5>(), other.get<5>());
1941 break;
1942 case 6:
1943 swap(this->get<6>(), other.get<6>());
1944 break;
1945 case 7:
1946 swap(this->get<7>(), other.get<7>());
1947 break;
1948 case 8:
1949 swap(this->get<8>(), other.get<8>());
1950 break;
1951 case 9:
1952 swap(this->get<9>(), other.get<9>());
1953 break;
1954 case 10:
1955 swap(this->get<10>(), other.get<10>());
1956 break;
1957 case 11:
1958 swap(this->get<11>(), other.get<11>());
1959 break;
1960 case 12:
1961 swap(this->get<12>(), other.get<12>());
1962 break;
1963 case 13:
1964 swap(this->get<13>(), other.get<13>());
1965 break;
1966 case 14:
1967 swap(this->get<14>(), other.get<14>());
1968 break;
1969 case 15:
1970 swap(this->get<15>(), other.get<15>());
1971 break;
1972 }
1973 }
1974
1975 private:
1976 enum { data_size = detail::typelist_max<variant_types>::value };
1977
1978#if variant_CPP11_OR_GREATER
1979
1980 enum { data_align = detail::typelist_max_alignof<variant_types>::value };
1981
1982 using aligned_storage_t =
1983 typename std::aligned_storage<data_size, data_align>::type;
1984 aligned_storage_t data;
1985
1986#elif variant_CONFIG_MAX_ALIGN_HACK
1987
1988 typedef union {
1989 unsigned char data[data_size];
1991
1992 detail::max_align_t hack;
1993 aligned_storage_t data;
1994
1995#else
1996 typedef typename detail::typelist_max<variant_types>::type max_type;
1997
1998 typedef variant_ALIGN_AS(max_type) align_as_type;
1999
2000 typedef union {
2001 align_as_type data[1 + (data_size - 1) / sizeof(align_as_type)];
2003 aligned_storage_t data;
2004
2005 // # undef variant_ALIGN_AS
2006
2007#endif // variant_CONFIG_MAX_ALIGN_HACK
2008
2009 type_index_t type_index;
2010};
2011
2012// 19.7.5 Value access
2013
2014template <class T, class T0, class T1, class T2, class T3, class T4, class T5,
2015 class T6, class T7, class T8, class T9, class T10, class T11,
2016 class T12, class T13, class T14, class T15>
2017inline bool
2018holds_alternative(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2019 T13, T14, T15> const& v) variant_noexcept {
2020 return v.index() ==
2021 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
2022 T14, T15>::template index_of<T>();
2023}
2024
2025template <class R, class T0, class T1, class T2, class T3, class T4, class T5,
2026 class T6, class T7, class T8, class T9, class T10, class T11,
2027 class T12, class T13, class T14, class T15>
2028inline R& get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2029 T13, T14, T15>& v,
2030 nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R)) {
2031 return v.template get<R>();
2032}
2033
2034template <class R, class T0, class T1, class T2, class T3, class T4, class T5,
2035 class T6, class T7, class T8, class T9, class T10, class T11,
2036 class T12, class T13, class T14, class T15>
2037inline R const&
2038get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2039 T15> const& v,
2040 nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R)) {
2041 return v.template get<R>();
2042}
2043
2044template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2045 class T5, class T6, class T7, class T8, class T9, class T10,
2046 class T11, class T12, class T13, class T14, class T15>
2047inline
2048 typename variant_alternative<K,
2049 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9,
2050 T10, T11, T12, T13, T14, T15>>::type&
2051 get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2052 T15>& v,
2053 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2054#if variant_CONFIG_NO_EXCEPTIONS
2055 assert(K == v.index());
2056#else
2057 if (K != v.index()) {
2058 throw bad_variant_access();
2059 }
2060#endif
2061 return v.template get<K>();
2062}
2063
2064template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2065 class T5, class T6, class T7, class T8, class T9, class T10,
2066 class T11, class T12, class T13, class T14, class T15>
2067inline typename variant_alternative<
2068 K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2069 T15>>::type const&
2070get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2071 T15> const& v,
2072 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2073#if variant_CONFIG_NO_EXCEPTIONS
2074 assert(K == v.index());
2075#else
2076 if (K != v.index()) {
2077 throw bad_variant_access();
2078 }
2079#endif
2080 return v.template get<K>();
2081}
2082
2083#if variant_CPP11_OR_GREATER
2084
2085template <class R, class T0, class T1, class T2, class T3, class T4, class T5,
2086 class T6, class T7, class T8, class T9, class T10, class T11,
2087 class T12, class T13, class T14, class T15>
2088inline R&& get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2089 T13, T14, T15>&& v,
2090 nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R)) {
2091 return std::move(v.template get<R>());
2092}
2093
2094template <class R, class T0, class T1, class T2, class T3, class T4, class T5,
2095 class T6, class T7, class T8, class T9, class T10, class T11,
2096 class T12, class T13, class T14, class T15>
2097inline R const&&
2098get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2099 T15> const&& v,
2100 nonstd_lite_in_place_type_t(R) = nonstd_lite_in_place_type(R)) {
2101 return std::move(v.template get<R>());
2102}
2103
2104template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2105 class T5, class T6, class T7, class T8, class T9, class T10,
2106 class T11, class T12, class T13, class T14, class T15>
2107inline
2108 typename variant_alternative<K,
2109 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9,
2110 T10, T11, T12, T13, T14, T15>>::type&&
2111 get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2112 T15>&& v,
2113 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2114#if variant_CONFIG_NO_EXCEPTIONS
2115 assert(K == v.index());
2116#else
2117 if (K != v.index()) {
2118 throw bad_variant_access();
2119 }
2120#endif
2121 return std::move(v.template get<K>());
2122}
2123
2124template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2125 class T5, class T6, class T7, class T8, class T9, class T10,
2126 class T11, class T12, class T13, class T14, class T15>
2127inline typename variant_alternative<
2128 K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2129 T15>>::type const&&
2130get(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2131 T15> const&& v,
2132 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2133#if variant_CONFIG_NO_EXCEPTIONS
2134 assert(K == v.index());
2135#else
2136 if (K != v.index()) {
2137 throw bad_variant_access();
2138 }
2139#endif
2140 return std::move(v.template get<K>());
2141}
2142
2143#endif // variant_CPP11_OR_GREATER
2144
2145template <class T, class T0, class T1, class T2, class T3, class T4, class T5,
2146 class T6, class T7, class T8, class T9, class T10, class T11,
2147 class T12, class T13, class T14, class T15>
2148inline typename std11::add_pointer<T>::type
2149get_if(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2150 T15>* pv,
2151 nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T)) {
2152 return (pv->index() ==
2153 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
2154 T14, T15>::template index_of<T>())
2155 ? &get<T>(*pv)
2156 : variant_nullptr;
2157}
2158
2159template <class T, class T0, class T1, class T2, class T3, class T4, class T5,
2160 class T6, class T7, class T8, class T9, class T10, class T11,
2161 class T12, class T13, class T14, class T15>
2162inline typename std11::add_pointer<const T>::type
2163get_if(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2164 T15> const* pv,
2165 nonstd_lite_in_place_type_t(T) = nonstd_lite_in_place_type(T)) {
2166 return (pv->index() ==
2167 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
2168 T14, T15>::template index_of<T>())
2169 ? &get<T>(*pv)
2170 : variant_nullptr;
2171}
2172
2173template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2174 class T5, class T6, class T7, class T8, class T9, class T10,
2175 class T11, class T12, class T13, class T14, class T15>
2176inline typename std11::add_pointer<typename variant_alternative<
2177 K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2178 T15>>::type>::type
2179get_if(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2180 T15>* pv,
2181 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2182 return (pv->index() == K) ? &get<K>(*pv) : variant_nullptr;
2183}
2184
2185template <std::size_t K, class T0, class T1, class T2, class T3, class T4,
2186 class T5, class T6, class T7, class T8, class T9, class T10,
2187 class T11, class T12, class T13, class T14, class T15>
2188inline typename std11::add_pointer<const typename variant_alternative<
2189 K, variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2190 T15>>::type>::type
2191get_if(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14,
2192 T15> const* pv,
2193 nonstd_lite_in_place_index_t(K) = nonstd_lite_in_place_index(K)) {
2194 return (pv->index() == K) ? &get<K>(*pv) : variant_nullptr;
2195}
2196
2197// 19.7.10 Specialized algorithms
2198
2199template <
2200 class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2201 class T7, class T8, class T9, class T10, class T11, class T12, class T13,
2202 class T14,
2203 class T15
2204#if variant_CPP11_OR_GREATER
2205 variant_REQUIRES_T(
2206 std::is_move_constructible<T0>::value&& std17::is_swappable<
2207 T0>::value&& std::is_move_constructible<T1>::value&&
2208 std17::is_swappable<T1>::value&& std::is_move_constructible<
2209 T2>::value&& std17::is_swappable<T2>::value&&
2210 std::is_move_constructible<T3>::value&& std17::is_swappable<
2211 T3>::value&& std::is_move_constructible<T4>::value&& std17::
2212 is_swappable<T4>::value&& std::is_move_constructible<
2213 T5>::value&& std17::is_swappable<T5>::value&& std::
2214 is_move_constructible<T6>::value&& std17::is_swappable<
2215 T6>::value&& std::is_move_constructible<T7>::value&&
2216 std17::is_swappable<T7>::value&& std::is_move_constructible<
2217 T8>::value&& std17::is_swappable<T8>::
2218 value&& std::is_move_constructible<
2219 T9>::value&& std17::is_swappable<T9>::
2220 value&& std::is_move_constructible<
2221 T10>::value&& std17::is_swappable<T10>::
2222 value&& std::is_move_constructible<
2223 T11>::value&& std17::is_swappable<T11>::
2224 value&& std::is_move_constructible<
2225 T12>::value&&
2226 std17::is_swappable<
2227 T12>::value&& std::
2228 is_move_constructible<
2229 T13>::value&&
2230 std17::is_swappable<
2231 T13>::value&& std::
2232 is_move_constructible<
2233 T14>::value&&
2234 std17::is_swappable<
2235 T14>::value&&
2236 std::is_move_constructible<
2237 T15>::value&&
2238 std17::is_swappable<
2239 T15>::
2240 value)
2241#endif
2242 >
2243inline void swap(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2244 T13, T14, T15>& a,
2245 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2246 T13, T14, T15>& b)
2247#if variant_CPP11_OR_GREATER
2248 noexcept(noexcept(a.swap(b)))
2249#endif
2250{
2251 a.swap(b);
2252}
2253
2254// 19.7.7 Visitation
2255
2256// Variant 'visitor' implementation
2257
2258namespace detail {
2259
2260template <typename R, typename VT> struct VisitorApplicatorImpl {
2261 template <typename Visitor, typename T>
2262 static R apply(Visitor const& v, T const& arg) {
2263 return v(arg);
2264 }
2265};
2266
2267template <typename R, typename VT> struct VisitorApplicatorImpl<R, TX<VT>> {
2268 template <typename Visitor, typename T> static R apply(Visitor const&, T) {
2269 // prevent default construction of a const reference, see issue #39:
2270 std::terminate();
2271 }
2272};
2273
2274template <typename R> struct VisitorApplicator;
2275
2276template <typename R, typename Visitor, typename V1> struct VisitorUnwrapper;
2277
2278#if variant_CPP11_OR_GREATER
2279template <size_t NumVars, typename R, typename Visitor, typename... T>
2280#else
2281template <size_t NumVars, typename R, typename Visitor, typename T1,
2282 typename T2 = S0, typename T3 = S0, typename T4 = S0,
2283 typename T5 = S0>
2284#endif
2286
2287template <typename R, typename Visitor, typename T2>
2288struct TypedVisitorUnwrapper<2, R, Visitor, T2> {
2289 const Visitor& visitor;
2290 T2 const& val2;
2291
2292 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_)
2293 : visitor(visitor_), val2(val2_)
2294
2295 {}
2296
2297 template <typename T> R operator()(const T& val1) const {
2298 return visitor(val1, val2);
2299 }
2300};
2301
2302template <typename R, typename Visitor, typename T2, typename T3>
2303struct TypedVisitorUnwrapper<3, R, Visitor, T2, T3> {
2304 const Visitor& visitor;
2305 T2 const& val2;
2306 T3 const& val3;
2307
2308 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_,
2309 T3 const& val3_)
2310 : visitor(visitor_), val2(val2_), val3(val3_)
2311
2312 {}
2313
2314 template <typename T> R operator()(const T& val1) const {
2315 return visitor(val1, val2, val3);
2316 }
2317};
2318
2319template <typename R, typename Visitor, typename T2, typename T3, typename T4>
2320struct TypedVisitorUnwrapper<4, R, Visitor, T2, T3, T4> {
2321 const Visitor& visitor;
2322 T2 const& val2;
2323 T3 const& val3;
2324 T4 const& val4;
2325
2326 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_,
2327 T3 const& val3_, T4 const& val4_)
2328 : visitor(visitor_), val2(val2_), val3(val3_), val4(val4_)
2329
2330 {}
2331
2332 template <typename T> R operator()(const T& val1) const {
2333 return visitor(val1, val2, val3, val4);
2334 }
2335};
2336
2337template <typename R, typename Visitor, typename T2, typename T3, typename T4,
2338 typename T5>
2339struct TypedVisitorUnwrapper<5, R, Visitor, T2, T3, T4, T5> {
2340 const Visitor& visitor;
2341 T2 const& val2;
2342 T3 const& val3;
2343 T4 const& val4;
2344 T5 const& val5;
2345
2346 TypedVisitorUnwrapper(const Visitor& visitor_, T2 const& val2_,
2347 T3 const& val3_, T4 const& val4_, T5 const& val5_)
2348 : visitor(visitor_), val2(val2_), val3(val3_), val4(val4_), val5(val5_)
2349
2350 {}
2351
2352 template <typename T> R operator()(const T& val1) const {
2353 return visitor(val1, val2, val3, val4, val5);
2354 }
2355};
2356
2357template <typename R, typename Visitor, typename V2> struct VisitorUnwrapper {
2358 const Visitor& visitor;
2359 const V2& r;
2360
2361 VisitorUnwrapper(const Visitor& visitor_, const V2& r_)
2362 : visitor(visitor_), r(r_) {}
2363
2364 template <typename T1> R operator()(T1 const& val1) const {
2365 typedef TypedVisitorUnwrapper<2, R, Visitor, T1> visitor_type;
2366 return VisitorApplicator<R>::apply(visitor_type(visitor, val1), r);
2367 }
2368
2369 template <typename T1, typename T2>
2370 R operator()(T1 const& val1, T2 const& val2) const {
2372 return VisitorApplicator<R>::apply(visitor_type(visitor, val1, val2),
2373 r);
2374 }
2375
2376 template <typename T1, typename T2, typename T3>
2377 R operator()(T1 const& val1, T2 const& val2, T3 const& val3) const {
2379 return VisitorApplicator<R>::apply(
2380 visitor_type(visitor, val1, val2, val3), r);
2381 }
2382
2383 template <typename T1, typename T2, typename T3, typename T4>
2384 R operator()(T1 const& val1, T2 const& val2, T3 const& val3,
2385 T4 const& val4) const {
2387 visitor_type;
2388 return VisitorApplicator<R>::apply(
2389 visitor_type(visitor, val1, val2, val3, val4), r);
2390 }
2391
2392 template <typename T1, typename T2, typename T3, typename T4, typename T5>
2393 R operator()(T1 const& val1, T2 const& val2, T3 const& val3, T4 const& val4,
2394 T5 const& val5) const {
2396 visitor_type;
2397 return VisitorApplicator<R>::apply(
2398 visitor_type(visitor, val1, val2, val3, val4, val5), r);
2399 }
2400};
2401
2402template <typename R> struct VisitorApplicator {
2403 template <typename Visitor, typename V1>
2404 static R apply(const Visitor& v, const V1& arg) {
2405 switch (arg.index()) {
2406 case 0:
2407 return apply_visitor<0>(v, arg);
2408 case 1:
2409 return apply_visitor<1>(v, arg);
2410 case 2:
2411 return apply_visitor<2>(v, arg);
2412 case 3:
2413 return apply_visitor<3>(v, arg);
2414 case 4:
2415 return apply_visitor<4>(v, arg);
2416 case 5:
2417 return apply_visitor<5>(v, arg);
2418 case 6:
2419 return apply_visitor<6>(v, arg);
2420 case 7:
2421 return apply_visitor<7>(v, arg);
2422 case 8:
2423 return apply_visitor<8>(v, arg);
2424 case 9:
2425 return apply_visitor<9>(v, arg);
2426 case 10:
2427 return apply_visitor<10>(v, arg);
2428 case 11:
2429 return apply_visitor<11>(v, arg);
2430 case 12:
2431 return apply_visitor<12>(v, arg);
2432 case 13:
2433 return apply_visitor<13>(v, arg);
2434 case 14:
2435 return apply_visitor<14>(v, arg);
2436 case 15:
2437 return apply_visitor<15>(v, arg);
2438
2439 // prevent default construction of a const reference, see issue #39:
2440 default:
2441 std::terminate();
2442 }
2443 }
2444
2445 template <size_t Idx, typename Visitor, typename V1>
2446 static R apply_visitor(const Visitor& v, const V1& arg) {
2447
2448#if variant_CPP11_OR_GREATER
2449 typedef typename variant_alternative<
2450 Idx, typename std::decay<V1>::type>::type value_type;
2451#else
2452 typedef typename variant_alternative<Idx, V1>::type value_type;
2453#endif
2454 return VisitorApplicatorImpl<R, value_type>::apply(v, get<Idx>(arg));
2455 }
2456
2457#if variant_CPP11_OR_GREATER
2458 template <typename Visitor, typename V1, typename V2, typename... V>
2459 static R apply(const Visitor& v, const V1& arg1, const V2& arg2,
2460 const V... args) {
2461 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
2462 Unwrapper unwrapper(v, arg1);
2463 return apply(unwrapper, arg2, args...);
2464 }
2465#else
2466
2467 template <typename Visitor, typename V1, typename V2>
2468 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2) {
2469 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
2470 Unwrapper unwrapper(v, arg1);
2471 return apply(unwrapper, arg2);
2472 }
2473
2474 template <typename Visitor, typename V1, typename V2, typename V3>
2475 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2,
2476 V3 const& arg3) {
2477 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
2478 Unwrapper unwrapper(v, arg1);
2479 return apply(unwrapper, arg2, arg3);
2480 }
2481
2482 template <typename Visitor, typename V1, typename V2, typename V3,
2483 typename V4>
2484 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2,
2485 V3 const& arg3, V4 const& arg4) {
2486 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
2487 Unwrapper unwrapper(v, arg1);
2488 return apply(unwrapper, arg2, arg3, arg4);
2489 }
2490
2491 template <typename Visitor, typename V1, typename V2, typename V3,
2492 typename V4, typename V5>
2493 static R apply(const Visitor& v, V1 const& arg1, V2 const& arg2,
2494 V3 const& arg3, V4 const& arg4, V5 const& arg5) {
2495 typedef VisitorUnwrapper<R, Visitor, V1> Unwrapper;
2496 Unwrapper unwrapper(v, arg1);
2497 return apply(unwrapper, arg2, arg3, arg4, arg5);
2498 }
2499
2500#endif
2501};
2502
2503#if variant_CPP11_OR_GREATER
2504template <size_t NumVars, typename Visitor, typename... V> struct VisitorImpl {
2505 typedef decltype(std::declval<Visitor>()(
2506 get<0>(static_cast<const V&>(std::declval<V>()))...)) result_type;
2507 typedef VisitorApplicator<result_type> applicator_type;
2508};
2509#endif
2510} // namespace detail
2511
2512#if variant_CPP11_OR_GREATER
2513// No perfect forwarding here in order to simplify code
2514template <typename Visitor, typename... V>
2515inline auto visit(Visitor const& v, V const&... vars) ->
2516 typename detail::VisitorImpl<sizeof...(V), Visitor, V...>::result_type {
2517 typedef detail::VisitorImpl<sizeof...(V), Visitor, V...> impl_type;
2518 return impl_type::applicator_type::apply(v, vars...);
2519}
2520#else
2521
2522template <typename R, typename Visitor, typename V1>
2523inline R visit(const Visitor& v, V1 const& arg1) {
2524 return detail::VisitorApplicator<R>::apply(v, arg1);
2525}
2526
2527template <typename R, typename Visitor, typename V1, typename V2>
2528inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2) {
2529 return detail::VisitorApplicator<R>::apply(v, arg1, arg2);
2530}
2531
2532template <typename R, typename Visitor, typename V1, typename V2, typename V3>
2533inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2,
2534 V3 const& arg3) {
2535 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3);
2536}
2537
2538template <typename R, typename Visitor, typename V1, typename V2, typename V3,
2539 typename V4>
2540inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3,
2541 V4 const& arg4) {
2542 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3, arg4);
2543}
2544
2545template <typename R, typename Visitor, typename V1, typename V2, typename V3,
2546 typename V4, typename V5>
2547inline R visit(const Visitor& v, V1 const& arg1, V2 const& arg2, V3 const& arg3,
2548 V4 const& arg4, V5 const& arg5) {
2549 return detail::VisitorApplicator<R>::apply(v, arg1, arg2, arg3, arg4, arg5);
2550}
2551
2552#endif
2553
2554// 19.7.6 Relational operators
2555
2556namespace detail {
2557
2558template <class Variant> struct Comparator {
2559 static inline bool equal(Variant const& v, Variant const& w) {
2560 switch (v.index()) {
2561 case 0:
2562 return get<0>(v) == get<0>(w);
2563 case 1:
2564 return get<1>(v) == get<1>(w);
2565 case 2:
2566 return get<2>(v) == get<2>(w);
2567 case 3:
2568 return get<3>(v) == get<3>(w);
2569 case 4:
2570 return get<4>(v) == get<4>(w);
2571 case 5:
2572 return get<5>(v) == get<5>(w);
2573 case 6:
2574 return get<6>(v) == get<6>(w);
2575 case 7:
2576 return get<7>(v) == get<7>(w);
2577 case 8:
2578 return get<8>(v) == get<8>(w);
2579 case 9:
2580 return get<9>(v) == get<9>(w);
2581 case 10:
2582 return get<10>(v) == get<10>(w);
2583 case 11:
2584 return get<11>(v) == get<11>(w);
2585 case 12:
2586 return get<12>(v) == get<12>(w);
2587 case 13:
2588 return get<13>(v) == get<13>(w);
2589 case 14:
2590 return get<14>(v) == get<14>(w);
2591 case 15:
2592 return get<15>(v) == get<15>(w);
2593
2594 default:
2595 return false;
2596 }
2597 }
2598
2599 static inline bool less_than(Variant const& v, Variant const& w) {
2600 switch (v.index()) {
2601 case 0:
2602 return get<0>(v) < get<0>(w);
2603 case 1:
2604 return get<1>(v) < get<1>(w);
2605 case 2:
2606 return get<2>(v) < get<2>(w);
2607 case 3:
2608 return get<3>(v) < get<3>(w);
2609 case 4:
2610 return get<4>(v) < get<4>(w);
2611 case 5:
2612 return get<5>(v) < get<5>(w);
2613 case 6:
2614 return get<6>(v) < get<6>(w);
2615 case 7:
2616 return get<7>(v) < get<7>(w);
2617 case 8:
2618 return get<8>(v) < get<8>(w);
2619 case 9:
2620 return get<9>(v) < get<9>(w);
2621 case 10:
2622 return get<10>(v) < get<10>(w);
2623 case 11:
2624 return get<11>(v) < get<11>(w);
2625 case 12:
2626 return get<12>(v) < get<12>(w);
2627 case 13:
2628 return get<13>(v) < get<13>(w);
2629 case 14:
2630 return get<14>(v) < get<14>(w);
2631 case 15:
2632 return get<15>(v) < get<15>(w);
2633
2634 default:
2635 return false;
2636 }
2637 }
2638};
2639
2640} // namespace detail
2641
2642template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2643 class T7, class T8, class T9, class T10, class T11, class T12,
2644 class T13, class T14, class T15>
2645inline bool operator==(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2646 T12, T13, T14, T15> const& v,
2647 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2648 T12, T13, T14, T15> const& w) {
2649 if (v.index() != w.index())
2650 return false;
2651 else if (v.valueless_by_exception())
2652 return true;
2653 else
2654 return detail::Comparator<
2655 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
2656 T14, T15>>::equal(v, w);
2657}
2658
2659template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2660 class T7, class T8, class T9, class T10, class T11, class T12,
2661 class T13, class T14, class T15>
2662inline bool operator!=(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2663 T12, T13, T14, T15> const& v,
2664 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2665 T12, T13, T14, T15> const& w) {
2666 return !(v == w);
2667}
2668
2669template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2670 class T7, class T8, class T9, class T10, class T11, class T12,
2671 class T13, class T14, class T15>
2672inline bool operator<(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2673 T12, T13, T14, T15> const& v,
2674 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2675 T12, T13, T14, T15> const& w) {
2676 if (w.valueless_by_exception())
2677 return false;
2678 else if (v.valueless_by_exception())
2679 return true;
2680 else if (v.index() < w.index())
2681 return true;
2682 else if (v.index() > w.index())
2683 return false;
2684 else
2685 return detail::Comparator<
2686 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13,
2687 T14, T15>>::less_than(v, w);
2688}
2689
2690template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2691 class T7, class T8, class T9, class T10, class T11, class T12,
2692 class T13, class T14, class T15>
2693inline bool operator>(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2694 T12, T13, T14, T15> const& v,
2695 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2696 T12, T13, T14, T15> const& w) {
2697 return w < v;
2698}
2699
2700template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2701 class T7, class T8, class T9, class T10, class T11, class T12,
2702 class T13, class T14, class T15>
2703inline bool operator<=(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2704 T12, T13, T14, T15> const& v,
2705 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2706 T12, T13, T14, T15> const& w) {
2707 return !(v > w);
2708}
2709
2710template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2711 class T7, class T8, class T9, class T10, class T11, class T12,
2712 class T13, class T14, class T15>
2713inline bool operator>=(variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2714 T12, T13, T14, T15> const& v,
2715 variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2716 T12, T13, T14, T15> const& w) {
2717 return !(v < w);
2718}
2719
2720} // namespace variants
2721
2722using namespace variants;
2723
2724} // namespace nonstd
2725
2726#if variant_CPP11_OR_GREATER
2727
2728// 19.7.12 Hash support
2729
2730namespace std {
2731
2732template <> struct hash<nonstd::monostate> {
2733 std::size_t operator()(nonstd::monostate) const variant_noexcept {
2734 return 42;
2735 }
2736};
2737
2738template <class T0, class T1, class T2, class T3, class T4, class T5, class T6,
2739 class T7, class T8, class T9, class T10, class T11, class T12,
2740 class T13, class T14, class T15>
2741struct hash<nonstd::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,
2742 T12, T13, T14, T15>> {
2743 std::size_t operator()(
2744 nonstd::variant<T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12,
2745 T13, T14, T15> const& v) const variant_noexcept {
2746 namespace nvd = nonstd::variants::detail;
2747
2748 switch (v.index()) {
2749 case 0:
2750 return nvd::hash(0) ^ nvd::hash(get<0>(v));
2751 case 1:
2752 return nvd::hash(1) ^ nvd::hash(get<1>(v));
2753 case 2:
2754 return nvd::hash(2) ^ nvd::hash(get<2>(v));
2755 case 3:
2756 return nvd::hash(3) ^ nvd::hash(get<3>(v));
2757 case 4:
2758 return nvd::hash(4) ^ nvd::hash(get<4>(v));
2759 case 5:
2760 return nvd::hash(5) ^ nvd::hash(get<5>(v));
2761 case 6:
2762 return nvd::hash(6) ^ nvd::hash(get<6>(v));
2763 case 7:
2764 return nvd::hash(7) ^ nvd::hash(get<7>(v));
2765 case 8:
2766 return nvd::hash(8) ^ nvd::hash(get<8>(v));
2767 case 9:
2768 return nvd::hash(9) ^ nvd::hash(get<9>(v));
2769 case 10:
2770 return nvd::hash(10) ^ nvd::hash(get<10>(v));
2771 case 11:
2772 return nvd::hash(11) ^ nvd::hash(get<11>(v));
2773 case 12:
2774 return nvd::hash(12) ^ nvd::hash(get<12>(v));
2775 case 13:
2776 return nvd::hash(13) ^ nvd::hash(get<13>(v));
2777 case 14:
2778 return nvd::hash(14) ^ nvd::hash(get<14>(v));
2779 case 15:
2780 return nvd::hash(15) ^ nvd::hash(get<15>(v));
2781
2782 default:
2783 return 0;
2784 }
2785 }
2786};
2787
2788} // namespace std
2789
2790#endif // variant_CPP11_OR_GREATER
2791
2792#if variant_BETWEEN(variant_COMPILER_MSVC_VER, 1300, 1900)
2793#pragma warning(pop)
2794#endif
2795
2796#endif // variant_USES_STD_VARIANT
2797
2798#endif // NONSTD_VARIANT_LITE_HPP
2799//
2800// Copyright (c) 2014-2018 Martin Moene
2801//
2802// https://github.com/martinmoene/optional-lite
2803//
2804// Distributed under the Boost Software License, Version 1.0.
2805// (See accompanying file LICENSE.txt or copy at
2806// http://www.boost.org/LICENSE_1_0.txt)
2807
2808#pragma once
2809
2810#ifndef NONSTD_OPTIONAL_LITE_HPP
2811#define NONSTD_OPTIONAL_LITE_HPP
2812
2813#define optional_lite_MAJOR 3
2814#define optional_lite_MINOR 2
2815#define optional_lite_PATCH 0
2816
2817#define optional_lite_VERSION \
2818 optional_STRINGIFY(optional_lite_MAJOR) "." optional_STRINGIFY( \
2819 optional_lite_MINOR) "." optional_STRINGIFY(optional_lite_PATCH)
2820
2821#define optional_STRINGIFY(x) optional_STRINGIFY_(x)
2822#define optional_STRINGIFY_(x) #x
2823
2824// optional-lite configuration:
2825
2826#define optional_OPTIONAL_DEFAULT 0
2827#define optional_OPTIONAL_NONSTD 1
2828#define optional_OPTIONAL_STD 2
2829
2830#if !defined(optional_CONFIG_SELECT_OPTIONAL)
2831#define optional_CONFIG_SELECT_OPTIONAL \
2832 (optional_HAVE_STD_OPTIONAL ? optional_OPTIONAL_STD \
2833 : optional_OPTIONAL_NONSTD)
2834#endif
2835
2836// Control presence of exception handling (try and auto discover):
2837
2838#ifndef optional_CONFIG_NO_EXCEPTIONS
2839#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)
2840#define optional_CONFIG_NO_EXCEPTIONS 0
2841#else
2842#define optional_CONFIG_NO_EXCEPTIONS 1
2843#endif
2844#endif
2845
2846// C++ language version detection (C++20 is speculative):
2847// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
2848
2849#ifndef optional_CPLUSPLUS
2850#if defined(_MSVC_LANG) && !defined(__clang__)
2851#define optional_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
2852#else
2853#define optional_CPLUSPLUS __cplusplus
2854#endif
2855#endif
2856
2857#define optional_CPP98_OR_GREATER (optional_CPLUSPLUS >= 199711L)
2858#define optional_CPP11_OR_GREATER (optional_CPLUSPLUS >= 201103L)
2859#define optional_CPP11_OR_GREATER_ (optional_CPLUSPLUS >= 201103L)
2860#define optional_CPP14_OR_GREATER (optional_CPLUSPLUS >= 201402L)
2861#define optional_CPP17_OR_GREATER (optional_CPLUSPLUS >= 201703L)
2862#define optional_CPP20_OR_GREATER (optional_CPLUSPLUS >= 202000L)
2863
2864// C++ language version (represent 98 as 3):
2865
2866#define optional_CPLUSPLUS_V \
2867 (optional_CPLUSPLUS / 100 - (optional_CPLUSPLUS > 200000 ? 2000 : 1994))
2868
2869// Use C++17 std::optional if available and requested:
2870
2871#if optional_CPP17_OR_GREATER && defined(__has_include)
2872#if __has_include(<optional> )
2873#define optional_HAVE_STD_OPTIONAL 1
2874#else
2875#define optional_HAVE_STD_OPTIONAL 0
2876#endif
2877#else
2878#define optional_HAVE_STD_OPTIONAL 0
2879#endif
2880
2881#define optional_USES_STD_OPTIONAL \
2882 ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_STD) || \
2883 ((optional_CONFIG_SELECT_OPTIONAL == optional_OPTIONAL_DEFAULT) && \
2884 optional_HAVE_STD_OPTIONAL))
2885
2886//
2887// in_place: code duplicated in any-lite, expected-lite, optional-lite,
2888// value-ptr-lite, variant-lite:
2889//
2890
2891#ifndef nonstd_lite_HAVE_IN_PLACE_TYPES
2892#define nonstd_lite_HAVE_IN_PLACE_TYPES 1
2893
2894// C++17 std::in_place in <utility>:
2895
2896#if optional_CPP17_OR_GREATER
2897
2898#include <utility>
2899
2900namespace nonstd {
2901
2902using std::in_place;
2903using std::in_place_index;
2904using std::in_place_index_t;
2905using std::in_place_t;
2906using std::in_place_type;
2907using std::in_place_type_t;
2908
2909#define nonstd_lite_in_place_t(T) std::in_place_t
2910#define nonstd_lite_in_place_type_t(T) std::in_place_type_t<T>
2911#define nonstd_lite_in_place_index_t(K) std::in_place_index_t<K>
2912
2913#define nonstd_lite_in_place(T) \
2914 std::in_place_t {}
2915#define nonstd_lite_in_place_type(T) \
2916 std::in_place_type_t<T> {}
2917#define nonstd_lite_in_place_index(K) \
2918 std::in_place_index_t<K> {}
2919
2920} // namespace nonstd
2921
2922#else // optional_CPP17_OR_GREATER
2923
2924#include <cstddef>
2925
2926namespace nonstd {
2927namespace detail {
2928
2929template <class T> struct in_place_type_tag {};
2930
2931template <std::size_t K> struct in_place_index_tag {};
2932
2933} // namespace detail
2934
2935struct in_place_t {};
2936
2937template <class T>
2938inline in_place_t in_place(
2940 return in_place_t();
2941}
2942
2943template <std::size_t K>
2944inline in_place_t in_place(detail::in_place_index_tag<K> /*unused*/ =
2946 return in_place_t();
2947}
2948
2949template <class T>
2950inline in_place_t in_place_type(
2952 return in_place_t();
2953}
2954
2955template <std::size_t K>
2956inline in_place_t in_place_index(detail::in_place_index_tag<K> /*unused*/ =
2958 return in_place_t();
2959}
2960
2961// mimic templated typedef:
2962
2963#define nonstd_lite_in_place_t(T) \
2964 nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag<T>)
2965#define nonstd_lite_in_place_type_t(T) \
2966 nonstd::in_place_t (&)(nonstd::detail::in_place_type_tag<T>)
2967#define nonstd_lite_in_place_index_t(K) \
2968 nonstd::in_place_t (&)(nonstd::detail::in_place_index_tag<K>)
2969
2970#define nonstd_lite_in_place(T) nonstd::in_place_type<T>
2971#define nonstd_lite_in_place_type(T) nonstd::in_place_type<T>
2972#define nonstd_lite_in_place_index(K) nonstd::in_place_index<K>
2973
2974} // namespace nonstd
2975
2976#endif // optional_CPP17_OR_GREATER
2977#endif // nonstd_lite_HAVE_IN_PLACE_TYPES
2978
2979//
2980// Using std::optional:
2981//
2982
2983#if optional_USES_STD_OPTIONAL
2984
2985#include <optional>
2986
2987namespace nonstd {
2988
2989using std::bad_optional_access;
2990using std::hash;
2991using std::optional;
2992
2993using std::nullopt;
2994using std::nullopt_t;
2995
2996using std::operator==;
2997using std::operator!=;
2998using std::operator<;
2999using std::operator<=;
3000using std::operator>;
3001using std::operator>=;
3002using std::make_optional;
3003using std::swap;
3004} // namespace nonstd
3005
3006#else // optional_USES_STD_OPTIONAL
3007
3008#include <cassert>
3009#include <utility>
3010
3011// optional-lite alignment configuration:
3012
3013#ifndef optional_CONFIG_MAX_ALIGN_HACK
3014#define optional_CONFIG_MAX_ALIGN_HACK 0
3015#endif
3016
3017#ifndef optional_CONFIG_ALIGN_AS
3018// no default, used in #if defined()
3019#endif
3020
3021#ifndef optional_CONFIG_ALIGN_AS_FALLBACK
3022#define optional_CONFIG_ALIGN_AS_FALLBACK double
3023#endif
3024
3025// Compiler warning suppression:
3026
3027#if defined(__clang__)
3028#pragma clang diagnostic push
3029#pragma clang diagnostic ignored "-Wundef"
3030#elif defined(__GNUC__)
3031#pragma GCC diagnostic push
3032#pragma GCC diagnostic ignored "-Wundef"
3033#elif defined(_MSC_VER)
3034#pragma warning(push)
3035#endif
3036
3037// half-open range [lo..hi):
3038#define optional_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
3039
3040// Compiler versions:
3041//
3042// MSVC++ 6.0 _MSC_VER == 1200 optional_COMPILER_MSVC_VERSION == 60 (Visual
3043// Studio 6.0) MSVC++ 7.0 _MSC_VER == 1300 optional_COMPILER_MSVC_VERSION ==
3044// 70 (Visual Studio .NET 2002) MSVC++ 7.1 _MSC_VER == 1310
3045// optional_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) MSVC++ 8.0
3046// _MSC_VER == 1400 optional_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
3047// MSVC++ 9.0 _MSC_VER == 1500 optional_COMPILER_MSVC_VERSION == 90 (Visual
3048// Studio 2008) MSVC++ 10.0 _MSC_VER == 1600 optional_COMPILER_MSVC_VERSION ==
3049// 100 (Visual Studio 2010) MSVC++ 11.0 _MSC_VER == 1700
3050// optional_COMPILER_MSVC_VERSION == 110 (Visual Studio 2012) MSVC++ 12.0
3051// _MSC_VER == 1800 optional_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013)
3052// MSVC++ 14.0 _MSC_VER == 1900 optional_COMPILER_MSVC_VERSION == 140 (Visual
3053// Studio 2015) MSVC++ 14.1 _MSC_VER >= 1910 optional_COMPILER_MSVC_VERSION ==
3054// 141 (Visual Studio 2017) MSVC++ 14.2 _MSC_VER >= 1920
3055// optional_COMPILER_MSVC_VERSION == 142 (Visual Studio 2019)
3056
3057#if defined(_MSC_VER) && !defined(__clang__)
3058#define optional_COMPILER_MSVC_VER (_MSC_VER)
3059#define optional_COMPILER_MSVC_VERSION \
3060 (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
3061#else
3062#define optional_COMPILER_MSVC_VER 0
3063#define optional_COMPILER_MSVC_VERSION 0
3064#endif
3065
3066#define optional_COMPILER_VERSION(major, minor, patch) \
3067 (10 * (10 * (major) + (minor)) + (patch))
3068
3069#if defined(__GNUC__) && !defined(__clang__)
3070#define optional_COMPILER_GNUC_VERSION \
3071 optional_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
3072#else
3073#define optional_COMPILER_GNUC_VERSION 0
3074#endif
3075
3076#if defined(__clang__)
3077#define optional_COMPILER_CLANG_VERSION \
3078 optional_COMPILER_VERSION(__clang_major__, __clang_minor__, \
3079 __clang_patchlevel__)
3080#else
3081#define optional_COMPILER_CLANG_VERSION 0
3082#endif
3083
3084#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 140)
3085#pragma warning(disable : 4345) // initialization behavior changed
3086#endif
3087
3088#if optional_BETWEEN(optional_COMPILER_MSVC_VERSION, 70, 150)
3089#pragma warning(disable : 4814) // in C++14 'constexpr' will not imply 'const'
3090#endif
3091
3092// Presence of language and library features:
3093
3094#define optional_HAVE(FEATURE) (optional_HAVE_##FEATURE)
3095
3096#ifdef _HAS_CPP0X
3097#define optional_HAS_CPP0X _HAS_CPP0X
3098#else
3099#define optional_HAS_CPP0X 0
3100#endif
3101
3102// Unless defined otherwise below, consider VC14 as C++11 for optional-lite:
3103
3104#if optional_COMPILER_MSVC_VER >= 1900
3105#undef optional_CPP11_OR_GREATER
3106#define optional_CPP11_OR_GREATER 1
3107#endif
3108
3109#define optional_CPP11_90 \
3110 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1500)
3111#define optional_CPP11_100 \
3112 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1600)
3113#define optional_CPP11_110 \
3114 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1700)
3115#define optional_CPP11_120 \
3116 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1800)
3117#define optional_CPP11_140 \
3118 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1900)
3119#define optional_CPP11_141 \
3120 (optional_CPP11_OR_GREATER_ || optional_COMPILER_MSVC_VER >= 1910)
3121
3122#define optional_CPP11_140_490 \
3123 ((optional_CPP11_OR_GREATER_ && optional_COMPILER_GNUC_VERSION >= 490) || \
3124 (optional_COMPILER_MSVC_VER >= 1910))
3125
3126#define optional_CPP14_000 (optional_CPP14_OR_GREATER)
3127#define optional_CPP17_000 (optional_CPP17_OR_GREATER)
3128
3129// Presence of C++11 language features:
3130
3131#define optional_HAVE_CONSTEXPR_11 optional_CPP11_140
3132#define optional_HAVE_IS_DEFAULT optional_CPP11_140
3133#define optional_HAVE_NOEXCEPT optional_CPP11_140
3134#define optional_HAVE_NULLPTR optional_CPP11_100
3135#define optional_HAVE_REF_QUALIFIER optional_CPP11_140_490
3136#define optional_HAVE_INITIALIZER_LIST optional_CPP11_140
3137
3138// Presence of C++14 language features:
3139
3140#define optional_HAVE_CONSTEXPR_14 optional_CPP14_000
3141
3142// Presence of C++17 language features:
3143
3144#define optional_HAVE_NODISCARD optional_CPP17_000
3145
3146// Presence of C++ library features:
3147
3148#define optional_HAVE_CONDITIONAL optional_CPP11_120
3149#define optional_HAVE_REMOVE_CV optional_CPP11_120
3150#define optional_HAVE_TYPE_TRAITS optional_CPP11_90
3151
3152#define optional_HAVE_TR1_TYPE_TRAITS (!!optional_COMPILER_GNUC_VERSION)
3153#define optional_HAVE_TR1_ADD_POINTER (!!optional_COMPILER_GNUC_VERSION)
3154
3155// C++ feature usage:
3156
3157#if optional_HAVE(CONSTEXPR_11)
3158#define optional_constexpr constexpr
3159#else
3160#define optional_constexpr /*constexpr*/
3161#endif
3162
3163#if optional_HAVE(IS_DEFAULT)
3164#define optional_is_default = default;
3165#else
3166#define optional_is_default \
3167 { \
3168 }
3169#endif
3170
3171#if optional_HAVE(CONSTEXPR_14)
3172#define optional_constexpr14 constexpr
3173#else
3174#define optional_constexpr14 /*constexpr*/
3175#endif
3176
3177#if optional_HAVE(NODISCARD)
3178#define optional_nodiscard [[nodiscard]]
3179#else
3180#define optional_nodiscard /*[[nodiscard]]*/
3181#endif
3182
3183#if optional_HAVE(NOEXCEPT)
3184#define optional_noexcept noexcept
3185#else
3186#define optional_noexcept /*noexcept*/
3187#endif
3188
3189#if optional_HAVE(NULLPTR)
3190#define optional_nullptr nullptr
3191#else
3192#define optional_nullptr NULL
3193#endif
3194
3195#if optional_HAVE(REF_QUALIFIER)
3196// NOLINTNEXTLINE( bugprone-macro-parentheses )
3197#define optional_ref_qual &
3198#define optional_refref_qual &&
3199#else
3200#define optional_ref_qual /*&*/
3201#define optional_refref_qual /*&&*/
3202#endif
3203
3204// additional includes:
3205
3206#if optional_CONFIG_NO_EXCEPTIONS
3207// already included: <cassert>
3208#else
3209#include <stdexcept>
3210#endif
3211
3212#if optional_CPP11_OR_GREATER
3213#include <functional>
3214#endif
3215
3216#if optional_HAVE(INITIALIZER_LIST)
3217#include <initializer_list>
3218#endif
3219
3220#if optional_HAVE(TYPE_TRAITS)
3221#include <type_traits>
3222#elif optional_HAVE(TR1_TYPE_TRAITS)
3223#include <tr1/type_traits>
3224#endif
3225
3226// Method enabling
3227
3228#if optional_CPP11_OR_GREATER
3229
3230#define optional_REQUIRES_0(...) \
3231 template <bool B = (__VA_ARGS__), typename std::enable_if<B, int>::type = 0>
3232
3233#define optional_REQUIRES_T(...) \
3234 , typename std::enable_if<(__VA_ARGS__), int>::type = 0
3235
3236#define optional_REQUIRES_R(R, ...) \
3237 typename std::enable_if<(__VA_ARGS__), R>::type
3238
3239#define optional_REQUIRES_A(...) \
3240 , typename std::enable_if<(__VA_ARGS__), void*>::type = nullptr
3241
3242#endif
3243
3244//
3245// optional:
3246//
3247
3248namespace nonstd {
3249namespace optional_lite {
3250
3251namespace std11 {
3252
3253#if optional_CPP11_OR_GREATER
3254using std::move;
3255#else
3256template <typename T> T& move(T& t) {
3257 return t;
3258}
3259#endif
3260
3261#if optional_HAVE(CONDITIONAL)
3262using std::conditional;
3263#else
3264template <bool B, typename T, typename F> struct conditional {
3265 typedef T type;
3266};
3267template <typename T, typename F> struct conditional<false, T, F> {
3268 typedef F type;
3269};
3270#endif // optional_HAVE_CONDITIONAL
3271
3272// gcc < 5:
3273#if optional_CPP11_OR_GREATER
3274#if optional_BETWEEN(optional_COMPILER_GNUC_VERSION, 1, 500)
3275template <typename T>
3276struct is_trivially_copy_constructible : std::true_type {};
3277template <typename T>
3278struct is_trivially_move_constructible : std::true_type {};
3279#else
3280using std::is_trivially_copy_constructible;
3281using std::is_trivially_move_constructible;
3282#endif
3283#endif
3284} // namespace std11
3285
3286#if optional_CPP11_OR_GREATER
3287
3289
3290namespace std17 {
3291
3292#if optional_CPP17_OR_GREATER
3293
3294using std::is_nothrow_swappable;
3295using std::is_swappable;
3296
3297#elif optional_CPP11_OR_GREATER
3298
3299namespace detail {
3300
3301using std::swap;
3302
3303struct is_swappable {
3304 template <typename T,
3305 typename = decltype(swap(std::declval<T&>(), std::declval<T&>()))>
3306 static std::true_type test(int /*unused*/);
3307
3308 template <typename> static std::false_type test(...);
3309};
3310
3311struct is_nothrow_swappable {
3312 // wrap noexcept(expr) in separate function as work-around for VC140
3313 // (VS2015):
3314
3315 template <typename T> static constexpr bool satisfies() {
3316 return noexcept(swap(std::declval<T&>(), std::declval<T&>()));
3317 }
3318
3319 template <typename T>
3320 static auto test(int /*unused*/)
3321 -> std::integral_constant<bool, satisfies<T>()> {}
3322
3323 template <typename> static auto test(...) -> std::false_type;
3324};
3325
3326} // namespace detail
3327
3328// is [nothow] swappable:
3329
3330template <typename T>
3331struct is_swappable : decltype(detail::is_swappable::test<T>(0)) {};
3332
3333template <typename T>
3334struct is_nothrow_swappable
3335 : decltype(detail::is_nothrow_swappable::test<T>(0)) {};
3336
3337#endif // optional_CPP17_OR_GREATER
3338
3339} // namespace std17
3340
3342
3343namespace std20 {
3344
3345template <typename T> struct remove_cvref {
3346 typedef
3347 typename std::remove_cv<typename std::remove_reference<T>::type>::type
3348 type;
3349};
3350
3351} // namespace std20
3352
3353#endif // optional_CPP11_OR_GREATER
3354
3356
3357template <typename T> class optional;
3358
3359namespace detail {
3360
3361// C++11 emulation:
3362
3363struct nulltype {};
3364
3365template <typename Head, typename Tail> struct typelist {
3366 typedef Head head;
3367 typedef Tail tail;
3368};
3369
3370#if optional_CONFIG_MAX_ALIGN_HACK
3371
3372// Max align, use most restricted type for alignment:
3373
3374#define optional_UNIQUE(name) optional_UNIQUE2(name, __LINE__)
3375#define optional_UNIQUE2(name, line) optional_UNIQUE3(name, line)
3376#define optional_UNIQUE3(name, line) name##line
3377
3378#define optional_ALIGN_TYPE(type) \
3379 type optional_UNIQUE(_t); \
3380 struct_t<type> optional_UNIQUE(_st)
3381
3382template <typename T> struct struct_t {
3383 T _;
3384};
3385
3386union max_align_t {
3387 optional_ALIGN_TYPE(char);
3388 optional_ALIGN_TYPE(short int);
3389 optional_ALIGN_TYPE(int);
3390 optional_ALIGN_TYPE(long int);
3391 optional_ALIGN_TYPE(float);
3392 optional_ALIGN_TYPE(double);
3393 optional_ALIGN_TYPE(long double);
3394 optional_ALIGN_TYPE(char*);
3395 optional_ALIGN_TYPE(short int*);
3396 optional_ALIGN_TYPE(int*);
3397 optional_ALIGN_TYPE(long int*);
3398 optional_ALIGN_TYPE(float*);
3399 optional_ALIGN_TYPE(double*);
3400 optional_ALIGN_TYPE(long double*);
3401 optional_ALIGN_TYPE(void*);
3402
3403#ifdef HAVE_LONG_LONG
3404 optional_ALIGN_TYPE(long long);
3405#endif
3406
3407 struct Unknown;
3408
3409 Unknown (*optional_UNIQUE(_))(Unknown);
3410 Unknown* Unknown::* optional_UNIQUE(_);
3411 Unknown (Unknown::* optional_UNIQUE(_))(Unknown);
3412
3413 struct_t<Unknown (*)(Unknown)> optional_UNIQUE(_);
3414 struct_t<Unknown * Unknown::*> optional_UNIQUE(_);
3415 struct_t<Unknown (Unknown::*)(Unknown)> optional_UNIQUE(_);
3416};
3417
3418#undef optional_UNIQUE
3419#undef optional_UNIQUE2
3420#undef optional_UNIQUE3
3421
3422#undef optional_ALIGN_TYPE
3423
3424#elif defined(optional_CONFIG_ALIGN_AS) // optional_CONFIG_MAX_ALIGN_HACK
3425
3426// Use user-specified type for alignment:
3427
3428#define optional_ALIGN_AS(unused) optional_CONFIG_ALIGN_AS
3429
3430#else // optional_CONFIG_MAX_ALIGN_HACK
3431
3432// Determine POD type to use for alignment:
3433
3434#define optional_ALIGN_AS(to_align) \
3435 typename type_of_size<alignment_types, alignment_of<to_align>::value>::type
3436
3437template <typename T> struct alignment_of;
3438
3439template <typename T> struct alignment_of_hack {
3440 char c;
3441 T t;
3442 alignment_of_hack();
3443};
3444
3445template <size_t A, size_t S> struct alignment_logic {
3446 enum { value = A < S ? A : S };
3447};
3448
3449template <typename T> struct alignment_of {
3450 enum {
3451 value = alignment_logic<sizeof(alignment_of_hack<T>) - sizeof(T),
3452 sizeof(T)>::value
3453 };
3454};
3455
3456template <typename List, size_t N> struct type_of_size {
3457 typedef typename std11::conditional<
3458 N == sizeof(typename List::head), typename List::head,
3459 typename type_of_size<typename List::tail, N>::type>::type type;
3460};
3461
3462template <size_t N> struct type_of_size<nulltype, N> {
3463 typedef optional_CONFIG_ALIGN_AS_FALLBACK type;
3464};
3465
3466template <typename T> struct struct_t {
3467 T _;
3468};
3469
3470#define optional_ALIGN_TYPE(type) typelist < type, typelist < struct_t<type>
3471
3472struct Unknown;
3473
3474typedef optional_ALIGN_TYPE(char), optional_ALIGN_TYPE(short),
3475 optional_ALIGN_TYPE(int), optional_ALIGN_TYPE(long),
3476 optional_ALIGN_TYPE(float), optional_ALIGN_TYPE(double),
3477 optional_ALIGN_TYPE(long double),
3478
3479 optional_ALIGN_TYPE(char*), optional_ALIGN_TYPE(short*),
3480 optional_ALIGN_TYPE(int*), optional_ALIGN_TYPE(long*),
3481 optional_ALIGN_TYPE(float*), optional_ALIGN_TYPE(double*),
3482 optional_ALIGN_TYPE(long double*),
3483
3484 optional_ALIGN_TYPE(Unknown (*)(Unknown)),
3485 optional_ALIGN_TYPE(Unknown* Unknown::*),
3486 optional_ALIGN_TYPE(Unknown (Unknown::*)(Unknown)),
3487
3488 nulltype >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> alignment_types;
3489
3490#undef optional_ALIGN_TYPE
3491
3492#endif // optional_CONFIG_MAX_ALIGN_HACK
3493
3495
3496template <typename T> union storage_t {
3497 // private:
3498 // template< typename > friend class optional;
3499
3500 typedef T value_type;
3501
3502 storage_t() optional_is_default
3503
3504 explicit storage_t(value_type const& v) {
3505 construct_value(v);
3506 }
3507
3508 void construct_value(value_type const& v) {
3509 ::new (value_ptr()) value_type(v);
3510 }
3511
3512#if optional_CPP11_OR_GREATER
3513
3514 explicit storage_t(value_type&& v) { construct_value(std::move(v)); }
3515
3516 void construct_value(value_type&& v) {
3517 ::new (value_ptr()) value_type(std::move(v));
3518 }
3519
3520 template <class... Args> void emplace(Args&&... args) {
3521 ::new (value_ptr()) value_type(std::forward<Args>(args)...);
3522 }
3523
3524 template <class U, class... Args>
3525 void emplace(std::initializer_list<U> il, Args&&... args) {
3526 ::new (value_ptr()) value_type(il, std::forward<Args>(args)...);
3527 }
3528
3529#endif
3530
3531 void destruct_value() { value_ptr()->~T(); }
3532
3533 optional_nodiscard value_type const* value_ptr() const {
3534 return as<value_type>();
3535 }
3536
3537 value_type* value_ptr() { return as<value_type>(); }
3538
3539 optional_nodiscard value_type const& value() const optional_ref_qual {
3540 return *value_ptr();
3541 }
3542
3543 value_type& value() optional_ref_qual { return *value_ptr(); }
3544
3545#if optional_HAVE(REF_QUALIFIER)
3546
3547 optional_nodiscard value_type const&& value() const optional_refref_qual {
3548 return std::move(value());
3549 }
3550
3551 value_type&& value() optional_refref_qual { return std::move(value()); }
3552
3553#endif
3554
3555#if optional_CPP11_OR_GREATER
3556
3557 using aligned_storage_t =
3558 typename std::aligned_storage<sizeof(value_type),
3559 alignof(value_type)>::type;
3560 aligned_storage_t data;
3561
3562#elif optional_CONFIG_MAX_ALIGN_HACK
3563
3564 typedef struct {
3565 unsigned char data[sizeof(value_type)];
3566 } aligned_storage_t;
3567
3568 max_align_t hack;
3569 aligned_storage_t data;
3570
3571#else
3572 typedef optional_ALIGN_AS(value_type) align_as_type;
3573
3574 typedef struct {
3575 align_as_type
3576 data[1 + (sizeof(value_type) - 1) / sizeof(align_as_type)];
3577 } aligned_storage_t;
3578 aligned_storage_t data;
3579
3580#undef optional_ALIGN_AS
3581
3582#endif // optional_CONFIG_MAX_ALIGN_HACK
3583
3584 optional_nodiscard void* ptr() optional_noexcept { return &data; }
3585
3586 optional_nodiscard void const* ptr() const optional_noexcept {
3587 return &data;
3588 }
3589
3590 template <typename U> optional_nodiscard U* as() {
3591 return reinterpret_cast<U*>(ptr());
3592 }
3593
3594 template <typename U> optional_nodiscard U const* as() const {
3595 return reinterpret_cast<U const*>(ptr());
3596 }
3597};
3598
3599} // namespace detail
3600
3602
3603struct nullopt_t {
3604 struct init {};
3605 explicit optional_constexpr nullopt_t(init /*unused*/) optional_noexcept {}
3606};
3607
3608#if optional_HAVE(CONSTEXPR_11)
3609constexpr nullopt_t nullopt{nullopt_t::init{}};
3610#else
3611// extra parenthesis to prevent the most vexing parse:
3612const nullopt_t nullopt((nullopt_t::init()));
3613#endif
3614
3616
3617#if !optional_CONFIG_NO_EXCEPTIONS
3618
3619class bad_optional_access : public std::logic_error {
3620 public:
3621 explicit bad_optional_access() : logic_error("bad optional access") {}
3622};
3623
3624#endif // optional_CONFIG_NO_EXCEPTIONS
3625
3627
3628template <typename T> class optional {
3629 private:
3630 template <typename> friend class optional;
3631
3632 typedef void (optional::*safe_bool)() const;
3633
3634 public:
3635 typedef T value_type;
3636
3637 // x.x.3.1, constructors
3638
3639 // 1a - default construct
3640 optional_constexpr optional() optional_noexcept : has_value_(false),
3641 contained() {}
3642
3643 // 1b - construct explicitly empty
3644 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
3645 optional_constexpr optional(nullopt_t /*unused*/) optional_noexcept
3646 : has_value_(false),
3647 contained() {}
3648
3649 // 2 - copy-construct
3650#if optional_CPP11_OR_GREATER
3651 // template< typename U = T
3652 // optional_REQUIRES_T(
3653 // std::is_copy_constructible<U>::value
3654 // || std11::is_trivially_copy_constructible<U>::value
3655 // )
3656 // >
3657#endif
3658 optional_constexpr14 optional(optional const& other)
3659 : has_value_(other.has_value()) {
3660 if (other.has_value()) {
3661 contained.construct_value(other.contained.value());
3662 }
3663 }
3664
3665#if optional_CPP11_OR_GREATER
3666
3667 // 3 (C++11) - move-construct from optional
3668 template <typename U = T optional_REQUIRES_T(
3669 std::is_move_constructible<U>::value ||
3670 std11::is_trivially_move_constructible<U>::value)>
3671 optional_constexpr14 optional(optional&& other)
3672 // NOLINTNEXTLINE( performance-noexcept-move-constructor )
3673 noexcept(std::is_nothrow_move_constructible<T>::value)
3674 : has_value_(other.has_value()) {
3675 if (other.has_value()) {
3676 contained.construct_value(std::move(other.contained.value()));
3677 }
3678 }
3679
3680 // 4a (C++11) - explicit converting copy-construct from optional
3681 template <typename U optional_REQUIRES_T(
3682 std::is_constructible<T, U const&>::value &&
3683 !std::is_constructible<T, optional<U>&>::value &&
3684 !std::is_constructible<T, optional<U>&&>::value &&
3685 !std::is_constructible<T, optional<U> const&>::value &&
3686 !std::is_constructible<T, optional<U> const&&>::value &&
3687 !std::is_convertible<optional<U>&, T>::value &&
3688 !std::is_convertible<optional<U>&&, T>::value &&
3689 !std::is_convertible<optional<U> const&, T>::value &&
3690 !std::is_convertible<optional<U> const&&, T>::value &&
3691 !std::is_convertible<U const&, T>::value /*=> explicit
3692 */
3693 )>
3694 explicit optional(optional<U> const& other)
3695 : has_value_(other.has_value()) {
3696 if (other.has_value()) {
3697 contained.construct_value(T{other.contained.value()});
3698 }
3699 }
3700#endif // optional_CPP11_OR_GREATER
3701
3702 // 4b (C++98 and later) - non-explicit converting copy-construct from
3703 // optional
3704 template <typename U
3705#if optional_CPP11_OR_GREATER
3706 optional_REQUIRES_T(
3707 std::is_constructible<T, U const&>::value &&
3708 !std::is_constructible<T, optional<U>&>::value &&
3709 !std::is_constructible<T, optional<U>&&>::value &&
3710 !std::is_constructible<T, optional<U> const&>::value &&
3711 !std::is_constructible<T, optional<U> const&&>::value &&
3712 !std::is_convertible<optional<U>&, T>::value &&
3713 !std::is_convertible<optional<U>&&, T>::value &&
3714 !std::is_convertible<optional<U> const&, T>::value &&
3715 !std::is_convertible<optional<U> const&&, T>::value &&
3716 std::is_convertible<U const&, T>::value /*=> non-explicit
3717 */
3718 )
3719#endif // optional_CPP11_OR_GREATER
3720 >
3721 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
3722 /*non-explicit*/ optional(optional<U> const& other)
3723 : has_value_(other.has_value()) {
3724 if (other.has_value()) {
3725 contained.construct_value(other.contained.value());
3726 }
3727 }
3728
3729#if optional_CPP11_OR_GREATER
3730
3731 // 5a (C++11) - explicit converting move-construct from optional
3732 template <typename U optional_REQUIRES_T(
3733 std::is_constructible<T, U&&>::value &&
3734 !std::is_constructible<T, optional<U>&>::value &&
3735 !std::is_constructible<T, optional<U>&&>::value &&
3736 !std::is_constructible<T, optional<U> const&>::value &&
3737 !std::is_constructible<T, optional<U> const&&>::value &&
3738 !std::is_convertible<optional<U>&, T>::value &&
3739 !std::is_convertible<optional<U>&&, T>::value &&
3740 !std::is_convertible<optional<U> const&, T>::value &&
3741 !std::is_convertible<optional<U> const&&, T>::value &&
3742 !std::is_convertible<U&&, T>::value /*=> explicit */
3743 )>
3744 explicit optional(optional<U>&& other) : has_value_(other.has_value()) {
3745 if (other.has_value()) {
3746 contained.construct_value(T{std::move(other.contained.value())});
3747 }
3748 }
3749
3750 // 5a (C++11) - non-explicit converting move-construct from optional
3751 template <typename U optional_REQUIRES_T(
3752 std::is_constructible<T, U&&>::value &&
3753 !std::is_constructible<T, optional<U>&>::value &&
3754 !std::is_constructible<T, optional<U>&&>::value &&
3755 !std::is_constructible<T, optional<U> const&>::value &&
3756 !std::is_constructible<T, optional<U> const&&>::value &&
3757 !std::is_convertible<optional<U>&, T>::value &&
3758 !std::is_convertible<optional<U>&&, T>::value &&
3759 !std::is_convertible<optional<U> const&, T>::value &&
3760 !std::is_convertible<optional<U> const&&, T>::value &&
3761 std::is_convertible<U&&, T>::value /*=> non-explicit */
3762 )>
3763 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
3764 /*non-explicit*/ optional(optional<U>&& other)
3765 : has_value_(other.has_value()) {
3766 if (other.has_value()) {
3767 contained.construct_value(std::move(other.contained.value()));
3768 }
3769 }
3770
3771 // 6 (C++11) - in-place construct
3772 template <typename... Args optional_REQUIRES_T(
3773 std::is_constructible<T, Args&&...>::value)>
3774 optional_constexpr explicit optional(nonstd_lite_in_place_t(T),
3775 Args&&... args)
3776 : has_value_(true), contained(T(std::forward<Args>(args)...)) {}
3777
3778 // 7 (C++11) - in-place construct, initializer-list
3779 template <typename U,
3780 typename... Args optional_REQUIRES_T(
3781 std::is_constructible<T, std::initializer_list<U>&,
3782 Args&&...>::value)>
3783 optional_constexpr explicit optional(nonstd_lite_in_place_t(T),
3784 std::initializer_list<U> il,
3785 Args&&... args)
3786 : has_value_(true), contained(T(il, std::forward<Args>(args)...)) {}
3787
3788 // 8a (C++11) - explicit move construct from value
3789 template <typename U = T optional_REQUIRES_T(
3790 std::is_constructible<T, U&&>::value &&
3791 !std::is_same<typename std20::remove_cvref<U>::type,
3792 nonstd_lite_in_place_t(U)>::value &&
3793 !std::is_same<typename std20::remove_cvref<U>::type,
3794 optional<T>>::value &&
3795 !std::is_convertible<U&&, T>::value /*=> explicit */
3796 )>
3797 optional_constexpr explicit optional(U&& value)
3798 : has_value_(true), contained(T{std::forward<U>(value)}) {}
3799
3800 // 8b (C++11) - non-explicit move construct from value
3801 template <typename U = T optional_REQUIRES_T(
3802 std::is_constructible<T, U&&>::value &&
3803 !std::is_same<typename std20::remove_cvref<U>::type,
3804 nonstd_lite_in_place_t(U)>::value &&
3805 !std::is_same<typename std20::remove_cvref<U>::type,
3806 optional<T>>::value &&
3807 std::is_convertible<U&&, T>::value /*=> non-explicit */
3808 )>
3809 // NOLINTNEXTLINE( google-explicit-constructor, hicpp-explicit-conversions )
3810 optional_constexpr /*non-explicit*/ optional(U&& value)
3811 : has_value_(true), contained(std::forward<U>(value)) {}
3812
3813#else // optional_CPP11_OR_GREATER
3814
3815 // 8 (C++98)
3816 optional(value_type const& value) : has_value_(true), contained(value) {}
3817
3818#endif // optional_CPP11_OR_GREATER
3819
3820 // x.x.3.2, destructor
3821
3822 ~optional() {
3823 if (has_value()) {
3824 contained.destruct_value();
3825 }
3826 }
3827
3828 // x.x.3.3, assignment
3829
3830 // 1 (C++98and later) - assign explicitly empty
3831 optional& operator=(nullopt_t /*unused*/) optional_noexcept {
3832 reset();
3833 return *this;
3834 }
3835
3836 // 2 (C++98and later) - copy-assign from optional
3837#if optional_CPP11_OR_GREATER
3838 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
3839 // misc-unconventional-assign-operator )
3840 optional_REQUIRES_R(optional&, true
3841 // std::is_copy_constructible<T>::value
3842 // && std::is_copy_assignable<T>::value
3843 )
3844 operator=(optional const& other) noexcept(
3845 std::is_nothrow_move_assignable<T>::value &&
3846 std::is_nothrow_move_constructible<T>::value)
3847#else
3848 optional& operator=(optional const& other)
3849#endif
3850 {
3851 if ((has_value() == true) && (other.has_value() == false)) {
3852 reset();
3853 } else if ((has_value() == false) && (other.has_value() == true)) {
3854 initialize(*other);
3855 } else if ((has_value() == true) && (other.has_value() == true)) {
3856 contained.value() = *other;
3857 }
3858 return *this;
3859 }
3860
3861#if optional_CPP11_OR_GREATER
3862
3863 // 3 (C++11) - move-assign from optional
3864 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
3865 // misc-unconventional-assign-operator )
3866 optional_REQUIRES_R(optional&, true
3867 // std::is_move_constructible<T>::value
3868 // && std::is_move_assignable<T>::value
3869 ) operator=(optional && other) noexcept {
3870 if ((has_value() == true) && (other.has_value() == false)) {
3871 reset();
3872 } else if ((has_value() == false) && (other.has_value() == true)) {
3873 initialize(std::move(*other));
3874 } else if ((has_value() == true) && (other.has_value() == true)) {
3875 contained.value() = std::move(*other);
3876 }
3877 return *this;
3878 }
3879
3880 // 4 (C++11) - move-assign from value
3881 template <typename U = T>
3882 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
3883 // misc-unconventional-assign-operator )
3884 optional_REQUIRES_R(
3885 optional&,
3886 std::is_constructible<T, U>::value&& std::is_assignable<T&, U>::value &&
3887 !std::is_same<typename std20::remove_cvref<U>::type,
3888 nonstd_lite_in_place_t(U)>::value &&
3889 !std::is_same<typename std20::remove_cvref<U>::type,
3890 optional<T>>::value &&
3891 !(std::is_scalar<T>::value &&
3892 std::is_same<T, typename std::decay<U>::type>::value))
3893 operator=(U && value) {
3894 if (has_value()) {
3895 contained.value() = std::forward<U>(value);
3896 } else {
3897 initialize(T(std::forward<U>(value)));
3898 }
3899 return *this;
3900 }
3901
3902#else // optional_CPP11_OR_GREATER
3903
3904 // 4 (C++98) - copy-assign from value
3905 template <typename U /*= T*/> optional& operator=(U const& value) {
3906 if (has_value())
3907 contained.value() = value;
3908 else
3909 initialize(T(value));
3910 return *this;
3911 }
3912
3913#endif // optional_CPP11_OR_GREATER
3914
3915 // 5 (C++98 and later) - converting copy-assign from optional
3916 template <typename U>
3917#if optional_CPP11_OR_GREATER
3918 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
3919 // misc-unconventional-assign-operator )
3920 optional_REQUIRES_R(
3921 optional&, std::is_constructible<T, U const&>::value&&
3922 std::is_assignable<T&, U const&>::value &&
3923 !std::is_constructible<T, optional<U>&>::value &&
3924 !std::is_constructible<T, optional<U>&&>::value &&
3925 !std::is_constructible<T, optional<U> const&>::value &&
3926 !std::is_constructible<T, optional<U> const&&>::value &&
3927 !std::is_convertible<optional<U>&, T>::value &&
3928 !std::is_convertible<optional<U>&&, T>::value &&
3929 !std::is_convertible<optional<U> const&, T>::value &&
3930 !std::is_convertible<optional<U> const&&, T>::value &&
3931 !std::is_assignable<T&, optional<U>&>::value &&
3932 !std::is_assignable<T&, optional<U>&&>::value &&
3933 !std::is_assignable<T&, optional<U> const&>::value &&
3934 !std::is_assignable<T&, optional<U> const&&>::value)
3935#else
3936 optional&
3937#endif // optional_CPP11_OR_GREATER
3938 operator=(optional<U> const& other) {
3939 return *this = optional(other);
3940 }
3941
3942#if optional_CPP11_OR_GREATER
3943
3944 // 6 (C++11) - converting move-assign from optional
3945 template <typename U>
3946 // NOLINTNEXTLINE( cppcoreguidelines-c-copy-assignment-signature,
3947 // misc-unconventional-assign-operator )
3948 optional_REQUIRES_R(
3949 optional&,
3950 std::is_constructible<T, U>::value&& std::is_assignable<T&, U>::value &&
3951 !std::is_constructible<T, optional<U>&>::value &&
3952 !std::is_constructible<T, optional<U>&&>::value &&
3953 !std::is_constructible<T, optional<U> const&>::value &&
3954 !std::is_constructible<T, optional<U> const&&>::value &&
3955 !std::is_convertible<optional<U>&, T>::value &&
3956 !std::is_convertible<optional<U>&&, T>::value &&
3957 !std::is_convertible<optional<U> const&, T>::value &&
3958 !std::is_convertible<optional<U> const&&, T>::value &&
3959 !std::is_assignable<T&, optional<U>&>::value &&
3960 !std::is_assignable<T&, optional<U>&&>::value &&
3961 !std::is_assignable<T&, optional<U> const&>::value &&
3962 !std::is_assignable<T&, optional<U> const&&>::value)
3963 operator=(optional<U>&& other) {
3964 return *this = optional(std::move(other));
3965 }
3966
3967 // 7 (C++11) - emplace
3968 template <typename... Args optional_REQUIRES_T(
3969 std::is_constructible<T, Args&&...>::value)>
3970 T& emplace(Args&&... args) {
3971 *this = nullopt;
3972 contained.emplace(std::forward<Args>(args)...);
3973 has_value_ = true;
3974 return contained.value();
3975 }
3976
3977 // 8 (C++11) - emplace, initializer-list
3978 template <typename U,
3979 typename... Args optional_REQUIRES_T(
3980 std::is_constructible<T, std::initializer_list<U>&,
3981 Args&&...>::value)>
3982 T& emplace(std::initializer_list<U> il, Args&&... args) {
3983 *this = nullopt;
3984 contained.emplace(il, std::forward<Args>(args)...);
3985 has_value_ = true;
3986 return contained.value();
3987 }
3988
3989#endif // optional_CPP11_OR_GREATER
3990
3991 // x.x.3.4, swap
3992
3993 void swap(optional& other)
3994#if optional_CPP11_OR_GREATER
3995 noexcept(std::is_nothrow_move_constructible<T>::value &&
3996 std17::is_nothrow_swappable<T>::value)
3997#endif
3998 {
3999 using std::swap;
4000 if ((has_value() == true) && (other.has_value() == true)) {
4001 swap(**this, *other);
4002 } else if ((has_value() == false) && (other.has_value() == true)) {
4003 initialize(std11::move(*other));
4004 other.reset();
4005 } else if ((has_value() == true) && (other.has_value() == false)) {
4006 other.initialize(std11::move(**this));
4007 reset();
4008 }
4009 }
4010
4011 // x.x.3.5, observers
4012
4013 optional_constexpr value_type const* operator->() const {
4014 return assert(has_value()), contained.value_ptr();
4015 }
4016
4017 optional_constexpr14 value_type* operator->() {
4018 return assert(has_value()), contained.value_ptr();
4019 }
4020
4021 optional_constexpr value_type const& operator*() const optional_ref_qual {
4022 return assert(has_value()), contained.value();
4023 }
4024
4025 optional_constexpr14 value_type& operator*() optional_ref_qual {
4026 return assert(has_value()), contained.value();
4027 }
4028
4029#if optional_HAVE(REF_QUALIFIER)
4030
4031 optional_constexpr value_type const&&
4032 operator*() const optional_refref_qual {
4033 return std::move(**this);
4034 }
4035
4036 optional_constexpr14 value_type&& operator*() optional_refref_qual {
4037 return std::move(**this);
4038 }
4039
4040#endif
4041
4042#if optional_CPP11_OR_GREATER
4043 optional_constexpr explicit operator bool() const optional_noexcept {
4044 return has_value();
4045 }
4046#else
4047 optional_constexpr operator safe_bool() const optional_noexcept {
4048 return has_value() ? &optional::this_type_does_not_support_comparisons
4049 : 0;
4050 }
4051#endif
4052
4053 // NOLINTNEXTLINE( modernize-use-nodiscard )
4054 /*optional_nodiscard*/ optional_constexpr bool
4055 has_value() const optional_noexcept {
4056 return has_value_;
4057 }
4058
4059 // NOLINTNEXTLINE( modernize-use-nodiscard )
4060 /*optional_nodiscard*/ optional_constexpr14 value_type const&
4061 value() const optional_ref_qual {
4062#if optional_CONFIG_NO_EXCEPTIONS
4063 assert(has_value());
4064#else
4065 if (!has_value()) {
4066 throw bad_optional_access();
4067 }
4068#endif
4069 return contained.value();
4070 }
4071
4072 optional_constexpr14 value_type& value() optional_ref_qual {
4073#if optional_CONFIG_NO_EXCEPTIONS
4074 assert(has_value());
4075#else
4076 if (!has_value()) {
4077 throw bad_optional_access();
4078 }
4079#endif
4080 return contained.value();
4081 }
4082
4083#if optional_HAVE(REF_QUALIFIER) && \
4084 (!optional_COMPILER_GNUC_VERSION || optional_COMPILER_GNUC_VERSION >= 490)
4085
4086 // NOLINTNEXTLINE( modernize-use-nodiscard )
4087 /*optional_nodiscard*/ optional_constexpr value_type const&&
4088 value() const optional_refref_qual {
4089 return std::move(value());
4090 }
4091
4092 optional_constexpr14 value_type&& value() optional_refref_qual {
4093 return std::move(value());
4094 }
4095
4096#endif
4097
4098#if optional_CPP11_OR_GREATER
4099
4100 template <typename U>
4101 optional_constexpr value_type value_or(U&& v) const optional_ref_qual {
4102 return has_value() ? contained.value()
4103 : static_cast<T>(std::forward<U>(v));
4104 }
4105
4106 template <typename U>
4107 optional_constexpr14 value_type value_or(U&& v) optional_refref_qual {
4108 return has_value() ? std::move(contained.value())
4109 : static_cast<T>(std::forward<U>(v));
4110 }
4111
4112#else
4113
4114 template <typename U>
4115 optional_constexpr value_type value_or(U const& v) const {
4116 return has_value() ? contained.value() : static_cast<value_type>(v);
4117 }
4118
4119#endif // optional_CPP11_OR_GREATER
4120
4121 // x.x.3.6, modifiers
4122
4123 void reset() optional_noexcept {
4124 if (has_value()) {
4125 contained.destruct_value();
4126 }
4127
4128 has_value_ = false;
4129 }
4130
4131 private:
4132 void this_type_does_not_support_comparisons() const {}
4133
4134 template <typename V> void initialize(V const& value) {
4135 assert(!has_value());
4136 contained.construct_value(value);
4137 has_value_ = true;
4138 }
4139
4140#if optional_CPP11_OR_GREATER
4141 template <typename V> void initialize(V&& value) {
4142 assert(!has_value());
4143 contained.construct_value(std::move(value));
4144 has_value_ = true;
4145 }
4146
4147#endif
4148
4149 private:
4150 bool has_value_;
4151 detail::storage_t<value_type> contained;
4152};
4153
4154// Relational operators
4155
4156template <typename T, typename U>
4157inline optional_constexpr bool operator==(optional<T> const& x,
4158 optional<U> const& y) {
4159 return bool(x) != bool(y) ? false : !bool(x) ? true : *x == *y;
4160}
4161
4162template <typename T, typename U>
4163inline optional_constexpr bool operator!=(optional<T> const& x,
4164 optional<U> const& y) {
4165 return !(x == y);
4166}
4167
4168template <typename T, typename U>
4169inline optional_constexpr bool operator<(optional<T> const& x,
4170 optional<U> const& y) {
4171 return (!y) ? false : (!x) ? true : *x < *y;
4172}
4173
4174template <typename T, typename U>
4175inline optional_constexpr bool operator>(optional<T> const& x,
4176 optional<U> const& y) {
4177 return (y < x);
4178}
4179
4180template <typename T, typename U>
4181inline optional_constexpr bool operator<=(optional<T> const& x,
4182 optional<U> const& y) {
4183 return !(y < x);
4184}
4185
4186template <typename T, typename U>
4187inline optional_constexpr bool operator>=(optional<T> const& x,
4188 optional<U> const& y) {
4189 return !(x < y);
4190}
4191
4192// Comparison with nullopt
4193
4194template <typename T>
4195inline optional_constexpr bool
4196operator==(optional<T> const& x, nullopt_t /*unused*/) optional_noexcept {
4197 return (!x);
4198}
4199
4200template <typename T>
4201inline optional_constexpr bool
4202operator==(nullopt_t /*unused*/, optional<T> const& x) optional_noexcept {
4203 return (!x);
4204}
4205
4206template <typename T>
4207inline optional_constexpr bool
4208operator!=(optional<T> const& x, nullopt_t /*unused*/) optional_noexcept {
4209 return bool(x);
4210}
4211
4212template <typename T>
4213inline optional_constexpr bool
4214operator!=(nullopt_t /*unused*/, optional<T> const& x) optional_noexcept {
4215 return bool(x);
4216}
4217
4218template <typename T>
4219inline optional_constexpr bool
4220operator<(optional<T> const& /*unused*/,
4221 nullopt_t /*unused*/) optional_noexcept {
4222 return false;
4223}
4224
4225template <typename T>
4226inline optional_constexpr bool
4227operator<(nullopt_t /*unused*/, optional<T> const& x) optional_noexcept {
4228 return bool(x);
4229}
4230
4231template <typename T>
4232inline optional_constexpr bool
4233operator<=(optional<T> const& x, nullopt_t /*unused*/) optional_noexcept {
4234 return (!x);
4235}
4236
4237template <typename T>
4238inline optional_constexpr bool
4239operator<=(nullopt_t /*unused*/,
4240 optional<T> const& /*unused*/) optional_noexcept {
4241 return true;
4242}
4243
4244template <typename T>
4245inline optional_constexpr bool
4246operator>(optional<T> const& x, nullopt_t /*unused*/) optional_noexcept {
4247 return bool(x);
4248}
4249
4250template <typename T>
4251inline optional_constexpr bool
4252operator>(nullopt_t /*unused*/,
4253 optional<T> const& /*unused*/) optional_noexcept {
4254 return false;
4255}
4256
4257template <typename T>
4258inline optional_constexpr bool
4259operator>=(optional<T> const& /*unused*/,
4260 nullopt_t /*unused*/) optional_noexcept {
4261 return true;
4262}
4263
4264template <typename T>
4265inline optional_constexpr bool
4266operator>=(nullopt_t /*unused*/, optional<T> const& x) optional_noexcept {
4267 return (!x);
4268}
4269
4270// Comparison with T
4271
4272template <typename T, typename U>
4273inline optional_constexpr bool operator==(optional<T> const& x, U const& v) {
4274 return bool(x) ? *x == v : false;
4275}
4276
4277template <typename T, typename U>
4278inline optional_constexpr bool operator==(U const& v, optional<T> const& x) {
4279 return bool(x) ? v == *x : false;
4280}
4281
4282template <typename T, typename U>
4283inline optional_constexpr bool operator!=(optional<T> const& x, U const& v) {
4284 return bool(x) ? *x != v : true;
4285}
4286
4287template <typename T, typename U>
4288inline optional_constexpr bool operator!=(U const& v, optional<T> const& x) {
4289 return bool(x) ? v != *x : true;
4290}
4291
4292template <typename T, typename U>
4293inline optional_constexpr bool operator<(optional<T> const& x, U const& v) {
4294 return bool(x) ? *x < v : true;
4295}
4296
4297template <typename T, typename U>
4298inline optional_constexpr bool operator<(U const& v, optional<T> const& x) {
4299 return bool(x) ? v < *x : false;
4300}
4301
4302template <typename T, typename U>
4303inline optional_constexpr bool operator<=(optional<T> const& x, U const& v) {
4304 return bool(x) ? *x <= v : true;
4305}
4306
4307template <typename T, typename U>
4308inline optional_constexpr bool operator<=(U const& v, optional<T> const& x) {
4309 return bool(x) ? v <= *x : false;
4310}
4311
4312template <typename T, typename U>
4313inline optional_constexpr bool operator>(optional<T> const& x, U const& v) {
4314 return bool(x) ? *x > v : false;
4315}
4316
4317template <typename T, typename U>
4318inline optional_constexpr bool operator>(U const& v, optional<T> const& x) {
4319 return bool(x) ? v > *x : true;
4320}
4321
4322template <typename T, typename U>
4323inline optional_constexpr bool operator>=(optional<T> const& x, U const& v) {
4324 return bool(x) ? *x >= v : false;
4325}
4326
4327template <typename T, typename U>
4328inline optional_constexpr bool operator>=(U const& v, optional<T> const& x) {
4329 return bool(x) ? v >= *x : true;
4330}
4331
4332// Specialized algorithms
4333
4334template <typename T
4335#if optional_CPP11_OR_GREATER
4336 optional_REQUIRES_T(std::is_move_constructible<T>::value&&
4337 std17::is_swappable<T>::value)
4338#endif
4339 >
4340void swap(optional<T>& x, optional<T>& y)
4341#if optional_CPP11_OR_GREATER
4342 noexcept(noexcept(x.swap(y)))
4343#endif
4344{
4345 x.swap(y);
4346}
4347
4348#if optional_CPP11_OR_GREATER
4349
4350template <typename T>
4351optional_constexpr optional<typename std::decay<T>::type>
4352 make_optional(T&& value) {
4353 return optional<typename std::decay<T>::type>(std::forward<T>(value));
4354}
4355
4356template <typename T, typename... Args>
4357optional_constexpr optional<T> make_optional(Args&&... args) {
4358 return optional<T>(nonstd_lite_in_place(T), std::forward<Args>(args)...);
4359}
4360
4361template <typename T, typename U, typename... Args>
4362optional_constexpr optional<T> make_optional(std::initializer_list<U> il,
4363 Args&&... args) {
4364 return optional<T>(nonstd_lite_in_place(T), il,
4365 std::forward<Args>(args)...);
4366}
4367
4368#else
4369
4370template <typename T> optional<T> make_optional(T const& value) {
4371 return optional<T>(value);
4372}
4373
4374#endif // optional_CPP11_OR_GREATER
4375
4376} // namespace optional_lite
4377
4378using optional_lite::nullopt;
4379using optional_lite::nullopt_t;
4380using optional_lite::optional;
4381
4382#if !optional_CONFIG_NO_EXCEPTIONS
4383using optional_lite::bad_optional_access;
4384#endif
4385
4386using optional_lite::make_optional;
4387
4388} // namespace nonstd
4389
4390#if optional_CPP11_OR_GREATER
4391
4392// specialize the std::hash algorithm:
4393
4394namespace std {
4395
4396template <class T> struct hash<nonstd::optional<T>> {
4397 public:
4398 std::size_t
4399 operator()(nonstd::optional<T> const& v) const optional_noexcept {
4400 return bool(v) ? std::hash<T>{}(*v) : 0;
4401 }
4402};
4403
4404} // namespace std
4405
4406#endif // optional_CPP11_OR_GREATER
4407
4408#if defined(__clang__)
4409#pragma clang diagnostic pop
4410#elif defined(__GNUC__)
4411#pragma GCC diagnostic pop
4412#elif defined(_MSC_VER)
4413#pragma warning(pop)
4414#endif
4415
4416#endif // optional_USES_STD_OPTIONAL
4417
4418#endif // NONSTD_OPTIONAL_LITE_HPP
4419// Copyright 2017-2020 by Martin Moene
4420//
4421// string-view lite, a C++17-like string_view for C++98 and later.
4422// For more information see https://github.com/martinmoene/string-view-lite
4423//
4424// Distributed under the Boost Software License, Version 1.0.
4425// (See accompanying file LICENSE.txt or copy at
4426// http://www.boost.org/LICENSE_1_0.txt)
4427
4428#pragma once
4429
4430#ifndef NONSTD_SV_LITE_H_INCLUDED
4431#define NONSTD_SV_LITE_H_INCLUDED
4432
4433#define string_view_lite_MAJOR 1
4434#define string_view_lite_MINOR 6
4435#define string_view_lite_PATCH 0
4436
4437#define string_view_lite_VERSION \
4438 nssv_STRINGIFY(string_view_lite_MAJOR) "." nssv_STRINGIFY( \
4439 string_view_lite_MINOR) "." nssv_STRINGIFY(string_view_lite_PATCH)
4440
4441#define nssv_STRINGIFY(x) nssv_STRINGIFY_(x)
4442#define nssv_STRINGIFY_(x) #x
4443
4444// string-view lite configuration:
4445
4446#define nssv_STRING_VIEW_DEFAULT 0
4447#define nssv_STRING_VIEW_NONSTD 1
4448#define nssv_STRING_VIEW_STD 2
4449
4450// tweak header support:
4451
4452#ifdef __has_include
4453#if __has_include(<nonstd/string_view.tweak.hpp>)
4454#include <nonstd/string_view.tweak.hpp>
4455#endif
4456#define nssv_HAVE_TWEAK_HEADER 1
4457#else
4458#define nssv_HAVE_TWEAK_HEADER 0
4459// # pragma message("string_view.hpp: Note: Tweak header not supported.")
4460#endif
4461
4462// string_view selection and configuration:
4463
4464#if !defined(nssv_CONFIG_SELECT_STRING_VIEW)
4465#define nssv_CONFIG_SELECT_STRING_VIEW \
4466 (nssv_HAVE_STD_STRING_VIEW ? nssv_STRING_VIEW_STD : nssv_STRING_VIEW_NONSTD)
4467#endif
4468
4469#ifndef nssv_CONFIG_STD_SV_OPERATOR
4470#define nssv_CONFIG_STD_SV_OPERATOR 0
4471#endif
4472
4473#ifndef nssv_CONFIG_USR_SV_OPERATOR
4474#define nssv_CONFIG_USR_SV_OPERATOR 1
4475#endif
4476
4477#ifdef nssv_CONFIG_CONVERSION_STD_STRING
4478#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS \
4479 nssv_CONFIG_CONVERSION_STD_STRING
4480#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS \
4481 nssv_CONFIG_CONVERSION_STD_STRING
4482#endif
4483
4484#ifndef nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
4485#define nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS 1
4486#endif
4487
4488#ifndef nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
4489#define nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS 1
4490#endif
4491
4492#ifndef nssv_CONFIG_NO_STREAM_INSERTION
4493#define nssv_CONFIG_NO_STREAM_INSERTION 0
4494#endif
4495
4496// Control presence of exception handling (try and auto discover):
4497
4498#ifndef nssv_CONFIG_NO_EXCEPTIONS
4499#if defined(_MSC_VER)
4500#include <cstddef> // for _HAS_EXCEPTIONS
4501#endif
4502#if defined(__cpp_exceptions) || defined(__EXCEPTIONS) || (_HAS_EXCEPTIONS)
4503#define nssv_CONFIG_NO_EXCEPTIONS 0
4504#else
4505#define nssv_CONFIG_NO_EXCEPTIONS 1
4506#endif
4507#endif
4508
4509// C++ language version detection (C++20 is speculative):
4510// Note: VC14.0/1900 (VS2015) lacks too much from C++14.
4511
4512#ifndef nssv_CPLUSPLUS
4513#if defined(_MSVC_LANG) && !defined(__clang__)
4514#define nssv_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG)
4515#else
4516#define nssv_CPLUSPLUS __cplusplus
4517#endif
4518#endif
4519
4520#define nssv_CPP98_OR_GREATER (nssv_CPLUSPLUS >= 199711L)
4521#define nssv_CPP11_OR_GREATER (nssv_CPLUSPLUS >= 201103L)
4522#define nssv_CPP11_OR_GREATER_ (nssv_CPLUSPLUS >= 201103L)
4523#define nssv_CPP14_OR_GREATER (nssv_CPLUSPLUS >= 201402L)
4524#define nssv_CPP17_OR_GREATER (nssv_CPLUSPLUS >= 201703L)
4525#define nssv_CPP20_OR_GREATER (nssv_CPLUSPLUS >= 202000L)
4526
4527// use C++17 std::string_view if available and requested:
4528
4529#if nssv_CPP17_OR_GREATER && defined(__has_include)
4530#if __has_include(<string_view> )
4531#define nssv_HAVE_STD_STRING_VIEW 1
4532#else
4533#define nssv_HAVE_STD_STRING_VIEW 0
4534#endif
4535#else
4536#define nssv_HAVE_STD_STRING_VIEW 0
4537#endif
4538
4539#define nssv_USES_STD_STRING_VIEW \
4540 ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_STD) || \
4541 ((nssv_CONFIG_SELECT_STRING_VIEW == nssv_STRING_VIEW_DEFAULT) && \
4542 nssv_HAVE_STD_STRING_VIEW))
4543
4544#define nssv_HAVE_STARTS_WITH \
4545 (nssv_CPP20_OR_GREATER || !nssv_USES_STD_STRING_VIEW)
4546#define nssv_HAVE_ENDS_WITH nssv_HAVE_STARTS_WITH
4547
4548//
4549// Use C++17 std::string_view:
4550//
4551
4552#if nssv_USES_STD_STRING_VIEW
4553
4554#include <string_view>
4555
4556// Extensions for std::string:
4557
4558#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
4559
4560namespace nonstd {
4561
4562template <class CharT, class Traits, class Allocator = std::allocator<CharT>>
4563std::basic_string<CharT, Traits, Allocator>
4564to_string(std::basic_string_view<CharT, Traits> v,
4565 Allocator const& a = Allocator()) {
4566 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
4567}
4568
4569template <class CharT, class Traits, class Allocator>
4570std::basic_string_view<CharT, Traits>
4571to_string_view(std::basic_string<CharT, Traits, Allocator> const& s) {
4572 return std::basic_string_view<CharT, Traits>(s.data(), s.size());
4573}
4574
4575// Literal operators sv and _sv:
4576
4577#if nssv_CONFIG_STD_SV_OPERATOR
4578
4579using namespace std::literals::string_view_literals;
4580
4581#endif
4582
4583#if nssv_CONFIG_USR_SV_OPERATOR
4584
4585inline namespace literals {
4586inline namespace string_view_literals {
4587
4588constexpr std::string_view operator"" _sv(const char* str,
4589 size_t len) noexcept // (1)
4590{
4591 return std::string_view{str, len};
4592}
4593
4594constexpr std::u16string_view operator"" _sv(const char16_t* str,
4595 size_t len) noexcept // (2)
4596{
4597 return std::u16string_view{str, len};
4598}
4599
4600constexpr std::u32string_view operator"" _sv(const char32_t* str,
4601 size_t len) noexcept // (3)
4602{
4603 return std::u32string_view{str, len};
4604}
4605
4606constexpr std::wstring_view operator"" _sv(const wchar_t* str,
4607 size_t len) noexcept // (4)
4608{
4609 return std::wstring_view{str, len};
4610}
4611
4612} // namespace string_view_literals
4613} // namespace literals
4614
4615#endif // nssv_CONFIG_USR_SV_OPERATOR
4616
4617} // namespace nonstd
4618
4619#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
4620
4621namespace nonstd {
4622
4623using std::basic_string_view;
4624using std::string_view;
4625using std::u16string_view;
4626using std::u32string_view;
4627using std::wstring_view;
4628
4629// literal "sv" and "_sv", see above
4630
4631using std::operator==;
4632using std::operator!=;
4633using std::operator<;
4634using std::operator<=;
4635using std::operator>;
4636using std::operator>=;
4637
4638using std::operator<<;
4639
4640} // namespace nonstd
4641
4642#else // nssv_HAVE_STD_STRING_VIEW
4643
4644//
4645// Before C++17: use string_view lite:
4646//
4647
4648// Compiler versions:
4649//
4650// MSVC++ 6.0 _MSC_VER == 1200 nssv_COMPILER_MSVC_VERSION == 60 (Visual
4651// Studio 6.0) MSVC++ 7.0 _MSC_VER == 1300 nssv_COMPILER_MSVC_VERSION == 70
4652// (Visual Studio .NET 2002) MSVC++ 7.1 _MSC_VER == 1310
4653// nssv_COMPILER_MSVC_VERSION == 71 (Visual Studio .NET 2003) MSVC++ 8.0
4654// _MSC_VER == 1400 nssv_COMPILER_MSVC_VERSION == 80 (Visual Studio 2005)
4655// MSVC++ 9.0 _MSC_VER == 1500 nssv_COMPILER_MSVC_VERSION == 90 (Visual
4656// Studio 2008) MSVC++ 10.0 _MSC_VER == 1600 nssv_COMPILER_MSVC_VERSION == 100
4657// (Visual Studio 2010) MSVC++ 11.0 _MSC_VER == 1700 nssv_COMPILER_MSVC_VERSION
4658// == 110 (Visual Studio 2012) MSVC++ 12.0 _MSC_VER == 1800
4659// nssv_COMPILER_MSVC_VERSION == 120 (Visual Studio 2013) MSVC++ 14.0 _MSC_VER
4660// == 1900 nssv_COMPILER_MSVC_VERSION == 140 (Visual Studio 2015) MSVC++ 14.1
4661// _MSC_VER >= 1910 nssv_COMPILER_MSVC_VERSION == 141 (Visual Studio 2017)
4662// MSVC++ 14.2 _MSC_VER >= 1920 nssv_COMPILER_MSVC_VERSION == 142 (Visual
4663// Studio 2019)
4664
4665#if defined(_MSC_VER) && !defined(__clang__)
4666#define nssv_COMPILER_MSVC_VER (_MSC_VER)
4667#define nssv_COMPILER_MSVC_VERSION \
4668 (_MSC_VER / 10 - 10 * (5 + (_MSC_VER < 1900)))
4669#else
4670#define nssv_COMPILER_MSVC_VER 0
4671#define nssv_COMPILER_MSVC_VERSION 0
4672#endif
4673
4674#define nssv_COMPILER_VERSION(major, minor, patch) \
4675 (10 * (10 * (major) + (minor)) + (patch))
4676
4677#if defined(__apple_build_version__)
4678#define nssv_COMPILER_APPLECLANG_VERSION \
4679 nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, \
4680 __clang_patchlevel__)
4681#define nssv_COMPILER_CLANG_VERSION 0
4682#elif defined(__clang__)
4683#define nssv_COMPILER_APPLECLANG_VERSION 0
4684#define nssv_COMPILER_CLANG_VERSION \
4685 nssv_COMPILER_VERSION(__clang_major__, __clang_minor__, \
4686 __clang_patchlevel__)
4687#else
4688#define nssv_COMPILER_APPLECLANG_VERSION 0
4689#define nssv_COMPILER_CLANG_VERSION 0
4690#endif
4691
4692#if defined(__GNUC__) && !defined(__clang__)
4693#define nssv_COMPILER_GNUC_VERSION \
4694 nssv_COMPILER_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
4695#else
4696#define nssv_COMPILER_GNUC_VERSION 0
4697#endif
4698
4699// half-open range [lo..hi):
4700#define nssv_BETWEEN(v, lo, hi) ((lo) <= (v) && (v) < (hi))
4701
4702// Presence of language and library features:
4703
4704#ifdef _HAS_CPP0X
4705#define nssv_HAS_CPP0X _HAS_CPP0X
4706#else
4707#define nssv_HAS_CPP0X 0
4708#endif
4709
4710// Unless defined otherwise below, consider VC14 as C++11 for variant-lite:
4711
4712#if nssv_COMPILER_MSVC_VER >= 1900
4713#undef nssv_CPP11_OR_GREATER
4714#define nssv_CPP11_OR_GREATER 1
4715#endif
4716
4717#define nssv_CPP11_90 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1500)
4718#define nssv_CPP11_100 \
4719 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1600)
4720#define nssv_CPP11_110 \
4721 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1700)
4722#define nssv_CPP11_120 \
4723 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1800)
4724#define nssv_CPP11_140 \
4725 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1900)
4726#define nssv_CPP11_141 \
4727 (nssv_CPP11_OR_GREATER_ || nssv_COMPILER_MSVC_VER >= 1910)
4728
4729#define nssv_CPP14_000 (nssv_CPP14_OR_GREATER)
4730#define nssv_CPP17_000 (nssv_CPP17_OR_GREATER)
4731
4732// Presence of C++11 language features:
4733
4734#define nssv_HAVE_CONSTEXPR_11 nssv_CPP11_140
4735#define nssv_HAVE_EXPLICIT_CONVERSION nssv_CPP11_140
4736#define nssv_HAVE_INLINE_NAMESPACE nssv_CPP11_140
4737#define nssv_HAVE_NOEXCEPT nssv_CPP11_140
4738#define nssv_HAVE_NULLPTR nssv_CPP11_100
4739#define nssv_HAVE_REF_QUALIFIER nssv_CPP11_140
4740#define nssv_HAVE_UNICODE_LITERALS nssv_CPP11_140
4741#define nssv_HAVE_USER_DEFINED_LITERALS nssv_CPP11_140
4742#define nssv_HAVE_WCHAR16_T nssv_CPP11_100
4743#define nssv_HAVE_WCHAR32_T nssv_CPP11_100
4744
4745#if !((nssv_CPP11_OR_GREATER && nssv_COMPILER_CLANG_VERSION) || \
4746 nssv_BETWEEN(nssv_COMPILER_CLANG_VERSION, 300, 400))
4747#define nssv_HAVE_STD_DEFINED_LITERALS nssv_CPP11_140
4748#else
4749#define nssv_HAVE_STD_DEFINED_LITERALS 0
4750#endif
4751
4752// Presence of C++14 language features:
4753
4754#define nssv_HAVE_CONSTEXPR_14 nssv_CPP14_000
4755
4756// Presence of C++17 language features:
4757
4758#define nssv_HAVE_NODISCARD nssv_CPP17_000
4759
4760// Presence of C++ library features:
4761
4762#define nssv_HAVE_STD_HASH nssv_CPP11_120
4763
4764// Presence of compiler intrinsics:
4765
4766// Providing char-type specializations for compare() and length() that
4767// use compiler intrinsics can improve compile- and run-time performance.
4768//
4769// The challenge is in using the right combinations of builtin availability
4770// and its constexpr-ness.
4771//
4772// | compiler | __builtin_memcmp (constexpr) | memcmp (constexpr) |
4773// |----------|------------------------------|---------------------|
4774// | clang | 4.0 (>= 4.0 ) | any (? ) |
4775// | clang-a | 9.0 (>= 9.0 ) | any (? ) |
4776// | gcc | any (constexpr) | any (? ) |
4777// | msvc | >= 14.2 C++17 (>= 14.2 ) | any (? ) |
4778
4779#define nssv_HAVE_BUILTIN_VER \
4780 ((nssv_CPP17_000 && nssv_COMPILER_MSVC_VERSION >= 142) || \
4781 nssv_COMPILER_GNUC_VERSION > 0 || nssv_COMPILER_CLANG_VERSION >= 400 || \
4782 nssv_COMPILER_APPLECLANG_VERSION >= 900)
4783#define nssv_HAVE_BUILTIN_CE (nssv_HAVE_BUILTIN_VER)
4784
4785#define nssv_HAVE_BUILTIN_MEMCMP \
4786 ((nssv_HAVE_CONSTEXPR_14 && nssv_HAVE_BUILTIN_CE) || \
4787 !nssv_HAVE_CONSTEXPR_14)
4788#define nssv_HAVE_BUILTIN_STRLEN \
4789 ((nssv_HAVE_CONSTEXPR_11 && nssv_HAVE_BUILTIN_CE) || \
4790 !nssv_HAVE_CONSTEXPR_11)
4791
4792#ifdef __has_builtin
4793#define nssv_HAVE_BUILTIN(x) __has_builtin(x)
4794#else
4795#define nssv_HAVE_BUILTIN(x) 0
4796#endif
4797
4798#if nssv_HAVE_BUILTIN(__builtin_memcmp) || nssv_HAVE_BUILTIN_VER
4799#define nssv_BUILTIN_MEMCMP __builtin_memcmp
4800#else
4801#define nssv_BUILTIN_MEMCMP memcmp
4802#endif
4803
4804#if nssv_HAVE_BUILTIN(__builtin_strlen) || nssv_HAVE_BUILTIN_VER
4805#define nssv_BUILTIN_STRLEN __builtin_strlen
4806#else
4807#define nssv_BUILTIN_STRLEN strlen
4808#endif
4809
4810// C++ feature usage:
4811
4812#if nssv_HAVE_CONSTEXPR_11
4813#define nssv_constexpr constexpr
4814#else
4815#define nssv_constexpr /*constexpr*/
4816#endif
4817
4818#if nssv_HAVE_CONSTEXPR_14
4819#define nssv_constexpr14 constexpr
4820#else
4821#define nssv_constexpr14 /*constexpr*/
4822#endif
4823
4824#if nssv_HAVE_EXPLICIT_CONVERSION
4825#define nssv_explicit explicit
4826#else
4827#define nssv_explicit /*explicit*/
4828#endif
4829
4830#if nssv_HAVE_INLINE_NAMESPACE
4831#define nssv_inline_ns inline
4832#else
4833#define nssv_inline_ns /*inline*/
4834#endif
4835
4836#if nssv_HAVE_NOEXCEPT
4837#define nssv_noexcept noexcept
4838#else
4839#define nssv_noexcept /*noexcept*/
4840#endif
4841
4842// #if nssv_HAVE_REF_QUALIFIER
4843// # define nssv_ref_qual &
4844// # define nssv_refref_qual &&
4845// #else
4846// # define nssv_ref_qual /*&*/
4847// # define nssv_refref_qual /*&&*/
4848// #endif
4849
4850#if nssv_HAVE_NULLPTR
4851#define nssv_nullptr nullptr
4852#else
4853#define nssv_nullptr NULL
4854#endif
4855
4856#if nssv_HAVE_NODISCARD
4857#define nssv_nodiscard [[nodiscard]]
4858#else
4859#define nssv_nodiscard /*[[nodiscard]]*/
4860#endif
4861
4862// Additional includes:
4863
4864#include <algorithm>
4865#include <cassert>
4866#include <iterator>
4867#include <limits>
4868#include <string> // std::char_traits<>
4869
4870#if !nssv_CONFIG_NO_STREAM_INSERTION
4871#include <ostream>
4872#endif
4873
4874#if !nssv_CONFIG_NO_EXCEPTIONS
4875#include <stdexcept>
4876#endif
4877
4878#if nssv_CPP11_OR_GREATER
4879#include <type_traits>
4880#endif
4881
4882// Clang, GNUC, MSVC warning suppression macros:
4883
4884#if defined(__clang__)
4885#pragma clang diagnostic ignored "-Wreserved-user-defined-literal"
4886#pragma clang diagnostic push
4887#pragma clang diagnostic ignored "-Wuser-defined-literals"
4888#elif defined(__GNUC__)
4889#pragma GCC diagnostic push
4890#pragma GCC diagnostic ignored "-Wliteral-suffix"
4891#endif // __clang__
4892
4893#if nssv_COMPILER_MSVC_VERSION >= 140
4894#define nssv_SUPPRESS_MSGSL_WARNING(expr) [[gsl::suppress(expr)]]
4895#define nssv_SUPPRESS_MSVC_WARNING(code, descr) \
4896 __pragma(warning(suppress : code))
4897#define nssv_DISABLE_MSVC_WARNINGS(codes) \
4898 __pragma(warning(push)) __pragma(warning(disable : codes))
4899#else
4900#define nssv_SUPPRESS_MSGSL_WARNING(expr)
4901#define nssv_SUPPRESS_MSVC_WARNING(code, descr)
4902#define nssv_DISABLE_MSVC_WARNINGS(codes)
4903#endif
4904
4905#if defined(__clang__)
4906#define nssv_RESTORE_WARNINGS() _Pragma("clang diagnostic pop")
4907#elif defined(__GNUC__)
4908#define nssv_RESTORE_WARNINGS() _Pragma("GCC diagnostic pop")
4909#elif nssv_COMPILER_MSVC_VERSION >= 140
4910#define nssv_RESTORE_WARNINGS() __pragma(warning(pop))
4911#else
4912#define nssv_RESTORE_WARNINGS()
4913#endif
4914
4915// Suppress the following MSVC (GSL) warnings:
4916// - C4455, non-gsl : 'operator ""sv': literal suffix identifiers that do not
4917// start with an underscore are reserved
4918// - C26472, gsl::t.1 : don't use a static_cast for arithmetic conversions;
4919// use brace initialization, gsl::narrow_cast or gsl::narow
4920// - C26481: gsl::b.1 : don't use pointer arithmetic. Use span instead
4921
4922nssv_DISABLE_MSVC_WARNINGS(4455 26481 26472)
4923 // nssv_DISABLE_CLANG_WARNINGS( "-Wuser-defined-literals" )
4924 // nssv_DISABLE_GNUC_WARNINGS( -Wliteral-suffix )
4925
4926 namespace nonstd {
4927 namespace sv_lite {
4928
4929 namespace detail {
4930
4931 // support constexpr comparison in C++14;
4932 // for C++17 and later, use provided traits:
4933
4934 template <typename CharT>
4935 inline nssv_constexpr14 int compare(CharT const* s1, CharT const* s2,
4936 std::size_t count) {
4937 while (count-- != 0) {
4938 if (*s1 < *s2)
4939 return -1;
4940 if (*s1 > *s2)
4941 return +1;
4942 ++s1;
4943 ++s2;
4944 }
4945 return 0;
4946 }
4947
4948#if nssv_HAVE_BUILTIN_MEMCMP
4949
4950 // specialization of compare() for char, see also generic compare() above:
4951
4952 inline nssv_constexpr14 int compare(char const* s1, char const* s2,
4953 std::size_t count) {
4954 return nssv_BUILTIN_MEMCMP(s1, s2, count);
4955 }
4956
4957#endif
4958
4959#if nssv_HAVE_BUILTIN_STRLEN
4960
4961 // specialization of length() for char, see also generic length() further
4962 // below:
4963
4964 inline nssv_constexpr std::size_t length(char const* s) {
4965 return nssv_BUILTIN_STRLEN(s);
4966 }
4967
4968#endif
4969
4970#if defined(__OPTIMIZE__)
4971
4972 // gcc, clang provide __OPTIMIZE__
4973 // Expect tail call optimization to make length() non-recursive:
4974
4975 template <typename CharT>
4976 inline nssv_constexpr std::size_t length(CharT* s, std::size_t result = 0) {
4977 return *s == '\0' ? result : length(s + 1, result + 1);
4978 }
4979
4980#else // OPTIMIZE
4981
4982 // non-recursive:
4983
4984 template <typename CharT>
4985 inline nssv_constexpr14 std::size_t length(CharT* s) {
4986 std::size_t result = 0;
4987 while (*s++ != '\0') {
4988 ++result;
4989 }
4990 return result;
4991 }
4992
4993#endif // OPTIMIZE
4994
4995 } // namespace detail
4996
4997 template <class CharT, class Traits = std::char_traits<CharT>>
4998 class basic_string_view;
4999
5000 //
5001 // basic_string_view:
5002 //
5003
5004 template <class CharT, class Traits /* = std::char_traits<CharT> */
5005 >
5006 class basic_string_view {
5007 public:
5008 // Member types:
5009
5010 typedef Traits traits_type;
5011 typedef CharT value_type;
5012
5013 typedef CharT* pointer;
5014 typedef CharT const* const_pointer;
5015 typedef CharT& reference;
5016 typedef CharT const& const_reference;
5017
5018 typedef const_pointer iterator;
5019 typedef const_pointer const_iterator;
5020 typedef std::reverse_iterator<const_iterator> reverse_iterator;
5021 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
5022
5023 typedef std::size_t size_type;
5024 typedef std::ptrdiff_t difference_type;
5025
5026 // 24.4.2.1 Construction and assignment:
5027
5028 nssv_constexpr basic_string_view() nssv_noexcept : data_(nssv_nullptr),
5029 size_(0) {}
5030
5031#if nssv_CPP11_OR_GREATER
5032 nssv_constexpr basic_string_view(basic_string_view const& other)
5033 nssv_noexcept = default;
5034#else
5035 nssv_constexpr
5036 basic_string_view(basic_string_view const& other) nssv_noexcept
5037 : data_(other.data_),
5038 size_(other.size_) {}
5039#endif
5040
5041 nssv_constexpr basic_string_view(CharT const* s, size_type count)
5042 nssv_noexcept // non-standard noexcept
5043 : data_(s),
5044 size_(count) {}
5045
5046 nssv_constexpr
5047 basic_string_view(CharT const* s) nssv_noexcept // non-standard noexcept
5048 : data_(s)
5049#if nssv_CPP17_OR_GREATER
5050 ,
5051 size_(Traits::length(s))
5052#elif nssv_CPP11_OR_GREATER
5053 ,
5054 size_(detail::length(s))
5055#else
5056 ,
5057 size_(Traits::length(s))
5058#endif
5059 {
5060 }
5061
5062 // Assignment:
5063
5064#if nssv_CPP11_OR_GREATER
5065 nssv_constexpr14 basic_string_view&
5066 operator=(basic_string_view const& other) nssv_noexcept = default;
5067#else
5068 nssv_constexpr14 basic_string_view&
5069 operator=(basic_string_view const& other) nssv_noexcept {
5070 data_ = other.data_;
5071 size_ = other.size_;
5072 return *this;
5073 }
5074#endif
5075
5076 // 24.4.2.2 Iterator support:
5077
5078 nssv_constexpr const_iterator begin() const nssv_noexcept {
5079 return data_;
5080 }
5081 nssv_constexpr const_iterator end() const nssv_noexcept {
5082 return data_ + size_;
5083 }
5084
5085 nssv_constexpr const_iterator cbegin() const nssv_noexcept {
5086 return begin();
5087 }
5088 nssv_constexpr const_iterator cend() const nssv_noexcept {
5089 return end();
5090 }
5091
5092 nssv_constexpr const_reverse_iterator rbegin() const nssv_noexcept {
5093 return const_reverse_iterator(end());
5094 }
5095 nssv_constexpr const_reverse_iterator rend() const nssv_noexcept {
5096 return const_reverse_iterator(begin());
5097 }
5098
5099 nssv_constexpr const_reverse_iterator crbegin() const nssv_noexcept {
5100 return rbegin();
5101 }
5102 nssv_constexpr const_reverse_iterator crend() const nssv_noexcept {
5103 return rend();
5104 }
5105
5106 // 24.4.2.3 Capacity:
5107
5108 nssv_constexpr size_type size() const nssv_noexcept { return size_; }
5109 nssv_constexpr size_type length() const nssv_noexcept { return size_; }
5110 nssv_constexpr size_type max_size() const nssv_noexcept {
5111 return (std::numeric_limits<size_type>::max)();
5112 }
5113
5114 // since C++20
5115 nssv_nodiscard nssv_constexpr bool empty() const nssv_noexcept {
5116 return 0 == size_;
5117 }
5118
5119 // 24.4.2.4 Element access:
5120
5121 nssv_constexpr const_reference operator[](size_type pos) const {
5122 return data_at(pos);
5123 }
5124
5125 nssv_constexpr14 const_reference at(size_type pos) const {
5126#if nssv_CONFIG_NO_EXCEPTIONS
5127 assert(pos < size());
5128#else
5129 if (pos >= size()) {
5130 throw std::out_of_range("nonstd::string_view::at()");
5131 }
5132#endif
5133 return data_at(pos);
5134 }
5135
5136 nssv_constexpr const_reference front() const { return data_at(0); }
5137 nssv_constexpr const_reference back() const {
5138 return data_at(size() - 1);
5139 }
5140
5141 nssv_constexpr const_pointer data() const nssv_noexcept {
5142 return data_;
5143 }
5144
5145 // 24.4.2.5 Modifiers:
5146
5147 nssv_constexpr14 void remove_prefix(size_type n) {
5148 assert(n <= size());
5149 data_ += n;
5150 size_ -= n;
5151 }
5152
5153 nssv_constexpr14 void remove_suffix(size_type n) {
5154 assert(n <= size());
5155 size_ -= n;
5156 }
5157
5158 nssv_constexpr14 void swap(basic_string_view& other) nssv_noexcept {
5159 const basic_string_view tmp(other);
5160 other = *this;
5161 *this = tmp;
5162 }
5163
5164 // 24.4.2.6 String operations:
5165
5166 size_type copy(CharT* dest, size_type n, size_type pos = 0) const {
5167#if nssv_CONFIG_NO_EXCEPTIONS
5168 assert(pos <= size());
5169#else
5170 if (pos > size()) {
5171 throw std::out_of_range("nonstd::string_view::copy()");
5172 }
5173#endif
5174 const size_type rlen = (std::min)(n, size() - pos);
5175
5176 (void) Traits::copy(dest, data() + pos, rlen);
5177
5178 return rlen;
5179 }
5180
5181 nssv_constexpr14 basic_string_view substr(size_type pos = 0,
5182 size_type n = npos) const {
5183#if nssv_CONFIG_NO_EXCEPTIONS
5184 assert(pos <= size());
5185#else
5186 if (pos > size()) {
5187 throw std::out_of_range("nonstd::string_view::substr()");
5188 }
5189#endif
5190 return basic_string_view(data() + pos, (std::min)(n, size() - pos));
5191 }
5192
5193 // compare(), 6x:
5194
5195 nssv_constexpr14 int
5196 compare(basic_string_view other) const nssv_noexcept // (1)
5197 {
5198#if nssv_CPP17_OR_GREATER
5199 if (const int result = Traits::compare(
5200 data(), other.data(), (std::min)(size(), other.size())))
5201#else
5202 if (const int result = detail::compare(
5203 data(), other.data(), (std::min)(size(), other.size())))
5204#endif
5205 {
5206 return result;
5207 }
5208
5209 return size() == other.size() ? 0 : size() < other.size() ? -1 : 1;
5210 }
5211
5212 nssv_constexpr int compare(size_type pos1, size_type n1,
5213 basic_string_view other) const // (2)
5214 {
5215 return substr(pos1, n1).compare(other);
5216 }
5217
5218 nssv_constexpr int compare(size_type pos1, size_type n1,
5219 basic_string_view other, size_type pos2,
5220 size_type n2) const // (3)
5221 {
5222 return substr(pos1, n1).compare(other.substr(pos2, n2));
5223 }
5224
5225 nssv_constexpr int compare(CharT const* s) const // (4)
5226 {
5227 return compare(basic_string_view(s));
5228 }
5229
5230 nssv_constexpr int compare(size_type pos1, size_type n1,
5231 CharT const* s) const // (5)
5232 {
5233 return substr(pos1, n1).compare(basic_string_view(s));
5234 }
5235
5236 nssv_constexpr int compare(size_type pos1, size_type n1, CharT const* s,
5237 size_type n2) const // (6)
5238 {
5239 return substr(pos1, n1).compare(basic_string_view(s, n2));
5240 }
5241
5242 // 24.4.2.7 Searching:
5243
5244 // starts_with(), 3x, since C++20:
5245
5246 nssv_constexpr bool
5247 starts_with(basic_string_view v) const nssv_noexcept // (1)
5248 {
5249 return size() >= v.size() && compare(0, v.size(), v) == 0;
5250 }
5251
5252 nssv_constexpr bool starts_with(CharT c) const nssv_noexcept // (2)
5253 {
5254 return starts_with(basic_string_view(&c, 1));
5255 }
5256
5257 nssv_constexpr bool starts_with(CharT const* s) const // (3)
5258 {
5259 return starts_with(basic_string_view(s));
5260 }
5261
5262 // ends_with(), 3x, since C++20:
5263
5264 nssv_constexpr bool
5265 ends_with(basic_string_view v) const nssv_noexcept // (1)
5266 {
5267 return size() >= v.size() &&
5268 compare(size() - v.size(), npos, v) == 0;
5269 }
5270
5271 nssv_constexpr bool ends_with(CharT c) const nssv_noexcept // (2)
5272 {
5273 return ends_with(basic_string_view(&c, 1));
5274 }
5275
5276 nssv_constexpr bool ends_with(CharT const* s) const // (3)
5277 {
5278 return ends_with(basic_string_view(s));
5279 }
5280
5281 // find(), 4x:
5282
5283 nssv_constexpr14 size_type
5284 find(basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
5285 {
5286 return assert(v.size() == 0 || v.data() != nssv_nullptr),
5287 pos >= size()
5288 ? npos
5289 : to_pos(std::search(cbegin() + pos, cend(), v.cbegin(),
5290 v.cend(), Traits::eq));
5291 }
5292
5293 nssv_constexpr14 size_type
5294 find(CharT c, size_type pos = 0) const nssv_noexcept // (2)
5295 {
5296 return find(basic_string_view(&c, 1), pos);
5297 }
5298
5299 nssv_constexpr14 size_type find(CharT const* s, size_type pos,
5300 size_type n) const // (3)
5301 {
5302 return find(basic_string_view(s, n), pos);
5303 }
5304
5305 nssv_constexpr14 size_type find(CharT const* s,
5306 size_type pos = 0) const // (4)
5307 {
5308 return find(basic_string_view(s), pos);
5309 }
5310
5311 // rfind(), 4x:
5312
5313 nssv_constexpr14 size_type
5314 rfind(basic_string_view v,
5315 size_type pos = npos) const nssv_noexcept // (1)
5316 {
5317 if (size() < v.size()) {
5318 return npos;
5319 }
5320
5321 if (v.empty()) {
5322 return (std::min)(size(), pos);
5323 }
5324
5325 const_iterator last =
5326 cbegin() + (std::min)(size() - v.size(), pos) + v.size();
5327 const_iterator result =
5328 std::find_end(cbegin(), last, v.cbegin(), v.cend(), Traits::eq);
5329
5330 return result != last ? size_type(result - cbegin()) : npos;
5331 }
5332
5333 nssv_constexpr14 size_type
5334 rfind(CharT c, size_type pos = npos) const nssv_noexcept // (2)
5335 {
5336 return rfind(basic_string_view(&c, 1), pos);
5337 }
5338
5339 nssv_constexpr14 size_type rfind(CharT const* s, size_type pos,
5340 size_type n) const // (3)
5341 {
5342 return rfind(basic_string_view(s, n), pos);
5343 }
5344
5345 nssv_constexpr14 size_type rfind(CharT const* s,
5346 size_type pos = npos) const // (4)
5347 {
5348 return rfind(basic_string_view(s), pos);
5349 }
5350
5351 // find_first_of(), 4x:
5352
5353 nssv_constexpr size_type find_first_of(
5354 basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
5355 {
5356 return pos >= size()
5357 ? npos
5358 : to_pos(std::find_first_of(cbegin() + pos, cend(),
5359 v.cbegin(), v.cend(),
5360 Traits::eq));
5361 }
5362
5363 nssv_constexpr size_type
5364 find_first_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
5365 {
5366 return find_first_of(basic_string_view(&c, 1), pos);
5367 }
5368
5369 nssv_constexpr size_type find_first_of(CharT const* s, size_type pos,
5370 size_type n) const // (3)
5371 {
5372 return find_first_of(basic_string_view(s, n), pos);
5373 }
5374
5375 nssv_constexpr size_type find_first_of(CharT const* s,
5376 size_type pos = 0) const // (4)
5377 {
5378 return find_first_of(basic_string_view(s), pos);
5379 }
5380
5381 // find_last_of(), 4x:
5382
5383 nssv_constexpr size_type
5384 find_last_of(basic_string_view v,
5385 size_type pos = npos) const nssv_noexcept // (1)
5386 {
5387 return empty() ? npos
5388 : pos >= size()
5389 ? find_last_of(v, size() - 1)
5390 : to_pos(std::find_first_of(
5391 const_reverse_iterator(cbegin() + pos + 1),
5392 crend(), v.cbegin(), v.cend(), Traits::eq));
5393 }
5394
5395 nssv_constexpr size_type
5396 find_last_of(CharT c, size_type pos = npos) const nssv_noexcept // (2)
5397 {
5398 return find_last_of(basic_string_view(&c, 1), pos);
5399 }
5400
5401 nssv_constexpr size_type find_last_of(CharT const* s, size_type pos,
5402 size_type count) const // (3)
5403 {
5404 return find_last_of(basic_string_view(s, count), pos);
5405 }
5406
5407 nssv_constexpr size_type find_last_of(CharT const* s,
5408 size_type pos = npos) const // (4)
5409 {
5410 return find_last_of(basic_string_view(s), pos);
5411 }
5412
5413 // find_first_not_of(), 4x:
5414
5415 nssv_constexpr size_type find_first_not_of(
5416 basic_string_view v, size_type pos = 0) const nssv_noexcept // (1)
5417 {
5418 return pos >= size() ? npos
5419 : to_pos(std::find_if(cbegin() + pos, cend(),
5420 not_in_view(v)));
5421 }
5422
5423 nssv_constexpr size_type
5424 find_first_not_of(CharT c, size_type pos = 0) const nssv_noexcept // (2)
5425 {
5426 return find_first_not_of(basic_string_view(&c, 1), pos);
5427 }
5428
5429 nssv_constexpr size_type find_first_not_of(CharT const* s,
5430 size_type pos,
5431 size_type count) const // (3)
5432 {
5433 return find_first_not_of(basic_string_view(s, count), pos);
5434 }
5435
5436 nssv_constexpr size_type
5437 find_first_not_of(CharT const* s, size_type pos = 0) const // (4)
5438 {
5439 return find_first_not_of(basic_string_view(s), pos);
5440 }
5441
5442 // find_last_not_of(), 4x:
5443
5444 nssv_constexpr size_type
5445 find_last_not_of(basic_string_view v,
5446 size_type pos = npos) const nssv_noexcept // (1)
5447 {
5448 return empty() ? npos
5449 : pos >= size()
5450 ? find_last_not_of(v, size() - 1)
5451 : to_pos(std::find_if(
5452 const_reverse_iterator(cbegin() + pos + 1),
5453 crend(), not_in_view(v)));
5454 }
5455
5456 nssv_constexpr size_type find_last_not_of(
5457 CharT c, size_type pos = npos) const nssv_noexcept // (2)
5458 {
5459 return find_last_not_of(basic_string_view(&c, 1), pos);
5460 }
5461
5462 nssv_constexpr size_type find_last_not_of(CharT const* s, size_type pos,
5463 size_type count) const // (3)
5464 {
5465 return find_last_not_of(basic_string_view(s, count), pos);
5466 }
5467
5468 nssv_constexpr size_type
5469 find_last_not_of(CharT const* s, size_type pos = npos) const // (4)
5470 {
5471 return find_last_not_of(basic_string_view(s), pos);
5472 }
5473
5474 // Constants:
5475
5476#if nssv_CPP17_OR_GREATER
5477 static nssv_constexpr size_type npos = size_type(-1);
5478#elif nssv_CPP11_OR_GREATER
5479 enum : size_type { npos = size_type(-1) };
5480#else
5481 enum { npos = size_type(-1) };
5482#endif
5483
5484 private:
5485 struct not_in_view {
5486 const basic_string_view v;
5487
5488 nssv_constexpr explicit not_in_view(basic_string_view v_) : v(v_) {}
5489
5490 nssv_constexpr bool operator()(CharT c) const {
5491 return npos == v.find_first_of(c);
5492 }
5493 };
5494
5495 nssv_constexpr size_type to_pos(const_iterator it) const {
5496 return it == cend() ? npos : size_type(it - cbegin());
5497 }
5498
5499 nssv_constexpr size_type to_pos(const_reverse_iterator it) const {
5500 return it == crend() ? npos : size_type(crend() - it - 1);
5501 }
5502
5503 nssv_constexpr const_reference data_at(size_type pos) const {
5504#if nssv_BETWEEN(nssv_COMPILER_GNUC_VERSION, 1, 500)
5505 return data_[pos];
5506#else
5507 return assert(pos < size()), data_[pos];
5508#endif
5509 }
5510
5511 private:
5512 const_pointer data_;
5513 size_type size_;
5514
5515 public:
5516#if nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
5517
5518 template <class Allocator>
5519 basic_string_view(std::basic_string<CharT, Traits, Allocator> const& s)
5520 nssv_noexcept : data_(s.data()),
5521 size_(s.size()) {}
5522
5523#if nssv_HAVE_EXPLICIT_CONVERSION
5524
5525 template <class Allocator>
5526 explicit operator std::basic_string<CharT, Traits, Allocator>() const {
5527 return to_string(Allocator());
5528 }
5529
5530#endif // nssv_HAVE_EXPLICIT_CONVERSION
5531
5532#if nssv_CPP11_OR_GREATER
5533
5534 template <class Allocator = std::allocator<CharT>>
5535 std::basic_string<CharT, Traits, Allocator>
5536 to_string(Allocator const& a = Allocator()) const {
5537 return std::basic_string<CharT, Traits, Allocator>(begin(), end(),
5538 a);
5539 }
5540
5541#else
5542
5543 std::basic_string<CharT, Traits> to_string() const {
5544 return std::basic_string<CharT, Traits>(begin(), end());
5545 }
5546
5547 template <class Allocator>
5548 std::basic_string<CharT, Traits, Allocator>
5549 to_string(Allocator const& a) const {
5550 return std::basic_string<CharT, Traits, Allocator>(begin(), end(),
5551 a);
5552 }
5553
5554#endif // nssv_CPP11_OR_GREATER
5555
5556#endif // nssv_CONFIG_CONVERSION_STD_STRING_CLASS_METHODS
5557 };
5558
5559 //
5560 // Non-member functions:
5561 //
5562
5563 // 24.4.3 Non-member comparison functions:
5564 // lexicographically compare two string views (function template):
5565
5566 template <class CharT, class Traits>
5567 nssv_constexpr bool
5568 operator==(basic_string_view<CharT, Traits> lhs,
5569 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5570 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
5571 }
5572
5573 template <class CharT, class Traits>
5574 nssv_constexpr bool
5575 operator!=(basic_string_view<CharT, Traits> lhs,
5576 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5577 return !(lhs == rhs);
5578 }
5579
5580 template <class CharT, class Traits>
5581 nssv_constexpr bool
5582 operator<(basic_string_view<CharT, Traits> lhs,
5583 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5584 return lhs.compare(rhs) < 0;
5585 }
5586
5587 template <class CharT, class Traits>
5588 nssv_constexpr bool
5589 operator<=(basic_string_view<CharT, Traits> lhs,
5590 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5591 return lhs.compare(rhs) <= 0;
5592 }
5593
5594 template <class CharT, class Traits>
5595 nssv_constexpr bool
5596 operator>(basic_string_view<CharT, Traits> lhs,
5597 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5598 return lhs.compare(rhs) > 0;
5599 }
5600
5601 template <class CharT, class Traits>
5602 nssv_constexpr bool
5603 operator>=(basic_string_view<CharT, Traits> lhs,
5604 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5605 return lhs.compare(rhs) >= 0;
5606 }
5607
5608 // Let S be basic_string_view<CharT, Traits>, and sv be an instance of S.
5609 // Implementations shall provide sufficient additional overloads marked
5610 // constexpr and noexcept so that an object t with an implicit conversion
5611 // to S can be compared according to Table 67.
5612
5613#if !nssv_CPP11_OR_GREATER || nssv_BETWEEN(nssv_COMPILER_MSVC_VERSION, 100, 141)
5614
5615 // accommodate for older compilers:
5616
5617 // ==
5618
5619 template <class CharT, class Traits>
5620 nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
5621 CharT const* rhs) nssv_noexcept {
5622 return lhs.size() == detail::length(rhs) && lhs.compare(rhs) == 0;
5623 }
5624
5625 template <class CharT, class Traits>
5626 nssv_constexpr bool
5627 operator==(CharT const* lhs,
5628 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5629 return detail::length(lhs) == rhs.size() && rhs.compare(lhs) == 0;
5630 }
5631
5632 template <class CharT, class Traits>
5633 nssv_constexpr bool
5634 operator==(basic_string_view<CharT, Traits> lhs,
5635 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5636 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
5637 }
5638
5639 template <class CharT, class Traits>
5640 nssv_constexpr bool
5641 operator==(std::basic_string<CharT, Traits> rhs,
5642 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5643 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
5644 }
5645
5646 // !=
5647
5648 template <class CharT, class Traits>
5649 nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs,
5650 CharT const* rhs) nssv_noexcept {
5651 return !(lhs == rhs);
5652 }
5653
5654 template <class CharT, class Traits>
5655 nssv_constexpr bool
5656 operator!=(CharT const* lhs,
5657 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5658 return !(lhs == rhs);
5659 }
5660
5661 template <class CharT, class Traits>
5662 nssv_constexpr bool
5663 operator!=(basic_string_view<CharT, Traits> lhs,
5664 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5665 return !(lhs == rhs);
5666 }
5667
5668 template <class CharT, class Traits>
5669 nssv_constexpr bool
5670 operator!=(std::basic_string<CharT, Traits> rhs,
5671 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5672 return !(lhs == rhs);
5673 }
5674
5675 // <
5676
5677 template <class CharT, class Traits>
5678 nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs,
5679 CharT const* rhs) nssv_noexcept {
5680 return lhs.compare(rhs) < 0;
5681 }
5682
5683 template <class CharT, class Traits>
5684 nssv_constexpr bool
5685 operator<(CharT const* lhs,
5686 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5687 return rhs.compare(lhs) > 0;
5688 }
5689
5690 template <class CharT, class Traits>
5691 nssv_constexpr bool
5692 operator<(basic_string_view<CharT, Traits> lhs,
5693 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5694 return lhs.compare(rhs) < 0;
5695 }
5696
5697 template <class CharT, class Traits>
5698 nssv_constexpr bool
5699 operator<(std::basic_string<CharT, Traits> rhs,
5700 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5701 return rhs.compare(lhs) > 0;
5702 }
5703
5704 // <=
5705
5706 template <class CharT, class Traits>
5707 nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs,
5708 CharT const* rhs) nssv_noexcept {
5709 return lhs.compare(rhs) <= 0;
5710 }
5711
5712 template <class CharT, class Traits>
5713 nssv_constexpr bool
5714 operator<=(CharT const* lhs,
5715 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5716 return rhs.compare(lhs) >= 0;
5717 }
5718
5719 template <class CharT, class Traits>
5720 nssv_constexpr bool
5721 operator<=(basic_string_view<CharT, Traits> lhs,
5722 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5723 return lhs.compare(rhs) <= 0;
5724 }
5725
5726 template <class CharT, class Traits>
5727 nssv_constexpr bool
5728 operator<=(std::basic_string<CharT, Traits> rhs,
5729 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5730 return rhs.compare(lhs) >= 0;
5731 }
5732
5733 // >
5734
5735 template <class CharT, class Traits>
5736 nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs,
5737 CharT const* rhs) nssv_noexcept {
5738 return lhs.compare(rhs) > 0;
5739 }
5740
5741 template <class CharT, class Traits>
5742 nssv_constexpr bool
5743 operator>(CharT const* lhs,
5744 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5745 return rhs.compare(lhs) < 0;
5746 }
5747
5748 template <class CharT, class Traits>
5749 nssv_constexpr bool
5750 operator>(basic_string_view<CharT, Traits> lhs,
5751 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5752 return lhs.compare(rhs) > 0;
5753 }
5754
5755 template <class CharT, class Traits>
5756 nssv_constexpr bool
5757 operator>(std::basic_string<CharT, Traits> rhs,
5758 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5759 return rhs.compare(lhs) < 0;
5760 }
5761
5762 // >=
5763
5764 template <class CharT, class Traits>
5765 nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs,
5766 CharT const* rhs) nssv_noexcept {
5767 return lhs.compare(rhs) >= 0;
5768 }
5769
5770 template <class CharT, class Traits>
5771 nssv_constexpr bool
5772 operator>=(CharT const* lhs,
5773 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5774 return rhs.compare(lhs) <= 0;
5775 }
5776
5777 template <class CharT, class Traits>
5778 nssv_constexpr bool
5779 operator>=(basic_string_view<CharT, Traits> lhs,
5780 std::basic_string<CharT, Traits> rhs) nssv_noexcept {
5781 return lhs.compare(rhs) >= 0;
5782 }
5783
5784 template <class CharT, class Traits>
5785 nssv_constexpr bool
5786 operator>=(std::basic_string<CharT, Traits> rhs,
5787 basic_string_view<CharT, Traits> lhs) nssv_noexcept {
5788 return rhs.compare(lhs) <= 0;
5789 }
5790
5791#else // newer compilers:
5792
5793#define nssv_BASIC_STRING_VIEW_I(T, U) \
5794 typename std::decay<basic_string_view<T, U>>::type
5795
5796#if defined(_MSC_VER) // issue 40
5797#define nssv_MSVC_ORDER(x) , int = x
5798#else
5799#define nssv_MSVC_ORDER(x) /*, int=x*/
5800#endif
5801
5802 // ==
5803
5804 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5805 nssv_constexpr bool operator==(basic_string_view<CharT, Traits> lhs,
5806 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5807 rhs) nssv_noexcept {
5808 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
5809 }
5810
5811 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5812 nssv_constexpr bool
5813 operator==(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5814 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5815 return lhs.size() == rhs.size() && lhs.compare(rhs) == 0;
5816 }
5817
5818 // !=
5819
5820 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5821 nssv_constexpr bool operator!=(basic_string_view<CharT, Traits> lhs,
5822 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5823 rhs) nssv_noexcept {
5824 return !(lhs == rhs);
5825 }
5826
5827 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5828 nssv_constexpr bool
5829 operator!=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5830 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5831 return !(lhs == rhs);
5832 }
5833
5834 // <
5835
5836 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5837 nssv_constexpr bool operator<(basic_string_view<CharT, Traits> lhs,
5838 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5839 rhs) nssv_noexcept {
5840 return lhs.compare(rhs) < 0;
5841 }
5842
5843 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5844 nssv_constexpr bool
5845 operator<(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5846 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5847 return lhs.compare(rhs) < 0;
5848 }
5849
5850 // <=
5851
5852 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5853 nssv_constexpr bool operator<=(basic_string_view<CharT, Traits> lhs,
5854 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5855 rhs) nssv_noexcept {
5856 return lhs.compare(rhs) <= 0;
5857 }
5858
5859 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5860 nssv_constexpr bool
5861 operator<=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5862 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5863 return lhs.compare(rhs) <= 0;
5864 }
5865
5866 // >
5867
5868 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5869 nssv_constexpr bool operator>(basic_string_view<CharT, Traits> lhs,
5870 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5871 rhs) nssv_noexcept {
5872 return lhs.compare(rhs) > 0;
5873 }
5874
5875 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5876 nssv_constexpr bool
5877 operator>(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5878 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5879 return lhs.compare(rhs) > 0;
5880 }
5881
5882 // >=
5883
5884 template <class CharT, class Traits nssv_MSVC_ORDER(1)>
5885 nssv_constexpr bool operator>=(basic_string_view<CharT, Traits> lhs,
5886 nssv_BASIC_STRING_VIEW_I(CharT, Traits)
5887 rhs) nssv_noexcept {
5888 return lhs.compare(rhs) >= 0;
5889 }
5890
5891 template <class CharT, class Traits nssv_MSVC_ORDER(2)>
5892 nssv_constexpr bool
5893 operator>=(nssv_BASIC_STRING_VIEW_I(CharT, Traits) lhs,
5894 basic_string_view<CharT, Traits> rhs) nssv_noexcept {
5895 return lhs.compare(rhs) >= 0;
5896 }
5897
5898#undef nssv_MSVC_ORDER
5899#undef nssv_BASIC_STRING_VIEW_I
5900
5901#endif // compiler-dependent approach to comparisons
5902
5903 // 24.4.4 Inserters and extractors:
5904
5905#if !nssv_CONFIG_NO_STREAM_INSERTION
5906
5907 namespace detail {
5908
5909 template <class Stream> void write_padding(Stream& os, std::streamsize n) {
5910 for (std::streamsize i = 0; i < n; ++i)
5911 os.rdbuf()->sputc(os.fill());
5912 }
5913
5914 template <class Stream, class View>
5915 Stream& write_to_stream(Stream& os, View const& sv) {
5916 typename Stream::sentry sentry(os);
5917
5918 if (!os)
5919 return os;
5920
5921 const std::streamsize length =
5922 static_cast<std::streamsize>(sv.length());
5923
5924 // Whether, and how, to pad:
5925 const bool pad = (length < os.width());
5926 const bool left_pad =
5927 pad &&
5928 (os.flags() & std::ios_base::adjustfield) == std::ios_base::right;
5929
5930 if (left_pad)
5931 write_padding(os, os.width() - length);
5932
5933 // Write span characters:
5934 os.rdbuf()->sputn(sv.begin(), length);
5935
5936 if (pad && !left_pad)
5937 write_padding(os, os.width() - length);
5938
5939 // Reset output stream width:
5940 os.width(0);
5941
5942 return os;
5943 }
5944
5945 } // namespace detail
5946
5947 template <class CharT, class Traits>
5948 std::basic_ostream<CharT, Traits>&
5949 operator<<(std::basic_ostream<CharT, Traits>& os,
5950 basic_string_view<CharT, Traits> sv) {
5951 return detail::write_to_stream(os, sv);
5952 }
5953
5954#endif // nssv_CONFIG_NO_STREAM_INSERTION
5955
5956 // Several typedefs for common character types are provided:
5957
5958 typedef basic_string_view<char> string_view;
5959 typedef basic_string_view<wchar_t> wstring_view;
5960#if nssv_HAVE_WCHAR16_T
5961 typedef basic_string_view<char16_t> u16string_view;
5962 typedef basic_string_view<char32_t> u32string_view;
5963#endif
5964
5965 } // namespace sv_lite
5966} // namespace nonstd::sv_lite
5967
5968//
5969// 24.4.6 Suffix for basic_string_view literals:
5970//
5971
5972#if nssv_HAVE_USER_DEFINED_LITERALS
5973
5974namespace nonstd {
5975nssv_inline_ns namespace literals {
5976 nssv_inline_ns namespace string_view_literals {
5977
5978#if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
5979
5980 nssv_constexpr nonstd::sv_lite::string_view operator"" sv(
5981 const char* str, size_t len) nssv_noexcept // (1)
5982 {
5983 return nonstd::sv_lite::string_view{str, len};
5984 }
5985
5986 nssv_constexpr nonstd::sv_lite::u16string_view operator"" sv(
5987 const char16_t* str, size_t len) nssv_noexcept // (2)
5988 {
5989 return nonstd::sv_lite::u16string_view{str, len};
5990 }
5991
5992 nssv_constexpr nonstd::sv_lite::u32string_view operator"" sv(
5993 const char32_t* str, size_t len) nssv_noexcept // (3)
5994 {
5995 return nonstd::sv_lite::u32string_view{str, len};
5996 }
5997
5998 nssv_constexpr nonstd::sv_lite::wstring_view operator"" sv(
5999 const wchar_t* str, size_t len) nssv_noexcept // (4)
6000 {
6001 return nonstd::sv_lite::wstring_view{str, len};
6002 }
6003
6004#endif // nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS
6005
6006#if nssv_CONFIG_USR_SV_OPERATOR
6007
6008 nssv_constexpr nonstd::sv_lite::string_view operator"" _sv(
6009 const char* str, size_t len) nssv_noexcept // (1)
6010 {
6011 return nonstd::sv_lite::string_view{str, len};
6012 }
6013
6014 nssv_constexpr nonstd::sv_lite::u16string_view operator"" _sv(
6015 const char16_t* str, size_t len) nssv_noexcept // (2)
6016 {
6017 return nonstd::sv_lite::u16string_view{str, len};
6018 }
6019
6020 nssv_constexpr nonstd::sv_lite::u32string_view operator"" _sv(
6021 const char32_t* str, size_t len) nssv_noexcept // (3)
6022 {
6023 return nonstd::sv_lite::u32string_view{str, len};
6024 }
6025
6026 nssv_constexpr nonstd::sv_lite::wstring_view operator"" _sv(
6027 const wchar_t* str, size_t len) nssv_noexcept // (4)
6028 {
6029 return nonstd::sv_lite::wstring_view{str, len};
6030 }
6031
6032#endif // nssv_CONFIG_USR_SV_OPERATOR
6033 }
6034}
6035} // namespace nonstd
6036
6037#endif
6038
6039//
6040// Extensions for std::string:
6041//
6042
6043#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
6044
6045namespace nonstd {
6046namespace sv_lite {
6047
6048// Exclude MSVC 14 (19.00): it yields ambiguous to_string():
6049
6050#if nssv_CPP11_OR_GREATER && nssv_COMPILER_MSVC_VERSION != 140
6051
6052template <class CharT, class Traits, class Allocator = std::allocator<CharT>>
6053std::basic_string<CharT, Traits, Allocator>
6054to_string(basic_string_view<CharT, Traits> v,
6055 Allocator const& a = Allocator()) {
6056 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
6057}
6058
6059#else
6060
6061template <class CharT, class Traits>
6062std::basic_string<CharT, Traits> to_string(basic_string_view<CharT, Traits> v) {
6063 return std::basic_string<CharT, Traits>(v.begin(), v.end());
6064}
6065
6066template <class CharT, class Traits, class Allocator>
6067std::basic_string<CharT, Traits, Allocator>
6068to_string(basic_string_view<CharT, Traits> v, Allocator const& a) {
6069 return std::basic_string<CharT, Traits, Allocator>(v.begin(), v.end(), a);
6070}
6071
6072#endif // nssv_CPP11_OR_GREATER
6073
6074template <class CharT, class Traits, class Allocator>
6075basic_string_view<CharT, Traits>
6076to_string_view(std::basic_string<CharT, Traits, Allocator> const& s) {
6077 return basic_string_view<CharT, Traits>(s.data(), s.size());
6078}
6079
6080} // namespace sv_lite
6081} // namespace nonstd
6082
6083#endif // nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
6084
6085//
6086// make types and algorithms available in namespace nonstd:
6087//
6088
6089namespace nonstd {
6090
6091using sv_lite::basic_string_view;
6092using sv_lite::string_view;
6093using sv_lite::wstring_view;
6094
6095#if nssv_HAVE_WCHAR16_T
6096using sv_lite::u16string_view;
6097#endif
6098#if nssv_HAVE_WCHAR32_T
6099using sv_lite::u32string_view;
6100#endif
6101
6102// literal "sv"
6103
6104using sv_lite::operator==;
6105using sv_lite::operator!=;
6106using sv_lite::operator<;
6107using sv_lite::operator<=;
6108using sv_lite::operator>;
6109using sv_lite::operator>=;
6110
6111#if !nssv_CONFIG_NO_STREAM_INSERTION
6112using sv_lite::operator<<;
6113#endif
6114
6115#if nssv_CONFIG_CONVERSION_STD_STRING_FREE_FUNCTIONS
6116using sv_lite::to_string;
6117using sv_lite::to_string_view;
6118#endif
6119
6120} // namespace nonstd
6121
6122// 24.4.5 Hash support (C++11):
6123
6124// Note: The hash value of a string view object is equal to the hash value of
6125// the corresponding string object.
6126
6127#if nssv_HAVE_STD_HASH
6128
6129#include <functional>
6130
6131namespace std {
6132
6133template <> struct hash<nonstd::string_view> {
6134 public:
6135 std::size_t operator()(nonstd::string_view v) const nssv_noexcept {
6136 return std::hash<std::string>()(std::string(v.data(), v.size()));
6137 }
6138};
6139
6140template <> struct hash<nonstd::wstring_view> {
6141 public:
6142 std::size_t operator()(nonstd::wstring_view v) const nssv_noexcept {
6143 return std::hash<std::wstring>()(std::wstring(v.data(), v.size()));
6144 }
6145};
6146
6147template <> struct hash<nonstd::u16string_view> {
6148 public:
6149 std::size_t operator()(nonstd::u16string_view v) const nssv_noexcept {
6150 return std::hash<std::u16string>()(std::u16string(v.data(), v.size()));
6151 }
6152};
6153
6154template <> struct hash<nonstd::u32string_view> {
6155 public:
6156 std::size_t operator()(nonstd::u32string_view v) const nssv_noexcept {
6157 return std::hash<std::u32string>()(std::u32string(v.data(), v.size()));
6158 }
6159};
6160
6161} // namespace std
6162
6163#endif // nssv_HAVE_STD_HASH
6164
6165nssv_RESTORE_WARNINGS()
6166
6167#endif // nssv_HAVE_STD_STRING_VIEW
6168#endif // NONSTD_SV_LITE_H_INCLUDED
6179
6180#ifndef TERMCOLOR_HPP_
6181#define TERMCOLOR_HPP_
6182
6183// the following snippet of code detects the current OS and
6184// defines the appropriate macro that is used to wrap some
6185// platform specific things
6186#if defined(_WIN32) || defined(_WIN64)
6187#define TERMCOLOR_OS_WINDOWS
6188#elif defined(__APPLE__)
6189#define TERMCOLOR_OS_MACOS
6190#elif defined(__unix__) || defined(__unix)
6191#define TERMCOLOR_OS_LINUX
6192#else
6193#error unsupported platform
6194#endif
6195
6196// This headers provides the `isatty()`/`fileno()` functions,
6197// which are used for testing whether a standart stream refers
6198// to the terminal. As for Windows, we also need WinApi funcs
6199// for changing colors attributes of the terminal.
6200#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6201#include <unistd.h>
6202#elif defined(TERMCOLOR_OS_WINDOWS)
6203#include <io.h>
6204#include <windows.h>
6205#endif
6206
6207#include <cstdio>
6208#include <iostream>
6209
6210namespace termcolor {
6211// Forward declaration of the `_internal` namespace.
6212// All comments are below.
6213namespace _internal {
6214// An index to be used to access a private storage of I/O streams. See
6215// colorize / nocolorize I/O manipulators for details.
6216static int colorize_index = std::ios_base::xalloc();
6217
6218inline FILE* get_standard_stream(const std::ostream& stream);
6219inline bool is_colorized(std::ostream& stream);
6220inline bool is_atty(const std::ostream& stream);
6221
6222#if defined(TERMCOLOR_OS_WINDOWS)
6223inline void win_change_attributes(std::ostream& stream, int foreground,
6224 int background = -1);
6225#endif
6226} // namespace _internal
6227
6228inline std::ostream& colorize(std::ostream& stream) {
6229 stream.iword(_internal::colorize_index) = 1L;
6230 return stream;
6231}
6232
6233inline std::ostream& nocolorize(std::ostream& stream) {
6234 stream.iword(_internal::colorize_index) = 0L;
6235 return stream;
6236}
6237
6238inline std::ostream& reset(std::ostream& stream) {
6239 if (_internal::is_colorized(stream)) {
6240#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6241 stream << "\033[00m";
6242#elif defined(TERMCOLOR_OS_WINDOWS)
6243 _internal::win_change_attributes(stream, -1, -1);
6244#endif
6245 }
6246 return stream;
6247}
6248
6249inline std::ostream& bold(std::ostream& stream) {
6250 if (_internal::is_colorized(stream)) {
6251#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6252 stream << "\033[1m";
6253#elif defined(TERMCOLOR_OS_WINDOWS)
6254#endif
6255 }
6256 return stream;
6257}
6258
6259inline std::ostream& dark(std::ostream& stream) {
6260 if (_internal::is_colorized(stream)) {
6261#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6262 stream << "\033[2m";
6263#elif defined(TERMCOLOR_OS_WINDOWS)
6264#endif
6265 }
6266 return stream;
6267}
6268
6269inline std::ostream& italic(std::ostream& stream) {
6270 if (_internal::is_colorized(stream)) {
6271#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6272 stream << "\033[3m";
6273#elif defined(TERMCOLOR_OS_WINDOWS)
6274#endif
6275 }
6276 return stream;
6277}
6278
6279inline std::ostream& underline(std::ostream& stream) {
6280 if (_internal::is_colorized(stream)) {
6281#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6282 stream << "\033[4m";
6283#elif defined(TERMCOLOR_OS_WINDOWS)
6284#endif
6285 }
6286 return stream;
6287}
6288
6289inline std::ostream& blink(std::ostream& stream) {
6290 if (_internal::is_colorized(stream)) {
6291#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6292 stream << "\033[5m";
6293#elif defined(TERMCOLOR_OS_WINDOWS)
6294#endif
6295 }
6296 return stream;
6297}
6298
6299inline std::ostream& reverse(std::ostream& stream) {
6300 if (_internal::is_colorized(stream)) {
6301#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6302 stream << "\033[7m";
6303#elif defined(TERMCOLOR_OS_WINDOWS)
6304#endif
6305 }
6306 return stream;
6307}
6308
6309inline std::ostream& concealed(std::ostream& stream) {
6310 if (_internal::is_colorized(stream)) {
6311#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6312 stream << "\033[8m";
6313#elif defined(TERMCOLOR_OS_WINDOWS)
6314#endif
6315 }
6316 return stream;
6317}
6318
6319inline std::ostream& crossed(std::ostream& stream) {
6320 if (_internal::is_colorized(stream)) {
6321#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6322 stream << "\033[9m";
6323#elif defined(TERMCOLOR_OS_WINDOWS)
6324#endif
6325 }
6326 return stream;
6327}
6328
6329inline std::ostream& grey(std::ostream& stream) {
6330 if (_internal::is_colorized(stream)) {
6331#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6332 stream << "\033[30m";
6333#elif defined(TERMCOLOR_OS_WINDOWS)
6334 _internal::win_change_attributes(stream,
6335 0 // grey (black)
6336 );
6337#endif
6338 }
6339 return stream;
6340}
6341
6342inline std::ostream& red(std::ostream& stream) {
6343 if (_internal::is_colorized(stream)) {
6344#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6345 stream << "\033[31m";
6346#elif defined(TERMCOLOR_OS_WINDOWS)
6347 _internal::win_change_attributes(stream, FOREGROUND_RED);
6348#endif
6349 }
6350 return stream;
6351}
6352
6353inline std::ostream& green(std::ostream& stream) {
6354 if (_internal::is_colorized(stream)) {
6355#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6356 stream << "\033[32m";
6357#elif defined(TERMCOLOR_OS_WINDOWS)
6358 _internal::win_change_attributes(stream, FOREGROUND_GREEN);
6359#endif
6360 }
6361 return stream;
6362}
6363
6364inline std::ostream& yellow(std::ostream& stream) {
6365 if (_internal::is_colorized(stream)) {
6366#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6367 stream << "\033[33m";
6368#elif defined(TERMCOLOR_OS_WINDOWS)
6369 _internal::win_change_attributes(stream,
6370 FOREGROUND_GREEN | FOREGROUND_RED);
6371#endif
6372 }
6373 return stream;
6374}
6375
6376inline std::ostream& blue(std::ostream& stream) {
6377 if (_internal::is_colorized(stream)) {
6378#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6379 stream << "\033[34m";
6380#elif defined(TERMCOLOR_OS_WINDOWS)
6381 _internal::win_change_attributes(stream, FOREGROUND_BLUE);
6382#endif
6383 }
6384 return stream;
6385}
6386
6387inline std::ostream& magenta(std::ostream& stream) {
6388 if (_internal::is_colorized(stream)) {
6389#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6390 stream << "\033[35m";
6391#elif defined(TERMCOLOR_OS_WINDOWS)
6392 _internal::win_change_attributes(stream,
6393 FOREGROUND_BLUE | FOREGROUND_RED);
6394#endif
6395 }
6396 return stream;
6397}
6398
6399inline std::ostream& cyan(std::ostream& stream) {
6400 if (_internal::is_colorized(stream)) {
6401#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6402 stream << "\033[36m";
6403#elif defined(TERMCOLOR_OS_WINDOWS)
6404 _internal::win_change_attributes(stream, FOREGROUND_BLUE |
6405 FOREGROUND_GREEN);
6406#endif
6407 }
6408 return stream;
6409}
6410
6411inline std::ostream& white(std::ostream& stream) {
6412 if (_internal::is_colorized(stream)) {
6413#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6414 stream << "\033[37m";
6415#elif defined(TERMCOLOR_OS_WINDOWS)
6416 _internal::win_change_attributes(
6417 stream, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED);
6418#endif
6419 }
6420 return stream;
6421}
6422
6423inline std::ostream& on_grey(std::ostream& stream) {
6424 if (_internal::is_colorized(stream)) {
6425#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6426 stream << "\033[40m";
6427#elif defined(TERMCOLOR_OS_WINDOWS)
6428 _internal::win_change_attributes(stream, -1,
6429 0 // grey (black)
6430 );
6431#endif
6432 }
6433 return stream;
6434}
6435
6436inline std::ostream& on_red(std::ostream& stream) {
6437 if (_internal::is_colorized(stream)) {
6438#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6439 stream << "\033[41m";
6440#elif defined(TERMCOLOR_OS_WINDOWS)
6441 _internal::win_change_attributes(stream, -1, BACKGROUND_RED);
6442#endif
6443 }
6444 return stream;
6445}
6446
6447inline std::ostream& on_green(std::ostream& stream) {
6448 if (_internal::is_colorized(stream)) {
6449#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6450 stream << "\033[42m";
6451#elif defined(TERMCOLOR_OS_WINDOWS)
6452 _internal::win_change_attributes(stream, -1, BACKGROUND_GREEN);
6453#endif
6454 }
6455 return stream;
6456}
6457
6458inline std::ostream& on_yellow(std::ostream& stream) {
6459 if (_internal::is_colorized(stream)) {
6460#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6461 stream << "\033[43m";
6462#elif defined(TERMCOLOR_OS_WINDOWS)
6463 _internal::win_change_attributes(stream, -1,
6464 BACKGROUND_GREEN | BACKGROUND_RED);
6465#endif
6466 }
6467 return stream;
6468}
6469
6470inline std::ostream& on_blue(std::ostream& stream) {
6471 if (_internal::is_colorized(stream)) {
6472#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6473 stream << "\033[44m";
6474#elif defined(TERMCOLOR_OS_WINDOWS)
6475 _internal::win_change_attributes(stream, -1, BACKGROUND_BLUE);
6476#endif
6477 }
6478 return stream;
6479}
6480
6481inline std::ostream& on_magenta(std::ostream& stream) {
6482 if (_internal::is_colorized(stream)) {
6483#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6484 stream << "\033[45m";
6485#elif defined(TERMCOLOR_OS_WINDOWS)
6486 _internal::win_change_attributes(stream, -1,
6487 BACKGROUND_BLUE | BACKGROUND_RED);
6488#endif
6489 }
6490 return stream;
6491}
6492
6493inline std::ostream& on_cyan(std::ostream& stream) {
6494 if (_internal::is_colorized(stream)) {
6495#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6496 stream << "\033[46m";
6497#elif defined(TERMCOLOR_OS_WINDOWS)
6498 _internal::win_change_attributes(
6499 stream, -1, BACKGROUND_GREEN | BACKGROUND_BLUE);
6500#endif
6501 }
6502 return stream;
6503}
6504
6505inline std::ostream& on_white(std::ostream& stream) {
6506 if (_internal::is_colorized(stream)) {
6507#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6508 stream << "\033[47m";
6509#elif defined(TERMCOLOR_OS_WINDOWS)
6510 _internal::win_change_attributes(
6511 stream, -1,
6512 BACKGROUND_GREEN | BACKGROUND_BLUE | BACKGROUND_RED);
6513#endif
6514 }
6515
6516 return stream;
6517}
6518
6523namespace _internal {
6527inline FILE* get_standard_stream(const std::ostream& stream) {
6528 if (&stream == &std::cout)
6529 return stdout;
6530 else if ((&stream == &std::cerr) || (&stream == &std::clog))
6531 return stderr;
6532
6533 return 0;
6534}
6535
6536// Say whether a given stream should be colorized or not. It's always
6537// true for ATTY streams and may be true for streams marked with
6538// colorize flag.
6539inline bool is_colorized(std::ostream& stream) {
6540 return is_atty(stream) || static_cast<bool>(stream.iword(colorize_index));
6541}
6542
6545inline bool is_atty(const std::ostream& stream) {
6546 FILE* std_stream = get_standard_stream(stream);
6547
6548 // Unfortunately, fileno() ends with segmentation fault
6549 // if invalid file descriptor is passed. So we need to
6550 // handle this case gracefully and assume it's not a tty
6551 // if standard stream is not detected, and 0 is returned.
6552 if (!std_stream)
6553 return false;
6554
6555#if defined(TERMCOLOR_OS_MACOS) || defined(TERMCOLOR_OS_LINUX)
6556 return ::isatty(fileno(std_stream));
6557#elif defined(TERMCOLOR_OS_WINDOWS)
6558 return ::_isatty(_fileno(std_stream));
6559#endif
6560}
6561
6562#if defined(TERMCOLOR_OS_WINDOWS)
6565inline void win_change_attributes(std::ostream& stream, int foreground,
6566 int background) {
6567 // yeah, i know.. it's ugly, it's windows.
6568 static WORD defaultAttributes = 0;
6569
6570 // Windows doesn't have ANSI escape sequences and so we use special
6571 // API to change Terminal output color. That means we can't
6572 // manipulate colors by means of "std::stringstream" and hence
6573 // should do nothing in this case.
6574 if (!_internal::is_atty(stream))
6575 return;
6576
6577 // get terminal handle
6578 HANDLE hTerminal = INVALID_HANDLE_VALUE;
6579 if (&stream == &std::cout)
6580 hTerminal = GetStdHandle(STD_OUTPUT_HANDLE);
6581 else if (&stream == &std::cerr)
6582 hTerminal = GetStdHandle(STD_ERROR_HANDLE);
6583
6584 // save default terminal attributes if it unsaved
6585 if (!defaultAttributes) {
6586 CONSOLE_SCREEN_BUFFER_INFO info;
6587 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
6588 return;
6589 defaultAttributes = info.wAttributes;
6590 }
6591
6592 // restore all default settings
6593 if (foreground == -1 && background == -1) {
6594 SetConsoleTextAttribute(hTerminal, defaultAttributes);
6595 return;
6596 }
6597
6598 // get current settings
6599 CONSOLE_SCREEN_BUFFER_INFO info;
6600 if (!GetConsoleScreenBufferInfo(hTerminal, &info))
6601 return;
6602
6603 if (foreground != -1) {
6604 info.wAttributes &= ~(info.wAttributes & 0x0F);
6605 info.wAttributes |= static_cast<WORD>(foreground);
6606 }
6607
6608 if (background != -1) {
6609 info.wAttributes &= ~(info.wAttributes & 0xF0);
6610 info.wAttributes |= static_cast<WORD>(background);
6611 }
6612
6613 SetConsoleTextAttribute(hTerminal, info.wAttributes);
6614}
6615#endif // TERMCOLOR_OS_WINDOWS
6616
6617} // namespace _internal
6618
6619} // namespace termcolor
6620
6621#undef TERMCOLOR_OS_WINDOWS
6622#undef TERMCOLOR_OS_MACOS
6623#undef TERMCOLOR_OS_LINUX
6624
6625#endif // TERMCOLOR_HPP_
6626
6627/*
6628 __ ___. .__ __
6629_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6630\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6631 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6632 |__| (____ /___ /____/|____(____ /__| \___ >
6633 \/ \/ \/ \/
6634Table Maker for Modern C++
6635https://github.com/p-ranav/tabulate
6636
6637Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6638SPDX-License-Identifier: MIT
6639Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6640
6641Permission is hereby granted, free of charge, to any person obtaining a copy
6642of this software and associated documentation files (the "Software"), to deal
6643in the Software without restriction, including without limitation the rights
6644to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6645copies of the Software, and to permit persons to whom the Software is
6646furnished to do so, subject to the following conditions:
6647
6648The above copyright notice and this permission notice shall be included in all
6649copies or substantial portions of the Software.
6650
6651THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6652IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6653FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6654AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6655LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6656OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6657SOFTWARE.
6658*/
6659#pragma once
6660#include <algorithm>
6661#include <cstdint>
6662#include <string>
6663
6664#include <clocale>
6665#include <locale>
6666
6667#include <cstdlib>
6668// #include <tabulate/termcolor.hpp>
6669#include <wchar.h>
6670
6671namespace tabulate {
6672
6673#if defined(__unix__) || defined(__unix) || defined(__APPLE__)
6674inline int get_wcswidth(const std::string& string, const std::string& locale,
6675 size_t max_column_width) {
6676 if (string.size() == 0)
6677 return 0;
6678
6679 // The behavior of wcswidth() depends on the LC_CTYPE category of the
6680 // current locale. Set the current locale based on cell properties before
6681 // computing width
6682 auto old_locale = std::locale::global(std::locale(locale));
6683
6684 // Convert from narrow std::string to wide string
6685 wchar_t* wide_string = new wchar_t[string.size()];
6686 std::mbstowcs(wide_string, string.c_str(), string.size());
6687
6688 // Compute display width of wide string
6689 int result = wcswidth(wide_string, max_column_width);
6690 delete[] wide_string;
6691
6692 // Restore old locale
6693 std::locale::global(old_locale);
6694
6695 return result;
6696}
6697#endif
6698
6699inline size_t
6700get_sequence_length(const std::string& text, const std::string& locale,
6701 bool is_multi_byte_character_support_enabled) {
6702 if (!is_multi_byte_character_support_enabled)
6703 return text.length();
6704
6705#if defined(_WIN32) || defined(_WIN64)
6706 (void) locale; // unused parameter
6707 return (text.length() -
6708 std::count_if(text.begin(), text.end(),
6709 [](char c) -> bool { return (c & 0xC0) == 0x80; }));
6710#elif defined(__unix__) || defined(__unix) || defined(__APPLE__)
6711 auto result = get_wcswidth(text, locale, text.size());
6712 if (result >= 0)
6713 return result;
6714 else
6715 return (text.length() -
6716 std::count_if(text.begin(), text.end(), [](char c) -> bool {
6717 return (c & 0xC0) == 0x80;
6718 }));
6719#endif
6720}
6721
6722} // namespace tabulate
6723
6724/*
6725 __ ___. .__ __
6726_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6727\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6728 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6729 |__| (____ /___ /____/|____(____ /__| \___ >
6730 \/ \/ \/ \/
6731Table Maker for Modern C++
6732https://github.com/p-ranav/tabulate
6733
6734Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6735SPDX-License-Identifier: MIT
6736Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6737
6738Permission is hereby granted, free of charge, to any person obtaining a copy
6739of this software and associated documentation files (the "Software"), to deal
6740in the Software without restriction, including without limitation the rights
6741to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6742copies of the Software, and to permit persons to whom the Software is
6743furnished to do so, subject to the following conditions:
6744
6745The above copyright notice and this permission notice shall be included in all
6746copies or substantial portions of the Software.
6747
6748THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6749IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6750FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6751AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6752LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6753OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6754SOFTWARE.
6755*/
6756#pragma once
6757// #include <tabulate/termcolor.hpp>
6758
6759namespace tabulate {
6760
6761enum class Color { none, grey, red, green, yellow, blue, magenta, cyan, white };
6762}
6763
6764/*
6765 __ ___. .__ __
6766_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6767\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6768 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6769 |__| (____ /___ /____/|____(____ /__| \___ >
6770 \/ \/ \/ \/
6771Table Maker for Modern C++
6772https://github.com/p-ranav/tabulate
6773
6774Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6775SPDX-License-Identifier: MIT
6776Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6777
6778Permission is hereby granted, free of charge, to any person obtaining a copy
6779of this software and associated documentation files (the "Software"), to deal
6780in the Software without restriction, including without limitation the rights
6781to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6782copies of the Software, and to permit persons to whom the Software is
6783furnished to do so, subject to the following conditions:
6784
6785The above copyright notice and this permission notice shall be included in all
6786copies or substantial portions of the Software.
6787
6788THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6789IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6790FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6791AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6792LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6793OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6794SOFTWARE.
6795*/
6796#pragma once
6797
6798namespace tabulate {
6799
6800enum class FontAlign { left, right, center };
6801}
6802
6803/*
6804 __ ___. .__ __
6805_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6806\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6807 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6808 |__| (____ /___ /____/|____(____ /__| \___ >
6809 \/ \/ \/ \/
6810Table Maker for Modern C++
6811https://github.com/p-ranav/tabulate
6812
6813Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6814SPDX-License-Identifier: MIT
6815Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6816
6817Permission is hereby granted, free of charge, to any person obtaining a copy
6818of this software and associated documentation files (the "Software"), to deal
6819in the Software without restriction, including without limitation the rights
6820to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6821copies of the Software, and to permit persons to whom the Software is
6822furnished to do so, subject to the following conditions:
6823
6824The above copyright notice and this permission notice shall be included in all
6825copies or substantial portions of the Software.
6826
6827THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6828IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6829FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6830AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6831LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6832OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6833SOFTWARE.
6834*/
6835#pragma once
6836
6837namespace tabulate {
6838
6839enum class FontStyle {
6840 bold,
6841 dark,
6842 italic,
6843 underline,
6844 blink,
6845 reverse,
6846 concealed,
6847 crossed
6848};
6849}
6850
6851/*
6852 __ ___. .__ __
6853_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6854\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6855 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6856 |__| (____ /___ /____/|____(____ /__| \___ >
6857 \/ \/ \/ \/
6858Table Maker for Modern C++
6859https://github.com/p-ranav/tabulate
6860
6861Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6862SPDX-License-Identifier: MIT
6863Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6864
6865Permission is hereby granted, free of charge, to any person obtaining a copy
6866of this software and associated documentation files (the "Software"), to deal
6867in the Software without restriction, including without limitation the rights
6868to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6869copies of the Software, and to permit persons to whom the Software is
6870furnished to do so, subject to the following conditions:
6871
6872The above copyright notice and this permission notice shall be included in all
6873copies or substantial portions of the Software.
6874
6875THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6876IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6877FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6878AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6879LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6880OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6881SOFTWARE.
6882*/
6883#pragma once
6884#include <iostream>
6885#include <memory>
6886#include <string>
6887// #include <tabulate/format.hpp>
6888/*
6889 __ ___. .__ __
6890_/ |______ \_ |__ __ __| | _____ _/ |_ ____
6891\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
6892 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
6893 |__| (____ /___ /____/|____(____ /__| \___ >
6894 \/ \/ \/ \/
6895Table Maker for Modern C++
6896https://github.com/p-ranav/tabulate
6897
6898Licensed under the MIT License <http://opensource.org/licenses/MIT>.
6899SPDX-License-Identifier: MIT
6900Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
6901
6902Permission is hereby granted, free of charge, to any person obtaining a copy
6903of this software and associated documentation files (the "Software"), to deal
6904in the Software without restriction, including without limitation the rights
6905to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
6906copies of the Software, and to permit persons to whom the Software is
6907furnished to do so, subject to the following conditions:
6908
6909The above copyright notice and this permission notice shall be included in all
6910copies or substantial portions of the Software.
6911
6912THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
6913IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6914FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
6915AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
6916LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
6917OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
6918SOFTWARE.
6919*/
6920
6921#include <algorithm>
6922#include <cctype>
6923#include <cstddef>
6924#include <sstream>
6925#include <string>
6926// #include <tabulate/color.hpp>
6927// #include <tabulate/font_align.hpp>
6928// #include <tabulate/font_style.hpp>
6929// #include <tabulate/utf8.hpp>
6930
6931#if __cplusplus >= 201703L
6932#include <optional>
6933using std::optional;
6934#else
6935// #include <tabulate/optional_lite.hpp>
6936using nonstd::optional;
6937#endif
6938
6939#include <vector>
6940
6941namespace tabulate {
6942
6943class Format {
6944 public:
6945 Format& width(size_t value) {
6946 width_ = value;
6947 return *this;
6948 }
6949
6950 Format& height(size_t value) {
6951 height_ = value;
6952 return *this;
6953 }
6954
6955 Format& padding(size_t value) {
6956 padding_left_ = value;
6957 padding_right_ = value;
6958 padding_top_ = value;
6959 padding_bottom_ = value;
6960 return *this;
6961 }
6962
6963 Format& padding_left(size_t value) {
6964 padding_left_ = value;
6965 return *this;
6966 }
6967
6968 Format& padding_right(size_t value) {
6969 padding_right_ = value;
6970 return *this;
6971 }
6972
6973 Format& padding_top(size_t value) {
6974 padding_top_ = value;
6975 return *this;
6976 }
6977
6978 Format& padding_bottom(size_t value) {
6979 padding_bottom_ = value;
6980 return *this;
6981 }
6982
6983 Format& border(const std::string& value) {
6984 border_left_ = value;
6985 border_right_ = value;
6986 border_top_ = value;
6987 border_bottom_ = value;
6988 return *this;
6989 }
6990
6991 Format& border_color(Color value) {
6992 border_left_color_ = value;
6993 border_right_color_ = value;
6994 border_top_color_ = value;
6995 border_bottom_color_ = value;
6996 return *this;
6997 }
6998
6999 Format& border_background_color(Color value) {
7000 border_left_background_color_ = value;
7001 border_right_background_color_ = value;
7002 border_top_background_color_ = value;
7003 border_bottom_background_color_ = value;
7004 return *this;
7005 }
7006
7007 Format& border_left(const std::string& value) {
7008 border_left_ = value;
7009 return *this;
7010 }
7011
7012 Format& border_left_color(Color value) {
7013 border_left_color_ = value;
7014 return *this;
7015 }
7016
7017 Format& border_left_background_color(Color value) {
7018 border_left_background_color_ = value;
7019 return *this;
7020 }
7021
7022 Format& border_right(const std::string& value) {
7023 border_right_ = value;
7024 return *this;
7025 }
7026
7027 Format& border_right_color(Color value) {
7028 border_right_color_ = value;
7029 return *this;
7030 }
7031
7032 Format& border_right_background_color(Color value) {
7033 border_right_background_color_ = value;
7034 return *this;
7035 }
7036
7037 Format& border_top(const std::string& value) {
7038 border_top_ = value;
7039 return *this;
7040 }
7041
7042 Format& border_top_color(Color value) {
7043 border_top_color_ = value;
7044 return *this;
7045 }
7046
7047 Format& border_top_background_color(Color value) {
7048 border_top_background_color_ = value;
7049 return *this;
7050 }
7051
7052 Format& border_bottom(const std::string& value) {
7053 border_bottom_ = value;
7054 return *this;
7055 }
7056
7057 Format& border_bottom_color(Color value) {
7058 border_bottom_color_ = value;
7059 return *this;
7060 }
7061
7062 Format& border_bottom_background_color(Color value) {
7063 border_bottom_background_color_ = value;
7064 return *this;
7065 }
7066
7067 Format& show_border() {
7068 show_border_top_ = true;
7069 show_border_bottom_ = true;
7070 show_border_left_ = true;
7071 show_border_right_ = true;
7072 return *this;
7073 }
7074
7075 Format& hide_border() {
7076 show_border_top_ = false;
7077 show_border_bottom_ = false;
7078 show_border_left_ = false;
7079 show_border_right_ = false;
7080 return *this;
7081 }
7082
7083 Format& show_border_top() {
7084 show_border_top_ = true;
7085 return *this;
7086 }
7087
7088 Format& hide_border_top() {
7089 show_border_top_ = false;
7090 return *this;
7091 }
7092
7093 Format& show_border_bottom() {
7094 show_border_bottom_ = true;
7095 return *this;
7096 }
7097
7098 Format& hide_border_bottom() {
7099 show_border_bottom_ = false;
7100 return *this;
7101 }
7102
7103 Format& show_border_left() {
7104 show_border_left_ = true;
7105 return *this;
7106 }
7107
7108 Format& hide_border_left() {
7109 show_border_left_ = false;
7110 return *this;
7111 }
7112
7113 Format& show_border_right() {
7114 show_border_right_ = true;
7115 return *this;
7116 }
7117
7118 Format& hide_border_right() {
7119 show_border_right_ = false;
7120 return *this;
7121 }
7122
7123 Format& show_row_separator() {
7124 show_border_top_ = true;
7125 show_row_separator_ = true;
7126 return *this;
7127 }
7128
7129 Format& corner(const std::string& value) {
7130 corner_top_left_ = value;
7131 corner_top_right_ = value;
7132 corner_bottom_left_ = value;
7133 corner_bottom_right_ = value;
7134 return *this;
7135 }
7136
7137 Format& corner_color(Color value) {
7138 corner_top_left_color_ = value;
7139 corner_top_right_color_ = value;
7140 corner_bottom_left_color_ = value;
7141 corner_bottom_right_color_ = value;
7142 return *this;
7143 }
7144
7145 Format& corner_background_color(Color value) {
7146 corner_top_left_background_color_ = value;
7147 corner_top_right_background_color_ = value;
7148 corner_bottom_left_background_color_ = value;
7149 corner_bottom_right_background_color_ = value;
7150 return *this;
7151 }
7152
7153 Format& corner_top_left(const std::string& value) {
7154 corner_top_left_ = value;
7155 return *this;
7156 }
7157
7158 Format& corner_top_left_color(Color value) {
7159 corner_top_left_color_ = value;
7160 return *this;
7161 }
7162
7163 Format& corner_top_left_background_color(Color value) {
7164 corner_top_left_background_color_ = value;
7165 return *this;
7166 }
7167
7168 Format& corner_top_right(const std::string& value) {
7169 corner_top_right_ = value;
7170 return *this;
7171 }
7172
7173 Format& corner_top_right_color(Color value) {
7174 corner_top_right_color_ = value;
7175 return *this;
7176 }
7177
7178 Format& corner_top_right_background_color(Color value) {
7179 corner_top_right_background_color_ = value;
7180 return *this;
7181 }
7182
7183 Format& corner_bottom_left(const std::string& value) {
7184 corner_bottom_left_ = value;
7185 return *this;
7186 }
7187
7188 Format& corner_bottom_left_color(Color value) {
7189 corner_bottom_left_color_ = value;
7190 return *this;
7191 }
7192
7193 Format& corner_bottom_left_background_color(Color value) {
7194 corner_bottom_left_background_color_ = value;
7195 return *this;
7196 }
7197
7198 Format& corner_bottom_right(const std::string& value) {
7199 corner_bottom_right_ = value;
7200 return *this;
7201 }
7202
7203 Format& corner_bottom_right_color(Color value) {
7204 corner_bottom_right_color_ = value;
7205 return *this;
7206 }
7207
7208 Format& corner_bottom_right_background_color(Color value) {
7209 corner_bottom_right_background_color_ = value;
7210 return *this;
7211 }
7212
7213 Format& column_separator(const std::string& value) {
7214 column_separator_ = value;
7215 return *this;
7216 }
7217
7218 Format& column_separator_color(Color value) {
7219 column_separator_color_ = value;
7220 return *this;
7221 }
7222
7223 Format& column_separator_background_color(Color value) {
7224 column_separator_background_color_ = value;
7225 return *this;
7226 }
7227
7228 Format& font_align(FontAlign value) {
7229 font_align_ = value;
7230 return *this;
7231 }
7232
7233 Format& font_style(const std::vector<FontStyle>& style) {
7234 if (font_style_.has_value()) {
7235 for (auto& s : style)
7236 font_style_->push_back(s);
7237 } else {
7238 font_style_ = style;
7239 }
7240 return *this;
7241 }
7242
7243 Format& font_color(Color value) {
7244 font_color_ = value;
7245 return *this;
7246 }
7247
7248 Format& font_background_color(Color value) {
7249 font_background_color_ = value;
7250 return *this;
7251 }
7252
7253 Format& color(Color value) {
7254 font_color(value);
7255 border_color(value);
7256 corner_color(value);
7257 return *this;
7258 }
7259
7260 Format& background_color(Color value) {
7261 font_background_color(value);
7262 border_background_color(value);
7263 corner_background_color(value);
7264 return *this;
7265 }
7266
7267 Format& multi_byte_characters(bool value) {
7268 multi_byte_characters_ = value;
7269 return *this;
7270 }
7271
7272 Format& locale(const std::string& value) {
7273 locale_ = value;
7274 return *this;
7275 }
7276
7277 enum class TrimMode {
7278 kNone = 0,
7279 kLeft = 1 << 0,
7280 kRight = 1 << 1,
7281 kBoth = kLeft | kRight,
7282 };
7283
7284 Format& trim_mode(TrimMode trim_mode) {
7285 trim_mode_ = trim_mode;
7286 return *this;
7287 }
7288
7289 // Apply word wrap
7290 // Given an input string and a line length, this will insert \n
7291 // in strategic places in input string and apply word wrapping
7292 static std::string word_wrap(const std::string& str, size_t width,
7293 const std::string& locale,
7294 bool is_multi_byte_character_support_enabled) {
7295 std::vector<std::string> words = explode_string(str, {" ", "-", "\t"});
7296 size_t current_line_length = 0;
7297 std::string result;
7298
7299 for (size_t i = 0; i < words.size(); ++i) {
7300 std::string word = words[i];
7301 // If adding the new word to the current line would be too long,
7302 // then put it on a new line (and split it up if it's too long).
7303 if (current_line_length +
7304 get_sequence_length(
7305 word, locale, is_multi_byte_character_support_enabled) >
7306 width) {
7307 // Only move down to a new line if we have text on the current
7308 // line. Avoids situation where wrapped whitespace causes
7309 // emptylines in text.
7310 if (current_line_length > 0) {
7311 result += '\n';
7312 current_line_length = 0;
7313 }
7314
7315 // If the current word is too long to fit on a line even on it's
7316 // own then split the word up.
7317 while (get_sequence_length(
7318 word, locale,
7319 is_multi_byte_character_support_enabled) > width) {
7320 result += word.substr(0, width - 1) + "-";
7321 word = word.substr(width - 1);
7322 result += '\n';
7323 }
7324
7325 // Remove leading whitespace from the word so the new line
7326 // starts flush to the left.
7327 word = trim_left(word);
7328 }
7329 result += word;
7330 current_line_length += get_sequence_length(
7331 word, locale, is_multi_byte_character_support_enabled);
7332 }
7333 return result;
7334 }
7335
7336 static std::vector<std::string>
7337 split_lines(const std::string& text, const std::string& delimiter,
7338 const std::string& locale,
7339 bool is_multi_byte_character_support_enabled) {
7340 std::vector<std::string> result{};
7341 std::string input = text;
7342 size_t pos = 0;
7343 std::string token;
7344 while ((pos = input.find(delimiter)) != std::string::npos) {
7345 token = input.substr(0, pos);
7346 result.push_back(token);
7347 input.erase(0, pos + delimiter.length());
7348 }
7349 if (get_sequence_length(input, locale,
7350 is_multi_byte_character_support_enabled))
7351 result.push_back(input);
7352 return result;
7353 };
7354
7355 // Merge two formats
7356 // first has higher precedence
7357 // e.g., first = cell-level formatting and
7358 // second = row-level formatting
7359 // Result has attributes of both with cell-level
7360 // formatting taking precedence
7361 static Format merge(Format first, Format second) {
7362 Format result;
7363
7364 // Width and height
7365 if (first.width_.has_value())
7366 result.width_ = first.width_;
7367 else
7368 result.width_ = second.width_;
7369
7370 if (first.height_.has_value())
7371 result.height_ = first.height_;
7372 else
7373 result.height_ = second.height_;
7374
7375 // Font styling
7376 if (first.font_align_.has_value())
7377 result.font_align_ = first.font_align_;
7378 else
7379 result.font_align_ = second.font_align_;
7380
7381 if (first.font_style_.has_value()) {
7382 // Merge font styles using std::set_union
7383 std::vector<FontStyle> merged_font_style(
7384 first.font_style_->size() + second.font_style_->size());
7385#if defined(_WIN32) || defined(_WIN64)
7386 // Fixes error in Windows - Sequence not ordered
7387 std::sort(first.font_style_->begin(), first.font_style_->end());
7388 std::sort(second.font_style_->begin(), second.font_style_->end());
7389#endif
7390 std::set_union(first.font_style_->begin(), first.font_style_->end(),
7391 second.font_style_->begin(),
7392 second.font_style_->end(),
7393 merged_font_style.begin());
7394 result.font_style_ = merged_font_style;
7395 } else
7396 result.font_style_ = second.font_style_;
7397
7398 if (first.font_color_.has_value())
7399 result.font_color_ = first.font_color_;
7400 else
7401 result.font_color_ = second.font_color_;
7402
7403 if (first.font_background_color_.has_value())
7404 result.font_background_color_ = first.font_background_color_;
7405 else
7406 result.font_background_color_ = second.font_background_color_;
7407
7408 // Padding
7409 if (first.padding_left_.has_value())
7410 result.padding_left_ = first.padding_left_;
7411 else
7412 result.padding_left_ = second.padding_left_;
7413
7414 if (first.padding_top_.has_value())
7415 result.padding_top_ = first.padding_top_;
7416 else
7417 result.padding_top_ = second.padding_top_;
7418
7419 if (first.padding_right_.has_value())
7420 result.padding_right_ = first.padding_right_;
7421 else
7422 result.padding_right_ = second.padding_right_;
7423
7424 if (first.padding_bottom_.has_value())
7425 result.padding_bottom_ = first.padding_bottom_;
7426 else
7427 result.padding_bottom_ = second.padding_bottom_;
7428
7429 // Border
7430 if (first.border_left_.has_value())
7431 result.border_left_ = first.border_left_;
7432 else
7433 result.border_left_ = second.border_left_;
7434
7435 if (first.border_left_color_.has_value())
7436 result.border_left_color_ = first.border_left_color_;
7437 else
7438 result.border_left_color_ = second.border_left_color_;
7439
7440 if (first.border_left_background_color_.has_value())
7441 result.border_left_background_color_ =
7442 first.border_left_background_color_;
7443 else
7444 result.border_left_background_color_ =
7445 second.border_left_background_color_;
7446
7447 if (first.border_top_.has_value())
7448 result.border_top_ = first.border_top_;
7449 else
7450 result.border_top_ = second.border_top_;
7451
7452 if (first.border_top_color_.has_value())
7453 result.border_top_color_ = first.border_top_color_;
7454 else
7455 result.border_top_color_ = second.border_top_color_;
7456
7457 if (first.border_top_background_color_.has_value())
7458 result.border_top_background_color_ =
7459 first.border_top_background_color_;
7460 else
7461 result.border_top_background_color_ =
7462 second.border_top_background_color_;
7463
7464 if (first.border_bottom_.has_value())
7465 result.border_bottom_ = first.border_bottom_;
7466 else
7467 result.border_bottom_ = second.border_bottom_;
7468
7469 if (first.border_bottom_color_.has_value())
7470 result.border_bottom_color_ = first.border_bottom_color_;
7471 else
7472 result.border_bottom_color_ = second.border_bottom_color_;
7473
7474 if (first.border_bottom_background_color_.has_value())
7475 result.border_bottom_background_color_ =
7476 first.border_bottom_background_color_;
7477 else
7478 result.border_bottom_background_color_ =
7479 second.border_bottom_background_color_;
7480
7481 if (first.border_right_.has_value())
7482 result.border_right_ = first.border_right_;
7483 else
7484 result.border_right_ = second.border_right_;
7485
7486 if (first.border_right_color_.has_value())
7487 result.border_right_color_ = first.border_right_color_;
7488 else
7489 result.border_right_color_ = second.border_right_color_;
7490
7491 if (first.border_right_background_color_.has_value())
7492 result.border_right_background_color_ =
7493 first.border_right_background_color_;
7494 else
7495 result.border_right_background_color_ =
7496 second.border_right_background_color_;
7497
7498 if (first.show_border_top_.has_value())
7499 result.show_border_top_ = first.show_border_top_;
7500 else
7501 result.show_border_top_ = second.show_border_top_;
7502
7503 if (first.show_border_bottom_.has_value())
7504 result.show_border_bottom_ = first.show_border_bottom_;
7505 else
7506 result.show_border_bottom_ = second.show_border_bottom_;
7507
7508 if (first.show_border_left_.has_value())
7509 result.show_border_left_ = first.show_border_left_;
7510 else
7511 result.show_border_left_ = second.show_border_left_;
7512
7513 if (first.show_border_right_.has_value())
7514 result.show_border_right_ = first.show_border_right_;
7515 else
7516 result.show_border_right_ = second.show_border_right_;
7517
7518 // Corner
7519 if (first.corner_top_left_.has_value())
7520 result.corner_top_left_ = first.corner_top_left_;
7521 else
7522 result.corner_top_left_ = second.corner_top_left_;
7523
7524 if (first.corner_top_left_color_.has_value())
7525 result.corner_top_left_color_ = first.corner_top_left_color_;
7526 else
7527 result.corner_top_left_color_ = second.corner_top_left_color_;
7528
7529 if (first.corner_top_left_background_color_.has_value())
7530 result.corner_top_left_background_color_ =
7531 first.corner_top_left_background_color_;
7532 else
7533 result.corner_top_left_background_color_ =
7534 second.corner_top_left_background_color_;
7535
7536 if (first.corner_top_right_.has_value())
7537 result.corner_top_right_ = first.corner_top_right_;
7538 else
7539 result.corner_top_right_ = second.corner_top_right_;
7540
7541 if (first.corner_top_right_color_.has_value())
7542 result.corner_top_right_color_ = first.corner_top_right_color_;
7543 else
7544 result.corner_top_right_color_ = second.corner_top_right_color_;
7545
7546 if (first.corner_top_right_background_color_.has_value())
7547 result.corner_top_right_background_color_ =
7548 first.corner_top_right_background_color_;
7549 else
7550 result.corner_top_right_background_color_ =
7551 second.corner_top_right_background_color_;
7552
7553 if (first.corner_bottom_left_.has_value())
7554 result.corner_bottom_left_ = first.corner_bottom_left_;
7555 else
7556 result.corner_bottom_left_ = second.corner_bottom_left_;
7557
7558 if (first.corner_bottom_left_color_.has_value())
7559 result.corner_bottom_left_color_ = first.corner_bottom_left_color_;
7560 else
7561 result.corner_bottom_left_color_ = second.corner_bottom_left_color_;
7562
7563 if (first.corner_bottom_left_background_color_.has_value())
7564 result.corner_bottom_left_background_color_ =
7565 first.corner_bottom_left_background_color_;
7566 else
7567 result.corner_bottom_left_background_color_ =
7568 second.corner_bottom_left_background_color_;
7569
7570 if (first.corner_bottom_right_.has_value())
7571 result.corner_bottom_right_ = first.corner_bottom_right_;
7572 else
7573 result.corner_bottom_right_ = second.corner_bottom_right_;
7574
7575 if (first.corner_bottom_right_color_.has_value())
7576 result.corner_bottom_right_color_ =
7577 first.corner_bottom_right_color_;
7578 else
7579 result.corner_bottom_right_color_ =
7580 second.corner_bottom_right_color_;
7581
7582 if (first.corner_bottom_right_background_color_.has_value())
7583 result.corner_bottom_right_background_color_ =
7584 first.corner_bottom_right_background_color_;
7585 else
7586 result.corner_bottom_right_background_color_ =
7587 second.corner_bottom_right_background_color_;
7588
7589 if (first.column_separator_.has_value())
7590 result.column_separator_ = first.column_separator_;
7591 else
7592 result.column_separator_ = second.column_separator_;
7593
7594 if (first.column_separator_color_.has_value())
7595 result.column_separator_color_ = first.column_separator_color_;
7596 else
7597 result.column_separator_color_ = second.column_separator_color_;
7598
7599 if (first.column_separator_background_color_.has_value())
7600 result.column_separator_background_color_ =
7601 first.column_separator_background_color_;
7602 else
7603 result.column_separator_background_color_ =
7604 second.column_separator_background_color_;
7605
7606 // Internationlization
7607 if (first.multi_byte_characters_.has_value())
7608 result.multi_byte_characters_ = first.multi_byte_characters_;
7609 else
7610 result.multi_byte_characters_ = second.multi_byte_characters_;
7611
7612 if (first.locale_.has_value())
7613 result.locale_ = first.locale_;
7614 else
7615 result.locale_ = second.locale_;
7616
7617 if (first.trim_mode_.has_value())
7618 result.trim_mode_ = first.trim_mode_;
7619 else
7620 result.trim_mode_ = second.trim_mode_;
7621
7622 if (first.show_row_separator_.has_value())
7623 result.show_row_separator_ = first.show_row_separator_;
7624 else
7625 result.show_row_separator_ = second.show_row_separator_;
7626
7627 return result;
7628 }
7629
7630 private:
7631 friend class Cell;
7632 friend class Row;
7633 friend class Column;
7634 friend class TableInternal;
7635 friend class Printer;
7636 friend class MarkdownExporter;
7637 friend class LatexExporter;
7638 friend class AsciiDocExporter;
7639
7640 void set_defaults() {
7641 // NOTE: width and height are not set here
7642 font_align_ = FontAlign::left;
7643 font_style_ = std::vector<FontStyle>{};
7644 font_color_ = font_background_color_ = Color::none;
7645 padding_left_ = padding_right_ = 1;
7646 padding_top_ = padding_bottom_ = 0;
7647 border_top_ = border_bottom_ = "-";
7648 border_left_ = border_right_ = "|";
7649 show_border_left_ = show_border_right_ = show_border_top_ =
7650 show_border_bottom_ = true;
7651 border_top_color_ = border_top_background_color_ =
7652 border_bottom_color_ = border_bottom_background_color_ =
7653 border_left_color_ = border_left_background_color_ =
7654 border_right_color_ = border_right_background_color_ =
7655 Color::none;
7656 corner_top_left_ = corner_top_right_ = corner_bottom_left_ =
7657 corner_bottom_right_ = "+";
7658 corner_top_left_color_ = corner_top_left_background_color_ =
7659 corner_top_right_color_ = corner_top_right_background_color_ =
7660 corner_bottom_left_color_ =
7661 corner_bottom_left_background_color_ =
7662 corner_bottom_right_color_ =
7663 corner_bottom_right_background_color_ = Color::none;
7664 column_separator_ = "|";
7665 column_separator_color_ = column_separator_background_color_ =
7666 Color::none;
7667 multi_byte_characters_ = false;
7668 locale_ = "";
7669 trim_mode_ = TrimMode::kBoth;
7670 show_row_separator_ = false;
7671 }
7672
7673 // Helper methods for word wrapping:
7674
7675 // trim white spaces from the left end of an input string
7676 static std::string trim_left(const std::string& input_string) {
7677 std::string result = input_string;
7678 result.erase(result.begin(),
7679 std::find_if(result.begin(), result.end(),
7680 [](int ch) { return !std::isspace(ch); }));
7681 return result;
7682 }
7683
7684 // trim white spaces from right end of an input string
7685 static std::string trim_right(const std::string& input_string) {
7686 std::string result = input_string;
7687 result.erase(std::find_if(result.rbegin(), result.rend(),
7688 [](int ch) { return !std::isspace(ch); })
7689 .base(),
7690 result.end());
7691 return result;
7692 }
7693
7694 // trim white spaces from either end of an input string
7695 static std::string trim(const std::string& input_string) {
7696 return trim_left(trim_right(input_string));
7697 }
7698
7699 static size_t
7700 index_of_any(const std::string& input, size_t start_index,
7701 const std::vector<std::string>& split_characters) {
7702 std::vector<size_t> indices{};
7703 for (auto& c : split_characters) {
7704 auto index = input.find(c, start_index);
7705 if (index != std::string::npos)
7706 indices.push_back(index);
7707 }
7708 if (indices.size() > 0)
7709 return *std::min_element(indices.begin(), indices.end());
7710 else
7711 return std::string::npos;
7712 }
7713
7714 static std::vector<std::string>
7715 explode_string(const std::string& input,
7716 const std::vector<std::string>& split_characters) {
7717 std::vector<std::string> result{};
7718 size_t start_index{0};
7719 while (true) {
7720 auto index = index_of_any(input, start_index, split_characters);
7721
7722 if (index == std::string::npos) {
7723 result.push_back(input.substr(start_index));
7724 return result;
7725 }
7726
7727 std::string word = input.substr(start_index, index - start_index);
7728 char next_character = input.substr(index, 1)[0];
7729 // Unlike whitespace, dashes and the like should stick to the word
7730 // occurring before it.
7731 if (isspace(next_character)) {
7732 result.push_back(word);
7733 result.push_back(std::string(1, next_character));
7734 } else {
7735 result.push_back(word + next_character);
7736 }
7737 start_index = index + 1;
7738 }
7739
7740 return result;
7741 }
7742
7743 // Element width and height
7744 optional<size_t> width_{};
7745 optional<size_t> height_{};
7746
7747 // Font styling
7748 optional<FontAlign> font_align_{};
7749 optional<std::vector<FontStyle>> font_style_{};
7750 optional<Color> font_color_{};
7751 optional<Color> font_background_color_{};
7752
7753 // Element padding
7754 optional<size_t> padding_left_{};
7755 optional<size_t> padding_top_{};
7756 optional<size_t> padding_right_{};
7757 optional<size_t> padding_bottom_{};
7758
7759 // Element border
7760 optional<bool> show_border_top_{};
7761 optional<std::string> border_top_{};
7762 optional<Color> border_top_color_{};
7763 optional<Color> border_top_background_color_{};
7764
7765 optional<bool> show_border_bottom_{};
7766 optional<std::string> border_bottom_{};
7767 optional<Color> border_bottom_color_{};
7768 optional<Color> border_bottom_background_color_{};
7769
7770 optional<bool> show_border_left_{};
7771 optional<std::string> border_left_{};
7772 optional<Color> border_left_color_{};
7773 optional<Color> border_left_background_color_{};
7774
7775 optional<bool> show_border_right_{};
7776 optional<std::string> border_right_{};
7777 optional<Color> border_right_color_{};
7778 optional<Color> border_right_background_color_{};
7779
7780 // Element corner
7781 optional<std::string> corner_top_left_{};
7782 optional<Color> corner_top_left_color_{};
7783 optional<Color> corner_top_left_background_color_{};
7784
7785 optional<std::string> corner_top_right_{};
7786 optional<Color> corner_top_right_color_{};
7787 optional<Color> corner_top_right_background_color_{};
7788
7789 optional<std::string> corner_bottom_left_{};
7790 optional<Color> corner_bottom_left_color_{};
7791 optional<Color> corner_bottom_left_background_color_{};
7792
7793 optional<std::string> corner_bottom_right_{};
7794 optional<Color> corner_bottom_right_color_{};
7795 optional<Color> corner_bottom_right_background_color_{};
7796
7797 // Element column separator
7798 optional<std::string> column_separator_{};
7799 optional<Color> column_separator_color_{};
7800 optional<Color> column_separator_background_color_{};
7801
7802 // Internationalization
7803 optional<bool> multi_byte_characters_{};
7804 optional<std::string> locale_{};
7805
7806 optional<TrimMode> trim_mode_{};
7807
7808 optional<bool> show_row_separator_{};
7809};
7810
7811} // namespace tabulate
7812
7813// #include <tabulate/utf8.hpp>
7814
7815#if __cplusplus >= 201703L
7816#include <optional>
7817using std::optional;
7818#else
7819// #include <tabulate/optional_lite.hpp>
7820using nonstd::optional;
7821#endif
7822
7823#include <vector>
7824
7825namespace tabulate {
7826
7827class Cell {
7828 public:
7829 explicit Cell(std::shared_ptr<class Row> parent) : parent_(parent) {}
7830
7831 void set_text(const std::string& text) { data_ = text; }
7832
7833 const std::string& get_text() { return data_; }
7834
7835 size_t size() {
7836 return get_sequence_length(data_, locale(),
7837 is_multi_byte_character_support_enabled());
7838 }
7839
7840 std::string locale() { return *format().locale_; }
7841
7842 Format& format();
7843
7844 bool is_multi_byte_character_support_enabled();
7845
7846 private:
7847 std::string data_;
7848 std::weak_ptr<class Row> parent_;
7849 optional<Format> format_;
7850};
7851
7852} // namespace tabulate
7853
7854/*
7855 __ ___. .__ __
7856_/ |______ \_ |__ __ __| | _____ _/ |_ ____
7857\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
7858 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
7859 |__| (____ /___ /____/|____(____ /__| \___ >
7860 \/ \/ \/ \/
7861Table Maker for Modern C++
7862https://github.com/p-ranav/tabulate
7863
7864Licensed under the MIT License <http://opensource.org/licenses/MIT>.
7865SPDX-License-Identifier: MIT
7866Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
7867
7868Permission is hereby granted, free of charge, to any person obtaining a copy
7869of this software and associated documentation files (the "Software"), to deal
7870in the Software without restriction, including without limitation the rights
7871to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7872copies of the Software, and to permit persons to whom the Software is
7873furnished to do so, subject to the following conditions:
7874
7875The above copyright notice and this permission notice shall be included in all
7876copies or substantial portions of the Software.
7877
7878THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
7879IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
7880FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7881AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
7882LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
7883OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
7884SOFTWARE.
7885*/
7886#pragma once
7887#include <iostream>
7888#include <memory>
7889#include <string>
7890// #include <tabulate/cell.hpp>
7891
7892#if __cplusplus >= 201703L
7893#include <optional>
7894using std::optional;
7895#else
7896// #include <tabulate/optional_lite.hpp>
7897using nonstd::optional;
7898#endif
7899
7900#include <vector>
7901#ifdef max
7902#undef max
7903#endif
7904#ifdef min
7905#undef min
7906#endif
7907
7908namespace tabulate {
7909
7910class Row {
7911 public:
7912 explicit Row(std::shared_ptr<class TableInternal> parent)
7913 : parent_(parent) {}
7914
7915 void add_cell(std::shared_ptr<Cell> cell) { cells_.push_back(cell); }
7916
7917 Cell& operator[](size_t index) { return cell(index); }
7918
7919 Cell& cell(size_t index) { return *(cells_[index]); }
7920
7921 std::vector<std::shared_ptr<Cell>> cells() const { return cells_; }
7922
7923 size_t size() const { return cells_.size(); }
7924
7925 Format& format();
7926
7927 class CellIterator {
7928 public:
7929 explicit CellIterator(std::vector<std::shared_ptr<Cell>>::iterator ptr)
7930 : ptr(ptr) {}
7931
7932 CellIterator operator++() {
7933 ++ptr;
7934 return *this;
7935 }
7936 bool operator!=(const CellIterator& other) const {
7937 return ptr != other.ptr;
7938 }
7939 Cell& operator*() { return **ptr; }
7940
7941 private:
7942 std::vector<std::shared_ptr<Cell>>::iterator ptr;
7943 };
7944
7945 auto begin() -> CellIterator { return CellIterator(cells_.begin()); }
7946 auto end() -> CellIterator { return CellIterator(cells_.end()); }
7947
7948 private:
7949 friend class Printer;
7950
7951 // Returns the row height as configured
7952 // For each cell in the row, check the cell.format.height
7953 // property and return the largest configured row height
7954 // This is used to ensure that all cells in a row are
7955 // aligned when printing the column
7956 size_t get_configured_height() {
7957 size_t result{0};
7958 for (size_t i = 0; i < size(); ++i) {
7959 auto cell = cells_[i];
7960 auto format = cell->format();
7961 if (format.height_.has_value())
7962 result = std::max(result, *format.height_);
7963 }
7964 return result;
7965 }
7966
7967 // Computes the height of the row based on cell contents
7968 // and configured cell padding
7969 // For each cell, compute:
7970 // padding_top + (cell_contents / column height) + padding_bottom
7971 // and return the largest value
7972 //
7973 // This is useful when no cell.format.height is configured
7974 // Call get_configured_height()
7975 // - If this returns 0, then use get_computed_height()
7976 size_t get_computed_height(const std::vector<size_t>& column_widths) {
7977 size_t result{0};
7978 for (size_t i = 0; i < size(); ++i) {
7979 result = std::max(result, get_cell_height(i, column_widths[i]));
7980 }
7981 return result;
7982 }
7983
7984 // Returns padding_top + cell_contents / column_height + padding_bottom
7985 // for a given cell in the column
7986 // e.g.,
7987 // column width = 5
7988 // cell_contents = "I love tabulate" (size/length = 15)
7989 // padding top and padding bottom are 1
7990 // then, cell height = 1 + (15 / 5) + 1 = 1 + 3 + 1 = 5
7991 // The cell will look like this:
7992 //
7993 // .....
7994 // I lov
7995 // e tab
7996 // ulate
7997 // .....
7998 size_t get_cell_height(size_t cell_index, size_t column_width) {
7999 size_t result{0};
8000 Cell& cell = *(cells_[cell_index]);
8001 auto format = cell.format();
8002 auto text = cell.get_text();
8003
8004 auto padding_left = *format.padding_left_;
8005 auto padding_right = *format.padding_right_;
8006
8007 result += *format.padding_top_;
8008
8009 if (column_width > (padding_left + padding_right)) {
8010 column_width -= (padding_left + padding_right);
8011 }
8012
8013 // Check if input text has embedded newline characters
8014 auto newlines_in_text = std::count(text.begin(), text.end(), '\n');
8015 std::string word_wrapped_text;
8016 if (newlines_in_text == 0) {
8017 // No new lines in input
8018 // Apply automatic word wrapping and compute row height
8019 word_wrapped_text = Format::word_wrap(
8020 text, column_width, cell.locale(),
8021 cell.is_multi_byte_character_support_enabled());
8022 } else {
8023 // There are embedded '\n' characters
8024 // Respect these characters
8025 word_wrapped_text = text;
8026 }
8027
8028 auto newlines_in_wrapped_text = std::count(
8029 word_wrapped_text.begin(), word_wrapped_text.end(), '\n');
8030 auto estimated_row_height = newlines_in_wrapped_text;
8031
8032 if (!word_wrapped_text.empty() &&
8033 word_wrapped_text[word_wrapped_text.size() - 1] !=
8034 '\n') // text doesn't end with a newline
8035 estimated_row_height += 1;
8036
8037 result += estimated_row_height;
8038
8039 result += *format.padding_bottom_;
8040
8041 return result;
8042 }
8043
8044 std::vector<std::shared_ptr<Cell>> cells_;
8045 std::weak_ptr<class TableInternal> parent_;
8046 optional<Format> format_;
8047};
8048
8049} // namespace tabulate
8050
8051/*
8052 __ ___. .__ __
8053_/ |______ \_ |__ __ __| | _____ _/ |_ ____
8054\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
8055 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
8056 |__| (____ /___ /____/|____(____ /__| \___ >
8057 \/ \/ \/ \/
8058Table Maker for Modern C++
8059https://github.com/p-ranav/tabulate
8060
8061Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8062SPDX-License-Identifier: MIT
8063Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
8064
8065Permission is hereby granted, free of charge, to any person obtaining a copy
8066of this software and associated documentation files (the "Software"), to deal
8067in the Software without restriction, including without limitation the rights
8068to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8069copies of the Software, and to permit persons to whom the Software is
8070furnished to do so, subject to the following conditions:
8071
8072The above copyright notice and this permission notice shall be included in all
8073copies or substantial portions of the Software.
8074
8075THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8076IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8077FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8078AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8079LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8080OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8081SOFTWARE.
8082*/
8083#pragma once
8084
8085namespace tabulate {
8086
8087class ColumnFormat : public Format {
8088 public:
8089 explicit ColumnFormat(class Column& column) : column_(column) {}
8090
8091 ColumnFormat& width(size_t value);
8092 ColumnFormat& height(size_t value);
8093
8094 // Padding
8095 ColumnFormat& padding(size_t value);
8096 ColumnFormat& padding_left(size_t value);
8097 ColumnFormat& padding_right(size_t value);
8098 ColumnFormat& padding_top(size_t value);
8099 ColumnFormat& padding_bottom(size_t value);
8100
8101 // Border
8102 ColumnFormat& border(const std::string& value);
8103 ColumnFormat& border_color(Color value);
8104 ColumnFormat& border_background_color(Color value);
8105 ColumnFormat& border_left(const std::string& value);
8106 ColumnFormat& border_left_color(Color value);
8107 ColumnFormat& border_left_background_color(Color value);
8108 ColumnFormat& border_right(const std::string& value);
8109 ColumnFormat& border_right_color(Color value);
8110 ColumnFormat& border_right_background_color(Color value);
8111 ColumnFormat& border_top(const std::string& value);
8112 ColumnFormat& border_top_color(Color value);
8113 ColumnFormat& border_top_background_color(Color value);
8114 ColumnFormat& border_bottom(const std::string& value);
8115 ColumnFormat& border_bottom_color(Color value);
8116 ColumnFormat& border_bottom_background_color(Color value);
8117
8118 // Corner
8119 ColumnFormat& corner(const std::string& value);
8120 ColumnFormat& corner_color(Color value);
8121 ColumnFormat& corner_background_color(Color value);
8122
8123 // Column separator
8124 ColumnFormat& column_separator(const std::string& value);
8125 ColumnFormat& column_separator_color(Color value);
8126 ColumnFormat& column_separator_background_color(Color value);
8127
8128 // Font styling
8129 ColumnFormat& font_align(FontAlign value);
8130 ColumnFormat& font_style(const std::vector<FontStyle>& style);
8131 ColumnFormat& font_color(Color value);
8132 ColumnFormat& font_background_color(Color value);
8133 ColumnFormat& color(Color value);
8134 ColumnFormat& background_color(Color value);
8135
8136 // Locale
8137 ColumnFormat& multi_byte_characters(bool value);
8138 ColumnFormat& locale(const std::string& value);
8139
8140 private:
8141 std::reference_wrapper<class Column> column_;
8142};
8143
8144} // namespace tabulate
8145
8146/*
8147 __ ___. .__ __
8148_/ |______ \_ |__ __ __| | _____ _/ |_ ____
8149\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
8150 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
8151 |__| (____ /___ /____/|____(____ /__| \___ >
8152 \/ \/ \/ \/
8153Table Maker for Modern C++
8154https://github.com/p-ranav/tabulate
8155
8156Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8157SPDX-License-Identifier: MIT
8158Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
8159
8160Permission is hereby granted, free of charge, to any person obtaining a copy
8161of this software and associated documentation files (the "Software"), to deal
8162in the Software without restriction, including without limitation the rights
8163to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8164copies of the Software, and to permit persons to whom the Software is
8165furnished to do so, subject to the following conditions:
8166
8167The above copyright notice and this permission notice shall be included in all
8168copies or substantial portions of the Software.
8169
8170THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8171IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8172FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8173AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8174LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8175OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8176SOFTWARE.
8177*/
8178#pragma once
8179#include <algorithm>
8180#include <functional>
8181#include <iostream>
8182#include <memory>
8183
8184#if __cplusplus >= 201703L
8185#include <optional>
8186using std::optional;
8187#else
8188// #include <tabulate/optional_lite.hpp>
8189using nonstd::optional;
8190#endif
8191
8192#include <string>
8193// #include <tabulate/cell.hpp>
8194// #include <tabulate/column_format.hpp>
8195#include <vector>
8196#ifdef max
8197#undef max
8198#endif
8199#ifdef min
8200#undef min
8201#endif
8202
8203namespace tabulate {
8204
8205class Column {
8206 public:
8207 explicit Column(std::shared_ptr<class TableInternal> parent)
8208 : parent_(parent) {}
8209
8210 void add_cell(Cell& cell) { cells_.push_back(cell); }
8211
8212 Cell& operator[](size_t index) { return cells_[index]; }
8213
8214 std::vector<std::reference_wrapper<Cell>> cells() const { return cells_; }
8215
8216 size_t size() const { return cells_.size(); }
8217
8218 ColumnFormat format() { return ColumnFormat(*this); }
8219
8220 class CellIterator {
8221 public:
8222 explicit CellIterator(
8223 std::vector<std::reference_wrapper<Cell>>::iterator ptr)
8224 : ptr(ptr) {}
8225
8226 CellIterator operator++() {
8227 ++ptr;
8228 return *this;
8229 }
8230 bool operator!=(const CellIterator& other) const {
8231 return ptr != other.ptr;
8232 }
8233 Cell& operator*() { return *ptr; }
8234
8235 private:
8236 std::vector<std::reference_wrapper<Cell>>::iterator ptr;
8237 };
8238
8239 auto begin() -> CellIterator { return CellIterator(cells_.begin()); }
8240 auto end() -> CellIterator { return CellIterator(cells_.end()); }
8241
8242 private:
8243 friend class ColumnFormat;
8244 friend class Printer;
8245
8246 // Returns the column width as configured
8247 // For each cell in the column, check the cell.format.width
8248 // property and return the largest configured column width
8249 // This is used to ensure that all cells in a column are
8250 // aligned when printing the column
8251 size_t get_configured_width() {
8252 size_t result{0};
8253 for (size_t i = 0; i < size(); ++i) {
8254 auto cell = cells_[i];
8255 auto format = cell.get().format();
8256 if (format.width_.has_value())
8257 result = std::max(result, *format.width_);
8258 }
8259 return result;
8260 }
8261
8262 // Computes the width of the column based on cell contents
8263 // and configured cell padding
8264 // For each cell, compute padding_left + cell_contents + padding_right
8265 // and return the largest value
8266 //
8267 // This is useful when no cell.format.width is configured
8268 // Call get_configured_width()
8269 // - If this returns 0, then use get_computed_width()
8270 size_t get_computed_width() {
8271 size_t result{0};
8272 for (size_t i = 0; i < size(); ++i) {
8273 result = std::max(result, get_cell_width(i));
8274 }
8275 return result;
8276 }
8277
8278 // Returns padding_left + cell_contents.size() + padding_right
8279 // for a given cell in the column
8280 size_t get_cell_width(size_t cell_index) {
8281 size_t result{0};
8282 Cell& cell = cells_[cell_index].get();
8283 auto format = cell.format();
8284 if (format.padding_left_.has_value())
8285 result += *format.padding_left_;
8286
8287 // Check if input text has newlines
8288 auto text = cell.get_text();
8289 auto split_lines =
8290 Format::split_lines(text, "\n", cell.locale(),
8291 cell.is_multi_byte_character_support_enabled());
8292
8293 // If there are no newlines in input, set column_width = text.size()
8294 if (split_lines.size() == 1) {
8295 result += cell.size();
8296 } else {
8297 // There are newlines in input
8298 // Find widest substring in input and use this as column_width
8299 size_t widest_sub_string_size{0};
8300 for (auto& line : split_lines)
8301 if (get_sequence_length(
8302 line, cell.locale(),
8303 cell.is_multi_byte_character_support_enabled()) >
8304 widest_sub_string_size)
8305 widest_sub_string_size = get_sequence_length(
8306 line, cell.locale(),
8307 cell.is_multi_byte_character_support_enabled());
8308 result += widest_sub_string_size;
8309 }
8310
8311 if (format.padding_right_.has_value())
8312 result += *format.padding_right_;
8313
8314 return result;
8315 }
8316
8317 std::vector<std::reference_wrapper<Cell>> cells_;
8318 std::weak_ptr<class TableInternal> parent_;
8319};
8320
8321inline ColumnFormat& ColumnFormat::width(size_t value) {
8322 for (auto& cell : column_.get().cells_)
8323 cell.get().format().width(value);
8324 return *this;
8325}
8326
8327inline ColumnFormat& ColumnFormat::height(size_t value) {
8328 for (auto& cell : column_.get().cells_)
8329 cell.get().format().height(value);
8330 return *this;
8331}
8332
8333inline ColumnFormat& ColumnFormat::padding(size_t value) {
8334 for (auto& cell : column_.get().cells_)
8335 cell.get().format().padding(value);
8336 return *this;
8337}
8338
8339inline ColumnFormat& ColumnFormat::padding_left(size_t value) {
8340 for (auto& cell : column_.get().cells_)
8341 cell.get().format().padding_left(value);
8342 return *this;
8343}
8344
8345inline ColumnFormat& ColumnFormat::padding_right(size_t value) {
8346 for (auto& cell : column_.get().cells_)
8347 cell.get().format().padding_right(value);
8348 return *this;
8349}
8350
8351inline ColumnFormat& ColumnFormat::padding_top(size_t value) {
8352 for (auto& cell : column_.get().cells_)
8353 cell.get().format().padding_top(value);
8354 return *this;
8355}
8356
8357inline ColumnFormat& ColumnFormat::padding_bottom(size_t value) {
8358 for (auto& cell : column_.get().cells_)
8359 cell.get().format().padding_bottom(value);
8360 return *this;
8361}
8362
8363inline ColumnFormat& ColumnFormat::border(const std::string& value) {
8364 for (auto& cell : column_.get().cells_)
8365 cell.get().format().border(value);
8366 return *this;
8367}
8368
8369inline ColumnFormat& ColumnFormat::border_color(Color value) {
8370 for (auto& cell : column_.get().cells_)
8371 cell.get().format().border_color(value);
8372 return *this;
8373}
8374
8375inline ColumnFormat& ColumnFormat::border_background_color(Color value) {
8376 for (auto& cell : column_.get().cells_)
8377 cell.get().format().border_background_color(value);
8378 return *this;
8379}
8380
8381inline ColumnFormat& ColumnFormat::border_left(const std::string& value) {
8382 for (auto& cell : column_.get().cells_)
8383 cell.get().format().border_left(value);
8384 return *this;
8385}
8386
8387inline ColumnFormat& ColumnFormat::border_left_color(Color value) {
8388 for (auto& cell : column_.get().cells_)
8389 cell.get().format().border_left_color(value);
8390 return *this;
8391}
8392
8393inline ColumnFormat& ColumnFormat::border_left_background_color(Color value) {
8394 for (auto& cell : column_.get().cells_)
8395 cell.get().format().border_left_background_color(value);
8396 return *this;
8397}
8398
8399inline ColumnFormat& ColumnFormat::border_right(const std::string& value) {
8400 for (auto& cell : column_.get().cells_)
8401 cell.get().format().border_right(value);
8402 return *this;
8403}
8404
8405inline ColumnFormat& ColumnFormat::border_right_color(Color value) {
8406 for (auto& cell : column_.get().cells_)
8407 cell.get().format().border_right_color(value);
8408 return *this;
8409}
8410
8411inline ColumnFormat& ColumnFormat::border_right_background_color(Color value) {
8412 for (auto& cell : column_.get().cells_)
8413 cell.get().format().border_right_background_color(value);
8414 return *this;
8415}
8416
8417inline ColumnFormat& ColumnFormat::border_top(const std::string& value) {
8418 for (auto& cell : column_.get().cells_)
8419 cell.get().format().border_top(value);
8420 return *this;
8421}
8422
8423inline ColumnFormat& ColumnFormat::border_top_color(Color value) {
8424 for (auto& cell : column_.get().cells_)
8425 cell.get().format().border_top_color(value);
8426 return *this;
8427}
8428
8429inline ColumnFormat& ColumnFormat::border_top_background_color(Color value) {
8430 for (auto& cell : column_.get().cells_)
8431 cell.get().format().border_top_background_color(value);
8432 return *this;
8433}
8434
8435inline ColumnFormat& ColumnFormat::border_bottom(const std::string& value) {
8436 for (auto& cell : column_.get().cells_)
8437 cell.get().format().border_bottom(value);
8438 return *this;
8439}
8440
8441inline ColumnFormat& ColumnFormat::border_bottom_color(Color value) {
8442 for (auto& cell : column_.get().cells_)
8443 cell.get().format().border_bottom_color(value);
8444 return *this;
8445}
8446
8447inline ColumnFormat& ColumnFormat::border_bottom_background_color(Color value) {
8448 for (auto& cell : column_.get().cells_)
8449 cell.get().format().border_bottom_background_color(value);
8450 return *this;
8451}
8452
8453inline ColumnFormat& ColumnFormat::corner(const std::string& value) {
8454 for (auto& cell : column_.get().cells_)
8455 cell.get().format().corner(value);
8456 return *this;
8457}
8458
8459inline ColumnFormat& ColumnFormat::corner_color(Color value) {
8460 for (auto& cell : column_.get().cells_)
8461 cell.get().format().corner_color(value);
8462 return *this;
8463}
8464
8465inline ColumnFormat& ColumnFormat::corner_background_color(Color value) {
8466 for (auto& cell : column_.get().cells_)
8467 cell.get().format().corner_background_color(value);
8468 return *this;
8469}
8470
8471inline ColumnFormat& ColumnFormat::column_separator(const std::string& value) {
8472 for (auto& cell : column_.get().cells_)
8473 cell.get().format().column_separator(value);
8474 return *this;
8475}
8476
8477inline ColumnFormat& ColumnFormat::column_separator_color(Color value) {
8478 for (auto& cell : column_.get().cells_)
8479 cell.get().format().column_separator_color(value);
8480 return *this;
8481}
8482
8483inline ColumnFormat&
8484ColumnFormat::column_separator_background_color(Color value) {
8485 for (auto& cell : column_.get().cells_)
8486 cell.get().format().column_separator_background_color(value);
8487 return *this;
8488}
8489
8490inline ColumnFormat& ColumnFormat::font_align(FontAlign value) {
8491 for (auto& cell : column_.get().cells_)
8492 cell.get().format().font_align(value);
8493 return *this;
8494}
8495
8496inline ColumnFormat&
8497ColumnFormat::font_style(const std::vector<FontStyle>& style) {
8498 for (auto& cell : column_.get().cells_)
8499 cell.get().format().font_style(style);
8500 return *this;
8501}
8502
8503inline ColumnFormat& ColumnFormat::font_color(Color value) {
8504 for (auto& cell : column_.get().cells_)
8505 cell.get().format().font_color(value);
8506 return *this;
8507}
8508
8509inline ColumnFormat& ColumnFormat::font_background_color(Color value) {
8510 for (auto& cell : column_.get().cells_)
8511 cell.get().format().font_background_color(value);
8512 return *this;
8513}
8514
8515inline ColumnFormat& ColumnFormat::color(Color value) {
8516 for (auto& cell : column_.get().cells_)
8517 cell.get().format().color(value);
8518 return *this;
8519}
8520
8521inline ColumnFormat& ColumnFormat::background_color(Color value) {
8522 for (auto& cell : column_.get().cells_)
8523 cell.get().format().background_color(value);
8524 return *this;
8525}
8526
8527inline ColumnFormat& ColumnFormat::multi_byte_characters(bool value) {
8528 for (auto& cell : column_.get().cells_)
8529 cell.get().format().multi_byte_characters(value);
8530 return *this;
8531}
8532
8533inline ColumnFormat& ColumnFormat::locale(const std::string& value) {
8534 for (auto& cell : column_.get().cells_)
8535 cell.get().format().locale(value);
8536 return *this;
8537}
8538
8539} // namespace tabulate
8540
8541/*
8542 __ ___. .__ __
8543_/ |______ \_ |__ __ __| | _____ _/ |_ ____
8544\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
8545 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
8546 |__| (____ /___ /____/|____(____ /__| \___ >
8547 \/ \/ \/ \/
8548Table Maker for Modern C++
8549https://github.com/p-ranav/tabulate
8550
8551Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8552SPDX-License-Identifier: MIT
8553Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
8554
8555Permission is hereby granted, free of charge, to any person obtaining a copy
8556of this software and associated documentation files (the "Software"), to deal
8557in the Software without restriction, including without limitation the rights
8558to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8559copies of the Software, and to permit persons to whom the Software is
8560furnished to do so, subject to the following conditions:
8561
8562The above copyright notice and this permission notice shall be included in all
8563copies or substantial portions of the Software.
8564
8565THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8566IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8567FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8568AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8569LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8570OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8571SOFTWARE.
8572*/
8573#pragma once
8574// #include <tabulate/color.hpp>
8575// #include <tabulate/font_style.hpp>
8576#include <utility>
8577#include <vector>
8578
8579namespace tabulate {
8580
8581class Printer {
8582 public:
8583 static std::pair<std::vector<size_t>, std::vector<size_t>>
8584 compute_cell_dimensions(TableInternal& table);
8585
8586 static void print_table(std::ostream& stream, TableInternal& table);
8587
8588 static void
8589 print_row_in_cell(std::ostream& stream, TableInternal& table,
8590 const std::pair<size_t, size_t>& index,
8591 const std::pair<size_t, size_t>& dimension,
8592 size_t num_columns, size_t row_index,
8593 const std::vector<std::string>& splitted_cell_text);
8594
8595 static bool
8596 print_cell_border_top(std::ostream& stream, TableInternal& table,
8597 const std::pair<size_t, size_t>& index,
8598 const std::pair<size_t, size_t>& dimension,
8599 size_t num_columns);
8600 static bool
8601 print_cell_border_bottom(std::ostream& stream, TableInternal& table,
8602 const std::pair<size_t, size_t>& index,
8603 const std::pair<size_t, size_t>& dimension,
8604 size_t num_columns);
8605
8606 static void apply_element_style(std::ostream& stream,
8607 Color foreground_color,
8608 Color background_color,
8609 const std::vector<FontStyle>& font_style) {
8610 apply_foreground_color(stream, foreground_color);
8611 apply_background_color(stream, background_color);
8612 for (auto& style : font_style)
8613 apply_font_style(stream, style);
8614 }
8615
8616 static void reset_element_style(std::ostream& stream) {
8617 stream << termcolor::reset;
8618 }
8619
8620 private:
8621 static void print_content_left_aligned(std::ostream& stream,
8622 const std::string& cell_content,
8623 const Format& format,
8624 size_t text_with_padding_size,
8625 size_t column_width) {
8626
8627 // Apply font style
8628 apply_element_style(stream, *format.font_color_,
8629 *format.font_background_color_,
8630 *format.font_style_);
8631 stream << cell_content;
8632 // Only apply font_style to the font
8633 // Not the padding. So calling apply_element_style with font_style = {}
8634 reset_element_style(stream);
8635 apply_element_style(stream, *format.font_color_,
8636 *format.font_background_color_, {});
8637
8638 if (text_with_padding_size < column_width) {
8639 for (size_t j = 0; j < (column_width - text_with_padding_size);
8640 ++j) {
8641 stream << " ";
8642 }
8643 }
8644 }
8645
8646 static void print_content_center_aligned(std::ostream& stream,
8647 const std::string& cell_content,
8648 const Format& format,
8649 size_t text_with_padding_size,
8650 size_t column_width) {
8651 auto num_spaces = column_width - text_with_padding_size;
8652 if (num_spaces % 2 == 0) {
8653 // Even spacing on either side
8654 for (size_t j = 0; j < num_spaces / 2; ++j)
8655 stream << " ";
8656
8657 // Apply font style
8658 apply_element_style(stream, *format.font_color_,
8659 *format.font_background_color_,
8660 *format.font_style_);
8661 stream << cell_content;
8662 // Only apply font_style to the font
8663 // Not the padding. So calling apply_element_style with font_style =
8664 // {}
8665 reset_element_style(stream);
8666 apply_element_style(stream, *format.font_color_,
8667 *format.font_background_color_, {});
8668
8669 for (size_t j = 0; j < num_spaces / 2; ++j)
8670 stream << " ";
8671 } else {
8672 auto num_spaces_before = num_spaces / 2 + 1;
8673 for (size_t j = 0; j < num_spaces_before; ++j)
8674 stream << " ";
8675
8676 // Apply font style
8677 apply_element_style(stream, *format.font_color_,
8678 *format.font_background_color_,
8679 *format.font_style_);
8680 stream << cell_content;
8681 // Only apply font_style to the font
8682 // Not the padding. So calling apply_element_style with font_style =
8683 // {}
8684 reset_element_style(stream);
8685 apply_element_style(stream, *format.font_color_,
8686 *format.font_background_color_, {});
8687
8688 for (size_t j = 0; j < num_spaces - num_spaces_before; ++j)
8689 stream << " ";
8690 }
8691 }
8692
8693 static void print_content_right_aligned(std::ostream& stream,
8694 const std::string& cell_content,
8695 const Format& format,
8696 size_t text_with_padding_size,
8697 size_t column_width) {
8698 if (text_with_padding_size < column_width) {
8699 for (size_t j = 0; j < (column_width - text_with_padding_size);
8700 ++j) {
8701 stream << " ";
8702 }
8703 }
8704
8705 // Apply font style
8706 apply_element_style(stream, *format.font_color_,
8707 *format.font_background_color_,
8708 *format.font_style_);
8709 stream << cell_content;
8710 // Only apply font_style to the font
8711 // Not the padding. So calling apply_element_style with font_style = {}
8712 reset_element_style(stream);
8713 apply_element_style(stream, *format.font_color_,
8714 *format.font_background_color_, {});
8715 }
8716
8717 static void apply_font_style(std::ostream& stream, FontStyle style) {
8718 switch (style) {
8719 case FontStyle::bold:
8720 stream << termcolor::bold;
8721 break;
8722 case FontStyle::dark:
8723 stream << termcolor::dark;
8724 break;
8725 case FontStyle::italic:
8726 stream << termcolor::italic;
8727 break;
8728 case FontStyle::underline:
8729 stream << termcolor::underline;
8730 break;
8731 case FontStyle::blink:
8732 stream << termcolor::blink;
8733 break;
8734 case FontStyle::reverse:
8735 stream << termcolor::reverse;
8736 break;
8737 case FontStyle::concealed:
8738 stream << termcolor::concealed;
8739 break;
8740 case FontStyle::crossed:
8741 stream << termcolor::crossed;
8742 break;
8743 default:
8744 break;
8745 }
8746 }
8747
8748 static void apply_foreground_color(std::ostream& stream,
8749 Color foreground_color) {
8750 switch (foreground_color) {
8751 case Color::grey:
8752 stream << termcolor::grey;
8753 break;
8754 case Color::red:
8755 stream << termcolor::red;
8756 break;
8757 case Color::green:
8758 stream << termcolor::green;
8759 break;
8760 case Color::yellow:
8761 stream << termcolor::yellow;
8762 break;
8763 case Color::blue:
8764 stream << termcolor::blue;
8765 break;
8766 case Color::magenta:
8767 stream << termcolor::magenta;
8768 break;
8769 case Color::cyan:
8770 stream << termcolor::cyan;
8771 break;
8772 case Color::white:
8773 stream << termcolor::white;
8774 break;
8775 case Color::none:
8776 default:
8777 break;
8778 }
8779 }
8780
8781 static void apply_background_color(std::ostream& stream,
8782 Color background_color) {
8783 switch (background_color) {
8784 case Color::grey:
8785 stream << termcolor::on_grey;
8786 break;
8787 case Color::red:
8788 stream << termcolor::on_red;
8789 break;
8790 case Color::green:
8791 stream << termcolor::on_green;
8792 break;
8793 case Color::yellow:
8794 stream << termcolor::on_yellow;
8795 break;
8796 case Color::blue:
8797 stream << termcolor::on_blue;
8798 break;
8799 case Color::magenta:
8800 stream << termcolor::on_magenta;
8801 break;
8802 case Color::cyan:
8803 stream << termcolor::on_cyan;
8804 break;
8805 case Color::white:
8806 stream << termcolor::on_white;
8807 break;
8808 case Color::none:
8809 default:
8810 break;
8811 }
8812 }
8813};
8814
8815} // namespace tabulate
8816
8817/*
8818 __ ___. .__ __
8819_/ |______ \_ |__ __ __| | _____ _/ |_ ____
8820\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
8821 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
8822 |__| (____ /___ /____/|____(____ /__| \___ >
8823 \/ \/ \/ \/
8824Table Maker for Modern C++
8825https://github.com/p-ranav/tabulate
8826
8827Licensed under the MIT License <http://opensource.org/licenses/MIT>.
8828SPDX-License-Identifier: MIT
8829Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
8830
8831Permission is hereby granted, free of charge, to any person obtaining a copy
8832of this software and associated documentation files (the "Software"), to deal
8833in the Software without restriction, including without limitation the rights
8834to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8835copies of the Software, and to permit persons to whom the Software is
8836furnished to do so, subject to the following conditions:
8837
8838The above copyright notice and this permission notice shall be included in all
8839copies or substantial portions of the Software.
8840
8841THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
8842IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
8843FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
8844AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8845LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
8846OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
8847SOFTWARE.
8848*/
8849#pragma once
8850#include <algorithm>
8851#include <iostream>
8852#include <string>
8853// #include <tabulate/column.hpp>
8854// #include <tabulate/font_style.hpp>
8855// #include <tabulate/printer.hpp>
8856// #include <tabulate/row.hpp>
8857// #include <tabulate/termcolor.hpp>
8858#include <vector>
8859#ifdef max
8860#undef max
8861#endif
8862#ifdef min
8863#undef min
8864#endif
8865
8866namespace tabulate {
8867
8868class TableInternal : public std::enable_shared_from_this<TableInternal> {
8869 public:
8870 static std::shared_ptr<TableInternal> create() {
8871 auto result = std::shared_ptr<TableInternal>(new TableInternal());
8872 result->format_.set_defaults();
8873 return result;
8874 }
8875
8876 void add_row(const std::vector<std::string>& cells) {
8877 auto row = std::make_shared<Row>(shared_from_this());
8878 for (auto& c : cells) {
8879 auto cell = std::make_shared<Cell>(row);
8880 cell->set_text(c);
8881 row->add_cell(cell);
8882 }
8883 rows_.push_back(row);
8884 }
8885
8886 Row& operator[](size_t index) { return *(rows_[index]); }
8887
8888 const Row& operator[](size_t index) const { return *(rows_[index]); }
8889
8890 Column column(size_t index) {
8891 Column column(shared_from_this());
8892 for (size_t i = 0; i < rows_.size(); ++i) {
8893 auto row = rows_[i];
8894 auto& cell = row->cell(index);
8895 column.add_cell(cell);
8896 }
8897 return column;
8898 }
8899
8900 size_t size() const { return rows_.size(); }
8901
8902 std::pair<size_t, size_t> shape() {
8903 std::pair<size_t, size_t> result{0, 0};
8904 std::stringstream stream;
8905 print(stream);
8906 auto buffer = stream.str();
8907 auto lines = Format::split_lines(buffer, "\n", "", true);
8908 if (lines.size()) {
8909 result = {get_sequence_length(lines[0], "", true), lines.size()};
8910 }
8911 return result;
8912 }
8913
8914 Format& format() { return format_; }
8915
8916 void print(std::ostream& stream) { Printer::print_table(stream, *this); }
8917
8918 size_t estimate_num_columns() const {
8919 size_t result{0};
8920 if (size()) {
8921 auto first_row = operator[](size_t(0));
8922 result = first_row.size();
8923 }
8924 return result;
8925 }
8926
8927 private:
8928 friend class Table;
8929 friend class MarkdownExporter;
8930
8931 TableInternal() {}
8932 TableInternal& operator=(const TableInternal&);
8933 TableInternal(const TableInternal&);
8934
8935 std::vector<std::shared_ptr<Row>> rows_;
8936 Format format_;
8937};
8938
8939inline Format& Cell::format() {
8940 std::shared_ptr<Row> parent = parent_.lock();
8941 if (!format_.has_value()) { // no cell format
8942 format_ = parent->format(); // Use parent row format
8943 } else {
8944 // Cell has formatting
8945 // Merge cell formatting with parent row formatting
8946 format_ = Format::merge(*format_, parent->format());
8947 }
8948 return *format_;
8949}
8950
8951inline bool Cell::is_multi_byte_character_support_enabled() {
8952 return (*format().multi_byte_characters_);
8953}
8954
8955inline Format& Row::format() {
8956 std::shared_ptr<TableInternal> parent = parent_.lock();
8957 if (!format_.has_value()) { // no row format
8958 format_ = parent->format(); // Use parent table format
8959 } else {
8960 // Row has formatting rules
8961 // Merge with parent table format
8962 format_ = Format::merge(*format_, parent->format());
8963 }
8964 return *format_;
8965}
8966
8967inline std::pair<std::vector<size_t>, std::vector<size_t>>
8968Printer::compute_cell_dimensions(TableInternal& table) {
8969 std::pair<std::vector<size_t>, std::vector<size_t>> result;
8970 size_t num_rows = table.size();
8971 size_t num_columns = table.estimate_num_columns();
8972
8973 std::vector<size_t> row_heights, column_widths{};
8974
8975 for (size_t i = 0; i < num_columns; ++i) {
8976 Column column = table.column(i);
8977 size_t configured_width = column.get_configured_width();
8978 size_t computed_width = column.get_computed_width();
8979 if (configured_width != 0)
8980 column_widths.push_back(configured_width);
8981 else
8982 column_widths.push_back(computed_width);
8983 }
8984
8985 for (size_t i = 0; i < num_rows; ++i) {
8986 Row row = table[i];
8987 size_t configured_height = row.get_configured_height();
8988 size_t computed_height = row.get_computed_height(column_widths);
8989
8990 // NOTE: Unlike column width, row height is calculated as the max
8991 // b/w configured height and computed height
8992 // which means that .width() has higher precedence than .height()
8993 // when both are configured by the user
8994 //
8995 // TODO: Maybe this can be configured?
8996 // If such a configuration is exposed, i.e., prefer height over width
8997 // then the logic will be reversed, i.e.,
8998 // column_widths.push_back(std::max(configured_width, computed_width))
8999 // and
9000 // row_height = configured_height if != 0 else computed_height
9001
9002 row_heights.push_back(std::max(configured_height, computed_height));
9003 }
9004
9005 result.first = row_heights;
9006 result.second = column_widths;
9007
9008 return result;
9009}
9010
9011inline void Printer::print_table(std::ostream& stream, TableInternal& table) {
9012 size_t num_rows = table.size();
9013 size_t num_columns = table.estimate_num_columns();
9014 auto dimensions = compute_cell_dimensions(table);
9015 auto row_heights = dimensions.first;
9016 auto column_widths = dimensions.second;
9017 auto splitted_cells_text =
9018 std::vector<std::vector<std::vector<std::string>>>(
9019 num_rows, std::vector<std::vector<std::string>>(
9020 num_columns, std::vector<std::string>{}));
9021
9022 // Pre-compute the cells' content and split them into lines before actually
9023 // iterating the cells.
9024 for (size_t i = 0; i < num_rows; ++i) {
9025 Row row = table[i];
9026 for (size_t j = 0; j < num_columns; ++j) {
9027 Cell cell = row.cell(j);
9028 const std::string& text = cell.get_text();
9029 auto padding_left = *cell.format().padding_left_;
9030 auto padding_right = *cell.format().padding_right_;
9031
9032 // Check if input text has embedded \n that are to be respected
9033 bool has_new_line = text.find_first_of('\n') != std::string::npos;
9034
9035 if (has_new_line) {
9036 // Respect to the embedded '\n' characters
9037 splitted_cells_text[i][j] = Format::split_lines(
9038 text, "\n", cell.locale(),
9039 cell.is_multi_byte_character_support_enabled());
9040 } else {
9041 // If there are no embedded \n characters, then apply word wrap.
9042 //
9043 // Configured column width cannot be lower than (padding_left +
9044 // padding_right) This is a bad configuration E.g., the user is
9045 // trying to force the column width to be 5 when padding_left
9046 // and padding_right are each configured to 3 (padding_left +
9047 // padding_right) = 6 > column_width
9048 auto content_width =
9049 column_widths[j] > padding_left + padding_right
9050 ? column_widths[j] - padding_left - padding_right
9051 : column_widths[j];
9052 auto word_wrapped_text = Format::word_wrap(
9053 text, content_width, cell.locale(),
9054 cell.is_multi_byte_character_support_enabled());
9055 splitted_cells_text[i][j] = Format::split_lines(
9056 word_wrapped_text, "\n", cell.locale(),
9057 cell.is_multi_byte_character_support_enabled());
9058 }
9059 }
9060 }
9061
9062 // For each row,
9063 for (size_t i = 0; i < num_rows; ++i) {
9064
9065 // Print top border
9066 bool border_top_printed{true};
9067 for (size_t j = 0; j < num_columns; ++j) {
9068 border_top_printed &= print_cell_border_top(
9069 stream, table, {i, j}, {row_heights[i], column_widths[j]},
9070 num_columns);
9071 }
9072 if (border_top_printed)
9073 stream << termcolor::reset << "\n";
9074
9075 // Print row contents with word wrapping
9076 for (size_t k = 0; k < row_heights[i]; ++k) {
9077 for (size_t j = 0; j < num_columns; ++j) {
9078 print_row_in_cell(stream, table, {i, j},
9079 {row_heights[i], column_widths[j]},
9080 num_columns, k, splitted_cells_text[i][j]);
9081 }
9082 if (k + 1 < row_heights[i])
9083 stream << termcolor::reset << "\n";
9084 }
9085
9086 if (i + 1 == num_rows) {
9087
9088 // Check if there is bottom border to print:
9089 auto bottom_border_needed{true};
9090 for (size_t j = 0; j < num_columns; ++j) {
9091 auto cell = table[i][j];
9092 auto format = cell.format();
9093 auto corner = *format.corner_bottom_left_;
9094 auto border_bottom = *format.border_bottom_;
9095 if (corner == "" && border_bottom == "") {
9096 bottom_border_needed = false;
9097 break;
9098 }
9099 }
9100
9101 if (bottom_border_needed)
9102 stream << termcolor::reset << "\n";
9103 // Print bottom border for table
9104 for (size_t j = 0; j < num_columns; ++j) {
9105 print_cell_border_bottom(stream, table, {i, j},
9106 {row_heights[i], column_widths[j]},
9107 num_columns);
9108 }
9109 }
9110 if (i + 1 < num_rows)
9111 stream << termcolor::reset
9112 << "\n"; // Don't add newline after last row
9113 }
9114}
9115
9116inline void
9117Printer::print_row_in_cell(std::ostream& stream, TableInternal& table,
9118 const std::pair<size_t, size_t>& index,
9119 const std::pair<size_t, size_t>& dimension,
9120 size_t num_columns, size_t row_index,
9121 const std::vector<std::string>& splitted_cell_text) {
9122 auto column_width = dimension.second;
9123 auto cell = table[index.first][index.second];
9124 auto locale = cell.locale();
9125 auto is_multi_byte_character_support_enabled =
9126 cell.is_multi_byte_character_support_enabled();
9127 auto old_locale = std::locale::global(std::locale(locale));
9128 auto format = cell.format();
9129 auto text_height = splitted_cell_text.size();
9130 auto padding_top = *format.padding_top_;
9131
9132 if (*format.show_border_left_) {
9133 apply_element_style(stream, *format.border_left_color_,
9134 *format.border_left_background_color_, {});
9135 stream << *format.border_left_;
9136 reset_element_style(stream);
9137 }
9138
9139 apply_element_style(stream, *format.font_color_,
9140 *format.font_background_color_, {});
9141 if (row_index < padding_top) {
9142 // Padding top
9143 stream << std::string(column_width, ' ');
9144 } else if (row_index >= padding_top &&
9145 (row_index <= (padding_top + text_height))) {
9146 // Retrieve padding left and right
9147 // (column_width - padding_left - padding_right) is the amount of space
9148 // available for cell text - Use this to word wrap cell contents
9149 auto padding_left = *format.padding_left_;
9150 auto padding_right = *format.padding_right_;
9151
9152 if (row_index - padding_top < text_height) {
9153 auto line = splitted_cell_text[row_index - padding_top];
9154
9155 // Print left padding characters
9156 stream << std::string(padding_left, ' ');
9157
9158 // Print word-wrapped line
9159 switch (*format.trim_mode_) {
9160 case Format::TrimMode::kBoth:
9161 line = Format::trim(line);
9162 break;
9163 case Format::TrimMode::kLeft:
9164 line = Format::trim_left(line);
9165 break;
9166 case Format::TrimMode::kRight:
9167 line = Format::trim_right(line);
9168 break;
9169 case Format::TrimMode::kNone:
9170 break;
9171 }
9172
9173 auto line_with_padding_size =
9174 get_sequence_length(line, cell.locale(),
9175 is_multi_byte_character_support_enabled) +
9176 padding_left + padding_right;
9177 switch (*format.font_align_) {
9178 case FontAlign::left:
9179 print_content_left_aligned(
9180 stream, line, format, line_with_padding_size, column_width);
9181 break;
9182 case FontAlign::center:
9183 print_content_center_aligned(
9184 stream, line, format, line_with_padding_size, column_width);
9185 break;
9186 case FontAlign::right:
9187 print_content_right_aligned(
9188 stream, line, format, line_with_padding_size, column_width);
9189 break;
9190 }
9191
9192 // Print right padding characters
9193 stream << std::string(padding_right, ' ');
9194 } else
9195 stream << std::string(column_width, ' ');
9196
9197 } else {
9198 // Padding bottom
9199 stream << std::string(column_width, ' ');
9200 }
9201
9202 reset_element_style(stream);
9203
9204 if (index.second + 1 == num_columns) {
9205 // Print right border after last column
9206 if (*format.show_border_right_) {
9207 apply_element_style(stream, *format.border_right_color_,
9208 *format.border_right_background_color_, {});
9209 stream << *format.border_right_;
9210 reset_element_style(stream);
9211 }
9212 }
9213 std::locale::global(old_locale);
9214}
9215
9216inline bool
9217Printer::print_cell_border_top(std::ostream& stream, TableInternal& table,
9218 const std::pair<size_t, size_t>& index,
9219 const std::pair<size_t, size_t>& dimension,
9220 size_t num_columns) {
9221 auto cell = table[index.first][index.second];
9222 auto locale = cell.locale();
9223 auto old_locale = std::locale::global(std::locale(locale));
9224 auto format = cell.format();
9225 auto column_width = dimension.second;
9226
9227 auto corner = *format.corner_top_left_;
9228 auto corner_color = *format.corner_top_left_color_;
9229 auto corner_background_color = *format.corner_top_left_background_color_;
9230 auto border_top = *format.border_top_;
9231
9232 if ((corner == "" && border_top == "") || !*format.show_border_top_)
9233 return false;
9234
9235 apply_element_style(stream, corner_color, corner_background_color, {});
9236 if (*format.show_row_separator_) {
9237 if (index.first != 0)
9238 stream << corner;
9239 else
9240 stream << " ";
9241 } else
9242 stream << corner;
9243 reset_element_style(stream);
9244
9245 for (size_t i = 0; i < column_width; ++i) {
9246 apply_element_style(stream, *format.border_top_color_,
9247 *format.border_top_background_color_, {});
9248 if (*format.show_row_separator_) {
9249 if (index.first != 0)
9250 stream << border_top;
9251 else
9252 stream << " ";
9253 } else
9254 stream << border_top;
9255 reset_element_style(stream);
9256 }
9257
9258 if (index.second + 1 == num_columns) {
9259 // Print corner after last column
9260 corner = *format.corner_top_right_;
9261 corner_color = *format.corner_top_right_color_;
9262 corner_background_color = *format.corner_top_right_background_color_;
9263
9264 apply_element_style(stream, corner_color, corner_background_color, {});
9265 if (*format.show_row_separator_) {
9266 if (index.first != 0)
9267 stream << corner;
9268 else
9269 stream << " ";
9270 } else
9271 stream << corner;
9272 reset_element_style(stream);
9273 }
9274 std::locale::global(old_locale);
9275 return true;
9276}
9277
9278inline bool
9279Printer::print_cell_border_bottom(std::ostream& stream, TableInternal& table,
9280 const std::pair<size_t, size_t>& index,
9281 const std::pair<size_t, size_t>& dimension,
9282 size_t num_columns) {
9283 auto cell = table[index.first][index.second];
9284 auto locale = cell.locale();
9285 auto old_locale = std::locale::global(std::locale(locale));
9286 auto format = cell.format();
9287 auto column_width = dimension.second;
9288
9289 auto corner = *format.corner_bottom_left_;
9290 auto corner_color = *format.corner_bottom_left_color_;
9291 auto corner_background_color = *format.corner_bottom_left_background_color_;
9292 auto border_bottom = *format.border_bottom_;
9293
9294 if ((corner == "" && border_bottom == "") || !*format.show_border_bottom_)
9295 return false;
9296
9297 apply_element_style(stream, corner_color, corner_background_color, {});
9298 stream << corner;
9299 reset_element_style(stream);
9300
9301 for (size_t i = 0; i < column_width; ++i) {
9302 apply_element_style(stream, *format.border_bottom_color_,
9303 *format.border_bottom_background_color_, {});
9304 stream << border_bottom;
9305 reset_element_style(stream);
9306 }
9307
9308 if (index.second + 1 == num_columns) {
9309 // Print corner after last column
9310 corner = *format.corner_bottom_right_;
9311 corner_color = *format.corner_bottom_right_color_;
9312 corner_background_color = *format.corner_bottom_right_background_color_;
9313
9314 apply_element_style(stream, corner_color, corner_background_color, {});
9315 stream << corner;
9316 reset_element_style(stream);
9317 }
9318 std::locale::global(old_locale);
9319 return true;
9320}
9321
9322} // namespace tabulate
9323
9324/*
9325 __ ___. .__ __
9326_/ |______ \_ |__ __ __| | _____ _/ |_ ____
9327\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
9328 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
9329 |__| (____ /___ /____/|____(____ /__| \___ >
9330 \/ \/ \/ \/
9331Table Maker for Modern C++
9332https://github.com/p-ranav/tabulate
9333
9334Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9335SPDX-License-Identifier: MIT
9336Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
9337
9338Permission is hereby granted, free of charge, to any person obtaining a copy
9339of this software and associated documentation files (the "Software"), to deal
9340in the Software without restriction, including without limitation the rights
9341to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9342copies of the Software, and to permit persons to whom the Software is
9343furnished to do so, subject to the following conditions:
9344
9345The above copyright notice and this permission notice shall be included in all
9346copies or substantial portions of the Software.
9347
9348THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9349IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9350FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9351AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9352LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9353OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9354SOFTWARE.
9355*/
9356#pragma once
9357// #include <tabulate/table_internal.hpp>
9358
9359#if __cplusplus >= 201703L
9360#include <string_view>
9361#include <variant>
9362using std::get_if;
9363using std::holds_alternative;
9364using std::string_view;
9365using std::variant;
9366using std::visit;
9367#else
9368// #include <tabulate/string_view_lite.hpp>
9369// #include <tabulate/variant_lite.hpp>
9370using nonstd::get_if;
9371using nonstd::holds_alternative;
9372using nonstd::string_view;
9373using nonstd::variant;
9374using nonstd::visit;
9375#endif
9376
9377#include <utility>
9378
9379namespace tabulate {
9380
9381class Table {
9382 public:
9383 Table() : table_(TableInternal::create()) {}
9384
9385 using Row_t =
9386 std::vector<variant<std::string, const char*, string_view, Table>>;
9387
9388 Table& add_row(const Row_t& cells) {
9389
9390 if (rows_ == 0) {
9391 // This is the first row added
9392 // cells.size() is the number of columns
9393 cols_ = cells.size();
9394 }
9395
9396 std::vector<std::string> cell_strings;
9397 if (cells.size() < cols_) {
9398 cell_strings.resize(cols_);
9399 std::fill(cell_strings.begin(), cell_strings.end(), "");
9400 } else {
9401 cell_strings.resize(cells.size());
9402 std::fill(cell_strings.begin(), cell_strings.end(), "");
9403 }
9404
9405 for (size_t i = 0; i < cells.size(); ++i) {
9406 auto cell = cells[i];
9407 if (holds_alternative<std::string>(cell)) {
9408 cell_strings[i] = *get_if<std::string>(&cell);
9409 } else if (holds_alternative<const char*>(cell)) {
9410 cell_strings[i] = *get_if<const char*>(&cell);
9411 } else if (holds_alternative<string_view>(cell)) {
9412 cell_strings[i] = std::string{*get_if<string_view>(&cell)};
9413 } else {
9414 auto table = *get_if<Table>(&cell);
9415 std::stringstream stream;
9416 table.print(stream);
9417 cell_strings[i] = stream.str();
9418 }
9419 }
9420
9421 table_->add_row(cell_strings);
9422 rows_ += 1;
9423 return *this;
9424 }
9425
9426 Row& operator[](size_t index) { return row(index); }
9427
9428 Row& row(size_t index) { return (*table_)[index]; }
9429
9430 Column column(size_t index) { return table_->column(index); }
9431
9432 Format& format() { return table_->format(); }
9433
9434 void print(std::ostream& stream) { table_->print(stream); }
9435
9436 std::string str() {
9437 std::stringstream stream;
9438 print(stream);
9439 return stream.str();
9440 }
9441
9442 size_t size() const { return table_->size(); }
9443
9444 std::pair<size_t, size_t> shape() { return table_->shape(); }
9445
9446 class RowIterator {
9447 public:
9448 explicit RowIterator(std::vector<std::shared_ptr<Row>>::iterator ptr)
9449 : ptr(ptr) {}
9450
9451 RowIterator operator++() {
9452 ++ptr;
9453 return *this;
9454 }
9455 bool operator!=(const RowIterator& other) const {
9456 return ptr != other.ptr;
9457 }
9458 Row& operator*() { return **ptr; }
9459
9460 private:
9461 std::vector<std::shared_ptr<Row>>::iterator ptr;
9462 };
9463
9464 auto begin() -> RowIterator { return RowIterator(table_->rows_.begin()); }
9465 auto end() -> RowIterator { return RowIterator(table_->rows_.end()); }
9466
9467 private:
9468 friend class MarkdownExporter;
9469 friend class LatexExporter;
9470 friend class AsciiDocExporter;
9471
9472 friend std::ostream& operator<<(std::ostream& stream, const Table& table);
9473 size_t rows_{0};
9474 size_t cols_{0};
9475 std::shared_ptr<TableInternal> table_;
9476};
9477
9478inline std::ostream& operator<<(std::ostream& stream, const Table& table) {
9479 const_cast<Table&>(table).print(stream);
9480 return stream;
9481}
9482
9483class RowStream {
9484 public:
9485 operator const Table::Row_t&() const { return row_; }
9486
9487 template <typename T,
9488 typename = typename std::enable_if<!std::is_convertible<
9489 T, Table::Row_t::value_type>::value>::type>
9490 RowStream& operator<<(const T& obj) {
9491 oss_ << obj;
9492 std::string cell{oss_.str()};
9493 oss_.str("");
9494 if (!cell.empty()) {
9495 row_.push_back(cell);
9496 }
9497 return *this;
9498 }
9499
9500 RowStream& operator<<(const Table::Row_t::value_type& cell) {
9501 row_.push_back(cell);
9502 return *this;
9503 }
9504
9505 RowStream& copyfmt(const RowStream& other) {
9506 oss_.copyfmt(other.oss_);
9507 return *this;
9508 }
9509
9510 RowStream& copyfmt(const std::ios& other) {
9511 oss_.copyfmt(other);
9512 return *this;
9513 }
9514
9515 std::ostringstream::char_type fill() const { return oss_.fill(); }
9516 std::ostringstream::char_type fill(std::ostringstream::char_type ch) {
9517 return oss_.fill(ch);
9518 }
9519
9520 std::ios_base::iostate exceptions() const { return oss_.exceptions(); }
9521 void exceptions(std::ios_base::iostate except) { oss_.exceptions(except); }
9522
9523 std::locale imbue(const std::locale& loc) { return oss_.imbue(loc); }
9524 std::locale getloc() const { return oss_.getloc(); }
9525
9526 char narrow(std::ostringstream::char_type c, char dfault) const {
9527 return oss_.narrow(c, dfault);
9528 }
9529 std::ostringstream::char_type widen(char c) const { return oss_.widen(c); }
9530
9531 std::ios::fmtflags flags() const { return oss_.flags(); }
9532 std::ios::fmtflags flags(std::ios::fmtflags flags) {
9533 return oss_.flags(flags);
9534 }
9535
9536 std::ios::fmtflags setf(std::ios::fmtflags flags) {
9537 return oss_.setf(flags);
9538 }
9539 std::ios::fmtflags setf(std::ios::fmtflags flags, std::ios::fmtflags mask) {
9540 return oss_.setf(flags, mask);
9541 }
9542
9543 void unsetf(std::ios::fmtflags flags) { oss_.unsetf(flags); }
9544
9545 std::streamsize precision() const { return oss_.precision(); }
9546 std::streamsize precision(std::streamsize new_precision) {
9547 return oss_.precision(new_precision);
9548 }
9549
9550 std::streamsize width() const { return oss_.width(); }
9551 std::streamsize width(std::streamsize new_width) {
9552 return oss_.width(new_width);
9553 }
9554
9555 private:
9556 Table::Row_t row_;
9557 std::ostringstream oss_;
9558};
9559
9560} // namespace tabulate
9561
9562/*
9563 __ ___. .__ __
9564_/ |______ \_ |__ __ __| | _____ _/ |_ ____
9565\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
9566 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
9567 |__| (____ /___ /____/|____(____ /__| \___ >
9568 \/ \/ \/ \/
9569Table Maker for Modern C++
9570https://github.com/p-ranav/tabulate
9571
9572Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9573SPDX-License-Identifier: MIT
9574Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
9575
9576Permission is hereby granted, free of charge, to any person obtaining a copy
9577of this software and associated documentation files (the "Software"), to deal
9578in the Software without restriction, including without limitation the rights
9579to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9580copies of the Software, and to permit persons to whom the Software is
9581furnished to do so, subject to the following conditions:
9582
9583The above copyright notice and this permission notice shall be included in all
9584copies or substantial portions of the Software.
9585
9586THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9587IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9588FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9589AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9590LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9591OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9592SOFTWARE.
9593*/
9594#pragma once
9595#include <string>
9596// #include <tabulate/table.hpp>
9597
9598namespace tabulate {
9599
9600class Exporter {
9601 public:
9602 virtual std::string dump(Table& table) = 0;
9603 virtual ~Exporter() {}
9604};
9605
9606} // namespace tabulate
9607
9608/*
9609 __ ___. .__ __
9610_/ |______ \_ |__ __ __| | _____ _/ |_ ____
9611\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
9612 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
9613 |__| (____ /___ /____/|____(____ /__| \___ >
9614 \/ \/ \/ \/
9615Table Maker for Modern C++
9616https://github.com/p-ranav/tabulate
9617
9618Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9619SPDX-License-Identifier: MIT
9620Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
9621
9622Permission is hereby granted, free of charge, to any person obtaining a copy
9623of this software and associated documentation files (the "Software"), to deal
9624in the Software without restriction, including without limitation the rights
9625to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9626copies of the Software, and to permit persons to whom the Software is
9627furnished to do so, subject to the following conditions:
9628
9629The above copyright notice and this permission notice shall be included in all
9630copies or substantial portions of the Software.
9631
9632THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9633IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9634FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9635AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9636LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9637OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9638SOFTWARE.
9639*/
9640#pragma once
9641// #include <tabulate/exporter.hpp>
9642
9643namespace tabulate {
9644
9645class MarkdownExporter : public Exporter {
9646 public:
9647 std::string dump(Table& table) override {
9648 std::string result{""};
9649 apply_markdown_format(table);
9650 result = table.str();
9651 restore_table_format(table);
9652 return result;
9653 }
9654
9655 virtual ~MarkdownExporter() {}
9656
9657 private:
9658 void add_alignment_header_row(Table& table) {
9659 auto& rows = table.table_->rows_;
9660
9661 if (rows.size() >= 1) {
9662 auto alignment_row =
9663 std::make_shared<Row>(table.table_->shared_from_this());
9664
9665 // Create alignment header cells
9666 std::vector<std::string> alignment_cells{};
9667 for (auto& cell : table[0]) {
9668 auto format = cell.format();
9669 if (format.font_align_.value() == FontAlign::left) {
9670 alignment_cells.push_back(":----");
9671 } else if (format.font_align_.value() == FontAlign::center) {
9672 alignment_cells.push_back(":---:");
9673 } else if (format.font_align_.value() == FontAlign::right) {
9674 alignment_cells.push_back("----:");
9675 }
9676 }
9677
9678 // Add alignment header cells to alignment row
9679 for (auto& c : alignment_cells) {
9680 auto cell = std::make_shared<Cell>(alignment_row);
9681 cell->format()
9682 .hide_border_top()
9683 .hide_border_bottom()
9684 .border_left("|")
9685 .border_right("|")
9686 .column_separator("|")
9687 .corner("|");
9688 cell->set_text(c);
9689 if (c == ":---:")
9690 cell->format().font_align(FontAlign::center);
9691 else if (c == "----:")
9692 cell->format().font_align(FontAlign::right);
9693 alignment_row->add_cell(cell);
9694 }
9695
9696 // Insert alignment header row
9697 if (rows.size() > 1)
9698 rows.insert(rows.begin() + 1, alignment_row);
9699 else
9700 rows.push_back(alignment_row);
9701 }
9702 }
9703
9704 void remove_alignment_header_row(Table& table) {
9705 auto& rows = table.table_->rows_;
9706 table.table_->rows_.erase(rows.begin() + 1);
9707 }
9708
9709 void apply_markdown_format(Table& table) {
9710 // Apply markdown format to cells in each row
9711 for (auto row : table) {
9712 for (auto& cell : row) {
9713 auto format = cell.format();
9714 formats_.push_back(format);
9715 cell.format()
9716 .hide_border_top()
9717 .hide_border_bottom()
9718 .border_left("|")
9719 .border_right("|")
9720 .column_separator("|")
9721 .corner("|");
9722 }
9723 }
9724 // Add alignment header row at position 1
9725 add_alignment_header_row(table);
9726 }
9727
9728 void restore_table_format(Table& table) {
9729 // Remove alignment header row at position 1
9730 remove_alignment_header_row(table);
9731
9732 // Restore original formatting for each cell
9733 size_t format_index{0};
9734 for (auto row : table) {
9735 for (auto& cell : row) {
9736 cell.format() = formats_[format_index];
9737 format_index += 1;
9738 }
9739 }
9740 }
9741
9742 std::vector<Format> formats_;
9743};
9744
9745} // namespace tabulate
9746
9747/*
9748 __ ___. .__ __
9749_/ |______ \_ |__ __ __| | _____ _/ |_ ____
9750\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
9751 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
9752 |__| (____ /___ /____/|____(____ /__| \___ >
9753 \/ \/ \/ \/
9754Table Maker for Modern C++
9755https://github.com/p-ranav/tabulate
9756
9757Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9758SPDX-License-Identifier: MIT
9759Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
9760
9761Permission is hereby granted, free of charge, to any person obtaining a copy
9762of this software and associated documentation files (the "Software"), to deal
9763in the Software without restriction, including without limitation the rights
9764to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9765copies of the Software, and to permit persons to whom the Software is
9766furnished to do so, subject to the following conditions:
9767
9768The above copyright notice and this permission notice shall be included in all
9769copies or substantial portions of the Software.
9770
9771THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9772IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9773FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9774AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9775LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9776OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9777SOFTWARE.
9778*/
9779#pragma once
9780// #include <tabulate/exporter.hpp>
9781
9782#if __cplusplus >= 201703L
9783#include <optional>
9784using std::optional;
9785#else
9786// #include <tabulate/optional_lite.hpp>
9787using nonstd::optional;
9788#endif
9789
9790namespace tabulate {
9791
9792class LatexExporter : public Exporter {
9793
9794 static const char new_line = '\n';
9795
9796 public:
9797 class ExportOptions {
9798 public:
9799 ExportOptions& indentation(std::size_t value) {
9800 indentation_ = value;
9801 return *this;
9802 }
9803
9804 private:
9805 friend class LatexExporter;
9806 optional<size_t> indentation_;
9807 };
9808
9809 ExportOptions& configure() { return options_; }
9810
9811 std::string dump(Table& table) override {
9812 std::string result{"\\begin{tabular}"};
9813 result += new_line;
9814
9815 result += add_alignment_header(table);
9816 result += new_line;
9817 const auto rows = table.rows_;
9818 // iterate content and put text into the table.
9819 for (size_t i = 0; i < rows; i++) {
9820 auto& row = table[i];
9821 // apply row content indentation
9822 if (options_.indentation_.has_value()) {
9823 result += std::string(options_.indentation_.value(), ' ');
9824 }
9825
9826 for (size_t j = 0; j < row.size(); j++) {
9827
9828 result += row[j].get_text();
9829
9830 // check column position, need "\\" at the end of each row
9831 if (j < row.size() - 1) {
9832 result += " & ";
9833 } else {
9834 result += " \\\\";
9835 }
9836 }
9837 result += new_line;
9838 }
9839
9840 result += "\\end{tabular}";
9841 return result;
9842 }
9843
9844 virtual ~LatexExporter() {}
9845
9846 private:
9847 std::string add_alignment_header(Table& table) {
9848 std::string result{"{"};
9849
9850 for (auto& cell : table[0]) {
9851 auto format = cell.format();
9852 if (format.font_align_.value() == FontAlign::left) {
9853 result += 'l';
9854 } else if (format.font_align_.value() == FontAlign::center) {
9855 result += 'c';
9856 } else if (format.font_align_.value() == FontAlign::right) {
9857 result += 'r';
9858 }
9859 }
9860
9861 result += "}";
9862 return result;
9863 }
9864 ExportOptions options_;
9865};
9866
9867} // namespace tabulate
9868
9869/*
9870 __ ___. .__ __
9871_/ |______ \_ |__ __ __| | _____ _/ |_ ____
9872\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
9873 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
9874 |__| (____ /___ /____/|____(____ /__| \___ >
9875 \/ \/ \/ \/
9876Table Maker for Modern C++
9877https://github.com/p-ranav/tabulate
9878
9879Licensed under the MIT License <http://opensource.org/licenses/MIT>.
9880SPDX-License-Identifier: MIT
9881Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
9882
9883Permission is hereby granted, free of charge, to any person obtaining a copy
9884of this software and associated documentation files (the "Software"), to deal
9885in the Software without restriction, including without limitation the rights
9886to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9887copies of the Software, and to permit persons to whom the Software is
9888furnished to do so, subject to the following conditions:
9889
9890The above copyright notice and this permission notice shall be included in all
9891copies or substantial portions of the Software.
9892
9893THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
9894IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
9895FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
9896AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
9897LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9898OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
9899SOFTWARE.
9900*/
9901#pragma once
9902#include <algorithm>
9903#include <optional>
9904#include <sstream>
9905#include <string>
9906// #include <tabulate/exporter.hpp>
9907
9908namespace tabulate {
9909
9910class AsciiDocExporter : public Exporter {
9911
9912 static const char new_line = '\n';
9913
9914 public:
9915 std::string dump(Table& table) override {
9916 std::stringstream ss;
9917 ss << add_alignment_header(table);
9918 ss << new_line;
9919
9920 const auto rows = table.rows_;
9921 // iterate content and put text into the table.
9922 for (size_t row_index = 0; row_index < rows; row_index++) {
9923 auto& row = table[row_index];
9924
9925 for (size_t cell_index = 0; cell_index < row.size(); cell_index++) {
9926 ss << "|";
9927 ss << add_formatted_cell(row[cell_index]);
9928 }
9929 ss << new_line;
9930 if (row_index == 0) {
9931 ss << new_line;
9932 }
9933 }
9934
9935 ss << "|===";
9936 return ss.str();
9937 }
9938
9939 virtual ~AsciiDocExporter() {}
9940
9941 private:
9942 std::string add_formatted_cell(Cell& cell) const {
9943 std::stringstream ss;
9944 auto format = cell.format();
9945 std::string cell_string = cell.get_text();
9946
9947 auto font_style = format.font_style_.value();
9948
9949 bool format_bold = false;
9950 bool format_italic = false;
9951 std::for_each(font_style.begin(), font_style.end(),
9952 [&](FontStyle& style) {
9953 if (style == FontStyle::bold) {
9954 format_bold = true;
9955 } else if (style == FontStyle::italic) {
9956 format_italic = true;
9957 }
9958 });
9959
9960 if (format_bold) {
9961 ss << '*';
9962 }
9963 if (format_italic) {
9964 ss << '_';
9965 }
9966
9967 ss << cell_string;
9968 if (format_italic) {
9969 ss << '_';
9970 }
9971 if (format_bold) {
9972 ss << '*';
9973 }
9974 return ss.str();
9975 }
9976
9977 std::string add_alignment_header(Table& table) {
9978 std::stringstream ss;
9979 ss << (R"([cols=")");
9980
9981 size_t column_count = table[0].size();
9982 size_t column_index = 0;
9983 for (auto& cell : table[0]) {
9984 auto format = cell.format();
9985
9986 if (format.font_align_.value() == FontAlign::left) {
9987 ss << '<';
9988 } else if (format.font_align_.value() == FontAlign::center) {
9989 ss << '^';
9990 } else if (format.font_align_.value() == FontAlign::right) {
9991 ss << '>';
9992 }
9993
9994 ++column_index;
9995 if (column_index != column_count) {
9996 ss << ",";
9997 }
9998 }
9999
10000 ss << R"("])";
10001 ss << new_line;
10002 ss << "|===";
10003
10004 return ss.str();
10005 }
10006};
10007
10008} // namespace tabulate
10009
10010/*
10011 __ ___. .__ __
10012_/ |______ \_ |__ __ __| | _____ _/ |_ ____
10013\ __\__ \ | __ \| | \ | \__ \\ __\/ __ \
10014 | | / __ \| \_\ \ | / |__/ __ \| | \ ___/
10015 |__| (____ /___ /____/|____(____ /__| \___ >
10016 \/ \/ \/ \/
10017Table Maker for Modern C++
10018https://github.com/p-ranav/tabulate
10019
10020Licensed under the MIT License <http://opensource.org/licenses/MIT>.
10021SPDX-License-Identifier: MIT
10022Copyright (c) 2019 Pranav Srinivas Kumar <pranav.srinivas.kumar@gmail.com>.
10023
10024Permission is hereby granted, free of charge, to any person obtaining a copy
10025of this software and associated documentation files (the "Software"), to deal
10026in the Software without restriction, including without limitation the rights
10027to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10028copies of the Software, and to permit persons to whom the Software is
10029furnished to do so, subject to the following conditions:
10030
10031The above copyright notice and this permission notice shall be included in all
10032copies or substantial portions of the Software.
10033
10034THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
10035IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
10036FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
10037AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
10038LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
10039OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
10040SOFTWARE.
10041*/
10042
10043#ifndef TABULATE_EXPORT_HPP
10044#define TABULATE_EXPORT_HPP
10045
10046// #ifdef _WIN32
10047// #ifdef TABULATE_STATIC_LIB
10048// #define TABULATE_API
10049// #else
10050// #ifdef TABULATE_EXPORTS
10051// #define TABULATE_API __declspec(dllexport)
10052// #else
10053// #define TABULATE_API __declspec(dllimport)
10054// #endif
10055// #endif
10056// #else
10057// #define TABULATE_API
10058// #endif
10059
10060// Project version
10061#define TABULATE_VERSION_MAJOR 1
10062#define TABULATE_VERSION_MINOR 5
10063#define TABULATE_VERSION_PATCH 0
10064
10065// Composing the protocol version string from major, and minor
10066#define TABULATE_CONCATENATE(A, B) TABULATE_CONCATENATE_IMPL(A, B)
10067#define TABULATE_CONCATENATE_IMPL(A, B) A##B
10068#define TABULATE_STRINGIFY(a) TABULATE_STRINGIFY_IMPL(a)
10069#define TABULATE_STRINGIFY_IMPL(a) #a
10070
10071#endif
Definition tabulate.hpp:1362
Definition tabulate.hpp:1480
type traits C++17:
Definition tabulate.hpp:518
Definition tabulate.hpp:134
Definition tabulate.hpp:132
Definition tabulate.hpp:138
Definition tabulate.hpp:2558
Definition tabulate.hpp:668
Definition tabulate.hpp:688
Definition tabulate.hpp:690
Definition tabulate.hpp:692
Definition tabulate.hpp:694
Definition tabulate.hpp:696
Definition tabulate.hpp:698
Definition tabulate.hpp:670
Definition tabulate.hpp:672
Definition tabulate.hpp:674
Definition tabulate.hpp:676
Definition tabulate.hpp:678
Definition tabulate.hpp:680
Definition tabulate.hpp:682
Definition tabulate.hpp:684
Definition tabulate.hpp:686
Definition tabulate.hpp:614
Definition tabulate.hpp:2357
Definition tabulate.hpp:935
Definition tabulate.hpp:1040
Definition tabulate.hpp:701
Definition tabulate.hpp:952
Definition tabulate.hpp:942
Definition tabulate.hpp:710
Definition tabulate.hpp:759
Definition tabulate.hpp:703
Definition tabulate.hpp:464
Definition tabulate.hpp:502
Definition tabulate.hpp:476
Definition tabulate.hpp:490
Definition tabulate.hpp:483
Definition tabulate.hpp:1418
Definition tabulate.hpp:1393