1 /*---------------------------------------------------------------------------*\
3 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
5 \\ / A nd | Copyright held by original author
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 the
13 Free Software Foundation; either version 2 of the License, or (at your
14 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, write to the Free Software Foundation,
23 Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
25 \*---------------------------------------------------------------------------*/
27 #include "dictionary.H"
28 #include "primitiveEntry.H"
29 #include "dictionaryEntry.H"
31 #include "OSHA1stream.H"
33 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
35 defineTypeNameAndDebug(Foam::dictionary, 0);
37 const Foam::dictionary Foam::dictionary::null;
40 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
42 bool Foam::dictionary::findInPatterns
44 const bool patternMatch,
46 DLList<entry*>::const_iterator& wcLink,
47 DLList<autoPtr<regExp> >::const_iterator& reLink
50 if (patternEntries_.size())
52 while (wcLink != patternEntries_.end())
57 ? reLink()->match(Keyword)
58 : wcLink()->keyword() == Keyword
73 bool Foam::dictionary::findInPatterns
75 const bool patternMatch,
77 DLList<entry*>::iterator& wcLink,
78 DLList<autoPtr<regExp> >::iterator& reLink
81 if (patternEntries_.size())
83 while (wcLink != patternEntries_.end())
88 ? reLink()->match(Keyword)
89 : wcLink()->keyword() == Keyword
104 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
106 Foam::dictionary::dictionary()
108 parent_(dictionary::null)
112 Foam::dictionary::dictionary(const fileName& name)
114 dictionaryName(name),
115 parent_(dictionary::null)
119 Foam::dictionary::dictionary
121 const dictionary& parentDict,
122 const dictionary& dict
125 dictionaryName(dict.name()),
126 IDLList<entry>(dict, *this),
129 forAllIter(IDLList<entry>, *this, iter)
131 hashedEntries_.insert(iter().keyword(), &iter());
133 if (iter().keyword().isPattern())
135 patternEntries_.insert(&iter());
136 patternRegexps_.insert
138 autoPtr<regExp>(new regExp(iter().keyword()))
145 Foam::dictionary::dictionary
147 const dictionary& dict
150 dictionaryName(dict.name()),
151 IDLList<entry>(dict, *this),
152 parent_(dictionary::null)
154 forAllIter(IDLList<entry>, *this, iter)
156 hashedEntries_.insert(iter().keyword(), &iter());
158 if (iter().keyword().isPattern())
160 patternEntries_.insert(&iter());
161 patternRegexps_.insert
163 autoPtr<regExp>(new regExp(iter().keyword()))
170 Foam::dictionary::dictionary
172 const dictionary* dictPtr
175 parent_(dictionary::null)
184 Foam::dictionary::dictionary
186 const dictionary& parentDict,
187 const Xfer<dictionary>& dict
193 name() = parentDict.name() + "::" + name();
197 Foam::dictionary::dictionary
199 const Xfer<dictionary>& dict
202 parent_(dictionary::null)
208 Foam::autoPtr<Foam::dictionary> Foam::dictionary::clone() const
210 return autoPtr<dictionary>(new dictionary(*this));
214 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
216 Foam::dictionary::~dictionary()
218 // cerr<< "~dictionary() " << name() << " " << long(this) << std::endl;
222 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
224 Foam::label Foam::dictionary::startLineNumber() const
228 return first()->startLineNumber();
237 Foam::label Foam::dictionary::endLineNumber() const
241 return last()->endLineNumber();
250 Foam::SHA1Digest Foam::dictionary::digest() const
255 forAllConstIter(IDLList<entry>, *this, iter)
264 bool Foam::dictionary::found(const word& keyword, bool recursive) const
266 if (hashedEntries_.found(keyword))
272 if (patternEntries_.size())
274 DLList<entry*>::const_iterator wcLink =
275 patternEntries_.begin();
276 DLList<autoPtr<regExp> >::const_iterator reLink =
277 patternRegexps_.begin();
279 // Find in patterns using regular expressions only
280 if (findInPatterns(true, keyword, wcLink, reLink))
286 if (recursive && &parent_ != &dictionary::null)
288 return parent_.found(keyword, recursive);
298 const Foam::entry* Foam::dictionary::lookupEntryPtr
305 HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
307 if (iter == hashedEntries_.end())
309 if (patternMatch && patternEntries_.size())
311 DLList<entry*>::const_iterator wcLink =
312 patternEntries_.begin();
313 DLList<autoPtr<regExp> >::const_iterator reLink =
314 patternRegexps_.begin();
316 // Find in patterns using regular expressions only
317 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
323 if (recursive && &parent_ != &dictionary::null)
325 return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
337 Foam::entry* Foam::dictionary::lookupEntryPtr
344 HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
346 if (iter == hashedEntries_.end())
348 if (patternMatch && patternEntries_.size())
350 DLList<entry*>::iterator wcLink =
351 patternEntries_.begin();
352 DLList<autoPtr<regExp> >::iterator reLink =
353 patternRegexps_.begin();
355 // Find in patterns using regular expressions only
356 if (findInPatterns(patternMatch, keyword, wcLink, reLink))
362 if (recursive && &parent_ != &dictionary::null)
364 return const_cast<dictionary&>(parent_).lookupEntryPtr
381 const Foam::entry& Foam::dictionary::lookupEntry
388 const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
390 if (entryPtr == NULL)
394 "dictionary::lookupEntry(const word&, bool, bool) const",
396 ) << "keyword " << keyword << " is undefined in dictionary "
398 << exit(FatalIOError);
405 Foam::ITstream& Foam::dictionary::lookup
412 return lookupEntry(keyword, recursive, patternMatch).stream();
416 bool Foam::dictionary::isDict(const word& keyword) const
418 // Find non-recursive with patterns
419 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
423 return entryPtr->isDict();
432 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
434 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
438 return &entryPtr->dict();
447 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
449 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
451 if (entryPtr == NULL)
455 "dictionary::subDict(const word& keyword) const",
457 ) << "keyword " << keyword << " is undefined in dictionary "
459 << exit(FatalIOError);
461 return entryPtr->dict();
465 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
467 entry* entryPtr = lookupEntryPtr(keyword, false, true);
469 if (entryPtr == NULL)
473 "dictionary::subDict(const word& keyword)",
475 ) << "keyword " << keyword << " is undefined in dictionary "
477 << exit(FatalIOError);
479 return entryPtr->dict();
483 Foam::dictionary Foam::dictionary::subOrEmptyDict
488 const entry* entryPtr = lookupEntryPtr(keyword, false, true);
490 if (entryPtr == NULL)
492 return dictionary(*this, dictionary(name() + "::" + keyword));
496 return entryPtr->dict();
501 Foam::wordList Foam::dictionary::toc() const
503 wordList keys(size());
506 forAllConstIter(IDLList<entry>, *this, iter)
508 keys[nKeys++] = iter().keyword();
515 Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
517 List<keyType> keys(size());
520 forAllConstIter(IDLList<entry>, *this, iter)
522 if (iter().keyword().isPattern() ? patterns : !patterns)
524 keys[nKeys++] = iter().keyword();
533 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
535 HashTable<entry*>::iterator iter = hashedEntries_.find
540 if (mergeEntry && iter != hashedEntries_.end())
542 // merge dictionary with dictionary
543 if (iter()->isDict() && entryPtr->isDict())
545 iter()->dict().merge(entryPtr->dict());
552 // replace existing dictionary with entry or vice versa
553 IDLList<entry>::replace(iter(), entryPtr);
555 hashedEntries_.erase(iter);
557 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
559 entryPtr->name() = name() + "::" + entryPtr->keyword();
561 if (entryPtr->keyword().isPattern())
563 patternEntries_.insert(entryPtr);
564 patternRegexps_.insert
566 autoPtr<regExp>(new regExp(entryPtr->keyword()))
574 IOWarningIn("dictionary::add(entry*, bool)", (*this))
575 << "problem replacing entry "<< entryPtr->keyword()
576 << " in dictionary " << name() << endl;
578 IDLList<entry>::remove(entryPtr);
585 if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
587 entryPtr->name() = name() + "::" + entryPtr->keyword();
588 IDLList<entry>::append(entryPtr);
590 if (entryPtr->keyword().isPattern())
592 patternEntries_.insert(entryPtr);
593 patternRegexps_.insert
595 autoPtr<regExp>(new regExp(entryPtr->keyword()))
603 IOWarningIn("dictionary::add(entry*, bool)", (*this))
604 << "attempt to add entry "<< entryPtr->keyword()
605 << " which already exists in dictionary " << name()
614 void Foam::dictionary::add(const entry& e, bool mergeEntry)
616 add(e.clone(*this).ptr(), mergeEntry);
620 void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
622 add(new primitiveEntry(k, token(w)), overwrite);
626 void Foam::dictionary::add
629 const Foam::string& s,
633 add(new primitiveEntry(k, token(s)), overwrite);
637 void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
639 add(new primitiveEntry(k, token(l)), overwrite);
643 void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
645 add(new primitiveEntry(k, token(s)), overwrite);
649 void Foam::dictionary::add
656 add(new dictionaryEntry(k, *this, d), mergeEntry);
660 void Foam::dictionary::set(entry* entryPtr)
662 entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
664 // clear dictionary so merge acts like overwrite
665 if (existingPtr && existingPtr->isDict())
667 existingPtr->dict().clear();
673 void Foam::dictionary::set(const entry& e)
675 set(e.clone(*this).ptr());
679 void Foam::dictionary::set(const keyType& k, const dictionary& d)
681 set(new dictionaryEntry(k, *this, d));
685 bool Foam::dictionary::remove(const word& Keyword)
687 HashTable<entry*>::iterator iter = hashedEntries_.find(Keyword);
689 if (iter != hashedEntries_.end())
691 // Delete from patterns first
692 DLList<entry*>::iterator wcLink =
693 patternEntries_.begin();
694 DLList<autoPtr<regExp> >::iterator reLink =
695 patternRegexps_.begin();
697 // Find in pattern using exact match only
698 if (findInPatterns(false, Keyword, wcLink, reLink))
700 patternEntries_.remove(wcLink);
701 patternRegexps_.remove(reLink);
704 IDLList<entry>::remove(iter());
706 hashedEntries_.erase(iter);
717 bool Foam::dictionary::changeKeyword
719 const keyType& oldKeyword,
720 const keyType& newKeyword,
725 if (oldKeyword == newKeyword)
730 HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
732 // oldKeyword not found - do nothing
733 if (iter == hashedEntries_.end())
738 if (iter()->keyword().isPattern())
742 "dictionary::changeKeyword(const word&, const word&, bool)"
743 ) << "Old keyword "<< oldKeyword
745 << "Pattern replacement not yet implemented."
750 HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
752 // newKeyword already exists
753 if (iter2 != hashedEntries_.end())
757 if (iter2()->keyword().isPattern())
759 // Delete from patterns first
760 DLList<entry*>::iterator wcLink =
761 patternEntries_.begin();
762 DLList<autoPtr<regExp> >::iterator reLink =
763 patternRegexps_.begin();
765 // Find in patterns using exact match only
766 if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
768 patternEntries_.remove(wcLink);
769 patternRegexps_.remove(reLink);
773 IDLList<entry>::replace(iter2(), iter());
775 hashedEntries_.erase(iter2);
782 "dictionary::changeKeyword(const word&, const word&, bool)"
783 ) << "cannot rename keyword "<< oldKeyword
784 << " to existing keyword " << newKeyword
785 << " in dictionary " << name() << endl;
790 // change name and HashTable, but leave DL-List untouched
791 iter()->keyword() = newKeyword;
792 iter()->name() = name() + "::" + newKeyword;
793 hashedEntries_.erase(oldKeyword);
794 hashedEntries_.insert(newKeyword, iter());
796 if (newKeyword.isPattern())
798 patternEntries_.insert(iter());
799 patternRegexps_.insert
801 autoPtr<regExp>(new regExp(newKeyword))
809 bool Foam::dictionary::merge(const dictionary& dict)
811 // Check for assignment to self
814 FatalErrorIn("dictionary::merge(const dictionary&)")
815 << "attempted merge to self for dictionary " << name()
816 << abort(FatalError);
819 bool changed = false;
821 forAllConstIter(IDLList<entry>, dict, iter)
823 HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
825 if (fnd != hashedEntries_.end())
827 // Recursively merge sub-dictionaries
828 // TODO: merge without copying
829 if (fnd()->isDict() && iter().isDict())
831 if (fnd()->dict().merge(iter().dict()))
838 add(iter().clone(*this).ptr(), true);
844 // not found - just add
845 add(iter().clone(*this).ptr());
854 void Foam::dictionary::clear()
856 IDLList<entry>::clear();
857 hashedEntries_.clear();
858 patternEntries_.clear();
859 patternRegexps_.clear();
863 void Foam::dictionary::transfer(dictionary& dict)
865 // changing parents probably doesn't make much sense,
866 // but what about the names?
867 name() = dict.name();
869 IDLList<entry>::transfer(dict);
870 hashedEntries_.transfer(dict.hashedEntries_);
871 patternEntries_.transfer(dict.patternEntries_);
872 patternRegexps_.transfer(dict.patternRegexps_);
876 Foam::Xfer<Foam::dictionary> Foam::dictionary::xfer()
878 return xferMove(*this);
882 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
884 Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
886 return lookup(keyword);
890 void Foam::dictionary::operator=(const dictionary& rhs)
892 // Check for assignment to self
895 FatalErrorIn("dictionary::operator=(const dictionary&)")
896 << "attempted assignment to self for dictionary " << name()
897 << abort(FatalError);
903 // Create clones of the entries in the given dictionary
904 // resetting the parentDict to this dictionary
906 forAllConstIter(IDLList<entry>, rhs, iter)
908 add(iter().clone(*this).ptr());
913 void Foam::dictionary::operator+=(const dictionary& rhs)
915 // Check for assignment to self
918 FatalErrorIn("dictionary::operator+=(const dictionary&)")
919 << "attempted addition assignment to self for dictionary " << name()
920 << abort(FatalError);
923 forAllConstIter(IDLList<entry>, rhs, iter)
925 add(iter().clone(*this).ptr());
930 void Foam::dictionary::operator|=(const dictionary& rhs)
932 // Check for assignment to self
935 FatalErrorIn("dictionary::operator|=(const dictionary&)")
936 << "attempted assignment to self for dictionary " << name()
937 << abort(FatalError);
940 forAllConstIter(IDLList<entry>, rhs, iter)
942 if (!found(iter().keyword()))
944 add(iter().clone(*this).ptr());
950 void Foam::dictionary::operator<<=(const dictionary& rhs)
952 // Check for assignment to self
955 FatalErrorIn("dictionary::operator<<=(const dictionary&)")
956 << "attempted assignment to self for dictionary " << name()
957 << abort(FatalError);
960 forAllConstIter(IDLList<entry>, rhs, iter)
962 set(iter().clone(*this).ptr());
967 /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */
969 Foam::dictionary Foam::operator+
971 const dictionary& dict1,
972 const dictionary& dict2
975 dictionary sum(dict1);
981 Foam::dictionary Foam::operator|
983 const dictionary& dict1,
984 const dictionary& dict2
987 dictionary sum(dict1);
993 // ************************************************************************* //