diff options
Diffstat (limited to 'lib/impure')
-rw-r--r-- | lib/impure/db_mysql.nim | 61 | ||||
-rw-r--r-- | lib/impure/db_postgres.nim | 88 | ||||
-rw-r--r-- | lib/impure/db_sqlite.nim | 61 | ||||
-rw-r--r-- | lib/impure/graphics.nim | 58 | ||||
-rw-r--r-- | lib/impure/rdstdin.nim | 2 | ||||
-rw-r--r-- | lib/impure/re.nim | 4 | ||||
-rw-r--r-- | lib/impure/ssl.nim | 13 | ||||
-rw-r--r-- | lib/impure/zipfiles.nim | 102 |
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") |