json-parser.c revision 2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74c
/* Copyright (c) 2013-2016 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "str.h"
#include "istream.h"
#include "hex-dec.h"
#include "unichar.h"
#include "istream-jsonstr.h"
#include "json-parser.h"
enum json_state {
JSON_STATE_ROOT = 0,
};
struct json_parser {
enum json_parser_flags flags;
const char *error;
enum json_state state;
unsigned int nested_skip_count;
bool skipping;
bool seen_eof;
};
{
return -1;
if (ret == -2) {
return -1;
}
/* call it once more to finish any pending number */
} else if (ret <= 0) {
return ret;
} else {
}
}
return 1;
}
{
return;
if (size > 0) {
/* we skipped over some data and there's still data left.
no need to read() the next time. */
parser->highwater_offset = 0;
} else {
}
}
{
return json_parser_init_flags(input, 0);
}
enum json_parser_flags flags)
{
struct json_parser *parser;
if ((flags & JSON_PARSER_NO_ROOT_OBJECT) != 0)
return parser;
}
{
/* actual parser error */
*error_r = "Missing '}'";
} else {
}
}
{
case ' ':
case '\t':
case '\r':
case '\n':
break;
default:
return TRUE;
}
}
return FALSE;
}
{
return 1;
}
case '"':
case '\\':
case '/':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
break;
case 'u':
return -1;
break;
default:
return -1;
}
}
}
return 0;
}
const char **value_r)
{
return -1;
return json_skip_string(parser);
}
return 1;
}
else {
return 0;
case '"':
case '\\':
case '/':
break;
case 'b':
break;
case 'f':
break;
case 'n':
break;
case 'r':
break;
case 't':
break;
case 'u':
/* wait for more data */
return 0;
}
break;
default:
return -1;
}
}
}
return 0;
}
static int
{
return 0;
return -1;
return 1;
}
{
int ret;
return 0;
}
else {
return ret;
}
return 1;
}
{
int ret;
return ret;
/* frac */
return ret;
}
/* exp */
return 0;
return ret;
}
return 0;
return 1;
}
{
return -1;
/* everything matches so far, but we need more data */
return 0;
}
return -1;
return 1;
}
{
const enum json_state *nested_states;
unsigned count;
if (count == 1) {
/* closing root */
return 0;
/* we want to return the ending "]" or "}" to caller */
return 1;
}
/* closing a nested object */
if (parser->nested_skip_count > 0) {
return 0;
}
return 1;
}
static int
{
if (json_parse_denest(parser) == 0)
return 0;
return 1;
}
static int
{
if (json_parse_denest(parser) == 0)
return 0;
return 1;
}
{
}
static int
const char **value_r)
{
int ret;
if (!json_parse_whitespace(parser))
return -1;
case JSON_STATE_ROOT:
return -1;
}
return 0;
case JSON_STATE_OBJECT_VALUE:
case JSON_STATE_ARRAY_VALUE:
case JSON_STATE_VALUE:
return 0;
}
return 1;
return 0;
}
return 1;
}
*type_r = JSON_TYPE_TRUE;
*value_r = "true";
*value_r = "false";
*type_r = JSON_TYPE_NULL;
} else {
return -1;
}
if (ret == 0) {
/* a large string that we want to skip over. */
return 0;
}
return -1;
}
case JSON_STATE_OBJECT_VALUE:
break;
case JSON_STATE_ARRAY_VALUE:
break;
case JSON_STATE_VALUE:
break;
default:
i_unreached();
}
break;
case JSON_STATE_OBJECT_OPEN:
/* fall through */
case JSON_STATE_OBJECT_KEY:
return -1;
}
break;
case JSON_STATE_OBJECT_COLON:
return -1;
}
return 0;
case JSON_STATE_OBJECT_NEXT:
/* we skipped over the previous value */
}
return -1;
}
return 0;
case JSON_STATE_ARRAY_OPEN:
return 0;
case JSON_STATE_ARRAY_NEXT:
/* we skipped over the previous value */
}
return -1;
}
return 0;
if (json_skip_string(parser) <= 0)
return -1;
return 0;
case JSON_STATE_DONE:
return -1;
}
return skipping ? 0 : 1;
}
const char **value_r)
{
int ret;
;
if (ret > 0)
break;
return -1;
/* parsing probably failed because there wasn't enough input.
reset the error and try reading more. */
}
return ret;
}
{
}
{
}
static int
{
if (!json_parse_whitespace(parser))
return -1;
return -1;
}
if (!json_parse_whitespace(parser))
return -1;
}
return -1;
return 0;
}
{
int ret;
break;
return -1;
/* parsing probably failed because there wasn't enough input.
reset the error and try reading more. */
}
return ret;
}
{
switch (src) {
case '\b':
break;
case '\f':
break;
case '\n':
break;
case '\r':
break;
case '\t':
break;
case '"':
break;
case '\\':
break;
default:
if (src < 32)
else
break;
}
}
{
}
{
}
{
size_t i;
for (i = 0; i < size; i++)
}