summary refs log tree commit diff stats
path: root/lib/impure
diff options
context:
space:
mode:
Diffstat (limited to 'lib/impure')
-rw-r--r--lib/impure/db_mysql.nim61
-rw-r--r--lib/impure/db_postgres.nim88
-rw-r--r--lib/impure/db_sqlite.nim61
-rw-r--r--lib/impure/graphics.nim58
-rw-r--r--lib/impure/rdstdin.nim2
-rw-r--r--lib/impure/re.nim4
-rw-r--r--lib/impure/ssl.nim13
-rw-r--r--lib/impure/zipfiles.nim102
8 files changed, 205 insertions, 184 deletions
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim
index b8180cd87..619c2a656 100644
--- a/lib/impure/db_mysql.nim
+++ b/lib/impure/db_mysql.nim
@@ -13,27 +13,28 @@
 import strutils, mysql
 
 type
-  TDbConn* = PMySQL    ## encapsulates a database connection
-  TRow* = seq[string]  ## a row of a dataset. NULL database values will be
+  DbConn* = PMySQL    ## encapsulates a database connection
+  Row* = seq[string]   ## a row of a dataset. NULL database values will be
                        ## transformed always to the empty string.
   EDb* = object of IOError ## exception that is raised if a database error occurs
 
-  TSqlQuery* = distinct string ## an SQL query string
+  SqlQuery* = distinct string ## an SQL query string
 
   FDb* = object of IOEffect ## effect that denotes a database operation
   FReadDb* = object of FDb   ## effect that denotes a read operation
   FWriteDb* = object of FDb  ## effect that denotes a write operation
+{.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn].}
 
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =
-  ## constructs a TSqlQuery from the string `query`. This is supposed to be 
+proc sql*(query: string): SqlQuery {.noSideEffect, inline.} =
+  ## constructs a SqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
   ## ``sql"update user set counter = counter + 1"``
   ##
   ## If assertions are turned off, it does nothing. If assertions are turned 
   ## on, later versions will check the string for valid syntax.
-  result = TSqlQuery(query)
+  result = SqlQuery(query)
 
-proc dbError(db: TDbConn) {.noreturn.} = 
+proc dbError(db: DbConn) {.noreturn.} = 
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
@@ -48,7 +49,7 @@ proc dbError*(msg: string) {.noreturn.} =
   raise e
 
 when false:
-  proc dbQueryOpt*(db: TDbConn, query: string, args: varargs[string, `$`]) =
+  proc dbQueryOpt*(db: DbConn, query: string, args: varargs[string, `$`]) =
     var stmt = mysql_stmt_init(db)
     if stmt == nil: dbError(db)
     if mysql_stmt_prepare(stmt, query, len(query)) != 0: 
@@ -65,7 +66,7 @@ proc dbQuote*(s: string): string =
     else: add(result, c)
   add(result, '\'')
 
-proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
+proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
   result = ""
   var a = 0
   for c in items(string(formatstr)):
@@ -78,23 +79,23 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     else: 
       add(result, c)
   
-proc tryExec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]): bool {.
+proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
   tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
   return mysql.realQuery(db, q, q.len) == 0'i32
 
-proc rawExec(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) =
+proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) =
   var q = dbFormat(query, args)
   if mysql.realQuery(db, q, q.len) != 0'i32: dbError(db)
 
-proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
+proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
   tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   var q = dbFormat(query, args)
   if mysql.realQuery(db, q, q.len) != 0'i32: dbError(db)
     
-proc newRow(L: int): TRow = 
+proc newRow(L: int): Row = 
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
@@ -103,8 +104,8 @@ proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) =
     while mysql.fetchRow(sqlres) != nil: discard
   mysql.freeResult(sqlres)
   
-iterator fastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+iterator fastRows*(db: DbConn, query: SqlQuery,
+                   args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For MySQL this is the case!.
@@ -126,10 +127,10 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
       yield result
     properFreeResult(sqlres, row)
 
-proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+proc getRow*(db: DbConn, query: SqlQuery,
+             args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a TRow with empty strings for each column.
+  ## will return a Row with empty strings for each column.
   rawExec(db, query, args)
   var sqlres = mysql.useResult(db)
   if sqlres != nil:
@@ -145,8 +146,8 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
           add(result[i], row[i])
     properFreeResult(sqlres, row)
 
-proc getAllRows*(db: TDbConn, query: TSqlQuery, 
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
+proc getAllRows*(db: DbConn, query: SqlQuery, 
+                 args: varargs[string, `$`]): seq[Row] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   rawExec(db, query, args)
@@ -168,12 +169,12 @@ proc getAllRows*(db: TDbConn, query: TSqlQuery,
       inc(j)
     mysql.freeResult(sqlres)
 
-iterator rows*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+iterator rows*(db: DbConn, query: SqlQuery, 
+               args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## same as `fastRows`, but slower and safe.
   for r in items(getAllRows(db, query, args)): yield r
 
-proc getValue*(db: TDbConn, query: TSqlQuery, 
+proc getValue*(db: DbConn, query: SqlQuery, 
                args: varargs[string, `$`]): string {.tags: [FReadDB].} = 
   ## executes the query and returns the first column of the first row of the
   ## result dataset. Returns "" if the dataset contains no rows or the database
@@ -183,7 +184,7 @@ proc getValue*(db: TDbConn, query: TSqlQuery,
     result = row[0]
     break
 
-proc tryInsertId*(db: TDbConn, query: TSqlQuery, 
+proc tryInsertId*(db: DbConn, query: SqlQuery, 
                   args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error.
@@ -193,14 +194,14 @@ proc tryInsertId*(db: TDbConn, query: TSqlQuery,
   else:
     result = mysql.insertId(db)
   
-proc insertId*(db: TDbConn, query: TSqlQuery, 
+proc insertId*(db: DbConn, query: SqlQuery, 
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row.
   result = tryInsertID(db, query, args)
   if result < 0: dbError(db)
 
-proc execAffectedRows*(db: TDbConn, query: TSqlQuery, 
+proc execAffectedRows*(db: DbConn, query: SqlQuery, 
                        args: varargs[string, `$`]): int64 {.
                        tags: [FReadDB, FWriteDb].} = 
   ## runs the query (typically "UPDATE") and returns the
@@ -208,11 +209,11 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
   rawExec(db, query, args)
   result = mysql.affectedRows(db)
 
-proc close*(db: TDbConn) {.tags: [FDb].} = 
+proc close*(db: DbConn) {.tags: [FDb].} = 
   ## closes the database connection.
   if db != nil: mysql.close(db)
 
-proc open*(connection, user, password, database: string): TDbConn {.
+proc open*(connection, user, password, database: string): DbConn {.
   tags: [FDb].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established.
@@ -230,8 +231,8 @@ proc open*(connection, user, password, database: string): TDbConn {.
     db_mysql.close(result)
     dbError(errmsg)
 
-proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+proc setEncoding*(connection: DbConn, encoding: string): bool {.
   tags: [FDb].} =
   ## sets the encoding of a database connection, returns true for 
   ## success, false for failure.
-  result = mysql.set_character_set(connection, encoding) == 0
\ No newline at end of file
+  result = mysql.set_character_set(connection, encoding) == 0
diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim
index ffb8bbcda..774cb1510 100644
--- a/lib/impure/db_postgres.nim
+++ b/lib/impure/db_postgres.nim
@@ -13,28 +13,30 @@
 import strutils, postgres
 
 type
-  TDbConn* = PPGconn   ## encapsulates a database connection
-  TRow* = seq[string]  ## a row of a dataset. NULL database values will be
+  DbConn* = PPGconn   ## encapsulates a database connection
+  Row* = seq[string]  ## a row of a dataset. NULL database values will be
                        ## transformed always to the empty string.
   EDb* = object of IOError ## exception that is raised if a database error occurs
   
-  TSqlQuery* = distinct string ## an SQL query string
-  TSqlPrepared* = distinct string ## a identifier for the prepared queries
+  SqlQuery* = distinct string ## an SQL query string
+  SqlPrepared* = distinct string ## a identifier for the prepared queries
 
   FDb* = object of IOEffect ## effect that denotes a database operation
   FReadDb* = object of FDb   ## effect that denotes a read operation
   FWriteDb* = object of FDb  ## effect that denotes a write operation
+{.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn,
+              TSqlPrepared: SqlPrepared].}
 
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
-  ## constructs a TSqlQuery from the string `query`. This is supposed to be 
+proc sql*(query: string): SqlQuery {.noSideEffect, inline.} =  
+  ## constructs a SqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
   ## ``sql"update user set counter = counter + 1"``
   ##
   ## If assertions are turned off, it does nothing. If assertions are turned 
   ## on, later versions will check the string for valid syntax.
-  result = TSqlQuery(query)
+  result = SqlQuery(query)
  
-proc dbError*(db: TDbConn) {.noreturn.} =
+proc dbError*(db: DbConn) {.noreturn.} =
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
@@ -56,7 +58,7 @@ proc dbQuote*(s: string): string =
     else: add(result, c)
   add(result, '\'')
 
-proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
+proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
   result = ""
   var a = 0
   for c in items(string(formatstr)):
@@ -69,7 +71,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     else:
       add(result, c)
   
-proc tryExec*(db: TDbConn, query: TSqlQuery,
+proc tryExec*(db: DbConn, query: SqlQuery,
               args: varargs[string, `$`]): bool {.tags: [FReadDB, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var arr = allocCStringArray(args)
@@ -79,7 +81,7 @@ proc tryExec*(db: TDbConn, query: TSqlQuery,
   result = pqresultStatus(res) == PGRES_COMMAND_OK
   pqclear(res)
 
-proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
+proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
   tags: [FReadDB, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   var arr = allocCStringArray(args)
@@ -89,7 +91,7 @@ proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`]) {.
   if pqresultStatus(res) != PGRES_COMMAND_OK: dbError(db)
   pqclear(res)
 
-proc exec*(db: TDbConn, stmtName: TSqlPrepared,
+proc exec*(db: DbConn, stmtName: SqlPrepared,
           args: varargs[string]) {.tags: [FReadDB, FWriteDb].} =
   var arr = allocCStringArray(args)
   var res = pqexecPrepared(db, stmtName.string, int32(args.len), arr,
@@ -98,11 +100,11 @@ proc exec*(db: TDbConn, stmtName: TSqlPrepared,
   if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
   pqclear(res)
 
-proc newRow(L: int): TRow =
+proc newRow(L: int): Row =
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
-proc setupQuery(db: TDbConn, query: TSqlQuery,
+proc setupQuery(db: DbConn, query: SqlQuery,
                 args: varargs[string]): PPGresult =
   var arr = allocCStringArray(args)
   result = pqexecParams(db, query.string, int32(args.len), nil, arr,
@@ -110,7 +112,7 @@ proc setupQuery(db: TDbConn, query: TSqlQuery,
   deallocCStringArray(arr)
   if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
 
-proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
+proc setupQuery(db: DbConn, stmtName: SqlPrepared,
                  args: varargs[string]): PPGresult =
   var arr = allocCStringArray(args)
   result = pqexecPrepared(db, stmtName.string, int32(args.len), arr,
@@ -118,13 +120,13 @@ proc setupQuery(db: TDbConn, stmtName: TSqlPrepared,
   deallocCStringArray(arr)
   if pqResultStatus(result) != PGRES_TUPLES_OK: dbError(db)
 
-proc prepare*(db: TDbConn; stmtName: string, query: TSqlQuery;
-              nParams: int): TSqlPrepared =
+proc prepare*(db: DbConn; stmtName: string, query: SqlQuery;
+              nParams: int): SqlPrepared =
   var res = pqprepare(db, stmtName, query.string, int32(nParams), nil)
   if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db)
-  return TSqlPrepared(stmtName)
+  return SqlPrepared(stmtName)
    
-proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
+proc setRow(res: PPGresult, r: var Row, line, cols: int32) =
   for col in 0..cols-1:
     setLen(r[col], 0)
     let x = pqgetvalue(res, line, col)
@@ -133,8 +135,8 @@ proc setRow(res: PPGresult, r: var TRow, line, cols: int32) =
     else:
       add(r[col], x)
 
-iterator fastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+iterator fastRows*(db: DbConn, query: SqlQuery,
+                   args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For Postgres it is safe though.
@@ -146,8 +148,8 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
     yield result
   pqclear(res)
 
-iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
-                   args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+iterator fastRows*(db: DbConn, stmtName: SqlPrepared,
+                   args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## executes the prepared query and iterates over the result dataset.
   var res = setupQuery(db, stmtName, args)
   var L = pqNfields(res)
@@ -157,44 +159,44 @@ iterator fastRows*(db: TDbConn, stmtName: TSqlPrepared,
     yield result
   pqClear(res)
 
-proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+proc getRow*(db: DbConn, query: SqlQuery,
+             args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a TRow with empty strings for each column.
+  ## will return a Row with empty strings for each column.
   var res = setupQuery(db, query, args)
   var L = pqnfields(res)
   result = newRow(L)
   setRow(res, result, 0, L)
   pqclear(res)
 
-proc getRow*(db: TDbConn, stmtName: TSqlPrepared,
-             args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+proc getRow*(db: DbConn, stmtName: SqlPrepared,
+             args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   var res = setupQuery(db, stmtName, args)
   var L = pqNfields(res)
   result = newRow(L)
   setRow(res, result, 0, L)
   pqClear(res)
 
-proc getAllRows*(db: TDbConn, query: TSqlQuery,
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
+proc getAllRows*(db: DbConn, query: SqlQuery,
+                 args: varargs[string, `$`]): seq[Row] {.tags: [FReadDB].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in fastRows(db, query, args):
     result.add(r)
 
-proc getAllRows*(db: TDbConn, stmtName: TSqlPrepared,
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDB].} =
+proc getAllRows*(db: DbConn, stmtName: SqlPrepared,
+                 args: varargs[string, `$`]): seq[Row] {.tags: [FReadDB].} =
   ## executes the prepared query and returns the whole result dataset.
   result = @[]
   for r in fastRows(db, stmtName, args):
     result.add(r)
 
-iterator rows*(db: TDbConn, query: TSqlQuery,
-               args: varargs[string, `$`]): TRow {.tags: [FReadDB].} =
+iterator rows*(db: DbConn, query: SqlQuery,
+               args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
   ## same as `fastRows`, but slower and safe.
   for r in items(getAllRows(db, query, args)): yield r
 
-proc getValue*(db: TDbConn, query: TSqlQuery,
+proc getValue*(db: DbConn, query: SqlQuery,
                args: varargs[string, `$`]): string {.tags: [FReadDB].} =
   ## executes the query and returns the first column of the first row of the
   ## result dataset. Returns "" if the dataset contains no rows or the database
@@ -202,20 +204,20 @@ proc getValue*(db: TDbConn, query: TSqlQuery,
   var x = pqgetvalue(setupQuery(db, query, args), 0, 0)
   result = if isNil(x): "" else: $x
   
-proc tryInsertID*(db: TDbConn, query: TSqlQuery,
+proc tryInsertID*(db: DbConn, query: SqlQuery,
                   args: varargs[string, `$`]): int64  {.tags: [FWriteDb].}=
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row or -1 in case of an error. For Postgre this adds
   ## ``RETURNING id`` to the query, so it only works if your primary key is
   ## named ``id``. 
-  var x = pqgetvalue(setupQuery(db, TSqlQuery(string(query) & " RETURNING id"), 
+  var x = pqgetvalue(setupQuery(db, SqlQuery(string(query) & " RETURNING id"), 
     args), 0, 0)
   if not isNil(x):
     result = parseBiggestInt($x)
   else:
     result = -1
 
-proc insertID*(db: TDbConn, query: TSqlQuery,
+proc insertID*(db: DbConn, query: SqlQuery,
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} =
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row. For Postgre this adds
@@ -224,7 +226,7 @@ proc insertID*(db: TDbConn, query: TSqlQuery,
   result = tryInsertID(db, query, args)
   if result < 0: dbError(db)
   
-proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
+proc execAffectedRows*(db: DbConn, query: SqlQuery,
                        args: varargs[string, `$`]): int64 {.tags: [
                        FReadDB, FWriteDb].} =
   ## executes the query (typically "UPDATE") and returns the
@@ -235,11 +237,11 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
   result = parseBiggestInt($pqcmdTuples(res))
   pqclear(res)
 
-proc close*(db: TDbConn) {.tags: [FDb].} =
+proc close*(db: DbConn) {.tags: [FDb].} =
   ## closes the database connection.
   if db != nil: pqfinish(db)
 
-proc open*(connection, user, password, database: string): TDbConn {.
+proc open*(connection, user, password, database: string): DbConn {.
   tags: [FDb].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established.
@@ -261,8 +263,8 @@ proc open*(connection, user, password, database: string): TDbConn {.
   result = pqsetdbLogin(nil, nil, nil, nil, database, user, password)
   if pqStatus(result) != CONNECTION_OK: dbError(result) # result = nil
 
-proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+proc setEncoding*(connection: DbConn, encoding: string): bool {.
   tags: [FDb].} =
   ## sets the encoding of a database connection, returns true for 
   ## success, false for failure.
-  return pqsetClientEncoding(connection, encoding) == 0
\ No newline at end of file
+  return pqsetClientEncoding(connection, encoding) == 0
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index 8536ab6f2..47e7c1900 100644
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -13,27 +13,28 @@
 import strutils, sqlite3
 
 type
-  TDbConn* = PSqlite3  ## encapsulates a database connection
-  TRow* = seq[string]  ## a row of a dataset. NULL database values will be
+  DbConn* = PSqlite3  ## encapsulates a database connection
+  Row* = seq[string]  ## a row of a dataset. NULL database values will be
                        ## transformed always to the empty string.
   EDb* = object of IOError ## exception that is raised if a database error occurs
   
-  TSqlQuery* = distinct string ## an SQL query string
+  SqlQuery* = distinct string ## an SQL query string
   
   FDb* = object of IOEffect ## effect that denotes a database operation
   FReadDb* = object of FDb   ## effect that denotes a read operation
   FWriteDb* = object of FDb  ## effect that denotes a write operation
+{.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn].}
   
-proc sql*(query: string): TSqlQuery {.noSideEffect, inline.} =  
-  ## constructs a TSqlQuery from the string `query`. This is supposed to be 
+proc sql*(query: string): SqlQuery {.noSideEffect, inline.} =  
+  ## constructs a SqlQuery from the string `query`. This is supposed to be 
   ## used as a raw-string-literal modifier:
   ## ``sql"update user set counter = counter + 1"``
   ##
   ## If assertions are turned off, it does nothing. If assertions are turned 
   ## on, later versions will check the string for valid syntax.
-  result = TSqlQuery(query)
+  result = SqlQuery(query)
  
-proc dbError(db: TDbConn) {.noreturn.} = 
+proc dbError(db: DbConn) {.noreturn.} = 
   ## raises an EDb exception.
   var e: ref EDb
   new(e)
@@ -55,7 +56,7 @@ proc dbQuote(s: string): string =
     else: add(result, c)
   add(result, '\'')
 
-proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
+proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
   result = ""
   var a = 0
   for c in items(string(formatstr)):
@@ -65,7 +66,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     else:
       add(result, c)
   
-proc tryExec*(db: TDbConn, query: TSqlQuery, 
+proc tryExec*(db: DbConn, query: SqlQuery, 
               args: varargs[string, `$`]): bool {.tags: [FReadDb, FWriteDb].} =
   ## tries to execute the query and returns true if successful, false otherwise.
   var q = dbFormat(query, args)
@@ -74,29 +75,29 @@ proc tryExec*(db: TDbConn, query: TSqlQuery,
     if step(stmt) == SQLITE_DONE:
       result = finalize(stmt) == SQLITE_OK
 
-proc exec*(db: TDbConn, query: TSqlQuery, args: varargs[string, `$`])  {.
+proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`])  {.
   tags: [FReadDb, FWriteDb].} =
   ## executes the query and raises EDB if not successful.
   if not tryExec(db, query, args): dbError(db)
   
-proc newRow(L: int): TRow =
+proc newRow(L: int): Row =
   newSeq(result, L)
   for i in 0..L-1: result[i] = ""
   
-proc setupQuery(db: TDbConn, query: TSqlQuery, 
+proc setupQuery(db: DbConn, query: SqlQuery, 
                 args: varargs[string]): Pstmt = 
   var q = dbFormat(query, args)
   if prepare_v2(db, q, q.len.cint, result, nil) != SQLITE_OK: dbError(db)
   
-proc setRow(stmt: Pstmt, r: var TRow, cols: cint) =
+proc setRow(stmt: Pstmt, r: var Row, cols: cint) =
   for col in 0..cols-1:
     setLen(r[col], column_bytes(stmt, col)) # set capacity
     setLen(r[col], 0)
     let x = column_text(stmt, col)
     if not isNil(x): add(r[col], x)
   
-iterator fastRows*(db: TDbConn, query: TSqlQuery,
-                   args: varargs[string, `$`]): TRow  {.tags: [FReadDb].} =
+iterator fastRows*(db: DbConn, query: SqlQuery,
+                   args: varargs[string, `$`]): Row  {.tags: [FReadDb].} =
   ## executes the query and iterates over the result dataset. This is very 
   ## fast, but potenially dangerous: If the for-loop-body executes another
   ## query, the results can be undefined. For Sqlite it is safe though.
@@ -108,10 +109,10 @@ iterator fastRows*(db: TDbConn, query: TSqlQuery,
     yield result
   if finalize(stmt) != SQLITE_OK: dbError(db)
 
-proc getRow*(db: TDbConn, query: TSqlQuery,
-             args: varargs[string, `$`]): TRow {.tags: [FReadDb].} =
+proc getRow*(db: DbConn, query: SqlQuery,
+             args: varargs[string, `$`]): Row {.tags: [FReadDb].} =
   ## retrieves a single row. If the query doesn't return any rows, this proc
-  ## will return a TRow with empty strings for each column.
+  ## will return a Row with empty strings for each column.
   var stmt = setupQuery(db, query, args)
   var L = (column_count(stmt))
   result = newRow(L)
@@ -119,19 +120,19 @@ proc getRow*(db: TDbConn, query: TSqlQuery,
     setRow(stmt, result, L)
   if finalize(stmt) != SQLITE_OK: dbError(db)
 
-proc getAllRows*(db: TDbConn, query: TSqlQuery, 
-                 args: varargs[string, `$`]): seq[TRow] {.tags: [FReadDb].} =
+proc getAllRows*(db: DbConn, query: SqlQuery, 
+                 args: varargs[string, `$`]): seq[Row] {.tags: [FReadDb].} =
   ## executes the query and returns the whole result dataset.
   result = @[]
   for r in fastRows(db, query, args):
     result.add(r)
 
-iterator rows*(db: TDbConn, query: TSqlQuery, 
-               args: varargs[string, `$`]): TRow {.tags: [FReadDb].} =
+iterator rows*(db: DbConn, query: SqlQuery, 
+               args: varargs[string, `$`]): Row {.tags: [FReadDb].} =
   ## same as `FastRows`, but slower and safe.
   for r in fastRows(db, query, args): yield r
 
-proc getValue*(db: TDbConn, query: TSqlQuery, 
+proc getValue*(db: DbConn, query: SqlQuery, 
                args: varargs[string, `$`]): string {.tags: [FReadDb].} = 
   ## executes the query and returns the first column of the first row of the
   ## result dataset. Returns "" if the dataset contains no rows or the database
@@ -148,7 +149,7 @@ proc getValue*(db: TDbConn, query: TSqlQuery,
     result = ""
   if finalize(stmt) != SQLITE_OK: dbError(db)
   
-proc tryInsertID*(db: TDbConn, query: TSqlQuery, 
+proc tryInsertID*(db: DbConn, query: SqlQuery, 
                   args: varargs[string, `$`]): int64
                   {.tags: [FWriteDb], raises: [].} =
   ## executes the query (typically "INSERT") and returns the 
@@ -162,7 +163,7 @@ proc tryInsertID*(db: TDbConn, query: TSqlQuery,
     if finalize(stmt) != SQLITE_OK:
       result = -1
 
-proc insertID*(db: TDbConn, query: TSqlQuery, 
+proc insertID*(db: DbConn, query: SqlQuery, 
                args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = 
   ## executes the query (typically "INSERT") and returns the 
   ## generated ID for the row. For Postgre this adds
@@ -171,7 +172,7 @@ proc insertID*(db: TDbConn, query: TSqlQuery,
   result = tryInsertID(db, query, args)
   if result < 0: dbError(db)
   
-proc execAffectedRows*(db: TDbConn, query: TSqlQuery, 
+proc execAffectedRows*(db: DbConn, query: SqlQuery, 
                        args: varargs[string, `$`]): int64 {.
                        tags: [FReadDb, FWriteDb].} = 
   ## executes the query (typically "UPDATE") and returns the
@@ -179,21 +180,21 @@ proc execAffectedRows*(db: TDbConn, query: TSqlQuery,
   exec(db, query, args)
   result = changes(db)
 
-proc close*(db: TDbConn) {.tags: [FDb].} = 
+proc close*(db: DbConn) {.tags: [FDb].} = 
   ## closes the database connection.
   if sqlite3.close(db) != SQLITE_OK: dbError(db)
     
-proc open*(connection, user, password, database: string): TDbConn {.
+proc open*(connection, user, password, database: string): DbConn {.
   tags: [FDb].} =
   ## opens a database connection. Raises `EDb` if the connection could not
   ## be established. Only the ``connection`` parameter is used for ``sqlite``.
-  var db: TDbConn
+  var db: DbConn
   if sqlite3.open(connection, db) == SQLITE_OK:
     result = db
   else:
     dbError(db)
 
-proc setEncoding*(connection: TDbConn, encoding: string): bool {.
+proc setEncoding*(connection: DbConn, encoding: string): bool {.
   tags: [FDb].} =
   ## sets the encoding of a database connection, returns true for 
   ## success, false for failure.
diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim
index 814c0ebe1..1b3d1d5b6 100644
--- a/lib/impure/graphics.nim
+++ b/lib/impure/graphics.nim
@@ -17,23 +17,24 @@ from sdl import PSurface # Bug
 from sdl_ttf import openFont, closeFont
 
 type
-  TRect* = tuple[x, y, width, height: int]
-  TPoint* = tuple[x, y: int]
+  Rect* = tuple[x, y, width, height: int]
+  Point* = tuple[x, y: int]
 
-  PSurface* = ref TSurface ## a surface to draw onto
-  TSurface* {.pure, final.} = object
+  PSurface* = ref Surface ## a surface to draw onto
+  Surface* {.pure, final.} = object
     w*, h*: Natural
     s*: sdl.PSurface
   
   EGraphics* = object of IOError
 
-  TFont {.pure, final.} = object
+  Font {.pure, final.} = object
     f: sdl_ttf.PFont
-    color: sdl.TColor
-  PFont* = ref TFont ## represents a font
+    color: sdl.Color
+  PFont* = ref Font ## represents a font
+{.deprecated: [TSurface: Surface, TFont: Font, TRect: Rect, TPoint: Point].}
 
-proc toSdlColor*(c: Color): sdl.TColor =
-  ## Convert colors.TColor to sdl.TColor
+proc toSdlColor*(c: Color): sdl.Color =
+  ## Convert colors.Color to sdl.Color
   var x = c.extractRGB  
   result.r = x.r and 0xff
   result.g = x.g and 0xff
@@ -45,8 +46,8 @@ proc createSdlColor*(sur: PSurface, c: Color, alpha: int = 0): int32 =
   return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, 
                      x.b and 0xff, alpha and 0xff)
 
-proc toSdlRect*(r: TRect): sdl.TRect =
-  ## Convert ``graphics.TRect`` to ``sdl.TRect``.
+proc toSdlRect*(r: Rect): sdl.Rect =
+  ## Convert ``graphics.Rect`` to ``sdl.Rect``.
   result.x = int16(r.x)
   result.y = int16(r.y)
   result.w = uint16(r.width)
@@ -103,8 +104,9 @@ proc writeToBMP*(sur: PSurface, filename: string) =
     raise newException(IOError, "cannot write: " & filename)
 
 type
-  TPixels = array[0..1000_000-1, int32]
-  PPixels = ptr TPixels
+  Pixels = array[0..1000_000-1, int32]
+  PPixels = ptr Pixels
+{.deprecated: [TPixels: Pixels].}
 
 template setPix(video, pitch, x, y, col: expr): stmt =
   video[y * pitch + x] = int32(col)
@@ -128,7 +130,7 @@ proc setPixel(sur: PSurface, x, y: Natural, col: colors.Color) {.inline.} =
   #pixs[y * (sur.s.pitch div colSize) + x] = int(col)
   setPix(pixs, sur.s.pitch.int div ColSize, x, y, col)
 
-proc `[]`*(sur: PSurface, p: TPoint): Color =
+proc `[]`*(sur: PSurface, p: Point): Color =
   ## get pixel at position `p`. No range checking is done!
   result = getPixel(sur, p.x, p.y)
 
@@ -136,7 +138,7 @@ proc `[]`*(sur: PSurface, x, y: int): Color =
   ## get pixel at position ``(x, y)``. No range checking is done!
   result = getPixel(sur, x, y)
 
-proc `[]=`*(sur: PSurface, p: TPoint, col: Color) =
+proc `[]=`*(sur: PSurface, p: Point, col: Color) =
   ## set the pixel at position `p`. No range checking is done!
   setPixel(sur, p.x, p.y, col)
 
@@ -144,10 +146,10 @@ proc `[]=`*(sur: PSurface, x, y: int, col: Color) =
   ## set the pixel at position ``(x, y)``. No range checking is done!
   setPixel(sur, x, y, col)
 
-proc blit*(destSurf: PSurface, destRect: TRect, srcSurf: PSurface, 
-           srcRect: TRect) =
+proc blit*(destSurf: PSurface, destRect: Rect, srcSurf: PSurface, 
+           srcRect: Rect) =
   ## Copies ``srcSurf`` into ``destSurf``
-  var destTRect, srcTRect: sdl.TRect
+  var destTRect, srcTRect: sdl.Rect
 
   destTRect.x = int16(destRect.x)
   destTRect.y = int16(destRect.y)
@@ -168,7 +170,7 @@ proc textBounds*(text: string, font = defaultFont): tuple[width, height: int] =
   result.width = int(w)
   result.height = int(h)
 
-proc drawText*(sur: PSurface, p: TPoint, text: string, font = defaultFont) =
+proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) =
   ## Draws text with a transparent background, at location ``p`` with the given
   ## font.
   var textSur: PSurface # This surface will have the text drawn on it
@@ -179,7 +181,7 @@ proc drawText*(sur: PSurface, p: TPoint, text: string, font = defaultFont) =
   # Merge the text surface with sur
   sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
 
-proc drawText*(sur: PSurface, p: TPoint, text: string,
+proc drawText*(sur: PSurface, p: Point, text: string,
                bg: Color, font = defaultFont) =
   ## Draws text, at location ``p`` with font ``font``. ``bg`` 
   ## is the background color.
@@ -189,7 +191,7 @@ proc drawText*(sur: PSurface, p: TPoint, text: string,
   # Merge the text surface with sur
   sur.blit((p.x, p.y, sur.w, sur.h), textSur, (0, 0, sur.w, sur.h))
   
-proc drawCircle*(sur: PSurface, p: TPoint, r: Natural, color: Color) =
+proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) =
   ## draws a circle with center `p` and radius `r` with the given color
   ## onto the surface `sur`.
   var video = cast[PPixels](sur.s.pixels)
@@ -229,7 +231,7 @@ proc `>-<`(val: int, s: PSurface): int {.inline.} =
 proc `>|<`(val: int, s: PSurface): int {.inline.} = 
   return if val < 0: 0 elif val >= s.h: s.h-1 else: val
 
-proc drawLine*(sur: PSurface, p1, p2: TPoint, color: Color) =
+proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) =
   ## draws a line between the two points `p1` and `p2` with the given color
   ## onto the surface `sur`.
   var stepx, stepy: int = 0
@@ -291,7 +293,7 @@ proc drawVerLine*(sur: PSurface, x, y, h: Natural, color: Color) =
     for i in 0 .. min(sur.s.h-y, h)-1:
       setPix(video, pitch, x, y + i, color)
 
-proc fillCircle*(s: PSurface, p: TPoint, r: Natural, color: Color) =
+proc fillCircle*(s: PSurface, p: Point, r: Natural, color: Color) =
   ## draws a circle with center `p` and radius `r` with the given color
   ## onto the surface `sur` and fills it.
   var a = 1 - r
@@ -319,7 +321,7 @@ proc fillCircle*(s: PSurface, p: TPoint, r: Natural, color: Color) =
         drawVerLine(s, x - py - 1, y - px,  px, color)
     px = px + 1
 
-proc drawRect*(sur: PSurface, r: TRect, color: Color) =
+proc drawRect*(sur: PSurface, r: Rect, color: Color) =
   ## draws a rectangle.
   var video = cast[PPixels](sur.s.pixels)
   var pitch = sur.s.pitch.int div ColSize
@@ -337,7 +339,7 @@ proc drawRect*(sur: PSurface, r: TRect, color: Color) =
       setPix(video, pitch, r.x, r.y + i, color)
       setPix(video, pitch, r.x + minW - 1, r.y + i, color) # Draw right side
     
-proc fillRect*(sur: PSurface, r: TRect, col: Color) =
+proc fillRect*(sur: PSurface, r: Rect, col: Color) =
   ## Fills a rectangle using sdl's ``FillRect`` function.
   var rect = toSdlRect(r)
   if sdl.fillRect(sur.s, addr(rect), sur.createSdlColor(col)) == -1:
@@ -424,7 +426,7 @@ template cround(x: expr): expr = ipart(x + 0.5)
 template fpart(x: expr): expr = x - ipart(x)
 template rfpart(x: expr): expr = 1.0 - fpart(x)
 
-proc drawLineAA*(sur: PSurface, p1, p2: TPoint, color: Color) =
+proc drawLineAA*(sur: PSurface, p1, p2: Point, color: Color) =
   ## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's 
   ## line algorithm
   var (x1, x2, y1, y2) = (p1.x.toFloat(), p2.x.toFloat(), 
@@ -490,9 +492,9 @@ proc fillSurface*(sur: PSurface, color: Color) =
 template withEvents*(surf: PSurface, event: expr, actions: stmt): stmt {.
   immediate.} =
   ## Simple template which creates an event loop. ``Event`` is the name of the
-  ## variable containing the TEvent object.
+  ## variable containing the Event object.
   while true:
-    var event: sdl.TEvent
+    var event: sdl.Event
     if sdl.waitEvent(addr(event)) == 1:
       actions
 
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index f4d00979c..dfe3e22eb 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -135,7 +135,7 @@ else:
     var cur, old: Termios
     discard fd.tcgetattr(cur.addr)
     old = cur
-    cur.c_lflag = cur.c_lflag and not Tcflag(ECHO)
+    cur.c_lflag = cur.c_lflag and not Cflag(ECHO)
     discard fd.tcsetattr(TCSADRAIN, cur.addr)
     stdout.write prompt
     result = stdin.readLine(password)
diff --git a/lib/impure/re.nim b/lib/impure/re.nim
index fb95610f6..279f8aadd 100644
--- a/lib/impure/re.nim
+++ b/lib/impure/re.nim
@@ -146,8 +146,8 @@ proc findBounds*(s: string, pattern: Regex,
 
 proc findBounds*(s: string, pattern: Regex,
                  start = 0): tuple[first, last: int] =
-  ## returns the starting position of `pattern` in `s`. If it does not
-  ## match, ``(-1,0)`` is returned.
+  ## returns the starting position and end position of ``pattern`` in ``s``.
+  ## If it does not match, ``(-1,0)`` is returned.
   var
     rtarray = initRtArray[cint](3)
     rawMatches = rtarray.getRawData
diff --git a/lib/impure/ssl.nim b/lib/impure/ssl.nim
index d318a1979..079a2c3a2 100644
--- a/lib/impure/ssl.nim
+++ b/lib/impure/ssl.nim
@@ -15,11 +15,12 @@
 import openssl, strutils, os
 
 type
-  TSecureSocket* = object
+  SecureSocket* = object
     ssl: SslPtr
     bio: BIO
+{.deprecated: [TSecureSocket: SecureSocket].}
 
-proc connect*(sock: var TSecureSocket, address: string, 
+proc connect*(sock: var SecureSocket, address: string, 
     port: int): int =
   ## Connects to the specified `address` on the specified `port`.
   ## Returns the result of the certificate validation.
@@ -52,7 +53,7 @@ proc connect*(sock: var TSecureSocket, address: string,
   
   result = SSL_get_verify_result(sock.ssl)
 
-proc recvLine*(sock: TSecureSocket, line: var TaintedString): bool =
+proc recvLine*(sock: SecureSocket, line: var TaintedString): bool =
   ## Acts in a similar fashion to the `recvLine` in the sockets module.
   ## Returns false when no data is available to be read.
   ## `Line` must be initialized and not nil!
@@ -71,19 +72,19 @@ proc recvLine*(sock: TSecureSocket, line: var TaintedString): bool =
     add(line.string, c)
 
 
-proc send*(sock: TSecureSocket, data: string) =
+proc send*(sock: SecureSocket, data: string) =
   ## Writes `data` to the socket.
   if BIO_write(sock.bio, data, data.len.cint) <= 0:
     raiseOSError(osLastError())
 
-proc close*(sock: TSecureSocket) =
+proc close*(sock: SecureSocket) =
   ## Closes the socket
   if BIO_free(sock.bio) <= 0:
     ERR_print_errors_fp(stderr)
     raiseOSError(osLastError())
 
 when not defined(testing) and isMainModule:
-  var s: TSecureSocket
+  var s: SecureSocket
   echo connect(s, "smtp.gmail.com", 465)
   
   #var buffer: array[0..255, char]
diff --git a/lib/impure/zipfiles.nim b/lib/impure/zipfiles.nim
index c22294061..d8903f5c1 100644
--- a/lib/impure/zipfiles.nim
+++ b/lib/impure/zipfiles.nim
@@ -9,23 +9,23 @@
 
 ## This module implements a zip archive creator/reader/modifier.
 
-import 
-  streams, libzip, times, os
+import
+  streams, libzip, times, os, strutils
 
 type
-  TZipArchive* = object of RootObj ## represents a zip archive
+  ZipArchive* = object of RootObj ## represents a zip archive
     mode: FileMode
     w: PZip
+{.deprecated: [TZipArchive: ZipArchive].}
 
-
-proc zipError(z: var TZipArchive) = 
+proc zipError(z: var ZipArchive) =
   var e: ref IOError
   new(e)
   e.msg = $zip_strerror(z.w)
   raise e
-  
-proc open*(z: var TZipArchive, filename: string, mode: FileMode = fmRead): bool =
-  ## Opens a zip file for reading, writing or appending. All file modes are 
+
+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
@@ -38,24 +38,24 @@ proc open*(z: var TZipArchive, filename: string, mode: FileMode = fmRead): bool
   z.mode = mode
   result = z.w != nil
 
-proc close*(z: var TZipArchive) =
+proc close*(z: var ZipArchive) =
   ## Closes a zip file.
   zip_close(z.w)
- 
-proc createDir*(z: var TZipArchive, dir: string) = 
+
+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 
+  ## 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) 
+  ## 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 TZipArchive, dest, src: string) = 
+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) 
+  ## 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)
@@ -67,26 +67,26 @@ proc addFile*(z: var TZipArchive, dest, src: string) =
     zip_source_free(zipsrc)
     zipError(z)
 
-proc addFile*(z: var TZipArchive, file: string) = 
+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: TZipSourceCmd): int {.cdecl.} = 
+
+proc mySourceCallback(state, data: pointer, len: int,
+                      cmd: ZipSourceCmd): int {.cdecl.} =
   var src = cast[Stream](state)
   case cmd
-  of ZIP_SOURCE_OPEN: 
+  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: 
+  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(TZipStat)
+    result = sizeof(ZipStat)
   of ZIP_SOURCE_ERROR:
     var err = cast[ptr array[0..1, cint]](data)
     err[0] = ZIP_ER_INTERNAL
@@ -94,8 +94,8 @@ proc mySourceCallback(state, data: pointer, len: int,
     result = 2*sizeof(cint)
   of constZIP_SOURCE_FREE: GC_unref(src)
   else: assert(false)
-  
-proc addFile*(z: var TZipArchive, dest: string, src: Stream) = 
+
+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)
@@ -105,39 +105,45 @@ proc addFile*(z: var TZipArchive, dest: string, src: Stream) =
   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 
+  PZipFileStream* =
+    ref TZipFileStream ## a reader stream of a file within a zip archive
 
 proc fsClose(s: Stream) = zip_fclose(PZipFileStream(s).f)
-proc fsReadData(s: Stream, buffer: pointer, bufLen: int): int = 
+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 = 
+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 TZipArchive, filename: string): PZipFileStream = 
+
+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`, 
+  ## 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 TZipArchive): string = 
-  ## walks over all files in the archive `z` and returns the filename 
+
+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)
@@ -146,7 +152,7 @@ iterator walkFiles*(z: var TZipArchive): string =
     inc(i)
 
 
-proc extractFile*(z: var TZipArchive, srcFile: string, dest: Stream) =
+proc extractFile*(z: var ZipArchive, srcFile: string, dest: Stream) =
   ## extracts a file from the zip archive `z` to the destination stream.
   var strm = getStream(z, srcFile)
   while true:
@@ -156,14 +162,22 @@ proc extractFile*(z: var TZipArchive, srcFile: string, dest: Stream) =
   dest.flush()
   strm.close()
 
-proc extractFile*(z: var TZipArchive, srcFile: string, dest: string) =
+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, fmReadWrite)
+  var file = newFileStream(dest, fmWrite)
   extractFile(z, srcFile, file)
   file.close()
 
-proc extractAll*(z: var TZipArchive, dest: string) =
+proc extractAll*(z: var ZipArchive, dest: string) =
   ## extracts all files from archive `z` to the destination directory.
   for file in walkFiles(z):
-    extractFile(z, file, dest / extractFilename(file))
-
+    if file.endsWith("/"):
+      createDir(dest / file)
+    else:
+      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")