~ehmry/nim-tkrzw

25ffe728a20cc60e5be81f1b2e63077f61d1cb34 — Emery Hemingway 3 years ago 18cf1c6
Support for non-string keys and values
1 files changed, 30 insertions(+), 20 deletions(-)

M src/tkrzw.nim
M src/tkrzw.nim => src/tkrzw.nim +30 -20
@@ 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`.