1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | foam-extend: Open Source CFD
4 \\ / O peration | Version: 3.2
5 \\ / A nd | Web: http://www.foam-extend.org
6 \\/ M anipulation | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
9 This file is part of foam-extend.
11 foam-extend is free software: you can redistribute it and/or modify it
12 under the terms of the GNU General Public License as published by the
13 Free Software Foundation, either version 3 of the License, or (at your
14 option) any later version.
16 foam-extend is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with foam-extend. 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(const word& keyword, bool recursive) const
265 if (hashedEntries_.found(keyword))
271 if (patternEntries_.size())
273 DLList<entry*>::const_iterator wcLink =
274 patternEntries_.begin();
275 DLList<autoPtr<regExp> >::const_iterator reLink =
276 patternRegexps_.begin();
278 // Find in patterns using regular expressions only
279 if (findInPatterns(true, keyword, wcLink, reLink))
285 if (recursive && &parent_ != &dictionary::null)
287 return parent_.found(keyword, recursive);
297 const Foam::entry* Foam::dictionary::lookupEntryPtr
304 HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
306 if (iter == hashedEntries_.end())
308 if (patternMatch && patternEntries_.size())
310 DLList<entry*>::const_iterator wcLink =
311 patternEntries_.begin();
312 DLList<autoPtr<regExp> >::const_iterator reLink =
313 patternRegexps_.begin();
315 // Find in patterns using regular expressions only
316 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
322 if (recursive && &parent_ != &dictionary::null)
324 return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
336 Foam::entry* Foam::dictionary::lookupEntryPtr
343 HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
345 if (iter == hashedEntries_.end())
347 if (patternMatch && patternEntries_.size())
349 DLList<entry*>::iterator wcLink =
350 patternEntries_.begin();
351 DLList<autoPtr<regExp> >::iterator reLink =
352 patternRegexps_.begin();
354 // Find in patterns using regular expressions only
355 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
361 if (recursive && &parent_ != &dictionary::null)
363 return const_cast<dictionary&>(parent_).lookupEntryPtr
380 const Foam::entry& Foam::dictionary::lookupEntry
387 const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
389 if (entryPtr == NULL)
393 "dictionary::lookupEntry(const word&, bool, bool) const",
395 ) << "keyword " << keyword << " is undefined in dictionary "
397 << exit(FatalIOError);
404 Foam::ITstream& Foam::dictionary::lookup
411 return lookupEntry(keyword, recursive, patternMatch).stream();
415 bool Foam::dictionary::isDict(const word& keyword) const
417 // Find non-recursive with patterns
418 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
422 return entryPtr->isDict();
431 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
433 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
437 return &entryPtr->dict();
446 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
448 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
450 if (entryPtr == NULL)
454 "dictionary::subDict(const word& keyword) const",
456 ) << "keyword " << keyword << " is undefined in dictionary "
458 << exit(FatalIOError);
460 return entryPtr->dict();
464 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
466 entry* entryPtr = lookupEntryPtr(keyword, false, true);
468 if (entryPtr == NULL)
472 "dictionary::subDict(const word& keyword)",
474 ) << "keyword " << keyword << " is undefined in dictionary "
476 << exit(FatalIOError);
478 return entryPtr->dict();
482 Foam::dictionary Foam::dictionary::subOrEmptyDict
487 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
489 if (entryPtr == NULL)
491 return dictionary(*this, dictionary(name() + "::" + keyword));
495 return entryPtr->dict();
500 Foam::wordList Foam::dictionary::toc() const
502 wordList keys(size());
505 forAllConstIter(IDLList<entry>, *this, iter)
507 keys[nKeys++] = iter().keyword();
514 Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
516 List<keyType> keys(size());
519 forAllConstIter(IDLList<entry>, *this, iter)
521 if (iter().keyword().isPattern() ? patterns : !patterns)
523 keys[nKeys++] = iter().keyword();
532 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
534 HashTable<entry*>::iterator iter = hashedEntries_.find
539 if (mergeEntry && iter != hashedEntries_.end())
541 // merge dictionary with dictionary
542 if (iter()->isDict() && entryPtr->isDict())
544 iter()->dict().merge(entryPtr->dict());
551 // replace existing dictionary with entry or vice versa
552 IDLList<entry>::replace(iter(), entryPtr);
554 hashedEntries_.erase(iter);
556 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
558 entryPtr->name() = name() + "::" + entryPtr->keyword();
560 if (entryPtr->keyword().isPattern())
562 patternEntries_.insert(entryPtr);
563 patternRegexps_.insert
565 autoPtr<regExp>(new regExp(entryPtr->keyword()))
573 IOWarningIn("dictionary::add(entry*, bool)", (*this))
574 << "problem replacing entry "<< entryPtr->keyword()
575 << " in dictionary " << name() << endl;
577 IDLList<entry>::remove(entryPtr);
584 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
586 entryPtr->name() = name() + "::" + entryPtr->keyword();
587 IDLList<entry>::append(entryPtr);
589 if (entryPtr->keyword().isPattern())
591 patternEntries_.insert(entryPtr);
592 patternRegexps_.insert
594 autoPtr<regExp>(new regExp(entryPtr->keyword()))
602 IOWarningIn("dictionary::add(entry*, bool)", (*this))
603 << "attempt to add entry "<< entryPtr->keyword()
604 << " which already exists in dictionary " << name()
613 void Foam::dictionary::add(const entry& e, bool mergeEntry)
615 add(e.clone(*this).ptr(), mergeEntry);
619 void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
621 add(new primitiveEntry(k, token(w)), overwrite);
625 void Foam::dictionary::add
628 const Foam::string& s,
632 add(new primitiveEntry(k, token(s)), overwrite);
636 void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
638 add(new primitiveEntry(k, token(l)), overwrite);
642 void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
644 add(new primitiveEntry(k, token(s)), overwrite);
648 void Foam::dictionary::add
655 add(new dictionaryEntry(k, *this, d), mergeEntry);
659 void Foam::dictionary::set(entry* entryPtr)
661 entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
663 // clear dictionary so merge acts like overwrite
664 if (existingPtr && existingPtr->isDict())
666 existingPtr->dict().clear();
672 void Foam::dictionary::set(const entry& e)
674 set(e.clone(*this).ptr());
678 void Foam::dictionary::set(const keyType& k, const dictionary& d)
680 set(new dictionaryEntry(k, *this, d));
684 bool Foam::dictionary::remove(const word& Keyword)
686 HashTable<entry*>::iterator iter = hashedEntries_.find(Keyword);
688 if (iter != hashedEntries_.end())
690 // Delete from patterns first
691 DLList<entry*>::iterator wcLink =
692 patternEntries_.begin();
693 DLList<autoPtr<regExp> >::iterator reLink =
694 patternRegexps_.begin();
696 // Find in pattern using exact match only
697 if (findInPatterns(false, Keyword, wcLink, reLink))
699 patternEntries_.remove(wcLink);
700 patternRegexps_.remove(reLink);
703 IDLList<entry>::remove(iter());
705 hashedEntries_.erase(iter);
716 bool Foam::dictionary::changeKeyword
718 const keyType& oldKeyword,
719 const keyType& newKeyword,
724 if (oldKeyword == newKeyword)
729 HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
731 // oldKeyword not found - do nothing
732 if (iter == hashedEntries_.end())
737 if (iter()->keyword().isPattern())
741 "dictionary::changeKeyword(const word&, const word&, bool)"
742 ) << "Old keyword "<< oldKeyword
744 << "Pattern replacement not yet implemented."
749 HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
751 // newKeyword already exists
752 if (iter2 != hashedEntries_.end())
756 if (iter2()->keyword().isPattern())
758 // Delete from patterns first
759 DLList<entry*>::iterator wcLink =
760 patternEntries_.begin();
761 DLList<autoPtr<regExp> >::iterator reLink =
762 patternRegexps_.begin();
764 // Find in patterns using exact match only
765 if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
767 patternEntries_.remove(wcLink);
768 patternRegexps_.remove(reLink);
772 IDLList<entry>::replace(iter2(), iter());
774 hashedEntries_.erase(iter2);
781 "dictionary::changeKeyword(const word&, const word&, bool)"
782 ) << "cannot rename keyword "<< oldKeyword
783 << " to existing keyword " << newKeyword
784 << " in dictionary " << name() << endl;
789 // change name and HashTable, but leave DL-List untouched
790 iter()->keyword() = newKeyword;
791 iter()->name() = name() + "::" + newKeyword;
792 hashedEntries_.erase(oldKeyword);
793 hashedEntries_.insert(newKeyword, iter());
795 if (newKeyword.isPattern())
797 patternEntries_.insert(iter());
798 patternRegexps_.insert
800 autoPtr<regExp>(new regExp(newKeyword))
808 bool Foam::dictionary::merge(const dictionary& dict)
810 // Check for assignment to self
813 FatalErrorIn("dictionary::merge(const dictionary&)")
814 << "attempted merge to self for dictionary " << name()
815 << abort(FatalError);
818 bool changed = false;
820 forAllConstIter(IDLList<entry>, dict, iter)
822 HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
824 if (fnd != hashedEntries_.end())
826 // Recursively merge sub-dictionaries
827 // TODO: merge without copying
828 if (fnd()->isDict() && iter().isDict())
830 if (fnd()->dict().merge(iter().dict()))
837 add(iter().clone(*this).ptr(), true);
843 // not found - just add
844 add(iter().clone(*this).ptr());
853 void Foam::dictionary::clear()
855 IDLList<entry>::clear();
856 hashedEntries_.clear();
857 patternEntries_.clear();
858 patternRegexps_.clear();
862 void Foam::dictionary::transfer(dictionary& dict)
864 // changing parents probably doesn't make much sense,
865 // but what about the names?
866 name() = dict.name();
868 IDLList<entry>::transfer(dict);
869 hashedEntries_.transfer(dict.hashedEntries_);
870 patternEntries_.transfer(dict.patternEntries_);
871 patternRegexps_.transfer(dict.patternRegexps_);
875 Foam::Xfer<Foam::dictionary> Foam::dictionary::xfer()
877 return xferMove(*this);
881 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
883 Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
885 return lookup(keyword);
889 void Foam::dictionary::operator=(const dictionary& rhs)
891 // Check for assignment to self
894 FatalErrorIn("dictionary::operator=(const dictionary&)")
895 << "attempted assignment to self for dictionary " << name()
896 << abort(FatalError);
902 // Create clones of the entries in the given dictionary
903 // resetting the parentDict to this dictionary
905 forAllConstIter(IDLList<entry>, rhs, iter)
907 add(iter().clone(*this).ptr());
912 void Foam::dictionary::operator+=(const dictionary& rhs)
914 // Check for assignment to self
917 FatalErrorIn("dictionary::operator+=(const dictionary&)")
918 << "attempted addition assignment to self for dictionary " << name()
919 << abort(FatalError);
922 forAllConstIter(IDLList<entry>, rhs, iter)
924 add(iter().clone(*this).ptr());
929 void Foam::dictionary::operator|=(const dictionary& rhs)
931 // Check for assignment to self
934 FatalErrorIn("dictionary::operator|=(const dictionary&)")
935 << "attempted assignment to self for dictionary " << name()
936 << abort(FatalError);
939 forAllConstIter(IDLList<entry>, rhs, iter)
941 if (!found(iter().keyword()))
943 add(iter().clone(*this).ptr());
949 void Foam::dictionary::operator<<=(const dictionary& rhs)
951 // Check for assignment to self
954 FatalErrorIn("dictionary::operator<<=(const dictionary&)")
955 << "attempted assignment to self for dictionary " << name()
956 << abort(FatalError);
959 forAllConstIter(IDLList<entry>, rhs, iter)
961 set(iter().clone(*this).ptr());
966 /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */
968 Foam::dictionary Foam::operator+
970 const dictionary& dict1,
971 const dictionary& dict2
974 dictionary sum(dict1);
980 Foam::dictionary Foam::operator|
982 const dictionary& dict1,
983 const dictionary& dict2
986 dictionary sum(dict1);
992 // ************************************************************************* //