-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathh2unit.h
10338 lines (9301 loc) · 438 KB
/
h2unit.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
/* https://github.com/lingjf/h2unit */
/* Apache Licence 2.0 */
#ifndef __H2UNIT_H__
#define __H2UNIT_H__
#define H2UNIT_VERSION 5.17
#define H2UNIT_DATE 2022-01-02
#define H2UNIT_REVISION branches/v5/9b29b4d30ff8a25bf1c579e0b260ac68e123ef78
#ifndef __H2_UNIT_HPP__
#define __H2_UNIT_HPP__
#include <cstdio> /* printf */
#include <cstdlib> /* malloc */
#include <cstdint> /* std::uintptr_t */
#include <cstring> /* strcpy, memcpy */
#include <cmath> /* fabs, NAN */
#include <csetjmp> /* setjmp, longjmp */
#include <sstream> /* std::basic_ostringstream */
#include <string> /* std::string */
#include <vector> /* std::vector */
#include <memory> /* std::allocator, std::shared_ptr */
#include <tuple> /* std::tuple */
#include <functional> /* std::function */
#include <utility> /* std::forward, std::pair */
#include <type_traits> /* std::true_type */
#if defined _MSC_VER || defined __CYGWIN__
#include <iomanip> /* std::fixed, std::setprecision */
#include <limits> /* std::numeric_limits */
#endif
#if defined _MSC_VER
#include <malloc.h> /* _alloca _msize _expand */
#define alloca _alloca
#elif defined __MINGW32__ || defined __MINGW64__
#else
#include <alloca.h> /* alloca */
#endif
#if defined __GNUC__ || defined __clang__
// #pragma clang diagnostic ignored === #pragma GCC diagnostic ignored
#pragma GCC diagnostic ignored "-Wparentheses" // OK
#pragma GCC diagnostic ignored "-Wsign-compare" // (in)equation
#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#elif defined _MSC_VER
#pragma warning(disable : 4244) // conversion possible loss of data
#pragma warning(disable : 4267) // conversion possible loss of data
#pragma warning(disable : 4305) // type cast
#pragma warning(disable : 4312) // type cast
#pragma warning(disable : 4611) // setjmp non-portable
#pragma warning(disable : 4996) // unsafe
#endif
#if defined __H2UNIT_HPP__
#define h2_inline
#else
#define h2_inline inline
#endif
namespace h2 {
// source/utils/h2_macro.hpp
/* clang-format off */
#define H2PP_STR(...) _H2PP_STR(__VA_ARGS__)
#define _H2PP_STR(...) #__VA_ARGS__
#define H2PP_CAT(_1, _2) _H2PP_CAT2(_1, _2)
#define H2PP_CAT2(_1, _2) _H2PP_CAT2(_1, _2)
#define _H2PP_CAT2(_1, _2) _1##_2
#define H2PP_CAT5(_1, _2, _3, _4, _5) _H2PP_CAT5(_1, _2, _3, _4, _5)
#define _H2PP_CAT5(_1, _2, _3, _4, _5) _1##_2##_3##_4##_5
#define H2PP_COMMA(...) ,
#define H2PP_EMPTY(...)
#define H2PP_DEFER(...) __VA_ARGS__ H2PP_EMPTY()
#define H2PP_RESCAN(_1) _1
// MSVC workaround: Calling arguments not equal with callee parameters
#define H2PP_PROXY(_Macro, _Args) _H2PP_PROXY(_Macro, _Args)
#define H2PP_PROXY2(_Macro, _Spec, _Args) _H2PP_PROXY(_H2PP_CAT2(_Macro, _Spec), _Args)
#define _H2PP_PROXY(_Macro, _Args) H2PP_RESCAN(_Macro _Args)
#ifdef _MSC_VER // MSVC workaround
# define H2PP_IS_PROBE(...) H2PP_PROXY(_H2PP_TH1, (__VA_ARGS__, 0))
#else
# define H2PP_IS_PROBE(...) _H2PP_TH1(__VA_ARGS__, 0, )
#endif
#define H2PP_PROBE() ~, 1,
#define H2PP_EVAL(...) _H2PP_EVAL_128(__VA_ARGS__)
#define H2PP_EQ(_1, _2) H2PP_IS_PROBE(H2PP_CAT5(_H2PP_EQ, __, _1, __, _2))
#define H2PP_NOT(_Cond) H2PP_IS_PROBE(_H2PP_CAT2(_H2PP_NOT_, _Cond))
#define _H2PP_NOT_0 H2PP_PROBE()
#define H2PP_COMPL(_Value) _H2PP_CAT2(_H2PP_COMPL_, _Value)
#define _H2PP_COMPL_0 1
#define _H2PP_COMPL_1 0
#define H2PP_BOOL(_Cond) H2PP_COMPL(H2PP_NOT(_Cond)) // non-zero evaluate to 1
#define H2PP_AND(_1, _2) H2PP_CAT2(_H2PP_AND_, H2PP_BOOL(_1)) (H2PP_BOOL(_2))
#define _H2PP_AND_0(_2) 0
#define _H2PP_AND_1(_2) _2
#define H2PP_OR(_1, _2) H2PP_CAT2(_H2PP_OR_, H2PP_BOOL(_1)) (H2PP_BOOL(_2))
#define _H2PP_OR_0(_2) _2
#define _H2PP_OR_1(_2) 1
#define H2PP_IF_ELSE(_Cond, _Then, _Else) H2PP_CAT2(_H2PP_IF_ELSE_, _Cond) (_Then, _Else)
#define _H2PP_IF_ELSE_1(_Then, _Else) _Then
#define _H2PP_IF_ELSE_0(_Then, _Else) _Else
#define H2PP_IF(_Cond) H2PP_CAT2(_H2PP_IF_, H2PP_BOOL(_Cond))
#define _H2PP_IF_1(...) __VA_ARGS__
#define _H2PP_IF_0(...)
// the first argument starts with something in parentheses
#define H2PP_IS_BEGIN_PARENTHESIS(...) H2PP_IS_PROBE(_H2PP_IS_BEGIN_PARENTHESIS_PROBE __VA_ARGS__)
#define _H2PP_IS_BEGIN_PARENTHESIS_PROBE(...) H2PP_PROBE()
// only one argument and it is enclosed in parentheses
#define H2PP_IS_PARENTHESIS(...) H2PP_IF_ELSE(H2PP_IS_BEGIN_PARENTHESIS(__VA_ARGS__), H2PP_IS_EMPTY(H2PP_EMPTY __VA_ARGS__), 0)
#define H2PP_REMOVE_PARENTHESES(...) _H2PP_REMOVE_PARENTHESES __VA_ARGS__
#define _H2PP_REMOVE_PARENTHESES(...) __VA_ARGS__
#define H2PP_REMOVE_PARENTHESES_IF(...) H2PP_CAT2(_H2PP_REMOVE_PARENTHESES_IF_, H2PP_IS_PARENTHESIS(__VA_ARGS__)) (__VA_ARGS__)
#define _H2PP_REMOVE_PARENTHESES_IF_1(...) H2PP_REMOVE_PARENTHESES(__VA_ARGS__)
#define _H2PP_REMOVE_PARENTHESES_IF_0(...) __VA_ARGS__
// 1. __VA_ARGS__ has no unparen'd commas. ==> 0
// 2. __VA_ARGS__ is not enclosed in parenthesis. ==> 0
// 3. __VA_ARGS__ is not a macro that ()-evaluates to a comma. ==> 0
// 4. __VA_ARGS__ is empty, or has unparen'd commas, or is enclosed in parenthesis, or is a macro that ()-evaluates to comma. ==> 1
#define H2PP_IS_EMPTY(...) _H2PP_IS_EMPTY(H2PP_HAS_COMMA(__VA_ARGS__), \
H2PP_HAS_COMMA(H2PP_COMMA __VA_ARGS__), \
H2PP_HAS_COMMA(__VA_ARGS__()), \
H2PP_HAS_COMMA(H2PP_COMMA __VA_ARGS__()))
#define _H2PP_IS_EMPTY(_1, _2, _3, _4) H2PP_HAS_COMMA(_H2PP_CAT5(_H2PP_IS_EMPTY_CASE_, _1, _2, _3, _4))
#define _H2PP_IS_EMPTY_CASE_0001 ,
#define H2PP_NARG(...) H2PP_CAT(_H2PP_NARG_, H2PP_IS_EMPTY(__VA_ARGS__)) (__VA_ARGS__)
#define _H2PP_NARG_0(...) H2PP_ARG_COUNT(__VA_ARGS__)
#define _H2PP_NARG_1(...) 0
#define H2PP_NCALL(_Macro, N, ...) H2PP_RESCAN(H2PP_CAT2(_Macro, H2PP_EQ(N, H2PP_NARG(__VA_ARGS__))) (__VA_ARGS__))
#define H2PP_VCALL(_Macro, ...) H2PP_RESCAN(H2PP_CAT2(_Macro, H2PP_NARG(__VA_ARGS__)) (__VA_ARGS__))
#define H2PP_HEAD(...) H2PP_CAT2(_H2PP_HEAD_, H2PP_IS_EMPTY(__VA_ARGS__)) ((__VA_ARGS__))
#define _H2PP_HEAD_0(MSVC_Workaround) H2PP_RESCAN(_H2PP_HEAD_0_R MSVC_Workaround)
#define _H2PP_HEAD_0_R(_1, ...) _1
#define _H2PP_HEAD_1(...)
#define H2PP_TAIL(...) H2PP_CAT2(_H2PP_TAIL_, H2PP_IS_EMPTY(__VA_ARGS__)) ((__VA_ARGS__))
#define _H2PP_TAIL_0(MSVC_Workaround) H2PP_RESCAN(_H2PP_TAIL_0_R MSVC_Workaround)
#define _H2PP_TAIL_0_R(_1, ...) __VA_ARGS__
#define _H2PP_TAIL_1(...)
#define H2PP_LAST(...) H2PP_EVAL(_H2PP_LAST(__VA_ARGS__))
#define _H2PP_LAST(...) H2PP_CAT2(_H2PP_LAST_, H2PP_IS_EMPTY(__VA_ARGS__)) (__VA_ARGS__) //is empty?
#define _H2PP_LAST_1(...) // 0 argument
#define _H2PP_LAST_0(...) H2PP_CAT2(_H2PP_LAST_0_, H2PP_EQ(1, H2PP_NARG(__VA_ARGS__))) (__VA_ARGS__) // at least 1 argument, one and only one?
#define _H2PP_LAST_0_1(...) __VA_ARGS__ // only 1 argument
#define _H2PP_LAST_0_0(...) H2PP_DEFER(__H2PP_LAST)()(H2PP_TAIL(__VA_ARGS__)) // shift first, and again
#define __H2PP_LAST() _H2PP_LAST_0
#define H2PP_REPEAT(_Split, _Macro, _Args, _Count) H2PP_EVAL(_H2PP_REPEAT(_Split, _Macro, _Args, _Count))
#define _H2PP_REPEAT(_Split, _Macro, _Args, _Count) H2PP_CAT2(_H2PP_REPEAT_, H2PP_BOOL(_Count)) (_Split, _Macro, _Args, _Count)
#define _H2PP_REPEAT_0(...)
#define _H2PP_REPEAT_1(_Split, _Macro, _Args, _Count) H2PP_DEFER(__H2PP_REPEAT)()(_Split, _Macro, _Args, H2PP_CAT2(H2PP_DEC_, _Count)) _H2PP_REPEAT_CALL_MACRO(_Split, _Macro, _Args, H2PP_CAT2(H2PP_DEC_, _Count))
#define __H2PP_REPEAT() _H2PP_REPEAT
#define _H2PP_REPEAT_CALL_MACRO(_Split, _Macro, _Args, _i) H2PP_CAT2(_H2PP_REPEAT_CALL_MACRO_, H2PP_EQ(0, _i)) (_Split, _Macro, _Args, _i)
#define _H2PP_REPEAT_CALL_MACRO_1(_Split, _Macro, _Args, _i) _Macro(_Args, _i)
#define _H2PP_REPEAT_CALL_MACRO_0(_Split, _Macro, _Args, _i) H2PP_REMOVE_PARENTHESES_IF(_Split) _Macro(_Args, _i)
#define H2PP_FOREACH(_Split, _Macro, _Args, ...) H2PP_EVAL(_H2PP_FOREACH(_Split, _Macro, _Args, 0, __VA_ARGS__))
#define _H2PP_FOREACH(_Split, _Macro, _Args, _i, ...) H2PP_CAT2(_H2PP_FOREACH_, H2PP_IS_EMPTY(__VA_ARGS__)) (_Split, _Macro, _Args, _i, __VA_ARGS__)
#define _H2PP_FOREACH_1(...)
#define _H2PP_FOREACH_0(_Split, _Macro, _Args, _i, ...) _H2PP_FOREACH_CALL_MACRO(_Split, _Macro, _Args, _i, H2PP_HEAD(__VA_ARGS__)) H2PP_DEFER(__H2PP_FOREACH)()(_Split, _Macro, _Args, H2PP_CAT2(H2PP_INC_, _i), H2PP_TAIL(__VA_ARGS__))
#define __H2PP_FOREACH() _H2PP_FOREACH
#define _H2PP_FOREACH_CALL_MACRO(_Split, _Macro, _Args, _i, _x) H2PP_CAT2(_H2PP_FOREACH_CALL_MACRO_, H2PP_EQ(0, _i)) (_Split, _Macro, _Args, _i, _x)
#define _H2PP_FOREACH_CALL_MACRO_1(_Split, _Macro, _Args, _i, _x) _Macro(_Args, _i, _x)
#define _H2PP_FOREACH_CALL_MACRO_0(_Split, _Macro, _Args, _i, _x) H2PP_REMOVE_PARENTHESES_IF(_Split) _Macro(_Args, _i, _x)
#define H2PP_FULLMESH(_Split, _Macro, _Args, ...) H2PP_RESCAN(H2PP_CAT2(_H2PP_FULLMESH1_, H2PP_IS_EMPTY(__VA_ARGS__)) ((_Split, _Macro, _Args, __VA_ARGS__)))
#define _H2PP_FULLMESH1_1(...)
#define _H2PP_FULLMESH1_0(MSVC_Workaround) H2PP_RESCAN(H2PP_FULLMESH1 MSVC_Workaround)
#define H2PP_FULLMESH1(_Split, _Macro, _Args, _1, ...) H2PP_CAT2(_H2PP_FULLMESH2_, H2PP_IS_EMPTY(__VA_ARGS__)) (_Split, _Macro, _Args, _1, __VA_ARGS__)
#define _H2PP_FULLMESH2_1(_Split, _Macro, _Args, _1, ...) H2PP_FULLMESH2(_Split, _Macro, _Args, _1, _1) // Fullmesh((1,2,3)) => (1,2,3) x (1,2,3)
#define _H2PP_FULLMESH2_0(...) _H2PP_FULLMESH2_0_R((__VA_ARGS__)) // Fullmesh((1,2,3), (4,5,6)) => (1,2,3) x (4,5,6)
#define _H2PP_FULLMESH2_0_R(MSVC_Workaround) H2PP_RESCAN(H2PP_FULLMESH2 MSVC_Workaround)
#define H2PP_FULLMESH2(_Split, _Macro, _Args, _Tuplex, _Tupley) H2PP_EVAL(_H2PP_FOREACHx(_Split, _Macro, _Args, 0, _Tupley, H2PP_REMOVE_PARENTHESES(_Tuplex)))
#define _H2PP_FOREACHx(_Split, _Macro, _Args, _i, _Tupley, ...) H2PP_CAT2(_H2PP_FOREACHx_, H2PP_IS_EMPTY(__VA_ARGS__)) (_Split, _Macro, _Args, _i, _Tupley, __VA_ARGS__)
#define _H2PP_FOREACHx_1(...)
#define _H2PP_FOREACHx_0(_Split, _Macro, _Args, _i, _Tupley, ...) _H2PP_FOREACHy(_Split, _Macro, _Args, _i, 0, H2PP_HEAD(__VA_ARGS__), H2PP_REMOVE_PARENTHESES(_Tupley)) H2PP_DEFER(__H2PP_FOREACHx)()(_Split, _Macro, _Args, H2PP_CAT2(H2PP_INC_, _i), _Tupley, H2PP_TAIL(__VA_ARGS__))
#define __H2PP_FOREACHx() _H2PP_FOREACHx
#define _H2PP_FOREACHy(_Split, _Macro, _Args, _i, _j, _x, ...) H2PP_CAT2(_H2PP_FOREACHy_, H2PP_IS_EMPTY(__VA_ARGS__)) (_Split, _Macro, _Args, _i, _j, _x, __VA_ARGS__)
#define _H2PP_FOREACHy_1(...)
#define _H2PP_FOREACHy_0(_Split, _Macro, _Args, _i, _j, _x, ...) _H2PP_FULLMESH_CALL_MACRO(_Split, _Macro, _Args, _i, _j, _x, H2PP_HEAD(__VA_ARGS__)) H2PP_DEFER(__H2PP_FOREACHy)()(_Split, _Macro, _Args, _i, H2PP_CAT2(H2PP_INC_, _j), _x, H2PP_TAIL(__VA_ARGS__))
#define __H2PP_FOREACHy() _H2PP_FOREACHy
#define _H2PP_FULLMESH_CALL_MACRO(_Split, _Macro, _Args, _i, _j, _x, _y) H2PP_CAT2(_H2PP_FULLMESH_CALL_MACRO_, H2PP_AND(H2PP_EQ(0, _i), H2PP_EQ(0, _j))) (_Split, _Macro, _Args, _i, _j, _x, _y)
#define _H2PP_FULLMESH_CALL_MACRO_1(_Split, _Macro, _Args, _i, _j, _x, _y) _Macro(_Args, _i, _j, _x, _y)
#define _H2PP_FULLMESH_CALL_MACRO_0(_Split, _Macro, _Args, _i, _j, _x, _y) H2PP_REMOVE_PARENTHESES_IF(_Split) _Macro(_Args, _i, _j, _x, _y)
#define H2PP_UNIQUE(...) H2PP_CAT5(h2_, __VA_ARGS__, __COUNTER__, L, __LINE__) // generate unique identifier [with(out) prefix]
#define H2PP_DEBUG(...) ::printf("%s\n", #__VA_ARGS__);
// source/utils/h2_macro.in.hpp
//////// >>>>> generated by build/generate.py DON'T EDIT
#define _H2PP_EQ__0__0 H2PP_PROBE()
#define _H2PP_EQ__1__1 H2PP_PROBE()
#define _H2PP_EQ__2__2 H2PP_PROBE()
#define _H2PP_EQ__3__3 H2PP_PROBE()
#define _H2PP_EQ__4__4 H2PP_PROBE()
#define _H2PP_EQ__5__5 H2PP_PROBE()
#define _H2PP_EQ__6__6 H2PP_PROBE()
#define _H2PP_EQ__7__7 H2PP_PROBE()
#define _H2PP_EQ__8__8 H2PP_PROBE()
#define _H2PP_EQ__9__9 H2PP_PROBE()
#define _H2PP_EQ__10__10 H2PP_PROBE()
#define _H2PP_EQ__11__11 H2PP_PROBE()
#define _H2PP_EQ__12__12 H2PP_PROBE()
#define _H2PP_EQ__13__13 H2PP_PROBE()
#define _H2PP_EQ__14__14 H2PP_PROBE()
#define _H2PP_EQ__15__15 H2PP_PROBE()
#define _H2PP_EQ__16__16 H2PP_PROBE()
#define _H2PP_EQ__17__17 H2PP_PROBE()
#define _H2PP_EQ__18__18 H2PP_PROBE()
#define _H2PP_EQ__19__19 H2PP_PROBE()
#define _H2PP_EQ__20__20 H2PP_PROBE()
#define _H2PP_EQ__21__21 H2PP_PROBE()
#define _H2PP_EQ__22__22 H2PP_PROBE()
#define _H2PP_EQ__23__23 H2PP_PROBE()
#define _H2PP_EQ__24__24 H2PP_PROBE()
#define _H2PP_EQ__25__25 H2PP_PROBE()
#define _H2PP_EQ__26__26 H2PP_PROBE()
#define _H2PP_EQ__27__27 H2PP_PROBE()
#define _H2PP_EQ__28__28 H2PP_PROBE()
#define _H2PP_EQ__29__29 H2PP_PROBE()
#define _H2PP_EQ__30__30 H2PP_PROBE()
#define _H2PP_EQ__31__31 H2PP_PROBE()
#define _H2PP_TH0(_0, ...) _0
#define _H2PP_TH1(_0, _1, ...) _1
#define _H2PP_TH2(_0, _1, _2, ...) _2
#define _H2PP_TH3(_0, _1, _2, _3, ...) _3
#define _H2PP_TH4(_0, _1, _2, _3, _4, ...) _4
#define _H2PP_TH5(_0, _1, _2, _3, _4, _5, ...) _5
#define _H2PP_TH6(_0, _1, _2, _3, _4, _5, _6, ...) _6
#define _H2PP_TH7(_0, _1, _2, _3, _4, _5, _6, _7, ...) _7
#define _H2PP_TH8(_0, _1, _2, _3, _4, _5, _6, _7, _8, ...) _8
#define _H2PP_TH9(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, ...) _9
#define _H2PP_TH10(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, ...) _10
#define _H2PP_TH11(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, ...) _11
#define _H2PP_TH12(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ...) _12
#define _H2PP_TH13(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, ...) _13
#define _H2PP_TH14(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, ...) _14
#define _H2PP_TH15(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, ...) _15
#define _H2PP_TH16(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, ...) _16
#define _H2PP_TH17(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, ...) _17
#define _H2PP_TH18(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, ...) _18
#define _H2PP_TH19(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, ...) _19
#define _H2PP_TH20(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, ...) _20
#define _H2PP_TH21(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, ...) _21
#define _H2PP_TH22(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, ...) _22
#define _H2PP_TH23(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, ...) _23
#define _H2PP_TH24(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, ...) _24
#define _H2PP_TH25(_0, _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, ...) _25
#define _H2PP_TH26(_0, _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, ...) _26
#define _H2PP_TH27(_0, _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, ...) _27
#define _H2PP_TH28(_0, _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, ...) _28
#define _H2PP_TH29(_0, _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, ...) _29
#define _H2PP_TH30(_0, _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, ...) _30
#define _H2PP_TH31(_0, _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, ...) _31
#define H2PP_TH0(...) H2PP_PROXY2(_H2PP_TH, 0, (__VA_ARGS__, ))
#define H2PP_TH1(...) H2PP_PROXY2(_H2PP_TH, 1, (__VA_ARGS__, , ))
#define H2PP_TH2(...) H2PP_PROXY2(_H2PP_TH, 2, (__VA_ARGS__, , , ))
#define H2PP_TH3(...) H2PP_PROXY2(_H2PP_TH, 3, (__VA_ARGS__, , , , ))
#define H2PP_TH4(...) H2PP_PROXY2(_H2PP_TH, 4, (__VA_ARGS__, , , , , ))
#define H2PP_TH5(...) H2PP_PROXY2(_H2PP_TH, 5, (__VA_ARGS__, , , , , , ))
#define H2PP_TH6(...) H2PP_PROXY2(_H2PP_TH, 6, (__VA_ARGS__, , , , , , , ))
#define H2PP_TH7(...) H2PP_PROXY2(_H2PP_TH, 7, (__VA_ARGS__, , , , , , , , ))
#define H2PP_TH8(...) H2PP_PROXY2(_H2PP_TH, 8, (__VA_ARGS__, , , , , , , , , ))
#define H2PP_TH9(...) H2PP_PROXY2(_H2PP_TH, 9, (__VA_ARGS__, , , , , , , , , , ))
#define H2PP_TH10(...) H2PP_PROXY2(_H2PP_TH, 10, (__VA_ARGS__, , , , , , , , , , , ))
#define H2PP_TH11(...) H2PP_PROXY2(_H2PP_TH, 11, (__VA_ARGS__, , , , , , , , , , , , ))
#define H2PP_TH12(...) H2PP_PROXY2(_H2PP_TH, 12, (__VA_ARGS__, , , , , , , , , , , , , ))
#define H2PP_TH13(...) H2PP_PROXY2(_H2PP_TH, 13, (__VA_ARGS__, , , , , , , , , , , , , , ))
#define H2PP_TH14(...) H2PP_PROXY2(_H2PP_TH, 14, (__VA_ARGS__, , , , , , , , , , , , , , , ))
#define H2PP_TH15(...) H2PP_PROXY2(_H2PP_TH, 15, (__VA_ARGS__, , , , , , , , , , , , , , , , ))
#define H2PP_TH16(...) H2PP_PROXY2(_H2PP_TH, 16, (__VA_ARGS__, , , , , , , , , , , , , , , , , ))
#define H2PP_TH17(...) H2PP_PROXY2(_H2PP_TH, 17, (__VA_ARGS__, , , , , , , , , , , , , , , , , , ))
#define H2PP_TH18(...) H2PP_PROXY2(_H2PP_TH, 18, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH19(...) H2PP_PROXY2(_H2PP_TH, 19, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH20(...) H2PP_PROXY2(_H2PP_TH, 20, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH21(...) H2PP_PROXY2(_H2PP_TH, 21, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH22(...) H2PP_PROXY2(_H2PP_TH, 22, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH23(...) H2PP_PROXY2(_H2PP_TH, 23, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH24(...) H2PP_PROXY2(_H2PP_TH, 24, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH25(...) H2PP_PROXY2(_H2PP_TH, 25, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH26(...) H2PP_PROXY2(_H2PP_TH, 26, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH27(...) H2PP_PROXY2(_H2PP_TH, 27, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH28(...) H2PP_PROXY2(_H2PP_TH, 28, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH29(...) H2PP_PROXY2(_H2PP_TH, 29, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH30(...) H2PP_PROXY2(_H2PP_TH, 30, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_TH31(...) H2PP_PROXY2(_H2PP_TH, 31, (__VA_ARGS__, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ))
#define H2PP_INC_0 1
#define H2PP_INC_1 2
#define H2PP_INC_2 3
#define H2PP_INC_3 4
#define H2PP_INC_4 5
#define H2PP_INC_5 6
#define H2PP_INC_6 7
#define H2PP_INC_7 8
#define H2PP_INC_8 9
#define H2PP_INC_9 10
#define H2PP_INC_10 11
#define H2PP_INC_11 12
#define H2PP_INC_12 13
#define H2PP_INC_13 14
#define H2PP_INC_14 15
#define H2PP_INC_15 16
#define H2PP_INC_16 17
#define H2PP_INC_17 18
#define H2PP_INC_18 19
#define H2PP_INC_19 20
#define H2PP_INC_20 21
#define H2PP_INC_21 22
#define H2PP_INC_22 23
#define H2PP_INC_23 24
#define H2PP_INC_24 25
#define H2PP_INC_25 26
#define H2PP_INC_26 27
#define H2PP_INC_27 28
#define H2PP_INC_28 29
#define H2PP_INC_29 30
#define H2PP_INC_30 31
#define H2PP_INC_31 32
#define H2PP_DEC_1 0
#define H2PP_DEC_2 1
#define H2PP_DEC_3 2
#define H2PP_DEC_4 3
#define H2PP_DEC_5 4
#define H2PP_DEC_6 5
#define H2PP_DEC_7 6
#define H2PP_DEC_8 7
#define H2PP_DEC_9 8
#define H2PP_DEC_10 9
#define H2PP_DEC_11 10
#define H2PP_DEC_12 11
#define H2PP_DEC_13 12
#define H2PP_DEC_14 13
#define H2PP_DEC_15 14
#define H2PP_DEC_16 15
#define H2PP_DEC_17 16
#define H2PP_DEC_18 17
#define H2PP_DEC_19 18
#define H2PP_DEC_20 19
#define H2PP_DEC_21 20
#define H2PP_DEC_22 21
#define H2PP_DEC_23 22
#define H2PP_DEC_24 23
#define H2PP_DEC_25 24
#define H2PP_DEC_26 25
#define H2PP_DEC_27 26
#define H2PP_DEC_28 27
#define H2PP_DEC_29 28
#define H2PP_DEC_30 29
#define H2PP_DEC_31 30
#define H2PP_DEC_32 31
#define _H2PP_EVAL_128(...) _H2PP_EVAL_64(_H2PP_EVAL_64(__VA_ARGS__))
#define _H2PP_EVAL_64(...) _H2PP_EVAL_32(_H2PP_EVAL_32(__VA_ARGS__))
#define _H2PP_EVAL_32(...) _H2PP_EVAL_16(_H2PP_EVAL_16(__VA_ARGS__))
#define _H2PP_EVAL_16(...) _H2PP_EVAL_8(_H2PP_EVAL_8(__VA_ARGS__))
#define _H2PP_EVAL_8(...) _H2PP_EVAL_4(_H2PP_EVAL_4(__VA_ARGS__))
#define _H2PP_EVAL_4(...) _H2PP_EVAL_2(_H2PP_EVAL_2(__VA_ARGS__))
#define _H2PP_EVAL_2(...) _H2PP_EVAL_1(_H2PP_EVAL_1(__VA_ARGS__))
#define _H2PP_EVAL_1(...) __VA_ARGS__
#define _H2PP_64TH(_0, _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, ...) _64
#define H2PP_HAS_COMMA(...) H2PP_PROXY(_H2PP_64TH, (__VA_ARGS__, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0))
#define H2PP_ARG_COUNT(...) H2PP_PROXY(_H2PP_64TH, (__VA_ARGS__, 64, 63, 62, 61, 60, 59, 58, 57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46, 45, 44, 43, 42, 41, 40, 39, 38, 37, 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1))
//////// <<<<< generated by build/generate.py
// source/utils/h2_array.hpp
template <typename T>
struct h2_array {
typedef typename std::decay<T>::type value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef value_type* iterator;
typedef const value_type* const_iterator;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
value_type* elems;
std::size_t count;
h2_array(const value_type* elems_, const std::size_t count_) : elems((value_type*)elems_), count(count_) {}
iterator begin() noexcept { return iterator(data()); }
const_iterator begin() const noexcept { return const_iterator(data()); }
iterator end() noexcept { return iterator(data() + count); }
const_iterator end() const noexcept { return const_iterator(data() + count); }
const_iterator cbegin() const noexcept { return const_iterator(data()); }
const_iterator cend() const noexcept { return const_iterator(data() + count); }
constexpr size_type size() const noexcept { return count; }
constexpr size_type max_size() const noexcept { return count; }
constexpr bool empty() const noexcept { return size() == 0; }
reference operator[](size_type __n) noexcept { return elems[__n]; }
constexpr const_reference operator[](size_type __n) const noexcept { return elems[__n]; }
reference at(size_type __n) { return elems[__n]; }
constexpr const_reference at(size_type __n) const { return elems[__n]; }
reference front() noexcept { return *begin(); }
constexpr const_reference front() const noexcept { return elems[0]; }
reference back() noexcept { return count ? *(end() - 1) : *end(); }
constexpr const_reference back() const noexcept { return count ? elems[count - 1] : elems[0]; }
pointer data() noexcept { return elems; }
const_pointer data() const noexcept { return elems; }
};
// source/utils/h2_template.hpp
template <typename T> struct h2_type_identity { typedef T type; }; // std::type_identity
template <typename...> struct h2_true_type : std::true_type {};
template <typename T, typename = void>
struct h2_is_smart_ptr : std::false_type {};
template <typename T>
struct h2_is_smart_ptr<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::shared_ptr<typename T::element_type>>::value>::type> : std::true_type {};
template <typename T>
struct h2_is_smart_ptr<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::unique_ptr<typename T::element_type>>::value>::type> : std::true_type {};
template <typename T>
struct h2_is_smart_ptr<T, typename std::enable_if<std::is_same<typename std::remove_cv<T>::type, std::weak_ptr<typename T::element_type>>::value>::type> : std::true_type {};
template <typename U, typename = void>
struct h2_decay_impl : h2_type_identity<U> {};
template <>
struct h2_decay_impl<char*> : h2_type_identity<const char*> {};
template <typename U>
struct h2_decay_impl<U, typename std::enable_if<std::is_enum<U>::value>::type> : h2_type_identity<typename std::underlying_type<U>::type> {};
template <typename T>
struct h2_decay : h2_decay_impl<typename std::decay<T>::type> {};
template <std::size_t I, typename T, typename... S>
struct h2_nth_type_impl : h2_type_identity<typename h2_nth_type_impl<I - 1, S...>::type> {};
template <typename T, typename... S>
struct h2_nth_type_impl<0, T, S...> : h2_type_identity<T> {};
template <std::size_t I, typename... S>
struct h2_nth_type : h2_type_identity<typename h2_nth_type_impl<I, S..., int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>::type> {};
template <std::size_t I, typename... S>
using h2_nth_decay = typename h2_decay<typename h2_nth_type<I, S...>::type>::type;
template <typename T, typename = void>
struct h2_sizeof_pointee : std::integral_constant<std::size_t, sizeof(typename std::remove_pointer<T>::type)> {};
template <typename T>
struct h2_sizeof_pointee<T, typename std::enable_if<std::is_void<typename std::remove_pointer<T>::type>::value>::type> : std::integral_constant<std::size_t, 1> {};
template <typename T>
struct h2_sizeof_pointee<T, typename std::enable_if<h2_is_smart_ptr<T>::value>::type> : std::integral_constant<std::size_t, sizeof(typename T::element_type)> {}; // smart ptr not hold void*
template <typename T>
struct h2_pointee_type : h2_type_identity<typename T::element_type> {};
template <typename T>
struct h2_pointee_type<T*> : h2_type_identity<T> {};
template <typename T>
inline T* h2_pointer_if(T* a) { return a; }
template <typename T>
inline auto h2_pointer_if(T& a) -> typename std::enable_if<h2_is_smart_ptr<T>::value, typename T::element_type*>::type { return a.get(); }
template <typename T>
inline auto h2_pointer_if(T& a) -> typename std::enable_if<!h2_is_smart_ptr<T>::value, T*>::type { return &a; }
template <typename T>
struct h2_is_pair : std::false_type {};
template <typename K, typename V>
struct h2_is_pair<std::pair<K, V>> : std::true_type {};
template <typename T, typename = void>
struct h2_is_iterable : std::false_type {};
template <typename T>
struct h2_is_iterable<T,
typename std::enable_if<h2_true_type<typename T::value_type,
typename T::size_type,
typename T::iterator,
typename T::const_iterator,
decltype(std::declval<T>().begin()),
decltype(std::declval<T>().end()),
decltype(std::declval<T>().cbegin()),
decltype(std::declval<T>().cend())>::value>::type> : std::true_type {};
template <typename T, typename = void>
struct h2_has_substr : std::false_type {};
template <typename T>
struct h2_has_substr<T, typename std::enable_if<h2_true_type<decltype(std::declval<T>().substr())>::value>::type> : std::true_type {};
template <typename T> struct h2_is_container : std::conditional<h2_is_iterable<T>::value && !h2_has_substr<T>::value, std::true_type, std::false_type>::type {};
template <typename T> struct h2_is_string : std::conditional<h2_is_iterable<T>::value && h2_has_substr<T>::value, std::true_type, std::false_type>::type {};
template <typename T, typename = void>
struct h2_is_map : std::false_type {};
template <typename T>
struct h2_is_map<T, typename std::enable_if<h2_is_iterable<T>::value && h2_true_type<typename T::mapped_type>::value>::type> : std::true_type {};
template <typename T, typename = void>
struct h2_is_container_adaptor : std::false_type {};
template <typename T>
struct h2_is_container_adaptor<T, typename std::enable_if<h2_true_type<typename T::value_type, typename T::size_type, typename T::container_type>::value>::type> : std::true_type {};
template <typename ContainerAdaptor>
const typename ContainerAdaptor::container_type& underlying_container(const ContainerAdaptor& ca)
{
struct AntiProtected : ContainerAdaptor {
static const typename ContainerAdaptor::container_type& get(const ContainerAdaptor& ca) { return ca.*&AntiProtected::c; }
};
return AntiProtected::get(ca);
}
#if __cplusplus >= 201402L || (defined _MSVC_LANG && _MSVC_LANG >= 201402L)
#define h2_index_sequence std::index_sequence
#define h2_make_index_sequence std::make_index_sequence
#else
template <std::size_t...> struct h2_index_sequence {};
template <std::size_t N, std::size_t... S> struct h2_make_index_sequence : h2_make_index_sequence<N - 1, N - 1, S...> {};
template <std::size_t... S> struct h2_make_index_sequence<0, S...> : h2_index_sequence<S...> {};
#endif
// source/utils/h2_numberfy.hpp
template <typename T, typename = void>
struct h2_numberfy_impl {
static std::uintptr_t cast(T a) { return a; }
};
template <typename T>
struct h2_numberfy_impl<T, typename std::enable_if<std::is_pointer<T>::value>::type> {
static std::uintptr_t cast(T a) { return reinterpret_cast<std::uintptr_t>(a); } // https://stackoverflow.com/questions/153065/converting-a-pointer-into-an-integer
};
template <typename T>
struct h2_numberfy_impl<T, typename std::enable_if<std::is_member_pointer<T>::value>::type> { // non-static member object or non-static member function
static std::uintptr_t cast(T a)
{
union {
T a;
std::uintptr_t b;
} u;
u.a = a;
return u.b;
}
};
template <typename T>
struct h2_numberfy_impl<T, typename std::enable_if<h2_is_smart_ptr<T>::value>::type> {
static std::uintptr_t cast(T a) { return h2_numberfy_impl<typename T::element_type*>::cast(a.get()); }
};
template <>
struct h2_numberfy_impl<std::nullptr_t> {
static std::uintptr_t cast(std::nullptr_t) { return 0; }
};
template <typename R, typename F>
static R h2_numberfy(F f) { return (R)h2_numberfy_impl<F>::cast(f); }
// template function can't partial specialization, redirect to template class partial specialization
// source/utils/h2_list.hpp
#define h2_list_entry(ptr, type, link) ((type*)((char*)(ptr) - (char*)(&(((type*)(1))->link)) + 1))
#define h2_list_for_each_entry(...) H2PP_VCALL(__h2_list_for_each_entry, H2PP_UNIQUE(t), __VA_ARGS__)
#define __h2_list_for_each_entry5(t, p, head, type, link) \
for (type* p = h2_list_entry((head).next, type, link), *t = h2_list_entry(p->link.next, type, link); &p->link != &(head); p = t, t = h2_list_entry(t->link.next, type, link))
#define __h2_list_for_each_entry6(t, p, i, head, type, link) \
for (int i = 0; !i; ++i) \
for (type* p = h2_list_entry((head).next, type, link), *t = h2_list_entry(p->link.next, type, link); &p->link != &(head); p = t, t = h2_list_entry(t->link.next, type, link), ++i)
#define h2_list_for_each_reverse_entry(p, head, type, link) \
for (type* p = h2_list_entry((head).prev, type, link), *t_ = h2_list_entry(p->link.prev, type, link); &p->link != &(head); p = t_, t_ = h2_list_entry(t_->link.prev, type, link))
#define h2_list_pop_entry(head, type, link) ((head).empty() ? (type*)0 : h2_list_entry(&(head).pop(), type, link))
#define h2_list_top_entry(head, type, link) ((head).empty() ? (type*)0 : h2_list_entry((head).next, type, link))
#define h2_list_bottom_entry(head, type, link) ((head).empty() ? (type*)0 : h2_list_entry((head).prev, type, link))
struct h2_list {
struct h2_list *next, *prev;
h2_list() : next(this), prev(this) {}
h2_list& add_head(h2_list& entry);
h2_list& add_tail(h2_list& entry);
h2_list& add_before(h2_list& entry);
h2_list& add_after(h2_list& entry);
h2_list& push_back(h2_list& entry) { return add_tail(entry); }
h2_list& push(h2_list& entry) { return add_head(entry); }
h2_list& pop() { return next->out(); }
h2_list& pop_back() { return prev->out(); }
bool is_first(h2_list* entry) const { return next == entry; }
bool is_last(h2_list* entry) const { return prev == entry; }
h2_list& out();
bool empty() const { return next == this; }
int count() const;
void sort(int (*cmp)(h2_list*, h2_list*));
};
// source/utils/h2_pattern.hpp
struct h2_pattern {
static bool regex_match(const char* pattern, const char* subject, bool caseless = false);
static bool wildcard_match(const char* pattern, const char* subject, bool caseless = false);
static bool match(const char* pattern, const char* subject, bool caseless = false);
};
// source/utils/h2_misc.hpp
#define H2_FILINE __FILE__ ":" H2PP_STR(__LINE__)
struct h2_once {
unsigned long long c = 0;
operator bool() { return !c++; }
};
#define h2_once_if() for (static h2_once ___1_; ___1_;)
// #define M(...) func(#__VA_ARGS__, other)
// Unix M() ==> func("", other) stringify empty __VA_ARGS__ to "" string
// Windows M() ==> func(, other) stringify empty __VA_ARGS__ to empty
// #define M(...) func(ss(#__VA_ARGS__), other)
static inline const char* ss(const char* a = "") { return a ? a : ""; }
static inline const char* comma_if(bool a, const char* t = ", ", const char* f = "") { return a ? t : f; }
static inline const char* quote_if(bool a, const char* t = "\"", const char* f = "") { return a ? t : f; }
#define H2Foreach(Callback_x, ...) H2PP_FOREACH(, _H2ForeachMacro, (Callback_x), H2PP_REMOVE_PARENTHESES_IF(__VA_ARGS__))
#define _H2ForeachMacro(_Args, i, x) H2PP_REMOVE_PARENTHESES(_Args)(x)
#define H2Fullmesh(Callback_x_y, ...) H2PP_FULLMESH(, _H2FullmeshMacro, (Callback_x_y), __VA_ARGS__)
#define _H2FullmeshMacro(_Args, i, j, x, y) H2PP_REMOVE_PARENTHESES(_Args)(x, y)
/* clang-format off */
#define h2_singleton(Class) static Class& I() { static Class i; return i; }
#define h2_array_append(Array, a) do { for (size_t i = 0; i < sizeof(Array) / sizeof(Array)[0] - 1; ++i) if (!(Array)[i]) { (Array)[i] = (a); break; } } while (0)
// source/utils/h2_libc.hpp
struct h2_libc {
static void* malloc(size_t size);
static void free(void* ptr);
static void* operator new(std::size_t size) { return malloc(size); }
static void operator delete(void* ptr) { free(ptr); }
};
// source/utils/h2_shared_ptr.hpp
template <typename T>
struct h2_shared_ptr {
h2_shared_ptr() = default;
explicit h2_shared_ptr(T* p) { acquire(p, nullptr); }
h2_shared_ptr(const h2_shared_ptr& that) { acquire(that.px, that.pn); }
~h2_shared_ptr() { release(); }
h2_shared_ptr& operator=(h2_shared_ptr that)
{
std::swap(px, that.px);
std::swap(pn, that.pn);
return *this;
}
void reset() { release(); }
operator bool() const { return pn && 0 < *pn; }
T& operator*() const { return *px; }
T* operator->() const { return px; }
void acquire(T* p, long* n)
{
pn = n;
if (p) pn ? ++*pn : *(pn = (long*)h2_libc::malloc(sizeof(long))) = 1;
px = p;
}
void release()
{
if (pn && !--*pn) {
delete px;
h2_libc::free(pn);
}
px = nullptr;
pn = nullptr;
}
T* px = nullptr;
long* pn = nullptr;
};
// source/utils/h2_allocate.hpp
template <typename T>
class h2_allocator {
public:
typedef size_t size_type;
typedef long long difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
h2_allocator() {}
h2_allocator(const h2_allocator&) {}
pointer allocate(size_type n, const void* = 0) { return (T*)h2_libc::malloc(n * sizeof(T)); }
void deallocate(void* p, size_type) { h2_libc::free(p); }
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
h2_allocator<T>& operator=(const h2_allocator&) { return *this; }
void construct(pointer p, const T& val) { new ((T*)p) T(val); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const { return size_t(-1); }
template <typename U> struct rebind {
typedef h2_allocator<U> other;
};
template <typename U> h2_allocator(const h2_allocator<U>&) {}
template <typename U> h2_allocator& operator=(const h2_allocator<U>&) { return *this; }
};
template <typename T> inline bool operator==(const h2_allocator<T>&, const h2_allocator<T>&) { return true; }
template <typename T> inline bool operator!=(const h2_allocator<T>&, const h2_allocator<T>&) { return false; }
template <typename T> using h2_vector = std::vector<T, h2_allocator<T>>;
using h2_ostringstream = std::basic_ostringstream<char, std::char_traits<char>, h2_allocator<char>>;
// source/utils/h2_string.hpp
struct h2_string : public std::basic_string<char, std::char_traits<char>, h2_allocator<char>> {
h2_string() : basic_string() {}
h2_string(const h2_string& s) : basic_string(s.data(), s.size()) {}
h2_string(const std::string& s) : basic_string(s.data(), s.size()) {}
template <typename... T>
h2_string(const char* fmt, T... t) : basic_string() { sizeof...(T) ? sprintf(fmt, t...) : assign(fmt ? fmt : "(null)"); }
h2_string(size_t n, const char* s) : basic_string(s, n) {}
h2_string(size_t n, const char c) : basic_string(n, c) {}
h2_string& operator=(const h2_string& s) { return assign(s.data(), s.size()), *this; }
h2_string& operator=(const std::string& s) { return assign(s.data(), s.size()), *this; }
h2_string& operator=(const char* s) { return assign(s ? s : "(null)"), *this; }
h2_string& operator=(const char c) { return assign(1, c), *this; }
h2_string& operator+=(const h2_string& s) { return append(s.data(), s.size()), *this; }
h2_string& operator+=(const std::string& s) { return append(s.data(), s.size()), *this; }
h2_string& operator+=(const char* s) { return append(s), *this; }
h2_string& operator+=(const char c) { return push_back(c), *this; }
operator unsigned char*() const { return (unsigned char*)data(); }
h2_string& sprintf(const char* fmt, ...);
h2_string& replace_all(const char* from, const char* to);
size_t width(size_t fat = 2) const;
bool equals(const h2_string& fulstr, bool caseless = false) const;
bool contains(const h2_string& substr, bool caseless = false) const;
bool startswith(const h2_string& prefix, bool caseless = false) const;
bool endswith(const h2_string& suffix, bool caseless = false) const;
bool enclosed(char left = '\"', char right = '\0') const;
h2_string unenclose(char left = '\"', char right = '\0') const;
h2_string escape(bool utf8 = false) const;
h2_string unescape() const;
h2_string trim() const;
h2_string squash(bool quote = false) const;
h2_string tolower() const;
h2_string centre(size_t width) const;
h2_vector<h2_string> disperse() const;
};
/* clang-format off */
inline h2_string operator+(const h2_string& lhs, const h2_string& rhs) { h2_string s(lhs); s.append(rhs); return s; }
inline h2_string operator+(const h2_string& lhs, const char* rhs) { h2_string s(lhs); s.append(rhs); return s; }
inline h2_string operator+(const char* lhs, const h2_string& rhs) { h2_string s(lhs); s.append(rhs); return s; }
inline h2_string operator+(const h2_string& lhs, const std::string& rhs) { h2_string s(lhs); s.append(rhs.c_str()); return s; }
inline h2_string operator+(const std::string& lhs, const h2_string& rhs) { h2_string s(lhs.c_str()); s.append(rhs); return s; }
inline h2_string operator+(const h2_string& lhs, const char rhs) { h2_string s(lhs); s.push_back(rhs); return s; }
inline h2_string operator+(const char lhs, const h2_string& rhs) { h2_string s(1, lhs); s.append(rhs); return s; }
// source/utils/h2_line.hpp
struct h2_line : h2_vector<h2_string> {
h2_line() {}
h2_line(const char* a) : h2_vector<h2_string>({a}) {}
h2_line(const h2_string& a) : h2_vector<h2_string>({a}) {}
h2_line(std::initializer_list<h2_string> il) : h2_vector<h2_string>(il) {}
size_t width(bool ignore_indent = false) const;
h2_line& indent(size_t n, const char c = ' ');
h2_line& padding(size_t n, const char c = ' ');
h2_line& printf(const char* style, const char* format, ...);
h2_line& operator+=(const h2_line& line);
h2_line& brush(const char* style);
bool enclosed(char left = '\"', char right = '\0') const;
bool has(const char* word) const;
h2_line gray_quote() const;
h2_line abbreviate(size_t width = 16, size_t tail = 0) const;
h2_string string() const;
static void samesizify(h2_line& a, h2_line& b);
};
inline h2_line operator+(const h2_line& a, const h2_line& b) // implicit conversion const char* / h2_string
{
h2_line line;
line.insert(line.end(), a.begin(), a.end());
line.insert(line.end(), b.begin(), b.end());
return line;
}
static inline const h2_line color(const h2_line& line, const char* style) { return ("\033{" + h2_string(style) + "}") + line + "\033{reset}"; }
static inline const h2_line delta(const h2_line& line, const char* style) { return ("\033{+" + h2_string(style) + "}") + line + ("\033{-" + h2_string(style) + "}"); }
static inline const h2_line gray(const char* s) { return s && strlen(s) ? delta(s, "dark gray") : h2_line(); }
///// h2_lines
struct h2_lines : h2_vector<h2_line> {
h2_lines() {}
h2_lines(std::initializer_list<h2_line> il) : h2_vector<h2_line>(il) {}
h2_lines& operator+=(const h2_lines& lines);
size_t width() const;
bool foldable(size_t width = 20) const;
h2_line folds() const;
h2_string string() const;
void sequence(size_t indent = 0, size_t start = 0);
static void samesizify(h2_lines& a, h2_lines& b);
};
// source/utils/h2_stringify.hpp
template <typename T, typename = void>
struct h2_stringify_impl {
static h2_line print(const T&, bool = false) { return "?"; }
};
#define H2_TOSTRING_ABLE(tostring) \
template <typename T> struct h2_##tostring##_able { \
template <typename U> static auto return_type(U* u) -> decltype(u->tostring()); \
template <typename U> static void return_type(...); \
static constexpr bool value = std::is_convertible<decltype(return_type<T>(nullptr)), h2_string>::value; \
};
H2_TOSTRING_ABLE(tostring);
H2_TOSTRING_ABLE(toString);
H2_TOSTRING_ABLE(Tostring);
H2_TOSTRING_ABLE(ToString);
H2_TOSTRING_ABLE(to_string);
/* tostring() may not be mark const, remove cast const in T a; fix multi-tostring */
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<h2::h2_tostring_able<T>::value || h2::h2_toString_able<T>::value || h2::h2_Tostring_able<T>::value || h2::h2_ToString_able<T>::value || h2::h2_to_string_able<T>::value>::type> {
static h2_line print(const T& a, bool represent = false) { return gray(quote_if(represent)) + print__tostring(a) + gray(quote_if(represent)); }
template <typename U> static auto print__tostring(const U& a) -> typename std::enable_if<h2::h2_tostring_able<U>::value, h2_string>::type { return const_cast<U&>(a).tostring(); }
template <typename U> static auto print__tostring(const U& a) -> typename std::enable_if<!h2::h2_tostring_able<U>::value, h2_string>::type { return print__toString(a); }
template <typename U> static auto print__toString(const U& a) -> typename std::enable_if<h2::h2_toString_able<U>::value, h2_string>::type { return const_cast<U&>(a).toString(); }
template <typename U> static auto print__toString(const U& a) -> typename std::enable_if<!h2::h2_toString_able<U>::value, h2_string>::type { return print__Tostring(a); }
template <typename U> static auto print__Tostring(const U& a) -> typename std::enable_if<h2::h2_Tostring_able<U>::value, h2_string>::type { return const_cast<U&>(a).toString(); }
template <typename U> static auto print__Tostring(const U& a) -> typename std::enable_if<!h2::h2_Tostring_able<U>::value, h2_string>::type { return print__ToString(a); }
template <typename U> static auto print__ToString(const U& a) -> typename std::enable_if<h2::h2_ToString_able<U>::value, h2_string>::type { return const_cast<U&>(a).ToString(); }
template <typename U> static auto print__ToString(const U& a) -> typename std::enable_if<!h2::h2_ToString_able<U>::value, h2_string>::type { return print__to_string(a); }
template <typename U> static auto print__to_string(const U& a) -> typename std::enable_if<h2::h2_to_string_able<U>::value, h2_string>::type { return const_cast<U&>(a).to_string(); }
template <typename U> static auto print__to_string(const U& a) -> typename std::enable_if<!h2::h2_to_string_able<U>::value, h2_string>::type { return ""; }
};
template <typename T>
struct h2_is_streamable { // exclude number
template <typename U> static auto test(U* u) -> decltype(std::declval<std::ostream&>() << *u, std::true_type());
template <typename U> static auto test(...) -> std::false_type;
static constexpr bool value = decltype(test<T>(nullptr))::value && !std::is_arithmetic<T>::value;
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<h2_is_streamable<T>::value>::type> {
static h2_line print(const T& a, bool represent = false)
{
h2_ostringstream oss;
oss << a;
represent = represent && std::is_convertible<T, h2_string>::value;
return gray(quote_if(represent)) + oss.str().c_str() + gray(quote_if(represent));
}
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<std::is_arithmetic<T>::value>::type> {
static h2_line print(const T& a, bool = false)
{
#if defined _MSC_VER || defined __CYGWIN__ // std::to_string issue
h2_ostringstream oss;
oss << std::fixed << std::setprecision(std::numeric_limits<T>::digits10 + 1) << a;
auto str = oss.str();
#else
auto str = std::to_string(a);
#endif
if (str.find_first_of('.') != std::string::npos) {
str.erase(str.find_last_not_of("0") + 1);
str.erase(str.find_last_not_of(".") + 1);
}
return str.c_str();
}
};
template <typename K, typename V>
struct h2_stringify_impl<std::pair<K, V>> {
static h2_line print(const std::pair<K, V>& a, bool represent = false)
{
return gray("(") + h2_stringify_impl<K>::print(a.first, represent) + gray(", ") + h2_stringify_impl<V>::print(a.second, represent) + gray(")");
}
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<h2_is_container<T>::value>::type> {
static h2_line print(const T& a, bool represent = false)
{
h2_line line;
int count = 0; // too large too print
for (auto it = a.begin(); it != a.end(); ++it)
if (++count > 100) return gray("[") + "..." + gray("]");
for (auto it = a.begin(); it != a.end(); ++it)
line += gray(comma_if(it != a.begin())) + h2_stringify_impl<typename T::value_type>::print(*it, represent);
return gray("[") + line + gray("]");
}
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<h2_is_container_adaptor<T>::value>::type> {
static h2_line print(const T& a, bool represent = false)
{
auto _a = underlying_container(a);
return h2_stringify_impl<decltype(_a)>::print(_a, represent);
}
};
template <typename... Args>
struct h2_stringify_impl<std::tuple<Args...>> {
static h2_line print(const std::tuple<Args...>& a, bool represent = false)
{
return gray("(") + tuple_print(a, represent, std::integral_constant<std::size_t, sizeof...(Args)>()) + gray(")");
}
static h2_line tuple_print(const std::tuple<Args...>& a, bool represent, std::integral_constant<std::size_t, 0>) { return {}; }
template <std::size_t I>
static h2_line tuple_print(const std::tuple<Args...>& a, bool represent, std::integral_constant<std::size_t, I>)
{
return tuple_print(a, represent, std::integral_constant<std::size_t, I - 1>()) + gray(comma_if(1 < I)) + h2_stringify_impl<typename std::decay<decltype(std::get<I - 1>(a))>::type>::print(std::get<I - 1>(a), represent);
}
};
template <>
struct h2_stringify_impl<std::nullptr_t> {
static h2_line print(std::nullptr_t a, bool = false) { return "nullptr"; }
};
template <>
struct h2_stringify_impl<bool> {
static h2_line print(const bool a, bool = false) { return a ? "true" : "false"; }
};
template <>
struct h2_stringify_impl<const char*> {
static h2_line print(const char* a, bool represent) { return a ? h2_stringify_impl<h2_string>::print(h2_string{a}, represent) : h2_line{"(null)"}; }
};
template <>
struct h2_stringify_impl<char*> {
static h2_line print(char* a, bool represent) { return h2_stringify_impl<const char*>::print(a, represent); }
};
template <>
struct h2_stringify_impl<unsigned char> { // https://en.cppreference.com/w/cpp/string/byte/isprint
static h2_line print(unsigned char a, bool) { return h2_stringify_impl<unsigned int>::print(static_cast<unsigned int>(a), false); }
};
template <>
struct h2_stringify_impl<char> {
static h2_line print(char a, bool represent) { return gray(quote_if(represent, "'")) + h2_string(1, a) + gray(quote_if(represent, "'")); }
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<h2_is_string<T>::value && std::is_same<wchar_t, typename T::value_type>::value>::type> {
static h2_line print(const T& a, bool represent = false)
{
h2_string s;
for (auto c : a) s += (c <= 0xff) ? static_cast<char>(c) : '?';
return h2_stringify_impl<h2_string>::print(s, represent);
}
};
template <>
struct h2_stringify_impl<const wchar_t*> {
static h2_line print(const wchar_t* a, bool represent) { return a ? h2_stringify_impl<std::wstring>::print(std::wstring{a}, represent) : h2_line{"(null)"}; }
};
template <>
struct h2_stringify_impl<wchar_t*> {
static h2_line print(wchar_t* a, bool represent) { return h2_stringify_impl<const wchar_t*>::print(a, represent); }
};
template <>
struct h2_stringify_impl<wchar_t> {
static h2_line print(wchar_t a, bool represent) { return h2_stringify_impl<char>::print((a <= 0xff) ? static_cast<char>(a) : '?', represent); }
};
template <typename T>
struct h2_stringify_impl<T, typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {