json: wrap up decode()
parent
5eb71c4a13
commit
fd8a194df0
|
@ -6,6 +6,7 @@ module json
|
|||
#flag -I @VROOT/thirdparty/cJSON
|
||||
#flag @VROOT/thirdparty/cJSON/cJSON.o
|
||||
#include "cJSON.h"
|
||||
#define js_get(object, key) cJSON_GetObjectItemCaseSensitive((object), (key))
|
||||
struct C.cJSON {
|
||||
valueint int
|
||||
valuedouble f32
|
||||
|
@ -22,84 +23,84 @@ pub fn encode(x voidptr) string {
|
|||
return ''
|
||||
}
|
||||
|
||||
fn jsdecode_int(root &C.cJSON) int {
|
||||
fn decode_int(root &C.cJSON) int {
|
||||
if isnil(root) {
|
||||
return 0
|
||||
}
|
||||
return root.valueint
|
||||
}
|
||||
|
||||
fn jsdecode_i8(root &C.cJSON) i8 {
|
||||
fn decode_i8(root &C.cJSON) i8 {
|
||||
if isnil(root) {
|
||||
return i8(0)
|
||||
}
|
||||
return i8(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_i16(root &C.cJSON) i16 {
|
||||
fn decode_i16(root &C.cJSON) i16 {
|
||||
if isnil(root) {
|
||||
return i16(0)
|
||||
}
|
||||
return i16(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_i64(root &C.cJSON) i64 {
|
||||
fn decode_i64(root &C.cJSON) i64 {
|
||||
if isnil(root) {
|
||||
return i64(0)
|
||||
}
|
||||
return i64(root.valuedouble) // i64 is double in C
|
||||
}
|
||||
|
||||
fn jsdecode_byte(root &C.cJSON) byte {
|
||||
fn decode_byte(root &C.cJSON) byte {
|
||||
if isnil(root) {
|
||||
return byte(0)
|
||||
}
|
||||
return byte(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_u16(root &C.cJSON) u16 {
|
||||
fn decode_u16(root &C.cJSON) u16 {
|
||||
if isnil(root) {
|
||||
return u16(0)
|
||||
}
|
||||
return u16(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_u32(root &C.cJSON) u32 {
|
||||
fn decode_u32(root &C.cJSON) u32 {
|
||||
if isnil(root) {
|
||||
return u32(0)
|
||||
}
|
||||
return u32(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_u64(root &C.cJSON) u64 {
|
||||
fn decode_u64(root &C.cJSON) u64 {
|
||||
if isnil(root) {
|
||||
return u64(0)
|
||||
}
|
||||
return u64(root.valueint)
|
||||
}
|
||||
|
||||
fn jsdecode_f32(root &C.cJSON) f32 {
|
||||
fn decode_f32(root &C.cJSON) f32 {
|
||||
if isnil(root) {
|
||||
return f32(0)
|
||||
}
|
||||
return root.valuedouble
|
||||
}
|
||||
|
||||
fn jsdecode_f64(root &C.cJSON) f64 {
|
||||
fn decode_f64(root &C.cJSON) f64 {
|
||||
if isnil(root) {
|
||||
return f64(0)
|
||||
}
|
||||
return f64(root.valuedouble)
|
||||
}
|
||||
|
||||
fn jsdecode_string(root &C.cJSON) string {
|
||||
fn decode_string(root &C.cJSON) string {
|
||||
if isnil(root) {
|
||||
return ''
|
||||
}
|
||||
if isnil(root.valuestring) {
|
||||
return ''
|
||||
}
|
||||
// println('jsdecode string valuestring="$root.valuestring"')
|
||||
// println('decode string valuestring="$root.valuestring"')
|
||||
// return tos(root.valuestring, _strlen(root.valuestring))
|
||||
return tos_clone(root.valuestring) // , _strlen(root.valuestring))
|
||||
}
|
||||
|
@ -122,7 +123,7 @@ fn C.cJSON_Parse() &C.cJSON
|
|||
fn C.cJSON_PrintUnformatted() byteptr
|
||||
|
||||
|
||||
fn jsdecode_bool(root &C.cJSON) bool {
|
||||
fn decode_bool(root &C.cJSON) bool {
|
||||
if isnil(root) {
|
||||
return false
|
||||
}
|
||||
|
|
|
@ -721,13 +721,14 @@ pub fn (mut c Checker) call_fn(call_expr mut ast.CallExpr) table.Type {
|
|||
// println(fn_name)
|
||||
// }
|
||||
if fn_name == 'json.encode' {
|
||||
} else if fn_name == 'json.decode' {
|
||||
expr := call_expr.args[0].expr
|
||||
if !(expr is ast.Type) {
|
||||
c.error('json.decode: first argument needs to be a type', call_expr.pos)
|
||||
return table.void_type
|
||||
}
|
||||
if fn_name == 'json.decode' {
|
||||
ident := call_expr.args[0].expr as ast.Ident
|
||||
// sym := c.table.find_type(ident.name)
|
||||
idx := c.table.find_type_idx(ident.name)
|
||||
println('js.decode t=$ident.name')
|
||||
return table.Type(idx)
|
||||
typ := expr as ast.Type
|
||||
return typ.typ.set_flag(.optional)
|
||||
}
|
||||
// look for function in format `mod.fn` or `fn` (main/builtin)
|
||||
mut f := table.Fn{}
|
||||
|
|
|
@ -383,12 +383,22 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
mut name := node.name
|
||||
is_print := name == 'println' || name == 'print'
|
||||
print_method := if name == 'println' { 'println' } else { 'print' }
|
||||
g.is_json_fn = name == 'json.encode'
|
||||
is_json_encode := name == 'json.encode'
|
||||
is_json_decode := name == 'json.decode'
|
||||
g.is_json_fn = is_json_encode || is_json_decode
|
||||
mut json_type_str := ''
|
||||
if g.is_json_fn {
|
||||
if name == 'json.encode' {
|
||||
g.write('json__json_print(')
|
||||
g.gen_json_for_type(node.args[0].typ)
|
||||
json_type_str = g.table.get_type_symbol(node.args[0].typ).name
|
||||
} else {
|
||||
g.insert_before('// json.decode')
|
||||
ast_type := node.args[0].expr as ast.Type
|
||||
// `json.decode(User, s)` => json.decode_User(s)
|
||||
sym := g.table.get_type_symbol(ast_type.typ)
|
||||
name += '_' + sym.name
|
||||
}
|
||||
}
|
||||
if node.is_c {
|
||||
// Skip "C."
|
||||
|
@ -397,8 +407,8 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
} else {
|
||||
name = c_name(name)
|
||||
}
|
||||
if g.is_json_fn {
|
||||
// `json__decode` => `json__decode_User`
|
||||
if is_json_encode {
|
||||
// `json__encode` => `json__encode_User`
|
||||
name += '_' + json_type_str
|
||||
}
|
||||
// Generate tmp vars for values that have to be freed.
|
||||
|
@ -476,14 +486,25 @@ fn (mut g Gen) fn_call(node ast.CallExpr) {
|
|||
pafn := g.fn_decl.name.after('.')
|
||||
mut pamod := g.fn_decl.name.all_before_last('.')
|
||||
if pamod == pafn {
|
||||
pamod = if g.fn_decl.is_builtin { 'builtin' } else { 'main' }
|
||||
pamod = if g.fn_decl.is_builtin {
|
||||
'builtin'
|
||||
} else {
|
||||
'main'
|
||||
}
|
||||
}
|
||||
g.write('panic_debug($paline, tos3("$pafile"), tos3("$pamod"), tos3("$pafn"), ')
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
g.write(')')
|
||||
} else {
|
||||
g.write('${name}(')
|
||||
if is_json_decode {
|
||||
g.write('json__json_parse(')
|
||||
// Skip the first argument in json.decode which is a type
|
||||
// its name was already used to generate the function call
|
||||
g.call_args(node.args[1..], node.expected_arg_types)
|
||||
} else {
|
||||
g.call_args(node.args, node.expected_arg_types)
|
||||
}
|
||||
g.write(')')
|
||||
}
|
||||
// if node.or_block.stmts.len > 0 {
|
||||
|
|
|
@ -31,8 +31,9 @@ fn (mut g Gen) gen_json_for_type(typ table.Type) {
|
|||
// Code gen decoder
|
||||
dec_fn_name := js_dec_name(sym.name)
|
||||
dec.writeln('
|
||||
Option ${dec_fn_name}(cJSON* root, $styp* res) {
|
||||
// $styp res;
|
||||
//Option ${dec_fn_name}(cJSON* root, $styp* res) {
|
||||
Option ${dec_fn_name}(cJSON* root) {
|
||||
$styp res;
|
||||
if (!root) {
|
||||
const char *error_ptr = cJSON_GetErrorPtr();
|
||||
if (error_ptr != NULL) {
|
||||
|
@ -70,7 +71,7 @@ cJSON* ${enc_fn_name}($styp val) {
|
|||
g.gen_json_for_type(field.typ)
|
||||
dec_name := js_dec_name(field_type)
|
||||
if is_js_prim(field_type) {
|
||||
dec.writeln(' res->$field.name = $dec_name (js_get(' + 'root, "$name"))')
|
||||
dec.writeln(' res . $field.name = $dec_name (js_get(' + 'root, "$name"))')
|
||||
} else {
|
||||
dec.writeln(' $dec_name (js_get(root, "$name"), & (res->$field.name))')
|
||||
}
|
||||
|
@ -80,7 +81,7 @@ cJSON* ${enc_fn_name}($styp val) {
|
|||
}
|
||||
// cJSON_delete
|
||||
// p.cgen.fns << '$dec return opt_ok(res); \n}'
|
||||
dec.writeln('return opt_ok(res, sizeof(*res)); \n}')
|
||||
dec.writeln('return opt_ok(&res, sizeof(res)); \n}')
|
||||
enc.writeln('\treturn o;\n}')
|
||||
g.definitions.writeln(dec.str())
|
||||
g.gowrappers.writeln(enc.str())
|
||||
|
|
|
@ -20,6 +20,11 @@ pub fn (mut p Parser) call_expr(is_c, is_js bool, mod string) ast.CallExpr {
|
|||
} else {
|
||||
name
|
||||
}
|
||||
if fn_name == 'json.decode' {
|
||||
// Makes name_expr() parse the type (`User` in `json.decode(User, txt)`)`
|
||||
p.inside_is = true
|
||||
p.expr_mod = ''
|
||||
}
|
||||
p.check(.lpar)
|
||||
args := p.call_args()
|
||||
last_pos := p.tok.position()
|
||||
|
|
|
@ -32,7 +32,7 @@ mut:
|
|||
mod string // current module name
|
||||
attr string
|
||||
attr_ctdefine string
|
||||
expr_mod string
|
||||
expr_mod string // for constructing full type names in parse_type()
|
||||
scope &ast.Scope
|
||||
global_scope &ast.Scope
|
||||
imports map[string]string
|
||||
|
@ -588,8 +588,9 @@ pub fn (mut p Parser) name_expr() ast.Expr {
|
|||
p.inside_is = false
|
||||
// get type position before moving to next
|
||||
type_pos := p.tok.position()
|
||||
typ := p.parse_type()
|
||||
return ast.Type{
|
||||
typ: p.parse_type()
|
||||
typ: typ
|
||||
pos: type_pos
|
||||
}
|
||||
}
|
||||
|
@ -1062,8 +1063,8 @@ fn (mut p Parser) return_stmt() ast.Return {
|
|||
|
||||
// left hand side of `=` or `:=` in `a,b,c := 1,2,3`
|
||||
fn (mut p Parser) global_decl() ast.GlobalDecl {
|
||||
if !p.pref.translated && !p.pref.is_livemain && !p.builtin_mod && !p.pref.building_v && p.mod !=
|
||||
'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals {
|
||||
if !p.pref.translated && !p.pref.is_livemain && !p.builtin_mod && !p.pref.building_v &&
|
||||
p.mod != 'ui' && p.mod != 'gg2' && p.mod != 'uiold' && !os.getwd().contains('/volt') && !p.pref.enable_globals {
|
||||
p.error('use `v --enable-globals ...` to enable globals')
|
||||
}
|
||||
p.next()
|
||||
|
|
Loading…
Reference in New Issue