CMS 3D CMS Logo

Trie.h
Go to the documentation of this file.
1 #ifndef DataFormats_Common_Trie_h
2 #define DataFormats_Common_Trie_h
3 /*
4 **
5 **
6 ** Copyright (C) 2006 Julien Lemoine
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU Lesser General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU Lesser General Public License for more details.
16 **
17 ** You should have received a copy of the GNU Lesser General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 **
21 **
22 ** modified by Vincenzo Innocente on 15/08/2007
23 **
24 */
25 
26 #include <list>
27 #include <string>
28 
29 namespace edm {
30  // fwd declaration
31  template <typename T>
32  class TrieNode;
33 
38  template <typename T>
39  class TrieFactory {
40  public:
41  TrieFactory(unsigned paquetSize);
42  ~TrieFactory();
43 
44  private:
46  TrieFactory() = delete;
48  TrieFactory(const TrieFactory &e) = delete;
50  TrieFactory &operator=(const TrieFactory &e) = delete;
51 
52  public:
53  TrieNode<T> *newNode(const T &value);
54  void clear();
55 
56  private:
57  unsigned _paquetSize;
58  std::list<TrieNode<T> *> _allocatedNodes;
61  };
62 } // namespace edm
63 
64 namespace edm {
65  template <typename T>
66  class TrieNodeIter;
67 
73  template <typename T>
74  class TrieNode {
75  public:
77 
78  TrieNode();
79  ~TrieNode();
80 
81  private:
83  TrieNode(const TrieNode &e) = delete;
85  TrieNode &operator=(const TrieNode &e) = delete;
86 
87  public:
89  void setValue(const T &val);
91  const T &value() const;
92 
94  const TrieNode<T> *brother() const;
97  unsigned char brotherLabel() const;
98 
100  TrieNodeIter<T> begin() const;
102  TrieNodeIter<T> end() const;
103 
104  // get first sub Node
105  const TrieNode<T> *subNode() const;
106  TrieNode<T> *subNode();
107  unsigned char subNodeLabel() const;
108 
109  // Looking for a sub node
110  const TrieNode<T> *subNodeByLabel(unsigned char chr) const;
111  TrieNode<T> *subNodeByLabel(unsigned char chr);
112 
113  // add an edge
114  void addSubNode(unsigned char chr, TrieNode<T> *node);
115 
117  void display(std::ostream &os, unsigned offset, unsigned char label) const;
118 
120  void clear();
121 
122  private:
123  template <typename Node>
124  Node _sequentialSearch(Node first, unsigned char label, unsigned char val) const;
126  void _setBrother(TrieNode<T> *brother, unsigned char brotherLabel);
128  void _addBrother(unsigned char chr, TrieNode<T> *brother);
133  const TrieNode<T> *_getBrother(unsigned char chr) const;
138  TrieNode<T> *_getBrother(unsigned char chr);
139 
140  private:
144  unsigned char _brotherLabel;
148  unsigned char _firstSubNodeLabel;
151  };
152 } // namespace edm
153 
154 #include <ostream>
155 
156 namespace edm {
157  //fwd declaration
158  template <typename T>
159  class TrieFactory;
160  template <typename T>
161  class TrieNode;
162 
167  template <typename T>
168  class Trie {
169  public:
172  Trie(const T &empty);
173  ~Trie();
174 
175  private:
177  Trie() = delete;
179  Trie(const Trie &e) = delete;
181  Trie &operator=(const Trie &e) = delete;
182 
183  public:
186  void insert(std::string const &str, const T &value);
187  void insert(const char *str, unsigned strLen, const T &value);
190  void setEntry(std::string const &str, const T &value);
191  void setEntry(const char *str, unsigned strLen, const T &value);
193  const T &find(std::string const &str) const;
194  const T &find(const char *str, unsigned strLen) const;
196  const TrieNode<T> *node(std::string const &str) const;
197  const TrieNode<T> *node(const char *str, unsigned strLen) const;
199  const TrieNode<T> *initialNode() const;
201  void display(std::ostream &os);
203  void clear();
204 
205  private:
206  TrieNode<T> *_addEntry(const char *str, unsigned strLen);
207 
208  private:
215  };
216 } // namespace edm
217 
218 #include <boost/iterator/iterator_facade.hpp>
219 
220 #include <string>
221 #include <ostream>
222 
223 // iterators and visitors
224 
225 namespace edm {
226 
227  template <typename T>
228  class TrieNodeIter : public boost::iterator_facade<TrieNodeIter<T>, TrieNode<T> const, boost::forward_traversal_tag> {
229  public:
230  typedef TrieNodeIter<T> self;
231  typedef TrieNode<T> const node_base;
232  TrieNodeIter() : m_node(nullptr), m_label(0) {}
233 
234  explicit TrieNodeIter(node_base *p) : m_node(p ? p->subNode() : nullptr), m_label(p ? p->subNodeLabel() : 0) {}
235 
236  unsigned char label() const { return m_label; }
237 
238  private:
240 
241  void increment() {
243  m_node = m_node->brother();
244  }
245 
246  bool equal(self const &other) const { return this->m_node == other.m_node; }
247 
248  node_base &dereference() const { return *m_node; }
249 
251  unsigned char m_label;
252  };
253 
255  template <typename V, typename T>
256  void walkTrie(V &v, TrieNode<T> const &n, std::string const &label = "") {
257  typedef TrieNodeIter<T> node_iterator;
258  node_iterator e;
259  for (node_iterator p(&n); p != e; ++p) {
260  v((*p).value(), label + (char)p.label());
261  walkTrie(v, *p, label + (char)p.label());
262  }
263  }
264 
266  template <typename V, typename T>
267  bool iterateTrieLeaves(V &v, TrieNode<T> const &n, std::string const &label = "") {
268  typedef TrieNodeIter<T> node_iterator;
269  node_iterator e;
270  node_iterator p(&n);
271  if (p == e)
272  return true;
273  for (; p != e; ++p) {
274  if (iterateTrieLeaves(v, *p, label + (char)p.label()))
275  v((*p).value(), label + (char)p.label());
276  }
277  return false;
278  }
279 
280 } // namespace edm
281 
282 //
283 //----------------------------------------------------------------
284 //
285 // implementations
286 
287 template <typename T>
289  : _paquetSize(paquetSize), _lastNodes(nullptr), _nbUsedInLastNodes(0) {
290  _lastNodes = new TrieNode<T>[paquetSize];
291 }
292 
293 template <typename T>
295  typename std::list<TrieNode<T> *>::const_iterator it;
296 
297  for (it = _allocatedNodes.begin(); it != _allocatedNodes.end(); ++it)
298  delete[] * it;
299  if (_lastNodes)
300  delete[] _lastNodes;
301 }
302 
303 template <typename T>
305  if (_nbUsedInLastNodes == _paquetSize) {
306  _allocatedNodes.push_back(_lastNodes);
307  _nbUsedInLastNodes = 0;
308  _lastNodes = new TrieNode<T>[_paquetSize];
309  }
310  TrieNode<T> *res = &_lastNodes[_nbUsedInLastNodes];
311  ++_nbUsedInLastNodes;
312  res->setValue(value);
313  res->clear();
314  return res;
315 }
316 
317 template <typename T>
319  typename std::list<TrieNode<T> *>::const_iterator it;
320  for (it = _allocatedNodes.begin(); it != _allocatedNodes.end(); ++it)
321  delete[] * it;
322  _allocatedNodes.clear();
323  _nbUsedInLastNodes = 0;
324 }
325 
326 template <typename T>
328  : _brother(nullptr),
329  _brotherLabel(0),
330  _firstSubNode(nullptr),
331  _firstSubNodeLabel(0),
332  _value()
335 {}
336 
337 template <typename T>
339  // do not delete _brother and _firstSubNode because they are
340  // allocated by factory (TrieFactory) and factory will delete them
341 }
342 
343 template <typename T>
345  return const_iterator(this);
346 }
347 template <typename T>
349  return const_iterator(nullptr);
350 }
351 
352 template <typename T>
354  _value = val;
355 }
356 
357 template <typename T>
358 const T &edm::TrieNode<T>::value() const {
359  return _value;
360 }
361 
362 template <typename T>
364  return _brother;
365 }
366 
367 template <typename T>
369  return _brother;
370 }
371 
372 template <typename T>
373 const edm::TrieNode<T> *edm::TrieNode<T>::_getBrother(unsigned char chr) const {
374  const TrieNode<T> *brother = _brother;
375  return _sequentialSearch(brother, _brotherLabel, chr);
376 }
377 
378 template <typename T>
380  return _sequentialSearch(_brother, _brotherLabel, chr);
381 }
382 
383 template <typename T>
384 void edm::TrieNode<T>::_addBrother(unsigned char chr, TrieNode<T> *brother) {
385  if (!_brother || _brotherLabel > chr) {
386  brother->_setBrother(_brother, _brotherLabel);
387  _brother = brother;
388  _brotherLabel = chr;
389  } else
390  _brother->_addBrother(chr, brother);
391 }
392 
393 template <typename T>
394 unsigned char edm::TrieNode<T>::brotherLabel() const {
395  return _brotherLabel;
396 }
397 
398 template <typename T>
400  return _firstSubNode;
401 }
402 
403 template <typename T>
405  return _firstSubNode;
406 }
407 
408 template <typename T>
409 unsigned char edm::TrieNode<T>::subNodeLabel() const {
410  return _firstSubNodeLabel;
411 }
412 
413 template <typename T>
414 const edm::TrieNode<T> *edm::TrieNode<T>::subNodeByLabel(unsigned char chr) const {
415  const TrieNode<T> *first = _firstSubNode;
416  return _sequentialSearch(first, _firstSubNodeLabel, chr);
417 }
418 
419 template <typename T>
421  return _sequentialSearch(_firstSubNode, _firstSubNodeLabel, chr);
422 }
423 
424 template <typename T>
425 void edm::TrieNode<T>::addSubNode(unsigned char chr, TrieNode<T> *node) {
426  if (!_firstSubNode || _firstSubNodeLabel > chr) {
427  node->_setBrother(_firstSubNode, _firstSubNodeLabel);
428  _firstSubNode = node;
429  _firstSubNodeLabel = chr;
430  } else
431  _firstSubNode->_addBrother(chr, node);
432 }
433 
434 template <typename T>
435 template <typename Node>
436 inline Node edm::TrieNode<T>::_sequentialSearch(Node first, unsigned char label, unsigned char val) const {
437  if (first && label <= val) {
438  if (label == val)
439  return first;
440  return first->_getBrother(val);
441  }
442  return 0x0;
443 }
444 
445 template <typename T>
446 void edm::TrieNode<T>::_setBrother(TrieNode<T> *brother, unsigned char brotherLabel) {
447  _brother = brother;
448  _brotherLabel = brotherLabel;
449 }
450 
451 template <typename T>
452 void edm::TrieNode<T>::display(std::ostream &os, unsigned offset, unsigned char label) const {
453  unsigned int i;
454  for (i = 0; i < offset; ++i)
455  os << " ";
456  if (label)
457  os << "label[" << label << "] ";
458  os << "value[" << _value << "]" << std::endl;
459  if (_firstSubNode)
460  _firstSubNode->display(os, offset + 2, _firstSubNodeLabel);
461  if (_brother)
462  _brother->display(os, offset, _brotherLabel);
463 }
464 
465 template <typename T>
467  _brother = nullptr;
468  _brotherLabel = 0;
469  _firstSubNode = nullptr;
470  _firstSubNodeLabel = 0;
471 }
472 
473 #include <vector>
474 #include <algorithm>
475 #include <string>
476 #include <cassert>
477 
479 
480 namespace edm {
481  namespace detailsTrie {
482  inline void errorInsert(std::string const &key) {
484  "Trie::insert called with a key already in collection;\n"
485  "key value: ",
486  key.c_str());
487  }
488  } // namespace detailsTrie
489 } // namespace edm
490 
491 template <typename T>
492 edm::Trie<T>::Trie(const T &empty) : _empty(empty), _factory(nullptr), _initialNode(nullptr) {
493  // initialize nodes by paquets of 10000
494  _factory = new TrieFactory<T>(10000);
495  _initialNode = _factory->newNode(_empty);
496 }
497 
498 template <typename T>
500  delete _factory;
501 }
502 
503 template <typename T>
505  setEntry(str.c_str(), str.size(), value);
506 }
507 template <typename T>
508 void edm::Trie<T>::setEntry(const char *str, unsigned strLen, const T &value) {
509  TrieNode<T> *node = _addEntry(str, strLen);
510  node->setValue(value);
511 }
512 
513 template <typename T>
514 edm::TrieNode<T> *edm::Trie<T>::_addEntry(const char *str, unsigned strLen) {
515  unsigned pos = 0;
516  bool found = true;
517  TrieNode<T> *node = _initialNode, *previous = nullptr;
518 
519  // Look for the part of the word which is in Trie
520  while (found && pos < strLen) {
521  found = false;
522  previous = node;
523  node = node->subNodeByLabel(str[pos]);
524  if (node) {
525  found = true;
526  ++pos;
527  }
528  }
529 
530  // Add part of the word which is not in Trie
531  if (!node || pos != strLen) {
532  node = previous;
533  for (unsigned i = pos; i < strLen; ++i) {
534  TrieNode<T> *newNode = _factory->newNode(_empty);
535  node->addSubNode(str[pos], newNode);
536  node = newNode;
537  ++pos;
538  }
539  }
540  assert(node != nullptr);
541  return node;
542 }
543 
544 template <typename T>
546  insert(str.c_str(), str.size(), value);
547 }
548 
549 template <typename T>
550 void edm::Trie<T>::insert(const char *str, unsigned strLen, const T &value) {
551  TrieNode<T> *node = _addEntry(str, strLen);
552 
553  // Set the value on the last node
554  if (node && node->value() != _empty)
556  node->setValue(value);
557 }
558 
559 template <typename T>
560 const T &edm::Trie<T>::find(std::string const &str) const {
561  return find(str.c_str(), str.size());
562 }
563 
564 template <typename T>
565 const T &edm::Trie<T>::find(const char *str, unsigned strLen) const {
566  unsigned pos = 0;
567  bool found = true;
568  const TrieNode<T> *node = _initialNode;
569 
570  while (found && pos < strLen) {
571  found = false;
572  node = node->subNodeByLabel(str[pos]);
573  if (node) {
574  found = true;
575  ++pos;
576  }
577  }
578  if (node && pos == strLen) // The word is complet in the automaton
579  return node->value();
580  return _empty;
581 }
582 
583 template <typename T>
585  return node(str.c_str(), str.size());
586 }
587 
588 template <typename T>
589 edm::TrieNode<T> const *edm::Trie<T>::node(const char *str, unsigned strLen) const {
590  unsigned pos = 0;
591  bool found = true;
592  const TrieNode<T> *node = _initialNode;
593 
594  while (found && pos < strLen) {
595  found = false;
596  node = node->subNodeByLabel(str[pos]);
597  if (node) {
598  found = true;
599  ++pos;
600  }
601  }
602  return node;
603 }
604 
605 template <typename T>
607  return _initialNode;
608 }
609 
610 template <typename T>
612  _factory->clear();
613  _initialNode = _factory->newNode(_empty);
614 }
615 
616 template <typename T>
617 void edm::Trie<T>::display(std::ostream &os) {
618  if (_initialNode)
619  _initialNode->display(os, 0, 0);
620 }
621 
622 #endif // DataFormats_Common_Trie_h
void clear()
clear content of TrieNode
Definition: Trie.h:466
unsigned char brotherLabel() const
get brother label
Definition: Trie.h:394
unsigned char m_label
Definition: Trie.h:251
~Trie()
Definition: Trie.h:499
void display(std::ostream &os, unsigned offset, unsigned char label) const
display content of node in output stream
Definition: Trie.h:452
const TrieNode< T > * subNode() const
Definition: Trie.h:399
std::list< TrieNode< T > * > _allocatedNodes
Definition: Trie.h:58
TGeoNode Node
this class represent the node of a trie, it contains a link to a sub node and a link to a brother (no...
Definition: Trie.h:32
void _setBrother(TrieNode< T > *brother, unsigned char brotherLabel)
set brother (used by sort)
Definition: Trie.h:446
void addSubNode(unsigned char chr, TrieNode< T > *node)
Definition: Trie.h:425
TrieNode< T > * _lastNodes
Definition: Trie.h:59
const T & find(std::string const &str) const
get an entry in the Trie
Definition: Trie.h:560
void setValue(const T &val)
set value associed to node
Definition: Trie.h:353
TrieNodeIter< T > end() const
mark end of iteration (std conforming)
Definition: Trie.h:348
node_base & dereference() const
Definition: Trie.h:248
Trie()=delete
avoid default constructor
unsigned char _firstSubNodeLabel
character to go to first subnode
Definition: Trie.h:148
void clear()
Definition: Trie.h:318
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
assert(be >=bs)
TrieNode< T > * _firstSubNode
pointer to first sub node
Definition: Trie.h:146
Definition: Electron.h:6
TrieNode< T > * newNode(const T &value)
Definition: Trie.h:304
static void throwThis(Code category, char const *message0="", char const *message1="", char const *message2="", char const *message3="", char const *message4="")
Definition: EDMException.cc:86
TrieNode()
Definition: Trie.h:327
bool iterateTrieLeaves(V &v, TrieNode< T > const &n, std::string const &label="")
visits only leaf nodes
Definition: Trie.h:267
void display(std::ostream &os)
display content of trie in output stream
Definition: Trie.h:617
void insert(std::string const &str, const T &value)
Definition: Trie.h:545
TrieNode & operator=(const TrieNode &e)=delete
avoid affectation operator
char const * label
~TrieNode()
Definition: Trie.h:338
bool equal(self const &other) const
Definition: Trie.h:246
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t V
unsigned char subNodeLabel() const
Definition: Trie.h:409
void setEntry(std::string const &str, const T &value)
Definition: Trie.h:504
unsigned char label() const
Definition: Trie.h:236
TrieNode< T > const node_base
Definition: Trie.h:231
void increment()
Definition: Trie.h:241
const TrieNode< T > * brother() const
get brother (return 0x0 this node has no brother)
Definition: Trie.h:363
void _addBrother(unsigned char chr, TrieNode< T > *brother)
add a new brother
Definition: Trie.h:384
T _empty
value returned when no match is found in trie
Definition: Trie.h:210
const TrieNode< T > * _getBrother(unsigned char chr) const
Definition: Trie.h:373
Definition: value.py:1
bool insert(Storage &iStorage, ItemType *iItem, const IdTag &iIdTag)
Definition: HCMethods.h:50
friend class boost::iterator_core_access
Definition: Trie.h:239
TrieNodeIter< T > const_iterator
Definition: Trie.h:76
void errorInsert(std::string const &key)
Definition: Trie.h:482
void walkTrie(V &v, TrieNode< T > const &n, std::string const &label="")
visit each node of the trie
Definition: Trie.h:256
unsigned _nbUsedInLastNodes
Definition: Trie.h:60
const TrieNode< T > * initialNode() const
get initial TrieNode
Definition: Trie.h:606
Trie & operator=(const Trie &e)=delete
avoid affectation operator
Node _sequentialSearch(Node first, unsigned char label, unsigned char val) const
Definition: Trie.h:436
const TrieNode< T > * subNodeByLabel(unsigned char chr) const
Definition: Trie.h:414
void clear()
clear the content of trie
Definition: Trie.h:611
TrieNodeIter(node_base *p)
Definition: Trie.h:234
TrieFactory< T > * _factory
factory
Definition: Trie.h:212
TrieFactory & operator=(const TrieFactory &e)=delete
avoid affectation operator
HLT enums.
TrieNode< T > * _initialNode
first node of trie
Definition: Trie.h:214
T _value
value associed to this node
Definition: Trie.h:150
const T & value() const
get value associed to node
Definition: Trie.h:358
node_base * m_node
Definition: Trie.h:250
TrieFactory()=delete
avoid default constructor
unsigned _paquetSize
Definition: Trie.h:57
T first(std::pair< T, U > const &p)
#define str(s)
long double T
unsigned char _brotherLabel
character to go to brother (node with same father as this one)
Definition: Trie.h:144
TrieNode< T > * _addEntry(const char *str, unsigned strLen)
Definition: Trie.h:514
TrieNodeIter< T > begin() const
initialize subnode iterator (std conforming)
Definition: Trie.h:344
const TrieNode< T > * node(std::string const &str) const
get node matching a string
Definition: Trie.h:584
TrieNode< T > * _brother
pointer to brother (node with same father as this one)
Definition: Trie.h:142