Convert to C api.
--- a/Makefile Sat Oct 06 21:08:55 2012 -0400
+++ b/Makefile Sun Oct 07 14:30:52 2012 -0400
@@ -1,6 +1,7 @@
all: tests
-CC=g++
+clean:
+ rm -f *.o tests
tests: tests.o jsonsax.o
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jsonsax.c Sun Oct 07 14:30:52 2012 -0400
@@ -0,0 +1,341 @@
+/*
+Copyright (c) Fabien Ninoles <fabien@tzone.org>
+All rights reserved.
+
+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 the University 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+*/
+
+#include "jsonsax.h"
+
+#include <assert.h>
+
+#define CASE_IS_SPACE \
+ case ' ': \
+case '\n': \
+case '\t': \
+case '\r'
+
+#define CASE_IS_DIGIT \
+ case '0': \
+case '1': \
+case '2': \
+case '3': \
+case '4': \
+case '5': \
+case '6': \
+case '7': \
+case '8': \
+case '9'
+
+
+struct _jsonsax_state
+{
+ struct jsonsax_backend m_backend;
+ char m_lastchar;
+ void* m_data;
+};
+
+#define JSONSAX_GETCHAR(state) \
+ (state)->m_backend.m_getchar((state)->m_data)
+#define JSONSAX_ONERROR(state, err) \
+ (state)->m_backend.m_onerror((state)->m_data, err)
+#define JSONSAX_ONSTART(state,type) \
+ (state)->m_backend.m_onstart((state)->m_data, type)
+#define JSONSAX_ONSTOP(state,type) \
+ (state)->m_backend.m_onstop((state)->m_data, type)
+
+static int jsonsax_parsevalue(struct _jsonsax_state* state);
+
+static int _jsonsax_getc(struct _jsonsax_state* state)
+{
+ int c = JSONSAX_GETCHAR(state);
+ if (c > 0)
+ {
+ state->m_lastchar = c;
+ return 0;
+ };
+ return -1;
+}
+
+static int _jsonsax_trim(struct _jsonsax_state* state)
+{
+ do
+ {
+ switch(state->m_lastchar)
+ {
+ CASE_IS_SPACE:
+ break;
+ default:
+ return 0;
+ }
+ }
+ while(_jsonsax_getc(state) == 0);
+ return -1;
+}
+
+static int jsonsax_getc(struct _jsonsax_state* state)
+{
+ int err = _jsonsax_getc(state);
+ if (err == 0)
+ {
+ return _jsonsax_trim(state);
+ }
+ return err;
+}
+
+int jsonsax_parsearray(struct _jsonsax_state* state)
+{
+ assert(state->m_lastchar == '[');
+ int err = jsonsax_getc(state);
+ if (err != 0) return err;
+ while(jsonsax_parsevalue(state))
+ {
+ switch(state->m_lastchar)
+ {
+ case ',':
+ jsonsax_getc(state);
+ break;
+ case ']':
+ JSONSAX_ONSTOP(state, EJSONSAX_ARRAY);
+ jsonsax_getc(state);
+ return 0;
+ default:
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ }
+ if (state->m_lastchar != ']')
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ JSONSAX_ONSTOP(state, EJSONSAX_ARRAY);
+ jsonsax_getc(state);
+ return 0;
+}
+
+int jsonsax_parsestring(struct _jsonsax_state* state)
+{
+ assert(state->m_lastchar == '"');
+ JSONSAX_ONSTART(state, EJSONSAX_STRING);
+ while(jsonsax_getc(state) == 0)
+ {
+ switch(state->m_lastchar)
+ {
+ case '\\':
+ jsonsax_getc(state);
+ break;
+ case '"':
+ JSONSAX_ONSTOP(state, EJSONSAX_STRING);
+ jsonsax_getc(state);
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int jsonsax_parsenumber(struct _jsonsax_state* state)
+{
+ assert(state->m_lastchar == '-' ||
+ state->m_lastchar == '0' ||
+ state->m_lastchar == '1' ||
+ state->m_lastchar == '2' ||
+ state->m_lastchar == '3' ||
+ state->m_lastchar == '4' ||
+ state->m_lastchar == '5' ||
+ state->m_lastchar == '6' ||
+ state->m_lastchar == '7' ||
+ state->m_lastchar == '8' ||
+ state->m_lastchar == '9');
+
+ JSONSAX_ONSTART(state, EJSONSAX_NUMBER);
+ while(jsonsax_getc(state) == 0)
+ {
+ switch(state->m_lastchar)
+ {
+ // TODO: lookup for correct number format.
+ case 'e':
+ case '-':
+ case '.':
+ CASE_IS_DIGIT:
+ break;
+ default:
+ JSONSAX_ONSTOP(state, EJSONSAX_NUMBER);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int jsonsax_parseconstant(struct _jsonsax_state* state,
+ const char* constant,
+ enum EJSONSAX_TYPE etype)
+{
+ assert(state->m_lastchar == constant[0]);
+ ++constant;
+ while(jsonsax_getc(state) == 0)
+ {
+ if (*constant == '\0') break;
+ if (*constant != state->m_lastchar) break;
+ constant++;
+ }
+
+ if (*constant == '\0')
+ {
+ JSONSAX_ONSTOP(state, etype);
+ return 0;
+ }
+ else
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+}
+
+int jsonsax_parsenull(struct _jsonsax_state* state)
+{
+ return jsonsax_parseconstant(state, "null", EJSONSAX_NULL);
+}
+
+int jsonsax_parsetrue(struct _jsonsax_state* state)
+{
+ return jsonsax_parseconstant(state, "true", EJSONSAX_TRUE);
+}
+
+int jsonsax_parsefalse(struct _jsonsax_state* state)
+{
+ return jsonsax_parseconstant(state, "false", EJSONSAX_FALSE);
+}
+
+int jsonsax_parsepair(struct _jsonsax_state* state)
+{
+ if (state->m_lastchar != '"')
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ if (jsonsax_parsestring(state) != 0)
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ if (state->m_lastchar != ':')
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ if (jsonsax_getc(state) != 0)
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ return jsonsax_parsevalue(state);
+}
+
+static int jsonsax_parseobject(struct _jsonsax_state* state)
+{
+ assert(state->m_lastchar == '{');
+ JSONSAX_ONSTART(state, EJSONSAX_OBJECT);
+ jsonsax_getc(state);
+ while(jsonsax_parsepair(state) == 0)
+ {
+ switch(state->m_lastchar)
+ {
+ case ',':
+ jsonsax_getc(state);
+ break;
+ case '}':
+ JSONSAX_ONSTOP(state, EJSONSAX_OBJECT);
+ jsonsax_getc(state);
+ return 0;
+ default:
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ }
+ if (state->m_lastchar != '}')
+ {
+ JSONSAX_ONERROR(state, -1);
+ return -1;
+ }
+ JSONSAX_ONSTOP(state, EJSONSAX_OBJECT);
+ jsonsax_getc(state);
+ return 0;
+}
+
+static int jsonsax_parsevalue(struct _jsonsax_state* state)
+{
+ switch(state->m_lastchar)
+ {
+ case '[':
+ return jsonsax_parsearray(state);
+ case '{':
+ return jsonsax_parseobject(state);
+ case '"':
+ return jsonsax_parsestring(state);
+ case '-':
+ CASE_IS_DIGIT:
+ return jsonsax_parsenumber(state);
+ case 'n':
+ return jsonsax_parsenull(state);
+ case 't':
+ return jsonsax_parsetrue(state);
+ case 'f':
+ return jsonsax_parsefalse(state);
+ default:
+ return -1;
+ }
+}
+
+static int default_onevent(void* data, enum EJSONSAX_TYPE type)
+{
+ return 0;
+}
+
+static void default_onerror(void* data, int error)
+{
+ (void)data;
+ (void)error;
+}
+
+int jsonsax_parse(struct jsonsax_backend* backend, void* data)
+{
+ assert(backend != 0);
+ assert(backend->m_getchar != 0);
+ struct _jsonsax_state state;
+ state.m_backend.m_getchar = backend->m_getchar;
+ state.m_backend.m_onstart = backend->m_onstart ? backend->m_onstart : default_onevent;
+ state.m_backend.m_onstop = backend->m_onstop ? backend->m_onstop : default_onevent;
+ state.m_backend.m_onerror = backend->m_onerror ? backend->m_onerror : default_onerror;
+ state.m_data = data;
+ state.m_lastchar = '\0';
+ int err = jsonsax_getc(&state);
+ if (err != 0) return err;
+ err = jsonsax_parsevalue(&state);
+ return err;
+}
+
+#undef CASE_IS_DIGIT
+#undef CASE_IS_SPACE
--- a/jsonsax.cpp Sat Oct 06 21:08:55 2012 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,276 +0,0 @@
-#include "jsonsax.hpp"
-
-#include <assert.h>
-
-#define CASE_IS_SPACE \
- case ' ': \
-case '\n': \
-case '\t': \
-case '\r'
-
-#define CASE_IS_DIGIT \
- case '0': \
-case '1': \
-case '2': \
-case '3': \
-case '4': \
-case '5': \
-case '6': \
-case '7': \
-case '8': \
-case '9'
-
-JSLXParser::JSLXParser(IJSLXBackend* pBackend)
- : m_pBackend(pBackend)
-{}
-bool JSLXParser::Parse()
-{
- return GetNextChar() && ParseValue();
-}
-
-bool JSLXParser::_GetNextChar()
-{
- if (!m_pBackend->Eof())
- {
- m_lastChar = m_pBackend->GetChar();
- return true;
- }
- return false;
-}
-
-bool JSLXParser::TrimWhiteSpace()
-{
- do
- {
- switch(m_lastChar)
- {
- CASE_IS_SPACE:
- break;
- default:
- return true;
- }
- }
- while(_GetNextChar());
- return false;
-}
-
-bool JSLXParser::GetNextChar(bool trim /* = true */)
-{
- if (trim)
- {
- return _GetNextChar() && TrimWhiteSpace();
- }
- return _GetNextChar();
-}
-
-bool JSLXParser::ParseValue()
-{
- switch(m_lastChar)
- {
- case '[':
- return ParseArray();
- case '{':
- return ParseObject();
- case '"':
- return ParseString();
- case '-':
- CASE_IS_DIGIT:
- return ParseNumber();
- case 'n':
- return ParseNull();
- case 't':
- return ParseTrue();
- case 'f':
- return ParseFalse();
- default:
- return false;
- }
-}
-
-bool JSLXParser::ParseObject()
-{
- assert(m_lastChar == '{');
- m_pBackend->OnStartObject();
- GetNextChar();
- while(ParsePair())
- {
- switch(m_lastChar)
- {
- case ',':
- GetNextChar();
- break;
- case '}':
- m_pBackend->OnStopObject();
- GetNextChar();
- return true;
- default:
- m_pBackend->OnError("ParseObject: invalid char");
- return false;
- }
- }
- if (m_lastChar != '}')
- {
- m_pBackend->OnError("ParseObject: invalid char");
- return false;
- }
- m_pBackend->OnStopObject();
- GetNextChar();
- return true;
-}
-
-bool JSLXParser::ParsePair()
-{
- if (m_lastChar != '"')
- {
- m_pBackend->OnError("ParsePair: Invalid Key");
- return false;
- }
- if (!ParseString())
- {
- m_pBackend->OnError("ParsePair: Invalid Key");
- return false;
- }
- if (m_lastChar != ':')
- {
- m_pBackend->OnError("ParsePair: Missing pair separator");
- return false;
- }
- if (!GetNextChar())
- {
- m_pBackend->OnError("ParsePair: Missing value");
- return false;
- }
- return ParseValue();
-}
-
-bool JSLXParser::ParseArray()
-{
- assert(m_lastChar == '[');
- if (!GetNextChar()) return false;
- while(ParseValue())
- {
- switch(m_lastChar)
- {
- case ',':
- GetNextChar();
- break;
- case ']':
- m_pBackend->OnStopArray();
- GetNextChar();
- return true;
- default:
- m_pBackend->OnError("ParseArray: Missing seperator in array");
- return false;
- }
- }
- if (m_lastChar != ']')
- {
- m_pBackend->OnError("ParseArray: Bad value in array");
- return false;
- }
- m_pBackend->OnStopArray();
- GetNextChar();
- return true;
-}
-
-bool JSLXParser::ParseString()
-{
- assert(m_lastChar == '"');
- m_pBackend->OnStartString();
- while(GetNextChar())
- {
- switch(m_lastChar)
- {
- case '\\':
- GetNextChar();
- break;
- case '"':
- m_pBackend->OnStopString();
- GetNextChar();
- return true;
- }
- }
- return false;
-}
-
-bool JSLXParser::ParseNumber()
-{
- assert(m_lastChar == '-' ||
- m_lastChar == '0' ||
- m_lastChar == '1' ||
- m_lastChar == '2' ||
- m_lastChar == '3' ||
- m_lastChar == '4' ||
- m_lastChar == '5' ||
- m_lastChar == '6' ||
- m_lastChar == '7' ||
- m_lastChar == '8' ||
- m_lastChar == '9');
-
- m_pBackend->OnStartNumber();
- while(GetNextChar())
- {
- switch(m_lastChar)
- {
- // TODO: lookup for correct number format.
- case 'e':
- case '-':
- case '.':
- CASE_IS_DIGIT:
- break;
- default:
- m_pBackend->OnStopNumber();
- return true;
- }
- }
- return true;
-}
-
-bool JSLXParser::ParseNull()
-{
- if (ParseConstant("null"))
- {
- m_pBackend->OnNull();
- return true;
- }
- return false;
-}
-
-bool JSLXParser::ParseTrue()
-{
- if (ParseConstant("true"))
- {
- m_pBackend->OnTrue();
- return true;
- }
- return false;
-}
-
-bool JSLXParser::ParseFalse()
-{
- if (ParseConstant("false"))
- {
- m_pBackend->OnFalse();
- return true;
- }
- return false;
-}
-
-bool JSLXParser::ParseConstant(const char* constant)
-{
- assert(m_lastChar == constant[0]);
- ++constant;
- while(GetNextChar())
- {
- if (*constant == '\0')
- return true;
- if (*constant != m_lastChar)
- return false;
- constant++;
- }
- return *constant == '\0';
-}
-
-#undef CASE_IS_DIGIT
-#undef CASE_IS_SPACE
-
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jsonsax.h Sun Oct 07 14:30:52 2012 -0400
@@ -0,0 +1,65 @@
+/*
+Copyright (c) Fabien Ninoles <fabien@tzone.org>
+All rights reserved.
+
+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 the University 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 REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+*/
+
+#ifndef _JSONSAX_H_
+#define _JSONSAX_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+enum EJSONSAX_TYPE {
+ EJSONSAX_OBJECT,
+ EJSONSAX_ARRAY,
+ EJSONSAX_STRING,
+ EJSONSAX_NUMBER,
+ EJSONSAX_NULL,
+ EJSONSAX_TRUE,
+ EJSONSAX_FALSE
+};
+
+struct jsonsax_backend
+{
+ int (*m_getchar)(void* data);
+ int (*m_onstart)(void* data, enum EJSONSAX_TYPE type);
+ int (*m_onstop)(void* data, enum EJSONSAX_TYPE type);
+ void (*m_onerror)(void* data, int error);
+};
+
+// Note: the structure members would be copied before
+// being used. You cannot change the functions called after
+// it.
+int jsonsax_parse(struct jsonsax_backend* backend, void* data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests.c Sun Oct 07 14:30:52 2012 -0400
@@ -0,0 +1,127 @@
+#include "jsonsax.h"
+
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <stdarg.h>
+
+#define DEBUGTEST
+
+void debug(const char* msg, ...)
+{
+#ifdef DEBUGTEST
+ fprintf(stderr, "\n-*- ");
+ va_list ap;
+ va_start(ap, msg);
+ vfprintf(stderr, msg, ap);
+ va_end(ap);
+ fprintf(stderr, " -*-\n");
+#else
+ (void)msg;
+#endif
+}
+
+const char* TEST_JSONTYPE_STR[] = {
+ "EJSONSAX_OBJECT",
+ "EJSONSAX_ARRAY",
+ "EJSONSAX_STRING",
+ "EJSONSAX_NUMBER",
+ "EJSONSAX_NULL",
+ "EJSONSAX_TRUE",
+ "EJSONSAX_FALSE"
+};
+
+struct test_data
+{
+ const char* m_str;
+};
+
+int test_getchar(void* data)
+{
+ assert(data);
+ struct test_data* t = (struct test_data*)(data);
+ if (t->m_str[0] == 0) return -1;
+#ifdef DEBUGTEST
+ char c = t->m_str[0];
+ fprintf(stderr, "%c", c == ' ' ? '_' : c);
+#endif
+ return *(t->m_str++);
+}
+
+int test_on_start(void* data, enum EJSONSAX_TYPE etype)
+{
+ assert(data);
+ struct test_data* t = (struct test_data*)(data);
+ debug("start %s", TEST_JSONTYPE_STR[etype]);
+
+ switch (etype)
+ {
+case EJSONSAX_OBJECT:
+ assert(t->m_str[-1] == '{');
+ break;
+case EJSONSAX_ARRAY:
+ assert(t->m_str[-1] == '[');
+ break;
+case EJSONSAX_STRING:
+ assert(t->m_str[-1] == '"');
+ break;
+case EJSONSAX_NUMBER:
+ break;
+case EJSONSAX_NULL:
+case EJSONSAX_TRUE:
+case EJSONSAX_FALSE:
+ assert(0);
+}
+ return 0;
+}
+
+int test_on_stop(void* data, enum EJSONSAX_TYPE etype)
+{
+ assert(data);
+ struct test_data* t = (struct test_data*)(data);
+ debug("stop %s", TEST_JSONTYPE_STR[etype]);
+
+ switch (etype)
+ {
+case EJSONSAX_OBJECT:
+ assert(t->m_str[-1] == '}');
+ break;
+case EJSONSAX_ARRAY:
+ assert(t->m_str[-1] == ']');
+ break;
+case EJSONSAX_STRING:
+ assert(t->m_str[-1] == '"');
+ break;
+case EJSONSAX_NUMBER:
+case EJSONSAX_NULL:
+case EJSONSAX_TRUE:
+case EJSONSAX_FALSE:
+ break;
+}
+ return 0;
+}
+
+void test_on_error(void* data, int error)
+{
+ assert(data);
+ debug("Error %d", error);
+}
+
+int main()
+{
+ const char json[] =
+ "{ \"hello\" : [ 11, 12 ,1"
+ "3 ], \n \"world\" : -3.45e2 }";
+ struct test_data data;
+ data.m_str = json;
+ struct jsonsax_backend tester;
+ memset(&tester, 0, sizeof(tester));
+ tester.m_getchar = &test_getchar;
+ tester.m_onstart = &test_on_start;
+ tester.m_onstop = &test_on_stop;
+
+ int err = jsonsax_parse(&tester, &data);
+ assert(err == 0);
+
+ return err;
+};
--- a/tests.cpp Sat Oct 06 21:08:55 2012 -0400
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,138 +0,0 @@
-#include "jsonsax.hpp"
-
-#include <iostream>
-#include <assert.h>
-
-// #define DEBUGTEST
-class JSLXTester : public IJSLXBackend
-{
-public:
- explicit JSLXTester(const char* json)
- : m_json(json)
- {}
-
- void debug(const char* data)
- {
-#ifdef DEBUGTEST
- std::cerr << std::endl << "-*- " << data << " -*-" << std::endl;
-#endif
- }
-
- virtual bool Eof()
- {
- return *m_json == '\0';
- }
-
- virtual char GetChar()
- {
- assert(!Eof());
-#ifdef DEBUGTEST
- std::cerr.put(*m_json == ' ' ? '_' : *m_json);
-#endif
- return *m_json++;
- }
-
- virtual bool OnStartObject()
- {
- assert(m_json[-1] == '{');
- debug("OnStartObject");
- return true;
- }
-
- virtual bool OnStopObject()
- {
- assert(m_json[-1] == '}');
- debug("OnStopObject");
- return true;
- }
-
- virtual bool OnStartArray()
- {
- assert(m_json[-1] == '[');
- debug("OnStartArray");
- return true;
- }
-
- virtual bool OnStopArray()
- {
- assert(m_json[-1] == ']');
- debug("OnStopArray");
- return true;
- }
-
- virtual bool OnStartNumber()
- {
- // assert(m_json[-1] == ']');
- debug("OnStartNumber");
- return true;
- }
-
- virtual bool OnStopNumber()
- {
- // assert(m_json[-1] == ']');
- debug("OnStopNumber");
- return true;
- }
-
- virtual bool OnStartString()
- {
- assert(m_json[-1] == '"');
- debug("OnStartString");
- return true;
- }
-
- virtual bool OnStopString()
- {
- assert(m_json[-1] == '"');
- debug("OnStopString");
- return true;
- }
-
- virtual bool OnNull()
- {
- // assert(m_json[-1] == ']');
- debug("OnNull");
- return true;
- }
-
- virtual bool OnTrue()
- {
- // assert(m_json[-1] == ']');
- debug("OnTrue");
- return true;
- }
-
- virtual bool OnFalse()
- {
- // assert(m_json[-1] == ']');
- debug("OnFalse");
- return true;
- }
-
- virtual void OnError(const char* err)
- {
- debug("Error");
- debug(err);
- }
-
- bool Check()
- {
- return Eof();
- }
-
-private:
- const char* m_json;
-};
-
-int main()
-{
- const char json[] =
- "{ \"hello\" : [ 11, 12 ,1"
- "3 ], \n \"world\" : -3.45e2 }";
- JSLXTester tester(json);
- JSLXParser parser(&tester);
- assert(parser.Parse());
- assert(tester.Check());
-
- return 0;
-}