aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/scheme/scimpl_private.h
blob: 3527e0911c8f672ad501d680192e0e3a063e755f (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; 
        }; 
    } 
}