mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 05:08:14 +00:00
Improve MJSON handling
This commit is contained in:
@@ -109,63 +109,61 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) {
|
|||||||
token := p.curr_token
|
token := p.curr_token
|
||||||
#partial switch token.kind {
|
#partial switch token.kind {
|
||||||
case .Null:
|
case .Null:
|
||||||
value = Null{}
|
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
|
value = Null{}
|
||||||
return
|
return
|
||||||
case .False:
|
case .False:
|
||||||
value = Boolean(false)
|
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
|
value = Boolean(false)
|
||||||
return
|
return
|
||||||
case .True:
|
case .True:
|
||||||
value = Boolean(true)
|
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
|
value = Boolean(true)
|
||||||
return
|
return
|
||||||
|
|
||||||
case .Integer:
|
case .Integer:
|
||||||
|
advance_token(p)
|
||||||
i, _ := strconv.parse_i64(token.text)
|
i, _ := strconv.parse_i64(token.text)
|
||||||
value = Integer(i)
|
value = Integer(i)
|
||||||
advance_token(p)
|
|
||||||
return
|
return
|
||||||
case .Float:
|
case .Float:
|
||||||
|
advance_token(p)
|
||||||
f, _ := strconv.parse_f64(token.text)
|
f, _ := strconv.parse_f64(token.text)
|
||||||
value = Float(f)
|
value = Float(f)
|
||||||
advance_token(p)
|
|
||||||
return
|
return
|
||||||
case .String:
|
|
||||||
value = unquote_string(token, p.spec, p.allocator) or_return
|
|
||||||
advance_token(p)
|
|
||||||
return
|
|
||||||
|
|
||||||
case .Open_Brace:
|
|
||||||
return parse_object(p)
|
|
||||||
|
|
||||||
case .Open_Bracket:
|
|
||||||
return parse_array(p)
|
|
||||||
|
|
||||||
case .Ident:
|
case .Ident:
|
||||||
if p.spec == .MJSON {
|
if p.spec == .MJSON {
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
return string(token.text), nil
|
return string(token.text), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case .String:
|
||||||
|
advance_token(p)
|
||||||
|
return unquote_string(token, p.spec, p.allocator)
|
||||||
|
|
||||||
|
case .Open_Brace:
|
||||||
|
return parse_object(p)
|
||||||
|
|
||||||
|
case .Open_Bracket:
|
||||||
|
return parse_array(p)
|
||||||
|
|
||||||
case:
|
case:
|
||||||
if p.spec != .JSON {
|
if p.spec != .JSON {
|
||||||
#partial switch token.kind {
|
switch {
|
||||||
case .Infinity:
|
case allow_token(p, .Infinity):
|
||||||
inf: u64 = 0x7ff0000000000000
|
inf: u64 = 0x7ff0000000000000
|
||||||
if token.text[0] == '-' {
|
if token.text[0] == '-' {
|
||||||
inf = 0xfff0000000000000
|
inf = 0xfff0000000000000
|
||||||
}
|
}
|
||||||
value = transmute(f64)inf
|
value = transmute(f64)inf
|
||||||
advance_token(p)
|
|
||||||
return
|
return
|
||||||
case .NaN:
|
case allow_token(p, .NaN):
|
||||||
nan: u64 = 0x7ff7ffffffffffff
|
nan: u64 = 0x7ff7ffffffffffff
|
||||||
if token.text[0] == '-' {
|
if token.text[0] == '-' {
|
||||||
nan = 0xfff7ffffffffffff
|
nan = 0xfff7ffffffffffff
|
||||||
}
|
}
|
||||||
value = transmute(f64)nan
|
value = transmute(f64)nan
|
||||||
advance_token(p)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -139,6 +139,56 @@ assign_float :: proc(val: any, i: $T) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@(private)
|
||||||
|
unmarsal_string :: proc(p: ^Parser, val: any, str: string, ti: ^reflect.Type_Info) -> bool {
|
||||||
|
val := val
|
||||||
|
switch dst in &val {
|
||||||
|
case string:
|
||||||
|
dst = str
|
||||||
|
return true
|
||||||
|
case cstring:
|
||||||
|
if str == "" {
|
||||||
|
dst = strings.clone_to_cstring("", p.allocator)
|
||||||
|
} else {
|
||||||
|
// NOTE: This is valid because 'clone_string' appends a NUL terminator
|
||||||
|
dst = cstring(raw_data(str))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
defer delete(str, p.allocator)
|
||||||
|
|
||||||
|
#partial switch variant in ti.variant {
|
||||||
|
case reflect.Type_Info_Enum:
|
||||||
|
for name, i in variant.names {
|
||||||
|
if name == str {
|
||||||
|
assign_int(val, variant.values[i])
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO(bill): should this be an error or not?
|
||||||
|
return true
|
||||||
|
|
||||||
|
case reflect.Type_Info_Integer:
|
||||||
|
i := strconv.parse_i128(str) or_return
|
||||||
|
if assign_int(val, i) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if assign_float(val, i) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
case reflect.Type_Info_Float:
|
||||||
|
f := strconv.parse_f64(str) or_return
|
||||||
|
if assign_int(val, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if assign_float(val, f) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@(private)
|
@(private)
|
||||||
unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
||||||
@@ -195,60 +245,22 @@ unmarsal_value :: proc(p: ^Parser, v: any) -> (err: Unmarshal_Error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return UNSUPPORTED_TYPE
|
return UNSUPPORTED_TYPE
|
||||||
|
|
||||||
|
case .Ident:
|
||||||
|
advance_token(p)
|
||||||
|
if p.spec == .MJSON {
|
||||||
|
if unmarsal_string(p, any{v.data, ti.id}, token.text, ti) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return UNSUPPORTED_TYPE
|
||||||
|
|
||||||
case .String:
|
case .String:
|
||||||
advance_token(p)
|
advance_token(p)
|
||||||
str := unquote_string(token, p.spec, p.allocator) or_return
|
str := unquote_string(token, p.spec, p.allocator) or_return
|
||||||
val := any{v.data, ti.id}
|
if unmarsal_string(p, any{v.data, ti.id}, str, ti) {
|
||||||
switch dst in &val {
|
|
||||||
case string:
|
|
||||||
dst = str
|
|
||||||
return
|
|
||||||
case cstring:
|
|
||||||
if str == "" {
|
|
||||||
dst = strings.clone_to_cstring("", p.allocator)
|
|
||||||
} else {
|
|
||||||
// NOTE: This is valid because 'clone_string' appends a NUL terminator
|
|
||||||
dst = cstring(raw_data(str))
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer delete(str, p.allocator)
|
|
||||||
|
|
||||||
#partial switch variant in ti.variant {
|
|
||||||
case reflect.Type_Info_Enum:
|
|
||||||
for name, i in variant.names {
|
|
||||||
if name == str {
|
|
||||||
assign_int(val, variant.values[i])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// TODO(bill): should this be an error or not?
|
|
||||||
return nil
|
return nil
|
||||||
|
|
||||||
case reflect.Type_Info_Integer:
|
|
||||||
i, ok := strconv.parse_i128(token.text)
|
|
||||||
if !ok {
|
|
||||||
return UNSUPPORTED_TYPE
|
|
||||||
}
|
|
||||||
if assign_int(val, i) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if assign_float(val, i) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case reflect.Type_Info_Float:
|
|
||||||
f, ok := strconv.parse_f64(token.text)
|
|
||||||
if !ok {
|
|
||||||
return UNSUPPORTED_TYPE
|
|
||||||
}
|
|
||||||
if assign_int(val, f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if assign_float(val, f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return UNSUPPORTED_TYPE
|
return UNSUPPORTED_TYPE
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -102,6 +102,13 @@ validate_value :: proc(p: ^Parser) -> bool {
|
|||||||
|
|
||||||
case .Open_Bracket:
|
case .Open_Bracket:
|
||||||
return validate_array(p)
|
return validate_array(p)
|
||||||
|
|
||||||
|
case .Ident:
|
||||||
|
if p.spec == .MJSON {
|
||||||
|
advance_token(p)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
|
||||||
case:
|
case:
|
||||||
if p.spec != .JSON {
|
if p.spec != .JSON {
|
||||||
|
|||||||
Reference in New Issue
Block a user