aboutsummaryrefslogtreecommitdiff
path: root/core/encoding
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2021-09-28 15:01:11 +0100
committergingerBill <bill@gingerbill.org>2021-09-28 15:01:11 +0100
commitd452758afc2a503bc5bc04da04cfdd4af90da1ac (patch)
tree15044c491080813957c99d7cce32ab148a7c00fa /core/encoding
parentc9330548726965ffe64f97c37b43bc96a30f4dc7 (diff)
Improve MJSON handling
Diffstat (limited to 'core/encoding')
-rw-r--r--core/encoding/json/parser.odin34
-rw-r--r--core/encoding/json/unmarshal.odin108
-rw-r--r--core/encoding/json/validator.odin7
3 files changed, 83 insertions, 66 deletions
diff --git a/core/encoding/json/parser.odin b/core/encoding/json/parser.odin
index 0bb4c03a5..af32e7266 100644
--- a/core/encoding/json/parser.odin
+++ b/core/encoding/json/parser.odin
@@ -109,63 +109,61 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) {
token := p.curr_token
#partial switch token.kind {
case .Null:
- value = Null{}
advance_token(p)
+ value = Null{}
return
case .False:
- value = Boolean(false)
advance_token(p)
+ value = Boolean(false)
return
case .True:
- value = Boolean(true)
advance_token(p)
+ value = Boolean(true)
return
case .Integer:
+ advance_token(p)
i, _ := strconv.parse_i64(token.text)
value = Integer(i)
- advance_token(p)
return
case .Float:
+ advance_token(p)
f, _ := strconv.parse_f64(token.text)
value = Float(f)
- advance_token(p)
return
+
+ case .Ident:
+ if p.spec == .MJSON {
+ advance_token(p)
+ return string(token.text), nil
+ }
+
case .String:
- value = unquote_string(token, p.spec, p.allocator) or_return
advance_token(p)
- return
+ return unquote_string(token, p.spec, p.allocator)
case .Open_Brace:
return parse_object(p)
case .Open_Bracket:
return parse_array(p)
-
- case .Ident:
- if p.spec == .MJSON {
- advance_token(p)
- return string(token.text), nil
- }
case:
if p.spec != .JSON {
- #partial switch token.kind {
- case .Infinity:
+ switch {
+ case allow_token(p, .Infinity):
inf: u64 = 0x7ff0000000000000
if token.text[0] == '-' {
inf = 0xfff0000000000000
}
value = transmute(f64)inf
- advance_token(p)
return
- case .NaN:
+ case allow_token(p, .NaN):
nan: u64 = 0x7ff7ffffffffffff
if token.text[0] == '-' {
nan = 0xfff7ffffffffffff
}
value = transmute(f64)nan
- advance_token(p)
return
}
}
diff --git a/core/encoding/json/unmarshal.odin b/core/encoding/json/unmarshal.odin
index e05c140da..46c248e01 100644
--- a/core/encoding/json/unmarshal.odin
+++ b/core/encoding/json/unmarshal.odin
@@ -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)
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
- case .String:
+
+ case .Ident:
advance_token(p)
- str := unquote_string(token, p.spec, p.allocator) or_return
- val := any{v.data, ti.id}
- 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))
+ if p.spec == .MJSON {
+ if unmarsal_string(p, any{v.data, ti.id}, token.text, ti) {
+ return nil
}
- return
}
- defer delete(str, p.allocator)
+ return UNSUPPORTED_TYPE
- #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?
+ case .String:
+ advance_token(p)
+ str := unquote_string(token, p.spec, p.allocator) or_return
+ if unmarsal_string(p, any{v.data, ti.id}, str, ti) {
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
diff --git a/core/encoding/json/validator.odin b/core/encoding/json/validator.odin
index 085dd384a..961c2dc23 100644
--- a/core/encoding/json/validator.odin
+++ b/core/encoding/json/validator.odin
@@ -102,6 +102,13 @@ validate_value :: proc(p: ^Parser) -> bool {
case .Open_Bracket:
return validate_array(p)
+
+ case .Ident:
+ if p.spec == .MJSON {
+ advance_token(p)
+ return true
+ }
+ return false
case:
if p.spec != .JSON {