added basic json encoding
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Jun 2021 00:55:43 +0000 (19:55 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sat, 19 Jun 2021 00:55:43 +0000 (19:55 -0500)
modules/json/encoder.onyx
modules/json/example.onyx
modules/json/parser.onyx

index 09d59843e04644472d2e4093886e20f237c8fead..eb08922b2b1a470ec47f97a67e5e790c421fdc01 100644 (file)
@@ -1 +1,121 @@
-package json
\ No newline at end of file
+package json
+
+use package core
+
+Encoding_Error :: enum {
+    None;
+    Unsupported_Type;
+}
+
+encode_string :: (v: $T, allocator := context.allocator) -> (str, Encoding_Error) {
+    stream := io.dynamic_string_stream_make(256);
+    writer := io.writer_make(^stream);
+    defer io.dynamic_string_stream_free(^stream);
+
+    err := encode(^writer, v);
+    if err != .None {
+        return "", err;
+    }
+
+    s := string.alloc_copy(io.dynamic_string_stream_to_str(^stream), allocator);
+    return s, .None;
+}
+
+encode :: #match {
+    (w: ^io.Writer, v: i32) -> Encoding_Error {
+        io.write_i32(w, ~~v);
+        return .None;
+    },
+
+    (w: ^io.Writer, v: i64) -> Encoding_Error {
+        io.write_i64(w, ~~v);
+        return .None;
+    },
+
+    (w: ^io.Writer, v: f32) -> Encoding_Error {
+        io.write_f32(w, ~~v);
+        return .None;
+    },
+
+    (w: ^io.Writer, v: f64) -> Encoding_Error {
+        io.write_f64(w, ~~v);
+        return .None;
+    },
+
+    (w: ^io.Writer, v: str) -> Encoding_Error {
+        io.write_escaped_str(w, v);
+        return .None;
+    },
+
+    (w: ^io.Writer, v: [..] $T) -> Encoding_Error {
+        io.write_byte(w, #char "[");
+
+        for i: v.count {
+            if i > 0 do io.write_byte(w, #char ",");
+
+            err := encode(w, v[i]);
+            if err != .None do return err;
+        }
+
+        io.write_byte(w, #char "]");
+        return .None;
+    },
+
+    (w: ^io.Writer, v: map.Map(str, $T)) -> Encoding_Error {
+        io.write_byte(w, #char "{");
+
+        for i: v.entries.count {
+            if i > 0 do io.write_byte(w, #char ",");
+            entry := v.entries[i];
+
+            io.write_escaped_str(w, entry.key);
+            io.write_byte(w, #char ":");
+
+            err := encode(w, entry.value);
+            if err != .None do return err;
+        }
+
+        io.write_byte(w, #char "}");
+        return .None;
+    },
+
+    (w: ^io.Writer, v: ^Value) -> Encoding_Error {
+        switch v.type {
+            case .Null    do io.write_str(w, "null");
+            case .Bool    do io.write(w, v->as_bool());
+            case .Integer do io.write(w, v->as_int());
+            case .Float   do io.write(w, v->as_float());
+            case .String  do   encode(w, v->as_str());
+            case .Array   do   encode(w, v->as_array());
+
+            case .Object {
+                io.write_byte(w, #char "{");
+                obj := cast(^Value_Object) v;
+
+                for i: obj.object_.count {
+                    if i > 0 do io.write_byte(w, #char ",");
+
+                    io.write_escaped_str(w, obj.object_[i].key);
+                    io.write_byte(w, #char ":");
+
+                    err := encode(w, obj.object_[i].value);
+                    if err != .None do return err;
+                }
+
+                io.write_byte(w, #char "}");
+            }
+
+            case #default {
+                return .Unsupported_Type;
+            }
+        }
+
+        return .None;
+    },
+
+
+    // Inserted after any of the #add_match directives
+    #precedence 1000 (w: ^io.Writer, v: $T) -> Encoding_Error {
+        return .Unsupported_Type;
+    }
+}
\ No newline at end of file
index 96ba62d4864400e38de92313c396a7a2470073e9..d45297c4222ae3f28c6e2adbce6ac329a057c897 100644 (file)
@@ -5,7 +5,7 @@
 use package core
 json :: package json
 
-json_string := "{ \"test\": \"\\tHello,\\nWorld!\", \"array\": [1,2,3,4,5,1423], \"sub\": { \"mem\": true } }";
+json_string := "{ \"test\": \"\\tHello,\\n\\\"World!\\\"\", \"array\": [1,2,3,4,5,1423], \"sub\": { \"mem\": true } }";
 
 main :: (args: [] cstr) {
     arena := alloc.arena.make(context.allocator, 4096);
@@ -20,7 +20,7 @@ main :: (args: [] cstr) {
     //     println(v["friends"][1]["name"]->as_str());
     // }
 
-    #if true {
+    #if false {
         value := decoded_json.root["array"];
         for v: value->as_array() {
             println(v->as_int());
@@ -30,5 +30,8 @@ main :: (args: [] cstr) {
 
         decoded_json.root["test"]->as_str() |> println();
     }
+
+    json.encode(^stdio.print_writer, decoded_json.root);
+    print("\n");
 }
     
\ No newline at end of file
index 25741d235bfe8232d8c75d033e5901cd71238bd3..52edaa65857c70897ccbb0d53568ca21bf1888cd 100644 (file)
@@ -208,7 +208,7 @@ parse_object :: (use parser: ^Parser) -> (^Value_Object, Error) {
 
         array.push(^value.object_, .{
             key = key,
-            value = elem            
+            value = elem
         });
 
         if !consume_token_if_next(parser, .Comma) {