diff options
author | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-11 08:41:22 -0700 |
---|---|---|
committer | Ben Johnson <benbjohnson@yahoo.com> | 2014-02-11 09:07:07 -0700 |
commit | b8122bf568813a975caa365fe51cd2a4e5c1c578 (patch) | |
tree | 1892b36889754c39e3d451045e0dc6003a31dbff /cursor.go | |
parent | Merge pull request #20 from benbjohnson/freelist (diff) | |
download | dedo-b8122bf568813a975caa365fe51cd2a4e5c1c578.tar.gz dedo-b8122bf568813a975caa365fe51cd2a4e5c1c578.tar.xz |
Cursor iteration.
Diffstat (limited to 'cursor.go')
-rw-r--r-- | cursor.go | 53 |
1 files changed, 50 insertions, 3 deletions
@@ -13,13 +13,35 @@ type Cursor struct { // First moves the cursor to the first item in the bucket and returns its key and data. func (c *Cursor) First() ([]byte, []byte) { - // TODO: Traverse to the first key. - return nil, nil + if len(c.stack) > 0 { + c.stack = c.stack[:0] + } + c.stack = append(c.stack, pageElementRef{page: c.transaction.page(c.root), index: 0}) + c.first() + return c.keyValue() } // Move the cursor to the next key/value. func (c *Cursor) Next() ([]byte, []byte) { - return nil, nil + // Attempt to move over one element until we're successful. + // Move up the stack as we hit the end of each page in our stack. + for i := len(c.stack) - 1; i >= 0; i-- { + elem := &c.stack[i] + if elem.index < elem.page.count-1 { + elem.index++ + break + } + c.stack = c.stack[:i] + } + + // If we've hit the end then return nil. + if len(c.stack) == 0 { + return nil, nil + } + + // Move down the stack to find the first element of the first leaf under this branch. + c.first() + return c.keyValue() } // Get positions the cursor at a specific key and returns the its value. @@ -42,6 +64,21 @@ func (c *Cursor) Get(key []byte) []byte { return c.element().value() } +// first moves the cursor to the first leaf element under a page. +func (c *Cursor) first() { + p := c.stack[len(c.stack)-1].page + for { + // Exit when we hit a leaf page. + if (p.flags & p_leaf) != 0 { + break + } + + // Keep adding pages pointing to the first element to the stack. + p = c.transaction.page(p.branchPageElement(c.stack[len(c.stack)-1].index).pgid) + c.stack = append(c.stack, pageElementRef{page: p, index: 0}) + } +} + func (c *Cursor) search(key []byte, p *page) { _assert((p.flags&(p_branch|p_leaf)) != 0, "invalid page type: "+p.typ()) e := pageElementRef{page: p} @@ -99,6 +136,16 @@ func (c *Cursor) element() *leafPageElement { return ref.page.leafPageElement(ref.index) } +// keyValue returns the key and value of the current leaf element. +func (c *Cursor) keyValue() ([]byte, []byte) { + ref := &c.stack[len(c.stack)-1] + if ref.index >= ref.page.count { + return nil, nil + } + e := ref.page.leafPageElement(ref.index) + return e.key(), e.value() +} + // node returns the node that the cursor is currently positioned on. func (c *Cursor) node(t *RWTransaction) *node { if len(c.stack) == 0 { |