aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/scheme/domscheme_traits.h
blob: 18e1798fd98729272cb6fcda9e250d7398cce40a (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
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
#pragma once

#include "scheme.h"
#include <util/string/cast.h> 

struct TSchemeTraits {
    using TValue = NSc::TValue;
    using TValueRef = TValue*;
    using TConstValueRef = const TValue*;
    using TStringType = TStringBuf;

    // anyvalue defaults
    template <class T>
    static inline TValue Value(T&& t) {
        return TValue(std::forward<T>(t));
    }

    template <class T>
    static inline TValue Value(std::initializer_list<T> t) {
        return TValue().SetArray().AppendAll(t);
    }

    static inline TValueRef Ref(TValue& v) {
        return &v;
    }

    static inline TConstValueRef Ref(const TValue& v) {
        return &v;
    }

    // common ops
    static inline bool IsNull(TConstValueRef v) {
        return v->IsNull();
    }

    static inline TString ToJson(TConstValueRef v) {
        return v->ToJson();
    }

    // struct ops
    static inline TValueRef GetField(TValueRef v, const TStringBuf& name) {
        return &(*v)[name];
    }

    static inline TConstValueRef GetField(TConstValueRef v, const TStringBuf& name) {
        return &(*v)[name];
    }

    // array ops
    static bool IsArray(TConstValueRef v) {
        return v->IsArray();
    }

    static inline void ArrayClear(TValueRef v) {
        v->SetArray();
        v->ClearArray();
    }

    using TArrayIterator = size_t;

    static inline TValueRef ArrayElement(TValueRef v, TArrayIterator n) {
        return &(*v)[n];
    }

    static inline TConstValueRef ArrayElement(TConstValueRef v, TArrayIterator n) {
        return &(*v)[n];
    }

    static inline size_t ArraySize(TConstValueRef v) {
        return v->GetArray().size();
    }

    static inline TArrayIterator ArrayBegin(TConstValueRef) {
        return 0;
    }

    static inline TArrayIterator ArrayEnd(TConstValueRef v) {
        return ArraySize(v);
    }

    // dict ops
    static bool IsDict(TConstValueRef v) {
        return v->IsDict();
    }

    static inline void DictClear(TValueRef v) {
        v->SetDict();
        v->ClearDict();
    }

    static inline TValueRef DictElement(TValueRef v, TStringBuf key) {
        return &(*v)[key];
    }

    static inline TConstValueRef DictElement(TConstValueRef v, TStringBuf key) {
        return &(*v)[key];
    }

    static inline size_t DictSize(TConstValueRef v) {
        return v->GetDict().size();
    }

    using TDictIterator = NSc::TDict::const_iterator;

    static inline TDictIterator DictBegin(TConstValueRef v) {
        return v->GetDict().begin();
    }

    static inline TDictIterator DictEnd(TConstValueRef v) {
        return v->GetDict().end();
    }

    static inline TStringBuf DictIteratorKey(TConstValueRef /*dict*/, const TDictIterator& it) {
        return it->first;
    }

    static inline TConstValueRef DictIteratorValue(TConstValueRef /*dict*/, const TDictIterator& it) {
        return &it->second;
    }

    // boolean ops
    static inline void Get(TConstValueRef v, bool def, bool& b) {
        b = def == true ? !v->IsExplicitFalse() : v->IsTrue();
    }

    static inline void Get(TConstValueRef v, bool& b) {
        b = v->IsTrue();
    }

    static inline void Set(TValueRef v, bool b) {
        v->SetIntNumber(b ? 1 : 0);
    }

    static inline bool IsValidPrimitive(const bool&, TConstValueRef v) {
        return v->IsTrue() || v->IsExplicitFalse();
    }

#define INTEGER_OPS_EX(type, min, max, isUnsigned)                                 \
    static inline void Get(TConstValueRef v, type def, type& i) {                  \
        if (isUnsigned) {                                                          \
            i = v->IsNumber() && v->GetIntNumber() >= 0 ? v->GetIntNumber() : def; \
        } else {                                                                   \
            i = v->IsNumber() ? v->GetIntNumber() : def;                           \
        }                                                                          \
    }                                                                              \
    static inline void Get(TConstValueRef v, type& i) {                            \
        if (isUnsigned) {                                                          \
            i = Max<i64>(0, v->GetIntNumber());                                    \
        } else {                                                                   \
            i = v->GetIntNumber();                                                 \
        }                                                                          \
    }                                                                              \
    static inline bool IsValidPrimitive(const type&, TConstValueRef v) {           \
        return v->IsIntNumber() &&                                                 \
               v->GetIntNumber() >= min &&                                         \
               v->GetIntNumber() <= max;                                           \
    }                                                                              \
    static inline void Set(TValueRef v, type i) {                                  \
        v->SetIntNumber(i);                                                        \
    }

#define INTEGER_OPS(type, isUnsigned) INTEGER_OPS_EX(type, Min<type>(), Max<type>(), isUnsigned)

    INTEGER_OPS(i8, false)
    INTEGER_OPS(i16, false)
    INTEGER_OPS(i32, false)
    INTEGER_OPS(i64, false)
    INTEGER_OPS(ui8, true)
    INTEGER_OPS(ui16, true)
    INTEGER_OPS(ui32, true)
    INTEGER_OPS_EX(ui64, 0, (i64)(Max<i64>() >> 1), true)

#undef INTEGER_OPS
#undef INTEGER_OPS_EX

    // double ops
    static inline bool Get(TConstValueRef v, double def, double& d) {
        if (v->IsNumber()) {
            d = v->GetNumber(def);
            return true;
        }
        d = def;
        return false;
    }

    static inline void Get(TConstValueRef v, double& d) {
        d = v->GetNumber();
    }

    static inline void Set(TValueRef v, double d) {
        v->SetNumber(d);
    }

    static inline bool IsValidPrimitive(const double&, TConstValueRef v) {
        return v->IsNumber();
    }

    // string ops
    static inline void Get(TConstValueRef v, TStringBuf def, TStringBuf& s) {
        s = v->GetString(def);
    }

    static inline void Get(TConstValueRef v, TStringBuf& s) {
        s = v->GetString();
    }

    static inline void Set(TValueRef v, TStringBuf s) {
        v->SetString(s);
    }

    static inline bool IsValidPrimitive(const TStringBuf&, TConstValueRef v) {
        return v->IsString();
    }

    // validation ops
    static inline TVector<TString> GetKeys(TConstValueRef v) {
        TVector<TString> res;
        for (const auto& key : v->DictKeys(true)) {
            res.push_back(ToString(key));
        }
        return res;
    }

    template <typename T>
    static inline bool IsValidPrimitive(const T&, TConstValueRef) {
        return false;
    }
};