#include "restvar.h" #include "conv.h" #define _IS_VALID_VT(vt) ((vt > CRestStringVariable::VT_Invalid) && (vt < CRestStringVariable::VT_Last)) ///////////////////////////////////////////////////////////////////////////// CRestStringVariable::CRestStringVariable(void *pData, size_t nCChData, VT vt, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, CRest *pParent) : m_name(pszName), m_pszPath(NULL), m_nIndex(nIndex), m_vt(VT_Invalid), m_data({NULL}), m_nCbBuffer(0), m_pszUTF8(NULL), m_nCbUTF8(0), m_pParent(pParent), m_nCbVarpath(0) { if(!pData || !hShm || !nCChData || !_IS_VALID_VT(vt)) { ASSERT(false); return; } m_vt = vt; m_data.pVoid = pData; m_hShm = hShm; if( (rti == typeid(char)) || (rti == typeid(signed char)) || (rti == typeid(unsigned char))) { switch(vt) { case VT_Latin1: case VT_UTF_8: m_nCbBuffer = nCChData; zeroTerm(m_data, nCChData - 1); break; default: ASSERT(false); return; } } else if(rti == typeid(char16_t)) { switch(vt) { case VT_UTF_16: m_nCbBuffer = nCChData * sizeof(char16_t); zeroTerm(m_data, nCChData - 1); break; default: ASSERT(false); return; } } else if(rti == typeid(char32_t)) { switch(vt) { case VT_UTF_32: m_nCbBuffer = nCChData * sizeof(char32_t); zeroTerm(m_data, nCChData - 1); break; default: ASSERT(false); return; } } else if(rti == typeid(wchar_t)) { switch(vt) { case VT_Unicode: m_nCbBuffer = nCChData * sizeof(wchar_t); zeroTerm(m_data, nCChData - 1); break; default: ASSERT(false); return; } } else { ASSERT(false); } m_nCbUTF8 = m_nCbBuffer * 4; m_pszUTF8 = new char[m_nCbUTF8]; memset(m_pszUTF8, 0, m_nCbUTF8); } CRestStringVariable::~CRestStringVariable(void) { if(m_pszUTF8) delete [] m_pszUTF8; } ///////////////////////////////////////////////////////////////////////////// void CRestStringVariable::CreateMembersTable(CRestVarTable &vt) { vt.AddVar(static_cast(this)); } void CRestStringVariable::InitPath(CRest *pParent, const char *pszMemberName, int nIndex) { CRest::CreatePath(pParent, pszMemberName, nIndex, m_path); m_pszPath = m_path.c_str(); m_nCbVarpath = m_path.length(); } void CRestStringVariable::GetValue(int nReqIndex, json_t* pjtMap) { json_array_append_new(pjtMap, GetValue(nReqIndex)); } json_t* CRestStringVariable::GetValue(int nReqIndex) { json_t *pjtVal = NULL; size_t nCChBuf = 0; size_t nCChString = 0; memset(m_pszUTF8, 0, m_nCbUTF8); Lock(); switch(m_vt) { case VT_Latin1: nCChBuf = m_nCbBuffer - 1; zeroTerm(m_data, nCChBuf); nCChString = strlen(m_data.pszMbs); ::Latin1ToUtf8(m_data.pszMbs, nCChString, m_pszUTF8, m_nCbUTF8); pjtVal = json_string(m_pszUTF8); break; case VT_UTF_8: nCChBuf = m_nCbBuffer - 1; zeroTerm(m_data, nCChBuf); nCChString = strlen(m_data.pszMbs); memcpy(m_pszUTF8, m_data.pszMbs, nCChString); pjtVal = json_string(m_pszUTF8); break; case VT_UTF_16: nCChBuf = m_nCbBuffer / sizeof(char16_t) - 1; zeroTerm(m_data, nCChBuf); nCChString = wcs16len(m_data.pszWc16); ::Utf16ToUtf8(m_data.pszWc16, nCChString, m_pszUTF8, m_nCbUTF8); pjtVal = json_string(m_pszUTF8); break; case VT_UTF_32: nCChBuf = m_nCbBuffer / sizeof(char32_t) - 1; zeroTerm(m_data, nCChBuf); nCChString = wcs32len(m_data.pszWc32); ::Utf32ToUtf8(m_data.pszWc32, nCChString, m_pszUTF8, m_nCbUTF8); pjtVal = json_string(m_pszUTF8); break; case VT_Unicode: nCChBuf = m_nCbBuffer / sizeof(wchar_t) - 1; zeroTerm(m_data, nCChBuf); nCChString = wcslen(m_data.pszWcs); ::WcsToUtf8(m_data.pszWcs, nCChString, m_pszUTF8, m_nCbUTF8); pjtVal = json_string(m_pszUTF8); break; default: ASSERT(false); break; } Unlock(); if(pjtVal) return CreateValueObject(nReqIndex, m_pszPath, m_nIndex, json_typeof(pjtVal), m_name.c_str(), pjtVal); else return CreateStatusObject(nReqIndex, -1, "Unexpected Error!", m_pszPath); } json_t* CRestStringVariable::SetValue(int nReqIndex, json_t *pjtVal) { if(!pjtVal) return CreateStatusObject(nReqIndex, -1, "Unexpected error!", GetPath()); int nCode = 0; const char *pszMsg = NULL; size_t nCChBuf = 0, nCChString = 0; int nType = json_typeof(pjtVal); if(nType == JSON_STRING) { const char *pszUtf8 = json_string_value(pjtVal); size_t nLen = strlen(pszUtf8); Lock(); switch(m_vt) { case VT_Latin1: nCChBuf = m_nCbBuffer; nCChString = ::Utf8ToLatin1(pszUtf8, nLen, m_data.pszMbs, nCChBuf); zeroTerm(m_data, nCChString); break; case VT_UTF_8: nCChBuf = m_nCbBuffer - 1; nCChString = __min(nLen, nCChBuf); memcpy(m_data.pszMbs, pszUtf8, nCChString); zeroTerm(m_data, nCChString); break; case VT_UTF_16: nCChBuf = m_nCbBuffer / sizeof(char16_t); nCChString = ::Utf8ToUtf16(pszUtf8, nLen, m_data.pszWc16, nCChBuf) / sizeof(char16_t); zeroTerm(m_data, nCChString); break; case VT_UTF_32: nCChBuf = m_nCbBuffer / sizeof(char32_t); nCChString = ::Utf8ToUtf32(pszUtf8, nLen, m_data.pszWc32, nCChBuf) / sizeof(char32_t); zeroTerm(m_data, nCChString); break; case VT_Unicode: nCChBuf = m_nCbBuffer / sizeof(wchar_t); nCChString = ::Utf8ToWcs(pszUtf8, nLen, m_data.pszWcs, nCChBuf) / sizeof(wchar_t); zeroTerm(m_data, nCChString); break; default: ASSERT(false); break; } Unlock(); } else { pszMsg = "Cannot assign incompatible JSON type to string variable!"; nCode = 1; } return CreateStatusObject(nReqIndex, nCode, pszMsg, GetPath()); } ///////////////////////////////////////////////////////////////////////////// void CRestStringVariable::Lock(void) { ::GfaIpcLockSHM(m_hShm); } void CRestStringVariable::Unlock(void) { ::GfaIpcUnlockSHM(m_hShm); } void CRestStringVariable::zeroTerm(volatile V_Ptr &rp, size_t at) { switch(m_vt) { case VT_Latin1: case VT_UTF_8: rp.pszMbs[at] = '\0'; break; case VT_UTF_16: rp.pszWc16[at] = (char16_t)0; break; case VT_UTF_32: rp.pszWc32[at] = (char32_t)0; break; case VT_Unicode: rp.pszWcs[at] = L'\0'; break; default: ASSERT(false); break; } }