Merge branch 'dict-lookup' into 'develop'

Dict lookup

See merge request !105
This commit is contained in:
Andrew Heather
2017-05-02 16:37:57 +01:00
13 changed files with 368 additions and 247 deletions

View File

@ -0,0 +1,53 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: plus |
| \\ / A nd | Web: www.OpenFOAM.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object testDict;
note "test with foamDictionary -expand";
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// #inputMode overwrite
key1 val1;
subdict
{
key1 a;
key2 b;
}
update
{
key1 val1b;
key2 val2;
subdict
{
key2 $key1;
key3 val3;
key2b ${..key2};
key3b $^key1;
}
}
$update
// Can a leading '^' or ':' as anchor for scoping
key3 $^subdict.key1;
key3 ${^update.subdict.key3};
key4 ${:update.subdict...subdict.key1};
// This is currently not working
#remove update.key1
// #remove update
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -288,6 +288,9 @@ Foam::vtkPVFoam::vtkPVFoam
fullCasePath = cwd(); fullCasePath = cwd();
} }
// The name of the executable, unless already present in the environment
setEnv("FOAM_EXECUTABLE", "paraview", false);
// Set the case as an environment variable - some BCs might use this // Set the case as an environment variable - some BCs might use this
if (fullCasePath.name().find("processor", 0) == 0) if (fullCasePath.name().find("processor", 0) == 0)
{ {

View File

@ -206,6 +206,9 @@ Foam::vtkPVblockMesh::vtkPVblockMesh
fullCasePath = cwd(); fullCasePath = cwd();
} }
// The name of the executable, unless already present in the environment
setEnv("FOAM_EXECUTABLE", "paraview", false);
// Set the case as an environment variable - some BCs might use this // Set the case as an environment variable - some BCs might use this
if (fullCasePath.name().find("processor", 0) == 0) if (fullCasePath.name().find("processor", 0) == 0)
{ {

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2015-2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -60,114 +60,101 @@ const Foam::entry* Foam::dictionary::lookupScopedSubEntryPtr
// Non-scoped lookup // Non-scoped lookup
return lookupEntryPtr(keyword, recursive, patternMatch); return lookupEntryPtr(keyword, recursive, patternMatch);
} }
else else if (dotPos == 0)
{ {
if (dotPos == 0) // Starting with a '.' -> go up for every further '.' found
++dotPos;
const dictionary* dictPtr = this;
for
(
string::const_iterator it = keyword.begin()+1;
it != keyword.end() && *it == '.';
++dotPos, ++it
)
{ {
// Starting with a '.'. Go up for every 2nd '.' found // Go to parent
if (&dictPtr->parent_ != &dictionary::null)
const dictionary* dictPtr = this;
string::size_type begVar = dotPos + 1;
string::const_iterator iter = keyword.begin() + begVar;
string::size_type endVar = begVar;
while (iter != keyword.end() && *iter == '.')
{ {
++iter;
++endVar;
// Go to parent
if (&dictPtr->parent_ == &dictionary::null)
{
FatalIOErrorInFunction
(
*this
) << "No parent of current dictionary"
<< " when searching for "
<< keyword.substr(begVar, keyword.size()-begVar)
<< exit(FatalIOError);
}
dictPtr = &dictPtr->parent_; dictPtr = &dictPtr->parent_;
} }
else
{
FatalIOErrorInFunction
(
*this
) << "No parent of current dictionary when searching for "
<< keyword.substr(1)
<< exit(FatalIOError);
return dictPtr->lookupScopedSubEntryPtr return nullptr;
}
}
return dictPtr->lookupScopedSubEntryPtr
(
keyword.substr(dotPos),
false,
patternMatch
);
}
else
{
// The first word
const entry* entPtr = lookupScopedSubEntryPtr
(
keyword.substr(0, dotPos),
false,
patternMatch
);
if (!entPtr)
{
// Fall back to finding key with '.' so e.g. if keyword is
// a.b.c.d it would try
// a.b, a.b.c, a.b.c.d
while (true)
{
dotPos = keyword.find('.', dotPos+1);
entPtr = lookupEntryPtr
(
keyword.substr(0, dotPos),
false,
patternMatch
);
if (dotPos == string::npos)
{
// Parsed the whole word. Return entry or null.
return entPtr;
}
if (entPtr && entPtr->isDict())
{
return entPtr->dict().lookupScopedSubEntryPtr
(
keyword.substr(dotPos),
false,
patternMatch
);
}
}
}
if (entPtr->isDict())
{
return entPtr->dict().lookupScopedSubEntryPtr
( (
keyword.substr(endVar), keyword.substr(dotPos),
false, false,
patternMatch patternMatch
); );
} }
else
{
// Extract the first word
word firstWord = keyword.substr(0, dotPos);
const entry* entPtr = lookupScopedSubEntryPtr
(
firstWord,
false, //recursive
patternMatch
);
if (!entPtr)
{
// Fall back to finding key with '.' so e.g. if keyword is
// a.b.c.d it would try
// a.b, a.b.c, a.b.c.d
string::size_type nextDotPos = keyword.find
(
'.',
dotPos+1
);
while (true)
{
const entry* subEntPtr = lookupEntryPtr
(
keyword.substr(0, nextDotPos),
false, //recursive,
patternMatch
);
if (nextDotPos == string::npos)
{
// Parsed the whole word. Return entry or null.
return subEntPtr;
}
if (subEntPtr && subEntPtr->isDict())
{
return subEntPtr->dict().lookupScopedSubEntryPtr
(
keyword.substr
(
nextDotPos,
keyword.size()-nextDotPos
),
false,
patternMatch
);
}
nextDotPos = keyword.find('.', nextDotPos+1);
}
}
if (entPtr->isDict())
{
return entPtr->dict().lookupScopedSubEntryPtr
(
keyword.substr(dotPos, keyword.size()-dotPos),
false,
patternMatch
);
}
else
{
return nullptr;
}
}
} }
return nullptr;
} }
@ -588,7 +575,7 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
bool patternMatch bool patternMatch
) const ) const
{ {
if (keyword[0] == ':') if (keyword[0] == ':' || keyword[0] == '^')
{ {
// Go up to top level // Go up to top level
const dictionary* dictPtr = this; const dictionary* dictPtr = this;
@ -597,10 +584,9 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
dictPtr = &dictPtr->parent_; dictPtr = &dictPtr->parent_;
} }
// At top. Recurse to find entries
return dictPtr->lookupScopedSubEntryPtr return dictPtr->lookupScopedSubEntryPtr
( (
keyword.substr(1, keyword.size()-1), keyword.substr(1),
false, false,
patternMatch patternMatch
); );
@ -617,9 +603,13 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
} }
bool Foam::dictionary::substituteScopedKeyword(const word& keyword) bool Foam::dictionary::substituteScopedKeyword
(
const word& keyword,
bool mergeEntry
)
{ {
word varName = keyword(1, keyword.size()-1); const word varName = keyword(1, keyword.size()-1);
// Lookup the variable name in the given dictionary // Lookup the variable name in the given dictionary
const entry* ePtr = lookupScopedEntryPtr(varName, true, true); const entry* ePtr = lookupScopedEntryPtr(varName, true, true);
@ -631,7 +621,7 @@ bool Foam::dictionary::substituteScopedKeyword(const word& keyword)
forAllConstIter(IDLList<entry>, addDict, iter) forAllConstIter(IDLList<entry>, addDict, iter)
{ {
add(iter()); add(iter(), mergeEntry);
} }
return true; return true;
@ -1034,7 +1024,6 @@ bool Foam::dictionary::changeKeyword
IDLList<entry>::replace(iter2(), iter()); IDLList<entry>::replace(iter2(), iter());
delete iter2(); delete iter2();
hashedEntries_.erase(iter2); hashedEntries_.erase(iter2);
} }
else else
{ {

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd. \\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -25,26 +25,57 @@ Class
Foam::dictionary Foam::dictionary
Description Description
A list of keyword definitions, which are a keyword followed by any number A list of keyword definitions, which are a keyword followed by a number
of values (e.g. words and numbers). The keywords can represent patterns of values (eg, words and numbers) or by a sub-dictionary.
which are matched using Posix regular expressions. The general order for Since the dictionary format is used extensively throughout OpenFOAM for
searching is as follows: input/output files, there are many examples of its use.
- exact match
- pattern match (in reverse order)
- optional recursion into the enclosing (parent) dictionaries
The dictionary class is the base class for IOdictionary. Dictionary keywords are a plain word or a pattern (regular expression).
It also serves as a bootstrap dictionary for the objectRegistry data The general order for searching is as follows:
dictionaries since, unlike the IOdictionary class, it does not use an - exact match
objectRegistry itself to work. - pattern match (in reverse order)
- optional recursion into the enclosing (parent) dictionaries
To add - a merge() member function with a non-const dictionary parameter? The dictionary class is the base class for IOdictionary and also serves
This would avoid unnecessary cloning in the add(entry*, bool) method. as a bootstrap dictionary for the objectRegistry data dictionaries.
Note
Within dictionaries, entries can be referenced by using the '$' syntax
familiar from shell programming. A '.' separator is used when referencing
sub-dictionary entries. Leading '.' prefixes can be used to specify
an entry from a parent directory. A leading ':' or '^' prefix specifies
starting from the top-level entry. For example,
\verbatim
key1 val1;
key2 $key1; // use key1 value from current scope
key3 $.key1; // use key1 value from current scope
subdict1
{
key1 val1b;
key2 $..key1; // use key1 value from parent
subdict2
{
key2 val2;
key3 $...key1; // use key1 value from grandparent
}
}
key4 $^subdict1.subdict2.key3; // lookup with absolute scoping
\endverbatim
It is also possible to use the '${}' syntax for clarity.
SourceFiles SourceFiles
dictionary.C dictionary.C
dictionaryIO.C dictionaryIO.C
SeeAlso
- Foam::entry
- Foam::dictionaryEntry
- Foam::primitiveEntry
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef dictionary_H #ifndef dictionary_H
@ -76,6 +107,7 @@ Ostream& operator<<(Ostream&, const dictionary&);
Class dictionaryName Declaration Class dictionaryName Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- Holds name for a dictionary
class dictionaryName class dictionaryName
{ {
// Private data // Private data
@ -87,11 +119,11 @@ public:
// Constructors // Constructors
//- Construct dictionaryName null //- Construct null
dictionaryName() dictionaryName()
{} {}
//- Construct dictionaryName as copy of the given fileName //- Construct as copy of the given fileName
dictionaryName(const fileName& name) dictionaryName(const fileName& name)
: :
name_(name) name_(name)
@ -116,16 +148,15 @@ public:
const word dictName() const const word dictName() const
{ {
const word scopedName = name_.name(); const word scopedName = name_.name();
const std::string::size_type i = scopedName.rfind('.');
string::size_type i = scopedName.rfind('.'); if (i == std::string::npos)
if (i == scopedName.npos)
{ {
return scopedName; return scopedName;
} }
else else
{ {
return scopedName.substr(i + 1, scopedName.npos); return scopedName.substr(i+1);
} }
} }
}; };
@ -142,8 +173,7 @@ class dictionary
{ {
// Private data // Private data
//- If true write optional keywords and values //- Report optional keywords and values if not present in dictionary
// if not present in dictionary
static bool writeOptionalEntries; static bool writeOptionalEntries;
//- HashTable of the entries held on the DL-list for quick lookup //- HashTable of the entries held on the DL-list for quick lookup
@ -165,7 +195,7 @@ class dictionary
// otherwise return nullptr. Allows scoping using '.' // otherwise return nullptr. Allows scoping using '.'
const entry* lookupScopedSubEntryPtr const entry* lookupScopedSubEntryPtr
( (
const word&, const word& keyword,
bool recursive, bool recursive,
bool patternMatch bool patternMatch
) const; ) const;
@ -217,38 +247,38 @@ public:
( (
const fileName& name, const fileName& name,
const dictionary& parentDict, const dictionary& parentDict,
Istream& Istream& is
); );
//- Construct top-level dictionary from Istream, //- Construct top-level dictionary from Istream,
// reading entries until EOF // reading entries until EOF
dictionary(Istream&); dictionary(Istream& is);
//- Construct top-level dictionary from Istream, //- Construct top-level dictionary from Istream,
// reading entries until EOF, optionally keeping the header // reading entries until EOF, optionally keeping the header
dictionary(Istream&, const bool keepHeader); dictionary(Istream& is, const bool keepHeader);
//- Construct as copy given the parent dictionary //- Construct as copy given the parent dictionary
dictionary(const dictionary& parentDict, const dictionary&); dictionary(const dictionary& parentDict, const dictionary&);
//- Construct top-level dictionary as copy //- Construct top-level dictionary as copy
dictionary(const dictionary&); dictionary(const dictionary& dict);
//- Construct top-level dictionary as copy from pointer to dictionary. //- Construct top-level dictionary as copy from pointer to dictionary.
// A null pointer is treated like an empty dictionary. // A null pointer is treated like an empty dictionary.
dictionary(const dictionary*); dictionary(const dictionary* dictPtr);
//- Construct by transferring parameter contents given parent dictionary //- Construct by transferring parameter contents given parent dictionary
dictionary(const dictionary& parentDict, const Xfer<dictionary>&); dictionary(const dictionary& parentDict, const Xfer<dictionary>& dict);
//- Construct top-level dictionary by transferring parameter contents //- Construct top-level dictionary by transferring parameter contents
dictionary(const Xfer<dictionary>&); dictionary(const Xfer<dictionary>& dict);
//- Construct and return clone //- Construct and return clone
autoPtr<dictionary> clone() const; autoPtr<dictionary> clone() const;
//- Construct top-level dictionary on freestore from Istream //- Construct top-level dictionary on freestore from Istream
static autoPtr<dictionary> New(Istream&); static autoPtr<dictionary> New(Istream& is);
//- Destructor //- Destructor
@ -286,8 +316,8 @@ public:
// If patternMatch, use regular expressions // If patternMatch, use regular expressions
bool found bool found
( (
const word&, const word& keyword,
bool recursive=false, bool recursive = false,
bool patternMatch = true bool patternMatch = true
) const; ) const;
@ -297,7 +327,7 @@ public:
// If patternMatch, use regular expressions // If patternMatch, use regular expressions
const entry* lookupEntryPtr const entry* lookupEntryPtr
( (
const word&, const word& keyword,
bool recursive, bool recursive,
bool patternMatch bool patternMatch
) const; ) const;
@ -308,7 +338,7 @@ public:
// If patternMatch, use regular expressions. // If patternMatch, use regular expressions.
entry* lookupEntryPtr entry* lookupEntryPtr
( (
const word&, const word& keyword,
bool recursive, bool recursive,
bool patternMatch bool patternMatch
); );
@ -318,7 +348,7 @@ public:
// If patternMatch, use regular expressions. // If patternMatch, use regular expressions.
const entry& lookupEntry const entry& lookupEntry
( (
const word&, const word& keyword,
bool recursive, bool recursive,
bool patternMatch bool patternMatch
) const; ) const;
@ -328,22 +358,21 @@ public:
// If patternMatch, use regular expressions. // If patternMatch, use regular expressions.
ITstream& lookup ITstream& lookup
( (
const word&, const word& keyword,
bool recursive=false, bool recursive = false,
bool patternMatch=true bool patternMatch = true
) const; ) const;
//- Find and return a T, //- Find and return a T, or return the given default value
// if not found return the given default value
// If recursive, search parent dictionaries. // If recursive, search parent dictionaries.
// If patternMatch, use regular expressions. // If patternMatch, use regular expressions.
template<class T> template<class T>
T lookupOrDefault T lookupOrDefault
( (
const word&, const word& keyword,
const T&, const T& deflt,
bool recursive=false, bool recursive = false,
bool patternMatch=true bool patternMatch = true
) const; ) const;
//- Find and return a T, if not found return the given //- Find and return a T, if not found return the given
@ -353,10 +382,10 @@ public:
template<class T> template<class T>
T lookupOrAddDefault T lookupOrAddDefault
( (
const word&, const word& keyword,
const T&, const T& deflt,
bool recursive=false, bool recursive = false,
bool patternMatch=true bool patternMatch = true
); );
//- Find an entry if present, and assign to T //- Find an entry if present, and assign to T
@ -366,10 +395,10 @@ public:
template<class T> template<class T>
bool readIfPresent bool readIfPresent
( (
const word&, const word& keyword,
T&, T& val,
bool recursive=false, bool recursive = false,
bool patternMatch=true bool patternMatch = true
) const; ) const;
//- Find and return an entry data stream pointer if present //- Find and return an entry data stream pointer if present
@ -377,33 +406,33 @@ public:
// Special handling for ':' at start of keyword and '..'. // Special handling for ':' at start of keyword and '..'.
const entry* lookupScopedEntryPtr const entry* lookupScopedEntryPtr
( (
const word&, const word& keyword,
bool recursive, bool recursive,
bool patternMatch bool patternMatch
) const; ) const;
//- Check if entry is a sub-dictionary //- Check if entry is a sub-dictionary
bool isDict(const word&) const; bool isDict(const word& keyword) const;
//- Find and return a sub-dictionary pointer if present //- Find and return a sub-dictionary pointer if present
// otherwise return nullptr. // otherwise return nullptr.
const dictionary* subDictPtr(const word&) const; const dictionary* subDictPtr(const word& keyword) const;
//- Find and return a sub-dictionary pointer if present //- Find and return a sub-dictionary pointer if present
// otherwise return nullptr. // otherwise return nullptr.
dictionary* subDictPtr(const word&); dictionary* subDictPtr(const word& keyword);
//- Find and return a sub-dictionary //- Find and return a sub-dictionary
const dictionary& subDict(const word&) const; const dictionary& subDict(const word& keyword) const;
//- Find and return a sub-dictionary for manipulation //- Find and return a sub-dictionary for manipulation
dictionary& subDict(const word&); dictionary& subDict(const word& keyword);
//- Find and return a sub-dictionary as a copy, or //- Find and return a sub-dictionary as a copy, or
// return an empty dictionary if the sub-dictionary does not exist // return an empty dictionary if the sub-dictionary does not exist
dictionary subOrEmptyDict dictionary subOrEmptyDict
( (
const word&, const word& keyword,
const bool mustRead = false const bool mustRead = false
) const; ) const;
@ -414,74 +443,78 @@ public:
wordList sortedToc() const; wordList sortedToc() const;
//- Return the list of available keys or patterns //- Return the list of available keys or patterns
List<keyType> keys(bool patterns=false) const; List<keyType> keys(bool patterns = false) const;
// Editing // Editing
//- Substitute the given keyword prepended by '$' with the //- Substitute the given keyword prepended by '$' with the
// corresponding sub-dictionary entries // corresponding sub-dictionary entries
bool substituteKeyword(const word& keyword); bool substituteKeyword(const word& keyword, bool mergeEntry=false);
//- Substitute the given scoped keyword prepended by '$' with the //- Substitute the given scoped keyword prepended by '$' with the
// corresponding sub-dictionary entries // corresponding sub-dictionary entries
bool substituteScopedKeyword(const word& keyword); bool substituteScopedKeyword
(
const word& keyword,
bool mergeEntry=false
);
//- Add a new entry //- Add a new entry
// With the merge option, dictionaries are interwoven and // With the merge option, dictionaries are interwoven and
// primitive entries are overwritten // primitive entries are overwritten
bool add(entry*, bool mergeEntry=false); bool add(entry* entryPtr, bool mergeEntry=false);
//- Add an entry //- Add an entry
// With the merge option, dictionaries are interwoven and // With the merge option, dictionaries are interwoven and
// primitive entries are overwritten // primitive entries are overwritten
void add(const entry&, bool mergeEntry=false); void add(const entry& e, bool mergeEntry=false);
//- Add a word entry //- Add a word entry
// optionally overwrite an existing entry // optionally overwrite an existing entry
void add(const keyType&, const word&, bool overwrite=false); void add(const keyType& k, const word& w, bool overwrite=false);
//- Add a string entry //- Add a string entry
// optionally overwrite an existing entry // optionally overwrite an existing entry
void add(const keyType&, const string&, bool overwrite=false); void add(const keyType& k, const string& s, bool overwrite=false);
//- Add a label entry //- Add a label entry
// optionally overwrite an existing entry // optionally overwrite an existing entry
void add(const keyType&, const label, bool overwrite=false); void add(const keyType&, const label l, bool overwrite=false);
//- Add a scalar entry //- Add a scalar entry
// optionally overwrite an existing entry // optionally overwrite an existing entry
void add(const keyType&, const scalar, bool overwrite=false); void add(const keyType&, const scalar s, bool overwrite=false);
//- Add a dictionary entry //- Add a dictionary entry
// optionally merge with an existing sub-dictionary // optionally merge with an existing sub-dictionary
void add void add
( (
const keyType&, const keyType& k,
const dictionary&, const dictionary& d,
bool mergeEntry=false bool mergeEntry = false
); );
//- Add a T entry //- Add a T entry
// optionally overwrite an existing entry // optionally overwrite an existing entry
template<class T> template<class T>
void add(const keyType&, const T&, bool overwrite=false); void add(const keyType& k, const T& t, bool overwrite=false);
//- Assign a new entry, overwrite any existing entry //- Assign a new entry, overwrite any existing entry
void set(entry*); void set(entry* entryPtr);
//- Assign a new entry, overwrite any existing entry //- Assign a new entry, overwrite any existing entry
void set(const entry&); void set(const entry& e);
//- Assign a dictionary entry, overwrite any existing entry //- Assign a dictionary entry, overwrite any existing entry
void set(const keyType&, const dictionary&); void set(const keyType& k, const dictionary& d);
//- Assign a T entry, overwrite any existing entry //- Assign a T entry, overwrite any existing entry
template<class T> template<class T>
void set(const keyType&, const T&); void set(const keyType& k, const T& t);
//- Remove an entry specified by keyword //- Remove an entry specified by keyword
bool remove(const word&); bool remove(const word& Keyword);
//- Change the keyword for an entry, //- Change the keyword for an entry,
// optionally forcing overwrite of an existing entry // optionally forcing overwrite of an existing entry
@ -494,13 +527,13 @@ public:
//- Merge entries from the given dictionary. //- Merge entries from the given dictionary.
// Also merge sub-dictionaries as required. // Also merge sub-dictionaries as required.
bool merge(const dictionary&); bool merge(const dictionary& dict);
//- Clear the dictionary //- Clear the dictionary
void clear(); void clear();
//- Transfer the contents of the argument and annul the argument. //- Transfer the contents of the argument and annul the argument.
void transfer(dictionary&); void transfer(dictionary& dict);
//- Transfer contents to the Xfer container //- Transfer contents to the Xfer container
Xfer<dictionary> xfer(); Xfer<dictionary> xfer();
@ -509,53 +542,53 @@ public:
// Read // Read
//- Read dictionary from Istream //- Read dictionary from Istream
bool read(Istream&); bool read(Istream& is);
//- Read dictionary from Istream, optionally keeping the header //- Read dictionary from Istream, optionally keeping the header
bool read(Istream&, const bool keepHeader); bool read(Istream& is, const bool keepHeader);
// Write // Write
//- Write sub-dictionary with the keyword as its header //- Write sub-dictionary with the keyword as its header
void writeEntry(const keyType& keyword, Ostream&) const; void writeEntry(const keyType& keyword, Ostream& os) const;
//- Write dictionary entries. //- Write dictionary entries.
// Optionally with extra new line between entries for // Optionally with extra new line between entries for
// "top-level" dictionaries // "top-level" dictionaries
void writeEntries(Ostream&, const bool extraNewLine=false) const; void writeEntries(Ostream& os, const bool extraNewLine=false) const;
//- Write dictionary, normally with sub-dictionary formatting //- Write dictionary, normally with sub-dictionary formatting
void write(Ostream&, const bool subDict=true) const; void write(Ostream& os, const bool subDict=true) const;
// Member Operators // Member Operators
//- Find and return entry //- Find and return entry
ITstream& operator[](const word&) const; ITstream& operator[](const word& keyword) const;
void operator=(const dictionary&); void operator=(const dictionary& rhs);
//- Include entries from the given dictionary. //- Include entries from the given dictionary.
// Warn, but do not overwrite existing entries. // Warn, but do not overwrite existing entries.
void operator+=(const dictionary&); void operator+=(const dictionary& rhs);
//- Conditionally include entries from the given dictionary. //- Conditionally include entries from the given dictionary.
// Do not overwrite existing entries. // Do not overwrite existing entries.
void operator|=(const dictionary&); void operator|=(const dictionary& rhs);
//- Unconditionally include entries from the given dictionary. //- Unconditionally include entries from the given dictionary.
// Overwrite existing entries. // Overwrite existing entries.
void operator<<=(const dictionary&); void operator<<=(const dictionary& rhs);
// IOstream operators // IOstream operators
//- Read dictionary from Istream //- Read dictionary from Istream
friend Istream& operator>>(Istream&, dictionary&); friend Istream& operator>>(Istream& is, dictionary& dict);
//- Write dictionary to Ostream //- Write dictionary to Ostream
friend Ostream& operator<<(Ostream&, const dictionary&); friend Ostream& operator<<(Ostream& os, const dictionary& dict);
}; };

View File

@ -128,21 +128,21 @@ bool Foam::dictionary::read(Istream& is)
} }
bool Foam::dictionary::substituteKeyword(const word& keyword) bool Foam::dictionary::substituteKeyword(const word& keyword, bool mergeEntry)
{ {
word varName = keyword(1, keyword.size()-1); const word varName = keyword(1, keyword.size()-1);
// lookup the variable name in the given dictionary // Lookup the variable name in the given dictionary
const entry* ePtr = lookupEntryPtr(varName, true, true); const entry* ePtr = lookupEntryPtr(varName, true, true);
// if defined insert its entries into this dictionary // If defined insert its entries into this dictionary
if (ePtr != nullptr) if (ePtr != nullptr)
{ {
const dictionary& addDict = ePtr->dict(); const dictionary& addDict = ePtr->dict();
forAllConstIter(IDLList<entry>, addDict, iter) forAllConstIter(IDLList<entry>, addDict, iter)
{ {
add(iter()); add(iter(), mergeEntry);
} }
return true; return true;

View File

@ -73,7 +73,7 @@ bool Foam::entry::getKeyword(keyType& keyword, token& keywordToken, Istream& is)
bool Foam::entry::getKeyword(keyType& keyword, Istream& is) bool Foam::entry::getKeyword(keyType& keyword, Istream& is)
{ {
token keywordToken; token keywordToken;
bool ok = getKeyword(keyword, keywordToken, is); const bool ok = getKeyword(keyword, keywordToken, is);
if (ok) if (ok)
{ {
@ -112,7 +112,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
token keyToken; token keyToken;
// Get the next keyword and if a valid keyword return true // Get the next keyword and if a valid keyword return true
bool valid = getKeyword(keyword, keyToken, is); const bool valid = getKeyword(keyword, keyToken, is);
if (!valid) if (!valid)
{ {
@ -153,7 +153,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
{ {
if (keyword[0] == '#') // ... Function entry if (keyword[0] == '#') // ... Function entry
{ {
word functionName = keyword(1, keyword.size()-1); const word functionName = keyword(1, keyword.size()-1);
if (disableFunctionEntries) if (disableFunctionEntries)
{ {
return parentDict.add return parentDict.add
@ -195,7 +195,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
if (nextToken == token::BEGIN_BLOCK) if (nextToken == token::BEGIN_BLOCK)
{ {
word varName = keyword(1, keyword.size()-1); const word varName = keyword(1, keyword.size()-1);
// lookup the variable name in the given dictionary // lookup the variable name in the given dictionary
const entry* ePtr = parentDict.lookupScopedEntryPtr const entry* ePtr = parentDict.lookupScopedEntryPtr
@ -227,7 +227,14 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
} }
else else
{ {
parentDict.substituteScopedKeyword(keyword); // Deal with duplicate entries (at least partially)
const bool mergeEntry =
(
functionEntries::inputModeEntry::merge()
|| functionEntries::inputModeEntry::overwrite()
);
parentDict.substituteScopedKeyword(keyword, mergeEntry);
} }
return true; return true;

View File

@ -62,7 +62,7 @@ void Foam::functionEntries::inputModeEntry::setMode(Istream& is)
{ {
clear(); clear();
word mode(is); const word mode(is);
if (mode == "merge" || mode == "default") if (mode == "merge" || mode == "default")
{ {
mode_ = MERGE; mode_ = MERGE;
@ -97,7 +97,7 @@ void Foam::functionEntries::inputModeEntry::setMode(Istream& is)
bool Foam::functionEntries::inputModeEntry::execute bool Foam::functionEntries::inputModeEntry::execute
( (
dictionary& parentDict, dictionary& unused,
Istream& is Istream& is
) )
{ {

View File

@ -34,12 +34,20 @@ Description
\endverbatim \endverbatim
The possible input modes: The possible input modes:
- \par merge merge sub-dictionaries when possible - \par merge
- \par overwrite keep last entry and silently remove previous ones merge sub-dictionaries when possible
- \par protect keep initial entry and silently ignore subsequent ones - \par overwrite
- \par warn keep initial entry and warn about subsequent ones keep last entry and silently remove previous ones
- \par error issue a FatalError for duplicate entries - \par protect
- \par default currently identical to merge keep initial entry and silently ignore subsequent ones
- \par warn
keep initial entry and warn about subsequent ones
- \par error
issue a FatalError for duplicate entries
- \par default
The default treatment - currently identical to \b merge.
Note that the clear() method resets to the default mode (merge).
SourceFiles SourceFiles
inputModeEntry.C inputModeEntry.C
@ -83,13 +91,13 @@ class inputModeEntry
// Private Member Functions // Private Member Functions
//- Read the mode as a word and set enum appropriately //- Read the mode as a word and set enum appropriately
static void setMode(Istream&); static void setMode(Istream& is);
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
inputModeEntry(const inputModeEntry&); inputModeEntry(const inputModeEntry&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const inputModeEntry&); void operator=(const inputModeEntry&) = delete;
public: public:
@ -101,7 +109,7 @@ public:
// Member Functions // Member Functions
//- Execute the functionEntry in a sub-dict context //- Execute the functionEntry in a sub-dict context
static bool execute(dictionary& parentDict, Istream&); static bool execute(dictionary& parentDict, Istream& is);
//- Reset the inputMode to %default (ie, %merge) //- Reset the inputMode to %default (ie, %merge)
static void clear(); static void clear();

View File

@ -67,10 +67,10 @@ class removeEntry
// Private Member Functions // Private Member Functions
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
removeEntry(const removeEntry&); removeEntry(const removeEntry&) = delete;
//- Disallow default bitwise assignment //- Disallow default bitwise assignment
void operator=(const removeEntry&); void operator=(const removeEntry&) = delete;
public: public:
@ -82,7 +82,7 @@ public:
// Member Functions // Member Functions
//- Execute the functionEntry in a sub-dict context //- Execute the functionEntry in a sub-dict context
static bool execute(dictionary& parentDict, Istream&); static bool execute(dictionary& parentDict, Istream& is);
}; };

View File

@ -21,9 +21,6 @@ License
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Description
PrimitiveEntry constructor from Istream and Ostream output operator.
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "primitiveEntry.H" #include "primitiveEntry.H"

View File

@ -310,17 +310,17 @@ bool Foam::argList::postProcess(int argc, char *argv[])
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Convert argv -> args_
// Transform sequences with "(" ... ")" into string lists in the process
bool Foam::argList::regroupArgv(int& argc, char**& argv) bool Foam::argList::regroupArgv(int& argc, char**& argv)
{ {
int nArgs = 0; int nArgs = 1;
int listDepth = 0; unsigned listDepth = 0;
string tmpString; string tmpString;
// Note: we also re-write directly into args_ // Note: we rewrite directly into args_
// and use a second pass to sort out args/options // and use a second pass to sort out args/options
for (int argI = 0; argI < argc; ++argI)
args_[0] = fileName(argv[0]);
for (int argI = 1; argI < argc; ++argI)
{ {
if (strcmp(argv[argI], "(") == 0) if (strcmp(argv[argI], "(") == 0)
{ {
@ -333,7 +333,7 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
{ {
--listDepth; --listDepth;
tmpString += ")"; tmpString += ")";
if (listDepth == 0) if (!listDepth)
{ {
args_[nArgs++] = tmpString; args_[nArgs++] = tmpString;
tmpString.clear(); tmpString.clear();
@ -359,11 +359,21 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
if (tmpString.size()) if (tmpString.size())
{ {
// Group(s) not closed, but flush anything still pending
args_[nArgs++] = tmpString; args_[nArgs++] = tmpString;
} }
args_.setSize(nArgs); args_.setSize(nArgs);
std::string::size_type len = (nArgs-1); // Spaces between args
forAll(args_, argi)
{
len += args_[argi].size();
}
// Length needed for regrouped command-line
argListStr_.reserve(len);
return nArgs < argc; return nArgs < argc;
} }
@ -403,6 +413,8 @@ void Foam::argList::getRootCase()
globalCase_ = casePath.name(); globalCase_ = casePath.name();
case_ = globalCase_; case_ = globalCase_;
// The name of the executable, unless already present in the environment
setEnv("FOAM_EXECUTABLE", executable_, false);
// Set the case and case-name as an environment variable // Set the case and case-name as an environment variable
if (rootPath_.isAbsolute()) if (rootPath_.isAbsolute())
@ -440,7 +452,7 @@ Foam::argList::argList
{ {
// Check if this run is a parallel run by searching for any parallel option // Check if this run is a parallel run by searching for any parallel option
// If found call runPar which might filter argv // If found call runPar which might filter argv
for (int argI = 0; argI < argc; ++argI) for (int argI = 1; argI < argc; ++argI)
{ {
if (argv[argI][0] == '-') if (argv[argI][0] == '-')
{ {
@ -455,17 +467,11 @@ Foam::argList::argList
} }
// Convert argv -> args_ and capture ( ... ) lists // Convert argv -> args_ and capture ( ... ) lists
// for normal arguments and for options
regroupArgv(argc, argv); regroupArgv(argc, argv);
argListStr_ += args_[0];
// Get executable name // Check arguments and options, argv[0] was already handled
args_[0] = fileName(argv[0]);
executable_ = fileName(argv[0]).name();
// Check arguments and options, we already have argv[0]
int nArgs = 1; int nArgs = 1;
argListStr_ = args_[0];
for (int argI = 1; argI < args_.size(); ++argI) for (int argI = 1; argI < args_.size(); ++argI)
{ {
argListStr_ += ' '; argListStr_ += ' ';
@ -525,6 +531,9 @@ Foam::argList::argList
args_.setSize(nArgs); args_.setSize(nArgs);
// Set executable name
executable_ = fileName(args_[0]).name();
parse(checkArgs, checkOpts, initialise); parse(checkArgs, checkOpts, initialise);
} }
@ -769,7 +778,7 @@ void Foam::argList::parse
} }
// Distribute the master's argument list (with new root) // Distribute the master's argument list (with new root)
bool hadCaseOpt = options_.found("case"); const bool hadCaseOpt = options_.found("case");
for for
( (
int slave = Pstream::firstSlave(); int slave = Pstream::firstSlave();

View File

@ -42,6 +42,8 @@ Description
Default command-line options: Default command-line options:
- \par -case \<dir\> - \par -case \<dir\>
Select a case directory instead of the current working directory Select a case directory instead of the current working directory
- \par -decomposeParDict \<file\>
Read decomposePar dictionary from specified location
- \par -parallel - \par -parallel
Specify case as a parallel job Specify case as a parallel job
- \par -doc - \par -doc
@ -51,10 +53,25 @@ Description
- \par -help - \par -help
Print the usage Print the usage
The environment variable \b FOAM_CASE is set to the path of the Additionally, the \b -noFunctionObjects and \b -postProcess options
global case (same for serial and parallel jobs). may be present for some solvers or utilities.
The environment variable \b FOAM_CASENAME is set to the name of the
global case. Environment variables set by argList or by Time:
- \par FOAM_CASE
The path of the global case.
It is the same for serial and parallel jobs.
- \par FOAM_CASENAME
The name of the global case.
- \par FOAM_EXECUTABLE
If not already present in the calling environment,
it is set to the \a name portion of the calling executable.
- \par FOAM_APPLICATION
If not already present in the calling environment,
it is set to the value of the \c application entry
(from \c controlDict) if that entry is present.
The value of the \b FOAM_APPLICATION may be inconsistent if the value of
the \c application entry is adjusted during runtime.
Note Note
- The document browser used is defined by the \b FOAM_DOC_BROWSER - The document browser used is defined by the \b FOAM_DOC_BROWSER
@ -131,10 +148,12 @@ class argList
// * cwd // * cwd
// //
// Also export FOAM_CASE and FOAM_CASENAME environment variables // Also export FOAM_CASE and FOAM_CASENAME environment variables
// so they can be used immediately (eg, in decomposeParDict) // so they can be used immediately (eg, in decomposeParDict), as well
// as the FOAM_EXECUTABLE environment.
void getRootCase(); void getRootCase();
//- Transcribe argv into internal args_ //- Transcribe argv into internal args_.
// Transform sequences with "(" ... ")" into string lists
// return true if any "(" ... ")" sequences were captured // return true if any "(" ... ")" sequences were captured
bool regroupArgv(int& argc, char**& argv); bool regroupArgv(int& argc, char**& argv);