Browse Source

Add helper json_{asprintf,vasprintf}

CL: Add helper json_{sprintf,vsprintf}

PUBLISHED_FROM=65a36a60225a5e71dca694c033e20e8362666655
Sergey Lyubka 7 years ago
parent
commit
b52e38f8eb
4 changed files with 80 additions and 0 deletions
  1. 18 0
      README.md
  2. 31 0
      frozen.c
  3. 14 0
      frozen.h
  4. 17 0
      unit_test.c

+ 18 - 0
README.md

@@ -293,6 +293,24 @@ int json_fprintf(const char *file_name, const char *fmt, ...);
 int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
 ```
 
+## `json_sprintf()`, `json_vsprintf()`
+
+```c
+/*
+ * Print JSON into an allocated 0-terminated string.
+ * Return allocated string, or NULL on error.
+ * Example:
+ *
+ * ```c
+ *   char *str = json_asprintf("{a:%H}", 3, "abc");
+ *   printf("%s\n", str);  // Prints "616263"
+ *   free(str);
+ * ```
+ */
+char *json_asprintf(const char *fmt, ...);
+char *json_vasprintf(const char *fmt, va_list ap);
+```
+
 ## `json_fread()`
 
 ```c

+ 31 - 0
frozen.c

@@ -1373,3 +1373,34 @@ void *json_next_elem(const char *s, int len, void *handle, const char *path,
                      int *idx, struct json_token *val) {
   return json_next(s, len, handle, path, NULL, val, idx);
 }
+
+static int json_sprinter(struct json_out *out, const char *str, size_t len) {
+  size_t old_len = out->u.buf.buf == NULL ? 0 : strlen(out->u.buf.buf);
+  size_t new_len = len + old_len;
+  char *p = (char *) realloc(out->u.buf.buf, new_len + 1);
+  if (p != NULL) {
+    memcpy(p + old_len, str, len);
+    p[new_len] = '\0';
+    out->u.buf.buf = p;
+  }
+  return len;
+}
+
+char *json_vasprintf(const char *fmt, va_list ap) WEAK;
+char *json_vasprintf(const char *fmt, va_list ap) {
+  struct json_out out;
+  memset(&out, 0, sizeof(out));
+  out.printer = json_sprinter;
+  json_vprintf(&out, fmt, ap);
+  return out.u.buf.buf;
+}
+
+char *json_asprintf(const char *fmt, ...) WEAK;
+char *json_asprintf(const char *fmt, ...) {
+  char *result = NULL;
+  va_list ap;
+  va_start(ap, fmt);
+  result = json_vasprintf(fmt, ap);
+  va_end(ap);
+  return result;
+}

+ 14 - 0
frozen.h

@@ -165,6 +165,20 @@ int json_vprintf(struct json_out *, const char *fmt, va_list ap);
 int json_fprintf(const char *file_name, const char *fmt, ...);
 int json_vfprintf(const char *file_name, const char *fmt, va_list ap);
 
+/*
+ * Print JSON into an allocated 0-terminated string.
+ * Return allocated string, or NULL on error.
+ * Example:
+ *
+ * ```c
+ *   char *str = json_sprintf("{a:%H}", 3, "abc");
+ *   printf("%s\n", str);  // Prints "616263"
+ *   free(str);
+ * ```
+ */
+char *json_asprintf(const char *fmt, ...);
+char *json_vasprintf(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

+ 17 - 0
unit_test.c

@@ -935,7 +935,24 @@ static const char *test_json_next(void) {
   return NULL;
 }
 
+static const char *test_json_sprintf(void) {
+  {
+    char *s = json_asprintf("%H", 3, "abc");
+    const char *result = "\"616263\"";
+    ASSERT(strcmp(s, result) == 0);
+    free(s);
+  }
+  {
+    char *s = json_asprintf("{a:%d,b:%V}", 77, "hi", 2);
+    const char *result = "{\"a\":77,\"b\":\"aGk=\"}";
+    ASSERT(strcmp(s, result) == 0);
+    free(s);
+  }
+  return NULL;
+}
+
 static const char *run_all_tests(void) {
+  RUN_TEST(test_json_sprintf);
   RUN_TEST(test_json_next);
   RUN_TEST(test_prettify);
   RUN_TEST(test_eos);