Reworked dictionary code :

* finally removed #ifdef's with old merge method
 * use autoPtr::ptr() instead of autoPtr::() to reduce cloning
 * eliminated a few add() methods that are covered by the templated form
 * added a 'set()' method that forces overwrite - symmetric with HashTable
This commit is contained in:
Mark Olesen
2008-06-13 14:40:46 +02:00
parent 1e8d4b2a82
commit 92cd94ac66
4 changed files with 178 additions and 171 deletions

View File

@ -34,74 +34,6 @@ defineTypeNameAndDebug(Foam::dictionary, 0);
const Foam::dictionary Foam::dictionary::null; const Foam::dictionary Foam::dictionary::null;
#define DICTIONARY_INPLACE_MERGE
// * * * * * * * * * * * * * Private member functions * * * * * * * * * * * //
bool Foam::dictionary::add(entry* ePtr, bool mergeEntry)
{
HashTable<entry*>::iterator iter = hashedEntries_.find(ePtr->keyword());
if (mergeEntry && iter != hashedEntries_.end())
{
// merge dictionary with dictionary
if (iter()->isDict() && ePtr->isDict())
{
iter()->dict().merge(ePtr->dict());
delete ePtr;
return true;
}
else
{
// replace existing dictionary with entry or vice versa
#ifdef DICTIONARY_INPLACE_MERGE
IDLList<entry>::replace(iter(), ePtr);
delete iter();
hashedEntries_.erase(iter);
if (hashedEntries_.insert(ePtr->keyword(), ePtr))
{
ePtr->name() = name_ + "::" + ePtr->keyword();
return true;
}
else
{
IOWarningIn("dictionary::add(entry* ePtr)", (*this))
<< "problem replacing entry "<< ePtr->keyword()
<< " in dictionary " << name()
<< endl;
IDLList<entry>::remove(ePtr);
delete ePtr;
return false;
}
#else
remove(ePtr->keyword());
#endif
}
}
if (hashedEntries_.insert(ePtr->keyword(), ePtr))
{
ePtr->name() = name_ + "::" + ePtr->keyword();
IDLList<entry>::append(ePtr);
return true;
}
else
{
IOWarningIn("dictionary::add(entry* ePtr)", (*this))
<< "attempt to add entry "<< ePtr->keyword()
<< " which already exists in dictionary " << name()
<< endl;
delete ePtr;
return false;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dictionary::dictionary() Foam::dictionary::dictionary()
@ -270,11 +202,10 @@ const Foam::entry& Foam::dictionary::lookupEntry
bool recursive bool recursive
) const ) const
{ {
const entry* ePtr = lookupEntryPtr(keyword, recursive); const entry* entryPtr = lookupEntryPtr(keyword, recursive);
if (ePtr == NULL) if (entryPtr == NULL)
{ {
// If keyword not found print error message ...
FatalIOErrorIn FatalIOErrorIn
( (
"dictionary::lookupEntry(const word& keyword) const", "dictionary::lookupEntry(const word& keyword) const",
@ -284,7 +215,7 @@ const Foam::entry& Foam::dictionary::lookupEntry
<< exit(FatalIOError); << exit(FatalIOError);
} }
return *ePtr; return *entryPtr;
} }
@ -300,7 +231,9 @@ Foam::ITstream& Foam::dictionary::lookup
bool Foam::dictionary::isDict(const word& keyword) const bool Foam::dictionary::isDict(const word& keyword) const
{ {
if (const entry* entryPtr = lookupEntryPtr(keyword)) const entry* entryPtr = lookupEntryPtr(keyword);
if (entryPtr)
{ {
return entryPtr->isDict(); return entryPtr->isDict();
} }
@ -313,7 +246,9 @@ bool Foam::dictionary::isDict(const word& keyword) const
const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
{ {
if (const entry* entryPtr = lookupEntryPtr(keyword)) const entry* entryPtr = lookupEntryPtr(keyword);
if (entryPtr)
{ {
return &entryPtr->dict(); return &entryPtr->dict();
} }
@ -326,13 +261,9 @@ const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
{ {
if (const entry* entryPtr = lookupEntryPtr(keyword)) const entry* entryPtr = lookupEntryPtr(keyword);
if (entryPtr == NULL)
{ {
return entryPtr->dict();
}
else
{
// If keyword not found print error message ...
FatalIOErrorIn FatalIOErrorIn
( (
"dictionary::subDict(const word& keyword) const", "dictionary::subDict(const word& keyword) const",
@ -340,37 +271,31 @@ const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
) << " keyword " << keyword << " is undefined in dictionary " ) << " keyword " << keyword << " is undefined in dictionary "
<< name() << name()
<< exit(FatalIOError); << exit(FatalIOError);
return entryPtr->dict();
} }
return entryPtr->dict();
} }
Foam::dictionary& Foam::dictionary::subDict(const word& keyword) Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
{ {
if (entry* entryPtr = lookupEntryPtr(keyword)) entry* entryPtr = lookupEntryPtr(keyword);
if (entryPtr == NULL)
{ {
return entryPtr->dict();
}
else
{
// If keyword not found print error message ...
FatalIOErrorIn FatalIOErrorIn
( (
"dictionary::subDict(const word& keyword) const", "dictionary::subDict(const word& keyword)",
*this *this
) << " keyword " << keyword << " is undefined in dictionary " ) << " keyword " << keyword << " is undefined in dictionary "
<< name() << name()
<< exit(FatalIOError); << exit(FatalIOError);
return entryPtr->dict();
} }
return entryPtr->dict();
} }
Foam::wordList Foam::dictionary::toc() const Foam::wordList Foam::dictionary::toc() const
{ {
wordList keywords(size()); wordList keys(size());
label i = 0; label i = 0;
for for
@ -380,56 +305,124 @@ Foam::wordList Foam::dictionary::toc() const
++iter ++iter
) )
{ {
keywords[i++] = iter().keyword(); keys[i++] = iter().keyword();
} }
return keywords; return keys;
} }
void Foam::dictionary::add(const entry& e) bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
{ {
add(e.clone(*this).ptr()); HashTable<entry*>::iterator iter = hashedEntries_.find(entryPtr->keyword());
if (mergeEntry && iter != hashedEntries_.end())
{
// merge dictionary with dictionary
if (iter()->isDict() && entryPtr->isDict())
{
iter()->dict().merge(entryPtr->dict());
delete entryPtr;
return true;
}
else
{
// replace existing dictionary with entry or vice versa
IDLList<entry>::replace(iter(), entryPtr);
delete iter();
hashedEntries_.erase(iter);
if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
{
entryPtr->name() = name_ + "::" + entryPtr->keyword();
return true;
}
else
{
IOWarningIn("dictionary::add(entry*)", (*this))
<< "problem replacing entry "<< entryPtr->keyword()
<< " in dictionary " << name() << endl;
IDLList<entry>::remove(entryPtr);
delete entryPtr;
return false;
}
}
}
if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
{
entryPtr->name() = name_ + "::" + entryPtr->keyword();
IDLList<entry>::append(entryPtr);
return true;
}
else
{
IOWarningIn("dictionary::add(entry* entryPtr)", (*this))
<< "attempt to add entry "<< entryPtr->keyword()
<< " which already exists in dictionary " << name()
<< endl;
delete entryPtr;
return false;
}
} }
void Foam::dictionary::add(const word& keyword, const token& t)
void Foam::dictionary::add(const entry& e, bool mergeEntry)
{ {
add(new primitiveEntry(keyword, t)); add(e.clone(*this).ptr(), mergeEntry);
} }
void Foam::dictionary::add(const word& keyword, const word& w) void Foam::dictionary::add(const word& k, const word& w, bool overwrite)
{ {
add(new primitiveEntry(keyword, token(w))); add(new primitiveEntry(k, token(w)), overwrite);
} }
void Foam::dictionary::add(const word& keyword, const Foam::string& s) void Foam::dictionary::add(const word& k, const Foam::string& s, bool overwrite)
{ {
add(new primitiveEntry(keyword, token(s))); add(new primitiveEntry(k, token(s)), overwrite);
} }
void Foam::dictionary::add(const word& keyword, const label l) void Foam::dictionary::add(const word& k, const label l, bool overwrite)
{ {
add(new primitiveEntry(keyword, token(l))); add(new primitiveEntry(k, token(l)), overwrite);
} }
void Foam::dictionary::add(const word& keyword, const scalar s) void Foam::dictionary::add(const word& k, const scalar s, bool overwrite)
{ {
add(new primitiveEntry(keyword, token(s))); add(new primitiveEntry(k, token(s)), overwrite);
} }
void Foam::dictionary::add(const word& keyword, const ITstream& tokens) void Foam::dictionary::add(const word& k, const dictionary& d, bool mergeEntry)
{ {
add(new primitiveEntry(keyword, tokens)); add(new dictionaryEntry(k, *this, d), mergeEntry);
} }
void Foam::dictionary::add(const word& keyword, const tokenList& tokens)
void Foam::dictionary::set(entry* entryPtr)
{ {
add(new primitiveEntry(keyword, tokens)); entry* existingPtr = lookupEntryPtr(entryPtr->keyword());
// clear dictionary so merge acts like overwrite
if (existingPtr && existingPtr->isDict())
{
existingPtr->dict().clear();
}
add(entryPtr, true);
} }
void Foam::dictionary::add(const word& keyword, const dictionary& dict)
void Foam::dictionary::set(const entry& e)
{ {
add(new dictionaryEntry(keyword, *this, dict)); set(e.clone(*this).ptr());
}
void Foam::dictionary::set(const word& k, const dictionary& d)
{
set(new dictionaryEntry(k, *this, d));
} }
@ -486,7 +479,10 @@ bool Foam::dictionary::changeKeyword
} }
else else
{ {
// could issue warning if desired WarningIn("dictionary::changeKeyword(const word& old, const word& new)")
<< "cannot rename keyword "<< oldKeyword
<< " to existing keyword " << newKeyword
<< " in dictionary " << name() << endl;
return false; return false;
} }
} }
@ -527,34 +523,24 @@ bool Foam::dictionary::merge(const dictionary& dict)
if (iter2 != hashedEntries_.end()) if (iter2 != hashedEntries_.end())
{ {
// Recursively merge sub-dictionaries // Recursively merge sub-dictionaries
// TODO: merge without copying
if (iter2()->isDict() && iter().isDict()) if (iter2()->isDict() && iter().isDict())
{ {
// without copying and without remove/add? if (iter2()->dict().merge(iter().dict()))
// this certainly looks ugly and doesn't necessarily
// retain the original sort order (perhaps nice to have)
if
(
iter2()->dict().merge(iter().dict())
)
{ {
changed = true; changed = true;
} }
} }
else else
{ {
#ifdef DICTIONARY_INPLACE_MERGE
add(iter().clone(*this).ptr(), true); add(iter().clone(*this).ptr(), true);
#else
remove(keyword);
add(iter().clone(*this)());
#endif
changed = true; changed = true;
} }
} }
else else
{ {
// not found - just add // not found - just add
add(iter().clone(*this)()); add(iter().clone(*this).ptr());
changed = true; changed = true;
} }
} }
@ -588,8 +574,8 @@ void Foam::dictionary::operator=(const dictionary& dict)
<< abort(FatalError); << abort(FatalError);
} }
// Clear the current entries name_ = dict.name();
IDLList<entry>::clear(); clear();
// Create clones of the entries in the given dictionary // Create clones of the entries in the given dictionary
// resetting the parentDict to this dictionary // resetting the parentDict to this dictionary
@ -603,10 +589,6 @@ void Foam::dictionary::operator=(const dictionary& dict)
IDLList<entry>::append(iter().clone(*this).ptr()); IDLList<entry>::append(iter().clone(*this).ptr());
} }
name_ = dict.name();
hashedEntries_.clear();
for for
( (
IDLList<entry>::iterator iter = begin(); IDLList<entry>::iterator iter = begin();
@ -636,7 +618,7 @@ void Foam::dictionary::operator+=(const dictionary& dict)
++iter ++iter
) )
{ {
add(iter().clone(*this)()); add(iter().clone(*this).ptr());
} }
} }
@ -660,7 +642,7 @@ void Foam::dictionary::operator|=(const dictionary& dict)
{ {
if (!found(iter().keyword())) if (!found(iter().keyword()))
{ {
add(iter().clone(*this)()); add(iter().clone(*this).ptr());
} }
} }
} }
@ -683,8 +665,7 @@ void Foam::dictionary::operator<<=(const dictionary& dict)
++iter ++iter
) )
{ {
remove(iter().keyword()); set(iter().clone(*this).ptr());
add(iter().clone(*this)());
} }
} }

View File

@ -34,6 +34,10 @@ Description
data dictionaries, since unlike the IOdictionary class, it does not use data dictionaries, since unlike the IOdictionary class, it does not use
a objectRegistry itself to work. a objectRegistry itself to work.
ToDo
A merge() member function with a non-const dictionary parameter.
This would avoid unnecessary cloning in the add(entry*,bool) method
SourceFiles SourceFiles
dictionary.C dictionary.C
dictionaryIO.C dictionaryIO.C
@ -217,38 +221,57 @@ public:
// Editing // Editing
//- Add a new entry //- Add a new entry
bool add(entry*, bool mergeEntry = false); // With the merge option, dictionaries are interwoven and
// primitive entries are overwritten
bool add(entry*, bool mergeEntry=false);
//- Add an entry //- Add an entry
void add(const entry&); // With the merge option, dictionaries are interwoven and
// primitive entries are overwritten
//- Add a token entry void add(const entry&, bool mergeEntry=false);
void add(const word& keyword, const token&);
//- Add a word entry //- Add a word entry
void add(const word& keyword, const word&); // optionally overwrite an existing entry
void add(const word& keyword, const word&, bool overwrite=false);
//- Add a string entry //- Add a string entry
void add(const word& keyword, const string&); // optionally overwrite an existing entry
void add(const word& keyword, const string&, bool overwrite=false);
//- Add a label entry //- Add a label entry
void add(const word& keyword, const label); // optionally overwrite an existing entry
void add(const word& keyword, const label, bool overwrite=false);
//- Add a scalar entry //- Add a scalar entry
void add(const word& keyword, const scalar); // optionally overwrite an existing entry
void add (const word& keyword, const scalar, bool overwrite=false);
//- Add an entry constructed from a ITstream
void add(const word& keyword, const ITstream&);
//- Add an entry constructed from a tokenList
void add(const word& keyword, const tokenList& tokens);
//- Add a T entry
template<class T>
void add(const word& keyword, const T&);
//- Add a dictionary entry //- Add a dictionary entry
void add(const word& keyword, const dictionary&); // optionally merge with an existing sub-dictionary
void add
(
const word& keyword,
const dictionary&,
bool mergeEntry=false
);
//- Add a T entry
// optionally overwrite an existing entry
template<class T>
void add(const word& keyword, const T&, bool overwrite=false);
//- Assign a new entry, overwrite any existing entry
void set(entry*);
//- Assign a new entry, overwrite any existing entry
void set(const entry&);
//- Assign a dictionary entry, overwrite any existing entry
void set(const word& keyword, const dictionary&);
//- Assign a T entry, overwrite any existing entry
template<class T>
void set(const word& keyword, const T&);
//- Remove an entry specified by keyword //- Remove an entry specified by keyword
bool remove(const word& keyword); bool remove(const word& keyword);
@ -307,14 +330,12 @@ public:
// Global Operators // Global Operators
// Combine dictionaries starting from the entries in dict one and then including //- Combine dictionaries starting from the entries in dict1 and then including those from dict2.
// those from dict2. // Warn, but do not overwrite the entries from dict1.
// Warn, but do not overwrite the entries from dict1.
dictionary operator+(const dictionary& dict1, const dictionary& dict2); dictionary operator+(const dictionary& dict1, const dictionary& dict2);
// Combine dictionaries starting from the entries in dict one and then including //- Combine dictionaries starting from the entries in dict1 and then including those from dict2.
// those from dict2. // Do not overwrite the entries from dict1.
// Do not overwrite the entries from dict1.
dictionary operator|(const dictionary& dict1, const dictionary& dict2); dictionary operator|(const dictionary& dict1, const dictionary& dict2);

View File

@ -33,30 +33,34 @@ template<class T>
T Foam::dictionary::lookupOrDefault T Foam::dictionary::lookupOrDefault
( (
const word& keyword, const word& keyword,
const T& deft, const T& deflt,
bool recursive bool recursive
) const ) const
{ {
const entry* ePtr = lookupEntryPtr(keyword, recursive); const entry* entryPtr = lookupEntryPtr(keyword, recursive);
if (ePtr == NULL) if (entryPtr == NULL)
{ {
return deft; return deflt;
} }
else else
{ {
return pTraits<T>(ePtr->stream()); return pTraits<T>(entryPtr->stream());
} }
} }
template<class T> template<class T>
void Foam::dictionary::add(const word& keyword, const T& t) void Foam::dictionary::add(const word& k, const T& t, bool overwrite)
{ {
entry* ePtr = new primitiveEntry(keyword, t); add(new primitiveEntry(k, t), overwrite);
append(ePtr);
hashedEntries_.insert(ePtr->keyword(), ePtr);
} }
template<class T>
void Foam::dictionary::set(const word& k, const T& t)
{
set(new primitiveEntry(k, t));
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -59,6 +59,7 @@ Foam::label Foam::functionEntries::inputModeEntry::mode_ = imError;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// we could combine this into execute() directly, but leave it here for now
void Foam::functionEntries::inputModeEntry::setMode(Istream& is) void Foam::functionEntries::inputModeEntry::setMode(Istream& is)
{ {
clear(); clear();