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

烂漫一生 提交于 2020-08-14 16:32:02

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

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个空白字符" \t\r\n"
            static constexpr auto _T_ENDL{ static_cast<unsigned int>(0x40) };                    // 2个换行符"\r\n"
            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("\n");*/
                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('\n');
                        break;
                    case 'r':
                        tree->append_char('\r');
                        break;
                    case 't':
                        tree->append_char('\t');
                        break;
                    case 'b':
                        tree->append_char('\b');
                        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['\n'] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
    sztext['\r'] = aqx::aqx_internal::JSON_SYNTAX::_T_ENDL | aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
    sztext[' '] = aqx::aqx_internal::JSON_SYNTAX::_T_SPACE;
    sztext['\t'] = 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("\n");
    }

    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\n", 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









 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!