mirror of
https://github.com/odin-lang/Odin.git
synced 2025-12-28 17:04:34 +00:00
125 lines
2.2 KiB
Odin
125 lines
2.2 KiB
Odin
package encoding_json
|
|
|
|
import "core:mem"
|
|
|
|
// NOTE(bill): is_valid will not check for duplicate keys
|
|
is_valid :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false) -> bool {
|
|
p := make_parser(data, spec, parse_integers, mem.nil_allocator())
|
|
|
|
switch p.spec {
|
|
case .JSON:
|
|
return validate_object(&p)
|
|
case .JSON5:
|
|
return validate_value(&p)
|
|
case .MJSON:
|
|
#partial switch p.curr_token.kind {
|
|
case .Ident, .String:
|
|
return validate_object_body(&p, .EOF)
|
|
}
|
|
return validate_value(&p)
|
|
}
|
|
return validate_object(&p)
|
|
}
|
|
|
|
validate_object_key :: proc(p: ^Parser) -> bool {
|
|
if p.spec != .JSON {
|
|
if allow_token(p, .Ident) {
|
|
return true
|
|
}
|
|
}
|
|
err := expect_token(p, .String)
|
|
return err == .None
|
|
}
|
|
|
|
validate_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> bool {
|
|
for p.curr_token.kind != end_token {
|
|
if !validate_object_key(p) {
|
|
return false
|
|
}
|
|
if parse_colon(p) != nil {
|
|
return false
|
|
}
|
|
validate_value(p) or_return
|
|
|
|
if parse_comma(p) {
|
|
break
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
|
|
validate_object :: proc(p: ^Parser) -> bool {
|
|
if err := expect_token(p, .Open_Brace); err != .None {
|
|
return false
|
|
}
|
|
|
|
validate_object_body(p, .Close_Brace) or_return
|
|
|
|
if err := expect_token(p, .Close_Brace); err != .None {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
validate_array :: proc(p: ^Parser) -> bool {
|
|
if err := expect_token(p, .Open_Bracket); err != .None {
|
|
return false
|
|
}
|
|
|
|
for p.curr_token.kind != .Close_Bracket {
|
|
if !validate_value(p) {
|
|
return false
|
|
}
|
|
|
|
if parse_comma(p) {
|
|
break
|
|
}
|
|
}
|
|
|
|
if err := expect_token(p, .Close_Bracket); err != .None {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
validate_value :: proc(p: ^Parser) -> bool {
|
|
token := p.curr_token
|
|
|
|
#partial switch token.kind {
|
|
case .Null, .False, .True:
|
|
advance_token(p)
|
|
return true
|
|
case .Integer, .Float:
|
|
advance_token(p)
|
|
return true
|
|
case .String:
|
|
advance_token(p)
|
|
return is_valid_string_literal(token.text, p.spec)
|
|
|
|
case .Open_Brace:
|
|
return validate_object(p)
|
|
|
|
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 {
|
|
#partial switch token.kind {
|
|
case .Infinity, .NaN:
|
|
advance_token(p)
|
|
return true
|
|
}
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|