fixed writing out entries in advective bc
[OpenFOAM-1.6-ext.git] / src / OpenFOAM / db / dictionary / dictionary.C
blob494278ce07fcb3a8192da13c0390845f912fadbc
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright held by original author
6      \\/     M anipulation  |
7 -------------------------------------------------------------------------------
8 License
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
19     for more details.
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"
30 #include "regExp.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,
45     const word& Keyword,
46     DLList<entry*>::const_iterator& wcLink,
47     DLList<autoPtr<regExp> >::const_iterator& reLink
48 ) const
50     if (patternEntries_.size())
51     {
52         while (wcLink != patternEntries_.end())
53         {
54             if
55             (
56                 patternMatch
57               ? reLink()->match(Keyword)
58               : wcLink()->keyword() == Keyword
59             )
60             {
61                 return true;
62             }
64             ++reLink;
65             ++wcLink;
66         }
67     }
69     return false;
73 bool Foam::dictionary::findInPatterns
75     const bool patternMatch,
76     const word& Keyword,
77     DLList<entry*>::iterator& wcLink,
78     DLList<autoPtr<regExp> >::iterator& reLink
81     if (patternEntries_.size())
82     {
83         while (wcLink != patternEntries_.end())
84         {
85             if
86             (
87                 patternMatch
88               ? reLink()->match(Keyword)
89               : wcLink()->keyword() == Keyword
90             )
91             {
92                 return true;
93             }
95             ++reLink;
96             ++wcLink;
97         }
98     }
100     return false;
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),
127     parent_(parentDict)
129     forAllIter(IDLList<entry>, *this, iter)
130     {
131         hashedEntries_.insert(iter().keyword(), &iter());
133         if (iter().keyword().isPattern())
134         {
135             patternEntries_.insert(&iter());
136             patternRegexps_.insert
137             (
138                 autoPtr<regExp>(new regExp(iter().keyword()))
139             );
140         }
141     }
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)
155     {
156         hashedEntries_.insert(iter().keyword(), &iter());
158         if (iter().keyword().isPattern())
159         {
160             patternEntries_.insert(&iter());
161             patternRegexps_.insert
162             (
163                 autoPtr<regExp>(new regExp(iter().keyword()))
164             );
165         }
166     }
170 Foam::dictionary::dictionary
172     const dictionary* dictPtr
175     parent_(dictionary::null)
177     if (dictPtr)
178     {
179         operator=(*dictPtr);
180     }
184 Foam::dictionary::dictionary
186     const dictionary& parentDict,
187     const Xfer<dictionary>& dict
190     parent_(parentDict)
192     transfer(dict());
193     name() = parentDict.name() + "::" + name();
197 Foam::dictionary::dictionary
199     const Xfer<dictionary>& dict
202     parent_(dictionary::null)
204     transfer(dict());
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
226     if (size())
227     {
228         return first()->startLineNumber();
229     }
230     else
231     {
232         return -1;
233     }
237 Foam::label Foam::dictionary::endLineNumber() const
239     if (size())
240     {
241         return last()->endLineNumber();
242     }
243     else
244     {
245         return -1;
246     }
250 Foam::SHA1Digest Foam::dictionary::digest() const
252     OSHA1stream os;
254     // process entries
255     forAllConstIter(IDLList<entry>, *this, iter)
256     {
257         os << *iter;
258     }
260     return os.digest();
264 bool Foam::dictionary::found(const word& keyword, bool recursive) const
266     if (hashedEntries_.found(keyword))
267     {
268         return true;
269     }
270     else
271     {
272         if (patternEntries_.size())
273         {
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))
281             {
282                 return true;
283             }
284         }
286         if (recursive && &parent_ != &dictionary::null)
287         {
288             return parent_.found(keyword, recursive);
289         }
290         else
291         {
292             return false;
293         }
294     }
298 const Foam::entry* Foam::dictionary::lookupEntryPtr
300     const word& keyword,
301     bool recursive,
302     bool patternMatch
303 ) const
305     HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
307     if (iter == hashedEntries_.end())
308     {
309         if (patternMatch && patternEntries_.size())
310         {
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))
318             {
319                 return wcLink();
320             }
321         }
323         if (recursive && &parent_ != &dictionary::null)
324         {
325             return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
326         }
327         else
328         {
329             return NULL;
330         }
331     }
333     return iter();
337 Foam::entry* Foam::dictionary::lookupEntryPtr
339     const word& keyword,
340     bool recursive,
341     bool patternMatch
344     HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
346     if (iter == hashedEntries_.end())
347     {
348         if (patternMatch && patternEntries_.size())
349         {
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))
357             {
358                 return wcLink();
359             }
360         }
362         if (recursive && &parent_ != &dictionary::null)
363         {
364             return const_cast<dictionary&>(parent_).lookupEntryPtr
365             (
366                 keyword,
367                 recursive,
368                 patternMatch
369             );
370         }
371         else
372         {
373             return NULL;
374         }
375     }
377     return iter();
381 const Foam::entry& Foam::dictionary::lookupEntry
383     const word& keyword,
384     bool recursive,
385     bool patternMatch
386 ) const
388     const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
390     if (entryPtr == NULL)
391     {
392         FatalIOErrorIn
393         (
394             "dictionary::lookupEntry(const word&, bool, bool) const",
395             *this
396         )   << "keyword " << keyword << " is undefined in dictionary "
397             << name()
398             << exit(FatalIOError);
399     }
401     return *entryPtr;
405 Foam::ITstream& Foam::dictionary::lookup
407     const word& keyword,
408     bool recursive,
409     bool patternMatch
410 ) const
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);
421     if (entryPtr)
422     {
423         return entryPtr->isDict();
424     }
425     else
426     {
427         return false;
428     }
432 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
434     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
436     if (entryPtr)
437     {
438         return &entryPtr->dict();
439     }
440     else
441     {
442         return NULL;
443     }
447 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
449     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
451     if (entryPtr == NULL)
452     {
453         FatalIOErrorIn
454         (
455             "dictionary::subDict(const word& keyword) const",
456             *this
457         )   << "keyword " << keyword << " is undefined in dictionary "
458             << name()
459             << exit(FatalIOError);
460     }
461     return entryPtr->dict();
465 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
467     entry* entryPtr = lookupEntryPtr(keyword, false, true);
469     if (entryPtr == NULL)
470     {
471         FatalIOErrorIn
472         (
473             "dictionary::subDict(const word& keyword)",
474             *this
475         )   << "keyword " << keyword << " is undefined in dictionary "
476             << name()
477             << exit(FatalIOError);
478     }
479     return entryPtr->dict();
483 Foam::dictionary Foam::dictionary::subOrEmptyDict
485     const word& keyword
486 ) const
488     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
490     if (entryPtr == NULL)
491     {
492         return dictionary(*this, dictionary(name() + "::" + keyword));
493     }
494     else
495     {
496         return entryPtr->dict();
497     }
501 Foam::wordList Foam::dictionary::toc() const
503     wordList keys(size());
505     label nKeys = 0;
506     forAllConstIter(IDLList<entry>, *this, iter)
507     {
508         keys[nKeys++] = iter().keyword();
509     }
511     return keys;
515 Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
517     List<keyType> keys(size());
519     label nKeys = 0;
520     forAllConstIter(IDLList<entry>, *this, iter)
521     {
522         if (iter().keyword().isPattern() ? patterns : !patterns)
523         {
524             keys[nKeys++] = iter().keyword();
525         }
526     }
527     keys.setSize(nKeys);
529     return keys;
533 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
535     HashTable<entry*>::iterator iter = hashedEntries_.find
536     (
537         entryPtr->keyword()
538     );
540     if (mergeEntry && iter != hashedEntries_.end())
541     {
542         // merge dictionary with dictionary
543         if (iter()->isDict() && entryPtr->isDict())
544         {
545             iter()->dict().merge(entryPtr->dict());
546             delete entryPtr;
548             return true;
549         }
550         else
551         {
552             // replace existing dictionary with entry or vice versa
553             IDLList<entry>::replace(iter(), entryPtr);
554             delete iter();
555             hashedEntries_.erase(iter);
557             if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
558             {
559                 entryPtr->name() = name() + "::" + entryPtr->keyword();
561                 if (entryPtr->keyword().isPattern())
562                 {
563                     patternEntries_.insert(entryPtr);
564                     patternRegexps_.insert
565                     (
566                         autoPtr<regExp>(new regExp(entryPtr->keyword()))
567                     );
568                 }
570                 return true;
571             }
572             else
573             {
574                 IOWarningIn("dictionary::add(entry*, bool)", (*this))
575                     << "problem replacing entry "<< entryPtr->keyword()
576                     << " in dictionary " << name() << endl;
578                 IDLList<entry>::remove(entryPtr);
579                 delete entryPtr;
580                 return false;
581             }
582         }
583     }
585     if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
586     {
587         entryPtr->name() = name() + "::" + entryPtr->keyword();
588         IDLList<entry>::append(entryPtr);
590         if (entryPtr->keyword().isPattern())
591         {
592             patternEntries_.insert(entryPtr);
593             patternRegexps_.insert
594             (
595                 autoPtr<regExp>(new regExp(entryPtr->keyword()))
596             );
597         }
599         return true;
600     }
601     else
602     {
603         IOWarningIn("dictionary::add(entry*, bool)", (*this))
604             << "attempt to add entry "<< entryPtr->keyword()
605             << " which already exists in dictionary " << name()
606             << endl;
608         delete entryPtr;
609         return false;
610     }
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
628     const keyType& k,
629     const Foam::string& s,
630     bool overwrite
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
651     const keyType& k,
652     const dictionary& d,
653     bool mergeEntry
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())
666     {
667         existingPtr->dict().clear();
668     }
669     add(entryPtr, true);
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())
690     {
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))
699         {
700             patternEntries_.remove(wcLink);
701             patternRegexps_.remove(reLink);
702         }
704         IDLList<entry>::remove(iter());
705         delete iter();
706         hashedEntries_.erase(iter);
708         return true;
709     }
710     else
711     {
712         return false;
713     }
717 bool Foam::dictionary::changeKeyword
719     const keyType& oldKeyword,
720     const keyType& newKeyword,
721     bool forceOverwrite
724     // no change
725     if (oldKeyword == newKeyword)
726     {
727         return false;
728     }
730     HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
732     // oldKeyword not found - do nothing
733     if (iter == hashedEntries_.end())
734     {
735         return false;
736     }
738     if (iter()->keyword().isPattern())
739     {
740         FatalErrorIn
741         (
742             "dictionary::changeKeyword(const word&, const word&, bool)"
743         )   << "Old keyword "<< oldKeyword
744             << " is a pattern."
745             << "Pattern replacement not yet implemented."
746             << exit(FatalError);
747     }
750     HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
752     // newKeyword already exists
753     if (iter2 != hashedEntries_.end())
754     {
755         if (forceOverwrite)
756         {
757             if (iter2()->keyword().isPattern())
758             {
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))
767                 {
768                     patternEntries_.remove(wcLink);
769                     patternRegexps_.remove(reLink);
770                 }
771             }
773             IDLList<entry>::replace(iter2(), iter());
774             delete iter2();
775             hashedEntries_.erase(iter2);
777         }
778         else
779         {
780             WarningIn
781             (
782                 "dictionary::changeKeyword(const word&, const word&, bool)"
783             )   << "cannot rename keyword "<< oldKeyword
784                 << " to existing keyword " << newKeyword
785                 << " in dictionary " << name() << endl;
786             return false;
787         }
788     }
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())
797     {
798         patternEntries_.insert(iter());
799         patternRegexps_.insert
800         (
801             autoPtr<regExp>(new regExp(newKeyword))
802         );
803     }
805     return true;
809 bool Foam::dictionary::merge(const dictionary& dict)
811     // Check for assignment to self
812     if (this == &dict)
813     {
814         FatalErrorIn("dictionary::merge(const dictionary&)")
815             << "attempted merge to self for dictionary " << name()
816             << abort(FatalError);
817     }
819     bool changed = false;
821     forAllConstIter(IDLList<entry>, dict, iter)
822     {
823         HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
825         if (fnd != hashedEntries_.end())
826         {
827             // Recursively merge sub-dictionaries
828             // TODO: merge without copying
829             if (fnd()->isDict() && iter().isDict())
830             {
831                 if (fnd()->dict().merge(iter().dict()))
832                 {
833                     changed = true;
834                 }
835             }
836             else
837             {
838                 add(iter().clone(*this).ptr(), true);
839                 changed = true;
840             }
841         }
842         else
843         {
844             // not found - just add
845             add(iter().clone(*this).ptr());
846             changed = true;
847         }
848     }
850     return changed;
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
893     if (this == &rhs)
894     {
895         FatalErrorIn("dictionary::operator=(const dictionary&)")
896             << "attempted assignment to self for dictionary " << name()
897             << abort(FatalError);
898     }
900     name() = rhs.name();
901     clear();
903     // Create clones of the entries in the given dictionary
904     // resetting the parentDict to this dictionary
906     forAllConstIter(IDLList<entry>, rhs, iter)
907     {
908         add(iter().clone(*this).ptr());
909     }
913 void Foam::dictionary::operator+=(const dictionary& rhs)
915     // Check for assignment to self
916     if (this == &rhs)
917     {
918         FatalErrorIn("dictionary::operator+=(const dictionary&)")
919             << "attempted addition assignment to self for dictionary " << name()
920             << abort(FatalError);
921     }
923     forAllConstIter(IDLList<entry>, rhs, iter)
924     {
925         add(iter().clone(*this).ptr());
926     }
930 void Foam::dictionary::operator|=(const dictionary& rhs)
932     // Check for assignment to self
933     if (this == &rhs)
934     {
935         FatalErrorIn("dictionary::operator|=(const dictionary&)")
936             << "attempted assignment to self for dictionary " << name()
937             << abort(FatalError);
938     }
940     forAllConstIter(IDLList<entry>, rhs, iter)
941     {
942         if (!found(iter().keyword()))
943         {
944             add(iter().clone(*this).ptr());
945         }
946     }
950 void Foam::dictionary::operator<<=(const dictionary& rhs)
952     // Check for assignment to self
953     if (this == &rhs)
954     {
955         FatalErrorIn("dictionary::operator<<=(const dictionary&)")
956             << "attempted assignment to self for dictionary " << name()
957             << abort(FatalError);
958     }
960     forAllConstIter(IDLList<entry>, rhs, iter)
961     {
962         set(iter().clone(*this).ptr());
963     }
967 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
969 Foam::dictionary Foam::operator+
971     const dictionary& dict1,
972     const dictionary& dict2
975     dictionary sum(dict1);
976     sum += dict2;
977     return sum;
981 Foam::dictionary Foam::operator|
983     const dictionary& dict1,
984     const dictionary& dict2
987     dictionary sum(dict1);
988     sum |= dict2;
989     return sum;
993 // ************************************************************************* //