Commit fd348374 authored by Mark Olesen's avatar Mark Olesen
Browse files

ENH: add 'default' as possible Switch state, but not as input/output

- in some circumstances we need to pass a bool value upwards to the
  caller and know if the true/false value was set based on real input
  or is a default value.

  Eg, in the object::read() we might normally have

     enabled_(dict.readIfPresent(key, true));

  but would lose information about why the value is true/false.

  We can change that by using

     enabled_(dict.readIfPresent<Switch>(key, Switch::DEFAULT_ON));

  After which we can use this information is testing.

      if
      (
          child.enabled().nonDefault()
        ? child.enabled()
        : parent.enabled()
      )
      { ... }

   And thus enable output if the parent requested it explicitly or by
   default and it has not been explicitly disabled in the child.

  No difference when testing as a bool and the text representation
  of DEFAULT_ON / DEFAULT_OFF will simply be "true" / "false".

ENH: add construction of Switch from dictionary (similar to Enum)
parent 01b02a9c
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -35,6 +35,8 @@ Description
#include "NASCore.H"
#include "parsing.H"
#include "Tuple2.H"
#include "Switch.H"
#include "dictionary.H"
using namespace Foam;
......@@ -45,6 +47,20 @@ inline scalar readNasScalar(const std::string& str)
}
// As a function
inline Switch readSwitch(const std::string& str)
{
Switch sw(str);
if (sw.type() == Switch::ON)
{
Info<< "Was 'on'" << nl;
}
return sw;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T>
......@@ -96,7 +112,8 @@ unsigned testParsing
string errMsg;
// Expect some failures
const bool prev = FatalIOError.throwExceptions();
const bool prev1 = FatalError.throwExceptions();
const bool prev2 = FatalIOError.throwExceptions();
for (const std::pair<bool, std::string>& test : tests)
{
......@@ -120,7 +137,8 @@ unsigned testParsing
hadParsingError(test, result, errMsg);
}
FatalIOError.throwExceptions(prev);
FatalError.throwExceptions(prev1);
FatalIOError.throwExceptions(prev2);
return nFail;
}
......@@ -130,6 +148,36 @@ int main(int argc, char *argv[])
{
unsigned nFail = 0;
{
Info<< nl << "Test Switch parsing:" << nl;
nFail += testParsing
(
&readSwitch,
{
{ false, "True" },
{ true, "false" },
{ true, "on" },
{ false, "None" },
{ false, "default" },
}
);
dictionary dict;
dict.add("key1" , "true");
{
Switch sw("key", dict, Switch::DEFAULT_ON);
Info<<"got: " << sw << " type is DEFAULT_ON? "
<< (sw.type() == Switch::DEFAULT_ON) << nl;
}
{
Switch sw("key1", dict, Switch::DEFAULT_ON);
Info<<"got: " << sw << " type is DEFAULT_ON? "
<< (sw.type() == Switch::DEFAULT_ON) << nl;
}
}
{
Info<< nl << "Test readDouble: (small=" << doubleScalarVSMALL
<< " great=" << doubleScalarVSMALL << "):" << nl;
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -121,6 +121,54 @@ Foam::Switch Foam::Switch::lookupOrAddToDict
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::Switch::Switch
(
const word& key,
const dictionary& dict
)
{
const word str(dict.get<word>(key, keyType::LITERAL));
(*this) = parse(str, true);
if (!valid())
{
FatalIOErrorInFunction(dict)
<< "Expected 'true/false', 'on/off' ... found " << str << nl
<< exit(FatalIOError);
}
}
Foam::Switch::Switch
(
const word& key,
const dictionary& dict,
const Switch defaultValue
)
:
Switch(defaultValue)
{
const entry* eptr = dict.findEntry(key, keyType::LITERAL);
if (eptr)
{
const word str(eptr->get<word>());
(*this) = parse(str, true);
if (!valid())
{
// Found entry, but was bad input
FatalIOErrorInFunction(dict)
<< "Expected 'true/false', 'on/off' ... found " << str << nl
<< exit(FatalIOError);
}
}
}
Foam::Switch::Switch(Istream& is)
{
is >> *this;
......@@ -131,19 +179,37 @@ Foam::Switch::Switch(Istream& is)
bool Foam::Switch::valid() const noexcept
{
return switch_ <= switchType::NONE;
return switch_ != switchType::INVALID;
}
Foam::Switch::switchType Foam::Switch::type() const noexcept
{
return switchType(switch_);
}
bool Foam::Switch::isDefault() const noexcept
{
return (switch_ & 0x10);
}
bool Foam::Switch::nonDefault() const noexcept
{
return !isDefault();
}
const char* Foam::Switch::c_str() const noexcept
{
return names[switch_];
return names[(switch_ & 0x0F)];
}
std::string Foam::Switch::str() const
{
return names[switch_];
return names[(switch_ & 0x0F)];
}
......
......@@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | Copyright (C) 2017-2019 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
......@@ -81,7 +81,9 @@ public:
NO = 2 /*!< "no" */, YES = 3 /*!< "yes" */,
OFF = 4 /*!< "off" */, ON = 5 /*!< "on" */,
NONE = 6 /*!< "none" */,
INVALID = 8 /*!< "invalid" */
INVALID = 8 /*!< "invalid" */,
DEFAULT_OFF = 0x10 /*!< off/false (as default value) */,
DEFAULT_ON = 0x11 /*!< on/true (as default value) */
};
......@@ -92,6 +94,7 @@ private:
//- The logic and enumerated text representation stored in a byte
unsigned char switch_;
// Static Member Functions
//- Return enum value for input string
......@@ -152,6 +155,24 @@ public:
switch_(parse(str, allowBad))
{}
//- Construct from dictionary lookup.
// FatalError if anything is incorrect.
Switch
(
const word& key, //!< Lookup key. Uses LITERAL (not REGEX)
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.
Switch
(
const word& key, //!< Lookup key. Uses LITERAL (not REGEX)
const dictionary& dict, //!< dictionary
const Switch defaultValue //!< fallback if not found
);
//- Construct from Istream
explicit Switch(Istream& is);
......@@ -159,7 +180,7 @@ public:
// Helpers
//- Construct from dictionary, supplying default value so that if the
// value is not found, it is added into the dictionary.
//- value is not found, it is added into the dictionary.
static Switch lookupOrAddToDict
(
const word& name,
......@@ -170,9 +191,18 @@ public:
// Member Functions
//- Return true if the Switch has a valid value
//- True if the Switch has a valid value
bool valid() const noexcept;
//- The underlying enumeration value
switchType type() const noexcept;
//- Underlying enumeration is DEFAULT_ON or DEFAULT_OFF
  • @Mattijs - Andy figures that this fattens up Switch too much. I argued for occasional need for a tristate boolean. Eg,

    Switch useXyz(Switch::DEFAULT_TRUE);
    
    // later on
    dict.readIfPresent("something", useXyz);
    
    
    // much later on
    
    if (useXyz.specified())
    {
         ....
    }

    Since we always test for bool or cast to bool based on the last bit, there is no difference in its use as a logical.

    if (useXyz) ...

    And displays the same as: os << useXyz => "true"

    What's your opinion? Keep it as a poor man's std::optional for booleans, or rip it out (ie, revert)?

    Edited by Mark Olesen
Please register or sign in to reply
bool isDefault() const noexcept;
//- Underlying enumeration is not DEFAULT_ON or DEFAULT_OFF
bool nonDefault() const noexcept;
//- A string representation of the Switch value
const char* c_str() const noexcept;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment