diff --git a/internal/btree/btree.go b/internal/btree/btree.go index ccbdb00..24b5f99 100644 --- a/internal/btree/btree.go +++ b/internal/btree/btree.go @@ -475,15 +475,7 @@ func (d *DB) Insert(chash *byte, data []byte) { d.flushSuper() } -// Get look up item with the given key 'hash' in the database file. Length of the -// item is stored in 'len'. Returns a pointer to the contents of the item. -// The returned pointer should be released with free() after use. -func (d *DB) Get(hash *byte) []byte { - off := d.lookup(d.top, hash) - if off == 0 { - return nil - } - +func (d *DB) readValue(off int64) []byte { d.fd.Seek(off, io.SeekStart) length, err := read32(d.fd) if err != nil { @@ -497,6 +489,17 @@ func (d *DB) Get(hash *byte) []byte { return data[:n] } +// Get look up item with the given key 'hash' in the database file. Length of the +// item is stored in 'len'. Returns a pointer to the contents of the item. +// The returned pointer should be released with free() after use. +func (d *DB) Get(hash *byte) []byte { + off := d.lookup(d.top, hash) + if off == 0 { + return nil + } + return d.readValue(off) +} + // Delete remove item with the given key 'hash' from the database file. func (d *DB) Delete(hash *byte) error { var h [hashSize]byte @@ -522,3 +525,21 @@ func (d *DB) Delete(hash *byte) error { d.flushSuper() return nil } + +func (d *DB) Foreach(iter func(key [16]byte, value []byte)) { + top := d.get(d.top) + d.iterate(top, iter) +} + +func (d *DB) iterate(table *table, iter func(key [16]byte, value []byte)) { + for i := 0; i < table.size; i++ { + item := table.items[i] + offset := item.offset + iter(item.hash, d.readValue(offset)) + + if item.child != 0 { + child := d.get(item.child) + d.iterate(child, iter) + } + } +} diff --git a/internal/btree/btree_test.go b/internal/btree/btree_test.go index d617570..accec46 100644 --- a/internal/btree/btree_test.go +++ b/internal/btree/btree_test.go @@ -45,6 +45,12 @@ func TestBtree(t *testing.T) { bt, err = Open(f) assert2.NoError(t, err) + var ss []string + bt.Foreach(func(key [16]byte, value []byte) { + ss = append(ss, string(value)) + }) + assert2.ElementsMatch(t, tests, ss) + for i, tt := range tests { assert2.Equal(t, []byte(tt), bt.Get(sha[i])) }