diff --git a/applications/test/NamedEnum/Test-NamedEnum.C b/applications/test/NamedEnum/Test-NamedEnum.C index 08d1f74972e66c68471671c0b7d32483ed1762d7..079938b6b79405f8baf8c00701113ddd0dc4f7f0 100644 --- a/applications/test/NamedEnum/Test-NamedEnum.C +++ b/applications/test/NamedEnum/Test-NamedEnum.C @@ -66,6 +66,9 @@ int main(int argc, char *argv[]) const List<namedEnumTest::option> options = namedEnumTest::namedEnum.enums(); + dictionary testDict; + testDict.add("lookup1", "c"); + Info<< "enums: " << options << nl; Info<< "loop over enums (as list):" << nl; @@ -88,6 +91,30 @@ int main(int argc, char *argv[]) << namedEnumTest::namedEnum["a"] << nl << namedEnumTest::namedEnum[namedEnumTest::a] << nl; + Info<< "--- test dictionary lookup ---" << endl; + { + Info<< "dict: " << testDict << endl; + + namedEnumTest::option gotOpt = + namedEnumTest::namedEnum.lookupOrDefault + ( + "test", + testDict, + namedEnumTest::option::a + ); + + Info<< "got: " << gotOpt << endl; + + gotOpt = namedEnumTest::namedEnum.lookupOrDefault + ( + "lookup1", + testDict, + namedEnumTest::option::a + ); + + Info<< "got: " << gotOpt << endl; + } + Info<< "--- test read construction ---" << endl; namedEnumTest::option dummy(namedEnumTest::namedEnum.read(Sin)); diff --git a/src/OpenFOAM/containers/NamedEnum/NamedEnum.C b/src/OpenFOAM/containers/NamedEnum/NamedEnum.C index 89784a1400b731514148fcb57d313b9e3bd92c00..0f5e05630f70402f72b51a5e2e49f5e7313e8e24 100644 --- a/src/OpenFOAM/containers/NamedEnum/NamedEnum.C +++ b/src/OpenFOAM/containers/NamedEnum/NamedEnum.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -24,33 +24,60 @@ License \*---------------------------------------------------------------------------*/ #include "NamedEnum.H" +#include "dictionary.H" + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +template<class Enum, int nEnum> +template<class StringType> +Foam::List<StringType> Foam::NamedEnum<Enum, nEnum>::getNamesList() +{ + List<StringType> lst(nEnum); + + label count = 0; + for (int enumi=0; enumi < nEnum; ++enumi) + { + if (names[enumi] && names[enumi][0]) + { + lst[count++] = names[enumi]; + } + } + + lst.setSize(count); + return lst; +} + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // template<class Enum, int nEnum> Foam::NamedEnum<Enum, nEnum>::NamedEnum() : - HashTable<int>(2*nEnum) + table_type(2*nEnum) { - for (int enumI = 0; enumI < nEnum; ++enumI) + for (int enumi=0; enumi < nEnum; ++enumi) { - if (!names[enumI] || names[enumI][0] == '\0') + if (names[enumi] && names[enumi][0]) + { + insert(names[enumi], enumi); + } + else { - stringList goodNames(enumI); + // Bad name - generate error message + stringList goodNames(enumi); - for (int i = 0; i < enumI; ++i) + for (int i = 0; i < enumi; ++i) { goodNames[i] = names[i]; } FatalErrorInFunction - << "Illegal enumeration name at position " << enumI << endl - << "after entries " << goodNames << ".\n" + << "Illegal enumeration name at position " << enumi << nl + << "after entries " << goodNames << nl << "Possibly your NamedEnum<Enum, nEnum>::names array" << " is not of size " << nEnum << endl << abort(FatalError); } - insert(names[enumI], enumI); } } @@ -60,14 +87,13 @@ Foam::NamedEnum<Enum, nEnum>::NamedEnum() template<class Enum, int nEnum> Enum Foam::NamedEnum<Enum, nEnum>::read(Istream& is) const { - const word name(is); - - HashTable<int>::const_iterator iter = find(name); + const word enumName(is); + table_type::const_iterator iter = find(enumName); if (!iter.found()) { FatalIOErrorInFunction(is) - << name << " is not in enumeration: " + << enumName << " is not in enumeration: " << sortedToc() << exit(FatalIOError); } @@ -78,45 +104,47 @@ Enum Foam::NamedEnum<Enum, nEnum>::read(Istream& is) const template<class Enum, int nEnum> void Foam::NamedEnum<Enum, nEnum>::write(const Enum e, Ostream& os) const { - os << operator[](e); + os << names[int(e)]; } template<class Enum, int nEnum> -Foam::stringList Foam::NamedEnum<Enum, nEnum>::strings() +Enum Foam::NamedEnum<Enum, nEnum>::lookup +( + const word& key, + const dictionary& dict +) const { - stringList lst(nEnum); + const word enumName(dict.lookup(key)); + table_type::const_iterator iter = find(enumName); - label nElem = 0; - for (int enumI = 0; enumI < nEnum; ++enumI) + if (!iter.found()) { - if (names[enumI] && names[enumI][0]) - { - lst[nElem++] = names[enumI]; - } + FatalIOErrorInFunction(dict) + << enumName << " is not in enumeration: " + << sortedToc() << exit(FatalIOError); } - lst.setSize(nElem); - return lst; + return Enum(iter.object()); } template<class Enum, int nEnum> -Foam::wordList Foam::NamedEnum<Enum, nEnum>::words() +Enum Foam::NamedEnum<Enum, nEnum>::lookupOrDefault +( + const word& key, + const dictionary& dict, + const enum_type deflt +) const { - wordList lst(nEnum); - - label nElem = 0; - for (int enumI = 0; enumI < nEnum; ++enumI) + if (dict.found(key)) { - if (names[enumI] && names[enumI][0]) - { - lst[nElem++] = names[enumI]; - } + return lookup(key, dict); + } + else + { + return deflt; } - - lst.setSize(nElem); - return lst; } @@ -125,18 +153,32 @@ Foam::List<Enum> Foam::NamedEnum<Enum, nEnum>::enums() { List<Enum> lst(nEnum); - label nElem = 0; - for (int enumI = 0; enumI < nEnum; ++enumI) + label count = 0; + for (int enumi = 0; enumi < nEnum; ++enumi) { - if (names[enumI] && names[enumI][0]) + if (names[enumi] && names[enumi][0]) { - lst[nElem++] = Enum(enumI); + lst[count++] = Enum(enumi); } } - lst.setSize(nElem); + lst.setSize(count); return lst; } +template<class Enum, int nEnum> +Foam::stringList Foam::NamedEnum<Enum, nEnum>::strings() +{ + return getNamesList<string>(); +} + + +template<class Enum, int nEnum> +Foam::wordList Foam::NamedEnum<Enum, nEnum>::words() +{ + return getNamesList<word>(); +} + + // ************************************************************************* // diff --git a/src/OpenFOAM/containers/NamedEnum/NamedEnum.H b/src/OpenFOAM/containers/NamedEnum/NamedEnum.H index b9054aee85f1a8a0580d343bc8b9944727b4360f..0c1c0826fa35391abc87120609e3d141412619e5 100644 --- a/src/OpenFOAM/containers/NamedEnum/NamedEnum.H +++ b/src/OpenFOAM/containers/NamedEnum/NamedEnum.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -25,7 +25,9 @@ Class Foam::NamedEnum Description - Initialise the NamedEnum HashTable from the static list of names. + A NamedEnum is a wrapper around a static list of names that represent + a particular enumeration. Internally it uses a HashTable for quicker + lookups. SourceFiles NamedEnum.C @@ -44,6 +46,7 @@ SourceFiles namespace Foam { +class dictionary; // Forward declaration template<class Enum, int> class NamedEnum; @@ -57,11 +60,19 @@ class NamedEnum : public HashTable<int> { - //- nEnum must be positive (non-zero) + //- The nEnum must be positive (non-zero) static_assert(nEnum > 0, "nEnum must be positive (non-zero)"); + //- The type of HashTable used for the lookup. + typedef HashTable<int> table_type; + + // Private Member Functions + //- The names as a list of strings + template<class StringType> + static List<StringType> getNamesList(); + //- Disallow default bitwise copy construct NamedEnum(const NamedEnum&) = delete; @@ -71,6 +82,10 @@ class NamedEnum public: + //- The type of enumeration wrapped by NamedEnum + typedef Enum enum_type; + + // Static data members //- The set of names corresponding to the enumeration Enum @@ -87,10 +102,33 @@ public: //- Read a word from Istream and return the corresponding // enumeration element - Enum read(Istream& is) const; + enum_type read(Istream& is) const; //- Write the name representation of the enumeration to an Ostream - void write(const Enum e, Ostream& os) const; + void write(const enum_type e, Ostream& os) const; + + //- Lookup the key in the dictionary and return the corresponding + // enumeration element based on its name. + // Fatal if anything is incorrect. + enum_type lookup + ( + const word& key, + const dictionary& dict + ) const; + + //- Find the key in the dictionary and return the corresponding + // enumeration element based on its name. + // Return the default value if the key was not found in the dictionary. + // Fatal if enumerated name was incorrect. + enum_type lookupOrDefault + ( + const word& key, + const dictionary& dict, + const enum_type deflt + ) const; + + //- List of enumerations + static List<enum_type> enums(); //- The set of names as a list of strings static stringList strings(); @@ -98,26 +136,23 @@ public: //- The set of names as a list of words static wordList words(); - //- List of enumerations - static List<Enum> enums(); - // Member Operators //- Return the enumeration element corresponding to the given name - const Enum operator[](const char* name) const + inline const enum_type operator[](const char* name) const { - return Enum(HashTable<int>::operator[](name)); + return enum_type(table_type::operator[](name)); } //- Return the enumeration element corresponding to the given name - const Enum operator[](const word& name) const + inline const enum_type operator[](const word& name) const { - return Enum(HashTable<int>::operator[](name)); + return enum_type(table_type::operator[](name)); } //- Return the name of the given enumeration element - const char* operator[](const Enum e) const + inline const char* operator[](const enum_type e) const { return names[int(e)]; }