Refactor decoder input stream
[jansson.git] / src / pack_unpack.c
index 758e2f9..4fb8c1b 100644 (file)
@@ -10,6 +10,7 @@
 #include "jansson_private.h"
 
 typedef struct {
+    const char *start;
     const char *fmt;
     char token;
     json_error_t *error;
@@ -57,8 +58,12 @@ static void next_token(scanner_t *s)
 static void set_error(scanner_t *s, const char *fmt, ...)
 {
     va_list ap;
+    size_t pos;
     va_start(ap, fmt);
-    jsonp_error_vset(s->error, s->line, s->column, fmt, ap);
+
+    pos = (size_t)(s->fmt - s->start);
+    jsonp_error_vset(s->error, s->line, s->column, pos, fmt, ap);
+
     va_end(ap);
 }
 
@@ -441,23 +446,26 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags,
                       const char *fmt, va_list ap)
 {
     scanner_t s;
+    va_list ap_copy;
     json_t *value;
 
     jsonp_error_init(error, "");
 
     if(!fmt || !*fmt) {
-        jsonp_error_set(error, 1, 1, "Null or empty format string");
+        jsonp_error_set(error, -1, -1, 0, "Null or empty format string");
         return NULL;
     }
 
     s.error = error;
     s.flags = flags;
-    s.fmt = fmt;
+    s.fmt = s.start = fmt;
     s.line = 1;
     s.column = 0;
 
     next_token(&s);
-    value = pack(&s, &ap);
+    va_copy(ap_copy, ap);
+    value = pack(&s, &ap_copy);
+    va_end(ap_copy);
 
     next_token(&s);
     if(s.token) {
@@ -497,24 +505,29 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags,
                     const char *fmt, va_list ap)
 {
     scanner_t s;
+    va_list ap_copy;
 
     jsonp_error_init(error, "");
 
     if(!fmt || !*fmt) {
-        jsonp_error_set(error, 1, 1, "Null or empty format string");
+        jsonp_error_set(error, -1, -1, 0, "Null or empty format string");
         return -1;
     }
 
     s.error = error;
     s.flags = flags;
-    s.fmt = fmt;
+    s.fmt = s.start = fmt;
     s.line = 1;
     s.column = 0;
 
     next_token(&s);
 
-    if(unpack(&s, root, &ap))
+    va_copy(ap_copy, ap);
+    if(unpack(&s, root, &ap_copy)) {
+        va_end(ap_copy);
         return -1;
+    }
+    va_end(ap_copy);
 
     next_token(&s);
     if(s.token) {