FreeFOAM The Cross-Platform CFD Toolkit
HashTableIO.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 "HashTable.H"
27 #include <OpenFOAM/Istream.H>
28 #include <OpenFOAM/Ostream.H>
29 
30 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
31 
32 template<class T, class Key, class Hash>
34 :
35  HashTableName(),
36  nElmts_(0),
37  tableSize_(canonicalSize(size)),
38  table_(new hashedEntry*[tableSize_]),
39  endIter_(*this, NULL, 0),
40  endConstIter_(*this, NULL, 0)
41 {
42  for (label hashIdx = 0; hashIdx < tableSize_; hashIdx++)
43  {
44  table_[hashIdx] = 0;
45  }
46 
47  operator>>(is, *this);
48 }
49 
50 
51 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
52 
53 template<class T, class Key, class Hash>
56 {
57  label used = 0;
58  label maxChain = 0;
59  unsigned avgChain = 0;
60 
61  for (label hashIdx = 0; hashIdx < tableSize_; ++hashIdx)
62  {
63  label count = 0;
64  for (hashedEntry* ep = table_[hashIdx]; ep; ep = ep->next_)
65  {
66  ++count;
67  }
68 
69  if (count)
70  {
71  ++used;
72  avgChain += count;
73 
74  if (maxChain < count)
75  {
76  maxChain = count;
77  }
78  }
79  }
80 
81  os << "HashTable<T,Key,Hash>"
82  << " elements:" << size() << " slots:" << used << "/" << tableSize_
83  << " chaining(avg/max):" << (used ? (float(avgChain)/used) : 0)
84  << "/" << maxChain << endl;
85 
86  return os;
87 }
88 
89 
90 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
91 
92 template<class T, class Key, class Hash>
93 Foam::Istream& Foam::operator>>
94 (
95  Istream& is,
97 )
98 {
99  is.fatalCheck("operator>>(Istream&, HashTable<T, Key, Hash>&)");
100 
101  // Anull list
102  L.clear();
103 
104  is.fatalCheck("operator>>(Istream&, HashTable<T, Key, Hash>&)");
105 
106  token firstToken(is);
107 
108  is.fatalCheck
109  (
110  "operator>>(Istream&, HashTable<T, Key, Hash>&) : "
111  "reading first token"
112  );
113 
114  if (firstToken.isLabel())
115  {
116  label s = firstToken.labelToken();
117 
118  // Read beginning of contents
119  char delimiter = is.readBeginList("HashTable<T, Key, Hash>");
120 
121  if (s)
122  {
123  if (2*s > L.tableSize_)
124  {
125  L.resize(2*s);
126  }
127 
128  if (delimiter == token::BEGIN_LIST)
129  {
130  for (label i=0; i<s; i++)
131  {
132  Key key;
133  is >> key;
134  L.insert(key, pTraits<T>(is));
135 
136  is.fatalCheck
137  (
138  "operator>>(Istream&, HashTable<T, Key, Hash>&) : "
139  "reading entry"
140  );
141  }
142  }
143  else
144  {
146  (
147  "operator>>(Istream&, HashTable<T, Key, Hash>&)",
148  is
149  ) << "incorrect first token, '(', found " << firstToken.info()
150  << exit(FatalIOError);
151  }
152  }
153 
154  // Read end of contents
155  is.readEndList("HashTable");
156  }
157  else if (firstToken.isPunctuation())
158  {
159  if (firstToken.pToken() != token::BEGIN_LIST)
160  {
162  (
163  "operator>>(Istream&, HashTable<T, Key, Hash>&)",
164  is
165  ) << "incorrect first token, '(', found " << firstToken.info()
166  << exit(FatalIOError);
167  }
168 
169  token lastToken(is);
170  while
171  (
172  !(
173  lastToken.isPunctuation()
174  && lastToken.pToken() == token::END_LIST
175  )
176  )
177  {
178  is.putBack(lastToken);
179 
180  Key key;
181  is >> key;
182 
183  T element;
184  is >> element;
185 
186  L.insert(key, element);
187 
188  is.fatalCheck
189  (
190  "operator>>(Istream&, HashTable<T, Key, Hash>&) : "
191  "reading entry"
192  );
193 
194  is >> lastToken;
195  }
196  }
197  else
198  {
200  (
201  "operator>>(Istream&, HashTable<T, Key, Hash>&)",
202  is
203  ) << "incorrect first token, expected <int> or '(', found "
204  << firstToken.info()
205  << exit(FatalIOError);
206  }
207 
208  is.fatalCheck("operator>>(Istream&, HashTable<T, Key, Hash>&)");
209 
210  return is;
211 }
212 
213 
214 template<class T, class Key, class Hash>
215 Foam::Ostream& Foam::operator<<
216 (
217  Ostream& os,
218  const HashTable<T, Key, Hash>& L
219 )
220 {
221  // Write size and start delimiter
222  os << nl << L.size() << nl << token::BEGIN_LIST << nl;
223 
224  // Write contents
225  for
226  (
227  typename HashTable<T, Key, Hash>::const_iterator iter = L.cbegin();
228  iter != L.cend();
229  ++iter
230  )
231  {
232  os << iter.key() << token::SPACE << iter() << nl;
233  }
234 
235  // Write end delimiter
236  os << token::END_LIST;
237 
238  // Check state of IOstream
239  os.check("Ostream& operator<<(Ostream&, const HashTable&)");
240 
241  return os;
242 }
243 
244 
245 // ************************ vim: set sw=4 sts=4 et: ************************ //