snapshot before regression test
This commit is contained in:
237
includes/json/__init__.py
Normal file
237
includes/json/__init__.py
Normal file
@@ -0,0 +1,237 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
import viperio
|
||||
|
||||
# ============================================================
|
||||
# JSON 值类型枚举
|
||||
# ============================================================
|
||||
JSON_NULL: t.CDefine = 0
|
||||
JSON_BOOL: t.CDefine = 1
|
||||
JSON_INT: t.CDefine = 2
|
||||
JSON_FLOAT: t.CDefine = 3
|
||||
JSON_STRING: t.CDefine = 4
|
||||
JSON_ARRAY: t.CDefine = 5
|
||||
JSON_OBJECT: t.CDefine = 6
|
||||
|
||||
|
||||
# ============================================================
|
||||
# JsonValue - JSON 值节点
|
||||
# 使用 mpool 分配:JsonValue(pool) 从池中分配内存
|
||||
# ============================================================
|
||||
class JsonValue:
|
||||
vtype: t.CInt
|
||||
bool_val: t.CInt
|
||||
int_val: t.CInt64T
|
||||
float_val: t.CDouble
|
||||
str_val: t.CChar | t.CPtr
|
||||
next: 'JsonValue' | t.CPtr
|
||||
key: t.CChar | t.CPtr
|
||||
child: 'JsonValue' | t.CPtr
|
||||
child_count: t.CSizeT
|
||||
|
||||
def __new__(self, pool: memhub.MemManager | t.CPtr):
|
||||
"""从 mpool 分配 JsonValue 结构体内存并零初始化"""
|
||||
ptr: JsonValue | t.CPtr = pool.alloc(JsonValue.__sizeof__())
|
||||
if ptr:
|
||||
string.memset(ptr, 0, JsonValue.__sizeof__())
|
||||
return ptr
|
||||
|
||||
def type(self) -> t.CInt:
|
||||
return self.vtype
|
||||
|
||||
def is_null(self) -> bool:
|
||||
return self.vtype == JSON_NULL
|
||||
|
||||
def is_bool(self) -> bool:
|
||||
return self.vtype == JSON_BOOL
|
||||
|
||||
def is_int(self) -> bool:
|
||||
return self.vtype == JSON_INT
|
||||
|
||||
def is_float(self) -> bool:
|
||||
return self.vtype == JSON_FLOAT
|
||||
|
||||
def is_string(self) -> bool:
|
||||
return self.vtype == JSON_STRING
|
||||
|
||||
def is_array(self) -> bool:
|
||||
return self.vtype == JSON_ARRAY
|
||||
|
||||
def is_object(self) -> bool:
|
||||
return self.vtype == JSON_OBJECT
|
||||
|
||||
def as_bool(self) -> bool:
|
||||
return self.bool_val != 0
|
||||
|
||||
def as_int(self) -> t.CInt64T:
|
||||
return self.int_val
|
||||
|
||||
def as_float(self) -> t.CDouble:
|
||||
return self.float_val
|
||||
|
||||
def as_string(self) -> t.CChar | t.CPtr:
|
||||
return self.str_val
|
||||
|
||||
def __len__(self) -> t.CSizeT:
|
||||
return self.child_count
|
||||
|
||||
def __getitem__(self, key: t.CChar | t.CPtr) -> 'JsonValue' | t.CPtr:
|
||||
"""Python风格取值:v["key"] 取对象字段"""
|
||||
if self.vtype != JSON_OBJECT:
|
||||
return None
|
||||
if key == None:
|
||||
return None
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
return cur
|
||||
cur = cur.next
|
||||
return None
|
||||
|
||||
def __setitem__(self, key: t.CChar | t.CPtr, val: 'JsonValue' | t.CPtr):
|
||||
"""Python风格赋值:v["key"] = val"""
|
||||
if self.vtype != JSON_OBJECT or key == None or val == None:
|
||||
return
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
cur.vtype = val.vtype
|
||||
cur.bool_val = val.bool_val
|
||||
cur.int_val = val.int_val
|
||||
cur.float_val = val.float_val
|
||||
cur.str_val = val.str_val
|
||||
cur.child = val.child
|
||||
cur.child_count = val.child_count
|
||||
return
|
||||
cur = cur.next
|
||||
# key 不存在,追加新子节点
|
||||
klen: t.CSizeT = string.strlen(key)
|
||||
kbuf: t.CChar | t.CPtr = self._pool_alloc(klen + 1)
|
||||
if kbuf != None:
|
||||
string.memcpy(kbuf, key, klen + 1)
|
||||
val.key = kbuf
|
||||
self._append_child(val)
|
||||
|
||||
def get_item(self, index: t.CSizeT) -> 'JsonValue' | t.CPtr:
|
||||
"""按索引取数组元素:v.get_item(0)"""
|
||||
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
|
||||
return None
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
i: t.CSizeT = 0
|
||||
while cur != None:
|
||||
if i == index:
|
||||
return cur
|
||||
cur = cur.next
|
||||
i += 1
|
||||
return None
|
||||
|
||||
def _pool_alloc(self, size: t.CSizeT) -> t.CChar | t.CPtr:
|
||||
"""内部方法:从当前对象的 mpool 分配内存(预留,暂返回 None)"""
|
||||
return None
|
||||
|
||||
def _append_child(self, child: 'JsonValue' | t.CPtr):
|
||||
if self.child == None:
|
||||
self.child = child
|
||||
else:
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
while cur.next != None:
|
||||
cur = cur.next
|
||||
cur.next = child
|
||||
self.child_count += 1
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 构造函数:创建各类 JsonValue(从 mpool 分配)
|
||||
# ============================================================
|
||||
|
||||
def null(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_NULL
|
||||
return v
|
||||
|
||||
def bool_val(pool: memhub.MemManager | t.CPtr, val: bool) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_BOOL
|
||||
v.bool_val = 1 if val else 0
|
||||
return v
|
||||
|
||||
def int_val(pool: memhub.MemManager | t.CPtr, val: t.CInt64T) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_INT
|
||||
v.int_val = val
|
||||
return v
|
||||
|
||||
def float_val(pool: memhub.MemManager | t.CPtr, val: t.CDouble) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_FLOAT
|
||||
v.float_val = val
|
||||
return v
|
||||
|
||||
def string_val(pool: memhub.MemManager | t.CPtr, val: t.CChar | t.CPtr) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_STRING
|
||||
if val != None:
|
||||
slen: t.CSizeT = string.strlen(val)
|
||||
buf: t.CChar | t.CPtr = pool.alloc(slen + 1)
|
||||
if buf != None:
|
||||
string.memcpy(buf, val, slen + 1)
|
||||
v.str_val = buf
|
||||
return v
|
||||
|
||||
def array(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_ARRAY
|
||||
return v
|
||||
|
||||
def object(pool: memhub.MemManager | t.CPtr) -> JsonValue | t.CPtr:
|
||||
v: JsonValue | t.CPtr = JsonValue(pool)
|
||||
if v == None: return None
|
||||
v.vtype = JSON_OBJECT
|
||||
return v
|
||||
|
||||
# 向数组追加元素
|
||||
def array_append(pool: memhub.MemManager | t.CPtr, arr: JsonValue | t.CPtr, item: JsonValue | t.CPtr):
|
||||
if arr == None or item == None: return
|
||||
if arr.vtype != JSON_ARRAY: return
|
||||
arr._append_child(item)
|
||||
|
||||
# 向对象设置键值对
|
||||
def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t.CChar | t.CPtr, val: JsonValue | t.CPtr):
|
||||
if obj == None or key == None or val == None: return
|
||||
if obj.vtype != JSON_OBJECT: return
|
||||
cur: JsonValue | t.CPtr = obj.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
cur.vtype = val.vtype
|
||||
cur.bool_val = val.bool_val
|
||||
cur.int_val = val.int_val
|
||||
cur.float_val = val.float_val
|
||||
cur.str_val = val.str_val
|
||||
cur.child = val.child
|
||||
cur.child_count = val.child_count
|
||||
return
|
||||
cur = cur.next
|
||||
klen: t.CSizeT = string.strlen(key)
|
||||
kbuf: t.CChar | t.CPtr = pool.alloc(klen + 1)
|
||||
if kbuf != None:
|
||||
string.memcpy(kbuf, key, klen + 1)
|
||||
val.key = kbuf
|
||||
obj._append_child(val)
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 导入子模块
|
||||
# ============================================================
|
||||
from .__parser import parse
|
||||
from .__writer import write
|
||||
291
includes/json/__parser.py
Normal file
291
includes/json/__parser.py
Normal file
@@ -0,0 +1,291 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from . import (
|
||||
JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT,
|
||||
JSON_STRING, JSON_ARRAY, JSON_OBJECT,
|
||||
null, bool_val, int_val, float_val, string_val, array, object,
|
||||
)
|
||||
|
||||
|
||||
class ParseState:
|
||||
src: t.CChar | t.CPtr
|
||||
pos: t.CSizeT
|
||||
len: t.CSizeT
|
||||
pool: memhub.MemManager | t.CPtr
|
||||
|
||||
def __init__(self, src: t.CChar | t.CPtr, pool: memhub.MemManager | t.CPtr):
|
||||
self.src = src
|
||||
self.pos = 0
|
||||
self.len = string.strlen(src) if src != None else 0
|
||||
self.pool = pool
|
||||
|
||||
|
||||
def _peek(s: ParseState | t.CPtr) -> t.CChar:
|
||||
if s.pos >= s.len:
|
||||
return '\0'
|
||||
return s.src[s.pos]
|
||||
|
||||
def _advance(s: ParseState | t.CPtr) -> t.CChar:
|
||||
if s.pos >= s.len:
|
||||
return '\0'
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
s.pos += 1
|
||||
return ch
|
||||
|
||||
def _skip_whitespace(s: ParseState | t.CPtr):
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch == ' ' or ch == '\t' or ch == '\n' or ch == '\r':
|
||||
s.pos += 1
|
||||
else:
|
||||
break
|
||||
|
||||
def _expect(s: ParseState | t.CPtr, ch: t.CChar) -> bool:
|
||||
_skip_whitespace(s)
|
||||
if s.pos >= s.len:
|
||||
return False
|
||||
if s.src[s.pos] != ch:
|
||||
return False
|
||||
s.pos += 1
|
||||
return True
|
||||
|
||||
|
||||
def _parse_string(s: ParseState | t.CPtr) -> t.CChar | t.CPtr:
|
||||
if _peek(s) != '"':
|
||||
return None
|
||||
_advance(s)
|
||||
|
||||
start: t.CSizeT = s.pos
|
||||
slen: t.CSizeT = 0
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch == '"':
|
||||
break
|
||||
if ch == '\\':
|
||||
s.pos += 1
|
||||
slen += 1
|
||||
slen += 1
|
||||
s.pos += 1
|
||||
|
||||
buf: t.CChar | t.CPtr = s.pool.alloc(slen + 1)
|
||||
if buf == None:
|
||||
return None
|
||||
|
||||
s.pos = start
|
||||
di: t.CSizeT = 0
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch == '"':
|
||||
s.pos += 1
|
||||
break
|
||||
if ch == '\\':
|
||||
s.pos += 1
|
||||
if s.pos < s.len:
|
||||
esc: t.CChar = s.src[s.pos]
|
||||
if esc == 'n':
|
||||
buf[di] = '\n'
|
||||
elif esc == 't':
|
||||
buf[di] = '\t'
|
||||
elif esc == 'r':
|
||||
buf[di] = '\r'
|
||||
elif esc == '\\':
|
||||
buf[di] = '\\'
|
||||
elif esc == '"':
|
||||
buf[di] = '"'
|
||||
elif esc == '/':
|
||||
buf[di] = '/'
|
||||
else:
|
||||
buf[di] = esc
|
||||
di += 1
|
||||
s.pos += 1
|
||||
continue
|
||||
buf[di] = ch
|
||||
di += 1
|
||||
s.pos += 1
|
||||
|
||||
buf[di] = '\0'
|
||||
return buf
|
||||
|
||||
|
||||
def _parse_number(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
||||
_skip_whitespace(s)
|
||||
is_float: bool = False
|
||||
start: t.CSizeT = s.pos
|
||||
|
||||
if s.pos < s.len and s.src[s.pos] == '-':
|
||||
s.pos += 1
|
||||
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch >= '0' and ch <= '9':
|
||||
s.pos += 1
|
||||
else:
|
||||
break
|
||||
|
||||
if s.pos < s.len and s.src[s.pos] == '.':
|
||||
is_float = True
|
||||
s.pos += 1
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch >= '0' and ch <= '9':
|
||||
s.pos += 1
|
||||
else:
|
||||
break
|
||||
|
||||
if s.pos < s.len and (s.src[s.pos] == 'e' or s.src[s.pos] == 'E'):
|
||||
is_float = True
|
||||
s.pos += 1
|
||||
if s.pos < s.len and (s.src[s.pos] == '+' or s.src[s.pos] == '-'):
|
||||
s.pos += 1
|
||||
while s.pos < s.len:
|
||||
ch: t.CChar = s.src[s.pos]
|
||||
if ch >= '0' and ch <= '9':
|
||||
s.pos += 1
|
||||
else:
|
||||
break
|
||||
|
||||
num_len: t.CSizeT = s.pos - start
|
||||
buf: t.CChar | t.CPtr = s.pool.alloc(num_len + 1)
|
||||
if buf == None:
|
||||
return null(s.pool)
|
||||
|
||||
i: t.CSizeT = 0
|
||||
while i < num_len:
|
||||
buf[i] = s.src[start + i]
|
||||
i += 1
|
||||
buf[num_len] = '\0'
|
||||
|
||||
if is_float:
|
||||
val: t.CDouble = string.atof(buf)
|
||||
return float_val(s.pool, val)
|
||||
else:
|
||||
ival: t.CInt64T = string.atoll(buf)
|
||||
return int_val(s.pool, ival)
|
||||
|
||||
|
||||
def _parse_value(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
||||
_skip_whitespace(s)
|
||||
if s.pos >= s.len:
|
||||
return null(s.pool)
|
||||
|
||||
ch: t.CChar = _peek(s)
|
||||
|
||||
if ch == '"':
|
||||
sv: t.CChar | t.CPtr = _parse_string(s)
|
||||
return string_val(s.pool, sv)
|
||||
|
||||
if ch == '{':
|
||||
return _parse_object(s)
|
||||
|
||||
if ch == '[':
|
||||
return _parse_array(s)
|
||||
|
||||
if ch == '-' or (ch >= '0' and ch <= '9'):
|
||||
return _parse_number(s)
|
||||
|
||||
if ch == 't':
|
||||
if s.pos + 3 < s.len:
|
||||
if s.src[s.pos + 1] == 'r' and s.src[s.pos + 2] == 'u' and s.src[s.pos + 3] == 'e':
|
||||
s.pos += 4
|
||||
return bool_val(s.pool, True)
|
||||
return null(s.pool)
|
||||
|
||||
if ch == 'f':
|
||||
if s.pos + 4 < s.len:
|
||||
if s.src[s.pos + 1] == 'a' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 's' and s.src[s.pos + 4] == 'e':
|
||||
s.pos += 5
|
||||
return bool_val(s.pool, False)
|
||||
return null(s.pool)
|
||||
|
||||
if ch == 'n':
|
||||
if s.pos + 3 < s.len:
|
||||
if s.src[s.pos + 1] == 'u' and s.src[s.pos + 2] == 'l' and s.src[s.pos + 3] == 'l':
|
||||
s.pos += 4
|
||||
return null(s.pool)
|
||||
return null(s.pool)
|
||||
|
||||
return null(s.pool)
|
||||
|
||||
|
||||
def _parse_array(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
||||
if not _expect(s, '['):
|
||||
return null(s.pool)
|
||||
|
||||
arr: JsonValue | t.CPtr = array(s.pool)
|
||||
|
||||
_skip_whitespace(s)
|
||||
if s.pos < s.len and _peek(s) == ']':
|
||||
_advance(s)
|
||||
return arr
|
||||
|
||||
item: JsonValue | t.CPtr = _parse_value(s)
|
||||
arr._append_child(item)
|
||||
|
||||
while True:
|
||||
_skip_whitespace(s)
|
||||
if s.pos >= s.len:
|
||||
break
|
||||
if _peek(s) != ',':
|
||||
break
|
||||
_advance(s)
|
||||
item = _parse_value(s)
|
||||
arr._append_child(item)
|
||||
|
||||
_expect(s, ']')
|
||||
return arr
|
||||
|
||||
|
||||
def _parse_object(s: ParseState | t.CPtr) -> JsonValue | t.CPtr:
|
||||
if not _expect(s, '{'):
|
||||
return null(s.pool)
|
||||
|
||||
obj: JsonValue | t.CPtr = object(s.pool)
|
||||
|
||||
_skip_whitespace(s)
|
||||
if s.pos < s.len and _peek(s) == '}':
|
||||
_advance(s)
|
||||
return obj
|
||||
|
||||
_skip_whitespace(s)
|
||||
key: t.CChar | t.CPtr = _parse_string(s)
|
||||
_expect(s, ':')
|
||||
val: JsonValue | t.CPtr = _parse_value(s)
|
||||
if key != None and val != None:
|
||||
klen: t.CSizeT = string.strlen(key)
|
||||
kbuf: t.CChar | t.CPtr = s.pool.alloc(klen + 1)
|
||||
if kbuf != None:
|
||||
string.memcpy(kbuf, key, klen + 1)
|
||||
val.key = kbuf
|
||||
obj._append_child(val)
|
||||
|
||||
while True:
|
||||
_skip_whitespace(s)
|
||||
if s.pos >= s.len:
|
||||
break
|
||||
if _peek(s) != ',':
|
||||
break
|
||||
_advance(s)
|
||||
_skip_whitespace(s)
|
||||
key = _parse_string(s)
|
||||
_expect(s, ':')
|
||||
val = _parse_value(s)
|
||||
if key != None and val != None:
|
||||
klen2: t.CSizeT = string.strlen(key)
|
||||
kbuf2: t.CChar | t.CPtr = s.pool.alloc(klen2 + 1)
|
||||
if kbuf2 != None:
|
||||
string.memcpy(kbuf2, key, klen2 + 1)
|
||||
val.key = kbuf2
|
||||
obj._append_child(val)
|
||||
|
||||
_expect(s, '}')
|
||||
return obj
|
||||
|
||||
|
||||
def parse(pool: memhub.MemManager | t.CPtr, src: t.CChar | t.CPtr) -> JsonValue | t.CPtr:
|
||||
"""解析 JSON 字符串,返回 JsonValue 树"""
|
||||
if src == None:
|
||||
return null(pool)
|
||||
s: ParseState | t.CPtr = ParseState(src, pool)
|
||||
return _parse_value(s)
|
||||
119
includes/json/__writer.py
Normal file
119
includes/json/__writer.py
Normal file
@@ -0,0 +1,119 @@
|
||||
import t, c
|
||||
from stdint import *
|
||||
import memhub
|
||||
import string
|
||||
from stdio import snprintf
|
||||
from . import (
|
||||
JsonValue, JSON_NULL, JSON_BOOL, JSON_INT, JSON_FLOAT,
|
||||
JSON_STRING, JSON_ARRAY, JSON_OBJECT,
|
||||
)
|
||||
|
||||
|
||||
def _write_char(buf: t.CChar | t.CPtr, pos: t.CSizeT, ch: t.CChar) -> t.CSizeT:
|
||||
buf[pos] = ch
|
||||
return pos + 1
|
||||
|
||||
def _write_str(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT:
|
||||
if s == None: return pos
|
||||
slen: t.CSizeT = string.strlen(s)
|
||||
string.memcpy(t.CChar(t.CUInt64T(buf) + pos, t.CPtr), s, slen)
|
||||
return pos + slen
|
||||
|
||||
def _write_string_escaped(buf: t.CChar | t.CPtr, pos: t.CSizeT, s: t.CChar | t.CPtr) -> t.CSizeT:
|
||||
if s == None:
|
||||
pos = _write_str(buf, pos, "null")
|
||||
return pos
|
||||
pos = _write_char(buf, pos, '"')
|
||||
i: t.CSizeT = 0
|
||||
slen: t.CSizeT = string.strlen(s)
|
||||
while i < slen:
|
||||
ch: t.CChar = s[i]
|
||||
if ch == '"':
|
||||
pos = _write_str(buf, pos, "\\\"")
|
||||
elif ch == '\\':
|
||||
pos = _write_str(buf, pos, "\\\\")
|
||||
elif ch == '\n':
|
||||
pos = _write_str(buf, pos, "\\n")
|
||||
elif ch == '\r':
|
||||
pos = _write_str(buf, pos, "\\r")
|
||||
elif ch == '\t':
|
||||
pos = _write_str(buf, pos, "\\t")
|
||||
else:
|
||||
pos = _write_char(buf, pos, ch)
|
||||
i += 1
|
||||
pos = _write_char(buf, pos, '"')
|
||||
return pos
|
||||
|
||||
|
||||
def _write_value(buf: t.CChar | t.CPtr, pos: t.CSizeT, val: JsonValue | t.CPtr, pool: memhub.MemManager | t.CPtr) -> t.CSizeT:
|
||||
if val == None:
|
||||
pos = _write_str(buf, pos, "null")
|
||||
return pos
|
||||
|
||||
if val.vtype == JSON_NULL:
|
||||
pos = _write_str(buf, pos, "null")
|
||||
|
||||
elif val.vtype == JSON_BOOL:
|
||||
if val.bool_val != 0:
|
||||
pos = _write_str(buf, pos, "true")
|
||||
else:
|
||||
pos = _write_str(buf, pos, "false")
|
||||
|
||||
elif val.vtype == JSON_INT:
|
||||
tmp: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if tmp != None:
|
||||
snprintf(tmp, 32, "%lld", val.int_val)
|
||||
pos = _write_str(buf, pos, tmp)
|
||||
|
||||
elif val.vtype == JSON_FLOAT:
|
||||
tmp2: t.CChar | t.CPtr = pool.alloc(32)
|
||||
if tmp2 != None:
|
||||
snprintf(tmp2, 32, "%.6g", val.float_val)
|
||||
pos = _write_str(buf, pos, tmp2)
|
||||
|
||||
elif val.vtype == JSON_STRING:
|
||||
pos = _write_string_escaped(buf, pos, val.str_val)
|
||||
|
||||
elif val.vtype == JSON_ARRAY:
|
||||
if val.child == None:
|
||||
pos = _write_str(buf, pos, "[]")
|
||||
return pos
|
||||
pos = _write_char(buf, pos, '[')
|
||||
cur: JsonValue | t.CPtr = val.child
|
||||
first: bool = True
|
||||
while cur != None:
|
||||
if not first:
|
||||
pos = _write_char(buf, pos, ',')
|
||||
pos = _write_value(buf, pos, cur, pool)
|
||||
first = False
|
||||
cur = cur.next
|
||||
pos = _write_char(buf, pos, ']')
|
||||
|
||||
elif val.vtype == JSON_OBJECT:
|
||||
if val.child == None:
|
||||
pos = _write_str(buf, pos, "{}")
|
||||
return pos
|
||||
pos = _write_char(buf, pos, '{')
|
||||
cur2: JsonValue | t.CPtr = val.child
|
||||
first2: bool = True
|
||||
while cur2 != None:
|
||||
if not first2:
|
||||
pos = _write_char(buf, pos, ',')
|
||||
pos = _write_string_escaped(buf, pos, cur2.key)
|
||||
pos = _write_char(buf, pos, ':')
|
||||
pos = _write_value(buf, pos, cur2, pool)
|
||||
first2 = False
|
||||
cur2 = cur2.next
|
||||
pos = _write_char(buf, pos, '}')
|
||||
|
||||
return pos
|
||||
|
||||
|
||||
def write(pool: memhub.MemManager | t.CPtr, val: JsonValue | t.CPtr, pretty: bool) -> t.CChar | t.CPtr:
|
||||
"""将 JsonValue 序列化为 JSON 字符串"""
|
||||
buf: t.CChar | t.CPtr = pool.alloc(4096)
|
||||
if buf == None:
|
||||
return None
|
||||
end_pos: t.CSizeT = _write_value(buf, 0, val, pool)
|
||||
buf[end_pos] = '\0'
|
||||
return buf
|
||||
Reference in New Issue
Block a user