json-parser.c revision 4e8e7a93628b4ed60aaaa47c6f72c1433f21e81d
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenjson_try_parse_next(struct json_parser *parser, enum json_type *type_r,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char **value_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int json_parser_read_more(struct json_parser *parser)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t cur_highwater = parser->input->v_offset +
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen i_assert(parser->highwater_offset <= cur_highwater);
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen if (parser->highwater_offset == cur_highwater) {
e8490a52a1bc71bc53034e68f464435684ad810fTimo Sirainen i_assert(parser->highwater_offset < cur_highwater);
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen parser->start = parser->data = i_stream_get_data(parser->input, &size);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic void json_parser_update_input_pos(struct json_parser *parser)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_skip(parser->input, parser->data - parser->start);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen parser->start = parser->data = i_stream_get_data(parser->input, &size);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* we skipped over some data and there's still data left.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen no need to read() the next time. */
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen parser->highwater_offset = parser->input->v_offset;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainenstruct json_parser *json_parser_init(struct istream *input)
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenint json_parser_deinit(struct json_parser **_parser, const char **error_r)
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen /* actual parser error */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else if (parser->input->stream_errno != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *error_r = t_strdup_printf("read(%s) failed: %m",
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainenstatic bool json_parse_whitespace(struct json_parser *parser)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen for (; parser->data != parser->end; parser->data++) {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainenstatic int json_parse_string(struct json_parser *parser, const char **value_r)
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen for (; parser->data != parser->end; parser->data++) {
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen /* wait for more data */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (*parser->data < '0' || *parser->data > '9')
dce5a2719df4fc64a8762d2aa94ba98dcf9cd6feTimo Sirainenstatic int json_parse_int(struct json_parser *parser)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenstatic int json_parse_number(struct json_parser *parser, const char **value_r)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (parser->data != parser->end && *parser->data == '.') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (*parser->data == 'e' || *parser->data == 'E')) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (*parser->data == '+' || *parser->data == '-')
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (parser->data == parser->end && !parser->input->eof)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic int json_parse_atom(struct json_parser *parser, const char *atom)
e63bdfedcf61e1a9ee21990140cbd0d0638da7e1Timo Sirainen /* everything matches so far, but we need more data */
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenjson_parse_object_close(struct json_parser *parser, enum json_type *type_r,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen const char **value_r)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen /* closing a nested object */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return json_try_parse_next(parser, type_r, value_r);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenjson_try_parse_next(struct json_parser *parser, enum json_type *type_r,
d6badc27cd6e8d3398877b6766cb0aaeef3a7800Timo Sirainen const char **value_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen parser->error = "Object doesn't begin with '{'";
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return json_try_parse_next(parser, type_r, value_r);
case JSON_STATE_OBJECT_VALUE:
if (ret == 0) {
case JSON_STATE_OBJECT_OPEN:
case JSON_STATE_OBJECT_KEY:
case JSON_STATE_OBJECT_COLON:
case JSON_STATE_DONE:
const char **value_r)
int ret;
return ret;