Merge pull request #4676 from jmarshallnz/dont_set_scraper_on_tvshow_on_nfo
[vuplus_xbmc] / xbmc / utils / JSONVariantParser.cpp
1 /*
2  *      Copyright (C) 2005-2013 Team XBMC
3  *      http://xbmc.org
4  *
5  *  This Program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This Program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with XBMC; see the file COPYING.  If not, see
17  *  <http://www.gnu.org/licenses/>.
18  *
19  */
20
21 #include "JSONVariantParser.h"
22
23 yajl_callbacks CJSONVariantParser::callbacks = {
24   CJSONVariantParser::ParseNull,
25   CJSONVariantParser::ParseBoolean,
26   CJSONVariantParser::ParseInteger,
27   CJSONVariantParser::ParseDouble,
28   NULL,
29   CJSONVariantParser::ParseString,
30   CJSONVariantParser::ParseMapStart,
31   CJSONVariantParser::ParseMapKey,
32   CJSONVariantParser::ParseMapEnd,
33   CJSONVariantParser::ParseArrayStart,
34   CJSONVariantParser::ParseArrayEnd
35 };
36
37 CJSONVariantParser::CJSONVariantParser(IParseCallback *callback)
38 {
39   m_callback = callback;
40
41 #if YAJL_MAJOR == 2
42   m_handler = yajl_alloc(&callbacks, NULL, this);
43
44   yajl_config(m_handler, yajl_allow_comments, 1);
45   yajl_config(m_handler, yajl_dont_validate_strings, 0);
46 #else
47   yajl_parser_config cfg = { 1, 1 };
48
49   m_handler = yajl_alloc(&callbacks, &cfg, NULL, this);
50 #endif
51
52   m_status = ParseVariable;
53 }
54
55 CJSONVariantParser::~CJSONVariantParser()
56 {
57 #if YAJL_MAJOR == 2
58   yajl_complete_parse(m_handler);
59 #else
60   yajl_parse_complete(m_handler);
61 #endif
62   yajl_free(m_handler);
63 }
64
65 void CJSONVariantParser::push_buffer(const unsigned char *buffer, unsigned int length)
66 {
67   yajl_parse(m_handler, buffer, length);
68 }
69
70 CVariant CJSONVariantParser::Parse(const unsigned char *json, unsigned int length)
71 {
72   CSimpleParseCallback callback;
73   CJSONVariantParser parser(&callback);
74
75   parser.push_buffer(json, length);
76
77   return callback.GetOutput();
78 }
79
80 int CJSONVariantParser::ParseNull(void * ctx)
81 {
82   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
83
84   parser->PushObject(CVariant::VariantTypeNull);
85   parser->PopObject();
86
87   return 1;
88 }
89
90 int CJSONVariantParser::ParseBoolean(void * ctx, int boolean)
91 {
92   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
93
94   parser->PushObject(CVariant(boolean != 0));
95   parser->PopObject();
96
97   return 1;
98 }
99
100 #if YAJL_MAJOR ==2
101 int CJSONVariantParser::ParseInteger(void * ctx, long long integerVal)
102 #else
103 int CJSONVariantParser::ParseInteger(void * ctx, long integerVal)
104 #endif
105 {
106   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
107
108   parser->PushObject(CVariant((int64_t)integerVal));
109   parser->PopObject();
110
111   return 1;
112 }
113
114 int CJSONVariantParser::ParseDouble(void * ctx, double doubleVal)
115 {
116   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
117
118   parser->PushObject(CVariant((float)doubleVal));
119   parser->PopObject();
120
121   return 1;
122 }
123
124 #if YAJL_MAJOR == 2
125 int CJSONVariantParser::ParseString(void * ctx, const unsigned char * stringVal, size_t stringLen)
126 #else
127 int CJSONVariantParser::ParseString(void * ctx, const unsigned char * stringVal, unsigned int stringLen)
128 #endif
129 {
130   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
131
132   parser->PushObject(CVariant((const char *)stringVal, stringLen));
133   parser->PopObject();
134
135   return 1;
136 }
137
138 int CJSONVariantParser::ParseMapStart(void * ctx)
139 {
140   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
141
142   parser->PushObject(CVariant::VariantTypeObject);
143
144   return 1;
145 }
146
147 #if YAJL_MAJOR == 2
148 int CJSONVariantParser::ParseMapKey(void * ctx, const unsigned char * stringVal, size_t stringLen)
149 #else
150 int CJSONVariantParser::ParseMapKey(void * ctx, const unsigned char * stringVal, unsigned int stringLen)
151 #endif
152 {
153   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
154
155   parser->m_key = std::string((const char *)stringVal, 0, stringLen);
156
157   return 1;
158 }
159
160 int CJSONVariantParser::ParseMapEnd(void * ctx)
161 {
162   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
163
164   parser->PopObject();
165
166   return 1;
167 }
168
169 int CJSONVariantParser::ParseArrayStart(void * ctx)
170 {
171   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
172
173   parser->PushObject(CVariant::VariantTypeArray);
174
175   return 1;
176 }
177
178 int CJSONVariantParser::ParseArrayEnd(void * ctx)
179 {
180   CJSONVariantParser *parser = (CJSONVariantParser *)ctx;
181
182   parser->PopObject();
183
184   return 1;
185 }
186
187 void CJSONVariantParser::PushObject(CVariant variant)
188 {
189   if (m_status == ParseObject)
190   {
191     (*m_parse[m_parse.size() - 1])[m_key] = variant;
192     m_parse.push_back(&(*m_parse[m_parse.size() - 1])[m_key]);
193   }
194   else if (m_status == ParseArray)
195   {
196     CVariant *temp = m_parse[m_parse.size() - 1];
197     temp->push_back(variant);
198     m_parse.push_back(&(*temp)[temp->size() - 1]);
199   }
200   else if (m_parse.size() == 0)
201   {
202     m_parse.push_back(new CVariant(variant));
203   }
204
205   if (variant.isObject())
206     m_status = ParseObject;
207   else if (variant.isArray())
208     m_status = ParseArray;
209   else
210     m_status = ParseVariable;
211 }
212
213 void CJSONVariantParser::PopObject()
214 {
215   CVariant *variant = m_parse[m_parse.size() - 1];
216   m_parse.pop_back();
217
218   if (m_parse.size())
219   {
220     variant = m_parse[m_parse.size() - 1];
221     if (variant->isObject())
222       m_status = ParseObject;
223     else if (variant->isArray())
224       m_status = ParseArray;
225     else
226       m_status = ParseVariable;
227   }
228   else if (m_callback)
229   {
230     m_callback->onParsed(variant);
231     delete variant;
232
233     m_parse.clear();
234     m_status = ParseVariable;
235   }
236 }