Permalink
Browse files

initial merge/port of Florian Forster's yajl_tree implementation, alo…

…ng with a new utility routine yajl_tree_get() and an example
  • Loading branch information...
1 parent d2ec58b commit 668e787b1cdba118d73efc233e8a48306c2033d6 @lloyd committed Apr 22, 2011
Showing with 234 additions and 24 deletions.
  1. +1 −0 CMakeLists.txt
  2. +23 −0 example/CMakeLists.txt
  3. +3 −0 example/README.md
  4. +54 −0 example/parse_config.c
  5. +101 −0 example/sample.config
  6. +8 −1 src/api/yajl_tree.h
  7. +44 −23 src/yajl_tree.c
View
@@ -67,6 +67,7 @@ ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(test)
ADD_SUBDIRECTORY(reformatter)
ADD_SUBDIRECTORY(verify)
+ADD_SUBDIRECTORY(example)
INCLUDE(YAJLDoc.cmake)
View
@@ -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)
View
@@ -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.
View
@@ -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;
+}
View
@@ -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
+}
View
@@ -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.
View
@@ -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,15 +292,15 @@ 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;
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,31 +464,58 @@ 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)
return;
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 : */

0 comments on commit 668e787

Please sign in to comment.