diff --git a/SHAMap.cpp b/SHAMap.cpp index 9a1d5b028..e5e8d5622 100644 --- a/SHAMap.cpp +++ b/SHAMap.cpp @@ -56,11 +56,8 @@ SHAMapLeafNode::pointer SHAMap::walkToLeaf(const uint256& id, bool create, for(int i=1; iselectBranch(id); - if(branch<0) - { // somehow we got on the wrong branch - assert(false); - return SHAMapLeafNode::pointer(); - } + if(branch<0) // somehow we got on the wrong branch + throw SHAMapException(InvalidNode); if(inNode->isEmptyBranch(branch)) { // no nodes below this one if(!create) return SHAMapLeafNode::pointer(); @@ -69,7 +66,7 @@ SHAMapLeafNode::pointer SHAMap::walkToLeaf(const uint256& id, bool create, if(i!=(SHAMapNode::leafDepth)-1) { // child is another inner node inNode=getInner(inNode->getChildNodeID(branch), inNode->getChildHash(branch)); - if(inNode==NULL) return SHAMapLeafNode::pointer(); // we don't have the node + if(inNode==NULL) throw SHAMapException(InvalidNode); path.push_back(inNode); } else // child is leaf node @@ -142,13 +139,13 @@ SHAMapItem::SHAMapItem(const uint160& tag, const std::vector& dat : mTag(uint160to256(tag)), mData(data) { ; } -SHAMapItem::pointer SHAMap::firstItem() +SHAMapItem::pointer SHAMap::peekFirstItem() { ScopedLock sl(mLock); return firstBelow(root); } -SHAMapItem::pointer SHAMap::lastItem() +SHAMapItem::pointer SHAMap::peekLastItem() { ScopedLock sl(mLock); return lastBelow(root); @@ -220,12 +217,50 @@ SHAMapItem::pointer SHAMap::lastBelow(SHAMapInnerNode::pointer Node) } } -SHAMapItem::pointer SHAMap::nextItem(const SHAMapItem &) -{ - // WRITEME +SHAMapItem::pointer SHAMap::peekNextItem(const uint256& id) +{ // Get a pointer to the next item in the tree after a given item - item must be in tree + ScopedLock sl(mLock); + + std::vector path; + SHAMapLeafNode::pointer leaf=walkToLeaf(id, false, path); + if(!leaf) return SHAMapItem::pointer(); + + // is there another item in this leaf? (there almost never will be) + SHAMapItem::pointer next=leaf->nextItem(id); + if(next) return next; + + for(std::vector::reverse_iterator rit=path.rbegin(); ritselectBranch(id)+1; i<32; i++) + if(!!node->getChildHash(i)) + { // node has a subsequent child + SHAMapNode nextNode=node->getChildNodeID(i); + uint256 nextHash=node->getChildHash(i); + + if(nextNode.isLeaf()) + { // this is a terminal inner node + leaf=getLeaf(nextNode, nextHash); + if(!leaf) throw SHAMapException(MissingNode); + next=leaf->firstItem(); + if(!next) throw SHAMapException(InvalidNode); + return next; + } + + // the next item is the first item below this node + SHAMapInnerNode::pointer inner=getInner(nextNode, nextHash); + if(!inner) throw SHAMapException(MissingNode); + next=firstBelow(inner); + if(!next) throw SHAMapException(InvalidNode); + return next; + } + } + + // must be last item + return SHAMapItem::pointer(); } -SHAMapItem::pointer SHAMap::prevItem(const SHAMapItem &) +SHAMapItem::pointer SHAMap::peekPrevItem(const uint256& id) { // WRITEME } @@ -257,7 +292,7 @@ SHAMapItem::pointer SHAMap::peekItem(const uint256& id) bool SHAMap::hasItem(const uint256& id) { // does the tree have an item with this ID - ScopedLock sl(mLock); + ScopedLock sl(mLock); std::vector path; SHAMapLeafNode::pointer leaf=walkToLeaf(id, false, path); if(!leaf) return false; diff --git a/SHAMap.h b/SHAMap.h index 4e43312f3..950150f9a 100644 --- a/SHAMap.h +++ b/SHAMap.h @@ -17,7 +17,7 @@ class SHAMap; // The trees are designed for rapid synchronization and compression of differences -class SHAMapNode + class SHAMapNode { // Identifies a node in a SHA256 hash public: typedef boost::shared_ptr pointer; @@ -133,7 +133,8 @@ public: SHAMapItem::pointer findItem(const uint256& tag); SHAMapItem::pointer firstItem(); SHAMapItem::pointer lastItem(); - SHAMapItem::pointer nextItem(SHAMapItem::pointer); + SHAMapItem::pointer nextItem(const uint256& tag); + SHAMapItem::pointer prevItem(const uint256& tag); virtual void dump(void); }; @@ -241,10 +242,13 @@ public: SHAMapItem::pointer peekItem(const uint256& id); // traverse functions - SHAMapItem::pointer firstItem(); - SHAMapItem::pointer lastItem(); - SHAMapItem::pointer nextItem(const SHAMapItem &); - SHAMapItem::pointer prevItem(const SHAMapItem &); + SHAMapItem::pointer peekFirstItem(); + SHAMapItem::pointer peekLastItem(); + SHAMapItem::pointer peekNextItem(const uint256&); + SHAMapItem::pointer peekPrevItem(const uint256&); + + SHAMapItem::pointer peekPrevItem(const uint160& u) { return peekPrevItem(uint160to256(u)); } + SHAMapItem::pointer peekNextItem(const uint160& u) { return peekNextItem(uint160to256(u)); } // comparison/sync functions void getMissingNodes(std::vector& nodeHashes, int max); diff --git a/SHAMapNodes.cpp b/SHAMapNodes.cpp index e6810049f..62681623c 100644 --- a/SHAMapNodes.cpp +++ b/SHAMapNodes.cpp @@ -163,6 +163,17 @@ SHAMapItem::pointer SHAMapLeafNode::firstItem(void) return *(mItems.begin()); } +SHAMapItem::pointer SHAMapLeafNode::nextItem(const uint256& tag) +{ + bool found=false; + BOOST_FOREACH(SHAMapItem::pointer& it, mItems) + { + if(found) return it; + if(it->getTag() == tag) found=true; + } + return SHAMapItem::pointer(); +} + SHAMapItem::pointer SHAMapLeafNode::lastItem(void) { if(mItems.size()==0) return SHAMapItem::pointer();