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个空白字符" \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
lua table与json的之间的互相转换高性能c++实现的更多相关文章
- cocos2d-x lua table与json的转换
cocos2d-x lua table与json的转换 version: cocos2d-x 3.6 1.引入json库 require("src/cocos/cocos2d/json&qu ...
- 前端页面使用 Json对象与Json字符串之间的互相转换
前言 在前端页面很多时候都会用到Json这种格式的数据,最近没有前端,后端的我也要什么都要搞,对于Json对象与Json字符串之间的转换终于摸清楚了几种方式,归纳如下! 一:Json对象转换为json ...
- 我为什么要再给lua写一个json模块
最近要给自己编写的服务器加上json解析模块.根据我当前的项目,可以预测服务器中使用json的地方: 通信.由于与客户端通信使用google protocolbuffer,仅在与SDK通信中使用jso ...
- 高并发 Nginx+Lua OpenResty系列(7)——Lua开发库json
JSON库 在进行数据传输时JSON格式目前应用广泛,因此从Lua对象与JSON字符串之间相互转换是一个非常常见的功能:目前Lua也有几个JSON库,如:cjson.dkjson.其中cjson的语法 ...
- Json——使用Json jar包实现Json字符串与Java对象或集合之间的互相转换
总结一下利用Json相关jar包实现Java对象和集合与Json字符串之间的互相转换: 1.创建的User类: package com.ghj.packageofdomain; public clas ...
- cocos2d-x lua table数据存储
cocos2d-x lua table数据存储 version: cocos2d-x 3.6 1. 将table转为json http://blog.csdn.net/songcf_faith/art ...
- Lua 数据类型和 Redis 数据类型之间转换
当 Lua 通过 call() 或 pcall() 函数执行 Redis 命令的时候,命令的返回值会被转换成 Lua 数据结构. 同样地,当 Lua 脚本在 Redis 内置的解释器里运行时,Lua ...
- lua table integer index 特性
table.maxn (table) Returns the largest positive numerical index of the given table, or zero if the t ...
- 树形打印lua table表
为方便调试lua程序,往往想以树的形式打印出一个table,以观其表内数据.以下罗列了三种种关于树形打印lua table的方法;法一 local print = print local tconca ...
随机推荐
- 「总结」$dp1$
大概就是做点题. 先列一下要做的题目列表,从\(UOJ\)上找的. 129寿司晚宴 348州区划分 370滑稽树上滑稽果 457数树 22外星人 37主旋律 300吉夫特 196线段树 311积劳成疾 ...
- Linux零基础之shell基础编程入门
从程序员的角度来看, Shell本身是一种用C语言编写的程序,从用户的角度来看,Shell是用户与Linux操作系统沟通的桥梁.用户既可以输入命令执行,又可以利用 Shell脚本编程,完成更加复杂的操 ...
- 页表 Page tables
逻辑地址与物理地址的转化 页表是由页表项(PTE)组成的数组.512个PTE构成一个页表页(Page-table page). PTE中包含了物理页码(PPN physical page number ...
- 你知道怎么使用Google两步验证保护账户安全吗?
目录 为什么我们需要使用它? 对有些人来说,盗取密码比您想象的更简单 什么是Google两步验证? 多一道安全防线 什么是Google Authenticator ? 使用Google两步验证的好处 ...
- cf13B Letter A(分类+简单计算几何,,)
题意: 给三个线段(每个线段的两个端点的坐标),问这三个线段能否组成字母A. 组成字母A的条件: 1.两个线段有公共端点. 2.这两个线段夹角小于等于90度. 3.第三个线段的两个端点分别在这两个线段 ...
- 微服务(七)Gateway服务网关
1 为什么要有网关 权限控制:网关作为微服务入口,需要校验用户是是否有请求资格,如果没有则进行拦截. 路由和负载均衡:一切请求都必须先经过gateway,但网关不处理业务,而是根据某种规则,把请求转发 ...
- Linux ps -ef 命令输出解释
UID: 程序拥有者PID:程序的 IDPPID:程序父级程序的 IDC: CPU 使用的百分比STIME: 程序的启动时间TTY: 登录终端TIME : 程序使用掉 CPU 的时间CMD: 下达的 ...
- centos 7 安装nfs 实现主机目录共享
多台服务器之间共享目录,实现每个服务器进入目录看到的内容都一样 服务器A 服务器B 1.服务器A和服务器B,安装 nfs-utils和rpcbind #yum install -y nfs-utils ...
- Linux ns 3. Mnt Namespace 详解
1. 文件系统层次化 对 Linux 系统来说一切皆文件,Linux 使用树形的层次化结构来管理所有的文件对象. 完整的Linux文件系统,是由多种设备.多种文件系统组成的一个混合的树形结构.我们首先 ...
- adduser vs useradd
Always use adduser (and deluser when deleting users) when you're creating new users from the command ...