summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy J. Wood <tjw@omnigroup.com>2009-02-26 13:41:46 -0800
committerTimothy J. Wood <tjw@omnigroup.com>2009-02-26 13:41:46 -0800
commit1a7a73039abf621af36f73adf4a4ca77c2c94bd9 (patch)
treee7ea2f80377f3dcb2c80bfc2a9b53c5332ec29b6
parentd4d5f5af2cc52d7b8c92fc2a57f18e38d1f6f5d2 (diff)
downloadyajl-1a7a73039abf621af36f73adf4a4ca77c2c94bd9.tar.gz
A simple fix for lonely_number.json
- Add new parser function, yajl_parse_complete(). This is defined to parse any buffered data assuming that there is no more input forthcoming and may issue callbacks based on that parse. - Implement this as parsing a single space character. This is sufficient to handle the problem case, a number at the end of the stream. - Updated yagl_test.c to call this when the stream ends.
-rw-r--r--src/api/yajl_parse.h11
-rw-r--r--src/yajl.c12
-rw-r--r--test/yajl_test.c31
3 files changed, 42 insertions, 12 deletions
diff --git a/src/api/yajl_parse.h b/src/api/yajl_parse.h
index a6d5b1a..6f6dba3 100644
--- a/src/api/yajl_parse.h
+++ b/src/api/yajl_parse.h
@@ -143,6 +143,17 @@ extern "C" {
const unsigned char * jsonText,
unsigned int jsonTextLength);
+ /** Parse any remaining buffered json.
+ * Since yajl is a stream-based parser, without an explicit end of
+ * input, yajl sometimes can't decide if content at the end of the
+ * stream is valid or not. For example, if "1" has been fed in,
+ * yajl can't know whether another digit is next or some character
+ * that would terminate the integer token.
+ *
+ * \param hand - a handle to the json parser allocated with yajl_alloc
+ */
+ yajl_status yajl_parse_complete(yajl_handle hand);
+
/** get an error string describing the state of the
* parse.
*
diff --git a/src/yajl.c b/src/yajl.c
index 4ed4ef5..4993b62 100644
--- a/src/yajl.c
+++ b/src/yajl.c
@@ -104,6 +104,18 @@ yajl_parse(yajl_handle hand, const unsigned char * jsonText,
return status;
}
+yajl_status
+yajl_parse_complete(yajl_handle hand)
+{
+ /* The particular case we want to handle is a trailing number.
+ * Further input consisting of digits could cause our interpretation
+ * of the number to change (buffered "1" but "2" comes in).
+ * A very simple approach to this is to inject whitespace to terminate
+ * any number in the lex buffer.
+ */
+ return yajl_parse(hand, (const unsigned char *)" ", 1);
+}
+
unsigned char *
yajl_get_error(yajl_handle hand, int verbose,
const unsigned char * jsonText, unsigned int jsonTextLen)
diff --git a/test/yajl_test.c b/test/yajl_test.c
index 35bcc9d..5f1dd31 100644
--- a/test/yajl_test.c
+++ b/test/yajl_test.c
@@ -185,26 +185,33 @@ main(int argc, char ** argv)
/* ok. open file. let's read and parse */
hand = yajl_alloc(&callbacks, &cfg, NULL);
- for(;;) {
+ int done = 0;
+ while (!done) {
rd = fread((void *) fileData, 1, bufSize, stdin);
if (rd == 0) {
if (!feof(stdin)) {
fprintf(stderr, "error reading from '%s'\n", fileName);
+ break;
}
- break;
- } else {
+ 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, (char *) str);
- yajl_free_error(str);
- break;
- }
+
+ if (stat != yajl_status_insufficient_data &&
+ stat != yajl_status_ok)
+ {
+ unsigned char * str = yajl_get_error(hand, 0, fileData, rd);
+ fflush(stdout);
+ fprintf(stderr, (char *) str);
+ yajl_free_error(str);
+ break;
}
}