diff options
author | Lloyd Hilaiel <lloyd@hilaiel.com> | 2011-04-22 15:39:40 -0600 |
---|---|---|
committer | Lloyd Hilaiel <lloyd@hilaiel.com> | 2011-04-22 15:39:40 -0600 |
commit | 668e787b1cdba118d73efc233e8a48306c2033d6 (patch) | |
tree | 38488d9afe9d58c47e1c6ed5c6f7ad1cbed5cd45 | |
parent | d2ec58b70b429b908d9f395ef378443b6101153b (diff) | |
download | yajl-668e787b1cdba118d73efc233e8a48306c2033d6.tar.gz |
initial merge/port of Florian Forster's yajl_tree implementation, along with a new utility routine yajl_tree_get() and an example
-rw-r--r-- | CMakeLists.txt | 1 | ||||
-rw-r--r-- | example/CMakeLists.txt | 23 | ||||
-rw-r--r-- | example/README.md | 3 | ||||
-rw-r--r-- | example/parse_config.c | 54 | ||||
-rw-r--r-- | example/sample.config | 101 | ||||
-rw-r--r-- | src/api/yajl_tree.h | 9 | ||||
-rw-r--r-- | src/yajl_tree.c | 67 |
7 files changed, 234 insertions, 24 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index d944472..5aafe40 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,6 +67,7 @@ ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(test) ADD_SUBDIRECTORY(reformatter) ADD_SUBDIRECTORY(verify) +ADD_SUBDIRECTORY(example) INCLUDE(YAJLDoc.cmake) diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt new file mode 100644 index 0000000..29cee35 --- /dev/null +++ b/example/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +SET (SRCS parse_config.c) + +# use the library we build, duh. +INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/../${YAJL_DIST_NAME}/include) +LINK_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/../${YAJL_DIST_NAME}/lib) + +ADD_EXECUTABLE(parse_config ${SRCS}) + +TARGET_LINK_LIBRARIES(parse_config yajl_s) diff --git a/example/README.md b/example/README.md new file mode 100644 index 0000000..20da388 --- /dev/null +++ b/example/README.md @@ -0,0 +1,3 @@ +This directory holds an example of how one might use yajl in the +simplest possible way, to do something like parse and extract values +from a configuration file. diff --git a/example/parse_config.c b/example/parse_config.c new file mode 100644 index 0000000..56d44f8 --- /dev/null +++ b/example/parse_config.c @@ -0,0 +1,54 @@ +#include <stdio.h> +#include <string.h> + +#include "yajl/yajl_tree.h" + +static unsigned char fileData[65536]; + +int +main(void) +{ + size_t rd; + yajl_value_t * node; + char errbuf[1024]; + + /* null plug buffers */ + fileData[0] = errbuf[0] = 0; + + /* read the entire config file */ + rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin); + + if (rd == 0 && !feof(stdin)) { + fprintf(stderr, "error encountered on file read\n"); + return 1; + } + + 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 */ + node = yajl_tree_parse((const char *) fileData, errbuf, sizeof(errbuf)); + + /* error handling */ + if (node == NULL) { + fprintf(stderr, "parse_error: "); + if (strlen(errbuf)) fprintf(stderr, " %s", errbuf); + else fprintf(stderr, "unknown error"); + fprintf(stderr, "\n"); + return 1; + } + + /* now extract a nested value from the config file */ + { + const char * path[] = { "Logging", "timeFormat", (const char *) 0 }; + yajl_value_t * v = yajl_tree_get(node, path, YAJL_TYPE_STRING); + if (v) printf("Logging/timeFomat: %s\n", YAJL_TO_STRING(v)); + else printf("no such node: %s/%s\n", path[0], path[1]); + } + + yajl_tree_free(node); + + return 0; +} diff --git a/example/sample.config b/example/sample.config new file mode 100644 index 0000000..deb6f7b --- /dev/null +++ b/example/sample.config @@ -0,0 +1,101 @@ +/* + * The configuration file for Yahoo! BrowserPlus, included in the YAJL + * tree as a sample configuration file for parsing. + * + * This is the configuration file for BrowserPlus + */ + +{ + // The type of build this is, which is accessible to JavaScript via + // BrowserPlus.getPlatformInfo(); + // Different build types should only differ in signatures accepted + // (BrowserPlus.crt) and configured distribution servers. + "BuildType": "ephemeral", + + // the base url for the "primary" distribution server. This server will + // be the single source of truth for Permissions, and will used to + // attain services + "DistServer": "http://browserplus.yahoo.com", + + // An array of "secondary" distribution servers, which will be checked + // in order for services if the primary server has no components + // available which match an issued require statement. + "SecondaryDistServers": [ + "http://first.fictional.server", + "http://second.fictional.server" + ], + + // Logging Setup + "Logging" : + { + // Log level. Values: "debug"|"info"|"warn"|"error"|"fatal"|"off" + "level": "BP_LOG_LEVEL", + + // Destination. Values: "file"|"console"|"win32" + "dest": "BP_LOG_DEST", + + // Log message layout. Values: "standard"|"source"|"raw" + "layout": "standard", + + // Time format. Values: "utc"|"local"|"msec" + "timeFormat": "utc", + + // File size in KB which will trigger a rollover + "fileRolloverKB": 2048, + + // Whether to send file logging from each service to a distinct file. + // Values: "combined"|"separate" + "serviceLogMode": "combined" + }, + + // Daemon setup + // Syntax: "Options": "option1 option2 etc" + // -fg run in foreground, log to console + "Options":"", + + // Auto-shutdown daemon if idle for this time. Use 0 for no auto-shutdown. + "MaxIdleSecs": 5, + + // At the end of each BrowserPlus session a small web request is made + // to yahoo to indicate that BrowserPlus was used. This report includes + // * information about the browser being used + // * an "installation id", which is a unique token that's generated + // the first time BrowserPlus runs. + // + // By design, there is *no information* in this request that gives + // Yahoo! information about: + // a) the site that the user is visiting (see, "url": false) + // b) who the user is (the installation token cannot be tracked to a + // specific user). + // + // This information is primarily captured to help Yahoo! understand + // adoption and usage of the BrowserPlus platform. + "UsageReporting": + { + "enabled": true, + "url": false, + "id": true + }, + + // "Breakpoints" is an array of strings holding named breakpoints. + // Platform code checks for specific entries at certain key points, and if + // a matching entry is found here a DebugBreak will be performed. + // For developers with Visual Studio installed, the DebugBreak will cause an + // opportunity to perform just-in-time attachment of an existing or new + // debugger instance. + // The currently-defined breakpoints are listed below: + // runServiceProcess - A DebugBreak is performed in the service + // "harness" just prior to service load. + // ax.FinalConstruct - A DebugBreak is performed at entry to + // FinalConstruct of the ActiveX plugin. + // PluginInit - Very early in the NPAPI plugin initialization. + // A wonderful spot to stop and set more + // breakpoints. + //"Breakpoints": ["runServiceProcess"], + + // How often we check for service updates. We guarantee at least this + // much time will pass between checks, though the true time may be + // much more if sites which use browserplus are not visited. + // The time is in seconds. + "ServiceUpdatePollPeriod": 86400 +} diff --git a/src/api/yajl_tree.h b/src/api/yajl_tree.h index 7c056f6..42ba6de 100644 --- a/src/api/yajl_tree.h +++ b/src/api/yajl_tree.h @@ -178,6 +178,13 @@ YAJL_API yajl_value_t *yajl_tree_parse (const char *input, YAJL_API void yajl_tree_free (yajl_value_t *v); /** + * Access a nested value. + */ +YAJL_API yajl_value_t * yajl_tree_get(yajl_value_t * parent, + const char ** path, + int type); + +/** * Checks if value is a string. * * Returns true if the value is a string, false otherwise. @@ -232,7 +239,7 @@ YAJL_API void yajl_tree_free (yajl_value_t *v); * Returns a pointer to a yajl_value_string_t or NULL if the value is not a * string. */ -#define YAJL_TO_STRING(v) (YAJL_IS_STRING(v) ? &(v)->data.string : NULL) +#define YAJL_TO_STRING(v) (YAJL_IS_STRING(v) ? (v)->data.string.value : NULL) /** * Convert value to number. diff --git a/src/yajl_tree.c b/src/yajl_tree.c index a4603c2..c1609e0 100644 --- a/src/yajl_tree.c +++ b/src/yajl_tree.c @@ -39,6 +39,8 @@ #include "api/yajl_tree.h" #include "api/yajl_parse.h" +#define YAJL_TO_STRING2(v) (YAJL_IS_STRING(v) ? &(v)->data.string : NULL) + #define STATUS_CONTINUE 1 #define STATUS_ABORT 0 @@ -290,7 +292,7 @@ static int context_add_value (context_t *ctx, yajl_value_t *v) /* {{{ */ } /* }}} int context_add_value */ static int handle_string (void *ctx, /* {{{ */ - const unsigned char *string, unsigned int string_length) + const unsigned char *string, size_t string_length) { yajl_value_t *v; yajl_value_string_t *s; @@ -298,7 +300,7 @@ static int handle_string (void *ctx, /* {{{ */ v = value_alloc (YAJL_TYPE_STRING); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); - s = YAJL_TO_STRING (v); + s = YAJL_TO_STRING2 (v); s->value = malloc (string_length + 1); if (s->value == NULL) @@ -313,13 +315,13 @@ static int handle_string (void *ctx, /* {{{ */ } /* }}} int handle_string */ static int handle_number (void *ctx, /* {{{ */ - const char *string, unsigned int string_length) + const char *string, size_t string_length) { yajl_value_t *v; yajl_value_number_t *n; char *endptr; - v = value_alloc (YAJL_TYPE_STRING); + v = value_alloc (YAJL_TYPE_NUMBER); if (v == NULL) RETURN_ERROR ((context_t *) ctx, STATUS_ABORT, "Out of memory"); n = YAJL_TO_NUMBER (v); @@ -448,12 +450,6 @@ yajl_value_t *yajl_tree_parse (const char *input, /* {{{ */ /* end array = */ handle_end_array }; - yajl_parser_config parser_config = - { - /* allowComments = */ 1, - /* checkUTF8 = */ 0 - }; - context_t ctx = { /* key = */ NULL, @@ -468,23 +464,50 @@ yajl_value_t *yajl_tree_parse (const char *input, /* {{{ */ if (error_buffer != NULL) memset (error_buffer, 0, error_buffer_size); - handle = yajl_alloc (&callbacks, &parser_config, - /* alloc funcs = */ NULL, &ctx); + handle = yajl_alloc (&callbacks, NULL, &ctx); + yajl_config(handle, yajl_allow_comments, 1); status = yajl_parse (handle, - (unsigned char *) input, - (unsigned int) strlen (input)); - if (status != yajl_status_ok) - return (NULL); - - status = yajl_parse_complete (handle); - if (status != yajl_status_ok) - return (NULL); + (unsigned char *) input, + strlen (input)); + status = yajl_complete_parse (handle); + if (status != yajl_status_ok) { + if (error_buffer != NULL && error_buffer_size > 0) { + snprintf( + error_buffer, error_buffer_size, + (char *) yajl_get_error(handle, 1, + (const unsigned char *) input, + strlen(input))); + } + yajl_free (handle); + return NULL; + } yajl_free (handle); return (ctx.root); } /* }}} yajl_value_t *yajl_tree_parse */ +yajl_value_t * yajl_tree_get(yajl_value_t * n, + const char ** path, + int type) +{ + if (!path) return NULL; + while (n && *path) { + unsigned int i; + + if (n->type != YAJL_TYPE_OBJECT) return NULL; + for (i = 0; i < n->data.object.children_num; i++) { + if (!strcmp(*path, n->data.object.keys[i]->data.string.value)) { + n = n->data.object.values[i]; + break; + } + } + if (i == n->data.object.children_num) return NULL; + path++; + } + return n; +} + void yajl_tree_free (yajl_value_t *v) /* {{{ */ { if (v == NULL) @@ -492,7 +515,7 @@ void yajl_tree_free (yajl_value_t *v) /* {{{ */ if (YAJL_IS_STRING (v)) { - yajl_value_string_t *s = YAJL_TO_STRING (v); + yajl_value_string_t *s = YAJL_TO_STRING2 (v); free (s->value); free (v); @@ -524,5 +547,3 @@ void yajl_tree_free (yajl_value_t *v) /* {{{ */ return; } } /* void yajl_tree_free */ - -/* vim: set sw=2 sts=2 et fdm=marker : */ |