diff --git a/leveldb.nim b/leveldb.nim index 9c4c105..6ca09c7 100644 --- a/leveldb.nim +++ b/leveldb.nim @@ -11,6 +11,10 @@ type LevelDbException* = object of Exception +const + levelDbTrue = cuchar(1) + levelDbFalse = cuchar(0) + proc checkError(errPtr: cstring) = if errPtr != nil: defer: free(errPtr) @@ -18,7 +22,7 @@ proc checkError(errPtr: cstring) = proc close*(self: LevelDb) = if self.db == nil: - return + return leveldb_close(self.db) leveldb_writeoptions_destroy(self.syncWriteOptions) leveldb_writeoptions_destroy(self.asyncWriteOptions) @@ -29,20 +33,20 @@ proc open*(path: string): LevelDb = new(result, close) let options = leveldb_options_create() - leveldb_options_set_create_if_missing(options, 1.cuchar) + leveldb_options_set_create_if_missing(options, levelDbTrue) defer: leveldb_options_destroy(options) result.syncWriteOptions = leveldb_writeoptions_create() - leveldb_writeoptions_set_sync(result.syncWriteOptions, cuchar(1)) + leveldb_writeoptions_set_sync(result.syncWriteOptions, levelDbTrue) result.asyncWriteOptions = leveldb_writeoptions_create() - leveldb_writeoptions_set_sync(result.asyncWriteOptions, cuchar(0)) + leveldb_writeoptions_set_sync(result.asyncWriteOptions, levelDbFalse) result.readOptions = leveldb_readoptions_create() var errPtr: cstring = nil result.db = leveldb_open(options, path, addr errPtr) checkError(errPtr) -proc put*(self: LevelDb, key: string, value: string, sync=true) = +proc put*(self: LevelDb, key: string, value: string, sync = true) = assert self.db != nil var errPtr: cstring = nil let writeOptions = if sync: self.syncWriteOptions else: self.asyncWriteOptions @@ -62,8 +66,80 @@ proc get*(self: LevelDb, key: string): Option[string] = result = some($s) free(s) +proc delete*(self: LevelDb, key: string, sync = true) = + var errPtr: cstring = nil + let writeOptions = if sync: self.syncWriteOptions else: self.asyncWriteOptions + leveldb_delete(self.db, writeOptions, key, key.len, addr errPtr) + checkError(errPtr) + +proc getIterData(iterPtr: ptr leveldb_iterator_t): (Option[string], Option[string]) = + var len: csize + var str: cstring + + str = leveldb_iter_key(iterPtr, addr len) + if len > 0: + result[0] = some ($str)[0.. 0: + result[1] = some ($str)[0.. 0: + leveldb_iter_seek(iterPtr, seek, seek.len) + else: + if reverse: + leveldb_iter_seek_to_last(iterPtr) + else: + leveldb_iter_seek_to_first(iterPtr) + + while true: + if leveldb_iter_valid(iterPtr) == levelDbFalse: + break + + var (key, value) = getIterData(iterPtr) + var err: cstring = nil + leveldb_iter_get_error(iterPtr, addr err) + checkError(err) + yield (key.get(), value.get()) + + if reverse: + leveldb_iter_prev(iterPtr) + else: + leveldb_iter_next(iterPtr) + when isMainModule: let db = leveldb.open("test.db") db.put("hello", "world") - echo db.get("one") + echo db.get("nothing") echo db.get("hello") + db.delete("hello") + echo db.get("hello") + + db.put("aaa", "1") + db.put("aba", "2") + db.put("abb", "3") + + echo ">> iter" + for i in db.iter: + echo i + + echo ">> iter reverse" + for i in db.iter(reverse = true): + echo i + + echo ">> iter seek ab" + for i in db.iter(seek = "ab"): + echo i + + echo ">> iter seek ab reverse" + for i in db.iter(seek = "ab", reverse = true): + echo i