Implement json_load, json_loadf and json_loadfd
authorPetri Lehtinen <petri@digip.org>
Sat, 13 Jun 2009 19:28:26 +0000 (22:28 +0300)
committerPetri Lehtinen <petri@digip.org>
Mon, 15 Jun 2009 10:53:50 +0000 (13:53 +0300)
src/jansson.h
src/load.c

index bb15b6c..e6ece0c 100644 (file)
@@ -90,6 +90,7 @@ typedef struct {
 json_t *json_load(const char *path, json_error_t *error);
 json_t *json_loads(const char *input, json_error_t *error);
 json_t *json_loadf(FILE *input, json_error_t *error);
+json_t *json_loadfd(int fd, json_error_t *error);
 
 #define JSON_INDENT(n)   (n & 0xFF)
 #define JSON_SORT_KEYS   0x100
index 2104e8a..912f97d 100644 (file)
@@ -1,11 +1,15 @@
 #define _GNU_SOURCE
+#include <ctype.h>
+#include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
+#include <stdarg.h>
+#include <unistd.h>
 #include <assert.h>
 
 #include <jansson.h>
+#include "strbuffer.h"
 
 
 #define JSON_TOKEN_INVALID         -1
@@ -31,23 +35,35 @@ typedef struct {
 /*** error reporting ***/
 
 static void json_set_error(json_error_t *error, const json_lex *lex,
-                           const char *msg)
+                           const char *msg, ...)
 {
+    va_list ap;
+    char text[JSON_ERROR_TEXT_LENGTH];
+
     if(!error)
         return;
 
-    if(*lex->start)
+    va_start(ap, msg);
+    vsnprintf(text, JSON_ERROR_TEXT_LENGTH, msg, ap);
+    va_end(ap);
+
+    if(lex)
     {
-        int n = (int)(lex->input - lex->start);
         error->line = lex->line;
-        snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
-                 "%s near '%.*s'", msg, n, lex->start);
+        if(*lex->start)
+        {
+            int n = (int)(lex->input - lex->start);
+            snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
+                     "%s near '%.*s'", text, n, lex->start);
+        }
+        else
+        {
+            snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
+                     "%s near end of file", text);
+        }
     }
     else
-    {
-        snprintf(error->text, JSON_ERROR_TEXT_LENGTH,
-                 "%s near end of file", msg);
-    }
+        snprintf(error->text, JSON_ERROR_TEXT_LENGTH, "%s", msg);
 }
 
 
@@ -418,6 +434,25 @@ static json_t *json_parse(json_lex *lex, json_error_t *error)
     return json;
 }
 
+json_t *json_load(const char *path, json_error_t *error)
+{
+    json_t *result;
+    FILE *fp;
+
+    fp = fopen(path, "r");
+    if(!fp)
+    {
+        json_set_error(error, NULL, "unable to open %s: %s",
+                       path, strerror(errno));
+        return NULL;
+    }
+
+    result = json_loadf(fp, error);
+
+    fclose(fp);
+    return result;
+}
+
 json_t *json_loads(const char *string, json_error_t *error)
 {
     json_lex lex;
@@ -445,3 +480,71 @@ out:
     json_lex_close(&lex);
     return result;
 }
+
+#define BUFFER_SIZE 4096
+
+json_t *json_loadf(FILE *input, json_error_t *error)
+{
+    strbuffer_t strbuff;
+    char buffer[BUFFER_SIZE];
+    size_t length;
+    json_t *result = NULL;
+
+    strbuffer_init(&strbuff);
+
+    while(1)
+    {
+        length = fread(buffer, 1, BUFFER_SIZE, input);
+        if(length == 0)
+        {
+            if(ferror(input))
+            {
+                json_set_error(error, NULL, "read error");
+                goto out;
+            }
+            break;
+        }
+        if(strbuffer_append_bytes(&strbuff, buffer, length))
+            goto out;
+    }
+
+    result = json_loads(strbuffer_value(&strbuff), error);
+
+out:
+    strbuffer_close(&strbuff);
+    return result;
+}
+
+json_t *json_loadfd(int fd, json_error_t *error)
+{
+    strbuffer_t strbuff;
+    char buffer[BUFFER_SIZE];
+    ssize_t length;
+    json_t *result = NULL;
+
+    strbuffer_init(&strbuff);
+
+    while(1)
+    {
+        length = read(fd, buffer, BUFFER_SIZE);
+        if(length == -1)
+        {
+            json_set_error(error, NULL, "read error: %s", strerror(errno));
+            goto out;
+        }
+        else if(length == 0)
+            break;
+
+        if(strbuffer_append_bytes(&strbuff, buffer, length))
+        {
+            json_set_error(error, NULL, "error allocating memory");
+            goto out;
+        }
+    }
+
+    result = json_loads(strbuffer_value(&strbuff), error);
+
+out:
+    strbuffer_close(&strbuff);
+    return result;
+}