diff options
73 files changed, 1132 insertions, 1214 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 727a488..d944472 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,40 +1,26 @@ -# Copyright 2010, 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. +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. CMAKE_MINIMUM_REQUIRED(VERSION 2.6) PROJECT(YetAnotherJSONParser C) +# XXX: attempt to clearly indicate that the 2.x branch is not yet stable, +# bump to 2.0.0 and remove this comment when baked. SET (YAJL_MAJOR 1) -SET (YAJL_MINOR 0) -SET (YAJL_MICRO 11) +SET (YAJL_MINOR 99) +SET (YAJL_MICRO 99) SET (YAJL_DIST_NAME "yajl-${YAJL_MAJOR}.${YAJL_MINOR}.${YAJL_MICRO}") @@ -1,29 +1,13 @@ -Copyright 2010, 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. +Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
\ No newline at end of file @@ -21,9 +21,10 @@ 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! +Permissive licensing means you can use it in open source and +commercial products alike without any fees. My request beyond the +licensing is that if you find bugs drop me a email, or better yet, +fork and fix. 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. @@ -1,33 +1,18 @@ #!/usr/bin/env ruby -# Copyright 2010, 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. +# +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. require 'fileutils' require 'optparse' diff --git a/reformatter/CMakeLists.txt b/reformatter/CMakeLists.txt index dc3bc3e..da4032b 100644 --- a/reformatter/CMakeLists.txt +++ b/reformatter/CMakeLists.txt @@ -1,32 +1,16 @@ -# Copyright 2010, 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. +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # set up a paths SET (binDir ${CMAKE_CURRENT_BINARY_DIR}/../${YAJL_DIST_NAME}/bin) diff --git a/reformatter/json_reformat.c b/reformatter/json_reformat.c index fbfc02c..ba55748 100644 --- a/reformatter/json_reformat.c +++ b/reformatter/json_reformat.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include <yajl/yajl_parse.h> #include <yajl/yajl_gen.h> @@ -40,67 +24,58 @@ static int reformat_null(void * ctx) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_null(g); - return 1; + return yajl_gen_status_ok == yajl_gen_null(g); } static int reformat_boolean(void * ctx, int boolean) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_bool(g, boolean); - return 1; + return yajl_gen_status_ok == yajl_gen_bool(g, boolean); } -static int reformat_number(void * ctx, const char * s, unsigned int l) +static int reformat_number(void * ctx, const char * s, size_t l) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_number(g, s, l); - return 1; + return yajl_gen_status_ok == yajl_gen_number(g, s, l); } static int reformat_string(void * ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_string(g, stringVal, stringLen); - return 1; + return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen); } static int reformat_map_key(void * ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_string(g, stringVal, stringLen); - return 1; + return yajl_gen_status_ok == yajl_gen_string(g, stringVal, stringLen); } static int reformat_start_map(void * ctx) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_map_open(g); - return 1; + return yajl_gen_status_ok == yajl_gen_map_open(g); } static int reformat_end_map(void * ctx) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_map_close(g); - return 1; + return yajl_gen_status_ok == yajl_gen_map_close(g); } static int reformat_start_array(void * ctx) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_array_open(g); - return 1; + return yajl_gen_status_ok == yajl_gen_array_open(g); } static int reformat_end_array(void * ctx) { yajl_gen g = (yajl_gen) ctx; - yajl_gen_array_close(g); - return 1; + return yajl_gen_status_ok == yajl_gen_array_close(g); } static yajl_callbacks callbacks = { @@ -135,13 +110,19 @@ main(int argc, char ** argv) yajl_handle hand; static unsigned char fileData[65536]; /* generator config */ - yajl_gen_config conf = { 1, " " }; - yajl_gen g; + yajl_gen g; yajl_status stat; size_t rd; - /* allow comments */ - yajl_parser_config cfg = { 1, 1 }; - int retval = 0, done = 0; + int retval = 0; + + g = yajl_gen_alloc(NULL); + yajl_gen_config(g, yajl_gen_beautify, 1); + yajl_gen_config(g, yajl_gen_validate_utf8, 1); + + /* ok. open file. let's read and parse */ + hand = yajl_alloc(&callbacks, NULL, (void *) g); + /* and let's allow comments by default */ + yajl_config(hand, yajl_allow_comments, 1); /* check arguments.*/ int a = 1; @@ -150,13 +131,14 @@ main(int argc, char ** argv) for ( i=1; i < strlen(argv[a]); i++) { switch (argv[a][i]) { case 'm': - conf.beautify = 0; + yajl_gen_config(g, yajl_gen_beautify, 0); break; case 'u': - cfg.checkUTF8 = 0; + yajl_config(hand, yajl_dont_validate_strings, 1); break; default: - fprintf(stderr, "unrecognized option: '%c'\n\n", argv[a][i]); + fprintf(stderr, "unrecognized option: '%c'\n\n", + argv[a][i]); usage(argv[0]); } } @@ -165,51 +147,44 @@ main(int argc, char ** argv) if (a < argc) { usage(argv[0]); } - - g = yajl_gen_alloc(&conf, NULL); - /* ok. open file. let's read and parse */ - hand = yajl_alloc(&callbacks, &cfg, NULL, (void *) g); - - while (!done) { + + for (;;) { rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin); - + if (rd == 0) { if (!feof(stdin)) { fprintf(stderr, "error on file read.\n"); retval = 1; - break; } - done = 1; + break; } 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) + + stat = yajl_parse(hand, fileData, rd); + + if (stat != yajl_status_ok) break; + { - unsigned char * str = yajl_get_error(hand, 1, fileData, rd); - fprintf(stderr, "%s", (const char *) str); - yajl_free_error(hand, str); - retval = 1; - break; - } else { const unsigned char * buf; - unsigned int len; + size_t len; yajl_gen_get_buf(g, &buf, &len); fwrite(buf, 1, len, stdout); yajl_gen_clear(g); } } + stat = yajl_complete_parse(hand); + + if (stat != yajl_status_ok) { + unsigned char * str = yajl_get_error(hand, 1, fileData, rd); + fprintf(stderr, "%s", (const char *) str); + yajl_free_error(hand, str); + retval = 1; + } + yajl_gen_free(g); yajl_free(hand); - + return retval; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3ca0dc5..479b405 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,32 +1,16 @@ -# Copyright 2010, 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. +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. SET (SRCS yajl.c yajl_lex.c yajl_parser.c yajl_buf.c yajl_encode.c yajl_gen.c yajl_alloc.c diff --git a/src/api/yajl_common.h b/src/api/yajl_common.h index 0e75db1..49ca3a5 100644 --- a/src/api/yajl_common.h +++ b/src/api/yajl_common.h @@ -1,38 +1,24 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifndef __YAJL_COMMON_H__ #define __YAJL_COMMON_H__ +#include <stddef.h> + #ifdef __cplusplus extern "C" { #endif @@ -58,14 +44,14 @@ extern "C" { /** pointer to a malloc function, supporting client overriding memory * allocation routines */ -typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz); +typedef void * (*yajl_malloc_func)(void *ctx, size_t 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); +typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, size_t sz); /** A structure which can be passed to yajl_*_alloc routines to allow the * client to specify memory allocation functions to be used. */ @@ -84,6 +70,6 @@ typedef struct #ifdef __cplusplus } -#endif +#endif #endif diff --git a/src/api/yajl_gen.h b/src/api/yajl_gen.h index a3fbd4c..61c0bd1 100644 --- a/src/api/yajl_gen.h +++ b/src/api/yajl_gen.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /** * \file yajl_gen.h @@ -40,6 +24,8 @@ #ifndef __YAJL_GEN_H__ #define __YAJL_GEN_H__ +#include <stddef.h> + #ifdef __cplusplus extern "C" { #endif @@ -63,7 +49,11 @@ extern "C" { yajl_gen_invalid_number, /** A print callback was passed in, so there is no internal * buffer to get from */ - yajl_gen_no_buf + yajl_gen_no_buf, + /** returned from yajl_gen_string() when the yajl_gen_validate_utf8 + * option is enabled and an invalid was passed by client code. + */ + yajl_gen_invalid_string } yajl_gen_status; /** an opaque handle to a generator */ @@ -72,17 +62,43 @@ extern "C" { /** a callback used for "printing" the results. */ typedef void (*yajl_print_t)(void * ctx, const char * str, - unsigned int len); + size_t len); - /** configuration structure for the generator */ - typedef struct { + /** configuration parameters for the parser, these may be passed to + * yajl_gen_config() along with option specific argument(s). In general, + * all configuration parameters default to *off*. */ + typedef enum { /** 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; + yajl_gen_beautify = 0x01, + /** + * Set an indent string which is used when yajl_gen_beautify + * is enabled. Maybe something like \\t or some number of + * spaces. The default is four spaces ' '. + */ + yajl_gen_indent_string = 0x02, + /** + * Set a function and context argument that should be used to + * output generated json. the function should conform to the + * yajl_print_t prototype while the context argument is a + * void * of your choosing. + * + * example: + * yajl_gen_config(g, yajl_gen_print_callback, myFunc, myVoidPtr); + */ + yajl_gen_print_callback = 0x04, + /** + * Normally the generator does not validate that strings you + * pass to it via yajl_gen_string() are valid UTF8. Enabling + * this option will cause it to do so. + */ + yajl_gen_validate_utf8 = 0x08 + } yajl_gen_option; + + /** allow the modification of generator options subsequent to handle + * allocation (via yajl_alloc) + * \returns zero in case of errors, non-zero otherwise + */ + YAJL_API int yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...); /** allocate a generator handle * \param config a pointer to a structure containing parameters which @@ -94,45 +110,22 @@ extern "C" { * * \returns an allocated handle on success, NULL on failure (bad params) */ - YAJL_API yajl_gen yajl_gen_alloc(const yajl_gen_config * config, - const yajl_alloc_funcs * allocFuncs); - - /** allocate a generator handle that will print to the specified - * callback rather than storing the results in an internal buffer. - * \param callback a pointer to a printer function. May be NULL - * in which case, the results will be store in an - * internal buffer. - * \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. - * \param ctx a context pointer that will be passed to the - * printer callback. - * - * \returns an allocated handle on success, NULL on failure (bad params) - */ - YAJL_API yajl_gen yajl_gen_alloc2(const yajl_print_t callback, - const yajl_gen_config * config, - const yajl_alloc_funcs * allocFuncs, - void * ctx); + YAJL_API yajl_gen yajl_gen_alloc(const yajl_alloc_funcs * allocFuncs); /** free a generator handle */ YAJL_API void yajl_gen_free(yajl_gen handle); - YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long int number); + YAJL_API yajl_gen_status yajl_gen_integer(yajl_gen hand, long long int number); /** generate a floating point number. number may not be infinity or * NaN, as these have no representation in JSON. In these cases the * generator will return 'yajl_gen_invalid_number' */ YAJL_API yajl_gen_status yajl_gen_double(yajl_gen hand, double number); YAJL_API yajl_gen_status yajl_gen_number(yajl_gen hand, const char * num, - unsigned int len); + size_t len); YAJL_API yajl_gen_status yajl_gen_string(yajl_gen hand, const unsigned char * str, - unsigned int len); + size_t len); YAJL_API yajl_gen_status yajl_gen_null(yajl_gen hand); YAJL_API yajl_gen_status yajl_gen_bool(yajl_gen hand, int boolean); YAJL_API yajl_gen_status yajl_gen_map_open(yajl_gen hand); @@ -145,7 +138,7 @@ extern "C" { * buffer. This allows stream generation. */ YAJL_API yajl_gen_status yajl_gen_get_buf(yajl_gen hand, const unsigned char ** buf, - unsigned int * len); + size_t * len); /** clear yajl's output buffer, but maintain all internal generation * state. This function will not "reset" the generator state, and is diff --git a/src/api/yajl_parse.h b/src/api/yajl_parse.h index 1cbd930..0a241d3 100644 --- a/src/api/yajl_parse.h +++ b/src/api/yajl_parse.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /** * \file yajl_parse.h @@ -40,19 +24,17 @@ #ifndef __YAJL_PARSE_H__ #define __YAJL_PARSE_H__ +#include <stddef.h> + #ifdef __cplusplus extern "C" { -#endif +#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 @@ -77,62 +59,108 @@ extern "C" { * * 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 + * or a 64 bit (long long) int. All other numbers will be passed to the client * in string form using the yajl_number callback. Furthermore, if * yajl_number is not NULL, it will always be used to return numbers, * that is yajl_integer and yajl_double will be ignored. If * yajl_number is NULL but one of yajl_integer or yajl_double are * defined, parsing of a number larger than is representable - * in a double or long int will result in a parse error. + * in a double or 64 bit integer 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_integer)(void * ctx, long 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); + size_t 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); + size_t 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); + size_t stringLen); + int (* yajl_end_map)(void * ctx); int (* yajl_start_array)(void * ctx); - int (* yajl_end_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 afs memory allocation functions, may be NULL for to use + * C runtime library routines (malloc and friends) * \param ctx a context pointer that will be passed to callbacks. */ YAJL_API yajl_handle yajl_alloc(const yajl_callbacks * callbacks, - const yajl_parser_config * config, - const yajl_alloc_funcs * allocFuncs, + yajl_alloc_funcs * afs, void * ctx); - /** free a parser handle */ + + /** configuration parameters for the parser, these may be passed to + * yajl_config() along with option specific argument(s). In general, + * all configuration parameters default to *off*. */ + typedef enum { + /** Ignore javascript style comments present in + * JSON input. Non-standard, but rather fun + * arguments: toggled off with integer zero, on otherwise. + * + * example: + * yajl_config(h, yajl_allow_comments, 1); // turn comment support on + */ + yajl_allow_comments = 0x01, + /** + * When set the parser will verify that all strings in JSON input are + * valid UTF8 and will emit a parse error if this is not so. When set, + * this option makes parsing slightly more expensive (~10%) (XXX: get real numbers) + * + * example: + * yajl_config(h, yajl_dont_validate_strings, 1); // disable utf8 checking + */ + yajl_dont_validate_strings = 0x02, + /** + * By default, upon calls to yajl_complete_parse(), yajl will + * ensure the entire input text was consumed and will raise an error + * otherwise. Enabling this flag will cause yajl to disable this + * check. This can be useful when parsing json out of a that contains more + * than a single JSON document. + */ + yajl_allow_trailing_garbage = 0x04, + /** + * Allow multiple values to be parsed by a single handle. The + * entire text must be valid JSON, and values can be seperated + * by any kind of whitespace. This flag will change the + * behavior of the parser, and cause it continue parsing after + * a value is parsed, rather than transitioning into a + * complete state. This option can be useful when parsing multiple + * values from an input stream. + */ + yajl_allow_multiple_values = 0x08, + /** + * When yajl_complete_parse() is called the parser will + * check that the top level value was completely consumed. I.E., + * if called whilst in the middle of parsing a value + * yajl will enter an error state (premature EOF). Setting this + * flag suppresses that check and the corresponding error. + */ + yajl_allow_partial_values = 0x10 + } yajl_option; + + /** allow the modification of parser options subsequent to handle + * allocation (via yajl_alloc) + * \returns zero in case of errors, non-zero otherwise + */ + YAJL_API int yajl_config(yajl_handle h, yajl_option opt, ...); + + /** free a parser handle */ YAJL_API void yajl_free(yajl_handle handle); /** Parse some json! @@ -142,7 +170,7 @@ extern "C" { */ YAJL_API yajl_status yajl_parse(yajl_handle hand, const unsigned char * jsonText, - unsigned int jsonTextLength); + size_t jsonTextLength); /** Parse any remaining buffered json. * Since yajl is a stream-based parser, without an explicit end of @@ -153,8 +181,8 @@ extern "C" { * * \param hand - a handle to the json parser allocated with yajl_alloc */ - YAJL_API yajl_status yajl_parse_complete(yajl_handle hand); - + YAJL_API yajl_status yajl_complete_parse(yajl_handle hand); + /** get an error string describing the state of the * parse. * @@ -163,31 +191,31 @@ extern "C" { * the specific char. * * \returns A dynamically allocated string will be returned which should - * be freed with yajl_free_error + * be freed with yajl_free_error */ YAJL_API unsigned char * yajl_get_error(yajl_handle hand, int verbose, const unsigned char * jsonText, - unsigned int jsonTextLength); + size_t jsonTextLength); /** * get the amount of data consumed from the last chunk passed to YAJL. * * In the case of a successful parse this can help you understand if * the entire buffer was consumed (which will allow you to handle - * "junk at end of input". - * + * "junk at end of input"). + * * In the event an error is encountered during parsing, this function * affords the client a way to get the offset into the most recent * chunk where the error occured. 0 will be returned if no error * was encountered. */ - YAJL_API unsigned int yajl_get_bytes_consumed(yajl_handle hand); + YAJL_API size_t yajl_get_bytes_consumed(yajl_handle hand); /** free an error returned from yajl_get_error */ YAJL_API void yajl_free_error(yajl_handle hand, unsigned char * str); #ifdef __cplusplus } -#endif +#endif #endif @@ -1,11 +1,11 @@ /*! - \mainpage Yet Another JSON Library (YAJL) + \mainpage Yet Another JSON Library (YAJL) \author Lloyd Hilaiel \date 2010 Yet Another JSON Library (YAJL) is a small event-driven (SAX-style) JSON parser written in ANSI C, and a small validating JSON -generator. YAJL is released under the BSD license. +generator. YAJL is released under the ISC license. \section features Features @@ -19,7 +19,7 @@ generator. YAJL is released under the BSD license. \section usage Usage The following code sample is a complete JSON "reformating" program. It -demonstrates how to perform stream parsing and generation. +demonstrates how to perform stream parsing and generation. \code #include <yajl/yajl_parse.h> @@ -43,7 +43,7 @@ static int reformat_boolean(void * ctx, int boolean) return 1; } -static int reformat_number(void * ctx, const char * s, unsigned int l) +static int reformat_number(void * ctx, const char * s, size_t l) { yajl_gen g = (yajl_gen) ctx; yajl_gen_number(g, s, l); @@ -51,7 +51,7 @@ static int reformat_number(void * ctx, const char * s, unsigned int l) } static int reformat_string(void * ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { yajl_gen g = (yajl_gen) ctx; yajl_gen_string(g, stringVal, stringLen); @@ -59,7 +59,7 @@ static int reformat_string(void * ctx, const unsigned char * stringVal, } static int reformat_map_key(void * ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { yajl_gen g = (yajl_gen) ctx; yajl_gen_string(g, stringVal, stringLen); @@ -167,7 +167,7 @@ main(int argc, char ** argv) if (done) /* parse any remaining buffered data */ - stat = yajl_parse_complete(hand); + stat = yajl_complete_parse(hand); else /* read file data, pass to parser */ stat = yajl_parse(hand, fileData, rd); @@ -180,7 +180,7 @@ main(int argc, char ** argv) yajl_free_error(hand, str); } else { const unsigned char * buf; - unsigned int len; + size_tnq len; yajl_gen_get_buf(g, &buf, &len); fwrite(buf, 1, len, stdout); yajl_gen_clear(g); @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include "api/yajl_parse.h" #include "yajl_lex.h" @@ -37,6 +21,7 @@ #include <stdlib.h> #include <string.h> +#include <stdarg.h> #include <assert.h> const char * @@ -50,9 +35,6 @@ yajl_status_to_string(yajl_status stat) 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; @@ -62,12 +44,9 @@ yajl_status_to_string(yajl_status stat) yajl_handle yajl_alloc(const yajl_callbacks * callbacks, - const yajl_parser_config * config, - const yajl_alloc_funcs * afs, + yajl_alloc_funcs * afs, void * ctx) { - unsigned int allowComments = 0; - unsigned int validateUTF8 = 0; yajl_handle hand = NULL; yajl_alloc_funcs afsBuffer; @@ -87,61 +66,86 @@ yajl_alloc(const yajl_callbacks * callbacks, /* 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->lexer = NULL; hand->bytesConsumed = 0; hand->decodeBuf = yajl_buf_alloc(&(hand->alloc)); + hand->flags = 0; yajl_bs_init(hand->stateStack, &(hand->alloc)); - yajl_bs_push(hand->stateStack, yajl_state_start); return hand; } +int +yajl_config(yajl_handle h, yajl_option opt, ...) +{ + int rv = 1; + va_list ap; + va_start(ap, opt); + + switch(opt) { + case yajl_allow_comments: + case yajl_dont_validate_strings: + case yajl_allow_trailing_garbage: + case yajl_allow_multiple_values: + case yajl_allow_partial_values: + if (va_arg(ap, int)) h->flags |= opt; + else h->flags &= ~opt; + break; + default: + rv = 0; + } + va_end(ap); + + return rv; +} + void yajl_free(yajl_handle handle) { yajl_bs_free(handle->stateStack); yajl_buf_free(handle->decodeBuf); - yajl_lex_free(handle->lexer); + if (handle->lexer) { + yajl_lex_free(handle->lexer); + handle->lexer = NULL; + } YA_FREE(&(handle->alloc), handle); } yajl_status yajl_parse(yajl_handle hand, const unsigned char * jsonText, - unsigned int jsonTextLen) + size_t jsonTextLen) { yajl_status status; + + // lazy allocate the lexer + if (hand->lexer == NULL) { + hand->lexer = yajl_lex_alloc(&(hand->alloc), + hand->flags & yajl_allow_comments, + !(hand->flags & yajl_dont_validate_strings)); + } + status = yajl_do_parse(hand, jsonText, jsonTextLen); return status; } + yajl_status -yajl_parse_complete(yajl_handle hand) +yajl_complete_parse(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); + return yajl_do_finish(hand); } unsigned char * yajl_get_error(yajl_handle hand, int verbose, - const unsigned char * jsonText, unsigned int jsonTextLen) + const unsigned char * jsonText, size_t jsonTextLen) { return yajl_render_error_string(hand, jsonText, jsonTextLen, verbose); } -unsigned int +size_t yajl_get_bytes_consumed(yajl_handle hand) { if (!hand) return 0; diff --git a/src/yajl_alloc.c b/src/yajl_alloc.c index ccfb7c3..276315a 100644 --- a/src/yajl_alloc.c +++ b/src/yajl_alloc.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /** * \file yajl_alloc.h @@ -39,13 +23,13 @@ #include "yajl_alloc.h" #include <stdlib.h> -static void * yajl_internal_malloc(void *ctx, unsigned int sz) +static void * yajl_internal_malloc(void *ctx, size_t sz) { return malloc(sz); } static void * yajl_internal_realloc(void *ctx, void * previous, - unsigned int sz) + size_t sz) { return realloc(previous, sz); } diff --git a/src/yajl_alloc.h b/src/yajl_alloc.h index 94e7de5..85dbad0 100644 --- a/src/yajl_alloc.h +++ b/src/yajl_alloc.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /** * \file yajl_alloc.h diff --git a/src/yajl_buf.c b/src/yajl_buf.c index 04e608a..0d249d3 100644 --- a/src/yajl_buf.c +++ b/src/yajl_buf.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include "yajl_buf.h" @@ -39,16 +23,16 @@ #define YAJL_BUF_INIT_SIZE 2048 struct yajl_buf_t { - unsigned int len; - unsigned int used; + size_t len; + size_t used; unsigned char * data; yajl_alloc_funcs * alloc; }; static -void yajl_buf_ensure_available(yajl_buf buf, unsigned int want) +void yajl_buf_ensure_available(yajl_buf buf, size_t want) { - unsigned int need; + size_t need; assert(buf != NULL); @@ -84,7 +68,7 @@ void yajl_buf_free(yajl_buf buf) YA_FREE(buf->alloc, buf); } -void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len) +void yajl_buf_append(yajl_buf buf, const void * data, size_t len) { yajl_buf_ensure_available(buf, len); if (len > 0) { @@ -106,13 +90,13 @@ const unsigned char * yajl_buf_data(yajl_buf buf) return buf->data; } -unsigned int yajl_buf_len(yajl_buf buf) +size_t yajl_buf_len(yajl_buf buf) { return buf->used; } void -yajl_buf_truncate(yajl_buf buf, unsigned int len) +yajl_buf_truncate(yajl_buf buf, size_t len) { assert(len <= buf->used); buf->used = len; diff --git a/src/yajl_buf.h b/src/yajl_buf.h index e330f33..682457f 100644 --- a/src/yajl_buf.h +++ b/src/yajl_buf.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifndef __YAJL_BUF_H__ #define __YAJL_BUF_H__ @@ -56,7 +40,7 @@ yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc); 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); +void yajl_buf_append(yajl_buf buf, const void * data, size_t len); /* empty the buffer */ void yajl_buf_clear(yajl_buf buf); @@ -65,9 +49,9 @@ void yajl_buf_clear(yajl_buf buf); const unsigned char * yajl_buf_data(yajl_buf buf); /* get the length of the buffer */ -unsigned int yajl_buf_len(yajl_buf buf); +size_t yajl_buf_len(yajl_buf buf); /* truncate the buffer */ -void yajl_buf_truncate(yajl_buf buf, unsigned int len); +void yajl_buf_truncate(yajl_buf buf, size_t len); #endif diff --git a/src/yajl_bytestack.h b/src/yajl_bytestack.h index 872ede1..50b0557 100644 --- a/src/yajl_bytestack.h +++ b/src/yajl_bytestack.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ /* * A header only implementation of a simple stack of bytes, used in YAJL @@ -45,8 +29,8 @@ typedef struct yajl_bytestack_t { unsigned char * stack; - unsigned int size; - unsigned int used; + size_t size; + size_t used; yajl_alloc_funcs * yaf; } yajl_bytestack; diff --git a/src/yajl_encode.c b/src/yajl_encode.c index ad5b1c5..a0ab8d1 100644 --- a/src/yajl_encode.c +++ b/src/yajl_encode.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include "yajl_encode.h" @@ -46,7 +30,7 @@ static void CharToHex(unsigned char c, char * hexBuf) void yajl_string_encode(yajl_buf buf, const unsigned char * str, - unsigned int len) + size_t len) { yajl_string_encode2((const yajl_print_t) &yajl_buf_append, buf, str, len); } @@ -55,10 +39,10 @@ void yajl_string_encode2(const yajl_print_t print, void * ctx, const unsigned char * str, - unsigned int len) + size_t len) { - unsigned int beg = 0; - unsigned int end = 0; + size_t beg = 0; + size_t end = 0; char hexBuf[7]; hexBuf[0] = '\\'; hexBuf[1] = 'u'; hexBuf[2] = '0'; hexBuf[3] = '0'; hexBuf[6] = 0; @@ -83,7 +67,7 @@ yajl_string_encode2(const yajl_print_t print, } if (escaped != NULL) { print(ctx, (const char *) (str + beg), end - beg); - print(ctx, escaped, strlen(escaped)); + print(ctx, escaped, (unsigned int)strlen(escaped)); beg = ++end; } else { ++end; @@ -131,10 +115,10 @@ static void Utf32toUtf8(unsigned int codepoint, char * utf8Buf) } void yajl_string_decode(yajl_buf buf, const unsigned char * str, - unsigned int len) + size_t len) { - unsigned int beg = 0; - unsigned int end = 0; + size_t beg = 0; + size_t end = 0; while (end < len) { if (str[end] == '\\') { @@ -173,12 +157,19 @@ void yajl_string_decode(yajl_buf buf, const unsigned char * str, Utf32toUtf8(codepoint, utf8Buf); unescaped = utf8Buf; + + if (codepoint == 0) { + yajl_buf_append(buf, unescaped, 1); + beg = ++end; + continue; + } + break; } default: assert("this should never happen" == NULL); } - yajl_buf_append(buf, unescaped, strlen(unescaped)); + yajl_buf_append(buf, unescaped, (unsigned int)strlen(unescaped)); beg = ++end; } else { end++; @@ -186,3 +177,45 @@ void yajl_string_decode(yajl_buf buf, const unsigned char * str, } yajl_buf_append(buf, str + beg, end - beg); } + +#define ADV_PTR s++; if (!(len--)) return 0; + +int yajl_string_validate_utf8(const unsigned char * s, size_t len) +{ + if (!len) return 1; + if (!s) return 0; + + while (len--) { + /* single byte */ + if (*s <= 0x7f) { + /* noop */ + } + /* two byte */ + else if ((*s >> 5) == 0x6) { + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + } + /* three byte */ + else if ((*s >> 4) == 0x0e) { + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + } + /* four byte */ + else if ((*s >> 3) == 0x1e) { + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + ADV_PTR; + if (!((*s >> 6) == 0x2)) return 0; + } else { + return 0; + } + + s++; + } + + return 1; +} diff --git a/src/yajl_encode.h b/src/yajl_encode.h index f242779..25fbd70 100644 --- a/src/yajl_encode.h +++ b/src/yajl_encode.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifndef __YAJL_ENCODE_H__ #define __YAJL_ENCODE_H__ @@ -39,12 +23,14 @@ void yajl_string_encode2(const yajl_print_t printer, void * ctx, const unsigned char * str, - unsigned int length); + size_t length); void yajl_string_encode(yajl_buf buf, const unsigned char * str, - unsigned int length); + size_t length); void yajl_string_decode(yajl_buf buf, const unsigned char * str, - unsigned int length); + size_t length); + +int yajl_string_validate_utf8(const unsigned char * s, size_t len); #endif diff --git a/src/yajl_gen.c b/src/yajl_gen.c index 548d948..dd693e6 100644 --- a/src/yajl_gen.c +++ b/src/yajl_gen.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include "api/yajl_gen.h" #include "yajl_buf.h" @@ -38,6 +22,7 @@ #include <string.h> #include <stdio.h> #include <math.h> +#include <stdarg.h> typedef enum { yajl_gen_start, @@ -52,8 +37,8 @@ typedef enum { struct yajl_gen_t { + unsigned int flags; unsigned int depth; - unsigned int pretty; const char * indentString; yajl_gen_state state[YAJL_MAX_DEPTH]; yajl_print_t print; @@ -62,18 +47,54 @@ struct yajl_gen_t yajl_alloc_funcs alloc; }; -yajl_gen -yajl_gen_alloc(const yajl_gen_config * config, - const yajl_alloc_funcs * afs) +int +yajl_gen_config(yajl_gen g, yajl_gen_option opt, ...) { - return yajl_gen_alloc2(NULL, config, afs, NULL); + int rv = 1; + va_list ap; + va_start(ap, opt); + + switch(opt) { + case yajl_gen_beautify: + case yajl_gen_validate_utf8: + if (va_arg(ap, int)) g->flags |= opt; + else g->flags &= ~opt; + break; + case yajl_gen_indent_string: { + const char *indent = va_arg(ap, const char *); + g->indentString = indent; + for (; *indent; indent++) { + if (*indent != '\n' + && *indent != '\v' + && *indent != '\f' + && *indent != '\t' + && *indent != '\r' + && *indent != ' ') + { + g->indentString = NULL; + rv = 0; + } + } + break; + } + case yajl_gen_print_callback: + yajl_buf_free(g->ctx); + g->print = va_arg(ap, const yajl_print_t); + g->ctx = va_arg(ap, void *); + break; + default: + rv = 0; + } + + va_end(ap); + + return rv; } + + yajl_gen -yajl_gen_alloc2(const yajl_print_t callback, - const yajl_gen_config * config, - const yajl_alloc_funcs * afs, - void * ctx) +yajl_gen_alloc(const yajl_alloc_funcs * afs) { yajl_gen g = NULL; yajl_alloc_funcs afsBuffer; @@ -90,22 +111,15 @@ yajl_gen_alloc2(const yajl_print_t callback, } g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t)); + if (!g) return NULL; + 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 : " "; - } - - if (callback) { - g->print = callback; - g->ctx = ctx; - } else { - g->print = (yajl_print_t)&yajl_buf_append; - g->ctx = yajl_buf_alloc(&(g->alloc)); - } + g->print = (yajl_print_t)&yajl_buf_append; + g->ctx = yajl_buf_alloc(&(g->alloc)); + g->indentString = " "; return g; } @@ -121,26 +135,28 @@ yajl_gen_free(yajl_gen g) if (g->state[g->depth] == yajl_gen_map_key || \ g->state[g->depth] == yajl_gen_in_array) { \ g->print(g->ctx, ",", 1); \ - if (g->pretty) g->print(g->ctx, "\n", 1); \ + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); \ } else if (g->state[g->depth] == yajl_gen_map_val) { \ g->print(g->ctx, ":", 1); \ - if (g->pretty) g->print(g->ctx, " ", 1); \ + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, " ", 1); \ } #define INSERT_WHITESPACE \ - if (g->pretty) { \ + if ((g->flags & yajl_gen_beautify)) { \ if (g->state[g->depth] != yajl_gen_map_val) { \ unsigned int _i; \ for (_i=0;_i<g->depth;_i++) \ - g->print(g->ctx, g->indentString, \ - strlen(g->indentString)); \ + g->print(g->ctx, \ + g->indentString, \ + (unsigned int)strlen(g->indentString)); \ } \ } #define ENSURE_NOT_KEY \ - if (g->state[g->depth] == yajl_gen_map_key) { \ - return yajl_gen_keys_must_be_strings; \ - } \ + if (g->state[g->depth] == yajl_gen_map_key || \ + g->state[g->depth] == yajl_gen_map_start) { \ + return yajl_gen_keys_must_be_strings; \ + } \ /* check that we're not complete, or in error state. in a valid state * to be generating */ @@ -154,6 +170,9 @@ yajl_gen_free(yajl_gen g) #define INCREMENT_DEPTH \ if (++(g->depth) >= YAJL_MAX_DEPTH) return yajl_max_depth_exceeded; +#define DECREMENT_DEPTH \ + if (--(g->depth) >= YAJL_MAX_DEPTH) return yajl_gen_error; + #define APPENDED_ATOM \ switch (g->state[g->depth]) { \ case yajl_gen_start: \ @@ -174,16 +193,16 @@ yajl_gen_free(yajl_gen g) } \ #define FINAL_NEWLINE \ - if (g->pretty && g->state[g->depth] == yajl_gen_complete) \ - g->print(g->ctx, "\n", 1); - + if ((g->flags & yajl_gen_beautify) && g->state[g->depth] == yajl_gen_complete) \ + g->print(g->ctx, "\n", 1); + yajl_gen_status -yajl_gen_integer(yajl_gen g, long int number) +yajl_gen_integer(yajl_gen g, long long int number) { char i[32]; ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; - sprintf(i, "%ld", number); - g->print(g->ctx, i, strlen(i)); + sprintf(i, "%lld", number); + g->print(g->ctx, i, (unsigned int)strlen(i)); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; @@ -203,14 +222,14 @@ yajl_gen_double(yajl_gen g, double number) if (isnan(number) || isinf(number)) return yajl_gen_invalid_number; INSERT_SEP; INSERT_WHITESPACE; sprintf(i, "%.20g", number); - g->print(g->ctx, i, strlen(i)); + g->print(g->ctx, i, (unsigned int)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) +yajl_gen_number(yajl_gen g, const char * s, size_t l) { ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, s, l); @@ -221,8 +240,16 @@ yajl_gen_number(yajl_gen g, const char * s, unsigned int l) yajl_gen_status yajl_gen_string(yajl_gen g, const unsigned char * str, - unsigned int len) + size_t len) { + // if validation is enabled, check that the string is valid utf8 + // XXX: This checking could be done a little faster, in the same pass as + // the string encoding + if (g->flags & yajl_gen_validate_utf8) { + if (!yajl_string_validate_utf8(str, len)) { + return yajl_gen_invalid_string; + } + } ENSURE_VALID_STATE; INSERT_SEP; INSERT_WHITESPACE; g->print(g->ctx, "\"", 1); yajl_string_encode2(g->print, g->ctx, str, len); @@ -248,7 +275,7 @@ yajl_gen_bool(yajl_gen g, int boolean) const char * val = boolean ? "true" : "false"; ENSURE_VALID_STATE; ENSURE_NOT_KEY; INSERT_SEP; INSERT_WHITESPACE; - g->print(g->ctx, val, strlen(val)); + g->print(g->ctx, val, (unsigned int)strlen(val)); APPENDED_ATOM; FINAL_NEWLINE; return yajl_gen_status_ok; @@ -262,7 +289,7 @@ yajl_gen_map_open(yajl_gen g) g->state[g->depth] = yajl_gen_map_start; g->print(g->ctx, "{", 1); - if (g->pretty) g->print(g->ctx, "\n", 1); + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } @@ -271,8 +298,9 @@ yajl_gen_status yajl_gen_map_close(yajl_gen g) { ENSURE_VALID_STATE; - (g->depth)--; - if (g->pretty) g->print(g->ctx, "\n", 1); + DECREMENT_DEPTH; + + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); APPENDED_ATOM; INSERT_WHITESPACE; g->print(g->ctx, "}", 1); @@ -287,7 +315,7 @@ yajl_gen_array_open(yajl_gen g) INCREMENT_DEPTH; g->state[g->depth] = yajl_gen_array_start; g->print(g->ctx, "[", 1); - if (g->pretty) g->print(g->ctx, "\n", 1); + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); FINAL_NEWLINE; return yajl_gen_status_ok; } @@ -296,8 +324,8 @@ yajl_gen_status yajl_gen_array_close(yajl_gen g) { ENSURE_VALID_STATE; - if (g->pretty) g->print(g->ctx, "\n", 1); - (g->depth)--; + DECREMENT_DEPTH; + if ((g->flags & yajl_gen_beautify)) g->print(g->ctx, "\n", 1); APPENDED_ATOM; INSERT_WHITESPACE; g->print(g->ctx, "]", 1); @@ -307,7 +335,7 @@ yajl_gen_array_close(yajl_gen g) yajl_gen_status yajl_gen_get_buf(yajl_gen g, const unsigned char ** buf, - unsigned int * len) + size_t * len) { if (g->print != (yajl_print_t)&yajl_buf_append) return yajl_gen_no_buf; *buf = yajl_buf_data((yajl_buf)g->ctx); diff --git a/src/yajl_lex.c b/src/yajl_lex.c index 11e5f7b..ccb651c 100644 --- a/src/yajl_lex.c +++ b/src/yajl_lex.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include "yajl_lex.h" #include "yajl_buf.h" @@ -83,8 +67,8 @@ tokToStr(yajl_tok tok) struct yajl_lexer_t { /* the overal line and char offset into the data */ - unsigned int lineOff; - unsigned int charOff; + size_t lineOff; + size_t charOff; /* error */ yajl_lex_error error; @@ -95,7 +79,7 @@ struct yajl_lexer_t { /* in the case where we have data in the lexBuf, bufOff holds * the current offset into the lexBuf. */ - unsigned int bufOff; + size_t bufOff; /* are we using the lex buf? */ unsigned int bufInUse; @@ -206,7 +190,7 @@ static const char charLookupTable[256] = static yajl_tok yajl_lex_utf8_char(yajl_lexer lexer, const unsigned char * jsonText, - unsigned int jsonTextLen, unsigned int * offset, + size_t jsonTextLen, size_t * offset, unsigned char curChar) { if (curChar <= 0x7f) { @@ -262,7 +246,7 @@ if (*offset >= jsonTextLen) { \ static yajl_tok yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText, - unsigned int jsonTextLen, unsigned int * offset) + size_t jsonTextLen, size_t * offset) { yajl_tok tok = yajl_tok_error; int hasEscapes = 0; @@ -343,7 +327,7 @@ yajl_lex_string(yajl_lexer lexer, const unsigned char * jsonText, static yajl_tok yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText, - unsigned int jsonTextLen, unsigned int * offset) + size_t jsonTextLen, size_t * offset) { /** XXX: numbers are the only entities in json that we must lex * _beyond_ in order to know that they are complete. There @@ -430,7 +414,7 @@ yajl_lex_number(yajl_lexer lexer, const unsigned char * jsonText, static yajl_tok yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText, - unsigned int jsonTextLen, unsigned int * offset) + size_t jsonTextLen, size_t * offset) { unsigned char c; @@ -471,12 +455,12 @@ yajl_lex_comment(yajl_lexer lexer, const unsigned char * jsonText, 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) + size_t jsonTextLen, size_t * offset, + const unsigned char ** outBuf, size_t * outLen) { yajl_tok tok = yajl_tok_error; unsigned char c; - unsigned int startOffset = *offset; + size_t startOffset = *offset; *outBuf = NULL; *outLen = 0; @@ -706,23 +690,23 @@ yajl_lex_get_error(yajl_lexer lexer) return lexer->error; } -unsigned int yajl_lex_current_line(yajl_lexer lexer) +size_t yajl_lex_current_line(yajl_lexer lexer) { return lexer->lineOff; } -unsigned int yajl_lex_current_char(yajl_lexer lexer) +size_t 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) + size_t jsonTextLen, size_t offset) { const unsigned char * outBuf; - unsigned int outLen; - unsigned int bufLen = yajl_buf_len(lexer->buf); - unsigned int bufOff = lexer->bufOff; + size_t outLen; + size_t bufLen = yajl_buf_len(lexer->buf); + size_t bufOff = lexer->bufOff; unsigned int bufInUse = lexer->bufInUse; yajl_tok tok; diff --git a/src/yajl_lex.h b/src/yajl_lex.h index 6791a29..20edf47 100644 --- a/src/yajl_lex.h +++ b/src/yajl_lex.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifndef __YAJL_LEX_H__ #define __YAJL_LEX_H__ @@ -92,12 +76,12 @@ n * error messages. * 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); + size_t jsonTextLen, size_t * offset, + const unsigned char ** outBuf, size_t * 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); + size_t jsonTextLen, size_t offset); typedef enum { @@ -121,13 +105,13 @@ const char * yajl_lex_error_to_string(yajl_lex_error 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); +size_t 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); +size_t 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); +size_t yajl_lex_current_char(yajl_lexer lexer); #endif diff --git a/src/yajl_parser.c b/src/yajl_parser.c index 7fae6c6..65d5ed6 100644 --- a/src/yajl_parser.c +++ b/src/yajl_parser.c @@ -1,35 +1,20 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#include "api/yajl_parse.h" #include "yajl_lex.h" #include "yajl_parser.h" #include "yajl_encode.h" @@ -44,16 +29,41 @@ #include <assert.h> #include <math.h> +#define MAX_VALUE_TO_MULTIPLY ((LLONG_MAX / 10) + (LLONG_MAX % 10)) + + /* same semantics as strtol */ +static long long +yajl_parse_integer(const unsigned char *number, unsigned int length) +{ + long long ret = 0; + long sign = 1; + const unsigned char *pos = number; + if (*pos == '-') { pos++; sign = -1; } + if (*pos == '+') { pos++; } + + while (pos < number + length) { + + if ( ret > MAX_VALUE_TO_MULTIPLY ) { + errno = ERANGE; + return sign == 1 ? LLONG_MAX : LLONG_MIN; + } + ret *= 10; + ret += (*pos++ - '0'); + } + + return sign * ret; +} + unsigned char * yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, - unsigned int jsonTextLen, int verbose) + size_t jsonTextLen, int verbose) { - unsigned int offset = hand->bytesConsumed; + size_t offset = hand->bytesConsumed; unsigned char * str; const char * errorType = NULL; const char * errorText = NULL; char text[72]; - const char * arrow = " (right here) ------^\n"; + const char * arrow = " (right here) ------^\n"; if (yajl_bs_current(hand->stateStack) == yajl_state_parse_error) { errorType = "parse"; @@ -66,34 +76,35 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, } { - unsigned int memneeded = 0; + size_t memneeded = 0; memneeded += strlen(errorType); memneeded += strlen(" error"); if (errorText != NULL) { - memneeded += strlen(": "); - memneeded += strlen(errorText); + memneeded += strlen(": "); + memneeded += strlen(errorText); } str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2); + if (!str) return NULL; str[0] = 0; strcat((char *) str, errorType); - strcat((char *) str, " error"); + strcat((char *) str, " error"); if (errorText != NULL) { - strcat((char *) str, ": "); - strcat((char *) str, errorText); + strcat((char *) str, ": "); + strcat((char *) str, errorText); } - strcat((char *) str, "\n"); + 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; + size_t start, end, i; + size_t 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++) { @@ -111,13 +122,15 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, 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_MALLOC(&(hand->alloc), (unsigned int)(strlen((char *) str) + + strlen((char *) text) + + strlen(arrow) + 1)); + if (newStr) { + 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; } @@ -136,34 +149,77 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, yajl_status +yajl_do_finish(yajl_handle hand) +{ + yajl_status stat; + stat = yajl_do_parse(hand,(const unsigned char *)" ",1); + + if (stat != yajl_status_ok) return stat; + + switch(yajl_bs_current(hand->stateStack)) + { + case yajl_state_parse_error: + case yajl_state_lexical_error: + return yajl_status_error; + case yajl_state_got_value: + case yajl_state_parse_complete: + return yajl_status_ok; + default: + if (!(hand->flags & yajl_allow_partial_values)) + { + yajl_bs_set(hand->stateStack, yajl_state_parse_error); + hand->parseError = "premature EOF"; + return yajl_status_error; + } + return yajl_status_ok; + } +} + +yajl_status yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, - unsigned int jsonTextLen) + size_t jsonTextLen) { yajl_tok tok; const unsigned char * buf; - unsigned int bufLen; - unsigned int * offset = &(hand->bytesConsumed); + size_t bufLen; + size_t * offset = &(hand->bytesConsumed); *offset = 0; - around_again: switch (yajl_bs_current(hand->stateStack)) { case yajl_state_parse_complete: + if (hand->flags & yajl_allow_multiple_values) { + yajl_bs_set(hand->stateStack, yajl_state_got_value); + goto around_again; + } + if (!(hand->flags & yajl_allow_trailing_garbage)) { + if (*offset != jsonTextLen) { + tok = yajl_lex_lex(hand->lexer, jsonText, jsonTextLen, + offset, &buf, &bufLen); + if (tok != yajl_tok_eof) { + yajl_bs_set(hand->stateStack, yajl_state_parse_error); + hand->parseError = "trailing garbage"; + } + goto around_again; + } + } return yajl_status_ok; case yajl_state_lexical_error: - case yajl_state_parse_error: + case yajl_state_parse_error: return yajl_status_error; case yajl_state_start: + case yajl_state_got_value: case yajl_state_map_need_val: case yajl_state_array_need_val: - case yajl_state_array_start: { + 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, @@ -171,7 +227,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, switch (tok) { case yajl_tok_eof: - return yajl_status_insufficient_data; + return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; @@ -190,13 +246,13 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, yajl_buf_len(hand->decodeBuf))); } break; - case yajl_tok_bool: + 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: + case yajl_tok_null: if (hand->callbacks && hand->callbacks->yajl_null) { _CC_CHK(hand->callbacks->yajl_null(hand->ctx)); } @@ -214,29 +270,14 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, 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) && + long long int i = 0; + i = yajl_parse_integer(buf, bufLen); + if ((i == LLONG_MIN || i == LLONG_MAX) && errno == ERANGE) { yajl_bs_set(hand->stateStack, @@ -290,13 +331,13 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); } yajl_bs_pop(hand->stateStack); - goto around_again; + goto around_again; } /* intentional fall-through */ } - case yajl_tok_colon: - case yajl_tok_comma: - case yajl_tok_right_bracket: + 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"; @@ -309,11 +350,11 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, /* got a value. transition depends on the state we're in. */ { yajl_state s = yajl_bs_current(hand->stateStack); - if (s == yajl_state_start) { + if (s == yajl_state_start || s == yajl_state_got_value) { 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 { + } else { yajl_bs_set(hand->stateStack, yajl_state_array_got_val); } } @@ -323,7 +364,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, goto around_again; } - case yajl_state_map_start: + 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 @@ -332,7 +373,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, offset, &buf, &bufLen); switch (tok) { case yajl_tok_eof: - return yajl_status_insufficient_data; + return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; @@ -359,7 +400,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); } yajl_bs_pop(hand->stateStack); - goto around_again; + goto around_again; } default: yajl_bs_set(hand->stateStack, yajl_state_parse_error); @@ -374,9 +415,9 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, switch (tok) { case yajl_tok_colon: yajl_bs_set(hand->stateStack, yajl_state_map_need_val); - goto around_again; + goto around_again; case yajl_tok_eof: - return yajl_status_insufficient_data; + return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; @@ -396,19 +437,19 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, _CC_CHK(hand->callbacks->yajl_end_map(hand->ctx)); } yajl_bs_pop(hand->stateStack); - goto around_again; + goto around_again; case yajl_tok_comma: yajl_bs_set(hand->stateStack, yajl_state_map_need_key); - goto around_again; + goto around_again; case yajl_tok_eof: - return yajl_status_insufficient_data; + return yajl_status_ok; 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 '}'"; + hand->parseError = "after key and value, inside map, " + "I expect ',' or '}'"; /* try to restore error offset */ if (*offset >= bufLen) *offset -= bufLen; else *offset = 0; @@ -424,12 +465,12 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, _CC_CHK(hand->callbacks->yajl_end_array(hand->ctx)); } yajl_bs_pop(hand->stateStack); - goto around_again; + goto around_again; case yajl_tok_comma: yajl_bs_set(hand->stateStack, yajl_state_array_need_val); - goto around_again; + goto around_again; case yajl_tok_eof: - return yajl_status_insufficient_data; + return yajl_status_ok; case yajl_tok_error: yajl_bs_set(hand->stateStack, yajl_state_lexical_error); goto around_again; @@ -441,7 +482,7 @@ yajl_do_parse(yajl_handle hand, const unsigned char * jsonText, } } } - + abort(); return yajl_status_error; } diff --git a/src/yajl_parser.h b/src/yajl_parser.h index f72f3de..97ef207 100644 --- a/src/yajl_parser.h +++ b/src/yajl_parser.h @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #ifndef __YAJL_PARSER_H__ #define __YAJL_PARSER_H__ @@ -50,7 +34,8 @@ typedef enum { yajl_state_map_need_key, yajl_state_array_start, yajl_state_array_got_val, - yajl_state_array_need_val + yajl_state_array_need_val, + yajl_state_got_value, } yajl_state; struct yajl_handle_t { @@ -61,22 +46,27 @@ struct yajl_handle_t { /* the number of bytes consumed from the last client buffer, * in the case of an error this will be an error offset, in the * case of an error this can be used as the error offset */ - unsigned int bytesConsumed; + size_t bytesConsumed; /* 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; + /* bitfield */ + unsigned int flags; }; yajl_status yajl_do_parse(yajl_handle handle, const unsigned char * jsonText, - unsigned int jsonTextLen); + size_t jsonTextLen); + +yajl_status +yajl_do_finish(yajl_handle handle); unsigned char * yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText, - unsigned int jsonTextLen, int verbose); + size_t jsonTextLen, int verbose); #endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e179b2b..153288c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,32 +1,16 @@ -# Copyright 2010, 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. +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. SET (SRCS yajl_test.c) diff --git a/test/cases/difficult_json_c_test_case_with_comments.json b/test/cases/ac_difficult_json_c_test_case_with_comments.json index 2463c71..2463c71 100644 --- a/test/cases/difficult_json_c_test_case_with_comments.json +++ b/test/cases/ac_difficult_json_c_test_case_with_comments.json diff --git a/test/cases/difficult_json_c_test_case_with_comments.json.gold b/test/cases/ac_difficult_json_c_test_case_with_comments.json.gold index c3adc11..c3adc11 100644 --- a/test/cases/difficult_json_c_test_case_with_comments.json.gold +++ b/test/cases/ac_difficult_json_c_test_case_with_comments.json.gold diff --git a/test/cases/dc_simple_with_comments.json b/test/cases/ac_simple_with_comments.json index 3b79bba..3b79bba 100644 --- a/test/cases/dc_simple_with_comments.json +++ b/test/cases/ac_simple_with_comments.json diff --git a/test/cases/ac_simple_with_comments.json.gold b/test/cases/ac_simple_with_comments.json.gold new file mode 100644 index 0000000..80fcad2 --- /dev/null +++ b/test/cases/ac_simple_with_comments.json.gold @@ -0,0 +1,9 @@ +map open '{' +key: 'this' +string: 'is' +key: 'really' +string: 'simple' +key: 'json' +string: 'right?' +map close '}' +memory leaks: 0 diff --git a/test/cases/false_then_garbage.json b/test/cases/ag_false_then_garbage.json index 78f4e96..78f4e96 100644 --- a/test/cases/false_then_garbage.json +++ b/test/cases/ag_false_then_garbage.json diff --git a/test/cases/false_then_garbage.json.gold b/test/cases/ag_false_then_garbage.json.gold index e55fa1f..e55fa1f 100644 --- a/test/cases/false_then_garbage.json.gold +++ b/test/cases/ag_false_then_garbage.json.gold diff --git a/test/cases/null_then_garbage.json b/test/cases/ag_null_then_garbage.json index 7b65b35..7b65b35 100644 --- a/test/cases/null_then_garbage.json +++ b/test/cases/ag_null_then_garbage.json diff --git a/test/cases/null_then_garbage.json.gold b/test/cases/ag_null_then_garbage.json.gold index 94ad0fa..94ad0fa 100644 --- a/test/cases/null_then_garbage.json.gold +++ b/test/cases/ag_null_then_garbage.json.gold diff --git a/test/cases/true_then_garbage.json b/test/cases/ag_true_then_garbage.json index 9151612..9151612 100644 --- a/test/cases/true_then_garbage.json +++ b/test/cases/ag_true_then_garbage.json diff --git a/test/cases/true_then_garbage.json.gold b/test/cases/ag_true_then_garbage.json.gold index 0858bf7..0858bf7 100644 --- a/test/cases/true_then_garbage.json.gold +++ b/test/cases/ag_true_then_garbage.json.gold diff --git a/test/cases/am_eof.json b/test/cases/am_eof.json new file mode 100644 index 0000000..43a772f --- /dev/null +++ b/test/cases/am_eof.json @@ -0,0 +1 @@ +{ "123": diff --git a/test/cases/am_eof.json.gold b/test/cases/am_eof.json.gold new file mode 100644 index 0000000..5a9708b --- /dev/null +++ b/test/cases/am_eof.json.gold @@ -0,0 +1,4 @@ +map open '{' +key: '123' +parse error: premature EOF +memory leaks: 0 diff --git a/test/cases/am_integers.json b/test/cases/am_integers.json new file mode 100644 index 0000000..856809b --- /dev/null +++ b/test/cases/am_integers.json @@ -0,0 +1 @@ +1221 21 diff --git a/test/cases/am_integers.json.gold b/test/cases/am_integers.json.gold new file mode 100644 index 0000000..7b8a953 --- /dev/null +++ b/test/cases/am_integers.json.gold @@ -0,0 +1,3 @@ +integer: 1221 +integer: 21 +memory leaks: 0 diff --git a/test/cases/am_multiple.json b/test/cases/am_multiple.json new file mode 100644 index 0000000..b573db0 --- /dev/null +++ b/test/cases/am_multiple.json @@ -0,0 +1,3 @@ + +{} +{} diff --git a/test/cases/am_multiple.json.gold b/test/cases/am_multiple.json.gold new file mode 100644 index 0000000..bf705d4 --- /dev/null +++ b/test/cases/am_multiple.json.gold @@ -0,0 +1,5 @@ +map open '{' +map close '}' +map open '{' +map close '}' +memory leaks: 0 diff --git a/test/cases/am_stuff.json b/test/cases/am_stuff.json new file mode 100644 index 0000000..89c607d --- /dev/null +++ b/test/cases/am_stuff.json @@ -0,0 +1,7 @@ +{} +[] +[] +"sdfasd" +123 +{ "123" : 123 } +3.1e124 diff --git a/test/cases/am_stuff.json.gold b/test/cases/am_stuff.json.gold new file mode 100644 index 0000000..bf3a5bb --- /dev/null +++ b/test/cases/am_stuff.json.gold @@ -0,0 +1,14 @@ +map open '{' +map close '}' +array open '[' +array close ']' +array open '[' +array close ']' +string: 'sdfasd' +integer: 123 +map open '{' +key: '123' +integer: 123 +map close '}' +double: 3.1e+124 +memory leaks: 0 diff --git a/test/cases/array_open.json b/test/cases/ap_array_open.json index 558ed37..558ed37 100644 --- a/test/cases/array_open.json +++ b/test/cases/ap_array_open.json diff --git a/test/cases/array_open.json.gold b/test/cases/ap_array_open.json.gold index 478b6b9..478b6b9 100644 --- a/test/cases/array_open.json.gold +++ b/test/cases/ap_array_open.json.gold diff --git a/test/cases/ap_eof_str.json b/test/cases/ap_eof_str.json new file mode 100644 index 0000000..6a21793 --- /dev/null +++ b/test/cases/ap_eof_str.json @@ -0,0 +1 @@ +"abc
\ No newline at end of file diff --git a/test/cases/ap_eof_str.json.gold b/test/cases/ap_eof_str.json.gold new file mode 100644 index 0000000..736730b --- /dev/null +++ b/test/cases/ap_eof_str.json.gold @@ -0,0 +1 @@ +memory leaks: 0 diff --git a/test/cases/map_open.json b/test/cases/ap_map_open.json index 98232c6..98232c6 100644 --- a/test/cases/map_open.json +++ b/test/cases/ap_map_open.json diff --git a/test/cases/map_open.json.gold b/test/cases/ap_map_open.json.gold index ab1f33d..ab1f33d 100644 --- a/test/cases/map_open.json.gold +++ b/test/cases/ap_map_open.json.gold diff --git a/test/cases/ap_partial_ok.json b/test/cases/ap_partial_ok.json new file mode 100644 index 0000000..2fbd027 --- /dev/null +++ b/test/cases/ap_partial_ok.json @@ -0,0 +1 @@ +[ "foo", "bar" diff --git a/test/cases/ap_partial_ok.json.gold b/test/cases/ap_partial_ok.json.gold new file mode 100644 index 0000000..9f754c7 --- /dev/null +++ b/test/cases/ap_partial_ok.json.gold @@ -0,0 +1,4 @@ +array open '[' +string: 'foo' +string: 'bar' +memory leaks: 0 diff --git a/test/cases/dc_simple_with_comments.json.gold b/test/cases/dc_simple_with_comments.json.gold deleted file mode 100644 index d222e9b..0000000 --- a/test/cases/dc_simple_with_comments.json.gold +++ /dev/null @@ -1,5 +0,0 @@ -map open '{' -key: 'this' -string: 'is' -lexical error: probable comment found in input text, comments are not enabled. -memory leaks: 0 diff --git a/test/cases/doubles_in_array.json b/test/cases/doubles_in_array.json new file mode 100644 index 0000000..06bf727 --- /dev/null +++ b/test/cases/doubles_in_array.json @@ -0,0 +1 @@ +[0.00011999999999999999, 6E-06, 6E-06, 1E-06, 1E-06] diff --git a/test/cases/doubles_in_array.json.gold b/test/cases/doubles_in_array.json.gold new file mode 100644 index 0000000..57f5b9a --- /dev/null +++ b/test/cases/doubles_in_array.json.gold @@ -0,0 +1,8 @@ +array open '[' +double: 0.00012 +double: 6e-06 +double: 6e-06 +double: 1e-06 +double: 1e-06 +array close ']' +memory leaks: 0 diff --git a/test/cases/fg_false_then_garbage.json b/test/cases/fg_false_then_garbage.json new file mode 100644 index 0000000..78f4e96 --- /dev/null +++ b/test/cases/fg_false_then_garbage.json @@ -0,0 +1 @@ +falsex
\ No newline at end of file diff --git a/test/cases/fg_false_then_garbage.json.gold b/test/cases/fg_false_then_garbage.json.gold new file mode 100644 index 0000000..fe8fc1a --- /dev/null +++ b/test/cases/fg_false_then_garbage.json.gold @@ -0,0 +1,3 @@ +bool: false +parse error: trailing garbage +memory leaks: 0 diff --git a/test/cases/fg_issue_7.json b/test/cases/fg_issue_7.json new file mode 100644 index 0000000..77152a9 --- /dev/null +++ b/test/cases/fg_issue_7.json @@ -0,0 +1 @@ +2009-10-20@20:38:21.539575 diff --git a/test/cases/fg_issue_7.json.gold b/test/cases/fg_issue_7.json.gold new file mode 100644 index 0000000..4d0de0f --- /dev/null +++ b/test/cases/fg_issue_7.json.gold @@ -0,0 +1,3 @@ +integer: 2009 +parse error: trailing garbage +memory leaks: 0 diff --git a/test/cases/fg_null_then_garbage.json b/test/cases/fg_null_then_garbage.json new file mode 100644 index 0000000..7b65b35 --- /dev/null +++ b/test/cases/fg_null_then_garbage.json @@ -0,0 +1 @@ +nullx diff --git a/test/cases/fg_null_then_garbage.json.gold b/test/cases/fg_null_then_garbage.json.gold new file mode 100644 index 0000000..349235c --- /dev/null +++ b/test/cases/fg_null_then_garbage.json.gold @@ -0,0 +1,3 @@ +null +parse error: trailing garbage +memory leaks: 0 diff --git a/test/cases/fg_true_then_garbage.json b/test/cases/fg_true_then_garbage.json new file mode 100644 index 0000000..31f9deb --- /dev/null +++ b/test/cases/fg_true_then_garbage.json @@ -0,0 +1 @@ +truex diff --git a/test/cases/fg_true_then_garbage.json.gold b/test/cases/fg_true_then_garbage.json.gold new file mode 100644 index 0000000..73af6ce --- /dev/null +++ b/test/cases/fg_true_then_garbage.json.gold @@ -0,0 +1,3 @@ +bool: true +parse error: trailing garbage +memory leaks: 0 diff --git a/test/cases/multiple.json b/test/cases/multiple.json new file mode 100644 index 0000000..b573db0 --- /dev/null +++ b/test/cases/multiple.json @@ -0,0 +1,3 @@ + +{} +{} diff --git a/test/cases/multiple.json.gold b/test/cases/multiple.json.gold new file mode 100644 index 0000000..0f6f3df --- /dev/null +++ b/test/cases/multiple.json.gold @@ -0,0 +1,4 @@ +map open '{' +map close '}' +parse error: trailing garbage +memory leaks: 0 diff --git a/test/cases/np_partial_bad.json b/test/cases/np_partial_bad.json new file mode 100644 index 0000000..2fbd027 --- /dev/null +++ b/test/cases/np_partial_bad.json @@ -0,0 +1 @@ +[ "foo", "bar" diff --git a/test/cases/np_partial_bad.json.gold b/test/cases/np_partial_bad.json.gold new file mode 100644 index 0000000..b981bda --- /dev/null +++ b/test/cases/np_partial_bad.json.gold @@ -0,0 +1,5 @@ +array open '[' +string: 'foo' +string: 'bar' +parse error: premature EOF +memory leaks: 0 diff --git a/test/cases/simple_with_comments.json.gold b/test/cases/simple_with_comments.json.gold index 80fcad2..d222e9b 100644 --- a/test/cases/simple_with_comments.json.gold +++ b/test/cases/simple_with_comments.json.gold @@ -1,9 +1,5 @@ map open '{' key: 'this' string: 'is' -key: 'really' -string: 'simple' -key: 'json' -string: 'right?' -map close '}' +lexical error: probable comment found in input text, comments are not enabled. memory leaks: 0 diff --git a/test/cases/zerobyte.json b/test/cases/zerobyte.json new file mode 100644 index 0000000..09c5044 --- /dev/null +++ b/test/cases/zerobyte.json @@ -0,0 +1 @@ +"\u0000" diff --git a/test/cases/zerobyte.json.gold b/test/cases/zerobyte.json.gold Binary files differnew file mode 100644 index 0000000..b0c58fc --- /dev/null +++ b/test/cases/zerobyte.json.gold diff --git a/test/run_tests.sh b/test/run_tests.sh index d596daf..0d75ed3 100755 --- a/test/run_tests.sh +++ b/test/run_tests.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/sh ECHO=`which echo` @@ -28,35 +28,54 @@ fi ${ECHO} "using test binary: $testBin" +testBinShort=`basename $testBin` + testsSucceeded=0 -testsTotal=0 +testsTotal=0 for file in cases/*.json ; do - allowComments="-c" + allowComments="" + allowGarbage="" + allowMultiple="" + allowPartials="" # if the filename starts with dc_, we disallow comments for this test case $(basename $file) in - dc_*) - allowComments="" + ac_*) + allowComments="-c " + ;; + ag_*) + allowGarbage="-g " + ;; + am_*) + allowMultiple="-m "; + ;; + ap_*) + allowPartials="-p "; ;; esac - ${ECHO} -n " test case: '$file': " + fileShort=`basename $file` + testName=`echo $fileShort | sed -e 's/\.json$//'` + + ${ECHO} -n " test ($testName): " iter=1 - success="success" + success="SUCCESS" - ${ECHO} "$testBin $allowComments -b $iter < $file > ${file}.test " + ${ECHO} -n "$testBinShort $allowPartials$allowComments$allowGarbage$allowMultiple-b $iter < $fileShort > ${fileShort}.test : " # parse with a read buffer size ranging from 1-31 to stress stream parsing - while [ $iter -lt 32 ] && [ $success = "success" ] ; do - $testBin $allowComments -b $iter < $file > ${file}.test 2>&1 - diff ${DIFF_FLAGS} ${file}.gold ${file}.test + while [ $iter -lt 32 ] && [ $success = "SUCCESS" ] ; do + $testBin $allowPartials $allowComments $allowGarbage $allowMultiple -b $iter < $file > ${file}.test 2>&1 + diff ${DIFF_FLAGS} ${file}.gold ${file}.test > ${file}.out if [ $? -eq 0 ] ; then if [ $iter -eq 31 ] ; then : $(( testsSucceeded += 1)) ; fi - else + else success="FAILURE" iter=32 + ${ECHO} + cat ${file}.out fi : $(( iter += 1 )) - rm ${file}.test + rm ${file}.test ${file}.out done ${ECHO} $success diff --git a/test/yajl_test.c b/test/yajl_test.c index 0f07a94..d669ca4 100644 --- a/test/yajl_test.c +++ b/test/yajl_test.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include <yajl/yajl_parse.h> #include <yajl/yajl_gen.h> @@ -40,12 +24,12 @@ #include <assert.h> /* memory debugging routines */ -typedef struct +typedef struct { - unsigned int numFrees; - unsigned int numMallocs; + size_t numFrees; + size_t numMallocs; /* XXX: we really need a hash table here with per-allocation - * information */ + * information */ } yajlTestMemoryContext; /* cast void * into context */ @@ -58,20 +42,20 @@ static void yajlTestFree(void * ctx, void * ptr) free(ptr); } -static void * yajlTestMalloc(void * ctx, unsigned int sz) +static void * yajlTestMalloc(void * ctx, size_t sz) { assert(sz != 0); TEST_CTX(ctx)->numMallocs++; return malloc(sz); } -static void * yajlTestRealloc(void * ctx, void * ptr, unsigned int sz) +static void * yajlTestRealloc(void * ctx, void * ptr, size_t sz) { if (ptr == NULL) { assert(sz != 0); - TEST_CTX(ctx)->numMallocs++; + TEST_CTX(ctx)->numMallocs++; } else if (sz == 0) { - TEST_CTX(ctx)->numFrees++; + TEST_CTX(ctx)->numFrees++; } return realloc(ptr, sz); @@ -93,9 +77,9 @@ static int test_yajl_boolean(void * ctx, int boolVal) return 1; } -static int test_yajl_integer(void *ctx, long integerVal) +static int test_yajl_integer(void *ctx, long long integerVal) { - printf("integer: %ld\n", integerVal); + printf("integer: %lld\n", integerVal); return 1; } @@ -106,16 +90,16 @@ static int test_yajl_double(void *ctx, double doubleVal) } static int test_yajl_string(void *ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { printf("string: '"); fwrite(stringVal, 1, stringLen, stdout); - printf("'\n"); + printf("'\n"); return 1; } static int test_yajl_map_key(void *ctx, const unsigned char * stringVal, - unsigned int stringLen) + size_t stringLen) { char * str = (char *) malloc(stringLen + 1); str[stringLen] = 0; @@ -167,24 +151,29 @@ static yajl_callbacks callbacks = { static void usage(const char * progname) { fprintf(stderr, - "usage: %s [options] <filename>\n" + "usage: %s [options]\n" + "Parse input from stdin as JSON and ouput parsing details " + "to stdout\n" + " -b set the read buffer size\n" " -c allow comments\n" - " -b set the read buffer size\n", + " -g allow *g*arbage after valid JSON text\n" + " -m allows the parser to consume multiple JSON values\n" + " from a single string separated by whitespace\n" + " -p partial JSON documents should not cause errors\n", progname); exit(1); } -int +int main(int argc, char ** argv) { yajl_handle hand; const char * fileName; static unsigned char * fileData = NULL; - unsigned int bufSize = BUF_SIZE; + size_t bufSize = BUF_SIZE; yajl_status stat; size_t rd; - yajl_parser_config cfg = { 0, 1 }; - int i, j, done; + int i, j; /* memory allocation debugging: allocate a structure which collects * statistics */ @@ -201,10 +190,13 @@ main(int argc, char ** argv) allocFuncs.ctx = (void *) &memCtx; + /* allocate the parser */ + hand = yajl_alloc(&callbacks, &allocFuncs, NULL); + /* check arguments. We expect exactly one! */ for (i=1;i<argc;i++) { if (!strcmp("-c", argv[i])) { - cfg.allowComments = 1; + yajl_config(hand, yajl_allow_comments, 1); } else if (!strcmp("-b", argv[i])) { if (++i >= argc) usage(argv[0]); @@ -218,9 +210,15 @@ main(int argc, char ** argv) bufSize = atoi(argv[i]); if (!bufSize) { - fprintf(stderr, "%d is an invalid buffer size\n", + fprintf(stderr, "%zu is an invalid buffer size\n", bufSize); } + } else if (!strcmp("-g", argv[i])) { + yajl_config(hand, yajl_allow_trailing_garbage, 1); + } else if (!strcmp("-m", argv[i])) { + yajl_config(hand, yajl_allow_multiple_values, 1); + } else if (!strcmp("-p", argv[i])) { + yajl_config(hand, yajl_allow_partial_values, 1); } else { fprintf(stderr, "invalid command line option: '%s'\n", argv[i]); @@ -232,45 +230,37 @@ main(int argc, char ** argv) if (fileData == NULL) { fprintf(stderr, - "failed to allocate read buffer of %u bytes, exiting.", + "failed to allocate read buffer of %zu bytes, exiting.", bufSize); + yajl_free(hand); 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) { + for (;;) { 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; } - } + /* read file data, now pass to parser */ + stat = yajl_parse(hand, fileData, rd); + + if (stat != yajl_status_ok) break; + } + + stat = yajl_complete_parse(hand); + if (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); + } yajl_free(hand); free(fileData); @@ -285,7 +275,7 @@ main(int argc, char ** argv) */ fflush(stderr); fflush(stdout); - printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees); + printf("memory leaks:\t%zu\n", memCtx.numMallocs - memCtx.numFrees); return 0; } diff --git a/verify/CMakeLists.txt b/verify/CMakeLists.txt index 34f9f2e..4c296d0 100644 --- a/verify/CMakeLists.txt +++ b/verify/CMakeLists.txt @@ -1,32 +1,16 @@ -# Copyright 2010, 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. +# Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # set up some paths SET (binDir ${CMAKE_CURRENT_BINARY_DIR}/../${YAJL_DIST_NAME}/bin) diff --git a/verify/json_verify.c b/verify/json_verify.c index 9281a4c..10e8733 100644 --- a/verify/json_verify.c +++ b/verify/json_verify.c @@ -1,34 +1,18 @@ /* - * Copyright 2010, 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. - */ + * Copyright (c) 2007-2011, Lloyd Hilaiel <lloyd@hilaiel.com> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ #include <yajl/yajl_parse.h> @@ -48,7 +32,7 @@ usage(const char * progname) exit(1); } -int +int main(int argc, char ** argv) { yajl_status stat; @@ -56,8 +40,10 @@ main(int argc, char ** argv) yajl_handle hand; static unsigned char fileData[65536]; int quiet = 0; - int retval = 0, done = 0; - yajl_parser_config cfg = { 0, 1 }; + int retval = 0; + + /* allocate a parser */ + hand = yajl_alloc(NULL, NULL, NULL); /* check arguments.*/ int a = 1; @@ -69,10 +55,10 @@ main(int argc, char ** argv) quiet = 1; break; case 'c': - cfg.allowComments = 1; + yajl_config(hand, yajl_allow_comments, 1); break; case 'u': - cfg.checkUTF8 = 0; + yajl_config(hand, yajl_dont_validate_strings, 1); break; default: fprintf(stderr, "unrecognized option: '%c'\n\n", argv[a][i]); @@ -84,52 +70,47 @@ main(int argc, char ** argv) if (a < argc) { usage(argv[0]); } - - /* allocate a parser */ - hand = yajl_alloc(NULL, &cfg, NULL, NULL); - - while (!done) { + + for (;;) { 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; + break; } 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; + + /* read file data, pass to parser */ + stat = yajl_parse(hand, fileData, rd); + + if (stat != yajl_status_ok) break; + } + + /* parse any remaining buffered data */ + stat = yajl_complete_parse(hand); + + if (stat != yajl_status_ok) + { + 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; } - + yajl_free(hand); if (!quiet) { printf("JSON is %s\n", retval ? "invalid" : "valid"); } - + return retval; } |
