diff --git a/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C b/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C index 3146bb8019..703d32e5b5 100644 --- a/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C +++ b/applications/utilities/surface/surfaceFeatureExtract/surfaceFeatureExtract.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2015-2017 OpenCFD Ltd. + Copyright (C) 2015-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -279,16 +279,9 @@ int main(int argc, char *argv[]) surfaceIntersection::NONE ); - const Switch writeObj = surfaceDict.lookupOrDefault - ( - "writeObj", - Switch::OFF - ); - const Switch writeVTK = surfaceDict.lookupOrDefault - ( - "writeVTK", - Switch::OFF - ); + const Switch writeObj("writeObj", surfaceDict, Switch::OFF); + + const Switch writeVTK("writeVTK", surfaceDict, Switch::OFF); // The "surfaces" entry is normally optional, but make it mandatory // if the dictionary name doesn't have an extension diff --git a/src/OSspecific/MSwindows/signals/sigFpe.C b/src/OSspecific/MSwindows/signals/sigFpe.C index 06f90bf1ce..a00e7929df 100644 --- a/src/OSspecific/MSwindows/signals/sigFpe.C +++ b/src/OSspecific/MSwindows/signals/sigFpe.C @@ -7,7 +7,7 @@ ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation Copyright (C) 2011 Symscape - Copyright (C) 2016-2018 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -69,16 +69,11 @@ static void clearFpe() // or by the specified flag static bool isTrue(const char* envName, bool deflt) { - const auto str(Foam::getEnv(envName)); + Foam::Switch sw(Foam::Switch::find(Foam::getEnv(envName))); - if (str.size()) + if (sw.good()) { - Foam::Switch sw(str, true); // Silently ignores bad input - - if (sw.valid()) - { - return sw; - } + return static_cast(sw); } // Env was not set or did not contain a valid bool value diff --git a/src/OSspecific/POSIX/signals/sigFpe.C b/src/OSspecific/POSIX/signals/sigFpe.C index 55c1fed73e..29a9585259 100644 --- a/src/OSspecific/POSIX/signals/sigFpe.C +++ b/src/OSspecific/POSIX/signals/sigFpe.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2015 OpenFOAM Foundation - Copyright (C) 2016-2019 OpenCFD Ltd. + Copyright (C) 2016-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -67,16 +67,11 @@ bool Foam::sigFpe::nanActive_ = false; // or by the specified flag static bool isTrue(const char* envName, bool deflt) { - const auto str(Foam::getEnv(envName)); + Foam::Switch sw(Foam::Switch::find(Foam::getEnv(envName))); - if (str.size()) + if (sw.good()) { - Foam::Switch sw(str, true); // Silently ignores bad input - - if (sw.valid()) - { - return sw; - } + return static_cast(sw); } // Env was not set or did not contain a valid bool value diff --git a/src/OpenFOAM/db/IOstreams/IOstreams/IOstreamOption.C b/src/OpenFOAM/db/IOstreams/IOstreams/IOstreamOption.C index c3ecc3941d..a5ecc291ea 100644 --- a/src/OpenFOAM/db/IOstreams/IOstreams/IOstreamOption.C +++ b/src/OpenFOAM/db/IOstreams/IOstreams/IOstreamOption.C @@ -71,8 +71,8 @@ Foam::IOstreamOption::compressionEnum(const word& compName) { // Handle bad input graciously - const Switch sw(compName, true); - if (sw.valid()) + const Switch sw = Switch::find(compName); + if (sw.good()) { return ( diff --git a/src/OpenFOAM/primitives/bools/Switch/Switch.C b/src/OpenFOAM/primitives/bools/Switch/Switch.C index bcb0c1110b..36f9d8145a 100644 --- a/src/OpenFOAM/primitives/bools/Switch/Switch.C +++ b/src/OpenFOAM/primitives/bools/Switch/Switch.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -30,7 +30,6 @@ License #include "scalar.H" #include "error.H" #include "dictionary.H" -#include "IOstreams.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // @@ -50,23 +49,45 @@ static const char* names[9] = "no", "yes", "off", "on", "none", "any", - "invalid" + "invalid" //< Output representation only }; } // End anonymous namespace -// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // -const char* Foam::Switch::name(const bool b) noexcept +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam { - return names[(b ? 1 : 0)]; -} +template +static OS& printTokenError(OS& os, const token& tok) +{ + if (!tok.good()) + { + os << "Bad token - could not get bool/switch" << nl; + } + else if (tok.isWord()) + { + os << "Expected true/false, on/off... found " + << tok.wordToken() << nl; + } + else + { + os << "Wrong token - expected bool/switch, found " + << tok.info() << nl; + } + return os; +} +} // End namespace Foam + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // Foam::Switch::switchType Foam::Switch::parse ( const std::string& str, - bool allowBad + const bool failOnError ) { switch (str.size()) @@ -108,10 +129,10 @@ Foam::Switch::switchType Foam::Switch::parse } } - if (!allowBad) + if (failOnError) { FatalErrorInFunction - << "Unknown switch word " << str << nl + << "Unknown switch " << str << nl << abort(FatalError); } @@ -119,45 +140,116 @@ Foam::Switch::switchType Foam::Switch::parse } +// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * // + +const char* Foam::Switch::name(const bool b) noexcept +{ + return names[(b ? 1 : 0)]; +} + + +Foam::Switch Foam::Switch::find(const std::string& str) +{ + return Switch(parse(str, false)); // failOnError=false +} + + +bool Foam::Switch::found(const std::string& str) +{ + return (switchType::INVALID != parse(str, false)); // failOnError=false +} + + Foam::Switch Foam::Switch::getOrAddToDict ( - const word& name, + const word& key, dictionary& dict, const Switch deflt ) { - return dict.getOrAdd(name, deflt); + return dict.getOrAdd(key, deflt, keyType::LITERAL); } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // +Foam::Switch::Switch(const std::string& str) +: + value_(parse(str, true)) +{} + + +Foam::Switch::Switch(const char* str) +: + value_(parse(str, true)) +{} + + +Foam::Switch::Switch(const std::string& str, bool allowBad) +: + value_(parse(str, !allowBad)) +{} + + +Foam::Switch::Switch(const char* str, bool allowBad) +: + value_(parse(str, !allowBad)) +{} + + Foam::Switch::Switch(const float val, const float tol) : - switch_((mag(val) > tol) ? switchType::TRUE : switchType::FALSE) + value_((mag(val) > tol) ? switchType::TRUE : switchType::FALSE) {} Foam::Switch::Switch(const double val, const double tol) : - switch_((mag(val) > tol) ? switchType::TRUE : switchType::FALSE) + value_((mag(val) > tol) ? switchType::TRUE : switchType::FALSE) {} +Foam::Switch::Switch(const token& tok) +: + value_(switchType::INVALID) +{ + if (tok.good()) + { + if (tok.isBool()) + { + (*this) = tok.boolToken(); + } + else if (tok.isLabel()) + { + (*this) = bool(tok.labelToken()); + } + else if (tok.isWord()) + { + value_ = parse(tok.wordToken(), false); // failOnError=false + } + } +} + + Foam::Switch::Switch ( const word& key, const dictionary& dict ) +: + value_(switchType::INVALID) { - const word str(dict.get(key, keyType::LITERAL)); + const token tok(dict.get(key, keyType::LITERAL)); - (*this) = parse(str, true); + Switch sw(tok); - if (!valid()) + if (sw.good()) { - FatalIOErrorInFunction(dict) - << "Expected 'true/false', 'on/off' ... found " << str << nl + (*this) = sw; + } + else + { + printTokenError(FatalIOErrorInFunction(dict), tok) << exit(FatalIOError); } } @@ -167,25 +259,30 @@ Foam::Switch::Switch ( const word& key, const dictionary& dict, - const Switch deflt + const Switch deflt, + const bool failsafe ) : - Switch(deflt) + value_(deflt.value_) { - const entry* eptr = dict.findEntry(key, keyType::LITERAL); + token tok; - if (eptr) + if (dict.readIfPresent(key, tok, keyType::LITERAL)) { - const word str(eptr->get()); + Switch sw(tok); - (*this) = parse(str, true); - - if (!valid()) + if (sw.good()) { - // Found entry, but was bad input - - FatalIOErrorInFunction(dict) - << "Expected 'true/false', 'on/off' ... found " << str << nl + (*this) = sw; + } + else if (failsafe) + { + printTokenError(IOWarningInFunction(dict), tok) + << "using failsafe " << deflt.c_str() << endl; + } + else + { + printTokenError(FatalIOErrorInFunction(dict), tok) << exit(FatalIOError); } } @@ -200,33 +297,37 @@ Foam::Switch::Switch(Istream& is) // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // -bool Foam::Switch::valid() const noexcept +bool Foam::Switch::good() const noexcept { - return switch_ != switchType::INVALID; + return (value_ < switchType::INVALID); } Foam::Switch::switchType Foam::Switch::type() const noexcept { - return switchType(switch_); + return switchType(value_); } const char* Foam::Switch::c_str() const noexcept { - return names[(switch_ & 0x0F)]; + return names[(value_ & 0x0F)]; } std::string Foam::Switch::str() const { - return names[(switch_ & 0x0F)]; + return names[(value_ & 0x0F)]; } -bool Foam::Switch::readIfPresent(const word& name, const dictionary& dict) +bool Foam::Switch::readIfPresent +( + const word& key, + const dictionary& dict +) { - return dict.readIfPresent(name, *this); + return dict.readIfPresent(key, *this, keyType::LITERAL); } @@ -234,47 +335,21 @@ bool Foam::Switch::readIfPresent(const word& name, const dictionary& dict) Foam::Istream& Foam::operator>>(Istream& is, Switch& sw) { - token t(is); + token tok(is); - if (!t.good()) - { - FatalIOErrorInFunction(is) - << "Bad token - could not get bool" - << exit(FatalIOError); - is.setBad(); - return is; - } + sw = Switch(tok); - if (t.isLabel()) + if (sw.good()) { - sw = bool(t.labelToken()); - } - else if (t.isWord()) - { - // Permit invalid value, but catch immediately for better messages - sw = Switch(t.wordToken(), true); - - if (!sw.valid()) - { - FatalIOErrorInFunction(is) - << "Expected 'true/false', 'on/off' ... found " - << t.wordToken() - << exit(FatalIOError); - is.setBad(); - return is; - } + is.check(FUNCTION_NAME); } else { - FatalIOErrorInFunction(is) - << "Wrong token type - expected bool, found " - << t.info() + printTokenError(FatalIOErrorInFunction(is), tok) << exit(FatalIOError); is.setBad(); - return is; } - is.check(FUNCTION_NAME); return is; } diff --git a/src/OpenFOAM/primitives/bools/Switch/Switch.H b/src/OpenFOAM/primitives/bools/Switch/Switch.H index 13cc7fee68..dc937778e6 100644 --- a/src/OpenFOAM/primitives/bools/Switch/Switch.H +++ b/src/OpenFOAM/primitives/bools/Switch/Switch.H @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2017-2019 OpenCFD Ltd. + Copyright (C) 2017-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,7 +40,7 @@ SourceFiles #define Switch_H #include "bool.H" -#include "word.H" +#include "stdFoam.H" // Avoid any pre-processor conflicts with enum names #undef FALSE @@ -56,12 +56,18 @@ SourceFiles namespace Foam { -// Forward declarations -class Switch; +// Forward Declarations class dictionary; +class token; +class word; +class Switch; // IOstream Operators + +//- Read Switch from stream using Foam::Switch(Istream&) Istream& operator>>(Istream& is, Switch& sw); + +//- Write Switch to stream as its text value (eg, "true", "false") Ostream& operator<<(Ostream& is, const Switch& sw); /*---------------------------------------------------------------------------*\ @@ -72,19 +78,21 @@ class Switch { public: - //- Switch enumerations corresponding to common text representations. - // \note the values specified here are critical for its proper behaviour. - // The lower bit is tested for the true/false condition. - // The values correspond to an index into the predefined output names - // for the c_str() method. - enum switchType : unsigned char - { - FALSE = 0 /*!< "false" */, TRUE = 1 /*!< "true" */, - NO = 2 /*!< "no" */, YES = 3 /*!< "yes" */, - OFF = 4 /*!< "off" */, ON = 5 /*!< "on" */, - NONE = 6 /*!< "none" */, ANY = 7 /*!< "any" */, - INVALID = 8 /*!< "invalid" */ - }; + // Data Types + + //- Switch enumerations corresponding to common text representations. + // \note The values here are critical for its proper behaviour. + // The values correspond to an index into the predefined output names + // for the c_str() method and the lower bit is tested for + // determining the true/false bool value. + enum switchType : unsigned char + { + FALSE = 0 /*!< "false" */, TRUE = 1 /*!< "true" */, + NO = 2 /*!< "no" */, YES = 3 /*!< "yes" */, + OFF = 4 /*!< "off" */, ON = 5 /*!< "on" */, + NONE = 6 /*!< "none" */, ANY = 7 /*!< "any" */, + INVALID = 8 /*!< "invalid" */, + }; private: @@ -92,43 +100,61 @@ private: // Private Data //- The logic and enumerated text representation stored in a byte - unsigned char switch_; + unsigned char value_; - // Static Member Functions + // Private Member Functions - //- Return enum value for input string - static switchType parse(const std::string& str, bool allowBad); + //- Find switchType for given string. Return 'INVALID' if not found. + // With failOnError, trigger FatalError if not found + static switchType parse(const std::string& str, const bool failOnError); public: + // Generated Methods + + //- Copy construct + Switch(const Switch&) noexcept = default; + + //- Copy assignment + Switch& operator=(const Switch&) noexcept = default; + + // Constructors - //- Null constructible as false + //- Default construct as false constexpr Switch() noexcept : - switch_(switchType::FALSE) + value_(switchType::FALSE) {} //- Construct from enumerated value constexpr Switch(const switchType sw) noexcept : - switch_(sw) + value_(sw) {} //- Construct from bool constexpr Switch(const bool b) noexcept : - switch_(b ? switchType::TRUE : switchType::FALSE) + value_(b ? switchType::TRUE : switchType::FALSE) {} //- Construct from int (treat integer as bool value) constexpr Switch(const int i) noexcept : - switch_(i ? switchType::TRUE : switchType::FALSE) + value_(i ? switchType::TRUE : switchType::FALSE) {} + //- Construct from string - catches bad input. + // Use static find() method for a failsafe alternative + explicit Switch(const std::string& str); + + //- Construct from character array - catches bad input. + // Use static find() method for a failsafe alternative + explicit Switch(const char* str); + //- Construct from float with rounding to zero given by //- the tolerance (default: 0.5) explicit Switch(const float val, const float tol=0.5); @@ -137,31 +163,8 @@ public: //- the tolerance (default: 0.5) explicit Switch(const double val, const double tol=0.5); - //- Construct from string - catches bad input. - explicit Switch(const std::string& str) - : - switch_(parse(str, false)) - {} - - //- Construct from character array - catches bad input. - explicit Switch(const char* str) - : - switch_(parse(str, false)) - {} - - //- Construct from string. - // Optionally allow bad words, and catch the error elsewhere - Switch(const std::string& str, bool allowBad) - : - switch_(parse(str, allowBad)) - {} - - //- Construct from character array. - // Optionally allow bad words, and catch the error elsewhere - Switch(const char* str, bool allowBad) - : - switch_(parse(str, allowBad)) - {} + //- Construct from token. Handles bool/label/word types. + explicit Switch(const token& tok); //- Construct from dictionary lookup. // FatalError if anything is incorrect. @@ -171,17 +174,20 @@ public: const dictionary& dict //!< dictionary ); - //- Find the key in the dictionary and return the corresponding - //- switch value, or the default value. - // FatalError if anything is incorrect. + //- Find the key in the dictionary and use the corresponding + //- switch value or the default if not found in dictionary. + // + // FatalIOError if the switch name is incorrect. + // Specifying failsafe downgrades the FatalIOError to an IOWarning. Switch ( const word& key, //!< Lookup key. Uses LITERAL (not REGEX) const dictionary& dict, //!< dictionary - const Switch deflt //!< fallback if not found + const Switch deflt, //!< fallback if not found + const bool failsafe = false //!< Warn only on bad input ); - //- Construct from Istream + //- Construct from Istream by reading a token explicit Switch(Istream& is); @@ -191,9 +197,9 @@ public: //- value is not found, it is added into the dictionary. static Switch getOrAddToDict ( - const word& name, //!< Lookup key. Uses REGEX! - dictionary& dict, //!< dictionary - const Switch deflt = switchType::FALSE //!< default to add + const word& key, //!< Lookup key. Uses LITERAL (not REGEX) + dictionary& dict, //!< dictionary + const Switch deflt = switchType::FALSE //!< default value to add ); @@ -202,16 +208,26 @@ public: //- A string representation of bool as "false" / "true" static const char* name(const bool b) noexcept; + //- Find switchType for the given string, returning as a Switch that + //- can be tested for good() or bad(). + static Switch find(const std::string& str); + + //- Test if there is a switch type corresponding to the given string. + static bool found(const std::string& str); + // Member Functions //- True if the Switch represents a valid enumeration - bool valid() const noexcept; + bool good() const noexcept; + + //- True if the Switch does not represent a valid enumeration + bool bad() const noexcept { return !good(); } //- The underlying enumeration value switchType type() const noexcept; - //- A string representation of the Switch value + //- A C-string representation of the Switch value const char* c_str() const noexcept; //- A string representation of the Switch value @@ -220,8 +236,8 @@ public: //- Update the value of the Switch if it is found in the dictionary bool readIfPresent ( - const word& name, //!< Lookup key. Uses REGEX! - const dictionary& dict //!< dictionary + const word& key, //!< Lookup key. Uses LITERAL (not REGEX) + const dictionary& dict //!< dictionary ); @@ -230,41 +246,54 @@ public: //- Conversion to bool operator bool() const noexcept { - return (switch_ & 0x1); + return (value_ & 0x1); } //- Assignment from enumerated value Switch& operator=(const switchType sw) noexcept { - switch_ = sw; + value_ = sw; return *this; } //- Assignment from bool Switch& operator=(const bool b) noexcept { - switch_ = (b ? Switch::TRUE : Switch::FALSE); + value_ = (b ? Switch::TRUE : Switch::FALSE); return *this; } // Housekeeping - //- Construct from dictionary, supplying default value so that if the - //- value is not found, it is added into the dictionary. + //- Deprecated(2020-01) From string with/without bad input test + // \deprecated(2020-01) - confusing syntax, use static find() method + FOAM_DEPRECATED_FOR(2019-02, "static find() method") + Switch(const std::string& str, bool allowBad); + + //- Deprecated(2020-01) From string with/without bad input test + // \deprecated(2020-01) - confusing syntax, use static find() method + FOAM_DEPRECATED_FOR(2019-02, "static find() method") + Switch(const char* str, bool allowBad); + + //- Deprecated(2020-01) Use good() method, or static found() method + // \deprecated(2020-01) Use good() method, or static found() method + FOAM_DEPRECATED_FOR(2019-02, "good() or static found() method") + bool valid() const noexcept + { + return good(); + } + + //- Same as getOrAddToDict() static Switch lookupOrAddToDict ( - const word& name, //!< Lookup key. Uses REGEX! - dictionary& dict, //!< dictionary - const Switch deflt = switchType::FALSE //!< default to add + const word& name, + dictionary& dict, + const Switch deflt = switchType::FALSE ) { return getOrAddToDict(name, dict, deflt); } - - //- Deprecated(2018-03) text representation of the Switch value - // \deprecated(2018-03) - use c_str() method - inline const char* asText() const { return c_str(); }; }; diff --git a/src/OpenFOAM/primitives/bools/bool/bool.C b/src/OpenFOAM/primitives/bools/bool/bool.C index 1974670778..378173fc08 100644 --- a/src/OpenFOAM/primitives/bools/bool/bool.C +++ b/src/OpenFOAM/primitives/bools/bool/bool.C @@ -6,7 +6,7 @@ \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation - Copyright (C) 2018 OpenCFD Ltd. + Copyright (C) 2018-2020 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -61,7 +61,7 @@ Foam::Istream& Foam::operator>>(Istream& is, bool& b) Foam::Ostream& Foam::operator<<(Ostream& os, const bool b) { // Emit as label (not byte etc) for proper send/receive in parallel - os.write(label(b)); + os.write(static_cast