// faults.hpp // // Copyright (C) 2004-2020 MicroNeil Research Corporation. // // This software is released under the MIT license. See LICENSE.TXT. // // Faults and Checks are classes we can use in place of assert() to handle // unreasonable or necessary conditions in our code. They are constructed with // friendly descriptions (and optionally error codes) and then used just // like assert() would be used-- except they are designed to remain in the // production code. After all, assert() is a C (not C++) concept. // // A ...Check(test_expression) activates when the test_expression is not true. // A ...Fault(text_expression) activates when the test_expression is true. // // An Abort...() sends it's description to cerr then aborts (no cleanup). // An Exit...() sends it's description to cerr then exits with a result code. // A Runtime...() throws a runtime_error (self) with it's description in what(). // A Logic...() throws a logic_error (self) with it's description in what(). #pragma once #include #include #include #include namespace codedweller { const int DefaultExitCode = EXIT_FAILURE; // Use this when no code is provided. class AbortCheck { // If this check is false we will abort. private: const std::string myDescription; // This is what I have to say. public: AbortCheck(const std::string& Text) : myDescription(Text) {} // I am constructed with a description void operator()(bool X) const { // Apply me like assert(exp) if(false == X) { // If the expression is false then we std::cerr << myDescription << std::endl; // failed the check so we display our abort(); // description and abort. } } const std::string Description() { return myDescription; } // You can ask for my Description. }; class AbortFault { // If this fault occurs we will abort. private: const std::string myDescription; // This is what I have to say. public: AbortFault(const std::string& Text) : myDescription(Text) {} // I am constructed with a description void operator()(bool X) const { // Apply me like assert(! exp) if(true == X) { // If the expression is true then we std::cerr << myDescription << std::endl; // have a fault so we display our fault abort(); // description and abort. } } const std::string Description() const { return myDescription; } // You can ask for my Description. }; class ExitCheck { // If this check is false we will exit. private: const std::string myDescription; // This is what I have to say. const int myExitCode; // This is what I send to exit(). public: ExitCheck(const std::string& Text, int Code=DefaultExitCode) : // I am constructed with a description myDescription(Text), myExitCode(Code) {} // and (optionlly) an exit code. void operator()(bool X) const { // Apply me like assert(exp) if(false == X) { // If the expression is false then we std::cerr << myDescription << std::endl; // failed the check so we display our exit(myExitCode); // description and exit with our code. } } const std::string Description() { return myDescription; } // You can ask for my Description. const int ExitCode() { return myExitCode; } // You can ask for my ExitCode. }; class ExitFault { // If this fault occurs we will exit. private: const std::string myDescription; // This is what I have to say. const int myExitCode; // This is what I send to exit(). public: ExitFault(const std::string& Text, int Code=DefaultExitCode) : // I am constructed with a description myDescription(Text), myExitCode(Code) {} // and (optionlly) an exit code. void operator()(bool X) const { // Apply me like assert(! exp) if(true == X) { // If the expression is true then we std::cerr << myDescription << std::endl; // have a fault so we display our fault exit(myExitCode); // description and exit with our code. } } const std::string Description() const { return myDescription; } // You can ask for my Description. const int ExitCode() const { return myExitCode; } // You can ask for my ExitCode. }; class RuntimeCheck : public std::runtime_error { // Throw if this check fails. public: RuntimeCheck(const std::string& Text) : std::runtime_error(Text) {} // Construct me with a description. void operator()(bool X) const { // Apply me like assert(exp) if(false == X) { // If the expression is false then we throw *this; // failed the check so we throw. } } }; class RuntimeFault : public std::runtime_error { // Throw if we find this fault. public: RuntimeFault(const std::string& Text) : std::runtime_error(Text) {} // Construct me with a description. void operator()(bool X) const { // Apply me like assert(exp) if(true == X) { // If the expression is true then we throw *this; // found the fault so we throw. } } }; class LogicCheck : public std::logic_error { // Throw if this check fails. public: LogicCheck(const std::string& Text) : std::logic_error(Text) {} // Construct me with a description. void operator()(bool X) const { // Apply me like assert(exp) if(false == X) { // If the expression is false then we throw *this; // failed the check so we throw. } } }; class LogicFault : public std::logic_error { // Throw if we find this fault. public: LogicFault(const std::string& Text) : std::logic_error(Text) {} // Construct me with a description. void operator()(bool X) const { // Apply me like assert(exp) if(true == X) { // If the expression is true then we throw *this; // found the fault so we throw. } } }; } // End namespace codedweller