30 #include <boost/concept/assert.hpp> 
   31 #include <boost/concept_check.hpp> 
   32 #include <type_traits> 
   39 BOOST_CONCEPT_ASSERT((boost::ForwardIterator<NameTree::const_iterator>));
 
   42 #ifdef HAVE_IS_DEFAULT_CONSTRUCTIBLE 
   43 static_assert(std::is_default_constructible<NameTree::const_iterator>::value,
 
   44               "NameTree::const_iterator must be default-constructible");
 
   46 BOOST_CONCEPT_ASSERT((boost::DefaultConstructible<NameTree::const_iterator>));
 
   47 #endif // HAVE_IS_DEFAULT_CONSTRUCTIBLE 
   55   compute(
const char* buffer, 
size_t length)
 
   57     return static_cast<size_t>(
CityHash32(buffer, length));
 
   65   compute(
const char* buffer, 
size_t length)
 
   67     return static_cast<size_t>(
CityHash64(buffer, length));
 
   80   size_t hashUpdate = 0;
 
   82   for (Name::const_iterator it = prefix.begin(); it != prefix.end(); it++)
 
   84       const char* wireFormat = 
reinterpret_cast<const char*
>( it->wire() );
 
   85       hashUpdate = CityHash::compute(wireFormat, it->size());
 
   86       hashValue ^= hashUpdate;
 
   98   size_t hashUpdate = 0;
 
  100   std::vector<size_t> hashValueSet;
 
  101   hashValueSet.push_back(hashValue);
 
  103   for (Name::const_iterator it = prefix.begin(); it != prefix.end(); it++)
 
  105       const char* wireFormat = 
reinterpret_cast<const char*
>( it->wire() );
 
  106       hashUpdate = CityHash::compute(wireFormat, it->size());
 
  107       hashValue ^= hashUpdate;
 
  108       hashValueSet.push_back(hashValue);
 
  118   , m_nBuckets(nBuckets)
 
  119   , m_minNBuckets(nBuckets)
 
  120   , m_enlargeLoadFactor(0.5)       
 
  122   , m_shrinkLoadFactor(0.1) 
 
  123   , m_shrinkFactor(0.5)     
 
  124   , m_endIterator(FULL_ENUMERATE_TYPE, *this, m_end)
 
  126   m_enlargeThreshold = 
static_cast<size_t>(m_enlargeLoadFactor *
 
  127                                           static_cast<double>(m_nBuckets));
 
  129   m_shrinkThreshold = 
static_cast<size_t>(m_shrinkLoadFactor *
 
  130                                           static_cast<double>(m_nBuckets));
 
  135   for (
size_t i = 0; i < m_nBuckets; i++)
 
  141   for (
size_t i = 0; i < m_nBuckets; i++)
 
  143       if (m_buckets[i] != 0) {
 
  152 std::pair<shared_ptr<name_tree::Entry>, 
bool>
 
  153 NameTree::insert(
const Name& prefix)
 
  158   size_t loc = hashValue % m_nBuckets;
 
  160   NFD_LOG_TRACE(
"Name " << prefix << 
" hash value = " << hashValue << 
"  location = " << loc);
 
  166   for (node = m_buckets[loc]; node != 0; node = node->
m_next)
 
  168       if (static_cast<bool>(node->
m_entry))
 
  170           if (prefix == node->
m_entry->m_prefix)
 
  172               return std::make_pair(node->
m_entry, 
false); 
 
  178   NFD_LOG_TRACE(
"Did not find " << prefix << 
", need to insert it to the table");
 
  182   node = 
new name_tree::Node();
 
  187       m_buckets[loc] = node;
 
  195   shared_ptr<name_tree::Entry> entry(make_shared<name_tree::Entry>(prefix));
 
  196   entry->setHash(hashValue);
 
  198   entry->m_node = node; 
 
  200   return std::make_pair(entry, 
true); 
 
  204 shared_ptr<name_tree::Entry>
 
  209   shared_ptr<name_tree::Entry> entry;
 
  210   shared_ptr<name_tree::Entry> parent;
 
  212   for (
size_t i = 0; i <= prefix.size(); i++)
 
  214       Name temp = prefix.getPrefix(i);
 
  217       std::pair<shared_ptr<name_tree::Entry>, 
bool> ret = insert(temp);
 
  220       if (ret.second == 
true)
 
  223           entry->m_parent = parent;
 
  225           if (static_cast<bool>(parent))
 
  227               parent->m_children.push_back(entry);
 
  231       if (m_nItems > m_enlargeThreshold)
 
  233           resize(m_enlargeFactor * m_nBuckets);
 
  242 shared_ptr<name_tree::Entry>
 
  248   size_t loc = hashValue % m_nBuckets;
 
  250   NFD_LOG_TRACE(
"Name " << prefix << 
" hash value = " << hashValue <<
 
  251                 "  location = " << loc);
 
  253   shared_ptr<name_tree::Entry> entry;
 
  256   for (node = m_buckets[loc]; node != 0; node = node->
m_next)
 
  259       if (static_cast<bool>(entry))
 
  261           if (hashValue == entry->getHash() && prefix == entry->getPrefix())
 
  274 shared_ptr<name_tree::Entry>
 
  279   shared_ptr<name_tree::Entry> entry;
 
  282   size_t hashValue = 0;
 
  285   for (
int i = static_cast<int>(prefix.size()); i >= 0; i--)
 
  287       hashValue = hashValueSet[i];
 
  288       loc = hashValue % m_nBuckets;
 
  291       for (node = m_buckets[loc]; node != 0; node = node->
m_next)
 
  294           if (static_cast<bool>(entry))
 
  297               if (hashValue == entry->getHash() &&
 
  298                   entry->getPrefix().isPrefixOf(prefix) &&
 
  299                   entrySelector(*entry))
 
  312 shared_ptr<name_tree::Entry>
 
  316   while (static_cast<bool>(entry))
 
  318       if (entrySelector(*entry))
 
  320       entry = entry->getParent();
 
  322   return shared_ptr<name_tree::Entry>();
 
  329   BOOST_ASSERT(static_cast<bool>(entry));
 
  334   if (entry->isEmpty())
 
  337       shared_ptr<name_tree::Entry> parent = entry->getParent();
 
  339       if (static_cast<bool>(parent))
 
  341           std::vector<shared_ptr<name_tree::Entry> >& parentChildrenList =
 
  342             parent->getChildren();
 
  344           bool isFound = 
false;
 
  345           size_t size = parentChildrenList.size();
 
  346           for (
size_t i = 0; i < 
size; i++)
 
  348               if (parentChildrenList[i] == entry)
 
  350                   parentChildrenList[i] = parentChildrenList[size - 1];
 
  351                   parentChildrenList.pop_back();
 
  357           BOOST_VERIFY(isFound == 
true);
 
  372           m_buckets[entry->getHash() % m_nBuckets] = node->
m_next;
 
  382       BOOST_ASSERT(node->
m_next == 0);
 
  387       if (static_cast<bool>(parent))
 
  390       size_t newNBuckets = 
static_cast<size_t>(m_shrinkFactor *
 
  391                                      static_cast<double>(m_nBuckets));
 
  393       if (newNBuckets >= m_minNBuckets && m_nItems < m_shrinkThreshold)
 
  405 boost::iterator_range<NameTree::const_iterator>
 
  411   for (
size_t i = 0; i < m_nBuckets; i++) {
 
  413       if (static_cast<bool>(node->
m_entry) && entrySelector(*node->
m_entry)) {
 
  424 boost::iterator_range<NameTree::const_iterator>
 
  430   if (!static_cast<bool>(entry)) {
 
  434   std::pair<bool, bool>result = entrySubTreeSelector(*entry);
 
  439                     entrySubTreeSelector);
 
  441   it.m_shouldVisitChildren = (result.second && entry->hasChildren());
 
  453 boost::iterator_range<NameTree::const_iterator>
 
  467   if (static_cast<bool>(entry)) {
 
  477 NameTree::resize(
size_t newNBuckets)
 
  493   for (i = 0; i < newNBuckets; i++)
 
  498   for (i = 0; i < m_nBuckets; i++)
 
  500       for (p = m_buckets[i]; p != 0; p = q)
 
  504           BOOST_ASSERT(static_cast<bool>(p->
m_entry));
 
  508           for (pp = &newBuckets[b]; *pp != 0; pp = &((*pp)->m_next))
 
  519   BOOST_ASSERT(count == m_nItems);
 
  521   name_tree::Node** oldBuckets = m_buckets;
 
  522   m_buckets = newBuckets;
 
  523   delete [] oldBuckets;
 
  525   m_nBuckets = newNBuckets;
 
  527   m_enlargeThreshold = 
static_cast<size_t>(m_enlargeLoadFactor *
 
  528                                               static_cast<double>(m_nBuckets));
 
  529   m_shrinkThreshold = 
static_cast<size_t>(m_shrinkLoadFactor *
 
  530                                               static_cast<double>(m_nBuckets));
 
  540   shared_ptr<name_tree::Entry> entry;
 
  544   for (
size_t i = 0; i < m_nBuckets; i++)
 
  546       for (node = m_buckets[i]; node != 0; node = node->
m_next)
 
  551           if (static_cast<bool>(entry))
 
  553               output << 
"Bucket" << i << 
"\t" << entry->m_prefix.toUri() << endl;
 
  554               output << 
"\t\tHash " << entry->m_hash << endl;
 
  556               if (static_cast<bool>(entry->m_parent))
 
  558                   output << 
"\t\tparent->" << entry->m_parent->m_prefix.toUri();
 
  562                   output << 
"\t\tROOT";
 
  566               if (entry->m_children.size() != 0)
 
  568                   output << 
"\t\tchildren = " << entry->m_children.size() << endl;
 
  570                   for (
size_t j = 0; j < entry->m_children.size(); j++)
 
  572                       output << 
"\t\t\tChild " << j << 
" " <<
 
  573                         entry->m_children[j]->getPrefix() << endl;
 
  582   output << 
"Bucket count = " << m_nBuckets << endl;
 
  583   output << 
"Stored item = " << m_nItems << endl;
 
  584   output << 
"--------------------------\n";
 
  588   : m_nameTree(nullptr)
 
  594                             shared_ptr<name_tree::Entry> entry,
 
  597   : m_nameTree(&nameTree)
 
  599   , m_subTreeRoot(entry)
 
  600   , m_entrySelector(make_shared<name_tree::
EntrySelector>(entrySelector))
 
  603   , m_shouldVisitChildren(true)
 
  613   BOOST_ASSERT(m_entry != m_nameTree->m_end);
 
  617       bool isFound = 
false;
 
  619       while (m_entry->m_node->m_next != 0)
 
  621           m_entry = m_entry->m_node->m_next->m_entry;
 
  622           if ((*m_entrySelector)(*m_entry))
 
  631       for (
int newLocation = m_entry->m_hash % m_nameTree->m_nBuckets + 1;
 
  632            newLocation < static_cast<int>(m_nameTree->m_nBuckets);
 
  640               if ((*m_entrySelector)(*m_entry))
 
  648       BOOST_VERIFY(isFound == 
false);
 
  650       m_entry = m_nameTree->m_end;
 
  663       if (m_entry == m_subTreeRoot)
 
  665           if (m_shouldVisitChildren)
 
  667               m_entry = m_entry->getChildren()[0];
 
  668               std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
 
  669               m_shouldVisitChildren = (result.second && m_entry->hasChildren());
 
  690       while (m_entry != m_subTreeRoot)
 
  692           if (m_shouldVisitChildren)
 
  695               m_entry = m_entry->getChildren()[0];
 
  696               std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
 
  697               m_shouldVisitChildren = (result.second && m_entry->hasChildren());
 
  711               shared_ptr<name_tree::Entry> parent = m_entry->getParent();
 
  713               std::vector<shared_ptr<name_tree::Entry> >& parentChildrenList = parent->getChildren();
 
  714               bool isFound = 
false;
 
  716               for (i = 0; i < parentChildrenList.size(); i++)
 
  718                   if (parentChildrenList[i] == m_entry)
 
  725               BOOST_VERIFY(isFound == 
true);
 
  726               if (i < parentChildrenList.size() - 1) 
 
  728                   m_entry = parentChildrenList[i + 1];
 
  729                   std::pair<bool, bool> result = ((*m_entrySubTreeSelector)(*m_entry));
 
  730                   m_shouldVisitChildren = (result.second && m_entry->hasChildren());
 
  744                   m_shouldVisitChildren = 
false;
 
  750       m_entry = m_nameTree->m_end;
 
  760       while (static_cast<bool>(m_entry->getParent()))
 
  762           m_entry = m_entry->getParent();
 
  763           if ((*m_entrySelector)(*m_entry))
 
  768       m_entry = m_nameTree->m_end;
 
boost::iterator_range< const_iterator > partialEnumerate(const Name &prefix, const name_tree::EntrySubTreeSelector &entrySubTreeSelector=name_tree::AnyEntrySubTree()) const 
Enumerate all entries under a prefix, optionally filtered by an EntrySubTreeSelector. 
 
size_t computeHash(const Name &prefix)
Compute the hash value of the given name prefix's WIRE FORMAT. 
 
NameTree(size_t nBuckets=1024)
 
static size_t compute(const char *buffer, size_t length)
 
const_iterator begin() const 
Get an iterator pointing to the first NameTree entry. 
 
shared_ptr< Entry > m_entry
 
bool eraseEntryIfEmpty(shared_ptr< name_tree::Entry > entry)
Delete a Name Tree Entry if this entry is empty. 
 
uint32 CityHash32(const char *s, size_t len)
 
boost::iterator_range< const_iterator > findAllMatches(const Name &prefix, const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const 
Enumerate all the name prefixes that satisfy the prefix and entrySelector. 
 
function< std::pair< bool, bool >const Entry &entry)> EntrySubTreeSelector
a predicate to accept or reject an Entry and its children 
 
const_iterator end() const 
Get an iterator referring to the past-the-end FIB entry. 
 
shared_ptr< name_tree::Entry > findLongestPrefixMatch(const Name &prefix, const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const 
Longest prefix matching for the given name. 
 
std::vector< size_t > computeHashSet(const Name &prefix)
Incrementally compute hash values. 
 
size_t size() const 
Get the number of occupied entries in the Name Tree. 
 
uint64 CityHash64(const char *s, size_t len)
 
void dump(std::ostream &output) const 
Dump all the information stored in the Name Tree for debugging. 
 
shared_ptr< name_tree::Entry > lookup(const Name &prefix)
Look for the Name Tree Entry that contains this name prefix. 
 
const_iterator operator++()
 
static size_t compute(const char *buffer, size_t length)
 
#define NFD_LOG_INIT(name)
 
#define NFD_LOG_TRACE(expression)
 
function< bool(const Entry &entry)> EntrySelector
a predicate to accept or reject an Entry in find operations 
 
shared_ptr< name_tree::Entry > findExactMatch(const Name &prefix) const 
Exact match lookup for the given name prefix. 
 
boost::iterator_range< const_iterator > fullEnumerate(const name_tree::EntrySelector &entrySelector=name_tree::AnyEntry()) const 
Enumerate all entries, optionally filtered by an EntrySelector.