Explorar o código

Implement json_fprintf()

PUBLISHED_FROM=74a4d40d7b6234ad219020fc9c6815f15392020f
Бобби %!s(int64=8) %!d(string=hai) anos
pai
achega
ad17bf0e2c
Modificáronse 4 ficheiros con 95 adicións e 2 borrados
  1. 21 0
      README.md
  2. 46 0
      frozen.c
  3. 14 1
      frozen.h
  4. 14 1
      unit_test.c

+ 21 - 0
README.md

@@ -276,6 +276,27 @@ If top-level element is a scalar: `true`
 - type: `JSON_TYPE_TRUE`, name: `NULL`, path: `""`, value: `"true"`
 
 
+## `json_fprintf()`, `json_vfprintf()`
+
+```c
+/*
+ * Same as json_printf, but prints to a file.
+ * File is created if does not exist. File is truncated if already exists.
+ */
+int json_fprintf(const char *file_name, const char *fmt, ...);
+int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
+```
+
+## `json_fread()`
+
+```c
+/*
+ * Read the whole file in memory.
+ * Return malloc-ed file content, or NULL on error. The caller must free().
+ */
+char *json_fread(const char *file_name);
+```
+
 # Contributions
 
 To submit contributions, sign

+ 46 - 0
frozen.c

@@ -1016,3 +1016,49 @@ int json_scanf(const char *str, int len, const char *fmt, ...) {
   va_end(ap);
   return result;
 }
+
+int json_vfprintf(const char *file_name, const char *fmt, va_list ap) WEAK;
+int json_vfprintf(const char *file_name, const char *fmt, va_list ap) {
+  int res = -1;
+  FILE *fp = fopen(file_name, "w");
+  if (fp != NULL) {
+    struct json_out out = JSON_OUT_FILE(fp);
+    res = json_vprintf(&out, fmt, ap);
+    fputc('\n', fp);
+    fclose(fp);
+  }
+  return res;
+}
+
+int json_fprintf(const char *file_name, const char *fmt, ...) WEAK;
+int json_fprintf(const char *file_name, const char *fmt, ...) {
+  int result;
+  va_list ap;
+  va_start(ap, fmt);
+  result = json_vfprintf(file_name, fmt, ap);
+  va_end(ap);
+  return result;
+}
+
+char *json_fread(const char *path) WEAK;
+char *json_fread(const char *path) {
+  FILE *fp;
+  char *data = NULL;
+  if ((fp = fopen(path, "rb")) == NULL) {
+  } else if (fseek(fp, 0, SEEK_END) != 0) {
+    fclose(fp);
+  } else {
+    size_t size = ftell(fp);
+    data = (char *) malloc(size + 1);
+    if (data != NULL) {
+      fseek(fp, 0, SEEK_SET); /* Some platforms might not have rewind(), Oo */
+      if (fread(data, 1, size, fp) != size) {
+        free(data);
+        return NULL;
+      }
+      data[size] = '\0';
+    }
+    fclose(fp);
+  }
+  return data;
+}

+ 14 - 1
frozen.h

@@ -133,7 +133,7 @@ extern int json_printer_file(struct json_out *, const char *, size_t);
 #define JSON_OUT_FILE(fp)   \
   {                         \
     json_printer_file, {    \
-      { (void *) fp, 0, 0 } \
+      { (char *) fp, 0, 0 } \
     }                       \
   }
 
@@ -157,6 +157,13 @@ typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
 int json_printf(struct json_out *, const char *fmt, ...);
 int json_vprintf(struct json_out *, const char *fmt, va_list ap);
 
+/*
+ * Same as json_printf, but prints to a file.
+ * File is created if does not exist. File is truncated if already exists.
+ */
+int json_fprintf(const char *file_name, const char *fmt, ...);
+int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
+
 /*
  * Helper %M callback that prints contiguous C arrays.
  * Consumes void *array_ptr, size_t array_size, size_t elem_size, char *fmt
@@ -220,6 +227,12 @@ int json_unescape(const char *src, int slen, char *dst, int dlen);
  */
 int json_escape(struct json_out *out, const char *str, size_t str_len);
 
+/*
+ * Read the whole file in memory.
+ * Return malloc-ed file content, or NULL on error. The caller must free().
+ */
+char *json_fread(const char *file_name);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

+ 14 - 1
unit_test.c

@@ -28,10 +28,10 @@
 
 #include "frozen.c"
 
+#include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <stdbool.h>
 
 const char *tok_type_names[] = {
     "INVALID", "STRING",       "NUMBER",     "TRUE",        "FALSE",
@@ -648,6 +648,18 @@ static const char *test_eos(void) {
   return NULL;
 }
 
+static const char *test_fprintf(void) {
+  const char *fname = "a.json";
+  char *p;
+  ASSERT(json_fprintf(fname, "{a:%d}", 123) > 0);
+  ASSERT((p = json_fread(fname)) != NULL);
+  ASSERT(strcmp(p, "{\"a\":123}\n") == 0);
+  free(p);
+  remove(fname);
+  ASSERT(json_fread(fname) == NULL);
+  return NULL;
+}
+
 static const char *run_all_tests(void) {
   RUN_TEST(test_eos);
   RUN_TEST(test_scanf);
@@ -658,6 +670,7 @@ static const char *run_all_tests(void) {
   RUN_TEST(test_callback_api_long_path);
   RUN_TEST(test_json_unescape);
   RUN_TEST(test_parse_string);
+  RUN_TEST(test_fprintf);
   return NULL;
 }