C++实现精简实用的json解析库

 fcjson.h

#pragma once

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define _CRT_SECURE_NO_WARNINGS
#endif

#include <cstdint>
#include <string>
#include <vector>
#include <map>
#include <cfloat>

// VS sets the execution character set to UTF-8
// Project Property Pages -> Configuration Properties -> C/C++ -> Command Line -> Additional Options (D)
// Add /execution-charset:utf-8 or /utf-8
//

// This compiler directive is obsolete in Visual Studio 2015 Update 2 and later.
// #pragma execution_character_set("utf-8")

// JSON specification: https://www.json.org/json-zh.html

#ifdef _UNICODE

#define __T(x)      L ## x
using _tstring = std::wstring;
using _tchar = wchar_t;
using _utchar = _tchar;

#else

#define __T(x)      x
using _tstring = std::string;
using _tchar = char;
using _utchar = unsigned char;

#endif

#define _T(x)       __T(x)
#define _TEXT(x)    __T(x)

#define FC_JSON_RETURN              "\n"
#define FC_JSON_FLOAT_FORMAT        "%.16g"

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
#define FC_JSON_INT64_FORMAT        "%lld"
#define FC_JSON_UINT64_FORMAT       "%llu"
#else
#define FC_JSON_INT64_FORMAT        "%ld"
#define FC_JSON_UINT64_FORMAT       "%lu"
#endif

// JSON Parse / Dump
// FlameCyclone
namespace fcjson
{
    class json_value;
    using json_null = nullptr_t;
    using json_bool = bool;
    using json_int = int64_t;
    using json_uint = uint64_t;
    using json_float = double;
    using json_string = _tstring;
    using json_object = std::map<_tstring, json_value>;
    using json_array = std::vector<json_value>;
    using json_bin = std::vector<uint8_t>;

    // Exception
    class json_exception
    {
    public:
        json_exception(const _tstring& msg) :
            m_msg(msg)
        {
        }

        _tstring get_message() const
        {
            return m_msg;
        }

        _tstring get_text_pos() const
        {
            return m_msg;
        }

    private:
        _tstring    m_msg;      // Message
    };

    // JSON Data type
    enum json_type :uint8_t
    {
        json_type_null,              // null
        json_type_bool,              // true Or false
        json_type_int,               // 0 - 9223372036854775807 Or -1 - (9223372036854775807 - 1)
        json_type_uint,              // 0 - 18446744073709551615
        json_type_float,             // 3.141592653589793
        json_type_string,            // "FlameCyclone"
        json_type_object,            // [128,256,512,1204,"string",{"name":"FlameCyclone"}]
        json_type_array,             // {"name":"FlameCyclone"}
        json_type_bin,               // binary data
    };

    // JSON Bin Tpye
    enum json_raw_type :uint8_t
    {
        raw_null            = 0x10, // Null
        raw_false           = 0x20, // Boolean false
        raw_true            = 0x30, // Boolean true

        raw_int8            = 0x40, // Signed int, value: [-128,-1]                 and [0,127]
        raw_int16           = 0x41, // Signed int, value: [-32768,-1]               and [0,32767]
        raw_int32           = 0x42, // Signed int, value: [-2147483648,-1]          and [0,2147483647]
        raw_int64           = 0x43, // Signed int, value: [-9223372036854775808,-1] and [0,9223372036854775807]

        raw_uint8           = 0x50, // Unsigned int, value: [0,255]
        raw_uint16          = 0x51, // Unsigned int, value: [0,65535]
        raw_uint32          = 0x52, // Unsigned int, value: [0,4294967295]
        raw_uint64          = 0x53, // Unsigned int, value: [0,18446744073709551615]

        raw_float           = 0x60, // Float, value: [2.2250738585072014e-308, 1.7976931348623158e+308]

        raw_string_empty    = 0xA0, // Empty string
        raw_string8         = 0xA1, // String, length: [0,255]
        raw_string16        = 0xA2, // String, length: [0,65535]
        raw_string32        = 0xA3, // String, length: [0,4294967295]

        raw_object_empty    = 0xB0, // Empty object
        raw_object_beg      = 0xB1, // Object Start
        raw_object_end      = 0xBF, // Object End

        raw_array_empty     = 0xC0, // Empty array
        raw_array_beg       = 0xC1, // Array Start
        raw_array_end       = 0xCF, // Array End

        raw_bin_empty       = 0xE0, // Empty binary
        raw_bin8            = 0xE1, // binary, length: [0,255]
        raw_bin16           = 0xE2, // binary, length: [0,65535]
        raw_bin32           = 0xE3, // binary, length: [0,4294967295]
    };

    // JSON Character Encoding
    enum json_encoding :uint8_t
    {
        json_encoding_auto,              // Auto
        json_encoding_utf8,              // Utf8
        json_encoding_utf16,             // Utf16
    };

    // JSON value class
    class json_value
    {
    public:

        // Constructor
        json_value(json_type type = json_type::json_type_object);
        json_value(nullptr_t);
        json_value(json_bool val);
        json_value(int32_t val);
        json_value(uint32_t val);
        json_value(int64_t val);
        json_value(uint64_t val);
        json_value(json_float val);
        json_value(const _tchar* val);
        json_value(const json_string& r);
        json_value(const json_object& r);
        json_value(const json_array& r);
        json_value(const json_bin& r);
        json_value(const json_value& r);
        json_value(json_value&& r) noexcept;
        json_value(json_string&& r);
        json_value(json_object&& r);
        json_value(json_array&& r);
        json_value(json_bin&& r);

        // Operator Overloading
        json_value& operator = (nullptr_t);
        json_value& operator = (json_type type);
        json_value& operator = (json_bool val);
        json_value& operator = (int32_t val);
        json_value& operator = (uint32_t val);
        json_value& operator = (int64_t val);
        json_value& operator = (uint64_t val);
        json_value& operator = (json_float val);
        json_value& operator = (const _tchar* val);
        json_value& operator = (const json_string& r);
        json_value& operator = (const json_object& r);
        json_value& operator = (const json_array& r);
        json_value& operator = (const json_value& r);
        json_value& operator = (json_string&& r);
        json_value& operator = (json_object&& r);
        json_value& operator = (json_array&& r);
        json_value& operator = (json_value&& r) noexcept;

        // [] Overloading, Accessing a non-existent index will create a new sub-item
        json_value& operator [] (const _tstring& val_name) noexcept;
        json_value& operator [] (size_t index) noexcept;

        ~json_value();

        // Type checking
        bool is_null() const;
        bool is_bool() const;
        bool is_int() const;
        bool is_float() const;
        bool is_number() const;
        bool is_string() const;
        bool is_object() const;
        bool is_array() const;
        bool is_bin() const;

        // Get data
        json_bool as_bool() const;
        json_int as_int() const;
        json_uint as_uint() const;
        json_float as_float() const;
        json_float as_number() const;
        json_string& as_string() const;
        json_object& as_object() const;
        json_array& as_array() const;
        json_bin& as_bin() const;

        // Parse
        bool parse(const _tstring& text);
        bool parse_from_file(const _tstring& file_path);
        bool parse_from_binary(uint8_t* data, size_t size);
        bool parse_from_binary_file(const _tstring& file_path);

        // Dump
        _tstring dump(int indent = 0, bool flag_escape = false) const;
        bool dump_to_file(const _tstring& file_path, int indent = 0, bool flag_escape = false, json_encoding enc = json_encoding::json_encoding_auto);
        std::vector<uint8_t> dump_to_binary();
        bool dump_to_binary_file(const _tstring& strPath);

        // Others
        size_t count() const;
        bool is_value(const _tstring& name = _T("")) const;
        bool remove(const _tstring& name);
        bool remove(const size_t index);
        json_type type() const;
        _tstring type_name() const;
        void clear();

#ifdef _WIN32

        // ANSI string
        static std::wstring AStrToWStr(const std::string& str);
        static std::string AStrToU8Str(const std::string& str);
        static _tstring AStrToTStr(const std::string& str);

        // Wide string
        static std::string WStrToU8Str(const std::wstring& str);
        static std::string WStrToAStr(const std::wstring& str);
        static _tstring WStrToTStr(const std::wstring& str);

        // UTF-8 string
        static std::wstring U8StrToWStr(const std::string& str);
        static std::string U8StrToAStr(const std::string& str);
        static _tstring U8StrToTStr(const std::string& str);

        // Text string
        static std::string TStrToAStr(const _tstring& str);
        static std::wstring TStrToWStr(const _tstring& str);
        static std::string TStrToU8Str(const _tstring& str);

#endif

    private:

        static json_value& _get_none_value();

        // Reset type
        inline void _reset_type(json_type type);

        // Parse
        bool _parse_number(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr);
        bool _parse_unicode(const _tchar* data_ptr, _tstring& val, const _tchar** end_ptr);
        bool _parse_string(const _tchar* data_ptr, _tstring& val, const _tchar** end_ptr);
        bool _parse_object(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr);
        bool _parse_array(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr);
        bool _parse_value(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr);
        bool _parse(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr);

        // Dump
        void _dump_int(_tstring& append_buf, int64_t val) const;
        void _dump_uint(_tstring& append_buf, uint64_t val) const;
        void _dump_float(_tstring& append_buf, double val) const;
        void _dump_string(_tstring& append_buf, const _tstring& text, bool flag_escape) const;
        void _dump_object(_tstring& append_buf, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const;
        void _dump_array(_tstring& append_buf, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const;
        void _dump(_tstring& append_buf, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const;

        // Dump raw
        void _dump_raw_int(std::vector<uint8_t>& append_buf, int64_t val) const;
        void _dump_raw_uint(std::vector<uint8_t>& append_buf, uint64_t val) const;
        void _dump_raw_float(std::vector<uint8_t>& append_buf, double val) const;
        void _dump_raw_string(std::vector<uint8_t>& append_buf, const std::string& text) const;
        void _dump_raw_object(std::vector<uint8_t>& append_buf, const json_object& object) const;
        void _dump_raw_array(std::vector<uint8_t>& append_buf, const json_array& arrry) const;
        void _dump_raw_bin(std::vector<uint8_t>& append_buf, const json_bin& arrry) const;
        void _dump_raw(std::vector<uint8_t>& append_buf) const;

        // Parse raw
        bool _parse_raw_string(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val);
        bool _parse_raw_object(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val);
        bool _parse_raw_array(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val);
        bool _parse_raw_bin(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val);
        bool _parse_raw(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val);

    private:

        // JSON data
        union json_data
        {
            json_bool    _bool;             // bool
            json_int     _int;              // int64_t
            json_uint    _uint;             // uint64_t
            json_float   _float;            // double
            json_string* _string_ptr;       // std::string
            json_object* _object_ptr;       // std::map
            json_array*  _array_ptr;        // std::vector
            json_bin*    _raw_ptr;          // std::vector<uint8_t>
        }m_data;                            //

        json_type    m_type;                // Data type
    };
}

fcjson.cpp

#include "fcjson.h"
#include <cwctype>
#include <fstream>
#include <cstring>
#include <cstdio>

#ifdef _WIN32
#include <Windows.h>
#endif

// UTF-8 encoding standard
// 
// 1Byte  U+0000000 - U+0000007F 0xxxxxxx
// 2Bytes U+0000080 - U+000007FF 110xxxxx 10xxxxxx
// 3Bytes U+0000800 - U+0000FFFF 1110xxxx 10xxxxxx 10xxxxxx
// 4Bytes U+0010000 - U+001FFFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 5Bytes U+0200000 - U+03FFFFFF 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
// 6Bytes U+4000000 - U+7FFFFFFF 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

// UTF-16 encoding standard
// 
//
// Basic Multilingual Plane (U+0000 - U+FFFF)
//
// Supplementary Planes (U+10000 - U+10FFFF)
// 1. Subtract 0x10000 from the code point to get a 20-bit surrogate value (0x00 - 0xFFFFF)
// 2. Add 0xD800 to the high 10 bits (range 0 - 0x3FF) to get the high surrogate (0xD800 - 0xDBFF)
// 3. Add 0xDC00 to the low 10 bits (range 0 - 0x3FF) to get the low surrogate (0xDC00 - 0xDFFF)

namespace fcjson
{

#ifdef _UNICODE

#define _json_istxdigit          std::iswxdigit
#define _json_istdigit           std::iswdigit
#define _json_tcsncmp            std::wcsncmp
#define _json_tcsstr             std::wcsstr
#define _json_tcstod             std::wcstod
#define _json_tcstol             std::wcstol
#define _json_tcstoll            std::wcstoll
#define _json_tcstoull           std::wcstoull
#define _json_stprintf_s         _snwprintf
#define _json_tisgraph           iswgraph
#define __JSON_FUNCTION__        __FUNCTIONW__
#else

#define _json_istxdigit          std::iswxdigit
#define _json_istdigit           std::iswdigit
#define _json_tcsncmp            std::strncmp
#define _json_tcsstr             std::strstr
#define _json_tcstod             std::strtod
#define _json_tcstol             std::strtol
#define _json_tcstoll            std::strtoll
#define _json_tcstoull           std::strtoull
#define _json_stprintf_s         snprintf
#define _json_tisgraph           isgraph
#define __JSON_FUNCTION__        __FUNCTION__

#endif

    static std::string _get_utf8_text_for_code_point(uint32_t cp32);
    static bool _get_utf16_code_point(const _tchar* data_ptr, uint32_t* code_point_ptr, const _tchar** end_ptr);
    static bool _get_unicode_string(_tstring& append_str, const _tchar* data_ptr, const _tchar** end_ptr);
    static int32_t _utf8_to_utf16(const void* data_ptr, size_t size = -1, std::string* text_utf8_ptr = nullptr, std::wstring* text_utf16_ptr = nullptr);
    static int32_t _utf16_to_utf8(const void* data_ptr, size_t size = -1, std::string* text_utf8_ptr = nullptr, std::wstring* text_utf16_ptr = nullptr);
    static std::string _utf16_to_utf8(const std::wstring utf16);
    static std::wstring _utf8_to_utf16(const std::string utf8);
    inline const _tchar* _skip_whitespace(const _tchar* data_ptr);
    inline const _tchar* _skip_bom(const _tchar* data_ptr);
    static bool _skip_digit(const _tchar* data_ptr, const _tchar** end_ptr);

    inline const _tchar* _skip_whitespace(const _tchar* data_ptr)
    {
        while (_T('\0') != *data_ptr)
        {
            if (*data_ptr > _T(' '))
            {
                break;
            }

            data_ptr++;
        }

        return data_ptr;
    }

    inline const _tchar* _skip_bom(const _tchar* data_ptr)
    {
#ifdef _UNICODE

        while (0xFEFF == *data_ptr)
        {
            data_ptr++;
        }

#else
        while (nullptr != _json_tcsstr(data_ptr, "\xEF\xBB\xBF"))
        {
            data_ptr += 3;
        }

#endif
        return data_ptr;
    }

    json_value::json_value(json_type type) :
        m_data{ 0 },
        m_type(type)
    {
        if (json_type::json_type_string == m_type)
        {
            m_data._string_ptr = new (std::nothrow) json_string;
        }

        if (json_type::json_type_array == m_type)
        {
            m_data._array_ptr = new (std::nothrow) json_array;
        }

        if (json_type::json_type_object == m_type)
        {
            m_data._object_ptr = new (std::nothrow) json_object;
        }
    }

    json_value::json_value(nullptr_t) : json_value()
    {
    }

    json_value::json_value(json_bool val)
    {
        m_type = json_type::json_type_bool;
        m_data._bool = val;
    }

    json_value::json_value(int32_t val)
    {
        m_type = json_type::json_type_int;
        m_data._int = val;
    }

    json_value::json_value(uint32_t val)
    {
        m_type = json_type::json_type_int;
        m_data._uint = val;
    }

    json_value::json_value(int64_t val)
    {
        m_type = json_type::json_type_int;
        m_data._int = val;
    }

    json_value::json_value(uint64_t val)
    {
        m_type = json_type::json_type_uint;
        m_data._uint = val;
    }

    json_value::json_value(json_float val)
    {
        m_type = json_type::json_type_float;
        m_data._float = val;
    }

    json_value::json_value(const _tchar* val)
    {
        if (val)
        {
            m_type = json_type::json_type_string;
            m_data._string_ptr = new (std::nothrow) json_string(val);
        }
        else
        {
            m_type = json_type::json_type_string;
            m_data = { 0 };
        }
    }

    json_value::json_value(const json_string& r)
    {
        m_type = json_type::json_type_string;
        m_data._string_ptr = new (std::nothrow) json_string(r);
    }

    json_value::json_value(const json_object& r)
    {
        m_type = json_type::json_type_object;
        m_data._object_ptr = new (std::nothrow) json_object(r);
    }

    json_value::json_value(const json_array& r)
    {
        m_type = json_type::json_type_array;
        m_data._array_ptr = new (std::nothrow) json_array(r);
    }

    json_value::json_value(const json_bin& r)
    {
        m_type = json_type::json_type_bin;
        m_data._raw_ptr = new (std::nothrow) json_bin(r);

    }

    json_value::json_value(const json_value& r)
    {
        m_type = r.m_type;

        switch (m_type)
        {
        case json_type::json_type_string:
        {
            m_data._string_ptr = new (std::nothrow) json_string(*r.m_data._string_ptr);
        }
        break;
        case json_type::json_type_object:
        {
            m_data._object_ptr = new (std::nothrow) json_object(*r.m_data._object_ptr);
        }
        break;
        case json_type::json_type_array:
        {
            m_data._array_ptr = new (std::nothrow) json_array(*r.m_data._array_ptr);
        }
        break;
        default:
        {
            m_data = r.m_data;
        }
        break;
        }
    }

    json_value::json_value(json_string&& r)
    {
        m_type = json_type::json_type_string;
        m_data._string_ptr = new (std::nothrow) json_string(std::move(r));
    }

    json_value::json_value(json_object&& r)
    {
        m_type = json_type::json_type_object;
        m_data._object_ptr = new (std::nothrow) json_object(std::move(r));
    }

    json_value::json_value(json_array&& r)
    {
        m_type = json_type::json_type_array;
        m_data._array_ptr = new (std::nothrow) json_array(std::move(r));
    }

    json_value::json_value(json_bin&& r)
    {
        m_type = json_type::json_type_bin;
        m_data._raw_ptr = new (std::nothrow) json_bin(std::move(r));
    }

    json_value::json_value(json_value&& r) noexcept
    {
        m_type = r.m_type;
        m_data = r.m_data;

        r.m_data = { 0 };
        r.m_type = json_type::json_type_null;
    }

    void json_value::clear()
    {
        switch (m_type)
        {
        case json_type::json_type_string:
        {
            if (m_data._string_ptr)
            {
                delete m_data._string_ptr;
            }
        }
        break;
        case json_type::json_type_object:
        {
            if (m_data._object_ptr)
            {
                delete m_data._object_ptr;
            }
        }
        break;
        case json_type::json_type_array:
        {
            if (m_data._array_ptr)
            {
                delete m_data._array_ptr;
            }
        }
        break;
        case json_type::json_type_bin:
        {
            if (m_data._raw_ptr)
            {
                delete m_data._raw_ptr;
            }
        }
        break;
        }

        m_data = { 0 };
    }

    inline void json_value::_reset_type(json_type type)
    {
        if (this == &_get_none_value())
        {
            return;
        }

        clear();
        m_type = type;

        if (json_type::json_type_string == m_type)
        {
            m_data._string_ptr = new (std::nothrow) json_string;
        }

        if (json_type::json_type_array == m_type)
        {
            m_data._array_ptr = new (std::nothrow) json_array;
        }

        if (json_type::json_type_object == m_type)
        {
            m_data._object_ptr = new (std::nothrow) json_object;
        }

        if (json_type::json_type_bin == m_type)
        {
            m_data._raw_ptr = new (std::nothrow) json_bin;
        }
    }

    json_value& json_value::operator = (nullptr_t)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_null);
        return *this;
    }

    json_value& json_value::operator = (json_type type)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(type);
        return *this;
    }

    json_value& json_value::operator = (json_bool val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_bool);
        m_data._bool = val;
        return *this;
    }

    json_value& json_value::operator = (int32_t val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_int);
        m_data._int = val;
        return *this;
    }

    json_value& json_value::operator = (uint32_t val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_int);
        m_data._uint = val;
        return *this;
    }

    json_value& json_value::operator = (int64_t val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_int);
        m_data._int = val;
        return *this;
    }

    json_value& json_value::operator = (uint64_t val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_uint);
        m_data._uint = val;
        return *this;
    }

    json_value& json_value::operator = (json_float val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_float);
        m_data._float = val;
        return *this;
    }

    json_value& json_value::operator = (const _tchar* val)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_string);
        if (nullptr == m_data._string_ptr)
        {
            m_data._string_ptr = new (std::nothrow) json_string(val);
        }
        return *this;
    }

    json_value& json_value::operator = (const json_string& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_string);
        if (nullptr != m_data._string_ptr)
        {
            *m_data._string_ptr = r;
        }
        return *this;
    }

    json_value& json_value::operator = (const json_object& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_object);
        if (nullptr != m_data._object_ptr)
        {
            *m_data._object_ptr = r;
        }
        return *this;
    }

    json_value& json_value::operator = (const json_array& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_array);
        if (nullptr != m_data._array_ptr)
        {
            *m_data._array_ptr = r;
        }
        return *this;
    }

    json_value& json_value::operator = (const json_value& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        if (&r != this)
        {
            clear();
            m_type = r.m_type;

            switch (m_type)
            {
            case json_type::json_type_string:
            {
                m_data._string_ptr = new (std::nothrow) json_string(*r.m_data._string_ptr);
            }
            break;
            case json_type::json_type_object:
            {
                m_data._object_ptr = new (std::nothrow) json_object(*r.m_data._object_ptr);
            }
            break;
            case json_type::json_type_array:
            {
                m_data._array_ptr = new (std::nothrow) json_array(*r.m_data._array_ptr);
            }
            break;
            case json_type::json_type_bin:
            {
                m_data._raw_ptr = new (std::nothrow) json_bin(*r.m_data._raw_ptr);
            }
            break;
            default:
            {
                m_data = r.m_data;
            }
            break;
            }
        }

        return *this;
    }

    json_value& json_value::operator = (json_string&& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_string);
        if (nullptr != m_data._string_ptr)
        {
            *m_data._string_ptr = std::move(r);
        }
        return *this;
    }

    json_value& json_value::operator = (json_object&& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_object);
        if (nullptr != m_data._object_ptr)
        {
            *m_data._object_ptr = std::move(r);
        }
        return *this;
    }

    json_value& json_value::operator = (json_array&& r)
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        _reset_type(json_type::json_type_array);
        if (nullptr != m_data._array_ptr)
        {
            *m_data._array_ptr = std::move(r);
        }
        return *this;
    }

    json_value& json_value::operator = (json_value&& r) noexcept
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        if (&r != this)
        {
            clear();
            m_type = r.m_type;
            m_data = r.m_data;

            r.m_data = { 0 };
            r.m_type = json_type::json_type_null;
        }

        return *this;
    }

    json_value& json_value::operator[](const _tstring& val_name) noexcept
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        if (!is_object())
        {
            return _get_none_value();
        }

        if (nullptr == m_data._object_ptr)
        {
            m_data._object_ptr = new (std::nothrow) json_object;
            if (nullptr == m_data._object_ptr)
            {
                return _get_none_value();
            }
        }

        auto it_find = m_data._object_ptr->find(val_name);
        if (m_data._object_ptr->end() != it_find)
        {
            return it_find->second;
        }

        auto it_insert = m_data._object_ptr->insert(std::make_pair(val_name, json_value()));
        return it_insert.first->second;
    }

    json_value& json_value::operator[](size_t index) noexcept
    {
        if (this == &_get_none_value())
        {
            return _get_none_value();
        }

        if (!is_array())
        {
            return _get_none_value();
        }

        if (nullptr == m_data._array_ptr)
        {
            m_data._array_ptr = new (std::nothrow) json_array;
            if (nullptr == m_data._array_ptr)
            {
                return _get_none_value();
            }
        }

        if (m_data._array_ptr->size() <= index)
        {
            m_data._array_ptr->resize(index + 1);
        }

        return (*m_data._array_ptr)[index];
    }

    json_value::~json_value()
    {
        clear();
    }

    json_type json_value::type() const
    {
        return m_type;
    }

    _tstring json_value::type_name() const
    {
        if (json_type::json_type_null == m_type) return _T("Null");
        if (json_type::json_type_bool == m_type) return _T("Bool");
        if (json_type::json_type_int == m_type) return _T("Integer");
        if (json_type::json_type_uint == m_type) return _T("Unsigned Integer");
        if (json_type::json_type_float == m_type) return _T("Float");
        if (json_type::json_type_string == m_type) return _T("String");
        if (json_type::json_type_object == m_type) return _T("Object");
        if (json_type::json_type_array == m_type) return _T("Array");
        return _T("None");
    }

    bool json_value::remove(const _tstring& name)
    {
        if (!is_object())
        {
            return false;
        }

        if (nullptr == m_data._object_ptr)
        {
            return false;
        }

        json_object& object = *m_data._object_ptr;
        auto it_find = object.find(name);
        if (object.end() == it_find)
        {
            return false;
        }

        object.erase(it_find);

        return true;
    }

    bool json_value::remove(const size_t index)
    {
        if (!is_array())
        {
            return false;
        }

        if (nullptr == m_data._array_ptr)
        {
            return false;
        }

        json_array& array = *m_data._array_ptr;
        if (index >= array.size())
        {
            return false;
        }

        array.erase(array.begin() + index);

        return true;
    }

    bool json_value::is_null() const
    {
        return json_type::json_type_null == m_type;
    }

    bool json_value::is_bool() const
    {
        return json_type::json_type_bool == m_type;
    }

    bool json_value::is_int() const
    {
        return json_type::json_type_int == m_type || json_type::json_type_uint == m_type;
    }

    bool json_value::is_float() const
    {
        return json_type::json_type_float == m_type;
    }

    bool json_value::is_number() const
    {
        return json_type::json_type_int == m_type || json_type::json_type_uint == m_type || json_type::json_type_float == m_type;
    }

    bool json_value::is_string() const
    {
        return json_type::json_type_string == m_type;
    }

    bool json_value::is_object() const
    {
        return json_type::json_type_object == m_type;
    }

    bool json_value::is_array() const
    {
        return json_type::json_type_array == m_type;
    }

    bool json_value::is_bin() const
    {
        return json_type::json_type_bin == m_type;
    }

    json_bool json_value::as_bool() const
    {
        if (json_type::json_type_bool != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return m_data._bool;
    }

    json_int json_value::as_int() const
    {
        if (!(json_type::json_type_int == m_type || json_type::json_type_uint == m_type))
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return m_data._int;
    }

    json_uint json_value::as_uint() const
    {
        if (!(json_type::json_type_int == m_type || json_type::json_type_uint == m_type))
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return m_data._uint;
    }

    json_float json_value::as_float() const
    {
        if (json_type::json_type_float != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return m_data._float;
    }

    json_float json_value::as_number() const
    {
        if (!is_number())
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return m_data._float;
    }

    json_string& json_value::as_string() const
    {
        if (json_type::json_type_string != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return *m_data._string_ptr;
    }

    json_object& json_value::as_object() const
    {
        if (json_type::json_type_object != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return *m_data._object_ptr;
    }

    json_array& json_value::as_array() const
    {
        if (json_type::json_type_array != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return *m_data._array_ptr;
    }

    json_bin& json_value::as_bin() const
    {
        if (json_type::json_type_bin != m_type)
        {
            throw json_exception(__JSON_FUNCTION__);
        }

        return *m_data._raw_ptr;
    }

    bool json_value::is_value(const _tstring& name) const
    {
        if (this == &_get_none_value())
        {
            return false;
        }

        if (is_object() && m_data._object_ptr)
        {
            auto it_find = m_data._object_ptr->find(name);
            if (m_data._object_ptr->end() != it_find)
            {
                return true;
            }
        }

        return false;
    }

    size_t json_value::count() const
    {
        if (this == &_get_none_value())
        {
            return 0;
        }

        if (is_array() && m_data._array_ptr)
        {
            return m_data._array_ptr->size();
        }

        if (is_object() && m_data._object_ptr)
        {
            return m_data._object_ptr->size();
        }

        return 0;
    }

    bool json_value::parse(const _tstring& text)
    {
        clear();
        const _tchar* end_ptr = nullptr;
        return _parse(text.c_str(), *this, &end_ptr);
    }

    bool json_value::parse_from_file(const _tstring& file_path)
    {
        std::string str_utf8;
        std::wstring str_utf16;
        _tstring read_text;

        clear();
        do
        {
            std::ifstream input_file(file_path, std::ios::binary | std::ios::in);
            if (!input_file.is_open())
            {
                return false;
            }

            input_file.seekg(0, std::ios::end);
            std::streamoff text_size = input_file.tellg();
            input_file.seekg(0, std::ios::beg);

            std::string text_buffer(text_size, 0);
            input_file.read((char*)&text_buffer[0], text_size);
            size_t byte_count = (size_t)input_file.gcount();
            input_file.close();

            if (0 == byte_count)
            {
                break;
            }

            int32_t utf8_length = _utf8_to_utf16(text_buffer.data(), text_buffer.size(), &str_utf8, &str_utf16);

#ifdef _UNICODE
            if (utf8_length > 0)
            {
                read_text = str_utf16;
                break;
            }
#else
            if (utf8_length > 0)
            {
                read_text = str_utf8;
                break;
            }
#endif

            int32_t utf16_length = _utf16_to_utf8(text_buffer.data(), text_buffer.size(), &str_utf8, &str_utf16);

#ifdef _UNICODE
            if (utf16_length > 0)
            {
                read_text = str_utf16;
                break;
            }
#else
            if (utf16_length > 0)
            {
                read_text = str_utf8;
                break;
            }
#endif

        } while (false);

        const _tchar* end_ptr = nullptr;
        return _parse(read_text.c_str(), *this, &end_ptr);
    }

    bool json_value::parse_from_binary(uint8_t* data, size_t size)
    {
        clear();
        const uint8_t* data_end = data + size;
        return _parse_raw(data, &data_end, *this);
    }

    bool json_value::parse_from_binary_file(const _tstring& file_path)
    {
        clear();

        std::ifstream input_file(file_path, std::ios::binary | std::ios::in);
        if (!input_file.is_open())
        {
            return false;
        }

        input_file.seekg(0, std::ios::end);
        std::streamoff text_size = input_file.tellg();
        input_file.seekg(0, std::ios::beg);

        std::vector<uint8_t> text_buffer(text_size, 0);
        input_file.read((char*)&text_buffer[0], text_size);
        size_t byte_count = (size_t)input_file.gcount();
        input_file.close();

        const uint8_t* data_end = text_buffer.data() + text_buffer.size();
        return _parse_raw(text_buffer.data(), &data_end, *this);
    }

    _tstring json_value::dump(int indent/* = 0*/, bool flag_escape/* = false*/) const
    {
        _tstring result_text;
        std::vector<_tstring> indent_text({ _T("") });
        _dump(result_text, indent_text, 0, indent, flag_escape);
        return result_text;
    }

    bool json_value::dump_to_file(const _tstring& strPath, int indent/* = 0*/, bool flag_escape/* = false*/, json_encoding encoding/* = json_encoding::json_encoding_auto*/)
    {
        _tstring dump_text;
        std::vector<_tstring> indent_text({ _T("") });
        _dump(dump_text, indent_text, 0, indent, flag_escape);

        std::string str_utf8;
        std::wstring str_utf16;
        _tstring result_text;

        str_utf16.push_back((uint16_t)0xFEFF);

        std::ofstream output_file(strPath, std::ios::binary | std::ios::out);
        if (!output_file.is_open())
        {
            return false;
        }

#ifdef _UNICODE
        result_text = str_utf16;

        if (json_encoding::json_encoding_utf16 == encoding || json_encoding::json_encoding_auto == encoding)
        {
            result_text += dump_text;
            output_file.write((const char*)result_text.data(), result_text.size() * sizeof(_tchar));
            output_file.close();
        }

        if (json_encoding::json_encoding_utf8 == encoding)
        {
            int32_t utf8_length = _utf16_to_utf8(dump_text.c_str(), (size_t)-1, &str_utf8, nullptr);
            if (utf8_length >= 0)
            {
                output_file.write((const char*)str_utf8.data(), str_utf8.size() * sizeof(char));
                output_file.close();
            }
        }

#else
        result_text = str_utf8;

        if (json_encoding::json_encoding_utf8 == encoding || json_encoding::json_encoding_auto == encoding)
        {
            result_text += dump_text;
            output_file.write((const char*)result_text.data(), result_text.size() * sizeof(_tchar));
            output_file.close();
        }

        if (json_encoding::json_encoding_utf16 == encoding)
        {
            int32_t utf8_length = _utf8_to_utf16(dump_text.c_str(), (size_t)-1, nullptr, &str_utf16);
            if (utf8_length >= 0)
            {
                output_file.write((const char*)str_utf16.data(), str_utf16.size() * sizeof(wchar_t));
                output_file.close();
            }
        }

#endif

        return true;
    }

    bool json_value::_parse_number(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr)
    {
        // [-]?[0-9]+\.[0-9]+[eE]?[-+]?[0-9]+
        const _tchar* start_ptr = data_ptr;
        bool flag_negative = false;
        bool flag_dot = false;
        bool flag_exponent = false;
        bool result_flag = false;

        do
        {
            if (_T('-') == *data_ptr)
            {
                flag_negative = true;
                data_ptr++;
            }

            if (!_skip_digit(data_ptr, &data_ptr))
            {
                result_flag = false;
                break;
            }

            if (_T('.') == *data_ptr)
            {
                flag_dot = true;
                data_ptr++;
            }

            if (flag_dot)
            {
                if (!_skip_digit(data_ptr, &data_ptr))
                {
                    break;
                }
            }

            if (_T('E') == *data_ptr || _T('e') == *data_ptr)
            {
                flag_exponent = true;
                data_ptr++;

                if (_T('-') == *data_ptr || _T('+') == *data_ptr)
                {
                    data_ptr++;
                }

                if (!_skip_digit(data_ptr, &data_ptr))
                {
                    break;
                }
            }

            _tstring number_text(start_ptr, data_ptr - start_ptr);

            if (flag_dot || flag_exponent)
            {
                val = _json_tcstod(number_text.c_str(), nullptr);
            }
            else
            {
                if (flag_negative)
                {
                    val = (int64_t)_json_tcstoll(number_text.c_str(), nullptr, 10);
                }
                else
                {
                    val = (uint64_t)_json_tcstoull(number_text.c_str(), nullptr, 10);
                }

                if (ERANGE == errno)
                {
                    val = _json_tcstod(number_text.c_str(), nullptr);
                    errno = 0;
                }
            }

            result_flag = true;

        } while (false);

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool json_value::_parse_unicode(const _tchar* data_ptr, _tstring& val, const _tchar** end_ptr)
    {
        uint32_t cp32 = 0;
        bool result_flag = false;

        do
        {
            if (!_get_utf16_code_point(data_ptr, &cp32, &data_ptr))
            {
                break;
            }

            // High bits
            if (cp32 >= 0xD800 && cp32 <= 0xDBFF)
            {
                cp32 -= 0xD800;

                if (0 != _json_tcsncmp(_T(R"(\u)"), data_ptr, 2))
                {
                    break;
                }

                data_ptr += 2;

                uint32_t cp_low = 0;
                if (!_get_utf16_code_point(data_ptr, &cp_low, &data_ptr))
                {
                    break;
                }

                // Low Bits
                if (cp_low >= 0xDC00 && cp_low <= 0xDFFF)
                {
                    cp_low -= 0xDC00;

                    cp32 = 0x10000 + ((cp32 << 10) | cp_low);
#ifdef _UNICODE
                    uint16_t cp = (uint16_t)(cp32 - 0x10000);
                    uint16_t cp32_high = (uint16_t)(cp >> 10) + 0xD800;
                    uint16_t cp32_low = (uint16_t)(cp & 0x3FF) + 0xDC00;
                    val.push_back(cp32_high);
                    val.push_back(cp32_low);
#else
                    val += std::move(_get_utf8_text_for_code_point(cp32));
#endif
                }
                else
                {
                    break;
                }
            }
            else
            {
#ifdef _UNICODE
                val.push_back((_tchar)cp32);
#else
                val += std::move(_get_utf8_text_for_code_point(cp32));
#endif
            }

            result_flag = true;

        } while (false);

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool json_value::_parse_string(const _tchar* data_ptr, _tstring& val, const _tchar** end_ptr)
    {
        bool flag_abort = false;

        data_ptr = _skip_whitespace(data_ptr);
        if (_T('\"') != *data_ptr)
        {
            return false;
        }

        data_ptr++;

        while (_T('\0') != *data_ptr)
        {
            _tchar ch = *data_ptr;
            if (_T('\"') == ch)
            {
                break;
            }

            if (_T('\\') == ch)
            {
                data_ptr++;
                ch = *data_ptr;

                switch (ch)
                {
                case _T('\"'):
                {
                    val.push_back(_T('\"'));
                }
                break;
                case _T('\\'):
                {
                    val.push_back(_T('\\'));
                }
                break;
                case _T('/'):
                {
                    val.push_back(_T('/'));
                }
                break;
                case _T('b'):
                {
                    val.push_back(_T('\b'));
                }
                break;
                case _T('n'):
                {
                    val.push_back(_T('\n'));
                }
                break;
                case _T('r'):
                {
                    val.push_back(_T('\r'));
                }
                break;
                case _T('t'):
                {
                    val.push_back(_T('\t'));
                }
                break;
                case _T('u'):
                {
                    data_ptr++;
                    if (!_parse_unicode(data_ptr, val, &data_ptr))
                    {
                        flag_abort = true;
                        break;
                    }
                    continue;
                }
                break;
                default:
                    data_ptr--;
                    flag_abort = true;
                    break;
                }
            }
            else
            {
                val.push_back(ch);
            }

            if (flag_abort)
            {
                break;
            }

            data_ptr++;
        }

        if (_T('\"') != *data_ptr || flag_abort)
        {
            *end_ptr = data_ptr;
            return false;
        }

        data_ptr++;

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return true;
    }

    void json_value::_dump_int(_tstring& append_str, int64_t val) const
    {
        _tchar out_buffer[64] = { 0 };
        size_t length = _json_stprintf_s(out_buffer, 64, _T(FC_JSON_INT64_FORMAT), val);
        append_str.append(out_buffer, length);
    }

    void json_value::_dump_uint(_tstring& append_str, uint64_t val) const
    {
        _tchar out_buffer[64] = { 0 };
        size_t length = _json_stprintf_s(out_buffer, 64, _T(FC_JSON_UINT64_FORMAT), val);
        append_str.append(out_buffer, length);
    }

    void json_value::_dump_float(_tstring& append_str, double val) const
    {
        _tchar out_buffer[64] = { 0 };
        size_t length = _json_stprintf_s(out_buffer, 64, _T(FC_JSON_FLOAT_FORMAT), val);
        append_str.append(out_buffer, length);

        _tchar* ch_ptr = out_buffer;
        bool flag_dot = false;
        bool flag_exponent = false;

        while (_T('\0') != *ch_ptr)
        {
            _tchar ch = *ch_ptr;
            if (_T('.') == ch)
            {
                flag_dot = true;
            }
            else if (_T('e') == ch)
            {
                flag_exponent = true;
            }
            ch_ptr++;
        }

        if (!flag_dot && 0 == !flag_exponent)
        {
            append_str += _T(".0");
        }
    }

    void json_value::_dump_string(_tstring& append_str, const _tstring& text, bool flag_escape) const
    {
        const _tchar* data_ptr = text.c_str();

        while (_T('\0') != *data_ptr)
        {
            _utchar ch = *data_ptr;

            switch (ch)
            {
            case _T('\b'):
            {
                append_str += _T(R"(\b)");
            }
            break;
            case _T('\t'):
            {
                append_str += _T(R"(\t)");
            }
            break;
            case _T('\n'):
            {
                append_str += _T(R"(\n)");
            }
            break;
            case _T('\f'):
            {
                append_str += _T(R"(\f)");
            }
            break;
            case _T('\r'):
            {
                append_str += _T(R"(\r)");
            }
            break;
            case _T('\"'):
            {
                append_str += _T(R"(\")");
            }
            break;
            case _T('/'):
            {
                append_str += _T(R"(/)");
            }
            case _T('\\'):
            {
                append_str += _T(R"(\\)");
            }
            break;
            default:
            {
                if (ch < 0x80 || !flag_escape)
                {
                    append_str.push_back(ch);
                }
                else
                {
                    _get_unicode_string(append_str, data_ptr, &data_ptr);
                    continue;
                }
            }
            break;
            }

            data_ptr++;
        }
    }

    void json_value::_dump_object(_tstring& append_str, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const
    {
        const json_object& object = *m_data._object_ptr;
        size_t size = object.size();

        append_str += _T("{");
        if (indent > 0)
        {
            depth++;

            if (indent_text.size() <= depth)
            {
                indent_text.emplace_back(_tstring(depth * indent, _T(' ')));
            }

            append_str += _T(FC_JSON_RETURN);

            for (const auto& item : object)
            {
                append_str += indent_text[depth];
                append_str += _T("\"");
                _dump_string(append_str, item.first, flag_escape);
                append_str += _T("\": ");
                item.second._dump(append_str, indent_text, depth, indent, flag_escape);
                size--;

                if (0 != size)
                {
                    append_str += _T(",");
                }

                append_str += _T(FC_JSON_RETURN);
            }

            depth--;
            append_str += indent_text[depth];
        }
        else
        {
            for (const auto& item : object)
            {
                append_str += _T("\"");
                _dump_string(append_str, item.first, flag_escape);
                append_str += _T("\":");
                item.second._dump(append_str, indent_text, depth, indent, flag_escape);
                size--;

                if (0 != size)
                {
                    append_str += _T(",");
                }
            }
        }
        append_str += _T("}");
    }

    void json_value::_dump_array(_tstring& append_str, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const
    {
        const json_array& array = *m_data._array_ptr;
        size_t size = array.size();

        append_str += _T("[");
        if (indent > 0)
        {
            depth++;

            if (indent_text.size() <= depth)
            {
                indent_text.emplace_back(_tstring(depth * indent, _T(' ')));
            }

            append_str += _T(FC_JSON_RETURN);

            for (const auto& item : array)
            {
                append_str += indent_text[depth];
                item._dump(append_str, indent_text, depth, indent, flag_escape);
                size--;
                if (0 != size)
                {
                    append_str += _T(",");
                }

                append_str += _T(FC_JSON_RETURN);
            }

            depth--;
            append_str += indent_text[depth];
        }
        else
        {
            for (const auto& item : array)
            {
                item._dump(append_str, indent_text, depth, indent, flag_escape);
                size--;
                if (0 != size)
                {
                    append_str += _T(",");
                }
            }
        }
        append_str += _T("]");
    }

    void json_value::_dump(_tstring& append_str, std::vector<_tstring>& indent_text, int depth, int indent, bool flag_escape) const
    {
        if (indent < 0)
        {
            indent = 0;
        }

        switch (m_type)
        {
        case json_type::json_type_null:
        {
            append_str += _T("null");
        }
        break;
        case json_type::json_type_bool:
        {
            append_str += m_data._bool ? _T("true") : _T("false");
        }
        break;
        case json_type::json_type_int:
        {
            _dump_int(append_str, m_data._int);
        }
        break;
        case json_type::json_type_uint:
        {
            _dump_uint(append_str, m_data._uint);
        }
        break;
        case json_type::json_type_float:
        {
            _dump_float(append_str, m_data._float);
        }
        break;
        case json_type::json_type_string:
        {
            append_str += _T("\"");
            _dump_string(append_str, *m_data._string_ptr, flag_escape);
            append_str += _T("\"");
        }
        break;
        case json_type::json_type_object:
        {
            if (nullptr == m_data._array_ptr)
            {
                append_str += _T("{}");
                break;
            }

            if (m_data._array_ptr->empty())
            {
                append_str += _T("{}");
                break;
            }

            _dump_object(append_str, indent_text, depth, indent, flag_escape);
        }
        break;
        case json_type::json_type_array:
        {
            if (nullptr == m_data._array_ptr)
            {
                append_str += _T("[]");
                break;
            }

            if (m_data._array_ptr->empty())
            {
                append_str += _T("[]");
                break;
            }

            _dump_array(append_str, indent_text, depth, indent, flag_escape);
        }
        break;
        default:
        {
        }
        break;
        }
    }

    void json_value::_dump_raw_int(std::vector<uint8_t>& append_buf, int64_t val) const
    {
        union _data_info
        {
            int64_t data;
            uint8_t bytes[sizeof(int64_t)];
        }data_info;

        data_info.data = val;
        int data_size = sizeof(int64_t);

        if (val <= INT8_MAX && val >= INT8_MIN)
        {
            append_buf.push_back(json_raw_type::raw_int8);
            data_size = sizeof(uint8_t);
        }
        else if (val <= INT16_MAX && val >= INT16_MIN)
        {
            append_buf.push_back(json_raw_type::raw_int16);
            data_size = sizeof(uint16_t);
        }
        else if (val <= INT32_MAX && val >= INT32_MIN)
        {
            append_buf.push_back(json_raw_type::raw_int32);
            data_size = sizeof(uint32_t);
        }
        else
        {
            append_buf.push_back(json_raw_type::raw_int64);
            data_size = sizeof(uint64_t);
        }

        for (int i = 0; i < data_size; i++)
        {
            append_buf.push_back(data_info.bytes[i]);
        }
    }

    void json_value::_dump_raw_uint(std::vector<uint8_t>& append_buf, uint64_t val) const
    {
        union _data_info
        {
            uint64_t data;
            uint8_t bytes[sizeof(uint64_t)];
        }data_info;

        data_info.data = val;
        int data_size = sizeof(uint64_t);

        if (val <= UINT8_MAX)
        {
            append_buf.push_back(json_raw_type::raw_uint8);
            data_size = sizeof(uint8_t);
        }
        else if (val <= UINT16_MAX)
        {
            append_buf.push_back(json_raw_type::raw_uint16);
            data_size = sizeof(uint16_t);
        }
        else if (val <= UINT32_MAX)
        {
            append_buf.push_back(json_raw_type::raw_uint32);
            data_size = sizeof(uint32_t);
        }
        else
        {
            append_buf.push_back(json_raw_type::raw_uint64);
            data_size = sizeof(uint64_t);
        }

        for (int i = 0; i < data_size; i++)
        {
            append_buf.push_back(data_info.bytes[i]);
        }
    }

    void json_value::_dump_raw_float(std::vector<uint8_t>& append_buf, double val) const
    {
        union _data_info
        {
            double data;
            uint8_t bytes[sizeof(double)];
        }data_info;

        data_info.data = val;

        for (int i = 0; i < sizeof(double); i++)
        {
            append_buf.push_back(data_info.bytes[i]);
        }
    }

    void json_value::_dump_raw_string(std::vector<uint8_t>& append_buf, const std::string& text) const
    {
        if (text.empty())
        {
            append_buf.push_back(json_raw_type::raw_string_empty);
        }
        else
        {
            int data_size = 0;
            union _data_info
            {
                uint32_t data;
                uint8_t bytes[sizeof(uint32_t)];
            }data_info;

            data_info.data = text.size();
            if (data_info.data <= UINT8_MAX)
            {
                append_buf.push_back(json_raw_type::raw_string8);
                data_size = sizeof(uint8_t);
            }
            else if (data_info.data <= UINT16_MAX)
            {
                append_buf.push_back(json_raw_type::raw_string16);
                data_size = sizeof(uint16_t);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_string32);
                data_size = sizeof(uint32_t);
            }

            for (int i = 0; i < data_size; i++)
            {
                append_buf.push_back(data_info.bytes[i]);
            }

            append_buf.insert(append_buf.end(), text.begin(), text.end());
        }
    }

    void json_value::_dump_raw_object(std::vector<uint8_t>& append_buf, const json_object& object) const
    {
        for (const auto& item : object)
        {
#ifdef _UNICODE
            _dump_raw_string(append_buf, _utf16_to_utf8(item.first));
#else
            _dump_raw_string(append_buf, item.first);
#endif
            item.second._dump_raw(append_buf);
        }
    }

    void json_value::_dump_raw_array(std::vector<uint8_t>& append_buf, const json_array& arrry) const
    {
        for (const auto& item : arrry)
        {
            item._dump_raw(append_buf);
        }
    }

    void json_value::_dump_raw_bin(std::vector<uint8_t>& append_buf, const json_bin& raw) const
    {
        if (raw.empty())
        {
            append_buf.push_back(json_raw_type::raw_bin_empty);
        }
        else
        {
            int data_size = 0;
            union _data_info
            {
                uint32_t data;
                uint8_t bytes[sizeof(uint32_t)];
            }data_info;

            data_info.data = raw.size();
            if (data_info.data <= UINT8_MAX)
            {
                append_buf.push_back(json_raw_type::raw_bin8);
                data_size = sizeof(uint8_t);
            }
            else if (data_info.data <= UINT16_MAX)
            {
                append_buf.push_back(json_raw_type::raw_bin16);
                data_size = sizeof(uint16_t);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_bin32);
                data_size = sizeof(uint32_t);
            }

            for (int i = 0; i < data_size; i++)
            {
                append_buf.push_back(data_info.bytes[i]);
            }

            append_buf.insert(append_buf.end(), raw.begin(), raw.end());
        }
    }

    void json_value::_dump_raw(std::vector<uint8_t>& append_buf) const
    {
        switch (m_type)
        {
        case json_type::json_type_null:
        {
            append_buf.push_back(json_raw_type::raw_null);
        }
        break;
        case json_type::json_type_bool:
        {
            if (m_data._bool)
            {
                append_buf.push_back(json_raw_type::raw_true);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_false);
            }
        }
        break;
        case json_type::json_type_int:
        {
            _dump_raw_int(append_buf, m_data._int);
        }
        break;
        case json_type::json_type_uint:
        {
            _dump_raw_uint(append_buf, m_data._uint);
        }
        break;
        case json_type::json_type_float:
        {
            append_buf.push_back(json_raw_type::raw_float);
            _dump_raw_float(append_buf, m_data._float);
        }
        break;
        case json_type::json_type_string:
        {
#ifdef _UNICODE
            _dump_raw_string(append_buf, _utf16_to_utf8(*m_data._string_ptr));
#else
            _dump_raw_string(append_buf, *m_data._string_ptr);
#endif
        }
        break;
        case json_type::json_type_object:
        {
            if (m_data._object_ptr && !m_data._object_ptr->empty())
            {
                append_buf.push_back(json_raw_type::raw_object_beg);
                _dump_raw_object(append_buf, *m_data._object_ptr);
                append_buf.push_back(json_raw_type::raw_object_end);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_object_empty);
            }
        }
        break;
        case json_type::json_type_array:
        {
            if (m_data._array_ptr && !m_data._array_ptr->empty())
            {
                append_buf.push_back(json_raw_type::raw_array_beg);
                _dump_raw_array(append_buf, *m_data._array_ptr);
                append_buf.push_back(json_raw_type::raw_array_end);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_array_empty);
            }
        }
        break;
        case json_type::json_type_bin:
        {
            if (m_data._raw_ptr && !m_data._raw_ptr->empty())
            {
                _dump_raw_bin(append_buf, *m_data._raw_ptr);
            }
            else
            {
                append_buf.push_back(json_raw_type::raw_bin_empty);
            }
        }
        break;
        }
    }

    bool json_value::_parse_raw_string(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val)
    {
        json_raw_type type = (json_raw_type)*data_ptr;
        const uint8_t* date_value_ptr = data_ptr + sizeof(json_raw_type);
        const uint8_t* data_next_ptr = data_ptr;
        std::string str_value;

        switch (*data_ptr)
        {
        case json_raw_type::raw_string_empty:
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_string8:
            str_value = std::string((const char*)(date_value_ptr + sizeof(uint8_t)), *(uint8_t*)date_value_ptr);
            data_next_ptr = date_value_ptr + sizeof(uint8_t) + *(uint8_t*)date_value_ptr;
            break;
        case json_raw_type::raw_string16:
            str_value = std::string((const char*)(date_value_ptr + sizeof(uint16_t)), *(uint16_t*)date_value_ptr);
            data_next_ptr = date_value_ptr + sizeof(uint16_t) + *(uint16_t*)date_value_ptr;
            break;
        case json_raw_type::raw_string32:
            str_value = std::string((const char*)(date_value_ptr + sizeof(uint32_t)), *(uint32_t*)date_value_ptr);
            data_next_ptr = date_value_ptr + sizeof(uint32_t) + *(uint32_t*)date_value_ptr;
            break;
        }

#ifdef _UNICODE
        val = _utf8_to_utf16(str_value);
#else
        val = str_value;
#endif

        if (end_ptr)
        {
            *end_ptr = data_next_ptr;
        }

        return true;
    }

    bool json_value::_parse_raw_object(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val)
    {
        val._reset_type(json_type::json_type_object);

        const uint8_t* data_next_ptr = data_ptr;
        while (true)
        {
            std::string key_name;
            json_value key_value;

            if (json_raw_type::raw_object_end == *data_next_ptr)
            {
                data_next_ptr++;
                break;
            }

            const uint8_t* value_ptr = data_next_ptr + sizeof(json_raw_type);
            size_t value_size = 0;
            switch (*data_next_ptr)
            {
            case json_raw_type::raw_string8:
                value_size = *(uint8_t*)value_ptr;
                key_name = std::string((const char*)(value_ptr + sizeof(uint8_t)), value_size);
                data_next_ptr = (value_ptr + sizeof(uint8_t)) + value_size;
                break;
            case json_raw_type::raw_string16:
                value_size = *(uint16_t*)value_ptr;
                key_name = std::string((const char*)(value_ptr + sizeof(uint16_t)), value_size);
                data_next_ptr = (value_ptr + sizeof(uint16_t)) + value_size;
                break;
            case json_raw_type::raw_string32:
                value_size = *(uint32_t*)value_ptr;
                key_name = std::string((const char*)(value_ptr + sizeof(uint32_t)), value_size);
                data_next_ptr = (value_ptr + sizeof(uint32_t)) + value_size;
                break;
            default:
                return false;
            }

            if (key_name.empty())
            {
                return false;
            }

            if (!_parse_raw(data_next_ptr, &data_next_ptr, key_value))
            {
                return false;
            }

#ifdef _UNICODE
            val[_utf8_to_utf16(key_name)] = key_value;
#else
            val[key_name] = key_value;
#endif
        }

        if (end_ptr)
        {
            *end_ptr = data_next_ptr;
        }

        return true;
    }

    bool json_value::_parse_raw_array(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val)
    {
        const uint8_t* data_next_ptr = data_ptr;
        val._reset_type(json_type::json_type_array);

        while (true)
        {
            if (json_raw_type::raw_array_end == *data_next_ptr)
            {
                data_next_ptr++;
                break;
            }

            json_value value;
            if (!_parse_raw(data_next_ptr, &data_next_ptr, value))
            {
                return false;
            }

            val.m_data._array_ptr->emplace_back(std::move(value));
        }

        if (end_ptr)
        {
            *end_ptr = data_next_ptr;
        }

        return true;
    }

    bool json_value::_parse_raw_bin(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val)
    {
        json_raw_type type = (json_raw_type)*data_ptr;
        const uint8_t* date_value_ptr = data_ptr + sizeof(json_raw_type);
        const uint8_t* data_next_ptr = data_ptr;

        json_bin raw;

        switch (*data_ptr)
        {
        case json_raw_type::raw_bin_empty:
            val = json_bin();
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_bin8:
            raw.assign(date_value_ptr + sizeof(uint8_t), date_value_ptr + sizeof(uint8_t) + *(uint8_t*)date_value_ptr);
            val = std::move(raw);
            data_next_ptr = date_value_ptr + sizeof(uint8_t) + *(uint8_t*)date_value_ptr;
            break;
        case json_raw_type::raw_bin16:
            raw.assign(date_value_ptr + sizeof(uint16_t), date_value_ptr + sizeof(uint16_t) + *(uint16_t*)date_value_ptr);
            val = std::move(raw);
            data_next_ptr = date_value_ptr + sizeof(uint16_t) + *(uint16_t*)date_value_ptr;
            break;
        case json_raw_type::raw_bin32:
            raw.assign(date_value_ptr + sizeof(uint32_t), date_value_ptr + sizeof(uint32_t) + *(uint32_t*)date_value_ptr);
            val = std::move(raw);
            data_next_ptr = date_value_ptr + sizeof(uint32_t) + *(uint32_t*)date_value_ptr;
            break;
        }

        if (end_ptr)
        {
            *end_ptr = data_next_ptr;
        }

        return true;
    }

    bool json_value::_parse_raw(const uint8_t* data_ptr, const uint8_t** end_ptr, json_value& val)
    {
        const uint8_t* date_value_ptr = data_ptr + sizeof(json_raw_type);
        const uint8_t* data_next_ptr = data_ptr;
        bool parse_result = true;

        switch (*data_next_ptr)
        {
        case json_raw_type::raw_null:
            val = json_type::json_type_null;
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_false:
            val = false;
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_true:
            val = true;
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_int8:
            val = *(int8_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(int8_t);
            break;
        case json_raw_type::raw_int16:
            val = *(int16_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(int16_t);
            break;
        case json_raw_type::raw_int32:
            val = *(int32_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(int32_t);
            break;
        case json_raw_type::raw_int64:
            val = *(int64_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(int64_t);
            break;
        case json_raw_type::raw_uint8:
            val = *(uint8_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(uint8_t);
            break;
        case json_raw_type::raw_uint16:
            val = *(uint16_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(uint16_t);
            break;
        case json_raw_type::raw_uint32:
            val = *(uint32_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(uint32_t);
            break;
        case json_raw_type::raw_uint64:
            val = *(uint64_t*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(uint64_t);
            break;
        case json_raw_type::raw_float:
            val = *(double*)date_value_ptr;
            data_next_ptr += sizeof(json_raw_type) + sizeof(double);
            break;
        case json_raw_type::raw_string_empty:
        case json_raw_type::raw_string8:
        case json_raw_type::raw_string16:
        case json_raw_type::raw_string32:
            parse_result = _parse_raw_string(data_next_ptr, &data_next_ptr, val);
            break;
        case json_raw_type::raw_bin_empty:
        case json_raw_type::raw_bin8:
        case json_raw_type::raw_bin16:
        case json_raw_type::raw_bin32:
            parse_result = _parse_raw_bin(data_next_ptr, &data_next_ptr, val);
            break;
        case json_raw_type::raw_object_empty:
            val._reset_type(json_type::json_type_object);
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_object_beg:
            parse_result = _parse_raw_object(date_value_ptr, &data_next_ptr, val);
            break;
        case json_raw_type::raw_object_end:
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_array_empty:
            val._reset_type(json_type::json_type_array);
            data_next_ptr += sizeof(json_raw_type);
            break;
        case json_raw_type::raw_array_beg:
            parse_result = _parse_raw_array(date_value_ptr, &data_next_ptr, val);
            break;
        case json_raw_type::raw_array_end:
            data_next_ptr += sizeof(json_raw_type);
            break;
        default:
            return false;
        }

        if (!parse_result)
        {
            return parse_result;
        }

        if (end_ptr)
        {
            *end_ptr = data_next_ptr;
        }

        return true;
    }

    std::vector<uint8_t> json_value::dump_to_binary()
    {
        std::vector<uint8_t> result;
        _dump_raw(result);
        return result;
    }

    bool json_value::dump_to_binary_file(const _tstring& strPath)
    {
        std::vector<uint8_t> result;
        _dump_raw(result);

        std::ofstream output_file(strPath, std::ios::binary | std::ios::out);
        if (!output_file.is_open())
        {
            return false;
        }

        output_file.write((char*)result.data(), result.size());
        output_file.close();

        return true;
    }

    json_value& json_value::_get_none_value()
    {
        static json_value val(json_type::json_type_null);
        return val;
    }

    bool _skip_digit(const _tchar* data_ptr, const _tchar** end_ptr)
    {
        if (0 == _json_istdigit(*data_ptr))
        {
            return false;
        }

        while (_json_istdigit(*data_ptr))
        {
            data_ptr++;
        }

        *end_ptr = data_ptr;

        return true;
    }

    bool json_value::_parse_object(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr)
    {
        bool result_flag = false;

        if (_T('{') == *data_ptr)
        {
            data_ptr++;
        }

        val._reset_type(json_type::json_type_object);
        _tstring value_name;
        while (_T('\0') != *data_ptr)
        {
            data_ptr = _skip_whitespace(data_ptr);
            if (_T('}') == *data_ptr)
            {
                result_flag = true;
                data_ptr++;
                break;
            }

            value_name.clear();
            if (!_parse_string(data_ptr, value_name, &data_ptr))
            {
                break;
            }

            data_ptr = _skip_whitespace(data_ptr);
            if (_T(':') != *data_ptr)
            {
                break;
            }
            data_ptr++;

            json_value value_data;
            if (!_parse_value(data_ptr, value_data, &data_ptr))
            {
                break;
            }

            if (val.m_data._object_ptr)
            {
                val.m_data._object_ptr->emplace(value_name, std::move(value_data));
            }

            data_ptr = _skip_whitespace(data_ptr);
            if (_T(',') == *data_ptr)
            {
                data_ptr++;
            }
            else if (_T('}') == *data_ptr)
            {
                result_flag = true;
                data_ptr++;
                break;
            }
            else
            {
                break;
            }
        }

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool json_value::_parse_array(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr)
    {
        bool result_flag = false;

        if (_T('[') == *data_ptr)
        {
            data_ptr++;
        }

        val._reset_type(json_type::json_type_array);
        while (_T('\0') != *data_ptr)
        {
            data_ptr = _skip_whitespace(data_ptr);
            if (_T(']') == *data_ptr)
            {
                result_flag = true;
                data_ptr++;
                break;
            }

            json_value value_data;
            if (!_parse_value(data_ptr, value_data, &data_ptr))
            {
                break;
            }

            if (val.m_data._array_ptr)
            {
                val.m_data._array_ptr->emplace_back(std::move(value_data));
            }

            data_ptr = _skip_whitespace(data_ptr);
            if (_T(',') == *data_ptr)
            {
                data_ptr++;
            }
            else if (_T(']') == *data_ptr)
            {
                result_flag = true;
                data_ptr++;
                break;
            }
            else
            {
                break;
            }
        }

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool json_value::_parse_value(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr)
    {
        data_ptr = _skip_whitespace(data_ptr);
        bool result_flag = false;
        bool abort_flag = false;

        do
        {
            _tchar ch = *data_ptr;

            switch (ch)
            {
            case _T('{'):
            {
                if (!_parse_object(data_ptr, val, &data_ptr))
                {
                    abort_flag = true;
                    break;
                }
            }
            break;
            case _T('['):
            {
                if (!_parse_array(data_ptr, val, &data_ptr))
                {
                    abort_flag = true;
                    break;
                }
            }
            break;
            case _T('\"'):
            {
                _tstring str_value;
                if (!_parse_string(data_ptr, str_value, &data_ptr))
                {
                    abort_flag = true;
                    break;
                }
                val = std::move(str_value);
            }
            break;
            case _T('-'):
            {
                if (!_parse_number(data_ptr, val, &data_ptr))
                {
                    abort_flag = true;
                    break;
                }
            }
            break;
            default:
            {
                if (_json_istdigit(ch))
                {
                    if (!_parse_number(data_ptr, val, &data_ptr))
                    {
                        abort_flag = true;
                        break;
                    }
                }
                else if (0 == _json_tcsncmp(_T("null"), data_ptr, 4))
                {
                    val = json_value(json_type::json_type_null);
                    data_ptr += 4;
                }
                else if (0 == _json_tcsncmp(_T("true"), data_ptr, 4))
                {
                    val = true;
                    data_ptr += 4;
                }
                else if (0 == _json_tcsncmp(_T("false"), data_ptr, 5))
                {
                    val = false;
                    data_ptr += 5;
                }
                else
                {
                    abort_flag = true;
                    break;
                }
            }
            break;
            }

            if (!abort_flag)
            {
                result_flag = true;
            }

        } while (false);

        data_ptr = _skip_whitespace(data_ptr);

        if (*end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool json_value::_parse(const _tchar* data_ptr, json_value& val, const _tchar** end_ptr)
    {
        bool result_flag = false;
        data_ptr = _skip_bom(data_ptr);
        if (_parse_value(data_ptr, val, &data_ptr))
        {
            if (_T('\0') != *data_ptr)
            {
                val = json_type::json_type_null;
            }
            else
            {
                result_flag = true;
            }
        }

        if (!result_flag)
        {
            _reset_type(json_type::json_type_null);
        }

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool _get_utf16_code_point(const _tchar* data_ptr, uint32_t* code_point_ptr, const _tchar** end_ptr)
    {
        _tchar text_buffer[16] = { 0 };
        _tchar* ch_end_ptr = nullptr;
        bool result_flag = false;

        do
        {
            int count = 0;
            for (count = 0; count < 4; count++)
            {
                _tchar ch = *data_ptr;
                if (0 == _json_istxdigit(ch))
                {
                    break;
                }

                text_buffer[count] = ch;
                data_ptr++;
            }

            if (4 != count)
            {
                break;
            }

            if (code_point_ptr)
            {
                *code_point_ptr = _json_tcstol(text_buffer, &ch_end_ptr, 16);
            }

            result_flag = true;

        } while (false);

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return result_flag;
    }

    bool _get_unicode_string(_tstring& append_str, const _tchar* data_ptr, const _tchar** end_ptr)
    {
        _utchar ch = *data_ptr;

#ifdef _UNICODE
        _tchar text_buffer[32] = { 0 };
        _json_stprintf_s(text_buffer, sizeof(text_buffer) / sizeof(_tchar), _T(R"(\u%.4x)"), ch);
        append_str += text_buffer;
        data_ptr++;

#else
        if (ch >= 0xC0)
        {
            // The number of bytes used to obtain characters.
            size_t byte_count = 0;
            uint32_t cp32 = 0;

            if (ch >= 0xE0 && ch <= 0xEF)
            {
                byte_count = 3;
                cp32 = ch & 0x0F;
            }
            else if (ch >= 0xC0 && ch <= 0xDF)
            {
                byte_count = 2;
                cp32 = ch & 0x1F;
            }
            else if (ch >= 0xF0 && ch <= 0xF7)
            {
                byte_count = 4;
                cp32 = ch & 0x07;
            }
            else if (ch >= 0xF8 && ch <= 0xFB)
            {
                byte_count = 5;
                cp32 = ch & 0x03;
            }
            else if (ch >= 0xFC && ch <= 0xFD)
            {
                byte_count = 6;
                cp32 = ch & 0x01;
            }

            if (0 == byte_count)
            {
                return false;
            }

            for (size_t i = 1; i < byte_count; i++)
            {
                cp32 = cp32 << 6;
                cp32 |= data_ptr[i] & 0x3F;
            }

            char text_buffer[32] = { 0 };
            if (cp32 < 0x10000)
            {
                snprintf(text_buffer, sizeof(text_buffer), R"(\u%.4x)", cp32);
                append_str.append(text_buffer, 6);
            }
            else
            {
                uint32_t cp = (uint16_t)(cp32 - 0x10000);
                uint16_t cp32_high = (uint16_t)(cp >> 10) + 0xD800;
                uint16_t cp32_low = (uint16_t)(cp & 0x3FF) + 0xDC00;

                snprintf(text_buffer, sizeof(text_buffer), R"(\u%.4x\u%.4x)", cp32_high, cp32_low);
                append_str.append(text_buffer, 12);
            }

            data_ptr += byte_count;
        }
#endif

        if (end_ptr)
        {
            *end_ptr = data_ptr;
        }

        return false;
    }

    std::string _get_utf8_text_for_code_point(uint32_t cp32)
    {
        char text_buffer[16] = { 0 };

        // 1byte 0xxxxxxx
        if (cp32 >= 0x00000000 && cp32 <= 0x0000007F)
        {
            text_buffer[0] = (uint8_t)cp32;
            text_buffer[1] = 0;
        }

        // 2bytes 110xxxxx 10xxxxxx
        else if (cp32 >= 0x00000080 && cp32 <= 0x000007FF)
        {
            text_buffer[0] = ((cp32 >> 6) & 0x1F) | 0xC0;
            text_buffer[1] = ((cp32 & 0x3F)) | 0x80;
            text_buffer[2] = 0;
        }
        // 3bytes 1110xxxx 10xxxxxx 10xxxxxx
        else if (cp32 >= 0x00000800 && cp32 <= 0x0000FFFF)
        {
            text_buffer[0] = ((cp32 >> 12) & 0x0F) | 0xE0;
            text_buffer[1] = ((cp32 >> 6) & 0x3F) | 0x80;
            text_buffer[2] = ((cp32 & 0x3F)) | 0x80;
            text_buffer[3] = 0;
        }
        // 4bytes 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
        else if (cp32 >= 0x00010000 && cp32 <= 0x001FFFFF)
        {
            text_buffer[0] = ((cp32 >> 18) & 0x07) | 0xF0;
            text_buffer[1] = ((cp32 >> 12) & 0x3F) | 0x80;
            text_buffer[2] = ((cp32 >> 6) & 0x3F) | 0x80;
            text_buffer[3] = ((cp32 & 0x3F)) | 0x80;
            text_buffer[4] = 0;
        }
        // 5bytes 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        else if (cp32 >= 0x00200000 && cp32 <= 0x03FFFFFF)
        {
            text_buffer[0] = ((cp32 >> 24) & 0x03) | 0xF8;
            text_buffer[1] = ((cp32 >> 18) & 0x3F) | 0x80;
            text_buffer[2] = ((cp32 >> 12) & 0x3F) | 0x80;
            text_buffer[3] = ((cp32 >> 6) & 0x3F) | 0x80;
            text_buffer[4] = ((cp32 & 0x3F)) | 0x80;
            text_buffer[5] = 0;
        }
        // 6bytes 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
        else if (cp32 >= 0x04000000 && cp32 <= 0x7FFFFFFF)
        {
            text_buffer[0] = ((cp32 >> 30) & 0x01) | 0xFC;
            text_buffer[1] = ((cp32 >> 24) & 0x3F) | 0x80;
            text_buffer[2] = ((cp32 >> 18) & 0x3F) | 0x80;
            text_buffer[3] = ((cp32 >> 12) & 0x3F) | 0x80;
            text_buffer[4] = ((cp32 >> 6) & 0x3F) | 0x80;
            text_buffer[5] = ((cp32 & 0x3F)) | 0x80;
            text_buffer[6] = 0;
        }

        return text_buffer;
    }

    int32_t _utf8_to_utf16(const void* data_ptr, size_t size/* = -1*/, std::string* text_utf8_ptr/* = nullptr*/, std::wstring* text_utf16_ptr/* = nullptr*/)
    {
        const uint8_t* ch_data_ptr = (const uint8_t*)data_ptr;
        std::wstring text_out_utf16;
        std::string text_out_utf8;
        uint32_t cp32 = 0;
        int32_t byte_count = 0;
        int32_t ch_count = 0;
        bool result_flag = true;
        bool flag_bom = true;

        if (text_utf8_ptr)
        {
            text_out_utf8 += *text_utf8_ptr;
        }

        if (text_utf16_ptr)
        {
            text_out_utf16 += *text_utf16_ptr;
        }

        while ((0 != *ch_data_ptr) && (0 != size))
        {
            uint8_t ch = *ch_data_ptr;

            if (ch < 0x7F)
            {
                cp32 = ch;
                ch_count++;
            }
            else
            {
                if (0 == byte_count)
                {
                    cp32 = 0;
                    if (ch >= 0xC0)
                    {
                        if (ch >= 0xC0 && ch <= 0xDF)
                        {
                            byte_count = 2;
                            cp32 = ch & 0x1F;
                        }
                        else if (ch >= 0xE0 && ch <= 0xEF)
                        {
                            byte_count = 3;
                            cp32 = ch & 0x0F;
                        }
                        else if (ch >= 0xF0 && ch <= 0xF7)
                        {
                            byte_count = 4;
                            cp32 = ch & 0x07;
                        }
                        else if (ch >= 0xF8 && ch <= 0xFB)
                        {
                            byte_count = 5;
                            cp32 = ch & 0x03;
                        }
                        else if (ch >= 0xFC && ch <= 0xFD)
                        {
                            byte_count = 6;
                            cp32 = ch & 0x01;
                        }

                        if (0 == byte_count)
                        {
                            result_flag = false;
                            break;
                        }

                        if (0xEF == ch && 3 == byte_count)
                        {
                            flag_bom = true;
                        }

                        byte_count--;
                    }
                    else
                    {
                        result_flag = false;
                        break;
                    }
                }
                else
                {
                    if (0x80 != (ch & 0xC0))
                    {
                        result_flag = false;
                        break;
                    }

                    if (flag_bom)
                    {
                        if (0xBB != ch && 2 == byte_count)
                        {
                            flag_bom = false;
                        }

                        if (0xBF != ch && 1 == byte_count)
                        {
                            flag_bom = false;
                        }
                    }

                    cp32 = cp32 << 6;
                    cp32 |= ch & 0x3F;

                    byte_count--;

                    if (0 == byte_count)
                    {
                        if (flag_bom)
                        {
                            flag_bom = false;
                            ch_data_ptr++;
                            continue;
                        }

                        ch_count++;
                    }
                }
            }

            if (0 == byte_count)
            {
                if (text_utf8_ptr)
                {
                    text_out_utf8 += std::move(_get_utf8_text_for_code_point(cp32));
                }

                if (text_utf16_ptr)
                {
                    if (cp32 < 0x10000)
                    {
                        text_out_utf16.push_back((uint16_t)(cp32 & 0xFFFF));
                    }
                    else
                    {
                        uint16_t cp = (uint16_t)(cp32 - 0x10000);
                        uint16_t cp32_high = (uint16_t)(cp >> 10) + 0xD800;
                        uint16_t cp32_low = (uint16_t)(cp & 0x3FF) + 0xDC00;

                        text_out_utf16.push_back(cp32_high);
                        text_out_utf16.push_back(cp32_low);
                    }
                }
            }

            ch_data_ptr++;

            if (-1 != size)
            {
                size--;
            }
        }

        if (!result_flag)
        {
            return -1;
        }

        if (text_utf8_ptr)
        {
            *text_utf8_ptr = std::move(text_out_utf8);
        }

        if (text_utf16_ptr)
        {
            *text_utf16_ptr = std::move(text_out_utf16);
        }

        return ch_count;
    }

    int32_t _utf16_to_utf8(const void* data_ptr, size_t size/* = -1*/, std::string* text_utf8_ptr/* = nullptr*/, std::wstring* text_utf16_ptr/* = nullptr*/)
    {
        const uint16_t* ch_data_ptr = (const uint16_t*)data_ptr;
        std::wstring text_out_utf16;
        std::string text_out_utf8;
        uint32_t cp32 = 0;
        uint16_t cp32_high = 0;
        uint16_t cp32_low = 0;
        uint16_t cp16 = 0;
        int32_t byte_count = 0;
        int32_t ch_count = 0;
        bool flag_big_endian = false;
        bool flag_little_endian = false;
        bool result_flag = true;

        if (text_utf8_ptr)
        {
            text_out_utf8 += *text_utf8_ptr;
        }

        if (text_utf16_ptr)
        {
            text_out_utf16 += *text_utf16_ptr;
        }

        if (-1 != size)
        {
            if ((size < 2) || (0 != (size % 2)))
            {
                return -1;
            }
        }

        while ((0 != *ch_data_ptr) && (0 != size))
        {
            cp16 = *ch_data_ptr;

            if (0xFFFE == cp16 || 0xFEFF == cp16)
            {
                if (0 == byte_count)
                {
                    if (0xFFFE == cp16)
                    {
                        flag_big_endian = true;
                    }

                    if (0xFEFF == cp16)
                    {
                        flag_little_endian = true;
                    }
                }
                else
                {
                    result_flag = false;
                    break;
                }

                if (flag_big_endian && flag_little_endian)
                {
                    result_flag = false;
                    break;
                }

                ch_data_ptr++;

                if (-1 != size)
                {
                    size -= 2;
                }

                continue;
            }

            if (flag_big_endian)
            {
                cp16 = ((cp16 >> 8) | (cp16 << 8));
            }

            if (!(cp16 >= 0xD800 && cp16 <= 0xDFFF))
            {
                if (cp32_high > 0)
                {
                    result_flag = false;
                    break;
                }

                cp32 = cp16;
                ch_count++;
            }
            else
            {
                if (0 == byte_count)
                {
                    if (cp16 >= 0xD800 && cp16 <= 0xDBFF)
                    {
                        cp32_high = (cp16 - 0xD800);
                        byte_count = 1;
                    }
                    else
                    {
                        result_flag = false;
                        break;
                    }
                }
                else
                {
                    if (1 == byte_count)
                    {
                        if ((cp16 >= 0xDC00) && (cp16 <= 0xDFFF))
                        {
                            cp32_low = (cp16 - 0xDC00);
                            cp32 = 0x10000 + ((uint32_t)cp32_high << 10 | cp32_low);
                            cp32_low = 0;
                            cp32_high = 0;
                        }
                        else
                        {
                            result_flag = false;
                            break;
                        }
                    }

                    byte_count--;

                    if (0 == byte_count)
                    {
                        ch_count++;
                    }
                }
            }

            if (0 == byte_count)
            {
                if (text_utf8_ptr)
                {
                    text_out_utf8 += std::move(_get_utf8_text_for_code_point(cp32));
                }

                if (text_utf16_ptr)
                {
                    if (cp32 < 0x10000)
                    {
                        text_out_utf16.push_back((uint16_t)(cp32 & 0xFFFF));
                    }
                    else
                    {
                        uint16_t cp = (uint16_t)(cp32 - 0x10000);
                        uint16_t cpHi = (uint16_t)(cp >> 10) + 0xD800;
                        uint16_t cp_low = (uint16_t)(cp & 0x3FF) + 0xDC00;

                        text_out_utf16.push_back(cpHi);
                        text_out_utf16.push_back(cp_low);
                    }
                }
            }

            ch_data_ptr++;

            if (-1 != size)
            {
                size -= 2;
            }
        }

        if (!result_flag)
        {
            return -1;
        }

        if (text_utf8_ptr)
        {
            *text_utf8_ptr = std::move(text_out_utf8);
        }

        if (text_utf16_ptr)
        {
            *text_utf16_ptr = std::move(text_out_utf16);
        }

        return ch_count;
    }

    std::string _utf16_to_utf8(const std::wstring utf16)
    {
        std::string str_utf8;
        std::wstring str_utf16;
        int32_t utf8_length = _utf16_to_utf8(utf16.data(), utf16.size() * sizeof(wchar_t), &str_utf8, &str_utf16);
        return str_utf8;
    }

    std::wstring _utf8_to_utf16(const std::string utf8)
    {
        std::string str_utf8;
        std::wstring str_utf16;
        int32_t utf16_length = _utf8_to_utf16(utf8.data(), utf8.size() * sizeof(wchar_t), &str_utf8, &str_utf16);
        return str_utf16;
    }

#ifdef _WIN32

    static std::string _WStrToMultiStr(uint32_t CodePage, const std::wstring& str)
    {
        int cbMultiByte = ::WideCharToMultiByte(CodePage, 0, str.c_str(), -1, NULL, 0, NULL, 0);
        std::string strResult(cbMultiByte, 0);
        size_t nConverted = ::WideCharToMultiByte(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size(), NULL, NULL);
        strResult.resize(nConverted);
        return strResult;
    }

    static std::wstring _MultiStrToWStr(uint32_t CodePage, const std::string& str)
    {
        int cchWideChar = ::MultiByteToWideChar(CodePage, 0, str.c_str(), -1, NULL, NULL);
        std::wstring strResult(cchWideChar, 0);
        size_t nConverted = ::MultiByteToWideChar(CodePage, 0, str.c_str(), (int)str.size(), &strResult[0], (int)strResult.size());
        strResult.resize(nConverted);
        return strResult;
    }

    std::wstring AStrToWStr(const std::string& str)
    {
        return _MultiStrToWStr(CP_ACP, str);
    }

    std::string AStrToU8Str(const std::string& str)
    {
        return _WStrToMultiStr(CP_UTF8, _MultiStrToWStr(CP_ACP, str));
    }

    _tstring AStrToTStr(const std::string& str)
    {
#ifdef _UNICODE
        return _MultiStrToWStr(CP_ACP, str);
#else
        return str;
#endif
    }

    std::string WStrToAStr(const std::wstring& str)
    {
        return _WStrToMultiStr(CP_ACP, str);
    }

    std::string WStrToU8Str(const std::wstring& str)
    {
        return _WStrToMultiStr(CP_UTF8, str);
    }

    _tstring WStrToTStr(const std::wstring& str)
    {
#ifdef _UNICODE
        return str;
#else
        return _WStrToMultiStr(CP_ACP, str);
#endif
    }

    std::wstring U8StrToWStr(const std::string& str)
    {
        return _MultiStrToWStr(CP_UTF8, str);
    }

    std::string U8StrToAStr(const std::string& str)
    {
        return _WStrToMultiStr(CP_ACP, U8StrToWStr(str));
    }

    _tstring U8StrToTStr(const std::string& str)
    {
#ifdef _UNICODE
        return _MultiStrToWStr(CP_UTF8, str);
#else
        return _WStrToMultiStr(CP_ACP, U8StrToWStr(str));
#endif
    }

    std::string TStrToU8Str(const _tstring& str)
    {
#ifdef _UNICODE
        return _WStrToMultiStr(CP_UTF8, str);
#else
        return _WStrToMultiStr(CP_UTF8, _MultiStrToWStr(CP_ACP, str));
#endif
    }

    std::string TStrToAStr(const _tstring& str)
    {
#ifdef _UNICODE
        return _WStrToMultiStr(CP_ACP, str);
#else
        return str;
#endif
    }

    std::wstring TStrToWStr(const _tstring& str)
    {
#ifdef _UNICODE
        return str;
#else
        return _MultiStrToWStr(CP_ACP, str);
#endif
    }

#endif

}

 用法

main.cpp

#include <iostream>
#include <locale>
#include <string>
#include <fstream>
#include "fcjson.h"

#pragma execution_character_set("utf-8")

#if  0
#define TEST_JSON_FILE  "data.json"
#else
#define TEST_JSON_FILE  "city_4.json"
#endif

int count = 1;
int dump_indent = 4;

int main()
{
    setlocale(LC_ALL, "zh_CN.UTF-8");
    system("chcp 65001");

    // 解析文件/转储文件
    std::cout << std::endl;
    std::cout << "解析文件/转储文件" << std::endl;
    {
        fcjson::json_value val;
        val.parse_from_file("data.json");
        val.dump_to_file("dump.json", 4);
    }

    // 构造 JSON 对象
    std::cout << "构造 JSON 对象" << std::endl;
    {
        fcjson::json_value val = fcjson::json_object{
            { "null", nullptr},
            { "bool_false", false },
            { "bool_true", true },
            { "int_min", INT64_MIN },
            { "int_max", INT64_MAX },
            { "uint_max", UINT64_MAX },
            { "float", 3.1415926535 },
            { "object", fcjson::json_object{
                    { "name", "我是地球🌍" },
                    { "age", 30 }
                },
            },
            { "array", fcjson::json_array{
                nullptr,
                false, true, INT64_MIN, INT64_MAX, 3.1415926535
                }
            }
        };

        // 序列化(不转义UNICODE字符)
        std::string str_dump = val.dump(4, false);
        std::cout << val.dump(4, false) << std::endl;

        // 序列化(转义UNICODE字符)
        std::cout << val.dump(4, true) << std::endl;
    }

    // 赋值操作
    std::cout << std::endl;
    std::cout << "赋值操作" << std::endl;
    {
        fcjson::json_value val;
        val = fcjson::json_array{ 1,2,3,4,5,6,7,8,9,0 };
        std::cout << "count: " << val.count() << std::endl;
        std::cout << "type: " << val.type_name() << std::endl;
        std::cout << val.dump(4, false) << std::endl;

        val = fcjson::json_object{{ "name", "我是地球🌍" }, { "age", 30 }};
        std::cout << "count: " << val.count() << std::endl;
        std::cout << "type: " << val.type_name() << std::endl;
        std::cout << val.dump(4, false) << std::endl;
    }

    // 解析字符串/转储字符串
    std::cout << std::endl;
    std::cout << "解析字符串/转储字符串" << std::endl;
    {
        fcjson::json_value val;

        val.parse(R"({"name":"FlameCyclone","age":30})");
        std::string strJson = val.dump(4, true);
        std::cout << strJson << std::endl;

        // 访问数组
        val["array"] = fcjson::json_type::json_type_array;
        auto& array = val["array"];
        for (int i = 0; i < 5; i++)
        {
            array[i] = i;
        }

        // 删除数组元素
        array.remove(4);

        // 访问对象
        val["object"] = fcjson::json_type::json_type_object;
        auto& object = val["object"];
        for (int i = 0; i < 5; i++)
        {
            object[std::to_string(i)] = i;
        }

        // 删除对象元素
        object.remove("1");

        //赋值
        val["hobby"] = "C++";
        val.remove("object");
        val["hobby"] = nullptr;

        std::cout << val.dump(4, true) << std::endl;
    }

    //多层嵌套
    std::cout << std::endl;
    std::cout << "多层嵌套" << std::endl;
    {
        fcjson::json_value val = fcjson::json_type::json_type_array;
        val[0] = fcjson::json_type::json_type_array;
        val[0][0] = fcjson::json_type::json_type_array;
        val[0][0][0] = fcjson::json_type::json_type_object;

        val[0][0][0]["string"] = "hello json";
        val[0][0][0]["object"] = fcjson::json_type::json_type_object;
        val[0][0][0]["object"]["name"] = "🌍FlameCyclone🌍";
        val[0][0][0]["object"]["age"] = 30;

        // 访问无效的元素将什么也不会发生
        val[0][1][2][4][5][6][7][8][9][10][11][12][13][14][15] = "test";

        std::cout << "type: " << val[0][1][2][4][5][6][7][8][9][10][11][12][13][14][15].type_name() << std::endl;
        std::cout << "count: " << val[0][1][2][4][5][6][7][8][9][10][11][12][13][14][15].count() << std::endl;

        // 序列化(转义UNICODE字符)
        std::cout << val.dump(4, false) << std::endl;
        std::cout << val.dump(4, true) << std::endl;

    }

    std::ifstream inputFile(TEST_JSON_FILE, std::ios::binary | std::ios::in);
    if (!inputFile.is_open())
    {
        return -1;
    }

    inputFile.seekg(0, std::ios::end);
    std::streamoff nSize = inputFile.tellg();
    inputFile.seekg(0, std::ios::beg);

    std::string strBuffer(nSize, 0);
    inputFile.read((char*)&strBuffer[0], nSize);
    inputFile.close();

    // 性能测试
    size_t nCount = count;
    clock_t timeBegin = clock();
    clock_t timeEnd = clock();

    std::cout << std::endl;
    std::cout << "性能测试" << std::endl;

    std::string strText;

    while (true)
    {
        {
            fcjson::json_value val;

            timeBegin = clock();
            for (int i = 0; i < nCount; i++)
            {
                val.parse(strBuffer);
            }
            timeEnd = clock();
            std::cout << "parse cost time: " << timeEnd - timeBegin << std::endl;

            timeBegin = clock();
            std::string strDump;
            for (int i = 0; i < nCount; i++)
            {
                strDump = val.dump(dump_indent, false);
            }
            timeEnd = clock();
            std::cout << "dump cost time: " << timeEnd - timeBegin << std::endl;
            std::cout << "dump text size: " << strDump.size() << std::endl;

            {
                std::ofstream outputFile("dump_fcjson.json", std::ios::binary | std::ios::out);
                if (outputFile.is_open())
                {
                    outputFile.write(strDump.data(), strDump.size());
                }
            }
            std::cout << std::endl;
        }

        system("pause");
    }

    return 0;
}

测试

233a8440937f42108d052e3827e036c7.png

性能测试

解析转储2.7MB的json文件

FlameCyclone/fcjson
parse: 67 ms Mem: 26.3086 MB
dump: 30 ms Mem: 5.07812 MB Dump size: 2850256 Bytes

RapidJSON
parse: 31 ms Mem: 6.84375 MB
dump: 17 ms Mem: 7.28516 MB Dump size: 2850256 Bytes

nlohmann/json
parse: 99 ms Mem: 27.7891 MB
dump: 31 ms Mem: 32.5625 MB Dump size: 2850256 Bytes

hjiang/jsonxx
parse: 409 ms Mem: 30.3203 MB
dump: 635 ms Mem: 20.0195 MB Dump size: 15973857 Bytes

Nomango/configor
parse: 765 ms Mem: 41.2227 MB
dump: 450 ms Mem: 5.65625 MB Dump size: 2850256 Bytes

gitee仓库

fcjson: 自己实现的精简的json解析库

https://gitee.com/flame_cyclone/fcjson

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值