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; if(!fmt || !*fmt) { jsonp_error_init(error, "<format>"); jsonp_error_set(error, -1, -1, 0, "NULL or empty format string"); return NULL; } jsonp_error_init(error, NULL); scanner_init(&s, error, flags, fmt); next_token(&s); va_copy(ap_copy, ap); value = pack(&s, &ap_copy); va_end(ap_copy); if(!value) return NULL; next_token(&s); if(s.token) { json_decref(value); set_error(&s, "<format>", "Garbage after format string"); return NULL; } return value; }
static void error_set(json_error_t *error, const lex_t *lex, const char *msg, ...) { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; char msg_with_context[JSON_ERROR_TEXT_LENGTH]; int line = -1, col = -1; size_t pos = 0; const char *result = msg_text; if(!error) return; va_start(ap, msg); vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap); msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; va_end(ap); if(lex) { const char *saved_text = strbuffer_value(&lex->saved_text); line = lex->stream.line; col = lex->stream.column; pos = lex->stream.position; if(saved_text && saved_text[0]) { if(lex->saved_text.length <= 20) { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", msg_text, saved_text); msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; } } else { if(lex->stream.state == STREAM_STATE_ERROR) { /* No context for UTF-8 decoding errors */ result = msg_text; } else { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file", msg_text); msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; } } } jsonp_error_set(error, line, col, pos, "%s", result); }
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; if(!root) { jsonp_error_init(error, "<root>"); jsonp_error_set(error, -1, -1, 0, "NULL root value"); return -1; } if(!fmt || !*fmt) { jsonp_error_init(error, "<format>"); jsonp_error_set(error, -1, -1, 0, "NULL or empty format string"); return -1; } jsonp_error_init(error, NULL); scanner_init(&s, error, flags, fmt); next_token(&s); 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) { set_error(&s, "<format>", "Garbage after format string"); return -1; } return 0; }
static void error_set(json_error_t *error, const lex_t *lex, const char *msg, ...) { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; int line = -1, col = -1; const char *result = msg_text; if(!error) return; va_start(ap, msg); vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap); va_end(ap); if(lex) { const char *saved_text = strbuffer_value(&lex->saved_text); char msg_with_context[JSON_ERROR_TEXT_LENGTH]; line = lex->line; if(saved_text && saved_text[0]) { if(lex->saved_text.length <= 20) { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", msg_text, saved_text); result = msg_with_context; } } else { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file", msg_text); result = msg_with_context; } } jsonp_error_set(error, line, col, "%s", result); }
static void error_set(json_error_t *error, stream_t *stream, const char *msg, ...) { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; size_t pos = 0; const char *result = msg_text; if(!error) return; if (stream) pos = stream->stream_pos + stream->pos; va_start(ap, msg); vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap); va_end(ap); jsonp_error_set(error, -1, -1, pos, "%s", result); }