validator.odin 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package json
  2. import "core:mem"
  3. // NOTE(bill): is_valid will not check for duplicate keys
  4. is_valid :: proc(data: []byte, spec := DEFAULT_SPECIFICATION, parse_integers := false) -> bool {
  5. p := make_parser(data, spec, parse_integers, mem.nil_allocator())
  6. switch p.spec {
  7. case .JSON:
  8. return validate_object(&p)
  9. case .JSON5:
  10. return validate_value(&p)
  11. case .MJSON:
  12. #partial switch p.curr_token.kind {
  13. case .Ident, .String:
  14. return validate_object_body(&p, .EOF)
  15. }
  16. return validate_value(&p)
  17. }
  18. return validate_object(&p)
  19. }
  20. validate_object_key :: proc(p: ^Parser) -> bool {
  21. if p.spec != .JSON {
  22. if allow_token(p, .Ident) {
  23. return true
  24. }
  25. }
  26. err := expect_token(p, .String)
  27. return err == .None
  28. }
  29. validate_object_body :: proc(p: ^Parser, end_token: Token_Kind) -> bool {
  30. for p.curr_token.kind != end_token {
  31. if !validate_object_key(p) {
  32. return false
  33. }
  34. if parse_colon(p) != nil {
  35. return false
  36. }
  37. validate_value(p) or_return
  38. if parse_comma(p) {
  39. break
  40. }
  41. }
  42. return true
  43. }
  44. validate_object :: proc(p: ^Parser) -> bool {
  45. if err := expect_token(p, .Open_Brace); err != .None {
  46. return false
  47. }
  48. validate_object_body(p, .Close_Brace) or_return
  49. if err := expect_token(p, .Close_Brace); err != .None {
  50. return false
  51. }
  52. return true
  53. }
  54. validate_array :: proc(p: ^Parser) -> bool {
  55. if err := expect_token(p, .Open_Bracket); err != .None {
  56. return false
  57. }
  58. for p.curr_token.kind != .Close_Bracket {
  59. if !validate_value(p) {
  60. return false
  61. }
  62. if parse_comma(p) {
  63. break
  64. }
  65. }
  66. if err := expect_token(p, .Close_Bracket); err != .None {
  67. return false
  68. }
  69. return true
  70. }
  71. validate_value :: proc(p: ^Parser) -> bool {
  72. token := p.curr_token
  73. #partial switch token.kind {
  74. case .Null, .False, .True:
  75. advance_token(p)
  76. return true
  77. case .Integer, .Float:
  78. advance_token(p)
  79. return true
  80. case .String:
  81. advance_token(p)
  82. return is_valid_string_literal(token.text, p.spec)
  83. case .Open_Brace:
  84. return validate_object(p)
  85. case .Open_Bracket:
  86. return validate_array(p)
  87. case .Ident:
  88. if p.spec == .MJSON {
  89. advance_token(p)
  90. return true
  91. }
  92. return false
  93. case:
  94. if p.spec != .JSON {
  95. #partial switch token.kind {
  96. case .Infinity, .NaN:
  97. advance_token(p)
  98. return true
  99. }
  100. }
  101. }
  102. return false
  103. }