1 module rocksdb.iterator; 2 3 import std.conv : to; 4 import std.string : fromStringz, toStringz; 5 6 import rocksdb.slice : Slice; 7 import rocksdb.options : ReadOptions, rocksdb_readoptions_t; 8 import rocksdb.database : Database, rocksdb_t; 9 import rocksdb.columnfamily : ColumnFamily, rocksdb_column_family_handle_t; 10 11 extern (C) { 12 struct rocksdb_iterator_t {}; 13 14 rocksdb_iterator_t* rocksdb_create_iterator(rocksdb_t*, rocksdb_readoptions_t*); 15 rocksdb_iterator_t* rocksdb_create_iterator_cf(rocksdb_t*, rocksdb_readoptions_t*, rocksdb_column_family_handle_t*); 16 17 void rocksdb_iter_destroy(rocksdb_iterator_t*); 18 ubyte rocksdb_iter_valid(const rocksdb_iterator_t*); 19 void rocksdb_iter_seek_to_first(rocksdb_iterator_t*); 20 void rocksdb_iter_seek_to_last(rocksdb_iterator_t*); 21 void rocksdb_iter_seek(rocksdb_iterator_t*, const char*, size_t); 22 void rocksdb_iter_seek_for_prev(rocksdb_iterator_t*, const char*, size_t); 23 void rocksdb_iter_next(rocksdb_iterator_t*); 24 void rocksdb_iter_prev(rocksdb_iterator_t*); 25 immutable(char*) rocksdb_iter_key(const rocksdb_iterator_t*, size_t*); 26 immutable(char*) rocksdb_iter_value(const rocksdb_iterator_t*, size_t*); 27 void rocksdb_iter_get_error(const rocksdb_iterator_t*, char**); 28 } 29 30 31 class Iterator { 32 rocksdb_iterator_t* iter; 33 34 this(Database db, ReadOptions opts) { 35 this.iter = rocksdb_create_iterator(db.db, opts.opts); 36 this.seekToFirst(); 37 } 38 39 this(Database db, ColumnFamily family, ReadOptions opts) { 40 this.iter = rocksdb_create_iterator_cf(db.db, opts.opts, family.cf); 41 this.seekToFirst(); 42 } 43 44 ~this() { 45 rocksdb_iter_destroy(this.iter); 46 } 47 48 void seekToFirst() { 49 rocksdb_iter_seek_to_first(this.iter); 50 } 51 52 void seekToLast() { 53 rocksdb_iter_seek_to_last(this.iter); 54 } 55 56 void seek(string key) { 57 this.seek(cast(ubyte[])key); 58 } 59 60 void seek(in ubyte[] key) { 61 rocksdb_iter_seek(this.iter, cast(char*)key.ptr, key.length); 62 } 63 64 void seekPrev(string key) { 65 this.seekPrev(cast(ubyte[])key); 66 } 67 68 void seekPrev(in ubyte[] key) { 69 rocksdb_iter_seek_for_prev(this.iter, cast(char*)key.ptr, key.length); 70 } 71 72 void next() { 73 rocksdb_iter_next(this.iter); 74 } 75 76 void prev() { 77 rocksdb_iter_prev(this.iter); 78 } 79 80 bool valid() { 81 return cast(bool)rocksdb_iter_valid(this.iter); 82 } 83 84 ubyte[] key() { 85 size_t size; 86 immutable char* ckey = rocksdb_iter_key(this.iter, &size); 87 return cast(ubyte[])ckey[0..size]; 88 } 89 90 Slice keySlice() { 91 size_t size; 92 immutable char* ckey = rocksdb_iter_key(this.iter, &size); 93 return Slice(size, ckey); 94 } 95 96 ubyte[] value() { 97 size_t size; 98 immutable char* cvalue = rocksdb_iter_value(this.iter, &size); 99 return cast(ubyte[])cvalue[0..size]; 100 } 101 102 Slice valueSlice() { 103 size_t size; 104 immutable char* cvalue = rocksdb_iter_value(this.iter, &size); 105 return Slice(size, cvalue); 106 } 107 108 /* 109 int opApply(scope int delegate(ref string, ref string) dg) { 110 int result = 0; 111 112 foreach (key, value; this) { 113 result = dg(cast(string)key, cast(string)value); 114 if (result) break; 115 } 116 117 return result; 118 } 119 */ 120 121 int opApply(scope int delegate(ubyte[], ubyte[]) dg) { 122 int result = 0; 123 124 while (this.valid()) { 125 result = dg(this.key(), this.value()); 126 if (result) break; 127 this.next(); 128 } 129 130 return result; 131 } 132 133 void close() { 134 destroy(this); 135 } 136 }