BUG: UListIO: byteSize overflowing on really big faceLists
[OpenFOAM-2.0.x.git] / src / OpenFOAM / db / dictionary / dictionary.C
bloba405d153dd7630cbbf37beed26e29ab587ef22e8
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 2011 OpenFOAM Foundation
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
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
19     for more details.
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"
29 #include "regExp.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,
44     const word& Keyword,
45     DLList<entry*>::const_iterator& wcLink,
46     DLList<autoPtr<regExp> >::const_iterator& reLink
47 ) const
49     if (patternEntries_.size())
50     {
51         while (wcLink != patternEntries_.end())
52         {
53             if
54             (
55                 patternMatch
56               ? reLink()->match(Keyword)
57               : wcLink()->keyword() == Keyword
58             )
59             {
60                 return true;
61             }
63             ++reLink;
64             ++wcLink;
65         }
66     }
68     return false;
72 bool Foam::dictionary::findInPatterns
74     const bool patternMatch,
75     const word& Keyword,
76     DLList<entry*>::iterator& wcLink,
77     DLList<autoPtr<regExp> >::iterator& reLink
80     if (patternEntries_.size())
81     {
82         while (wcLink != patternEntries_.end())
83         {
84             if
85             (
86                 patternMatch
87               ? reLink()->match(Keyword)
88               : wcLink()->keyword() == Keyword
89             )
90             {
91                 return true;
92             }
94             ++reLink;
95             ++wcLink;
96         }
97     }
99     return false;
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),
126     parent_(parentDict)
128     forAllIter(IDLList<entry>, *this, iter)
129     {
130         hashedEntries_.insert(iter().keyword(), &iter());
132         if (iter().keyword().isPattern())
133         {
134             patternEntries_.insert(&iter());
135             patternRegexps_.insert
136             (
137                 autoPtr<regExp>(new regExp(iter().keyword()))
138             );
139         }
140     }
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)
154     {
155         hashedEntries_.insert(iter().keyword(), &iter());
157         if (iter().keyword().isPattern())
158         {
159             patternEntries_.insert(&iter());
160             patternRegexps_.insert
161             (
162                 autoPtr<regExp>(new regExp(iter().keyword()))
163             );
164         }
165     }
169 Foam::dictionary::dictionary
171     const dictionary* dictPtr
174     parent_(dictionary::null)
176     if (dictPtr)
177     {
178         operator=(*dictPtr);
179     }
183 Foam::dictionary::dictionary
185     const dictionary& parentDict,
186     const Xfer<dictionary>& dict
189     parent_(parentDict)
191     transfer(dict());
192     name() = parentDict.name() + "::" + name();
196 Foam::dictionary::dictionary
198     const Xfer<dictionary>& dict
201     parent_(dictionary::null)
203     transfer(dict());
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
225     if (size())
226     {
227         return first()->startLineNumber();
228     }
229     else
230     {
231         return -1;
232     }
236 Foam::label Foam::dictionary::endLineNumber() const
238     if (size())
239     {
240         return last()->endLineNumber();
241     }
242     else
243     {
244         return -1;
245     }
249 Foam::SHA1Digest Foam::dictionary::digest() const
251     OSHA1stream os;
253     // process entries
254     forAllConstIter(IDLList<entry>, *this, iter)
255     {
256         os << *iter;
257     }
259     return os.digest();
263 bool Foam::dictionary::found
265     const word& keyword,
266     bool recursive,
267     bool patternMatch
268 ) const
270     if (hashedEntries_.found(keyword))
271     {
272         return true;
273     }
274     else
275     {
276         if (patternMatch && patternEntries_.size())
277         {
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))
285             {
286                 return true;
287             }
288         }
290         if (recursive && &parent_ != &dictionary::null)
291         {
292             return parent_.found(keyword, recursive, patternMatch);
293         }
294         else
295         {
296             return false;
297         }
298     }
302 const Foam::entry* Foam::dictionary::lookupEntryPtr
304     const word& keyword,
305     bool recursive,
306     bool patternMatch
307 ) const
309     HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
311     if (iter == hashedEntries_.end())
312     {
313         if (patternMatch && patternEntries_.size())
314         {
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))
322             {
323                 return wcLink();
324             }
325         }
327         if (recursive && &parent_ != &dictionary::null)
328         {
329             return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
330         }
331         else
332         {
333             return NULL;
334         }
335     }
337     return iter();
341 Foam::entry* Foam::dictionary::lookupEntryPtr
343     const word& keyword,
344     bool recursive,
345     bool patternMatch
348     HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
350     if (iter == hashedEntries_.end())
351     {
352         if (patternMatch && patternEntries_.size())
353         {
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))
361             {
362                 return wcLink();
363             }
364         }
366         if (recursive && &parent_ != &dictionary::null)
367         {
368             return const_cast<dictionary&>(parent_).lookupEntryPtr
369             (
370                 keyword,
371                 recursive,
372                 patternMatch
373             );
374         }
375         else
376         {
377             return NULL;
378         }
379     }
381     return iter();
385 const Foam::entry& Foam::dictionary::lookupEntry
387     const word& keyword,
388     bool recursive,
389     bool patternMatch
390 ) const
392     const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
394     if (entryPtr == NULL)
395     {
396         FatalIOErrorIn
397         (
398             "dictionary::lookupEntry(const word&, bool, bool) const",
399             *this
400         )   << "keyword " << keyword << " is undefined in dictionary "
401             << name()
402             << exit(FatalIOError);
403     }
405     return *entryPtr;
409 Foam::ITstream& Foam::dictionary::lookup
411     const word& keyword,
412     bool recursive,
413     bool patternMatch
414 ) const
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);
425     if (entryPtr)
426     {
427         return entryPtr->isDict();
428     }
429     else
430     {
431         return false;
432     }
436 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
438     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
440     if (entryPtr)
441     {
442         return &entryPtr->dict();
443     }
444     else
445     {
446         return NULL;
447     }
451 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
453     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
455     if (entryPtr == NULL)
456     {
457         FatalIOErrorIn
458         (
459             "dictionary::subDict(const word& keyword) const",
460             *this
461         )   << "keyword " << keyword << " is undefined in dictionary "
462             << name()
463             << exit(FatalIOError);
464     }
465     return entryPtr->dict();
469 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
471     entry* entryPtr = lookupEntryPtr(keyword, false, true);
473     if (entryPtr == NULL)
474     {
475         FatalIOErrorIn
476         (
477             "dictionary::subDict(const word& keyword)",
478             *this
479         )   << "keyword " << keyword << " is undefined in dictionary "
480             << name()
481             << exit(FatalIOError);
482     }
483     return entryPtr->dict();
487 Foam::dictionary Foam::dictionary::subOrEmptyDict
489     const word& keyword,
490     const bool mustRead
491 ) const
493     const entry* entryPtr = lookupEntryPtr(keyword, false, true);
495     if (entryPtr == NULL)
496     {
497         if (mustRead)
498         {
499             FatalIOErrorIn
500             (
501                 "dictionary::subOrEmptyDict(const word& keyword, const bool)",
502                 *this
503             )   << "keyword " << keyword << " is undefined in dictionary "
504                 << name()
505                 << exit(FatalIOError);
506             return entryPtr->dict();
507         }
508         else
509         {
510             return dictionary(*this, dictionary(name() + "::" + keyword));
511         }
512     }
513     else
514     {
515         return entryPtr->dict();
516     }
520 Foam::wordList Foam::dictionary::toc() const
522     wordList keys(size());
524     label nKeys = 0;
525     forAllConstIter(IDLList<entry>, *this, iter)
526     {
527         keys[nKeys++] = iter().keyword();
528     }
530     return keys;
534 Foam::List<Foam::keyType> Foam::dictionary::keys(bool patterns) const
536     List<keyType> keys(size());
538     label nKeys = 0;
539     forAllConstIter(IDLList<entry>, *this, iter)
540     {
541         if (iter().keyword().isPattern() ? patterns : !patterns)
542         {
543             keys[nKeys++] = iter().keyword();
544         }
545     }
546     keys.setSize(nKeys);
548     return keys;
552 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
554     HashTable<entry*>::iterator iter = hashedEntries_.find
555     (
556         entryPtr->keyword()
557     );
559     if (mergeEntry && iter != hashedEntries_.end())
560     {
561         // merge dictionary with dictionary
562         if (iter()->isDict() && entryPtr->isDict())
563         {
564             iter()->dict().merge(entryPtr->dict());
565             delete entryPtr;
567             return true;
568         }
569         else
570         {
571             // replace existing dictionary with entry or vice versa
572             IDLList<entry>::replace(iter(), entryPtr);
573             delete iter();
574             hashedEntries_.erase(iter);
576             if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
577             {
578                 entryPtr->name() = name() + "::" + entryPtr->keyword();
580                 if (entryPtr->keyword().isPattern())
581                 {
582                     patternEntries_.insert(entryPtr);
583                     patternRegexps_.insert
584                     (
585                         autoPtr<regExp>(new regExp(entryPtr->keyword()))
586                     );
587                 }
589                 return true;
590             }
591             else
592             {
593                 IOWarningIn("dictionary::add(entry*, bool)", (*this))
594                     << "problem replacing entry "<< entryPtr->keyword()
595                     << " in dictionary " << name() << endl;
597                 IDLList<entry>::remove(entryPtr);
598                 delete entryPtr;
599                 return false;
600             }
601         }
602     }
604     if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
605     {
606         entryPtr->name() = name() + "::" + entryPtr->keyword();
607         IDLList<entry>::append(entryPtr);
609         if (entryPtr->keyword().isPattern())
610         {
611             patternEntries_.insert(entryPtr);
612             patternRegexps_.insert
613             (
614                 autoPtr<regExp>(new regExp(entryPtr->keyword()))
615             );
616         }
618         return true;
619     }
620     else
621     {
622         IOWarningIn("dictionary::add(entry*, bool)", (*this))
623             << "attempt to add entry "<< entryPtr->keyword()
624             << " which already exists in dictionary " << name()
625             << endl;
627         delete entryPtr;
628         return false;
629     }
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
647     const keyType& k,
648     const Foam::string& s,
649     bool overwrite
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
670     const keyType& k,
671     const dictionary& d,
672     bool mergeEntry
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())
685     {
686         existingPtr->dict().clear();
687     }
688     add(entryPtr, true);
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())
709     {
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))
718         {
719             patternEntries_.remove(wcLink);
720             patternRegexps_.remove(reLink);
721         }
723         IDLList<entry>::remove(iter());
724         delete iter();
725         hashedEntries_.erase(iter);
727         return true;
728     }
729     else
730     {
731         return false;
732     }
736 bool Foam::dictionary::changeKeyword
738     const keyType& oldKeyword,
739     const keyType& newKeyword,
740     bool forceOverwrite
743     // no change
744     if (oldKeyword == newKeyword)
745     {
746         return false;
747     }
749     HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
751     // oldKeyword not found - do nothing
752     if (iter == hashedEntries_.end())
753     {
754         return false;
755     }
757     if (iter()->keyword().isPattern())
758     {
759         FatalIOErrorIn
760         (
761             "dictionary::changeKeyword(const word&, const word&, bool)",
762             *this
763         )   << "Old keyword "<< oldKeyword
764             << " is a pattern."
765             << "Pattern replacement not yet implemented."
766             << exit(FatalIOError);
767     }
770     HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
772     // newKeyword already exists
773     if (iter2 != hashedEntries_.end())
774     {
775         if (forceOverwrite)
776         {
777             if (iter2()->keyword().isPattern())
778             {
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))
787                 {
788                     patternEntries_.remove(wcLink);
789                     patternRegexps_.remove(reLink);
790                 }
791             }
793             IDLList<entry>::replace(iter2(), iter());
794             delete iter2();
795             hashedEntries_.erase(iter2);
797         }
798         else
799         {
800             IOWarningIn
801             (
802                 "dictionary::changeKeyword(const word&, const word&, bool)",
803                 *this
804             )   << "cannot rename keyword "<< oldKeyword
805                 << " to existing keyword " << newKeyword
806                 << " in dictionary " << name() << endl;
807             return false;
808         }
809     }
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())
818     {
819         patternEntries_.insert(iter());
820         patternRegexps_.insert
821         (
822             autoPtr<regExp>(new regExp(newKeyword))
823         );
824     }
826     return true;
830 bool Foam::dictionary::merge(const dictionary& dict)
832     // Check for assignment to self
833     if (this == &dict)
834     {
835         FatalIOErrorIn("dictionary::merge(const dictionary&)", *this)
836             << "attempted merge to self for dictionary " << name()
837             << abort(FatalIOError);
838     }
840     bool changed = false;
842     forAllConstIter(IDLList<entry>, dict, iter)
843     {
844         HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
846         if (fnd != hashedEntries_.end())
847         {
848             // Recursively merge sub-dictionaries
849             // TODO: merge without copying
850             if (fnd()->isDict() && iter().isDict())
851             {
852                 if (fnd()->dict().merge(iter().dict()))
853                 {
854                     changed = true;
855                 }
856             }
857             else
858             {
859                 add(iter().clone(*this).ptr(), true);
860                 changed = true;
861             }
862         }
863         else
864         {
865             // not found - just add
866             add(iter().clone(*this).ptr());
867             changed = true;
868         }
869     }
871     return changed;
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
914     if (this == &rhs)
915     {
916         FatalIOErrorIn("dictionary::operator=(const dictionary&)", *this)
917             << "attempted assignment to self for dictionary " << name()
918             << abort(FatalIOError);
919     }
921     name() = rhs.name();
922     clear();
924     // Create clones of the entries in the given dictionary
925     // resetting the parentDict to this dictionary
927     forAllConstIter(IDLList<entry>, rhs, iter)
928     {
929         add(iter().clone(*this).ptr());
930     }
934 void Foam::dictionary::operator+=(const dictionary& rhs)
936     // Check for assignment to self
937     if (this == &rhs)
938     {
939         FatalIOErrorIn("dictionary::operator+=(const dictionary&)", *this)
940             << "attempted addition assignment to self for dictionary " << name()
941             << abort(FatalIOError);
942     }
944     forAllConstIter(IDLList<entry>, rhs, iter)
945     {
946         add(iter().clone(*this).ptr());
947     }
951 void Foam::dictionary::operator|=(const dictionary& rhs)
953     // Check for assignment to self
954     if (this == &rhs)
955     {
956         FatalIOErrorIn("dictionary::operator|=(const dictionary&)", *this)
957             << "attempted assignment to self for dictionary " << name()
958             << abort(FatalIOError);
959     }
961     forAllConstIter(IDLList<entry>, rhs, iter)
962     {
963         if (!found(iter().keyword()))
964         {
965             add(iter().clone(*this).ptr());
966         }
967     }
971 void Foam::dictionary::operator<<=(const dictionary& rhs)
973     // Check for assignment to self
974     if (this == &rhs)
975     {
976         FatalIOErrorIn("dictionary::operator<<=(const dictionary&)", *this)
977             << "attempted assignment to self for dictionary " << name()
978             << abort(FatalIOError);
979     }
981     forAllConstIter(IDLList<entry>, rhs, iter)
982     {
983         set(iter().clone(*this).ptr());
984     }
988 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
990 Foam::dictionary Foam::operator+
992     const dictionary& dict1,
993     const dictionary& dict2
996     dictionary sum(dict1);
997     sum += dict2;
998     return sum;
1002 Foam::dictionary Foam::operator|
1004     const dictionary& dict1,
1005     const dictionary& dict2
1008     dictionary sum(dict1);
1009     sum |= dict2;
1010     return sum;
1014 // ************************************************************************* //