Skip to content
This repository
Fetching contributors…

Cannot retrieve contributors at this time

file 188 lines (172 sloc) 6.096 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
/*
* $Id: json_tokener.h,v 1.10 2006/07/25 03:24:50 mclark Exp $
*
* Copyright (c) 2004, 2005 Metaparadigm Pte. Ltd.
* Michael Clark <michael@metaparadigm.com>
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See COPYING for details.
*
*/

#ifndef _json_tokener_h_
#define _json_tokener_h_

#include <stddef.h>
#include "json_object.h"

#ifdef __cplusplus
extern "C" {
#endif

enum json_tokener_error {
  json_tokener_success,
  json_tokener_continue,
  json_tokener_error_depth,
  json_tokener_error_parse_eof,
  json_tokener_error_parse_unexpected,
  json_tokener_error_parse_null,
  json_tokener_error_parse_boolean,
  json_tokener_error_parse_number,
  json_tokener_error_parse_array,
  json_tokener_error_parse_object_key_name,
  json_tokener_error_parse_object_key_sep,
  json_tokener_error_parse_object_value_sep,
  json_tokener_error_parse_string,
  json_tokener_error_parse_comment
};

enum json_tokener_state {
  json_tokener_state_eatws,
  json_tokener_state_start,
  json_tokener_state_finish,
  json_tokener_state_null,
  json_tokener_state_comment_start,
  json_tokener_state_comment,
  json_tokener_state_comment_eol,
  json_tokener_state_comment_end,
  json_tokener_state_string,
  json_tokener_state_string_escape,
  json_tokener_state_escape_unicode,
  json_tokener_state_boolean,
  json_tokener_state_number,
  json_tokener_state_array,
  json_tokener_state_array_add,
  json_tokener_state_array_sep,
  json_tokener_state_object_field_start,
  json_tokener_state_object_field,
  json_tokener_state_object_field_end,
  json_tokener_state_object_value,
  json_tokener_state_object_value_add,
  json_tokener_state_object_sep
};

struct json_tokener_srec
{
  enum json_tokener_state state, saved_state;
  struct json_object *obj;
  struct json_object *current;
  char *obj_field_name;
};

#define JSON_TOKENER_MAX_DEPTH 32

struct json_tokener
{
  char *str;
  struct printbuf *pb;
  int depth, is_double, st_pos, char_offset;
  enum json_tokener_error err;
  unsigned int ucs_char;
  char quote_char;
  struct json_tokener_srec stack[JSON_TOKENER_MAX_DEPTH];
};

/**
* Given an error previously returned by json_tokener_get_error(),
* return a human readable description of the error.
*
* @return a generic error message is returned if an invalid error value is provided.
*/
const char *json_tokener_error_desc(enum json_tokener_error jerr);

/**
* @b XXX do not use json_tokener_errors directly.
* After v0.10 this will be removed.
*
* See json_tokener_error_desc() instead.
*/
extern const char* json_tokener_errors[];

/**
* Retrieve the error caused by the last call to json_tokener_parse_ex(),
* or json_tokener_success if there is no error.
*
* When parsing a JSON string in pieces, if the tokener is in the middle
* of parsing this will return json_tokener_continue.
*
* See also json_tokener_error_desc().
*/
enum json_tokener_error json_tokener_get_error(struct json_tokener *tok);

extern struct json_tokener* json_tokener_new(void);
extern void json_tokener_free(struct json_tokener *tok);
extern void json_tokener_reset(struct json_tokener *tok);
extern struct json_object* json_tokener_parse(const char *str);
extern struct json_object* json_tokener_parse_verbose(const char *str, enum json_tokener_error *error);

/**
* Parse a string and return a non-NULL json_object if a valid JSON value
* is found. The string does not need to be a JSON object or array;
* it can also be a string, number or boolean value.
*
* A partial JSON string can be parsed. If the parsing is incomplete,
* NULL will be returned and json_tokener_get_error() will be return
* json_tokener_continue.
* json_tokener_parse_ex() can then be called with additional bytes in str
* to continue the parsing.
*
* If json_tokener_parse_ex() returns NULL and the error anything other than
* json_tokener_continue, a fatal error has occurred and parsing must be
* halted. Then tok object must not be re-used until json_tokener_reset() is
* called.
*
* When a valid JSON value is parsed, a non-NULL json_object will be
* returned. Also, json_tokener_get_error() will return json_tokener_success.
* Be sure to check the type with json_object_is_type() or
* json_object_get_type() before using the object.
*
* @b XXX this shouldn't use internal fields:
* Trailing characters after the parsed value do not automatically cause an
* error. It is up to the caller to decide whether to treat this as an
* error or to handle the additional characters, perhaps by parsing another
* json value starting from that point.
*
* Extra characters can be detected by comparing the tok->char_offset against
* the length of the last len parameter passed in.
*
* The tokener does \b not maintain an internal buffer so the caller is
* responsible for calling json_tokener_parse_ex with an appropriate str
* parameter starting with the extra characters.
*
* Example:
* @code
json_object *jobj = NULL;
const char *mystring = NULL;
int stringlen = 0;
enum json_tokener_error jerr;
do {
mystring = ... // get JSON string, e.g. read from file, etc...
stringlen = strlen(mystring);
jobj = json_tokener_parse_ex(tok, mystring, stringlen);
} while ((jerr = json_tokener_get_error(tok)) == json_tokener_continue);
if (jerr != json_tokener_success)
{
fprintf(stderr, "Error: %s\n", json_tokener_error_desc(jerr));
// Handle errors, as appropriate for your application.
}
if (tok->char_offset < stringlen) // XXX shouldn't access internal fields
{
// Handle extra characters after parsed object as desired.
// e.g. issue an error, parse another object from that point, etc...
}
// Success, use jobj here.

@endcode
*
* @param tok a json_tokener previously allocated with json_tokener_new()
* @param str an string with any valid JSON expression, or portion of. This does not need to be null terminated.
* @param len the length of str
*/
extern struct json_object* json_tokener_parse_ex(struct json_tokener *tok,
const char *str, int len);

#ifdef __cplusplus
}
#endif

#endif
Something went wrong with that request. Please try again.