diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/check.h | 41 | ||||
-rw-r--r-- | src/util/system.cpp | 14 | ||||
-rw-r--r-- | src/util/time.cpp | 14 | ||||
-rw-r--r-- | src/util/time.h | 1 |
4 files changed, 63 insertions, 7 deletions
diff --git a/src/util/check.h b/src/util/check.h new file mode 100644 index 0000000000..d18887ae95 --- /dev/null +++ b/src/util/check.h @@ -0,0 +1,41 @@ +// Copyright (c) 2019 The Bitcoin Core developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_UTIL_CHECK_H +#define BITCOIN_UTIL_CHECK_H + +#include <tinyformat.h> + +#include <stdexcept> + +class NonFatalCheckError : public std::runtime_error +{ + using std::runtime_error::runtime_error; +}; + +/** + * Throw a NonFatalCheckError when the condition evaluates to false + * + * This should only be used + * - where the condition is assumed to be true, not for error handling or validating user input + * - where a failure to fulfill the condition is recoverable and does not abort the program + * + * For example in RPC code, where it is undersirable to crash the whole program, this can be generally used to replace + * asserts or recoverable logic errors. A NonFatalCheckError in RPC code is caught and passed as a string to the RPC + * caller, which can then report the issue to the developers. + */ +#define CHECK_NONFATAL(condition) \ + do { \ + if (!(condition)) { \ + throw NonFatalCheckError( \ + strprintf("%s:%d (%s)\n" \ + "Internal bug detected: '%s'\n" \ + "You may report this issue here: %s\n", \ + __FILE__, __LINE__, __func__, \ + (#condition), \ + PACKAGE_BUGREPORT)); \ + } \ + } while (false) + +#endif // BITCOIN_UTIL_CHECK_H diff --git a/src/util/system.cpp b/src/util/system.cpp index 526bf559c3..7da408eda5 100644 --- a/src/util/system.cpp +++ b/src/util/system.cpp @@ -305,7 +305,7 @@ NODISCARD static bool InterpretOption(std::string key, std::string val, unsigned LogPrintf("Warning: parsed potentially confusing double-negative %s=%s\n", key, val); val = "1"; } else { - error = strprintf("Negating of %s is meaningless and therefore forbidden", key.c_str()); + error = strprintf("Negating of %s is meaningless and therefore forbidden", key); return false; } } @@ -414,7 +414,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin return false; } } else { - error = strprintf("Invalid parameter %s", key.c_str()); + error = strprintf("Invalid parameter %s", key); return false; } } @@ -688,7 +688,7 @@ void PrintExceptionContinue(const std::exception* pex, const char* pszThread) { std::string message = FormatException(pex, pszThread); LogPrintf("\n\n************************\n%s\n", message); - tfm::format(std::cerr, "\n\n************************\n%s\n", message.c_str()); + tfm::format(std::cerr, "\n\n************************\n%s\n", message); } fs::path GetDefaultDataDir() @@ -870,7 +870,7 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file if (ignore_invalid_keys) { LogPrintf("Ignoring unknown configuration value %s\n", option.first); } else { - error = strprintf("Invalid configuration value %s", option.first.c_str()); + error = strprintf("Invalid configuration value %s", option.first); return false; } } @@ -925,7 +925,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) if (!ReadConfigStream(include_config, to_include, error, ignore_invalid_keys)) { return false; } - LogPrintf("Included configuration file %s\n", to_include.c_str()); + LogPrintf("Included configuration file %s\n", to_include); } else { error = "Failed to include configuration file " + to_include; return false; @@ -945,7 +945,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) } } for (const std::string& to_include : includeconf) { - tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str()); + tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include); } } } @@ -953,7 +953,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys) // If datadir is changed in .conf file: ClearDatadirCache(); if (!CheckDataDirOption()) { - error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str()); + error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "")); return false; } return true; diff --git a/src/util/time.cpp b/src/util/time.cpp index 2b202ae95f..2afff2626b 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -111,3 +111,17 @@ std::string FormatISO8601Date(int64_t nTime) { #endif return strprintf("%04i-%02i-%02i", ts.tm_year + 1900, ts.tm_mon + 1, ts.tm_mday); } + +int64_t ParseISO8601DateTime(const std::string& str) +{ + static const boost::posix_time::ptime epoch = boost::posix_time::from_time_t(0); + static const std::locale loc(std::locale::classic(), + new boost::posix_time::time_input_facet("%Y-%m-%dT%H:%M:%SZ")); + std::istringstream iss(str); + iss.imbue(loc); + boost::posix_time::ptime ptime(boost::date_time::not_a_date_time); + iss >> ptime; + if (ptime.is_not_a_date_time() || epoch > ptime) + return 0; + return (ptime - epoch).total_seconds(); +}
\ No newline at end of file diff --git a/src/util/time.h b/src/util/time.h index c0470a2136..af4390aa1c 100644 --- a/src/util/time.h +++ b/src/util/time.h @@ -48,5 +48,6 @@ T GetTime(); */ std::string FormatISO8601DateTime(int64_t nTime); std::string FormatISO8601Date(int64_t nTime); +int64_t ParseISO8601DateTime(const std::string& str); #endif // BITCOIN_UTIL_TIME_H |