Commit c9df5f92 authored by Andrew Heather's avatar Andrew Heather
Browse files

Merge branch 'dict-lookup' into 'develop'

Dict lookup

See merge request !105
parents a8e34825 ffe3e0e4
/*--------------------------------*- 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 2nd '.' found
const dictionary* dictPtr = this;
// Starting with a '.' -> go up for every further '.' found
++dotPos;
string::size_type begVar = dotPos + 1;
string::const_iterator iter = keyword.begin() + begVar;
string::size_type endVar = begVar;
while (iter != keyword.end() && *iter == '.')
const dictionary* dictPtr = this;
for
(
string::const_iterator it = keyword.begin()+1;
it != keyword.end() && *it == '.';
++dotPos, ++it
)
{
// 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
(
keyword.substr(endVar),
false,
patternMatch
);
return nullptr;
}
}
else
{
// Extract the first word
word firstWord = keyword.substr(0, dotPos);
const entry* entPtr = lookupScopedSubEntryPtr
(
firstWord,
false, //recursive
patternMatch
);
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
if (!entPtr)
while (true)
{
// 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
dotPos = keyword.find('.', dotPos+1);
string::size_type nextDotPos = keyword.find
entPtr = lookupEntryPtr
(
'.',
dotPos+1
keyword.substr(0, dotPos),
false,
patternMatch
);
while (true)
if (dotPos == string::npos)
{
// Parsed the whole word. Return entry or null.
return entPtr;
}
if (entPtr && entPtr->isDict())
{
const entry* subEntPtr = lookupEntryPtr
return entPtr->dict().lookupScopedSubEntryPtr
(
keyword.substr(0, nextDotPos),
false, //recursive,
keyword.substr(dotPos),
false,
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;
}
if (entPtr->isDict())
{
return entPtr->dict().lookupScopedSubEntryPtr
(
keyword.substr(dotPos),
false,
patternMatch
);
}
}
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
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.
To add - a merge() member function with a non-const dictionary parameter?
This would avoid unnecessary cloning in the add(entry*, bool) method.
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.
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
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;