shmstrvar.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. #include "shmvar.h"
  2. #include "conv.h"
  3. #include <QDebug>
  4. #define _IS_VALID_VT(vt) ((vt > CShmStringVariable::VT_Invalid) && (vt < CShmStringVariable::VT_Last))
  5. #define __min(x, y) ((x) < (y) ? (x) : (y))
  6. #define __max(x, y) ((x) > (y) ? (x) : (y))
  7. CShmStringVariable::CShmStringVariable(void *pData, size_t nCChData, VT vt, const std::type_info &rti, HSHM hShm, const char *pszName, int nIndex, QObject *pParent)
  8. : QObject(pParent), m_vt(VT_Invalid), m_data({NULL}), m_cache({NULL}), m_nCbString(0), m_varName(pszName)
  9. {
  10. if(!pData || !hShm || !nCChData || !_IS_VALID_VT(vt))
  11. {
  12. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid parameter!");
  13. return;
  14. }
  15. m_vt = vt;
  16. m_data.pVoid = pData;
  17. m_hShm = hShm;
  18. setObjectName(QStringLiteral("CShmStringVariable"));
  19. if((m_nIndex = nIndex) >= 0)
  20. {
  21. m_varName += QString("%1%2%3").arg('[').arg(nIndex).arg(']');
  22. }
  23. if( (rti == typeid(char)) ||
  24. (rti == typeid(signed char)) ||
  25. (rti == typeid(unsigned char)))
  26. {
  27. switch(vt)
  28. {
  29. case VT_Latin1:
  30. case VT_UTF_8:
  31. m_nCbBuffer = nCChData;
  32. m_cache.pVoid = ::malloc(m_nCbBuffer);
  33. zeroTerm(m_data, nCChData - 1);
  34. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  35. m_nCbString = strlen(m_cache.pszMbs);
  36. break;
  37. case VT_UTF_16:
  38. case VT_UTF_32:
  39. case VT_Unicode:
  40. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!");
  41. return;
  42. default:
  43. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!");
  44. return;
  45. }
  46. }
  47. else if(rti == typeid(char16_t))
  48. {
  49. switch(vt)
  50. {
  51. case VT_UTF_16:
  52. m_nCbBuffer = nCChData * sizeof(char16_t);
  53. m_cache.pVoid = malloc(m_nCbBuffer);
  54. zeroTerm(m_data, nCChData - 1);
  55. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  56. m_nCbString = wcs16len(m_cache.pszWc16) * sizeof(char16_t);
  57. break;
  58. case VT_Unicode:
  59. case VT_Latin1:
  60. case VT_UTF_8:
  61. case VT_UTF_32:
  62. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!");
  63. return;
  64. default:
  65. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!");
  66. return;
  67. }
  68. }
  69. else if(rti == typeid(char32_t))
  70. {
  71. switch(vt)
  72. {
  73. case VT_UTF_32:
  74. m_nCbBuffer = nCChData * sizeof(char32_t);
  75. m_cache.pVoid = malloc(m_nCbBuffer);
  76. zeroTerm(m_data, nCChData - 1);
  77. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  78. m_nCbString = wcs32len(m_cache.pszWc32) * sizeof(char32_t);
  79. break;
  80. case VT_Unicode:
  81. case VT_Latin1:
  82. case VT_UTF_8:
  83. case VT_UTF_16:
  84. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!");
  85. return;
  86. default:
  87. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!");
  88. return;
  89. }
  90. }
  91. else if(rti == typeid(wchar_t))
  92. {
  93. switch(vt)
  94. {
  95. case VT_Unicode:
  96. m_nCbBuffer = nCChData * sizeof(wchar_t);
  97. m_cache.pVoid = malloc(m_nCbBuffer);
  98. zeroTerm(m_data, nCChData - 1);
  99. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  100. m_nCbString = wcslen(m_cache.pszWcs) * sizeof(wchar_t);
  101. break;
  102. case VT_Latin1:
  103. case VT_UTF_8:
  104. case VT_UTF_16:
  105. case VT_UTF_32:
  106. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "data type does not support encoding type!");
  107. return;
  108. default:
  109. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Invalid string type!");
  110. return;
  111. }
  112. }
  113. else
  114. {
  115. Q_ASSERT_X(false, "CShmStringVariable::CShmStringVariable", "Unrecognized data type!");
  116. }
  117. }
  118. CShmStringVariable::~CShmStringVariable(void)
  119. {
  120. if(m_cache.pVoid)
  121. ::free(m_cache.pVoid);
  122. }
  123. void CShmStringVariable::valRaw(QString &v)
  124. {
  125. switch(m_vt)
  126. {
  127. case VT_Latin1:
  128. v = QString::fromLatin1(m_data.pszMbs, m_nCbString);
  129. break;
  130. case VT_UTF_8:
  131. v = QString::fromUtf8(m_data.pszMbs, m_nCbString);
  132. break;
  133. case VT_UTF_16:
  134. v = QString::fromUtf16(m_data.pszWc16, m_nCbString / sizeof(char16_t));
  135. break;
  136. case VT_UTF_32:
  137. v = QString::fromUcs4(m_data.pszWc32, m_nCbString / sizeof(char32_t));
  138. break;
  139. case VT_Unicode:
  140. v = QString::fromWCharArray(m_data.pszWcs, m_nCbString / sizeof(wchar_t));
  141. break;
  142. default:
  143. // Q_ASSERT_X(false, "CShmStringVariable::valRaw", "Unrecognized string type!");
  144. break;
  145. }
  146. }
  147. QString CShmStringVariable::val(void)
  148. {
  149. QString v;
  150. Lock();
  151. valRaw(v);
  152. Unlock();
  153. return v;
  154. }
  155. void CShmStringVariable::setVal(const QString &val)
  156. {
  157. QByteArray ba;
  158. QVector<uint> vec;
  159. size_t nCbVal = 0, nCChVal = 0;
  160. wchar_t *pszData;
  161. const void *pData;
  162. switch(m_vt)
  163. {
  164. case VT_Latin1:
  165. ba = val.toLatin1();
  166. nCbVal = ba.size();
  167. nCbVal = __min(nCbVal, m_nCbBuffer - 1);
  168. nCChVal = nCbVal;
  169. pData = ba.data();
  170. break;
  171. case VT_UTF_8:
  172. ba = val.toUtf8();
  173. nCbVal = ba.size();
  174. nCbVal = __min(nCbVal, m_nCbBuffer - 1);
  175. nCChVal = nCbVal;
  176. pData = ba.data();
  177. break;
  178. case VT_UTF_16:
  179. nCbVal = val.size() * sizeof(char16_t);
  180. nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(char16_t));
  181. nCChVal = nCbVal / sizeof(char16_t);
  182. pData = val.utf16();
  183. break;
  184. case VT_UTF_32:
  185. vec = val.toUcs4();
  186. nCbVal = vec.size() * sizeof(char32_t);
  187. nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(char32_t));
  188. nCChVal = nCbVal / sizeof(char32_t);
  189. pData = vec.data();
  190. break;
  191. case VT_Unicode:
  192. nCChVal = val.size();
  193. nCbVal = nCChVal * sizeof(wchar_t);
  194. pszData = (wchar_t*)alloca(nCbVal);
  195. val.toWCharArray(pszData);
  196. nCbVal = __min(nCbVal, m_nCbBuffer - sizeof(wchar_t));
  197. nCChVal = nCbVal / sizeof(wchar_t);
  198. pData = pszData;
  199. break;
  200. default:
  201. Q_ASSERT_X(false, "CShmStringVariable::setVal", "Unrecognized string type!");
  202. return;
  203. }
  204. Lock();
  205. m_nCbString = nCbVal;
  206. memcpy(m_cache.pVoid, pData, m_nCbString);
  207. zeroTerm(m_cache, nCChVal);
  208. if(shmChanged(false))
  209. {
  210. memcpy(m_data.pVoid, m_cache.pVoid, m_nCbString);
  211. zeroTerm(m_data, nCChVal);
  212. emitChanged(false);
  213. }
  214. Unlock();
  215. }
  216. void CShmStringVariable::zeroTerm(volatile V_Ptr &rp, size_t at)
  217. {
  218. switch(m_vt)
  219. {
  220. case VT_Latin1:
  221. case VT_UTF_8:
  222. rp.pszMbs[at] = '\0';
  223. break;
  224. case VT_UTF_16:
  225. rp.pszWc16[at] = (char16_t)0;
  226. break;
  227. case VT_UTF_32:
  228. rp.pszWc32[at] = (char32_t)0;
  229. break;
  230. case VT_Unicode:
  231. rp.pszWcs[at] = L'\0';
  232. break;
  233. default:
  234. // Q_ASSERT_X(false, "CShmStringVariable::zeroTerm", "Unrecognized string type!");
  235. return;
  236. }
  237. }
  238. unsigned int CShmStringVariable::vt(void) const
  239. {
  240. return CShmVariable::VT_string;
  241. }
  242. unsigned long long CShmStringVariable::CheckUpdateShm(bool fLock)
  243. {
  244. CHECK_UPDATE_SHM_RETVAL rv = {1, 0};
  245. size_t nCChBuf = 0;
  246. if(fLock)
  247. Lock();
  248. if(shmChanged(false))
  249. {
  250. switch(m_vt)
  251. {
  252. case VT_Latin1:
  253. case VT_UTF_8:
  254. nCChBuf = m_nCbBuffer - 1;
  255. zeroTerm(m_data, nCChBuf);
  256. m_nCbString = strlen(m_data.pszMbs);
  257. break;
  258. case VT_UTF_16:
  259. nCChBuf = m_nCbBuffer / sizeof(char16_t) - 1;
  260. zeroTerm(m_data, nCChBuf);
  261. m_nCbString = wcs16len(m_data.pszWc16) * sizeof(char16_t);
  262. break;
  263. case VT_UTF_32:
  264. nCChBuf = m_nCbBuffer / sizeof(char32_t) - 1;
  265. zeroTerm(m_data, nCChBuf);
  266. m_nCbString = wcs32len(m_data.pszWc32) * sizeof(char32_t);
  267. break;
  268. case VT_Unicode:
  269. nCChBuf = m_nCbBuffer / sizeof(wchar_t) - 1;
  270. zeroTerm(m_data, nCChBuf);
  271. m_nCbString = wcslen(m_data.pszWcs) * sizeof(wchar_t);
  272. break;
  273. default:
  274. return rv.nRetval;
  275. }
  276. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  277. emitChanged(false);
  278. rv.nUpdated = 1;
  279. }
  280. if(fLock)
  281. Unlock();
  282. return rv.nRetval;
  283. }
  284. bool CShmStringVariable::shmChanged(bool fLock)
  285. {
  286. bool bRet;
  287. if(fLock)
  288. Lock();
  289. bRet = !!memcmp(m_cache.pVoid, m_data.pVoid, m_nCbString + 1);
  290. if(fLock)
  291. Unlock();
  292. return bRet;
  293. }
  294. void CShmStringVariable::Lock(void)
  295. {
  296. ::GfaIpcLockSHM(m_hShm);
  297. // qDebug() << "CShmStringVariable::Lock";
  298. }
  299. void CShmStringVariable::Unlock(void)
  300. {
  301. // qDebug() << "CShmStringVariable::Unlock";
  302. ::GfaIpcUnlockSHM(m_hShm);
  303. }
  304. void CShmStringVariable::emitChanged(bool fLock)
  305. {
  306. // qDebug() << "CShmStringVariable: val changed!";
  307. if(fLock)
  308. emit valChanged(val());
  309. else
  310. {
  311. QString v;
  312. valRaw(v);
  313. emit valChanged(v);
  314. }
  315. }