void JsonSerializer::deserializeLabel(const char* label)
{
	if (!m_is_first_in_block)
	{
		expectToken(',');
		deserializeToken();
	}
	else
	{
		m_is_first_in_block = false;
	}
	if (!m_is_string_token)
	{
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator)
								<< "\", expected string.";
		deserializeToken();
	}
	if (compareStringN(label, m_token, m_token_size) != 0)
	{
		ErrorProxy(*this).log() << "Unexpected label \""
								<< string(m_token, m_token_size, m_allocator) << "\", expected \""
								<< label << "\".";
		deserializeToken();
	}
	deserializeToken();
	if (m_is_string_token || m_token_size != 1 || m_token[0] != ':')
	{
		ErrorProxy(*this).log() << "Unexpected label \""
								<< string(m_token, m_token_size, m_allocator) << "\", expected \""
								<< label << "\".";
		deserializeToken();
	}
	deserializeToken();
}
bool JsonSerializer::isArrayEnd()
{
	if (m_token == m_data + m_data_size)
	{
		ErrorProxy(*this).log() << "Unexpected end of file while looking for the end of an array.";
		return true;
	}

	return (!m_is_string_token && m_token_size == 1 && m_token[0] == ']');
}
void JsonSerializer::deserializeToken()
{
	m_token += m_token_size;
	if (m_is_string_token)
	{
		++m_token;
	}

	while (m_token < m_data + m_data_size && isDelimiter(*m_token))
	{
		++m_token;
	}
	if (*m_token == '/' && m_token < m_data + m_data_size - 1 && m_token[1] == '/')
	{
		m_token_size = int((m_data + m_data_size) - m_token);
		m_is_string_token = false;
	}
	else if (*m_token == '"')
	{
		++m_token;
		m_is_string_token = true;
		const char* token_end = m_token;
		while (token_end < m_data + m_data_size && *token_end != '"')
		{
			++token_end;
		}
		if (token_end == m_data + m_data_size)
		{
			ErrorProxy(*this).log() << "Unexpected end of file while looking for \".";
			m_token_size = 0;
		}
		else
		{
			m_token_size = int(token_end - m_token);
		}
	}
	else if (isSingleCharToken(*m_token))
	{
		m_is_string_token = false;
		m_token_size = 1;
	}
	else
	{
		m_is_string_token = false;
		const char* token_end = m_token;
		while (token_end < m_data + m_data_size && !isDelimiter(*token_end) &&
			   !isSingleCharToken(*token_end))
		{
			++token_end;
		}
		m_token_size = int(token_end - m_token);
	}
}
void JsonSerializer::expectToken(char expected_token)
{
	if (m_is_string_token || m_token_size != 1 || m_token[0] != expected_token)
	{
		char tmp[2];
		tmp[0] = expected_token;
		tmp[1] = 0;
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator) << "\", expected "
								<< tmp << ".";
		deserializeToken();
	}
}
void JsonSerializer::deserializeArrayItem(char* value, int max_length, const char* default_value)
{
	deserializeArrayComma();
	if (m_is_string_token)
	{
		int size = Math::minimum(max_length - 1, m_token_size);
		copyMemory(value, m_token, size);
		value[size] = '\0';
		deserializeToken();
	}
	else
	{
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator)
								<< "\", expected string.";
		deserializeToken();
		copyString(value, max_length, default_value);
	}
}
void JsonSerializer::deserializeLabel(char* label, int max_length)
{
	if (!m_is_first_in_block)
	{
		expectToken(',');
		deserializeToken();
	}
	else
	{
		m_is_first_in_block = false;
	}
	if (!m_is_string_token)
	{
		ErrorProxy(*this).log() << "Unexpected token \""
								<< string(m_token, m_token_size, m_allocator)
								<< "\", expected string.";
		deserializeToken();
	}
	copyNString(label, max_length, m_token, m_token_size);
	deserializeToken();
	expectToken(':');
	deserializeToken();
}
JsonSerializer::ErrorProxy JsonSerializer::error()
{
	m_is_error = true;
	return ErrorProxy(*this);
}