From db3501f61b6fd0ba9ec5b0ba06bd8188292810a7 Mon Sep 17 00:00:00 2001 From: gingerBill Date: Sun, 8 Aug 2021 12:59:35 +0100 Subject: [PATCH] [Breaking] Change the layout `json.Value` to be a `union` rather than a `struct` of a `json.Pos` and the union --- core/encoding/json/marshal.odin | 118 +++++++++++++++--------------- core/encoding/json/parser.odin | 34 +++------ core/encoding/json/tokenizer.odin | 6 ++ core/encoding/json/types.odin | 28 +++---- 4 files changed, 83 insertions(+), 103 deletions(-) diff --git a/core/encoding/json/marshal.odin b/core/encoding/json/marshal.odin index b3725a916..9295e647f 100644 --- a/core/encoding/json/marshal.odin +++ b/core/encoding/json/marshal.odin @@ -31,21 +31,19 @@ marshal :: proc(v: any, allocator := context.allocator) -> ([]byte, Marshal_Erro marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { - using strings; - using runtime; if v == nil { - write_string(b, "null"); + strings.write_string(b, "null"); return .None; } - ti := type_info_base(type_info_of(v.id)); + ti := runtime.type_info_base(type_info_of(v.id)); a := any{v.data, ti.id}; switch info in ti.variant { - case Type_Info_Named: + case runtime.Type_Info_Named: unreachable(); - case Type_Info_Integer: + case runtime.Type_Info_Integer: buf: [21]byte; u: u64; switch i in a { @@ -77,16 +75,16 @@ marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { } s := strconv.append_bits(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil); - write_string(b, s); + strings.write_string(b, s); - case Type_Info_Rune: + case runtime.Type_Info_Rune: r := a.(rune); - write_byte(b, '"'); - write_escaped_rune(b, r, '"', true); - write_byte(b, '"'); + strings.write_byte(b, '"'); + strings.write_escaped_rune(b, r, '"', true); + strings.write_byte(b, '"'); - case Type_Info_Float: + case runtime.Type_Info_Float: val: f64; switch f in a { case f16: val = f64(f); @@ -107,21 +105,21 @@ marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { s = s[1:]; } - write_string(b, string(s)); + strings.write_string(b, string(s)); - case Type_Info_Complex: + case runtime.Type_Info_Complex: return .Unsupported_Type; - case Type_Info_Quaternion: + case runtime.Type_Info_Quaternion: return .Unsupported_Type; - case Type_Info_String: + case runtime.Type_Info_String: switch s in a { - case string: write_quoted_string(b, s); - case cstring: write_quoted_string(b, string(s)); + case string: strings.write_quoted_string(b, s); + case cstring: strings.write_quoted_string(b, string(s)); } - case Type_Info_Boolean: + case runtime.Type_Info_Boolean: val: bool; switch b in a { case bool: val = bool(b); @@ -130,109 +128,109 @@ marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { case b32: val = bool(b); case b64: val = bool(b); } - write_string_builder(b, val ? "true" : "false"); + strings.write_string(b, val ? "true" : "false"); - case Type_Info_Any: + case runtime.Type_Info_Any: return .Unsupported_Type; - case Type_Info_Type_Id: + case runtime.Type_Info_Type_Id: return .Unsupported_Type; - case Type_Info_Pointer: + case runtime.Type_Info_Pointer: return .Unsupported_Type; - case Type_Info_Procedure: + case runtime.Type_Info_Procedure: return .Unsupported_Type; - case Type_Info_Tuple: + case runtime.Type_Info_Tuple: return .Unsupported_Type; - case Type_Info_Enumerated_Array: + case runtime.Type_Info_Enumerated_Array: return .Unsupported_Type; - case Type_Info_Simd_Vector: + case runtime.Type_Info_Simd_Vector: return .Unsupported_Type; - case Type_Info_Relative_Pointer: + case runtime.Type_Info_Relative_Pointer: return .Unsupported_Type; - case Type_Info_Relative_Slice: + case runtime.Type_Info_Relative_Slice: return .Unsupported_Type; - case Type_Info_Array: - write_byte(b, '['); + case runtime.Type_Info_Array: + strings.write_byte(b, '['); for i in 0.. 0 { write_string(b, ", "); } + if i > 0 { strings.write_string(b, ", "); } data := uintptr(v.data) + uintptr(i*info.elem_size); marshal_arg(b, any{rawptr(data), info.elem.id}); } - write_byte(b, ']'); + strings.write_byte(b, ']'); - case Type_Info_Dynamic_Array: - write_byte(b, '['); + case runtime.Type_Info_Dynamic_Array: + strings.write_byte(b, '['); array := cast(^mem.Raw_Dynamic_Array)v.data; for i in 0.. 0 { write_string(b, ", "); } + if i > 0 { strings.write_string(b, ", "); } data := uintptr(array.data) + uintptr(i*info.elem_size); marshal_arg(b, any{rawptr(data), info.elem.id}); } - write_byte(b, ']'); + strings.write_byte(b, ']'); - case Type_Info_Slice: - write_byte(b, '['); + case runtime.Type_Info_Slice: + strings.write_byte(b, '['); slice := cast(^mem.Raw_Slice)v.data; for i in 0.. 0 { write_string(b, ", "); } + if i > 0 { strings.write_string(b, ", "); } data := uintptr(slice.data) + uintptr(i*info.elem_size); marshal_arg(b, any{rawptr(data), info.elem.id}); } - write_byte(b, ']'); + strings.write_byte(b, ']'); - case Type_Info_Map: + case runtime.Type_Info_Map: m := (^mem.Raw_Map)(v.data); - write_byte(b, '{'); + strings.write_byte(b, '{'); if m != nil { if info.generated_struct == nil { return .Unsupported_Type; } entries := &m.entries; - gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct); - ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array); - entry_type := ed.elem.variant.(Type_Info_Struct); + gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct); + ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array); + entry_type := ed.elem.variant.(runtime.Type_Info_Struct); entry_size := ed.elem_size; for i in 0.. 0 { write_string(b, ", "); } + if i > 0 { strings.write_string(b, ", "); } data := uintptr(entries.data) + uintptr(i*entry_size); key := rawptr(data + entry_type.offsets[2]); value := rawptr(data + entry_type.offsets[3]); marshal_arg(b, any{key, info.key.id}); - write_string(b, ": "); + strings.write_string(b, ": "); marshal_arg(b, any{value, info.value.id}); } } - write_byte(b, '}'); + strings.write_byte(b, '}'); - case Type_Info_Struct: - write_byte(b, '{'); + case runtime.Type_Info_Struct: + strings.write_byte(b, '{'); for name, i in info.names { - if i > 0 { write_string(b, ", "); } - write_quoted_string(b, name); - write_string(b, ": "); + if i > 0 { strings.write_string(b, ", "); } + strings.write_quoted_string(b, name); + strings.write_string(b, ": "); id := info.types[i].id; data := rawptr(uintptr(v.data) + info.offsets[i]); marshal_arg(b, any{data, id}); } - write_byte(b, '}'); + strings.write_byte(b, '}'); - case Type_Info_Union: + case runtime.Type_Info_Union: tag_ptr := uintptr(v.data) + info.tag_offset; tag_any := any{rawptr(tag_ptr), info.tag_type.id}; @@ -250,16 +248,16 @@ marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { } if v.data == nil || tag == 0 { - write_string(b, "null"); + strings.write_string(b, "null"); } else { id := info.variants[tag-1].id; marshal_arg(b, any{v.data, id}); } - case Type_Info_Enum: + case runtime.Type_Info_Enum: return marshal_arg(b, any{v.data, info.base.id}); - case Type_Info_Bit_Set: + case runtime.Type_Info_Bit_Set: is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool { if ti == nil { return false; @@ -306,7 +304,7 @@ marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error { bit_data = u64(x); case: panic("unknown bit_size size"); } - write_u64(b, bit_data); + strings.write_u64(b, bit_data); return .Unsupported_Type; diff --git a/core/encoding/json/parser.odin b/core/encoding/json/parser.odin index 54cf9b6ef..57b68946b 100644 --- a/core/encoding/json/parser.odin +++ b/core/encoding/json/parser.odin @@ -68,36 +68,33 @@ expect_token :: proc(p: ^Parser, kind: Token_Kind) -> Error { parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) { - value.pos = p.curr_token.pos; - defer value.end = token_end_pos(p.prev_token); - token := p.curr_token; #partial switch token.kind { case .Null: - value.value = Null{}; + value = Null{}; advance_token(p); return; case .False: - value.value = Boolean(false); + value = Boolean(false); advance_token(p); return; case .True: - value.value = Boolean(true); + value = Boolean(true); advance_token(p); return; case .Integer: i, _ := strconv.parse_i64(token.text); - value.value = Integer(i); + value = Integer(i); advance_token(p); return; case .Float: f, _ := strconv.parse_f64(token.text); - value.value = Float(f); + value = Float(f); advance_token(p); return; case .String: - value.value = String(unquote_string(token, p.spec, p.allocator)); + value = String(unquote_string(token, p.spec, p.allocator)); advance_token(p); return; @@ -115,7 +112,7 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) { if token.text[0] == '-' { inf = 0xfff0000000000000; } - value.value = transmute(f64)inf; + value = transmute(f64)inf; advance_token(p); return; case .NaN: @@ -123,7 +120,7 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) { if token.text[0] == '-' { nan = 0xfff7ffffffffffff; } - value.value = transmute(f64)nan; + value = transmute(f64)nan; advance_token(p); return; } @@ -136,8 +133,6 @@ parse_value :: proc(p: ^Parser) -> (value: Value, err: Error) { } parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) { - value.pos = p.curr_token.pos; - defer value.end = token_end_pos(p.prev_token); if err = expect_token(p, .Open_Bracket); err != .None { return; } @@ -171,7 +166,7 @@ parse_array :: proc(p: ^Parser) -> (value: Value, err: Error) { return; } - value.value = array; + value = array; return; } @@ -205,11 +200,7 @@ parse_object_key :: proc(p: ^Parser) -> (key: string, err: Error) { } parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { - value.pos = p.curr_token.pos; - defer value.end = token_end_pos(p.prev_token); - if err = expect_token(p, .Open_Brace); err != .None { - value.pos = p.curr_token.pos; return; } @@ -228,26 +219,22 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { key, err = parse_object_key(p); if err != .None { delete(key, p.allocator); - value.pos = p.curr_token.pos; return; } if colon_err := expect_token(p, .Colon); colon_err != .None { err = .Expected_Colon_After_Key; - value.pos = p.curr_token.pos; return; } elem, elem_err := parse_value(p); if elem_err != .None { err = elem_err; - value.pos = p.curr_token.pos; return; } if key in obj { err = .Duplicate_Object_Key; - value.pos = p.curr_token.pos; delete(key, p.allocator); return; } @@ -270,11 +257,10 @@ parse_object :: proc(p: ^Parser) -> (value: Value, err: Error) { } if err = expect_token(p, .Close_Brace); err != .None { - value.pos = p.curr_token.pos; return; } - value.value = obj; + value = obj; return; } diff --git a/core/encoding/json/tokenizer.odin b/core/encoding/json/tokenizer.odin index df12ce0b6..7adc062c2 100644 --- a/core/encoding/json/tokenizer.odin +++ b/core/encoding/json/tokenizer.odin @@ -2,6 +2,12 @@ package json import "core:unicode/utf8" +Pos :: struct { + offset: int, + line: int, + column: int, +} + Token :: struct { using pos: Pos, kind: Token_Kind, diff --git a/core/encoding/json/types.odin b/core/encoding/json/types.odin index d016cf560..10b88d87d 100644 --- a/core/encoding/json/types.odin +++ b/core/encoding/json/types.odin @@ -14,26 +14,16 @@ String :: string; Array :: distinct [dynamic]Value; Object :: distinct map[string]Value; -Value :: struct { - pos, end: Pos, - value: union { - Null, - Integer, - Float, - Boolean, - String, - Array, - Object, - }, +Value :: union { + Null, + Integer, + Float, + Boolean, + String, + Array, + Object, } -Pos :: struct { - offset: int, - line: int, - column: int, -} - - Error :: enum { None, @@ -57,7 +47,7 @@ Error :: enum { destroy_value :: proc(value: Value) { - #partial switch v in value.value { + #partial switch v in value { case Object: for key, elem in v { delete(key);