Browse Source

Add json.is_valid file

gingerBill 6 years ago
parent
commit
d732a51587
1 changed files with 98 additions and 0 deletions
  1. 98 0
      core/encoding/json/validator.odin

+ 98 - 0
core/encoding/json/validator.odin

@@ -0,0 +1,98 @@
+package json
+
+import "core:mem"
+
+// NOTE(bill): is_valid will not check for duplicate keys
+is_valid :: proc(data: string) -> bool {
+	p := make_parser(data, mem.nil_allocator());
+	return validate_object(&p);
+}
+
+validate_object :: proc(p: ^Parser) -> bool {
+	if err := expect_token(p, Kind.Open_Brace); err != Error.None {
+		return false;
+	}
+
+	for p.curr_token.kind != Kind.Close_Brace {
+		tok := p.curr_token;
+		if tok_err := expect_token(p, Kind.String); tok_err != Error.None {
+			return false;
+		}
+		if colon_err := expect_token(p, Kind.Colon); colon_err != Error.None {
+			return false;
+		}
+
+		if !validate_value(p) {
+			return false;
+		}
+
+		// Disallow trailing commas for the time being
+		if allow_token(p, Kind.Comma) {
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	if err := expect_token(p, Kind.Close_Brace); err != Error.None {
+		return false;
+	}
+	return true;
+}
+
+validate_array :: proc(p: ^Parser) -> bool {
+	if err := expect_token(p, Kind.Open_Bracket); err != Error.None {
+		return false;
+	}
+
+	for p.curr_token.kind != Kind.Close_Bracket {
+		if !validate_value(p) {
+			return false;
+		}
+
+		// Disallow trailing commas for the time being
+		if allow_token(p, Kind.Comma) {
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	if err := expect_token(p, Kind.Close_Bracket); err != Error.None {
+		return false;
+	}
+
+	return true;
+}
+
+validate_value :: proc(p: ^Parser) -> bool {
+	token := p.curr_token;
+	switch token.kind {
+	case Kind.Null:
+		advance_token(p);
+		return true;
+	case Kind.False:
+		advance_token(p);
+		return true;
+	case Kind.True:
+		advance_token(p);
+		return true;
+	case Kind.Integer:
+		advance_token(p);
+		return true;
+	case Kind.Float:
+		advance_token(p);
+		return true;
+	case Kind.String:
+		advance_token(p);
+		return is_valid_string_literal(token.text);
+
+	case Kind.Open_Brace:
+		return validate_object(p);
+
+	case Kind.Open_Bracket:
+		return validate_array(p);
+	}
+
+	return false;
+}