Skip to content

Instantly share code, notes, and snippets.

@thennequin
Last active October 10, 2016 22:39
Show Gist options
  • Save thennequin/499e8eedd6feb0c9c85fbcba44c15fae to your computer and use it in GitHub Desktop.
Save thennequin/499e8eedd6feb0c9c85fbcba44c15fae to your computer and use it in GitHub Desktop.
JsonStthm: Easy to use Json parser/writer
#include "JsonStthm.h"
namespace JsonStthm
{
JsonValue::JsonMember::JsonMember(const ImwChar* pName, JsonValue* pValue)
{
m_pName = NULL;
SetName(pName);
m_pValue = pValue;
}
JsonValue::JsonMember::JsonMember(const JsonMember& oSource)
{
m_pName = NULL;
SetName(oSource.m_pName);
m_pValue = new JsonValue(*oSource.m_pValue);
}
JsonValue::JsonMember::~JsonMember()
{
ImwSafeFree(m_pName);
delete m_pValue;
}
void JsonValue::JsonMember::SetName(const ImwChar* pName)
{
ImwSafeFree(m_pName);
if (pName != NULL)
{
int iSize = (strlen(pName) + 1) * sizeof(ImwChar);
m_pName = (ImwChar*)ImwMalloc(iSize);
memcpy(m_pName, pName, iSize);
}
}
JsonValue JsonValue::INVALID = JsonValue::CreateConst();
JsonValue::JsonValue()
{
m_bConst = false;
m_eType = E_TYPE_INVALID;
m_pName = NULL;
m_pNext = NULL;
}
JsonValue::JsonValue(const JsonValue& oSource) : JsonValue()
{
m_bConst = oSource.m_bConst;
*this = oSource;
}
JsonValue::JsonValue(bool bValue) : JsonValue()
{
*this = bValue;
}
JsonValue::JsonValue(const ImwString& sValue) : JsonValue()
{
*this = sValue;
}
JsonValue::JsonValue(const ImwChar* pValue) : JsonValue()
{
*this = pValue;
}
JsonValue::JsonValue(long iValue) : JsonValue()
{
*this = iValue;
}
JsonValue::JsonValue(double fValue) : JsonValue()
{
*this = fValue;
}
JsonValue::~JsonValue()
{
Reset();
}
JsonValue JsonValue::CreateConst()
{
JsonValue oValue;
oValue.m_bConst = true;
return oValue;
}
void JsonValue::InitType(EType eType)
{
if (m_eType != eType)
{
Reset();
m_eType = eType;
switch (m_eType)
{
case E_TYPE_OBJECT:
case E_TYPE_ARRAY:
m_pChild = NULL;
m_pChildLast = NULL;
break;
case E_TYPE_STRING:
m_pString = NULL;
break;
}
}
}
void JsonValue::Reset()
{
if (m_eType != E_TYPE_INVALID)
{
switch (m_eType)
{
case E_TYPE_OBJECT:
case E_TYPE_ARRAY:
{
JsonValue* pChild = m_pChild;
while (pChild != NULL)
{
JsonValue* pTemp = pChild->m_pNext;
delete pChild;
pChild = pTemp;
}
m_pChild = NULL;
m_pChildLast = NULL;
}
break;
case E_TYPE_STRING:
ImwSafeFree(m_pString);
break;
}
m_eType = E_TYPE_INVALID;
}
}
void JsonValue::SetString(const ImwChar* pString)
{
ImwSafeFree(m_pString);
if (NULL != pString)
{
size_t iLen = sizeof(ImwChar) * (1 + strlen(pString));
m_pString = (ImwChar*)ImwMalloc(iLen);
memcpy(m_pString, pString, iLen);
}
}
void JsonValue::Write(ImwString& sOutJson, int iIndent, bool bCompact)
{
if (m_eType == E_TYPE_OBJECT)
{
ImwString sIndent(iIndent, '\t');
ImwString sIndent2(iIndent + 1, '\t');
sOutJson += "{";
//JsonMembers& oMembers = *m_pObject;
JsonValue* pChild = m_pChild;
bool bFirst = true;
//for (JsonMembers::iterator it = oMembers.begin(), itEnd = oMembers.end(); it != itEnd; ++it)
while (pChild != NULL)
{
if (!bFirst)
{
sOutJson += ",";
}
else
{
bFirst = false;
}
if (!bCompact)
{
sOutJson += "\n";
sOutJson += sIndent2;
}
sOutJson += "\"";
WriteStringEscaped(sOutJson, pChild->m_pName);
sOutJson += "\": ";
pChild->Write(sOutJson, iIndent + 1, bCompact);
pChild = pChild->m_pNext;
}
if (!bCompact)
{
sOutJson += "\n";
sOutJson += sIndent;
}
sOutJson += "}";
}
else if (m_eType == E_TYPE_ARRAY)
{
ImwString sIndent(iIndent, '\t');
ImwString sIndent2(iIndent + 1, '\t');
sOutJson += "[";
//JsonArray& oArray = *m_pArray;
JsonValue* pChild = m_pChild;
bool bFirst = true;
//for (JsonArray::iterator it = oArray.begin(), itEnd = oArray.end(); it != itEnd; ++it)
while (pChild != NULL)
{
if (!bFirst)
{
sOutJson += ",";
}
else
{
bFirst = false;
}
if (!bCompact)
{
sOutJson += "\n";
sOutJson += sIndent2;
}
pChild->Write(sOutJson, iIndent + 1, bCompact);
pChild = pChild->m_pNext;
}
if (!bCompact)
{
sOutJson += "\n";
sOutJson += sIndent;
}
sOutJson += "]";
}
else if (m_eType == E_TYPE_STRING)
{
sOutJson += "\"";
WriteStringEscaped(sOutJson, m_pString);
sOutJson += "\"";
}
else if (m_eType == E_TYPE_BOOLEAN)
{
if (m_bBoolean)
{
sOutJson += "true";
}
else
{
sOutJson += "false";
}
}
else if (m_eType == E_TYPE_INTEGER)
{
ImwChar sBuffer[256];
sprintf_s(sBuffer, 256, "%d", m_iInteger);
sOutJson += sBuffer;
}
else if (m_eType == E_TYPE_FLOAT)
{
ImwChar sBuffer[256];
sprintf_s(sBuffer, 256, "%.17Lg", m_fFloat);
sOutJson += sBuffer;
}
else
{
sOutJson += "null";
}
}
void JsonValue::WriteStringEscaped(ImwString& sOutJson, const ImwString& sInput)
{
const ImwChar* pString = sInput.c_str();
while (*pString != '\0')
{
ImwChar cChar = *pString;
if (cChar == '\n')
sOutJson += "\\n";
else if (cChar == '\r')
sOutJson += "\\r";
else if (cChar == '\t')
sOutJson += "\\t";
else if (cChar == '\b')
sOutJson += "\\b";
else if (cChar == '\f')
sOutJson += "\\f";
else if (cChar == '"')
sOutJson += "\\\"";
else if (cChar == '\\')
sOutJson += "\\\\";
else if ((uint8_t)cChar < 0x80)
sOutJson += cChar;
else
{
sOutJson += "\\u";
unsigned int iChar = (unsigned char)cChar;
if ((iChar & 0xF0) == 0xF0) // 4 bytes
{
iChar = ((((uint8_t)*(pString)) & 0x07) << 18) + ((((uint8_t)*(pString + 1)) & 0x3F) << 12) + ((((uint8_t)*(pString + 2)) & 0x3F) << 6) + ((((uint8_t)*(pString + 3)) & 0x3F));
pString += 3;
}
else if ((iChar & 0xF0) == 0xE0) // 3 bytes
{
iChar = ((((uint8_t)*(pString)) & 0x0F) << 12) + ((((uint8_t)*(pString + 1)) & 0x3F) << 6) + ((((uint8_t)*(pString + 2)) & 0x3F));
pString += 2;
}
else if ((iChar & 0xF0) == 0xC0) // 2 byte
{
iChar = ((((uint8_t)*(pString)) & 0x1F) << 6) + ((((uint8_t)*(pString + 1)) & 0x3F));
pString += 1;
}
ImwChar sHexa[5];
const char* const pHexa = "0123456789ABCDEF";
sHexa[0] = pHexa[(iChar >> 12) & 0x0f];
sHexa[1] = pHexa[(iChar >> 8) & 0x0f];
sHexa[2] = pHexa[(iChar >> 4) & 0x0f];
sHexa[3] = pHexa[(iChar) & 0x0f];
sHexa[4] = '\0';
sOutJson += sHexa;
}
++pString;
}
}
void JsonValue::WriteString(ImwString& sOutJson, bool bCompact)
{
Write(sOutJson, 0, bCompact);
}
bool JsonValue::WriteFile(const ImwChar* pFilename, bool bCompact)
{
FILE* pFile = fopen(pFilename, "w");
if (NULL != pFile)
{
ImwString sJson;
WriteString(sJson);
bool bRet = fwrite(sJson.c_str(), sizeof(ImwChar), sJson.length(), pFile) == (sizeof(ImwChar) * sJson.length());
fclose(pFile);
return bRet;
}
return false;
}
size_t JsonValue::GetMemberCount() const
{
/*if (m_eType == E_TYPE_OBJECT)
{
JsonMembers& oMembers = *m_pObject;
return oMembers.size();
}
else if (m_eType == E_TYPE_ARRAY)
{
JsonArray& oArray = *m_pArray;
return oArray.size();
}*/
int iCount = 0;
if (m_eType == E_TYPE_OBJECT || m_eType == E_TYPE_ARRAY)
{
JsonValue* pChild = m_pChild;
while (pChild != NULL)
{
++iCount;
pChild = pChild->m_pNext;
}
}
return iCount;
}
const JsonValue& JsonValue::operator[](const ImwChar* pName) const
{
if (m_eType == E_TYPE_OBJECT)
{
JsonValue* pChild = m_pChild;
while (pChild != NULL)
{
if (strcmp(pChild->m_pName, pName) == 0)
return *pChild;
if (pChild->m_pNext == NULL)
break;
pChild = pChild->m_pNext;
}
}
return JsonValue::INVALID;
}
JsonValue& JsonValue::operator[](const ImwChar* pName)
{
if (m_eType == E_TYPE_INVALID)
InitType(E_TYPE_OBJECT);
if (m_eType == E_TYPE_OBJECT)
{
JsonValue* pChild = m_pChild;
while (pChild != NULL)
{
if (strcmp(pChild->m_pName, pName) == 0)
return *pChild;
if (pChild->m_pNext == NULL)
break;
pChild = pChild->m_pNext;
}
if (!m_bConst)
{
JsonValue* pNewMember = new JsonValue();
pNewMember->m_pName = strdup(pName);
if (NULL != m_pChildLast)
m_pChildLast->m_pNext = pNewMember;
else
m_pChild = pNewMember;
m_pChildLast = pNewMember;
return *pNewMember;
}
}
return JsonValue::INVALID;
}
const JsonValue& JsonValue::operator [](int iIndex) const
{
if (m_eType == E_TYPE_OBJECT || m_eType == E_TYPE_ARRAY)
{
JsonValue* pChild = m_pChild;
int iCurrent = 0;
while (pChild != NULL)
{
if (iCurrent++ == iIndex)
return *pChild;
pChild = pChild->m_pNext;
}
}
return JsonValue::INVALID;
}
JsonValue& JsonValue::operator[](int iIndex)
{
if (m_eType == E_TYPE_INVALID)
InitType(E_TYPE_ARRAY);
if (m_eType == E_TYPE_OBJECT || m_eType == E_TYPE_ARRAY)
{
JsonValue* pChild = m_pChild;
int iCurrent = 0;
while (pChild != NULL)
{
if (iCurrent++ == iIndex)
return *pChild;
if (pChild->m_pNext == NULL)
break;
pChild = pChild->m_pNext;
}
if (m_eType == E_TYPE_ARRAY)
{
do
{
JsonValue* pNewChild = new JsonValue();
if (NULL != m_pChildLast)
m_pChildLast->m_pNext = pNewChild;
else
m_pChild = pNewChild;
m_pChildLast = pNewChild;
}
while (iCurrent++ != iIndex);
return *m_pChildLast;
}
}
return JsonValue::INVALID;
}
JsonValue& JsonValue::operator =(const JsonValue& oValue)
{
if (oValue.m_pName != NULL)
{
m_pName = strdup(oValue.m_pName);
}
if (oValue.m_eType == E_TYPE_OBJECT || oValue.m_eType == E_TYPE_ARRAY)
{
InitType(oValue.m_eType);
JsonValue* pSourceChild = oValue.m_pChild;;
JsonValue* pChild = NULL;
while (pSourceChild != NULL)
{
JsonValue* pNewChild = new JsonValue(*pSourceChild);
if (NULL != m_pChildLast)
m_pChildLast->m_pNext = pNewChild;
else
m_pChild = pNewChild;
m_pChildLast = pNewChild;
pSourceChild = pSourceChild->m_pNext;
}
}
else if (oValue.m_eType == E_TYPE_BOOLEAN)
{
*this = (bool)oValue;
}
else if (oValue.m_eType == E_TYPE_STRING)
{
*this = (ImwString)oValue;
}
else if (oValue.m_eType == E_TYPE_INTEGER)
{
*this = (long)oValue;
}
else if (oValue.m_eType == E_TYPE_FLOAT)
{
*this = (double)oValue;
}
return *this;
}
JsonValue& JsonValue::operator =(const ImwString& sValue)
{
if (!m_bConst)
{
InitType(E_TYPE_STRING);
SetString(sValue.c_str());
}
return *this;
}
JsonValue& JsonValue::operator =(const ImwChar* pValue)
{
if (!m_bConst)
{
if (NULL != pValue)
{
InitType(E_TYPE_STRING);
SetString(pValue);
}
else
{
InitType(E_TYPE_INVALID);
}
}
return *this;
}
JsonValue& JsonValue::operator =(bool bValue)
{
if (!m_bConst)
{
InitType(E_TYPE_BOOLEAN);
m_bBoolean = bValue;
}
return *this;
}
JsonValue& JsonValue::operator =(long iValue)
{
if (!m_bConst)
{
InitType(E_TYPE_INTEGER);
m_iInteger = iValue;
}
return *this;
}
JsonValue& JsonValue::operator =(double fValue)
{
if (!m_bConst)
{
InitType(E_TYPE_FLOAT);
m_fFloat = fValue;
}
return *this;
}
JsonValue& JsonValue::operator +=(const JsonValue& oValue)
{
if (m_eType == E_TYPE_ARRAY)
{
JsonValue* pNewValue = new JsonValue(oValue);
if (NULL != m_pChildLast)
m_pChildLast->m_pNext = pNewValue;
else
m_pChild = pNewValue;
m_pChildLast = pNewValue;
}
else if (m_eType == E_TYPE_STRING)
{
if (oValue.IsString())
{
ImwString sValue = m_pString;
sValue += (ImwString)oValue;
SetString(sValue.c_str());
}
}
return *this;
}
JsonValue::operator const char*() const
{
if (m_eType == E_TYPE_STRING)
return m_pString;
return NULL;
}
JsonValue::operator bool() const
{
if (m_eType == E_TYPE_BOOLEAN)
return m_bBoolean;
return false;
}
JsonValue::operator long() const
{
if (m_eType == E_TYPE_INTEGER)
return m_iInteger;
return 0;
}
JsonValue::operator double() const
{
if (m_eType == E_TYPE_FLOAT)
return m_fFloat;
return 0.0;
}
//Reading
bool JsonValue::IsSpace(ImwChar cChar) {
return cChar == ' ' || (cChar >= '\t' && cChar <= '\r');
}
bool JsonValue::IsDigit(ImwChar cChar)
{
return (cChar >= '0' && cChar <= '9');
}
bool JsonValue::IsXDigit(ImwChar cChar)
{
return (cChar >= '0' && cChar <= '9') || ((cChar & ~' ') >= 'A' && (cChar & ~' ') <= 'F') || ((cChar & ~' ') >= 'a' && (cChar & ~' ') <= 'f');
}
int JsonValue::CharToInt(ImwChar cChar)
{
if (cChar <= '9')
return cChar - '0';
else
return (cChar & ~' ') - 'A' + 10;
}
void JsonValue::SkipSpaces(const ImwChar*& pString)
{
while (IsSpace(*pString)) ++pString;
}
bool JsonValue::ReadSpecialChar(const ImwChar*& pString, CharBuffer& oTempBuffer)
{
if (*pString == 'n') oTempBuffer += '\n';
else if (*pString == 'r') oTempBuffer += '\r';
else if (*pString == 't') oTempBuffer += '\t';
else if (*pString == 'b') oTempBuffer += '\b';
else if (*pString == 'f') oTempBuffer += '\f';
else if (*pString == '"') oTempBuffer += '"';
else if (*pString == '\\') oTempBuffer += '\\';
else if (*pString == 'u')
{
int iChar = 0;
for (int i = 0; i < 4; ++i)
{
if (IsXDigit(*++pString))
iChar = iChar * 16 + CharToInt((unsigned char)*pString);
else
return false;
}
if (iChar < 0x0080)
{
oTempBuffer += iChar;
}
else if (iChar >= 0x80 && iChar < 0x800)
{
oTempBuffer += 0xC0 | (iChar >> 6);
oTempBuffer += 0x80 | (iChar & 0x3F);
}
else if (iChar >= 0x800 && iChar < 0x7FFF)
{
oTempBuffer += 0xE0 | (iChar >> 12);
oTempBuffer += 0x80 | ((iChar >> 6) & 0x3F);
oTempBuffer += 0x80 | (iChar & 0x3F);
}
else if (iChar >= 0x8000 && iChar < 0x7FFFF)
{
oTempBuffer += 0xF0 | (iChar >> 18);
oTempBuffer += 0xE0 | ((iChar >> 12) & 0x3F);
oTempBuffer += 0x80 | ((iChar >> 6) & 0x3F);
oTempBuffer += 0x80 | (iChar & 0x3F);
}
else
{
return false;
}
return true;
}
else
return false;
return true;
}
bool JsonValue::ReadStringValue(const ImwChar*& pString, CharBuffer& oTempBuffer)
{
oTempBuffer.Clear();
while (*pString != 0)
{
if (*pString == '\\')
{
++pString;
if (!ReadSpecialChar(pString, oTempBuffer))
return false;
++pString;
}
else if (*pString == '"')
{
oTempBuffer += '\0';
++pString;
return true;
}
else if ((unsigned int)*pString < ' ' || *pString == '\x7F')
{
return false;
}
else
{
oTempBuffer += *pString;
++pString;
}
}
return false;
}
bool JsonValue::ReadStringValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer)
{
if (ReadStringValue(pString, oTempBuffer))
{
oValue.InitType(E_TYPE_STRING);
oValue.m_pString = oTempBuffer.Take();
//oValue = oTempBuffer.Data();//Use Take();
return true;
}
return false;
}
bool JsonValue::ReadNumericValue(const ImwChar*& pString, JsonValue& oValue)
{
bool bNeg = false;
bool bHasSeparator = false;
long lValue = 0;
if (*pString == '-')
{
++pString;
bNeg = true;
}
while (IsDigit(*pString))
lValue = lValue * 10 + (*pString++ - '0');
if (*pString == '.')
{
++pString;
double fValue = (double)lValue;
double fFraction = 1;
while (IsDigit(*pString))
{
fFraction *= 0.1;
fValue += (*pString++ - '0') * fFraction;
}
if (*pString == 'e' || *pString == 'E')
{
++pString;
double fBase = 10;
if (*pString == '+')
{
++pString;
}
else if (*pString == '-')
{
++pString;
fBase = 0.1;
}
unsigned int iExponent = 0;
while (*pString != 0 && IsDigit(*pString))
iExponent = (iExponent * 10) + (*pString++ - '0');
double fPow = 1;
for (; iExponent; iExponent >>= 1, fBase *= fBase)
if (iExponent & 1)
fPow *= fBase;
fValue *= fPow;
}
oValue = bNeg ? -fValue : fValue;
}
else
{
//TODO manage E/e for long?
oValue = bNeg ? -lValue : lValue;
}
return true;
}
bool JsonValue::ReadObjectValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer)
{
oValue.InitType(JsonValue::E_TYPE_OBJECT);
while (*pString != 0)
{
SkipSpaces(pString);
// Read member name
if (*pString != '"' || !ReadStringValue(++pString, oTempBuffer))
return false;
JsonValue* pNewMember = new JsonValue();
pNewMember->m_pName = oTempBuffer.Take();
SkipSpaces(pString);
if (*pString != ':')
return false;
++pString;
SkipSpaces(pString);
if (!pNewMember->Parse(pString, oTempBuffer))
{
delete pNewMember;
return false;
}
if (oValue.m_pChild == NULL)
{
oValue.m_pChild = pNewMember;
}
else
{
oValue.m_pChildLast->m_pNext = pNewMember;
}
oValue.m_pChildLast = pNewMember;
SkipSpaces(pString);
if (*pString == '}')
{
++pString;
return true;
}
else if (*pString != ',')
{
return false;
}
++pString;
}
return false;
}
bool JsonValue::ReadArrayValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer)
{
oValue.InitType(JsonValue::E_TYPE_ARRAY);
while (*pString != 0)
{
SkipSpaces(pString);
JsonValue* pNewValue = new JsonValue();
if (!pNewValue->Parse(pString, oTempBuffer))
{
delete pNewValue;
return false;
}
if (oValue.m_pChild == NULL)
{
oValue.m_pChild = pNewValue;
}
else
{
oValue.m_pChildLast->m_pNext = pNewValue;
}
oValue.m_pChildLast = pNewValue;
SkipSpaces(pString);
if (*pString == ']')
{
++pString;
return true;
}
else if (*pString != ',')
{
return false;
}
++pString;
}
return false;
}
int JsonValue::ReadString(const ImwChar* pJson)
{
if (pJson != NULL)
{
CharBuffer oTempBuffer;
Reset();
const ImwChar* pEnd = pJson;
if (!Parse(pEnd, oTempBuffer))
{
int iLine = 1;
int iReturn = 1;
while (pJson != pEnd)
{
if (*pJson == '\n')
++iLine;
else if (*pJson == '\r')
++iReturn;
++pJson;
}
if (iReturn > iLine)
iLine = iReturn;
return iLine;
}
return 0;
}
return -1;
}
const bool JsonValue::Parse(const ImwChar*& pString, CharBuffer& oTempBuffer)
{
bool bOk = pString != NULL && *pString != 0;
while (*pString != 0 && bOk)
{
while (IsSpace(*pString)) ++pString;
if (*pString == '"')
{
++pString;
if (!ReadStringValue(pString, *this, oTempBuffer))
bOk = false;
break;
}
else if (IsDigit(*pString) || *pString == '-')
{
if (!ReadNumericValue(pString, *this))
bOk = false;
break;
}
else if (pString[0] == 't' && pString[1] == 'r' && pString[2] == 'u' && pString[3] == 'e')
{
pString += 4;
*this = true;
break;
}
else if (pString[0] == 'f' && pString[1] == 'a' && pString[2] == 'l' && pString[3] == 's' && pString[4] == 'e')
{
pString += 5;
*this = false;
break;
}
else if (pString[0] == 'n' && pString[1] == 'u' && pString[2] == 'l' && pString[3] == 'l')
{
pString += 4;
InitType(E_TYPE_INVALID);
break;
}
else if (*pString == '{')
{
++pString;
if (!ReadObjectValue(pString, *this, oTempBuffer))
{
bOk = false;
}
break;
}
else if (*pString == '[')
{
++pString;
if (!ReadArrayValue(pString, *this, oTempBuffer))
bOk = false;
break;
}
else
{
//Error
bOk = false;
break;
}
}
return bOk;
}
int JsonValue::ReadFile(const ImwChar* pFilename)
{
FILE* pFile = fopen(pFilename, "r");
if (NULL != pFile)
{
Reset();
fseek(pFile, 0, SEEK_END);
long iSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
ImwChar* pString = new ImwChar[iSize / sizeof(ImwChar)];
fread(pString, 1, iSize, pFile);
fclose(pFile);
int iLine = ReadString(pString);
delete pString;
return iLine;
}
return -1;
}
}
#ifndef __IMW_JSON_VALUE_H__
#define __IMW_JSON_VALUE_H__
#include "ImwConfig.h"
#ifndef ImwChar
#define ImwChar char
#endif // ImwChar
#define ImwMalloc(iSize) malloc(iSize)
#define ImwFree(pObj) free(pObj)
#define ImwSafeFree(pObj) {free(pObj); pObj = NULL;}
namespace JsonStthm
{
class JsonValue
{
protected:
template <typename T, int HeapSize = 1024>
struct Buffer
{
public:
Buffer(int iReserve = 8)
{
m_pData = NULL;
m_iSize = m_iCapacity = 0;
m_bUseHeap = true;
Reserve(iReserve);
}
~Buffer()
{
ImwSafeFree(m_pData);
}
Buffer<T>& operator +=(const T& oValue)
{
Push(oValue);
return *this;
}
void Push(const T& oValue)
{
Resize(m_iSize + 1);
if (m_bUseHeap)
m_pHeapData[m_iSize - 1] = oValue;
else
m_pData[m_iSize - 1] = oValue;
}
int Size() const
{
return m_iSize;
}
void Reserve(int iCapacity, bool bForceAlloc = false)
{
if (iCapacity != m_iCapacity)
{
if (!m_bUseHeap || iCapacity >= HeapSize || bForceAlloc)
{
T* pTemp = (T*)ImwMalloc(iCapacity * sizeof(T));
if (NULL != m_pData)
{
memcpy(pTemp, m_pData, (m_iCapacity > iCapacity ? m_iCapacity : iCapacity) * sizeof(T));
ImwFree(m_pData);
}
m_pData = pTemp;
}
m_iCapacity = iCapacity;
}
}
void Resize(int iSize)
{
int iNewCapacity = m_iCapacity > 0 ? m_iCapacity : 8;
while (iSize > iNewCapacity)
iNewCapacity *= 2;
if (iNewCapacity != m_iCapacity)
Reserve(iNewCapacity);
m_iSize = iSize;
}
const T* Data() const { return m_bUseHeap ? m_pHeapData : m_pData; }
T* Take()
{
ImwChar* pTemp;
if (m_bUseHeap)
{
pTemp = (T*)ImwMalloc(m_iSize * sizeof(T));
memcpy(pTemp, m_pHeapData, m_iSize * sizeof(T));
}
else
{
pTemp = m_pData;
m_pData = NULL;
}
m_iCapacity = 0;
m_iSize = 0;
m_bUseHeap = true;
return pTemp;
}
void Clear()
{
m_iSize = 0;
}
protected:
T m_pHeapData[HeapSize];
T* m_pData;
int m_iSize;
int m_iCapacity;
bool m_bUseHeap;
};
typedef Buffer<ImwChar> CharBuffer;
struct JsonMember
{
public:
JsonMember(const ImwChar* pName = NULL, JsonValue* pValue = NULL);
JsonMember(const JsonMember& oSource);
~JsonMember();
void SetName(const ImwChar* pName);
ImwChar* m_pName;
JsonValue* m_pValue;
};
struct ParseInfos;
public:
enum EType
{
E_TYPE_INVALID, //null
E_TYPE_OBJECT, //JsonMembers
E_TYPE_ARRAY, //JsonArray
E_TYPE_STRING, //ImwString
E_TYPE_BOOLEAN, //bool
E_TYPE_INTEGER, //long
E_TYPE_FLOAT //double
};
static JsonValue INVALID;
public:
JsonValue();
JsonValue(const JsonValue& oSource);
JsonValue(bool bValue);
JsonValue(const ImwString& sValue);
JsonValue(const ImwChar* pValue);
JsonValue(long iValue);
JsonValue(double fValue);
~JsonValue();
void InitType(EType eType);
int ReadString(const ImwChar* pJson);
int ReadFile(const ImwChar* pFilename);
void WriteString(ImwString& sOutJson, bool bCompact = false);
bool WriteFile(const ImwChar* pFilename, bool bCompact = false);
bool IsObject() const { return m_eType == E_TYPE_OBJECT; }
bool IsArray() const { return m_eType == E_TYPE_ARRAY; }
bool IsBoolean() const { return m_eType == E_TYPE_BOOLEAN; }
bool IsString() const { return m_eType == E_TYPE_STRING; }
bool IsIntefer() const { return m_eType == E_TYPE_INTEGER; }
bool IsFloat() const { return m_eType == E_TYPE_FLOAT; }
size_t GetMemberCount() const;
const JsonValue& operator [](const ImwChar* pName) const;
JsonValue& operator [](const ImwChar* pName);
const JsonValue& operator [](int iIndex) const;
JsonValue& operator [](int iIndex);
JsonValue& operator =(const JsonValue& oValue);
JsonValue& operator =(const ImwString& sValue);
JsonValue& operator =(const ImwChar* pValue);
JsonValue& operator =(bool bValue);
JsonValue& operator =(long iValue);
JsonValue& operator =(double fValue);
JsonValue& operator +=(const JsonValue& oValue);
operator const char*() const;
operator bool() const;
operator long() const;
operator double() const;
protected:
static JsonValue CreateConst();
void Reset();
void SetString(const ImwChar* pString);
void Write(ImwString& sOutJson, int iIndent, bool bCompact);
static void WriteStringEscaped(ImwString& sOutJson, const ImwString& sInput);
bool m_bConst;
EType m_eType;
ImwChar* m_pName;
JsonValue* m_pNext;
union
{
struct
{
JsonValue* m_pChild;
JsonValue* m_pChildLast;
};
ImwChar* m_pString;
bool m_bBoolean;
long m_iInteger;
double m_fFloat;
};
const bool Parse(const ImwChar*& pString, CharBuffer& oTempBuffer);
static inline bool IsSpace(ImwChar cChar);
static inline bool IsDigit(ImwChar cChar);
static inline bool IsXDigit(ImwChar cChar);
static inline int CharToInt(ImwChar cChar);
static inline void SkipSpaces(const ImwChar*& pString);
static inline bool ReadSpecialChar(const ImwChar*& pString, CharBuffer& oTempBuffer);
static inline bool ReadStringValue(const ImwChar*& pString, CharBuffer& oTempBuffer);
static inline bool ReadStringValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer);
static inline bool ReadNumericValue(const ImwChar*& pString, JsonValue& oValue);
static inline bool ReadObjectValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer);
static inline bool ReadArrayValue(const ImwChar*& pString, JsonValue& oValue, CharBuffer& oTempBuffer);
};
}
#endif // __IMW_JSON_VALUE_H__
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment