summary refs log tree commit diff stats
path: root/tests/deps/zip-0.2.1/zip/zipfiles.nim
diff options
context:
space:
mode:
Diffstat (limited to 'tests/deps/zip-0.2.1/zip/zipfiles.nim')
-rw-r--r--tests/deps/zip-0.2.1/zip/zipfiles.nim193
1 files changed, 193 insertions, 0 deletions
diff --git a/tests/deps/zip-0.2.1/zip/zipfiles.nim b/tests/deps/zip-0.2.1/zip/zipfiles.nim
new file mode 100644
index 000000000..ca1979488
--- /dev/null
+++ b/tests/deps/zip-0.2.1/zip/zipfiles.nim
@@ -0,0 +1,193 @@
+#
+#
+#            Nim's Runtime Library
+#        (c) Copyright 2012 Andreas Rumpf
+#
+#    See the file "copying.txt", included in this
+#    distribution, for details about the copyright.
+#
+
+## This module implements a zip archive creator/reader/modifier.
+
+import
+  streams, libzip, times, os, strutils
+
+const BufSize = 8 * 1024
+
+type
+  ZipArchive* = object of RootObj ## represents a zip archive
+    mode: FileMode
+    w: PZip
+{.deprecated: [TZipArchive: ZipArchive].}
+
+proc zipError(z: var ZipArchive) =
+  var e: ref IOError
+  new(e)
+  e.msg = $zip_strerror(z.w)
+  raise e
+
+proc open*(z: var ZipArchive, filename: string, mode: FileMode = fmRead): bool =
+  ## Opens a zip file for reading, writing or appending. All file modes are
+  ## supported. Returns true iff successful, false otherwise.
+  var err, flags: int32
+  case mode
+  of fmRead, fmReadWriteExisting, fmAppend: flags = 0
+  of fmWrite:
+    if existsFile(filename): removeFile(filename)
+    flags = ZIP_CREATE or ZIP_EXCL
+  of fmReadWrite: flags = ZIP_CREATE
+  z.w = zip_open(filename, flags, addr(err))
+  z.mode = mode
+  result = z.w != nil
+
+proc close*(z: var ZipArchive) =
+  ## Closes a zip file.
+  zip_close(z.w)
+
+proc createDir*(z: var ZipArchive, dir: string) =
+  ## Creates a directory within the `z` archive. This does not fail if the
+  ## directory already exists. Note that for adding a file like
+  ## ``"path1/path2/filename"`` it is not necessary
+  ## to create the ``"path/path2"`` subdirectories - it will be done
+  ## automatically by ``addFile``.
+  assert(z.mode != fmRead)
+  discard zip_add_dir(z.w, dir)
+  zip_error_clear(z.w)
+
+proc addFile*(z: var ZipArchive, dest, src: string) =
+  ## Adds the file `src` to the archive `z` with the name `dest`. `dest`
+  ## may contain a path that will be created.
+  assert(z.mode != fmRead)
+  if not fileExists(src):
+    raise newException(IOError, "File '" & src & "' does not exist")
+  var zipsrc = zip_source_file(z.w, src, 0, -1)
+  if zipsrc == nil:
+    #echo("Dest: " & dest)
+    #echo("Src: " & src)
+    zipError(z)
+  if zip_add(z.w, dest, zipsrc) < 0'i32:
+    zip_source_free(zipsrc)
+    zipError(z)
+
+proc addFile*(z: var ZipArchive, file: string) =
+  ## A shortcut for ``addFile(z, file, file)``, i.e. the name of the source is
+  ## the name of the destination.
+  addFile(z, file, file)
+
+proc mySourceCallback(state, data: pointer, len: int,
+                      cmd: ZipSourceCmd): int {.cdecl.} =
+  var src = cast[Stream](state)
+  case cmd
+  of ZIP_SOURCE_OPEN:
+    if src.setPositionImpl != nil: setPosition(src, 0) # reset
+  of ZIP_SOURCE_READ:
+    result = readData(src, data, len)
+  of ZIP_SOURCE_CLOSE: close(src)
+  of ZIP_SOURCE_STAT:
+    var stat = cast[PZipStat](data)
+    zip_stat_init(stat)
+    stat.size = high(int32)-1 # we don't know the size
+    stat.mtime = getTime()
+    result = sizeof(ZipStat)
+  of ZIP_SOURCE_ERROR:
+    var err = cast[ptr array[0..1, cint]](data)
+    err[0] = ZIP_ER_INTERNAL
+    err[1] = 0
+    result = 2*sizeof(cint)
+  of constZIP_SOURCE_FREE: GC_unref(src)
+  of ZIP_SOURCE_SUPPORTS:
+    # By default a read-only source is supported, which suits us.
+    result = -1
+  else:
+    # An unknown command, failing
+    result = -1
+
+proc addFile*(z: var ZipArchive, dest: string, src: Stream) =
+  ## Adds a file named with `dest` to the archive `z`. `dest`
+  ## may contain a path. The file's content is read from the `src` stream.
+  assert(z.mode != fmRead)
+  GC_ref(src)
+  var zipsrc = zip_source_function(z.w, mySourceCallback, cast[pointer](src))
+  if zipsrc == nil: zipError(z)
+  if zip_add(z.w, dest, zipsrc) < 0'i32:
+    zip_source_free(zipsrc)
+    zipError(z)
+
+# -------------- zip file stream ---------------------------------------------
+
+type
+  TZipFileStream = object of StreamObj
+    f: PZipFile
+    atEnd: bool
+
+  PZipFileStream* =
+    ref TZipFileStream ## a reader stream of a file within a zip archive
+
+proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f)
+proc fsAtEnd(s: Stream): bool = PZipFileStream(s).atEnd
+proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int =
+  result = zip_fread(PZipFileStream(s).f, buffer, bufLen)
+  if result == 0:
+    PZipFileStream(s).atEnd = true
+
+proc newZipFileStream(f: PZipFile): PZipFileStream =
+  new(result)
+  result.f = f
+  result.atEnd = false
+  result.closeImpl = fsClose
+  result.readDataImpl = fsReadData
+  result.atEndImpl = fsAtEnd
+  # other methods are nil!
+
+# ----------------------------------------------------------------------------
+
+proc getStream*(z: var ZipArchive, filename: string): PZipFileStream =
+  ## returns a stream that can be used to read the file named `filename`
+  ## from the archive `z`. Returns nil in case of an error.
+  ## The returned stream does not support the `setPosition`, `getPosition`,
+  ## `writeData` or `atEnd` methods.
+  var x = zip_fopen(z.w, filename, 0'i32)
+  if x != nil: result = newZipFileStream(x)
+
+iterator walkFiles*(z: var ZipArchive): string =
+  ## walks over all files in the archive `z` and returns the filename
+  ## (including the path).
+  var i = 0'i32
+  var num = zip_get_num_files(z.w)
+  while i < num:
+    yield $zip_get_name(z.w, i, 0'i32)
+    inc(i)
+
+proc extractFile*(z: var ZipArchive, srcFile: string, dest: Stream) =
+  ## extracts a file from the zip archive `z` to the destination stream.
+  var buf: array[BufSize, byte]
+  var strm = getStream(z, srcFile)
+  while true:
+    let bytesRead = strm.readData(addr(buf[0]), buf.len)
+    if bytesRead <= 0: break
+    dest.writeData(addr(buf[0]), bytesRead)
+
+  dest.flush()
+  strm.close()
+
+proc extractFile*(z: var ZipArchive, srcFile: string, dest: string) =
+  ## extracts a file from the zip archive `z` to the destination filename.
+  var file = newFileStream(dest, fmWrite)
+  if file.isNil:
+    raise newException(IOError, "Failed to create output file: " & dest)
+  extractFile(z, srcFile, file)
+  file.close()
+
+proc extractAll*(z: var ZipArchive, dest: string) =
+  ## extracts all files from archive `z` to the destination directory.
+  createDir(dest)
+  for file in walkFiles(z):
+    if file.contains("/"):
+      createDir(dest / file[0..file.rfind("/")])
+    extractFile(z, file, dest / file)
+
+when not defined(testing) and isMainModule:
+  var zip: ZipArchive
+  if not zip.open("nim-0.11.0.zip"):
+    raise newException(IOError, "opening zip failed")
+  zip.extractAll("test")