208 lines
7.0 KiB
C
208 lines
7.0 KiB
C
/*
|
|
* Copyright (C) 2009 Vincent Hanquez <vincent@snarc.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation; version 2.1 or version 3.0 only.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*/
|
|
|
|
#ifndef JSON_H
|
|
#define JSON_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
#define JSON_MAJOR 0
|
|
#define JSON_MINOR 7
|
|
#define JSON_VERSION (JSON_MAJOR * 100 + JSON_MINOR)
|
|
|
|
typedef enum
|
|
{
|
|
JSON_NONE,
|
|
JSON_ARRAY_BEGIN,
|
|
JSON_OBJECT_BEGIN,
|
|
JSON_ARRAY_END,
|
|
JSON_OBJECT_END,
|
|
JSON_INT,
|
|
JSON_FLOAT,
|
|
JSON_STRING,
|
|
JSON_KEY,
|
|
JSON_TRUE,
|
|
JSON_FALSE,
|
|
JSON_NULL,
|
|
} json_type;
|
|
|
|
typedef enum
|
|
{
|
|
/* SUCCESS = 0 */
|
|
/* running out of memory */
|
|
JSON_ERROR_NO_MEMORY = 1,
|
|
/* character < 32, except space newline tab */
|
|
JSON_ERROR_BAD_CHAR,
|
|
/* trying to pop more object/array than pushed on the stack */
|
|
JSON_ERROR_POP_EMPTY,
|
|
/* trying to pop wrong type of mode. popping array in object mode, vice versa */
|
|
JSON_ERROR_POP_UNEXPECTED_MODE,
|
|
/* reach nesting limit on stack */
|
|
JSON_ERROR_NESTING_LIMIT,
|
|
/* reach data limit on buffer */
|
|
JSON_ERROR_DATA_LIMIT,
|
|
/* comment are not allowed with current configuration */
|
|
JSON_ERROR_COMMENT_NOT_ALLOWED,
|
|
/* unexpected char in the current parser context */
|
|
JSON_ERROR_UNEXPECTED_CHAR,
|
|
/* unicode low surrogate missing after high surrogate */
|
|
JSON_ERROR_UNICODE_MISSING_LOW_SURROGATE,
|
|
/* unicode low surrogate missing without previous high surrogate */
|
|
JSON_ERROR_UNICODE_UNEXPECTED_LOW_SURROGATE,
|
|
/* found a comma not in structure (array/object) */
|
|
JSON_ERROR_COMMA_OUT_OF_STRUCTURE,
|
|
/* callback returns error */
|
|
JSON_ERROR_CALLBACK,
|
|
} json_error;
|
|
|
|
#define LIBJSON_DEFAULT_STACK_SIZE 256
|
|
#define LIBJSON_DEFAULT_BUFFER_SIZE 4096
|
|
|
|
typedef int (*json_parser_callback)(void *userdata, int type, const char *data, uint32_t length);
|
|
typedef int (*json_printer_callback)(void *userdata, const char *s, uint32_t length);
|
|
|
|
typedef struct {
|
|
uint32_t buffer_initial_size;
|
|
uint32_t max_nesting;
|
|
uint32_t max_data;
|
|
int allow_c_comments;
|
|
int allow_yaml_comments;
|
|
void * (*user_calloc)(size_t nmemb, size_t size);
|
|
void * (*user_realloc)(void *ptr, size_t size);
|
|
} json_config;
|
|
|
|
typedef struct json_parser {
|
|
json_config config;
|
|
|
|
/* SAJ callback */
|
|
json_parser_callback callback;
|
|
void *userdata;
|
|
|
|
/* parser state */
|
|
uint8_t state;
|
|
uint8_t save_state;
|
|
uint8_t expecting_key;
|
|
uint16_t unicode_multi;
|
|
json_type type;
|
|
|
|
/* state stack */
|
|
uint8_t *stack;
|
|
uint32_t stack_offset;
|
|
uint32_t stack_size;
|
|
|
|
/* parse buffer */
|
|
char *buffer;
|
|
uint32_t buffer_size;
|
|
uint32_t buffer_offset;
|
|
} json_parser;
|
|
|
|
typedef struct json_printer {
|
|
json_printer_callback callback;
|
|
void *userdata;
|
|
|
|
char *indentstr;
|
|
int indentlevel;
|
|
int afterkey;
|
|
int enter_object;
|
|
int first;
|
|
} json_printer;
|
|
|
|
/** json_parser_init initialize a parser structure taking a config,
|
|
* a config and its userdata.
|
|
* return JSON_ERROR_NO_MEMORY if memory allocation failed or SUCCESS. */
|
|
int json_parser_init(json_parser *parser, json_config *cfg,
|
|
json_parser_callback callback, void *userdata);
|
|
|
|
/** json_parser_free freed memory structure allocated by the parser */
|
|
int json_parser_free(json_parser *parser);
|
|
|
|
/** json_parser_string append a string s with a specific length to the parser
|
|
* return 0 if everything went ok, a JSON_ERROR_* otherwise.
|
|
* the user can supplied a valid processed pointer that will
|
|
* be fill with the number of processed characters before returning */
|
|
int json_parser_string(json_parser *parser, const char *string,
|
|
uint32_t length, uint32_t *processed);
|
|
|
|
/** json_parser_char append one single char to the parser
|
|
* return 0 if everything went ok, a JSON_ERROR_* otherwise */
|
|
int json_parser_char(json_parser *parser, unsigned char next_char);
|
|
|
|
/** json_parser_is_done return 0 is the parser isn't in a finish state. !0 if it is */
|
|
int json_parser_is_done(json_parser *parser);
|
|
|
|
/** json_print_init initialize a printer context. always succeed */
|
|
int json_print_init(json_printer *printer, json_printer_callback callback, void *userdata);
|
|
|
|
/** json_print_free free a printer context
|
|
* doesn't do anything now, but in future print_init could allocate memory */
|
|
int json_print_free(json_printer *printer);
|
|
|
|
/** json_print_pretty pretty print the passed argument (type/data/length). */
|
|
int json_print_pretty(json_printer *printer, int type, const char *data, uint32_t length);
|
|
|
|
/** json_print_raw prints without eye candy the passed argument (type/data/length). */
|
|
int json_print_raw(json_printer *printer, int type, const char *data, uint32_t length);
|
|
|
|
/** json_print_args takes multiple types and pass them to the printer function
|
|
* array, object and constants doesn't take a string and length argument.
|
|
* int, float, key, string need to be followed by a pointer to char and then a length.
|
|
* if the length argument is -1, then the strlen function will use on the string argument.
|
|
* the function call should always be terminated by -1 */
|
|
int json_print_args(json_printer *, int (*f)(json_printer *, int, const char *, uint32_t), ...);
|
|
|
|
/** callback from the parser_dom callback to create object and array */
|
|
typedef void * (*json_parser_dom_create_structure)(int, int);
|
|
|
|
/** callback from the parser_dom callback to create data values */
|
|
typedef void * (*json_parser_dom_create_data)(int, const char *, uint32_t);
|
|
|
|
/** callback from the parser helper callback to append a value to an object or array value
|
|
* append(parent, key, key_length, val); */
|
|
typedef int (*json_parser_dom_append)(void *, char *, uint32_t, void *);
|
|
|
|
/** the json_parser_dom permits to create a DOM like tree easily through the
|
|
* use of 3 callbacks where the user can choose the representation of the JSON values */
|
|
typedef struct json_parser_dom
|
|
{
|
|
/* object stack */
|
|
struct stack_elem { void *val; char *key; uint32_t key_length; } *stack;
|
|
uint32_t stack_size;
|
|
uint32_t stack_offset;
|
|
|
|
/* overridable memory allocator */
|
|
void * (*user_calloc)(size_t nmemb, size_t size);
|
|
void * (*user_realloc)(void *ptr, size_t size);
|
|
|
|
/* returned root structure (object or array) */
|
|
void *root_structure;
|
|
|
|
/* callbacks */
|
|
json_parser_dom_create_structure create_structure;
|
|
json_parser_dom_create_data create_data;
|
|
json_parser_dom_append append;
|
|
} json_parser_dom;
|
|
|
|
/** initialize a parser dom structure with the necessary callbacks */
|
|
int json_parser_dom_init(json_parser_dom *helper,
|
|
json_parser_dom_create_structure create_structure,
|
|
json_parser_dom_create_data create_data,
|
|
json_parser_dom_append append);
|
|
/** free memory allocated by the DOM callback helper */
|
|
int json_parser_dom_free(json_parser_dom *ctx);
|
|
|
|
/** helper to parser callback that arrange parsing events into comprehensive JSON data structure */
|
|
int json_parser_dom_callback(void *userdata, int type, const char *data, uint32_t length);
|
|
|
|
#endif /* JSON_H */
|