Skip to content

Add support for JSON5 #211

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions reformatter/json_reformat.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,16 @@ static int reformat_boolean(void * ctx, int boolean)
GEN_AND_RETURN(yajl_gen_bool(g, boolean));
}

static int reformat_number(void * ctx, const char * s, size_t l)
static int reformat_integer(void * ctx, long long int i)
{
yajl_gen g = (yajl_gen) ctx;
GEN_AND_RETURN(yajl_gen_number(g, s, l));
GEN_AND_RETURN(yajl_gen_integer(g, i));
}

static int reformat_double(void * ctx, double d)
{
yajl_gen g = (yajl_gen) ctx;
GEN_AND_RETURN(yajl_gen_double(g, d));
}

static int reformat_string(void * ctx, const unsigned char * stringVal,
Expand Down Expand Up @@ -93,9 +99,9 @@ static int reformat_end_array(void * ctx)
static yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
reformat_integer,
reformat_double,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
Expand All @@ -109,6 +115,8 @@ usage(const char * progname)
{
fprintf(stderr, "%s: reformat json from stdin\n"
"usage: json_reformat [options]\n"
" -5 allow JSON5 input\n"
" -g generate JSON5 output\n"
" -e escape any forward slashes (for embedding in HTML)\n"
" -m minimize json rather than beautify (default)\n"
" -s reformat a stream of multiple json entites\n"
Expand Down Expand Up @@ -143,6 +151,12 @@ main(int argc, char ** argv)
unsigned int i;
for ( i=1; i < strlen(argv[a]); i++) {
switch (argv[a][i]) {
case '5':
yajl_config(hand, yajl_allow_json5, 1);
break;
case 'g':
yajl_gen_config(g, yajl_gen_json5, 1);
break;
case 'm':
yajl_gen_config(g, yajl_gen_beautify, 0);
break;
Expand Down
26 changes: 15 additions & 11 deletions src/api/yajl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
extern "C" {
#endif

/** A limit used by the generator API, YAJL_MAX_DEPTH is the maximum
* depth to which arrays and maps may be nested.
*/
#define YAJL_MAX_DEPTH 128

/* msft dll export gunk. To build a DLL on windows, you
Expand All @@ -38,33 +41,34 @@ extern "C" {
# if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 303
# define YAJL_API __attribute__ ((visibility("default")))
# else
/** Marks a yajl routine for export from the DLL/shared library. */
# define YAJL_API
# endif
#endif

/** pointer to a malloc function, supporting client overriding memory
* allocation routines */
/** Pointer to a malloc() function, supporting client overriding memory
* allocation routines. */
typedef void * (*yajl_malloc_func)(void *ctx, size_t sz);

/** pointer to a free function, supporting client overriding memory
* allocation routines */
/** Pointer to a free() function, supporting client overriding memory
* allocation routines. */
typedef void (*yajl_free_func)(void *ctx, void * ptr);

/** pointer to a realloc function which can resize an allocation. */
/** Pointer to a realloc() function which can resize an allocation. */
typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz);

/** A structure which can be passed to yajl_*_alloc routines to allow the
/** A structure which can be passed to yajl_*_alloc() routines to allow the
* client to specify memory allocation functions to be used. */
typedef struct
{
/** pointer to a function that can allocate uninitialized memory */
/** Pointer to a function that can allocate uninitialized memory. */
yajl_malloc_func malloc;
/** pointer to a function that can resize memory allocations */
/** Pointer to a function that can resize memory allocations. */
yajl_realloc_func realloc;
/** pointer to a function that can free memory allocated using
* reallocFunction or mallocFunction */
/** Pointer to a function that can free memory allocated using
* reallocFunction or mallocFunction. */
yajl_free_func free;
/** a context pointer that will be passed to above allocation routines */
/** A context pointer that will be passed to above allocation routines. */
void * ctx;
} yajl_alloc_funcs;

Expand Down
152 changes: 100 additions & 52 deletions src/api/yajl_gen.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,101 +29,146 @@
#ifdef __cplusplus
extern "C" {
#endif
/** generator status codes */
/** Generator status codes. */
typedef enum {
/** no error */
/** No error. */
yajl_gen_status_ok = 0,
/** at a point where a map key is generated, a function other than
* yajl_gen_string was called */
/** At a point where a map key is generated, a function other than
* yajl_gen_string() was called. */
yajl_gen_keys_must_be_strings,
/** YAJL's maximum generation depth was exceeded. see
* YAJL_MAX_DEPTH */
* \ref YAJL_MAX_DEPTH. */
yajl_max_depth_exceeded,
/** A generator function (yajl_gen_XXX) was called while in an error
* state */
/** A generator function (yajl_gen_XXX()) was called while in an error
* state. */
yajl_gen_in_error_state,
/** A complete JSON document has been generated */
/** A complete JSON document has been generated. */
yajl_gen_generation_complete,
/** yajl_gen_double was passed an invalid floating point value
/** yajl_gen_double() was passed an invalid floating point value
* (infinity or NaN). */
yajl_gen_invalid_number,
/** A print callback was passed in, so there is no internal
* buffer to get from */
* buffer to get from. */
yajl_gen_no_buf,
/** returned from yajl_gen_string() when the yajl_gen_validate_utf8
* option is enabled and an invalid was passed by client code.
/** Returned from yajl_gen_string() when the \ref yajl_gen_validate_utf8
* option is enabled and invalid UTF8 was passed by client code.
*/
yajl_gen_invalid_string
} yajl_gen_status;

/** an opaque handle to a generator */
/** An opaque handle to a generator */
typedef struct yajl_gen_t * yajl_gen;

/** a callback used for "printing" the results. */
/** A callback used for "printing" the results. */
typedef void (*yajl_print_t)(void * ctx,
const char * str,
size_t len);

/** configuration parameters for the parser, these may be passed to
* yajl_gen_config() along with option specific argument(s). In general,
* all configuration parameters default to *off*. */
/** Configuration parameters for the parser, these may be passed to
* yajl_gen_config() followed by option specific argument(s). In general,
* all boolean configuration parameters default to *off*. */
typedef enum {
/** generate indented (beautiful) output */
/**
* Generate indented (beautiful) output.
*
* yajl_gen_config() argument type: int (boolean)
*
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_beautify, 1); // Human format please
* \endcode
*/
yajl_gen_beautify = 0x01,
/**
* Set an indent string which is used when yajl_gen_beautify
* is enabled. Maybe something like \\t or some number of
* spaces. The default is four spaces ' '.
* Set the indent string which is used when \ref yajl_gen_beautify
* is enabled, which may only contain whitespace characters such as
* \c \\t or some number of spaces. The default is four spaces ' '.
*
* yajl_gen_config() argument type: const char *
*
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_indent_string, " "); // 2 spaces
* \endcode
*/
yajl_gen_indent_string = 0x02,
/**
* Set a function and context argument that should be used to
* output generated json. the function should conform to the
* yajl_print_t prototype while the context argument is a
* output the generated json. The function should conform to the
* \ref yajl_print_t prototype while the context argument may be any
* void * of your choosing.
*
* example:
* yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
* yajl_gen_config() arguments: \ref yajl_print_t, void *
*
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr);
* \endcode
*/
yajl_gen_print_callback = 0x04,
/**
* Normally the generator does not validate that strings you
* pass to it via yajl_gen_string() are valid UTF8. Enabling
* this option will cause it to do so.
*
* yajl_gen_config() argument type: int (boolean)
*
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_validate_utf8, 1); // Check UTF8
* \endcode
*/
yajl_gen_validate_utf8 = 0x08,
/**
* the forward solidus (slash or '/' in human) is not required to be
* The forward solidus (slash or '/' in human) is not required to be
* escaped in json text. By default, YAJL will not escape it in the
* iterest of saving bytes. Setting this flag will cause YAJL to
* always escape '/' in generated JSON strings.
*
* yajl_gen_config() argument type: int (boolean)
*/
yajl_gen_escape_solidus = 0x10
yajl_gen_escape_solidus = 0x10,
/**
* Special numbers such as NaN and Infinity cannot be represented in
* the original JSON, but are permitted in JSON5. Setting this flag
* allows YAJL to output the JSON5 representation of these special
* numbers instead of returning with an error, and to emit map keys
* that are valid javascript identifiers without quotes.
*
* yajl_gen_config() argument type: int (boolean)
*
* Example: \code{.cpp}
* yajl_gen_config(g, yajl_gen_json5, 1); // Output JSON5
* \endcode
*/
yajl_gen_json5 = 0x20,
} yajl_gen_option;

/** allow the modification of generator options subsequent to handle
* allocation (via yajl_alloc)
* \returns zero in case of errors, non-zero otherwise
/** Set generator options associated with a generator handle. See the
* \ref yajl_gen_option documentation for details of the available
* options and their arguments.
* \returns Zero in case of error, non-zero otherwise.
*/
YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...);
YAJL_API int yajl_gen_config(yajl_gen hand, yajl_gen_option opt, ...);

/** allocate a generator handle
* \param allocFuncs an optional pointer to a structure which allows
* the client to overide the memory allocation
* used by yajl. May be NULL, in which case
* malloc/free/realloc will be used.
/** Allocate a generator handle
* \param allocFuncs An optional pointer to a structure which allows the
* client to provide memory allocation functions for
* use by yajl. May be \c NULL to use the C runtime
* library's malloc(), free() and realloc().
*
* \returns an allocated handle on success, NULL on failure (bad params)
* \returns An allocated handle on success, \c NULL on failure (bad params)
*/
YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs);

/** free a generator handle */
YAJL_API void yajl_gen_free(yajl_gen handle);
/** Free a generator handle. */
YAJL_API void yajl_gen_free(yajl_gen hand);

YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number);
/** generate a floating point number. number may not be infinity or
* NaN, as these have no representation in JSON. In these cases the
* generator will return 'yajl_gen_invalid_number' */
/** Generate a floating point number.
* \param hand The generator handle.
* \param number The value to output. The values Infinity or NaN are
* only accepted if the \ref yajl_gen_json5 option is set,
* as these values have no legal representation in JSON;
* the generator will return \ref yajl_gen_invalid_number
* otherwise.
*/
YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number);
YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand,
const char * num,
Expand All @@ -138,26 +183,29 @@ extern "C" {
YAJL_API yajl_gen_status yajl_gen_array_open(yajl_gen hand);
YAJL_API yajl_gen_status yajl_gen_array_close(yajl_gen hand);

/** access the null terminated generator buffer. If incrementally
/** Access the zero-terminated generator buffer. If incrementally
* outputing JSON, one should call yajl_gen_clear to clear the
* buffer. This allows stream generation. */
YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand,
const unsigned char ** buf,
size_t * len);

/** clear yajl's output buffer, but maintain all internal generation
* state. This function will not "reset" the generator state, and is
/** Clear yajl's output buffer, but maintain all internal generation
* state. This function will not reset the generator state, and is
* intended to enable incremental JSON outputing. */
YAJL_API void yajl_gen_clear(yajl_gen hand);

/** Reset the generator state. Allows a client to generate multiple
* json entities in a stream. The "sep" string will be inserted to
* separate the previously generated entity from the current,
* NULL means *no separation* of entites (clients beware, generating
* multiple JSON numbers without a separator, for instance, will result in ambiguous output)
/** Reset the generator state. Allows a client to generate multiple
* JSON entities in a stream.
* \param hand The generator handle.
* \param sep This string will be inserted to separate the previously
* generated output from the following; passing \c NULL means
* *no separation* of entites (beware that generating
* multiple JSON numbers without a separator creates
* ambiguous output).
*
* Note: this call will not clear yajl's output buffer. This
* may be accomplished explicitly by calling yajl_gen_clear() */
* Note: This call does not clear yajl's output buffer, which must be
* accomplished explicitly by calling yajl_gen_clear(). */
YAJL_API void yajl_gen_reset(yajl_gen hand, const char * sep);

#ifdef __cplusplus
Expand Down
Loading