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 | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd. Copyright (C) 2017-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -42,33 +42,55 @@ Description
using namespace Foam; using namespace Foam;
class Scalar bool verbosity = true;
// Gratuitous class inheritance
template<class T>
class BoxedType
{ {
scalar data_; T data_;
public: public:
static bool verbose; static bool verbose;
constexpr Scalar() noexcept : data_(0) {} constexpr BoxedType() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {} 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() ~Scalar()
{ {
if (verbose) Info<< "delete Scalar: " << data_ << endl; if (verbosity) Info<< "delete Scalar: " << value() << nl;
}
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;
} }
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> template<class T>

View File

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

View File

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

View File

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

View File

@ -41,35 +41,85 @@ Description
using namespace Foam; using namespace Foam;
class Scalar bool verbosity = true;
// Gratuitous class inheritance
template<class T>
class BoxedType
{ {
scalar data_; T data_;
public: public:
static bool verbose; static bool verbose;
constexpr Scalar() noexcept : data_(0) {} constexpr BoxedType() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {} 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() ~Scalar()
{ {
if (verbose) Info<< "delete Scalar: " << data_ << endl; if (verbosity) Info<< "delete Scalar: " << value() << nl;
}
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;
} }
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 // As per
@ -251,9 +301,9 @@ int main(int argc, char *argv[])
Info<< "DLPtrList: " << llist1 << endl; Info<< "DLPtrList: " << llist1 << endl;
Scalar::verbose = false; verbosity = false;
llist1.clear(); llist1.clear();
Scalar::verbose = true; verbosity = true;
} }
#endif #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); PtrList<Scalar> list2(15);
Info<< "Emplace set " << list2.size() << " values" << nl; Info<< "Emplace set " << list2.size() << " values" << nl;
forAll(list2, i) forAll(list2, i)

View File

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

View File

@ -39,26 +39,26 @@ Description
using namespace Foam; using namespace Foam;
bool verbosity = true;
class Scalar class Scalar
{ {
scalar data_; scalar data_;
public: public:
static bool verbose;
constexpr Scalar() noexcept : data_(0) {} constexpr Scalar() noexcept : data_(0) {}
Scalar(scalar val) noexcept : data_(val) {} Scalar(scalar val) noexcept : data_(val) {}
~Scalar() ~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_; } 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) friend Ostream& operator<<(Ostream& os, const Scalar& item)
{ {
@ -67,8 +67,6 @@ public:
} }
}; };
bool Scalar::verbose = true;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program: // Main program:

View File

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

View File

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

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com \\ / A nd | www.openfoam.com
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2017-2023 OpenCFD Ltd. Copyright (C) 2017-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -47,8 +47,18 @@ void entryInfo(entry* e)
{ {
if (e) if (e)
{ {
Info<<"added " Info<< "added "
<< e->keyword() << ": " << typeid(e).name() << nl; << 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; dictionary tmpdict;
// Add an empty entry and populate afterwards
if (entry* e = dict1.set(word::printf("entry%d", i), nullptr))
{ {
entry* e = dict1.add auto& toks = e->stream();
( toks.resize(2);
word::printf("entry%d", i),
string("entry" + Foam::name(i)) 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); entryInfo(e);
} }

View File

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

View File

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

View File

@ -717,6 +717,9 @@ public:
// Report FatalIOError and return false if token is not BOOL or LABEL // Report FatalIOError and return false if token is not BOOL or LABEL
inline bool boolToken() const; inline bool boolToken() const;
//- Assign to a boolean token
inline void boolToken(bool on);
//- Return flag bitmask value. //- Return flag bitmask value.
// Report FatalIOError and return NO_FLAG if token is not FLAG // Report FatalIOError and return NO_FLAG if token is not FLAG
inline int flagToken() const; inline int flagToken() const;
@ -725,10 +728,16 @@ public:
// Report FatalIOError and return \b \\0 if token is not PUNCTUATION // Report FatalIOError and return \b \\0 if token is not PUNCTUATION
inline punctuationToken pToken() const; inline punctuationToken pToken() const;
//- Assign to a punctuation token
inline void pToken(const punctuationToken p);
//- Return label value. //- Return label value.
// Report FatalIOError and return \b 0 if token is not LABEL // Report FatalIOError and return \b 0 if token is not LABEL
inline label labelToken() const; inline label labelToken() const;
//- Assign to a label token
inline void labelToken(const label val);
//- Return float value. //- Return float value.
// Report FatalIOError and return \b 0 if token is not FLOAT // Report FatalIOError and return \b 0 if token is not FLOAT
inline float floatToken() const; 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 inline bool Foam::token::isFlag() const noexcept
{ {
return (type_ == tokenType::FLAG); 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 inline bool Foam::token::isLabel() const noexcept
{ {
return 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 inline bool Foam::token::isFloat() const noexcept
{ {
return (type_ == tokenType::FLOAT); return (type_ == tokenType::FLOAT);
@ -1031,17 +1055,13 @@ inline void Foam::token::operator=(token&& tok)
inline void Foam::token::operator=(const punctuationToken p) inline void Foam::token::operator=(const punctuationToken p)
{ {
reset(); token::pToken(p);
type_ = tokenType::PUNCTUATION;
data_.punctuationVal = p;
} }
inline void Foam::token::operator=(const label val) inline void Foam::token::operator=(const label val)
{ {
reset(); token::labelToken(val);
type_ = tokenType::LABEL;
data_.labelVal = val;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2023 OpenCFD Ltd. Copyright (C) 2015-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. 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) bool Foam::dictionary::merge(const dictionary& dict)
{ {
if (this == &dict) if (this == &dict)

View File

@ -953,6 +953,21 @@ public:
// \return pointer to inserted entry or nullptr on failure // \return pointer to inserted entry or nullptr on failure
entry* set(const keyType& k, const dictionary& v); 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. //- Assign a T entry, overwriting any existing entry.
// \return pointer to inserted entry or nullptr on failure // \return pointer to inserted entry or nullptr on failure
template<class T> template<class T>

View File

@ -28,7 +28,13 @@ Class
Foam::Field Foam::Field
Description 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 SourceFiles
FieldFunctions.H FieldFunctions.H