// Copyright (c) 2009-2010 Satoshi Nakamoto
+// Copyright (c) 2009-2012 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
-// file license.txt or http://www.opensource.org/licenses/mit-license.php.
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+#ifndef BITCOIN_UTIL_H
+#define BITCOIN_UTIL_H
+
+#include "uint256.h"
+
+#ifndef __WXMSW__
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#endif
+#include <map>
+#include <vector>
+#include <string>
+
+#include <boost/thread.hpp>
+#include <boost/interprocess/sync/interprocess_recursive_mutex.hpp>
+#include <boost/date_time/gregorian/gregorian_types.hpp>
+#include <boost/date_time/posix_time/posix_time_types.hpp>
+
+#include <openssl/sha.h>
+#include <openssl/ripemd.h>
#if defined(_MSC_VER) || defined(__BORLANDC__)
#define __forceinline inline
#endif
-#define foreach BOOST_FOREACH
#define loop for (;;)
#define BEGIN(a) ((char*)&(a))
#define END(a) ((char*)&((&(a))[1]))
// This is needed because the foreach macro can't get over the comma in pair<t1, t2>
#define PAIRTYPE(t1, t2) pair<t1, t2>
-// Used to bypass the rule against non-const reference to temporary
-// where it makes sense with wrappers such as CFlatData or CTxDB
-template<typename T>
-inline T& REF(const T& val)
-{
- return (T&)val;
-}
-
// Align by increasing pointer, must have extra space at end of buffer
template <size_t nBytes, typename T>
T* alignup(T* p)
typedef int socklen_t;
#else
#define WSAGetLastError() errno
+#define WSAEINVAL EINVAL
+#define WSAEALREADY EALREADY
#define WSAEWOULDBLOCK EWOULDBLOCK
#define WSAEMSGSIZE EMSGSIZE
#define WSAEINTR EINTR
#define Beep(n1,n2) (0)
inline void Sleep(int64 n)
{
- boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n));
+ /*Boost has a year 2038 problem— if the request sleep time is past epoch+2^31 seconds the sleep returns instantly.
+ So we clamp our sleeps here to 10 years and hope that boost is fixed by 2028.*/
+ boost::thread::sleep(boost::get_system_time() + boost::posix_time::milliseconds(n>315576000000LL?315576000000LL:n));
}
#endif
-extern map<string, string> mapArgs;
-extern map<string, vector<string> > mapMultiArgs;
+extern std::map<std::string, std::string> mapArgs;
+extern std::map<std::string, std::vector<std::string> > mapMultiArgs;
extern bool fDebug;
extern bool fPrintToConsole;
extern bool fPrintToDebugger;
extern bool fDaemon;
extern bool fServer;
extern bool fCommandLine;
-extern string strMiscWarning;
+extern std::string strMiscWarning;
extern bool fTestNet;
extern bool fNoListen;
extern bool fLogTimestamps;
void RandAddSeedPerfmon();
int OutputDebugStringF(const char* pszFormat, ...);
int my_snprintf(char* buffer, size_t limit, const char* format, ...);
-string strprintf(const char* format, ...);
+std::string strprintf(const char* format, ...);
bool error(const char* format, ...);
void LogException(std::exception* pex, const char* pszThread);
void PrintException(std::exception* pex, const char* pszThread);
void PrintExceptionContinue(std::exception* pex, const char* pszThread);
-void ParseString(const string& str, char c, vector<string>& v);
-string FormatMoney(int64 n, bool fPlus=false);
-bool ParseMoney(const string& str, int64& nRet);
+void ParseString(const std::string& str, char c, std::vector<std::string>& v);
+std::string FormatMoney(int64 n, bool fPlus=false);
+bool ParseMoney(const std::string& str, int64& nRet);
bool ParseMoney(const char* pszIn, int64& nRet);
-vector<unsigned char> ParseHex(const char* psz);
-vector<unsigned char> ParseHex(const string& str);
+std::vector<unsigned char> ParseHex(const char* psz);
+std::vector<unsigned char> ParseHex(const std::string& str);
void ParseParameters(int argc, char* argv[]);
const char* wxGetTranslation(const char* psz);
bool WildcardMatch(const char* psz, const char* mask);
-bool WildcardMatch(const string& str, const string& mask);
+bool WildcardMatch(const std::string& str, const std::string& mask);
int GetFilesize(FILE* file);
void GetDataDir(char* pszDirRet);
-string GetConfigFile();
-string GetPidFile();
-void CreatePidFile(string pidFile, pid_t pid);
-void ReadConfigFile(map<string, string>& mapSettingsRet, map<string, vector<string> >& mapMultiSettingsRet);
+std::string GetConfigFile();
+std::string GetPidFile();
+void CreatePidFile(std::string pidFile, pid_t pid);
+void ReadConfigFile(std::map<std::string, std::string>& mapSettingsRet, std::map<std::string, std::vector<std::string> >& mapMultiSettingsRet);
#ifdef __WXMSW__
-string MyGetSpecialFolderPath(int nFolder, bool fCreate);
+std::string MyGetSpecialFolderPath(int nFolder, bool fCreate);
#endif
-string GetDefaultDataDir();
-string GetDataDir();
+std::string GetDefaultDataDir();
+std::string GetDataDir();
void ShrinkDebugFile();
int GetRandInt(int nMax);
uint64 GetRand(uint64 nMax);
int64 GetTime();
int64 GetAdjustedTime();
void AddTimeData(unsigned int ip, int64 nTime);
-string FormatFullVersion();
+std::string FormatFullVersion();
-// Wrapper to automatically initialize critical sections
+// Wrapper to automatically initialize mutex
class CCriticalSection
{
-#ifdef __WXMSW__
-protected:
- CRITICAL_SECTION cs;
-public:
- explicit CCriticalSection() { InitializeCriticalSection(&cs); }
- ~CCriticalSection() { DeleteCriticalSection(&cs); }
- void Enter() { EnterCriticalSection(&cs); }
- void Leave() { LeaveCriticalSection(&cs); }
- bool TryEnter() { return TryEnterCriticalSection(&cs); }
-#else
protected:
boost::interprocess::interprocess_recursive_mutex mutex;
public:
explicit CCriticalSection() { }
~CCriticalSection() { }
- void Enter() { mutex.lock(); }
- void Leave() { mutex.unlock(); }
- bool TryEnter() { return mutex.try_lock(); }
-#endif
-public:
- const char* pszFile;
- int nLine;
+ void Enter(const char* pszName, const char* pszFile, int nLine);
+ void Leave();
+ bool TryEnter(const char* pszName, const char* pszFile, int nLine);
};
// Automatically leave critical section when leaving block, needed for exception safety
{
protected:
CCriticalSection* pcs;
+
public:
- CCriticalBlock(CCriticalSection& csIn) { pcs = &csIn; pcs->Enter(); }
- ~CCriticalBlock() { pcs->Leave(); }
+ CCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+ {
+ pcs = &csIn;
+ pcs->Enter(pszName, pszFile, nLine);
+ }
+ ~CCriticalBlock()
+ {
+ pcs->Leave();
+ }
};
// WARNING: This will catch continue and break!
// I'd rather be careful than suffer the other more error prone syntax.
// The compiler will optimise away all this loop junk.
#define CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
- for (CCriticalBlock criticalblock(cs); fcriticalblockonce && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
+ for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
+ for (CCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce; fcriticalblockonce=false)
+
+#define ENTER_CRITICAL_SECTION(cs) \
+ (cs).Enter(#cs, __FILE__, __LINE__)
+
+#define LEAVE_CRITICAL_SECTION(cs) \
+ (cs).Leave()
class CTryCriticalBlock
{
protected:
CCriticalSection* pcs;
+
public:
- CTryCriticalBlock(CCriticalSection& csIn) { pcs = (csIn.TryEnter() ? &csIn : NULL); }
- ~CTryCriticalBlock() { if (pcs) pcs->Leave(); }
+ CTryCriticalBlock(CCriticalSection& csIn, const char* pszName, const char* pszFile, int nLine)
+ {
+ pcs = (csIn.TryEnter(pszName, pszFile, nLine) ? &csIn : NULL);
+ }
+ ~CTryCriticalBlock()
+ {
+ if (pcs)
+ {
+ pcs->Leave();
+ }
+ }
bool Entered() { return pcs != NULL; }
};
#define TRY_CRITICAL_BLOCK(cs) \
- for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!", !fcriticalblockonce)), fcriticalblockonce=false) \
- for (CTryCriticalBlock criticalblock(cs); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()) && (cs.pszFile=__FILE__, cs.nLine=__LINE__, true); fcriticalblockonce=false, cs.pszFile=NULL, cs.nLine=0)
+ for (bool fcriticalblockonce=true; fcriticalblockonce; assert(("break caught by TRY_CRITICAL_BLOCK!" && !fcriticalblockonce)), fcriticalblockonce=false) \
+ for (CTryCriticalBlock criticalblock(cs, #cs, __FILE__, __LINE__); fcriticalblockonce && (fcriticalblockonce = criticalblock.Entered()); fcriticalblockonce=false)
-inline string i64tostr(int64 n)
+inline std::string i64tostr(int64 n)
{
return strprintf("%"PRI64d, n);
}
-inline string itostr(int n)
+inline std::string itostr(int n)
{
return strprintf("%d", n);
}
#endif
}
-inline int64 atoi64(const string& str)
+inline int64 atoi64(const std::string& str)
{
#ifdef _MSC_VER
return _atoi64(str.c_str());
#endif
}
-inline int atoi(const string& str)
+inline int atoi(const std::string& str)
{
return atoi(str.c_str());
}
}
template<typename T>
-string HexStr(const T itbegin, const T itend, bool fSpaces=false)
+std::string HexStr(const T itbegin, const T itend, bool fSpaces=false)
{
if (itbegin == itend)
return "";
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
- string str;
+ std::string str;
str.reserve((pend-pbegin) * (fSpaces ? 3 : 2));
for (const unsigned char* p = pbegin; p != pend; p++)
str += strprintf((fSpaces && p != pend-1 ? "%02x " : "%02x"), *p);
return str;
}
-inline string HexStr(const vector<unsigned char>& vch, bool fSpaces=false)
+inline std::string HexStr(const std::vector<unsigned char>& vch, bool fSpaces=false)
{
return HexStr(vch.begin(), vch.end(), fSpaces);
}
template<typename T>
-string HexNumStr(const T itbegin, const T itend, bool f0x=true)
+std::string HexNumStr(const T itbegin, const T itend, bool f0x=true)
{
if (itbegin == itend)
return "";
const unsigned char* pbegin = (const unsigned char*)&itbegin[0];
const unsigned char* pend = pbegin + (itend - itbegin) * sizeof(itbegin[0]);
- string str = (f0x ? "0x" : "");
+ std::string str = (f0x ? "0x" : "");
str.reserve(str.size() + (pend-pbegin) * 2);
for (const unsigned char* p = pend-1; p >= pbegin; p--)
str += strprintf("%02x", *p);
return str;
}
-inline string HexNumStr(const vector<unsigned char>& vch, bool f0x=true)
+inline std::string HexNumStr(const std::vector<unsigned char>& vch, bool f0x=true)
{
return HexNumStr(vch.begin(), vch.end(), f0x);
}
printf(pszFormat, HexStr(pbegin, pend, fSpaces).c_str());
}
-inline void PrintHex(const vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true)
+inline void PrintHex(const std::vector<unsigned char>& vch, const char* pszFormat="%s", bool fSpaces=true)
{
printf(pszFormat, HexStr(vch, fSpaces).c_str());
}
inline int64 GetTimeMillis()
{
- return (posix_time::ptime(posix_time::microsec_clock::universal_time()) -
- posix_time::ptime(gregorian::date(1970,1,1))).total_milliseconds();
+ return (boost::posix_time::ptime(boost::posix_time::microsec_clock::universal_time()) -
+ boost::posix_time::ptime(boost::gregorian::date(1970,1,1))).total_milliseconds();
}
-inline string DateTimeStrFormat(const char* pszFormat, int64 nTime)
+inline std::string DateTimeStrFormat(const char* pszFormat, int64 nTime)
{
time_t n = nTime;
struct tm* ptmTime = gmtime(&n);
#endif
}
-inline string GetArg(const string& strArg, const string& strDefault)
+inline std::string GetArg(const std::string& strArg, const std::string& strDefault)
{
if (mapArgs.count(strArg))
return mapArgs[strArg];
return strDefault;
}
-inline int64 GetArg(const string& strArg, int64 nDefault)
+inline int64 GetArg(const std::string& strArg, int64 nDefault)
{
if (mapArgs.count(strArg))
return atoi64(mapArgs[strArg]);
return nDefault;
}
-inline bool GetBoolArg(const string& strArg)
+inline bool GetBoolArg(const std::string& strArg, bool fDefault=false)
{
if (mapArgs.count(strArg))
{
return true;
return (atoi(mapArgs[strArg]) != 0);
}
- return false;
+ return fDefault;
}
+/**
+ * Set an argument if it doesn't already have a value
+ *
+ * @param strArg Argument to set (e.g. "-foo")
+ * @param strValue Value (e.g. "1")
+ * @return true if argument gets set, false if it already had a value
+ */
+bool SoftSetArg(const std::string& strArg, const std::string& strValue);
+
+/**
+ * Set a boolean argument if it doesn't already have a value
+ *
+ * @param strArg Argument to set (e.g. "-foo")
+ * @param fValue Value (e.g. false)
+ * @return true if argument gets set, false if it already had a value
+ */
+bool SoftSetArg(const std::string& strArg, bool fValue);
return Hash(ss.begin(), ss.end());
}
-inline uint160 Hash160(const vector<unsigned char>& vch)
+inline uint160 Hash160(const std::vector<unsigned char>& vch)
{
uint256 hash1;
SHA256(&vch[0], vch.size(), (unsigned char*)&hash1);
return (pthread_t)0;
}
if (!fWantHandle)
+ {
+ pthread_detach(hthread);
return (pthread_t)-1;
+ }
return hthread;
}
return (pthread_cancel(hthread) == 0);
}
-inline void ExitThread(unsigned int nExitCode)
+inline void ExitThread(size_t nExitCode)
{
pthread_exit((void*)nExitCode);
}
{
#ifdef __WXMSW__
// Sometimes after a few hours affinity gets stuck on one processor
- DWORD dwProcessAffinityMask = -1;
- DWORD dwSystemAffinityMask = -1;
+ DWORD_PTR dwProcessAffinityMask = -1;
+ DWORD_PTR dwSystemAffinityMask = -1;
GetProcessAffinityMask(GetCurrentProcess(), &dwProcessAffinityMask, &dwSystemAffinityMask);
DWORD dwPrev1 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
DWORD dwPrev2 = SetThreadAffinityMask(GetCurrentThread(), dwProcessAffinityMask);
#endif
return false;
}
+
+#endif