| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*  json.cpp                                                             */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							|  |  |  | /*                       This file is part of:                           */ | 
					
						
							|  |  |  | /*                           GODOT ENGINE                                */ | 
					
						
							| 
									
										
										
										
											2017-08-27 14:16:55 +02:00
										 |  |  | /*                      https://godotengine.org                          */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2020-01-01 11:16:22 +01:00
										 |  |  | /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */ | 
					
						
							|  |  |  | /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */ | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the       */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including   */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,   */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to    */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to */ | 
					
						
							|  |  |  | /* the following conditions:                                             */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be        */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.       */ | 
					
						
							|  |  |  | /*                                                                       */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,       */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF    */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY  */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,  */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE     */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                */ | 
					
						
							|  |  |  | /*************************************************************************/ | 
					
						
							| 
									
										
										
										
											2018-01-05 00:50:27 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | #include "json.h"
 | 
					
						
							| 
									
										
										
										
											2018-09-11 18:13:45 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "core/print_string.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | const char *JSON::tk_name[TK_MAX] = { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	"'{'", | 
					
						
							|  |  |  | 	"'}'", | 
					
						
							|  |  |  | 	"'['", | 
					
						
							|  |  |  | 	"']'", | 
					
						
							|  |  |  | 	"identifier", | 
					
						
							|  |  |  | 	"string", | 
					
						
							|  |  |  | 	"number", | 
					
						
							|  |  |  | 	"':'", | 
					
						
							|  |  |  | 	"','", | 
					
						
							|  |  |  | 	"EOF", | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 01:27:02 +01:00
										 |  |  | static String _make_indent(const String &p_indent, int p_size) { | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String indent_text = ""; | 
					
						
							|  |  |  | 	if (!p_indent.empty()) { | 
					
						
							|  |  |  | 		for (int i = 0; i < p_size; i++) | 
					
						
							|  |  |  | 			indent_text += p_indent; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return indent_text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 01:27:02 +01:00
										 |  |  | String JSON::_print_var(const Variant &p_var, const String &p_indent, int p_cur_indent, bool p_sort_keys) { | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	String colon = ":"; | 
					
						
							|  |  |  | 	String end_statement = ""; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (!p_indent.empty()) { | 
					
						
							|  |  |  | 		colon += " "; | 
					
						
							|  |  |  | 		end_statement += "\n"; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	switch (p_var.get_type()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		case Variant::NIL: return "null"; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		case Variant::BOOL: return p_var.operator bool() ? "true" : "false"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case Variant::INT: return itos(p_var); | 
					
						
							|  |  |  | 		case Variant::REAL: return rtos(p_var); | 
					
						
							| 
									
										
										
										
											2017-01-11 00:52:51 -03:00
										 |  |  | 		case Variant::POOL_INT_ARRAY: | 
					
						
							|  |  |  | 		case Variant::POOL_REAL_ARRAY: | 
					
						
							|  |  |  | 		case Variant::POOL_STRING_ARRAY: | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		case Variant::ARRAY: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			String s = "["; | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 			s += end_statement; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			Array a = p_var; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (int i = 0; i < a.size(); i++) { | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 				if (i > 0) { | 
					
						
							|  |  |  | 					s += ","; | 
					
						
							|  |  |  | 					s += end_statement; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(a[i], p_indent, p_cur_indent + 1, p_sort_keys); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 			s += end_statement + _make_indent(p_indent, p_cur_indent) + "]"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return s; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 		case Variant::DICTIONARY: { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			String s = "{"; | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 			s += end_statement; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			Dictionary d = p_var; | 
					
						
							|  |  |  | 			List<Variant> keys; | 
					
						
							|  |  |  | 			d.get_key_list(&keys); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 			if (p_sort_keys) | 
					
						
							|  |  |  | 				keys.sort(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			for (List<Variant>::Element *E = keys.front(); E; E = E->next()) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 				if (E != keys.front()) { | 
					
						
							|  |  |  | 					s += ","; | 
					
						
							|  |  |  | 					s += end_statement; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				s += _make_indent(p_indent, p_cur_indent + 1) + _print_var(String(E->get()), p_indent, p_cur_indent + 1, p_sort_keys); | 
					
						
							|  |  |  | 				s += colon; | 
					
						
							|  |  |  | 				s += _print_var(d[E->get()], p_indent, p_cur_indent + 1, p_sort_keys); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 			s += end_statement + _make_indent(p_indent, p_cur_indent) + "}"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return s; | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		default: return "\"" + String(p_var).json_escape() + "\""; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-10 01:27:02 +01:00
										 |  |  | String JSON::print(const Variant &p_var, const String &p_indent, bool p_sort_keys) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-03 15:32:58 +08:00
										 |  |  | 	return _print_var(p_var, p_indent, 0, p_sort_keys); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | Error JSON::_get_token(const CharType *p_str, int &index, int p_len, Token &r_token, int &line, String &r_err_str) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-15 16:59:02 +08:00
										 |  |  | 	while (p_len > 0) { | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 		switch (p_str[index]) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			case '\n': { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				line++; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				break; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case 0: { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_EOF; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			} break; | 
					
						
							|  |  |  | 			case '{': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_CURLY_BRACKET_OPEN; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case '}': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_CURLY_BRACKET_CLOSE; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case '[': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_BRACKET_OPEN; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case ']': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_BRACKET_CLOSE; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case ':': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_COLON; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case ',': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_COMMA; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 			case '"': { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				String str; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				while (true) { | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					if (p_str[index] == 0) { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						r_err_str = "Unterminated String"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 						return ERR_PARSE_ERROR; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					} else if (p_str[index] == '"') { | 
					
						
							|  |  |  | 						index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 						break; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					} else if (p_str[index] == '\\') { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 						//escaped characters...
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 						index++; | 
					
						
							|  |  |  | 						CharType next = p_str[index]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						if (next == 0) { | 
					
						
							|  |  |  | 							r_err_str = "Unterminated String"; | 
					
						
							|  |  |  | 							return ERR_PARSE_ERROR; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						CharType res = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						switch (next) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 							case 'b': res = 8; break; | 
					
						
							|  |  |  | 							case 't': res = 9; break; | 
					
						
							|  |  |  | 							case 'n': res = 10; break; | 
					
						
							|  |  |  | 							case 'f': res = 12; break; | 
					
						
							|  |  |  | 							case 'r': res = 13; break; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 							case 'u': { | 
					
						
							|  |  |  | 								//hexnumbarh - oct is deprecated
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 								for (int j = 0; j < 4; j++) { | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 									CharType c = p_str[index + j + 1]; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 									if (c == 0) { | 
					
						
							|  |  |  | 										r_err_str = "Unterminated String"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 										return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 									} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 									if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'))) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 										r_err_str = "Malformed hex constant in string"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 										return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 									} | 
					
						
							|  |  |  | 									CharType v; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 									if (c >= '0' && c <= '9') { | 
					
						
							|  |  |  | 										v = c - '0'; | 
					
						
							|  |  |  | 									} else if (c >= 'a' && c <= 'f') { | 
					
						
							|  |  |  | 										v = c - 'a'; | 
					
						
							|  |  |  | 										v += 10; | 
					
						
							|  |  |  | 									} else if (c >= 'A' && c <= 'F') { | 
					
						
							|  |  |  | 										v = c - 'A'; | 
					
						
							|  |  |  | 										v += 10; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 									} else { | 
					
						
							|  |  |  | 										ERR_PRINT("BUG"); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 										v = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 									} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 									res <<= 4; | 
					
						
							|  |  |  | 									res |= v; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 								} | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 								index += 4; //will add at the end anyway
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 							} break; | 
					
						
							| 
									
										
										
										
											2015-11-16 17:05:39 +02:00
										 |  |  | 							//case '\"': res='\"'; break;
 | 
					
						
							|  |  |  | 							//case '\\': res='\\'; break;
 | 
					
						
							|  |  |  | 							//case '/': res='/'; break;
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 							default: { | 
					
						
							| 
									
										
										
										
											2015-11-16 17:05:39 +02:00
										 |  |  | 								res = next; | 
					
						
							|  |  |  | 								//r_err_str="Invalid escape sequence";
 | 
					
						
							|  |  |  | 								//return ERR_PARSE_ERROR;
 | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 							} break; | 
					
						
							|  |  |  | 						} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 						str += res; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					} else { | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 						if (p_str[index] == '\n') | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 							line++; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 						str += p_str[index]; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_token.type = TK_STRING; | 
					
						
							|  |  |  | 				r_token.value = str; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return OK; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			} break; | 
					
						
							|  |  |  | 			default: { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				if (p_str[index] <= 32) { | 
					
						
							|  |  |  | 					index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					break; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				if (p_str[index] == '-' || (p_str[index] >= '0' && p_str[index] <= '9')) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					//a number
 | 
					
						
							|  |  |  | 					const CharType *rptr; | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					double number = String::to_double(&p_str[index], &rptr); | 
					
						
							|  |  |  | 					index += (rptr - &p_str[index]); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					r_token.type = TK_NUMBER; | 
					
						
							|  |  |  | 					r_token.value = number; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					return OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 				} else if ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 					String id; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 					while ((p_str[index] >= 'A' && p_str[index] <= 'Z') || (p_str[index] >= 'a' && p_str[index] <= 'z')) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-08-11 15:10:05 -04:00
										 |  |  | 						id += p_str[index]; | 
					
						
							|  |  |  | 						index++; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					r_token.type = TK_IDENTIFIER; | 
					
						
							|  |  |  | 					r_token.value = id; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					return OK; | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					r_err_str = "Unexpected character."; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Error JSON::_parse_value(Variant &value, Token &token, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	if (token.type == TK_CURLY_BRACKET_OPEN) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:53:31 -03:00
										 |  |  | 		Dictionary d; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Error err = _parse_object(d, p_str, index, p_len, line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (err) | 
					
						
							|  |  |  | 			return err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		value = d; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return OK; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} else if (token.type == TK_BRACKET_OPEN) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-11 08:53:31 -03:00
										 |  |  | 		Array a; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Error err = _parse_array(a, p_str, index, p_len, line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (err) | 
					
						
							|  |  |  | 			return err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		value = a; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} else if (token.type == TK_IDENTIFIER) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		String id = token.value; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (id == "true") | 
					
						
							|  |  |  | 			value = true; | 
					
						
							|  |  |  | 		else if (id == "false") | 
					
						
							|  |  |  | 			value = false; | 
					
						
							|  |  |  | 		else if (id == "null") | 
					
						
							|  |  |  | 			value = Variant(); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			r_err_str = "Expected 'true','false' or 'null', got '" + id + "'."; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return OK; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} else if (token.type == TK_NUMBER) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		value = token.value; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return OK; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	} else if (token.type == TK_STRING) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		value = token.value; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return OK; | 
					
						
							|  |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		r_err_str = "Expected value, got " + String(tk_name[token.type]) + "."; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Error JSON::_parse_array(Array &array, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	Token token; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bool need_comma = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (index < p_len) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		Error err = _get_token(p_str, index, p_len, token, line, r_err_str); | 
					
						
							|  |  |  | 		if (err != OK) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		if (token.type == TK_BRACKET_CLOSE) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 			return OK; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (need_comma) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (token.type != TK_COMMA) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_err_str = "Expected ','"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				need_comma = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				continue; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Variant v; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		if (err) | 
					
						
							|  |  |  | 			return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		array.push_back(v); | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 		need_comma = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-06 19:34:34 +00:00
										 |  |  | 	return ERR_PARSE_ERROR; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Error JSON::_parse_object(Dictionary &object, const CharType *p_str, int &index, int p_len, int &line, String &r_err_str) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bool at_key = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	String key; | 
					
						
							|  |  |  | 	Token token; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	bool need_comma = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	while (index < p_len) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (at_key) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			Error err = _get_token(p_str, index, p_len, token, line, r_err_str); | 
					
						
							|  |  |  | 			if (err != OK) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (token.type == TK_CURLY_BRACKET_CLOSE) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				return OK; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (need_comma) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				if (token.type != TK_COMMA) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					r_err_str = "Expected '}' or ','"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 					need_comma = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (token.type != TK_STRING) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_err_str = "Expected key"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			key = token.value; | 
					
						
							|  |  |  | 			err = _get_token(p_str, index, p_len, token, line, r_err_str); | 
					
						
							|  |  |  | 			if (err != OK) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			if (token.type != TK_COLON) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 				r_err_str = "Expected ':'"; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return ERR_PARSE_ERROR; | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			at_key = false; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			Error err = _get_token(p_str, index, p_len, token, line, r_err_str); | 
					
						
							|  |  |  | 			if (err != OK) | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 				return err; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Variant v; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			err = _parse_value(v, token, p_str, index, p_len, line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 			if (err) | 
					
						
							|  |  |  | 				return err; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 			object[key] = v; | 
					
						
							|  |  |  | 			need_comma = true; | 
					
						
							|  |  |  | 			at_key = true; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-02-06 19:34:34 +00:00
										 |  |  | 	return ERR_PARSE_ERROR; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | Error JSON::parse(const String &p_json, Variant &r_ret, String &r_err_str, int &r_err_line) { | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	const CharType *str = p_json.ptr(); | 
					
						
							|  |  |  | 	int idx = 0; | 
					
						
							|  |  |  | 	int len = p_json.length(); | 
					
						
							|  |  |  | 	Token token; | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	r_err_line = 0; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	String aux_key; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	Error err = _get_token(str, idx, len, token, r_err_line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 	if (err) | 
					
						
							|  |  |  | 		return err; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-05 16:44:50 +01:00
										 |  |  | 	err = _parse_value(r_ret, token, str, idx, len, r_err_line, r_err_str); | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-08 22:40:00 -03:00
										 |  |  | 	return err; | 
					
						
							| 
									
										
										
										
											2014-02-09 22:10:30 -03:00
										 |  |  | } |