• lua table与json的之间的互相转换高性能c++实现


    请自行约束两种语言数据结构语法上的不同,避开如下问题:

    1、json本身不约束key是否符合一个编程语言中的变量名,所以编写用于和编程语言数据结构交互的json代码时应该注意key是否正确。

    2、lua没有数组,利用哈希表实现的逻辑上的数组,在中间可以存在不连续的情况时json将无法识别。

    3、lua的字符串key可以和数字key共存,这对于json来说,是不允许的。

     这些代码我已经用了很久了,所以暂时不多解释了,依赖c++11以上的版本,

    代码挺多,有需求可以直接复制,这么多代码的目的也就是更高性能,单纯的在C++里面跑,比谷歌的实现稍微快一点点。

    好了,废话不多说,上代码

    #pragma once
    #include <string>
    #include <functional>
    #include <setjmp.h>
    #include <fstream>
    #include <vector>
    
    namespace aqx {
    
    #ifndef jsize_t
        typedef unsigned int jsize_t;
    #endif
    
    #ifndef jnumber_t
        typedef double jnumber_t;
    #endif
    
        static short constexpr jsvt_null{ 0 };
        static short constexpr jsvt_string{ 1 };
        static short constexpr jsvt_number{ 2 };
        static short constexpr jsvt_boolean{ 3 };
        static short constexpr jsvt_object{ 4 };
        static short constexpr jsvt_group{ 5 };
    
        namespace aqx_internal {
    #ifndef __AQX_UTF8_CHAR_LEN
    #define __AQX_UTF8_CHAR_LEN
            static unsigned char utf8_char_len[] = {
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
                2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
                2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
                3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,
                4,4,4,4,4,4,4,4,5,5,5,5,6,6,1,1
            };
    #endif
    
            static unsigned int json_char_state[] = {
                0,0,0,0,0,0,0,0,0,32,96,0,0,96,0,0,
                0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
                32,0,640,0,0,0,0,0,0,0,0,1048576,65536,8192,131072,512,
                3072,3072,3072,3072,3072,3072,3072,3072,3072,3072,16,0,0,0,0,0,
                0,1024,1024,1024,1024,5120,1024,0,0,0,0,0,0,0,0,0,
                0,0,0,0,0,0,0,0,0,0,0,4,768,8,0,0,
                0,17408,1024,1024,1024,21504,50176,0,0,0,0,0,278528,0,524800,0,
                0,0,16896,16384,49664,279040,0,0,0,0,0,1,0,2,0,0
            };
    
            static int u16c2u8c(unsigned long u16c, unsigned char *u8c) {
                if (u16c <= 0x0000007F) {
                    u8c[0] = u16c & 0x7F;
                    return 1;
                }
                else if (u16c >= 0x00000080 && u16c <= 0x000007FF) {
                    u8c[1] = (u16c & 0x3F) | 0x80;
                    u8c[0] = ((u16c >> 6) & 0x1F) | 0xC0;
                    return 2;
                }
                else if (u16c >= 0x00000800 && u16c <= 0x0000FFFF)
                {
                    u8c[2] = (u16c & 0x3F) | 0x80;
                    u8c[1] = ((u16c >> 6) & 0x3F) | 0x80;
                    u8c[0] = ((u16c >> 12) & 0x0F) | 0xE0;
                    return 3;
                }
                else if (u16c >= 0x00010000 && u16c <= 0x001FFFFF)
                {
                    u8c[3] = (u16c & 0x3F) | 0x80;
                    u8c[2] = ((u16c >> 6) & 0x3F) | 0x80;
                    u8c[1] = ((u16c >> 12) & 0x3F) | 0x80;
                    u8c[0] = ((u16c >> 18) & 0x07) | 0xF0;
                    return 4;
                }
                else if (u16c >= 0x00200000 && u16c <= 0x03FFFFFF)
                {
                    u8c[4] = (u16c & 0x3F) | 0x80;
                    u8c[3] = ((u16c >> 6) & 0x3F) | 0x80;
                    u8c[2] = ((u16c >> 12) & 0x3F) | 0x80;
                    u8c[1] = ((u16c >> 18) & 0x3F) | 0x80;
                    u8c[0] = ((u16c >> 24) & 0x03) | 0xF8;
                    return 5;
                }
                else if (u16c >= 0x04000000 && u16c <= 0x7FFFFFFF)
                {
                    u8c[5] = (u16c & 0x3F) | 0x80;
                    u8c[4] = ((u16c >> 6) & 0x3F) | 0x80;
                    u8c[3] = ((u16c >> 12) & 0x3F) | 0x80;
                    u8c[2] = ((u16c >> 18) & 0x3F) | 0x80;
                    u8c[1] = ((u16c >> 24) & 0x3F) | 0x80;
                    u8c[0] = ((u16c >> 30) & 0x01) | 0xFC;
                    return 6;
                }
    
                return 0;
            }
    
            namespace JSON_SYNTAX {
                static constexpr auto _T_OBJECT_BEGIN{ static_cast<unsigned int>(0x01) };            // {
                static constexpr auto _T_OBJECT_END{ static_cast<unsigned int>(0x02) };            // }
                static constexpr auto _T_GROUP_BEGIN{ static_cast<unsigned int>(0x04) };            // [
                static constexpr auto _T_GROUP_END{ static_cast<unsigned int>(0x08) };            // ]
                static constexpr auto _T_VALUE{ static_cast<unsigned int>(0x10) };                // :
                static constexpr auto _T_SPACE{ static_cast<unsigned int>(0x20) };                // 4个空白字符" 	
    "
                static constexpr auto _T_ENDL{ static_cast<unsigned int>(0x40) };                    // 2个换行符"
    "
                static constexpr auto _T_TEXT{ static_cast<unsigned int>(0x80) };                    // "
                static constexpr auto _T_ESCAPE_BEGIN{ static_cast<unsigned int>(0x100) };            // 转义符开始 '\'
                static constexpr auto _T_ESCAPE_TYPE{ static_cast<unsigned int>(0x200) };            // 转义符类型 "nrtbfu\"
                static constexpr auto _T_HEX{ static_cast<unsigned int>(0x400) };                    // u之后UTF16的4字符HEX,"abcdefABCDEF"
                static constexpr auto _T_NUMBER{ static_cast<unsigned int>(0x800) };                // 数字"0-9"
                static constexpr auto _T_E{ static_cast<unsigned int>(0x1000) };                    // 科学计数法 e或E
                static constexpr auto _T_NEGATIVE{ static_cast<unsigned int>(0x2000) };            // 负数 -
                static constexpr auto _T_BOOL{ static_cast<unsigned int>(0x4000) };                // true false
                static constexpr auto _T_BOOL_BEGIN{ static_cast<unsigned int>(0x8000) };            // t f
                static constexpr auto _T_NEXT{ static_cast<unsigned int>(0x10000) };                // ,
                static constexpr auto _T_DECIMAL{ static_cast<unsigned int>(0x20000) };            // 小数点 .
                static constexpr auto _T_NULL{ static_cast<unsigned int>(0x40000) };                // null
                static constexpr auto _T_NULL_BEGIN{ static_cast<unsigned int>(0x80000) };            // n
                static constexpr auto _T_POSITIVE{ static_cast<unsigned int>(0x100000) };                // +
            }
    
    
            static constexpr auto _jnf{ static_cast<jsize_t>(-1) };
    
    
            template<typename _Ty> class _json_parser;
    
            class _jts_base {
            public:
                _jts_base() {
                    text = nullptr;
                }
    
                void init(const char *_Text, int _Size) {
                    text = _Text;
                    size = _Size;
                    instr = false;
                    flags = 0;
                    index = 0;
                }
    
                jsize_t open_instr() {
                    instr = true;
                    jsize_t _Result = flags;
                    flags = 0;
                    return _Result;
                }
    
                void close_instr(jsize_t _Flags) {
                    instr = false;
                    flags = _Flags;
                }
    
                jsize_t set_flags(jsize_t _Flags) {
                    auto _Result = flags;
                    flags = _Flags;
                    return _Result;
                }
    
                long subhextol(int left, int len) {
                    long _Result = 0;
                    int rlen = len;
                    for (int i = 0; i < len; i++) {
                        char c = text[--rlen];
                        long _Tmp;
                        switch (c) {
                        case '0':
                        case '1':
                        case '2':
                        case '3':
                        case '4':
                        case '5':
                        case '6':
                        case '7':
                        case '8':
                        case '9':
                            _Tmp = c - '0';
                            break;
                        case 'a':
                        case 'b':
                        case 'c':
                        case 'd':
                        case 'e':
                        case 'f':
                            _Tmp = c - 'a' + 10;
                            break;
                        case 'A':
                        case 'B':
                        case 'C':
                        case 'D':
                        case 'E':
                        case 'F':
                            _Tmp = c - 'A' + 10;
                            break;
                        default:
                            return 0;
                        }
                        _Result += (_Tmp << (i << 2));
                    }
                    return _Result;
                }
    
            protected:
                const char *text;
                jsize_t size;
                unsigned int s;
                char c;
                unsigned char cl;
                bool instr;
                unsigned int flags;
                jsize_t index;
                std::string tmp;
            };
    
            class _jts_utf8 : public _jts_base
            {
            public:
                int operator++() {
    
    
                    c = text[index];
                    cl = utf8_char_len[(unsigned char)c];
                    if (cl != 1) {
                        if (flags == JSON_SYNTAX::_T_ESCAPE_TYPE || !instr)
                            return -1;
                        do {
                            index += cl;
                            c = text[index];
                            cl = utf8_char_len[(unsigned char)c];
                        } while (cl != 1);
                    }
                    s = json_char_state[c];
                    if (flags & s) {
                        index += cl;
                        return 0;
                    }
    
                    if (instr) {
                        if (s & JSON_SYNTAX::_T_ENDL)
                            return -1;
    
                        index += cl;
                        return 0;
                    }
    
                    return -1;
                }
    
            private:
                friend class _json_parser<_jts_utf8>;
            };
    
            class _jts_gbk : public _jts_base
            {
            public:
                int operator++() {
                    c = text[index];
                    cl = ((unsigned char)c & 0x80) ? 2 : 1;
                    if (cl != 1) {
                        if (flags == JSON_SYNTAX::_T_ESCAPE_TYPE || !instr)
                            return -1;
                        do {
                            index += cl;
                            c = text[index];
                            cl = ((unsigned char)c & 0x80) ? 2 : 1;
                        } while (cl != 1);
                    }
                    s = json_char_state[c];
                    if (flags & s) {
                        index += cl;
                        return 0;
                    }
    
                    if (instr) {
                        if (s & JSON_SYNTAX::_T_ENDL)
                            return -1;
    
                        index += cl;
                        return 0;
                    }
    
                    return -1;
                }
    
            private:
                friend class _json_parser<_jts_gbk>;
            };
    
            class _json_tree {
            public:
                class node {
                public:
                    node() {
                        _Size = 0;
                        _Bgn = _Parent = _jnf;
                    }
    
                    node(jsize_t _Pa) {
                        _Size = 0;
                        _Parent = _Pa;
                        _Bgn = _jnf;
                    }
    
                    jsize_t size() {
                        return _Size;
                    }
    
                    jsize_t begin() {
                        return _Bgn;
                    }
    
                private:
                    friend class _json_parser<_jts_utf8>;
                    friend class _json_parser<_jts_gbk>;
                    friend class _json_tree;
                    jsize_t _Size, _Bgn, _End, _Parent;
                };
    
                class var {
                public:
    
                    var() {
                        Key = _jnf;
                        Next = _jnf;
                        Kty = 1;
                        Type = 0;
                    }
    
                    var(short _KTy, jsize_t _Key) {
                        Next = _jnf;
                        Kty = _KTy;
                        Key = _Key;
                        Type = 0;
                    }
    
                    var(short _KTy, jsize_t _Key, short _Type, jsize_t _Val) {
                        Next = _jnf;
                        Kty = _KTy;
                        Key = _Key;
                        Type = _Type;
                        Off = _Val;
                    }
    
                    var(short _KTy, jsize_t _Key, short _Type, bool _Val) {
                        Next = _jnf;
                        Kty = _KTy;
                        Key = _Key;
                        Type = _Type;
                        Stat = _Val;
                    }
    
                    var(short _KTy, jsize_t _Key, short _Type, jnumber_t _Val) {
                        Next = _jnf;
                        Kty = _KTy;
                        Key = _Key;
                        Type = _Type;
                        Number = _Val;
                    }
    
                    short type() { return Type; }
                    bool is_ikey() { return Kty == 1; }
                    var *next(_json_tree &_Tree) {
                        if (Next == _jnf)
                            return nullptr;
                        return _Tree.get_val(Next);
                    }
    
                    jsize_t ikey() {
                        return (is_ikey()) ? Key : _jnf;
                    }
    
                    const char *skey(_json_tree &_Tree) {
                        return (!is_ikey()) ? _Tree.get_text(Key) : "";
                    }
    
    
                    bool toboolean() {
                        return Stat;
                    }
    
                    const char *tostring(_json_tree &_Tree) {
                        return (type() == 1) ? _Tree.get_text(Off) : "";
                    }
    
                    jnumber_t tonumber() {
                        return (type() == 2) ? Number : 0;
                    }
    
                    node *toobject(_json_tree &_Tree) {
                        return (type() == aqx::jsvt_object || type() == aqx::jsvt_group) ? _Tree.get_node(Off) : nullptr;
                    }
    
    
                private:
                    friend class _json_parser<_jts_utf8>;
                    friend class _json_parser<_jts_gbk>;
                    friend class _json_tree;
                    jsize_t Key;
                    jsize_t Next;
                    short Type;
                    short Kty;
                    union {
                        bool Stat;
                        jsize_t Off;
                        jnumber_t Number;
                    };
                };
    
                _json_tree() {
                    _Texts = { 0, 0, 0 };
                }
    
                node *get_root() {
                    if (_Nodes.size() < 2)return nullptr;
                    return get_node(1);
                }
    
                var *get_root_val() {
                    if (_Nodes.size() < 2)return nullptr;
                    return get_val(1);
                }
    
                node *get_node(jsize_t _Ref) { return (_Ref < (jsize_t)_Nodes.size()) ? &(_Nodes[_Ref]) : nullptr; }
                var *get_val(jsize_t _Ref) { return (_Ref < (jsize_t)_Vals.size()) ? &(_Vals[_Ref]) : nullptr; }
                const char *get_text(jsize_t _Ref) { return (_Ref <= _Texts.size) ? _Texts.data + _Ref : nullptr; }
    
                void reserve(jsize_t _TextSize, jsize_t _Count) {
                    if (_TextSize << 1 > _Texts.capacity)
                        _Realloc_Texts(_TextSize << 1);
                    _Vals.reserve(_Count << 1);
                    _Nodes.reserve(_Count);
                }
    
                void clear() {
                    _Texts.size = 0;
                    _Vals.clear();
                    _Nodes.clear();
                }
    
            private:
                void _set_child(node *e, jsize_t v) {
                    if (e->_Bgn == _jnf) {
                        e->_Bgn = v;
                        e->_End = v;
                    }
                    else {
                        get_val(e->_End)->Next = v;
                        e->_End = v;
                    }
                }
    
                jsize_t new_node(jsize_t _Node, jsize_t &_Name, short _Type) {
                    jsize_t _Result = (jsize_t)_Nodes.size();
                    _Nodes.push_back(node(_Node));
                    jsize_t v = (jsize_t)_Vals.size();
                    auto e = get_node(_Node);
                    if (_Name != _jnf) {
                        _Vals.push_back(var(0, _Name, _Type, _Result));
                        _Name = _jnf;
                        e->_Size++;
                    }
                    else
                        _Vals.push_back(var(1, e->_Size++, _Type, _Result));
                    _set_child(e, v);
                    return _Result;
                }
    
    
    
                jsize_t new_root() {
                    jsize_t _Result = (jsize_t)_Nodes.size();
                    _Nodes.push_back(node());
                    jsize_t v = (jsize_t)_Vals.size();
                    _Vals.push_back(var(1, _jnf, aqx::jsvt_object, _Result));
                    return _Result;
                }
    
                void _Realloc_Texts(jsize_t _NewCapacity = 0) {
                    if (_NewCapacity != 0)
                        _Texts.capacity = (_NewCapacity + (_NewCapacity >> 1));
                    else
                        _Texts.capacity = (_Texts.capacity + (_Texts.capacity >> 1));
                    if (_Texts.capacity < 0x1000)
                        _Texts.capacity = 0x1000;
                    char *_Tmp = new char[_Texts.capacity];
                    if (_Texts.data) {
                        if (_Texts.size)
                            memcpy_s(_Tmp, _Texts.capacity, _Texts.data, _Texts.size);
                        delete _Texts.data;
                    }
                    _Texts.data = _Tmp;
                }
    
                jsize_t new_text(const char *_Text, int _Len) {
                    jsize_t x = _Texts.size + (sizeof(size_t) - (_Texts.size % sizeof(size_t)));
                    if (x + _Len >= _Texts.capacity)
                        _Realloc_Texts(x + _Len);
                    char *_Target = _Texts.data + x;
                    _Texts.size = x + (_Len--);
                    memcpy_s(_Target, _Len, _Text, _Len);
                    _Target[_Len] = 0;
                    return x;
                }
    
                void append_text(const char *_Text, int _Len) {
                    if (_Texts.size + _Len >= _Texts.capacity)
                        _Realloc_Texts(_Texts.size + _Len);
                    char *_Target = _Texts.data + _Texts.size - 1;
                    _Texts.size += _Len--;
                    _Texts.size--;
                    memcpy_s(_Target, _Len, _Text, _Len);
                    _Target[_Len] = 0;
                }
    
                void append_char(char _Chr) {
                    if (_Texts.size + 1 >= _Texts.capacity)
                        _Realloc_Texts(_Texts.size + 1);
                    _Texts.data[_Texts.size - 1] = _Chr;
                    _Texts.data[_Texts.size++] = 0;
                }
    
                void back_text(int _Len) {
                    _Texts.size -= _Len;
                    _Texts.data[_Texts.size] = 0;
                }
    
                jsize_t new_var_string(jsize_t _Node, jsize_t &_Name, jsize_t _Text) {
                    jsize_t v = (jsize_t)_Vals.size();
                    auto e = get_node(_Node);
                    if (_Name != _jnf) {
                        _Vals.push_back(var(0, _Name, aqx::jsvt_string, _Text));
                        _Name = _jnf;
                        e->_Size++;
                    }
                    else
                        _Vals.push_back(var(1, e->_Size++, aqx::jsvt_string, _Text));
                    _set_child(e, v);
                    return v;
                }
    
                jsize_t new_var_number(jsize_t _Node, jsize_t &_Name, jnumber_t _Number) {
                    jsize_t v = (jsize_t)_Vals.size();
                    auto e = get_node(_Node);
                    if (_Name != _jnf) {
                        _Vals.push_back(var(0, _Name, aqx::jsvt_number, _Number));
                        _Name = _jnf;
                        e->_Size++;
                    }
                    else
                        _Vals.push_back(var(1, e->_Size++, aqx::jsvt_number, _Number));
                    _set_child(e, v);
                    return v;
                }
    
                jsize_t new_var_boolean(jsize_t _Node, jsize_t &_Name, bool _Stat) {
                    jsize_t v = (jsize_t)_Vals.size();
                    auto e = get_node(_Node);
                    if (_Name != _jnf) {
                        _Vals.push_back(var(0, _Name, aqx::jsvt_boolean, _Stat));
                        _Name = _jnf;
                        e->_Size++;
                    }
                    else
                        _Vals.push_back(var(1, e->_Size++, aqx::jsvt_boolean, _Stat));
                    _set_child(e, v);
                    return v;
                }
    
                jsize_t new_var_null(jsize_t _Node, jsize_t &_Name) {
                    jsize_t v = (jsize_t)_Vals.size();
                    auto e = get_node(_Node);
                    if (_Name != _jnf) {
                        _Vals.push_back(var(0, _Name, aqx::jsvt_null, (jnumber_t)0));
                        _Name = _jnf;
                        e->_Size++;
                    }
                    else
                        _Vals.push_back(var(1, e->_Size++, aqx::jsvt_null, (jnumber_t)0));
                    _set_child(e, v);
                    return v;
                }
    
            private:
                friend class _json_parser<_jts_utf8>;
                friend class _json_parser<_jts_gbk>;
                std::vector<var> _Vals;
                std::vector<node> _Nodes;
                struct _TEXTS_POOL { char *data; jsize_t size; jsize_t capacity; }_Texts;
            };
    
            template<typename _Ty>
            class _json_parser {
            public:
                _json_parser(_json_tree &_Tree) {
                    tree = &_Tree;
                }
    
                bool load_string(const char *_Text, jsize_t _Len = _jnf, bool _MultiRoot = false) {
                    if ((int)_Len < 0)
                        _Len = (jsize_t)strlen(_Text) + 1;
                    jts.init(_Text, _Len);
                    tree->clear();
                    return j_root(_MultiRoot) == 0;
                }
    
                bool load_file(const std::string _File, bool _MultiRoot = false) {
                    std::ifstream f(_File.c_str(), std::ifstream::binary);
                    if (!f)
                        return false;
                    f.seekg(0, f.end);
                    size_t fs = (size_t)f.tellg();
                    f.seekg(0, f.beg);
                    char *_Buf = new char[fs + 2];
                    _Buf[fs] = 0;
                    _Buf[fs + 1] = 0;
                    f.read(_Buf, fs);
                    f.close();
                    bool _Result = load_string(_Buf, (jsize_t)fs, _MultiRoot);
                    delete _Buf;
                    return _Result;
                }
    
                jsize_t get_error_pos() {
    
                    /*for (int i = err_pos; i < err_pos + 10; i++)
                        printf("%c", jts.text[i]);
                    printf("
    ");*/
                    return err_pos;
                }
    
            private:
                void jtsnext() {
                    if ((jts.index >= jts.size) || (++jts) != 0) {
                        err_pos = jts.index;
                        longjmp(_Rem, -1);
                    }
                }
    
                void j_ec(jsize_t &_Off, jsize_t &_TextOff) {
                    jsize_t len = jts.index - _Off;
                    if (_TextOff == (jsize_t)-1)
                        _TextOff = tree->new_text(jts.text + _Off, len);
                    else
                        tree->append_text(jts.text + _Off, len);
    
                    jts.close_instr(JSON_SYNTAX::_T_ESCAPE_TYPE);
                    jtsnext();
                    if (jts.c == 'u') {
                        jsize_t ecpos = jts.index;
                        unsigned long _uc1 = 0;
                        int _uc1_len = 0;
                        char u8c[7];
                        for (;;) {
                            jts.set_flags(JSON_SYNTAX::_T_HEX);
                            for (int i = 0; i < 4; i++) {
                                jtsnext();
                            }
    
                            unsigned long uc = (unsigned short)jts.subhextol(ecpos, jts.index - ecpos);
                            if (_uc1 >= 0xD800 && _uc1 < 0xDBFF && uc >= 0xDC00 && uc < 0xDFFF) {
                                int u8l = u16c2u8c((_uc1 - 0xD800) * 0x400 + (uc - 0xDC00) + 0x10000, (unsigned char*)u8c);
                                u8c[u8l] = 0;
                                tree->back_text(_uc1_len + 1);
                                tree->append_text(u8c, u8l + 1);
                                _uc1 = 0;
                            }
                            else {
                                _uc1 = uc;
                                _uc1_len = u16c2u8c(uc, (unsigned char*)u8c);
                                u8c[_uc1_len] = 0;
                                tree->append_text(u8c, _uc1_len + 1);
                            }
    
                            jts.open_instr();
                            if (jts.c != '\') {
                                _Off = jts.index;
                                jts.index--;
                                break;
                            }
    
                            jts.close_instr(JSON_SYNTAX::_T_ESCAPE_TYPE);
                            jtsnext();
                            if (jts.c != 'u') {
                                _Off = jts.index - 1;
                                jts.index -= 2;
                                break;
                            }
                        }
                    }
                    else {
                        switch (jts.c)
                        {
                        case '\':
                            tree->append_char('\');
                            break;
                        case 'n':
                            tree->append_char('
    ');
                            break;
                        case 'r':
                            tree->append_char('
    ');
                            break;
                        case 't':
                            tree->append_char('	');
                            break;
                        case 'b':
                            tree->append_char('');
                            break;
                        case 'f':
                            tree->append_char('f');
                            break;
                        case '/':
                            tree->append_char('/');
                            break;
                        }
    
                        _Off = jts.index;
                    }
    
                    jts.open_instr(); //继续放飞自我
                }
    
                void j_text(bool isname = false) {
                    jsize_t pos = jts.index;
                    auto f = jts.open_instr();//字符串里的东西就开始放飞自我了,允许所有,除了不能换行
                    jsize_t text_off = (jsize_t)-1;
                    jsize_t text_len = 0;
    
                    for (;;)
                    {
                        jtsnext();
                        if (jts.c == '\') {
                            j_ec(pos, text_off);
                        }
                        else if (jts.c == '"') {
                            break;
                        }
                    }
    
                    jts.close_instr(f);
                    jsize_t len = jts.index - pos;
                    if (text_off == (jsize_t)-1)
                        text_off = tree->new_text(jts.text + pos, len);
                    else
                        tree->append_text(jts.text + pos, len);
    
    
                    if (isname)
                        name_off = text_off;
                    else
                        tree->new_var_string(cur, name_off, text_off);
                }
    
    
                void j_number() {
                    //考虑到可能会传入常量字符串到json解析,所以,在不拷贝源字符串,不能修改源字符串的情况下,只有自己实现数字转换的代码,这里统一使用浮点类型进行计算
    
                    /*
                    有一点没有遵循标准,标准对于数字前的多个0是不允许的,
                    但是它允许了-0  -0.00000000000 0e00000000000 之类的这些同样无意义的东西存在
                    而我没有判断这一点,因为我觉得这会带来额外的性能损失,也会使这段代码变得更为复杂,
                    我认为这一点,不管这些无意义的0在哪,由程序员自行控制它,
                    只约束头部,不管中间,尾巴的做法,除了降低性能,没有什么实际意义。
                    */
                    unsigned int myf;
                    long double _Number = 0;
                    long double factor;
                    bool neg = false;
                    if (jts.c == '-') {
                        neg = true;
                        jts.set_flags(JSON_SYNTAX::_T_NUMBER);
                        jtsnext();
                        myf = JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_E | JSON_SYNTAX::_T_DECIMAL |
                            JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT;
                        jts.set_flags(myf);
                    }
                    else
                    {
                        myf = JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_E | JSON_SYNTAX::_T_DECIMAL |
                            JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT;
                        jts.set_flags(myf);
                    }
    
                    do { //整数部分
                        _Number = _Number * 10 + (jts.c - '0');
                        jtsnext();
                    } while (jts.s & JSON_SYNTAX::_T_NUMBER);
    
                    if (jts.c == '.') {
                        //小数点之后的数字
                        factor = 1.0;
                        jts.set_flags(JSON_SYNTAX::_T_NUMBER);
                        jtsnext();
                        myf ^= JSON_SYNTAX::_T_DECIMAL;//之后不再允许小数点
                        jts.set_flags(myf);
    
                        do {
                            factor *= 0.1;
                            _Number += (jts.c - '0') * factor;
                            jtsnext();
                        } while (jts.s & JSON_SYNTAX::_T_NUMBER);
                    }
    
                    if ((jts.c | 32) == 'e') {
                        //科学计数的处理
                        unsigned int expo = 0;//指数
                        factor = 10.0;//因数
                        //e之后,必须是+-或者数字,如果是+-,那么后面必须是一个数字
                        //这里是json唯一允许+号出现的地方
                        jts.set_flags(JSON_SYNTAX::_T_NUMBER | JSON_SYNTAX::_T_NEGATIVE | JSON_SYNTAX::_T_POSITIVE);
                        jtsnext();
                        if (jts.c == '-') {
                            jts.set_flags(JSON_SYNTAX::_T_NUMBER);
                            jtsnext();
                            factor = 0.1;
                        }
                        else if (jts.c == '+') {
                            jts.set_flags(JSON_SYNTAX::_T_NUMBER);
                            jtsnext();
                        }
    
                        jts.set_flags(JSON_SYNTAX::_T_NUMBER |
                            JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_GROUP_END | JSON_SYNTAX::_T_NEXT);
                        do {
                            expo = 10 * expo + (jts.c - '0');
                            jtsnext();
                        } while (jts.s & JSON_SYNTAX::_T_NUMBER);
    
                        for (;;) {
                            //根据指数计算因数的快速求幂的方法
                            if (expo & 1)
                                _Number *= factor;
                            if ((expo >>= 1) == 0)
                                break;
                            factor *= factor;
                        }
                    }
    
                    if (!(jts.s & JSON_SYNTAX::_T_SPACE))//非空白字符时,倒退到上一个字符,由此处判断一下会由微小的性能提升,毕竟一次jtsnext()的代价更高一些
                        --jts.index;
                    tree->new_var_number(cur, name_off, (jnumber_t)(neg ? -_Number : _Number));
                }
    
                void j_true() {
                    jts.set_flags(JSON_SYNTAX::_T_BOOL);
                    for (int i = 0; i < 3; i++) {
                        jtsnext();
                        if ("rue"[i] != jts.c) {
                            err_pos = jts.index - 1;
                            longjmp(_Rem, -1);
                        }
                    }
                    tree->new_var_boolean(cur, name_off, true);
                }
    
                void j_false() {
                    jts.set_flags(JSON_SYNTAX::_T_BOOL);
                    for (int i = 0; i < 4; i++) {
                        jtsnext();
                        if ("alse"[i] != jts.c) {
                            err_pos = jts.index - 1;
                            longjmp(_Rem, -1);
                        }
                    }
                    tree->new_var_boolean(cur, name_off, false);
                }
    
                void j_null() {
                    jts.set_flags(JSON_SYNTAX::_T_NULL);
                    for (int i = 0; i < 3; i++) {
                        jtsnext();
                        if ("ull"[i] != jts.c) {
                            err_pos = jts.index - 1;
                            longjmp(_Rem, -1);
                        }
                    }
                    tree->new_var_null(cur, name_off);
                }
    
                void j_value() {
                    jts.set_flags(
                        JSON_SYNTAX::_T_SPACE |            // 空白字符
                        JSON_SYNTAX::_T_TEXT |            // "
                        JSON_SYNTAX::_T_OBJECT_BEGIN |        // {
                        JSON_SYNTAX::_T_GROUP_BEGIN |        // [
                        JSON_SYNTAX::_T_NUMBER |            // 0-9
                        JSON_SYNTAX::_T_NEGATIVE |            // -负号
                        JSON_SYNTAX::_T_BOOL_BEGIN |        // true false开头
                        JSON_SYNTAX::_T_NULL_BEGIN
                    );
    
                    bool ok = false;
                    do { jtsnext(); } while (jts.s & JSON_SYNTAX::_T_SPACE);
    
                    switch (jts.c) {
                    case '"':
                        j_text();
                        break;
                    case '{':
                        j_object();
                        break;
                    case '[':
                        j_group();
                        break;
                    case '-':
                        j_number();
                        break;
                    case 't':
                        j_true();
                        break;
                    case 'f':
                        j_false();
                        break;
                    case 'n':
                        j_null();
                        break;
                    default:
                        if (jts.s & JSON_SYNTAX::_T_NUMBER) {
                            j_number();
                            break;
                        }
                        break;
                    }
                }
    
                void j_group() {
                    // [ 之后,允许空白字符,"{0-9] true false null
                    auto f = jts.set_flags(
                        JSON_SYNTAX::_T_SPACE |            // 空白字符
                        JSON_SYNTAX::_T_TEXT |            // "
                        JSON_SYNTAX::_T_OBJECT_BEGIN |        // {
                        JSON_SYNTAX::_T_GROUP_END |        // ]
                        JSON_SYNTAX::_T_NUMBER |            // 0-9
                        JSON_SYNTAX::_T_NEGATIVE |            // -负号
                        JSON_SYNTAX::_T_BOOL_BEGIN |        // t f
                        JSON_SYNTAX::_T_NULL_BEGIN |        // n
                        JSON_SYNTAX::_T_GROUP_BEGIN        // 在遇到[时就递归前进
                    );
    
                    auto _Node = cur;
                    cur = tree->new_node(cur, name_off, aqx::jsvt_group);
                    bool ok = false;
    
                    do {
                        jtsnext();
    
                        switch (jts.c) {
                        case '"':
                            j_text();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case '{':
                            j_object();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case '[':
                            j_group();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case '-':
                            j_number();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case 't':
                            j_true();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case 'f':
                            j_false();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case 'n':
                            j_null();
                            jts.set_flags(JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_NEXT | JSON_SYNTAX::_T_GROUP_END);
                            break;
                        case ']':
                            ok = true;
                            break;
                        case ',':
                            jts.set_flags(
                                JSON_SYNTAX::_T_SPACE |            // 空白字符
                                JSON_SYNTAX::_T_TEXT |            // "
                                JSON_SYNTAX::_T_OBJECT_BEGIN |        // {
                                JSON_SYNTAX::_T_NUMBER |            // 0-9
                                JSON_SYNTAX::_T_NEGATIVE |            // -负号
                                JSON_SYNTAX::_T_BOOL_BEGIN |        // t f
                                JSON_SYNTAX::_T_NULL_BEGIN |        // n
                                JSON_SYNTAX::_T_GROUP_BEGIN        // 在遇到[时就递归前进
                            );
                            break;
                        default:
                            if (jts.s & JSON_SYNTAX::_T_NUMBER) {
                                j_number();
                                break;
                            }
                            break;
                        }
                    } while (!ok);
    
                    jts.set_flags(f);
                    cur = _Node;
                }
    
                void j_object() {
                    auto _Node = cur;
                    cur = tree->new_node(cur, name_off, aqx::jsvt_object);
                    auto f = jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END);
                    bool ok = false;
                    do {
                        jtsnext();
                        switch (jts.c) {
                        case '"':
                            j_text(true);
                            //名称字符串结束后,只允许 : 和 空白字符
                            jts.set_flags(JSON_SYNTAX::_T_VALUE | JSON_SYNTAX::_T_SPACE);
                            break;
                        case ':':
                            j_value();
                            jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE | JSON_SYNTAX::_T_OBJECT_END | JSON_SYNTAX::_T_NEXT);
                            break;
                        case ',':
                            // 碰到逗号时,新的一轮开始,但此时不再允许花括号,也就是不允许{"a":1,}这样的
                            jts.set_flags(JSON_SYNTAX::_T_TEXT | JSON_SYNTAX::_T_SPACE);
                            break;
                        case '}':
                            ok = true;
                            break;
                        }
                    } while (!ok);
                    cur = _Node;
                }
    
                int j_root(bool _MultiRoot) {
                    if (setjmp(_Rem)) {
                        tree->clear();
                        return -1;
                    }
    
                    root = tree->new_root();
                    cur = root;
                    name_off = _jnf;
                    err_pos = 0;
                    jts.set_flags(JSON_SYNTAX::_T_OBJECT_BEGIN | JSON_SYNTAX::_T_GROUP_BEGIN | JSON_SYNTAX::_T_SPACE);
                    for (;;) {
                        jtsnext();
                        if (jts.c == '{') {
                            j_object();
                            break;
                        }
                        else if (jts.c == '[') {
                            j_group();
                            break;
                        }
                    }
    
                    if (!_MultiRoot) {
                        jts.open_instr();
                        for (;;) {
                            if (jts.index >= jts.size)
                                break;
    
                            char _Chr = jts.text[jts.index++];
                            if (!_Chr)
                                break;
    
                            if (!(json_char_state[(unsigned char)_Chr] & JSON_SYNTAX::_T_SPACE)) {
                                err_pos = jts.index - 1;
                                //tree->clear();
                                return -1;
                            }
                        }
                    }
                    return 0;
                }
    
            private:
                jmp_buf _Rem;
                _Ty jts;
                _json_tree *tree;
                jsize_t cur;
                jsize_t root;
                jsize_t name_off;
                jsize_t err_pos;
            };
    
        }
    
        using json_tree = aqx_internal::_json_tree;
    
        template<typename _Ty>
        using json_parser_t = aqx_internal::_json_parser<_Ty>;
    
        using jts_gbk = aqx_internal::_jts_gbk;
        using jts_utf8 = aqx_internal::_jts_utf8;
    
    }
    
    /*
    
    //我已经把代码移植到C去了,最终我还是又回到C++来使用它,因为。。。C的性能,反而不如C++,无论是vc还是gcc都是不如c++...
    //可能的原因是我对C的二进制优化的手法并不纯熟而导致的问题,完全照搬结构大概是不合理的做法,
    //不过我认为更多的可能性还是,C入栈的参数比C++要多而导致的。
    //毕竟,this指针总在cx si之间传,而C,要写入太多太多结构指针
    
    //下面这一串是构建字符状态表的代码
    
        int sztext[128];
        memset(sztext, 0, 512);
    
        sztext['"'] = aqx::aqx_internal::JSON_SYNTAX::_T_TEXT | aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext[':'] = aqx::aqx_internal::JSON_SYNTAX::_T_VALUE;
        sztext[','] = aqx::aqx_internal::JSON_SYNTAX::_T_NEXT;
        sztext['{'] = aqx::aqx_internal::JSON_SYNTAX::_T_OBJECT_BEGIN;
        sztext['}'] = aqx::aqx_internal::JSON_SYNTAX::_T_OBJECT_END;
        sztext['['] = aqx::aqx_internal::JSON_SYNTAX::_T_GROUP_BEGIN;
        sztext[']'] = aqx::aqx_internal::JSON_SYNTAX::_T_GROUP_END;
        sztext['\'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_BEGIN | aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['n'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['r'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['t'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['b'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['f'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['u'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['/'] = aqx::aqx_internal::JSON_SYNTAX::_T_ESCAPE_TYPE;
        sztext['
    '] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
        sztext['
    '] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
        sztext[' '] = aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
        sztext['	'] = aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
    
    
    
        for (size_t i = 0; i < strlen("0123456789"); i++)
            sztext["0123456789"[i]] = aqx::aqx_internal::JSON_SYNTAX::_T_NUMBER | aqx::aqx_internal::JSON_SYNTAX::_T_HEX;
        for (size_t i = 0; i < strlen("abcdefABCDEF"); i++)
            sztext["abcdefABCDEF"[i]] = aqx::aqx_internal::JSON_SYNTAX::_T_HEX;
    
        sztext['.'] = aqx::aqx_internal::JSON_SYNTAX::_T_DECIMAL;
    
        sztext['+'] = aqx::aqx_internal::JSON_SYNTAX::_T_POSITIVE;
        sztext['-'] = aqx::aqx_internal::JSON_SYNTAX::_T_NEGATIVE;
        sztext['e'] |= aqx::aqx_internal::JSON_SYNTAX::_T_E;
        sztext['E'] |= aqx::aqx_internal::JSON_SYNTAX::_T_E;
    
        sztext['t'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['t'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL_BEGIN;
        sztext['r'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['u'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['e'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['f'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['f'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL_BEGIN;
        sztext['a'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['l'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
        sztext['s'] |= aqx::aqx_internal::JSON_SYNTAX::_T_BOOL;
    
        sztext['n'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL_BEGIN;
        sztext['u'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL;
        sztext['l'] |= aqx::aqx_internal::JSON_SYNTAX::_T_NULL;
        for (int y = 0; y < 8; y++)
        {
            for (int x = 0; x < 16; x++)
            {
                printf("%d,", sztext[y * 16 + x]);
            }
    
            printf("
    ");
        }
    
        return 0;
    
    
    */

    封装给lua使用的库:

    //ljsonlib.h
    #pragma once
    #include "lua/lua.hpp"
    #include "aqx/json.h"
    
    class ljson_convert {
    public:
        ljson_convert(lua_State *_s, int ec);
        int table_to_json(int n);
        int json_to_table(const char *_Text, int _Len);
    
    private:
        friend int lua_table_to_json(lua_State *s);
        void json_to_object(aqx::jsize_t _Ref);
        void json_to_group(aqx::jsize_t _Ref);
        int ec_mode;
        aqx::json_tree jt;
        aqx::json_parser_t<aqx::jts_gbk> *pgbk;
        aqx::json_parser_t<aqx::jts_utf8> *putf8;
        lua_State *s;
        std::string b;
    };
    
    //_CharEncoding为字符编码格式,默认为"gbk",可以传入"utf8"
    ljson_convert *lua_openljsonlib(lua_State *s, const char *_CharEncoding = "");
    //ljsonlib.cpp
    #include "pch.h"
    #include "ljsonlib.h"
    
    #define lua_isintnum(_Number_) (_Number_ - floor(_Number_) < 1e-6)
    
    ljson_convert::ljson_convert(lua_State *_s, int ec) {
        s = _s;
        jt.reserve(0x1000, 0x400);
        b.reserve(0x1000);
        ec_mode = ec;
        if (!ec_mode)
            pgbk = new aqx::json_parser_t<aqx::jts_gbk>(jt);
        else
            putf8 = new aqx::json_parser_t<aqx::jts_utf8>(jt);
    }
    
    int ljson_convert::table_to_json(int n) {
        char sznum[128];
        lua_pushnil(s);
        int t = 0;
        if (!lua_next(s, n))
            return 0;
    
        switch (lua_type(s, -2)) {
        case LUA_TNUMBER:
            b += '[';
            t = 2;
            break;
        case LUA_TSTRING:
            b += "{"";
            b += lua_tostring(s, -2);
            b += "":";
            t = 1;
            break;
        default:
            lua_pop(s, 1);
            return -1;
        }
    
        switch (lua_type(s, -1)) {
        case LUA_TBOOLEAN:
            b += (lua_toboolean(s, -1) == 1) ? "true" : "false";
            break;
        case LUA_TNUMBER: {
            double dv = lua_tonumber(s, -1);
            if (lua_isintnum(dv))
                sprintf_s(sznum, 128, "%I64d", (long long)dv);
            else
                sprintf_s(sznum, 128, "%lf", dv);
            b += sznum;
            break;
        }
        case LUA_TSTRING:
            b += '"';
            b += lua_tostring(s, -1);
            b += '"';
            break;
        case LUA_TTABLE:
            if (table_to_json(-2)) {
                lua_pop(s, 1);
                return -1;
            }
            break;
        default:
            lua_pop(s, 1);
            return -1;
        }
    
        lua_pop(s, 1);
        while (lua_next(s, n)) {
    
            switch (lua_type(s, -2)) {
            case LUA_TNUMBER:
                b += ',';
                break;
            case LUA_TSTRING:
                b += ","";
                b += lua_tostring(s, -2);
                b += "":";
                break;
            default:
                lua_pop(s, 1);
                return -1;
            }
    
            switch (lua_type(s, -1)) {
            case LUA_TBOOLEAN:
                b += (lua_toboolean(s, -1) == 1) ? "true" : "false";
                break;
            case LUA_TNUMBER: {
                double dv = lua_tonumber(s, -1);
                if (lua_isintnum(dv))
                    sprintf_s(sznum, 128, "%I64d", (long long)dv);
                else
                    sprintf_s(sznum, 128, "%lf", dv);
                b += sznum;
                break;
            }
            case LUA_TSTRING:
                b += '"';
                b += lua_tostring(s, -1);
                b += '"';
                break;
            case LUA_TTABLE:
                if (table_to_json(-2)) {
                    lua_pop(s, 1);
                    return -1;
                }
                break;
            default:
                lua_pop(s, 1);
                return -1;
            }
    
            lua_pop(s, 1);
    
        }
    
        b += t == 1 ? '}' : ']';
        return 0;
    }
        
    int ljson_convert::json_to_table(const char *_Text, int _Len) {
        if (!ec_mode)
        {
            if (!pgbk->load_string(_Text, _Len, true)) {
                return -1;
            }
        }
        else
        {
            if (!putf8->load_string(_Text, _Len, true))
                return -1;
        }
    
        auto root = jt.get_root();
        if (!root)
            return -1;
        json_to_object(root->begin());
        return 0;
    }
    
    void ljson_convert::json_to_object(aqx::jsize_t _Ref) {
        for (auto v = jt.get_val(_Ref); v != nullptr; v = v->next(jt)) {
            switch (v->type()) {
            case aqx::jsvt_null:
                lua_pushstring(s, v->skey(jt));
                lua_pushnil(s);
                lua_settable(s, -3);
                break;
            case aqx::jsvt_string:
                lua_pushstring(s, v->skey(jt));
                lua_pushstring(s, v->tostring(jt));
                lua_settable(s, -3);
                break;
            case aqx::jsvt_number:
            {
                lua_pushstring(s, v->skey(jt));
                double dv = v->tonumber();
                if (lua_isintnum(dv))
                    lua_pushinteger(s, (intptr_t)dv);
                else
                    lua_pushnumber(s, dv);
                lua_settable(s, -3);
                break;
            }
            case aqx::jsvt_boolean:
                lua_pushstring(s, v->skey(jt));
                lua_pushboolean(s, v->toboolean());
                lua_settable(s, -3);
                break;
            case aqx::jsvt_object: {
                auto n = v->toobject(jt);
                if (!n->size())
                    break;
                lua_pushstring(s, v->skey(jt));
                lua_newtable(s);
                json_to_object(n->begin());
                lua_settable(s, -3);
                break;
            }
            case aqx::jsvt_group: {
                auto n = v->toobject(jt);
                if (!n->size()) {
                    break;
                }
                lua_pushstring(s, v->skey(jt));
                lua_newtable(s);
                json_to_group(n->begin());
                lua_settable(s, -3);
                break;
            }
            }
            
        }
    }
        
    void ljson_convert::json_to_group(aqx::jsize_t _Ref) {
        int i = 1;
        
        for (auto v = jt.get_val(_Ref); v != nullptr; v = v->next(jt)) {
            switch (v->type()) {
            case aqx::jsvt_null:
                lua_pushnil(s);
                lua_rawseti(s, -2, i++);
                break;
            case aqx::jsvt_string:
                lua_pushstring(s, v->tostring(jt));
                lua_rawseti(s, -2, i++);
                break;
            case aqx::jsvt_number: {
                double dv = v->tonumber();
                if (lua_isintnum(dv))
                    lua_pushinteger(s, (intptr_t)dv);
                else
                    lua_pushnumber(s, dv);
                lua_rawseti(s, -2, i++);
                break;
            }
            case aqx::jsvt_boolean:
                lua_pushboolean(s, v->toboolean());
                break;
            case aqx::jsvt_object: {
                auto n = v->toobject(jt);
                if (!n->size())
                    break;
                lua_newtable(s);
                json_to_object(n->begin());
                lua_rawseti(s, -2, i++);
                break;
            }
            case aqx::jsvt_group: {
                auto n = v->toobject(jt);
                if (!n->size())
                    break;
                lua_newtable(s);
                json_to_group(n->begin());
                lua_rawseti(s, -2, i++);
                break;
            }
            }
            
        }
    }
    
    ljson_convert *get_ljson_convert(lua_State *s) {
        lua_getglobal(s, "__ljsonlib_convert_");
        if (lua_isnil(s, -1)) 
            return nullptr;
        return (ljson_convert*)lua_touserdata(s, -1);
    }
    
    int lua_table_to_json(lua_State *s) 
    {
        ljson_convert *pjc = get_ljson_convert(s);
        if (!pjc)
            return 0;
        if (!lua_gettop(s))
            return 0;
        if (lua_type(s, 1) != LUA_TTABLE)
            return 0;
        pjc->b.clear();
        if (pjc->table_to_json(1)) {
            pjc->b.clear();
        }
        lua_pushstring(s, pjc->b.c_str());
        return 1;
    }
    
    int lua_table_from_json(lua_State *s) {
        ljson_convert *pjc = get_ljson_convert(s);
        if (!pjc)
            return 0;
        if (!lua_gettop(s))
            return 0;
        if (lua_type(s, 1) != LUA_TSTRING)
            return 0;
        lua_newtable(s);
        
        if (!pjc->json_to_table(lua_tostring(s, 1), -1)) {
            return 1;
        }
            
        
        lua_pop(s, 1);
        return 0;
    }
    
    ljson_convert *lua_openljsonlib(lua_State *s, const char *_CharEncoding)
    {
        ljson_convert *pjc = get_ljson_convert(s);
        if (pjc)return pjc;
        pjc = new ljson_convert(s, (strstr(_CharEncoding, "utf") == nullptr) ? 0 : 1);
        lua_pushlightuserdata(s, pjc);
        lua_setglobal(s, "__ljsonlib_convert_");
    
        lua_getglobal(s, "table");
        lua_pushcfunction(s, lua_table_to_json);
        lua_setfield(s, -2, "tojson");
    
        lua_pushcfunction(s, lua_table_from_json);
        lua_setfield(s, -2, "fromjson");
        
        return pjc;
    }
    // ConsoleApplication2.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
    //
    
    #include "pch.h"
    #include <thread>
    #include <iostream>
    #pragma comment(lib, "lua54.lib")
    #include "lxsharelib.h"
    #include "ljsonlib.h"
    int main(int argc, char **argv)
    {
        lua_State *s = luaL_newstate();
        luaL_openlibs(s);
    
        //使用这个接口,向lua本身的table对象中,添加两个函数table.tojson和table.fromjson
        auto p = lua_openljsonlib(s, "");//第2个参数可以传入"utf8"来应对utf8的lua文件,默认的情况下是gbk
        if (luaL_dofile(s, "G:\vs2017\ConsoleApplication2\x64\Release\script\testjson.lua"))
            printf("%s
    ", lua_tostring(s, -1));
        lua_close(s);
        
        //用完之后,需要自己释放掉内存,这个问题没什么好办法解决,除非扩展到lua源码中,或者给lua_close实现回调
        delete p;
    
        return 0;
    }

    测试脚本代码:

    -- testjson.lua
    
    local t = {
        x = 3.14159,
        y = 2,
        z = {10,20,30,40,50}
    };
    
    
    local json_text = table.tojson(t);
    print(json_text);--{"z":[10,20,30,40,50],"y":2,"x":3.141590}
    
    local t2 = table.fromjson('{"a":1.21e-3,"b":2,"c":[3,4,5,6,7,"abcde"],"d":[]}');
    
    print(t2)
    --[[
        b:2
        a:0.00121
        c:table: 000001C74BABABE0
    ]]
    for i, e in pairs(t2) do
        print(i..':'..tostring(e));
    end
    
    
    --[[
        1:3
        2:4
        3:5
        4:6
        5:7
        6:abcde
    ]]
    for i, e in ipairs(t2.c) do
        print(i..':'..e);
    end

    {"y":2,"x":3.141590,"z":[10,20,30,40,50]}
    table: 0000025A15D5EFC0
    a:0.00121
    c:table: 0000025A15D7A340
    b:2
    1:3
    2:4
    3:5
    4:6
    5:7
    6:abcde

  • 相关阅读:
    Mysql之binlog日志说明及利用binlog日志恢复数据操作记录
    JS使用Cookie
    vue2 生命周期
    vue2 手记
    vue2 design 手记
    composer.json详解
    mysql查询优化
    dockerfile
    一套不错的docker lnmp
    服务器部署docker lnmp环境
  • 原文地址:https://www.cnblogs.com/babypapa/p/11723775.html
Copyright © 2020-2023  润新知