summaryrefslogtreecommitdiff
path: root/jcnf/yajl
diff options
context:
space:
mode:
Diffstat (limited to 'jcnf/yajl')
-rw-r--r--jcnf/yajl/COPYING29
-rw-r--r--jcnf/yajl/ChangeLog88
-rw-r--r--jcnf/yajl/Jamfile30
-rw-r--r--jcnf/yajl/Makefile.am13
-rw-r--r--jcnf/yajl/README68
-rw-r--r--jcnf/yajl/TODO9
-rw-r--r--jcnf/yajl/YAJL.dxy1258
-rw-r--r--jcnf/yajl/YAJLDoc.cmake26
-rw-r--r--jcnf/yajl/afiles84
-rw-r--r--jcnf/yajl/cases/array.json6
-rw-r--r--jcnf/yajl/cases/array.json.gold22
-rw-r--r--jcnf/yajl/cases/bogus_char.json4
-rw-r--r--jcnf/yajl/cases/bogus_char.json.gold9
-rw-r--r--jcnf/yajl/cases/codepoints_from_unicode_org.json1
-rw-r--r--jcnf/yajl/cases/codepoints_from_unicode_org.json.gold1
-rw-r--r--jcnf/yajl/cases/dc_simple_with_comments.json11
-rw-r--r--jcnf/yajl/cases/dc_simple_with_comments.json.gold4
-rw-r--r--jcnf/yajl/cases/deep_arrays.json1
-rw-r--r--jcnf/yajl/cases/deep_arrays.json.gold2048
-rw-r--r--jcnf/yajl/cases/difficult_json_c_test_case.json1
-rw-r--r--jcnf/yajl/cases/difficult_json_c_test_case.json.gold35
-rw-r--r--jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json1
-rw-r--r--jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json.gold35
-rw-r--r--jcnf/yajl/cases/doubles.json1
-rw-r--r--jcnf/yajl/cases/doubles.json.gold6
-rw-r--r--jcnf/yajl/cases/empty_array.json1
-rw-r--r--jcnf/yajl/cases/empty_array.json.gold2
-rw-r--r--jcnf/yajl/cases/escaped_bulgarian.json4
-rw-r--r--jcnf/yajl/cases/escaped_bulgarian.json.gold6
-rw-r--r--jcnf/yajl/cases/escaped_foobar.json1
-rw-r--r--jcnf/yajl/cases/escaped_foobar.json.gold1
-rw-r--r--jcnf/yajl/cases/integers.json3
-rw-r--r--jcnf/yajl/cases/integers.json.gold13
-rw-r--r--jcnf/yajl/cases/invalid_utf8.json1
-rw-r--r--jcnf/yajl/cases/invalid_utf8.json.gold2
-rw-r--r--jcnf/yajl/cases/isolated_surrogate_marker.json1
-rw-r--r--jcnf/yajl/cases/isolated_surrogate_marker.json.gold1
-rw-r--r--jcnf/yajl/cases/leading_zero_in_number.json1
-rw-r--r--jcnf/yajl/cases/leading_zero_in_number.json.gold4
-rw-r--r--jcnf/yajl/cases/lonely_minus_sign.json7
-rw-r--r--jcnf/yajl/cases/lonely_minus_sign.json.gold8
-rw-r--r--jcnf/yajl/cases/missing_integer_after_decimal_point.json1
-rw-r--r--jcnf/yajl/cases/missing_integer_after_decimal_point.json.gold1
-rw-r--r--jcnf/yajl/cases/missing_integer_after_exponent.json1
-rw-r--r--jcnf/yajl/cases/missing_integer_after_exponent.json.gold1
-rw-r--r--jcnf/yajl/cases/non_utf8_char_in_string.json1
-rw-r--r--jcnf/yajl/cases/non_utf8_char_in_string.json.gold7
-rw-r--r--jcnf/yajl/cases/nulls_and_bools.json5
-rw-r--r--jcnf/yajl/cases/nulls_and_bools.json.gold8
-rw-r--r--jcnf/yajl/cases/simple.json5
-rw-r--r--jcnf/yajl/cases/simple.json.gold8
-rw-r--r--jcnf/yajl/cases/simple_with_comments.json11
-rw-r--r--jcnf/yajl/cases/simple_with_comments.json.gold8
-rw-r--r--jcnf/yajl/cases/string_invalid_escape.json1
-rw-r--r--jcnf/yajl/cases/string_invalid_escape.json.gold2
-rw-r--r--jcnf/yajl/cases/string_invalid_hex_char.json1
-rw-r--r--jcnf/yajl/cases/string_invalid_hex_char.json.gold1
-rw-r--r--jcnf/yajl/cases/string_with_escapes.json3
-rw-r--r--jcnf/yajl/cases/string_with_escapes.json.gold6
-rw-r--r--jcnf/yajl/cases/string_with_invalid_newline.json2
-rw-r--r--jcnf/yajl/cases/string_with_invalid_newline.json.gold1
-rw-r--r--jcnf/yajl/cases/unescaped_bulgarian.json1
-rw-r--r--jcnf/yajl/cases/unescaped_bulgarian.json.gold3
-rw-r--r--jcnf/yajl/configure94
-rw-r--r--jcnf/yajl/json_reformat.c204
-rw-r--r--jcnf/yajl/json_verify.c129
-rw-r--r--jcnf/yajl/rfc4627.txt3
-rw-r--r--jcnf/yajl/run_tests.sh61
-rw-r--r--jcnf/yajl/yajl.c152
-rw-r--r--jcnf/yajl/yajl_alloc.c65
-rw-r--r--jcnf/yajl/yajl_alloc.h50
-rw-r--r--jcnf/yajl/yajl_buf.c119
-rw-r--r--jcnf/yajl/yajl_buf.h73
-rw-r--r--jcnf/yajl/yajl_bytestack.h85
-rw-r--r--jcnf/yajl/yajl_common.h85
-rw-r--r--jcnf/yajl/yajl_encode.c179
-rw-r--r--jcnf/yajl/yajl_encode.h44
-rw-r--r--jcnf/yajl/yajl_gen.c381
-rw-r--r--jcnf/yajl/yajl_gen.h129
-rw-r--r--jcnf/yajl/yajl_lex.c753
-rw-r--r--jcnf/yajl/yajl_lex.h135
-rw-r--r--jcnf/yajl/yajl_parse.h184
-rw-r--r--jcnf/yajl/yajl_parser.c505
-rw-r--r--jcnf/yajl/yajl_parser.h79
-rw-r--r--jcnf/yajl/yajl_test.c293
85 files changed, 7727 insertions, 0 deletions
diff --git a/jcnf/yajl/COPYING b/jcnf/yajl/COPYING
new file mode 100644
index 0000000..fac48ba
--- /dev/null
+++ b/jcnf/yajl/COPYING
@@ -0,0 +1,29 @@
+Copyright 2007-2009, Lloyd Hilaiel.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. Neither the name of Lloyd Hilaiel nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/jcnf/yajl/ChangeLog b/jcnf/yajl/ChangeLog
new file mode 100644
index 0000000..9acb334
--- /dev/null
+++ b/jcnf/yajl/ChangeLog
@@ -0,0 +1,88 @@
+1.0.5 mod ArgyllCMS
+
+ Flattened source code layout
+ Removed cmake files, and added Jamfile
+ Added support for reading and writing comments
+
+ (Graeme Gill)
+
+1.0.5
+ * lth several performance improvements related to function
+ inlinin'
+
+1.0.4
+ * lth fix broken utf8 validation for three & four byte represenations.
+ thanks to http://github.com/brianmario and
+ http://github.com/technoweenie
+
+1.0.3
+ * lth fix syntax error in cplusplus extern "C" statements for wider
+ compiler support
+
+1.0.2
+ * lth update doxygen documentation with new sample code, passing NULL
+ for allocation functions added in 1.0.0
+
+1.0.1
+ * lth resolve crash in json_reformatter due to incorrectly ordered
+ parameters.
+
+1.0.0
+ * lth add 'make install' rules, thaks to Andrei Soroker for the
+ contribution.
+ * lth client may override allocation routines at generator or parser
+ allocation time
+ * tjw add yajl_parse_complete routine to allow client to explicitly
+ specify end-of-input, solving the "lonely number" case, where
+ json text consists only of an element with no explicit syntactic
+ end.
+ * tjw many new test cases
+ * tjw cleanup of code for symmetry and ease of reading
+ * lth integration of patches from Robert Varga which cleanup
+ compilation warnings on 64 bit linux
+
+0.4.0
+ * lth buffer overflow bug in yajl_gen_double s/%lf/%g/ - thanks to
+ Eric Bergstrome
+ * lth yajl_number callback to allow passthrough of arbitrary precision
+ numbers to client. Thanks to Hatem Nassrat.
+ * lth yajl_integer now deals in long, instead of long long. This
+ combined with yajl_number improves compiler compatibility while
+ maintaining precision.
+ * lth better ./configure && make experience (still requires cmake and
+ ruby)
+ * lth fix handling of special characters hex 0F and 1F in yajl_encode
+ (thanks to Robert Geiger)
+ * lth allow leading zeros in exponents (thanks to Hatem Nassrat)
+
+0.3.0
+ * lth doxygen documentation (html & man) generated as part of the
+ build
+ * lth many documentation updates.
+ * lth fix to work with older versions of cmake (don't use LOOSE_LOOP
+ constructs)
+ * lth work around different behavior of freebsd 4 scanf. initialize
+ parameter to scanf to zero.
+ * lth all tests run 32x with ranging buffer sizes to stress stream
+ parsing
+ * lth yajl_test accepts -b option to allow read buffer size to be
+ set
+ * lth option to validate UTF8 added to parser (argument in
+ yajl_parser_cfg)
+ * lth fix buffer overrun when chunk ends inside \u escaped text
+ * lth support client cancelation
+
+0.2.2
+ * lth on windows build debug with C7 symbols and no pdb files.
+
+0.2.1
+ * fix yajl_reformat and yajl_verify to work on arbitrarily sized
+ inputs.
+ * fix win32 build break, clean up all errors and warnings.
+ * fix optimized build flags.
+
+0.2.0
+ * optionally support comments in input text
+
+0.1.0
+ * Initial release
diff --git a/jcnf/yajl/Jamfile b/jcnf/yajl/Jamfile
new file mode 100644
index 0000000..122253f
--- /dev/null
+++ b/jcnf/yajl/Jamfile
@@ -0,0 +1,30 @@
+
+# JAM style makefile for yajl
+
+#PREF_CCFLAGS = $(CCOPTFLAG) ; # Turn optimisation on
+PREF_CCFLAGS = $(CCDEBUGFLAG) ; # Debugging flags
+#PREF_CCFLAGS = $(CCHEAPDEBUG) ; # Heap Debugging flags
+PREF_LINKFLAGS = $(LINKDEBUGFLAG) ; # Link debugging flags
+
+#Products
+Libraries = libyajl ;
+Executables = ;
+Headers = yajl_common.h yajl_gen.h yajl_parse.h ; # API headers
+
+#Install
+#InstallBin $(DESTDIR)$(PREFIX)/bin : $(Executables) ;
+#InstallFile $(DESTDIR)$(PREFIX)/h : $(Headers) ;
+#InstallLib $(DESTDIR)$(PREFIX)/lib : $(Libraries) ;
+
+# config parser based on yajl
+Library libyajl : yajl.c yajl_alloc.c yajl_buf.c yajl_encode.c yajl_gen.c yajl_lex.c yajl_parser.c ;
+
+# Link all utilities here with libicc
+LINKLIBS = libyajl ;
+
+# All utils are made from a single source file
+MainsFromSources yajl_test.c json_verify.c ;
+
+
+
+
diff --git a/jcnf/yajl/Makefile.am b/jcnf/yajl/Makefile.am
new file mode 100644
index 0000000..5f477a9
--- /dev/null
+++ b/jcnf/yajl/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/Makefile.shared
+
+privatelib_LTLIBRARIES = libyajl.la
+privatelibdir = $(pkglibdir)
+
+libyajl_la_SOURCES = yajl_common.h yajl_gen.h yajl_parse.h yajl.c \
+ yajl_alloc.c yajl_alloc.h yajl_buf.c yajl_buf.h yajl_encode.c \
+ yajl_encode.h yajl_gen.c yajl_lex.c yajl_lex.h yajl_parser.c \
+ yajl_parser.h
+
+LDADD = ./libyajl.la
+
+check_PROGRAMS = yajl_test json_verify
diff --git a/jcnf/yajl/README b/jcnf/yajl/README
new file mode 100644
index 0000000..93b3a1a
--- /dev/null
+++ b/jcnf/yajl/README
@@ -0,0 +1,68 @@
+Welcome to Yet Another JSON Library (YAJL)
+
+## Why does the world need another C library for parsing JSON?
+
+Good question. In a review of current C JSON parsing libraries I was
+unable to find one that satisfies my requirements. Those are,
+0. written in C
+1. portable
+2. robust -- as close to "crash proof" as possible
+3. data representation independent
+4. fast
+5. generates verbose, useful error messages including context of where
+ the error occurs in the input text.
+6. can parse JSON data off a stream, incrementally
+7. simple to use
+8. tiny
+
+Numbers 3, 5, 6, and 7 where particularly hard to find, and were what
+caused me to ultimately create YAJL. This document is a tour of some
+of the more important aspects of YAJL.
+
+## YAJL is Free.
+
+BSD licensing means you can use it in open source and commercial products
+alike. My request beyond the licensing is that if you find bugs drop
+me a email, or better yet, fork me on git and fix it!
+
+Porting YAJL should be trivial, the implementation is ANSI C. If you
+port to new systems I'd love to hear of it and integrate your patches.
+
+## YAJL is data representation independent.
+
+BYODR! Many JSON libraries impose a structure based data representation
+on you. This is a benefit in some cases and a drawback in others.
+YAJL uses callbacks to remain agnostic of the in-memory representation.
+So if you wish to build up an in-memory representation, you may do so
+using YAJL, but you must bring the code that defines and populates the
+in memory structure.
+
+This also means that YAJL can be used by other (higher level) JSON
+libraries if so desired.
+
+## YAJL supports stream parsing
+
+This means you do not need to hold the whole JSON representation in
+textual form in memory. This makes YAJL ideal for filtering projects,
+where you're converting YAJL from one form to another (i.e. XML). The
+included JSON pretty printer is an example of such a filter program.
+
+## YAJL is fast
+
+Minimal memory copying is performed. YAJL, when possible, returns
+pointers into the client provided text (i.e. for strings that have no
+embedded escape chars, hopefully the common case). I've put a lot of
+effort into profiling and tuning performance, but I have ignored a
+couple possible performance improvements to keep the interface clean,
+small, and flexible. My hope is that YAJL will perform comparably to
+the fastest JSON parser out there.
+
+YAJL should impose both minimal CPU and memory requirements on your
+application.
+
+## YAJL is tiny.
+
+Fat free. No whip.
+
+enjoy,
+Lloyd - July, 2007
diff --git a/jcnf/yajl/TODO b/jcnf/yajl/TODO
new file mode 100644
index 0000000..56c3dc0
--- /dev/null
+++ b/jcnf/yajl/TODO
@@ -0,0 +1,9 @@
+* add a test for 0x1F bug
+* numeric overflow in integers and double
+* line and char offsets in the lexer and in error messages
+* testing:
+ a. the permuter
+ b. some performance comparison against json_checker.
+* investigate pull instead of push parsing
+* Handle memory allocation failures gracefully
+* cygwin/msys support on win32
diff --git a/jcnf/yajl/YAJL.dxy b/jcnf/yajl/YAJL.dxy
new file mode 100644
index 0000000..680eb43
--- /dev/null
+++ b/jcnf/yajl/YAJL.dxy
@@ -0,0 +1,1258 @@
+# Doxyfile 1.5.2
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file that
+# follow. The default is UTF-8 which is also the encoding used for all text before
+# the first occurrence of this tag. Doxygen uses libiconv (or the iconv built into
+# libc) for the transcoding. See http://www.gnu.org/software/libiconv for the list of
+# possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = YAJL
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @YAJL_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = yajl-@YAJL_VERSION@/share
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Finnish, French, German, Greek, Hungarian,
+# Italian, Japanese, Japanese-en (Japanese with English messages), Korean,
+# Korean-en, Lithuanian, Norwegian, Polish, Portuguese, Romanian, Russian,
+# Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = YES
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want to
+# include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = NO
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = YES
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = NO
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from the
+# version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = YES
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = ../src/yajl ../src/api
+
+# This tag can be used to specify the character encoding of the source files that
+# doxygen parses. Internally doxygen uses the UTF-8 encoding, which is also the default
+# input encoding. Doxygen uses libiconv (or the iconv built into libc) for the transcoding.
+# See http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py
+
+FILE_PATTERNS = *.h
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the output.
+# The symbol name can be a fully qualified name, a word, or if the wildcard * is used,
+# a substring. Examples: ANamespace, AClass, AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+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
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output. If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis. Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match. The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code. Otherwise they will link to the documentstion.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = doc/yajl-@YAJL_VERSION@
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = YES
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = YES
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see http://www.mcternan.me.uk/mscgen/) to
+# produce the chart and insert it in the documentation. The MSCGEN_PATH tag allows you to
+# specify the directory where the mscgen tool resides. If left empty the tool is assumed to
+# be found in the default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a caller dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable caller graphs for selected
+# functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen will always
+# show the root nodes and its direct children regardless of this setting.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, which results in a white background.
+# Warning: Depending on the platform used, enabling this option may lead to
+# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
+# read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = NO
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/jcnf/yajl/YAJLDoc.cmake b/jcnf/yajl/YAJLDoc.cmake
new file mode 100644
index 0000000..049cdef
--- /dev/null
+++ b/jcnf/yajl/YAJLDoc.cmake
@@ -0,0 +1,26 @@
+FIND_PROGRAM(doxygenPath doxygen)
+
+IF (doxygenPath)
+ SET (YAJL_VERSION ${YAJL_MAJOR}.${YAJL_MINOR}.${YAJL_MICRO})
+ SET(yajlDirName yajl-${YAJL_VERSION})
+ SET(docPath
+ "${CMAKE_CURRENT_BINARY_DIR}/${yajlDirName}/share/doc/${yajlDirName}")
+ MESSAGE("** using doxygen at: ${doxygenPath}")
+ MESSAGE("** documentation output to: ${docPath}")
+
+ CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/src/YAJL.dxy
+ ${CMAKE_CURRENT_BINARY_DIR}/YAJL.dxy @ONLY)
+
+ FILE(MAKE_DIRECTORY "${docPath}")
+
+ ADD_CUSTOM_TARGET(doc
+ ${doxygenPath} YAJL.dxy
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
+
+ELSE (doxygenPath)
+ MESSAGE("!! doxygen not found, not generating documentation")
+ ADD_CUSTOM_TARGET(
+ doc
+ echo doxygen not installed, not generating documentation
+ )
+ENDIF (doxygenPath)
diff --git a/jcnf/yajl/afiles b/jcnf/yajl/afiles
new file mode 100644
index 0000000..23cf626
--- /dev/null
+++ b/jcnf/yajl/afiles
@@ -0,0 +1,84 @@
+afiles
+COPYING
+ChangeLog
+Jamfile
+README
+TODO
+YAJL.dxy
+YAJLDoc.cmake
+configure
+json_reformat.c
+json_verify.c
+rfc4627.txt
+run_tests.sh
+yajl.c
+yajl_alloc.c
+yajl_alloc.h
+yajl_buf.c
+yajl_buf.h
+yajl_bytestack.h
+yajl_common.h
+yajl_encode.c
+yajl_encode.h
+yajl_gen.c
+yajl_gen.h
+yajl_lex.c
+yajl_lex.h
+yajl_parse.h
+yajl_parser.c
+yajl_parser.h
+yajl_test.c
+cases/array.json
+cases/array.json.gold
+cases/bogus_char.json
+cases/bogus_char.json.gold
+cases/codepoints_from_unicode_org.json
+cases/codepoints_from_unicode_org.json.gold
+cases/dc_simple_with_comments.json
+cases/dc_simple_with_comments.json.gold
+cases/deep_arrays.json
+cases/deep_arrays.json.gold
+cases/difficult_json_c_test_case.json
+cases/difficult_json_c_test_case.json.gold
+cases/difficult_json_c_test_case_with_comments.json
+cases/difficult_json_c_test_case_with_comments.json.gold
+cases/doubles.json
+cases/doubles.json.gold
+cases/empty_array.json
+cases/empty_array.json.gold
+cases/escaped_bulgarian.json
+cases/escaped_bulgarian.json.gold
+cases/escaped_foobar.json
+cases/escaped_foobar.json.gold
+cases/integers.json
+cases/integers.json.gold
+cases/invalid_utf8.json
+cases/invalid_utf8.json.gold
+cases/isolated_surrogate_marker.json
+cases/isolated_surrogate_marker.json.gold
+cases/leading_zero_in_number.json
+cases/leading_zero_in_number.json.gold
+cases/lonely_minus_sign.json
+cases/lonely_minus_sign.json.gold
+cases/missing_integer_after_decimal_point.json
+cases/missing_integer_after_decimal_point.json.gold
+cases/missing_integer_after_exponent.json
+cases/missing_integer_after_exponent.json.gold
+cases/non_utf8_char_in_string.json
+cases/non_utf8_char_in_string.json.gold
+cases/nulls_and_bools.json
+cases/nulls_and_bools.json.gold
+cases/simple.json
+cases/simple.json.gold
+cases/simple_with_comments.json
+cases/simple_with_comments.json.gold
+cases/string_invalid_escape.json
+cases/string_invalid_escape.json.gold
+cases/string_invalid_hex_char.json
+cases/string_invalid_hex_char.json.gold
+cases/string_with_escapes.json
+cases/string_with_escapes.json.gold
+cases/string_with_invalid_newline.json
+cases/string_with_invalid_newline.json.gold
+cases/unescaped_bulgarian.json
+cases/unescaped_bulgarian.json.gold
diff --git a/jcnf/yajl/cases/array.json b/jcnf/yajl/cases/array.json
new file mode 100644
index 0000000..f76058d
--- /dev/null
+++ b/jcnf/yajl/cases/array.json
@@ -0,0 +1,6 @@
+["foo",
+ "bar", "baz",
+ true,false,null,{"key":"value"},
+ [null,null,null,[]],
+ "\n\r\\"
+]
diff --git a/jcnf/yajl/cases/array.json.gold b/jcnf/yajl/cases/array.json.gold
new file mode 100644
index 0000000..d77e716
--- /dev/null
+++ b/jcnf/yajl/cases/array.json.gold
@@ -0,0 +1,22 @@
+array open '['
+string: 'foo'
+string: 'bar'
+string: 'baz'
+bool: true
+bool: false
+null
+map open '{'
+key: 'key'
+string: 'value'
+map close '}'
+array open '['
+null
+null
+null
+array open '['
+array close ']'
+array close ']'
+string: '
+
+\'
+array close ']'
diff --git a/jcnf/yajl/cases/bogus_char.json b/jcnf/yajl/cases/bogus_char.json
new file mode 100644
index 0000000..8163bd8
--- /dev/null
+++ b/jcnf/yajl/cases/bogus_char.json
@@ -0,0 +1,4 @@
+["this","is","what","should","be",
+ "a happy bit of json",
+ "but someone, misspelled \"true\"", ture,
+ "who says JSON is easy for humans to generate?"]
diff --git a/jcnf/yajl/cases/bogus_char.json.gold b/jcnf/yajl/cases/bogus_char.json.gold
new file mode 100644
index 0000000..ccbeed5
--- /dev/null
+++ b/jcnf/yajl/cases/bogus_char.json.gold
@@ -0,0 +1,9 @@
+array open '['
+string: 'this'
+string: 'is'
+string: 'what'
+string: 'should'
+string: 'be'
+string: 'a happy bit of json'
+string: 'but someone, misspelled "true"'
+lexical error: invalid string in json text.
diff --git a/jcnf/yajl/cases/codepoints_from_unicode_org.json b/jcnf/yajl/cases/codepoints_from_unicode_org.json
new file mode 100644
index 0000000..f91f3be
--- /dev/null
+++ b/jcnf/yajl/cases/codepoints_from_unicode_org.json
@@ -0,0 +1 @@
+"\u004d\u0430\u4e8c\ud800\udf02"
diff --git a/jcnf/yajl/cases/codepoints_from_unicode_org.json.gold b/jcnf/yajl/cases/codepoints_from_unicode_org.json.gold
new file mode 100644
index 0000000..12b358a
--- /dev/null
+++ b/jcnf/yajl/cases/codepoints_from_unicode_org.json.gold
@@ -0,0 +1 @@
+string: 'Mа二ðŒ‚'
diff --git a/jcnf/yajl/cases/dc_simple_with_comments.json b/jcnf/yajl/cases/dc_simple_with_comments.json
new file mode 100644
index 0000000..3b79bba
--- /dev/null
+++ b/jcnf/yajl/cases/dc_simple_with_comments.json
@@ -0,0 +1,11 @@
+{
+ "this": "is", // ignore this
+ "really": "simple",
+ /* ignore
+this
+too * /
+** //
+(/
+******/
+ "json": "right?"
+}
diff --git a/jcnf/yajl/cases/dc_simple_with_comments.json.gold b/jcnf/yajl/cases/dc_simple_with_comments.json.gold
new file mode 100644
index 0000000..92be7a5
--- /dev/null
+++ b/jcnf/yajl/cases/dc_simple_with_comments.json.gold
@@ -0,0 +1,4 @@
+map open '{'
+key: 'this'
+string: 'is'
+lexical error: probable comment found in input text, comments are not enabled.
diff --git a/jcnf/yajl/cases/deep_arrays.json b/jcnf/yajl/cases/deep_arrays.json
new file mode 100644
index 0000000..82d1b0d
--- /dev/null
+++ b/jcnf/yajl/cases/deep_arrays.json
@@ -0,0 +1 @@
+[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] \ No newline at end of file
diff --git a/jcnf/yajl/cases/deep_arrays.json.gold b/jcnf/yajl/cases/deep_arrays.json.gold
new file mode 100644
index 0000000..e549637
--- /dev/null
+++ b/jcnf/yajl/cases/deep_arrays.json.gold
@@ -0,0 +1,2048 @@
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array open '['
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
+array close ']'
diff --git a/jcnf/yajl/cases/difficult_json_c_test_case.json b/jcnf/yajl/cases/difficult_json_c_test_case.json
new file mode 100644
index 0000000..6998f55
--- /dev/null
+++ b/jcnf/yajl/cases/difficult_json_c_test_case.json
@@ -0,0 +1 @@
+{ "glossary": { "title": "example glossary", "GlossDiv": { "title": "S", "GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", "GlossSeeAlso": ["GML", "XML", "markup"] } ] } } }
diff --git a/jcnf/yajl/cases/difficult_json_c_test_case.json.gold b/jcnf/yajl/cases/difficult_json_c_test_case.json.gold
new file mode 100644
index 0000000..eaaf41a
--- /dev/null
+++ b/jcnf/yajl/cases/difficult_json_c_test_case.json.gold
@@ -0,0 +1,35 @@
+map open '{'
+key: 'glossary'
+map open '{'
+key: 'title'
+string: 'example glossary'
+key: 'GlossDiv'
+map open '{'
+key: 'title'
+string: 'S'
+key: 'GlossList'
+array open '['
+map open '{'
+key: 'ID'
+string: 'SGML'
+key: 'SortAs'
+string: 'SGML'
+key: 'GlossTerm'
+string: 'Standard Generalized Markup Language'
+key: 'Acronym'
+string: 'SGML'
+key: 'Abbrev'
+string: 'ISO 8879:1986'
+key: 'GlossDef'
+string: 'A meta-markup language, used to create markup languages such as DocBook.'
+key: 'GlossSeeAlso'
+array open '['
+string: 'GML'
+string: 'XML'
+string: 'markup'
+array close ']'
+map close '}'
+array close ']'
+map close '}'
+map close '}'
+map close '}'
diff --git a/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json b/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json
new file mode 100644
index 0000000..2463c71
--- /dev/null
+++ b/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json
@@ -0,0 +1 @@
+{ "glossary": { /* you */ "title": /**/ "example glossary", /*should*/"GlossDiv": { "title": /*never*/"S", /*ever*/"GlossList": [ { "ID": "SGML", "SortAs": "SGML", "GlossTerm": "Standard Generalized Markup Language", "Acronym": "SGML", "Abbrev": "ISO 8879:1986", "GlossDef": "A meta-markup language, used to create markup languages such as DocBook.", /*see*/"GlossSeeAlso"/*this*/:/*coming*/[/*out*/"GML"/*of*/,/*the*/"XML"/*parser!*/, "markup"] /*hey*/}/*ho*/]/*hey*/}/*ho*/} } // and the parser won't even get this far, so chill. /* hah!
diff --git a/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json.gold b/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json.gold
new file mode 100644
index 0000000..eaaf41a
--- /dev/null
+++ b/jcnf/yajl/cases/difficult_json_c_test_case_with_comments.json.gold
@@ -0,0 +1,35 @@
+map open '{'
+key: 'glossary'
+map open '{'
+key: 'title'
+string: 'example glossary'
+key: 'GlossDiv'
+map open '{'
+key: 'title'
+string: 'S'
+key: 'GlossList'
+array open '['
+map open '{'
+key: 'ID'
+string: 'SGML'
+key: 'SortAs'
+string: 'SGML'
+key: 'GlossTerm'
+string: 'Standard Generalized Markup Language'
+key: 'Acronym'
+string: 'SGML'
+key: 'Abbrev'
+string: 'ISO 8879:1986'
+key: 'GlossDef'
+string: 'A meta-markup language, used to create markup languages such as DocBook.'
+key: 'GlossSeeAlso'
+array open '['
+string: 'GML'
+string: 'XML'
+string: 'markup'
+array close ']'
+map close '}'
+array close ']'
+map close '}'
+map close '}'
+map close '}'
diff --git a/jcnf/yajl/cases/doubles.json b/jcnf/yajl/cases/doubles.json
new file mode 100644
index 0000000..626f21c
--- /dev/null
+++ b/jcnf/yajl/cases/doubles.json
@@ -0,0 +1 @@
+[ 0.1e2, 1e1, 3.141569, 10000000000000e-10]
diff --git a/jcnf/yajl/cases/doubles.json.gold b/jcnf/yajl/cases/doubles.json.gold
new file mode 100644
index 0000000..ab5f212
--- /dev/null
+++ b/jcnf/yajl/cases/doubles.json.gold
@@ -0,0 +1,6 @@
+array open '['
+double: 10.000000
+double: 10.000000
+double: 3.141569
+double: 1000.000000
+array close ']'
diff --git a/jcnf/yajl/cases/empty_array.json b/jcnf/yajl/cases/empty_array.json
new file mode 100644
index 0000000..0637a08
--- /dev/null
+++ b/jcnf/yajl/cases/empty_array.json
@@ -0,0 +1 @@
+[] \ No newline at end of file
diff --git a/jcnf/yajl/cases/empty_array.json.gold b/jcnf/yajl/cases/empty_array.json.gold
new file mode 100644
index 0000000..45924af
--- /dev/null
+++ b/jcnf/yajl/cases/empty_array.json.gold
@@ -0,0 +1,2 @@
+array open '['
+array close ']'
diff --git a/jcnf/yajl/cases/escaped_bulgarian.json b/jcnf/yajl/cases/escaped_bulgarian.json
new file mode 100644
index 0000000..9ce1d1c
--- /dev/null
+++ b/jcnf/yajl/cases/escaped_bulgarian.json
@@ -0,0 +1,4 @@
+["\u0414\u0430",
+ "\u041c\u0443",
+ "\u0415\u0431\u0430",
+ "\u041c\u0430\u0439\u043a\u0430\u0442\u0430"]
diff --git a/jcnf/yajl/cases/escaped_bulgarian.json.gold b/jcnf/yajl/cases/escaped_bulgarian.json.gold
new file mode 100644
index 0000000..9f2aa00
--- /dev/null
+++ b/jcnf/yajl/cases/escaped_bulgarian.json.gold
@@ -0,0 +1,6 @@
+array open '['
+string: 'Да'
+string: 'Му'
+string: 'Еба'
+string: 'Майката'
+array close ']'
diff --git a/jcnf/yajl/cases/escaped_foobar.json b/jcnf/yajl/cases/escaped_foobar.json
new file mode 100644
index 0000000..2c0e25f
--- /dev/null
+++ b/jcnf/yajl/cases/escaped_foobar.json
@@ -0,0 +1 @@
+"\u0066\u006f\u006f\u0062\u0061\u0072"
diff --git a/jcnf/yajl/cases/escaped_foobar.json.gold b/jcnf/yajl/cases/escaped_foobar.json.gold
new file mode 100644
index 0000000..774e867
--- /dev/null
+++ b/jcnf/yajl/cases/escaped_foobar.json.gold
@@ -0,0 +1 @@
+string: 'foobar'
diff --git a/jcnf/yajl/cases/integers.json b/jcnf/yajl/cases/integers.json
new file mode 100644
index 0000000..ca1393a
--- /dev/null
+++ b/jcnf/yajl/cases/integers.json
@@ -0,0 +1,3 @@
+[ 1,2,3,4,5,6,7,
+ 123456789 , -123456789,
+ 9223372036854775807, -9223372036854775807 ]
diff --git a/jcnf/yajl/cases/integers.json.gold b/jcnf/yajl/cases/integers.json.gold
new file mode 100644
index 0000000..f44b283
--- /dev/null
+++ b/jcnf/yajl/cases/integers.json.gold
@@ -0,0 +1,13 @@
+array open '['
+integer: 1
+integer: 2
+integer: 3
+integer: 4
+integer: 5
+integer: 6
+integer: 7
+integer: 123456789
+integer: -123456789
+integer: 9223372036854775807
+integer: -9223372036854775807
+array close ']'
diff --git a/jcnf/yajl/cases/invalid_utf8.json b/jcnf/yajl/cases/invalid_utf8.json
new file mode 100644
index 0000000..12f1718
--- /dev/null
+++ b/jcnf/yajl/cases/invalid_utf8.json
@@ -0,0 +1 @@
+["Да ÐœÑ Ð•Ð±Ð° Майката"]
diff --git a/jcnf/yajl/cases/invalid_utf8.json.gold b/jcnf/yajl/cases/invalid_utf8.json.gold
new file mode 100644
index 0000000..0cabb13
--- /dev/null
+++ b/jcnf/yajl/cases/invalid_utf8.json.gold
@@ -0,0 +1,2 @@
+array open '['
+lexical error: invalid bytes in UTF8 string.
diff --git a/jcnf/yajl/cases/isolated_surrogate_marker.json b/jcnf/yajl/cases/isolated_surrogate_marker.json
new file mode 100644
index 0000000..36959f4
--- /dev/null
+++ b/jcnf/yajl/cases/isolated_surrogate_marker.json
@@ -0,0 +1 @@
+"\ud800"
diff --git a/jcnf/yajl/cases/isolated_surrogate_marker.json.gold b/jcnf/yajl/cases/isolated_surrogate_marker.json.gold
new file mode 100644
index 0000000..1ad9e8b
--- /dev/null
+++ b/jcnf/yajl/cases/isolated_surrogate_marker.json.gold
@@ -0,0 +1 @@
+string: '?'
diff --git a/jcnf/yajl/cases/leading_zero_in_number.json b/jcnf/yajl/cases/leading_zero_in_number.json
new file mode 100644
index 0000000..959f5ba
--- /dev/null
+++ b/jcnf/yajl/cases/leading_zero_in_number.json
@@ -0,0 +1 @@
+{ "bad thing": 01 }
diff --git a/jcnf/yajl/cases/leading_zero_in_number.json.gold b/jcnf/yajl/cases/leading_zero_in_number.json.gold
new file mode 100644
index 0000000..828aec8
--- /dev/null
+++ b/jcnf/yajl/cases/leading_zero_in_number.json.gold
@@ -0,0 +1,4 @@
+map open '{'
+key: 'bad thing'
+integer: 0
+parse error: after key and value, inside map, I expect ',' or '}'
diff --git a/jcnf/yajl/cases/lonely_minus_sign.json b/jcnf/yajl/cases/lonely_minus_sign.json
new file mode 100644
index 0000000..85f69bd
--- /dev/null
+++ b/jcnf/yajl/cases/lonely_minus_sign.json
@@ -0,0 +1,7 @@
+[
+ "foo", true,
+ true, "blue",
+ "baby where are you?", "oh boo hoo!",
+ -
+]
+
diff --git a/jcnf/yajl/cases/lonely_minus_sign.json.gold b/jcnf/yajl/cases/lonely_minus_sign.json.gold
new file mode 100644
index 0000000..4b23c61
--- /dev/null
+++ b/jcnf/yajl/cases/lonely_minus_sign.json.gold
@@ -0,0 +1,8 @@
+array open '['
+string: 'foo'
+bool: true
+bool: true
+string: 'blue'
+string: 'baby where are you?'
+string: 'oh boo hoo!'
+lexical error: malformed number, a digit is required after the minus sign.
diff --git a/jcnf/yajl/cases/missing_integer_after_decimal_point.json b/jcnf/yajl/cases/missing_integer_after_decimal_point.json
new file mode 100644
index 0000000..2369f4b
--- /dev/null
+++ b/jcnf/yajl/cases/missing_integer_after_decimal_point.json
@@ -0,0 +1 @@
+10.e2
diff --git a/jcnf/yajl/cases/missing_integer_after_decimal_point.json.gold b/jcnf/yajl/cases/missing_integer_after_decimal_point.json.gold
new file mode 100644
index 0000000..1d85c91
--- /dev/null
+++ b/jcnf/yajl/cases/missing_integer_after_decimal_point.json.gold
@@ -0,0 +1 @@
+lexical error: malformed number, a digit is required after the decimal point.
diff --git a/jcnf/yajl/cases/missing_integer_after_exponent.json b/jcnf/yajl/cases/missing_integer_after_exponent.json
new file mode 100644
index 0000000..a62b45d
--- /dev/null
+++ b/jcnf/yajl/cases/missing_integer_after_exponent.json
@@ -0,0 +1 @@
+10e
diff --git a/jcnf/yajl/cases/missing_integer_after_exponent.json.gold b/jcnf/yajl/cases/missing_integer_after_exponent.json.gold
new file mode 100644
index 0000000..b9f184f
--- /dev/null
+++ b/jcnf/yajl/cases/missing_integer_after_exponent.json.gold
@@ -0,0 +1 @@
+lexical error: malformed number, a digit is required after the exponent.
diff --git a/jcnf/yajl/cases/non_utf8_char_in_string.json b/jcnf/yajl/cases/non_utf8_char_in_string.json
new file mode 100644
index 0000000..253a664
--- /dev/null
+++ b/jcnf/yajl/cases/non_utf8_char_in_string.json
@@ -0,0 +1 @@
+{"CoreletAPIVersion":2,"CoreletType":"standalone","documentation":"A corelet that provides the capability to upload a folder’s contents into a user’s locker.","functions":[{"documentation":"Displays a dialog box that allows user to select a folder on the local system.","name":"ShowBrowseDialog","parameters":[{"documentation":"The callback function for results.","name":"callback","required":true,"type":"callback"}]},{"documentation":"Uploads all mp3 files in the folder provided.","name":"UploadFolder","parameters":[{"documentation":"The path to upload mp3 files from.","name":"path","required":true,"type":"string"},{"documentation":"The callback function for progress.","name":"callback","required":true,"type":"callback"}]},{"documentation":"Returns the server name to the current locker service.","name":"GetLockerService","parameters":[]},{"documentation":"Changes the name of the locker service.","name":"SetLockerService","parameters":[{"documentation":"The value of the locker service to set active.","name":"LockerService","required":true,"type":"string"}]},{"documentation":"Downloads locker files to the suggested folder.","name":"DownloadFile","parameters":[{"documentation":"The origin path of the locker file.","name":"path","required":true,"type":"string"},{"documentation":"The Window destination path of the locker file.","name":"destination","required":true,"type":"integer"},{"documentation":"The callback function for progress.","name":"callback","required":true,"type":"callback"}]}],"name":"LockerUploader","version":{"major":0,"micro":1,"minor":0},"versionString":"0.0.1"} \ No newline at end of file
diff --git a/jcnf/yajl/cases/non_utf8_char_in_string.json.gold b/jcnf/yajl/cases/non_utf8_char_in_string.json.gold
new file mode 100644
index 0000000..b3780ae
--- /dev/null
+++ b/jcnf/yajl/cases/non_utf8_char_in_string.json.gold
@@ -0,0 +1,7 @@
+map open '{'
+key: 'CoreletAPIVersion'
+integer: 2
+key: 'CoreletType'
+string: 'standalone'
+key: 'documentation'
+lexical error: invalid bytes in UTF8 string.
diff --git a/jcnf/yajl/cases/nulls_and_bools.json b/jcnf/yajl/cases/nulls_and_bools.json
new file mode 100644
index 0000000..65eb01f
--- /dev/null
+++ b/jcnf/yajl/cases/nulls_and_bools.json
@@ -0,0 +1,5 @@
+{
+ "boolean, true": true,
+ "boolean, false": false,
+ "null": null
+}
diff --git a/jcnf/yajl/cases/nulls_and_bools.json.gold b/jcnf/yajl/cases/nulls_and_bools.json.gold
new file mode 100644
index 0000000..8dc173c
--- /dev/null
+++ b/jcnf/yajl/cases/nulls_and_bools.json.gold
@@ -0,0 +1,8 @@
+map open '{'
+key: 'boolean, true'
+bool: true
+key: 'boolean, false'
+bool: false
+key: 'null'
+null
+map close '}'
diff --git a/jcnf/yajl/cases/simple.json b/jcnf/yajl/cases/simple.json
new file mode 100644
index 0000000..9ed80c9
--- /dev/null
+++ b/jcnf/yajl/cases/simple.json
@@ -0,0 +1,5 @@
+{
+ "this": "is",
+ "really": "simple",
+ "json": "right?"
+}
diff --git a/jcnf/yajl/cases/simple.json.gold b/jcnf/yajl/cases/simple.json.gold
new file mode 100644
index 0000000..59b7d6a
--- /dev/null
+++ b/jcnf/yajl/cases/simple.json.gold
@@ -0,0 +1,8 @@
+map open '{'
+key: 'this'
+string: 'is'
+key: 'really'
+string: 'simple'
+key: 'json'
+string: 'right?'
+map close '}'
diff --git a/jcnf/yajl/cases/simple_with_comments.json b/jcnf/yajl/cases/simple_with_comments.json
new file mode 100644
index 0000000..3b79bba
--- /dev/null
+++ b/jcnf/yajl/cases/simple_with_comments.json
@@ -0,0 +1,11 @@
+{
+ "this": "is", // ignore this
+ "really": "simple",
+ /* ignore
+this
+too * /
+** //
+(/
+******/
+ "json": "right?"
+}
diff --git a/jcnf/yajl/cases/simple_with_comments.json.gold b/jcnf/yajl/cases/simple_with_comments.json.gold
new file mode 100644
index 0000000..59b7d6a
--- /dev/null
+++ b/jcnf/yajl/cases/simple_with_comments.json.gold
@@ -0,0 +1,8 @@
+map open '{'
+key: 'this'
+string: 'is'
+key: 'really'
+string: 'simple'
+key: 'json'
+string: 'right?'
+map close '}'
diff --git a/jcnf/yajl/cases/string_invalid_escape.json b/jcnf/yajl/cases/string_invalid_escape.json
new file mode 100644
index 0000000..c554182
--- /dev/null
+++ b/jcnf/yajl/cases/string_invalid_escape.json
@@ -0,0 +1 @@
+["\n foo \/ bar \r\f\\\uffff\t\b\"\\ and you can't escape thi\s"]
diff --git a/jcnf/yajl/cases/string_invalid_escape.json.gold b/jcnf/yajl/cases/string_invalid_escape.json.gold
new file mode 100644
index 0000000..bdc473e
--- /dev/null
+++ b/jcnf/yajl/cases/string_invalid_escape.json.gold
@@ -0,0 +1,2 @@
+array open '['
+lexical error: inside a string, '\' occurs before a character which it may not.
diff --git a/jcnf/yajl/cases/string_invalid_hex_char.json b/jcnf/yajl/cases/string_invalid_hex_char.json
new file mode 100644
index 0000000..bde7ee9
--- /dev/null
+++ b/jcnf/yajl/cases/string_invalid_hex_char.json
@@ -0,0 +1 @@
+"foo foo, blah blah \u0123 \u4567 \u89ab \uc/ef \uABCD \uEFFE bar baz bing"
diff --git a/jcnf/yajl/cases/string_invalid_hex_char.json.gold b/jcnf/yajl/cases/string_invalid_hex_char.json.gold
new file mode 100644
index 0000000..d8b535e
--- /dev/null
+++ b/jcnf/yajl/cases/string_invalid_hex_char.json.gold
@@ -0,0 +1 @@
+lexical error: invalid (non-hex) character occurs after '\u' inside string.
diff --git a/jcnf/yajl/cases/string_with_escapes.json b/jcnf/yajl/cases/string_with_escapes.json
new file mode 100644
index 0000000..59cc940
--- /dev/null
+++ b/jcnf/yajl/cases/string_with_escapes.json
@@ -0,0 +1,3 @@
+["\n foo \/ bar \r\f\\\uffff\t\b\"\\",
+ "\"and this string has an escape at the beginning",
+ "and this string has no escapes" ]
diff --git a/jcnf/yajl/cases/string_with_escapes.json.gold b/jcnf/yajl/cases/string_with_escapes.json.gold
new file mode 100644
index 0000000..ac878a2
--- /dev/null
+++ b/jcnf/yajl/cases/string_with_escapes.json.gold
@@ -0,0 +1,6 @@
+array open '['
+string: '
+ foo / bar \ï¿¿ "\'
+string: '"and this string has an escape at the beginning'
+string: 'and this string has no escapes'
+array close ']'
diff --git a/jcnf/yajl/cases/string_with_invalid_newline.json b/jcnf/yajl/cases/string_with_invalid_newline.json
new file mode 100644
index 0000000..0e3ea0d
--- /dev/null
+++ b/jcnf/yajl/cases/string_with_invalid_newline.json
@@ -0,0 +1,2 @@
+"la di dah. this is a string, and I can do this, \n, but not this
+"
diff --git a/jcnf/yajl/cases/string_with_invalid_newline.json.gold b/jcnf/yajl/cases/string_with_invalid_newline.json.gold
new file mode 100644
index 0000000..80c1b8a
--- /dev/null
+++ b/jcnf/yajl/cases/string_with_invalid_newline.json.gold
@@ -0,0 +1 @@
+lexical error: invalid character inside string.
diff --git a/jcnf/yajl/cases/unescaped_bulgarian.json b/jcnf/yajl/cases/unescaped_bulgarian.json
new file mode 100644
index 0000000..f9a70a6
--- /dev/null
+++ b/jcnf/yajl/cases/unescaped_bulgarian.json
@@ -0,0 +1 @@
+["Да Му Еба Майката"]
diff --git a/jcnf/yajl/cases/unescaped_bulgarian.json.gold b/jcnf/yajl/cases/unescaped_bulgarian.json.gold
new file mode 100644
index 0000000..ac34442
--- /dev/null
+++ b/jcnf/yajl/cases/unescaped_bulgarian.json.gold
@@ -0,0 +1,3 @@
+array open '['
+string: 'Да Му Еба Майката'
+array close ']'
diff --git a/jcnf/yajl/configure b/jcnf/yajl/configure
new file mode 100644
index 0000000..bed8c28
--- /dev/null
+++ b/jcnf/yajl/configure
@@ -0,0 +1,94 @@
+#!/usr/bin/env ruby
+# Copyright 2007-2009, Lloyd Hilaiel.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+#
+# 3. Neither the name of Lloyd Hilaiel nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+
+require 'fileutils'
+require 'optparse'
+
+prefix = "/usr/local"
+options = {}
+OptionParser.new do |opts|
+ opts.banner = "Usage: configure [options]"
+ opts.on("-p", "--prefix PATH", "Set installation prefix") do |p|
+ prefix = p
+ end
+ opts.on_tail("-h", "--help", "Output usage summary") do
+ puts opts
+ exit
+ end
+
+ opts.parse!(ARGV)
+end
+
+puts "== removing old build files"
+FileUtils.rm_rf("build")
+FileUtils.rm_f("Makefile")
+puts "== running CMake in build directory"
+FileUtils.mkdir("build")
+FileUtils.cd("build") do
+ if (!system("cmake .."))
+ puts "The \"cmake\" program is required to configure yajl. It's"
+ puts "available from most ports/packaging systems and http://cmake.org"
+ exit 1
+ end
+end
+
+# now generate a Makefile
+puts "== Generating Makefile"
+File.open("Makefile", "w+") do |f|
+ f.puts ".PHONY: all clean distclean install package test distro"
+ f.puts "all: distro doc test"
+ f.puts
+ f.puts "distro:"
+ f.puts " @cd build && make"
+ f.puts
+ f.puts "doc:"
+ f.puts " @cd build && make doc"
+ f.puts
+ f.puts "test:"
+ f.puts " @cd build && make test"
+ f.puts
+ f.puts "clean:"
+ f.puts " @cd build && make clean"
+ f.puts
+ f.puts "distclean:"
+ f.puts " @rm -rf Makefile build"
+ f.puts " @rm -f yajl-*.tgz"
+ f.puts
+ f.puts "install: all"
+ f.puts " @cd build && make install"
+ f.puts
+ f.puts "package: all"
+ f.puts " @echo \"compressing to `basename build/yajl-*`.tgz\""
+ f.puts " @cd build && tar czf ../`basename yajl-*`.tgz yajl-*"
+end
+
+puts "== Configured with installation prefix: #{prefix}"
+
diff --git a/jcnf/yajl/json_reformat.c b/jcnf/yajl/json_reformat.c
new file mode 100644
index 0000000..156a61b
--- /dev/null
+++ b/jcnf/yajl/json_reformat.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright 2007, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_parse.h"
+#include "yajl_gen.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int reformat_null(void * ctx)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_null(g);
+ return 1;
+}
+
+int reformat_boolean(void * ctx, int boolVal)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_bool(g, boolVal);
+ return 1;
+}
+
+int reformat_integer(void * ctx, long long integerVal)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_integer(g, integerVal);
+ return 1;
+}
+
+int reformat_double(void * ctx, double doubleVal)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_double(g, doubleVal);
+ return 1;
+}
+
+int reformat_string(void * ctx, const unsigned char * stringVal,
+ unsigned int stringLen)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_string(g, stringVal, stringLen);
+ return 1;
+}
+
+int reformat_map_key(void * ctx, const unsigned char * stringVal,
+ unsigned int stringLen)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_string(g, stringVal, stringLen);
+ return 1;
+}
+
+int reformat_start_map(void * ctx)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_map_open(g);
+ return 1;
+}
+
+
+int reformat_end_map(void * ctx)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_map_close(g);
+ return 1;
+}
+
+int reformat_start_array(void * ctx)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_array_open(g);
+ return 1;
+}
+
+int reformat_end_array(void * ctx)
+{
+ yajl_gen g = (yajl_gen) ctx;
+ yajl_gen_array_close(g);
+ return 1;
+}
+
+static yajl_callbacks callbacks = {
+ reformat_null,
+ reformat_boolean,
+ reformat_integer,
+ reformat_double,
+ 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, "usage: %s <filename>\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_config conf = { 1, " " };
+ yajl_gen g;
+ yajl_status stat;
+ size_t rd;
+ /* allow comments */
+ yajl_parser_config cfg = { 1, 1 };
+
+ /* check arguments. We expect exactly one! */
+ if (argc == 2) {
+ if (!strcmp("-m", argv[1])) {
+ conf.beautify = 0;
+
+ } else if (!strcmp("-u", argv[1])) {
+ cfg.checkUTF8 = 0;
+ } else {
+ usage(argv[0]);
+ }
+ } else if (argc != 1) {
+ usage(argv[0]);
+ }
+
+ g = yajl_gen_alloc(&conf);
+
+ /* ok. open file. let's read and parse */
+ hand = yajl_alloc(&callbacks, &cfg, (void *) g);
+
+ for (;;) {
+ rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
+
+ if (rd == 0) {
+ if (feof(stdin)) {
+ break;
+ } else {
+ fprintf(stderr, "error on file read.\n");
+ break;
+ }
+ } else {
+ fileData[rd] = 0;
+
+ /* read file data, pass to parser */
+ stat = yajl_parse(hand, fileData, rd);
+ if (stat != yajl_status_ok &&
+ stat != yajl_status_insufficient_data)
+ {
+ unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
+ fprintf(stderr, (const char *) str);
+ yajl_free_error(str);
+ } else {
+ const unsigned char * buf;
+ unsigned int len;
+ yajl_gen_get_buf(g, &buf, &len);
+ fwrite(buf, 1, len, stdout);
+ yajl_gen_clear(g);
+ }
+ }
+ }
+
+ yajl_gen_free(g);
+ yajl_free(hand);
+
+ return 0;
+}
diff --git a/jcnf/yajl/json_verify.c b/jcnf/yajl/json_verify.c
new file mode 100644
index 0000000..42b57a9
--- /dev/null
+++ b/jcnf/yajl/json_verify.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_parse.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+usage(const char * progname)
+{
+ fprintf(stderr, "%s: validate json from stdin\n"
+ "usage: json_verify [options]\n"
+ " -q quiet mode\n"
+ " -c allow comments\n"
+ " -u allow invalid utf8 inside strings\n",
+ progname);
+ exit(1);
+}
+
+int
+main(int argc, char ** argv)
+{
+ yajl_status stat;
+ size_t rd;
+ yajl_handle hand;
+ static unsigned char fileData[65536];
+ int quiet = 0;
+ int retval = 0, done = 0;
+ yajl_parser_config cfg = { 0, 1 };
+
+ /* check arguments.*/
+ if (argc > 1 && argc < 4) {
+ int i;
+
+ for (i=1; i < argc;i++) {
+ if (!strcmp("-q", argv[i])) {
+ quiet = 1;
+ } else if (!strcmp("-c", argv[i])) {
+ cfg.allowComments = 1;
+ } else if (!strcmp("-u", argv[i])) {
+ cfg.checkUTF8 = 0;
+ } else {
+ fprintf(stderr, "unrecognized option: '%s'\n\n", argv[i]);
+ usage(argv[0]);
+ }
+ }
+ } else if (argc != 1) {
+ usage(argv[0]);
+ }
+
+ /* allocate a parser */
+ hand = yajl_alloc(NULL, &cfg, NULL, NULL);
+
+ while (!done) {
+ rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
+
+ retval = 0;
+
+ if (rd == 0) {
+ if (!feof(stdin)) {
+ if (!quiet) {
+ fprintf(stderr, "error encountered on file read\n");
+ }
+ retval = 1;
+ break;
+ }
+ done = 1;
+ }
+ fileData[rd] = 0;
+
+ if (done)
+ /* parse any remaining buffered data */
+ stat = yajl_parse_complete(hand);
+ else
+ /* read file data, pass to parser */
+ stat = yajl_parse(hand, fileData, rd);
+
+ if (stat != yajl_status_ok &&
+ stat != yajl_status_insufficient_data)
+ {
+ if (!quiet) {
+ unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
+ fprintf(stderr, "%s", (const char *) str);
+ yajl_free_error(hand, str);
+ }
+ retval = 1;
+ break;
+ }
+ }
+
+ yajl_free(hand);
+
+ if (!quiet) {
+ printf("JSON is %s\n", retval ? "invalid" : "valid");
+ }
+
+ return retval;
+}
diff --git a/jcnf/yajl/rfc4627.txt b/jcnf/yajl/rfc4627.txt
new file mode 100644
index 0000000..c3325a9
--- /dev/null
+++ b/jcnf/yajl/rfc4627.txt
@@ -0,0 +1,3 @@
+
+See <http://www.ietf.org/rfc/rfc4627.txt>
+
diff --git a/jcnf/yajl/run_tests.sh b/jcnf/yajl/run_tests.sh
new file mode 100644
index 0000000..174932f
--- /dev/null
+++ b/jcnf/yajl/run_tests.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+
+DIFF_FLAGS="-u"
+if [[ `uname` == *W32* ]] ; then
+ DIFF_FLAGS="-wu"
+fi
+
+# find test binary on both platforms. allow the caller to force a
+# particular test binary (useful for non-cmake build systems).
+if [ -z "$testBin" ]; then
+ testBin="../build/test/Debug/yajl_test.exe"
+ if [[ ! -x $testBin ]] ; then
+ testBin="../build/test/yajl_test"
+ if [[ ! -x $testBin ]] ; then
+ echo "cannot execute test binary: '$testBin'"
+ exit 1;
+ fi
+ fi
+fi
+
+echo "using test binary: $testBin"
+
+let testsSucceeded=0
+let testsTotal=0
+
+for file in cases/*.json ; do
+ allowComments="-c"
+
+ # if the filename starts with dc_, we disallow comments for this test
+ if [[ $(basename $file) == dc_* ]] ; then
+ allowComments=""
+ fi
+ echo -n " test case: '$file': "
+ let iter=1
+ success="success"
+
+ # parse with a read buffer size ranging from 1-31 to stress stream parsing
+ while (( $iter < 32 )) && [ $success == "success" ] ; do
+ $testBin $allowComments -b $iter < $file > ${file}.test 2>&1
+ diff ${DIFF_FLAGS} ${file}.gold ${file}.test
+ if [[ $? == 0 ]] ; then
+ if (( $iter == 31 )) ; then let testsSucceeded+=1 ; fi
+ else
+ success="FAILURE"
+ let iter=32
+ fi
+ let iter+=1
+ rm ${file}.test
+ done
+
+ echo $success
+ let testsTotal+=1
+done
+
+echo $testsSucceeded/$testsTotal tests successful
+
+if [[ $testsSucceeded != $testsTotal ]] ; then
+ exit 1
+fi
+
+exit 0
diff --git a/jcnf/yajl/yajl.c b/jcnf/yajl/yajl.c
new file mode 100644
index 0000000..b0dc991
--- /dev/null
+++ b/jcnf/yajl/yajl.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_parse.h"
+#include "yajl_lex.h"
+#include "yajl_parser.h"
+#include "yajl_alloc.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+const char *
+yajl_status_to_string(yajl_status stat)
+{
+ const char * statStr = "unknown";
+ switch (stat) {
+ case yajl_status_ok:
+ statStr = "ok, no error";
+ break;
+ case yajl_status_client_canceled:
+ statStr = "client canceled parse";
+ break;
+ case yajl_status_insufficient_data:
+ statStr = "eof was met before the parse could complete";
+ break;
+ case yajl_status_error:
+ statStr = "parse error";
+ break;
+ }
+ return statStr;
+}
+
+yajl_handle
+yajl_alloc(const yajl_callbacks * callbacks,
+ const yajl_parser_config * config,
+ const yajl_alloc_funcs * afs,
+ void * ctx)
+{
+ unsigned int allowComments = 0;
+ unsigned int validateUTF8 = 0;
+ yajl_handle hand = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
+
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
+
+ if (config != NULL) {
+ allowComments = config->allowComments;
+ validateUTF8 = config->checkUTF8;
+ }
+
+ hand->callbacks = callbacks;
+ hand->ctx = ctx;
+ hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
+ hand->errorOffset = 0;
+ hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
+ yajl_bs_init(hand->stateStack, &(hand->alloc));
+
+ yajl_bs_push(hand->stateStack, yajl_state_start);
+
+ return hand;
+}
+
+void
+yajl_free(yajl_handle handle)
+{
+ yajl_bs_free(handle->stateStack);
+ yajl_buf_free(handle->decodeBuf);
+ yajl_lex_free(handle->lexer);
+ YA_FREE(&(handle->alloc), handle);
+}
+
+yajl_status
+yajl_parse(yajl_handle hand, const unsigned char * jsonText,
+ unsigned int jsonTextLen)
+{
+ unsigned int offset = 0;
+ yajl_status status;
+ status = yajl_do_parse(hand, &offset, jsonText, jsonTextLen);
+ return status;
+}
+
+yajl_status
+yajl_parse_complete(yajl_handle hand)
+{
+ /* The particular case we want to handle is a trailing number.
+ * Further input consisting of digits could cause our interpretation
+ * of the number to change (buffered "1" but "2" comes in).
+ * A very simple approach to this is to inject whitespace to terminate
+ * any number in the lex buffer.
+ */
+ return yajl_parse(hand, (const unsigned char *)" ", 1);
+}
+
+unsigned char *
+yajl_get_error(yajl_handle hand, int verbose,
+ const unsigned char * jsonText, unsigned int jsonTextLen)
+{
+ return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose);
+}
+
+void
+yajl_free_error(yajl_handle hand, unsigned char * str)
+{
+ /* use memory allocation functions if set */
+ YA_FREE(&(hand->alloc), str);
+}
+
+/* XXX: add utility routines to parse from file */
diff --git a/jcnf/yajl/yajl_alloc.c b/jcnf/yajl/yajl_alloc.c
new file mode 100644
index 0000000..0b4bf37
--- /dev/null
+++ b/jcnf/yajl/yajl_alloc.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#include "yajl_alloc.h"
+#include <stdlib.h>
+
+static void * yajl_internal_malloc(void *ctx, unsigned int sz)
+{
+ return malloc(sz);
+}
+
+static void * yajl_internal_realloc(void *ctx, void * previous,
+ unsigned int sz)
+{
+ return realloc(previous, sz);
+}
+
+static void yajl_internal_free(void *ctx, void * ptr)
+{
+ free(ptr);
+}
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf)
+{
+ yaf->malloc = yajl_internal_malloc;
+ yaf->free = yajl_internal_free;
+ yaf->realloc = yajl_internal_realloc;
+ yaf->ctx = NULL;
+}
+
diff --git a/jcnf/yajl/yajl_alloc.h b/jcnf/yajl/yajl_alloc.h
new file mode 100644
index 0000000..988a6c5
--- /dev/null
+++ b/jcnf/yajl/yajl_alloc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#ifndef __YAJL_ALLOC_H__
+#define __YAJL_ALLOC_H__
+
+#include "yajl_common.h"
+
+#define YA_MALLOC(afs, sz) (afs)->malloc((afs)->ctx, (sz))
+#define YA_FREE(afs, ptr) (afs)->free((afs)->ctx, (ptr))
+#define YA_REALLOC(afs, ptr, sz) (afs)->realloc((afs)->ctx, (ptr), (sz))
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf);
+
+#endif
diff --git a/jcnf/yajl/yajl_buf.c b/jcnf/yajl/yajl_buf.c
new file mode 100644
index 0000000..97f1ced
--- /dev/null
+++ b/jcnf/yajl/yajl_buf.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_buf.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define YAJL_BUF_INIT_SIZE 2048
+
+struct yajl_buf_t {
+ unsigned int len;
+ unsigned int used;
+ unsigned char * data;
+ yajl_alloc_funcs * alloc;
+};
+
+static
+void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
+{
+ unsigned int need;
+
+ assert(buf != NULL);
+
+ /* first call */
+ if (buf->data == NULL) {
+ buf->len = YAJL_BUF_INIT_SIZE;
+ buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
+ buf->data[0] = 0;
+ }
+
+ need = buf->len;
+
+ while (want >= (need - buf->used)) need <<= 1;
+
+ if (need != buf->len) {
+ buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
+ buf->len = need;
+ }
+}
+
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
+{
+ yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
+ memset((void *) b, 0, sizeof(struct yajl_buf_t));
+ b->alloc = alloc;
+ return b;
+}
+
+void yajl_buf_free(yajl_buf buf)
+{
+ assert(buf != NULL);
+ if (buf->data) YA_FREE(buf->alloc, buf->data);
+ YA_FREE(buf->alloc, buf);
+}
+
+void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
+{
+ yajl_buf_ensure_available(buf, len);
+ if (len > 0) {
+ assert(data != NULL);
+ memcpy(buf->data + buf->used, data, len);
+ buf->used += len;
+ buf->data[buf->used] = 0;
+ }
+}
+
+void yajl_buf_clear(yajl_buf buf)
+{
+ buf->used = 0;
+ if (buf->data) buf->data[buf->used] = 0;
+}
+
+const unsigned char * yajl_buf_data(yajl_buf buf)
+{
+ return buf->data;
+}
+
+unsigned int yajl_buf_len(yajl_buf buf)
+{
+ return buf->used;
+}
+
+void
+yajl_buf_truncate(yajl_buf buf, unsigned int len)
+{
+ assert(len <= buf->used);
+ buf->used = len;
+}
diff --git a/jcnf/yajl/yajl_buf.h b/jcnf/yajl/yajl_buf.h
new file mode 100644
index 0000000..e5b2c82
--- /dev/null
+++ b/jcnf/yajl/yajl_buf.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_BUF_H__
+#define __YAJL_BUF_H__
+
+#include "yajl_common.h"
+#include "yajl_alloc.h"
+
+/*
+ * Implementation/performance notes. If this were moved to a header
+ * only implementation using #define's where possible we might be
+ * able to sqeeze a little performance out of the guy by killing function
+ * call overhead. YMMV.
+ */
+
+/**
+ * yajl_buf is a buffer with exponential growth. the buffer ensures that
+ * you are always null padded.
+ */
+typedef struct yajl_buf_t * yajl_buf;
+
+/* allocate a new buffer */
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc);
+
+/* free the buffer */
+void yajl_buf_free(yajl_buf buf);
+
+/* append a number of bytes to the buffer */
+void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len);
+
+/* empty the buffer */
+void yajl_buf_clear(yajl_buf buf);
+
+/* get a pointer to the beginning of the buffer */
+const unsigned char * yajl_buf_data(yajl_buf buf);
+
+/* get the length of the buffer */
+unsigned int yajl_buf_len(yajl_buf buf);
+
+/* truncate the buffer */
+void yajl_buf_truncate(yajl_buf buf, unsigned int len);
+
+#endif
diff --git a/jcnf/yajl/yajl_bytestack.h b/jcnf/yajl/yajl_bytestack.h
new file mode 100644
index 0000000..9ce192f
--- /dev/null
+++ b/jcnf/yajl/yajl_bytestack.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * A header only implementation of a simple stack of bytes, used in YAJL
+ * to maintain parse state.
+ */
+
+#ifndef __YAJL_BYTESTACK_H__
+#define __YAJL_BYTESTACK_H__
+
+#include "yajl_common.h"
+
+#define YAJL_BS_INC 128
+
+typedef struct yajl_bytestack_t
+{
+ unsigned char * stack;
+ unsigned int size;
+ unsigned int used;
+ yajl_alloc_funcs * yaf;
+} yajl_bytestack;
+
+/* initialize a bytestack */
+#define yajl_bs_init(obs, _yaf) { \
+ (obs).stack = NULL; \
+ (obs).size = 0; \
+ (obs).used = 0; \
+ (obs).yaf = (_yaf); \
+ } \
+
+
+/* initialize a bytestack */
+#define yajl_bs_free(obs) \
+ if ((obs).stack) (obs).yaf->free((obs).yaf->ctx, (obs).stack);
+
+#define yajl_bs_current(obs) \
+ (assert((obs).used > 0), (obs).stack[(obs).used - 1])
+
+#define yajl_bs_push(obs, byte) { \
+ if (((obs).size - (obs).used) == 0) { \
+ (obs).size += YAJL_BS_INC; \
+ (obs).stack = (obs).yaf->realloc((obs).yaf->ctx,\
+ (void *) (obs).stack, (obs).size);\
+ } \
+ (obs).stack[((obs).used)++] = (byte); \
+}
+
+/* removes the top item of the stack, returns nothing */
+#define yajl_bs_pop(obs) { ((obs).used)--; }
+
+#define yajl_bs_set(obs, byte) \
+ (obs).stack[((obs).used) - 1] = (byte);
+
+
+#endif
diff --git a/jcnf/yajl/yajl_common.h b/jcnf/yajl/yajl_common.h
new file mode 100644
index 0000000..9ad5eb4
--- /dev/null
+++ b/jcnf/yajl/yajl_common.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_COMMON_H__
+#define __YAJL_COMMON_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define YAJL_MAX_DEPTH 128
+
+/* msft dll export gunk. To build a DLL on windows, you
+ * must define WIN32, YAJL_SHARED, and YAJL_BUILD. To use a shared
+ * DLL, you must define YAJL_SHARED and WIN32 */
+#if defined(WIN32) && defined(YAJL_SHARED)
+# ifdef YAJL_BUILD
+# define YAJL_API __declspec(dllexport)
+# else
+# define YAJL_API __declspec(dllimport)
+# endif
+#else
+# define YAJL_API
+#endif
+
+/** pointer to a malloc function, supporting client overriding memory
+ * allocation routines */
+typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz);
+
+/** 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. */
+typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, unsigned int sz);
+
+/** 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 */
+ yajl_malloc_func malloc;
+ /** 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 */
+ yajl_free_func free;
+ /** a context pointer that will be passed to above allocation routines */
+ void * ctx;
+} yajl_alloc_funcs;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jcnf/yajl/yajl_encode.c b/jcnf/yajl/yajl_encode.c
new file mode 100644
index 0000000..184277b
--- /dev/null
+++ b/jcnf/yajl/yajl_encode.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_encode.h"
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+static void CharToHex(unsigned char c, char * hexBuf)
+{
+ const char * hexchar = "0123456789ABCDEF";
+ hexBuf[0] = hexchar[c >> 4];
+ hexBuf[1] = hexchar[c & 0x0F];
+}
+
+void
+yajl_string_encode(yajl_buf buf, const unsigned char * str,
+ unsigned int len)
+{
+ unsigned int beg = 0;
+ unsigned int end = 0;
+ char hexBuf[7];
+ hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0';
+ hexBuf[6] = 0;
+
+ while (end < len) {
+ const char * escaped = NULL;
+ switch (str[end]) {
+ case '\r': escaped = "\\r"; break;
+ case '\n': escaped = "\\n"; break;
+ case '\\': escaped = "\\\\"; break;
+ /* case '/': escaped = "\\/"; break; */
+ case '"': escaped = "\\\""; break;
+ case '\f': escaped = "\\f"; break;
+ case '\b': escaped = "\\b"; break;
+ case '\t': escaped = "\\t"; break;
+ default:
+ if ((unsigned char) str[end] < 32) {
+ CharToHex(str[end], hexBuf + 4);
+ escaped = hexBuf;
+ }
+ break;
+ }
+ if (escaped != NULL) {
+ yajl_buf_append(buf, str + beg, end - beg);
+ yajl_buf_append(buf, escaped, strlen(escaped));
+ beg = ++end;
+ } else {
+ ++end;
+ }
+ }
+ yajl_buf_append(buf, str + beg, end - beg);
+}
+
+static void hexToDigit(unsigned int * val, const unsigned char * hex)
+{
+ unsigned int i;
+ for (i=0;i<4;i++) {
+ unsigned char c = hex[i];
+ if (c >= 'A') c = (c & ~0x20) - 7;
+ c -= '0';
+ assert(!(c & 0xF0));
+ *val = (*val << 4) | c;
+ }
+}
+
+static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf)
+{
+ if (codepoint < 0x80) {
+ utf8Buf[0] = (char) codepoint;
+ utf8Buf[1] = 0;
+ } else if (codepoint < 0x0800) {
+ utf8Buf[0] = (char) ((codepoint >> 6) | 0xC0);
+ utf8Buf[1] = (char) ((codepoint & 0x3F) | 0x80);
+ utf8Buf[2] = 0;
+ } else if (codepoint < 0x10000) {
+ utf8Buf[0] = (char) ((codepoint >> 12) | 0xE0);
+ utf8Buf[1] = (char) (((codepoint >> 6) & 0x3F) | 0x80);
+ utf8Buf[2] = (char) ((codepoint & 0x3F) | 0x80);
+ utf8Buf[3] = 0;
+ } else if (codepoint < 0x200000) {
+ utf8Buf[0] =(char)((codepoint >> 18) | 0xF0);
+ utf8Buf[1] =(char)(((codepoint >> 12) & 0x3F) | 0x80);
+ utf8Buf[2] =(char)(((codepoint >> 6) & 0x3F) | 0x80);
+ utf8Buf[3] =(char)((codepoint & 0x3F) | 0x80);
+ utf8Buf[4] = 0;
+ } else {
+ utf8Buf[0] = '?';
+ utf8Buf[1] = 0;
+ }
+}
+
+void yajl_string_decode(yajl_buf buf, const unsigned char * str,
+ unsigned int len)
+{
+ unsigned int beg = 0;
+ unsigned int end = 0;
+
+ while (end < len) {
+ if (str[end] == '\\') {
+ char utf8Buf[5];
+ const char * unescaped = "?";
+ yajl_buf_append(buf, str + beg, end - beg);
+ switch (str[++end]) {
+ case 'r': unescaped = "\r"; break;
+ case 'n': unescaped = "\n"; break;
+ case '\\': unescaped = "\\"; break;
+ case '/': unescaped = "/"; break;
+ case '"': unescaped = "\""; break;
+ case 'f': unescaped = "\f"; break;
+ case 'b': unescaped = "\b"; break;
+ case 't': unescaped = "\t"; break;
+ case 'u': {
+ unsigned int codepoint = 0;
+ hexToDigit(&codepoint, str + ++end);
+ end+=3;
+ /* check if this is a surrogate */
+ if ((codepoint & 0xFC00) == 0xD800) {
+ end++;
+ if (str[end] == '\\' && str[end + 1] == 'u') {
+ unsigned int surrogate = 0;
+ hexToDigit(&surrogate, str + end + 2);
+ codepoint =
+ (((codepoint & 0x3F) << 10) |
+ ((((codepoint >> 6) & 0xF) + 1) << 16) |
+ (surrogate & 0x3FF));
+ end += 5;
+ } else {
+ unescaped = "?";
+ break;
+ }
+ }
+
+ Utf32toUtf8(codepoint, utf8Buf);
+ unescaped = utf8Buf;
+ break;
+ }
+ default:
+ assert("this should never happen" == NULL);
+ }
+ yajl_buf_append(buf, unescaped, strlen(unescaped));
+ beg = ++end;
+ } else {
+ end++;
+ }
+ }
+ yajl_buf_append(buf, str + beg, end - beg);
+}
diff --git a/jcnf/yajl/yajl_encode.h b/jcnf/yajl/yajl_encode.h
new file mode 100644
index 0000000..8bd01af
--- /dev/null
+++ b/jcnf/yajl/yajl_encode.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_ENCODE_H__
+#define __YAJL_ENCODE_H__
+
+#include "yajl_buf.h"
+
+void yajl_string_encode(yajl_buf buf, const unsigned char * str,
+ unsigned int length);
+
+void yajl_string_decode(yajl_buf buf, const unsigned char * str,
+ unsigned int length);
+
+#endif
diff --git a/jcnf/yajl/yajl_gen.c b/jcnf/yajl/yajl_gen.c
new file mode 100644
index 0000000..a400176
--- /dev/null
+++ b/jcnf/yajl/yajl_gen.c
@@ -0,0 +1,381 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_gen.h"
+#include "yajl_buf.h"
+#include "yajl_encode.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+typedef enum {
+ yajl_gen_start,
+ yajl_gen_map_start,
+ yajl_gen_map_key,
+ yajl_gen_map_val,
+ yajl_gen_array_start,
+ yajl_gen_in_array,
+ yajl_gen_complete,
+ yajl_gen_error
+} yajl_gen_state;
+
+struct yajl_gen_t
+{
+ unsigned int depth;
+ unsigned int pretty;
+ const char * indentString;
+ yajl_gen_state state[YAJL_MAX_DEPTH];
+ yajl_buf buf;
+ unsigned char *pendingComment;
+ unsigned int pendingLen; /* Length of pending comment */
+ int pendingCpp; /* NZ if comment is C++ style, Z if C */
+ /* memory allocation routines */
+ yajl_alloc_funcs alloc;
+};
+
+yajl_gen
+yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * afs)
+{
+ yajl_gen g = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
+ memset((void *) g, 0, sizeof(struct yajl_gen_t));
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
+
+ if (config) {
+ g->pretty = config->beautify;
+ g->indentString = config->indentString ? config->indentString : " ";
+ }
+ g->buf = yajl_buf_alloc(&(g->alloc));
+
+ return g;
+}
+
+void
+yajl_gen_free(yajl_gen g)
+{
+ yajl_buf_free(g->buf);
+ YA_FREE(&(g->alloc), g);
+}
+
+#define INSERT_EOL \
+ if (g->pretty || g->pendingComment != NULL) \
+ yajl_insert_eol(g);
+
+#define INSERT_SEP \
+ if (g->state[g->depth] == yajl_gen_map_key || \
+ g->state[g->depth] == yajl_gen_in_array) { \
+ yajl_buf_append(g->buf, ",", 1); \
+ INSERT_EOL; \
+ } else if (g->state[g->depth] == yajl_gen_map_val) { \
+ yajl_buf_append(g->buf, ":", 1); \
+ if (g->pretty) yajl_buf_append(g->buf, " ", 1); \
+ }
+
+#define INSERT_WHITESPACE \
+ if (g->pretty) { \
+ if (g->state[g->depth] != yajl_gen_map_val) { \
+ unsigned int _i; \
+ for (_i=0;_i<g->depth;_i++) \
+ yajl_buf_append(g->buf, g->indentString, \
+ strlen(g->indentString)); \
+ } \
+ }
+
+#define INSERT_SOME_WHITESPACE \
+ if (g->pretty) { \
+ if (g->state[g->depth] != yajl_gen_map_val) { \
+ yajl_buf_append(g->buf, g->indentString, \
+ strlen(g->indentString)); \
+ } \
+ }
+
+#define ENSURE_NOT_KEY \
+ if (g->state[g->depth] == yajl_gen_map_key) { \
+ return yajl_gen_keys_must_be_strings; \
+ } \
+
+/* check that we're not complete, or in error state. in a valid state
+ * to be generating */
+#define ENSURE_VALID_STATE \
+ if (g->state[g->depth] == yajl_gen_error) { \
+ return yajl_gen_in_error_state;\
+ } else if (g->state[g->depth] == yajl_gen_complete) { \
+ return yajl_gen_generation_complete; \
+ }
+
+#define INCREMENT_DEPTH \
+ if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded;
+
+#define APPENDED_ATOM \
+ switch (g->state[g->depth]) { \
+ case yajl_gen_start: \
+ g->state[g->depth] = yajl_gen_complete; \
+ break; \
+ case yajl_gen_map_start: \
+ case yajl_gen_map_key: \
+ g->state[g->depth] = yajl_gen_map_val; \
+ break; \
+ case yajl_gen_array_start: \
+ g->state[g->depth] = yajl_gen_in_array; \
+ break; \
+ case yajl_gen_map_val: \
+ g->state[g->depth] = yajl_gen_map_key; \
+ break; \
+ default: \
+ break; \
+ } \
+
+#define FINAL_NEWLINE \
+ if (g->pretty && g->state[g->depth] == yajl_gen_complete) \
+ INSERT_EOL
+
+/* Insert an end of line, and take care of any */
+/* pending comments */
+static void yajl_insert_eol(yajl_gen g) {
+ if (g->pendingComment != NULL) {
+ INSERT_SOME_WHITESPACE;
+ if (g->pendingCpp)
+ yajl_buf_append(g->buf, "//", 2);
+ else
+ yajl_buf_append(g->buf, "/*", 2);
+ yajl_string_encode(g->buf, g->pendingComment, g->pendingLen);
+ if (!g->pendingCpp)
+ yajl_buf_append(g->buf, "*/", 2);
+ free(g->pendingComment);
+ g->pendingComment = NULL;
+ g->pendingLen = 0;
+ g->pendingCpp = 0;
+ }
+ yajl_buf_append(g->buf, "\n", 1);
+}
+
+/* Insert a comment at the end of the line. Append if there is already */
+/* one pending. */
+static void yajl_insert_pending_comment(
+yajl_gen g, const unsigned char * str, unsigned int len, int cpp) {
+ if (g->pendingComment != NULL) {
+ unsigned int tlen = g->pendingLen + 0 + len;
+ unsigned char *pendingComment;
+ pendingComment = (unsigned char *) realloc(g->pendingComment, sizeof(char) * tlen);
+ memcpy(pendingComment + g->pendingLen + 0, str, len);
+ g->pendingComment = pendingComment;
+ g->pendingLen = tlen;
+ } else {
+ g->pendingComment = (unsigned char *) malloc(sizeof(char) * len);
+ memcpy(g->pendingComment, str, len);
+ g->pendingLen = len;
+ }
+ g->pendingCpp = cpp;
+}
+
+yajl_gen_status
+yajl_gen_integer(yajl_gen g, long int number)
+{
+ char i[32];
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ sprintf(i, "%ld", number);
+ yajl_buf_append(g->buf, i, strlen(i));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_double(yajl_gen g, double number)
+{
+ char i[32];
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ sprintf(i, "%g", number);
+ yajl_buf_append(g->buf, i, strlen(i));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_number(yajl_gen g, const char * s, unsigned int l)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, s, l);
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_string(yajl_gen g, const unsigned char * str,
+ unsigned int len)
+{
+ ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "\"", 1);
+ yajl_string_encode(g->buf, str, len);
+ yajl_buf_append(g->buf, "\"", 1);
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_null(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "null", strlen("null"));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_bool(yajl_gen g, int boolean)
+{
+ const char * val = boolean ? "true" : "false";
+
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, val, strlen(val));
+ APPENDED_ATOM;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_map_open(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ INCREMENT_DEPTH;
+
+ g->state[g->depth] = yajl_gen_map_start;
+ yajl_buf_append(g->buf, "{", 1);
+ INSERT_EOL;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_map_close(yajl_gen g)
+{
+ ENSURE_VALID_STATE;
+ (g->depth)--;
+ INSERT_EOL;
+ APPENDED_ATOM;
+ INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "}", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_array_open(yajl_gen g)
+{
+ ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE;
+ INCREMENT_DEPTH;
+ g->state[g->depth] = yajl_gen_array_start;
+ yajl_buf_append(g->buf, "[", 1);
+ INSERT_EOL;
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_array_close(yajl_gen g)
+{
+ ENSURE_VALID_STATE;
+ INSERT_EOL;
+ (g->depth)--;
+ APPENDED_ATOM;
+ INSERT_WHITESPACE;
+ yajl_buf_append(g->buf, "]", 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_c_comment(yajl_gen g, const unsigned char * str,
+ unsigned int len, int dlytoeol)
+{
+ ENSURE_VALID_STATE;
+ if (dlytoeol) {
+ yajl_insert_pending_comment(g, str, len, 0);
+ } else {
+ if (g->pretty)
+ yajl_buf_append(g->buf, " /*", 3);
+ else
+ yajl_buf_append(g->buf, "/*", 2);
+ yajl_string_encode(g->buf, str, len);
+ if (g->pretty)
+ yajl_buf_append(g->buf, "*/ ", 3);
+ else
+ yajl_buf_append(g->buf, "*/", 2);
+ }
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_cpp_comment(yajl_gen g, const unsigned char * str,
+ unsigned int len)
+{
+ ENSURE_VALID_STATE;
+ yajl_insert_pending_comment(g, str, len, 1);
+ FINAL_NEWLINE;
+ return yajl_gen_status_ok;
+}
+
+yajl_gen_status
+yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf,
+ unsigned int * len)
+{
+ *buf = yajl_buf_data(g->buf);
+ *len = yajl_buf_len(g->buf);
+ return yajl_gen_status_ok;
+}
+
+void
+yajl_gen_clear(yajl_gen g)
+{
+ yajl_buf_clear(g->buf);
+}
diff --git a/jcnf/yajl/yajl_gen.h b/jcnf/yajl/yajl_gen.h
new file mode 100644
index 0000000..5bde0e8
--- /dev/null
+++ b/jcnf/yajl/yajl_gen.h
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_gen.h
+ * Interface to YAJL's JSON generation facilities.
+ */
+
+#include "yajl_common.h"
+
+#ifndef __YAJL_GEN_H__
+#define __YAJL_GEN_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /** generator status codes */
+ typedef enum {
+ /** 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 */
+ yajl_gen_keys_must_be_strings,
+ /** YAJL's maximum generation depth was exceeded. see
+ * YAJL_MAX_DEPTH */
+ yajl_max_depth_exceeded,
+ /** 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 */
+ yajl_gen_generation_complete
+ } yajl_gen_status;
+
+ /** an opaque handle to a generator */
+ typedef struct yajl_gen_t * yajl_gen;
+
+ /** configuration structure for the generator */
+ typedef struct {
+ /** generate indented (beautiful) output */
+ unsigned int beautify;
+ /** an opportunity to define an indent string. such as \\t or
+ * some number of spaces. default is four spaces ' '. This
+ * member is only relevant when beautify is true */
+ const char * indentString;
+ } yajl_gen_config;
+
+ /** allocate a generator handle
+ * \param config a pointer to a structure containing parameters which
+ * configure the behavior of the json generator
+ * \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.
+ *
+ * \returns an allocated handle on success, NULL on failure (bad params)
+ */
+ yajl_gen YAJL_API yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * allocFuncs);
+
+ /** free a generator handle */
+ void YAJL_API yajl_gen_free(yajl_gen handle);
+
+ yajl_gen_status YAJL_API yajl_gen_integer(yajl_gen hand, long int number);
+ yajl_gen_status YAJL_API yajl_gen_double(yajl_gen hand, double number);
+ yajl_gen_status YAJL_API yajl_gen_number(yajl_gen hand,
+ const char * num,
+ unsigned int len);
+ yajl_gen_status YAJL_API yajl_gen_string(yajl_gen hand,
+ const unsigned char * str,
+ unsigned int len);
+ yajl_gen_status YAJL_API yajl_gen_null(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_bool(yajl_gen hand, int boolean);
+ yajl_gen_status YAJL_API yajl_gen_map_open(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_map_close(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_array_open(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_array_close(yajl_gen hand);
+ yajl_gen_status YAJL_API yajl_gen_c_comment(yajl_gen hand,
+ const unsigned char * str,
+ unsigned int len, int dlytoeol);
+ yajl_gen_status YAJL_API yajl_gen_cpp_comment(yajl_gen hand,
+ const unsigned char * str,
+ unsigned int len);
+
+ /** access the null terminated generator buffer. If incrementally
+ * outputing JSON, one should call yajl_gen_clear to clear the
+ * buffer. This allows stream generation. */
+ yajl_gen_status YAJL_API yajl_gen_get_buf(yajl_gen hand,
+ const unsigned char ** buf,
+ unsigned int * len);
+
+ /** 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. */
+ void YAJL_API yajl_gen_clear(yajl_gen hand);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jcnf/yajl/yajl_lex.c b/jcnf/yajl/yajl_lex.c
new file mode 100644
index 0000000..56e563e
--- /dev/null
+++ b/jcnf/yajl/yajl_lex.c
@@ -0,0 +1,753 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_lex.h"
+#include "yajl_buf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+
+#ifdef YAJL_LEXER_DEBUG
+static const char *
+tokToStr(yajl_tok tok)
+{
+ switch (tok) {
+ case yajl_tok_bool: return "bool";
+ case yajl_tok_colon: return "colon";
+ case yajl_tok_comma: return "comma";
+ case yajl_tok_eof: return "eof";
+ case yajl_tok_error: return "error";
+ case yajl_tok_left_brace: return "brace";
+ case yajl_tok_left_bracket: return "bracket";
+ case yajl_tok_null: return "null";
+ case yajl_tok_integer: return "integer";
+ case yajl_tok_double: return "double";
+ case yajl_tok_right_brace: return "brace";
+ case yajl_tok_right_bracket: return "bracket";
+ case yajl_tok_string: return "string";
+ case yajl_tok_string_with_escapes: return "string_with_escapes";
+ case yajl_tok_c_comment: return "C comment";
+ case yajl_tok_cpp_comment: return "C++ comment";
+ }
+ return "unknown";
+}
+#endif
+
+/* Impact of the stream parsing feature on the lexer:
+ *
+ * YAJL support stream parsing. That is, the ability to parse the first
+ * bits of a chunk of JSON before the last bits are available (still on
+ * the network or disk). This makes the lexer more complex. The
+ * responsibility of the lexer is to handle transparently the case where
+ * a chunk boundary falls in the middle of a token. This is
+ * accomplished is via a buffer and a character reading abstraction.
+ *
+ * Overview of implementation
+ *
+ * When we lex to end of input string before end of token is hit, we
+ * copy all of the input text composing the token into our lexBuf.
+ *
+ * Every time we read a character, we do so through the readChar function.
+ * readChar's responsibility is to handle pulling all chars from the buffer
+ * before pulling chars from input text
+ */
+
+struct yajl_lexer_t {
+ /* the overal line and char offset into the data */
+ unsigned int lineOff;
+ unsigned int charOff;
+
+ /* error */
+ yajl_lex_error error;
+
+ /* a input buffer to handle the case where a token is spread over
+ * multiple chunks */
+ yajl_buf buf;
+
+ /* in the case where we have data in the lexBuf, bufOff holds
+ * the current offset into the lexBuf. */
+ unsigned int bufOff;
+
+ /* are we using the lex buf? */
+ unsigned int bufInUse;
+
+ /* shall we allow comments? */
+ unsigned int allowComments;
+
+ /* shall we validate utf8 inside strings? */
+ unsigned int validateUTF8;
+
+ yajl_alloc_funcs * alloc;
+};
+
+#define readChar(lxr, txt, off) \
+ (((lxr)->bufInUse && yajl_buf_len((lxr)->buf) && lxr->bufOff < yajl_buf_len((lxr)->buf)) ? \
+ (*((const unsigned char *) yajl_buf_data((lxr)->buf) + ((lxr)->bufOff)++)) : \
+ ((txt)[(*(off))++]))
+
+#define unreadChar(lxr, off) ((*(off) > 0) ? (*(off))-- : ((lxr)->bufOff--))
+
+yajl_lexer
+yajl_lex_alloc(yajl_alloc_funcs * alloc,
+ unsigned int allowComments, unsigned int validateUTF8)
+{
+ yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
+ memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
+ lxr->buf = yajl_buf_alloc(alloc);
+ lxr->allowComments = allowComments;
+ lxr->validateUTF8 = validateUTF8;
+ lxr->alloc = alloc;
+ return lxr;
+}
+
+void
+yajl_lex_free(yajl_lexer lxr)
+{
+ yajl_buf_free(lxr->buf);
+ YA_FREE(lxr->alloc, lxr);
+ return;
+}
+
+/* a lookup table which lets us quickly determine three things:
+ * VEC - valid escaped conrol char
+ * IJC - invalid json char
+ * VHC - valid hex char
+ * note. the solidus '/' may be escaped or not.
+ * note. the
+ */
+#define VEC 1
+#define IJC 2
+#define VHC 4
+static const char charLookupTable[256] =
+{
+/*00*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
+/*08*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
+/*10*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
+/*18*/ IJC , IJC , IJC , IJC , IJC , IJC , IJC , IJC ,
+
+/*20*/ 0 , 0 , VEC|IJC, 0 , 0 , 0 , 0 , 0 ,
+/*28*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , VEC ,
+/*30*/ VHC , VHC , VHC , VHC , VHC , VHC , VHC , VHC ,
+/*38*/ VHC , VHC , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+/*40*/ 0 , VHC , VHC , VHC , VHC , VHC , VHC , 0 ,
+/*48*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*50*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+/*58*/ 0 , 0 , 0 , 0 , VEC|IJC, 0 , 0 , 0 ,
+
+/*60*/ 0 , VHC , VEC|VHC, VHC , VHC , VHC , VEC|VHC, 0 ,
+/*68*/ 0 , 0 , 0 , 0 , 0 , 0 , VEC , 0 ,
+/*70*/ 0 , 0 , VEC , 0 , VEC , 0 , 0 , 0 ,
+/*78*/ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+/* include these so we don't have to always check the range of the char */
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ,
+ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0
+};
+
+/** process a variable length utf8 encoded codepoint.
+ *
+ * returns:
+ * yajl_tok_string - if valid utf8 char was parsed and offset was
+ * advanced
+ * yajl_tok_eof - if end of input was hit before validation could
+ * complete
+ * yajl_tok_error - if invalid utf8 was encountered
+ *
+ * NOTE: on error the offset will point to the first char of the
+ * invalid utf8 */
+#define UTF8_CHECK_EOF if (*offset >= jsonTextLen) { return yajl_tok_eof; }
+
+static yajl_tok
+yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset,
+ unsigned char curChar)
+{
+ if (curChar <= 0x7f) {
+ /* single byte */
+ return yajl_tok_string;
+ } else if ((curChar >> 5) == 0x6) {
+ /* two byte */
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) return yajl_tok_string;
+ } else if ((curChar >> 4) == 0x0e) {
+ /* three byte */
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) {
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) return yajl_tok_string;
+ }
+ } else if ((curChar >> 3) == 0x1e) {
+ /* four byte */
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) {
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) {
+ UTF8_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if ((curChar >> 6) == 0x2) return yajl_tok_string;
+ }
+ }
+ }
+
+ return yajl_tok_error;
+}
+
+/* lex a string. input is the lexer, pointer to beginning of
+ * json text, and start of string (offset).
+ * a token is returned which has the following meanings:
+ * yajl_tok_string: lex of string was successful. offset points to
+ * terminating '"'.
+ * yajl_tok_eof: end of text was encountered before we could complete
+ * the lex.
+ * yajl_tok_error: embedded in the string were unallowable chars. offset
+ * points to the offending char
+ */
+#define STR_CHECK_EOF \
+if (*offset >= jsonTextLen) { \
+ tok = yajl_tok_eof; \
+ goto finish_string_lex; \
+}
+
+static yajl_tok
+yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset)
+{
+ yajl_tok tok = yajl_tok_error;
+ int hasEscapes = 0;
+
+ for (;;) {
+ unsigned char curChar;
+
+ STR_CHECK_EOF;
+
+ curChar = readChar(lexer, jsonText, offset);
+
+ /* quote terminates */
+ if (curChar == '"') {
+ tok = yajl_tok_string;
+ break;
+ }
+ /* backslash escapes a set of control chars, */
+ else if (curChar == '\\') {
+ hasEscapes = 1;
+ STR_CHECK_EOF;
+
+ /* special case \u */
+ curChar = readChar(lexer, jsonText, offset);
+ if (curChar == 'u') {
+ unsigned int i = 0;
+
+ for (i=0;i<4;i++) {
+ STR_CHECK_EOF;
+ curChar = readChar(lexer, jsonText, offset);
+ if (!(charLookupTable[curChar] & VHC)) {
+ /* back up to offending char */
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_string_invalid_hex_char;
+ goto finish_string_lex;
+ }
+ }
+ } else if (!(charLookupTable[curChar] & VEC)) {
+ /* back up to offending char */
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_string_invalid_escaped_char;
+ goto finish_string_lex;
+ }
+ }
+ /* when not validating UTF8 it's a simple table lookup to determine
+ * if the present character is invalid */
+ else if(charLookupTable[curChar] & IJC) {
+ /* back up to offending char */
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_string_invalid_json_char;
+ goto finish_string_lex;
+ }
+ /* when in validate UTF8 mode we need to do some extra work */
+ else if (lexer->validateUTF8) {
+ yajl_tok t = yajl_lex_utf8_char(lexer, jsonText, jsonTextLen,
+ offset, curChar);
+
+ if (t == yajl_tok_eof) {
+ tok = yajl_tok_eof;
+ goto finish_string_lex;
+ } else if (t == yajl_tok_error) {
+ lexer->error = yajl_lex_string_invalid_utf8;
+ goto finish_string_lex;
+ }
+ }
+ /* accept it, and move on */
+ }
+ finish_string_lex:
+ /* tell our buddy, the parser, wether he needs to process this string
+ * again */
+ if (hasEscapes && tok == yajl_tok_string) {
+ tok = yajl_tok_string_with_escapes;
+ }
+
+ return tok;
+}
+
+#define RETURN_IF_EOF if (*offset >= jsonTextLen) return yajl_tok_eof;
+
+static yajl_tok
+yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset)
+{
+ /** XXX: numbers are the only entities in json that we must lex
+ * _beyond_ in order to know that they are complete. There
+ * is an ambiguous case for integers at EOF. */
+
+ unsigned char c;
+
+ yajl_tok tok = yajl_tok_integer;
+
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+
+ /* optional leading minus */
+ if (c == '-') {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ }
+
+ /* a single zero, or a series of integers */
+ if (c == '0') {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } else if (c >= '1' && c <= '9') {
+ do {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } while (c >= '0' && c <= '9');
+ } else {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_missing_integer_after_minus;
+ return yajl_tok_error;
+ }
+
+ /* optional fraction (indicates this is floating point) */
+ if (c == '.') {
+ int numRd = 0;
+
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+
+ while (c >= '0' && c <= '9') {
+ numRd++;
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ }
+
+ if (!numRd) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_missing_integer_after_decimal;
+ return yajl_tok_error;
+ }
+ tok = yajl_tok_double;
+ }
+
+ /* optional exponent (indicates this is floating point) */
+ if (c == 'e' || c == 'E') {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+
+ /* optional sign */
+ if (c == '+' || c == '-') {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ }
+
+ if (c >= '0' && c <= '9') {
+ do {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } while (c >= '0' && c <= '9');
+ } else {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_missing_integer_after_exponent;
+ return yajl_tok_error;
+ }
+ tok = yajl_tok_double;
+ }
+
+ /* we always go "one too far" */
+ unreadChar(lexer, offset);
+
+ return tok;
+}
+
+static yajl_tok
+yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset)
+{
+ unsigned char c;
+
+ yajl_tok tok;
+
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+
+ /* either slash or star expected */
+ if (c == '/') {
+ tok = yajl_tok_cpp_comment;
+ /* now we throw away until end of line */
+ do {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ } while (c != '\n');
+ } else if (c == '*') {
+ tok = yajl_tok_c_comment;
+ /* now we throw away until end of comment */
+ for (;;) {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ if (c == '*') {
+ RETURN_IF_EOF;
+ c = readChar(lexer, jsonText, offset);
+ if (c == '/') {
+ break;
+ } else {
+ unreadChar(lexer, offset);
+ }
+ }
+ }
+ } else {
+ lexer->error = yajl_lex_invalid_char;
+ tok = yajl_tok_error;
+ }
+
+ return tok;
+}
+
+yajl_tok
+yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset,
+ const unsigned char ** outBuf, unsigned int * outLen)
+{
+ yajl_tok tok = yajl_tok_error;
+ unsigned char c;
+ unsigned int startOffset = *offset;
+
+ *outBuf = NULL;
+ *outLen = 0;
+
+ for (;;) {
+ assert(*offset <= jsonTextLen);
+
+ if (*offset >= jsonTextLen) {
+ tok = yajl_tok_eof;
+ goto lexed;
+ }
+
+ c = readChar(lexer, jsonText, offset);
+
+ switch (c) {
+ case '{':
+ tok = yajl_tok_left_bracket;
+ goto lexed;
+ case '}':
+ tok = yajl_tok_right_bracket;
+ goto lexed;
+ case '[':
+ tok = yajl_tok_left_brace;
+ goto lexed;
+ case ']':
+ tok = yajl_tok_right_brace;
+ goto lexed;
+ case ',':
+ tok = yajl_tok_comma;
+ goto lexed;
+ case ':':
+ tok = yajl_tok_colon;
+ goto lexed;
+ case '\t': case '\n': case '\v': case '\f': case '\r': case ' ':
+ startOffset++;
+ break;
+ case 't': {
+ const char * want = "rue";
+ do {
+ if (*offset >= jsonTextLen) {
+ tok = yajl_tok_eof;
+ goto lexed;
+ }
+ c = readChar(lexer, jsonText, offset);
+ if (c != *want) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_invalid_string;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ } while (*(++want));
+ tok = yajl_tok_bool;
+ goto lexed;
+ }
+ case 'f': {
+ const char * want = "alse";
+ do {
+ if (*offset >= jsonTextLen) {
+ tok = yajl_tok_eof;
+ goto lexed;
+ }
+ c = readChar(lexer, jsonText, offset);
+ if (c != *want) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_invalid_string;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ } while (*(++want));
+ tok = yajl_tok_bool;
+ goto lexed;
+ }
+ case 'n': {
+ const char * want = "ull";
+ do {
+ if (*offset >= jsonTextLen) {
+ tok = yajl_tok_eof;
+ goto lexed;
+ }
+ c = readChar(lexer, jsonText, offset);
+ if (c != *want) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_invalid_string;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ } while (*(++want));
+ tok = yajl_tok_null;
+ goto lexed;
+ }
+ case '"': {
+ tok = yajl_lex_string(lexer, (const unsigned char *) jsonText,
+ jsonTextLen, offset);
+ goto lexed;
+ }
+ case '-':
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9': {
+ /* integer parsing wants to start from the beginning */
+ unreadChar(lexer, offset);
+ tok = yajl_lex_number(lexer, (const unsigned char *) jsonText,
+ jsonTextLen, offset);
+ goto lexed;
+ }
+ case '/':
+ /* hey, look, a probable comment! If comments are disabled
+ * it's an error. */
+ if (!lexer->allowComments) {
+ unreadChar(lexer, offset);
+ lexer->error = yajl_lex_unallowed_comment;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ /* if comments are enabled, then we should try to lex
+ * the thing. possible outcomes are
+ * - successful lex (tok_comment, which means continue),
+ * - malformed comment opening (slash not followed by
+ * '*' or '/') (tok_error)
+ * - eof hit. (tok_eof) */
+ tok = yajl_lex_comment(lexer, (const unsigned char *) jsonText,
+ jsonTextLen, offset);
+ if (tok == yajl_tok_c_comment
+ || tok == yajl_tok_cpp_comment) {
+ goto lexed;
+ }
+ /* hit error or eof, bail */
+ goto lexed;
+ default:
+ lexer->error = yajl_lex_invalid_char;
+ tok = yajl_tok_error;
+ goto lexed;
+ }
+ }
+
+
+ lexed:
+ /* need to append to buffer if the buffer is in use or
+ * if it's an EOF token */
+ if (tok == yajl_tok_eof || lexer->bufInUse) {
+ if (!lexer->bufInUse) yajl_buf_clear(lexer->buf);
+ lexer->bufInUse = 1;
+ yajl_buf_append(lexer->buf, jsonText + startOffset, *offset - startOffset);
+ lexer->bufOff = 0;
+
+ if (tok != yajl_tok_eof) {
+ *outBuf = yajl_buf_data(lexer->buf);
+ *outLen = yajl_buf_len(lexer->buf);
+ lexer->bufInUse = 0;
+ }
+ } else if (tok != yajl_tok_error) {
+ *outBuf = jsonText + startOffset;
+ *outLen = *offset - startOffset;
+ }
+
+ /* special case for strings. skip the quotes. */
+ if (tok == yajl_tok_string || tok == yajl_tok_string_with_escapes)
+ {
+ assert(*outLen >= 2);
+ (*outBuf)++;
+ *outLen -= 2;
+ }
+
+ /* remove comment delimeters */
+ if (tok == yajl_tok_c_comment)
+ {
+ assert(*outLen >= 4);
+ (*outBuf)+= 2;
+ *outLen -= 4;
+ }
+ if (tok == yajl_tok_cpp_comment)
+ {
+ assert(*outLen >= 2);
+ (*outBuf)+= 2;
+ *outLen -= 2;
+
+ if (*outLen >= 1 && (*outBuf)[(*outLen)-1] == 0x0a)
+ *outLen -= 1;
+ }
+
+
+#ifdef YAJL_LEXER_DEBUG
+ if (tok == yajl_tok_error) {
+ printf("lexical error: %s\n",
+ yajl_lex_error_to_string(yajl_lex_get_error(lexer)));
+ } else if (tok == yajl_tok_eof) {
+ printf("EOF hit\n");
+ } else {
+ printf("lexed %s: '", tokToStr(tok));
+ fwrite(*outBuf, 1, *outLen, stdout);
+ printf("'\n");
+ }
+#endif
+
+ return tok;
+}
+
+const char *
+yajl_lex_error_to_string(yajl_lex_error error)
+{
+ switch (error) {
+ case yajl_lex_e_ok:
+ return "ok, no error";
+ case yajl_lex_string_invalid_utf8:
+ return "invalid bytes in UTF8 string.";
+ case yajl_lex_string_invalid_escaped_char:
+ return "inside a string, '\\' occurs before a character "
+ "which it may not.";
+ case yajl_lex_string_invalid_json_char:
+ return "invalid character inside string.";
+ case yajl_lex_string_invalid_hex_char:
+ return "invalid (non-hex) character occurs after '\\u' inside "
+ "string.";
+ case yajl_lex_invalid_char:
+ return "invalid char in json text.";
+ case yajl_lex_invalid_string:
+ return "invalid string in json text.";
+ case yajl_lex_missing_integer_after_exponent:
+ return "malformed number, a digit is required after the exponent.";
+ case yajl_lex_missing_integer_after_decimal:
+ return "malformed number, a digit is required after the "
+ "decimal point.";
+ case yajl_lex_missing_integer_after_minus:
+ return "malformed number, a digit is required after the "
+ "minus sign.";
+ case yajl_lex_unallowed_comment:
+ return "probable comment found in input text, comments are "
+ "not enabled.";
+ }
+ return "unknown error code";
+}
+
+
+/** allows access to more specific information about the lexical
+ * error when yajl_lex_lex returns yajl_tok_error. */
+yajl_lex_error
+yajl_lex_get_error(yajl_lexer lexer)
+{
+ if (lexer == NULL) return (yajl_lex_error) -1;
+ return lexer->error;
+}
+
+unsigned int yajl_lex_current_line(yajl_lexer lexer)
+{
+ return lexer->lineOff;
+}
+
+unsigned int yajl_lex_current_char(yajl_lexer lexer)
+{
+ return lexer->charOff;
+}
+
+yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int offset)
+{
+ const unsigned char * outBuf;
+ unsigned int outLen;
+ unsigned int bufLen = yajl_buf_len(lexer->buf);
+ unsigned int bufOff = lexer->bufOff;
+ unsigned int bufInUse = lexer->bufInUse;
+ yajl_tok tok;
+
+ tok = yajl_lex_lex(lexer, jsonText, jsonTextLen, &offset,
+ &outBuf, &outLen);
+
+ lexer->bufOff = bufOff;
+ lexer->bufInUse = bufInUse;
+ yajl_buf_truncate(lexer->buf, bufLen);
+
+ return tok;
+}
diff --git a/jcnf/yajl/yajl_lex.h b/jcnf/yajl/yajl_lex.h
new file mode 100644
index 0000000..e1268ea
--- /dev/null
+++ b/jcnf/yajl/yajl_lex.h
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_LEX_H__
+#define __YAJL_LEX_H__
+
+#include "yajl_common.h"
+
+typedef enum {
+ yajl_tok_bool,
+ yajl_tok_colon,
+ yajl_tok_comma,
+ yajl_tok_eof,
+ yajl_tok_error,
+ yajl_tok_left_brace,
+ yajl_tok_left_bracket,
+ yajl_tok_null,
+ yajl_tok_right_brace,
+ yajl_tok_right_bracket,
+
+ /* we differentiate between integers and doubles to allow the
+ * parser to interpret the number without re-scanning */
+ yajl_tok_integer,
+ yajl_tok_double,
+
+ /* we differentiate between strings which require further processing,
+ * and strings that do not */
+ yajl_tok_string,
+ yajl_tok_string_with_escapes,
+
+ /* we return the two types of comment tokens as well */
+ yajl_tok_c_comment,
+ yajl_tok_cpp_comment
+
+} yajl_tok;
+
+typedef struct yajl_lexer_t * yajl_lexer;
+
+yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc,
+ unsigned int allowComments,
+ unsigned int validateUTF8);
+
+void yajl_lex_free(yajl_lexer lexer);
+
+/**
+ * run/continue a lex. "offset" is an input/output parameter.
+ * It should be initialized to zero for a
+ * new chunk of target text, and upon subsetquent calls with the same
+ * target text should passed with the value of the previous invocation.
+ *
+ * the client may be interested in the value of offset when an error is
+ * returned from the lexer. This allows the client to render useful
+n * error messages.
+ *
+ * When you pass the next chunk of data, context should be reinitialized
+ * to zero.
+ *
+ * Finally, the output buffer is usually just a pointer into the jsonText,
+ * however in cases where the entity being lexed spans multiple chunks,
+ * the lexer will buffer the entity and the data returned will be
+ * a pointer into that buffer.
+ *
+ * This behavior is abstracted from client code except for the performance
+ * implications which require that the client choose a reasonable chunk
+ * size to get adequate performance.
+ */
+yajl_tok yajl_lex_lex(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int * offset,
+ const unsigned char ** outBuf, unsigned int * outLen);
+
+/** have a peek at the next token, but don't move the lexer forward */
+yajl_tok yajl_lex_peek(yajl_lexer lexer, const unsigned char * jsonText,
+ unsigned int jsonTextLen, unsigned int offset);
+
+
+typedef enum {
+ yajl_lex_e_ok = 0,
+ yajl_lex_string_invalid_utf8,
+ yajl_lex_string_invalid_escaped_char,
+ yajl_lex_string_invalid_json_char,
+ yajl_lex_string_invalid_hex_char,
+ yajl_lex_invalid_char,
+ yajl_lex_invalid_string,
+ yajl_lex_missing_integer_after_decimal,
+ yajl_lex_missing_integer_after_exponent,
+ yajl_lex_missing_integer_after_minus,
+ yajl_lex_unallowed_comment
+} yajl_lex_error;
+
+const char * yajl_lex_error_to_string(yajl_lex_error error);
+
+/** allows access to more specific information about the lexical
+ * error when yajl_lex_lex returns yajl_tok_error. */
+yajl_lex_error yajl_lex_get_error(yajl_lexer lexer);
+
+/** get the current offset into the most recently lexed json string. */
+unsigned int yajl_lex_current_offset(yajl_lexer lexer);
+
+/** get the number of lines lexed by this lexer instance */
+unsigned int yajl_lex_current_line(yajl_lexer lexer);
+
+/** get the number of chars lexed by this lexer instance since the last
+ * \n or \r */
+unsigned int yajl_lex_current_char(yajl_lexer lexer);
+
+#endif
diff --git a/jcnf/yajl/yajl_parse.h b/jcnf/yajl/yajl_parse.h
new file mode 100644
index 0000000..250d3e1
--- /dev/null
+++ b/jcnf/yajl/yajl_parse.h
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_parse.h
+ * Interface to YAJL's JSON parsing facilities.
+ */
+
+#include "yajl_common.h"
+
+#ifndef __YAJL_PARSE_H__
+#define __YAJL_PARSE_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+ /** error codes returned from this interface */
+ typedef enum {
+ /** no error was encountered */
+ yajl_status_ok,
+ /** a client callback returned zero, stopping the parse */
+ yajl_status_client_canceled,
+ /** The parse cannot yet complete because more json input text
+ * is required, call yajl_parse with the next buffer of input text.
+ * (pertinent only when stream parsing) */
+ yajl_status_insufficient_data,
+ /** An error occured during the parse. Call yajl_get_error for
+ * more information about the encountered error */
+ yajl_status_error
+ } yajl_status;
+
+ /** attain a human readable, english, string for an error */
+ const char * YAJL_API yajl_status_to_string(yajl_status code);
+
+ /** an opaque handle to a parser */
+ typedef struct yajl_handle_t * yajl_handle;
+
+ /** yajl is an event driven parser. this means as json elements are
+ * parsed, you are called back to do something with the data. The
+ * functions in this table indicate the various events for which
+ * you will be called back. Each callback accepts a "context"
+ * pointer, this is a void * that is passed into the yajl_parse
+ * function which the client code may use to pass around context.
+ *
+ * All callbacks return an integer. If non-zero, the parse will
+ * 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 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 long int will result in a parse error.
+ */
+ typedef struct {
+ int (* yajl_null)(void * ctx);
+ int (* yajl_boolean)(void * ctx, int boolVal);
+ int (* yajl_integer)(void * ctx, long integerVal);
+ int (* yajl_double)(void * ctx, double doubleVal);
+ /** A callback which passes the string representation of the number
+ * back to the client. Will be used for all numbers when present */
+ int (* yajl_number)(void * ctx, const char * numberVal,
+ unsigned int numberLen);
+
+ /** strings are returned as pointers into the JSON text when,
+ * possible, as a result, they are _not_ null padded */
+ int (* yajl_string)(void * ctx, const unsigned char * stringVal,
+ unsigned int stringLen);
+ int (* yajl_c_comment)(void * ctx, const unsigned char * stringVal,
+ unsigned int stringLen);
+
+ int (* yajl_cpp_comment)(void * ctx, const unsigned char * stringVal,
+ unsigned int stringLen);
+
+ int (* yajl_start_map)(void * ctx);
+ int (* yajl_map_key)(void * ctx, const unsigned char * key,
+ unsigned int stringLen);
+ int (* yajl_end_map)(void * ctx);
+
+ int (* yajl_start_array)(void * ctx);
+ int (* yajl_end_array)(void * ctx);
+ } yajl_callbacks;
+
+ /** configuration structure for the generator */
+ typedef struct {
+ /** if nonzero, javascript style comments will be allowed in
+ * the json input, both slash star and slash slash */
+ unsigned int allowComments;
+ /** if nonzero, invalid UTF8 strings will cause a parse
+ * error */
+ unsigned int checkUTF8;
+ } yajl_parser_config;
+
+ /** allocate a parser handle
+ * \param callbacks a yajl callbacks structure specifying the
+ * functions to call when different JSON entities
+ * are encountered in the input text. May be NULL,
+ * which is only useful for validation.
+ * \param config configuration parameters for the parse.
+ * \param ctx a context pointer that will be passed to callbacks.
+ */
+ yajl_handle YAJL_API yajl_alloc(const yajl_callbacks * callbacks,
+ const yajl_parser_config * config,
+ const yajl_alloc_funcs * allocFuncs,
+ void * ctx);
+
+ /** free a parser handle */
+ void YAJL_API yajl_free(yajl_handle handle);
+
+ /** Parse some json!
+ * \param hand - a handle to the json parser allocated with yajl_alloc
+ * \param jsonText - a pointer to the UTF8 json text to be parsed
+ * \param jsonTextLength - the length, in bytes, of input text
+ */
+ yajl_status YAJL_API yajl_parse(yajl_handle hand,
+ const unsigned char * jsonText,
+ unsigned int jsonTextLength);
+
+ /** Parse any remaining buffered json.
+ * Since yajl is a stream-based parser, without an explicit end of
+ * input, yajl sometimes can't decide if content at the end of the
+ * stream is valid or not. For example, if "1" has been fed in,
+ * yajl can't know whether another digit is next or some character
+ * that would terminate the integer token.
+ *
+ * \param hand - a handle to the json parser allocated with yajl_alloc
+ */
+ yajl_status yajl_parse_complete(yajl_handle hand);
+
+ /** get an error string describing the state of the
+ * parse.
+ *
+ * If verbose is non-zero, the message will include the JSON
+ * text where the error occured, along with an arrow pointing to
+ * the specific char.
+ *
+ * A dynamically allocated string will be returned which should
+ * be freed with yajl_free_error
+ */
+ unsigned char * YAJL_API yajl_get_error(yajl_handle hand, int verbose,
+ const unsigned char * jsonText,
+ unsigned int jsonTextLength);
+
+ /** free an error returned from yajl_get_error */
+ void YAJL_API yajl_free_error(yajl_handle hand, unsigned char * str);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/jcnf/yajl/yajl_parser.c b/jcnf/yajl/yajl_parser.c
new file mode 100644
index 0000000..3d0f07f
--- /dev/null
+++ b/jcnf/yajl/yajl_parser.c
@@ -0,0 +1,505 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_lex.h"
+#include "yajl_parser.h"
+#include "yajl_encode.h"
+#include "yajl_bytestack.h"
+
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <math.h>
+
+unsigned char *
+yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
+ unsigned int jsonTextLen, int verbose)
+{
+ unsigned int offset = hand->errorOffset;
+ unsigned char * str;
+ const char * errorType = NULL;
+ const char * errorText = NULL;
+ char text[72];
+ const char * arrow = " (right here) ------^\n";
+
+ if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) {
+ errorType = "parse";
+ errorText = hand->parseError;
+ } else if (yajl_bs_current(hand->stateStack) == yajl_state_lexical_error) {
+ errorType = "lexical";
+ errorText = yajl_lex_error_to_string(yajl_lex_get_error(hand->lexer));
+ } else {
+ errorType = "unknown";
+ }
+
+ {
+ unsigned int memneeded = 0;
+ memneeded += strlen(errorType);
+ memneeded += strlen(" error");
+ if (errorText != NULL) {
+ memneeded += strlen(": ");
+ memneeded += strlen(errorText);
+ }
+ str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
+ str[0] = 0;
+ strcat((char *) str, errorType);
+ strcat((char *) str, " error");
+ if (errorText != NULL) {
+ strcat((char *) str, ": ");
+ strcat((char *) str, errorText);
+ }
+ strcat((char *) str, "\n");
+ }
+
+ /* now we append as many spaces as needed to make sure the error
+ * falls at char 41, if verbose was specified */
+ if (verbose) {
+ unsigned int start, end, i;
+ unsigned int spacesNeeded;
+
+ spacesNeeded = (offset < 30 ? 40 - offset : 10);
+ start = (offset >= 30 ? offset - 30 : 0);
+ end = (offset + 30 > jsonTextLen ? jsonTextLen : offset + 30);
+
+ for (i=0;i<spacesNeeded;i++) text[i] = ' ';
+
+ for (;start < end;start++, i++) {
+ if (jsonText[start] != '\n' && jsonText[start] != '\r')
+ {
+ text[i] = jsonText[start];
+ }
+ else
+ {
+ text[i] = ' ';
+ }
+ }
+ assert(i <= 71);
+ text[i++] = '\n';
+ text[i] = 0;
+ {
+ char * newStr = (char *)
+ YA_MALLOC(&(hand->alloc), (strlen((char *) str) +
+ strlen((char *) text) +
+ strlen(arrow) + 1));
+ newStr[0] = 0;
+ strcat((char *) newStr, (char *) str);
+ strcat((char *) newStr, text);
+ strcat((char *) newStr, arrow);
+ YA_FREE(&(hand->alloc), str);
+ str = (unsigned char *) newStr;
+ }
+ }
+ return str;
+}
+
+/* check for client cancelation */
+#define _CC_CHK(x) \
+ if (!(x)) { \
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error); \
+ hand->parseError = \
+ "client cancelled parse via callback return value"; \
+ return yajl_status_client_canceled; \
+ }
+
+
+yajl_status
+yajl_do_parse(yajl_handle hand, unsigned int * offset,
+ const unsigned char * jsonText, unsigned int jsonTextLen)
+{
+ yajl_tok tok;
+ const unsigned char * buf;
+ unsigned int bufLen;
+
+ around_again:
+ switch (yajl_bs_current(hand->stateStack)) {
+ case yajl_state_parse_complete:
+ return yajl_status_ok;
+ case yajl_state_lexical_error:
+ case yajl_state_parse_error:
+ hand->errorOffset = *offset;
+ return yajl_status_error;
+ case yajl_state_start:
+ case yajl_state_map_need_val:
+ case yajl_state_array_need_val:
+ case yajl_state_array_start: {
+ /* for arrays and maps, we advance the state for this
+ * depth, then push the state of the next depth.
+ * If an error occurs during the parsing of the nesting
+ * enitity, the state at this level will not matter.
+ * a state that needs pushing will be anything other
+ * than state_start */
+ yajl_state stateToPush = yajl_state_start;
+
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ offset, &buf, &bufLen);
+
+ switch (tok) {
+ case yajl_tok_eof:
+ return yajl_status_insufficient_data;
+ case yajl_tok_error:
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
+ goto around_again;
+ case yajl_tok_c_comment:
+ if (hand->callbacks && hand->callbacks->yajl_c_comment) {
+ _CC_CHK(hand->callbacks->yajl_c_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_cpp_comment:
+ if (hand->callbacks && hand->callbacks->yajl_cpp_comment) {
+ _CC_CHK(hand->callbacks->yajl_cpp_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_string:
+ if (hand->callbacks && hand->callbacks->yajl_string) {
+ _CC_CHK(hand->callbacks->yajl_string(hand->ctx,
+ buf, bufLen));
+ }
+ break;
+ case yajl_tok_string_with_escapes:
+ if (hand->callbacks && hand->callbacks->yajl_string) {
+ yajl_buf_clear(hand->decodeBuf);
+ yajl_string_decode(hand->decodeBuf, buf, bufLen);
+ _CC_CHK(hand->callbacks->yajl_string(
+ hand->ctx, yajl_buf_data(hand->decodeBuf),
+ yajl_buf_len(hand->decodeBuf)));
+ }
+ break;
+ case yajl_tok_bool:
+ if (hand->callbacks && hand->callbacks->yajl_boolean) {
+ _CC_CHK(hand->callbacks->yajl_boolean(hand->ctx,
+ *buf == 't'));
+ }
+ break;
+ case yajl_tok_null:
+ if (hand->callbacks && hand->callbacks->yajl_null) {
+ _CC_CHK(hand->callbacks->yajl_null(hand->ctx));
+ }
+ break;
+ case yajl_tok_left_bracket:
+ if (hand->callbacks && hand->callbacks->yajl_start_map) {
+ _CC_CHK(hand->callbacks->yajl_start_map(hand->ctx));
+ }
+ stateToPush = yajl_state_map_start;
+ break;
+ case yajl_tok_left_brace:
+ if (hand->callbacks && hand->callbacks->yajl_start_array) {
+ _CC_CHK(hand->callbacks->yajl_start_array(hand->ctx));
+ }
+ stateToPush = yajl_state_array_start;
+ break;
+ case yajl_tok_integer:
+ /*
+ * note. strtol does not respect the length of
+ * the lexical token. in a corner case where the
+ * lexed number is a integer with a trailing zero,
+ * immediately followed by the end of buffer,
+ * sscanf could run off into oblivion and cause a
+ * crash. for this reason we copy the integer
+ * (and doubles), into our parse buffer (the same
+ * one used for unescaping strings), before
+ * calling strtol. yajl_buf ensures null padding,
+ * so we're safe.
+ */
+ if (hand->callbacks) {
+ if (hand->callbacks->yajl_number) {
+ _CC_CHK(hand->callbacks->yajl_number(
+ hand->ctx,(const char *) buf, bufLen));
+ } else if (hand->callbacks->yajl_integer) {
+ long int i = 0;
+ yajl_buf_clear(hand->decodeBuf);
+ yajl_buf_append(hand->decodeBuf, buf, bufLen);
+ buf = yajl_buf_data(hand->decodeBuf);
+ i = strtol((const char *) buf, NULL, 10);
+ if ((i == LONG_MIN || i == LONG_MAX) &&
+ errno == ERANGE)
+ {
+ yajl_bs_set(hand->stateStack,
+ yajl_state_parse_error);
+ hand->parseError = "integer overflow" ;
+ /* try to restore error offset */
+ if (*offset >= bufLen) *offset -= bufLen;
+ else *offset = 0;
+ goto around_again;
+ }
+ _CC_CHK(hand->callbacks->yajl_integer(hand->ctx,
+ i));
+ }
+ }
+ break;
+ case yajl_tok_double:
+ if (hand->callbacks) {
+ if (hand->callbacks->yajl_number) {
+ _CC_CHK(hand->callbacks->yajl_number(
+ hand->ctx, (const char *) buf, bufLen));
+ } else if (hand->callbacks->yajl_double) {
+ double d = 0.0;
+ yajl_buf_clear(hand->decodeBuf);
+ yajl_buf_append(hand->decodeBuf, buf, bufLen);
+ buf = yajl_buf_data(hand->decodeBuf);
+ d = strtod((char *) buf, NULL);
+ if ((d == HUGE_VAL || d == -HUGE_VAL) &&
+ errno == ERANGE)
+ {
+ yajl_bs_set(hand->stateStack,
+ yajl_state_parse_error);
+ hand->parseError = "numeric (floating point) "
+ "overflow";
+ /* try to restore error offset */
+ if (*offset >= bufLen) *offset -= bufLen;
+ else *offset = 0;
+ goto around_again;
+ }
+ _CC_CHK(hand->callbacks->yajl_double(hand->ctx,
+ d));
+ }
+ }
+ break;
+ case yajl_tok_right_brace: {
+ if (yajl_bs_current(hand->stateStack) ==
+ yajl_state_array_start)
+ {
+ if (hand->callbacks &&
+ hand->callbacks->yajl_end_array)
+ {
+ _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
+ }
+ yajl_bs_pop(hand->stateStack);
+ goto around_again;
+ }
+ /* intentional fall-through */
+ }
+ case yajl_tok_colon:
+ case yajl_tok_comma:
+ case yajl_tok_right_bracket:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError =
+ "unallowed token at this point in JSON text";
+ goto around_again;
+ default:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError = "invalid token, internal error";
+ goto around_again;
+ }
+ /* got a value. transition depends on the state we're in. */
+ {
+ yajl_state s = yajl_bs_current(hand->stateStack);
+ if (s == yajl_state_start) {
+ yajl_bs_set(hand->stateStack, yajl_state_parse_complete);
+ } else if (s == yajl_state_map_need_val) {
+ yajl_bs_set(hand->stateStack, yajl_state_map_got_val);
+ } else {
+ yajl_bs_set(hand->stateStack, yajl_state_array_got_val);
+ }
+ }
+ if (stateToPush != yajl_state_start) {
+ yajl_bs_push(hand->stateStack, stateToPush);
+ }
+
+ goto around_again;
+ }
+ case yajl_state_map_start:
+ case yajl_state_map_need_key: {
+ /* only difference between these two states is that in
+ * start '}' is valid, whereas in need_key, we've parsed
+ * a comma, and a string key _must_ follow */
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ offset, &buf, &bufLen);
+ switch (tok) {
+ case yajl_tok_eof:
+ return yajl_status_insufficient_data;
+ case yajl_tok_error:
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
+ goto around_again;
+ case yajl_tok_string_with_escapes:
+ if (hand->callbacks && hand->callbacks->yajl_map_key) {
+ yajl_buf_clear(hand->decodeBuf);
+ yajl_string_decode(hand->decodeBuf, buf, bufLen);
+ buf = yajl_buf_data(hand->decodeBuf);
+ bufLen = yajl_buf_len(hand->decodeBuf);
+ }
+ /* intentional fall-through */
+ case yajl_tok_string:
+ if (hand->callbacks && hand->callbacks->yajl_map_key) {
+ _CC_CHK(hand->callbacks->yajl_map_key(hand->ctx, buf,
+ bufLen));
+ }
+ yajl_bs_set(hand->stateStack, yajl_state_map_sep);
+ goto around_again;
+ case yajl_tok_c_comment:
+ if (hand->callbacks && hand->callbacks->yajl_c_comment) {
+ _CC_CHK(hand->callbacks->yajl_c_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_cpp_comment:
+ if (hand->callbacks && hand->callbacks->yajl_cpp_comment) {
+ _CC_CHK(hand->callbacks->yajl_cpp_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_right_bracket:
+ if (yajl_bs_current(hand->stateStack) ==
+ yajl_state_map_start)
+ {
+ if (hand->callbacks && hand->callbacks->yajl_end_map) {
+ _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
+ }
+ yajl_bs_pop(hand->stateStack);
+ goto around_again;
+ }
+ default:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError =
+ "invalid object key (must be a string)";
+ goto around_again;
+ }
+ }
+ case yajl_state_map_sep: {
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ offset, &buf, &bufLen);
+ switch (tok) {
+ case yajl_tok_c_comment:
+ if (hand->callbacks && hand->callbacks->yajl_c_comment) {
+ _CC_CHK(hand->callbacks->yajl_c_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_cpp_comment:
+ if (hand->callbacks && hand->callbacks->yajl_cpp_comment) {
+ _CC_CHK(hand->callbacks->yajl_cpp_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_colon:
+ yajl_bs_set(hand->stateStack, yajl_state_map_need_val);
+ goto around_again;
+ case yajl_tok_eof:
+ return yajl_status_insufficient_data;
+ case yajl_tok_error:
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
+ goto around_again;
+ default:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError = "object key and value must "
+ "be separated by a colon (':')";
+ goto around_again;
+ }
+ }
+ case yajl_state_map_got_val: {
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ offset, &buf, &bufLen);
+ switch (tok) {
+ case yajl_tok_c_comment:
+ if (hand->callbacks && hand->callbacks->yajl_c_comment) {
+ _CC_CHK(hand->callbacks->yajl_c_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_cpp_comment:
+ if (hand->callbacks && hand->callbacks->yajl_cpp_comment) {
+ _CC_CHK(hand->callbacks->yajl_cpp_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_right_bracket:
+ if (hand->callbacks && hand->callbacks->yajl_end_map) {
+ _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx));
+ }
+ yajl_bs_pop(hand->stateStack);
+ goto around_again;
+ case yajl_tok_comma:
+ yajl_bs_set(hand->stateStack, yajl_state_map_need_key);
+ goto around_again;
+ case yajl_tok_eof:
+ return yajl_status_insufficient_data;
+ case yajl_tok_error:
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
+ goto around_again;
+ default:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError = "after key and value, inside map, "
+ "I expect ',' or '}'";
+ /* try to restore error offset */
+ if (*offset >= bufLen) *offset -= bufLen;
+ else *offset = 0;
+ goto around_again;
+ }
+ }
+ case yajl_state_array_got_val: {
+ tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen,
+ offset, &buf, &bufLen);
+ switch (tok) {
+ case yajl_tok_c_comment:
+ if (hand->callbacks && hand->callbacks->yajl_c_comment) {
+ _CC_CHK(hand->callbacks->yajl_c_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_cpp_comment:
+ if (hand->callbacks && hand->callbacks->yajl_cpp_comment) {
+ _CC_CHK(hand->callbacks->yajl_cpp_comment(hand->ctx,
+ buf, bufLen));
+ }
+ goto around_again;
+ case yajl_tok_right_brace:
+ if (hand->callbacks && hand->callbacks->yajl_end_array) {
+ _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx));
+ }
+ yajl_bs_pop(hand->stateStack);
+ goto around_again;
+ case yajl_tok_comma:
+ yajl_bs_set(hand->stateStack, yajl_state_array_need_val);
+ goto around_again;
+ case yajl_tok_eof:
+ return yajl_status_insufficient_data;
+ case yajl_tok_error:
+ yajl_bs_set(hand->stateStack, yajl_state_lexical_error);
+ goto around_again;
+ default:
+ yajl_bs_set(hand->stateStack, yajl_state_parse_error);
+ hand->parseError =
+ "after array element, I expect ',' or ']'";
+ goto around_again;
+ }
+ }
+ }
+
+ abort();
+ return yajl_status_error;
+}
+
diff --git a/jcnf/yajl/yajl_parser.h b/jcnf/yajl/yajl_parser.h
new file mode 100644
index 0000000..f8bc8ee
--- /dev/null
+++ b/jcnf/yajl/yajl_parser.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __YAJL_PARSER_H__
+#define __YAJL_PARSER_H__
+
+#include "yajl_parse.h"
+#include "yajl_bytestack.h"
+#include "yajl_buf.h"
+
+
+typedef enum {
+ yajl_state_start = 0,
+ yajl_state_parse_complete,
+ yajl_state_parse_error,
+ yajl_state_lexical_error,
+ yajl_state_map_start,
+ yajl_state_map_sep,
+ yajl_state_map_need_val,
+ yajl_state_map_got_val,
+ yajl_state_map_need_key,
+ yajl_state_array_start,
+ yajl_state_array_got_val,
+ yajl_state_array_need_val
+} yajl_state;
+
+struct yajl_handle_t {
+ const yajl_callbacks * callbacks;
+ void * ctx;
+ yajl_lexer lexer;
+ const char * parseError;
+ unsigned int errorOffset;
+ /* temporary storage for decoded strings */
+ yajl_buf decodeBuf;
+ /* a stack of states. access with yajl_state_XXX routines */
+ yajl_bytestack stateStack;
+ /* memory allocation routines */
+ yajl_alloc_funcs alloc;
+};
+
+yajl_status
+yajl_do_parse(yajl_handle handle, unsigned int * offset,
+ const unsigned char * jsonText, unsigned int jsonTextLen);
+
+unsigned char *
+yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
+ unsigned int jsonTextLen, int verbose);
+
+
+#endif
diff --git a/jcnf/yajl/yajl_test.c b/jcnf/yajl/yajl_test.c
new file mode 100644
index 0000000..de43570
--- /dev/null
+++ b/jcnf/yajl/yajl_test.c
@@ -0,0 +1,293 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "yajl_parse.h"
+#include "yajl_gen.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <assert.h>
+
+/* memory debugging routines */
+typedef struct
+{
+ unsigned int numFrees;
+ unsigned int numMallocs;
+ /* XXX: we really need a hash table here with per-allocation
+ * information */
+} yajlTestMemoryContext;
+
+/* cast void * into context */
+#define TEST_CTX(vptr) ((yajlTestMemoryContext *) (vptr))
+
+static void yajlTestFree(void * ctx, void * ptr)
+{
+ assert(ptr != NULL);
+ TEST_CTX(ctx)->numFrees++;
+ free(ptr);
+}
+
+static void * yajlTestMalloc(void * ctx, unsigned int sz)
+{
+ assert(sz != 0);
+ TEST_CTX(ctx)->numMallocs++;
+ return malloc(sz);
+}
+
+static void * yajlTestRealloc(void * ctx, void * ptr, unsigned int sz)
+{
+ if (ptr == NULL) {
+ assert(sz != 0);
+ TEST_CTX(ctx)->numMallocs++;
+ } else if (sz == 0) {
+ TEST_CTX(ctx)->numFrees++;
+ }
+
+ return realloc(ptr, sz);
+}
+
+
+/* begin parsing callback routines */
+#define BUF_SIZE 2048
+
+static int test_yajl_null(void *ctx)
+{
+ printf("null\n");
+ return 1;
+}
+
+static int test_yajl_boolean(void * ctx, int boolVal)
+{
+ printf("bool: %s\n", boolVal ? "true" : "false");
+ return 1;
+}
+
+static int test_yajl_integer(void *ctx, long integerVal)
+{
+ printf("integer: %ld\n", integerVal);
+ return 1;
+}
+
+static int test_yajl_double(void *ctx, double doubleVal)
+{
+ printf("double: %g\n", doubleVal);
+ return 1;
+}
+
+static int test_yajl_string(void *ctx, const unsigned char * stringVal,
+ unsigned int stringLen)
+{
+ printf("string: '");
+ fwrite(stringVal, 1, stringLen, stdout);
+ printf("'\n");
+ return 1;
+}
+
+static int test_yajl_map_key(void *ctx, const unsigned char * stringVal,
+ unsigned int stringLen)
+{
+ char * str = (char *) malloc(stringLen + 1);
+ str[stringLen] = 0;
+ memcpy(str, stringVal, stringLen);
+ printf("key: '%s'\n", str);
+ free(str);
+ return 1;
+}
+
+static int test_yajl_start_map(void *ctx)
+{
+ printf("map open '{'\n");
+ return 1;
+}
+
+
+static int test_yajl_end_map(void *ctx)
+{
+ printf("map close '}'\n");
+ return 1;
+}
+
+static int test_yajl_start_array(void *ctx)
+{
+ printf("array open '['\n");
+ return 1;
+}
+
+static int test_yajl_end_array(void *ctx)
+{
+ printf("array close ']'\n");
+ return 1;
+}
+
+static yajl_callbacks callbacks = {
+ test_yajl_null,
+ test_yajl_boolean,
+ test_yajl_integer,
+ test_yajl_double,
+ NULL,
+ test_yajl_string,
+ NULL,
+ NULL,
+ test_yajl_start_map,
+ test_yajl_map_key,
+ test_yajl_end_map,
+ test_yajl_start_array,
+ test_yajl_end_array
+};
+
+static void usage(const char * progname)
+{
+ fprintf(stderr,
+ "usage: %s [options] <filename>\n"
+ " -c allow comments\n"
+ " -b set the read buffer size\n",
+ progname);
+ exit(1);
+}
+
+int
+main(int argc, char ** argv)
+{
+ yajl_handle hand;
+ const char * fileName;
+ static unsigned char * fileData = NULL;
+ unsigned int bufSize = BUF_SIZE;
+ yajl_status stat;
+ size_t rd;
+ yajl_parser_config cfg = { 0, 1 };
+ int i, j, done;
+
+ /* memory allocation debugging: allocate a structure which collects
+ * statistics */
+ yajlTestMemoryContext memCtx = { 0,0 };
+
+ /* memory allocation debugging: allocate a structure which holds
+ * allocation routines */
+ yajl_alloc_funcs allocFuncs = {
+ yajlTestMalloc,
+ yajlTestRealloc,
+ yajlTestFree,
+ (void *) NULL
+ };
+
+ allocFuncs.ctx = (void *) &memCtx;
+
+ /* check arguments. We expect exactly one! */
+ for (i=1;i<argc;i++) {
+ if (!strcmp("-c", argv[i])) {
+ cfg.allowComments = 1;
+ } else if (!strcmp("-b", argv[i])) {
+ if (++i >= argc) usage(argv[0]);
+
+ /* validate integer */
+ for (j=0;j<(int)strlen(argv[i]);j++) {
+ if (argv[i][j] <= '9' && argv[i][j] >= '0') continue;
+ fprintf(stderr, "-b requires an integer argument. '%s' "
+ "is invalid\n", argv[i]);
+ usage(argv[0]);
+ }
+
+ bufSize = atoi(argv[i]);
+ if (!bufSize) {
+ fprintf(stderr, "%d is an invalid buffer size\n",
+ bufSize);
+ }
+ } else {
+ fprintf(stderr, "invalid command line option: '%s'\n",
+ argv[i]);
+ usage(argv[0]);
+ }
+ }
+
+ fileData = (unsigned char *) malloc(bufSize);
+
+ if (fileData == NULL) {
+ fprintf(stderr,
+ "failed to allocate read buffer of %u bytes, exiting.",
+ bufSize);
+ exit(2);
+ }
+
+ fileName = argv[argc-1];
+
+ /* ok. open file. let's read and parse */
+ hand = yajl_alloc(&callbacks, &cfg, &allocFuncs, NULL);
+
+ done = 0;
+ while (!done) {
+ rd = fread((void *) fileData, 1, bufSize, stdin);
+
+ if (rd == 0) {
+ if (!feof(stdin)) {
+ fprintf(stderr, "error reading from '%s'\n", fileName);
+ break;
+ }
+ done = 1;
+ }
+
+ if (done)
+ /* parse any remaining buffered data */
+ stat = yajl_parse_complete(hand);
+ else
+ /* read file data, pass to parser */
+ stat = yajl_parse(hand, fileData, rd);
+
+ if (stat != yajl_status_insufficient_data &&
+ stat != yajl_status_ok)
+ {
+ unsigned char * str = yajl_get_error(hand, 0, fileData, rd);
+ fflush(stdout);
+ fprintf(stderr, "%s", (char *) str);
+ yajl_free_error(hand, str);
+ break;
+ }
+ }
+
+ yajl_free(hand);
+ free(fileData);
+
+ /* finally, print out some memory statistics */
+
+/* (lth) only print leaks here, as allocations and frees may vary depending
+ * on read buffer size, causing false failures.
+ *
+ * printf("allocations:\t%u\n", memCtx.numMallocs);
+ * printf("frees:\t\t%u\n", memCtx.numFrees);
+*/
+ fflush(stderr);
+ fflush(stdout);
+ printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees);
+
+ return 0;
+}