jmisc.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*##############################################################################
  2. Copyright (C) 2011 HPCC Systems.
  3. All rights reserved. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU Affero General Public License as
  5. published by the Free Software Foundation, either version 3 of the
  6. License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU Affero General Public License for more details.
  11. You should have received a copy of the GNU Affero General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ############################################################################## */
  14. #ifndef __JMISC__
  15. #define __JMISC__
  16. #include "platform.h"
  17. #include <stdio.h>
  18. #include "jexpdef.hpp"
  19. #include "jiface.hpp"
  20. #include "jcrc.hpp"
  21. #include "jlog.hpp"
  22. #ifdef _WIN32
  23. #include <windows.h>
  24. #endif
  25. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) defines 0x00--0x7F and 0xA0--0xFF
  26. // ISO-8859-1 (aka ISO-Latin-1 and IBM-810) is identical to US-ASCII (aka ANSI_X3.4 and ISO-646) in the range 0x00--0x7F
  27. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) is identical to ISO-8859-15 (aka ISO-Latin-9 and IBM-923) except 0xA4 is Currency rather than Euro
  28. // ISO-8859-1 (aka ISO-Latin-1 and IBM-819) is identical to Windows-1252 (aka IBM-5348) and to IBM-1252 except the latter define 0x80--0x9F
  29. #define ASCII_LIKE_CODEPAGE "iso-8859-1"
  30. #define ASCII_LIKE_SUBS_CHAR 0x1a
  31. inline bool isValidAsciiLikeCharacter(unsigned char c) { return ((c < 0x80) || (c >= 0xA0)); }
  32. #define _LOG_TIME MSGFIELD_timeDate
  33. #define _LOG_TID MSGFIELD_thread
  34. #define _LOG_PID MSGFIELD_process //gcc 3.0.4 on Linux defines LOG_PID as 0x1 already in sys/syslog.h
  35. #define _LOG_CLOCK MSGFIELD_milliTime
  36. #define _LOG_HIRESCLOCK MSGFIELD_nanoTime
  37. class StringBuffer;
  38. class ILogIntercept
  39. {
  40. public:
  41. virtual void print(const char *fmt)=0;
  42. virtual void close()=0;
  43. virtual unsigned setLogDetail(unsigned)=0;
  44. };
  45. jlib_decl ILogIntercept* interceptLog(ILogIntercept *intercept); // for custom tracing
  46. //Use openLogFile() to create/append a simple, local component logfile, providing a filename(or filespec).
  47. //Typically used to create a non rolling, local logfile in cwd, using default logfile contents
  48. jlib_decl void openLogFile(StringBuffer & resolvedFS, const char *filename, unsigned detail = 0, bool enterQueueMode = true, bool append = false);
  49. #ifndef DISABLE_PRINTLOG
  50. jlib_decl void PrintLogDirect(const char *msg);
  51. jlib_decl int PrintLog(const char *fmt, ...);
  52. jlib_decl void SPrintLog(const char *fmt,...); // not terminated by LF
  53. #define PrintExceptionLog(_e,_txt) EXCLOG(_e, _txt)
  54. #ifdef _DEBUG
  55. #define PrintLogDebug PrintLog
  56. #else
  57. #define PrintLogDebug 1?0:PrintLog
  58. #endif
  59. #endif
  60. jlib_decl void PrintMemoryStatusLog();
  61. extern jlib_decl StringBuffer & hexdump2string(byte const * in, size32_t inSize, StringBuffer & out);
  62. jlib_decl StringBuffer &addFileTimestamp(StringBuffer &fname, bool daily=false);
  63. jlib_decl FILE *xfopen(const char *path, const char *mode);
  64. jlib_decl const char * queryCcLogName();
  65. jlib_decl StringBuffer& queryCcLogName(const char* wuid, StringBuffer& logname);
  66. jlib_decl char* readarg(char*& curptr);
  67. jlib_decl bool invoke_program(const char *command_line, DWORD &runcode, bool wait=true, const char *outfile=NULL, HANDLE *rethandle=NULL, bool throwException = false);
  68. jlib_decl bool wait_program(HANDLE handle,DWORD &runcode,bool block=true);
  69. jlib_decl bool interrupt_program(HANDLE handle,int signum=-9);
  70. #ifndef _WIN32
  71. jlib_decl bool CopyFile(const char *file, const char *newfile, bool fail);
  72. #endif
  73. //Endian support
  74. inline void _rev2(char *b) { char t=b[0]; b[0]=b[1]; b[1]=t; }
  75. inline void _rev4(char *b) { char t=b[0]; b[0]=b[3]; b[3]=t; t=b[1]; b[1]=b[2]; b[2]=t; }
  76. inline void _rev8(char *b) { char t=b[0]; b[0]=b[7]; b[7]=t; t=b[1]; b[1]=b[6]; b[6]=t; t=b[2]; b[2]=b[5]; b[5]=t; t=b[3]; b[3]=b[4]; b[4]=t; }
  77. inline void _rev(short &v) { _rev2((char *)&v); }
  78. inline void _rev(unsigned short &v) { _rev2((char *)&v); }
  79. inline void _rev(int &v) { _rev4((char *)&v); }
  80. #if defined (_MSC_VER) && _MSC_VER < 1300
  81. inline void _rev(__int32 &v) { _rev4((char *)&v); }
  82. #endif
  83. inline void _rev(unsigned int &v) { _rev4((char *)&v); }
  84. inline void _rev(long &v) { _rev4((char *)&v); }
  85. inline void _rev(unsigned long &v) { _rev4((char *)&v); }
  86. inline void _rev(__int64 &v) { _rev8((char *)&v); }
  87. inline void _rev(unsigned __int64 &v) { _rev8((char *)&v); }
  88. extern jlib_decl void _rev(size32_t len, void * ptr);
  89. #define _REV2(p) _rev2((char *)&p);
  90. #define _REV4(p) _rev4((char *)&p);
  91. #define _REV8(p) _rev8((char *)&p);
  92. #if __BYTE_ORDER == __LITTLE_ENDIAN
  93. #define _WINREV(x) _rev(x)
  94. #define _WINREV2(p) _REV2(p)
  95. #define _WINREV4(p) _REV4(p)
  96. #define _WINREV8(p) _REV8(p)
  97. #define _WINREVN(l,p) _rev(l, p)
  98. #else
  99. #define _WINREV(x)
  100. #define _WINREV2(p)
  101. #define _WINREV4(p)
  102. #define _WINREV8(p)
  103. #define _WINREVN(l,p)
  104. #endif
  105. inline void _cpyrev2(void * _tgt, const void * _src) {
  106. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  107. tgt[1]=src[0]; tgt[0] = src[1];
  108. }
  109. inline void _cpyrev3(void * _tgt, const void * _src) {
  110. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  111. tgt[2] = src[0]; tgt[1]=src[1]; tgt[0] = src[2];
  112. }
  113. inline void _cpyrev4(void * _tgt, const void * _src) {
  114. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  115. tgt[3]=src[0]; tgt[2] = src[1]; tgt[1]=src[2]; tgt[0] = src[3];
  116. }
  117. inline void _cpyrev5(void * _tgt, const void * _src) {
  118. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  119. tgt[4]=src[0];
  120. tgt[3]=src[1]; tgt[2] = src[2]; tgt[1]=src[3]; tgt[0] = src[4];
  121. }
  122. inline void _cpyrev6(void * _tgt, const void * _src) {
  123. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  124. tgt[5]=src[0]; tgt[4] = src[1];
  125. tgt[3]=src[2]; tgt[2] = src[3]; tgt[1]=src[4]; tgt[0] = src[5];
  126. }
  127. inline void _cpyrev7(void * _tgt, const void * _src) {
  128. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  129. tgt[6] = src[0]; tgt[5]=src[1]; tgt[4]=src[2];
  130. tgt[3] = src[3]; tgt[2]=src[4]; tgt[1]=src[5]; tgt[0]=src[6];
  131. }
  132. inline void _cpyrev8(void * _tgt, const void * _src) {
  133. char * tgt = (char *)_tgt; const char * src = (const char *)_src;
  134. tgt[7]=src[0]; tgt[6] = src[1]; tgt[5]=src[2]; tgt[4] = src[3];
  135. tgt[3]=src[4]; tgt[2] = src[5]; tgt[1]=src[6]; tgt[0] = src[7];
  136. }
  137. inline void _cpyrevn(void * _tgt, const void * _src, unsigned len) {
  138. char * tgt = (char *)_tgt; const char * src = (const char *)_src+len;
  139. for (;len;len--) {
  140. *tgt++ = *--src;
  141. }
  142. }
  143. #if __BYTE_ORDER == __LITTLE_ENDIAN
  144. #define _WINCPYREV(x, y, len) _cpyrevn(x, y, len)
  145. #define _WINCPYREV2(x, y) _cpyrev2(x, y)
  146. #define _WINCPYREV4(x, y) _cpyrev4(x, y)
  147. #define _WINCPYREV8(x, y) _cpyrev8(x, y)
  148. #else
  149. #define _WINCPYREV(x, y, len) memcpy(x, y, len)
  150. #define _WINCPYREV2(x, y) memcpy(x, y, 2)
  151. #define _WINCPYREV4(x, y) memcpy(x, y, 4)
  152. #define _WINCPYREV8(x, y) memcpy(x, y, 8)
  153. #endif
  154. #ifdef _WIN32
  155. class jlib_decl C64bitComposite // used to efficiently manage an int64 as two consecutive DWORDS and vice versa
  156. {
  157. private:
  158. LARGE_INTEGER value;
  159. public:
  160. C64bitComposite() {value.QuadPart = 0; }
  161. C64bitComposite(__int64 v) {value.QuadPart = v; }
  162. C64bitComposite(DWORD lo, DWORD hi) {value.LowPart = lo; value.HighPart = hi; }
  163. DWORD getLo() {return value.LowPart; }
  164. LONG getHi() {return value.HighPart; }
  165. __int64 get() {return value.QuadPart; }
  166. void get(DWORD &lo, DWORD &hi) {lo = value.LowPart, hi = value.HighPart; }
  167. C64bitComposite & set(__int64 v) {value.QuadPart = v; return *this; }
  168. C64bitComposite & set(DWORD lo, DWORD hi) {value.LowPart = lo; value.HighPart = hi; return *this; }
  169. C64bitComposite & operator = (__int64 v) {return set(v); }
  170. C64bitComposite & operator += (__int64 v) {value.QuadPart += v; return *this; }
  171. C64bitComposite & operator -= (__int64 v) {value.QuadPart -= v; return *this; }
  172. C64bitComposite & operator ++ () {++value.QuadPart; return * this; }
  173. C64bitComposite & operator -- () {--value.QuadPart; return * this; }
  174. int operator == (const C64bitComposite & s) {return value.QuadPart == s.value.QuadPart; }
  175. int operator != (const C64bitComposite & s) {return value.QuadPart != s.value.QuadPart; }
  176. int operator < (const C64bitComposite & s) {return value.QuadPart < s.value.QuadPart; }
  177. int operator > (const C64bitComposite & s) {return value.QuadPart > s.value.QuadPart; }
  178. int operator <= (const C64bitComposite & s) {return value.QuadPart <= s.value.QuadPart; }
  179. int operator >= (const C64bitComposite & s) {return value.QuadPart >= s.value.QuadPart; }
  180. int operator == (__int64 s) {return value.QuadPart == s; }
  181. int operator != (__int64 s) {return value.QuadPart != s; }
  182. int operator < (__int64 s) {return value.QuadPart < s; }
  183. int operator > (__int64 s) {return value.QuadPart > s; }
  184. int operator <= (__int64 s) {return value.QuadPart <= s; }
  185. int operator >= (__int64 s) {return value.QuadPart >= s; }
  186. };
  187. #endif
  188. // Functions to build and split 64bit integers. Do not depend on the byte order
  189. template<typename T1,typename T2> inline __int64 makeint64(T1 high, T2 low)
  190. {
  191. return (__int64)high<<32 | ((__int64)low & (__int64)0xffffffff);
  192. }
  193. inline __int32 high(__int64 n)
  194. {
  195. return (__int32)(n>>32);
  196. }
  197. inline unsigned __int32 low(__int64 n)
  198. {
  199. return (unsigned __int32)(n & (__int64)0xffffffff);
  200. }
  201. //MORE - We really should restructure this file. Also would this be better with a class interface?
  202. //Handle ^C/break from a console program.
  203. typedef bool (*AbortHandler)(); // return true to exit program
  204. interface IAbortHandler : public IInterface
  205. {
  206. virtual bool onAbort() = 0;
  207. };
  208. #define JLIBERR_UserAbort 0xffffff00
  209. extern jlib_decl void addAbortHandler(AbortHandler handler=NULL); // no parameter means just set the flag for later testing.
  210. extern jlib_decl void addAbortHandler(IAbortHandler & handler);
  211. extern jlib_decl void removeAbortHandler(AbortHandler handler);
  212. extern jlib_decl void removeAbortHandler(IAbortHandler & handler);
  213. extern jlib_decl bool isAborting();
  214. extern jlib_decl void throwAbortException();
  215. extern jlib_decl void throwExceptionIfAborting();
  216. interface IAbortRequestCallback
  217. {
  218. virtual bool abortRequested() = 0;
  219. };
  220. class LocalAbortHandler
  221. {
  222. public:
  223. LocalAbortHandler(AbortHandler _handler=NULL) { handler = _handler; addAbortHandler(handler); }
  224. ~LocalAbortHandler() { removeAbortHandler(handler); }
  225. private:
  226. AbortHandler handler;
  227. };
  228. class LocalIAbortHandler
  229. {
  230. public:
  231. LocalIAbortHandler(IAbortHandler & _handler) : handler(_handler) { addAbortHandler(handler); }
  232. ~LocalIAbortHandler() { removeAbortHandler(handler); }
  233. private:
  234. IAbortHandler & handler;
  235. };
  236. // These are undocumented by Microsoft
  237. #define ENABLE_QUICK_EDIT 0x0040
  238. #define ENABLE_INSERT_MODE 0x0020
  239. class NoQuickEditSection
  240. {
  241. DWORD savedmode;
  242. bool saved;
  243. public:
  244. NoQuickEditSection()
  245. {
  246. #ifdef _WIN32
  247. saved = false;
  248. HANDLE hStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
  249. if (hStdIn)
  250. {
  251. if (::GetConsoleMode(hStdIn, &savedmode))
  252. saved = true;
  253. // Set new console mode w/ QuickEdit disabled
  254. DWORD mode = savedmode & ~(ENABLE_QUICK_EDIT);
  255. if (!::SetConsoleMode(hStdIn, mode))
  256. DBGLOG("SetConsoleMode failed code %d", GetLastError());
  257. ::CloseHandle(hStdIn);
  258. }
  259. #endif
  260. }
  261. ~NoQuickEditSection()
  262. {
  263. #ifdef _WIN32
  264. if (saved)
  265. {
  266. HANDLE hStdIn = ::GetStdHandle(STD_INPUT_HANDLE);
  267. if (hStdIn)
  268. {
  269. ::SetConsoleMode(hStdIn, savedmode);;
  270. ::CloseHandle(hStdIn);
  271. }
  272. }
  273. #endif
  274. }
  275. };
  276. #endif