1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
7 -------------------------------------------------------------------------------
9 This file is part of OpenFOAM.
11 OpenFOAM is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by
13 the Free Software Foundation, either version 3 of the License, or
14 (at your option) any later version.
16 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
17 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 You should have received a copy of the GNU General Public License
22 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
24 \*---------------------------------------------------------------------------*/
26 #include "dictionary.H"
27 #include "primitiveEntry.H"
28 #include "dictionaryEntry.H"
30 #include "OSHA1stream.H"
32 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
34 defineTypeNameAndDebug(Foam::dictionary, 0);
36 const Foam::dictionary Foam::dictionary::null;
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
41 bool Foam::dictionary::findInPatterns
43 const bool patternMatch,
45 DLList<entry*>::const_iterator& wcLink,
46 DLList<autoPtr<regExp> >::const_iterator& reLink
49 if (patternEntries_.size())
51 while (wcLink != patternEntries_.end())
56 ? reLink()->match(Keyword)
57 : wcLink()->keyword() == Keyword
72 bool Foam::dictionary::findInPatterns
74 const bool patternMatch,
76 DLList<entry*>::iterator& wcLink,
77 DLList<autoPtr<regExp> >::iterator& reLink
80 if (patternEntries_.size())
82 while (wcLink != patternEntries_.end())
87 ? reLink()->match(Keyword)
88 : wcLink()->keyword() == Keyword
103 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
105 Foam::dictionary::dictionary()
107 parent_(dictionary::null)
111 Foam::dictionary::dictionary(const fileName& name)
113 dictionaryName(name),
114 parent_(dictionary::null)
118 Foam::dictionary::dictionary
120 const dictionary& parentDict,
121 const dictionary& dict
124 dictionaryName(dict.name()),
125 IDLList<entry>(dict, *this),
128 forAllIter(IDLList<entry>, *this, iter)
130 hashedEntries_.insert(iter().keyword(), &iter());
132 if (iter().keyword().isPattern())
134 patternEntries_.insert(&iter());
135 patternRegexps_.insert
137 autoPtr<regExp>(new regExp(iter().keyword()))
144 Foam::dictionary::dictionary
146 const dictionary& dict
149 dictionaryName(dict.name()),
150 IDLList<entry>(dict, *this),
151 parent_(dictionary::null)
153 forAllIter(IDLList<entry>, *this, iter)
155 hashedEntries_.insert(iter().keyword(), &iter());
157 if (iter().keyword().isPattern())
159 patternEntries_.insert(&iter());
160 patternRegexps_.insert
162 autoPtr<regExp>(new regExp(iter().keyword()))
169 Foam::dictionary::dictionary
171 const dictionary* dictPtr
174 parent_(dictionary::null)
183 Foam::dictionary::dictionary
185 const dictionary& parentDict,
186 const Xfer<dictionary>& dict
192 name() = parentDict.name() + "::" + name();
196 Foam::dictionary::dictionary
198 const Xfer<dictionary>& dict
201 parent_(dictionary::null)
207 Foam::autoPtr<Foam::dictionary> Foam::dictionary::clone() const
209 return autoPtr<dictionary>(new dictionary(*this));
213 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
215 Foam::dictionary::~dictionary()
217 // cerr<< "~dictionary() " << name() << " " << long(this) << std::endl;
221 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
223 Foam::label Foam::dictionary::startLineNumber() const
227 return first()->startLineNumber();
236 Foam::label Foam::dictionary::endLineNumber() const
240 return last()->endLineNumber();
249 Foam::SHA1Digest Foam::dictionary::digest() const
254 forAllConstIter(IDLList<entry>, *this, iter)
263 bool Foam::dictionary::found
270 if (hashedEntries_.found(keyword))
276 if (patternMatch && patternEntries_.size())
278 DLList<entry*>::const_iterator wcLink =
279 patternEntries_.begin();
280 DLList<autoPtr<regExp> >::const_iterator reLink =
281 patternRegexps_.begin();
283 // Find in patterns using regular expressions only
284 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
290 if (recursive && &parent_ != &dictionary::null)
292 return parent_.found(keyword, recursive, patternMatch);
302 const Foam::entry* Foam::dictionary::lookupEntryPtr
309 HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
311 if (iter == hashedEntries_.end())
313 if (patternMatch && patternEntries_.size())
315 DLList<entry*>::const_iterator wcLink =
316 patternEntries_.begin();
317 DLList<autoPtr<regExp> >::const_iterator reLink =
318 patternRegexps_.begin();
320 // Find in patterns using regular expressions only
321 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
327 if (recursive && &parent_ != &dictionary::null)
329 return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
341 Foam::entry* Foam::dictionary::lookupEntryPtr
348 HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
350 if (iter == hashedEntries_.end())
352 if (patternMatch && patternEntries_.size())
354 DLList<entry*>::iterator wcLink =
355 patternEntries_.begin();
356 DLList<autoPtr<regExp> >::iterator reLink =
357 patternRegexps_.begin();
359 // Find in patterns using regular expressions only
360 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
366 if (recursive && &parent_ != &dictionary::null)
368 return const_cast<dictionary&>(parent_).lookupEntryPtr
385 const Foam::entry& Foam::dictionary::lookupEntry
392 const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
394 if (entryPtr == NULL)
398 "dictionary::lookupEntry(const word&, bool, bool) const",
400 ) << "keyword " << keyword << " is undefined in dictionary "
402 << exit(FatalIOError);
409 Foam::ITstream& Foam::dictionary::lookup
416 return lookupEntry(keyword, recursive, patternMatch).stream();
420 bool Foam::dictionary::isDict(const word& keyword) const
422 // Find non-recursive with patterns
423 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
427 return entryPtr->isDict();
436 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
438 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
442 return &entryPtr->dict();
451 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
453 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
455 if (entryPtr == NULL)
459 "dictionary::subDict(const word& keyword) const",
461 ) << "keyword " << keyword << " is undefined in dictionary "
463 << exit(FatalIOError);
465 return entryPtr->dict();
469 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
471 entry* entryPtr = lookupEntryPtr(keyword, false, true);
473 if (entryPtr == NULL)
477 "dictionary::subDict(const word& keyword)",
479 ) << "keyword " << keyword << " is undefined in dictionary "
481 << exit(FatalIOError);
483 return entryPtr->dict();
487 Foam::dictionary Foam::dictionary::subOrEmptyDict
493 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
495 if (entryPtr == NULL)
501 "dictionary::subOrEmptyDict(const word& keyword, const bool)",
503 ) << "keyword " << keyword << " is undefined in dictionary "
505 << exit(FatalIOError);
506 return entryPtr->dict();
510 return dictionary(*this, dictionary(name() + "::" + keyword));
515 return entryPtr->dict();
520 Foam::wordList Foam::dictionary::toc() const
522 wordList keys(size());
525 forAllConstIter(IDLList<entry>, *this, iter)
527 keys[nKeys++] = iter().keyword();
534 Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
536 List<keyType> keys(size());
539 forAllConstIter(IDLList<entry>, *this, iter)
541 if (iter().keyword().isPattern() ? patterns : !patterns)
543 keys[nKeys++] = iter().keyword();
552 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
554 HashTable<entry*>::iterator iter = hashedEntries_.find
559 if (mergeEntry && iter != hashedEntries_.end())
561 // merge dictionary with dictionary
562 if (iter()->isDict() && entryPtr->isDict())
564 iter()->dict().merge(entryPtr->dict());
571 // replace existing dictionary with entry or vice versa
572 IDLList<entry>::replace(iter(), entryPtr);
574 hashedEntries_.erase(iter);
576 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
578 entryPtr->name() = name() + "::" + entryPtr->keyword();
580 if (entryPtr->keyword().isPattern())
582 patternEntries_.insert(entryPtr);
583 patternRegexps_.insert
585 autoPtr<regExp>(new regExp(entryPtr->keyword()))
593 IOWarningIn("dictionary::add(entry*, bool)", (*this))
594 << "problem replacing entry "<< entryPtr->keyword()
595 << " in dictionary " << name() << endl;
597 IDLList<entry>::remove(entryPtr);
604 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
606 entryPtr->name() = name() + "::" + entryPtr->keyword();
607 IDLList<entry>::append(entryPtr);
609 if (entryPtr->keyword().isPattern())
611 patternEntries_.insert(entryPtr);
612 patternRegexps_.insert
614 autoPtr<regExp>(new regExp(entryPtr->keyword()))
622 IOWarningIn("dictionary::add(entry*, bool)", (*this))
623 << "attempt to add entry "<< entryPtr->keyword()
624 << " which already exists in dictionary " << name()
633 void Foam::dictionary::add(const entry& e, bool mergeEntry)
635 add(e.clone(*this).ptr(), mergeEntry);
639 void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
641 add(new primitiveEntry(k, token(w)), overwrite);
645 void Foam::dictionary::add
648 const Foam::string& s,
652 add(new primitiveEntry(k, token(s)), overwrite);
656 void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
658 add(new primitiveEntry(k, token(l)), overwrite);
662 void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
664 add(new primitiveEntry(k, token(s)), overwrite);
668 void Foam::dictionary::add
675 add(new dictionaryEntry(k, *this, d), mergeEntry);
679 void Foam::dictionary::set(entry* entryPtr)
681 entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
683 // clear dictionary so merge acts like overwrite
684 if (existingPtr && existingPtr->isDict())
686 existingPtr->dict().clear();
692 void Foam::dictionary::set(const entry& e)
694 set(e.clone(*this).ptr());
698 void Foam::dictionary::set(const keyType& k, const dictionary& d)
700 set(new dictionaryEntry(k, *this, d));
704 bool Foam::dictionary::remove(const word& Keyword)
706 HashTable<entry*>::iterator iter = hashedEntries_.find(Keyword);
708 if (iter != hashedEntries_.end())
710 // Delete from patterns first
711 DLList<entry*>::iterator wcLink =
712 patternEntries_.begin();
713 DLList<autoPtr<regExp> >::iterator reLink =
714 patternRegexps_.begin();
716 // Find in pattern using exact match only
717 if (findInPatterns(false, Keyword, wcLink, reLink))
719 patternEntries_.remove(wcLink);
720 patternRegexps_.remove(reLink);
723 IDLList<entry>::remove(iter());
725 hashedEntries_.erase(iter);
736 bool Foam::dictionary::changeKeyword
738 const keyType& oldKeyword,
739 const keyType& newKeyword,
744 if (oldKeyword == newKeyword)
749 HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
751 // oldKeyword not found - do nothing
752 if (iter == hashedEntries_.end())
757 if (iter()->keyword().isPattern())
761 "dictionary::changeKeyword(const word&, const word&, bool)",
763 ) << "Old keyword "<< oldKeyword
765 << "Pattern replacement not yet implemented."
766 << exit(FatalIOError);
770 HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
772 // newKeyword already exists
773 if (iter2 != hashedEntries_.end())
777 if (iter2()->keyword().isPattern())
779 // Delete from patterns first
780 DLList<entry*>::iterator wcLink =
781 patternEntries_.begin();
782 DLList<autoPtr<regExp> >::iterator reLink =
783 patternRegexps_.begin();
785 // Find in patterns using exact match only
786 if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
788 patternEntries_.remove(wcLink);
789 patternRegexps_.remove(reLink);
793 IDLList<entry>::replace(iter2(), iter());
795 hashedEntries_.erase(iter2);
802 "dictionary::changeKeyword(const word&, const word&, bool)",
804 ) << "cannot rename keyword "<< oldKeyword
805 << " to existing keyword " << newKeyword
806 << " in dictionary " << name() << endl;
811 // change name and HashTable, but leave DL-List untouched
812 iter()->keyword() = newKeyword;
813 iter()->name() = name() + "::" + newKeyword;
814 hashedEntries_.erase(oldKeyword);
815 hashedEntries_.insert(newKeyword, iter());
817 if (newKeyword.isPattern())
819 patternEntries_.insert(iter());
820 patternRegexps_.insert
822 autoPtr<regExp>(new regExp(newKeyword))
830 bool Foam::dictionary::merge(const dictionary& dict)
832 // Check for assignment to self
835 FatalIOErrorIn("dictionary::merge(const dictionary&)", *this)
836 << "attempted merge to self for dictionary " << name()
837 << abort(FatalIOError);
840 bool changed = false;
842 forAllConstIter(IDLList<entry>, dict, iter)
844 HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
846 if (fnd != hashedEntries_.end())
848 // Recursively merge sub-dictionaries
849 // TODO: merge without copying
850 if (fnd()->isDict() && iter().isDict())
852 if (fnd()->dict().merge(iter().dict()))
859 add(iter().clone(*this).ptr(), true);
865 // not found - just add
866 add(iter().clone(*this).ptr());
875 void Foam::dictionary::clear()
877 IDLList<entry>::clear();
878 hashedEntries_.clear();
879 patternEntries_.clear();
880 patternRegexps_.clear();
884 void Foam::dictionary::transfer(dictionary& dict)
886 // changing parents probably doesn't make much sense,
887 // but what about the names?
888 name() = dict.name();
890 IDLList<entry>::transfer(dict);
891 hashedEntries_.transfer(dict.hashedEntries_);
892 patternEntries_.transfer(dict.patternEntries_);
893 patternRegexps_.transfer(dict.patternRegexps_);
897 Foam::Xfer<Foam::dictionary> Foam::dictionary::xfer()
899 return xferMove(*this);
903 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
905 Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
907 return lookup(keyword);
911 void Foam::dictionary::operator=(const dictionary& rhs)
913 // Check for assignment to self
916 FatalIOErrorIn("dictionary::operator=(const dictionary&)", *this)
917 << "attempted assignment to self for dictionary " << name()
918 << abort(FatalIOError);
924 // Create clones of the entries in the given dictionary
925 // resetting the parentDict to this dictionary
927 forAllConstIter(IDLList<entry>, rhs, iter)
929 add(iter().clone(*this).ptr());
934 void Foam::dictionary::operator+=(const dictionary& rhs)
936 // Check for assignment to self
939 FatalIOErrorIn("dictionary::operator+=(const dictionary&)", *this)
940 << "attempted addition assignment to self for dictionary " << name()
941 << abort(FatalIOError);
944 forAllConstIter(IDLList<entry>, rhs, iter)
946 add(iter().clone(*this).ptr());
951 void Foam::dictionary::operator|=(const dictionary& rhs)
953 // Check for assignment to self
956 FatalIOErrorIn("dictionary::operator|=(const dictionary&)", *this)
957 << "attempted assignment to self for dictionary " << name()
958 << abort(FatalIOError);
961 forAllConstIter(IDLList<entry>, rhs, iter)
963 if (!found(iter().keyword()))
965 add(iter().clone(*this).ptr());
971 void Foam::dictionary::operator<<=(const dictionary& rhs)
973 // Check for assignment to self
976 FatalIOErrorIn("dictionary::operator<<=(const dictionary&)", *this)
977 << "attempted assignment to self for dictionary " << name()
978 << abort(FatalIOError);
981 forAllConstIter(IDLList<entry>, rhs, iter)
983 set(iter().clone(*this).ptr());
988 /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */
990 Foam::dictionary Foam::operator+
992 const dictionary& dict1,
993 const dictionary& dict2
996 dictionary sum(dict1);
1002 Foam::dictionary Foam::operator|
1004 const dictionary& dict1,
1005 const dictionary& dict2
1008 dictionary sum(dict1);
1014 // ************************************************************************* //