#include "shmvar.h" #include "conv.h" #include #define _IS_VALID_VT(vt) ((vt > CShmStringVariable::VT_Invalid) && (vt < CShmStringVariable::VT_Last)) #define __min(x, y) ((x) < (y) ? (x) : (y)) #define __max(x, y) ((x) > (y) ? (x) : (y)) CShmStringVariable::CShmStringVariable(void *pData, size_t nCChData, VT vt, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, QObject *pParent) : QObject(pParent), m_vt(VT_Invalid), m_data({NULL}), m_cache({NULL}), m_nCbString(0), m_varName(pszName) { if(!pData || !hShm || !nCChData || !_IS_VALID_VT(vt)) { Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid parameter!"); return; } m_vt = vt; m_data.pVoid = pData; m_hShm = hShm; setObjectName(QStringLiteral("CShmStringVariable")); if((m_nIndex = nIndex) >= 0) { m_varName += QString("%1%2%3").arg('[').arg(nIndex).arg(']'); } if( (rti == typeid(char)) || (rti == typeid(signed char)) || (rti == typeid(unsigned char))) { switch(vt) { case VT_Latin1: case VT_UTF_8: m_nCbBuffer = nCChData; m_cache.pVoid = ::malloc(m_nCbBuffer); zeroTerm(m_data, nCChData - 1); memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer); m_nCbString = strlen(m_cache.pszMbs); break; case VT_UTF_16: case VT_UTF_32: case VT_Unicode: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!"); return; default: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!"); return; } } else if(rti == typeid(char16_t)) { switch(vt) { case VT_UTF_16: m_nCbBuffer = nCChData * sizeof(char16_t); m_cache.pVoid = malloc(m_nCbBuffer); zeroTerm(m_data, nCChData - 1); memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer); m_nCbString = wcs16len(m_cache.pszWc16) * sizeof(char16_t); break; case VT_Unicode: case VT_Latin1: case VT_UTF_8: case VT_UTF_32: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!"); return; default: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!"); return; } } else if(rti == typeid(char32_t)) { switch(vt) { case VT_UTF_32: m_nCbBuffer = nCChData * sizeof(char32_t); m_cache.pVoid = malloc(m_nCbBuffer); zeroTerm(m_data, nCChData - 1); memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer); m_nCbString = wcs32len(m_cache.pszWc32) * sizeof(char32_t); break; case VT_Unicode: case VT_Latin1: case VT_UTF_8: case VT_UTF_16: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!"); return; default: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!"); return; } } else if(rti == typeid(wchar_t)) { switch(vt) { case VT_Unicode: m_nCbBuffer = nCChData * sizeof(wchar_t); m_cache.pVoid = malloc(m_nCbBuffer); zeroTerm(m_data, nCChData - 1); memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer); m_nCbString = wcslen(m_cache.pszWcs) * sizeof(wchar_t); break; case VT_Latin1: case VT_UTF_8: case VT_UTF_16: case VT_UTF_32: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!"); return; default: Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!"); return; } } else { Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Unrecognized data type!"); } } CShmStringVariable::~CShmStringVariable(void) { if(m_cache.pVoid) ::free(m_cache.pVoid); } void CShmStringVariable::valRaw(QString &v) { switch(m_vt) { case VT_Latin1: v = QString::fromLatin1(m_data.pszMbs, m_nCbString); break; case VT_UTF_8: v = QString::fromUtf8(m_data.pszMbs, m_nCbString); break; case VT_UTF_16: v = QString::fromUtf16(m_data.pszWc16, m_nCbString / sizeof(char16_t)); break; case VT_UTF_32: v = QString::fromUcs4(m_data.pszWc32, m_nCbString / sizeof(char32_t)); break; case VT_Unicode: v = QString::fromWCharArray(m_data.pszWcs, m_nCbString / sizeof(wchar_t)); break; default: // Q_ASSERT_X(false, "CShmStringVariable::valRaw", "Unrecognized string type!"); break; } } QString CShmStringVariable::val(void) { QString v; Lock(); valRaw(v); Unlock(); return v; } void CShmStringVariable::setVal(const QString &val) { QByteArray ba; QVector vec; size_t nCbVal = 0, nCChVal = 0; wchar_t *pszData; const void *pData; switch(m_vt) { case VT_Latin1: ba = val.toLatin1(); nCbVal = ba.size(); nCbVal = __min(nCbVal, m_nCbBuffer - 1); nCChVal = nCbVal; pData = ba.data(); break; case VT_UTF_8: ba = val.toUtf8(); nCbVal = ba.size(); nCbVal = __min(nCbVal, m_nCbBuffer - 1); nCChVal = nCbVal; pData = ba.data(); break; case VT_UTF_16: nCbVal = val.size() * sizeof(char16_t); nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(char16_t)); nCChVal = nCbVal / sizeof(char16_t); pData = val.utf16(); break; case VT_UTF_32: vec = val.toUcs4(); nCbVal = vec.size() * sizeof(char32_t); nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(char32_t)); nCChVal = nCbVal / sizeof(char32_t); pData = vec.data(); break; case VT_Unicode: nCChVal = val.size(); nCbVal = nCChVal * sizeof(wchar_t); pszData = (wchar_t*)alloca(nCbVal); val.toWCharArray(pszData); nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(wchar_t)); nCChVal = nCbVal / sizeof(wchar_t); pData = pszData; break; default: Q_ASSERT_X(false, "CShmStringVariable::setVal", "Unrecognized string type!"); return; } Lock(); m_nCbString = nCbVal; memcpy(m_cache.pVoid, pData, m_nCbString); zeroTerm(m_cache, nCChVal); if(shmChanged(false)) { memcpy(m_data.pVoid, m_cache.pVoid, m_nCbString); zeroTerm(m_data, nCChVal); emitChanged(false); } Unlock(); } void CShmStringVariable::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: // Q_ASSERT_X(false, "CShmStringVariable::zeroTerm", "Unrecognized string type!"); return; } } unsigned int CShmStringVariable::vt(void) const { return CShmVariable::VT_string; } unsigned long long CShmStringVariable::CheckUpdateShm(bool fLock) { CHECK_UPDATE_SHM_RETVAL rv = {1, 0}; size_t nCChBuf = 0; if(fLock) Lock(); if(shmChanged(false)) { switch(m_vt) { case VT_Latin1: case VT_UTF_8: nCChBuf = m_nCbBuffer - 1; zeroTerm(m_data, nCChBuf); m_nCbString = strlen(m_data.pszMbs); break; case VT_UTF_16: nCChBuf = m_nCbBuffer / sizeof(char16_t) - 1; zeroTerm(m_data, nCChBuf); m_nCbString = wcs16len(m_data.pszWc16) * sizeof(char16_t); break; case VT_UTF_32: nCChBuf = m_nCbBuffer / sizeof(char32_t) - 1; zeroTerm(m_data, nCChBuf); m_nCbString = wcs32len(m_data.pszWc32) * sizeof(char32_t); break; case VT_Unicode: nCChBuf = m_nCbBuffer / sizeof(wchar_t) - 1; zeroTerm(m_data, nCChBuf); m_nCbString = wcslen(m_data.pszWcs) * sizeof(wchar_t); break; default: return rv.nRetval; } memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer); emitChanged(false); rv.nUpdated = 1; } if(fLock) Unlock(); return rv.nRetval; } bool CShmStringVariable::shmChanged(bool fLock) { bool bRet; if(fLock) Lock(); bRet = !!memcmp(m_cache.pVoid, m_data.pVoid, m_nCbString + 1); if(fLock) Unlock(); return bRet; } void CShmStringVariable::Lock(void) { ::GfaIpcLockSHM(m_hShm); // qDebug() << "CShmStringVariable::Lock"; } void CShmStringVariable::Unlock(void) { // qDebug() << "CShmStringVariable::Unlock"; ::GfaIpcUnlockSHM(m_hShm); } void CShmStringVariable::emitChanged(bool fLock) { // qDebug() << "CShmStringVariable: val changed!"; if(fLock) emit valChanged(val()); else { QString v; valRaw(v); emit valChanged(v); } }