aboutsummaryrefslogblamecommitdiffstats
path: root/library/cpp/json/writer/json_value.h
blob: 3f0f50bc4c8853500f566351f76489184d18b0b1 (plain) (tree)
1
2
3
4
5
6
7
8
9
            
                                         
 
                                
                                
                               
                                 

                                    









                                         
 
                     
 
                         
                                           
 
                                                                                        
 
                              
 

                                                       
 








                                                      
                                  










                                               
 
                                                         
 

                       
 
                                                 
 
                                                      
 





                                                                             
 


                                                         
                                       
 

                                                                                             
 

                                                                                               
 
                                        
 


                                                                           
 





                                               
 








                                                   
 



                                                                                  
 



                                                              
 





                                                                   
 






                                                                                      
 


                                                               
 




                                        
 
                                                                                       
 
                                                                          
 
                                                       
 
                                           
 
                                                     
 

                                                      
 
                                            
 
                                                                         
                                          
                                                                         
                                   
                                          
 








                                             
 
                                    
                            





                                                                                      



                                                                        
      
 

                                                                                      
 

                                                                                           
 

                                                                                                     
 

                                                                                       
 

                                                                               
 
                                                                                               
 

                                                                                        
 

                                                                                             
 

                                                                                                       
 

                                                                                         
 

                                                                                 
 
                                                                                                       
























                                                                                   
 
#pragma once

#include <library/cpp/json/common/defs.h>

#include <util/generic/string.h>
#include <util/generic/hash.h>
#include <util/generic/vector.h>
#include <util/generic/deque.h>
#include <util/generic/utility.h>
#include <util/generic/yexception.h>

namespace NJson {
    enum EJsonValueType {
        JSON_UNDEFINED /* "Undefined" */,
        JSON_NULL /* "Null" */,
        JSON_BOOLEAN /* "Boolean" */,
        JSON_INTEGER /* "Integer" */,
        JSON_DOUBLE /* "Double" */,
        JSON_STRING /* "String" */,
        JSON_MAP /* "Map" */,
        JSON_ARRAY /* "Array" */,
        JSON_UINTEGER /* "UInteger" */
    };

    class TJsonValue;

    class IScanCallback {
    public:
        virtual ~IScanCallback() = default;

        virtual bool Do(const TString& path, TJsonValue* parent, TJsonValue& value) = 0;
    };

    class TJsonValue {
        void Clear() noexcept;

    public:
        typedef THashMap<TString, TJsonValue> TMapType;
        typedef TDeque<TJsonValue> TArray;

        TJsonValue() noexcept = default;
        TJsonValue(EJsonValueType type);
        TJsonValue(bool value) noexcept;
        TJsonValue(int value) noexcept;
        TJsonValue(unsigned int value) noexcept;
        TJsonValue(long value) noexcept;
        TJsonValue(unsigned long value) noexcept;
        TJsonValue(long long value) noexcept;
        TJsonValue(unsigned long long value) noexcept;
        TJsonValue(double value) noexcept;
        TJsonValue(TString value);
        TJsonValue(const char* value);
        template <class T>
        TJsonValue(const T*) = delete;
        TJsonValue(TStringBuf value);

        TJsonValue(const std::string& s)
            : TJsonValue(TStringBuf(s))
        {
        }

        TJsonValue(const TJsonValue& vval);
        TJsonValue(TJsonValue&& vval) noexcept;

        TJsonValue& operator=(const TJsonValue& val);
        TJsonValue& operator=(TJsonValue&& val) noexcept;

        ~TJsonValue() {
            Clear();
        }

        EJsonValueType GetType() const noexcept;
        TJsonValue& SetType(EJsonValueType type);

        TJsonValue& SetValue(const TJsonValue& value);
        TJsonValue& SetValue(TJsonValue&& value);

        // for Map
        TJsonValue& InsertValue(const TString& key, const TJsonValue& value);
        TJsonValue& InsertValue(TStringBuf key, const TJsonValue& value);
        TJsonValue& InsertValue(const char* key, const TJsonValue& value);
        TJsonValue& InsertValue(const TString& key, TJsonValue&& value);
        TJsonValue& InsertValue(TStringBuf key, TJsonValue&& value);
        TJsonValue& InsertValue(const char* key, TJsonValue&& value);

        // for Array
        TJsonValue& AppendValue(const TJsonValue& value);
        TJsonValue& AppendValue(TJsonValue&& value);
        TJsonValue& Back();
        const TJsonValue& Back() const;

        bool GetValueByPath(TStringBuf path, TJsonValue& result, char delimiter = '.') const;
        bool SetValueByPath(TStringBuf path, const TJsonValue& value, char delimiter = '.');
        bool SetValueByPath(TStringBuf path, TJsonValue&& value, char delimiter = '.');

        // returns NULL on failure
        const TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') const noexcept;
        TJsonValue* GetValueByPath(TStringBuf path, char delimiter = '.') noexcept;

        void EraseValue(TStringBuf key);
        void EraseValue(size_t index);

        TJsonValue& operator[](size_t idx);
        TJsonValue& operator[](const TStringBuf& key);
        const TJsonValue& operator[](size_t idx) const noexcept;
        const TJsonValue& operator[](const TStringBuf& key) const noexcept;

        bool GetBoolean() const;
        long long GetInteger() const;
        unsigned long long GetUInteger() const;
        double GetDouble() const;
        const TString& GetString() const;
        const TMapType& GetMap() const;
        const TArray& GetArray() const;

        //throwing TJsonException possible
        bool GetBooleanSafe() const;
        long long GetIntegerSafe() const;
        unsigned long long GetUIntegerSafe() const;
        double GetDoubleSafe() const;
        const TString& GetStringSafe() const;
        const TMapType& GetMapSafe() const;
        TMapType& GetMapSafe();
        const TArray& GetArraySafe() const;
        TArray& GetArraySafe();

        bool GetBooleanSafe(bool defaultValue) const;
        long long GetIntegerSafe(long long defaultValue) const;
        unsigned long long GetUIntegerSafe(unsigned long long defaultValue) const;
        double GetDoubleSafe(double defaultValue) const;
        TString GetStringSafe(const TString& defaultValue) const;

        bool GetBooleanRobust() const noexcept;
        long long GetIntegerRobust() const noexcept;
        unsigned long long GetUIntegerRobust() const noexcept;
        double GetDoubleRobust() const noexcept;
        TString GetStringRobust() const;

        // Exception-free accessors
        bool GetBoolean(bool* value) const noexcept;
        bool GetInteger(long long* value) const noexcept;
        bool GetUInteger(unsigned long long* value) const noexcept;
        bool GetDouble(double* value) const noexcept;
        bool GetMapPointer(const TMapType** value) const noexcept;
        bool GetArrayPointer(const TArray** value) const noexcept;

        bool GetString(TString* value) const;
        bool GetMap(TMapType* value) const;
        bool GetArray(TArray* value) const;
        bool GetValue(size_t index, TJsonValue* value) const;
        bool GetValue(TStringBuf key, TJsonValue* value) const;
        bool GetValuePointer(size_t index, const TJsonValue** value) const noexcept;
        bool GetValuePointer(TStringBuf key, const TJsonValue** value) const noexcept;
        bool GetValuePointer(TStringBuf key, TJsonValue** value) noexcept;

        // Checking for defined non-null value
        bool IsDefined() const noexcept {
            return Type != JSON_UNDEFINED && Type != JSON_NULL;
        }

        bool IsNull() const noexcept;
        bool IsBoolean() const noexcept;
        bool IsDouble() const noexcept;
        bool IsString() const noexcept;
        bool IsMap() const noexcept;
        bool IsArray() const noexcept;

        /// @return true if JSON_INTEGER or (JSON_UINTEGER and Value <= Max<long long>)
        bool IsInteger() const noexcept;

        /// @return true if JSON_UINTEGER or (JSON_INTEGER and Value >= 0)
        bool IsUInteger() const noexcept;

        bool Has(const TStringBuf& key) const noexcept;
        bool Has(size_t key) const noexcept;

        void Scan(IScanCallback& callback);

        /// Non-robust comparison.
        bool operator==(const TJsonValue& rhs) const;

        bool operator!=(const TJsonValue& rhs) const {
            return !(*this == rhs);
        }

        void Swap(TJsonValue& rhs) noexcept;

        // save using util/ysaveload.h serialization (not to JSON stream)
        void Save(IOutputStream* s) const;

        // load using util/ysaveload.h serialization (not as JSON stream)
        void Load(IInputStream* s);

        static const TJsonValue UNDEFINED;

    private:
        EJsonValueType Type = JSON_UNDEFINED;
        union TValueUnion {
            bool Boolean;
            long long Integer;
            unsigned long long UInteger;
            double Double;
            TString String;
            TMapType* Map;
            TArray* Array;

            TValueUnion() noexcept {
                Zero(*this);
            }
            ~TValueUnion() noexcept {
            }
        };
        TValueUnion Value;
        void DoScan(const TString& path, TJsonValue* parent, IScanCallback& callback);
        void SwapWithUndefined(TJsonValue& output) noexcept;

        /**
            @throw yexception if Back shouldn't be called on the object.
         */
        void BackChecks() const;
    };

    inline bool GetBoolean(const TJsonValue& jv, size_t index, bool* value) noexcept {
        return jv[index].GetBoolean(value);
    }

    inline bool GetInteger(const TJsonValue& jv, size_t index, long long* value) noexcept {
        return jv[index].GetInteger(value);
    }

    inline bool GetUInteger(const TJsonValue& jv, size_t index, unsigned long long* value) noexcept {
        return jv[index].GetUInteger(value);
    }

    inline bool GetDouble(const TJsonValue& jv, size_t index, double* value) noexcept {
        return jv[index].GetDouble(value);
    }

    inline bool GetString(const TJsonValue& jv, size_t index, TString* value) {
        return jv[index].GetString(value);
    }

    bool GetMapPointer(const TJsonValue& jv, size_t index, const TJsonValue::TMapType** value);
    bool GetArrayPointer(const TJsonValue& jv, size_t index, const TJsonValue::TArray** value);

    inline bool GetBoolean(const TJsonValue& jv, TStringBuf key, bool* value) noexcept {
        return jv[key].GetBoolean(value);
    }

    inline bool GetInteger(const TJsonValue& jv, TStringBuf key, long long* value) noexcept {
        return jv[key].GetInteger(value);
    }

    inline bool GetUInteger(const TJsonValue& jv, TStringBuf key, unsigned long long* value) noexcept {
        return jv[key].GetUInteger(value);
    }

    inline bool GetDouble(const TJsonValue& jv, TStringBuf key, double* value) noexcept {
        return jv[key].GetDouble(value);
    }

    inline bool GetString(const TJsonValue& jv, TStringBuf key, TString* value) {
        return jv[key].GetString(value);
    }

    bool GetMapPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TMapType** value);
    bool GetArrayPointer(const TJsonValue& jv, const TStringBuf key, const TJsonValue::TArray** value);

    class TJsonMap: public TJsonValue {
    public:
        TJsonMap()
            : TJsonValue(NJson::JSON_MAP)
        {}

        TJsonMap(const std::initializer_list<std::pair<TString, TJsonValue>>& list)
            : TJsonValue(NJson::JSON_MAP)
        {
            GetMapSafe() = THashMap<TString, TJsonValue>(list);
        }
    };

    class TJsonArray: public TJsonValue {
    public:
        TJsonArray()
            : TJsonValue(NJson::JSON_ARRAY)
        {}

        TJsonArray(const std::initializer_list<TJsonValue>& list)
            : TJsonValue(NJson::JSON_ARRAY)
        {
            GetArraySafe() = TJsonValue::TArray(list);
        }
    };
}