Switch to builtin tolower
[novacoin.git] / src / util.cpp
index ed7b34d..f798da6 100644 (file)
@@ -7,38 +7,21 @@
 #include "sync.h"
 #include "version.h"
 #include "ui_interface.h"
-#include <boost/algorithm/string/join.hpp>
-#include <boost/algorithm/string/case_conv.hpp> // for to_lower()
-#include <boost/algorithm/string/predicate.hpp> // for startswith() and endswith()
-
-// Work around clang compilation problem in Boost 1.46:
-// /usr/include/boost/program_options/detail/config_file.hpp:163:17: error: call to function 'to_internal' that is neither visible in the template definition nor found by argument-dependent lookup
-// See also: http://stackoverflow.com/questions/10020179/compilation-fail-in-boost-librairies-program-options
-//           http://clang.debian.net/status.php?version=3.0&key=CANNOT_FIND_FUNCTION
-namespace boost {
-    namespace program_options {
-        std::string to_internal(const std::string&);
-    }
-}
 
+#include <random>
+
+#include <boost/algorithm/string/join.hpp>
 #include <boost/program_options/detail/config_file.hpp>
 #include <boost/program_options/parsers.hpp>
 #include <boost/filesystem.hpp>
 #include <boost/filesystem/fstream.hpp>
-
 #include <boost/date_time/posix_time/posix_time.hpp>
-#include <boost/foreach.hpp>
 #include <boost/thread.hpp>
+
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 
 #ifdef WIN32
-#ifdef _MSC_VER
-#pragma warning(disable:4786)
-#pragma warning(disable:4804)
-#pragma warning(disable:4805)
-#pragma warning(disable:4717)
-#endif
 #ifdef _WIN32_WINNT
 #undef _WIN32_WINNT
 #endif
@@ -54,14 +37,13 @@ namespace boost {
 #include <io.h> /* for _commit */
 #include "shlobj.h"
 #elif defined(__linux__)
-# include <sys/prctl.h>
+#include <sys/prctl.h>
 #endif
 
 #if !defined(WIN32) && !defined(ANDROID)
 #include <execinfo.h>
 #endif
 
-
 using namespace std;
 namespace bt = boost::posix_time;
 
@@ -85,17 +67,17 @@ bool fReopenDebugLog = false;
 
 // Extended DecodeDumpTime implementation, see this page for details:
 // http://stackoverflow.com/questions/3786201/parsing-of-date-time-from-string-boost
-const std::locale formats[] = {
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
-    std::locale(std::locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
+const locale formats[] = {
+    locale(locale::classic(),new bt::time_input_facet("%Y-%m-%dT%H:%M:%SZ")),
+    locale(locale::classic(),new bt::time_input_facet("%Y-%m-%d %H:%M:%S")),
+    locale(locale::classic(),new bt::time_input_facet("%Y/%m/%d %H:%M:%S")),
+    locale(locale::classic(),new bt::time_input_facet("%d.%m.%Y %H:%M:%S")),
+    locale(locale::classic(),new bt::time_input_facet("%Y-%m-%d"))
 };
 
 const size_t formats_n = sizeof(formats)/sizeof(formats[0]);
 
-std::time_t pt_to_time_t(const bt::ptime& pt)
+time_t pt_to_time_t(const bt::ptime& pt)
 {
     bt::ptime timet_start(boost::gregorian::date(1970,1,1));
     bt::time_duration diff = pt - timet_start;
@@ -146,13 +128,6 @@ public:
 }
 instance_of_cinit;
 
-
-
-
-
-
-
-
 void RandAddSeed()
 {
     // Seed with CPU performance counter
@@ -195,7 +170,7 @@ uint64_t GetRand(uint64_t nMax)
 
     // The range of the random source must be a multiple of the modulus
     // to give every possible output value an equal possibility
-    uint64_t nRange = (std::numeric_limits<uint64_t>::max() / nMax) * nMax;
+    uint64_t nRange = (numeric_limits<uint64_t>::max() / nMax) * nMax;
     uint64_t nRand = 0;
     do
         RAND_bytes((unsigned char*)&nRand, sizeof(nRand));
@@ -211,14 +186,14 @@ int GetRandInt(int nMax)
 uint256 GetRandHash()
 {
     uint256 hash;
-    RAND_bytes((unsigned char*)&hash, sizeof(hash));
+    RAND_bytes(hash.begin(), hash.size());
     return hash;
 }
 
-
-
-
-
+void FillRand(uint8_t *buffer, size_t nCount)
+{
+    RAND_bytes(buffer, nCount);
+}
 
 static FILE* fileout = NULL;
 
@@ -286,15 +261,15 @@ inline int OutputDebugStringF(const char* pszFormat, ...)
         // accumulate and output a line at a time
         {
             LOCK(cs_OutputDebugStringF);
-            static std::string buffer;
+            static string buffer;
 
             va_list arg_ptr;
             va_start(arg_ptr, pszFormat);
             buffer += vstrprintf(pszFormat, arg_ptr);
             va_end(arg_ptr);
 
-            int line_start = 0, line_end;
-            while((line_end = buffer.find('\n', line_start)) != -1)
+            size_t line_start = 0, line_end;
+            while((line_end = buffer.find('\n', line_start)) != string::npos)
             {
                 OutputDebugStringA(buffer.substr(line_start, line_end - line_start).c_str());
                 line_start = line_end + 1;
@@ -312,7 +287,7 @@ string vstrprintf(const char *format, va_list ap)
     char* p = buffer;
     int limit = sizeof(buffer);
     int ret;
-    while (true)
+    for ( ; ; )
     {
 #ifndef _MSC_VER
         va_list arg_ptr;
@@ -331,9 +306,9 @@ string vstrprintf(const char *format, va_list ap)
         if (p != buffer)
             delete[] p;
         limit *= 2;
-        p = new char[limit];
+        p = new(nothrow) char[limit];
         if (p == NULL)
-            throw std::bad_alloc();
+            throw bad_alloc();
     }
     string str(p, p+ret);
     if (p != buffer)
@@ -350,7 +325,7 @@ string real_strprintf(const char *format, int dummy, ...)
     return str;
 }
 
-string real_strprintf(const std::string &format, int dummy, ...)
+string real_strprintf(const string &format, int dummy, ...)
 {
     va_list arg_ptr;
     va_start(arg_ptr, dummy);
@@ -363,7 +338,7 @@ bool error(const char *format, ...)
 {
     va_list arg_ptr;
     va_start(arg_ptr, format);
-    std::string str = vstrprintf(format, arg_ptr);
+    string str = vstrprintf(format, arg_ptr);
     va_end(arg_ptr);
     printf("ERROR: %s\n", str.c_str());
     return false;
@@ -376,7 +351,7 @@ void ParseString(const string& str, char c, vector<string>& v)
         return;
     string::size_type i1 = 0;
     string::size_type i2;
-    while (true)
+    for ( ; ; )
     {
         i2 = str.find(c, i1);
         if (i2 == str.npos)
@@ -389,7 +364,6 @@ void ParseString(const string& str, char c, vector<string>& v)
     }
 }
 
-
 string FormatMoney(int64_t n, bool fPlus)
 {
     // Note: not using straight sprintf here because we do NOT want
@@ -400,20 +374,19 @@ string FormatMoney(int64_t n, bool fPlus)
     string str = strprintf("%" PRId64 ".%06" PRId64, quotient, remainder);
 
     // Right-trim excess zeros before the decimal point:
-    int nTrim = 0;
-    for (int i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
+    size_t nTrim = 0;
+    for (size_t i = str.size()-1; (str[i] == '0' && isdigit(str[i-2])); --i)
         ++nTrim;
     if (nTrim)
         str.erase(str.size()-nTrim, nTrim);
 
     if (n < 0)
-        str.insert((unsigned int)0, 1, '-');
+        str.insert(0u, 1, '-');
     else if (fPlus && n > 0)
-        str.insert((unsigned int)0, 1, '+');
+        str.insert(0u, 1, '+');
     return str;
 }
 
-
 bool ParseMoney(const string& str, int64_t& nRet)
 {
     return ParseMoney(str.c_str(), nRet);
@@ -452,35 +425,36 @@ bool ParseMoney(const char* pszIn, int64_t& nRet)
         return false;
     if (nUnits < 0 || nUnits > COIN)
         return false;
-    int64_t nWhole = atoi64(strWhole);
+    int64_t nWhole = strtoll(strWhole);
     int64_t nValue = nWhole*COIN + nUnits;
 
     nRet = nValue;
     return true;
 }
 
-
-static const signed char phexdigit[256] =
-{ -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
-  -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-  -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1, };
+static const int8_t phexdigit[256] =
+{
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+     0,  1,  2,  3,  4,  5,  6, 7, 8, 9,-1,-1,-1,-1,-1,-1,
+    -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1,0xa,0xb,0xc,0xd,0xe,0xf,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+    -1, -1, -1, -1, -1, -1, -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
+};
 
 bool IsHex(const string& str)
 {
-    BOOST_FOREACH(unsigned char c, str)
+    for(unsigned char c :  str)
     {
         if (phexdigit[c] < 0)
             return false;
@@ -492,16 +466,16 @@ vector<unsigned char> ParseHex(const char* psz)
 {
     // convert hex dump to vector
     vector<unsigned char> vch;
-    while (true)
+    for ( ; ; )
     {
         while (isspace(*psz))
             psz++;
-        signed char c = phexdigit[(unsigned char)*psz++];
+        auto c = phexdigit[(unsigned char)*psz++];
         if (c == (signed char)-1)
             break;
-        unsigned char n = (c << 4);
-        c = phexdigit[(unsigned char)*psz++];
-        if (c == (signed char)-1)
+        auto n = (c << 4);
+        c = phexdigit[(uint8_t)*psz++];
+        if (c == (int8_t)-1)
             break;
         n |= c;
         vch.push_back(n);
@@ -509,17 +483,12 @@ vector<unsigned char> ParseHex(const char* psz)
     return vch;
 }
 
-vector<unsigned char> ParseHex(const string& str)
-{
-    return ParseHex(str.c_str());
-}
-
 static void InterpretNegativeSetting(string name, map<string, string>& mapSettingsRet)
 {
     // interpret -nofoo as -foo=0 (and -nofoo=0 as -foo=1) as long as -foo not set
     if (name.find("-no") == 0)
     {
-        std::string positive("-");
+        string positive("-");
         positive.append(name.begin()+3, name.end());
         if (mapSettingsRet.count(positive) == 0)
         {
@@ -535,17 +504,17 @@ void ParseParameters(int argc, const char* const argv[])
     mapMultiArgs.clear();
     for (int i = 1; i < argc; i++)
     {
-        std::string str(argv[i]);
-        std::string strValue;
+        string str(argv[i]);
+        string strValue;
         size_t is_index = str.find('=');
-        if (is_index != std::string::npos)
+        if (is_index != string::npos)
         {
             strValue = str.substr(is_index+1);
             str = str.substr(0, is_index);
         }
 #ifdef WIN32
-        boost::to_lower(str);
-        if (boost::algorithm::starts_with(str, "/"))
+        transform(str.begin(), str.end(), str.begin(), ::tolower);
+        if (str.compare(0,1, "/") == 0)
             str = "-" + str.substr(1);
 #endif
         if (str[0] != '-')
@@ -556,14 +525,14 @@ void ParseParameters(int argc, const char* const argv[])
     }
 
     // New 0.6 features:
-    BOOST_FOREACH(const PAIRTYPE(string,string)& entry, mapArgs)
+    for(const auto& entry : mapArgs)
     {
         string name = entry.first;
 
         //  interpret --foo as -foo (as long as both are not set)
         if (name.find("--") == 0)
         {
-            std::string singleDash(name.begin()+1, name.end());
+            string singleDash(name.begin()+1, name.end());
             if (mapArgs.count(singleDash) == 0)
                 mapArgs[singleDash] = entry.second;
             name = singleDash;
@@ -574,21 +543,35 @@ void ParseParameters(int argc, const char* const argv[])
     }
 }
 
-std::string GetArg(const std::string& strArg, const std::string& strDefault)
+string GetArg(const string& strArg, const string& strDefault)
 {
     if (mapArgs.count(strArg))
         return mapArgs[strArg];
     return strDefault;
 }
 
-int64_t GetArg(const std::string& strArg, int64_t nDefault)
+int64_t GetArg(const string& strArg, int64_t nDefault)
+{
+    if (mapArgs.count(strArg))
+        return strtoll(mapArgs[strArg]);
+    return nDefault;
+}
+
+int32_t GetArgInt(const string& strArg, int32_t nDefault)
+{
+    if (mapArgs.count(strArg))
+        return strtol(mapArgs[strArg]);
+    return nDefault;
+}
+
+uint32_t GetArgUInt(const string& strArg, uint32_t nDefault)
 {
     if (mapArgs.count(strArg))
-        return atoi64(mapArgs[strArg]);
+        return strtoul(mapArgs[strArg]);
     return nDefault;
 }
 
-bool GetBoolArg(const std::string& strArg, bool fDefault)
+bool GetBoolArg(const string& strArg, bool fDefault)
 {
     if (mapArgs.count(strArg))
     {
@@ -599,7 +582,7 @@ bool GetBoolArg(const std::string& strArg, bool fDefault)
     return fDefault;
 }
 
-bool SoftSetArg(const std::string& strArg, const std::string& strValue)
+bool SoftSetArg(const string& strArg, const string& strValue)
 {
     if (mapArgs.count(strArg) || mapMultiArgs.count(strArg))
         return false;
@@ -609,12 +592,12 @@ bool SoftSetArg(const std::string& strArg, const std::string& strValue)
     return true;
 }
 
-bool SoftSetBoolArg(const std::string& strArg, bool fValue)
+bool SoftSetBoolArg(const string& strArg, bool fValue)
 {
     if (fValue)
-        return SoftSetArg(strArg, std::string("1"));
+        return SoftSetArg(strArg, string("1"));
     else
-        return SoftSetArg(strArg, std::string("0"));
+        return SoftSetArg(strArg, string("0"));
 }
 
 
@@ -697,7 +680,7 @@ vector<unsigned char> DecodeBase64(const char* p, bool* pfInvalid)
     int mode = 0;
     int left = 0;
 
-    while (1)
+    for ( ; ; )
     {
          int dec = decode64_table[(unsigned char)*p];
          if (dec == -1) break;
@@ -850,7 +833,7 @@ vector<unsigned char> DecodeBase32(const char* p, bool* pfInvalid)
     int mode = 0;
     int left = 0;
 
-    while (1)
+    for ( ; ; )
     {
          int dec = decode32_table[(unsigned char)*p];
          if (dec == -1) break;
@@ -946,13 +929,13 @@ string DecodeBase32(const string& str)
 }
 
 
-int64_t DecodeDumpTime(const std::string& s)
+int64_t DecodeDumpTime(const string& s)
 {
     bt::ptime pt;
 
     for(size_t i=0; i<formats_n; ++i)
     {
-        std::istringstream is(s);
+        istringstream is(s);
         is.imbue(formats[i]);
         is >> pt;
         if(pt != bt::ptime()) break;
@@ -961,13 +944,13 @@ int64_t DecodeDumpTime(const std::string& s)
     return pt_to_time_t(pt);
 }
 
-std::string EncodeDumpTime(int64_t nTime) {
+string EncodeDumpTime(int64_t nTime) {
     return DateTimeStrFormat("%Y-%m-%dT%H:%M:%SZ", nTime);
 }
 
-std::string EncodeDumpString(const std::string &str) {
-    std::stringstream ret;
-    BOOST_FOREACH(unsigned char c, str) {
+string EncodeDumpString(const string &str) {
+    stringstream ret;
+    for(unsigned char c :  str) {
         if (c <= 32 || c >= 128 || c == '%') {
             ret << '%' << HexStr(&c, &c + 1);
         } else {
@@ -977,8 +960,8 @@ std::string EncodeDumpString(const std::string &str) {
     return ret.str();
 }
 
-std::string DecodeDumpString(const std::string &str) {
-    std::stringstream ret;
+string DecodeDumpString(const string &str) {
+    stringstream ret;
     for (unsigned int pos = 0; pos < str.length(); pos++) {
         unsigned char c = str[pos];
         if (c == '%' && pos+2 < str.length()) {
@@ -993,7 +976,7 @@ std::string DecodeDumpString(const std::string &str) {
 
 bool WildcardMatch(const char* psz, const char* mask)
 {
-    while (true)
+    for ( ; ; )
     {
         switch (*mask)
         {
@@ -1021,13 +1004,7 @@ bool WildcardMatch(const string& str, const string& mask)
 }
 
 
-
-
-
-
-
-
-static std::string FormatException(std::exception* pex, const char* pszThread)
+static string FormatException(exception* pex, const char* pszThread)
 {
 #ifdef WIN32
     char pszModule[MAX_PATH] = "";
@@ -1043,15 +1020,15 @@ static std::string FormatException(std::exception* pex, const char* pszThread)
             "UNKNOWN EXCEPTION       \n%s in %s       \n", pszModule, pszThread);
 }
 
-void LogException(std::exception* pex, const char* pszThread)
+void LogException(exception* pex, const char* pszThread)
 {
-    std::string message = FormatException(pex, pszThread);
+    string message = FormatException(pex, pszThread);
     printf("\n%s", message.c_str());
 }
 
-void PrintException(std::exception* pex, const char* pszThread)
+void PrintException(exception* pex, const char* pszThread)
 {
-    std::string message = FormatException(pex, pszThread);
+    string message = FormatException(pex, pszThread);
     printf("\n\n************************\n%s\n", message.c_str());
     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
     strMiscWarning = message;
@@ -1071,9 +1048,9 @@ void LogStackTrace() {
     }
 }
 
-void PrintExceptionContinue(std::exception* pex, const char* pszThread)
+void PrintExceptionContinue(exception* pex, const char* pszThread)
 {
-    std::string message = FormatException(pex, pszThread);
+    string message = FormatException(pex, pszThread);
     printf("\n\n************************\n%s\n", message.c_str());
     fprintf(stderr, "\n\n************************\n%s\n", message.c_str());
     strMiscWarning = message;
@@ -1143,20 +1120,19 @@ const boost::filesystem::path &GetDataDir(bool fNetSpecific)
     return path;
 }
 
-string randomStrGen(int length) {
-    static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+string randomStrGen(size_t length) {
+    std::mt19937 mtrand;
+    mtrand.seed(static_cast<unsigned int>(time(NULL)));
+    static const string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
     string result;
     result.resize(length);
-    for (int32_t i = 0; i < length; i++)
-        result[i] = charset[rand() % charset.length()];
-
+    for (size_t i = 0; i < length; ++i)
+        result[i] = charset[mtrand() % charset.length()];
     return result;
 }
 
 void createConf()
 {
-    srand(static_cast<unsigned int>(time(NULL)));
-
     ofstream pConf;
 #if BOOST_FILESYSTEM_VERSION >= 3
     pConf.open(GetConfigFile().generic_string().c_str());
@@ -1166,13 +1142,11 @@ void createConf()
     pConf << "rpcuser=user\nrpcpassword="
             + randomStrGen(15)
             + "\nrpcport=8344"
-            + "\nport=7777"
             + "\n#(0=off, 1=on) daemon - run in the background as a daemon and accept commands"
             + "\ndaemon=0"
             + "\n#(0=off, 1=on) server - accept command line and JSON-RPC commands"
             + "\nserver=0"
-            + "\nrpcallowip=127.0.0.1"
-            + "\ntestnet=0";
+            + "\nrpcallowip=127.0.0.1";
     pConf.close();
 }
 
@@ -1237,7 +1211,7 @@ bool RenameOver(boost::filesystem::path src, boost::filesystem::path dest)
     return MoveFileExA(src.string().c_str(), dest.string().c_str(),
                        MOVEFILE_REPLACE_EXISTING) != 0;
 #else
-    int rc = std::rename(src.string().c_str(), dest.string().c_str());
+    int rc = rename(src.string().c_str(), dest.string().c_str());
     return (rc == 0);
 #endif /* WIN32 */
 }
@@ -1270,27 +1244,28 @@ void ShrinkDebugFile()
     if (file && GetFilesize(file) > 10 * 1000000)
     {
         // Restart the file with some of the end
-        char pch[200000];
-        fseek(file, -((long long)sizeof(pch)), SEEK_END);
-        int nBytes = fread(pch, 1, sizeof(pch), file);
-        fclose(file);
-
-        file = fopen(pathLog.string().c_str(), "w");
-        if (file)
-        {
-            fwrite(pch, 1, nBytes, file);
+        try {
+            vector<char>* vBuf = new vector <char>(200000, 0);
+            size_t nBytes = 1; //write one byte if fseek failed
+            if (fseek(file, -((long)(vBuf->size())), SEEK_END) == 0)
+                nBytes = fread(&vBuf->operator[](0), 1, vBuf->size(), file);
             fclose(file);
+            file = fopen(pathLog.string().c_str(), "w");
+            if (file)
+            {
+                fwrite(&vBuf->operator[](0), 1, nBytes, file);
+                fclose(file);
+            }
+            delete vBuf;
+        }
+        catch (const bad_alloc& e) {
+            // Bad things happen - no free memory in heap at program startup
+            fclose(file);
+            printf("Warning: %s in %s:%d\n ShrinkDebugFile failed - debug.log expands further", e.what(), __FILE__, __LINE__);
         }
     }
 }
 
-
-
-
-
-
-
-
 //
 // "Never go to sea with two chronometers; take one or three."
 // Our three time sources are:
@@ -1298,25 +1273,38 @@ void ShrinkDebugFile()
 //  - Median of other nodes clocks
 //  - The user (asking the user to fix the system clock if the first two disagree)
 //
-static int64_t nMockTime = 0;  // For unit testing
 
+// System clock
 int64_t GetTime()
 {
-    if (nMockTime) return nMockTime;
-
-    return time(NULL);
+    int64_t now = time(NULL);
+    assert(now > 0);
+    return now;
 }
 
-void SetMockTime(int64_t nMockTimeIn)
-{
-    nMockTime = nMockTimeIn;
-}
+// Trusted NTP offset or median of NTP samples.
+extern int64_t nNtpOffset;
 
-static int64_t nTimeOffset = 0;
+// Median of time samples given by other nodes.
+static int64_t nNodesOffset = numeric_limits<int64_t>::max();
 
+// Select time offset:
 int64_t GetTimeOffset()
 {
-    return nTimeOffset;
+    // If NTP and system clock are in agreement within 40 minutes, then use NTP.
+    if (abs(nNtpOffset) < 40 * 60)
+        return nNtpOffset;
+
+    // If not, then choose between median peer time and system clock.
+    if (abs(nNodesOffset) < 70 * 60)
+        return nNodesOffset;
+
+    return 0;
+}
+
+int64_t GetNodesOffset()
+{
+        return nNodesOffset;
 }
 
 int64_t GetAdjustedTime()
@@ -1338,24 +1326,25 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime)
     printf("Added time data, samples %d, offset %+" PRId64 " (%+" PRId64 " minutes)\n", vTimeOffsets.size(), nOffsetSample, nOffsetSample/60);
     if (vTimeOffsets.size() >= 5 && vTimeOffsets.size() % 2 == 1)
     {
-        int64_t nMedian = vTimeOffsets.median();
-        std::vector<int64_t> vSorted = vTimeOffsets.sorted();
+        auto nMedian = vTimeOffsets.median();
+        auto vSorted = vTimeOffsets.sorted();
         // Only let other nodes change our time by so much
-        if (abs64(nMedian) < 70 * 60)
+        if (abs(nMedian) < 70 * 60)
         {
-            nTimeOffset = nMedian;
+            nNodesOffset = nMedian;
         }
         else
         {
-            nTimeOffset = 0;
+            nNodesOffset = numeric_limits<int64_t>::max();
 
             static bool fDone;
             if (!fDone)
             {
-                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
                 bool fMatch = false;
-                BOOST_FOREACH(int64_t nOffset, vSorted)
-                    if (nOffset != 0 && abs64(nOffset) < 5 * 60)
+
+                // If nobody has a time different than ours but within 5 minutes of ours, give a warning
+                for(auto nOffset :  vSorted)
+                    if (nOffset != 0 && abs(nOffset) < 5 * 60)
                         fMatch = true;
 
                 if (!fMatch)
@@ -1369,21 +1358,15 @@ void AddTimeData(const CNetAddr& ip, int64_t nTime)
             }
         }
         if (fDebug) {
-            BOOST_FOREACH(int64_t n, vSorted)
+            for(int64_t n :  vSorted)
                 printf("%+" PRId64 "  ", n);
             printf("|  ");
         }
-        printf("nTimeOffset = %+" PRId64 "  (%+" PRId64 " minutes)\n", nTimeOffset, nTimeOffset/60);
+        if (nNodesOffset != numeric_limits<int64_t>::max())
+            printf("nNodesOffset = %+" PRId64 "  (%+" PRId64 " minutes)\n", nNodesOffset, nNodesOffset/60);
     }
 }
 
-
-
-
-
-
-
-
 string FormatVersion(int nVersion)
 {
     if (nVersion%100 == 0)
@@ -1398,9 +1381,9 @@ string FormatFullVersion()
 }
 
 // Format the subversion field according to BIP 14 spec (https://en.bitcoin.it/wiki/BIP_0014)
-std::string FormatSubVersion(const std::string& name, int nClientVersion, const std::vector<std::string>& comments)
+string FormatSubVersion(const string& name, int nClientVersion, const vector<string>& comments)
 {
-    std::ostringstream ss;
+    ostringstream ss;
     ss << "/";
     ss << name << ":" << FormatVersion(nClientVersion);
     if (!comments.empty())
@@ -1426,7 +1409,7 @@ boost::filesystem::path GetSpecialFolderPath(int nFolder, bool fCreate)
 }
 #endif
 
-void runCommand(std::string strCommand)
+void runCommand(string strCommand)
 {
     int nErr = ::system(strCommand.c_str());
     if (nErr)
@@ -1466,12 +1449,12 @@ bool NewThread(void(*pfn)(void*), void* parg)
     return true;
 }
 
-std::string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
+string DateTimeStrFormat(const char* pszFormat, int64_t nTime)
 {
-    // std::locale takes ownership of the pointer
-    std::locale loc(std::locale::classic(), new boost::posix_time::time_facet(pszFormat));
-    std::stringstream ss;
+    // locale takes ownership of the pointer
+    locale loc(locale::classic(), new boost::posix_time::time_facet(pszFormat));
+    stringstream ss;
     ss.imbue(loc);
     ss << boost::posix_time::from_time_t(nTime);
     return ss.str();
-}
\ No newline at end of file
+}