Files

237 lines
7.2 KiB
Plaintext

from stdint import *
import memhub
import string
# ============================================================
# JSON value type enum
# ============================================================
define JSON_NULL = 0
define JSON_BOOL = 1
define JSON_INT = 2
define JSON_FLOAT = 3
define JSON_STRING = 4
define JSON_ARRAY = 5
define JSON_OBJECT = 6
# ============================================================
# JsonValue - JSON value node.
# Allocated from mpool: JsonValue(pool) allocates from the pool.
# ============================================================
class JsonValue:
vtype: int
bool_val: int
int_val: int64
float_val: double
str_val: str
next: JsonValue*
key: str
child: JsonValue*
child_count: sizet
def __new__(self, pool: memhub.MemManager*):
"""Allocate and zero-initialize a JsonValue struct from mpool."""
ptr: JsonValue* = pool.alloc(JsonValue.__sizeof__())
if ptr:
string.memset(ptr, 0, JsonValue.__sizeof__())
return ptr
def type(self) -> int:
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) -> int64:
return self.int_val
def as_float(self) -> double:
return self.float_val
def as_string(self) -> str:
return self.str_val
def __len__(self) -> sizet:
return self.child_count
def __getitem__(self, key: str) -> JsonValue*:
"""Python-style get: v["key"] returns an object field."""
if self.vtype != JSON_OBJECT:
return None
if key == None:
return None
cur: JsonValue* = self.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
return cur
cur = cur.next
return None
def __setitem__(self, key: str, val: JsonValue*):
"""Python-style set: v["key"] = val."""
if self.vtype != JSON_OBJECT or key == None or val == None:
return
cur: JsonValue* = self.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
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 absent: append a new child node
klen: sizet = string.strlen(key)
kbuf: str = 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: sizet) -> JsonValue*:
"""Get an array element by index: v.get_item(0)."""
if self.vtype != JSON_ARRAY and self.vtype != JSON_OBJECT:
return None
cur: JsonValue* = self.child
i: sizet = 0
while cur != None:
if i == index:
return cur
cur = cur.next
i += 1
return None
def _pool_alloc(self, size: sizet) -> str:
"""Internal: allocate from current object's mpool (reserved; currently returns None)."""
return None
def _append_child(self, child: JsonValue*):
if self.child == None:
self.child = child
else:
cur: JsonValue* = self.child
while cur.next != None:
cur = cur.next
cur.next = child
self.child_count += 1
# ============================================================
# Constructors: create each kind of JsonValue (allocated from mpool)
# ============================================================
def null(pool: memhub.MemManager*) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_NULL
return v
def bool_val(pool: memhub.MemManager*, val: bool) -> JsonValue*:
v: JsonValue* = 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*, val: int64) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_INT
v.int_val = val
return v
def float_val(pool: memhub.MemManager*, val: double) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_FLOAT
v.float_val = val
return v
def string_val(pool: memhub.MemManager*, val: str) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_STRING
if val != None:
slen: sizet = string.strlen(val)
buf: str = pool.alloc(slen + 1)
if buf != None:
string.memcpy(buf, val, slen + 1)
v.str_val = buf
return v
def array(pool: memhub.MemManager*) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_ARRAY
return v
def object(pool: memhub.MemManager*) -> JsonValue*:
v: JsonValue* = JsonValue(pool)
if v == None: return None
v.vtype = JSON_OBJECT
return v
# Append an element to an array
def array_append(pool: memhub.MemManager*, arr: JsonValue*, item: JsonValue*):
if arr == None or item == None: return
if arr.vtype != JSON_ARRAY: return
arr._append_child(item)
# Set a key/value pair on an object
def object_set(pool: memhub.MemManager*, obj: JsonValue*, key: str, val: JsonValue*):
if obj == None or key == None or val == None: return
if obj.vtype != JSON_OBJECT: return
cur: JsonValue* = obj.child
while cur != None:
if cur.key != None:
if string.strcmp(cur.key, key) == 0:
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: sizet = string.strlen(key)
kbuf: str = pool.alloc(klen + 1)
if kbuf != None:
string.memcpy(kbuf, key, klen + 1)
val.key = kbuf
obj._append_child(val)
# ============================================================
# Import submodules
# ============================================================
from .__parser import parse
from .__writer import write