ROOT  6.06/09
Reference Guide
TExMap.cxx
Go to the documentation of this file.
1 // @(#)root/cont:$Id$
2 // Author: Fons Rademakers 26/05/99
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers. *
6  * All rights reserved. *
7  * *
8  * For the licensing terms see $ROOTSYS/LICENSE. *
9  * For the list of contributors see $ROOTSYS/README/CREDITS. *
10  *************************************************************************/
11 
12 /** \class TExMap
13 This class stores a (key,value) pair using an external hash.
14 The (key,value) are Long64_t's and therefore can contain object
15 pointers or any longs. The map uses an open addressing hashing
16 method (linear probing).
17 */
18 
19 #include "TExMap.h"
20 #include "TError.h"
21 #include "TMathBase.h"
22 #include <string.h>
23 
24 
26 
27 ////////////////////////////////////////////////////////////////////////////////
28 /// Create a TExMap.
29 
30 TExMap::TExMap(Int_t mapSize)
31 {
32  // needed for automatic resizing to guarantee that one slot is always empty
33  if (mapSize < 4) mapSize = 5;
34 
35  switch (mapSize) {
36  // Avoid calling NextPrime for the common case:
37  case 5: fSize = 5; break;
38  case 503: fSize = 503; break;
39  default:
40  fSize = (Int_t)TMath::NextPrime(mapSize);
41  }
42  fTable = new Assoc_t [fSize];
43 
44  memset(fTable,0,sizeof(Assoc_t)*fSize);
45  fTally = 0;
46 }
47 
48 ////////////////////////////////////////////////////////////////////////////////
49 /// Copy constructor.
50 
51 TExMap::TExMap(const TExMap &map) : TObject(map)
52 {
53  fSize = map.fSize;
54  fTally = map.fTally;
55  fTable = new Assoc_t [fSize];
56  memcpy(fTable, map.fTable, fSize*sizeof(Assoc_t));
57 }
58 
59 ////////////////////////////////////////////////////////////////////////////////
60 /// Assignment operator.
61 
63 {
64  if (this != &map) {
65  TObject::operator=(map);
66  fSize = map.fSize;
67  fTally = map.fTally;
68  fTable = new Assoc_t [fSize];
69  memcpy(fTable, map.fTable, fSize*sizeof(Assoc_t));
70  }
71  return *this;
72 }
73 
74 ////////////////////////////////////////////////////////////////////////////////
75 /// Delete TExMap.
76 
78 {
79  delete [] fTable; fTable = 0;
80 }
81 
82 ////////////////////////////////////////////////////////////////////////////////
83 /// Add an (key,value) pair to the table. The key should be unique.
84 
85 void TExMap::Add(ULong64_t hash, Long64_t key, Long64_t value)
86 {
87  if (!fTable) return;
88 
89  Int_t slot = FindElement(hash, key);
90  if (!fTable[slot].InUse()) {
91  fTable[slot].SetHash(hash);
92  fTable[slot].fKey = key;
93  fTable[slot].fValue = value;
94  fTally++;
95  if (HighWaterMark())
96  Expand(2 * fSize);
97  } else
98  Error("Add", "key %lld is not unique", key);
99 }
100 
101 ////////////////////////////////////////////////////////////////////////////////
102 /// Add an (key,value) pair to the table. The key should be unique.
103 /// If the 'slot' is open, use it to store the value,
104 /// otherwise revert to Add(hash,key,value)
105 /// This is usually used in conjunction with GetValue with 3 parameters:
106 /// ~~~ {.cpp}
107 /// if ((idx = (ULong64_t)fMap->GetValue(hash, key, slot)) != 0) {
108 /// ...
109 /// } else {
110 /// fMap->AddAt(slot,hash,key,value);
111 /// }
112 /// ~~~
113 
114 void TExMap::AddAt(UInt_t slot, ULong64_t hash, Long64_t key, Long64_t value)
115 {
116  if (!fTable) return;
117 
118  if (!fTable[slot].InUse()) {
119  fTable[slot].SetHash(hash);
120  fTable[slot].fKey = key;
121  fTable[slot].fValue = value;
122  fTally++;
123  if (HighWaterMark())
124  Expand(2 * fSize);
125  } else {
126  Add(hash,key,value);
127  }
128 }
129 
130 ////////////////////////////////////////////////////////////////////////////////
131 /// Return a reference to the value belonging to the key with the
132 /// specified hash value. If the key does not exist it will be added.
133 /// NOTE: the reference will be invalidated an Expand() triggered by
134 /// an Add() or another operator() call.
135 
137 {
138  static Long64_t err;
139  if (!fTable) {
140  Error("operator()", "fTable==0, should never happen");
141  return err;
142  }
143 
144  Int_t slot = FindElement(hash, key);
145  if (!fTable[slot].InUse()) {
146  fTable[slot].SetHash(hash);
147  fTable[slot].fKey = key;
148  fTable[slot].fValue = 0;
149  fTally++;
150  if (HighWaterMark()) {
151  Expand(2 * fSize);
152  slot = FindElement(hash, key);
153  }
154  }
155  return fTable[slot].fValue;
156 }
157 
158 ////////////////////////////////////////////////////////////////////////////////
159 /// Delete all entries stored in the TExMap.
160 
162 {
163  memset(fTable,0,sizeof(Assoc_t)*fSize);
164  fTally = 0;
165 }
166 
167 ////////////////////////////////////////////////////////////////////////////////
168 /// Return the value belonging to specified key and hash value. If key not
169 /// found return 0.
170 
172 {
173  if (!fTable) return 0;
174 
175  hash |= 0x1;
176  Int_t slot = Int_t(hash % fSize);
177  Int_t firstSlot = slot;
178  do {
179  if (!fTable[slot].InUse()) return 0;
180  if (key == fTable[slot].fKey) return fTable[slot].fValue;
181  if (++slot == fSize) slot = 0;
182  } while (firstSlot != slot);
183 
184  Error("GetValue", "table full");
185  return 0;
186 }
187 
188 ////////////////////////////////////////////////////////////////////////////////
189 /// Return the value belonging to specified key and hash value. If key not
190 /// found return 0.
191 /// In 'slot', return the index of the slot used or the first empty slot.
192 /// (to be used with AddAt).
193 
195 {
196  if (!fTable) { slot = 0; return 0; }
197 
198  hash |= 0x1;
199  slot = Int_t(hash % fSize);
200  UInt_t firstSlot = slot;
201  do {
202  if (!fTable[slot].InUse()) return 0;
203  if (key == fTable[slot].fKey) return fTable[slot].fValue;
204  if (++slot == (UInt_t)fSize) slot = 0;
205  } while (firstSlot != slot);
206 
207  Error("GetValue", "table full");
208  return 0;
209 }
210 
211 ////////////////////////////////////////////////////////////////////////////////
212 /// Remove entry with specified key from the TExMap.
213 
215 {
216  if (!fTable)
217  return;
218 
219  Int_t i = FindElement(hash, key);
220  if (!fTable[i].InUse()) {
221  Error("Remove", "key %lld not found at %d", key, i);
222  return;
223  }
224 
225  fTable[i].Clear();
226  FixCollisions(i);
227  fTally--;
228 }
229 
230 ////////////////////////////////////////////////////////////////////////////////
231 /// Find an entry with specified hash and key in the TExMap.
232 /// Returns the slot of the key or the next empty slot.
233 
235 {
236  if (!fTable) return 0;
237 
238  hash |= 0x1;
239  Int_t slot = Int_t(hash % fSize);
240  Int_t firstSlot = slot;
241  do {
242  if (!fTable[slot].InUse()) return slot;
243  if (key == fTable[slot].fKey) return slot;
244  if (++slot == fSize) slot = 0;
245  } while (firstSlot != slot);
246 
247  Error("FindElement", "table full");
248  return 0;
249 }
250 
251 ////////////////////////////////////////////////////////////////////////////////
252 /// Rehash the map in case an entry has been removed.
253 
255 {
256  Int_t oldIndex, nextIndex;
257  Assoc_t nextObject;
258 
259  for (oldIndex = index+1; ;oldIndex++) {
260  if (oldIndex >= fSize)
261  oldIndex = 0;
262  nextObject = fTable[oldIndex];
263  if (!nextObject.InUse())
264  break;
265  nextIndex = FindElement(nextObject.GetHash(), nextObject.fKey);
266  if (nextIndex != oldIndex) {
267  fTable[nextIndex] = nextObject;
268  fTable[oldIndex].Clear();
269  }
270  }
271 }
272 
273 ////////////////////////////////////////////////////////////////////////////////
274 /// Expand the TExMap.
275 
276 void TExMap::Expand(Int_t newSize)
277 {
278  Int_t i;
279  Assoc_t *oldTable = fTable;
280  Int_t oldsize = fSize;
281  newSize = (Int_t)TMath::NextPrime(newSize);
282  fTable = new Assoc_t [newSize];
283 
284  for (i = newSize; --i >= 0;) {
285  fTable[i].Clear();
286  }
287 
288  fSize = newSize;
289  for (i = 0; i < oldsize; i++)
290  if (oldTable[i].InUse()) {
291  Int_t slot = FindElement(oldTable[i].GetHash(), oldTable[i].fKey);
292  if (!fTable[slot].InUse())
293  fTable[slot] = oldTable[i];
294  else
295  Error("Expand", "slot %d not empty (should never happen)", slot);
296  }
297  delete [] oldTable;
298 }
299 
300 ////////////////////////////////////////////////////////////////////////////////
301 /// Stream all objects in the collection to or from the I/O buffer.
302 
303 void TExMap::Streamer(TBuffer &b)
304 {
305  Int_t i;
306  UInt_t R__s, R__c;
307 
308  if (b.IsReading()) {
309  Version_t R__v = b.ReadVersion(&R__s, &R__c);
310  TObject::Streamer(b);
311 
312  if (R__v >= 3) {
313  // new custom streamer with slots indices stored (Long64_t version).
314  Int_t size, tally;
315  b >> size;
316  Expand(size);
317  b >> tally;
318  Int_t slot;
319  ULong64_t hash;
320  Long64_t key, value;
321  for (i = 0; i < tally; ++i) {
322  b >> slot;
323  b >> hash;
324  b >> key;
325  b >> value;
326  Assoc_t *assoc = fTable + slot;
327  assoc->SetHash(hash);
328  assoc->fKey = key;
329  assoc->fValue = value;
330  }
331  fTally = tally;
332  } else if (R__v >= 2) {
333  // new custom streamer with slots indices stored.
334  Int_t size, tally;
335  b >> size;
336  Expand(size);
337  b >> tally;
338  Int_t slot;
339  ULong_t hash;
340  Long_t key, value;
341  for (i = 0; i < tally; ++i) {
342  b >> slot;
343  b >> hash;
344  b >> key;
345  b >> value;
346  Assoc_t* assoc = fTable + slot;
347  assoc->SetHash(hash);
348  assoc->fKey = key;
349  assoc->fValue = value;
350  }
351  fTally = tally;
352  } else {
353  // old custom streamer that only allows slow dynamic rebuild of TExMap:
354  Int_t n;
355  b >> n;
356  ULong_t hash;
357  Long_t key, value;
358  for (i = 0; i < n; i++) {
359  b >> hash;
360  b >> key;
361  b >> value;
362  Add(hash, key, value);
363  }
364  }
365  b.CheckByteCount(R__s, R__c, TExMap::IsA());
366  } else {
367  R__c = b.WriteVersion(TExMap::IsA(), kTRUE);
368  // new custom streamer stores slots indices
369  TObject::Streamer(b);
370  b << fSize;
371  b << fTally;
372 
373  for (i=0; i < fSize; i++) {
374  if (!fTable[i].InUse()) continue;
375  b << i;
376  b << fTable[i].GetHash();
377  b << fTable[i].fKey;
378  b << fTable[i].fValue;
379  }
380  b.SetByteCount(R__c, kTRUE);
381  }
382 }
383 
384 
386 
387 ////////////////////////////////////////////////////////////////////////////////
388 /// Create TExMap iterator.
389 
390 TExMapIter::TExMapIter(const TExMap *map) : fMap(map), fCursor(0)
391 {
392 }
393 
394 ////////////////////////////////////////////////////////////////////////////////
395 /// Overloaded assignment operator.
396 
398 {
399  if (this != &rhs) {
400  fMap = rhs.fMap;
401  fCursor = rhs.fCursor;
402  }
403  return *this;
404 }
405 
406 ////////////////////////////////////////////////////////////////////////////////
407 /// Get next entry from TExMap. Returns kFALSE at end of map.
408 
410 {
411  while (fCursor < fMap->fSize && !fMap->fTable[fCursor].InUse())
412  fCursor++;
413 
414  if (fCursor == fMap->fSize)
415  return kFALSE;
416 
417  hash = fMap->fTable[fCursor].GetHash();
418  key = fMap->fTable[fCursor].fKey;
419  value = fMap->fTable[fCursor].fValue;
420  fCursor++;
421 
422  return kTRUE;
423 }
424 
425 ////////////////////////////////////////////////////////////////////////////////
426 /// Get next entry from TExMap. Returns kFALSE at end of map.
427 
429 {
430  ULong64_t hash;
431  return Next(hash, key, value);
432 }
const TExMap * fMap
Definition: TExMap.h:90
void Add(ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table. The key should be unique.
Definition: TExMap.cxx:85
void Remove(ULong64_t hash, Long64_t key)
Remove entry with specified key from the TExMap.
Definition: TExMap.cxx:214
long long Long64_t
Definition: RtypesCore.h:69
Bool_t IsReading() const
Definition: TBuffer.h:81
short Version_t
Definition: RtypesCore.h:61
const char Option_t
Definition: RtypesCore.h:62
Int_t FindElement(ULong64_t hash, Long64_t key)
Find an entry with specified hash and key in the TExMap.
Definition: TExMap.cxx:234
Buffer base class used for serializing objects.
Definition: TBuffer.h:40
virtual Int_t CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)=0
int Int_t
Definition: RtypesCore.h:41
bool Bool_t
Definition: RtypesCore.h:59
const Bool_t kFALSE
Definition: Rtypes.h:92
Long64_t fKey
Definition: TExMap.h:44
virtual UInt_t WriteVersion(const TClass *cl, Bool_t useBcnt=kFALSE)=0
Int_t fCursor
Definition: TExMap.h:91
Assoc_t * fTable
Definition: TExMap.h:52
Int_t fSize
Definition: TExMap.h:53
ClassImp(TExMap) TExMap
Create a TExMap.
Definition: TExMap.cxx:25
void SetHash(ULong64_t h)
Definition: TExMap.h:46
TObject & operator=(const TObject &rhs)
TObject assignment operator.
Definition: TObject.cxx:102
virtual void Error(const char *method, const char *msgfmt,...) const
Issue error message.
Definition: TObject.cxx:918
~TExMap()
Delete TExMap.
Definition: TExMap.cxx:77
Long64_t GetValue(ULong64_t hash, Long64_t key)
Return the value belonging to specified key and hash value.
Definition: TExMap.cxx:171
TClass * IsA() const
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t fTally
Definition: TExMap.h:54
Long64_t & operator()(ULong64_t hash, Long64_t key)
Return a reference to the value belonging to the key with the specified hash value.
Definition: TExMap.cxx:136
Bool_t HighWaterMark()
Definition: TExMap.h:56
virtual void SetByteCount(UInt_t cntpos, Bool_t packInVersion=kFALSE)=0
void Delete(Option_t *opt="")
Delete all entries stored in the TExMap.
Definition: TExMap.cxx:161
TExMap & operator=(const TExMap &)
Assignment operator.
Definition: TExMap.cxx:62
long Long_t
Definition: RtypesCore.h:50
void FixCollisions(Int_t index)
Rehash the map in case an entry has been removed.
Definition: TExMap.cxx:254
Long_t NextPrime(Long_t x)
TMath Base functions.
Definition: TMathBase.cxx:29
TExMapIter & operator=(const TExMapIter &)
Overloaded assignment operator.
Definition: TExMap.cxx:397
Bool_t InUse() const
Definition: TExMap.h:48
Long64_t fValue
Definition: TExMap.h:45
unsigned long long ULong64_t
Definition: RtypesCore.h:70
unsigned long ULong_t
Definition: RtypesCore.h:51
Mother of all ROOT objects.
Definition: TObject.h:58
Bool_t Next(ULong64_t &hash, Long64_t &key, Long64_t &value)
Get next entry from TExMap. Returns kFALSE at end of map.
Definition: TExMap.cxx:409
void Clear()
Definition: TExMap.h:49
TExMap(Int_t mapSize=100)
ULong64_t GetHash() const
Definition: TExMap.h:47
const Bool_t kTRUE
Definition: Rtypes.h:91
float value
Definition: math.cpp:443
const Int_t n
Definition: legend1.C:16
This class stores a (key,value) pair using an external hash.
Definition: TExMap.h:35
void Expand(Int_t newsize)
Expand the TExMap.
Definition: TExMap.cxx:276
void AddAt(UInt_t slot, ULong64_t hash, Long64_t key, Long64_t value)
Add an (key,value) pair to the table.
Definition: TExMap.cxx:114
virtual Version_t ReadVersion(UInt_t *start=0, UInt_t *bcnt=0, const TClass *cl=0)=0