Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

* BREAKING API CHANGE: allow client to specify memory allocation rou…

…tines

 * bump yajl version to 1.0.0
 * update TODO list, removing completed tasks
 * update yajl_test to override allocation routines and count allocations/frees, providing an automated standalone way to validate we're not leaky
 * update all copyright dates
 * update all .gold files with new test output
 * update ChangeLog in preparation for 1.0.0 release
  • Loading branch information...
commit b78dd790825e3347422ef8ac56d2ad557a473e8f 1 parent af30552
@lloyd authored
Showing with 404 additions and 72 deletions.
  1. +4 −4 CMakeLists.txt
  2. +1 −1  COPYING
  3. +11 −0 ChangeLog
  4. +0 −4 TODO
  5. +1 −1  configure
  6. +1 −1  reformatter/CMakeLists.txt
  7. +4 −4 reformatter/json_reformat.c
  8. +4 −3 src/CMakeLists.txt
  9. +35 −1 src/api/yajl_common.h
  10. +13 −3 src/api/yajl_gen.h
  11. +3 −2 src/api/yajl_parse.h
  12. +1 −1  src/yajl
  13. +28 −9 src/yajl.c
  14. +65 −0 src/yajl_alloc.c
  15. +50 −0 src/yajl_alloc.h
  16. +11 −7 src/yajl_buf.c
  17. +5 −2 src/yajl_buf.h
  18. +1 −1  src/yajl_encode.c
  19. +1 −1  src/yajl_encode.h
  20. +26 −5 src/yajl_gen.c
  21. +10 −5 src/yajl_lex.c
  22. +5 −2 src/yajl_lex.h
  23. +7 −6 src/yajl_parser.c
  24. +3 −1 src/yajl_parser.h
  25. +1 −1  test/CMakeLists.txt
  26. +1 −0  test/cases/array.json.gold
  27. +1 −0  test/cases/array_close.json.gold
  28. +1 −0  test/cases/array_open.json.gold
  29. +1 −0  test/cases/bogus_char.json.gold
  30. +1 −0  test/cases/codepoints_from_unicode_org.json.gold
  31. +1 −0  test/cases/dc_simple_with_comments.json.gold
  32. +1 −0  test/cases/deep_arrays.json.gold
  33. +1 −0  test/cases/difficult_json_c_test_case.json.gold
  34. +1 −0  test/cases/difficult_json_c_test_case_with_comments.json.gold
  35. +1 −0  test/cases/doubles.json.gold
  36. +1 −0  test/cases/empty_array.json.gold
  37. +1 −0  test/cases/empty_string.json.gold
  38. +1 −0  test/cases/escaped_bulgarian.json.gold
  39. +1 −0  test/cases/escaped_foobar.json.gold
  40. +1 −0  test/cases/false.json.gold
  41. +1 −0  test/cases/false_then_garbage.json.gold
  42. +1 −0  test/cases/integers.json.gold
  43. +1 −0  test/cases/invalid_utf8.json.gold
  44. +1 −0  test/cases/isolated_surrogate_marker.json.gold
  45. +1 −0  test/cases/leading_zero_in_number.json.gold
  46. +1 −0  test/cases/lonely_minus_sign.json.gold
  47. +1 −0  test/cases/lonely_number.json.gold
  48. +1 −0  test/cases/map_close.json.gold
  49. +1 −0  test/cases/map_open.json.gold
  50. +1 −0  test/cases/missing_integer_after_decimal_point.json.gold
  51. +1 −0  test/cases/missing_integer_after_exponent.json.gold
  52. +1 −0  test/cases/non_utf8_char_in_string.json.gold
  53. +1 −0  test/cases/null.json.gold
  54. +1 −0  test/cases/null_then_garbage.json.gold
  55. +1 −0  test/cases/nulls_and_bools.json.gold
  56. +1 −0  test/cases/simple.json.gold
  57. +1 −0  test/cases/simple_with_comments.json.gold
  58. +1 −0  test/cases/string_invalid_escape.json.gold
  59. +1 −0  test/cases/string_invalid_hex_char.json.gold
  60. +1 −0  test/cases/string_with_escapes.json.gold
  61. +1 −0  test/cases/string_with_invalid_newline.json.gold
  62. +1 −0  test/cases/true.json.gold
  63. +1 −0  test/cases/true_then_garbage.json.gold
  64. +1 −0  test/cases/unescaped_bulgarian.json.gold
  65. +70 −3 test/yajl_test.c
  66. +1 −1  verify/CMakeLists.txt
  67. +3 −3 verify/json_verify.c
View
8 CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -32,9 +32,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
PROJECT(YetAnotherJSONParser)
-SET (YAJL_MAJOR 0)
-SET (YAJL_MINOR 4)
-SET (YAJL_MICRO 1)
+SET (YAJL_MAJOR 1)
+SET (YAJL_MINOR 0)
+SET (YAJL_MICRO 0)
SET (YAJL_DIST_NAME "yajl-${YAJL_MAJOR}.${YAJL_MINOR}.${YAJL_MICRO}")
View
2  COPYING
@@ -1,4 +1,4 @@
-Copyright 2007, Lloyd Hilaiel.
+Copyright 2007-2009, Lloyd Hilaiel.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
View
11 ChangeLog
@@ -1,6 +1,17 @@
1.0.0
* lth add 'make install' rules, thaks to Andrei Soroker for the
contribution.
+ * lth client may override allocation routines at generator or parser
+ allocation time
+ * tjw add yajl_parse_complete routine to allow client to explicitly
+ specify end-of-input, solving the "lonely number" case, where
+ json text consists only of an element with no explicit syntactic
+ end.
+ * tjw many new test cases
+ * tjw cleanup of code for symmetry and ease of reading
+ * lth integration of patches from Robert Varga which cleanup
+ compilation warnings on 64 bit linux
+
0.4.0
* lth buffer overflow bug in yajl_gen_double s/%lf/%g/ - thanks to
Eric Bergstrome
View
4 TODO
@@ -1,13 +1,9 @@
* add a test for 0x1F bug
* numeric overflow in integers and double
* line and char offsets in the lexer and in error messages
-* numbers at eof bug. client must have a way of indicating 'end of input'
- (other than passing in a ' ' whitespace byte),
- problem illustrated with lonely number test case.
* testing:
a. the permuter
b. some performance comparison against json_checker.
* investigate pull instead of push parsing
* Handle memory allocation failures gracefully
-* allow client to override malloc/calloc/free impl.
* cygwin/msys support on win32
View
2  configure
@@ -1,5 +1,5 @@
#!/usr/bin/env ruby
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
View
2  reformatter/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
View
8 reformatter/json_reformat.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -156,10 +156,10 @@ main(int argc, char ** argv)
usage(argv[0]);
}
- g = yajl_gen_alloc(&conf);
+ g = yajl_gen_alloc(&conf, NULL);
/* ok. open file. let's read and parse */
- hand = yajl_alloc(&callbacks, &cfg, (void *) g);
+ hand = yajl_alloc(&callbacks, &cfg, (void *) g, NULL);
while (!done) {
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
@@ -185,7 +185,7 @@ main(int argc, char ** argv)
{
unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
fprintf(stderr, (const char *) str);
- yajl_free_error(str);
+ yajl_free_error(hand, str);
} else {
const unsigned char * buf;
unsigned int len;
View
7 src/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
@@ -28,8 +28,9 @@
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
-SET (SRCS yajl.c yajl_lex.c yajl_parser.c yajl_buf.c yajl_encode.c yajl_gen.c)
-SET (HDRS yajl_parser.h yajl_lex.h yajl_buf.h yajl_encode.h)
+SET (SRCS yajl.c yajl_lex.c yajl_parser.c yajl_buf.c
+ yajl_encode.c yajl_gen.c yajl_alloc.c)
+SET (HDRS yajl_parser.h yajl_lex.h yajl_buf.h yajl_encode.h yajl_alloc.h)
SET (PUB_HDRS api/yajl_parse.h api/yajl_gen.h api/yajl_common.h)
# useful when fixing lexer bugs.
View
36 src/api/yajl_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,6 +33,10 @@
#ifndef __YAJL_COMMON_H__
#define __YAJL_COMMON_H__
+#ifdef __cplusplus
+extern "C" {
+#endif
+
#define YAJL_MAX_DEPTH 128
/* msft dll export gunk. To build a DLL on windows, you
@@ -48,4 +52,34 @@
# define YAJL_API
#endif
+/** pointer to a malloc function, supporting client overriding memory
+ * allocation routines */
+typedef void * (*yajl_malloc_func)(void *ctx, unsigned int sz);
+
+/** pointer to a free function, supporting client overriding memory
+ * allocation routines */
+typedef void (*yajl_free_func)(void *ctx, void * ptr);
+
+/** pointer to a realloc function which can resize an allocation. */
+typedef void * (*yajl_realloc_func)(void *ctx, void * ptr, unsigned int sz);
+
+/** A structure which can be passed to yajl_*_alloc routines to allow the
+ * client to specify memory allocation functions to be used. */
+typedef struct
+{
+ /** pointer to a function that can allocate uninitialized memory */
+ yajl_malloc_func malloc;
+ /** pointer to a function that can resize memory allocations */
+ yajl_realloc_func realloc;
+ /** pointer to a function that can free memory allocated using
+ * reallocFunction or mallocFunction */
+ yajl_free_func free;
+ /** a context pointer that will be passed to above allocation routines */
+ void * ctx;
+} yajl_alloc_funcs;
+
+#ifdef __cplusplus
+};
+#endif
+
#endif
View
16 src/api/yajl_gen.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -73,8 +73,18 @@ extern "C" {
const char * indentString;
} yajl_gen_config;
- /** allocate a generator handle */
- yajl_gen YAJL_API yajl_gen_alloc(const yajl_gen_config * config);
+ /** allocate a generator handle
+ * \param config a pointer to a structure containing parameters which
+ * configure the behavior of the json generator
+ * \param allocFuncs an optional pointer to a structure which allows
+ * the client to overide the memory allocation
+ * used by yajl. May be NULL, in which case
+ * malloc/free/realloc will be used.
+ *
+ * \returns an allocated handle on success, NULL on failure (bad params)
+ */
+ yajl_gen YAJL_API yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * allocFuncs);
/** free a generator handle */
void YAJL_API yajl_gen_free(yajl_gen handle);
View
5 src/api/yajl_parse.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -129,6 +129,7 @@ extern "C" {
*/
yajl_handle YAJL_API yajl_alloc(const yajl_callbacks * callbacks,
const yajl_parser_config * config,
+ const yajl_alloc_funcs * allocFuncs,
void * ctx);
/** free a parser handle */
@@ -169,7 +170,7 @@ extern "C" {
unsigned int jsonTextLength);
/** free an error returned from yajl_get_error */
- void YAJL_API yajl_free_error(unsigned char * str);
+ void YAJL_API yajl_free_error(yajl_handle hand, unsigned char * str);
#ifdef __cplusplus
};
View
2  src/yajl
@@ -1,7 +1,7 @@
/*!
\mainpage Yet Another JSON Library (YAJL)
\author Lloyd Hilaiel
- \date 2007-2008
+ \date 2007-2009
Yet Another JSON Library (YAJL) is a small event-driven (SAX-style)
JSON parser written in ANSI C, and a small validating JSON
View
37 src/yajl.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,6 +33,7 @@
#include "api/yajl_parse.h"
#include "yajl_lex.h"
#include "yajl_parser.h"
+#include "yajl_alloc.h"
#include <stdlib.h>
#include <string.h>
@@ -62,11 +63,29 @@ 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,
void * ctx)
{
unsigned int allowComments = 0;
unsigned int validateUTF8 = 0;
- yajl_handle hand = (yajl_handle) malloc(sizeof(struct yajl_handle_t));
+ yajl_handle hand = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ hand = (yajl_handle) YA_MALLOC(afs, sizeof(struct yajl_handle_t));
+
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(hand->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
if (config != NULL) {
allowComments = config->allowComments;
@@ -75,10 +94,10 @@ yajl_alloc(const yajl_callbacks * callbacks,
hand->callbacks = callbacks;
hand->ctx = ctx;
- hand->lexer = yajl_lex_alloc(allowComments, validateUTF8);
+ hand->lexer = yajl_lex_alloc(&(hand->alloc), allowComments, validateUTF8);
hand->errorOffset = 0;
- hand->decodeBuf = yajl_buf_alloc();
- hand->stateBuf = yajl_buf_alloc();
+ hand->decodeBuf = yajl_buf_alloc(&(hand->alloc));
+ hand->stateBuf = yajl_buf_alloc(&(hand->alloc));
yajl_state_push(hand, yajl_state_start);
@@ -91,7 +110,7 @@ yajl_free(yajl_handle handle)
yajl_buf_free(handle->stateBuf);
yajl_buf_free(handle->decodeBuf);
yajl_lex_free(handle->lexer);
- free(handle);
+ YA_FREE(&(handle->alloc), handle);
}
yajl_status
@@ -124,10 +143,10 @@ yajl_get_error(yajl_handle hand, int verbose,
}
void
-yajl_free_error(unsigned char * str)
+yajl_free_error(yajl_handle hand, unsigned char * str)
{
- /* XXX: use memory allocation functions if set */
- free(str);
+ /* use memory allocation functions if set */
+ YA_FREE(&(hand->alloc), str);
}
/* XXX: add utility routines to parse from file */
View
65 src/yajl_alloc.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#include "yajl_alloc.h"
+#include <stdlib.h>
+
+static void * yajl_internal_malloc(void *ctx, unsigned int sz)
+{
+ return malloc(sz);
+}
+
+static void * yajl_internal_realloc(void *ctx, void * previous,
+ unsigned int sz)
+{
+ return realloc(previous, sz);
+}
+
+static void yajl_internal_free(void *ctx, void * ptr)
+{
+ free(ptr);
+}
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf)
+{
+ yaf->malloc = yajl_internal_malloc;
+ yaf->free = yajl_internal_free;
+ yaf->realloc = yajl_internal_realloc;
+ yaf->ctx = NULL;
+}
+
View
50 src/yajl_alloc.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2007-2009, Lloyd Hilaiel.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. Neither the name of Lloyd Hilaiel nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * \file yajl_alloc.h
+ * default memory allocation routines for yajl which use malloc/realloc and
+ * free
+ */
+
+#ifndef __YAJL_ALLOC_H__
+#define __YAJL_ALLOC_H__
+
+#include "api/yajl_common.h"
+
+#define YA_MALLOC(afs, sz) (afs)->malloc((afs)->ctx, (sz))
+#define YA_FREE(afs, ptr) (afs)->free((afs)->ctx, (ptr))
+#define YA_REALLOC(afs, ptr, sz) (afs)->realloc((afs)->ctx, (ptr), (sz))
+
+void yajl_set_default_alloc_funcs(yajl_alloc_funcs * yaf);
+
+#endif
View
18 src/yajl_buf.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -42,6 +42,7 @@ struct yajl_buf_t {
unsigned int len;
unsigned int used;
unsigned char * data;
+ yajl_alloc_funcs * alloc;
};
static
@@ -54,7 +55,7 @@ void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
/* first call */
if (buf->data == NULL) {
buf->len = YAJL_BUF_INIT_SIZE;
- buf->data = (unsigned char *) malloc(buf->len);
+ buf->data = (unsigned char *) YA_MALLOC(buf->alloc, buf->len);
buf->data[0] = 0;
}
@@ -63,21 +64,24 @@ void yajl_buf_ensure_available(yajl_buf buf, unsigned int want)
while (want >= (need - buf->used)) need <<= 1;
if (need != buf->len) {
- buf->data = (unsigned char *) realloc(buf->data, need);
+ buf->data = (unsigned char *) YA_REALLOC(buf->alloc, buf->data, need);
buf->len = need;
}
}
-yajl_buf yajl_buf_alloc(void)
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc)
{
- return (yajl_buf) calloc(1, sizeof(struct yajl_buf_t));
+ yajl_buf b = YA_MALLOC(alloc, sizeof(struct yajl_buf_t));
+ memset((void *) b, 0, sizeof(struct yajl_buf_t));
+ b->alloc = alloc;
+ return b;
}
void yajl_buf_free(yajl_buf buf)
{
assert(buf != NULL);
- if (buf->data) free(buf->data);
- free(buf);
+ if (buf->data) YA_FREE(buf->alloc, buf->data);
+ YA_FREE(buf->alloc, buf);
}
void yajl_buf_append(yajl_buf buf, const void * data, unsigned int len)
View
7 src/yajl_buf.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,6 +33,9 @@
#ifndef __YAJL_BUF_H__
#define __YAJL_BUF_H__
+#include "api/yajl_common.h"
+#include "yajl_alloc.h"
+
/**
* yajl_buf is a buffer with exponential growth. the buffer ensures that
* you are always null padded.
@@ -40,7 +43,7 @@
typedef struct yajl_buf_t * yajl_buf;
/* allocate a new buffer */
-yajl_buf yajl_buf_alloc(void);
+yajl_buf yajl_buf_alloc(yajl_alloc_funcs * alloc);
/* free the buffer */
void yajl_buf_free(yajl_buf buf);
View
2  src/yajl_encode.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
View
2  src/yajl_encode.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
View
31 src/yajl_gen.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -56,18 +56,39 @@ struct yajl_gen_t
const char * indentString;
yajl_gen_state state[YAJL_MAX_DEPTH];
yajl_buf buf;
+ /* memory allocation routines */
+ yajl_alloc_funcs alloc;
};
yajl_gen
-yajl_gen_alloc(const yajl_gen_config * config)
+yajl_gen_alloc(const yajl_gen_config * config,
+ const yajl_alloc_funcs * afs)
{
- yajl_gen g = (yajl_gen) malloc(sizeof(struct yajl_gen_t));
+ yajl_gen g = NULL;
+ yajl_alloc_funcs afsBuffer;
+
+ /* first order of business is to set up memory allocation routines */
+ if (afs != NULL) {
+ if (afs->malloc == NULL || afs->realloc == NULL || afs->free == NULL)
+ {
+ return NULL;
+ }
+ } else {
+ yajl_set_default_alloc_funcs(&afsBuffer);
+ afs = &afsBuffer;
+ }
+
+ g = (yajl_gen) YA_MALLOC(afs, sizeof(struct yajl_gen_t));
memset((void *) g, 0, sizeof(struct yajl_gen_t));
+ /* copy in pointers to allocation routines */
+ memcpy((void *) &(g->alloc), (void *) afs, sizeof(yajl_alloc_funcs));
+
if (config) {
g->pretty = config->beautify;
g->indentString = config->indentString ? config->indentString : " ";
}
- g->buf = yajl_buf_alloc();
+ g->buf = yajl_buf_alloc(&(g->alloc));
+
return g;
}
@@ -75,7 +96,7 @@ void
yajl_gen_free(yajl_gen g)
{
yajl_buf_free(g->buf);
- free(g);
+ YA_FREE(&(g->alloc), g);
}
#define INSERT_SEP \
View
15 src/yajl_lex.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -105,6 +105,8 @@ struct yajl_lexer_t {
/* shall we validate utf8 inside strings? */
unsigned int validateUTF8;
+
+ yajl_alloc_funcs * alloc;
};
static unsigned char
@@ -127,12 +129,15 @@ unreadChar(yajl_lexer lxr, unsigned int *off)
}
yajl_lexer
-yajl_lex_alloc(unsigned int allowComments, unsigned int validateUTF8)
+yajl_lex_alloc(yajl_alloc_funcs * alloc,
+ unsigned int allowComments, unsigned int validateUTF8)
{
- yajl_lexer lxr = (yajl_lexer) calloc(1, sizeof(struct yajl_lexer_t));
- lxr->buf = yajl_buf_alloc();
+ yajl_lexer lxr = (yajl_lexer) YA_MALLOC(alloc, sizeof(struct yajl_lexer_t));
+ memset((void *) lxr, 0, sizeof(struct yajl_lexer_t));
+ lxr->buf = yajl_buf_alloc(alloc);
lxr->allowComments = allowComments;
lxr->validateUTF8 = validateUTF8;
+ lxr->alloc = alloc;
return lxr;
}
@@ -140,7 +145,7 @@ void
yajl_lex_free(yajl_lexer lxr)
{
yajl_buf_free(lxr->buf);
- free(lxr);
+ YA_FREE(lxr->alloc, lxr);
return;
}
View
7 src/yajl_lex.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -33,6 +33,8 @@
#ifndef __YAJL_LEX_H__
#define __YAJL_LEX_H__
+#include "api/yajl_common.h"
+
typedef enum {
yajl_tok_bool,
yajl_tok_colon,
@@ -61,7 +63,8 @@ typedef enum {
typedef struct yajl_lexer_t * yajl_lexer;
-yajl_lexer yajl_lex_alloc(unsigned int allowComments,
+yajl_lexer yajl_lex_alloc(yajl_alloc_funcs * alloc,
+ unsigned int allowComments,
unsigned int validateUTF8);
void yajl_lex_free(yajl_lexer lexer);
View
13 src/yajl_parser.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -71,7 +71,7 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
memneeded += strlen(": ");
memneeded += strlen(errorText);
}
- str = (unsigned char *) malloc(memneeded + 2);
+ str = (unsigned char *) YA_MALLOC(&(hand->alloc), memneeded + 2);
str[0] = 0;
strcat((char *) str, errorType);
strcat((char *) str, " error");
@@ -108,14 +108,15 @@ yajl_render_error_string(yajl_handle hand, const unsigned char * jsonText,
text[i++] = '\n';
text[i] = 0;
{
- char * newStr = (char *) malloc(strlen((char *) str) +
- strlen((char *) text) +
- strlen(arrow) + 1);
+ 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);
- free(str);
+ YA_FREE(&(hand->alloc), str);
str = (unsigned char *) newStr;
}
}
View
4 src/yajl_parser.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -61,6 +61,8 @@ struct yajl_handle_t {
yajl_buf decodeBuf;
/* a stack of states. access with yajl_state_XXX routines */
yajl_buf stateBuf;
+ /* memory allocation routines */
+ yajl_alloc_funcs alloc;
};
yajl_status
View
2  test/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
View
1  test/cases/array.json.gold
@@ -19,3 +19,4 @@ array close ']'
string: '
\'
array close ']'
+memory leaks: 0
View
1  test/cases/array_close.json.gold
@@ -1 +1,2 @@
parse error: unallowed token at this point in JSON text
+memory leaks: 0
View
1  test/cases/array_open.json.gold
@@ -1 +1,2 @@
array open '['
+memory leaks: 0
View
1  test/cases/bogus_char.json.gold
@@ -7,3 +7,4 @@ string: 'be'
string: 'a happy bit of json'
string: 'but someone, misspelled "true"'
lexical error: invalid string in json text.
+memory leaks: 0
View
1  test/cases/codepoints_from_unicode_org.json.gold
@@ -1 +1,2 @@
string: 'Mа二𐌂'
+memory leaks: 0
View
1  test/cases/dc_simple_with_comments.json.gold
@@ -2,3 +2,4 @@ map open '{'
key: 'this'
string: 'is'
lexical error: probable comment found in input text, comments are not enabled.
+memory leaks: 0
View
1  test/cases/deep_arrays.json.gold
@@ -2046,3 +2046,4 @@ array close ']'
array close ']'
array close ']'
array close ']'
+memory leaks: 0
View
1  test/cases/difficult_json_c_test_case.json.gold
@@ -33,3 +33,4 @@ array close ']'
map close '}'
map close '}'
map close '}'
+memory leaks: 0
View
1  test/cases/difficult_json_c_test_case_with_comments.json.gold
@@ -33,3 +33,4 @@ array close ']'
map close '}'
map close '}'
map close '}'
+memory leaks: 0
View
1  test/cases/doubles.json.gold
@@ -4,3 +4,4 @@ double: 10
double: 3.14157
double: 1000
array close ']'
+memory leaks: 0
View
1  test/cases/empty_array.json.gold
@@ -1,2 +1,3 @@
array open '['
array close ']'
+memory leaks: 0
View
1  test/cases/empty_string.json.gold
@@ -1 +1,2 @@
string: ''
+memory leaks: 0
View
1  test/cases/escaped_bulgarian.json.gold
@@ -4,3 +4,4 @@ string: 'Му'
string: 'Еба'
string: 'Майката'
array close ']'
+memory leaks: 0
View
1  test/cases/escaped_foobar.json.gold
@@ -1 +1,2 @@
string: 'foobar'
+memory leaks: 0
View
1  test/cases/false.json.gold
@@ -1 +1,2 @@
bool: false
+memory leaks: 0
View
1  test/cases/false_then_garbage.json.gold
@@ -1 +1,2 @@
bool: false
+memory leaks: 0
View
1  test/cases/integers.json.gold
@@ -11,3 +11,4 @@ integer: -123456789
integer: 2147483647
integer: -2147483647
parse error: integer overflow
+memory leaks: 0
View
1  test/cases/invalid_utf8.json.gold
@@ -1,2 +1,3 @@
array open '['
lexical error: invalid bytes in UTF8 string.
+memory leaks: 0
View
1  test/cases/isolated_surrogate_marker.json.gold
@@ -1 +1,2 @@
string: '?'
+memory leaks: 0
View
1  test/cases/leading_zero_in_number.json.gold
@@ -2,3 +2,4 @@ map open '{'
key: 'bad thing'
integer: 0
parse error: after key and value, inside map, I expect ',' or '}'
+memory leaks: 0
View
1  test/cases/lonely_minus_sign.json.gold
@@ -6,3 +6,4 @@ string: 'blue'
string: 'baby where are you?'
string: 'oh boo hoo!'
lexical error: malformed number, a digit is required after the minus sign.
+memory leaks: 0
View
1  test/cases/lonely_number.json.gold
@@ -1 +1,2 @@
integer: 123456789
+memory leaks: 0
View
1  test/cases/map_close.json.gold
@@ -1 +1,2 @@
parse error: unallowed token at this point in JSON text
+memory leaks: 0
View
1  test/cases/map_open.json.gold
@@ -1 +1,2 @@
map open '{'
+memory leaks: 0
View
1  test/cases/missing_integer_after_decimal_point.json.gold
@@ -1 +1,2 @@
lexical error: malformed number, a digit is required after the decimal point.
+memory leaks: 0
View
1  test/cases/missing_integer_after_exponent.json.gold
@@ -1 +1,2 @@
lexical error: malformed number, a digit is required after the exponent.
+memory leaks: 0
View
1  test/cases/non_utf8_char_in_string.json.gold
@@ -5,3 +5,4 @@ key: 'CoreletType'
string: 'standalone'
key: 'documentation'
lexical error: invalid bytes in UTF8 string.
+memory leaks: 0
View
1  test/cases/null.json.gold
@@ -1 +1,2 @@
null
+memory leaks: 0
View
1  test/cases/null_then_garbage.json.gold
@@ -1 +1,2 @@
null
+memory leaks: 0
View
1  test/cases/nulls_and_bools.json.gold
@@ -6,3 +6,4 @@ bool: false
key: 'null'
null
map close '}'
+memory leaks: 0
View
1  test/cases/simple.json.gold
@@ -6,3 +6,4 @@ string: 'simple'
key: 'json'
string: 'right?'
map close '}'
+memory leaks: 0
View
1  test/cases/simple_with_comments.json.gold
@@ -6,3 +6,4 @@ string: 'simple'
key: 'json'
string: 'right?'
map close '}'
+memory leaks: 0
View
1  test/cases/string_invalid_escape.json.gold
@@ -1,2 +1,3 @@
array open '['
lexical error: inside a string, '\' occurs before a character which it may not.
+memory leaks: 0
View
1  test/cases/string_invalid_hex_char.json.gold
@@ -1 +1,2 @@
lexical error: invalid (non-hex) character occurs after '\u' inside string.
+memory leaks: 0
View
1  test/cases/string_with_escapes.json.gold
@@ -4,3 +4,4 @@ string: '
string: '"and this string has an escape at the beginning'
string: 'and this string has no escapes'
array close ']'
+memory leaks: 0
View
1  test/cases/string_with_invalid_newline.json.gold
@@ -1 +1,2 @@
lexical error: invalid character inside string.
+memory leaks: 0
View
1  test/cases/true.json.gold
@@ -1 +1,2 @@
bool: true
+memory leaks: 0
View
1  test/cases/true_then_garbage.json.gold
@@ -1 +1,2 @@
bool: true
+memory leaks: 0
View
1  test/cases/unescaped_bulgarian.json.gold
@@ -1,3 +1,4 @@
array open '['
string: 'Да Му Еба Майката'
array close ']'
+memory leaks: 0
View
73 test/yajl_test.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -37,6 +37,48 @@
#include <stdlib.h>
#include <string.h>
+#include <assert.h>
+
+/* memory debugging routines */
+typedef struct
+{
+ unsigned int numFrees;
+ unsigned int numMallocs;
+ /* XXX: we really need a hash table here with per-allocation
+ * information */
+} yajlTestMemoryContext;
+
+/* cast void * into context */
+#define TEST_CTX(vptr) ((yajlTestMemoryContext *) (vptr))
+
+static void yajlTestFree(void * ctx, void * ptr)
+{
+ assert(ptr != NULL);
+ TEST_CTX(ctx)->numFrees++;
+ free(ptr);
+}
+
+static void * yajlTestMalloc(void * ctx, unsigned int sz)
+{
+ assert(sz != 0);
+ TEST_CTX(ctx)->numMallocs++;
+ return malloc(sz);
+}
+
+static void * yajlTestRealloc(void * ctx, void * ptr, unsigned int sz)
+{
+ if (ptr == NULL) {
+ assert(sz != 0);
+ TEST_CTX(ctx)->numMallocs++;
+ } else if (sz == 0) {
+ TEST_CTX(ctx)->numFrees++;
+ }
+
+ return realloc(ctx, sz);
+}
+
+
+/* begin parsing callback routines */
#define BUF_SIZE 2048
static int test_yajl_null(void *ctx)
@@ -144,6 +186,21 @@ main(int argc, char ** argv)
yajl_parser_config cfg = { 0, 1 };
int i, j, done;
+ /* memory allocation debugging: allocate a structure which collects
+ * statistics */
+ yajlTestMemoryContext memCtx = { 0,0 };
+
+ /* memory allocation debugging: allocate a structure which holds
+ * allocation routines */
+ yajl_alloc_funcs allocFuncs = {
+ yajlTestMalloc,
+ yajlTestRealloc,
+ yajlTestFree,
+ (void *) NULL
+ };
+
+ allocFuncs.ctx = (void *) &memCtx;
+
/* check arguments. We expect exactly one! */
for (i=1;i<argc;i++) {
if (!strcmp("-c", argv[i])) {
@@ -183,7 +240,7 @@ main(int argc, char ** argv)
fileName = argv[argc-1];
/* ok. open file. let's read and parse */
- hand = yajl_alloc(&callbacks, &cfg, NULL);
+ hand = yajl_alloc(&callbacks, &cfg, &allocFuncs, NULL);
done = 0;
while (!done) {
@@ -210,7 +267,7 @@ main(int argc, char ** argv)
unsigned char * str = yajl_get_error(hand, 0, fileData, rd);
fflush(stdout);
fprintf(stderr, (char *) str);
- yajl_free_error(str);
+ yajl_free_error(hand, str);
break;
}
}
@@ -218,5 +275,15 @@ main(int argc, char ** argv)
yajl_free(hand);
free(fileData);
+ /* finally, print out some memory statistics */
+
+/* (lth) only print leaks here, as allocations and frees may vary depending
+ * on read buffer size, causing false failures.
+ *
+ * printf("allocations:\t%u\n", memCtx.numMallocs);
+ * printf("frees:\t\t%u\n", memCtx.numFrees);
+*/
+ printf("memory leaks:\t%u\n", memCtx.numMallocs - memCtx.numFrees);
+
return 0;
}
View
2  verify/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright 2007, Lloyd Hilaiel.
+# Copyright 2007-2009, Lloyd Hilaiel.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
View
6 verify/json_verify.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2007, Lloyd Hilaiel.
+ * Copyright 2007-2009, Lloyd Hilaiel.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -80,7 +80,7 @@ main(int argc, char ** argv)
}
/* allocate a parser */
- hand = yajl_alloc(NULL, &cfg, NULL);
+ hand = yajl_alloc(NULL, &cfg, NULL, NULL);
while (!done) {
rd = fread((void *) fileData, 1, sizeof(fileData) - 1, stdin);
@@ -112,7 +112,7 @@ main(int argc, char ** argv)
if (!quiet) {
unsigned char * str = yajl_get_error(hand, 1, fileData, rd);
fprintf(stderr, (const char *) str);
- yajl_free_error(str);
+ yajl_free_error(hand, str);
}
retval = 1;
break;
Please sign in to comment.
Something went wrong with that request. Please try again.