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

bool and Switch reworked

- Switch now stores its value as an unsigned char, which gives it the same
  storage requirement as bool (1 byte). The original implementation had both
  bool+word (1+XXX bytes storage), an intermediate version with bool+enum
  had 8 bytes (1+4 + boundary alignment).

- The reading code in boolIO.C and SwitchIO.C is now identical except for
  the error message. This allows Switch to accept '1', '0' as logical
  values, and allows bool to accept 'yes', 'no' etc. as logical values.

- The Switch text translation of a bool value is now true/false instead of
  on/off. This is partly personal preference, but we could also output the
  same text when writing a bool value to Ostream.

- Switch gets null and integer constructors so it feels more like bool.
  Added Switch::operator=(const bool);

- Low-level types can be used for the constructors, and low-level return
  values are used for the greatest flexibility (and speed).

- Fixed bugginess with dictionary lookup. The previous version actually used
  a bool instead of a Switch and bombed on 'on/off'.

TODO?
  perhaps don't worry about the error message and just call the Switch
  routines from bool.
parent d5cbc3bf
......@@ -31,7 +31,7 @@ License
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// NB: values chosen such that bitwise '&' 0x1 yields the bool value
// INVALID is also evaluates to false, but don't rely on that
const char* Foam::Switch::names[Foam::Switch::INVALID+1] =
{
"false", "true",
......@@ -44,24 +44,31 @@ const char* Foam::Switch::names[Foam::Switch::INVALID+1] =
// * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * * //
Foam::Switch::switchType Foam::Switch::asEnum(const bool val)
{
return val ? Switch::FALSE : Switch::TRUE;
}
Foam::Switch::switchType Foam::Switch::asEnum
Foam::Switch::switchType
Foam::Switch::asEnum
(
const word& val,
const bool ignoreError
const std::string& str,
const bool allowInvalid
)
{
for (int sw = 0; sw < INVALID; sw++)
for (int sw = 0; sw < Switch::INVALID; sw++)
{
if (val == names[sw])
if (str == names[sw])
{
if (sw == NO_1)
// convert y/n to yes/no (perhaps should deprecate y/n)
if (sw == Switch::NO_1)
{
return NO;
return Switch::NO;
}
else if (sw == YES_1)
else if (sw == Switch::YES_1)
{
return YES;
return Switch::YES;
}
else
{
......@@ -70,10 +77,10 @@ Foam::Switch::switchType Foam::Switch::asEnum
}
}
if (!ignoreError)
if (!allowInvalid)
{
FatalErrorIn("Switch::asEnum(const word&)")
<< "unknown switch word " << val
FatalErrorIn("Switch::asEnum(const std::string&)")
<< "unknown switch word " << str << nl
<< abort(FatalError);
}
......@@ -81,47 +88,41 @@ Foam::Switch::switchType Foam::Switch::asEnum
}
Foam::Switch::switchType Foam::Switch::asEnum(const bool val)
bool Foam::Switch::asBool(const switchType sw)
{
return val ? ON : OFF;
return (sw & 0x1);
}
bool Foam::Switch::asBool
(
const word& val,
const bool ignoreError
const std::string& str,
const bool allowInvalid
)
{
switchType sw = asEnum(val, true);
// allow invalid values, but catch after for correct error message
switchType sw = asEnum(str, true);
// catch error here
if (sw == INVALID && !ignoreError)
if (sw == Switch::INVALID && !allowInvalid)
{
FatalErrorIn("Switch::asBool(const word&)")
<< "unknown switch word " << val
FatalErrorIn("Switch::asBool(const std::string&)")
<< "unknown switch word " << str << nl
<< abort(FatalError);
}
return asBool(sw);
}
bool Foam::Switch::asBool(const switchType& val)
{
return (val & 0x1);
return (sw & 0x1);
}
Foam::word Foam::Switch::asWord(const bool val)
const char* Foam::Switch::asText(const bool b)
{
return word((val ? names[ON] : names[OFF]), false);
return b ? names[Switch::TRUE] : names[Switch::FALSE];
}
Foam::word Foam::Switch::asWord(const switchType& val)
const char* Foam::Switch::asText(const switchType sw)
{
return word(names[val], false);
return names[sw];
}
......@@ -140,7 +141,7 @@ Foam::Switch Foam::Switch::lookupOrAddToDict
bool Foam::Switch::readIfPresent(const word& name, const dictionary& dict)
{
return dict.readIfPresent(name, bool_);
return dict.readIfPresent<Switch>(name, *this);
}
......
......@@ -27,7 +27,7 @@ Class
Description
A simple wrapper around bool so that it can be read as a word:
on/off, true/false, yes/no or y/n.
true/false, on/off, yes/no or y/n.
SourceFiles
Switch.C
......@@ -61,19 +61,28 @@ class dictionary;
class Switch
{
private:
// Private data
//- The logic and enumerated text representation stored as a single byte
unsigned char switch_;
public:
//- The various text representations for a switch value.
enum switchType
{
FALSE = 0, TRUE = 1,
OFF = 2, ON = 3,
NO = 4, YES = 5,
NO_1 = 6, YES_1 = 7,
INVALID
};
// Public data types
//- The various text representations for a switch value.
// These also correspond to the entries in names.
enum switchType
{
FALSE = 0, TRUE = 1,
OFF = 2, ON = 3,
NO = 4, YES = 5,
NO_1 = 6, YES_1 = 7,
INVALID
};
private:
// Static data members
......@@ -81,49 +90,68 @@ private:
// Includes an extra entry for "invalid".
static const char* names[INVALID+1];
// Private data
//- Enumerated string representation
switchType switch_;
//- The boolean value
bool bool_;
public:
// Private member functions
// Static Member Functions
//- Return a switchType representation of a bool
static switchType asEnum(const bool);
//- Return a switchType representation of a word
static switchType asEnum(const word&, const bool ignoreError=false);
// Optionally allow bad words, and catch the error elsewhere
static switchType asEnum
(
const std::string&,
const bool allowInvalid=false
);
//- Return a bool representation of a switchType
static bool asBool(const switchType);
//- Return a bool representation of a word
static bool asBool(const word&, const bool ignoreError=false);
// Optionally allow bad words, and catch the error elsewhere
static bool asBool
(
const std::string&,
const bool allowInvalid=false
);
//- Return a bool representation of a switchType
static bool asBool(const switchType&);
//- Return a text representation of a bool value
static const char* asText(const bool);
//- Return a word representation of a bool value
static word asWord(const bool);
//- Return a text representation of a switchType
static const char* asText(const switchType);
//- Return a word representation of a switchType
static word asWord(const switchType&);
// Constructors
//- Construct null as false
Switch()
:
switch_(Switch::FALSE)
{}
//- Construct from bool
Switch(const bool value)
:
switch_(asEnum(value)),
bool_(value)
switch_(asEnum(value))
{}
//- Construct from integer values (treats integer as bool value)
Switch(const int value)
:
switch_(asEnum(bool(value)))
{}
//- Construct from std::string, string, word
Switch(const std::string& value)
:
switch_(asEnum(value))
{}
//- Construct from word
Switch(const word& value)
//- Construct from character array
Switch(const char* value)
:
switch_(asEnum(value)),
bool_(asBool(switch_))
switch_(asEnum(std::string(value)))
{}
//- Construct from Istream
......@@ -141,24 +169,18 @@ public:
// Member Operators
Switch& operator=(const Switch& rhs)
//- Conversion to bool
operator bool() const
{
switch_ = rhs.switch_;
bool_ = rhs.bool_;
return *this;
return (switch_ & 0x1);
}
operator bool() const
//- Assignment from bool
void operator=(const bool b)
{
return bool_;
switch_ = (b ? Switch::TRUE : Switch::FALSE);
}
// operator const word&() const
// {
// return asWord(switch_);
// }
// Member fuctions
......
......@@ -39,11 +39,49 @@ Foam::Switch::Switch(Istream& is)
Foam::Istream& Foam::operator>>(Istream& is, Switch& s)
{
word w(is);
s.switch_ = Switch::asEnum(w);
s.bool_ = Switch::asBool(s.switch_);
token t(is);
if (!t.good())
{
is.setBad();
return is;
}
if (t.isLabel())
{
s.switch_ = Switch::asEnum(bool(t.labelToken()));
}
else if (t.isWord())
{
// allow invalid values, but catch after for correct error message
Switch::switchType sw = Switch::asEnum(t.wordToken(), true);
if (sw == Switch::INVALID)
{
is.setBad();
FatalIOErrorIn("operator>>(Istream&, Switch&)", is)
<< "expected 'true/false', 'on/off' ... found " << t.wordToken()
<< exit(FatalIOError);
return is;
}
else
{
s.switch_ = sw;
}
}
else
{
is.setBad();
FatalIOErrorIn("operator>>(Istream&, bool/Switch&)", is)
<< "wrong token type - expected bool found " << t
<< exit(FatalIOError);
return is;
}
// Check state of Istream
is.check("Istream& operator>>(Istream&, Switch&)");
return is;
......@@ -52,7 +90,7 @@ Foam::Istream& Foam::operator>>(Istream& is, Switch& s)
Foam::Ostream& Foam::operator<<(Ostream& os, const Switch& s)
{
os << Switch::names[s.switch_];
os << Switch::names[s.switch_];
os.check("Ostream& operator<<(Ostream&, const Switch&)");
return os;
}
......
......@@ -22,9 +22,6 @@ License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
\*---------------------------------------------------------------------------*/
#include "bool.H"
......@@ -32,8 +29,8 @@ Description
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
const char* const Foam::pTraits<bool>::typeName = "bool";
const bool Foam::pTraits<bool>::zero = 0;
const bool Foam::pTraits<bool>::one = 1;
const bool Foam::pTraits<bool>::zero(false);
const bool Foam::pTraits<bool>::one(true);
const char* Foam::pTraits<bool>::componentNames[] = { "x" };
......
......@@ -77,7 +77,7 @@ public:
enum
{
dim = 3, // Dimensionality of space
rank = 0, // Rank od bool is 0
rank = 0, // Rank of bool is 0
nComponents = 1 // Number of components in bool is 1
};
......@@ -91,7 +91,7 @@ public:
// Constructors
//- Construct from Istream
pTraits(Istream& is);
pTraits(Istream&);
// Member Functions
......
......@@ -32,12 +32,25 @@ Description
#include "error.H"
#include "bool.H"
#include "Switch.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, bool& b)
{
// we could also process everything via Switch
// The error messages are the problem: they are from SwitchIO.C
// Switch sw(is);
//
// if (is.good())
// {
// b = sw;
// }
//
// return is;
//
//
token t(is);
if (!t.good())
......@@ -52,29 +65,27 @@ Foam::Istream& Foam::operator>>(Istream& is, bool& b)
}
else if (t.isWord())
{
// use Switch asBool() here?
if (t.wordToken() == "true" || t.wordToken() == "on")
{
b = true;
}
else if (t.wordToken() == "false" || t.wordToken() == "off")
{
b = false;
}
else
// allow invalid values, but catch after for correct error message
Switch::switchType sw = Switch::asEnum(t.wordToken(), true);
if (sw == Switch::INVALID)
{
is.setBad();
FatalIOErrorIn("operator>>(Istream&, bool&)", is)
<< "expected 'true' or 'false', found " << t.wordToken()
<< "expected 'true/false', 'on/off', found " << t.wordToken()
<< exit(FatalIOError);
return is;
}
else
{
b = Switch::asBool(sw);
}
}
else
{
is.setBad();
FatalIOErrorIn("operator>>(Istream&, bool&)", is)
FatalIOErrorIn("operator>>(Istream&, bool/Switch&)", is)
<< "wrong token type - expected bool found " << t
<< exit(FatalIOError);
......@@ -82,7 +93,6 @@ Foam::Istream& Foam::operator>>(Istream& is, bool& b)
}
// Check state of Istream
is.check("Istream& operator>>(Istream&, bool&)");
......@@ -92,18 +102,21 @@ Foam::Istream& Foam::operator>>(Istream& is, bool& b)
Foam::Ostream& Foam::operator<<(Ostream& os, const bool b)
{
// we could also write as text string without any difficulty
// os << Switch::asText(b);
os.write(label(b));
os.check("Ostream& operator<<(Ostream&, const bool&)");
os.check("Ostream& operator<<(Ostream&, const bool)");
return os;
}
bool Foam::readBool(Istream& is)
{
bool b;
is >> b;
bool val;
is >> val;
return b;
return val;
}
// ************************************************************************* //
Supports Markdown
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