@@ 58,13 58,17 @@ type
using dbm: DBM
-type StringView {.importcpp: "std::string_view".} = object
-proc toStringView(s: pointer; count: int): StringView {.
+type CppString {.importcpp: "std::string".} = object
+proc data(s: CppString): pointer {.importcpp: "#.data()".}
+proc len(s: CppString): csize_t {.importcpp: "#.length()".}
+
+type CppStringView {.importcpp: "std::string_view".} = object
+proc toStringView(s: pointer; count: int): CppStringView {.
importcpp: "std::string_view(@)", constructor.}
-proc toStringView(s: string): StringView {.inline.} =
+proc toStringView(s: string): CppStringView {.inline.} =
if s.len == 0: toStringView(nil, 0)
else: toStringView(unsafeAddr s[0], s.len)
-proc toStringView(buf: openarray[byte]): StringView {.inline.} =
+proc toStringView(buf: openarray[byte]): CppStringView {.inline.} =
if buf.len == 0: toStringView(nil, 0)
else: toStringView(unsafeAddr buf[0], buf.len)
@@ 86,9 90,9 @@ template importDBM(T: untyped): untyped =
proc Open(dbm: T; path: cstring; writeable: bool; options: int32) {.
importcpp: "#->Open(@)".}
proc Close(dbm: T) {.importcpp: "#->Close()".}
- proc GetSimple(dbm: T; key: StringView; default: cstring): cstring {.
- importcpp: "#->GetSimple(@).c_str()".}
- proc Set(dbm: T; key, value: StringView; overwrite: bool) {.
+ proc Get(dbm: T; key: CppStringView; value: ptr CppString): Status {.
+ importcpp: "#->Get(@)".}
+ proc Set(dbm: T; key, value: CppStringView; overwrite: bool) {.
importcpp: "#->Set(@)".}
proc MakeIterator(dbm: T): Iterator {.importcpp: "#->MakeIterator()".}
proc Synchronize(dbm: T; hard: bool): Status {.
@@ 133,22 137,28 @@ proc close*(dbm: DBM) =
## Closes the database file.
dbm.Close()
-proc get*(dbm; key: string; default = ""): string =
- $dbm.GetSimple(key.toStringView, default)
+proc get*[A,B](dbm; key: A; result: var B) =
+ var
+ buf: CppString
+ st = dbm.Get(key.toStringView, addr buf)
+ if not IsOK(st):
+ raise newException(KeyError, $GetMessage(st))
+ result.setLen(buf.len)
+ copyMem(addr result[0], buf.data, result.len)
+ # TODO: is this copy avoidable?
+
+proc set*[A,B](dbm; key: A; value: B) =
+ dbm.Set(key.toStringView, value.toStringView, true)
+
+proc `[]`*(dbm; key: string): string {.inline.} = get(dbm, key, result)
-proc set*(dbm; key, value: string; overwrite = true) =
- dbm.Set(key.toStringView, value.toStringView, overwrite)
+proc `[]=`*(dbm; key, value: string) = set(dbm, key, value)
-proc `[]`*(dbm; key: string): string =
- const def = genSym().strVal
- result = dbm.get(key, def)
- if result == def:
- when compiles($key):
- raise newException(KeyError, "key not found: " & $key)
- else:
- raise newException(KeyError, "key not found")
+proc `[]`*(dbm; key: openarray[byte]): seq[byte] {.inline.} =
+ get(dbm, key, result)
-proc `[]=`*(dbm; key, value: string) = dbm.set(key, value, true)
+proc `[]=`*(dbm; key, value: openarray[byte]) {.inline.} =
+ set(dbm, key, value)
iterator pairs*(dbm): (string, string) =
## Iterate over any `(key, value)` pair in `dbm`.