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 | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2017-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "HashTable.H"
30 #include "Istream.H"
31 #include "Ostream.H"
32 
33 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
34 
35 template<class T, class Key, class Hash>
37 :
38  HashTable<T, Key, Hash>()
39 {
40  operator>>(is, *this);
41 }
42 
43 
44 // * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
45 
46 template<class T, class Key, class Hash>
48 {
49  label used = 0;
50  label maxChain = 0;
51  unsigned avgChain = 0;
52 
53  for (label i=0; i < capacity_; ++i)
54  {
55  label count = 0;
56  for (node_type* ep = table_[i]; ep; ep = ep->next_)
57  {
58  ++count;
59  }
60 
61  if (count)
62  {
63  ++used;
64  avgChain += count;
65 
66  if (maxChain < count)
67  {
68  maxChain = count;
69  }
70  }
71  }
72 
73  os << "HashTable<T,Key,Hash>"
74  << " elements:" << size() << " slots:" << used << "/" << capacity_
75  << " chaining(avg/max):" << (used ? (float(avgChain)/used) : 0)
76  << "/" << maxChain << endl;
77 
78  return os;
79 }
80 
81 
82 template<class T, class Key, class Hash>
84 (
85  Ostream& os,
86  const label shortLen
87 ) const
88 {
89  // Similar to UList::writeList version except the following:
90  // - the keys can never be uniform
91  // - never write in binary
92 
93  label i = this->size();
94 
95  if
96  (
97  (i <= 1 || !shortLen)
98  || (i <= shortLen)
99  )
100  {
101  // Write size and start delimiter
102  os << i << token::BEGIN_LIST;
103 
104  i = 0;
105  for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter)
106  {
107  if (i++) os << token::SPACE;
108  os << iter.key();
109  }
110 
111  os << token::END_LIST; // End delimiter
112  }
113  else
114  {
115  // Write size and start delimiter
116  os << nl << i << nl << token::BEGIN_LIST << nl;
117 
118  for (const_iterator iter = this->cbegin(); iter != this->cend(); ++iter)
119  {
120  os << iter.key() << nl;
121  }
122 
123  os << token::END_LIST << nl; // End delimiter
124  }
125 
126  os.check(FUNCTION_NAME);
127  return os;
128 }
129 
130 
131 template<class T, class Key, class Hash>
133 (
134  Istream& is
135 )
136 {
137  HashTable<T, Key, Hash>& tbl = *this;
138 
139  // Anull existing table
140  tbl.clear();
141 
142  is.fatalCheck(FUNCTION_NAME);
143 
144  token tok(is);
145 
146  is.fatalCheck
147  (
148  "operator>>(Istream&, HashTable&) : "
149  "reading first token"
150  );
151 
152  if (tok.isLabel())
153  {
154  const label len = tok.labelToken();
155 
156  // Read beginning of contents
157  const char delimiter = is.readBeginList("HashTable");
158 
159  if (len)
160  {
161  if (delimiter != token::BEGIN_LIST)
162  {
164  << "incorrect first token, '(', found "
165  << tok.info() << nl
166  << exit(FatalIOError);
167  }
168 
169  tbl.reserve(tbl.size() + len);
170 
171  for (label i=0; i<len; ++i)
172  {
173  Key key;
174 
175  is >> key; // Read the key
176  T& val = tbl(key); // Insert nameless T() into table
177  is >> val; // Read directly into the table value
178 
179  is.fatalCheck
180  (
181  "operator>>(Istream&, HashTable&) : "
182  "reading entry"
183  );
184  }
185  }
186 
187  // Read end of contents
188  is.readEndList("HashTable");
189  }
190  else if (tok.isPunctuation(token::BEGIN_LIST))
191  {
192  is >> tok;
193  while (!tok.isPunctuation(token::END_LIST))
194  {
195  is.putBack(tok);
196 
197  Key key;
198 
199  is >> key; // Read the key
200  T& val = tbl(key); // Insert nameless T() into table
201  is >> val; // Read directly into the table value
202 
203  is.fatalCheck
204  (
205  "operator>>(Istream&, HashTable&) : "
206  "reading entry"
207  );
208 
209  is >> tok;
210  }
211  }
212  else
213  {
215  << "incorrect first token, expected <int> or '(', found "
216  << tok.info() << nl
217  << exit(FatalIOError);
218  }
219 
220  is.fatalCheck(FUNCTION_NAME);
221  return is;
222 }
223 
224 
225 template<class T, class Key, class Hash>
227 (
228  Ostream& os
229 ) const
230 {
231  const HashTable<T, Key, Hash>& tbl = *this;
232 
233  const label len = tbl.size();
234 
235  if (len)
236  {
237  // Size and start list delimiter
238  os << nl << len << nl << token::BEGIN_LIST << nl;
239 
240  // Contents
241  for (auto iter = tbl.cbegin(); iter != tbl.cend(); ++iter)
242  {
243  iter.print(os) << nl;
244  }
245 
246  os << token::END_LIST; // End list delimiter
247  }
248  else
249  {
250  // Empty hash table
251  os << len << token::BEGIN_LIST << token::END_LIST;
252  }
253 
254  os.check(FUNCTION_NAME);
255  return os;
256 }
257 
258 
259 // * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
260 
261 template<class T, class Key, class Hash>
262 Foam::Istream& Foam::operator>>
263 (
264  Istream& is,
265  HashTable<T, Key, Hash>& tbl
266 )
267 {
268  return tbl.readTable(is);
269 }
270 
271 
272 template<class T, class Key, class Hash>
273 Foam::Ostream& Foam::operator<<
274 (
275  Ostream& os,
276  const HashTable<T, Key, Hash>& tbl
277 )
278 {
279  return tbl.writeTable(os);
280 }
281 
282 
283 // ************************************************************************* //
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
labelHashSet used(const bitSet &select)
Convert a bitset to a labelHashSet of the indices used.
Definition: HashOps.C:26
An Istream is an abstract base class for all input systems (streams, files, token lists etc)...
Definition: Istream.H:57
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
HashTable() noexcept
Default construct: empty without allocation (capacity=0)
Definition: HashTable.C:33
label size() const noexcept
The number of elements in table.
Definition: HashTable.H:342
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Ostream & writeKeys(Ostream &os, const label shortLen=0) const
Write unordered keys (list), with line-breaks when length exceeds shortLen.
Definition: HashTableIO.C:77
Ostream & printInfo(Ostream &os) const
Print information.
Definition: HashTableIO.C:40
Istream & operator>>(Istream &, directionInfo &)
void clear()
Remove all entries from table.
Definition: HashTable.C:725
constexpr auto cend(const C &c) -> decltype(c.end())
Return const_iterator to the end of the container c.
Definition: stdFoam.H:223
A HashTable similar to std::unordered_map.
Definition: HashTable.H:108
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:56
OBJstream os(runTime.globalPath()/outputName)
#define FUNCTION_NAME
constexpr auto cbegin(const C &c) -> decltype(c.begin())
Return const_iterator to the beginning of the container c.
Definition: stdFoam.H:190
const volScalarField & T
#define FatalIOErrorInFunction(ios)
Report an error message using Foam::FatalIOError.
Definition: error.H:627
Hash function class. The default definition is for primitives. Non-primitives used to hash entries on...
Definition: Hash.H:47
auto key(const Type &t) -> typename std::enable_if< std::is_enum< Type >::value, typename std::underlying_type< Type >::type >::type
Definition: foamGltfBase.H:103
IOerror FatalIOError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL IO ERROR&#39; header text and ...