瀏覽代碼

jim: replace Jim_Sink and Jim_Write with String Builder

rexim 1 月之前
父節點
當前提交
1f56723fbd
共有 6 個文件被更改,包括 47 次插入104 次删除
  1. 1 1
      Makefile
  2. 3 4
      README.md
  3. 3 4
      examples/01_from_readme.c
  4. 6 8
      examples/02_binary_tree.c
  5. 14 22
      jim.h
  6. 20 65
      test.c

+ 1 - 1
Makefile

@@ -1,4 +1,4 @@
-CFLAGS=-Wall -Wextra -Wswitch-enum -ggdb
+CFLAGS=-Wall -Wextra -Wswitch-enum -ggdb -I./thirdparty/
 
 .PHONY: all
 all: examples test

+ 3 - 4
README.md

@@ -14,10 +14,7 @@ Immediate Mode JSON Serialization Library in C. Similar to [imgui](https://githu
 
 int main()
 {
-    Jim jim = {
-        .sink = stdout,
-        .write = (Jim_Write) fwrite,
-    };
+    Jim jim = {0};
 
     jim_object_begin(&jim);
         jim_member_key(&jim, "null");
@@ -61,6 +58,8 @@ int main()
         return -1;
     }
 
+    fwrite(jim.sink, jim.sink_count, 1, stdout);
+
     return 0;
 }
 ```

+ 3 - 4
examples/01_from_readme.c

@@ -5,10 +5,7 @@
 
 int main()
 {
-    Jim jim = {
-        .sink = stdout,
-        .write = (Jim_Write) fwrite,
-    };
+    Jim jim = {0};
 
     jim_object_begin(&jim);
         jim_member_key(&jim, "null");
@@ -52,5 +49,7 @@ int main()
         return -1;
     }
 
+    fwrite(jim.sink, jim.sink_count, 1, stdout);
+
     return 0;
 }

+ 6 - 8
examples/02_binary_tree.c

@@ -32,7 +32,7 @@ Node *generate_tree_of_fruits(size_t level_cur, size_t level_max)
     }
 }
 
-void print_node_as_json(Jim *jim, Node *node)
+void render_node_as_json(Jim *jim, Node *node)
 {
     if (node == NULL) {
         jim_null(jim);
@@ -42,10 +42,10 @@ void print_node_as_json(Jim *jim, Node *node)
         jim_string(jim, node->value);
 
         jim_member_key(jim, "left");
-        print_node_as_json(jim, node->left);
+        render_node_as_json(jim, node->left);
 
         jim_member_key(jim, "right");
-        print_node_as_json(jim, node->right);
+        render_node_as_json(jim, node->right);
         jim_object_end(jim);
     }
 }
@@ -53,10 +53,8 @@ void print_node_as_json(Jim *jim, Node *node)
 int main()
 {
     srand(time(0));
-    Jim jim = {
-        .sink = stdout,
-        .write = (Jim_Write) fwrite,
-    };
-    print_node_as_json(&jim, generate_tree_of_fruits(0, 4));
+    Jim jim = {0};
+    render_node_as_json(&jim, generate_tree_of_fruits(0, 4));
+    fwrite(jim.sink, jim.sink_count, 1, stdout);
     return 0;
 }

+ 14 - 22
jim.h

@@ -7,13 +7,10 @@
 
 #include <assert.h>
 #include <stdlib.h>
-
-typedef void* Jim_Sink;
-typedef size_t (*Jim_Write)(const void *ptr, size_t size, size_t nmemb, Jim_Sink sink);
+#include <string.h>
 
 typedef enum {
     JIM_OK = 0,
-    JIM_WRITE_ERROR,
     JIM_SCOPES_UNDERFLOW,
     JIM_OUT_OF_SCOPE_KEY,
     JIM_DOUBLE_KEY
@@ -33,9 +30,10 @@ typedef struct {
 } Jim_Scope;
 
 typedef struct {
-    Jim_Sink sink;
-    Jim_Write write;
     Jim_Error error;
+    char *sink;
+    size_t sink_count;
+    size_t sink_capacity;
     Jim_Scope *scopes;
     size_t scopes_count;
     size_t scopes_capacity;
@@ -63,15 +61,6 @@ void jim_object_end(Jim *jim);
 
 #ifdef JIM_IMPLEMENTATION
 
-static size_t jim_strlen(const char *s)
-{
-    size_t count = 0;
-    while (*(s + count)) {
-        count += 1;
-    }
-    return count;
-}
-
 static void jim_scope_push(Jim *jim, Jim_Scope_Kind kind)
 {
     if (jim->error == JIM_OK) {
@@ -113,16 +102,21 @@ static Jim_Scope *jim_current_scope(Jim *jim)
 static void jim_write(Jim *jim, const char *buffer, size_t size)
 {
     if (jim->error == JIM_OK) {
-        if (jim->write(buffer, 1, size, jim->sink) < size) {
-            jim->error = 1;
+        while (jim->sink_count + size >= jim->sink_capacity) {
+            // TODO: rename JIM_SCOPES_CAPACITY to something else since it's used by both sink and scopes
+            if (jim->sink_capacity == 0) jim->sink_capacity = JIM_SCOPES_CAPACITY;
+            else jim->sink_capacity *= 2;
+            jim->sink = realloc(jim->sink, sizeof(*jim->sink)*jim->sink_capacity);
         }
+        memcpy(jim->sink + jim->sink_count, buffer, size);
+        jim->sink_count += size;
     }
 }
 
 static void jim_write_cstr(Jim *jim, const char *cstr)
 {
     if (jim->error == JIM_OK) {
-        jim_write(jim, cstr, jim_strlen(cstr));
+        jim_write(jim, cstr, strlen(cstr));
     }
 }
 
@@ -166,8 +160,6 @@ const char *jim_error_string(Jim_Error error)
     switch (error) {
     case JIM_OK:
         return "There is no error. The developer of this software just had a case of \"Task failed successfully\" https://i.imgur.com/Bdb3rkq.jpg - Please contact the developer and tell them that they are very lazy for not checking errors properly.";
-    case JIM_WRITE_ERROR:
-        return "Write error";
     case JIM_SCOPES_UNDERFLOW:
         return "Stack of Scopes Underflow";
     case JIM_OUT_OF_SCOPE_KEY:
@@ -319,7 +311,7 @@ void jim_string_sized(Jim *jim, const char *str, size_t size)
 void jim_string(Jim *jim, const char *str)
 {
     if (jim->error == JIM_OK) {
-        jim_string_sized(jim, str, jim_strlen(str));
+        jim_string_sized(jim, str, strlen(str));
     }
 }
 
@@ -354,7 +346,7 @@ void jim_object_begin(Jim *jim)
 void jim_member_key(Jim *jim, const char *str)
 {
     if (jim->error == JIM_OK) {
-        jim_member_key_sized(jim, str, jim_strlen(str));
+        jim_member_key_sized(jim, str, strlen(str));
     }
 }
 

+ 20 - 65
test.c

@@ -4,45 +4,12 @@
 
 #define JIM_IMPLEMENTATION
 #include "./jim.h"
+#define NOB_IMPLEMENTATION
+#define NOB_STRIP_PREFIX
+#include "./nob.h"
 
 #include "./test_expected.h"
 
-#define ARRAY_LEN(xs) (sizeof(xs) / sizeof((xs)[0]))
-
-typedef struct {
-    size_t capacity;
-    size_t size;
-    char *data;
-} Buffer;
-
-void buffer_clean(Buffer *buffer)
-{
-    buffer->size = 0;
-}
-
-size_t buffer_write(const void *ptr, size_t size, size_t nmemb,
-                    Buffer *sink)
-{
-    size_t esize = size * nmemb; // effective size
-
-    if (sink->size + esize <= sink->capacity) {
-        memcpy(sink->data + sink->size,
-               ptr,
-               esize);
-        sink->size += esize;
-        return esize;
-    } else {
-        return 0;
-    }
-}
-
-static char static_memory_for_buffer[1024];
-
-static Buffer buffer = {
-    .capacity = sizeof(static_memory_for_buffer),
-    .data = static_memory_for_buffer
-};
-
 void null_case(Jim *jim)
 {
     jim_array_begin(jim);
@@ -144,54 +111,42 @@ const Test_Case test_cases[] = {
     TEST_CASE(object_case),
 };
 
-void record(const char *header_path)
+bool record(const char *header_path)
 {
-    FILE *stream = fopen(header_path, "w");
-
-    Jim jim_stream = {
-        .sink = stream,
-        .write = (Jim_Write) fwrite,
-    };
+    Jim jim_stream = {0};
+    Jim jim_buffer = {0};
 
-    Jim jim_buffer = {
-        .sink = &buffer,
-        .write = (Jim_Write) buffer_write,
-    };
-
-    fprintf(stream, "const char *test_cases_expected[] = {\n");
+    jim_write_cstr(&jim_stream, "const char *test_cases_expected[] = {\n");
     for (size_t i = 0; i < ARRAY_LEN(test_cases); ++i) {
-        buffer_clean(&buffer);
+        jim_buffer.sink_count = 0;
         test_cases[i].run(&jim_buffer);
-        fprintf(stream, "    ");
-        jim_string_sized(&jim_stream, buffer.data, buffer.size);
-        fprintf(stream, ",\n");
+        jim_write_cstr(&jim_stream, "    ");
+        jim_string_sized(&jim_stream, jim_buffer.sink, jim_buffer.sink_count);
+        jim_write_cstr(&jim_stream, ",\n");
     }
-    fprintf(stream, "};\n");
-
-    fclose(stream);
+    jim_write_cstr(&jim_stream, "};\n");
 
+    if (!write_entire_file(header_path, jim_stream.sink, jim_stream.sink_count)) return false;
     printf("Updated %s\n", header_path);
+    return true;
 }
 
 void test(void)
 {
-    Jim jim_buffer = {
-        .sink = &buffer,
-        .write = (Jim_Write) buffer_write,
-    };
+    Jim jim_buffer = {0};
 
     for (size_t i = 0; i < ARRAY_LEN(test_cases); ++i) {
         printf("%s ... ", test_cases[i].name);
 
-        buffer_clean(&buffer);
+        jim_buffer.sink_count = 0;
         test_cases[i].run(&jim_buffer);
 
-        if (buffer.size != strlen(test_cases_expected[i])
-                || memcmp(buffer.data, test_cases_expected[i], buffer.size) != 0) {
+        if (jim_buffer.sink_count != strlen(test_cases_expected[i])
+                || memcmp(jim_buffer.sink, test_cases_expected[i], jim_buffer.sink_count) != 0) {
             printf("FAILED!\n");
             printf("Expected: %s\n", test_cases_expected[i]);
             printf("Actual:   ");
-            fwrite(buffer.data, 1, buffer.size, stdout);
+            fwrite(jim_buffer.sink, jim_buffer.sink_count, 1, stdout);
             printf("\n");
             exit(1);
         }
@@ -204,7 +159,7 @@ int main(int argc, char **argv)
 {
     if (argc >= 2) {
         if (strcmp(argv[1], "record") == 0) {
-            record("test_expected.h");
+            if (!record("test_expected.h")) return 1;
         } else {
             fprintf(stderr, "Usage: ./test [record]\n");
             fprintf(stderr, "ERROR: unknown subcommand %s.\n", argv[1]);