Merge branch 'dict-lookup' into 'develop'
Dict lookup See merge request !105
This commit is contained in:
commit
c9df5f9249
53
applications/test/dictionary/testSubkeyword
Normal file
53
applications/test/dictionary/testSubkeyword
Normal 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
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
@ -288,6 +288,9 @@ Foam::vtkPVFoam::vtkPVFoam
|
||||
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
|
||||
if (fullCasePath.name().find("processor", 0) == 0)
|
||||
{
|
||||
|
@ -206,6 +206,9 @@ Foam::vtkPVblockMesh::vtkPVblockMesh
|
||||
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
|
||||
if (fullCasePath.name().find("processor", 0) == 0)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2015 OpenCFD Ltd.
|
||||
\\/ M anipulation | Copyright (C) 2015-2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -60,114 +60,101 @@ const Foam::entry* Foam::dictionary::lookupScopedSubEntryPtr
|
||||
// Non-scoped lookup
|
||||
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
|
||||
|
||||
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 == '.')
|
||||
// Go to parent
|
||||
if (&dictPtr->parent_ != &dictionary::null)
|
||||
{
|
||||
++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_;
|
||||
}
|
||||
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,
|
||||
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
|
||||
) const
|
||||
{
|
||||
if (keyword[0] == ':')
|
||||
if (keyword[0] == ':' || keyword[0] == '^')
|
||||
{
|
||||
// Go up to top level
|
||||
const dictionary* dictPtr = this;
|
||||
@ -597,10 +584,9 @@ const Foam::entry* Foam::dictionary::lookupScopedEntryPtr
|
||||
dictPtr = &dictPtr->parent_;
|
||||
}
|
||||
|
||||
// At top. Recurse to find entries
|
||||
return dictPtr->lookupScopedSubEntryPtr
|
||||
(
|
||||
keyword.substr(1, keyword.size()-1),
|
||||
keyword.substr(1),
|
||||
false,
|
||||
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
|
||||
const entry* ePtr = lookupScopedEntryPtr(varName, true, true);
|
||||
@ -631,7 +621,7 @@ bool Foam::dictionary::substituteScopedKeyword(const word& keyword)
|
||||
|
||||
forAllConstIter(IDLList<entry>, addDict, iter)
|
||||
{
|
||||
add(iter());
|
||||
add(iter(), mergeEntry);
|
||||
}
|
||||
|
||||
return true;
|
||||
@ -1034,7 +1024,6 @@ bool Foam::dictionary::changeKeyword
|
||||
IDLList<entry>::replace(iter2(), iter());
|
||||
delete iter2();
|
||||
hashedEntries_.erase(iter2);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
\\/ M anipulation | Copyright (C) 2016 OpenCFD Ltd.
|
||||
\\/ M anipulation | Copyright (C) 2016-2017 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,26 +25,57 @@ Class
|
||||
Foam::dictionary
|
||||
|
||||
Description
|
||||
A list of keyword definitions, which are a keyword followed by any number
|
||||
of values (e.g. words and numbers). The keywords can represent patterns
|
||||
which are matched using Posix regular expressions. The general order for
|
||||
searching is as follows:
|
||||
- exact match
|
||||
- pattern match (in reverse order)
|
||||
- optional recursion into the enclosing (parent) dictionaries
|
||||
A list of keyword definitions, which are a keyword followed by a number
|
||||
of values (eg, words and numbers) or by a sub-dictionary.
|
||||
Since the dictionary format is used extensively throughout OpenFOAM for
|
||||
input/output files, there are many examples of its use.
|
||||
|
||||
The dictionary class is the base class for IOdictionary.
|
||||
It also serves as a bootstrap dictionary for the objectRegistry data
|
||||
dictionaries since, unlike the IOdictionary class, it does not use an
|
||||
objectRegistry itself to work.
|
||||
Dictionary keywords are a plain word or a pattern (regular expression).
|
||||
The general order for searching is as follows:
|
||||
- exact match
|
||||
- pattern match (in reverse order)
|
||||
- optional recursion into the enclosing (parent) dictionaries
|
||||
|
||||
To add - a merge() member function with a non-const dictionary parameter?
|
||||
This would avoid unnecessary cloning in the add(entry*, bool) method.
|
||||
The dictionary class is the base class for IOdictionary and also serves
|
||||
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
|
||||
dictionary.C
|
||||
dictionaryIO.C
|
||||
|
||||
SeeAlso
|
||||
- Foam::entry
|
||||
- Foam::dictionaryEntry
|
||||
- Foam::primitiveEntry
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef dictionary_H
|
||||
@ -76,6 +107,7 @@ Ostream& operator<<(Ostream&, const dictionary&);
|
||||
Class dictionaryName Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- Holds name for a dictionary
|
||||
class dictionaryName
|
||||
{
|
||||
// Private data
|
||||
@ -87,11 +119,11 @@ public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct dictionaryName null
|
||||
//- Construct null
|
||||
dictionaryName()
|
||||
{}
|
||||
|
||||
//- Construct dictionaryName as copy of the given fileName
|
||||
//- Construct as copy of the given fileName
|
||||
dictionaryName(const fileName& name)
|
||||
:
|
||||
name_(name)
|
||||
@ -116,16 +148,15 @@ public:
|
||||
const word dictName() const
|
||||
{
|
||||
const word scopedName = name_.name();
|
||||
const std::string::size_type i = scopedName.rfind('.');
|
||||
|
||||
string::size_type i = scopedName.rfind('.');
|
||||
|
||||
if (i == scopedName.npos)
|
||||
if (i == std::string::npos)
|
||||
{
|
||||
return scopedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
return scopedName.substr(i + 1, scopedName.npos);
|
||||
return scopedName.substr(i+1);
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -142,8 +173,7 @@ class dictionary
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- If true write optional keywords and values
|
||||
// if not present in dictionary
|
||||
//- Report optional keywords and values if not present in dictionary
|
||||
static bool writeOptionalEntries;
|
||||
|
||||
//- HashTable of the entries held on the DL-list for quick lookup
|
||||
@ -165,7 +195,7 @@ class dictionary
|
||||
// otherwise return nullptr. Allows scoping using '.'
|
||||
const entry* lookupScopedSubEntryPtr
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
@ -217,38 +247,38 @@ public:
|
||||
(
|
||||
const fileName& name,
|
||||
const dictionary& parentDict,
|
||||
Istream&
|
||||
Istream& is
|
||||
);
|
||||
|
||||
//- Construct top-level dictionary from Istream,
|
||||
// reading entries until EOF
|
||||
dictionary(Istream&);
|
||||
dictionary(Istream& is);
|
||||
|
||||
//- Construct top-level dictionary from Istream,
|
||||
// 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
|
||||
dictionary(const dictionary& parentDict, const dictionary&);
|
||||
|
||||
//- Construct top-level dictionary as copy
|
||||
dictionary(const dictionary&);
|
||||
dictionary(const dictionary& dict);
|
||||
|
||||
//- Construct top-level dictionary as copy from pointer to 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
|
||||
dictionary(const dictionary& parentDict, const Xfer<dictionary>&);
|
||||
dictionary(const dictionary& parentDict, const Xfer<dictionary>& dict);
|
||||
|
||||
//- Construct top-level dictionary by transferring parameter contents
|
||||
dictionary(const Xfer<dictionary>&);
|
||||
dictionary(const Xfer<dictionary>& dict);
|
||||
|
||||
//- Construct and return clone
|
||||
autoPtr<dictionary> clone() const;
|
||||
|
||||
//- Construct top-level dictionary on freestore from Istream
|
||||
static autoPtr<dictionary> New(Istream&);
|
||||
static autoPtr<dictionary> New(Istream& is);
|
||||
|
||||
|
||||
//- Destructor
|
||||
@ -286,8 +316,8 @@ public:
|
||||
// If patternMatch, use regular expressions
|
||||
bool found
|
||||
(
|
||||
const word&,
|
||||
bool recursive=false,
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
@ -297,7 +327,7 @@ public:
|
||||
// If patternMatch, use regular expressions
|
||||
const entry* lookupEntryPtr
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
@ -308,7 +338,7 @@ public:
|
||||
// If patternMatch, use regular expressions.
|
||||
entry* lookupEntryPtr
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
);
|
||||
@ -318,7 +348,7 @@ public:
|
||||
// If patternMatch, use regular expressions.
|
||||
const entry& lookupEntry
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
@ -328,22 +358,21 @@ public:
|
||||
// If patternMatch, use regular expressions.
|
||||
ITstream& lookup
|
||||
(
|
||||
const word&,
|
||||
bool recursive=false,
|
||||
bool patternMatch=true
|
||||
const word& keyword,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return a T,
|
||||
// if not found return the given default value
|
||||
//- Find and return a T, or return the given default value
|
||||
// If recursive, search parent dictionaries.
|
||||
// If patternMatch, use regular expressions.
|
||||
template<class T>
|
||||
T lookupOrDefault
|
||||
(
|
||||
const word&,
|
||||
const T&,
|
||||
bool recursive=false,
|
||||
bool patternMatch=true
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return a T, if not found return the given
|
||||
@ -353,10 +382,10 @@ public:
|
||||
template<class T>
|
||||
T lookupOrAddDefault
|
||||
(
|
||||
const word&,
|
||||
const T&,
|
||||
bool recursive=false,
|
||||
bool patternMatch=true
|
||||
const word& keyword,
|
||||
const T& deflt,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
);
|
||||
|
||||
//- Find an entry if present, and assign to T
|
||||
@ -366,10 +395,10 @@ public:
|
||||
template<class T>
|
||||
bool readIfPresent
|
||||
(
|
||||
const word&,
|
||||
T&,
|
||||
bool recursive=false,
|
||||
bool patternMatch=true
|
||||
const word& keyword,
|
||||
T& val,
|
||||
bool recursive = false,
|
||||
bool patternMatch = true
|
||||
) const;
|
||||
|
||||
//- Find and return an entry data stream pointer if present
|
||||
@ -377,33 +406,33 @@ public:
|
||||
// Special handling for ':' at start of keyword and '..'.
|
||||
const entry* lookupScopedEntryPtr
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
bool recursive,
|
||||
bool patternMatch
|
||||
) const;
|
||||
|
||||
//- 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
|
||||
// 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
|
||||
// otherwise return nullptr.
|
||||
dictionary* subDictPtr(const word&);
|
||||
dictionary* subDictPtr(const word& keyword);
|
||||
|
||||
//- 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
|
||||
dictionary& subDict(const word&);
|
||||
dictionary& subDict(const word& keyword);
|
||||
|
||||
//- Find and return a sub-dictionary as a copy, or
|
||||
// return an empty dictionary if the sub-dictionary does not exist
|
||||
dictionary subOrEmptyDict
|
||||
(
|
||||
const word&,
|
||||
const word& keyword,
|
||||
const bool mustRead = false
|
||||
) const;
|
||||
|
||||
@ -414,74 +443,78 @@ public:
|
||||
wordList sortedToc() const;
|
||||
|
||||
//- Return the list of available keys or patterns
|
||||
List<keyType> keys(bool patterns=false) const;
|
||||
List<keyType> keys(bool patterns = false) const;
|
||||
|
||||
|
||||
// Editing
|
||||
|
||||
//- Substitute the given keyword prepended by '$' with the
|
||||
// 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
|
||||
// corresponding sub-dictionary entries
|
||||
bool substituteScopedKeyword(const word& keyword);
|
||||
bool substituteScopedKeyword
|
||||
(
|
||||
const word& keyword,
|
||||
bool mergeEntry=false
|
||||
);
|
||||
|
||||
//- Add a new entry
|
||||
// With the merge option, dictionaries are interwoven and
|
||||
// primitive entries are overwritten
|
||||
bool add(entry*, bool mergeEntry=false);
|
||||
bool add(entry* entryPtr, bool mergeEntry=false);
|
||||
|
||||
//- Add an entry
|
||||
// With the merge option, dictionaries are interwoven and
|
||||
// primitive entries are overwritten
|
||||
void add(const entry&, bool mergeEntry=false);
|
||||
void add(const entry& e, bool mergeEntry=false);
|
||||
|
||||
//- Add a word 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
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// optionally merge with an existing sub-dictionary
|
||||
void add
|
||||
(
|
||||
const keyType&,
|
||||
const dictionary&,
|
||||
bool mergeEntry=false
|
||||
const keyType& k,
|
||||
const dictionary& d,
|
||||
bool mergeEntry = false
|
||||
);
|
||||
|
||||
//- Add a T entry
|
||||
// optionally overwrite an existing entry
|
||||
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
|
||||
void set(entry*);
|
||||
void set(entry* entryPtr);
|
||||
|
||||
//- 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
|
||||
void set(const keyType&, const dictionary&);
|
||||
void set(const keyType& k, const dictionary& d);
|
||||
|
||||
//- Assign a T entry, overwrite any existing entry
|
||||
template<class T>
|
||||
void set(const keyType&, const T&);
|
||||
void set(const keyType& k, const T& t);
|
||||
|
||||
//- Remove an entry specified by keyword
|
||||
bool remove(const word&);
|
||||
bool remove(const word& Keyword);
|
||||
|
||||
//- Change the keyword for an entry,
|
||||
// optionally forcing overwrite of an existing entry
|
||||
@ -494,13 +527,13 @@ public:
|
||||
|
||||
//- Merge entries from the given dictionary.
|
||||
// Also merge sub-dictionaries as required.
|
||||
bool merge(const dictionary&);
|
||||
bool merge(const dictionary& dict);
|
||||
|
||||
//- Clear the dictionary
|
||||
void clear();
|
||||
|
||||
//- Transfer the contents of the argument and annul the argument.
|
||||
void transfer(dictionary&);
|
||||
void transfer(dictionary& dict);
|
||||
|
||||
//- Transfer contents to the Xfer container
|
||||
Xfer<dictionary> xfer();
|
||||
@ -509,53 +542,53 @@ public:
|
||||
// Read
|
||||
|
||||
//- Read dictionary from Istream
|
||||
bool read(Istream&);
|
||||
bool read(Istream& is);
|
||||
|
||||
//- Read dictionary from Istream, optionally keeping the header
|
||||
bool read(Istream&, const bool keepHeader);
|
||||
bool read(Istream& is, const bool keepHeader);
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- 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.
|
||||
// Optionally with extra new line between entries for
|
||||
// "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
|
||||
void write(Ostream&, const bool subDict=true) const;
|
||||
void write(Ostream& os, const bool subDict=true) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- 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.
|
||||
// Warn, but do not overwrite existing entries.
|
||||
void operator+=(const dictionary&);
|
||||
void operator+=(const dictionary& rhs);
|
||||
|
||||
//- Conditionally include entries from the given dictionary.
|
||||
// Do not overwrite existing entries.
|
||||
void operator|=(const dictionary&);
|
||||
void operator|=(const dictionary& rhs);
|
||||
|
||||
//- Unconditionally include entries from the given dictionary.
|
||||
// Overwrite existing entries.
|
||||
void operator<<=(const dictionary&);
|
||||
void operator<<=(const dictionary& rhs);
|
||||
|
||||
|
||||
// IOstream operators
|
||||
|
||||
//- Read dictionary from Istream
|
||||
friend Istream& operator>>(Istream&, dictionary&);
|
||||
friend Istream& operator>>(Istream& is, dictionary& dict);
|
||||
|
||||
//- Write dictionary to Ostream
|
||||
friend Ostream& operator<<(Ostream&, const dictionary&);
|
||||
friend Ostream& operator<<(Ostream& os, const dictionary& dict);
|
||||
};
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
// if defined insert its entries into this dictionary
|
||||
// If defined insert its entries into this dictionary
|
||||
if (ePtr != nullptr)
|
||||
{
|
||||
const dictionary& addDict = ePtr->dict();
|
||||
|
||||
forAllConstIter(IDLList<entry>, addDict, iter)
|
||||
{
|
||||
add(iter());
|
||||
add(iter(), mergeEntry);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -73,7 +73,7 @@ bool Foam::entry::getKeyword(keyType& keyword, token& keywordToken, Istream& is)
|
||||
bool Foam::entry::getKeyword(keyType& keyword, Istream& is)
|
||||
{
|
||||
token keywordToken;
|
||||
bool ok = getKeyword(keyword, keywordToken, is);
|
||||
const bool ok = getKeyword(keyword, keywordToken, is);
|
||||
|
||||
if (ok)
|
||||
{
|
||||
@ -112,7 +112,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
|
||||
token keyToken;
|
||||
|
||||
// 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)
|
||||
{
|
||||
@ -153,7 +153,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
|
||||
{
|
||||
if (keyword[0] == '#') // ... Function entry
|
||||
{
|
||||
word functionName = keyword(1, keyword.size()-1);
|
||||
const word functionName = keyword(1, keyword.size()-1);
|
||||
if (disableFunctionEntries)
|
||||
{
|
||||
return parentDict.add
|
||||
@ -195,7 +195,7 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
|
||||
|
||||
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
|
||||
const entry* ePtr = parentDict.lookupScopedEntryPtr
|
||||
@ -227,7 +227,14 @@ bool Foam::entry::New(dictionary& parentDict, Istream& is)
|
||||
}
|
||||
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;
|
||||
|
@ -62,7 +62,7 @@ void Foam::functionEntries::inputModeEntry::setMode(Istream& is)
|
||||
{
|
||||
clear();
|
||||
|
||||
word mode(is);
|
||||
const word mode(is);
|
||||
if (mode == "merge" || mode == "default")
|
||||
{
|
||||
mode_ = MERGE;
|
||||
@ -97,7 +97,7 @@ void Foam::functionEntries::inputModeEntry::setMode(Istream& is)
|
||||
|
||||
bool Foam::functionEntries::inputModeEntry::execute
|
||||
(
|
||||
dictionary& parentDict,
|
||||
dictionary& unused,
|
||||
Istream& is
|
||||
)
|
||||
{
|
||||
|
@ -34,12 +34,20 @@ Description
|
||||
\endverbatim
|
||||
|
||||
The possible input modes:
|
||||
- \par merge merge sub-dictionaries when possible
|
||||
- \par overwrite keep last entry and silently remove previous ones
|
||||
- \par protect 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 currently identical to merge
|
||||
- \par merge
|
||||
merge sub-dictionaries when possible
|
||||
- \par overwrite
|
||||
keep last entry and silently remove previous ones
|
||||
- \par protect
|
||||
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
|
||||
inputModeEntry.C
|
||||
@ -83,13 +91,13 @@ class inputModeEntry
|
||||
// Private Member Functions
|
||||
|
||||
//- Read the mode as a word and set enum appropriately
|
||||
static void setMode(Istream&);
|
||||
static void setMode(Istream& is);
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
inputModeEntry(const inputModeEntry&);
|
||||
inputModeEntry(const inputModeEntry&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const inputModeEntry&);
|
||||
void operator=(const inputModeEntry&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
@ -101,7 +109,7 @@ public:
|
||||
// Member Functions
|
||||
|
||||
//- 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)
|
||||
static void clear();
|
||||
|
@ -67,10 +67,10 @@ class removeEntry
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
removeEntry(const removeEntry&);
|
||||
removeEntry(const removeEntry&) = delete;
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const removeEntry&);
|
||||
void operator=(const removeEntry&) = delete;
|
||||
|
||||
|
||||
public:
|
||||
@ -82,7 +82,7 @@ public:
|
||||
// Member Functions
|
||||
|
||||
//- Execute the functionEntry in a sub-dict context
|
||||
static bool execute(dictionary& parentDict, Istream&);
|
||||
static bool execute(dictionary& parentDict, Istream& is);
|
||||
};
|
||||
|
||||
|
||||
|
@ -21,9 +21,6 @@ License
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Description
|
||||
PrimitiveEntry constructor from Istream and Ostream output operator.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "primitiveEntry.H"
|
||||
|
@ -310,17 +310,17 @@ bool Foam::argList::postProcess(int argc, char *argv[])
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// Convert argv -> args_
|
||||
// Transform sequences with "(" ... ")" into string lists in the process
|
||||
bool Foam::argList::regroupArgv(int& argc, char**& argv)
|
||||
{
|
||||
int nArgs = 0;
|
||||
int listDepth = 0;
|
||||
int nArgs = 1;
|
||||
unsigned listDepth = 0;
|
||||
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
|
||||
for (int argI = 0; argI < argc; ++argI)
|
||||
|
||||
args_[0] = fileName(argv[0]);
|
||||
for (int argI = 1; argI < argc; ++argI)
|
||||
{
|
||||
if (strcmp(argv[argI], "(") == 0)
|
||||
{
|
||||
@ -333,7 +333,7 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
|
||||
{
|
||||
--listDepth;
|
||||
tmpString += ")";
|
||||
if (listDepth == 0)
|
||||
if (!listDepth)
|
||||
{
|
||||
args_[nArgs++] = tmpString;
|
||||
tmpString.clear();
|
||||
@ -359,11 +359,21 @@ bool Foam::argList::regroupArgv(int& argc, char**& argv)
|
||||
|
||||
if (tmpString.size())
|
||||
{
|
||||
// Group(s) not closed, but flush anything still pending
|
||||
args_[nArgs++] = tmpString;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -403,6 +413,8 @@ void Foam::argList::getRootCase()
|
||||
globalCase_ = casePath.name();
|
||||
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
|
||||
if (rootPath_.isAbsolute())
|
||||
@ -440,7 +452,7 @@ Foam::argList::argList
|
||||
{
|
||||
// Check if this run is a parallel run by searching for any parallel option
|
||||
// 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] == '-')
|
||||
{
|
||||
@ -455,17 +467,11 @@ Foam::argList::argList
|
||||
}
|
||||
|
||||
// Convert argv -> args_ and capture ( ... ) lists
|
||||
// for normal arguments and for options
|
||||
regroupArgv(argc, argv);
|
||||
argListStr_ += args_[0];
|
||||
|
||||
// Get executable name
|
||||
args_[0] = fileName(argv[0]);
|
||||
executable_ = fileName(argv[0]).name();
|
||||
|
||||
// Check arguments and options, we already have argv[0]
|
||||
// Check arguments and options, argv[0] was already handled
|
||||
int nArgs = 1;
|
||||
argListStr_ = args_[0];
|
||||
|
||||
for (int argI = 1; argI < args_.size(); ++argI)
|
||||
{
|
||||
argListStr_ += ' ';
|
||||
@ -525,6 +531,9 @@ Foam::argList::argList
|
||||
|
||||
args_.setSize(nArgs);
|
||||
|
||||
// Set executable name
|
||||
executable_ = fileName(args_[0]).name();
|
||||
|
||||
parse(checkArgs, checkOpts, initialise);
|
||||
}
|
||||
|
||||
@ -769,7 +778,7 @@ void Foam::argList::parse
|
||||
}
|
||||
|
||||
// Distribute the master's argument list (with new root)
|
||||
bool hadCaseOpt = options_.found("case");
|
||||
const bool hadCaseOpt = options_.found("case");
|
||||
for
|
||||
(
|
||||
int slave = Pstream::firstSlave();
|
||||
|
@ -42,6 +42,8 @@ Description
|
||||
Default command-line options:
|
||||
- \par -case \<dir\>
|
||||
Select a case directory instead of the current working directory
|
||||
- \par -decomposeParDict \<file\>
|
||||
Read decomposePar dictionary from specified location
|
||||
- \par -parallel
|
||||
Specify case as a parallel job
|
||||
- \par -doc
|
||||
@ -51,10 +53,25 @@ Description
|
||||
- \par -help
|
||||
Print the usage
|
||||
|
||||
The environment variable \b FOAM_CASE is set to the path of the
|
||||
global case (same for serial and parallel jobs).
|
||||
The environment variable \b FOAM_CASENAME is set to the name of the
|
||||
global case.
|
||||
Additionally, the \b -noFunctionObjects and \b -postProcess options
|
||||
may be present for some solvers or utilities.
|
||||
|
||||
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
|
||||
- The document browser used is defined by the \b FOAM_DOC_BROWSER
|
||||
@ -131,10 +148,12 @@ class argList
|
||||
// * cwd
|
||||
//
|
||||
// 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();
|
||||
|
||||
//- Transcribe argv into internal args_
|
||||
//- Transcribe argv into internal args_.
|
||||
// Transform sequences with "(" ... ")" into string lists
|
||||
// return true if any "(" ... ")" sequences were captured
|
||||
bool regroupArgv(int& argc, char**& argv);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user