FreeFOAM The Cross-Platform CFD Toolkit
dictionary.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd.
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8 License
9  This file is part of OpenFOAM.
10 
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.
15 
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.
20 
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/>.
23 
24 \*---------------------------------------------------------------------------*/
25 
26 #include "dictionary.H"
29 #include <OSspecific/regExp.H>
30 #include <OpenFOAM/OSHA1stream.H>
31 
32 /* * * * * * * * * * * * * * * Static Member Data * * * * * * * * * * * * * */
33 
35 
37 
38 
39 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
40 
41 bool Foam::dictionary::findInPatterns
42 (
43  const bool patternMatch,
44  const word& Keyword,
45  DLList<entry*>::const_iterator& wcLink,
46  DLList<autoPtr<regExp> >::const_iterator& reLink
47 ) const
48 {
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  }
62 
63  ++reLink;
64  ++wcLink;
65  }
66  }
67 
68  return false;
69 }
70 
71 
72 bool Foam::dictionary::findInPatterns
73 (
74  const bool patternMatch,
75  const word& Keyword,
77  DLList<autoPtr<regExp> >::iterator& reLink
78 )
79 {
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  }
93 
94  ++reLink;
95  ++wcLink;
96  }
97  }
98 
99  return false;
100 }
101 
102 
103 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
104 
106 :
107  parent_(dictionary::null)
108 {}
109 
110 
112 :
113  dictionaryName(name),
114  parent_(dictionary::null)
115 {}
116 
117 
119 (
120  const dictionary& parentDict,
121  const dictionary& dict
122 )
123 :
124  dictionaryName(dict.name()),
125  IDLList<entry>(dict, *this),
126  parent_(parentDict)
127 {
128  forAllIter(IDLList<entry>, *this, iter)
129  {
130  hashedEntries_.insert(iter().keyword(), &iter());
131 
132  if (iter().keyword().isPattern())
133  {
134  patternEntries_.insert(&iter());
135  patternRegexps_.insert
136  (
137  autoPtr<regExp>(new regExp(iter().keyword()))
138  );
139  }
140  }
141 }
142 
143 
145 (
146  const dictionary& dict
147 )
148 :
149  dictionaryName(dict.name()),
150  IDLList<entry>(dict, *this),
151  parent_(dictionary::null)
152 {
153  forAllIter(IDLList<entry>, *this, iter)
154  {
155  hashedEntries_.insert(iter().keyword(), &iter());
156 
157  if (iter().keyword().isPattern())
158  {
159  patternEntries_.insert(&iter());
160  patternRegexps_.insert
161  (
162  autoPtr<regExp>(new regExp(iter().keyword()))
163  );
164  }
165  }
166 }
167 
168 
170 (
171  const dictionary* dictPtr
172 )
173 :
174  parent_(dictionary::null)
175 {
176  if (dictPtr)
177  {
178  operator=(*dictPtr);
179  }
180 }
181 
182 
184 (
185  const dictionary& parentDict,
186  const Xfer<dictionary>& dict
187 )
188 :
189  parent_(parentDict)
190 {
191  transfer(dict());
192  name() = parentDict.name() + "::" + name();
193 }
194 
195 
197 (
198  const Xfer<dictionary>& dict
199 )
200 :
201  parent_(dictionary::null)
202 {
203  transfer(dict());
204 }
205 
206 
208 {
209  return autoPtr<dictionary>(new dictionary(*this));
210 }
211 
212 
213 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
214 
216 {
217  // cerr<< "~dictionary() " << name() << " " << long(this) << std::endl;
218 }
219 
220 
221 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
222 
224 {
225  if (size())
226  {
227  return first()->startLineNumber();
228  }
229  else
230  {
231  return -1;
232  }
233 }
234 
235 
237 {
238  if (size())
239  {
240  return last()->endLineNumber();
241  }
242  else
243  {
244  return -1;
245  }
246 }
247 
248 
250 {
251  OSHA1stream os;
252 
253  // process entries
254  forAllConstIter(IDLList<entry>, *this, iter)
255  {
256  os << *iter;
257  }
258 
259  return os.digest();
260 }
261 
262 
263 bool Foam::dictionary::found(const word& keyword, bool recursive) const
264 {
265  if (hashedEntries_.found(keyword))
266  {
267  return true;
268  }
269  else
270  {
271  if (patternEntries_.size())
272  {
274  patternEntries_.begin();
276  patternRegexps_.begin();
277 
278  // Find in patterns using regular expressions only
279  if (findInPatterns(true, keyword, wcLink, reLink))
280  {
281  return true;
282  }
283  }
284 
285  if (recursive && &parent_ != &dictionary::null)
286  {
287  return parent_.found(keyword, recursive);
288  }
289  else
290  {
291  return false;
292  }
293  }
294 }
295 
296 
298 (
299  const word& keyword,
300  bool recursive,
301  bool patternMatch
302 ) const
303 {
304  HashTable<entry*>::const_iterator iter = hashedEntries_.find(keyword);
305 
306  if (iter == hashedEntries_.end())
307  {
308  if (patternMatch && patternEntries_.size())
309  {
311  patternEntries_.begin();
313  patternRegexps_.begin();
314 
315  // Find in patterns using regular expressions only
316  if (findInPatterns(patternMatch, keyword, wcLink, reLink))
317  {
318  return wcLink();
319  }
320  }
321 
322  if (recursive && &parent_ != &dictionary::null)
323  {
324  return parent_.lookupEntryPtr(keyword, recursive, patternMatch);
325  }
326  else
327  {
328  return NULL;
329  }
330  }
331 
332  return iter();
333 }
334 
335 
337 (
338  const word& keyword,
339  bool recursive,
340  bool patternMatch
341 )
342 {
343  HashTable<entry*>::iterator iter = hashedEntries_.find(keyword);
344 
345  if (iter == hashedEntries_.end())
346  {
347  if (patternMatch && patternEntries_.size())
348  {
349  DLList<entry*>::iterator wcLink =
350  patternEntries_.begin();
352  patternRegexps_.begin();
353 
354  // Find in patterns using regular expressions only
355  if (findInPatterns(patternMatch, keyword, wcLink, reLink))
356  {
357  return wcLink();
358  }
359  }
360 
361  if (recursive && &parent_ != &dictionary::null)
362  {
363  return const_cast<dictionary&>(parent_).lookupEntryPtr
364  (
365  keyword,
366  recursive,
367  patternMatch
368  );
369  }
370  else
371  {
372  return NULL;
373  }
374  }
375 
376  return iter();
377 }
378 
379 
381 (
382  const word& keyword,
383  bool recursive,
384  bool patternMatch
385 ) const
386 {
387  const entry* entryPtr = lookupEntryPtr(keyword, recursive, patternMatch);
388 
389  if (entryPtr == NULL)
390  {
392  (
393  "dictionary::lookupEntry(const word&, bool, bool) const",
394  *this
395  ) << "keyword " << keyword << " is undefined in dictionary "
396  << name()
397  << exit(FatalIOError);
398  }
399 
400  return *entryPtr;
401 }
402 
403 
405 (
406  const word& keyword,
407  bool recursive,
408  bool patternMatch
409 ) const
410 {
411  return lookupEntry(keyword, recursive, patternMatch).stream();
412 }
413 
414 
415 bool Foam::dictionary::isDict(const word& keyword) const
416 {
417  // Find non-recursive with patterns
418  const entry* entryPtr = lookupEntryPtr(keyword, false, true);
419 
420  if (entryPtr)
421  {
422  return entryPtr->isDict();
423  }
424  else
425  {
426  return false;
427  }
428 }
429 
430 
432 {
433  const entry* entryPtr = lookupEntryPtr(keyword, false, true);
434 
435  if (entryPtr)
436  {
437  return &entryPtr->dict();
438  }
439  else
440  {
441  return NULL;
442  }
443 }
444 
445 
446 const Foam::dictionary& Foam::dictionary::subDict(const word& keyword) const
447 {
448  const entry* entryPtr = lookupEntryPtr(keyword, false, true);
449 
450  if (entryPtr == NULL)
451  {
453  (
454  "dictionary::subDict(const word& keyword) const",
455  *this
456  ) << "keyword " << keyword << " is undefined in dictionary "
457  << name()
458  << exit(FatalIOError);
459  }
460  return entryPtr->dict();
461 }
462 
463 
465 {
466  entry* entryPtr = lookupEntryPtr(keyword, false, true);
467 
468  if (entryPtr == NULL)
469  {
471  (
472  "dictionary::subDict(const word& keyword)",
473  *this
474  ) << "keyword " << keyword << " is undefined in dictionary "
475  << name()
476  << exit(FatalIOError);
477  }
478  return entryPtr->dict();
479 }
480 
481 
483 (
484  const word& keyword
485 ) const
486 {
487  const entry* entryPtr = lookupEntryPtr(keyword, false, true);
488 
489  if (entryPtr == NULL)
490  {
491  return dictionary(*this, dictionary(name() + "::" + keyword));
492  }
493  else
494  {
495  return entryPtr->dict();
496  }
497 }
498 
499 
501 {
502  wordList keys(size());
503 
504  label nKeys = 0;
505  forAllConstIter(IDLList<entry>, *this, iter)
506  {
507  keys[nKeys++] = iter().keyword();
508  }
509 
510  return keys;
511 }
512 
513 
515 {
516  List<keyType> keys(size());
517 
518  label nKeys = 0;
519  forAllConstIter(IDLList<entry>, *this, iter)
520  {
521  if (iter().keyword().isPattern() ? patterns : !patterns)
522  {
523  keys[nKeys++] = iter().keyword();
524  }
525  }
526  keys.setSize(nKeys);
527 
528  return keys;
529 }
530 
531 
532 bool Foam::dictionary::add(entry* entryPtr, bool mergeEntry)
533 {
534  HashTable<entry*>::iterator iter = hashedEntries_.find
535  (
536  entryPtr->keyword()
537  );
538 
539  if (mergeEntry && iter != hashedEntries_.end())
540  {
541  // merge dictionary with dictionary
542  if (iter()->isDict() && entryPtr->isDict())
543  {
544  iter()->dict().merge(entryPtr->dict());
545  delete entryPtr;
546 
547  return true;
548  }
549  else
550  {
551  // replace existing dictionary with entry or vice versa
552  IDLList<entry>::replace(iter(), entryPtr);
553  delete iter();
554  hashedEntries_.erase(iter);
555 
556  if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
557  {
558  entryPtr->name() = name() + "::" + entryPtr->keyword();
559 
560  if (entryPtr->keyword().isPattern())
561  {
562  patternEntries_.insert(entryPtr);
563  patternRegexps_.insert
564  (
565  autoPtr<regExp>(new regExp(entryPtr->keyword()))
566  );
567  }
568 
569  return true;
570  }
571  else
572  {
573  IOWarningIn("dictionary::add(entry*, bool)", (*this))
574  << "problem replacing entry "<< entryPtr->keyword()
575  << " in dictionary " << name() << endl;
576 
577  IDLList<entry>::remove(entryPtr);
578  delete entryPtr;
579  return false;
580  }
581  }
582  }
583 
584  if (hashedEntries_.insert(entryPtr->keyword(), entryPtr))
585  {
586  entryPtr->name() = name() + "::" + entryPtr->keyword();
587  IDLList<entry>::append(entryPtr);
588 
589  if (entryPtr->keyword().isPattern())
590  {
591  patternEntries_.insert(entryPtr);
592  patternRegexps_.insert
593  (
594  autoPtr<regExp>(new regExp(entryPtr->keyword()))
595  );
596  }
597 
598  return true;
599  }
600  else
601  {
602  IOWarningIn("dictionary::add(entry*, bool)", (*this))
603  << "attempt to add entry "<< entryPtr->keyword()
604  << " which already exists in dictionary " << name()
605  << endl;
606 
607  delete entryPtr;
608  return false;
609  }
610 }
611 
612 
613 void Foam::dictionary::add(const entry& e, bool mergeEntry)
614 {
615  add(e.clone(*this).ptr(), mergeEntry);
616 }
617 
618 
619 void Foam::dictionary::add(const keyType& k, const word& w, bool overwrite)
620 {
621  add(new primitiveEntry(k, token(w)), overwrite);
622 }
623 
624 
626 (
627  const keyType& k,
628  const Foam::string& s,
629  bool overwrite
630 )
631 {
632  add(new primitiveEntry(k, token(s)), overwrite);
633 }
634 
635 
636 void Foam::dictionary::add(const keyType& k, const label l, bool overwrite)
637 {
638  add(new primitiveEntry(k, token(l)), overwrite);
639 }
640 
641 
642 void Foam::dictionary::add(const keyType& k, const scalar s, bool overwrite)
643 {
644  add(new primitiveEntry(k, token(s)), overwrite);
645 }
646 
647 
649 (
650  const keyType& k,
651  const dictionary& d,
652  bool mergeEntry
653 )
654 {
655  add(new dictionaryEntry(k, *this, d), mergeEntry);
656 }
657 
658 
660 {
661  entry* existingPtr = lookupEntryPtr(entryPtr->keyword(), false, true);
662 
663  // clear dictionary so merge acts like overwrite
664  if (existingPtr && existingPtr->isDict())
665  {
666  existingPtr->dict().clear();
667  }
668  add(entryPtr, true);
669 }
670 
671 
673 {
674  set(e.clone(*this).ptr());
675 }
676 
677 
678 void Foam::dictionary::set(const keyType& k, const dictionary& d)
679 {
680  set(new dictionaryEntry(k, *this, d));
681 }
682 
683 
684 bool Foam::dictionary::remove(const word& Keyword)
685 {
686  HashTable<entry*>::iterator iter = hashedEntries_.find(Keyword);
687 
688  if (iter != hashedEntries_.end())
689  {
690  // Delete from patterns first
691  DLList<entry*>::iterator wcLink =
692  patternEntries_.begin();
694  patternRegexps_.begin();
695 
696  // Find in pattern using exact match only
697  if (findInPatterns(false, Keyword, wcLink, reLink))
698  {
699  patternEntries_.remove(wcLink);
700  patternRegexps_.remove(reLink);
701  }
702 
703  IDLList<entry>::remove(iter());
704  delete iter();
705  hashedEntries_.erase(iter);
706 
707  return true;
708  }
709  else
710  {
711  return false;
712  }
713 }
714 
715 
717 (
718  const keyType& oldKeyword,
719  const keyType& newKeyword,
720  bool forceOverwrite
721 )
722 {
723  // no change
724  if (oldKeyword == newKeyword)
725  {
726  return false;
727  }
728 
729  HashTable<entry*>::iterator iter = hashedEntries_.find(oldKeyword);
730 
731  // oldKeyword not found - do nothing
732  if (iter == hashedEntries_.end())
733  {
734  return false;
735  }
736 
737  if (iter()->keyword().isPattern())
738  {
740  (
741  "dictionary::changeKeyword(const word&, const word&, bool)"
742  ) << "Old keyword "<< oldKeyword
743  << " is a pattern."
744  << "Pattern replacement not yet implemented."
745  << exit(FatalError);
746  }
747 
748 
749  HashTable<entry*>::iterator iter2 = hashedEntries_.find(newKeyword);
750 
751  // newKeyword already exists
752  if (iter2 != hashedEntries_.end())
753  {
754  if (forceOverwrite)
755  {
756  if (iter2()->keyword().isPattern())
757  {
758  // Delete from patterns first
759  DLList<entry*>::iterator wcLink =
760  patternEntries_.begin();
762  patternRegexps_.begin();
763 
764  // Find in patterns using exact match only
765  if (findInPatterns(false, iter2()->keyword(), wcLink, reLink))
766  {
767  patternEntries_.remove(wcLink);
768  patternRegexps_.remove(reLink);
769  }
770  }
771 
772  IDLList<entry>::replace(iter2(), iter());
773  delete iter2();
774  hashedEntries_.erase(iter2);
775 
776  }
777  else
778  {
779  WarningIn
780  (
781  "dictionary::changeKeyword(const word&, const word&, bool)"
782  ) << "cannot rename keyword "<< oldKeyword
783  << " to existing keyword " << newKeyword
784  << " in dictionary " << name() << endl;
785  return false;
786  }
787  }
788 
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());
794 
795  if (newKeyword.isPattern())
796  {
797  patternEntries_.insert(iter());
798  patternRegexps_.insert
799  (
800  autoPtr<regExp>(new regExp(newKeyword))
801  );
802  }
803 
804  return true;
805 }
806 
807 
809 {
810  // Check for assignment to self
811  if (this == &dict)
812  {
813  FatalErrorIn("dictionary::merge(const dictionary&)")
814  << "attempted merge to self for dictionary " << name()
815  << abort(FatalError);
816  }
817 
818  bool changed = false;
819 
820  forAllConstIter(IDLList<entry>, dict, iter)
821  {
822  HashTable<entry*>::iterator fnd = hashedEntries_.find(iter().keyword());
823 
824  if (fnd != hashedEntries_.end())
825  {
826  // Recursively merge sub-dictionaries
827  // TODO: merge without copying
828  if (fnd()->isDict() && iter().isDict())
829  {
830  if (fnd()->dict().merge(iter().dict()))
831  {
832  changed = true;
833  }
834  }
835  else
836  {
837  add(iter().clone(*this).ptr(), true);
838  changed = true;
839  }
840  }
841  else
842  {
843  // not found - just add
844  add(iter().clone(*this).ptr());
845  changed = true;
846  }
847  }
848 
849  return changed;
850 }
851 
852 
854 {
856  hashedEntries_.clear();
857  patternEntries_.clear();
858  patternRegexps_.clear();
859 }
860 
861 
863 {
864  // changing parents probably doesn't make much sense,
865  // but what about the names?
866  name() = dict.name();
867 
869  hashedEntries_.transfer(dict.hashedEntries_);
870  patternEntries_.transfer(dict.patternEntries_);
871  patternRegexps_.transfer(dict.patternRegexps_);
872 }
873 
874 
876 {
877  return xferMove(*this);
878 }
879 
880 
881 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
882 
884 {
885  return lookup(keyword);
886 }
887 
888 
890 {
891  // Check for assignment to self
892  if (this == &rhs)
893  {
894  FatalErrorIn("dictionary::operator=(const dictionary&)")
895  << "attempted assignment to self for dictionary " << name()
896  << abort(FatalError);
897  }
898 
899  name() = rhs.name();
900  clear();
901 
902  // Create clones of the entries in the given dictionary
903  // resetting the parentDict to this dictionary
904 
905  forAllConstIter(IDLList<entry>, rhs, iter)
906  {
907  add(iter().clone(*this).ptr());
908  }
909 }
910 
911 
913 {
914  // Check for assignment to self
915  if (this == &rhs)
916  {
917  FatalErrorIn("dictionary::operator+=(const dictionary&)")
918  << "attempted addition assignment to self for dictionary " << name()
919  << abort(FatalError);
920  }
921 
922  forAllConstIter(IDLList<entry>, rhs, iter)
923  {
924  add(iter().clone(*this).ptr());
925  }
926 }
927 
928 
930 {
931  // Check for assignment to self
932  if (this == &rhs)
933  {
934  FatalErrorIn("dictionary::operator|=(const dictionary&)")
935  << "attempted assignment to self for dictionary " << name()
936  << abort(FatalError);
937  }
938 
939  forAllConstIter(IDLList<entry>, rhs, iter)
940  {
941  if (!found(iter().keyword()))
942  {
943  add(iter().clone(*this).ptr());
944  }
945  }
946 }
947 
948 
950 {
951  // Check for assignment to self
952  if (this == &rhs)
953  {
954  FatalErrorIn("dictionary::operator<<=(const dictionary&)")
955  << "attempted assignment to self for dictionary " << name()
956  << abort(FatalError);
957  }
958 
959  forAllConstIter(IDLList<entry>, rhs, iter)
960  {
961  set(iter().clone(*this).ptr());
962  }
963 }
964 
965 
966 /* * * * * * * * * * * * * * * * Global operators * * * * * * * * * * * * * */
967 
968 Foam::dictionary Foam::operator+
969 (
970  const dictionary& dict1,
971  const dictionary& dict2
972 )
973 {
974  dictionary sum(dict1);
975  sum += dict2;
976  return sum;
977 }
978 
979 
980 Foam::dictionary Foam::operator|
981 (
982  const dictionary& dict1,
983  const dictionary& dict2
984 )
985 {
986  dictionary sum(dict1);
987  sum |= dict2;
988  return sum;
989 }
990 
991 
992 // ************************ vim: set sw=4 sts=4 et: ************************ //