documentation updates

This commit is contained in:
Lloyd Hilaiel 2011-04-25 11:06:02 -06:00
parent 575226189f
commit c152ba0ab3
5 changed files with 60 additions and 210 deletions

View File

@ -34,20 +34,19 @@ main(void)
/* read the entire config file */
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
/* file read error handling */
if (rd == 0 && !feof(stdin)) {
fprintf(stderr, "error encountered on file read\n");
return 1;
}
if (rd >= sizeof(fileData) - 1) {
} else if (rd >= sizeof(fileData) - 1) {
fprintf(stderr, "config file too big\n");
return 1;
}
/* we have the whole config file in memory. let's parse it */
/* we have the whole config file in memory. let's parse it ... */
node = yajl_tree_parse((const char *) fileData, errbuf, sizeof(errbuf));
/* error handling */
/* parse error handling */
if (node == NULL) {
fprintf(stderr, "parse_error: ");
if (strlen(errbuf)) fprintf(stderr, " %s", errbuf);
@ -56,11 +55,11 @@ main(void)
return 1;
}
/* now extract a nested value from the config file */
/* ... and extract a nested value from the config file */
{
const char * path[] = { "Logging", "timeFormat", (const char *) 0 };
yajl_val v = yajl_tree_get(node, path, yajl_t_string);
if (v) printf("Logging/timeFomat: %s\n", YAJL_GET_STRING(v));
if (v) printf("%s/%s: %s\n", path[0], path[1], YAJL_GET_STRING(v));
else printf("no such node: %s/%s\n", path[0], path[1]);
}

View File

@ -518,7 +518,7 @@ EXCLUDE_SYMBOLS =
# directories that contain example code fragments that are included (see
# the \include command).
EXAMPLE_PATH =
EXAMPLE_PATH = ..
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp

View File

@ -16,7 +16,7 @@
/**
* \file yajl_parse.h
* Interface to YAJL's JSON parsing facilities.
* Interface to YAJL's JSON stream parsing facilities.
*/
#include <yajl/yajl_common.h>
@ -57,15 +57,19 @@ extern "C" {
* continue. If zero, the parse will be canceled and
* yajl_status_client_canceled will be returned from the parse.
*
* Note about handling of numbers:
* yajl will only convert numbers that can be represented in a double
* or a 64 bit (long long) int. All other numbers will be passed to the client
* in string form using the yajl_number callback. Furthermore, if
* yajl_number is not NULL, it will always be used to return numbers,
* that is yajl_integer and yajl_double will be ignored. If
* yajl_number is NULL but one of yajl_integer or yajl_double are
* defined, parsing of a number larger than is representable
* in a double or 64 bit integer will result in a parse error.
* \attention {
* A note about the handling of numbers:
*
* yajl will only convert numbers that can be represented in a
* double or a 64 bit (long long) int. All other numbers will
* be passed to the client in string form using the yajl_number
* callback. Furthermore, if yajl_number is not NULL, it will
* always be used to return numbers, that is yajl_integer and
* yajl_double will be ignored. If yajl_number is NULL but one
* of yajl_integer or yajl_double are defined, parsing of a
* number larger than is representable in a double or 64 bit
* integer will result in a parse error.
* }
*/
typedef struct {
int (* yajl_null)(void * ctx);

View File

@ -21,6 +21,11 @@
*
* \author Florian Forster
* \date August 2010
*
* This interface makes quick parsing and extraction of
* smallish JSON docs trivial:
*
* \include example/parse_config.c
*/
#ifndef YAJL_TREE_H
@ -50,17 +55,18 @@ typedef enum {
typedef struct yajl_val_s * yajl_val;
/**
* A JSON value:is one of the seven types above. For "string", "number",
* "object", and "array" additional data is available in the "data" union.
* The "YAJL_IS_*" and "YAJL_GET_*" macros below allow type checking
* and convenient value extraction.
* A JSON value representation capable of holding one of the seven
* types above. For "string", "number", "object", and "array"
* additional data is available in the union. The "YAJL_IS_*"
* and "YAJL_GET_*" macros below allow type checking and convenient
* value extraction.
*/
struct yajl_val_s
{
/** Type of the value contained. Use the "YAJL_IS_*" macors to check for a
* specific type. */
yajl_type type;
/** Type-specific data. Use the "YAJL_TO_*" macros to access these
/** Type-specific data. You may use the "YAJL_GET_*" macros to access these
* members. */
union
{
@ -76,7 +82,7 @@ struct yajl_val_s
} number;
struct {
const char **keys; /*< Array of keys */
yajl_val *values; /** Array of values. */
yajl_val *values; /*< Array of values. */
size_t len; /*< Number of key-value-pairs. */
} object;
struct {
@ -92,7 +98,7 @@ struct yajl_val_s
* Parses an null-terminated string containing JSON data and returns a pointer
* to the top-level value (root of the parse tree).
*
* \param input Pointer to a null-terminated string containing
* \param input Pointer to a null-terminated utf8 string containing
* JSON data.
* \param error_buffer Pointer to a buffer in which an error message will
* be stored if \em yajl_tree_parse fails, or
@ -112,9 +118,7 @@ YAJL_API yajl_val yajl_tree_parse (const char *input,
char *error_buffer, size_t error_buffer_size);
/**
* Free a parse tree.
*
* Recursively frees a pointer returned by "yajl_tree_parse".
* Free a parse tree returned by "yajl_tree_parse".
*
* \param v Pointer to a JSON value returned by "yajl_tree_parse". Passing NULL
* is valid and results in a no-op.
@ -122,7 +126,18 @@ YAJL_API yajl_val yajl_tree_parse (const char *input,
YAJL_API void yajl_tree_free (yajl_val v);
/**
* Access a nested value.
* Access a nested value inside a tree.
*
* \param parent the node under which you'd like to extract values.
* \param path A null terminated array of strings, each the name of an object key
* \param type the yajl_type of the object you seek, or yajl_t_any if any will do.
*
* \returns a pointer to the found value, or NULL if we came up empty.
*
* Future Ideas: it'd be nice to move path to a string and implement support for
* a teeny tiny micro language here, so you can extract array elements, do things
* like .first and .last, even .length. Inspiration from JSONPath and css selectors?
* No it wouldn't be fast, but that's not what this API is about.
*/
YAJL_API yajl_val yajl_tree_get(yajl_val parent, const char ** path, yajl_type type);

194
src/yajl
View File

@ -1,3 +1,8 @@
/**
\example reformatter/json_reformat.c
\example example/parse_config.c
*/
/*!
\mainpage Yet Another JSON Library (YAJL)
\author Lloyd Hilaiel
@ -5,9 +10,7 @@
Yet Another JSON Library (YAJL) is a small event-driven (SAX-style)
JSON parser written in ANSI C, and a small validating JSON
generator. It also includes a small simplified tree interface for
simplified parsing and extraction of data from smallish JSON documents.
YAJL is released under the permissive ISC license.
generator. YAJL is released under the permissive ISC license.
\section features Features
@ -17,186 +20,15 @@ YAJL is released under the permissive ISC license.
-# tiny
-# event driven
-# support for generating "beautified" JSON
-# includes
It also includes a small simplified tree interface for
simplified parsing and extraction of data from smallish JSON documents.
\section usage Usage
The following code sample is a complete JSON "reformating" program. It
demonstrates how to perform stream parsing and generation.
The following code sample is a complete JSON "reformating" program.
See <a href="reformatter_2json_reformat_8c-example.html">json_reformat.c</a> for a complete example of stream based parsing
and generation of JSON. See <a href="example_2parse_config_8c-example.html">parse_config.c</a> for an example of the
simplified tree interface.
\code
#include <yajl/yajl_parse.h>
#include <yajl/yajl_gen.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static int reformat_null(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_null(g);
}
static int reformat_boolean(void * ctx, int boolean)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_bool(g, boolean);
}
static int reformat_number(void * ctx, const char * s, size_t l)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_number(g, s, l);
}
static int reformat_string(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_map_key(void * ctx, const unsigned char * stringVal,
size_t stringLen)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen);
}
static int reformat_start_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_open(g);
}
static int reformat_end_map(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_map_close(g);
}
static int reformat_start_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_open(g);
}
static int reformat_end_array(void * ctx)
{
yajl_gen g = (yajl_gen) ctx;
return yajl_gen_status_ok == yajl_gen_array_close(g);
}
static yajl_callbacks callbacks = {
reformat_null,
reformat_boolean,
NULL,
NULL,
reformat_number,
reformat_string,
reformat_start_map,
reformat_map_key,
reformat_end_map,
reformat_start_array,
reformat_end_array
};
static void
usage(const char * progname)
{
fprintf(stderr, "%s: reformat json from stdin\n"
"usage: json_reformat [options]\n"
" -m minimize json rather than beautify (default)\n"
" -u allow invalid UTF8 inside strings during parsing\n",
progname);
exit(1);
}
int
main(int argc, char ** argv)
{
yajl_handle hand;
static unsigned char fileData[65536];
/* generator config */
yajl_gen g;
yajl_status stat;
size_t rd;
int retval = 0;
g = yajl_gen_alloc(NULL);
yajl_gen_config(g, yajl_gen_beautify, 1);
yajl_gen_config(g, yajl_gen_validate_utf8, 1);
/* ok. open file. let's read and parse */
hand = yajl_alloc(&callbacks, NULL, (void *) g);
/* and let's allow comments by default */
yajl_config(hand, yajl_allow_comments, 1);
/* check arguments.*/
int a = 1;
while ((a < argc) && (argv[a][0] == '-') && (strlen(argv[a]) > 1)) {
unsigned int i;
for ( i=1; i < strlen(argv[a]); i++) {
switch (argv[a][i]) {
case 'm':
yajl_gen_config(g, yajl_gen_beautify, 0);
break;
case 'u':
yajl_config(hand, yajl_dont_validate_strings, 1);
break;
default:
fprintf(stderr, "unrecognized option: '%c'\n\n",
argv[a][i]);
usage(argv[0]);
}
}
++a;
}
if (a < argc) {
usage(argv[0]);
}
for (;;) {
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
if (rd == 0) {
if (!feof(stdin)) {
fprintf(stderr, "error on file read.\n");
retval = 1;
}
break;
}
fileData[rd] = 0;
stat = yajl_parse(hand, fileData, rd);
if (stat != yajl_status_ok) break;
{
const unsigned char * buf;
size_t len;
yajl_gen_get_buf(g, &buf, &len);
fwrite(buf, 1, len, stdout);
yajl_gen_clear(g);
}
}
stat = yajl_complete_parse(hand);
if (stat != yajl_status_ok) {
unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
fprintf(stderr, "%s", (const char *) str);
yajl_free_error(hand, str);
retval = 1;
}
yajl_gen_free(g);
yajl_free(hand);
return retval;
}
\endcode
*/