CCriticalSection using wxWidgets instead of Windows OS calls
[novacoin.git] / util.h
1 // Copyright (c) 2009 Satoshi Nakamoto\r
2 // Distributed under the MIT/X11 software license, see the accompanying\r
3 // file license.txt or http://www.opensource.org/licenses/mit-license.php.\r
4 \r
5 \r
6 #if defined(_MSC_VER) || defined(__BORLANDC__)\r
7 typedef __int64  int64;\r
8 typedef unsigned __int64  uint64;\r
9 #else\r
10 typedef long long  int64;\r
11 typedef unsigned long long  uint64;\r
12 #endif\r
13 #if defined(_MSC_VER) && _MSC_VER < 1300\r
14 #define for  if (false) ; else for\r
15 #endif\r
16 \r
17 #ifndef _MSC_VER\r
18 #define __forceinline  inline\r
19 #endif\r
20 \r
21 #define foreach             BOOST_FOREACH\r
22 #define loop                for (;;)\r
23 #define BEGIN(a)            ((char*)&(a))\r
24 #define END(a)              ((char*)&((&(a))[1]))\r
25 #define UBEGIN(a)           ((unsigned char*)&(a))\r
26 #define UEND(a)             ((unsigned char*)&((&(a))[1]))\r
27 #define ARRAYLEN(array)     (sizeof(array)/sizeof((array)[0]))\r
28 \r
29 #ifdef _WINDOWS\r
30 #define printf              OutputDebugStringF\r
31 #endif\r
32 \r
33 #ifdef snprintf\r
34 #undef snprintf\r
35 #endif\r
36 #define snprintf my_snprintf\r
37 \r
38 #ifndef PRId64\r
39 #if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__MSVCRT__)\r
40 #define PRId64  "I64d"\r
41 #define PRIu64  "I64u"\r
42 #define PRIx64  "I64x"\r
43 #else\r
44 #define PRId64  "lld"\r
45 #define PRIu64  "llu"\r
46 #define PRIx64  "llx"\r
47 #endif\r
48 #endif\r
49 \r
50 // This is needed because the foreach macro can't get over the comma in pair<t1, t2>\r
51 #define PAIRTYPE(t1, t2)    pair<t1, t2>\r
52 \r
53 // Used to bypass the rule against non-const reference to temporary\r
54 // where it makes sense with wrappers such as CFlatData or CTxDB\r
55 template<typename T>\r
56 inline T& REF(const T& val)\r
57 {\r
58     return (T&)val;\r
59 }\r
60 \r
61 \r
62 \r
63 \r
64 \r
65 \r
66 \r
67 \r
68 \r
69 extern bool fDebug;\r
70 extern bool fPrintToDebugger;\r
71 extern bool fPrintToConsole;\r
72 extern map<string, string> mapArgs;\r
73 \r
74 void RandAddSeed();\r
75 void RandAddSeedPerfmon();\r
76 int my_snprintf(char* buffer, size_t limit, const char* format, ...);\r
77 string strprintf(const char* format, ...);\r
78 bool error(const char* format, ...);\r
79 void PrintException(std::exception* pex, const char* pszThread);\r
80 void LogException(std::exception* pex, const char* pszThread);\r
81 void ParseString(const string& str, char c, vector<string>& v);\r
82 string FormatMoney(int64 n, bool fPlus=false);\r
83 bool ParseMoney(const char* pszIn, int64& nRet);\r
84 vector<unsigned char> ParseHex(const char* psz);\r
85 vector<unsigned char> ParseHex(const std::string& str);\r
86 bool FileExists(const char* psz);\r
87 int GetFilesize(FILE* file);\r
88 uint64 GetRand(uint64 nMax);\r
89 int64 GetTime();\r
90 int64 GetAdjustedTime();\r
91 void AddTimeData(unsigned int ip, int64 nTime);\r
92 \r
93 \r
94 \r
95 \r
96 \r
97 \r
98 \r
99 \r
100 \r
101 \r
102 \r
103 \r
104 \r
105 // Wrapper to automatically initialize critical section\r
106 // Could use wxCriticalSection for portability, but it doesn't support TryEnterCriticalSection\r
107 class CCriticalSection\r
108 {\r
109 #ifdef __WXMSW__\r
110 protected:\r
111     CRITICAL_SECTION cs;\r
112 public:\r
113     explicit CCriticalSection() { InitializeCriticalSection(&cs); }\r
114     ~CCriticalSection() { DeleteCriticalSection(&cs); }\r
115     void Enter() { EnterCriticalSection(&cs); }\r
116     void Leave() { LeaveCriticalSection(&cs); }\r
117     bool TryEnter() { return TryEnterCriticalSection(&cs); }\r
118 #else\r
119 protected:\r
120     wxMutex mutex;\r
121 public:\r
122     explicit CCriticalSection() { }\r
123     ~CCriticalSection() { }\r
124     void Enter() { mutex.Lock(); }\r
125     void Leave() { mutex.Unlock(); }\r
126     bool TryEnter() { return mutex.TryLock() == wxMUTEX_NO_ERROR; }\r
127 #endif\r
128 public:\r
129     char* pszFile;\r
130     int nLine;\r
131 };\r
132 \r
133 // Automatically leave critical section when leaving block, needed for exception safety\r
134 class CCriticalBlock\r
135 {\r
136 protected:\r
137     CCriticalSection* pcs;\r
138 public:\r
139     CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); }\r
140     ~CCriticalBlock() { pcs->Leave(); }\r
141 };\r
142 \r
143 // WARNING: This will catch continue and break!\r
144 // break is caught with an assertion, but there's no way to detect continue.\r
145 // I'd rather be careful than suffer the other more error prone syntax.\r
146 // The compiler will optimise away all this loop junk.\r
147 #define CRITICAL_BLOCK(cs)     \\r
148     for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false)  \\r
149     for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)\r
150 \r
151 class CTryCriticalBlock\r
152 {\r
153 protected:\r
154     CCriticalSection* pcs;\r
155 public:\r
156     CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); }\r
157     ~CTryCriticalBlock() { if (pcs) pcs->Leave(); }\r
158     bool Entered() { return pcs != NULL; }\r
159 };\r
160 \r
161 #define TRY_CRITICAL_BLOCK(cs)     \\r
162     for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false)  \\r
163     for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)\r
164 \r
165 \r
166 \r
167 \r
168 \r
169 \r
170 \r
171 \r
172 \r
173 \r
174 \r
175 \r
176 inline int OutputDebugStringF(const char* pszFormat, ...)\r
177 {\r
178     int ret = 0;\r
179 #ifdef __WXDEBUG__\r
180     if (!fPrintToConsole)\r
181     {\r
182         // print to debug.log\r
183         FILE* fileout = fopen("debug.log", "a");\r
184         if (fileout)\r
185         {\r
186             va_list arg_ptr;\r
187             va_start(arg_ptr, pszFormat);\r
188             ret = vfprintf(fileout, pszFormat, arg_ptr);\r
189             va_end(arg_ptr);\r
190             fclose(fileout);\r
191         }\r
192     }\r
193 \r
194     if (fPrintToDebugger)\r
195     {\r
196         // accumulate a line at a time\r
197         static CCriticalSection cs_OutputDebugStringF;\r
198         CRITICAL_BLOCK(cs_OutputDebugStringF)\r
199         {\r
200             static char pszBuffer[50000];\r
201             static char* pend;\r
202             if (pend == NULL)\r
203                 pend = pszBuffer;\r
204             va_list arg_ptr;\r
205             va_start(arg_ptr, pszFormat);\r
206             int limit = END(pszBuffer) - pend - 2;\r
207             int ret = _vsnprintf(pend, limit, pszFormat, arg_ptr);\r
208             va_end(arg_ptr);\r
209             if (ret < 0 || ret >= limit)\r
210             {\r
211                 pend = END(pszBuffer) - 2;\r
212                 *pend++ = '\n';\r
213             }\r
214             else\r
215                 pend += ret;\r
216             *pend = '\0';\r
217             char* p1 = pszBuffer;\r
218             char* p2;\r
219             while (p2 = strchr(p1, '\n'))\r
220             {\r
221                 p2++;\r
222                 char c = *p2;\r
223                 *p2 = '\0';\r
224                 OutputDebugString(p1);\r
225                 *p2 = c;\r
226                 p1 = p2;\r
227             }\r
228             if (p1 != pszBuffer)\r
229                 memmove(pszBuffer, p1, pend - p1 + 1);\r
230             pend -= (p1 - pszBuffer);\r
231         }\r
232     }\r
233 #endif\r
234 \r
235     if (fPrintToConsole)\r
236     {\r
237         // print to console\r
238         va_list arg_ptr;\r
239         va_start(arg_ptr, pszFormat);\r
240         ret = vprintf(pszFormat, arg_ptr);\r
241         va_end(arg_ptr);\r
242     }\r
243     return ret;\r
244 }\r
245 \r
246 \r
247 \r
248 \r
249 \r
250 \r
251 \r
252 \r
253 \r
254 \r
255 inline string i64tostr(int64 n)\r
256 {\r
257     return strprintf("%"PRId64, n);\r
258 }\r
259 \r
260 inline string itostr(int n)\r
261 {\r
262     return strprintf("%d", n);\r
263 }\r
264 \r
265 inline int64 atoi64(const char* psz)\r
266 {\r
267 #ifdef _MSC_VER\r
268     return _atoi64(psz);\r
269 #else\r
270     return strtoll(psz, NULL, 10);\r
271 #endif\r
272 }\r
273 \r
274 inline int64 atoi64(const string& str)\r
275 {\r
276 #ifdef _MSC_VER\r
277     return _atoi64(str.c_str());\r
278 #else\r
279     return strtoll(str.c_str(), NULL, 10);\r
280 #endif\r
281 }\r
282 \r
283 inline int atoi(const string& str)\r
284 {\r
285     return atoi(str.c_str());\r
286 }\r
287 \r
288 inline int roundint(double d)\r
289 {\r
290     return (int)(d > 0 ? d + 0.5 : d - 0.5);\r
291 }\r
292 \r
293 template<typename T>\r
294 string HexStr(const T itbegin, const T itend, bool fSpaces=true)\r
295 {\r
296     const unsigned char* pbegin = (const unsigned char*)&itbegin[0];\r
297     const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);\r
298     string str;\r
299     for (const unsigned char* p = pbegin; p != pend; p++)\r
300         str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p);\r
301     return str;\r
302 }\r
303 \r
304 inline string HexStr(vector<unsigned char> vch, bool fSpaces=true)\r
305 {\r
306     return HexStr(vch.begin(), vch.end(), fSpaces);\r
307 }\r
308 \r
309 template<typename T>\r
310 string HexNumStr(const T itbegin, const T itend, bool f0x=true)\r
311 {\r
312     const unsigned char* pbegin = (const unsigned char*)&itbegin[0];\r
313     const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);\r
314     string str = (f0x ? "0x" : "");\r
315     for (const unsigned char* p = pend-1; p >= pbegin; p--)\r
316         str += strprintf("%02X", *p);\r
317     return str;\r
318 }\r
319 \r
320 template<typename T>\r
321 void PrintHex(const T pbegin, const T pend, const char* pszFormat="%s", bool fSpaces=true)\r
322 {\r
323     printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());\r
324 }\r
325 \r
326 inline void PrintHex(vector<unsigned char> vch, const char* pszFormat="%s", bool fSpaces=true)\r
327 {\r
328     printf(pszFormat, HexStr(vch, fSpaces).c_str());\r
329 }\r
330 \r
331 \r
332 \r
333 \r
334 \r
335 \r
336 \r
337 \r
338 \r
339 inline void heapchk()\r
340 {\r
341     if (_heapchk() != _HEAPOK)\r
342         DebugBreak();\r
343 }\r
344 \r
345 // Randomize the stack to help protect against buffer overrun exploits\r
346 #define IMPLEMENT_RANDOMIZE_STACK(ThreadFn)                         \\r
347     {                                                               \\r
348         static char nLoops;                                         \\r
349         if (nLoops <= 0)                                            \\r
350             nLoops = GetRand(50) + 1;                               \\r
351         if (nLoops-- > 1)                                           \\r
352         {                                                           \\r
353             ThreadFn;                                               \\r
354             return;                                                 \\r
355         }                                                           \\r
356     }\r
357 \r
358 #define CATCH_PRINT_EXCEPTION(pszFn)     \\r
359     catch (std::exception& e) {          \\r
360         PrintException(&e, (pszFn));     \\r
361     } catch (...) {                      \\r
362         PrintException(NULL, (pszFn));   \\r
363     }\r
364 \r
365 \r
366 \r
367 \r
368 \r
369 \r
370 \r
371 \r
372 \r
373 template<typename T1>\r
374 inline uint256 Hash(const T1 pbegin, const T1 pend)\r
375 {\r
376     uint256 hash1;\r
377     SHA256((unsigned char*)&pbegin[0], (pend - pbegin) * sizeof(pbegin[0]), (unsigned char*)&hash1);\r
378     uint256 hash2;\r
379     SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);\r
380     return hash2;\r
381 }\r
382 \r
383 template<typename T1, typename T2>\r
384 inline uint256 Hash(const T1 p1begin, const T1 p1end,\r
385                     const T2 p2begin, const T2 p2end)\r
386 {\r
387     uint256 hash1;\r
388     SHA256_CTX ctx;\r
389     SHA256_Init(&ctx);\r
390     SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]));\r
391     SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]));\r
392     SHA256_Final((unsigned char*)&hash1, &ctx);\r
393     uint256 hash2;\r
394     SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);\r
395     return hash2;\r
396 }\r
397 \r
398 template<typename T1, typename T2, typename T3>\r
399 inline uint256 Hash(const T1 p1begin, const T1 p1end,\r
400                     const T2 p2begin, const T2 p2end,\r
401                     const T3 p3begin, const T3 p3end)\r
402 {\r
403     uint256 hash1;\r
404     SHA256_CTX ctx;\r
405     SHA256_Init(&ctx);\r
406     SHA256_Update(&ctx, (unsigned char*)&p1begin[0], (p1end - p1begin) * sizeof(p1begin[0]));\r
407     SHA256_Update(&ctx, (unsigned char*)&p2begin[0], (p2end - p2begin) * sizeof(p2begin[0]));\r
408     SHA256_Update(&ctx, (unsigned char*)&p3begin[0], (p3end - p3begin) * sizeof(p3begin[0]));\r
409     SHA256_Final((unsigned char*)&hash1, &ctx);\r
410     uint256 hash2;\r
411     SHA256((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);\r
412     return hash2;\r
413 }\r
414 \r
415 template<typename T>\r
416 uint256 SerializeHash(const T& obj, int nType=SER_GETHASH, int nVersion=VERSION)\r
417 {\r
418     // Most of the time is spent allocating and deallocating CDataStream's\r
419     // buffer.  If this ever needs to be optimized further, make a CStaticStream\r
420     // class with its buffer on the stack.\r
421     CDataStream ss(nType, nVersion);\r
422     ss.reserve(10000);\r
423     ss << obj;\r
424     return Hash(ss.begin(), ss.end());\r
425 }\r
426 \r
427 inline uint160 Hash160(const vector<unsigned char>& vch)\r
428 {\r
429     uint256 hash1;\r
430     SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);\r
431     uint160 hash2;\r
432     RIPEMD160((unsigned char*)&hash1, sizeof(hash1), (unsigned char*)&hash2);\r
433     return hash2;\r
434 }\r