jmisc.hpp 13 KB

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