yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Yong HeLanguageServer: Enhance auto completion for override. (#7465)4d517794e

master
16.1 KiB561 linesraw
1// slang-json-value.h
2#ifndef SLANG_JSON_VALUE_H
3#define SLANG_JSON_VALUE_H
4
5#include "../core/slang-basic.h"
6#include "../core/slang-rtti-info.h"
7#include "slang-diagnostic-sink.h"
8#include "slang-json-parser.h"
9#include "slang-source-loc.h"
10
11#include <optional>
12
13namespace Slang
14{
15
16typedef uint32_t JSONKey;
17
18struct JSONValue
19{
20    enum class Kind
21    {
22        Invalid,
23
24        Null,
25
26        Bool,
27        String,
28        Integer,
29        Float,
30
31        Array,
32        Object,
33
34        CountOf,
35    };
36
37    enum class Type
38    {
39        Invalid,
40
41        True,
42        False,
43        Null,
44
45        StringLexeme,
46        IntegerLexeme,
47        FloatLexeme,
48
49        IntegerValue,
50        FloatValue,
51        StringValue,
52
53        StringRepresentation,
54
55        Array,
56        Object,
57
58        CountOf,
59    };
60
61    static bool isLexeme(Type type)
62    {
63        return Index(type) >= Index(Type::StringLexeme) && Index(type) <= Index(Type::FloatLexeme);
64    }
65
66    static JSONValue makeInt(int64_t inValue, SourceLoc loc = SourceLoc())
67    {
68        JSONValue value;
69        value.type = Type::IntegerValue;
70        value.loc = loc;
71        value.intValue = inValue;
72        return value;
73    }
74    static JSONValue makeFloat(double inValue, SourceLoc loc = SourceLoc())
75    {
76        JSONValue value;
77        value.type = Type::FloatValue;
78        value.loc = loc;
79        value.floatValue = inValue;
80        return value;
81    }
82    static JSONValue makeNull(SourceLoc loc = SourceLoc())
83    {
84        JSONValue value;
85        value.type = Type::Null;
86        value.loc = loc;
87        return value;
88    }
89    static JSONValue makeBool(bool inValue, SourceLoc loc = SourceLoc())
90    {
91        JSONValue value;
92        value.type = (inValue ? Type::True : Type::False);
93        value.loc = loc;
94        return value;
95    }
96
97    static JSONValue makeLexeme(Type type, SourceLoc loc, Index length)
98    {
99        SLANG_ASSERT(isLexeme(type));
100        JSONValue value;
101        value.type = type;
102        value.loc = loc;
103        value.length = length;
104        return value;
105    }
106
107    static JSONValue makeEmptyArray(SourceLoc loc = SourceLoc())
108    {
109        JSONValue value;
110        value.type = Type::Array;
111        value.loc = loc;
112        value.rangeIndex = 0;
113        return value;
114    }
115    static JSONValue makeEmptyObject(SourceLoc loc = SourceLoc())
116    {
117        JSONValue value;
118        value.type = Type::Object;
119        value.loc = loc;
120        value.rangeIndex = 0;
121        return value;
122    }
123
124    static JSONValue makeInvalid(SourceLoc loc = SourceLoc())
125    {
126        JSONValue value;
127        value.type = Type::Invalid;
128        value.loc = loc;
129        return value;
130    }
131    // The following functions only work if the value is stored directly NOT as a lexeme. Use the
132    // methods on the container to access values if it is potentially stored as a lexeme
133
134    /// As a boolean value
135    bool asBool() const;
136    /// As an integer value
137    int64_t asInteger() const;
138    /// As a float value
139    double asFloat() const;
140
141    /// True if this is a object like
142    bool isObjectLike() const { return Index(type) >= Index(Type::Array); }
143
144    /// True if this appears to be a valid value
145    bool isValid() const { return type != JSONValue::Type::Invalid; }
146
147    /// True if needs destroy
148    bool needsDestroy() const { return isObjectLike() && rangeIndex != 0; }
149
150    /// Get the kind
151    SLANG_FORCE_INLINE Kind getKind() const { return getKindForType(type); }
152
153    void reset()
154    {
155        type = Type::Invalid;
156        loc = SourceLoc();
157    }
158
159    /// Given a type return the associated kind
160    static Kind getKindForType(Type type) { return g_typeToKind[Index(type)]; }
161
162    Type type = Type::Invalid; ///< The type of value
163    SourceLoc loc;             ///< The (optional) location in source of this value.
164
165    union
166    {
167        Index rangeIndex;                ///< Used for Array/Object
168        Index length;                    ///< Length in bytes if it is a 'Lexeme'
169        double floatValue;               ///< Float value
170        int64_t intValue;                ///< Integer value
171        JSONKey stringKey;               ///< The pool key if it's a string
172        StringRepresentation* stringRep; ///< Only ever used on a 'PersistentJSONValue'
173    };
174
175    static const Kind g_typeToKind[Index(Type::CountOf)];
176
177    static const OtherRttiInfo g_rttiInfo;
178};
179
180template<>
181struct GetRttiInfo<JSONValue>
182{
183    static const RttiInfo* get() { return &JSONValue::g_rttiInfo; }
184};
185
186struct JSONKeyValue
187{
188    /// True if it's valid
189    bool isValid() const { return value.type != JSONValue::Type::Invalid; }
190
191    void reset()
192    {
193        key = JSONKey(0);
194        keyLoc = SourceLoc();
195        value.reset();
196    }
197
198    JSONKey key;
199    SourceLoc keyLoc;
200    JSONValue value;
201
202    static JSONKeyValue make(JSONKey inKey, JSONValue inValue, SourceLoc inKeyLoc = SourceLoc())
203    {
204        return JSONKeyValue{inKey, inKeyLoc, inValue};
205    }
206
207    static JSONKeyValue g_invalid;
208};
209
210class JSONContainer;
211
212/* Is similar to JSONValue, but is designed to
213
214* Only be able to hold 'Simple' types (ie not array/object)
215* Does not reference/require JSONContainer.
216
217Not requiring JSONContainer means it's useful to hold state when JSONContainer goes out of scope.
218Care may need to be taken if sourceManager goes out of scope, sourceLocs may become invalid. This
219is true of a regular JSONValue.
220
221Care must also be taken because it is derived from JSONValue. It *can* be sliced and work correctly,
222but *requires* that the PersistentJSONValue with same value to stay in scope in general. In practice
223this is only an issue with StringRepresention type.
224*/
225class PersistentJSONValue : public JSONValue
226{
227public:
228    typedef JSONValue Super;
229    typedef PersistentJSONValue ThisType;
230
231    /// If it's a string type this will always work
232    String getString() const;
233    UnownedStringSlice getSlice() const;
234
235    /// Set to the value
236    void set(const JSONValue& in, JSONContainer* container);
237    /// Set directly to a string
238    void set(const UnownedStringSlice& slice, SourceLoc loc);
239
240    /// True if identical
241    bool operator==(const ThisType& rhs) const;
242    bool operator!=(const ThisType& rhs) const { return !(*this == rhs); }
243
244    /// Assignable
245    void operator=(const ThisType& rhs);
246
247    PersistentJSONValue(const JSONValue& in, JSONContainer* container) { _init(in, container); }
248    PersistentJSONValue(const JSONValue& in, JSONContainer* container, SourceLoc inLoc)
249    {
250        _init(in, container);
251        loc = inLoc;
252    }
253
254    /// Copy Ctor
255    PersistentJSONValue(const ThisType& rhs);
256    /// Default Ctor (will be set to invalid)
257    PersistentJSONValue() {}
258
259
260    ~PersistentJSONValue()
261    {
262        if (type == Type::StringRepresentation && stringRep)
263        {
264            stringRep->releaseReference();
265        }
266    }
267
268protected:
269    /// Assumes this has no valid data
270    void _init(const JSONValue& in, JSONContainer* container);
271    void _init(const UnownedStringSlice& slice, SourceLoc loc);
272};
273
274class JSONContainer : public RefObject
275{
276public:
277    /// Make a new array
278    JSONValue createArray(const JSONValue* values, Index valuesCount, SourceLoc loc = SourceLoc());
279    /// Make a new object
280    JSONValue createObject(
281        const JSONKeyValue* keyValues,
282        Index keyValueCount,
283        SourceLoc loc = SourceLoc());
284    /// Make a string
285    JSONValue createString(const UnownedStringSlice& slice, SourceLoc loc = SourceLoc());
286
287    ConstArrayView<JSONValue> getArray(const JSONValue& in) const;
288    ConstArrayView<JSONKeyValue> getObject(const JSONValue& in) const;
289
290    ArrayView<JSONValue> getArray(const JSONValue& in);
291    ArrayView<JSONKeyValue> getObject(const JSONValue& in);
292
293    /// Add value to array.
294    void addToArray(JSONValue& array, const JSONValue& value);
295
296    /// Get the value at the index in the array
297    JSONValue& getAt(const JSONValue& array, Index index);
298
299    /// Returns the index of key in obj, or -1 if not found
300    Index findObjectIndex(const JSONValue& obj, JSONKey key) const;
301    /// Get the value in the object at key. Returns invalid if not found.
302    JSONValue findObjectValue(const JSONValue& obj, JSONKey key) const;
303
304    /// Returns the index
305    Index findKeyGlobalIndex(const JSONValue& obj, JSONKey key);
306    Index findKeyGlobalIndex(const JSONValue& obj, const UnownedStringSlice& slice);
307
308    /// Set a key value for the obj
309    void setKeyValue(
310        JSONValue& obj,
311        JSONKey key,
312        const JSONValue& value,
313        SourceLoc loc = SourceLoc());
314
315    /// Returns true if found
316    bool removeKey(JSONValue& obj, JSONKey key);
317    bool removeKey(JSONValue& obj, const UnownedStringSlice& slice);
318
319    /// As a boolean value
320    bool asBool(const JSONValue& value);
321    /// As an integer value
322    int64_t asInteger(const JSONValue& value);
323    /// As a float value
324    double asFloat(const JSONValue& value);
325
326    /// Returns string as a key
327    JSONKey getStringKey(const JSONValue& in);
328
329    /// Get as a string. The slice may used backing lexeme (ie will only last
330    /// as long as the backing JSON text, or be decoded and be transitory).
331    UnownedStringSlice getTransientString(const JSONValue& in);
332
333    /// Get as a string. The contents will stay in scope as long as the container
334    UnownedStringSlice getString(const JSONValue& in);
335
336    /// Gets the lexeme
337    UnownedStringSlice getLexeme(const JSONValue& in);
338
339    /// Get a key for a name
340    JSONKey getKey(const UnownedStringSlice& slice);
341    /// Returns JSONKey(0) if not found
342    JSONKey findKey(const UnownedStringSlice& slice) const;
343    /// Get the string from the key
344    UnownedStringSlice getStringFromKey(JSONKey key) const
345    {
346        return m_slicePool.getSlice(StringSlicePool::Handle(key));
347    }
348
349    /// True if they are the same value
350    /// If object like type comparison is performed recursively.
351    /// NOTE! That Float and Integer values do not compare & source locations are ignored.
352    bool areEqual(const JSONValue& a, const JSONValue& b);
353    bool areEqual(const JSONValue* a, const JSONValue* b, Index count);
354    bool areEqual(const JSONKeyValue* a, const JSONKeyValue* b, Index count);
355
356    bool areEqual(const JSONValue& a, const UnownedStringSlice& slice);
357
358    /// Destroy value
359    void destroy(JSONValue& value);
360    /// Destroy recursively from value
361    void destroyRecursively(JSONValue& value);
362
363    /// Traverse a JSON hierarchy from value, outputting to the listener
364    void traverseRecursively(const JSONValue& value, JSONListener* listener);
365
366    /// Returns the source manager used.
367    SourceManager* getSourceManager() const { return m_sourceManager; }
368    /// Set the source manager
369    void setSourceManager(SourceManager* sourceManger) { m_sourceManager = sourceManger; }
370
371    /// Clears all the source locs. Useful if the sourceManager is no longer available, or has
372    /// itself been reset. All JSONValues which were Lexeme based will become held in the container
373    /// The source manager will set to nullptr
374    void clearSourceManagerDependency(JSONValue* ioValues, Index count);
375
376    /// Reset the state
377    void reset();
378
379    /// Return inValue as a regular value (ie not held as a lexeme)
380    JSONValue asValue(const JSONValue& inValue);
381
382    // Ctor
383    JSONContainer(SourceManager* sourceManger);
384
385    /// Returns true if all the keys are unique
386    static bool areKeysUnique(const JSONKeyValue* keyValues, Index keyValueCount);
387
388    /// Access the internal set of strings, removing anything from this
389    /// will invalidate the container, so only do it immediately prior to
390    /// destruction.
391    StringSlicePool& getStringSlicePool() { return m_slicePool; };
392
393protected:
394    struct Range
395    {
396        // We want to record the underlying range, because we don't track JSONValue, and so we need
397        // to know what the range applies to if we want to reorder, flatten etc.
398        enum class Type
399        {
400            None,
401            Destroyed,
402            Object,
403            Array,
404        };
405
406        /// Is active if it consuming some part of a value list (even if zero count)
407        SLANG_FORCE_INLINE bool isActive() const { return Index(type) >= Index(Type::Object); }
408
409        Type type;
410        Index startIndex;
411        Index count;
412        Index capacity;
413    };
414
415    template<typename T>
416    static void _add(Range& range, List<T>& list, const T& value);
417
418    Index _addRange(Range::Type type, Index startIndex, Index count);
419    void _removeKey(JSONValue& obj, Index globalIndex);
420    /// Note does not destroy values in range.
421    void _destroyRange(Index rangeIndex);
422
423    static bool _sameKeyOrder(const JSONKeyValue* a, const JSONKeyValue* b, Index count);
424    /// True if the values are equal
425    bool _areEqualValues(const JSONKeyValue* a, const JSONKeyValue* b, Index count);
426    /// True if the key and value are equal
427    bool _areEqualOrderedKeys(const JSONKeyValue* a, const JSONKeyValue* b, Index count);
428
429    void _clearSourceManagerDependency(JSONValue* ioValues, Index count);
430    JSONValue _removeManagerDependency(const JSONValue& inValue);
431
432    StringBuilder m_buf; ///< A temporary buffer used to hold unescaped strings
433
434    SourceView* m_currentView = nullptr;
435    SourceManager* m_sourceManager;
436
437    StringSlicePool m_slicePool;
438    List<Range> m_ranges;
439    List<Index> m_freeRangeIndices;
440    List<JSONValue> m_arrayValues;
441    List<JSONKeyValue> m_objectValues;
442};
443
444template<typename T>
445class JSONOptional
446{
447public:
448    bool hasValue = false;
449    T value;
450    JSONOptional() = default;
451    JSONOptional(std::nullopt_t) {}
452    JSONOptional(const T& inValue)
453        : hasValue(true), value(inValue)
454    {
455    }
456};
457
458template<typename T>
459struct GetRttiInfo<JSONOptional<T>>
460{
461    static const OptionalRttiInfo _make()
462    {
463        OptionalRttiInfo info;
464        info.init<JSONOptional<T>>(RttiInfo::Kind::Optional);
465        info.m_elementType = GetRttiInfo<T>::get();
466        info.m_valueOffset = (uint32_t)offsetof(JSONOptional<T>, value);
467        return info;
468    }
469    static const RttiInfo* get()
470    {
471        static const OptionalRttiInfo g_info = _make();
472        return &g_info;
473    }
474};
475
476
477class JSONBuilder : public JSONListener
478{
479public:
480    typedef uint32_t Flags;
481    struct Flag
482    {
483        enum Enum : Flags
484        {
485            ConvertLexemes = 0x01,
486        };
487    };
488
489
490    virtual void startObject(SourceLoc loc) SLANG_OVERRIDE;
491    virtual void endObject(SourceLoc loc) SLANG_OVERRIDE;
492    virtual void startArray(SourceLoc loc) SLANG_OVERRIDE;
493    virtual void endArray(SourceLoc loc) SLANG_OVERRIDE;
494    virtual void addQuotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE;
495    virtual void addUnquotedKey(const UnownedStringSlice& key, SourceLoc loc) SLANG_OVERRIDE;
496    virtual void addLexemeValue(JSONTokenType type, const UnownedStringSlice& value, SourceLoc loc)
497        SLANG_OVERRIDE;
498    virtual void addIntegerValue(int64_t value, SourceLoc loc) SLANG_OVERRIDE;
499    virtual void addFloatValue(double value, SourceLoc loc) SLANG_OVERRIDE;
500    virtual void addBoolValue(bool value, SourceLoc loc) SLANG_OVERRIDE;
501    virtual void addStringValue(const UnownedStringSlice& string, SourceLoc loc) SLANG_OVERRIDE;
502    virtual void addNullValue(SourceLoc loc) SLANG_OVERRIDE;
503
504    /// Reset the state
505    void reset();
506
507    /// Get the root value. Will be set after valid construction
508    const JSONValue& getRootValue() const { return m_rootValue; }
509
510    JSONBuilder(JSONContainer* container, Flags flags = 0);
511
512protected:
513    struct State
514    {
515        enum class Kind : uint8_t
516        {
517            Root,
518            Object,
519            Array,
520        };
521        void setKey(JSONKey key, SourceLoc loc)
522        {
523            m_key = key;
524            m_keyLoc = loc;
525        }
526        void resetKey()
527        {
528            m_key = JSONKey(0);
529            m_keyLoc = SourceLoc();
530        }
531        bool hasKey() const { return m_key != JSONKey(0); }
532
533        Kind m_kind;
534        Index m_startIndex;
535        SourceLoc m_loc;
536        JSONKey m_key;
537        SourceLoc m_keyLoc;
538    };
539
540    void _popState();
541    void _add(const JSONValue& value);
542
543    Index _findKeyIndex(JSONKey key) const;
544
545    Flags m_flags;
546
547    List<JSONKeyValue> m_keyValues;
548    List<JSONValue> m_values;
549    List<State> m_stateStack;
550
551    State m_state;
552
553    JSONContainer* m_container;
554    JSONValue m_rootValue;
555
556    StringBuilder m_work;
557};
558
559} // namespace Slang
560
561#endif