remstrvar.cpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. #include "remvar.h"
  2. #include "conv.h"
  3. #define _IS_VALID_VT(vt) ((vt > CRemStringVariable::VT_Invalid) && (vt < CRemStringVariable::VT_Last))
  4. #define __min(x, y) ((x) < (y) ? (x) : (y))
  5. #define __max(x, y) ((x) > (y) ? (x) : (y))
  6. /////////////////////////////////////////////////////////////////////////////
  7. CRemStringVariable::CRemStringVariable(void *pData, size_t nCChData, VT vt, const std::type_info &rti, HSHM hShm, bool bIsDbPersitent, const char *pszName, int nIndex, CRemanent *pParent)
  8. : m_name(pszName), m_pszPath(NULL), m_nIndex(nIndex), m_vt(VT_Invalid), m_data({NULL}), m_cache({NULL}), m_nCbString(0),
  9. m_pParent(pParent), m_nUpdates(0), m_bMustLog(false), m_bIsDbPersitent(bIsDbPersitent), m_nCbVarpath(0), m_nCbLog(0)
  10. {
  11. if(!pData || !hShm || !nCChData || !_IS_VALID_VT(vt))
  12. {
  13. ASSERT(false);
  14. return;
  15. }
  16. m_vt = vt;
  17. m_data.pVoid = pData;
  18. m_hShm = hShm;
  19. memset(m_szLog, 0, sizeof(m_szLog));
  20. if( (rti == typeid(char)) ||
  21. (rti == typeid(signed char)) ||
  22. (rti == typeid(unsigned char)))
  23. {
  24. switch(vt)
  25. {
  26. case VT_Latin1:
  27. case VT_UTF_8:
  28. m_nCbBuffer = nCChData;
  29. m_cache.pVoid = ::malloc(m_nCbBuffer);
  30. zeroTerm(m_data, nCChData - 1);
  31. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  32. m_nCbString = strlen(m_cache.pszMbs);
  33. break;
  34. case VT_UTF_16:
  35. case VT_UTF_32:
  36. case VT_Unicode:
  37. ASSERT(false);
  38. return;
  39. default:
  40. ASSERT(false);
  41. return;
  42. }
  43. }
  44. else if(rti == typeid(char16_t))
  45. {
  46. switch(vt)
  47. {
  48. case VT_UTF_16:
  49. m_nCbBuffer = nCChData * sizeof(char16_t);
  50. m_cache.pVoid = malloc(m_nCbBuffer);
  51. zeroTerm(m_data, nCChData - 1);
  52. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  53. m_nCbString = wcs16len(m_cache.pszWc16) * sizeof(char16_t);
  54. break;
  55. case VT_Unicode:
  56. case VT_Latin1:
  57. case VT_UTF_8:
  58. case VT_UTF_32:
  59. ASSERT(false);
  60. return;
  61. default:
  62. ASSERT(false);
  63. return;
  64. }
  65. }
  66. else if(rti == typeid(char32_t))
  67. {
  68. switch(vt)
  69. {
  70. case VT_UTF_32:
  71. m_nCbBuffer = nCChData * sizeof(char32_t);
  72. m_cache.pVoid = malloc(m_nCbBuffer);
  73. zeroTerm(m_data, nCChData - 1);
  74. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  75. m_nCbString = wcs32len(m_cache.pszWc32) * sizeof(char32_t);
  76. break;
  77. case VT_Unicode:
  78. case VT_Latin1:
  79. case VT_UTF_8:
  80. case VT_UTF_16:
  81. ASSERT(false);
  82. return;
  83. default:
  84. ASSERT(false);
  85. return;
  86. }
  87. }
  88. else if(rti == typeid(wchar_t))
  89. {
  90. switch(vt)
  91. {
  92. case VT_Unicode:
  93. m_nCbBuffer = nCChData * sizeof(wchar_t);
  94. m_cache.pVoid = malloc(m_nCbBuffer);
  95. zeroTerm(m_data, nCChData - 1);
  96. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  97. m_nCbString = wcslen(m_cache.pszWcs) * sizeof(wchar_t);
  98. break;
  99. case VT_Latin1:
  100. case VT_UTF_8:
  101. case VT_UTF_16:
  102. case VT_UTF_32:
  103. ASSERT(false);
  104. return;
  105. default:
  106. ASSERT(false);
  107. return;
  108. }
  109. }
  110. else
  111. {
  112. ASSERT(false);
  113. }
  114. }
  115. CRemStringVariable::~CRemStringVariable(void)
  116. {
  117. }
  118. /////////////////////////////////////////////////////////////////////////////
  119. void CRemStringVariable::InitPath(CRemanent *pParent, const char *pszMemberName)
  120. {
  121. if(!pszMemberName)
  122. pszMemberName = "";
  123. if(pParent)
  124. {
  125. m_path = pParent->GetPath();
  126. if(m_path.size() > 0)
  127. m_path += "/";
  128. m_path += pszMemberName;
  129. if(m_nIndex >= 0)
  130. {
  131. char szIndex[32];
  132. sprintf(szIndex, "[%d]", m_nIndex);
  133. m_path += szIndex;
  134. }
  135. }
  136. else
  137. {
  138. m_path = pszMemberName;
  139. }
  140. m_pszPath = m_path.c_str();
  141. m_nCbVarpath = m_path.length();
  142. }
  143. #if 0
  144. static int _fnprintf(FILE *f, size_t n, const char * format, ...)
  145. {
  146. if(!n)
  147. return 0;
  148. int nRet;
  149. char *pszBuffer = malloc(n);
  150. va_list args;
  151. va_start (args, format);
  152. nRet = vsnprintf(pszBuffer, n, format, args);
  153. va_end (args);
  154. if(nRet > 0)
  155. nRet = (int)fwrite(pszBuffer, nRet, 1, f);
  156. free(pszBuffer);
  157. return nRet;
  158. }
  159. #endif
  160. bool CRemStringVariable::SaveJSON(FILE *f, int nIndent, bool bValueOnly, bool bWriteComma)
  161. {
  162. if(m_bIsDbPersitent)
  163. return true;
  164. size_t nToWrite;
  165. if(bWriteComma)
  166. {
  167. if(fprintf(f, ",") < 0)
  168. return false;
  169. }
  170. if(!bValueOnly)
  171. {
  172. if(fprintf(f, "\n") < 0)
  173. return false;
  174. if(nIndent > 0)
  175. {
  176. if(fprintf(f, "%*s", nIndent * _JSON_SPACES_PER_TAB, "") < 0)
  177. return false;
  178. }
  179. if(fprintf(f, "\"%s\": ", m_name.c_str()) < 0)
  180. return false;
  181. }
  182. switch(m_vt)
  183. {
  184. case VT_Latin1:
  185. case VT_UTF_8:
  186. if(fputc('\"', f) == EOF)
  187. return false;
  188. nToWrite = _MIN(m_nCbString, (m_nCbBuffer - 1));
  189. if(fwrite(m_cache.pszMbs, 1, nToWrite, f) != nToWrite)
  190. return false;
  191. if(fputc('\"', f) == EOF)
  192. return false;
  193. break;
  194. default:
  195. break;
  196. }
  197. return true;
  198. }
  199. void CRemStringVariable::CreateMembersTable(CRemVarTable &vt)
  200. {
  201. if(!m_bIsDbPersitent)
  202. vt.AddVar(static_cast<CRemanent*>(this));
  203. }
  204. bool CRemStringVariable::SetJSONValue(const Json::Value &jv, bool fLock)
  205. {
  206. if(jv.type() != Json::stringValue)
  207. return false;
  208. const char *pszStr = jv.asCString();
  209. if(!pszStr || !*pszStr)
  210. {
  211. memset(m_cache.pVoid, 0, m_nCbBuffer);
  212. if(fLock) Lock();
  213. memset(m_data.pVoid, 0, m_nCbBuffer);
  214. if(fLock) Unlock();
  215. return true;
  216. }
  217. size_t nLen = strlen(pszStr);
  218. switch(m_vt)
  219. {
  220. case VT_Latin1:
  221. Utf8ToLatin1(pszStr, nLen, m_cache.pszMbs, m_nCbBuffer);
  222. m_nCbString = strlen(m_cache.pszMbs);
  223. break;
  224. case VT_UTF_8:
  225. if(nLen >= m_nCbBuffer)
  226. nLen = m_nCbBuffer - 1;
  227. memset(m_cache.pszMbs, 0, m_nCbBuffer);
  228. memcpy(m_cache.pszMbs, pszStr, nLen);
  229. m_nCbString = nLen;
  230. break;
  231. case VT_UTF_16:
  232. Utf8ToUtf16(pszStr, nLen, m_cache.pszWc16, m_nCbBuffer / sizeof(char16_t));
  233. m_nCbString = wcs16len(m_cache.pszWc16) * sizeof(char16_t);
  234. break;
  235. case VT_UTF_32:
  236. Utf8ToUtf32(pszStr, nLen, m_cache.pszWc32, m_nCbBuffer / sizeof(char32_t));
  237. m_nCbString = wcs32len(m_cache.pszWc32) * sizeof(char32_t);
  238. break;
  239. case VT_Unicode:
  240. Utf8ToWcs(pszStr, nLen, m_cache.pszWcs, m_nCbBuffer / sizeof(wchar_t));
  241. m_nCbString = wcslen(m_cache.pszWcs) * sizeof(wchar_t);
  242. break;
  243. default:
  244. return false;
  245. }
  246. if(fLock) Lock();
  247. memcpy(m_data.pVoid, m_cache.pVoid, m_nCbBuffer);
  248. if(fLock) Unlock();
  249. return true;
  250. }
  251. unsigned long long CRemStringVariable::CheckUpdateShm(bool fLock)
  252. {
  253. CHECK_UPDATE_SHM_RETVAL rv = {1, 0};
  254. if(m_bIsDbPersitent)
  255. return rv.nRetval;
  256. size_t nCChBuf = 0;
  257. if(fLock)
  258. Lock();
  259. if(shmChanged(false))
  260. {
  261. switch(m_vt)
  262. {
  263. case VT_Latin1:
  264. nCChBuf = m_nCbBuffer - 1;
  265. zeroTerm(m_data, nCChBuf);
  266. m_nCbString = strlen(m_data.pszMbs);
  267. m_nCbLog = ::Latin1ToUtf8(m_data.pszMbs, m_nCbString, m_szLog, _RL_MAX_STRVAL_LENGTH);
  268. break;
  269. case VT_UTF_8:
  270. nCChBuf = m_nCbBuffer - 1;
  271. zeroTerm(m_data, nCChBuf);
  272. m_nCbString = strlen(m_data.pszMbs);
  273. m_nCbLog = _MIN(m_nCbString, _RL_MAX_STRVAL_LENGTH - 1);
  274. memcpy(m_szLog, m_data.pszMbs, m_nCbLog);
  275. m_szLog[m_nCbLog] = '\0';
  276. break;
  277. case VT_UTF_16:
  278. nCChBuf = m_nCbBuffer / sizeof(char16_t) - 1;
  279. zeroTerm(m_data, nCChBuf);
  280. m_nCbString = wcs16len(m_data.pszWc16) * sizeof(char16_t);
  281. m_nCbLog = ::Utf16ToUtf8(m_data.pszWc16, m_nCbString / sizeof(char16_t), m_szLog, _RL_MAX_STRVAL_LENGTH);
  282. break;
  283. case VT_UTF_32:
  284. nCChBuf = m_nCbBuffer / sizeof(char32_t) - 1;
  285. zeroTerm(m_data, nCChBuf);
  286. m_nCbString = wcs32len(m_data.pszWc32) * sizeof(char32_t);
  287. m_nCbLog = ::Utf32ToUtf8(m_data.pszWc32, m_nCbString / sizeof(char32_t), m_szLog, _RL_MAX_STRVAL_LENGTH);
  288. break;
  289. case VT_Unicode:
  290. nCChBuf = m_nCbBuffer / sizeof(wchar_t) - 1;
  291. zeroTerm(m_data, nCChBuf);
  292. m_nCbString = wcslen(m_data.pszWcs) * sizeof(wchar_t);
  293. m_nCbLog = ::WcsToUtf8(m_data.pszWcs, m_nCbString / sizeof(wchar_t), m_szLog, _RL_MAX_STRVAL_LENGTH);
  294. break;
  295. default:
  296. if(fLock)
  297. Unlock();
  298. return rv.nRetval;
  299. }
  300. memcpy(m_cache.pVoid, m_data.pVoid, m_nCbBuffer);
  301. rv.nUpdated = 1;
  302. }
  303. if(fLock)
  304. Unlock();
  305. if(rv.nUpdated)
  306. {
  307. m_bMustLog = true;
  308. m_nUpdates++;
  309. }
  310. return rv.nRetval;
  311. }
  312. void CRemStringVariable::Log(time_t ts, CRemLogger &rlogger)
  313. {
  314. if(!m_bIsDbPersitent && m_bMustLog)
  315. {
  316. rlogger.Log(m_pszPath, m_nCbVarpath, 0.0, m_szLog, m_nCbLog, ts, false);
  317. m_bMustLog = false;
  318. }
  319. }
  320. bool CRemStringVariable::shmChanged(bool fLock)
  321. {
  322. bool bRet;
  323. if(fLock) Lock();
  324. bRet = !!memcmp(m_cache.pVoid, m_data.pVoid, m_nCbString + 1);
  325. if(fLock) Unlock();
  326. return bRet;
  327. }
  328. void CRemStringVariable::Lock(void)
  329. {
  330. ::GfaIpcLockSHM(m_hShm);
  331. }
  332. void CRemStringVariable::Unlock(void)
  333. {
  334. ::GfaIpcUnlockSHM(m_hShm);
  335. }
  336. void CRemStringVariable::zeroTerm(volatile V_Ptr &rp, size_t at)
  337. {
  338. switch(m_vt)
  339. {
  340. case VT_Latin1:
  341. case VT_UTF_8:
  342. rp.pszMbs[at] = '\0';
  343. break;
  344. case VT_UTF_16:
  345. rp.pszWc16[at] = (char16_t)0;
  346. break;
  347. case VT_UTF_32:
  348. rp.pszWc32[at] = (char32_t)0;
  349. break;
  350. case VT_Unicode:
  351. rp.pszWcs[at] = L'\0';
  352. break;
  353. default:
  354. ASSERT(false);
  355. return;
  356. }
  357. }