diff options
author | kitsunyan | 2018-03-10 21:10:43 +0000 |
---|---|---|
committer | kitsunyan | 2018-03-10 21:10:43 +0000 |
commit | fd397b356e9be1d3572ace965ead57120803a0ac (patch) | |
tree | d9e6fe9f903ab935fa6df2e6862a97515caf926c /src/wrapper |
Initial commitv0.1
Diffstat (limited to 'src/wrapper')
-rw-r--r-- | src/wrapper/alpm.nim | 146 | ||||
-rw-r--r-- | src/wrapper/curl.nim | 123 |
2 files changed, 269 insertions, 0 deletions
diff --git a/src/wrapper/alpm.nim b/src/wrapper/alpm.nim new file mode 100644 index 0000000..00b5b86 --- /dev/null +++ b/src/wrapper/alpm.nim @@ -0,0 +1,146 @@ +import + strutils, + "../utils" + +type + AlpmHandle* = object + AlpmDatabase* = object + AlpmPackage* = object + + AlpmList*[T] = object + data*: T + prev*: ptr AlpmList[T] + next*: ptr AlpmList[T] + + AlpmDepMod* {.pure, size: sizeof(cint).} = enum + no = 1, + eq = 2, + ge = 3, + le = 4, + gt = 5, + lt = 6 + + AlpmReason* {.pure, size: sizeof(cint).} = enum + explicit = 0, + depend = 1 + + AlpmDependency* = object + name*: cstring + version*: cstring + desc*: cstring + nameHash: culong + depMod*: AlpmDepMod + + AlpmGroup* = object + name*: cstring + packages*: ptr AlpmList[ptr AlpmPackage] + +{.passL: "-lalpm".} + +proc newAlpmHandle*(root: cstring, dbpath: cstring, err: var cint): ptr AlpmHandle + {.cdecl, importc: "alpm_initialize".} + +proc release*(handle: ptr AlpmHandle): cint + {.cdecl, importc: "alpm_release".} + +proc setArch*(handle: ptr AlpmHandle, arch: cstring): cint + {.cdecl, importc: "alpm_option_set_arch".} + +proc vercmp*(a: cstring, b: cstring): cint + {.cdecl, importc: "alpm_pkg_vercmp".} + +proc errno*(handle: ptr AlpmHandle): cint + {.cdecl, importc: "alpm_errno".} + +proc errorAlpm*(errno: cint): cstring + {.cdecl, importc: "alpm_strerror".} + +proc register*(handle: ptr AlpmHandle, treeName: cstring, level: cint): ptr AlpmDatabase + {.cdecl, importc: "alpm_register_syncdb".} + +proc local*(handle: ptr AlpmHandle): ptr AlpmDatabase + {.cdecl, importc: "alpm_get_localdb".} + +proc packages*(db: ptr AlpmDatabase): ptr AlpmList[ptr AlpmPackage] + {.cdecl, importc: "alpm_db_get_pkgcache".} + +proc groups*(db: ptr AlpmDatabase): ptr AlpmList[ptr AlpmGroup] + {.cdecl, importc: "alpm_db_get_groupcache".} + +proc name*(db: ptr AlpmDatabase): cstring + {.cdecl, importc: "alpm_db_get_name".} + +proc `[]`*(db: ptr AlpmDatabase, name: cstring): ptr AlpmPackage + {.cdecl, importc: "alpm_db_get_pkg".} + +proc base*(pkg: ptr AlpmPackage): cstring + {.cdecl, importc: "alpm_pkg_get_base".} + +proc name*(pkg: ptr AlpmPackage): cstring + {.cdecl, importc: "alpm_pkg_get_name".} + +proc version*(pkg: ptr AlpmPackage): cstring + {.cdecl, importc: "alpm_pkg_get_version".} + +proc arch*(pkg: ptr AlpmPackage): cstring + {.cdecl, importc: "alpm_pkg_get_arch".} + +proc groups*(pkg: ptr AlpmPackage): ptr AlpmList[cstring] + {.cdecl, importc: "alpm_pkg_get_groups".} + +proc reason*(pkg: ptr AlpmPackage): AlpmReason + {.cdecl, importc: "alpm_pkg_get_reason".} + +proc depends*(pkg: ptr AlpmPackage): ptr AlpmList[ptr AlpmDependency] + {.cdecl, importc: "alpm_pkg_get_depends".} + +proc optional*(pkg: ptr AlpmPackage): ptr AlpmList[ptr AlpmDependency] + {.cdecl, importc: "alpm_pkg_get_optdepends".} + +proc provides*(pkg: ptr AlpmPackage): ptr AlpmList[ptr AlpmDependency] + {.cdecl, importc: "alpm_pkg_get_provides".} + +proc cfree*(data: pointer) + {.cdecl, importc: "free", header: "<stdlib.h>".} + +proc freeList*[T](list: ptr AlpmList[T]) + {.cdecl, importc: "alpm_list_free".} + +proc freeListInner*[T](list: ptr AlpmList[T], fn: proc (data: pointer): void {.cdecl.}) + {.cdecl, importc: "alpm_list_free_inner".} + +proc freeListFull*[T](list: ptr AlpmList[T]) = + list.freeListInner(cfree) + list.freeList() + +template withAlpm*(root: string, db: string, dbs: seq[string], arch: string, + handle: untyped, alpmDbs: untyped, errors: untyped, body: untyped): untyped = + block: + var errno: cint = 0 + let handle = newAlpmHandle(root, db, errno) + + if handle == nil: + raise commandError(trp("failed to initialize alpm library\n(%s: %s)\n").strip + .replace("%s", "$#") % [$errno.errorAlpm, db]) + + var alpmDbs = newSeq[ptr AlpmDatabase]() + var errors = newSeq[string]() + for dbName in dbs: + let alpmDb = handle.register(dbName, 1 shl 30) + if alpmDb != nil: + alpmDbs &= alpmDb + else: + errors &= trp("could not register '%s' database (%s)\n").strip + .replace("%s", "$#") % [dbName, $handle.errno.errorAlpm] + + try: + discard handle.setArch(arch) + body + finally: + discard handle.release() + +iterator items*[T](list: ptr AlpmList[T]): T = + var listi = list + while listi != nil: + yield listi.data + listi = listi.next diff --git a/src/wrapper/curl.nim b/src/wrapper/curl.nim new file mode 100644 index 0000000..5f3e814 --- /dev/null +++ b/src/wrapper/curl.nim @@ -0,0 +1,123 @@ +import + strutils, + "../utils" + +type + CurlHandle* = object + + CurlInstance* = object + handle: ptr CurlHandle + data: seq[char] + + CurlOption {.pure, size: sizeof(cint).} = enum + followLocation = 52, + noSignal = 99, + timeoutMs = 155, + connectTimeoutMs = 156, + writeData = 10001, + url = 10002, + writeFunction = 20011 + + CurlError* = object of Exception + +{.passL: "-lcurl".} + +proc initCurlGlobal*(flags: clong): cint + {.cdecl, importc: "curl_global_init".} + +proc cleanupCurlGlobal*: void + {.cdecl, importc: "curl_global_cleanup".} + +proc newCurlHandle*: ptr CurlHandle + {.cdecl, importc: "curl_easy_init".} + +proc cleanup*(handle: ptr CurlHandle) + {.cdecl, importc: "curl_easy_cleanup".} + +proc errorCurl*(error: cint): cstring + {.cdecl, importc: "curl_easy_strerror".} + +proc setOption*(handle: ptr CurlHandle, option: CurlOption): cint + {.cdecl, importc: "curl_easy_setopt", varargs.} + +proc perform*(handle: ptr CurlHandle): cint + {.cdecl, importc: "curl_easy_perform".} + +proc escape*(handle: ptr CurlHandle, input: cstring, length: cint): cstring + {.cdecl, importc: "curl_easy_escape".} + +proc freeCurl*(data: pointer) + {.cdecl, importc: "curl_free".} + +proc escape*(instance: ref CurlInstance, s: string): string = + let esc = instance.handle.escape(s, 0) + if esc != nil: + let nesc = $esc + freeCurl(esc) + nesc + else: + "" + +proc curlWriteMemory(mem: array[csize.high, char], size: csize, nmemb: csize, + userdata: ref CurlInstance): csize {.cdecl.} = + let total = size * nmemb + if total > 0: + userData.data &= mem[0 .. total - 1] + total + +var refCount = 0 + +template withCurlGlobal*(body: untyped): untyped = + block: + if refCount == 0: + if initCurlGlobal(0) != 0: + raise commandError(tr"failed to initialize curl library") + refCount += 1 + try: + body + finally: + refCount -= 1 + if refCount == 0: + cleanupCurlGlobal() + +template withCurl*(instance: untyped, body: untyped): untyped = + block: + let handle = newCurlHandle() + if handle == nil: + raise commandError(tr"failed to initialize curl handle") + + var instance: ref CurlInstance + new(instance) + instance.handle = handle + instance.data = newSeq[char]() + + proc raiseError(code: cint) = + if code != 0: + let msg = code.errorCurl + if msg != nil: + raise newException(CurlError, tr"failed to perform request" & (": $#" % [$msg])) + else: + raise newException(CurlError, tr"failed to perform request") + + proc performInternal(url: string): seq[char] = + raiseError(handle.setOption(CurlOption.followLocation, (clong) 1)) + raiseError(handle.setOption(CurlOption.noSignal, (clong) 1)) + raiseError(handle.setOption(CurlOption.timeoutMs, (clong) 15000)) + raiseError(handle.setOption(CurlOption.connectTimeoutMs, (clong) 15000)) + raiseError(handle.setOption(CurlOption.url, url)) + raiseError(handle.setOption(CurlOption.writeFunction, cast[pointer](curlWriteMemory))) + raiseError(handle.setOption(CurlOption.writeData, instance)) + raiseError(handle.perform()) + instance.data + + proc performString(url: string): string = + let data = performInternal(url) + var str = newStringOfCap(data.len) + for c in data: + str.add(c) + str + + try: + body + finally: + handle.cleanup() |