blob: b92badabde14c9d8c8f9aa53e8c00e52d241e631 (
plain) (
blame)
| 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
 | #pragma once
#include "scheme.h"
#include <util/thread/singleton.h>
namespace NSc {
    namespace NImpl {
        template <typename TContext>
        static inline TContext& GetTlsInstance() {
            return *FastTlsSingleton<TContext>();
        }
        template <typename TContext>
        class TContextGuard : TNonCopyable {
            using TElement = typename TContext::TElement;
            using TTarget = typename TContext::TTarget;
            using TVectorType = TVector<TElement>;
        public:
            TContextGuard(TContext& ctx, TTarget& target)
                : Ctx(ctx)
                , Active(TContext::Needed(target))
            {
                if (Active) {
                    Begin = Ctx.Vector.size();
                    Ok = Ctx.Process(target);
                    End = Ctx.Vector.size();
                }
            }
            ~TContextGuard() noexcept {
                if (Active) {
                    Ctx.Vector.resize(Begin);
                }
            }
            const TVectorType& GetVector() const {
                return Ctx.Vector;
            }
            using const_iterator = size_t;
            size_t begin() const {
                return Begin;
            }
            size_t end() const {
                return End;
            }
            bool Ok = true;
        private:
            TContext& Ctx;
            size_t Begin = 0;
            size_t End = 0;
            bool Active = false;
        };
        template <typename TElem, typename TTgt>
        class TBasicContext {
        public:
            using TElement = TElem;
            using TTarget = TTgt;
            TBasicContext() {
                Vector.reserve(64);
            }
            TVector<TElement> Vector;
        };
        class TKeySortContext: public TBasicContext<TStringBuf, const TDict> {
        public:
            using TGuard = TContextGuard<TKeySortContext>;
            bool Process(const TDict& self);
            static bool Needed(const TDict& self) {
                return self.size();
            }
        };
        class TSelfOverrideContext: public TBasicContext<TValue, TValue::TScCore> {
        public:
            using TGuard = TContextGuard<TSelfOverrideContext>;
            bool Process(TValue::TScCore& self);
            static bool Needed(const TValue::TScCore& self) {
                return self.HasChildren();
            }
        };
        class TSelfLoopContext: public TBasicContext<const void*, const TValue::TScCore> {
        public:
            enum class EMode {
                Assert, Throw, Abort, Stderr
            };
            using TGuard = TContextGuard<TSelfLoopContext>;
            bool Process(const TValue::TScCore& self);
            static bool Needed(const TValue::TScCore& self) {
                return self.HasChildren();
            }
        public:
            EMode ReportingMode = EMode::Assert;
        };
    }
}
 |