#define nullptr 0

#include "json.h"
#include <stdlib.h>
#include <string>
#include <algorithm>
#include <cstdlib>
#include <cstdio>
#include <climits>
#include <string.h>
#include <functional>
#include <cctype>
#include <stack>
#include <cerrno>

#ifndef WIN32
#define _stricmp strcasecmp
#endif

#ifdef _MSC_VER
#define snprintf sprintf_s
#endif

using namespace json;

namespace json
{
	enum StackDepthType
	{
		InObject,
		InArray
	};
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Helper functions
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static std::string Trim(const std::string& str)
{
	std::string s = str;
	
	// remove white space in front
	s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun<int, int>(std::isspace))));
	
	// remove trailing white space
	s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), s.end());
	
	return s;
}

// Finds the position of the first " character that is NOT preceeded immediately by a \ character.
// In JSON, \" is valid and has a different meaning than the escaped " character.
static size_t GetQuotePos(const std::string& str, size_t start_pos = 0)
{
	bool found_slash = false;
	for (size_t i = start_pos; i < str.length(); i++)
	{
		char c = str[i];
		if ((c == '\\') && !found_slash)
		{
			found_slash = true;
			continue;
		}
		else if ((c == '\"') && !found_slash)
			return i;
		
		found_slash = false;
	}
	
	return std::string::npos;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Value::Value(const Value& v) : mValueType(v.mValueType)
{
	switch (mValueType)
	{
		case StringVal		: mStringVal = v.mStringVal; break;
		case IntVal			: mIntVal = v.mIntVal; mFloatVal = (float)v.mIntVal; mDoubleVal = (double)v.mIntVal; break;
		case FloatVal		: mFloatVal = v.mFloatVal; mIntVal = (int)v.mFloatVal; mDoubleVal = (double)v.mDoubleVal; break;
		case DoubleVal		: mDoubleVal = v.mDoubleVal; mIntVal = (int)v.mDoubleVal; mFloatVal = (float)v.mDoubleVal; break;
		case BoolVal		: mBoolVal = v.mBoolVal; break;
		case ObjectVal		: mObjectVal = v.mObjectVal; break;
		case ArrayVal		: mArrayVal = v.mArrayVal; break;
		default				: break;
	}
}

Value& Value::operator =(const Value& v)
{
	if (&v == this)
		return *this;

	mValueType = v.mValueType;

	switch (mValueType)
	{
		case StringVal		: mStringVal = v.mStringVal; break;
		case IntVal			: mIntVal = v.mIntVal; mFloatVal = (float)v.mIntVal; mDoubleVal = (double)v.mIntVal; break;
		case FloatVal		: mFloatVal = v.mFloatVal; mIntVal = (int)v.mFloatVal; mDoubleVal = (double)v.mDoubleVal; break;
		case DoubleVal		: mDoubleVal = v.mDoubleVal; mIntVal = (int)v.mDoubleVal; mFloatVal = (float)v.mDoubleVal; break;
		case BoolVal		: mBoolVal = v.mBoolVal; break;
		case ObjectVal		: mObjectVal = v.mObjectVal; break;
		case ArrayVal		: mArrayVal = v.mArrayVal; break;
		default				: break;
	}

	return *this;
}

Value& Value::operator [](size_t idx)
{
	if (mValueType != ArrayVal)
		throw std::runtime_error("json mValueType==ArrayVal required");

	return mArrayVal[idx];
}

const Value& Value::operator [](size_t idx) const
{
	if (mValueType != ArrayVal)
		throw std::runtime_error("json mValueType==ArrayVal required");

	return mArrayVal[idx];
}

Value& Value::operator [](const std::string& key)
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal[key];
}

Value& Value::operator [](const char* key)
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal[key];
}

const Value& Value::operator [](const char* key) const
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal[key];
}

const Value& Value::operator [](const std::string& key) const
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal[key];
}

void Value::Clear()
{
	mValueType = NULLVal;
}

size_t Value::size() const
{
	if ((mValueType != ObjectVal) && (mValueType != ArrayVal))
		return 1;

	return mValueType == ObjectVal ? mObjectVal.size() : mArrayVal.size();
}

bool Value::HasKey(const std::string &key) const
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal.HasKey(key);
}

int Value::HasKeys(const std::vector<std::string> &keys) const
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal.HasKeys(keys);
}

int Value::HasKeys(const char **keys, int key_count) const
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal.HasKeys(keys, key_count);
}

int Value::ToInt() const		
{
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");

	return mIntVal;
}

float Value::ToFloat() const		
{
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");
	
	return mFloatVal;
}

double Value::ToDouble() const	
{
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");

	return mDoubleVal;
}

bool Value::ToBool() const		
{
	if (mValueType != BoolVal)
		throw std::runtime_error("json mValueType==BoolVal required");
	
	return mBoolVal;
}

const std::string& Value::ToString() const	
{
	if (mValueType != StringVal)
		throw std::runtime_error("json mValueType==StringVal required");
	
	return mStringVal;
}

Object Value::ToObject() const	
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal;
}

Array Value::ToArray() const		
{
	if (mValueType != ArrayVal)
		throw std::runtime_error("json mValueType==ArrayVal required");

	return mArrayVal;
}

Value::operator int() const
{ 
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");

	return mIntVal;
}

Value::operator float() const 			
{	
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");

	return mFloatVal;
}

Value::operator double() const
{
	if (!IsNumeric())
		throw std::runtime_error("json mValueType==IsNumeric() required");

	return mDoubleVal;
}

Value::operator bool() const 			
{
	if (mValueType != BoolVal)
		throw std::runtime_error("json mValueType==BoolVal required");

	return mBoolVal;
}

Value::operator std::string() const 	
{
	if (mValueType != StringVal)
		throw std::runtime_error("json mValueType==StringVal required");

	return mStringVal;
}

Value::operator Object() const 		
{
	if (mValueType != ObjectVal)
		throw std::runtime_error("json mValueType==ObjectVal required");

	return mObjectVal;
}

Value::operator Array() const 			
{
	if (mValueType != ArrayVal)
		throw std::runtime_error("json mValueType==ArrayVal required");

	return mArrayVal;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Array::Array()
{
}

Array::Array(const Array& a) : mValues(a.mValues)
{
}

Array& Array::operator =(const Array& a)
{
	if (&a == this)
		return *this;

	Clear();
	mValues = a.mValues;

	return *this;
}

Value& Array::operator [](size_t i)
{
	return mValues[i];
}

const Value& Array::operator [](size_t i) const
{
	return mValues[i];
}


Array::ValueVector::const_iterator Array::begin() const
{
	return mValues.begin();
}

Array::ValueVector::const_iterator Array::end() const
{
	return mValues.end();
}

Array::ValueVector::iterator Array::begin()
{
	return mValues.begin();
}

Array::ValueVector::iterator Array::end()
{
	return mValues.end();
}

void Array::push_back(const Value& v)
{
	mValues.push_back(v);
}

void Array::insert(size_t index, const Value& v)
{
	mValues.insert(mValues.begin() + index, v);
}

size_t Array::size() const
{
	return mValues.size();
}

void Array::Clear()
{
	mValues.clear();
}

Array::ValueVector::iterator Array::find(const Value& v)
{
	return std::find(mValues.begin(), mValues.end(), v);
}

Array::ValueVector::const_iterator Array::find(const Value& v) const
{
	return std::find(mValues.begin(), mValues.end(), v);
}

bool Array::HasValue(const Value& v) const
{
	return find(v) != end();
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Object::Object()
{
}

Object::Object(const Object& obj) : mValues(obj.mValues)
{

}

Object& Object::operator =(const Object& obj)
{
	if (&obj == this)
		return *this;

	Clear();
	mValues = obj.mValues;

	return *this;
}

Value& Object::operator [](const std::string& key)
{
	return mValues[key];
}

const Value& Object::operator [](const std::string& key) const
{
	ValueMap::const_iterator it = mValues.find(key);
	return it->second;
}

Value& Object::operator [](const char* key)
{
	return mValues[key];
}

const Value& Object::operator [](const char* key) const
{
	ValueMap::const_iterator it = mValues.find(key);
	return it->second;
}

Object::ValueMap::const_iterator Object::begin() const
{
	return mValues.begin();
}

Object::ValueMap::const_iterator Object::end() const
{
	return mValues.end();
}

Object::ValueMap::iterator Object::begin()
{
	return mValues.begin();
}

Object::ValueMap::iterator Object::end()
{
	return mValues.end();
}

Object::ValueMap::iterator Object::find(const std::string& key)
{
	return mValues.find(key);
}

Object::ValueMap::const_iterator Object::find(const std::string& key) const
{
	return mValues.find(key);
}

bool Object::HasKey(const std::string& key) const
{
	return find(key) != end();
}

int Object::HasKeys(const std::vector<std::string>& keys) const
{
	for (size_t i = 0; i < keys.size(); i++)
	{
		if (!HasKey(keys[i]))
			return (int)i;
	}
	
	return -1;
}

int Object::HasKeys(const char** keys, int key_count) const
{
	for (int i = 0; i < key_count; i++)
		if (!HasKey(keys[i]))
			return i;
	
	return -1;
}

void Object::Clear()
{
	mValues.clear();
}


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
std::string SerializeArray(const Array& a);
static std::string EscapeJSONString(const std::string& in);

std::string SerializeValue(const Value& v)
{
	std::string str;

	static const int BUFF_SZ = 500;
	char buff[BUFF_SZ];
	switch (v.GetType())
	{
		case IntVal			: snprintf(buff, BUFF_SZ, "%d", (int)v); str = buff; break;
		case FloatVal		: snprintf(buff, BUFF_SZ, "%f", (float)v); str = buff; break;
		case DoubleVal		: snprintf(buff, BUFF_SZ, "%f", (double)v); str = buff; break;
		case BoolVal		: str = v ? "true" : "false"; break;
		case NULLVal		: str = "null"; break;
		case ObjectVal		: str = Serialize(v); break;
		case ArrayVal		: str = SerializeArray(v); break;
        case StringVal		: str = "\"" + EscapeJSONString((std::string)v) + "\""; break;
	}

    // snprintf creates commas on german computers
    // json expets decimal points, so replace all commas with decimal points
    if(v.GetType() == FloatVal || v.GetType() == DoubleVal)
    {
        for(unsigned int i = 0; i < str.size(); i++)
            if(str[i] == ',')
                str[i] = '.';
    }

	return str;
}

std::string SerializeArray(const Array& a)
{
	std::string str = "[";

	bool first = true;
	for (size_t i = 0; i < a.size(); i++)
	{
		const Value& v = a[i];
		if (!first)
			str += std::string(",");

		str += SerializeValue(v);

		first = false;
	}

	str += "]";
	return str;
}

// in can be utf-8
static std::string EscapeJSONString(const std::string &in)
{
    std::string out = "";

    for (std::string::size_type i = 0; i < in.length(); i++)
    {
        switch (in[i])
        {
            case '"'  : out += "\\\""; break;
            case '\\' : out += "\\\\"; break;
            case '/'  : out += "\\/"; break;
            case '\t' : out += "\\t"; break;
            case '\n' : out += "\\n"; break;
            case '\r' : out += "\\r"; break;
            case '\b' :	out += "\\b"; break;
            case '\f' : out += "\\f"; break;
            default   : out += in[i]; break;
        }
    }

    return out;
}

std::string json::Serialize(const Value& v)
{
	std::string str;

	bool first = true;
	
	if (v.GetType() == ObjectVal)
	{
		str = "{";
		Object obj = v.ToObject();
		for (Object::ValueMap::const_iterator it = obj.begin(); it != obj.end(); ++it)
		{
			if (!first)
				str += std::string(",");

			str += std::string("\"") + it->first + std::string("\":") + SerializeValue(it->second);
			first = false;
		}

		str += "}";
	}
	else if (v.GetType() == ArrayVal)
	{
		str = "[";
		Array a = v.ToArray();
		for (Array::ValueVector::const_iterator it = a.begin(); it != a.end(); ++it)
		{
			if (!first)
				str += std::string(",");
			
			str += SerializeValue(*it);
			first = false;
		}
		
		str += "]";
			
	}
	// else it's not valid JSON, as a JSON data structure must be an array or an object. We'll return an empty string.
		
	
	return str;
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
static Value DeserializeArray(std::string& str, std::stack<StackDepthType>& depth_stack);
static Value DeserializeObj(const std::string& _str, std::stack<StackDepthType>& depth_stack);

static Value DeserializeInternal(const std::string& _str, std::stack<StackDepthType>& depth_stack)
{
	Value v;
	
	std::string str = Trim(_str);
	if (str[0] == '{')
	{
		// Error: Began with a { but doesn't end with one
		if (str[str.length() - 1] != '}')
			return Value();
		
		depth_stack.push(InObject);
		v = DeserializeObj(str, depth_stack);
		if ((v.GetType() == NULLVal) || (depth_stack.top() != InObject))
			return v;
		
		depth_stack.pop();
	}
	else if (str[0] == '[')
	{
		// Error: Began with a [ but doesn't end with one
		if (str[str.length() - 1] != ']')
			return Value();
		
		depth_stack.push(InArray);
		v = DeserializeArray(str, depth_stack);
		if ((v.GetType() == NULLVal) || (depth_stack.top() != InArray))
			return v;
		
		depth_stack.pop();
	}
	else
	{
		// Will never get here unless _str is not valid JSON
		return Value();
	}
	
	return v;
}

static size_t GetEndOfArrayOrObj(const std::string& str, std::stack<StackDepthType>& depth_stack)
{
	size_t i = 1;
	bool in_quote = false;
	size_t original_count = depth_stack.size();
	
	for (; i < str.length(); i++)
	{
		if (str[i] == '\"')
		{
			if (str[i - 1] != '\\')
				in_quote = !in_quote;
		}
		else if (!in_quote)
		{
			if (str[i] == '[')
				depth_stack.push(InArray);
			else if (str[i] == '{')
				depth_stack.push(InObject);
			else if (str[i] == ']')
			{
				StackDepthType t = depth_stack.top();
				if (t != InArray)
				{
					// expected to be closing an array but instead we're inside an object block.
					// Example problem: {]}
					return std::string::npos;
				}
				
				size_t count = depth_stack.size();
				depth_stack.pop();
				if (count == original_count)
					break;
			}
			else if (str[i] == '}')
			{
				StackDepthType t = depth_stack.top();
				if (t != InObject)
				{
					// expected to be closing an object but instead we're inside an array.
					// Example problem: [}]
					return std::string::npos;
				}
					
				size_t count = depth_stack.size();
				depth_stack.pop();
				if (count == original_count)
					break;
			}
		}
	}
	
	return i;
}

static std::string UnescapeJSONString(const std::string& str)
{
	std::string s = "";
	
	for (std::string::size_type i = 0; i < str.length(); i++)
	{
		char c = str[i];
		if ((c == '\\') && (i + 1 < str.length()))
		{
			int skip_ahead = 1;
			unsigned int hex;
			std::string hex_str;
			
			switch (str[i+1])
			{
				case '"' : 	s.push_back('\"'); break;
				case '\\': 	s.push_back('\\'); break;
				case '/' : 	s.push_back('/'); break;
				case 't' : 	s.push_back('\t'); break;
				case 'n' : 	s.push_back('\n'); break;
				case 'r' : 	s.push_back('\r'); break;
				case 'b' :	s.push_back('\b'); break;
				case 'f' : 	s.push_back('\f'); break;
				case 'u' : 	skip_ahead = 5;
					hex_str = str.substr(i + 4, 2);
					hex = (unsigned int)std::strtoul(hex_str.c_str(), nullptr, 16);
					s.push_back((char)hex);
					break;
					
				default: break;
			}
			
			i += skip_ahead;
		}
		else
			s.push_back(c);
	}
	
	return Trim(s);
}

static Value DeserializeValue(std::string& str, bool* had_error, std::stack<StackDepthType>& depth_stack)
{
	Value v;

	*had_error = false;
	str = Trim(str);

	if (str.length() == 0)
		return v;

	if (str[0] == '[')
	{
		// This value is an array, determine the end of it and then deserialize the array
		depth_stack.push(InArray);
		size_t i = GetEndOfArrayOrObj(str, depth_stack);
		if (i == std::string::npos)
		{
			*had_error = true;
			return Value();
		}
		
		std::string array_str = str.substr(0, i + 1);
		v = Value(DeserializeArray(array_str, depth_stack));
		str = str.substr(i + 1, str.length());
	}
	else if (str[0] == '{')
	{
		// This value is an object, determine the end of it and then deserialize the object
		depth_stack.push(InObject);
		size_t i = GetEndOfArrayOrObj(str, depth_stack);

		if (i == std::string::npos)
		{
			*had_error = true;
			return Value();
		}

		std::string obj_str = str.substr(0, i + 1);
		v = Value(DeserializeInternal(obj_str, depth_stack));
		str = str.substr(i + 1, str.length());
	}
	else if (str[0] == '\"')
	{
		// This value is a string
		size_t end_quote = GetQuotePos(str, 1);
		if (end_quote == std::string::npos)
		{
			*had_error = true;
			return Value();
		}

		v = Value(UnescapeJSONString(str.substr(1, end_quote - 1)));
		str = str.substr(end_quote + 1, str.length());
	}
	else
	{
		// it's not an object, string, or array so it's either a boolean or a number or null.
		// Numbers can contain an exponent indicator ('e') or a decimal point.
		bool has_dot = false;
		bool has_e = false;
		std::string temp_val;
		size_t i = 0;
		bool found_digit = false;

		for (; i < str.length(); i++)
		{
			if (str[i] == '.')
			{
				if (!found_digit)
				{
					// As per JSON standards, there must be a digit preceding a decimal point
					*had_error = true;
					return Value();
				}

				has_dot = true;
			}
			else if ((str[i] == 'e') || (str[i] == 'E'))
			{		
				if ((_stricmp(temp_val.c_str(), "fals") != 0) && (_stricmp(temp_val.c_str(), "tru") != 0))
				{
					// it's not a boolean, check for scientific notation validity. This will also trap booleans with extra 'e' characters like falsee/truee
					if (!found_digit)
					{
						// As per JSON standards, a digit must precede the 'e' notation
						*had_error = true;
						return Value();
					}
					else if (has_e)
					{
						// multiple 'e' characters not allowed
						*had_error = true;
						return Value();
					}

					has_e = true;
				}
			}
			else if (str[i] == ']')
			{
				if (depth_stack.empty() || (depth_stack.top() != InArray))
				{
					*had_error = true;
					return Value();
				}
				
				depth_stack.pop();
			}
			else if (str[i] == '}')
			{
				if (depth_stack.empty() || (depth_stack.top() != InObject))
				{
					*had_error = true;
					return Value();
				}
				
				depth_stack.pop();
			}
			else if (str[i] == ',')
				break;			
			else if ((str[i] == '[') || (str[i] == '{'))
			{
				// error, we're supposed to be processing things besides arrays/objects in here
				*had_error = true;
				return Value();
			}

			if (!std::isspace(str[i]))
			{
				if (std::isdigit(str[i]))
					found_digit = true;

				temp_val += str[i];
			}
		}

		// store all floating point as doubles. This will also set the float and int values as well.
		if (_stricmp(temp_val.c_str(), "true") == 0)
			v = Value(true);
		else if (_stricmp(temp_val.c_str(), "false") == 0)
			v = Value(false);
		else if (has_e || has_dot)
		{
			char* end_char;
			errno = 0;
			double d = strtod(temp_val.c_str(), &end_char);
			if ((errno != 0) || (*end_char != '\0'))
			{
				// invalid conversion or out of range
				*had_error = true;
				return Value();
			}

			v = Value(d);
		}
		else if (_stricmp(temp_val.c_str(), "null") == 0)
			v = Value();
		else
		{
			// Check if the value is beyond the size of an int and if so, store it as a double
			char* end_char;
			errno = 0;
			long int ival = strtol(temp_val.c_str(), &end_char, 10);
			if (*end_char != '\0')
			{
				// invalid character sequence, not a number
				*had_error = true;
				return Value();
			}
			else if ((errno == ERANGE) && ((ival == LONG_MAX) || (ival == LONG_MIN)))
			{
				// value is out of range for a long int, should be a double then. See if we can convert it correctly.
				errno = 0;
				double dval = strtod(temp_val.c_str(), &end_char);
				if ((errno != 0) || (*end_char != '\0'))
				{
					// error in conversion or it's too big for a double
					*had_error = true;
					return Value();
				}

				v = Value(dval);
			}
			else if ((ival >= INT_MIN) && (ival <= INT_MAX))
			{
				// valid integer range
				v = Value((int)ival);
			}
			else
			{
				// probably running on a very old OS since this block implies that long isn't the same size as int.
				// int is guaranteed to be at least 16 bits and long 32 bits...however nowadays they're almost
				// always the same 32 bit size. But it's possible someone is running this on a very old architecture
				// so for correctness, we'll error out here
				*had_error = true;
				return Value();
			}
		}

		str = str.substr(i, str.length());
	}

	return v;
}

static Value DeserializeArray(std::string& str, std::stack<StackDepthType>& depth_stack)
{
	Array a;
	bool had_error = false;

	str = Trim(str);

	// Arrays begin and end with [], so if we don't find one, it's an error
	if ((str[0] == '[') && (str[str.length() - 1] == ']'))
		str = str.substr(1, str.length() - 2);
	else
		return Value();

	// extract out all values from the array (remember, a value can also be an array or an object)
	while (str.length() > 0)
	{
		std::string tmp;

		size_t i = 0;
		for (; i < str.length(); i++)
		{
			// If we get to an object or array, parse it:
			if ((str[i] == '{') || (str[i] == '['))
			{
				Value v = DeserializeValue(str, &had_error, depth_stack);
				if (had_error)
					return Value();
				
				if (v.GetType() != NULLVal)
					a.push_back(v);

				break;
			}

			bool terminate_parsing = false;

			if ((str[i] == ',') || (str[i] == ']'))
				terminate_parsing = true;			// hit the end of a value, parse it in the next block
			else
			{
				// keep grabbing chars to build up the value
				tmp += str[i];
				if  (i == str.length() - 1)
					terminate_parsing = true; // end of string, finish parsing
			}

			if (terminate_parsing)
			{
				Value v = DeserializeValue(tmp, &had_error, depth_stack);
				if (had_error)
					return Value();
				
				if (v.GetType() != NULLVal)
					a.push_back(v);

				str = str.substr(i + 1, str.length());
				break;
			}
		}
	}

	return a;
}

static Value DeserializeObj(const std::string& _str, std::stack<StackDepthType>& depth_stack)
{
	Object obj;

	std::string str = Trim(_str);

	// Objects begin and end with {} so if we don't find a pair, it's an error
	if ((str[0] != '{') && (str[str.length() - 1] != '}'))
		return Value();
	else
		str = str.substr(1, str.length() - 2);

	// Get all key/value pairs in this object...
	while (str.length() > 0)
	{
		// Get the key name
		size_t start_quote_idx = GetQuotePos(str);
		size_t end_quote_idx = GetQuotePos(str, start_quote_idx + 1);
		size_t colon_idx = str.find(':', end_quote_idx);

		if ((start_quote_idx == std::string::npos) || (end_quote_idx == std::string::npos) || (colon_idx == std::string::npos))
			return Value();	// can't find key name
		
		std::string key = str.substr(start_quote_idx + 1, end_quote_idx - start_quote_idx - 1);
		if (key.length() == 0)
			return Value();

		bool had_error = false;
		str = str.substr(colon_idx + 1, str.length());

		// We have the key, now extract the value from the string
		obj[key] = DeserializeValue(str, &had_error, depth_stack);
		if (had_error)
			return Value();
	}

	return obj;
}

Value json::Deserialize(const std::string &str)
{
	std::stack<StackDepthType> depth_stack;
	return DeserializeInternal(str, depth_stack);
}

