/ webserv / practice / config / saved2 / JsonParser.cpp
JsonParser.cpp
  1  #include "JsonParser.hpp"
  2  
  3  static jsonType		_getPrimitiveType
  4  (std::string const& str);
  5  static std::string	_getStringData
  6  (std::string const& text, std::string::iterator& it);
  7  static std::string	_parseStringKey
  8  (std::string const& text, std::string::iterator& it);
  9  static std::string	_parseStringValue
 10  (std::string const& text, std::string::iterator& it);
 11  static std::string	_parsePrimitive
 12  (std::string const& text, std::string::iterator& it, jsonType& type);
 13  static bool	_checkLineEnd
 14  (std::string const& text, std::string::iterator& it);
 15  static bool	_checkElementEnd
 16  (std::string const& text, std::string::iterator& it);
 17  
 18  JsonParser::JsonParser(void) : _json(0) {}
 19  
 20  JsonParser::~JsonParser(void) {}
 21  
 22  JsonData*	JsonParser::getJson(void)
 23  {
 24  	return this->_json;
 25  }
 26  
 27  void	JsonParser::readFile
 28  (std::string const& filepath, std::string& output)
 29  {
 30  	std::ifstream	file(filepath.c_str());
 31  	std::string		line;
 32  
 33  	while (std::getline(file, line, '\0'))
 34  	{
 35  		output.append(line);
 36  	}
 37  }
 38  
 39  std::pair<std::string, JsonData>	JsonParser::retriveKeyValuePair
 40  (std::string const& text, std::string::iterator& it)
 41  {
 42  	std::string	key;
 43  	JsonData	data;
 44  
 45  	assert(it != text.end());
 46  
 47  	while (std::isspace(*it))
 48  		it++;
 49  	if (*it == '\"')
 50  	{
 51  		key = _parseStringKey(text, it);
 52  	}
 53  	else if (*it == '}')
 54  	{
 55  		return std::make_pair(key, data);
 56  	}
 57  	else
 58  	{
 59  		// throw error
 60  		std::cerr << "Error: Object must have valid key" << std::endl;
 61  		std::exit(1);
 62  	}
 63  
 64  	while (std::isspace(*it))
 65  		it++;
 66  
 67  	if (*it == '{')
 68  	{
 69  		data = parseObject(text, it);
 70  	}
 71  	else if (*it == '\"')
 72  	{
 73  		data._type = TYPE_STRING;
 74  		data._str = _parseStringValue(text, it);
 75  	}
 76  	else if (*it == '[')
 77  	{
 78  		data._type = TYPE_ARRAY;
 79  		data._arr = parseArray(text, it);
 80  	}
 81  	else if (std::isalnum(*it))
 82  	{
 83  		data._str = _parsePrimitive(text, it, data._type);
 84  	}
 85  	else
 86  	{
 87  		// throw error
 88  		std::cerr << "Error: Object must have valid value" << std::endl;
 89  		std::exit(1);
 90  	}
 91  
 92  	if (_checkLineEnd(text, it) == false)
 93  	{
 94  		// throw error
 95  		std::cerr << "Error: Malformed line end" << std::endl;
 96  		std::exit(1);
 97  	}
 98  	it++;
 99  	//std::cout << "before it: " << *it << std::endl;
100  	while (*it == ',' || std::isspace(*it))
101  		it++;
102  	return std::make_pair(key, data);
103  }
104  
105  std::vector<JsonData>	JsonParser::parseArray
106  (std::string const& text, std::string::iterator& it)
107  {
108  	std::vector<JsonData>	arr;
109  	std::string::iterator	nxt;
110  
111  	it++;
112  	while (it != text.end())
113  	{
114  		JsonData	data;
115  
116  		while (std::isspace(*it))
117  			it++;
118  		if (*it == '{')
119  		{
120  			data = parseObject(text, it);
121  		}
122  		else if (*it == '\"')
123  		{
124  			data._type = TYPE_STRING;
125  			data._str = _parseStringValue(text, it);
126  		}
127  		else if (*it == '[')
128  		{
129  			data._type = TYPE_ARRAY;
130  			data._arr = parseArray(text, it);
131  		}
132  		else if (*it == ']')
133  		{
134  			break;
135  		}
136  		else if (std::isalnum(*it))
137  		{
138  			data._str = _parsePrimitive(text, it, data._type);
139  		}
140  		else
141  		{
142  			// throw error
143  			std::cerr << "Error: Malformed Array 1" << std::endl;
144  			std::exit(1);
145  		}
146  
147  		if (_checkElementEnd(text, it) == false)
148  		{
149  			// throw error
150  			std::cerr << "Error: Malformed line end" << std::endl;
151  			std::exit(1);
152  		}
153  		it++;
154  		while (*it == ',' || std::isspace(*it))
155  			it++;
156  		arr.push_back(data);
157  	}
158  	return arr;
159  }
160  
161  JsonData	JsonParser::parseObject
162  (std::string const& text, std::string::iterator& it)
163  {
164  	JsonData										jsonData;
165  	std::vector<std::pair< std::string, JsonData> >	jsonObject;
166  
167  	while (std::isspace(*it))
168  		++it;
169  
170  	assert(*it == '{');
171  	it++;
172  
173  	do {
174  		std::pair<std::string, JsonData> keyValuePair
175  			= retriveKeyValuePair(text, it);
176  		jsonObject.push_back(keyValuePair);
177  
178  		while (std::isspace(*it))
179  			it++;
180  	} while (*it != '}');
181  
182  	jsonData._type = TYPE_OBJECT;
183  	jsonData._obj = jsonObject;
184  
185  	return jsonData;
186  }
187  
188  JsonData	JsonParser::parseJson(std::string const& filepath)
189  {
190  	std::string				text;
191  	std::string::iterator	start;
192  
193  	readFile(filepath, text);
194  	start = text.begin();
195  	return parseObject(text, start);
196  }
197  
198  /* *************************************************************************** *
199   * Helper Functions                                                            *
200   * ****************************************************************************/
201  
202  static bool	_checkElementEnd
203  (std::string const& text, std::string::iterator& it)
204  {
205  	std::string::iterator	cur;
206  	bool					comma = false;
207  
208  	if (it == text.end())
209  	{
210  		// throw error
211  		std::cerr << "Error: Malformed Array format EOF" << std::endl;
212  		std::exit(1);
213  	}
214  	cur = it + 1;
215  //	std::cout << "ARR *it: " << *it << " ARR *cur: " << *cur << std::endl;
216  	while (*cur == ',' || std::isspace(*cur))
217  	{
218  		if (*cur == ',')
219  		{
220  			if (comma == false)
221  				comma = true;
222  			else
223  			{
224  				// throw error
225  				std::cerr << "Error: Duplicate comma" << std::endl;
226  				std::exit(1);
227  			}
228  		}
229  		cur++;
230  	}
231  //	std::cout << "ARR after iter cur: " << *cur << std::endl;
232  	if (*cur == '\"')
233  	{
234  		if (comma == true)
235  			return true;
236  		else
237  		{
238  			// throw error
239  			std::cerr << "Error: No comma before key" << std::endl;
240  			std::exit(1);
241  		}
242  	}
243  	else if (*cur == '{')
244  	{
245  		if (comma == true)
246  			return true;
247  		else
248  		{
249  			// throw error
250  			std::cerr << "Error: No comma before block" << std::endl;
251  			std::exit(1);
252  		}
253  	}
254  	else if (*cur == '[')
255  	{
256  		if (comma == true)
257  			return true;
258  		else
259  		{
260  			// throw error
261  			std::cerr << "Error: No comma before array" << std::endl;
262  			std::exit(1);
263  		}
264  	}
265  	else if (std::isalnum(*cur))
266  	{
267  		if (comma == true)
268  			return true;
269  		else
270  		{
271  			// throw error
272  			std::cerr << "Error: No comma before primitive" << std::endl;
273  			std::exit(1);
274  		}
275  	}
276  	else if (*cur == ']')
277  	{
278  		if (comma == false)
279  			return true;
280  		else
281  		{
282  			// throw error
283  			std::cerr << "Error: Comma before end array" << std::endl;
284  			std::exit(1);
285  		}
286  	}
287  	return false;
288  }
289  
290  static bool	_checkLineEnd
291  (std::string const& text, std::string::iterator& it)
292  {
293  	std::string::iterator	cur;
294  	bool					comma = false;
295  
296  	if (it == text.end())
297  	{
298  		// throw error
299  		std::cerr << "Error: Malformed Json format EOF" << std::endl;
300  		std::exit(1);
301  	}
302  	cur = it + 1;
303  //	std::cout << "*it: " << *it << " *cur: " << *cur << std::endl;
304  	while (*cur == ',' || std::isspace(*cur))
305  	{
306  		if (*cur == ',')
307  		{
308  			if (comma == false)
309  				comma = true;
310  			else
311  			{
312  				// throw error
313  				std::cerr << "Error: Duplicate comma" << std::endl;
314  				std::exit(1);
315  			}
316  		}
317  		cur++;
318  	}
319  //	std::cout << "after iter cur: " << *cur << std::endl;
320  	if (*cur == '\"')
321  	{
322  		if (comma == true)
323  			return true;
324  		else
325  		{
326  			// throw error
327  			std::cerr << "Error: No comma before key" << std::endl;
328  			std::exit(1);
329  		}
330  	}
331  	else if (*cur == '}')
332  	{
333  		if (comma == false)
334  			return true;
335  		else
336  		{
337  			// throw error
338  			std::cerr << "Error: Comma before end block" << std::endl;
339  			std::exit(1);
340  		}
341  	}
342  	return false;
343  }
344  
345  static std::string	_parsePrimitive
346  (std::string const& text, std::string::iterator& it, jsonType& type)
347  {
348  	std::string	value;
349  
350  	while (*it != ',' && *it != '}' && *it != ']' && !std::isspace(*it))
351  	{
352  		if (*it == '\"')
353  		{
354  			// throw error
355  			std::cerr << "Error: Malformed Primitive Format" << std::endl;
356  			std::exit(1);
357  		}
358  		value += *it;
359  		it++;
360  	}
361  	it--;
362  	type = _getPrimitiveType(value);
363  	if (type == TYPE_ERROR)
364  	{
365  		// throw error
366  		std::cerr << "Error: Malformed primitive format" << std::endl;
367  		std::exit(1);
368  	}
369  	return value;
370  }
371  
372  static std::string	_parseStringKey
373  (std::string const& text, std::string::iterator& it)
374  {
375  	std::string	key;
376  
377  	key = _getStringData(text, it);
378  	it++;
379  	while (std::isspace(*it))
380  		it++;
381  	if (*it != ':')
382  	{
383  		// throw error
384  		std::cerr << "Error: Colon not found after key" << std::endl;
385  		std::exit(1);
386  	}
387  	it++;
388  	return key;
389  }
390  
391  static std::string	_parseStringValue
392  (std::string const& text, std::string::iterator& it)
393  {
394  	std::string				value;
395  	std::string::iterator	cur;
396  
397  	value = _getStringData(text, it);
398  //	it++;
399  //	while (std::isspace(*it))
400  //		it++;
401  	return value;
402  }
403  
404  static std::string	_getStringData
405  (std::string const& text, std::string::iterator& it)
406  {
407  	std::string	str;
408  	bool		insideQuote = false;
409  	bool		escape = false;
410  	char		ch;
411  
412  	while (it != text.end())
413  	{
414  		ch = *it;
415  		if (insideQuote)
416  		{
417  			if (ch == '\n')
418  			{
419  				// throw error
420  				std::cerr << "Error: Malformed String Data type" << std::endl;
421  				std::exit(1);
422  			}
423  			if (escape)
424  			{
425  				str += ch;
426  				escape = false;
427  			}
428  			else if (ch == '\\')
429  				escape = true;
430  			else if (ch == '\"')
431  			{
432  				insideQuote = false;
433  				break;
434  			}
435  			else
436  				str += ch;
437  		}
438  		else if (ch == '\"')
439  			insideQuote = true;
440  		else if (ch == '\\')
441  			escape = true;
442  		else
443  		{
444  			// throw error
445  			std::cerr << "Error: Malformed String Data type" << std::endl;
446  			std::exit(1);
447  		}
448  		it++;
449  	}
450  	if ((it == text.end()) || insideQuote)
451  	{
452  		// throw error
453  		std::cerr << "Error: Malformed Key value" << std::endl;
454  		std::exit(1);
455  	}
456  	return str;
457  }
458  
459  static jsonType	_getPrimitiveType(std::string const& str)
460  {
461  	char*	endptr;
462  
463  	static_cast<void>(strtol(str.c_str(), &endptr, 10));
464  	if (*endptr == '\0')
465  		return TYPE_INTEGER;
466  	static_cast<void>(strtod(str.c_str(), &endptr));
467  	if (*endptr == '\0')
468  		return TYPE_FLOAT;
469  	if (str == "true" || str == "false")
470  		return TYPE_BOOLEAN;
471  	if (str == "null")
472  		return TYPE_NULL;
473  	return TYPE_ERROR;
474  }