initial commit for version 1.5.x patch release
[OpenFOAM-1.5.x.git] / src / OpenFOAM / db / dictionary / dictionary.C
blob8a38ff9ba24ca1092d4563f1ef62338eb5d0afa1
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
4    \\    /   O peration     |
5     \\  /    A nd           | Copyright (C) 1991-2008 OpenCFD Ltd.
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"
31 /* * * * * * * * * * * * * * * Static Member Data  * * * * * * * * * * * * * */
33 defineTypeNameAndDebug(Foam::dictionary, 0);
35 const Foam::dictionary Foam::dictionary::null;
37 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
39 Foam::dictionary::dictionary()
41     parent_(dictionary::null)
45 Foam::dictionary::dictionary
47     const dictionary& parentDict,
48     const dictionary& dict
51     IDLList<entry>(dict, *this),
52     name_(dict.name()),
53     parent_(parentDict)
55     for
56     (
57         IDLList<entry>::iterator iter = begin();
58         iter != end();
59         ++iter
60     )
61     {
62         hashedEntries_.insert(iter().keyword(), &iter());
63     }
67 Foam::dictionary::dictionary
69     const dictionary& dict
72     IDLList<entry>(dict, *this),
73     name_(dict.name()),
74     parent_(dictionary::null)
76     for
77     (
78         IDLList<entry>::iterator iter = begin();
79         iter != end();
80         ++iter
81     )
82     {
83         hashedEntries_.insert(iter().keyword(), &iter());
84     }
88 Foam::autoPtr<Foam::dictionary> Foam::dictionary::clone() const
90     return autoPtr<dictionary>(new dictionary(*this));
94 // * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //
96 Foam::dictionary::~dictionary()
98     // cerr<< "~dictionary() " << name() << " " << long(this) << std::endl;
102 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
104 Foam::label Foam::dictionary::startLineNumber() const
106     if (size())
107     {
108         return first()->startLineNumber();
109     }
110     else
111     {
112         return -1;
113     }
117 Foam::label Foam::dictionary::endLineNumber() const
119     if (size())
120     {
121         return last()->endLineNumber();
122     }
123     else
124     {
125         return -1;
126     }
130 bool Foam::dictionary::found(const word& keyword, bool recursive) const
132     if (hashedEntries_.found(keyword))
133     {
134         return true;
135     }
136     else if (recursive && &parent_ != &dictionary::null)
137     {
138         return parent_.found(keyword, recursive);
139     }
140     else
141     {
142         return false;
143     }
147 const Foam::entry* Foam::dictionary::lookupEntryPtr
149     const word& keyword,
150     bool recursive
151 ) const
153     HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
155     if (iter == hashedEntries_.end())
156     {
157         if (recursive && &parent_ != &dictionary::null)
158         {
159             return parent_.lookupEntryPtr(keyword, recursive);
160         }
161         else
162         {
163             return NULL;
164         }
165     }
167     return iter();
171 Foam::entry* Foam::dictionary::lookupEntryPtr
173     const word& keyword,
174     bool recursive
177     HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
179     if (iter == hashedEntries_.end())
180     {
181         if (recursive && &parent_ != &dictionary::null)
182         {
183             return const_cast<dictionary&>(parent_).lookupEntryPtr
184             (
185                 keyword,
186                 recursive
187             );
188         }
189         else
190         {
191             return NULL;
192         }
193     }
195     return iter();
199 const Foam::entry& Foam::dictionary::lookupEntry
201     const word& keyword,
202     bool recursive
203 ) const
205     const entry* entryPtr = lookupEntryPtr(keyword, recursive);
207     if (entryPtr == NULL)
208     {
209         FatalIOErrorIn
210         (
211             "dictionary::lookupEntry(const word& keyword) const",
212             *this
213         )   << "keyword " << keyword << " is undefined in dictionary "
214             << name()
215             << exit(FatalIOError);
216     }
218     return *entryPtr;
222 Foam::ITstream& Foam::dictionary::lookup
224     const word& keyword,
225     bool recursive
226 ) const
228     return lookupEntry(keyword, recursive).stream();
232 bool Foam::dictionary::isDict(const word& keyword) const
234     const entry* entryPtr = lookupEntryPtr(keyword);
236     if (entryPtr)
237     {
238         return entryPtr->isDict();
239     }
240     else
241     {
242         return false;
243     }
247 const Foam::dictionary* Foam::dictionary::subDictPtr(const word& keyword) const
249     const entry* entryPtr = lookupEntryPtr(keyword);
251     if (entryPtr)
252     {
253         return &entryPtr->dict();
254     }
255     else
256     {
257         return NULL;
258     }
262 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
264     const entry* entryPtr = lookupEntryPtr(keyword);
265     if (entryPtr == NULL)
266     {
267         FatalIOErrorIn
268         (
269             "dictionary::subDict(const word& keyword) const",
270             *this
271         )   << "keyword " << keyword << " is undefined in dictionary "
272             << name()
273             << exit(FatalIOError);
274     }
275     return entryPtr->dict();
279 Foam::dictionary& Foam::dictionary::subDict(const word& keyword)
281     entry* entryPtr = lookupEntryPtr(keyword);
282     if (entryPtr == NULL)
283     {
284         FatalIOErrorIn
285         (
286             "dictionary::subDict(const word& keyword)",
287             *this
288         )   << "keyword " << keyword << " is undefined in dictionary "
289             << name()
290             << exit(FatalIOError);
291     }
292     return entryPtr->dict();
296 Foam::wordList Foam::dictionary::toc() const
298     wordList keys(size());
300     label i = 0;
301     for
302     (
303         IDLList<entry>::const_iterator iter = begin();
304         iter != end();
305         ++iter
306     )
307     {
308         keys[i++] = iter().keyword();
309     }
311     return keys;
315 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
317     HashTable<entry*>::iterator iter = hashedEntries_.find(entryPtr->keyword());
319     if (mergeEntry && iter != hashedEntries_.end())
320     {
321         // merge dictionary with dictionary
322         if (iter()->isDict() && entryPtr->isDict())
323         {
324             iter()->dict().merge(entryPtr->dict());
325             delete entryPtr;
327             return true;
328         }
329         else
330         {
331             // replace existing dictionary with entry or vice versa
332             IDLList<entry>::replace(iter(), entryPtr);
333             delete iter();
334             hashedEntries_.erase(iter);
336             if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
337             {
338                 entryPtr->name() = name_ + "::" + entryPtr->keyword();
339                 return true;
340             }
341             else
342             {
343                 IOWarningIn("dictionary::add(entry*)", (*this))
344                     << "problem replacing entry "<< entryPtr->keyword()
345                     << " in dictionary " << name() << endl;
347                 IDLList<entry>::remove(entryPtr);
348                 delete entryPtr;
349                 return false;
350             }
351         }
352     }
354     if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
355     {
356         entryPtr->name() = name_ + "::" + entryPtr->keyword();
357         IDLList<entry>::append(entryPtr);
359         return true;
360     }
361     else
362     {
363         IOWarningIn("dictionary::add(entry* entryPtr)", (*this))
364             << "attempt to add entry "<< entryPtr->keyword()
365             << " which already exists in dictionary " << name()
366             << endl;
368         delete entryPtr;
369         return false;
370     }
374 void Foam::dictionary::add(const entry& e, bool mergeEntry)
376     add(e.clone(*this).ptr(), mergeEntry);
379 void Foam::dictionary::add(const word& k, const word& w, bool overwrite)
381     add(new primitiveEntry(k, token(w)), overwrite);
384 void Foam::dictionary::add(const word& k, const Foam::string& s, bool overwrite)
386     add(new primitiveEntry(k, token(s)), overwrite);
389 void Foam::dictionary::add(const word& k, const label l, bool overwrite)
391     add(new primitiveEntry(k, token(l)), overwrite);
394 void Foam::dictionary::add(const word& k, const scalar s, bool overwrite)
396     add(new primitiveEntry(k, token(s)), overwrite);
399 void Foam::dictionary::add(const word& k, const dictionary& d, bool mergeEntry)
401     add(new dictionaryEntry(k, *this, d), mergeEntry);
405 void Foam::dictionary::set(entry* entryPtr)
407     entry* existingPtr = lookupEntryPtr(entryPtr->keyword());
409     // clear dictionary so merge acts like overwrite
410     if (existingPtr && existingPtr->isDict())
411     {
412         existingPtr->dict().clear();
413     }
414     add(entryPtr, true);
418 void Foam::dictionary::set(const entry& e)
420     set(e.clone(*this).ptr());
423 void Foam::dictionary::set(const word& k, const dictionary& d)
425     set(new dictionaryEntry(k, *this, d));
429 bool Foam::dictionary::remove(const word& Keyword)
431     HashTable<entry*>::iterator iter = hashedEntries_.find(Keyword);
433     if (iter != hashedEntries_.end())
434     {
435         IDLList<entry>::remove(iter());
436         delete iter();
437         hashedEntries_.erase(iter);
439         return true;
440     }
441     else
442     {
443         return false;
444     }
448 bool Foam::dictionary::changeKeyword
450     const word& oldKeyword,
451     const word& newKeyword,
452     bool forceOverwrite
455     // no change
456     if (oldKeyword == newKeyword)
457     {
458         return false;
459     }
461     HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
463     // oldKeyword not found - do nothing
464     if (iter == hashedEntries_.end())
465     {
466         return false;
467     }
469     HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
471     // newKeyword already exists
472     if (iter2 != hashedEntries_.end())
473     {
474         if (forceOverwrite)
475         {
476             IDLList<entry>::replace(iter2(), iter());
477             delete iter2();
478             hashedEntries_.erase(iter2);
479         }
480         else
481         {
482             WarningIn("dictionary::changeKeyword(const word&, const word&)")
483                 << "cannot rename keyword "<< oldKeyword
484                 << " to existing keyword " << newKeyword
485                 << " in dictionary " << name() << endl;
486             return false;
487         }
488     }
490     // change name and HashTable, but leave DL-List untouched
491     iter()->keyword() = newKeyword;
492     iter()->name() = name_ + "::" + newKeyword;
493     hashedEntries_.erase(oldKeyword);
494     hashedEntries_.insert(newKeyword, iter());
496     return true;
500 bool Foam::dictionary::merge(const dictionary& dict)
502     // Check for assignment to self
503     if (this == &dict)
504     {
505         FatalErrorIn("dictionary::merge(const dictionary&)")
506             << "attempted merge to self for dictionary " << name()
507             << abort(FatalError);
508     }
510     bool changed = false;
512     for
513     (
514         IDLList<entry>::const_iterator iter = dict.begin();
515         iter != dict.end();
516         ++iter
517     )
518     {
519         const word& keyword = iter().keyword();
521         HashTable<entry*>::iterator iter2 = hashedEntries_.find(keyword);
523         if (iter2 != hashedEntries_.end())
524         {
525             // Recursively merge sub-dictionaries
526             // TODO: merge without copying
527             if (iter2()->isDict() && iter().isDict())
528             {
529                 if (iter2()->dict().merge(iter().dict()))
530                 {
531                     changed = true;
532                 }
533             }
534             else
535             {
536                 add(iter().clone(*this).ptr(), true);
537                 changed = true;
538             }
539         }
540         else
541         {
542             // not found - just add
543             add(iter().clone(*this).ptr());
544             changed = true;
545         }
546     }
548     return changed;
552 void Foam::dictionary::clear()
554     IDLList<entry>::clear();
555     hashedEntries_.clear();
559 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
561 Foam::ITstream& Foam::dictionary::operator[](const word& keyword) const
563     return lookup(keyword);
567 void Foam::dictionary::operator=(const dictionary& dict)
569     // Check for assignment to self
570     if (this == &dict)
571     {
572         FatalErrorIn("dictionary::operator=(const dictionary&)")
573             << "attempted assignment to self for dictionary " << name()
574             << abort(FatalError);
575     }
577     name_ = dict.name();
578     clear();
580     // Create clones of the entries in the given dictionary
581     // resetting the parentDict to this dictionary
582     for
583     (
584         IDLList<entry>::const_iterator iter = dict.begin();
585         iter != dict.end();
586         ++iter
587     )
588     {
589         IDLList<entry>::append(iter().clone(*this).ptr());
590     }
592     for
593     (
594         IDLList<entry>::iterator iter = begin();
595         iter != end();
596         ++iter
597     )
598     {
599         hashedEntries_.insert(iter().keyword(), &iter());
600     }
604 void Foam::dictionary::operator+=(const dictionary& dict)
606     // Check for assignment to self
607     if (this == &dict)
608     {
609         FatalErrorIn("dictionary::operator+=(const dictionary&)")
610             << "attempted addition assignment to self for dictionary " << name()
611             << abort(FatalError);
612     }
614     for
615     (
616         IDLList<entry>::const_iterator iter = dict.begin();
617         iter != dict.end();
618         ++iter
619     )
620     {
621         add(iter().clone(*this).ptr());
622     }
626 void Foam::dictionary::operator|=(const dictionary& dict)
628     // Check for assignment to self
629     if (this == &dict)
630     {
631         FatalErrorIn("dictionary::operator|=(const dictionary&)")
632             << "attempted assignment to self for dictionary " << name()
633             << abort(FatalError);
634     }
636     for
637     (
638         IDLList<entry>::const_iterator iter = dict.begin();
639         iter != dict.end();
640         ++iter
641     )
642     {
643         if (!found(iter().keyword()))
644         {
645             add(iter().clone(*this).ptr());
646         }
647     }
651 void Foam::dictionary::operator<<=(const dictionary& dict)
653     // Check for assignment to self
654     if (this == &dict)
655     {
656         FatalErrorIn("dictionary::operator<<=(const dictionary&)")
657             << "attempted assignment to self for dictionary " << name()
658             << abort(FatalError);
659     }
661     for
662     (
663         IDLList<entry>::const_iterator iter = dict.begin();
664         iter != dict.end();
665         ++iter
666     )
667     {
668         set(iter().clone(*this).ptr());
669     }
673 /* * * * * * * * * * * * * * * * Global operators  * * * * * * * * * * * * * */
675 Foam::dictionary Foam::operator+
677     const dictionary& dict1,
678     const dictionary& dict2
681     dictionary sum(dict1);
682     sum += dict2;
683     return sum;
687 Foam::dictionary Foam::operator|
689     const dictionary& dict1,
690     const dictionary& dict2
693     dictionary sum(dict1);
694     sum |= dict2;
695     return sum;
699 // ************************************************************************* //