forked from sony/nmos-cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathall_in_one.h
4418 lines (3600 loc) · 150 KB
/
all_in_one.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#ifndef SLOG_ALL_IN_ONE_H
#define SLOG_ALL_IN_ONE_H
////////////////////////////////////////////////////////////////////////////////////////////
// AUTO-GENERATED AMALGAMATED HEADER
// Generated at r377; to be truly free of dependencies, define SLOG_DETAIL_PROVIDES_UNIQUE_PTR_BASED_OPTIONAL and probably SLOG_STATIC
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/config.h"
#ifndef SLOG_CONFIG_H
#define SLOG_CONFIG_H
////////////////////////////////////////////////////////////////////////////////////////////
// Compile-time severity and logging gateway configuration
// SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT - whether the configuration is varied in this compilation unit or not
#if !defined(SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT) && !defined(SLOG_DONT_PROVIDE_CONFIG_PER_TRANSLATION_UNIT)
#define SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT
#elif defined(SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT) && defined(SLOG_DONT_PROVIDE_CONFIG_PER_TRANSLATION_UNIT)
#error "SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT and SLOG_DONT_PROVIDE_CONFIG_PER_TRANSLATION_UNIT must not both be specified"
#endif
// SLOG_PROVIDES_SEVERITIES - whether names for typical severity levels (SLOG_FATAL, SLOG_INFO, etc.) are provided
// Note: Could be varied per compilation unit if necessary (so long as SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT is also defined)
#if !defined(SLOG_PROVIDES_SEVERITIES) && !defined(SLOG_DONT_PROVIDE_SEVERITIES)
#define SLOG_PROVIDES_SEVERITIES
#elif defined(SLOG_PROVIDES_SEVERITIES) && defined(SLOG_DONT_PROVIDE_SEVERITIES)
#error "SLOG_PROVIDES_SEVERITIES and SLOG_DONT_PROVIDE_SEVERITIES must not both be specified"
#endif
// SLOG_LOGGING_SEVERITY - compile-time control of logging loquacity, fulfilling the same purpose as GOOGLE_STRIP_LOG in google-glog
// Use never_log_severity to strip all logging at compile-time
// Note: Could be varied per compilation unit if necessary (so long as SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT is also defined)
#ifndef SLOG_LOGGING_SEVERITY
#ifdef SLOG_PROVIDES_SEVERITIES
#define SLOG_DETAIL_INCLUDE_SEVERITIES_HEADER
#define SLOG_LOGGING_SEVERITY slog::severities::info
#else
#define SLOG_LOGGING_SEVERITY slog::nil_severity
#endif
#endif
// SLOG_TERMINATING_SEVERITY - compile-time control of which levels terminate the application
// Use never_log_severity to be certain logging won't terminate the application
// Note: Could be varied per compilation unit if necessary (so long as SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT is also defined)
#ifndef SLOG_TERMINATING_SEVERITY
#ifdef SLOG_PROVIDES_SEVERITIES
#define SLOG_DETAIL_INCLUDE_SEVERITIES_HEADER
#define SLOG_TERMINATING_SEVERITY slog::severities::fatal
#else
#define SLOG_TERMINATING_SEVERITY slog::max_severity
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Compile-time logging statement configuration
// SLOG_CURRENT_FILE - name of the current source file for log messages; should be a string literal
// Note: Could be varied per compilation unit if necessary
#ifndef SLOG_CURRENT_FILE
#define SLOG_CURRENT_FILE __FILE__
#endif
// SLOG_CURRENT_LINE - line number in the current source file for log messages; other than __LINE__, only a counter or 0 to disable tracking make much sense!
// Note: Could be varied per compilation unit if necessary
#ifndef SLOG_CURRENT_LINE
#define SLOG_CURRENT_LINE __LINE__
#endif
// SLOG_CURRENT_FUNCTION - name of the enclosing function as a string literal for log messages; should be a string literal
// Depending on the platform, __PRETTY_FUNCTION__ or __FUNCSIG__ might be an alternative to __FUNCTION__
// Note: Could be varied per compilation unit if necessary
#ifndef SLOG_CURRENT_FUNCTION
#define SLOG_CURRENT_FUNCTION __FUNCTION__
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Additional configuration for the macro-based API
// SLOG_PROVIDES_ABBREVIATED_LOGGING - whether LOG macros are provided as synonyms for SLOG macros, for some google-glog (and g2log/g3log, easylogging++) compatibility
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_DONT_PROVIDE_ABBREVIATED_LOGGING) && !defined(SLOG_PROVIDES_ABBREVIATED_LOGGING)
#define SLOG_DONT_PROVIDE_ABBREVIATED_LOGGING
#elif defined(SLOG_DONT_PROVIDE_ABBREVIATED_LOGGING) && defined(SLOG_PROVIDES_ABBREVIATED_LOGGING)
#error "SLOG_DONT_PROVIDE_ABBREVIATED_LOGGING and SLOG_PROVIDES_ABBREVIATED_LOGGING must not both be specified"
#endif
// SLOG_PROVIDES_ABBREVIATED_SEVERITIES - whether abbreviated names for severity levels are provided, fulfilling the same purpose as GLOG_NO_ABBREVIATED_SEVERITIES in google-glog
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_DONT_PROVIDE_ABBREVIATED_SEVERITIES) && !defined(SLOG_PROVIDES_ABBREVIATED_SEVERITIES)
// Default is to provide them if and only if typical severity levels and abbreviated logging are both enabled
#if defined(SLOG_DONT_PROVIDE_SEVERITIES) || defined(SLOG_DONT_PROVIDE_ABBREVIATED_LOGGING)
#define SLOG_DONT_PROVIDE_ABBREVIATED_SEVERITIES
#else
#define SLOG_PROVIDES_ABBREVIATED_SEVERITIES
#endif
#elif defined(SLOG_DONT_PROVIDE_ABBREVIATED_SEVERITIES) && defined(SLOG_PROVIDES_ABBREVIATED_SEVERITIES)
#error "SLOG_DONT_PROVIDE_ABBREVIATED_SEVERITIES and SLOG_PROVIDES_ABBREVIATED_SEVERITIES must not both be specified"
#endif
// SLOG_PROVIDES_THREAD_LOCAL_LOGGING - whether SLOG macros use the thread-local API
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_PROVIDES_THREAD_LOCAL_LOGGING) && !defined(SLOG_DONT_PROVIDE_THREAD_LOCAL_LOGGING)
#define SLOG_PROVIDES_THREAD_LOCAL_LOGGING
#elif defined(SLOG_PROVIDES_THREAD_LOCAL_LOGGING) && defined(SLOG_DONT_PROVIDE_THREAD_LOCAL_LOGGING)
#error "SLOG_PROVIDES_THREAD_LOCAL_LOGGING and SLOG_DONT_PROVIDE_THREAD_LOCAL_LOGGING must not both be specified"
#endif
// SLOG_PROVIDES_ATOMIC_SLOG_COUNT - whether SLOG_COUNT should use atomic increment and thus guarantee to be accurate in multi-threaded apps
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_PROVIDES_ATOMIC_SLOG_COUNT) && !defined(SLOG_DONT_PROVIDE_ATOMIC_SLOG_COUNT)
#define SLOG_PROVIDES_ATOMIC_SLOG_COUNT
#elif defined(SLOG_PROVIDES_ATOMIC_SLOG_COUNT) && defined(SLOG_DONT_PROVIDE_ATOMIC_SLOG_COUNT)
#error "SLOG_PROVIDES_ATOMIC_SLOG_COUNT and SLOG_DONT_PROVIDE_ATOMIC_SLOG_COUNT must not both be specified"
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Other configuration and helpful preprocessor symbols
// SLOG_PROVIDES_LOGGING_IN_NAMESPACE_SLOG - whether the (global, for now) logging gateway functions are presented in namespace slog
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_PROVIDES_LOGGING_IN_NAMESPACE_SLOG) && !defined(SLOG_DONT_PROVIDE_LOGGING_IN_NAMESPACE_SLOG)
#define SLOG_PROVIDES_LOGGING_IN_NAMESPACE_SLOG
#elif defined(SLOG_PROVIDES_LOGGING_IN_NAMESPACE_SLOG) && defined(SLOG_DONT_PROVIDE_LOGGING_IN_NAMESPACE_SLOG)
#error "SLOG_PROVIDES_LOGGING_IN_NAMESPACE_SLOG and SLOG_DONT_PROVIDE_LOGGING_IN_NAMESPACE_SLOG must not both be specified"
#endif
// SLOG_LOGGING_GATEWAY - default gateway used by the macro-based API
#ifndef SLOG_LOGGING_GATEWAY
#define SLOG_DETAIL_INCLUDE_LOGGING_GATEWAY_HEADER
#ifdef SLOG_PROVIDES_THREAD_LOCAL_LOGGING
#define SLOG_LOGGING_GATEWAY slog::this_thread::gate
#else
#define SLOG_LOGGING_GATEWAY slog::global::gate
#endif
#endif
// SLOG_ID - unique integer value within the translation unit
#define SLOG_ID __COUNTER__
// SLOG_FLF - short-hand for SLOG_CURRENT_FILE, SLOG_CURRENT_LINE, SLOG_CURRENT_FUNCTION
#define SLOG_FLF SLOG_CURRENT_FILE, SLOG_CURRENT_LINE, SLOG_CURRENT_FUNCTION
////////////////////////////////////////////////////////////////////////////////////////////
// Implementation details
//
// Note: Preprocessor symbols that begin SLOG_DETAIL are private implementation detail
// which users should not rely upon. All other SLOG symbols are public, part of the API.
// ref-qualifiers aren't supported before Visual Studio 2015 (VC140, exactly speaking, the Nov 2013 CTP)
// See https://blogs.msdn.microsoft.com/vcblog/2013/12/02/c1114-core-language-features-in-vs-2013-and-the-nov-2013-ctp/
// As far as I can tell support was introduced in Clang 2.9 and GCC 4.8.1
// See https://akrzemi1.wordpress.com/2014/06/02/ref-qualifiers/
#ifndef SLOG_DETAIL_NO_REF_QUALIFIERS
#if defined(_MSC_VER) && _MSC_VER < 1900
#define SLOG_DETAIL_NO_REF_QUALIFIERS
#endif
#endif
// Conditional noexcept isn't supported before Visual Studio 2015 (VC140)
// As far as I can tell support was introduced in Clang 3.0 and GCC 4.8.1
#ifndef SLOG_DETAIL_NOEXCEPT_IF_NOEXCEPT
#if defined(_MSC_VER) && _MSC_VER < 1900
#define SLOG_DETAIL_NOEXCEPT_IF_NOEXCEPT(expr)
#else
#define SLOG_DETAIL_NOEXCEPT_IF_NOEXCEPT(expr) noexcept(noexcept(expr))
#endif
#endif
// SLOG_DETAIL_PROVIDES_TEMPLATE_BASED_MACRO_API - whether SLOG macros use the template-based API internally
// Be aware, there are a small number of inconsistencies in behaviour depending on whether this macro is defined or not.
// Note: Could be varied per compilation unit if necessary
#if !defined(SLOG_DETAIL_DONT_PROVIDE_TEMPLATE_BASED_MACRO_API) && !defined(SLOG_DETAIL_PROVIDES_TEMPLATE_BASED_MACRO_API)
#define SLOG_DETAIL_DONT_PROVIDE_TEMPLATE_BASED_MACRO_API
#elif defined(SLOG_DETAIL_DONT_PROVIDE_TEMPLATE_BASED_MACRO_API) && defined(SLOG_DETAIL_PROVIDES_TEMPLATE_BASED_MACRO_API)
#error "SLOG_DETAIL_DONT_PROVIDE_TEMPLATE_BASED_MACRO_API and SLOG_DETAIL_PROVIDES_TEMPLATE_BASED_MACRO_API must not both be specified"
#endif
// SLOG_DETAIL_BEGIN_ANONYMOUS_NAMESPACE_IF_CONFIG_PER_TRANSLATION_UNIT - introduce an anonymous namespace to get translation-unit specific API
#ifdef SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT
#define SLOG_DETAIL_BEGIN_ANONYMOUS_NAMESPACE_IF_CONFIG_PER_TRANSLATION_UNIT namespace {
#define SLOG_DETAIL_END_ANONYMOUS_NAMESPACE_IF_CONFIG_PER_TRANSLATION_UNIT }
#else
#define SLOG_DETAIL_BEGIN_ANONYMOUS_NAMESPACE_IF_CONFIG_PER_TRANSLATION_UNIT
#define SLOG_DETAIL_END_ANONYMOUS_NAMESPACE_IF_CONFIG_PER_TRANSLATION_UNIT
#endif
// SLOG_DETAIL_DO_TERMINATE - std::terminate
// Note: This symbol is to provide some 'indirection' for unit-testing (so long as SLOG_PROVIDES_CONFIG_PER_TRANSLATION_UNIT is also defined)
#ifndef SLOG_DETAIL_DO_TERMINATE
#define SLOG_DETAIL_DO_TERMINATE std::terminate
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/severity_type.h"
#ifndef SLOG_SEVERITY_TYPE_H
#define SLOG_SEVERITY_TYPE_H
#include <climits>
// Severity/verbosity levels
namespace slog
{
typedef int severity;
// Special values outside the range of severity/verbosity levels
const severity never_log_severity = INT_MAX;
const severity reset_log_severity = INT_MIN;
// Note: not using std::numeric_limits because max/min aren't constexpr with e.g. Visual Studio 2012
// Full range of severity/verbosity levels
// Levels in the range (nil_severity, max_severity] are severe to some degree
// Levels in the range [max_verbosity, nil_severity) are verbose to some degree
// The nil_severity level is neither severe nor verbose!
const severity max_severity = never_log_severity - 1;
const severity nil_severity = 0;
const severity max_verbosity = reset_log_severity + 1;
// Typical severity/verbosity levels are provided by slog::severities
// e.g. fatal, error, warning, info
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/log_message.h"
#ifndef SLOG_LOG_MESSAGE_H
#define SLOG_LOG_MESSAGE_H
#include <sstream>
#ifdef __GLIBCXX__
#include <type_traits> // for std::is_move_constructible, etc.
#endif
// Amalgamated: #include "slog/severity_type.h"
namespace slog
{
namespace detail
{
void copyfmtstate(std::ostream& target, const std::ostream& src);
#if defined(__GLIBCXX__) && defined(__GNUC__) && (__GNUC__ < 5) && !defined(__clang__)
// workaround for gcc 4.9 bug see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64385
const bool ostringstream_is_move_constructible = std::is_move_constructible< std::ostringstream >::value;
#endif
}
// To keep logging lightweight at the front end, log_message is non-copyable (but cf. copyable_log_message)
// log_message contains a set of attributes that are widely used and can be only be captured, and captured cheaply,
// at the log statement itself; others such as thread id and timestamp can be captured in the log handler
class log_message
{
public:
// The usual log_message constructor is the one called via the SLOG macros, which typically use
// the well-known __FILE__, __LINE__, __FUNCTION__ macros and a severity level
log_message(const char* file, int line, const char* function, severity level)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(std::ios_base::ate)
{}
// This constructor adds an initializing string for the message stream
log_message(const char* file, int line, const char* function, severity level, const std::string& str)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(str, std::ios_base::ate)
{}
// This constructor enables the implementation of a conversion operator in copyable_log_message
// to allow passing copyable_log_message to functions taking log_message
log_message(const char* file, int line, const char* function, severity level, const std::string& str, const std::ostream& stream)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(str, std::ios_base::ate)
{
detail::copyfmtstate(stream_, stream);
}
// Accessors
const char* file() const { return file_; }
int line() const { return line_; }
const char* function() const { return function_; }
severity level() const { return level_; }
// The message stream is the only publicly mutable member is the message stream
std::ostream& stream() { return stream_; }
const std::ostream& stream() const { return stream_; }
std::string str() const { return stream_.str(); }
// Trivial destructor
~log_message() {}
private:
const char* file_;
int line_;
const char* function_;
severity level_;
std::ostringstream stream_;
// Non-copyable
log_message(const log_message&);
const log_message& operator=(const log_message&);
public:
// Movable
#ifndef __GLIBCXX__
log_message(log_message&& src) // = default;
: file_(src.file_)
, line_(src.line_)
, function_(src.function_)
, level_(src.level_)
, stream_(std::move(src.stream_))
{}
#else
private:
struct move_enabler {};
template <typename LogMessage>
log_message(LogMessage&& src, typename std::enable_if<std::is_same<log_message, LogMessage>::value && std::is_move_constructible< std::ostringstream >::value, move_enabler>::type)
: file_(src.file_)
, line_(src.line_)
, function_(src.function_)
, level_(src.level_)
, stream_(std::move(src.stream_))
{}
// Workaround for missing move support for streams in libstdc++ before the version that will ship with GCC 5
// See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=54316
template <typename LogMessage>
log_message(LogMessage&& src, typename std::enable_if<std::is_same<log_message, LogMessage>::value && !std::is_move_constructible< std::ostringstream >::value, move_enabler>::type)
: file_(src.file_)
, line_(src.line_)
, function_(src.function_)
, level_(src.level_)
, stream_(src.stream_.str(), std::ios_base::ate)
{
detail::copyfmtstate(stream_, src.stream_);
}
public:
log_message(log_message&& src)
: log_message(std::move(src), move_enabler())
{
}
#endif
};
namespace detail
{
inline void copyfmtstate(std::ostream& target, const std::ostream& src)
{
// Perhaps should do target.seekp(const_cast<std::ostream&>(src).tellp());
// Copying stream state allows use to be made of the internal extensible array
target.copyfmt(src);
target.clear(src.rdstate());
}
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/base_gate.h"
#ifndef SLOG_BASE_GATE_H
#define SLOG_BASE_GATE_H
// Amalgamated: #include "slog/log_message.h" // or we could forward declare it
// Amalgamated: #include "slog/severity_type.h"
namespace slog
{
// base_gate is an abstract interface for a logging gateway, which therefore serves
// as a reasonable base class when polymorphism is required, e.g. to enable runtime
// selection of the logging gateway, or to allow separate compilation of modules
class base_gate
{
public:
virtual ~base_gate() {}
virtual bool pertinent(slog::severity level) const = 0;
virtual void log(const slog::log_message& message) const = 0;
};
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/copyable_log_message.h"
#ifndef SLOG_COPYABLE_LOG_MESSAGE_H
#define SLOG_COPYABLE_LOG_MESSAGE_H
// Amalgamated: #include "slog/log_message.h"
namespace slog
{
// A copyable log_message can be passed out of the scope of the logging statement
// e.g. sent to another thread or stored in a container
class copyable_log_message
{
public:
// Converting constructor fulfills the primary purpose of saving a log_message
// Note: No harm in not being explicit?
copyable_log_message(const log_message& message)
: file_(message.file())
, line_(message.line())
, function_(message.function())
, level_(message.level())
, stream_(message.str(), std::ios_base::ate)
{
detail::copyfmtstate(stream_, message.stream());
}
// This constructor provides compatibility with log_message construction
copyable_log_message(const std::string& file, int line, const std::string& function, severity level)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(std::ios_base::ate)
{}
// This constructor provides compatibility with log_message construction
copyable_log_message(const std::string& file, int line, const std::string& function, severity level, const std::string& str)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(str, std::ios_base::ate)
{}
// This constructor provides compatibility with log_message construction
copyable_log_message(const std::string& file, int line, const std::string& function, severity level, const std::string& str, const std::ostream& stream)
: file_(file)
, line_(line)
, function_(function)
, level_(level)
, stream_(str, std::ios_base::ate)
{
detail::copyfmtstate(stream_, stream);
}
// A default constructor seems like a good idea, even though it constructs a barely useful instance
copyable_log_message()
: file_()
, line_()
, function_()
, level_(nil_severity)
, stream_(std::ios_base::ate)
{}
// Likewise a constructor simply taking an initializing string for the message stream
explicit copyable_log_message(const std::string& str)
: file_()
, line_()
, function_()
, level_(nil_severity)
, stream_(str, std::ios_base::ate)
{}
// Trivial destructor
~copyable_log_message() {}
// Copy constructor (looks awfully like the log_message converting constructor, doesn't it?)
copyable_log_message(const copyable_log_message& message)
: file_(message.file())
, line_(message.line())
, function_(message.function())
, level_(message.level())
, stream_(message.str(), std::ios_base::ate)
{
detail::copyfmtstate(stream_, message.stream());
}
// The copy assignment operator is provided for consistency with the copy constructor (rule of 3 or so)
copyable_log_message& operator=(const copyable_log_message& message)
{
file_ = message.file();
line_ = message.line();
function_ = message.function();
level_ = message.level();
stream_.str(message.str());
detail::copyfmtstate(stream_, message.stream());
return *this;
}
// Accessors (identical to log_message)
const char* file() const { return file_.c_str(); }
int line() const { return line_; }
const char* function() const { return function_.c_str(); }
severity level() const { return level_; }
std::ostream& stream() { return stream_; }
const std::ostream& stream() const { return stream_; }
std::string str() const { return stream_.str(); }
// Conversion operator to allow passing copyable_log_message to functions taking log_message
// Note: The log_message is only a shallow copy, valid for the lifetime of this copyable_log_message!
operator log_message() const
{
return log_message(file(), line(), function(), level(), str(), stream());
}
protected:
std::string file_;
int line_;
std::string function_;
severity level_;
std::ostringstream stream_;
};
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "bst/function.h"
#ifndef BST_FUNCTION_H
#define BST_FUNCTION_H
// Provide bst::bind, bst::placeholders::_1, etc. using either std:: or boost:: symbols
// Note: Same condition as bst/thread.h because we want consistent use of function/thread/chrono
#ifndef BST_THREAD_BOOST
#include <functional>
namespace bst_functional = std;
namespace bst_placeholders = std::placeholders;
#else
#include <boost/function.hpp>
namespace bst_functional = boost;
#if BOOST_VERSION >= 106000
#include <boost/bind/bind.hpp>
namespace bst_placeholders = boost::placeholders;
#else
#include <boost/bind.hpp>
namespace bst_placeholders // can't alias the global namespace!
{
using ::_1;
using ::_2;
using ::_3;
using ::_4;
using ::_5;
using ::_6;
using ::_7;
using ::_8;
using ::_9;
}
#endif
#endif
namespace bst
{
using bst_functional::bind;
using bst_functional::ref;
using bst_functional::cref;
using bst_functional::reference_wrapper;
namespace placeholders
{
// could replace using-directive with using-declarations for symbols
using namespace bst_placeholders;
}
using bst_functional::function;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/iomanip.h"
#ifndef SLOG_IOMANIP_H
#define SLOG_IOMANIP_H
#include <iosfwd>
// Amalgamated: #include "bst/function.h"
////////////////////////////////////////////////////////////////////////////////////////////
// Utility classes and functions to provide manipulators created from e.g. lambda functions
namespace slog
{
// Use the free functions imanip, omanip, ios_manip and base_manip to construct manipulators.
// Instantiations of the manip_function class template are just tagged function object types,
// but without the conversion to bool or other baggage of std::function.
// Note: These types are not really to be used directly.
template <typename Manipulated>
struct manip_function
{
typedef Manipulated& argument_type;
typedef Manipulated& result_type;
#if defined(_MSC_VER) && _MSC_VER < 1900
// Visual Studio 2013 (VC140) does not implement the resolution to LWG 2420
// See http://cplusplus.github.io/LWG/lwg-defects.html#2420
// "function<void(ArgTypes...)> does not discard the return value of the target object"
// And in another twist, some VS2013 bind expressions don't have a const operator() so,
// in order that the captured copy of f can definitely be called, mark the lambda mutable
// See http://connect.microsoft.com/VisualStudio/feedbackdetail/view/981289/std-bind-operator-is-not-const-in-some-cases-where-it-should-be
template <typename F>
explicit manip_function(F f)
: function([f](argument_type arg) mutable { f(arg); })
{}
#else
// The target callable, f, is required to be copyable.
template <typename F>
explicit manip_function(F&& f)
: function(std::forward<F>(f))
{}
#endif
result_type operator()(argument_type arg) const { function(arg); return arg; }
private:
bst::function<void(argument_type)> function;
};
typedef manip_function<std::ios_base> base_manip_function;
typedef manip_function<std::ios> ios_manip_function;
typedef manip_function<std::ostream> omanip_function;
typedef manip_function<std::istream> imanip_function;
typedef manip_function<std::wios> wios_manip_function;
typedef manip_function<std::wostream> womanip_function;
typedef manip_function<std::wistream> wimanip_function;
// Functions for constructing manipulators
template <typename F>
inline base_manip_function base_manip(F&& f)
{
return base_manip_function(std::forward<F>(f));
}
template <typename F>
inline ios_manip_function ios_manip(F&& f)
{
return ios_manip_function(std::forward<F>(f));
}
template <typename F>
inline omanip_function omanip(F&& f)
{
return omanip_function(std::forward<F>(f));
}
template <typename F>
inline imanip_function imanip(F&& f)
{
return imanip_function(std::forward<F>(f));
}
template <typename F>
inline wios_manip_function wios_manip(F&& f)
{
return wios_manip_function(std::forward<F>(f));
}
template <typename F>
inline womanip_function womanip(F&& f)
{
return womanip_function(std::forward<F>(f));
}
template <typename F>
inline wimanip_function wimanip(F&& f)
{
return wimanip_function(std::forward<F>(f));
}
// Stream insertion operators for the relevant manipulators
template <typename CharT, typename TraitsT>
inline std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& s, const base_manip_function& f)
{
f(s); return s;
}
template <typename CharT, typename TraitsT>
inline std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& s, const manip_function<std::basic_ios<CharT, TraitsT>>& f)
{
f(s); return s;
}
template <typename CharT, typename TraitsT>
inline std::basic_ostream<CharT, TraitsT>& operator<<(std::basic_ostream<CharT, TraitsT>& s, const manip_function<std::basic_ostream<CharT, TraitsT>>& f)
{
return f(s);
}
// Stream extraction operators for the relevant manipulators
template <typename CharT, typename TraitsT>
inline std::basic_istream<CharT, TraitsT>& operator>>(std::basic_istream<CharT, TraitsT>& s, const base_manip_function& f)
{
f(s); return s;
}
template <typename CharT, typename TraitsT>
inline std::basic_istream<CharT, TraitsT>& operator>>(std::basic_istream<CharT, TraitsT>& s, const manip_function<std::basic_ios<CharT, TraitsT>>& f)
{
f(s); return s;
}
template <typename CharT, typename TraitsT>
inline std::basic_istream<CharT, TraitsT>& operator>>(std::basic_istream<CharT, TraitsT>& s, const manip_function<std::basic_istream<CharT, TraitsT>>& f)
{
return f(s);
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "detail/pragma_warnings.h"
#ifndef DETAIL_PRAGMA_WARNINGS_H
#define DETAIL_PRAGMA_WARNINGS_H
// Use compiler-specific pragma mechanisms that, unlike #pragma, can be used inside macros
#if defined(_MSC_VER)
#define PRAGMA_WARNING_PUSH __pragma(warning(push))
#define PRAGMA_WARNING_POP __pragma(warning(pop))
#elif defined(__clang__)
#define PRAGMA_WARNING_PUSH _Pragma("clang diagnostic push")
#define PRAGMA_WARNING_POP _Pragma("clang diagnostic pop")
#elif defined(__GNUC__)
#if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
#define PRAGMA_WARNING_PUSH _Pragma("GCC diagnostic push")
#define PRAGMA_WARNING_POP _Pragma("GCC diagnostic pop")
#else
#define PRAGMA_WARNING_PUSH
#define PRAGMA_WARNING_POP
#endif
#else
#define PRAGMA_WARNING_PUSH
#define PRAGMA_WARNING_POP
#endif
// Some specific warnings that shouldn't be disabled everywhere,
// but are likely to be worth disabling in some cases
#if defined(_MSC_VER)
#define PRAGMA_WARNING_DISABLE_FORCE_TO_BOOL \
__pragma(warning(disable:4800)) // forcing value to bool
#else
#define PRAGMA_WARNING_DISABLE_FORCE_TO_BOOL
#endif
#if defined(_MSC_VER)
#define PRAGMA_WARNING_DISABLE_DESTRUCTOR_NEVER_RETURNS \
__pragma(warning(disable:4722)) // destructor never returns
#else
#define PRAGMA_WARNING_DISABLE_DESTRUCTOR_NEVER_RETURNS
#endif
#if defined(_MSC_VER)
#define PRAGMA_WARNING_DISABLE_UNREACHABLE_CODE \
__pragma(warning(disable:4702)) // unreachable code
#else
#define PRAGMA_WARNING_DISABLE_UNREACHABLE_CODE
#endif
#if defined(_MSC_VER)
#define PRAGMA_WARNING_DISABLE_CONDITIONAL_EXPRESSION_IS_CONSTANT \
__pragma(warning(disable:4127)) // conditional expression is constant
#else
#define PRAGMA_WARNING_DISABLE_CONDITIONAL_EXPRESSION_IS_CONSTANT
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/detail/optional_log_message.h"
#ifndef SLOG_DETAIL_OPTIONAL_LOG_MESSAGE_H
#define SLOG_DETAIL_OPTIONAL_LOG_MESSAGE_H
// Amalgamated: #include "slog/config.h"
// No optional in std, no std::experimental::optional in VS2012, but somebody wanted to avoid Boost wherever possible...
// std::unique_ptr is slower because of the heap allocation, but it works...
#ifdef SLOG_DETAIL_PROVIDES_UNIQUE_PTR_BASED_OPTIONAL
#include <memory>
#else
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
#endif
// Amalgamated: #include "slog/log_message.h"
namespace slog
{
namespace detail
{
#ifdef SLOG_DETAIL_PROVIDES_UNIQUE_PTR_BASED_OPTIONAL
typedef std::unique_ptr<log_message> optional_log_message;
inline optional_log_message make_optional_log_message(const char* file, int line, const char* function, severity level)
{
return optional_log_message(new log_message(file, line, function, level));
}
#else
typedef boost::optional<log_message> optional_log_message;
// Taking arguments by const& is critical, because otherwise the returned boost::in_place_factory holds references to temporaries
inline auto make_optional_log_message(const char* const& file, int const& line, const char* const& function, severity const& level)
-> decltype(boost::in_place(file, line, function, level))
{
return boost::in_place(file, line, function, level);
}
#endif
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/detail/uncaught_exceptions.h"
#ifndef SLOG_DETAIL_UNCAUGHT_EXCEPTIONS_H
#define SLOG_DETAIL_UNCAUGHT_EXCEPTIONS_H
// std::uncaught_exceptions has been proposed by Herb Sutter in
// http://isocpp.org/files/papers/n4259.pdf
// This implementation is derived from the code snippet by
// Andrei Alexandrescu presented in "Declarative Control Flow"
// at C++ and Beyond, Stuttgart, Germany, September 2014.
#if defined(__clang__) || defined(__GNUC__)
namespace __cxxabiv1
{
struct __cxa_eh_globals;
extern "C" __cxa_eh_globals* __cxa_get_globals() noexcept;
}
namespace slog
{
namespace detail
{
inline int uncaught_exceptions()
{
// __cxa_get_globals returns a __cxa_eh_globals* (defined in unwind-cxx.h).
// The offset below returns __cxa_eh_globals::uncaughtExceptions.
return *reinterpret_cast<int*>(static_cast<char*>(static_cast<void*>(__cxxabiv1::__cxa_get_globals())) + sizeof(void*));
}
}
}
#elif defined(_MSC_VER) && _MSC_VER < 1900
// For Visual Studio 2005-2013 (VC80 to VC120) only.
struct _tiddata;
extern "C" _tiddata* _getptd();
namespace slog
{
namespace detail
{
inline int uncaught_exceptions()
{
// _getptd() returns a _tiddata* (defined in mtdll.h).
// The offset below returns _tiddata::_ProcessingThrow.
return *reinterpret_cast<int*>(static_cast<char*>(static_cast<void*>(_getptd())) + sizeof(void*) * 28 + 4 * 8);
}
}
}
#elif defined(_MSC_VER)
// For Visual Studio 2015 (VC140) CTP 6 onwards.
extern "C" int* __processing_throw();
namespace slog
{
namespace detail
{
inline int uncaught_exceptions()
{
return *__processing_throw();
}
}
}
#endif
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/severities.h"
#ifndef SLOG_SEVERITIES_H
#define SLOG_SEVERITIES_H
// Amalgamated: #include "slog/severity_type.h"
// Typical severity/verbosity levels
namespace slog
{
// Note: Additional or different values that meet the slog::severity criteria may also be used
namespace severities
{
// Note: Which severity levels terminate the application is configured at compile-time
const severity fatal = 40;
const severity severe = 30;
const severity error = 20;
const severity warning = 10;
const severity info = 0;
const severity more_info = -10;
//const severity debug = more_info;
const severity too_much_info = -40;
}
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "bst/atomic.h"
#ifndef BST_ATOMIC_H
#define BST_ATOMIC_H
// Provide bst::atomic, using either std:: or boost:: symbols
#ifndef BST_ATOMIC_BOOST
#include <atomic>
namespace bst_atomic = std;
#else
#include <boost/atomic.hpp>
namespace bst_atomic = boost;
#endif
namespace bst
{
using bst_atomic::atomic;
}
#endif
////////////////////////////////////////////////////////////////////////////////////////////
// Amalgamating: #include "slog/detail/hit_count.h"
#ifndef SLOG_DETAIL_HIT_COUNT_H
#define SLOG_DETAIL_HIT_COUNT_H
// Amalgamated: #include "bst/atomic.h"
namespace slog
{
namespace detail
{
template <typename tag>
class hit_count
{
public:
hit_count() : value(++static_value) {}
const int value;
static bst::atomic<int> static_value;
private:
// Non-copyable
hit_count(const hit_count&);
const hit_count& operator=(const hit_count&);
public:
// Movable
hit_count(hit_count&& src) // = default;
: value(src.value)
{}
};
template <typename tag>
bst::atomic<int> hit_count<tag>::static_value(0);
// These tags may be useful beyond hit_count...
namespace definition_tags
{
struct program;
template <int id>
struct program_c;
namespace
{
struct translation_unit;
template <int id>
struct translation_unit_c;
}
}
}