From c736387063a3b647f5584c08699b4c52cfb12fc4 Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sat, 4 May 2024 12:11:55 -0400 Subject: [PATCH] A simple little design-by-contract library to test out more advanced c++20 features. Looks like clang doesn't do std::source_location right. See https://github.com/llvm/llvm-project/issues/56379 --- PPP3/dbc.h | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ PPP3/goc.cpp | 51 +++++++++++++++++++++++++++------------------ 2 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 PPP3/dbc.h diff --git a/PPP3/dbc.h b/PPP3/dbc.h new file mode 100644 index 0000000..ad5e3d5 --- /dev/null +++ b/PPP3/dbc.h @@ -0,0 +1,59 @@ +#include +#include +#include + +using namespace std; + +namespace dbc { + class Error { + public: + const string message; + Error(string m) : message{m} {} + Error(const char *m) : message{m} {} + }; + + class CheckError : public Error {}; + + class SentinelError : public Error {}; + class PreCondError : public Error {}; + class PostCondError : public Error {}; + + void log(const string &message, std::source_location loc = std::source_location::current()) { + fmt::print("[{}:{}:{}] {}\n", loc.file_name(), loc.function_name(), loc.line(), message); + } + + void sentinel(const string &message, std::source_location loc = std::source_location::current()) { + string err = fmt::format("[SENTINEL! {}:{}:{}:{}] {}\n", + loc.file_name(), loc.function_name(), + loc.line(), loc.column(), message); + throw SentinelError{err}; + } + + void pre(const string &message, std::function tester, std::source_location loc = std::source_location::current()) { + if(!tester()) { + string err = fmt::format("[PRE! {}:{}:{}:{}] {}\n", + loc.file_name(), loc.function_name(), + loc.line(), loc.column(), message); + throw PreCondError{err}; + } + } + + void post(const string &message, std::function tester, std::source_location loc = std::source_location::current()) { + if(!tester()) { + string err = fmt::format("[POST! {}:{}:{}:{}] {}\n", + loc.file_name(), loc.function_name(), + loc.line(), loc.column(), message); + throw PostCondError{err}; + } + } + + void check(bool test, const string &message, std::source_location loc = std::source_location::current()) { + + if(!test) { + string err = fmt::format("[CHECK! {}:{}:{}:{}] {}\n", + loc.file_name(), loc.function_name(), + loc.line(), loc.column(), message); + throw CheckError{err}; + } + } +} diff --git a/PPP3/goc.cpp b/PPP3/goc.cpp index 90ac18c..36daa80 100644 --- a/PPP3/goc.cpp +++ b/PPP3/goc.cpp @@ -5,34 +5,45 @@ #include #include #include +#include "dbc.h" using namespace std; using namespace fmt; int main() { - regex err_re("(.*?):([0-9]+):([0-9]+):\\s*(.*?):\\s*(.*)"); - string line; - smatch err; - ofstream stats_out; - stats_out.open("stats.csv", ios::out | ios::app); - auto t = time(nullptr); - auto tm = *std::gmtime(&t); + try { + regex err_re("(.*?):([0-9]+):([0-9]+):\\s*(.*?):\\s*(.*)"); + string line; + smatch err; + ofstream stats_out; + stats_out.open("stats.csv", ios::out | ios::app); + auto t = time(nullptr); + auto tm = *std::gmtime(&t); - while(getline(cin, line)) { - print("{}\n", line); - if(regex_match(line, err, err_re)) { - string file_name = err[1].str(); - string line = err[2].str(); - string col = err[3].str(); - string type = err[4].str(); - string message = err[5].str(); + dbc::log("TEST 1 of the logging thing"); + dbc::check(stats_out.good(), "Error opening stats.csv file."); + dbc::pre("simple test", [&]() { return stats_out.good(); }); - stats_out << put_time(&tm, "%FT%TZ"); - stats_out << format(",{},{},{},{},{}\n", file_name, line, col, type, message); + while(getline(cin, line)) { + print("{}\n", line); + if(regex_match(line, err, err_re)) { + string file_name = err[1].str(); + string line = err[2].str(); + string col = err[3].str(); + string type = err[4].str(); + string message = err[5].str(); + + stats_out << put_time(&tm, "%FT%TZ"); + stats_out << format(",{},{},{},{},{}\n", file_name, line, col, type, message); + } } - } - stats_out.close(); - return 0; + stats_out.close(); + dbc::post("a post test", [&]() { return !stats_out.is_open(); }); + return 0; + } catch(dbc::Error &err) { + print("ERROR: {}\n", err.message); + return 1; + } }