aboutsummaryrefslogtreecommitdiff
path: root/src/utils/JSONVariantParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/utils/JSONVariantParser.cpp')
-rw-r--r--src/utils/JSONVariantParser.cpp236
1 files changed, 236 insertions, 0 deletions
diff --git a/src/utils/JSONVariantParser.cpp b/src/utils/JSONVariantParser.cpp
new file mode 100644
index 0000000000..db08849e49
--- /dev/null
+++ b/src/utils/JSONVariantParser.cpp
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2005-2013 Team XBMC
+ * http://xbmc.org
+ *
+ * This Program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This Program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with XBMC; see the file COPYING. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "JSONVariantParser.h"
+
+yajl_callbacks CJSONVariantParser::callbacks = {
+ CJSONVariantParser::ParseNull,
+ CJSONVariantParser::ParseBoolean,
+ CJSONVariantParser::ParseInteger,
+ CJSONVariantParser::ParseDouble,
+ NULL,
+ CJSONVariantParser::ParseString,
+ CJSONVariantParser::ParseMapStart,
+ CJSONVariantParser::ParseMapKey,
+ CJSONVariantParser::ParseMapEnd,
+ CJSONVariantParser::ParseArrayStart,
+ CJSONVariantParser::ParseArrayEnd
+};
+
+CJSONVariantParser::CJSONVariantParser(IParseCallback *callback)
+{
+ m_callback = callback;
+
+#if YAJL_MAJOR == 2
+ m_handler = yajl_alloc(&callbacks, NULL, this);
+
+ yajl_config(m_handler, yajl_allow_comments, 1);
+ yajl_config(m_handler, yajl_dont_validate_strings, 0);
+#else
+ yajl_parser_config cfg = { 1, 1 };
+
+ m_handler = yajl_alloc(&callbacks, &cfg, NULL, this);
+#endif
+
+ m_status = ParseVariable;
+}
+
+CJSONVariantParser::~CJSONVariantParser()
+{
+#if YAJL_MAJOR == 2
+ yajl_complete_parse(m_handler);
+#else
+ yajl_parse_complete(m_handler);
+#endif
+ yajl_free(m_handler);
+}
+
+void CJSONVariantParser::push_buffer(const unsigned char *buffer, unsigned int length)
+{
+ yajl_parse(m_handler, buffer, length);
+}
+
+CVariant CJSONVariantParser::Parse(const unsigned char *json, unsigned int length)
+{
+ CSimpleParseCallback callback;
+ CJSONVariantParser parser(&callback);
+
+ parser.push_buffer(json, length);
+
+ return callback.GetOutput();
+}
+
+int CJSONVariantParser::ParseNull(void * ctx)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant::VariantTypeNull);
+ parser->PopObject();
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseBoolean(void * ctx, int boolean)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant(boolean != 0));
+ parser->PopObject();
+
+ return 1;
+}
+
+#if YAJL_MAJOR ==2
+int CJSONVariantParser::ParseInteger(void * ctx, long long integerVal)
+#else
+int CJSONVariantParser::ParseInteger(void * ctx, long integerVal)
+#endif
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant((int64_t)integerVal));
+ parser->PopObject();
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseDouble(void * ctx, double doubleVal)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant((float)doubleVal));
+ parser->PopObject();
+
+ return 1;
+}
+
+#if YAJL_MAJOR == 2
+int CJSONVariantParser::ParseString(void * ctx, const unsigned char * stringVal, size_t stringLen)
+#else
+int CJSONVariantParser::ParseString(void * ctx, const unsigned char * stringVal, unsigned int stringLen)
+#endif
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant((const char *)stringVal, stringLen));
+ parser->PopObject();
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseMapStart(void * ctx)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant::VariantTypeObject);
+
+ return 1;
+}
+
+#if YAJL_MAJOR == 2
+int CJSONVariantParser::ParseMapKey(void * ctx, const unsigned char * stringVal, size_t stringLen)
+#else
+int CJSONVariantParser::ParseMapKey(void * ctx, const unsigned char * stringVal, unsigned int stringLen)
+#endif
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->m_key = std::string((const char *)stringVal, 0, stringLen);
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseMapEnd(void * ctx)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PopObject();
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseArrayStart(void * ctx)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PushObject(CVariant::VariantTypeArray);
+
+ return 1;
+}
+
+int CJSONVariantParser::ParseArrayEnd(void * ctx)
+{
+ CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
+
+ parser->PopObject();
+
+ return 1;
+}
+
+void CJSONVariantParser::PushObject(CVariant variant)
+{
+ if (m_status == ParseObject)
+ {
+ (*m_parse[m_parse.size() - 1])[m_key] = variant;
+ m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]);
+ }
+ else if (m_status == ParseArray)
+ {
+ CVariant *temp = m_parse[m_parse.size() - 1];
+ temp->push_back(variant);
+ m_parse.push_back(&(*temp)[temp->size() - 1]);
+ }
+ else if (m_parse.size() == 0)
+ {
+ m_parse.push_back(new CVariant(variant));
+ }
+
+ if (variant.isObject())
+ m_status = ParseObject;
+ else if (variant.isArray())
+ m_status = ParseArray;
+ else
+ m_status = ParseVariable;
+}
+
+void CJSONVariantParser::PopObject()
+{
+ CVariant *variant = m_parse[m_parse.size() - 1];
+ m_parse.pop_back();
+
+ if (m_parse.size())
+ {
+ variant = m_parse[m_parse.size() - 1];
+ if (variant->isObject())
+ m_status = ParseObject;
+ else if (variant->isArray())
+ m_status = ParseArray;
+ else
+ m_status = ParseVariable;
+ }
+ else if (m_callback)
+ {
+ m_callback->onParsed(variant);
+ delete variant;
+
+ m_parse.clear();
+ m_status = ParseVariable;
+ }
+}