From c7392f7fb02d6d8544f457dbd5c50d656e501e56 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 8 Nov 2017 19:08:10 +0100 Subject: [PATCH] ENH: additional dictionary compatibility/migration methods - when dictionary keywords change between versions, the programmer can use these compatibility methods to help with migration. * csearchCompat, foundCompat, lookupEntryPtrCompat, lookupEntryCompat, lookupCompat, lookupOrDefaultCompat, readIfPresentCompat, ... They behave like their similarly named base versions, but accept an additional list of older keyword names augmented by a version number. For example, dict.readIfPresentCompat ( "key", {{"olderName", 1612}, {"veryOld", 240}}, myscalar ); where 1612=OpenFOAM-v1612, 240=OpenFOAM-v2.4.x, etc. --- .../test/dictionary2/Test-dictionary2.C | 83 ++++++++- src/OpenFOAM/Make/files | 1 + src/OpenFOAM/db/dictionary/dictionary.H | 121 +++++++++++++ src/OpenFOAM/db/dictionary/dictionaryCompat.C | 162 ++++++++++++++++++ .../db/dictionary/dictionaryTemplates.C | 77 ++++++++- 5 files changed, 433 insertions(+), 11 deletions(-) create mode 100644 src/OpenFOAM/db/dictionary/dictionaryCompat.C diff --git a/applications/test/dictionary2/Test-dictionary2.C b/applications/test/dictionary2/Test-dictionary2.C index 9d01161e3e..2541f5cba6 100644 --- a/applications/test/dictionary2/Test-dictionary2.C +++ b/applications/test/dictionary2/Test-dictionary2.C @@ -112,7 +112,8 @@ int main(int argc, char *argv[]) // overwrite existing { - entry* e = dict1.set(word("dict2"), 1000); // overwrite + dict1.set("entry3", 1000); // overwrite + entry* e = dict1.set(word("dict3"), 1000); // overwrite entryInfo(e); } @@ -124,10 +125,86 @@ int main(int argc, char *argv[]) entry* e = dict1.add(word("dict4"), tmpdict, true); // merge entryInfo(e); - if (e) - Info<< nl << "=> " << *e << nl; + if (e) Info<< nl << "=> " << *e << nl; + + tmpdict.clear(); + tmpdict.add(word("other"), 2.718281); + + dict1.add(word("dict1"), tmpdict, true); // merge } + Info<< nl << "dictionary" << nl << nl; + dict1.write(Info, false); + + + { + dict1.foundCompat + ( + "newEntry", {{"entry1", 1612}, {"entry15", 1606}} + ); + dict1.foundCompat + ( + "newEntry", {{"entry15", 1612}, {"entry2", 1606}} + ); + dict1.foundCompat + ( + "newEntry", {{"entry3", 240}, {"entry2", 1606}} + ); + + // And some success + dict1.foundCompat + ( + "entry4", {{"none", 240}, {"entry2", 1606}} + ); + } + + { + label lval = readLabel + ( + dict1.lookupCompat + ( + "entry400", {{"none", 240}, {"entry3", 1606}} + ) + ); + Info<< "int value: " << lval << nl; + } + + + // Could have different dictionary names and different entries names etc. + // Quite ugly! + { + scalar sval = readScalar + ( + dict1.csearchCompat + ( + "newdictName", {{"dict4", 1706}, {"dict1", 1606}} + ) + .dict() + .lookupCompat + ( + "newval", {{"something", 1606}, {"other", 1612}} + ) + ); + + Info<< "scalar value: " << sval << nl; + + sval = readScalar + ( + dict1.csearchCompat + ( + "newdictName", {{"dict1", 1606}, {"dict4", 1706}} + ) + .dict() + .lookupCompat + ( + "newval", {{"something", 1606}, {"other", 1612}} + ) + ); + + Info<< "scalar value = " << sval << nl; + } + + Info<< nl << "dictionary" << nl << nl; dict1.write(Info, false); diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index cfe98bfe64..130b48e5b3 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -203,6 +203,7 @@ dictionary = db/dictionary $(dictionary)/dictionary.C $(dictionary)/dictionaryIO.C $(dictionary)/dictionarySearch.C +$(dictionary)/dictionaryCompat.C entry = $(dictionary)/entry $(entry)/entry.C diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index a4b8623c54..671aba903d 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -908,6 +908,127 @@ public: dictionary* makeScopedDictPtr(const fileName& dictPath); + // Compatibility helpers + + //- Search dictionary for given keyword and any compatibility names + // Default search: non-recursive with patterns. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // Old version 1600=OpenFOAM-v3.0, 240=OpenFOAM-2.4.x, + // 170=OpenFOAM-1.7.x,... + // + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + const_searcher csearchCompat + ( + const word& keyword, + std::initializer_list> compat, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Search dictionary for given keyword and any compatibility names + // Default search: non-recursive with patterns. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + bool foundCompat + ( + const word& keyword, + std::initializer_list> compat, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Find and return an entry pointer if present, or return a nullptr, + //- using any compatibility names it needed. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + const entry* lookupEntryPtrCompat + ( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch + ) const; + + //- Find and return an entry if present otherwise error, + //- using any compatibility names it needed. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + const entry& lookupEntryCompat + ( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch + ) const; + + //- Find and return an entry data stream, + //- using any compatibility names it needed. + // Default search: non-recursive with patterns. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + ITstream& lookupCompat + ( + const word& keyword, + std::initializer_list> compat, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Find and return a T, or return the given default value + //- using any compatibility names it needed. + // Default search: non-recursive with patterns. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + template + T lookupOrDefaultCompat + ( + const word& keyword, + std::initializer_list> compat, + const T& deflt, + bool recursive = false, + bool patternMatch = true + ) const; + + //- Find an entry if present, and assign to T val + //- using any compatibility names it needed. + // Default search: non-recursive with patterns. + // + // \param compat list of old compatibility keywords and the last + // OpenFOAM version for which they were used. + // \param val the value to read + // \param recursive search parent dictionaries + // \param patternMatch use regular expressions + // + // \return true if the entry was found. + template + bool readIfPresentCompat + ( + const word& keyword, + std::initializer_list> compat, + T& val, + bool recursive = false, + bool patternMatch = true + ) const; + + // Member Operators //- Find and return an entry data stream (identical to #lookup method). diff --git a/src/OpenFOAM/db/dictionary/dictionaryCompat.C b/src/OpenFOAM/db/dictionary/dictionaryCompat.C new file mode 100644 index 0000000000..624231fd14 --- /dev/null +++ b/src/OpenFOAM/db/dictionary/dictionaryCompat.C @@ -0,0 +1,162 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "dictionary.H" + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +static void warnAboutAge(const int oldVersion) +{ + if (oldVersion < 1000) + { + // Emit warning + std::cerr + << " This keyword is considered to be VERY old!\n" + << std::endl; + } +#if (OPENFOAM_PLUS > 1600) + else if (OPENFOAM_PLUS > oldVersion) + { + const int months = + ( + // YYMM -> months + (12 * (OPENFOAM_PLUS/100) + (OPENFOAM_PLUS % 100)) + - (12 * (oldVersion/100) + (oldVersion % 100)) + ); + + std::cerr + << " This keyword is deemed to be " << months + << " months old.\n" + << std::endl; + } +#endif +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::dictionary::const_searcher Foam::dictionary::csearchCompat +( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch +) const +{ + const_searcher finder(csearch(keyword, recursive,patternMatch)); + + if (finder.found()) + { + return finder; + } + + for (const std::pair& iter : compat) + { + finder = csearch(word::validate(iter.first), recursive,patternMatch); + + if (finder.found()) + { + // Emit warning + std::cerr + << "--> FOAM IOWarning :" << nl + << " Found [v" << iter.second << "] '" + << iter.first << "' instead of '" + << keyword.c_str() << "' in dictionary \"" + << name().c_str() << "\" " + << nl + << std::endl; + + warnAboutAge(iter.second); + + break; + } + } + + return finder; +} + + +bool Foam::dictionary::foundCompat +( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch +) const +{ + return csearchCompat(keyword, compat, recursive,patternMatch).found(); +} + + +const Foam::entry* Foam::dictionary::lookupEntryPtrCompat +( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch +) const +{ + return csearchCompat(keyword, compat, recursive,patternMatch).ptr(); +} + + +const Foam::entry& Foam::dictionary::lookupEntryCompat +( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch +) const +{ + const const_searcher + finder(csearchCompat(keyword, compat, recursive,patternMatch)); + + if (!finder.found()) + { + FatalIOErrorInFunction + ( + *this + ) << "keyword " << keyword << " is undefined in dictionary " + << name() + << exit(FatalIOError); + } + + return finder.ref(); +} + + +Foam::ITstream& Foam::dictionary::lookupCompat +( + const word& keyword, + std::initializer_list> compat, + bool recursive, + bool patternMatch +) const +{ + return lookupEntryCompat(keyword, compat, recursive,patternMatch).stream(); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C index 6857c2808e..833647b951 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C +++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C @@ -35,6 +35,20 @@ Foam::wordList Foam::dictionary::sortedToc(const Compare& comp) const } +template +Foam::entry* Foam::dictionary::add(const keyType& k, const T& v, bool overwrite) +{ + return add(new primitiveEntry(k, v), overwrite); +} + + +template +Foam::entry* Foam::dictionary::set(const keyType& k, const T& v) +{ + return set(new primitiveEntry(k, v)); +} + + template T Foam::dictionary::lookupType ( @@ -43,7 +57,7 @@ T Foam::dictionary::lookupType bool patternMatch ) const { - auto finder = csearch(keyword, recursive, patternMatch); + const const_searcher finder(csearch(keyword, recursive, patternMatch)); if (!finder.found()) { @@ -68,7 +82,7 @@ T Foam::dictionary::lookupOrDefault bool patternMatch ) const { - auto finder = csearch(keyword, recursive, patternMatch); + const const_searcher finder(csearch(keyword, recursive, patternMatch)); if (finder.found()) { @@ -96,7 +110,7 @@ T Foam::dictionary::lookupOrAddDefault bool patternMatch ) { - auto finder = csearch(keyword, recursive, patternMatch); + const const_searcher finder(csearch(keyword, recursive, patternMatch)); if (finder.found()) { @@ -125,7 +139,7 @@ bool Foam::dictionary::readIfPresent bool patternMatch ) const { - auto finder = csearch(keyword, recursive, patternMatch); + const const_searcher finder(csearch(keyword, recursive, patternMatch)); if (finder.found()) { @@ -146,16 +160,63 @@ bool Foam::dictionary::readIfPresent template -Foam::entry* Foam::dictionary::add(const keyType& k, const T& v, bool overwrite) +T Foam::dictionary::lookupOrDefaultCompat +( + const word& keyword, + std::initializer_list> compat, + const T& deflt, + bool recursive, + bool patternMatch +) const { - return add(new primitiveEntry(k, v), overwrite); + const const_searcher + finder(csearchCompat(keyword, compat, recursive, patternMatch)); + + if (finder.found()) + { + return pTraits(finder.ptr()->stream()); + } + + if (writeOptionalEntries) + { + IOInfoInFunction(*this) + << "Optional entry '" << keyword << "' is not present," + << " returning the default value '" << deflt << "'" + << endl; + } + + return deflt; } template -Foam::entry* Foam::dictionary::set(const keyType& k, const T& v) +bool Foam::dictionary::readIfPresentCompat +( + const word& keyword, + std::initializer_list> compat, + T& val, + bool recursive, + bool patternMatch +) const { - return set(new primitiveEntry(k, v)); + const const_searcher + finder(csearchCompat(keyword, compat, recursive, patternMatch)); + + if (finder.found()) + { + finder.ptr()->stream() >> val; + return true; + } + + if (writeOptionalEntries) + { + IOInfoInFunction(*this) + << "Optional entry '" << keyword << "' is not present," + << " the default value '" << val << "' will be used." + << endl; + } + + return false; }