ENH: simplify direct creation of dictionary primitive entries

- can now create an empty entry and add/overwrite with tokens afterwards,
  or copy/move construct from a list of tokens.

ENH: provided named token setter methods (disambiguates bool/char/label)

COMP: use 'if constexpr' for FlatOutput

DOC: more description for Field
This commit is contained in:
Mark Olesen
2025-09-02 14:54:06 +02:00
parent d4019e497d
commit c378893bcb
20 changed files with 284 additions and 89 deletions

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,33 +42,55 @@ Description
using namespace Foam;
class Scalar
bool verbosity = true;
// Gratuitous class inheritance
template<class T>
class BoxedType
{
scalar data_;
T data_;
public:
static bool verbose;
constexpr Scalar() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {}
constexpr BoxedType() noexcept : data_(0) {}
BoxedType(T val) noexcept : data_(val) {}
~BoxedType()
{
if (verbosity) Info<< " [delete BoxedType: " << value() << ']' << nl;
}
T value() const noexcept { return data_; }
T& value() noexcept { return data_; }
auto clone() const { return autoPtr<BoxedType<T>>::New(*this); }
};
template<class T> Ostream& operator<<(Ostream& os, const BoxedType<T>& item)
{
return (os << " -> " << item.value());
}
class Scalar : public BoxedType<scalar>
{
public:
using BoxedType<scalar>::BoxedType;
~Scalar()
{
if (verbose) Info<< "delete Scalar: " << data_ << endl;
}
const scalar& value() const noexcept { return data_; }
scalar& value() noexcept { return data_; }
friend Ostream& operator<<(Ostream& os, const Scalar& item)
{
os << item.value();
return os;
if (verbosity) Info<< "delete Scalar: " << value() << nl;
}
auto clone() const { return autoPtr<Scalar>::New(*this); }
};
bool Scalar::verbose = true;
Ostream& operator<<(Ostream& os, const Scalar& item)
{
return (os << item.value());
}
template<class T>

View File

@ -1,3 +1,3 @@
Test-ISLList.C
Test-ISLList.cxx
EXE = $(FOAM_USER_APPBIN)/Test-ISLList

View File

@ -1,3 +1,3 @@
Test-PtrDictionary1.C
Test-PtrDictionary1.cxx
EXE = $(FOAM_USER_APPBIN)/Test-PtrDictionary1

View File

@ -42,6 +42,8 @@ Description
using namespace Foam;
bool verbosity = true;
class ent
:
public Dictionary<ent>::link
@ -73,14 +75,12 @@ class Scalar
public:
static bool verbose;
constexpr Scalar() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {}
~Scalar()
{
if (verbose) Info<< "delete Scalar: " << data_ << endl;
if (verbosity) Info<< "delete Scalar: " << data_ << endl;
}
scalar value() const noexcept { return data_; }
@ -93,8 +93,6 @@ public:
}
};
bool Scalar::verbose = true;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:

View File

@ -41,35 +41,85 @@ Description
using namespace Foam;
class Scalar
bool verbosity = true;
// Gratuitous class inheritance
template<class T>
class BoxedType
{
scalar data_;
T data_;
public:
static bool verbose;
constexpr Scalar() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {}
constexpr BoxedType() noexcept : data_(0) {}
BoxedType(T val) noexcept : data_(val) {}
~BoxedType()
{
if (verbosity) Info<< " [delete BoxedType: " << value() << ']' << nl;
}
T value() const noexcept { return data_; }
T& value() noexcept { return data_; }
auto clone() const { return autoPtr<BoxedType<T>>::New(*this); }
};
template<class T> Ostream& operator<<(Ostream& os, const BoxedType<T>& item)
{
return (os << " -> " << item.value());
}
class Scalar : public BoxedType<scalar>
{
public:
using BoxedType<scalar>::BoxedType;
~Scalar()
{
if (verbose) Info<< "delete Scalar: " << data_ << endl;
}
scalar value() const noexcept { return data_; }
scalar& value() noexcept { return data_; }
autoPtr<Scalar> clone() const { return autoPtr<Scalar>::New(data_); }
friend Ostream& operator<<(Ostream& os, const Scalar& item)
{
os << item.value();
return os;
if (verbosity) Info<< "delete Scalar: " << value() << nl;
}
auto clone() const { return autoPtr<Scalar>::New(*this); }
};
bool Scalar::verbose = true;
Ostream& operator<<(Ostream& os, const Scalar& item)
{
return (os << item.value());
}
class Integer : public BoxedType<label>
{
public:
using BoxedType<label>::BoxedType;
~Integer()
{
if (verbosity) Info<< "delete Integer: " << value() << nl;
}
auto clone() const { return autoPtr<Integer>::New(*this); }
};
Ostream& operator<<(Ostream& os, const Integer& item)
{
return (os << item.value());
}
//- Permit up-casting to the base class (eg, fvMesh to polyMesh).
// Usually only for holding (const) references.
// Exercise caution with the
template<class Base, class Derived>
std::enable_if_t<std::is_base_of_v<Base, Derived>, const UPtrList<Base>&>
upcast(const UPtrList<Derived>& This)
{
return *reinterpret_cast<const UPtrList<Base>*>(&This);
}
// As per
@ -251,9 +301,9 @@ int main(int argc, char *argv[])
Info<< "DLPtrList: " << llist1 << endl;
Scalar::verbose = false;
verbosity = false;
llist1.clear();
Scalar::verbose = true;
verbosity = true;
}
#endif
@ -331,6 +381,44 @@ int main(int argc, char *argv[])
}
// Test upcasting - dangerous
{
const auto& base =
*reinterpret_cast<UPtrList<BoxedType<scalar>>*>(&list1);
Info<< "list :" << list1 << nl;
Info<< "base :" << base << nl;
}
// Expect bad things to happen!!
{
const auto& base =
*reinterpret_cast<UPtrList<BoxedType<label>>*>(&list1);
Info<< "list :" << list1 << nl;
Info<< "base :" << base << nl;
}
// Test upcasting - compile safer (make as member function?)
{
// const auto& base = list1.upcast<BoxedType<scalar>>();
const auto& base = upcast<BoxedType<scalar>>(list1);
Info<< "list :" << list1 << nl;
Info<< "base :" << base << nl;
}
// Refuse to compile (good!)
#if 0
{
// const auto& base = list1.upcast<BoxedType<label>>();
const auto& base = upcast<BoxedType<label>>(list1);
Info<< "list :" << list1 << nl;
Info<< "base :" << base << nl;
}
#endif
PtrList<Scalar> list2(15);
Info<< "Emplace set " << list2.size() << " values" << nl;
forAll(list2, i)

View File

@ -1,3 +1,3 @@
Test-PtrListDictionary.C
Test-PtrListDictionary.cxx
EXE = $(FOAM_USER_APPBIN)/Test-PtrListDictionary

View File

@ -39,26 +39,26 @@ Description
using namespace Foam;
bool verbosity = true;
class Scalar
{
scalar data_;
public:
static bool verbose;
constexpr Scalar() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {}
~Scalar()
{
if (verbose) Info<< "delete Scalar: " << data_ << endl;
if (verbosity) Info<< "delete Scalar: " << value() << nl;
}
const scalar& value() const noexcept { return data_; }
scalar value() const noexcept { return data_; }
scalar& value() noexcept { return data_; }
autoPtr<Scalar> clone() const { return autoPtr<Scalar>::New(data_); }
auto clone() const { return autoPtr<Scalar>::New(*this); }
friend Ostream& operator<<(Ostream& os, const Scalar& item)
{
@ -67,8 +67,6 @@ public:
}
};
bool Scalar::verbose = true;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:

View File

@ -1,3 +1,3 @@
Test-dictionary.C
Test-dictionary.cxx
EXE = $(FOAM_USER_APPBIN)/Test-dictionary

View File

@ -1,3 +1,3 @@
Test-dictionary2.C
Test-dictionary2.cxx
EXE = $(FOAM_USER_APPBIN)/Test-dictionary2

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,8 +47,18 @@ void entryInfo(entry* e)
{
if (e)
{
Info<<"added "
<< e->keyword() << ": " << typeid(e).name() << nl;
Info<< "added "
<< e->keyword() << ": " << typeid(e).name();
if (auto* stream = e->streamPtr())
{
Info<< " tokens: "; stream->tokens().writeList(Info);
}
if (auto* dict = e->dictPtr())
{
Info<< " dictionary:";
}
Info<< nl;
}
}
@ -200,12 +210,31 @@ int main(int argc, char *argv[])
{
dictionary tmpdict;
// Add an empty entry and populate afterwards
if (entry* e = dict1.set(word::printf("entry%d", i), nullptr))
{
entry* e = dict1.add
(
word::printf("entry%d", i),
string("entry" + Foam::name(i))
);
auto& toks = e->stream();
toks.resize(2);
toks[0] = word("value" + Foam::name(i));
toks[1] = 10*i;
entryInfo(e);
}
// Add an entry from given list of tokens
{
tokenList toks(2);
toks[0] = word("value" + Foam::name(i));
toks[1] = 10*i;
Info<< "set token0: " << Foam::name(&(toks[0])) << nl;
entry* e = dict1.set(word::printf("_entry%d", i), std::move(toks));
// verify that the address is identical (ie, move semantics worked)
auto& newToks = e->stream();
Info<< "get token0: " << Foam::name(&(newToks[0])) << nl;
entryInfo(e);
}

View File

@ -1,3 +1,3 @@
Test-dictionaryCopy.C
Test-dictionaryCopy.cxx
EXE = $(FOAM_USER_APPBIN)/Test-dictionaryCopy

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,8 +32,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef FlatOutput_H
#define FlatOutput_H
#ifndef Foam_FlatOutput_H
#define Foam_FlatOutput_H
#include "Ostream.H"
@ -134,8 +134,8 @@ public:
// Constructors
//- Construct from component
explicit OutputAdaptor(const Container& obj)
//- Construct from const reference
explicit OutputAdaptor(const Container& obj) noexcept
:
values(obj)
{}
@ -151,30 +151,22 @@ public:
// No special handling for newline separators.
inline Ostream& write(Ostream& os) const
{
bool started = false;
[[maybe_unused]] bool started = false;
// In c++17, can use constexpr if
if (Delimiters::open)
if constexpr (Delimiters::open) // Not nul char
{
os << Delimiters::open;
os << Delimiters::open;
}
for (const auto& item : values)
{
if (started)
{
if (Delimiters::separator)
{
os << Delimiters::separator;
}
}
else
if constexpr (Delimiters::separator) // Not nul char
{
if (started) os << Delimiters::separator;
started = true;
}
os << item;
os << item;
}
if (Delimiters::close)
if constexpr (Delimiters::close) // Not nul char
{
os << Delimiters::close;
}

View File

@ -717,6 +717,9 @@ public:
// Report FatalIOError and return false if token is not BOOL or LABEL
inline bool boolToken() const;
//- Assign to a boolean token
inline void boolToken(bool on);
//- Return flag bitmask value.
// Report FatalIOError and return NO_FLAG if token is not FLAG
inline int flagToken() const;
@ -725,10 +728,16 @@ public:
// Report FatalIOError and return \b \\0 if token is not PUNCTUATION
inline punctuationToken pToken() const;
//- Assign to a punctuation token
inline void pToken(const punctuationToken p);
//- Return label value.
// Report FatalIOError and return \b 0 if token is not LABEL
inline label labelToken() const;
//- Assign to a label token
inline void labelToken(const label val);
//- Return float value.
// Report FatalIOError and return \b 0 if token is not FLOAT
inline float floatToken() const;

View File

@ -547,6 +547,14 @@ inline bool Foam::token::boolToken() const
}
inline void Foam::token::boolToken(bool on)
{
reset();
type_ = tokenType::BOOL;
data_.labelVal = on;
}
inline bool Foam::token::isFlag() const noexcept
{
return (type_ == tokenType::FLAG);
@ -603,6 +611,14 @@ inline Foam::token::punctuationToken Foam::token::pToken() const
}
inline void Foam::token::pToken(const punctuationToken p)
{
reset();
type_ = tokenType::PUNCTUATION;
data_.punctuationVal = p;
}
inline bool Foam::token::isLabel() const noexcept
{
return
@ -649,6 +665,14 @@ inline Foam::label Foam::token::labelToken() const
}
inline void Foam::token::labelToken(const label val)
{
reset();
type_ = tokenType::LABEL;
data_.labelVal = val;
}
inline bool Foam::token::isFloat() const noexcept
{
return (type_ == tokenType::FLOAT);
@ -1031,17 +1055,13 @@ inline void Foam::token::operator=(token&& tok)
inline void Foam::token::operator=(const punctuationToken p)
{
reset();
type_ = tokenType::PUNCTUATION;
data_.punctuationVal = p;
token::pToken(p);
}
inline void Foam::token::operator=(const label val)
{
reset();
type_ = tokenType::LABEL;
data_.labelVal = val;
token::labelToken(val);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2023 OpenCFD Ltd.
Copyright (C) 2015-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -803,6 +803,24 @@ Foam::entry* Foam::dictionary::set(const keyType& k, const dictionary& v)
}
Foam::entry* Foam::dictionary::set(const keyType& k, std::nullptr_t)
{
return set(new primitiveEntry(k));
}
Foam::entry* Foam::dictionary::set(const keyType& k, const UList<token>& tokens)
{
return set(new primitiveEntry(k, tokens));
}
Foam::entry* Foam::dictionary::set(const keyType& k, List<token>&& tokens)
{
return set(new primitiveEntry(k, std::move(tokens)));
}
bool Foam::dictionary::merge(const dictionary& dict)
{
if (this == &dict)

View File

@ -953,6 +953,21 @@ public:
// \return pointer to inserted entry or nullptr on failure
entry* set(const keyType& k, const dictionary& v);
//- Assign an empty primitive entry,
//- overwriting any existing entry.
// \return pointer to entry or nullptr on failure
entry* set(const keyType& k, std::nullptr_t);
//- Assign a primitive entry from a list of tokens,
//- overwriting any existing entry.
// \return pointer to entry or nullptr on failure
entry* set(const keyType& k, const UList<token>& tokens);
//- Assign a primitive entry from a list of tokens,
//- overwriting any existing entry.
// \return pointer to entry or nullptr on failure
entry* set(const keyType& k, List<token>&& tokens);
//- Assign a T entry, overwriting any existing entry.
// \return pointer to inserted entry or nullptr on failure
template<class T>

View File

@ -28,7 +28,13 @@ Class
Foam::Field
Description
Generic templated field type.
Generic templated field type that is much like a Foam::List
except that it is expected to hold numerical content
(not generic elements such as strings etc).
In addition to methods specific to numerical fields
(e.g., clamp, min, max, transpose, ...), it also has a reference
counter that is used by Foam::tmp handling.
SourceFiles
FieldFunctions.H