diff options
67 files changed, 2436 insertions, 2436 deletions
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 197286f29..d61d951ba 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## A higher level `mySQL`:idx: database wrapper. The same interface is +## A higher level `mySQL`:idx: database wrapper. The same interface is ## implemented for other databases too. import strutils, mysql @@ -29,22 +29,22 @@ type {.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn].} proc sql*(query: string): SqlQuery {.noSideEffect, inline.} = - ## constructs a SqlQuery from the string `query`. This is supposed to be + ## 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 + ## If assertions are turned off, it does nothing. If assertions are turned ## on, later versions will check the string for valid syntax. result = SqlQuery(query) -proc dbError(db: DbConn) {.noreturn.} = +proc dbError(db: DbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb new(e) e.msg = $mysql.error(db) raise e -proc dbError*(msg: string) {.noreturn.} = +proc dbError*(msg: string) {.noreturn.} = ## raises an EDb exception with message `msg`. var e: ref EDb new(e) @@ -55,9 +55,9 @@ when false: 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: + if mysql_stmt_prepare(stmt, query, len(query)) != 0: dbError(db) - var + var binding: seq[MYSQL_BIND] discard mysql_stmt_close(stmt) @@ -79,9 +79,9 @@ proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = else: add(result, dbQuote(args[a])) inc(a) - else: + else: add(result, c) - + 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. @@ -97,19 +97,19 @@ proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. ## 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): Row = + +proc newRow(L: int): Row = newSeq(result, L) for i in 0..L-1: result[i] = "" - -proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) = + +proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) = if row != nil: while mysql.fetchRow(sqlres) != nil: discard mysql.freeResult(sqlres) - + iterator fastRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = - ## executes the query and iterates over the result dataset. This is very + ## 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!. rawExec(db, query, args) @@ -121,7 +121,7 @@ iterator fastRows*(db: DbConn, query: SqlQuery, while true: row = mysql.fetchRow(sqlres) if row == nil: break - for i in 0..L-1: + for i in 0..L-1: setLen(result[i], 0) if row[i] == nil: result[i] = nil @@ -164,8 +164,8 @@ proc getRow*(db: DbConn, query: SqlQuery, var L = int(mysql.numFields(sqlres)) result = newRow(L) var row = mysql.fetchRow(sqlres) - if row != nil: - for i in 0..L-1: + if row != nil: + for i in 0..L-1: setLen(result[i], 0) if row[i] == nil: result[i] = nil @@ -173,7 +173,7 @@ proc getRow*(db: DbConn, query: SqlQuery, add(result[i], row[i]) properFreeResult(sqlres, row) -proc getAllRows*(db: DbConn, query: SqlQuery, +proc getAllRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): seq[Row] {.tags: [FReadDB].} = ## executes the query and returns the whole result dataset. result = @[] @@ -196,44 +196,44 @@ proc getAllRows*(db: DbConn, query: SqlQuery, inc(j) mysql.freeResult(sqlres) -iterator rows*(db: DbConn, query: SqlQuery, +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: DbConn, query: SqlQuery, - args: varargs[string, `$`]): string {.tags: [FReadDB].} = +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 ## value is NULL. result = getRow(db, query, args)[0] -proc tryInsertId*(db: DbConn, query: SqlQuery, +proc tryInsertId*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## executes the query (typically "INSERT") and returns the + ## executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. var q = dbFormat(query, args) - if mysql.realQuery(db, q, q.len) != 0'i32: + if mysql.realQuery(db, q, q.len) != 0'i32: result = -1'i64 else: result = mysql.insertId(db) - -proc insertId*(db: DbConn, query: SqlQuery, - args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## executes the query (typically "INSERT") and returns the + +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: DbConn, query: SqlQuery, +proc execAffectedRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {. - tags: [FReadDB, FWriteDb].} = + tags: [FReadDB, FWriteDb].} = ## runs the query (typically "UPDATE") and returns the ## number of affected rows rawExec(db, query, args) result = mysql.affectedRows(db) -proc close*(db: DbConn) {.tags: [FDb].} = +proc close*(db: DbConn) {.tags: [FDb].} = ## closes the database connection. if db != nil: mysql.close(db) @@ -242,14 +242,14 @@ proc open*(connection, user, password, database: string): DbConn {. ## opens a database connection. Raises `EDb` if the connection could not ## be established. result = mysql.init(nil) - if result == nil: dbError("could not open database connection") + if result == nil: dbError("could not open database connection") let colonPos = connection.find(':') host = if colonPos < 0: connection else: substr(connection, 0, colonPos-1) port: int32 = if colonPos < 0: 0'i32 else: substr(connection, colonPos+1).parseInt.int32 - if mysql.realConnect(result, host, user, password, database, + if mysql.realConnect(result, host, user, password, database, port, nil, 0) == nil: var errmsg = $mysql.error(result) db_mysql.close(result) @@ -257,6 +257,6 @@ proc open*(connection, user, password, database: string): DbConn {. proc setEncoding*(connection: DbConn, encoding: string): bool {. tags: [FDb].} = - ## sets the encoding of a database connection, returns true for + ## sets the encoding of a database connection, returns true for ## success, false for failure. result = mysql.set_character_set(connection, encoding) == 0 diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index c88e660f4..b75915a72 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## A higher level `PostgreSQL`:idx: database wrapper. This interface +## A higher level `PostgreSQL`:idx: database wrapper. This interface ## is implemented for other databases too. import strutils, postgres @@ -20,7 +20,7 @@ type ## used to get a row's ## column text on demand EDb* = object of IOError ## exception that is raised if a database error occurs - + SqlQuery* = distinct string ## an SQL query string SqlPrepared* = distinct string ## a identifier for the prepared queries @@ -30,15 +30,15 @@ type {.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn, TSqlPrepared: SqlPrepared].} -proc sql*(query: string): SqlQuery {.noSideEffect, inline.} = - ## constructs a SqlQuery 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 + ## If assertions are turned off, it does nothing. If assertions are turned ## on, later versions will check the string for valid syntax. result = SqlQuery(query) - + proc dbError*(db: DbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb @@ -73,7 +73,7 @@ proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = inc(a) else: add(result, c) - + 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. @@ -106,7 +106,7 @@ proc exec*(db: DbConn, stmtName: SqlPrepared, proc newRow(L: int): Row = newSeq(result, L) for i in 0..L-1: result[i] = "" - + proc setupQuery(db: DbConn, query: SqlQuery, args: varargs[string]): PPGresult = var arr = allocCStringArray(args) @@ -128,7 +128,7 @@ proc prepare*(db: DbConn; stmtName: string, query: SqlQuery; var res = pqprepare(db, stmtName, query.string, int32(nParams), nil) if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db) return SqlPrepared(stmtName) - + proc setRow(res: PPGresult, r: var Row, line, cols: int32) = for col in 0..cols-1: setLen(r[col], 0) @@ -140,7 +140,7 @@ proc setRow(res: PPGresult, r: var Row, line, cols: int32) = iterator fastRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = - ## executes the query and iterates over the result dataset. This is very + ## 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. var res = setupQuery(db, query, args) @@ -224,14 +224,14 @@ proc getValue*(db: DbConn, query: SqlQuery, ## value is NULL. var x = pqgetvalue(setupQuery(db, query, args), 0, 0) result = if isNil(x): "" else: $x - + proc tryInsertID*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].}= - ## executes the query (typically "INSERT") and returns the + ## 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, SqlQuery(string(query) & " RETURNING id"), + ## named ``id``. + var x = pqgetvalue(setupQuery(db, SqlQuery(string(query) & " RETURNING id"), args), 0, 0) if not isNil(x): result = parseBiggestInt($x) @@ -240,13 +240,13 @@ proc tryInsertID*(db: DbConn, query: SqlQuery, proc insertID*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## executes the query (typically "INSERT") and returns the + ## executes the query (typically "INSERT") and returns the ## generated ID for the row. For Postgre this adds ## ``RETURNING id`` to the query, so it only works if your primary key is - ## named ``id``. + ## named ``id``. result = tryInsertID(db, query, args) if result < 0: dbError(db) - + proc execAffectedRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [ FReadDB, FWriteDb].} = @@ -286,6 +286,6 @@ proc open*(connection, user, password, database: string): DbConn {. proc setEncoding*(connection: DbConn, encoding: string): bool {. tags: [FDb].} = - ## sets the encoding of a database connection, returns true for + ## sets the encoding of a database connection, returns true for ## success, false for failure. return pqsetClientEncoding(connection, encoding) == 0 diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 1a037becc..66276e9a4 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## A higher level `SQLite`:idx: database wrapper. This interface +## A higher level `SQLite`:idx: database wrapper. This interface ## is implemented for other databases too. import strutils, sqlite3 @@ -19,31 +19,31 @@ type InstantRow* = Pstmt ## a handle that can be used to get a row's column ## text on demand EDb* = object of IOError ## exception that is raised if a database error occurs - + 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): SqlQuery {.noSideEffect, inline.} = - ## constructs a SqlQuery 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 + ## If assertions are turned off, it does nothing. If assertions are turned ## on, later versions will check the string for valid syntax. result = SqlQuery(query) - -proc dbError(db: DbConn) {.noreturn.} = + +proc dbError(db: DbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb new(e) e.msg = $sqlite3.errmsg(db) raise e -proc dbError*(msg: string) {.noreturn.} = +proc dbError*(msg: string) {.noreturn.} = ## raises an EDb exception with message `msg`. var e: ref EDb new(e) @@ -67,8 +67,8 @@ proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = inc(a) else: add(result, c) - -proc tryExec*(db: DbConn, query: SqlQuery, + +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) @@ -81,32 +81,32 @@ 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): Row = newSeq(result, L) for i in 0..L-1: result[i] = "" - -proc setupQuery(db: DbConn, query: SqlQuery, - args: varargs[string]): Pstmt = + +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 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: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDb].} = - ## executes the query and iterates over the result dataset. This is very + ## 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. var stmt = setupQuery(db, query, args) var L = (column_count(stmt)) var result = newRow(L) - while step(stmt) == SQLITE_ROW: + while step(stmt) == SQLITE_ROW: setRow(stmt, result, L) yield result if finalize(stmt) != SQLITE_OK: dbError(db) @@ -136,31 +136,31 @@ proc getRow*(db: DbConn, query: SqlQuery, var stmt = setupQuery(db, query, args) var L = (column_count(stmt)) result = newRow(L) - if step(stmt) == SQLITE_ROW: + if step(stmt) == SQLITE_ROW: setRow(stmt, result, L) if finalize(stmt) != SQLITE_OK: dbError(db) -proc getAllRows*(db: DbConn, query: SqlQuery, +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: DbConn, query: SqlQuery, +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: DbConn, query: SqlQuery, - args: varargs[string, `$`]): string {.tags: [FReadDb].} = +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 ## value is NULL. var stmt = setupQuery(db, query, args) if step(stmt) == SQLITE_ROW: let cb = column_bytes(stmt, 0) - if cb == 0: + if cb == 0: result = "" else: result = newStringOfCap(cb) @@ -168,12 +168,12 @@ proc getValue*(db: DbConn, query: SqlQuery, else: result = "" if finalize(stmt) != SQLITE_OK: dbError(db) - -proc tryInsertID*(db: DbConn, query: SqlQuery, + +proc tryInsertID*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb], raises: [].} = - ## executes the query (typically "INSERT") and returns the - ## generated ID for the row or -1 in case of an error. + ## executes the query (typically "INSERT") and returns the + ## generated ID for the row or -1 in case of an error. var q = dbFormat(query, args) var stmt: sqlite3.Pstmt result = -1 @@ -183,27 +183,27 @@ proc tryInsertID*(db: DbConn, query: SqlQuery, if finalize(stmt) != SQLITE_OK: result = -1 -proc insertID*(db: DbConn, query: SqlQuery, - args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## executes the query (typically "INSERT") and returns the +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 ## ``RETURNING id`` to the query, so it only works if your primary key is - ## named ``id``. + ## named ``id``. result = tryInsertID(db, query, args) if result < 0: dbError(db) - -proc execAffectedRows*(db: DbConn, query: SqlQuery, + +proc execAffectedRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {. - tags: [FReadDb, FWriteDb].} = + tags: [FReadDb, FWriteDb].} = ## executes the query (typically "UPDATE") and returns the ## number of affected rows. exec(db, query, args) result = changes(db) -proc close*(db: DbConn) {.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): DbConn {. tags: [FDb].} = ## opens a database connection. Raises `EDb` if the connection could not @@ -216,12 +216,12 @@ proc open*(connection, user, password, database: string): DbConn {. proc setEncoding*(connection: DbConn, encoding: string): bool {. tags: [FDb].} = - ## sets the encoding of a database connection, returns true for + ## sets the encoding of a database connection, returns true for ## success, false for failure. ## ## Note that the encoding cannot be changed once it's been set. - ## According to SQLite3 documentation, any attempt to change - ## the encoding after the database is created will be silently + ## According to SQLite3 documentation, any attempt to change + ## the encoding after the database is created will be silently ## ignored. exec(connection, sql"PRAGMA encoding = ?", [encoding]) result = connection.getValue(sql"PRAGMA encoding") == encoding diff --git a/lib/impure/graphics.nim b/lib/impure/graphics.nim index 1b3d1d5b6..8bd769fd8 100644 --- a/lib/impure/graphics.nim +++ b/lib/impure/graphics.nim @@ -9,7 +9,7 @@ ## This module implements graphical output for Nim; the current ## implementation uses SDL but the interface is meant to support multiple -## backends some day. There is no need to init SDL as this module does that +## backends some day. There is no need to init SDL as this module does that ## implicitly. import colors, math @@ -24,7 +24,7 @@ type Surface* {.pure, final.} = object w*, h*: Natural s*: sdl.PSurface - + EGraphics* = object of IOError Font {.pure, final.} = object @@ -35,7 +35,7 @@ type proc toSdlColor*(c: Color): sdl.Color = ## Convert colors.Color to sdl.Color - var x = c.extractRGB + var x = c.extractRGB result.r = x.r and 0xff result.g = x.g and 0xff result.b = x.b and 0xff @@ -43,7 +43,7 @@ proc toSdlColor*(c: Color): sdl.Color = proc createSdlColor*(sur: PSurface, c: Color, alpha: int = 0): int32 = ## Creates a color using ``sdl.MapRGBA``. var x = c.extractRGB - return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, + return sdl.mapRGBA(sur.s.format, x.r and 0xff, x.g and 0xff, x.b and 0xff, alpha and 0xff) proc toSdlRect*(r: Rect): sdl.Rect = @@ -53,26 +53,26 @@ proc toSdlRect*(r: Rect): sdl.Rect = result.w = uint16(r.width) result.h = uint16(r.height) -proc raiseEGraphics = +proc raiseEGraphics = raise newException(EGraphics, $sdl.getError()) - + proc surfaceFinalizer(s: PSurface) = sdl.freeSurface(s.s) - + proc newSurface*(width, height: int): PSurface = ## creates a new surface. new(result, surfaceFinalizer) result.w = width result.h = height - result.s = sdl.createRGBSurface(sdl.SWSURFACE, width, height, + result.s = sdl.createRGBSurface(sdl.SWSURFACE, width, height, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0) if result.s == nil: raiseEGraphics() - + assert(not sdl.mustLock(result.s)) proc fontFinalizer(f: PFont) = closeFont(f.f) -proc newFont*(name = "VeraMono.ttf", size = 9, color = colBlack): PFont = +proc newFont*(name = "VeraMono.ttf", size = 9, color = colBlack): PFont = ## Creates a new font object. Raises ``EIO`` if the font cannot be loaded. new(result, fontFinalizer) result.f = openFont(name, size.cint) @@ -84,7 +84,7 @@ var defaultFont*: PFont ## default font that is used; this needs to initialized ## by the client! -proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) = +proc initDefaultFont*(name = "VeraMono.ttf", size = 9, color = colBlack) = ## initializes the `defaultFont` var. defaultFont = newFont(name, size, color) @@ -98,7 +98,7 @@ proc newScreenSurface*(width, height: int): PSurface = raiseEGraphics() proc writeToBMP*(sur: PSurface, filename: string) = - ## Saves the contents of the surface `sur` to the file `filename` as a + ## Saves the contents of the surface `sur` to the file `filename` as a ## BMP file. if sdl.saveBMP(sur.s, filename) != 0: raise newException(IOError, "cannot write: " & filename) @@ -111,7 +111,7 @@ type template setPix(video, pitch, x, y, col: expr): stmt = video[y * pitch + x] = int32(col) -template getPix(video, pitch, x, y: expr): expr = +template getPix(video, pitch, x, y: expr): expr = colors.Color(video[y * pitch + x]) const @@ -120,7 +120,7 @@ const proc getPixel(sur: PSurface, x, y: Natural): colors.Color {.inline.} = assert x <% sur.w assert y <% sur.h - result = getPix(cast[PPixels](sur.s.pixels), sur.s.pitch.int div ColSize, + result = getPix(cast[PPixels](sur.s.pixels), sur.s.pitch.int div ColSize, x, y) proc setPixel(sur: PSurface, x, y: Natural, col: colors.Color) {.inline.} = @@ -146,7 +146,7 @@ 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: Rect, srcSurf: PSurface, +proc blit*(destSurf: PSurface, destRect: Rect, srcSurf: PSurface, srcRect: Rect) = ## Copies ``srcSurf`` into ``destSurf`` var destTRect, srcTRect: sdl.Rect @@ -175,7 +175,7 @@ proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) = ## font. var textSur: PSurface # This surface will have the text drawn on it new(textSur, surfaceFinalizer) - + # Render the text textSur.s = sdl_ttf.renderTextBlended(font.f, text, font.color) # Merge the text surface with sur @@ -183,14 +183,14 @@ proc drawText*(sur: PSurface, p: Point, text: string, font = defaultFont) = proc drawText*(sur: PSurface, p: Point, text: string, bg: Color, font = defaultFont) = - ## Draws text, at location ``p`` with font ``font``. ``bg`` + ## Draws text, at location ``p`` with font ``font``. ``bg`` ## is the background color. var textSur: PSurface # This surface will have the text drawn on it new(textSur, surfaceFinalizer) textSur.s = sdl_ttf.renderTextShaded(font.f, text, font.color, toSdlColor(bg)) # 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: Point, r: Natural, color: Color) = ## draws a circle with center `p` and radius `r` with the given color ## onto the surface `sur`. @@ -205,7 +205,7 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = if x+px <% sur.w: if y+py <% sur.h: setPix(video, pitch, x+px, y+py, color) if y-py <% sur.h: setPix(video, pitch, x+px, y-py, color) - + if x-px <% sur.w: if y+py <% sur.h: setPix(video, pitch, x-px, y+py, color) if y-py <% sur.h: setPix(video, pitch, x-px, y-py, color) @@ -213,7 +213,7 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = if x+py <% sur.w: if y+px <% sur.h: setPix(video, pitch, x+py, y+px, color) if y-px <% sur.h: setPix(video, pitch, x+py, y-px, color) - + if x-py <% sur.w: if y+px <% sur.h: setPix(video, pitch, x-py, y+px, color) if y-px <% sur.h: setPix(video, pitch, x-py, y-px, color) @@ -225,10 +225,10 @@ proc drawCircle*(sur: PSurface, p: Point, r: Natural, color: Color) = py = py - 1 px = px + 1 -proc `>-<`(val: int, s: PSurface): int {.inline.} = +proc `>-<`(val: int, s: PSurface): int {.inline.} = return if val < 0: 0 elif val >= s.w: s.w-1 else: val -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: Point, color: Color) = @@ -242,7 +242,7 @@ proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) = var dy = y1 - y0 var dx = x1 - x0 if dy < 0: - dy = -dy + dy = -dy stepy = -1 else: stepy = 1 @@ -251,7 +251,7 @@ proc drawLine*(sur: PSurface, p1, p2: Point, color: Color) = stepx = -1 else: stepx = 1 - dy = dy * 2 + dy = dy * 2 dx = dx * 2 var video = cast[PPixels](sur.s.pixels) var pitch = sur.s.pitch.int div ColSize @@ -328,17 +328,17 @@ proc drawRect*(sur: PSurface, r: Rect, color: Color) = if (r.x >= 0 and r.x <= sur.s.w) and (r.y >= 0 and r.y <= sur.s.h): var minW = min(sur.s.w - r.x, r.width) var minH = min(sur.s.h - r.y, r.height) - + # Draw Top for i in 0 .. minW - 1: setPix(video, pitch, r.x + i, r.y, color) setPix(video, pitch, r.x + i, r.y + minH - 1, color) # Draw bottom - + # Draw left side for i in 0 .. minH - 1: 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: Rect, col: Color) = ## Fills a rectangle using sdl's ``FillRect`` function. var rect = toSdlRect(r) @@ -350,23 +350,23 @@ proc plot4EllipsePoints(sur: PSurface, cx, cy, x, y: Natural, col: Color) = var pitch = sur.s.pitch.int div ColSize if cx+x <= sur.s.w-1: if cy+y <= sur.s.h-1: setPix(video, pitch, cx+x, cy+y, col) - if cy-y <= sur.s.h-1: setPix(video, pitch, cx+x, cy-y, col) + if cy-y <= sur.s.h-1: setPix(video, pitch, cx+x, cy-y, col) if cx-x <= sur.s.w-1: if cy+y <= sur.s.h-1: setPix(video, pitch, cx-x, cy+y, col) if cy-y <= sur.s.h-1: setPix(video, pitch, cx-x, cy-y, col) -proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, +proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, col: Color) = - ## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of the + ## Draws an ellipse, ``CX`` and ``CY`` specify the center X and Y of the ## ellipse, ``XRadius`` and ``YRadius`` specify half the width and height ## of the ellipse. - var + var x, y: Natural xChange, yChange: int ellipseError: Natural twoASquare, twoBSquare: Natural stoppingX, stoppingY: Natural - + twoASquare = 2 * xRadius * xRadius twoBSquare = 2 * yRadius * yRadius x = xRadius @@ -376,7 +376,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, ellipseError = 0 stoppingX = twoBSquare * xRadius stoppingY = 0 - + while stoppingX >= stoppingY: # 1st set of points, y` > - 1 sur.plot4EllipsePoints(cx, cy, x, y, col) inc(y) @@ -388,7 +388,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, dec(stoppingX, twoBSquare) inc(ellipseError, xChange) inc(xChange, twoBSquare) - + # 1st point set is done; start the 2nd set of points x = 0 y = yRadius @@ -408,7 +408,7 @@ proc drawEllipse*(sur: PSurface, cx, cy, xRadius, yRadius: Natural, dec(stoppingY, twoASquare) inc(ellipseError, yChange) inc(yChange,twoASquare) - + proc plotAA(sur: PSurface, x, y: int, c: float, color: Color) = if (x > 0 and x < sur.s.w) and (y > 0 and y < sur.s.h): @@ -419,43 +419,43 @@ proc plotAA(sur: PSurface, x, y: int, c: float, color: Color) = setPix(video, pitch, x, y, pixColor.intensity(1.0 - c) + color.intensity(c)) - -template ipart(x: expr): expr = floor(x) + +template ipart(x: expr): expr = floor(x) 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: Point, color: Color) = - ## Draws a anti-aliased line from ``p1`` to ``p2``, using Xiaolin Wu's + ## 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(), + var (x1, x2, y1, y2) = (p1.x.toFloat(), p2.x.toFloat(), p1.y.toFloat(), p2.y.toFloat()) var dx = x2 - x1 var dy = y2 - y1 - + var ax = dx if ax < 0'f64: ax = 0'f64 - ax var ay = dy if ay < 0'f64: ay = 0'f64 - ay - + if ax < ay: swap(x1, y1) swap(x2, y2) swap(dx, dy) - + template doPlot(x, y: int, c: float, color: Color): stmt = if ax < ay: sur.plotAA(y, x, c, color) else: sur.plotAA(x, y, c, color) - + if x2 < x1: swap(x1, x2) swap(y1, y2) - + var gradient = dy / dx # handle first endpoint var xend = cround(x1) @@ -509,19 +509,19 @@ when not defined(testing) and isMainModule: # Draw the shapes surf.drawLineAA((150, 170), (400, 471), colTan) surf.drawLine((100, 170), (400, 471), colRed) - + surf.drawEllipse(200, 300, 200, 30, colSeaGreen) - surf.drawHorLine(1, 300, 400, colViolet) + surf.drawHorLine(1, 300, 400, colViolet) # Check if the ellipse is the size it's suppose to be. surf.drawVerLine(200, 300 - 30 + 1, 60, colViolet) # ^^ | i suppose it is - + surf.drawEllipse(400, 300, 300, 300, colOrange) surf.drawEllipse(5, 5, 5, 5, colGreen) - + surf.drawHorLine(5, 5, 900, colRed) surf.drawVerLine(5, 60, 800, colRed) surf.drawCircle((600, 500), 60, colRed) - + surf.fillRect((50, 50, 100, 100), colFuchsia) surf.fillRect((150, 50, 100, 100), colGreen) surf.drawRect((50, 150, 100, 100), colGreen) @@ -530,12 +530,12 @@ when not defined(testing) and isMainModule: surf.drawHorLine(250, 150, 100, colRed) surf.drawLineAA((592, 160), (592, 280), colPurple) - + #surf.drawText((300, 300), "TEST", colMidnightBlue) #var textSize = textBounds("TEST") #surf.drawText((300, 300 + textSize.height), $textSize.width & ", " & # $textSize.height, colDarkGreen) - + var mouseStartX = -1 var mouseStartY = -1 withEvents(surf, event): @@ -561,17 +561,17 @@ when not defined(testing) and isMainModule: surf.drawLineAA((mouseStartX, mouseStartY), (int(mbd.x), int(mbd.y)), colPurple) mouseStartX = -1 mouseStartY = -1 - + of sdl.MOUSEMOTION: var mm = sdl.evMouseMotion(eventp) if mouseStartX != -1 and mouseStartY != -1: surf.drawLineAA((mouseStartX, mouseStartY), (int(mm.x), int(mm.y)), colPurple) #echo(mm.x, " ", mm.y, " ", mm.yrel) - + else: discard "echo(event.kind)" - + sdl.updateRect(surf.s, 0, 0, 800, 600) - + surf.writeToBMP("test.bmp") sdl.quit() diff --git a/lib/impure/re.nim b/lib/impure/re.nim index 0df8d4a9c..30081bb19 100644 --- a/lib/impure/re.nim +++ b/lib/impure/re.nim @@ -41,11 +41,11 @@ type reExtended = 3, ## ignore whitespace and ``#`` comments reStudy = 4 ## study the expression (may be omitted if the ## expression will be used only once) - - RegexDesc = object + + RegexDesc = object h: ptr Pcre e: ptr ExtraData - + Regex* {.deprecated.} = ref RegexDesc ## a compiled regular expression RegexError* = object of ValueError diff --git a/lib/impure/ssl.nim b/lib/impure/ssl.nim index 079a2c3a2..721e5ce51 100644 --- a/lib/impure/ssl.nim +++ b/lib/impure/ssl.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## This module provides an easy to use sockets-style +## This module provides an easy to use sockets-style ## nim interface to the OpenSSL library. {.deprecated.} @@ -20,37 +20,37 @@ type bio: BIO {.deprecated: [TSecureSocket: SecureSocket].} -proc connect*(sock: var SecureSocket, 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. SslLoadErrorStrings() ERR_load_BIO_strings() - + if SSL_library_init() != 1: raiseOSError(osLastError()) - + var ctx = SSL_CTX_new(SSLv23_client_method()) if ctx == nil: ERR_print_errors_fp(stderr) raiseOSError(osLastError()) - - #if SSL_CTX_load_verify_locations(ctx, + + #if SSL_CTX_load_verify_locations(ctx, # "/tmp/openssl-0.9.8e/certs/vsign1.pem", NIL) == 0: # echo("Failed load verify locations") # ERR_print_errors_fp(stderr) - + sock.bio = BIO_new_ssl_connect(ctx) if BIO_get_ssl(sock.bio, addr(sock.ssl)) == 0: raiseOSError(osLastError()) if BIO_set_conn_hostname(sock.bio, address & ":" & $port) != 1: raiseOSError(osLastError()) - + if BIO_do_connect(sock.bio) <= 0: ERR_print_errors_fp(stderr) raiseOSError(osLastError()) - + result = SSL_get_verify_result(sock.ssl) proc recvLine*(sock: SecureSocket, line: var TaintedString): bool = @@ -86,12 +86,12 @@ proc close*(sock: SecureSocket) = when not defined(testing) and isMainModule: var s: SecureSocket echo connect(s, "smtp.gmail.com", 465) - + #var buffer: array[0..255, char] #echo BIO_read(bio, buffer, buffer.len) var buffer: string = "" - + echo s.recvLine(buffer) - echo buffer + echo buffer echo buffer.len - + diff --git a/lib/nimrtl.nim b/lib/nimrtl.nim index 96dab1284..4e4cf7e0e 100644 --- a/lib/nimrtl.nim +++ b/lib/nimrtl.nim @@ -7,8 +7,8 @@ # distribution, for details about the copyright. # -## Main file to generate a DLL from the standard library. -## The default Nimrtl does not only contain the ``system`` module, but these +## Main file to generate a DLL from the standard library. +## The default Nimrtl does not only contain the ``system`` module, but these ## too: ## ## * parseutils @@ -22,12 +22,12 @@ ## * unicode ## * pegs ## * ropes -## +## when system.appType != "lib": {.error: "This file has to be compiled as a library!".} -when not defined(createNimRtl): +when not defined(createNimRtl): {.error: "This file has to be compiled with '-d:createNimRtl'".} import diff --git a/lib/posix/epoll.nim b/lib/posix/epoll.nim index bc84611a6..276dd812d 100644 --- a/lib/posix/epoll.nim +++ b/lib/posix/epoll.nim @@ -29,34 +29,34 @@ const # Valid opcodes ( "op" parameter ) to issue to epoll_ctl(). -const - EPOLL_CTL_ADD* = 1 # Add a file descriptor to the interface. - EPOLL_CTL_DEL* = 2 # Remove a file descriptor from the interface. - EPOLL_CTL_MOD* = 3 # Change file descriptor epoll_event structure. +const + EPOLL_CTL_ADD* = 1 # Add a file descriptor to the interface. + EPOLL_CTL_DEL* = 2 # Remove a file descriptor from the interface. + EPOLL_CTL_MOD* = 3 # Change file descriptor epoll_event structure. -type - epoll_data* {.importc: "union epoll_data", +type + epoll_data* {.importc: "union epoll_data", header: "<sys/epoll.h>", pure, final.} = object # TODO: This is actually a union. #thePtr* {.importc: "ptr".}: pointer fd* {.importc: "fd".}: cint # \ #u32*: uint32 #u64*: uint64 - epoll_event* {.importc: "struct epoll_event", header: "<sys/epoll.h>", pure, final.} = object - events*: uint32 # Epoll events - data*: epoll_data # User data variable + epoll_event* {.importc: "struct epoll_event", header: "<sys/epoll.h>", pure, final.} = object + events*: uint32 # Epoll events + data*: epoll_data # User data variable -proc epoll_create*(size: cint): cint {.importc: "epoll_create", +proc epoll_create*(size: cint): cint {.importc: "epoll_create", header: "<sys/epoll.h>".} ## Creates an epoll instance. Returns an fd for the new instance. ## The "size" parameter is a hint specifying the number of file ## descriptors to be associated with the new instance. The fd - ## returned by epoll_create() should be closed with close(). + ## returned by epoll_create() should be closed with close(). -proc epoll_create1*(flags: cint): cint {.importc: "epoll_create1", +proc epoll_create1*(flags: cint): cint {.importc: "epoll_create1", header: "<sys/epoll.h>".} ## Same as epoll_create but with an FLAGS parameter. The unused SIZE - ## parameter has been dropped. + ## parameter has been dropped. proc epoll_ctl*(epfd: cint; op: cint; fd: cint | SocketHandle; event: ptr epoll_event): cint {. importc: "epoll_ctl", header: "<sys/epoll.h>".} @@ -65,10 +65,10 @@ proc epoll_ctl*(epfd: cint; op: cint; fd: cint | SocketHandle; event: ptr epoll_ ## specific error code ) The "op" parameter is one of the EPOLL_CTL_* ## constants defined above. The "fd" parameter is the target of the ## operation. The "event" parameter describes which events the caller - ## is interested in and any associated user data. + ## is interested in and any associated user data. -proc epoll_wait*(epfd: cint; events: ptr epoll_event; maxevents: cint; - timeout: cint): cint {.importc: "epoll_wait", +proc epoll_wait*(epfd: cint; events: ptr epoll_event; maxevents: cint; + timeout: cint): cint {.importc: "epoll_wait", header: "<sys/epoll.h>".} ## Wait for events on an epoll instance "epfd". Returns the number of ## triggered events returned in "events" buffer. Or -1 in case of @@ -82,11 +82,11 @@ proc epoll_wait*(epfd: cint; events: ptr epoll_event; maxevents: cint; ## __THROW. -#proc epoll_pwait*(epfd: cint; events: ptr epoll_event; maxevents: cint; +#proc epoll_pwait*(epfd: cint; events: ptr epoll_event; maxevents: cint; # timeout: cint; ss: ptr sigset_t): cint {. # importc: "epoll_pwait", header: "<sys/epoll.h>".} # Same as epoll_wait, but the thread's signal mask is temporarily # and atomically replaced with the one provided as parameter. # # This function is a cancellation point and therefore not marked with -# __THROW. +# __THROW. diff --git a/lib/posix/inotify.nim b/lib/posix/inotify.nim index 14cac4d72..a206f8067 100644 --- a/lib/posix/inotify.nim +++ b/lib/posix/inotify.nim @@ -9,65 +9,65 @@ {.deadCodeElim:on.} -# Get the platform-dependent flags. -# Structure describing an inotify event. -type - InotifyEvent*{.pure, final, importc: "struct inotify_event", - header: "<sys/inotify.h>".} = object - wd*{.importc: "wd".}: cint # Watch descriptor. - mask*{.importc: "mask".}: uint32 # Watch mask. - cookie*{.importc: "cookie".}: uint32 # Cookie to synchronize two events. - len*{.importc: "len".}: uint32 # Length (including NULs) of name. - name*{.importc: "name".}: char # Name. +# Get the platform-dependent flags. +# Structure describing an inotify event. +type + InotifyEvent*{.pure, final, importc: "struct inotify_event", + header: "<sys/inotify.h>".} = object + wd*{.importc: "wd".}: cint # Watch descriptor. + mask*{.importc: "mask".}: uint32 # Watch mask. + cookie*{.importc: "cookie".}: uint32 # Cookie to synchronize two events. + len*{.importc: "len".}: uint32 # Length (including NULs) of name. + name*{.importc: "name".}: char # Name. {.deprecated: [Tinotify_event: InotifyEvent].} -# Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. -const - IN_ACCESS* = 0x00000001 # File was accessed. - IN_MODIFY* = 0x00000002 # File was modified. - IN_ATTRIB* = 0x00000004 # Metadata changed. - IN_CLOSE_WRITE* = 0x00000008 # Writtable file was closed. - IN_CLOSE_NOWRITE* = 0x00000010 # Unwrittable file closed. - IN_CLOSE* = (IN_CLOSE_WRITE or IN_CLOSE_NOWRITE) # Close. - IN_OPEN* = 0x00000020 # File was opened. - IN_MOVED_FROM* = 0x00000040 # File was moved from X. - IN_MOVED_TO* = 0x00000080 # File was moved to Y. - IN_MOVE* = (IN_MOVED_FROM or IN_MOVED_TO) # Moves. - IN_CREATE* = 0x00000100 # Subfile was created. - IN_DELETE* = 0x00000200 # Subfile was deleted. - IN_DELETE_SELF* = 0x00000400 # Self was deleted. - IN_MOVE_SELF* = 0x00000800 # Self was moved. -# Events sent by the kernel. -const - IN_UNMOUNT* = 0x00002000 # Backing fs was unmounted. - IN_Q_OVERFLOW* = 0x00004000 # Event queued overflowed. - IN_IGNORED* = 0x00008000 # File was ignored. -# Special flags. -const +# Supported events suitable for MASK parameter of INOTIFY_ADD_WATCH. +const + IN_ACCESS* = 0x00000001 # File was accessed. + IN_MODIFY* = 0x00000002 # File was modified. + IN_ATTRIB* = 0x00000004 # Metadata changed. + IN_CLOSE_WRITE* = 0x00000008 # Writtable file was closed. + IN_CLOSE_NOWRITE* = 0x00000010 # Unwrittable file closed. + IN_CLOSE* = (IN_CLOSE_WRITE or IN_CLOSE_NOWRITE) # Close. + IN_OPEN* = 0x00000020 # File was opened. + IN_MOVED_FROM* = 0x00000040 # File was moved from X. + IN_MOVED_TO* = 0x00000080 # File was moved to Y. + IN_MOVE* = (IN_MOVED_FROM or IN_MOVED_TO) # Moves. + IN_CREATE* = 0x00000100 # Subfile was created. + IN_DELETE* = 0x00000200 # Subfile was deleted. + IN_DELETE_SELF* = 0x00000400 # Self was deleted. + IN_MOVE_SELF* = 0x00000800 # Self was moved. +# Events sent by the kernel. +const + IN_UNMOUNT* = 0x00002000 # Backing fs was unmounted. + IN_Q_OVERFLOW* = 0x00004000 # Event queued overflowed. + IN_IGNORED* = 0x00008000 # File was ignored. +# Special flags. +const IN_ONLYDIR* = 0x01000000 # Only watch the path if it is a - # directory. - IN_DONT_FOLLOW* = 0x02000000 # Do not follow a sym link. + # directory. + IN_DONT_FOLLOW* = 0x02000000 # Do not follow a sym link. IN_EXCL_UNLINK* = 0x04000000 # Exclude events on unlinked - # objects. + # objects. IN_MASK_ADD* = 0x20000000 # Add to the mask of an already - # existing watch. - IN_ISDIR* = 0x40000000 # Event occurred against dir. - IN_ONESHOT* = 0x80000000 # Only send event once. -# All events which a program can wait on. -const + # existing watch. + IN_ISDIR* = 0x40000000 # Event occurred against dir. + IN_ONESHOT* = 0x80000000 # Only send event once. +# All events which a program can wait on. +const IN_ALL_EVENTS* = (IN_ACCESS or IN_MODIFY or IN_ATTRIB or IN_CLOSE_WRITE or IN_CLOSE_NOWRITE or IN_OPEN or IN_MOVED_FROM or IN_MOVED_TO or IN_CREATE or IN_DELETE or IN_DELETE_SELF or IN_MOVE_SELF) # Create and initialize inotify instance. -proc inotify_init*(): cint{.cdecl, importc: "inotify_init", +proc inotify_init*(): cint{.cdecl, importc: "inotify_init", header: "<sys/inotify.h>".} -# Create and initialize inotify instance. -proc inotify_init1*(flags: cint): cint{.cdecl, importc: "inotify_init1", +# Create and initialize inotify instance. +proc inotify_init1*(flags: cint): cint{.cdecl, importc: "inotify_init1", header: "<sys/inotify.h>".} # Add watch of object NAME to inotify instance FD. Notify about -# events specified by MASK. +# events specified by MASK. proc inotify_add_watch*(fd: cint; name: cstring; mask: uint32): cint{. cdecl, importc: "inotify_add_watch", header: "<sys/inotify.h>".} -# Remove the watch specified by WD from the inotify instance FD. -proc inotify_rm_watch*(fd: cint; wd: cint): cint{.cdecl, +# Remove the watch specified by WD from the inotify instance FD. +proc inotify_rm_watch*(fd: cint; wd: cint): cint{.cdecl, importc: "inotify_rm_watch", header: "<sys/inotify.h>".} diff --git a/lib/posix/linux.nim b/lib/posix/linux.nim index 05eab52bc..01d5e57de 100644 --- a/lib/posix/linux.nim +++ b/lib/posix/linux.nim @@ -24,5 +24,5 @@ const # fn should be of type proc (a2: pointer): void {.cdecl.} proc clone*(fn: pointer; child_stack: pointer; flags: cint; - arg: pointer; ptid: ptr Pid; tls: pointer; + arg: pointer; ptid: ptr Pid; tls: pointer; ctid: ptr Pid): cint {.importc, header: "<sched.h>".} diff --git a/lib/pure/actors.nim b/lib/pure/actors.nim index da9037285..f0791f954 100644 --- a/lib/pure/actors.nim +++ b/lib/pure/actors.nim @@ -41,7 +41,7 @@ type Actor[In, Out] = object{.pure, final.} i: Channel[Task[In, Out]] t: TThread[ptr Actor[In, Out]] - + PActor*[In, Out] = ptr Actor[In, Out] ## an actor {.deprecated: [TTask: Task, TActor: Actor].} @@ -83,7 +83,7 @@ proc send*[In, Out, X, Y](receiver: PActor[In, Out], msg: In, shallowCopy(t.data, msg) send(receiver.i, t) -proc send*[In, Out](receiver: PActor[In, Out], msg: In, +proc send*[In, Out](receiver: PActor[In, Out], msg: In, sender: ptr Channel[Out] = nil) = ## sends a message to `receiver`'s inbox. var t: Task[In, Out] @@ -138,7 +138,7 @@ proc createActorPool*[In, Out](a: var ActorPool[In, Out], poolSize = 4) = proc sync*[In, Out](a: var ActorPool[In, Out], polling=50) = ## waits for every actor of `a` to finish with its work. Currently this is - ## implemented as polling every `polling` ms and has a slight chance + ## implemented as polling every `polling` ms and has a slight chance ## of failing since we check for every actor to be in `ready` state and not ## for messages still in ether. This will change in a later ## version, however. @@ -146,7 +146,7 @@ proc sync*[In, Out](a: var ActorPool[In, Out], polling=50) = while true: var wait = false for i in 0..high(a.actors): - if not a.actors[i].i.ready: + if not a.actors[i].i.ready: wait = true allReadyCount = 0 break @@ -222,7 +222,7 @@ proc spawn*[In](p: var ActorPool[In, void], input: In, var t: Task[In, void] setupTask() schedule() - + when not defined(testing) and isMainModule: var a: ActorPool[int, void] diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim index ece9b4dfb..c7b9fac18 100644 --- a/lib/pure/asyncfile.nim +++ b/lib/pure/asyncfile.nim @@ -195,10 +195,10 @@ proc read*(f: AsyncFile, size: int): Future[string] = readBuffer.setLen(res) f.offset.inc(res) retFuture.complete(readBuffer) - + if not cb(f.fd): addRead(f.fd, cb) - + return retFuture proc readLine*(f: AsyncFile): Future[string] {.async.} = @@ -222,7 +222,7 @@ proc getFilePos*(f: AsyncFile): int64 = proc setFilePos*(f: AsyncFile, pos: int64) = ## Sets the position of the file pointer that is used for read/write - ## operations. The file's first byte has the index zero. + ## operations. The file's first byte has the index zero. f.offset = pos when not defined(windows) and not defined(nimdoc): let ret = lseek(f.fd.cint, pos, SEEK_SET) @@ -291,7 +291,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = retFuture.complete() else: var written = 0 - + proc cb(fd: AsyncFD): bool = result = true let remainderSize = data.len-written @@ -309,7 +309,7 @@ proc write*(f: AsyncFile, data: string): Future[void] = result = false # We still have data to write. else: retFuture.complete() - + if not cb(f.fd): addWrite(f.fd, cb) return retFuture diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim index 41d19dc0f..deab39c7c 100644 --- a/lib/pure/base64.nim +++ b/lib/pure/base64.nim @@ -9,11 +9,11 @@ ## This module implements a base64 encoder and decoder. -const +const cb64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" -template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediate.} = - ## encodes `s` into base64 representation. After `lineLen` characters, a +template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediate.} = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. var total = ((len(s) + 2) div 3) * 4 var numLines = (total + lineLen - 1) div lineLen @@ -29,13 +29,13 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat var c = ord(s[i+2]) result[r] = cb64[a shr 2] result[r+1] = cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result[r+2] = cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)] - result[r+3] = cb64[c and 0x3F] + result[r+2] = cb64[((b and 0x0F) shl 2) or ((c and 0xC0) shr 6)] + result[r+3] = cb64[c and 0x3F] inc(r, 4) inc(i, 3) inc(currLine, 4) - if currLine >= lineLen and i != s.len-2: - for x in items(newLine): + if currLine >= lineLen and i != s.len-2: + for x in items(newLine): result[r] = x inc(r) currLine = 0 @@ -45,7 +45,7 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat var b = ord(s[i+1]) result[r] = cb64[a shr 2] result[r+1] = cb64[((a and 3) shl 4) or ((b and 0xF0) shr 4)] - result[r+2] = cb64[((b and 0x0F) shl 2)] + result[r+2] = cb64[((b and 0x0F) shl 2)] result[r+3] = '=' if r+4 != result.len: setLen(result, r+4) @@ -61,17 +61,17 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat #assert(r == result.len) discard -proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = - ## encodes `s` into base64 representation. After `lineLen` characters, a +proc encode*[T:SomeInteger|char](s: openarray[T], lineLen = 75, newLine="\13\10"): string = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. encodeInternal(s, lineLen, newLine) - -proc encode*(s: string, lineLen = 75, newLine="\13\10"): string = - ## encodes `s` into base64 representation. After `lineLen` characters, a + +proc encode*(s: string, lineLen = 75, newLine="\13\10"): string = + ## encodes `s` into base64 representation. After `lineLen` characters, a ## `newline` is added. encodeInternal(s, lineLen, newLine) - -proc decodeByte(b: char): int {.inline.} = + +proc decodeByte(b: char): int {.inline.} = case b of '+': result = ord('>') of '0'..'9': result = ord(b) + 4 @@ -79,7 +79,7 @@ proc decodeByte(b: char): int {.inline.} = of 'a'..'z': result = ord(b) - 71 else: result = 63 -proc decode*(s: string): string = +proc decode*(s: string): string = ## decodes a string in base64 representation back into its original form. ## Whitespace is skipped. const Whitespace = {' ', '\t', '\v', '\r', '\l', '\f'} @@ -96,7 +96,7 @@ proc decode*(s: string): string = var b = s[i+1].decodeByte var c = s[i+2].decodeByte var d = s[i+3].decodeByte - + result[r] = chr((a shl 2) and 0xff or ((b shr 4) and 0x03)) result[r+1] = chr((b shl 4) and 0xff or ((c shr 2) and 0x0F)) result[r+2] = chr((c shl 6) and 0xff or (d and 0x3F)) @@ -105,19 +105,19 @@ proc decode*(s: string): string = else: break assert i == s.len # adjust the length: - if i > 0 and s[i-1] == '=': + if i > 0 and s[i-1] == '=': dec(r) if i > 1 and s[i-2] == '=': dec(r) setLen(result, r) - + when isMainModule: assert encode("leasure.") == "bGVhc3VyZS4=" assert encode("easure.") == "ZWFzdXJlLg==" assert encode("asure.") == "YXN1cmUu" assert encode("sure.") == "c3VyZS4=" - + const longText = """Man is distinguished, not only by his reason, but by this - singular passion from other animals, which is a lust of the mind, + singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.""" diff --git a/lib/pure/basic2d.nim b/lib/pure/basic2d.nim index 1392fdeba..ad8f8653d 100644 --- a/lib/pure/basic2d.nim +++ b/lib/pure/basic2d.nim @@ -13,26 +13,26 @@ import strutils ## Basic 2d support with vectors, points, matrices and some basic utilities. ## Vectors are implemented as direction vectors, ie. when transformed with a matrix -## the translation part of matrix is ignored. +## the translation part of matrix is ignored. ## Operators `+` , `-` , `*` , `/` , `+=` , `-=` , `*=` and `/=` are implemented for vectors and scalars. ## ## Quick start example: -## +## ## # Create a matrix which first rotates, then scales and at last translates -## +## ## var m:Matrix2d=rotate(DEG90) & scale(2.0) & move(100.0,200.0) -## +## ## # Create a 2d point at (100,0) and a vector (5,2) -## -## var pt:Point2d=point2d(100.0,0.0) -## +## +## var pt:Point2d=point2d(100.0,0.0) +## ## var vec:Vector2d=vector2d(5.0,2.0) -## -## +## +## ## pt &= m # transforms pt in place -## +## ## var pt2:Point2d=pt & m #concatenates pt with m and returns a new point -## +## ## var vec2:Vector2d=vec & m #concatenates vec with m and returns a new vector @@ -64,12 +64,12 @@ type ## not used for geometric transformations in 2d. ax*,ay*,bx*,by*,tx*,ty*:float Point2d* = object - ## Implements a non-homogeneous 2d point stored as + ## Implements a non-homogeneous 2d point stored as ## an `x` coordinate and an `y` coordinate. x*,y*:float - Vector2d* = object - ## Implements a 2d **direction vector** stored as - ## an `x` coordinate and an `y` coordinate. Direction vector means, + Vector2d* = object + ## Implements a 2d **direction vector** stored as + ## an `x` coordinate and an `y` coordinate. Direction vector means, ## that when transforming a vector with a matrix, the translational ## part of the matrix is ignored. x*,y*:float @@ -78,7 +78,7 @@ type # Some forward declarations... proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d {.noInit.} - ## Creates a new matrix. + ## Creates a new matrix. ## `ax`,`ay` is the local x axis ## `bx`,`by` is the local y axis ## `tx`,`ty` is the translation @@ -99,7 +99,7 @@ let YAXIS*:Vector2d=vector2d(0.0,1.0) ## Quick acces to an 2d y-axis unit vector - + # *************************************** # Private utils # *************************************** @@ -114,13 +114,13 @@ proc safeArccos(v:float):float= return arccos(clamp(v,-1.0,1.0)) -template makeBinOpVector(s:expr)= +template makeBinOpVector(s:expr)= ## implements binary operators + , - , * and / for vectors proc s*(a,b:Vector2d):Vector2d {.inline,noInit.} = vector2d(s(a.x,b.x),s(a.y,b.y)) proc s*(a:Vector2d,b:float):Vector2d {.inline,noInit.} = vector2d(s(a.x,b),s(a.y,b)) proc s*(a:float,b:Vector2d):Vector2d {.inline,noInit.} = vector2d(s(a,b.x),s(a,b.y)) - -template makeBinOpAssignVector(s:expr)= + +template makeBinOpAssignVector(s:expr)= ## implements inplace binary operators += , -= , /= and *= for vectors proc s*(a:var Vector2d,b:Vector2d) {.inline.} = s(a.x,b.x) ; s(a.y,b.y) proc s*(a:var Vector2d,b:float) {.inline.} = s(a.x,b) ; s(a.y,b) @@ -144,7 +144,7 @@ proc matrix2d*(ax,ay,bx,by,tx,ty:float):Matrix2d = proc `&`*(a,b:Matrix2d):Matrix2d {.noInit.} = #concatenate matrices ## Concatenates matrices returning a new matrix. - + # | a.AX a.AY 0 | | b.AX b.AY 0 | # | a.BX a.BY 0 | * | b.BX b.BY 0 | # | a.TX a.TY 1 | | b.TX b.TY 1 | @@ -153,7 +153,7 @@ proc `&`*(a,b:Matrix2d):Matrix2d {.noInit.} = #concatenate matrices a.ax * b.ay + a.ay * b.by, a.bx * b.ax + a.by * b.bx, a.bx * b.ay + a.by * b.by, - a.tx * b.ax + a.ty * b.bx + b.tx, + a.tx * b.ax + a.ty * b.bx + b.tx, a.tx * b.ay + a.ty * b.by + b.ty) @@ -169,13 +169,13 @@ proc stretch*(sx,sy:float):Matrix2d {.noInit.} = ## Returns new a stretch matrix, which is a ## scale matrix with non uniform scale in x and y. result.setElements(sx,0,0,sy,0,0) - + proc stretch*(sx,sy:float,org:Point2d):Matrix2d {.noInit.} = ## Returns a new stretch matrix, which is a ## scale matrix with non uniform scale in x and y. ## `org` is used as stretch origin. result.setElements(sx,0,0,sy,org.x-sx*org.x,org.y-sy*org.y) - + proc move*(dx,dy:float):Matrix2d {.noInit.} = ## Returns a new translation matrix. result.setElements(1,0,0,1,dx,dy) @@ -187,7 +187,7 @@ proc move*(v:Vector2d):Matrix2d {.noInit.} = proc rotate*(rad:float):Matrix2d {.noInit.} = ## Returns a new rotation matrix, which ## represents a rotation by `rad` radians - let + let s=sin(rad) c=cos(rad) result.setElements(c,s,-s,c,0,0) @@ -200,7 +200,7 @@ proc rotate*(rad:float,org:Point2d):Matrix2d {.noInit.} = s=sin(rad) c=cos(rad) result.setElements(c,s,-s,c,org.x+s*org.y-c*org.x,org.y-c*org.y-s*org.x) - + proc mirror*(v:Vector2d):Matrix2d {.noInit.} = ## Returns a new mirror matrix, mirroring ## around the line that passes through origo and @@ -211,7 +211,7 @@ proc mirror*(v:Vector2d):Matrix2d {.noInit.} = nd=1.0/(sqx+sqy) #used to normalize invector xy2=v.x*v.y*2.0*nd sqd=nd*(sqx-sqy) - + if nd==Inf or nd==NegInf: return IDMATRIX #mirroring around a zero vector is arbitrary=>just use identity @@ -230,7 +230,7 @@ proc mirror*(org:Point2d,v:Vector2d):Matrix2d {.noInit.} = nd=1.0/(sqx+sqy) #used to normalize invector xy2=v.x*v.y*2.0*nd sqd=nd*(sqx-sqy) - + if nd==Inf or nd==NegInf: return IDMATRIX #mirroring around a zero vector is arbitrary=>just use identity @@ -238,47 +238,47 @@ proc mirror*(org:Point2d,v:Vector2d):Matrix2d {.noInit.} = sqd,xy2, xy2,-sqd, org.x-org.y*xy2-org.x*sqd,org.y-org.x*xy2+org.y*sqd) - + proc skew*(xskew,yskew:float):Matrix2d {.noInit.} = - ## Returns a new skew matrix, which has its + ## Returns a new skew matrix, which has its ## x axis rotated `xskew` radians from the local x axis, and ## y axis rotated `yskew` radians from the local y axis result.setElements(cos(yskew),sin(yskew),-sin(xskew),cos(xskew),0,0) - + proc `$`* (t:Matrix2d):string {.noInit.} = ## Returns a string representation of the matrix return rtos(t.ax) & "," & rtos(t.ay) & - "," & rtos(t.bx) & "," & rtos(t.by) & + "," & rtos(t.bx) & "," & rtos(t.by) & "," & rtos(t.tx) & "," & rtos(t.ty) proc isUniform*(t:Matrix2d,tol=1.0e-6):bool= - ## Checks if the transform is uniform, that is + ## Checks if the transform is uniform, that is ## perpendicular axes of equal length, which means (for example) ## it cannot transform a circle into an ellipse. - ## `tol` is used as tolerance for both equal length comparison + ## `tol` is used as tolerance for both equal length comparison ## and perp. comparison. - + #dot product=0 means perpendicular coord. system: - if abs(t.ax*t.bx+t.ay*t.by)<=tol: + if abs(t.ax*t.bx+t.ay*t.by)<=tol: #subtract squared lengths of axes to check if uniform scaling: if abs((t.ax*t.ax+t.ay*t.ay)-(t.bx*t.bx+t.by*t.by))<=tol: return true return false - + proc determinant*(t:Matrix2d):float= ## Computes the determinant of the matrix. - + #NOTE: equivalent with perp.dot product for two 2d vectors - return t.ax*t.by-t.bx*t.ay + return t.ax*t.by-t.bx*t.ay proc isMirroring* (m:Matrix2d):bool= ## Checks if the `m` is a mirroring matrix, ## which means it will reverse direction of a curve transformed with it return m.determinant<0.0 - + proc inverse*(m:Matrix2d):Matrix2d {.noInit.} = ## Returns a new matrix, which is the inverse of the matrix ## If the matrix is not invertible (determinant=0), an EDivByZero @@ -286,7 +286,7 @@ proc inverse*(m:Matrix2d):Matrix2d {.noInit.} = let d=m.determinant if d==0.0: raise newException(DivByZeroError,"Cannot invert a zero determinant matrix") - + result.setElements( m.by/d,-m.ay/d, -m.bx/d,m.ax/d, @@ -296,14 +296,14 @@ proc inverse*(m:Matrix2d):Matrix2d {.noInit.} = proc equals*(m1:Matrix2d,m2:Matrix2d,tol=1.0e-6):bool= ## Checks if all elements of `m1`and `m2` is equal within ## a given tolerance `tol`. - return + return abs(m1.ax-m2.ax)<=tol and abs(m1.ay-m2.ay)<=tol and abs(m1.bx-m2.bx)<=tol and abs(m1.by-m2.by)<=tol and abs(m1.tx-m2.tx)<=tol and abs(m1.ty-m2.ty)<=tol - + proc `=~`*(m1,m2:Matrix2d):bool= ## Checks if `m1`and `m2` is approximately equal, using a ## tolerance of 1e-6. @@ -350,16 +350,16 @@ proc slopeVector2d*(slope:float,len:float):Vector2d {.noInit.} = proc len*(v:Vector2d):float {.inline.}= ## Returns the length of the vector. sqrt(v.x*v.x+v.y*v.y) - + proc `len=`*(v:var Vector2d,newlen:float) {.noInit.} = ## Sets the length of the vector, keeping its angle. let fac=newlen/v.len - + if newlen==0.0: v.x=0.0 v.y=0.0 return - + if fac==Inf or fac==NegInf: #to short for float accuracy #do as good as possible: @@ -368,30 +368,30 @@ proc `len=`*(v:var Vector2d,newlen:float) {.noInit.} = else: v.x*=fac v.y*=fac - + proc sqrLen*(v:Vector2d):float {.inline.}= ## Computes the squared length of the vector, which is ## faster than computing the absolute length. v.x*v.x+v.y*v.y - + proc angle*(v:Vector2d):float= - ## Returns the angle of the vector. + ## Returns the angle of the vector. ## (The counter clockwise plane angle between posetive x axis and `v`) result=arctan2(v.y,v.x) if result<0.0: result+=DEG360 - + proc `$` *(v:Vector2d):string= ## String representation of `v` result=rtos(v.x) result.add(",") result.add(rtos(v.y)) - - + + proc `&` *(v:Vector2d,m:Matrix2d):Vector2d {.noInit.} = ## Concatenate vector `v` with a transformation matrix. ## Transforming a vector ignores the translational part ## of the matrix. - + # | AX AY 0 | # | X Y 1 | * | BX BY 0 | # | 0 0 1 | @@ -403,7 +403,7 @@ proc `&=`*(v:var Vector2d,m:Matrix2d) {.inline.}= ## Applies transformation `m` onto `v` in place. ## Transforming a vector ignores the translational part ## of the matrix. - + # | AX AY 0 | # | X Y 1 | * | BX BY 0 | # | 0 0 1 | @@ -412,31 +412,31 @@ proc `&=`*(v:var Vector2d,m:Matrix2d) {.inline.}= v.x=newx -proc tryNormalize*(v:var Vector2d):bool= +proc tryNormalize*(v:var Vector2d):bool= ## Modifies `v` to have a length of 1.0, keeping its angle. - ## If `v` has zero length (and thus no angle), it is left unmodified and + ## If `v` has zero length (and thus no angle), it is left unmodified and ## false is returned, otherwise true is returned. let mag=v.len if mag==0.0: return false - + v.x/=mag v.y/=mag return true -proc normalize*(v:var Vector2d) {.inline.}= +proc normalize*(v:var Vector2d) {.inline.}= ## Modifies `v` to have a length of 1.0, keeping its angle. ## If `v` has zero length, an EDivByZero will be raised. if not tryNormalize(v): raise newException(DivByZeroError,"Cannot normalize zero length vector") - + proc transformNorm*(v:var Vector2d,t:Matrix2d)= ## Applies a normal direction transformation `t` onto `v` in place. - ## The resulting vector is *not* normalized. Transforming a vector ignores the - ## translational part of the matrix. If the matrix is not invertible + ## The resulting vector is *not* normalized. Transforming a vector ignores the + ## translational part of the matrix. If the matrix is not invertible ## (determinant=0), an EDivByZero will be raised. # transforming a normal is done by transforming @@ -469,16 +469,16 @@ proc transformInv*(v:var Vector2d,t:Matrix2d)= proc transformNormInv*(v:var Vector2d,t:Matrix2d)= ## Applies an inverse normal direction transformation `t` onto `v` in place. - ## This is faster than creating an inverse - ## matrix and transformNorm(...) it. Transforming a vector ignores the + ## This is faster than creating an inverse + ## matrix and transformNorm(...) it. Transforming a vector ignores the ## translational part of the matrix. # normal inverse transform is done by transforming # by the inverse of the transpose of the inverse of the org. matrix # which is equivalent with transforming with the transpose. # | | | AX AY 0 |^-1|^T|^-1 | AX BX 0 | - # | X Y 1 | * | | | BX BY 0 | | | = | X Y 1 | * | AY BY 0 | - # | | | 0 0 1 | | | | 0 0 1 | + # | X Y 1 | * | | | BX BY 0 | | | = | X Y 1 | * | AY BY 0 | + # | | | 0 0 1 | | | | 0 0 1 | # This can be heavily reduced to: let newx=t.ay*v.y+t.ax*v.x v.y=t.by*v.y+t.bx*v.x @@ -489,19 +489,19 @@ proc rotate90*(v:var Vector2d) {.inline.}= ## without using any trigonometrics. swap(v.x,v.y) v.x= -v.x - + proc rotate180*(v:var Vector2d){.inline.}= ## Quickly rotates vector `v` 180 degrees counter clockwise, ## without using any trigonometrics. v.x= -v.x v.y= -v.y - + proc rotate270*(v:var Vector2d) {.inline.}= ## Quickly rotates vector `v` 270 degrees counter clockwise, ## without using any trigonometrics. swap(v.x,v.y) v.y= -v.y - + proc rotate*(v:var Vector2d,rad:float) = ## Rotates vector `v` `rad` radians in place. let @@ -510,18 +510,18 @@ proc rotate*(v:var Vector2d,rad:float) = newx=c*v.x-s*v.y v.y=c*v.y+s*v.x v.x=newx - + proc scale*(v:var Vector2d,fac:float){.inline.}= ## Scales vector `v` `rad` radians in place. v.x*=fac v.y*=fac - + proc stretch*(v:var Vector2d,facx,facy:float){.inline.}= ## Stretches vector `v` `facx` times horizontally, ## and `facy` times vertically. v.x*=facx v.y*=facy - + proc mirror*(v:var Vector2d,mirrvec:Vector2d)= ## Mirrors vector `v` using `mirrvec` as mirror direction. let @@ -530,20 +530,20 @@ proc mirror*(v:var Vector2d,mirrvec:Vector2d)= nd=1.0/(sqx+sqy) #used to normalize invector xy2=mirrvec.x*mirrvec.y*2.0*nd sqd=nd*(sqx-sqy) - + if nd==Inf or nd==NegInf: return #mirroring around a zero vector is arbitrary=>keep as is is fastest - + let newx=xy2*v.y+sqd*v.x v.y=v.x*xy2-sqd*v.y v.x=newx - - + + proc `-` *(v:Vector2d):Vector2d= ## Negates a vector result.x= -v.x result.y= -v.y - + # declare templated binary operators makeBinOpVector(`+`) makeBinOpVector(`-`) @@ -556,27 +556,27 @@ makeBinOpAssignVector(`/=`) proc dot*(v1,v2:Vector2d):float= - ## Computes the dot product of two vectors. + ## Computes the dot product of two vectors. ## Returns 0.0 if the vectors are perpendicular. return v1.x*v2.x+v1.y*v2.y - + proc cross*(v1,v2:Vector2d):float= ## Computes the cross product of two vectors, also called ## the 'perpendicular dot product' in 2d. Returns 0.0 if the vectors ## are parallel. return v1.x*v2.y-v1.y*v2.x - + proc equals*(v1,v2:Vector2d,tol=1.0e-6):bool= ## Checks if two vectors approximately equals with a tolerance. return abs(v2.x-v1.x)<=tol and abs(v2.y-v1.y)<=tol - + proc `=~` *(v1,v2:Vector2d):bool= - ## Checks if two vectors approximately equals with a + ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(v1,v2) - + proc angleTo*(v1,v2:Vector2d):float= - ## Returns the smallest of the two possible angles + ## Returns the smallest of the two possible angles ## between `v1` and `v2` in radians. var nv1=v1 @@ -584,7 +584,7 @@ proc angleTo*(v1,v2:Vector2d):float= if not nv1.tryNormalize or not nv2.tryNormalize: return 0.0 # zero length vector has zero angle to any other vector return safeArccos(dot(nv1,nv2)) - + proc angleCCW*(v1,v2:Vector2d):float= ## Returns the counter clockwise plane angle from `v1` to `v2`, ## in range 0 - 2*PI @@ -592,7 +592,7 @@ proc angleCCW*(v1,v2:Vector2d):float= if v1.cross(v2)>=0.0: return a return DEG360-a - + proc angleCW*(v1,v2:Vector2d):float= ## Returns the clockwise plane angle from `v1` to `v2`, ## in range 0 - 2*PI @@ -612,32 +612,32 @@ proc turnAngle*(v1,v2:Vector2d):float= proc bisect*(v1,v2:Vector2d):Vector2d {.noInit.}= ## Computes the bisector between v1 and v2 as a normalized vector. ## If one of the input vectors has zero length, a normalized version - ## of the other is returned. If both input vectors has zero length, + ## of the other is returned. If both input vectors has zero length, ## an arbitrary normalized vector is returned. var vmag1=v1.len vmag2=v2.len - + # zero length vector equals arbitrary vector, just change to magnitude to one to # avoid zero division - if vmag1==0.0: + if vmag1==0.0: if vmag2==0: #both are zero length return any normalized vector return XAXIS vmag1=1.0 - if vmag2==0.0: vmag2=1.0 - + if vmag2==0.0: vmag2=1.0 + let x1=v1.x/vmag1 y1=v1.y/vmag1 x2=v2.x/vmag2 y2=v2.y/vmag2 - + result.x=(x1 + x2) * 0.5 result.y=(y1 + y2) * 0.5 - + if not result.tryNormalize(): # This can happen if vectors are colinear. In this special case - # there are actually two bisectors, we select just + # there are actually two bisectors, we select just # one of them (x1,y1 rotated 90 degrees ccw). result.x = -y1 result.y = x1 @@ -651,13 +651,13 @@ proc bisect*(v1,v2:Vector2d):Vector2d {.noInit.}= proc point2d*(x,y:float):Point2d = result.x=x result.y=y - + proc sqrDist*(a,b:Point2d):float= ## Computes the squared distance between `a` and `b` let dx=b.x-a.x let dy=b.y-a.y result=dx*dx+dy*dy - + proc dist*(a,b:Point2d):float {.inline.}= ## Computes the absolute distance between `a` and `b` result=sqrt(sqrDist(a,b)) @@ -675,11 +675,11 @@ proc `$` *(p:Point2d):string= result=rtos(p.x) result.add(",") result.add(rtos(p.y)) - + proc `&`*(p:Point2d,t:Matrix2d):Point2d {.noInit,inline.} = ## Concatenates a point `p` with a transform `t`, ## resulting in a new, transformed point. - + # | AX AY 0 | # | X Y 1 | * | BX BY 0 | # | TX TY 1 | @@ -697,21 +697,21 @@ proc transformInv*(p:var Point2d,t:Matrix2d){.inline.}= ## Applies the inverse of transformation `t` onto `p` in place. ## If the matrix is not invertable (determinant=0) , EDivByZero will ## be raised. - + # | AX AY 0 | ^-1 # | X Y 1 | * | BX BY 0 | # | TX TY 1 | let d=t.determinant if d==0.0: raise newException(DivByZeroError,"Cannot invert a zero determinant matrix") - let + let newx= (t.bx*t.ty-t.by*t.tx+p.x*t.by-p.y*t.bx)/d p.y = -(t.ax*t.ty-t.ay*t.tx+p.x*t.ay-p.y*t.ax)/d p.x=newx - - + + proc `+`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} = - ## Adds a vector `v` to a point `p`, resulting + ## Adds a vector `v` to a point `p`, resulting ## in a new point. result.x=p.x+v.x result.y=p.y+v.y @@ -722,7 +722,7 @@ proc `+=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} = p.y+=v.y proc `-`*(p:Point2d,v:Vector2d):Point2d {.noInit,inline.} = - ## Subtracts a vector `v` from a point `p`, resulting + ## Subtracts a vector `v` from a point `p`, resulting ## in a new point. result.x=p.x-v.x result.y=p.y-v.y @@ -736,13 +736,13 @@ proc `-=`*(p:var Point2d,v:Vector2d) {.noInit,inline.} = ## Subtracts a vector `v` from a point `p` in place. p.x-=v.x p.y-=v.y - + proc equals(p1,p2:Point2d,tol=1.0e-6):bool {.inline.}= ## Checks if two points approximately equals with a tolerance. return abs(p2.x-p1.x)<=tol and abs(p2.y-p1.y)<=tol proc `=~`*(p1,p2:Point2d):bool {.inline.}= - ## Checks if two vectors approximately equals with a + ## Checks if two vectors approximately equals with a ## hardcoded tolerance 1e-6 equals(p1,p2) @@ -759,7 +759,7 @@ proc rotate*(p:var Point2d,rad:float)= newx=p.x*c-p.y*s p.y=p.y*c+p.x*s p.x=newx - + proc rotate*(p:var Point2d,rad:float,org:Point2d)= ## Rotates a point in place `rad` radians using `org` as ## center of rotation. @@ -769,25 +769,25 @@ proc rotate*(p:var Point2d,rad:float,org:Point2d)= newx=(p.x - org.x) * c - (p.y - org.y) * s + org.x p.y=(p.y - org.y) * c + (p.x - org.x) * s + org.y p.x=newx - + proc scale*(p:var Point2d,fac:float) {.inline.}= ## Scales a point in place `fac` times with world origo as origin. p.x*=fac p.y*=fac - + proc scale*(p:var Point2d,fac:float,org:Point2d){.inline.}= ## Scales the point in place `fac` times with `org` as origin. p.x=(p.x - org.x) * fac + org.x p.y=(p.y - org.y) * fac + org.y proc stretch*(p:var Point2d,facx,facy:float){.inline.}= - ## Scales a point in place non uniformly `facx` and `facy` times with + ## Scales a point in place non uniformly `facx` and `facy` times with ## world origo as origin. p.x*=facx p.y*=facy proc stretch*(p:var Point2d,facx,facy:float,org:Point2d){.inline.}= - ## Scales the point in place non uniformly `facx` and `facy` times with + ## Scales the point in place non uniformly `facx` and `facy` times with ## `org` as origin. p.x=(p.x - org.x) * facx + org.x p.y=(p.y - org.y) * facy + org.y @@ -814,21 +814,21 @@ proc area*(a,b,c:Point2d):float= return abs(sgnArea(a,b,c)) proc closestPoint*(p:Point2d,pts:varargs[Point2d]):Point2d= - ## Returns a point selected from `pts`, that has the closest + ## Returns a point selected from `pts`, that has the closest ## euclidean distance to `p` assert(pts.len>0) # must have at least one point - - var + + var bestidx=0 bestdist=p.sqrDist(pts[0]) curdist:float - + for idx in 1..high(pts): curdist=p.sqrDist(pts[idx]) if curdist<bestdist: bestidx=idx bestdist=curdist - + result=pts[bestidx] @@ -843,7 +843,7 @@ proc normAngle*(ang:float):float= return ang return ang mod DEG360 - + proc degToRad*(deg:float):float {.inline.}= ## converts `deg` degrees to radians deg / RAD2DEGCONST @@ -852,4 +852,4 @@ proc radToDeg*(rad:float):float {.inline.}= ## converts `rad` radians to degrees rad * RAD2DEGCONST - + diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index 1758c5b1a..1d4471b21 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -6,32 +6,32 @@ import unsigned, math, hashes ## Memory Utility Functions proc newHeap*[T](): ptr T = - result = cast[ptr T](alloc0(sizeof(T))) + result = cast[ptr T](alloc0(sizeof(T))) proc copyNew*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = alloc(size) - copyMem(mem, x.addr, size) + var + size = sizeof(T) + mem = alloc(size) + copyMem(mem, x.addr, size) return cast[ptr T](mem) -proc copyTo*[T](val: var T, dest: int) = - copyMem(pointer(dest), val.addr, sizeof(T)) +proc copyTo*[T](val: var T, dest: int) = + copyMem(pointer(dest), val.addr, sizeof(T)) -proc allocType*[T](): pointer = alloc(sizeof(T)) +proc allocType*[T](): pointer = alloc(sizeof(T)) proc newShared*[T](): ptr T = - result = cast[ptr T](allocShared0(sizeof(T))) + result = cast[ptr T](allocShared0(sizeof(T))) proc copyShared*[T](x: var T): ptr T = - var - size = sizeof(T) - mem = allocShared(size) - copyMem(mem, x.addr, size) + var + size = sizeof(T) + mem = allocShared(size) + copyMem(mem, x.addr, size) return cast[ptr T](mem) #------------------------------------------------------------------------------ -## Pointer arithmetic +## Pointer arithmetic proc `+`*(p: pointer, i: int): pointer {.inline.} = cast[pointer](cast[int](p) + i) @@ -41,11 +41,11 @@ const reProbeLimit = 12 minCopyWork = 4096 intSize = sizeof(int) - + when sizeof(int) == 4: # 32bit - type + type Raw = range[0..1073741823] ## The range of uint values that can be stored directly in a value slot ## when on a 32 bit platform @@ -56,40 +56,40 @@ elif sizeof(int) == 8: # 64bit ## The range of uint values that can be stored directly in a value slot ## when on a 64 bit platform {.deprecated: [TRaw: Raw].} -else: +else: {.error: "unsupported platform".} - -type + +type Entry = tuple key: int value: int EntryArr = ptr array[0..10_000_000, Entry] - + PConcTable[K,V] = ptr object {.pure.} len: int used: int active: int copyIdx: int copyDone: int - next: PConcTable[K,V] + next: PConcTable[K,V] data: EntryArr {.deprecated: [TEntry: Entry, TEntryArr: EntryArr.} proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, - expVal: int, match: bool): int + expVal: int, match: bool): int #------------------------------------------------------------------------------ # Create a new table proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] = - let - dataLen = max(nextPowerOfTwo(size), minTableSize) - dataSize = dataLen*sizeof(Entry) - dataMem = allocShared0(dataSize) + let + dataLen = max(nextPowerOfTwo(size), minTableSize) + dataSize = dataLen*sizeof(Entry) + dataMem = allocShared0(dataSize) tableSize = 7 * intSize tableMem = allocShared0(tableSize) - table = cast[PConcTable[K,V]](tableMem) + table = cast[PConcTable[K,V]](tableMem) table.len = dataLen table.used = 0 table.active = 0 @@ -99,14 +99,14 @@ proc newLFTable*[K,V](size: int = minTableSize): PConcTable[K,V] = table.data = cast[EntryArr](dataMem) result = table -#------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ # Delete a table proc deleteConcTable[K,V](tbl: PConcTable[K,V]) = - deallocShared(tbl.data) + deallocShared(tbl.data) deallocShared(tbl) -#------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ proc `[]`[K,V](table: var PConcTable[K,V], i: int): var Entry {.inline.} = table.data[i] @@ -119,15 +119,15 @@ proc pack[T](x: T): int {.inline.} = result = (cast[int](x) shl 2) #echo("packKey ",cast[int](x) , " -> ", result) -# Pop the flags off returning a 4 byte aligned ptr to our Key or Val +# Pop the flags off returning a 4 byte aligned ptr to our Key or Val proc pop(x: int): int {.inline.} = result = x and 0xFFFFFFFC'i32 -# Pop the raw value off of our Key or Val +# Pop the raw value off of our Key or Val proc popRaw(x: int): int {.inline.} = - result = x shr 2 + result = x shr 2 -# Pop the flags off returning a 4 byte aligned ptr to our Key or Val +# Pop the flags off returning a 4 byte aligned ptr to our Key or Val proc popPtr[V](x: int): ptr V {.inline.} = result = cast[ptr V](pop(x)) #echo("popPtr " & $x & " -> " & $cast[int](result)) @@ -136,34 +136,34 @@ proc popPtr[V](x: int): ptr V {.inline.} = # K or V is no longer valid use new table const Ghost = 0xFFFFFFFC proc isGhost(x: int): bool {.inline.} = - result = x == 0xFFFFFFFC + result = x == 0xFFFFFFFC -# Tombstone -# applied to V = K is dead -proc isTomb(x: int): bool {.inline.} = +# Tombstone +# applied to V = K is dead +proc isTomb(x: int): bool {.inline.} = result = (x and 0x00000002) != 0 proc setTomb(x: int): int {.inline.} = result = x or 0x00000002 # Prime -# K or V is in new table copied from old -proc isPrime(x: int): bool {.inline.} = +# K or V is in new table copied from old +proc isPrime(x: int): bool {.inline.} = result = (x and 0x00000001) != 0 proc setPrime(x: int): int {.inline.} = result = x or 0x00000001 -#------------------------------------------------------------------------------ +#------------------------------------------------------------------------------ ##This is for i32 only need to override for i64 -proc hashInt(x: int):int {.inline.} = - var h = uint32(x) #shr 2'u32 +proc hashInt(x: int):int {.inline.} = + var h = uint32(x) #shr 2'u32 h = h xor (h shr 16'u32) h *= 0x85ebca6b'u32 h = h xor (h shr 13'u32) h *= 0xc2b2ae35'u32 - h = h xor (h shr 16'u32) + h = h xor (h shr 16'u32) result = int(h) #------------------------------------------------------------------------------ @@ -175,31 +175,31 @@ proc resize[K,V](self: PConcTable[K,V]): PConcTable[K,V] = #echo("A new table already exists, copy in progress") return next var - oldLen = atomic_load_n(self.len.addr, ATOMIC_RELAXED) + oldLen = atomic_load_n(self.len.addr, ATOMIC_RELAXED) newTable = newLFTable[K,V](oldLen*2) success = atomic_compare_exchange_n(self.next.addr, next.addr, newTable, false, ATOMIC_RELAXED, ATOMIC_RELAXED) if not success: echo("someone beat us to it! delete table we just created and return his " & $cast[int](next)) - deleteConcTable(newTable) - return next + deleteConcTable(newTable) + return next else: echo("Created New Table! " & $cast[int](newTable) & " Size = " & $newTable.len) return newTable - + #------------------------------------------------------------------------------ -#proc keyEQ[K](key1: ptr K, key2: ptr K): bool {.inline.} = -proc keyEQ[K](key1: int, key2: int): bool {.inline.} = +#proc keyEQ[K](key1: ptr K, key2: ptr K): bool {.inline.} = +proc keyEQ[K](key1: int, key2: int): bool {.inline.} = result = false when K is Raw: - if key1 == key2: + if key1 == key2: result = true else: - var + var p1 = popPtr[K](key1) p2 = popPtr[K](key2) - if p1 != nil and p2 != nil: + if p1 != nil and p2 != nil: if cast[int](p1) == cast[int](p2): return true if p1[] == p2[]: @@ -214,53 +214,53 @@ proc keyEQ[K](key1: int, key2: int): bool {.inline.} = proc copySlot[K,V](idx: int, oldTbl: var PConcTable[K,V], newTbl: var PConcTable[K,V]): bool = #echo("Copy idx " & $idx) - var + var oldVal = 0 - oldkey = 0 + oldkey = 0 ok = false result = false #Block the key so no other threads waste time here while not ok: - ok = atomic_compare_exchange_n(oldTbl[idx].key.addr, oldKey.addr, + ok = atomic_compare_exchange_n(oldTbl[idx].key.addr, oldKey.addr, setTomb(oldKey), false, ATOMIC_RELAXED, ATOMIC_RELAXED) - #echo("oldKey was = " & $oldKey & " set it to tomb " & $setTomb(oldKey)) - #Prevent new values from appearing in the old table by priming + #echo("oldKey was = " & $oldKey & " set it to tomb " & $setTomb(oldKey)) + #Prevent new values from appearing in the old table by priming oldVal = atomic_load_n(oldTbl[idx].value.addr, ATOMIC_RELAXED) while not isPrime(oldVal): - var box = if oldVal == 0 or isTomb(oldVal) : oldVal.setTomb.setPrime - else: oldVal.setPrime - if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, + var box = if oldVal == 0 or isTomb(oldVal) : oldVal.setTomb.setPrime + else: oldVal.setPrime + if atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, box, false, ATOMIC_RELAXED, ATOMIC_RELAXED): - if isPrime(box) and isTomb(box): + if isPrime(box) and isTomb(box): return true oldVal = box break #echo("oldVal was = ", oldVal, " set it to prime ", box) - if isPrime(oldVal) and isTomb(oldVal): + if isPrime(oldVal) and isTomb(oldVal): #when not (K is Raw): - # deallocShared(popPtr[K](oldKey)) + # deallocShared(popPtr[K](oldKey)) return false - if isTomb(oldVal): + if isTomb(oldVal): echo("oldVal is Tomb!!!, should not happen") - if pop(oldVal) != 0: + if pop(oldVal) != 0: result = setVal(newTbl, pop(oldKey), pop(oldVal), 0, true) == 0 - if result: - #echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal) - else: - #echo("copy slot failed") + if result: + #echo("Copied a Slot! idx= " & $idx & " key= " & $oldKey & " val= " & $oldVal) + else: + #echo("copy slot failed") # Our copy is done so we disable the old slot while not ok: - ok = atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, + ok = atomic_compare_exchange_n(oldTbl[idx].value.addr, oldVal.addr, oldVal.setTomb.setPrime , false, ATOMIC_RELAXED, ATOMIC_RELAXED) - #echo("disabled old slot") - #echo"---------------------" + #echo("disabled old slot") + #echo"---------------------" #------------------------------------------------------------------------------ proc promote[K,V](table: var PConcTable[K,V]) = var newData = atomic_load_n(table.next.data.addr, ATOMIC_RELAXED) - newLen = atomic_load_n(table.next.len.addr, ATOMIC_RELAXED) + newLen = atomic_load_n(table.next.len.addr, ATOMIC_RELAXED) newUsed = atomic_load_n(table.next.used.addr, ATOMIC_RELAXED) deallocShared(table.data) @@ -270,52 +270,52 @@ proc promote[K,V](table: var PConcTable[K,V]) = atomic_store_n(table.copyIdx.addr, 0, ATOMIC_RELAXED) atomic_store_n(table.copyDone.addr, 0, ATOMIC_RELAXED) deallocShared(table.next) - atomic_store_n(table.next.addr, nil, ATOMIC_RELAXED) + atomic_store_n(table.next.addr, nil, ATOMIC_RELAXED) echo("new table swapped!") #------------------------------------------------------------------------------ - -proc checkAndPromote[K,V](table: var PConcTable[K,V], workDone: int): bool = - var + +proc checkAndPromote[K,V](table: var PConcTable[K,V], workDone: int): bool = + var oldLen = atomic_load_n(table.len.addr, ATOMIC_RELAXED) copyDone = atomic_load_n(table.copyDone.addr, ATOMIC_RELAXED) ok: bool - result = false + result = false if workDone > 0: #echo("len to copy =" & $oldLen) - #echo("copyDone + workDone = " & $copyDone & " + " & $workDone) + #echo("copyDone + workDone = " & $copyDone & " + " & $workDone) while not ok: - ok = atomic_compare_exchange_n(table.copyDone.addr, copyDone.addr, + ok = atomic_compare_exchange_n(table.copyDone.addr, copyDone.addr, copyDone + workDone, false, ATOMIC_RELAXED, ATOMIC_RELAXED) - #if ok: echo("set copyDone") - # If the copy is done we can promote this table + #if ok: echo("set copyDone") + # If the copy is done we can promote this table if copyDone + workDone >= oldLen: # Swap new data - #echo("work is done!") + #echo("work is done!") table.promote result = true - + #------------------------------------------------------------------------------ proc copySlotAndCheck[K,V](table: var PConcTable[K,V], idx: int): PConcTable[K,V] = var newTable = cast[PConcTable[K,V]](atomic_load_n(table.next.addr, ATOMIC_RELAXED)) - result = newTable - if newTable != nil and copySlot(idx, table, newTable): - #echo("copied a single slot, idx = " & $idx) + result = newTable + if newTable != nil and copySlot(idx, table, newTable): + #echo("copied a single slot, idx = " & $idx) if checkAndPromote(table, 1): return table - + #------------------------------------------------------------------------------ - + proc helpCopy[K,V](table: var PConcTable[K,V]): PConcTable[K,V] = var - newTable = cast[PConcTable[K,V]](atomic_load_n(table.next.addr, ATOMIC_RELAXED)) - result = newTable - if newTable != nil: - var - oldLen = atomic_load_n(table.len.addr, ATOMIC_RELAXED) + newTable = cast[PConcTable[K,V]](atomic_load_n(table.next.addr, ATOMIC_RELAXED)) + result = newTable + if newTable != nil: + var + oldLen = atomic_load_n(table.len.addr, ATOMIC_RELAXED) copyDone = atomic_load_n(table.copyDone.addr, ATOMIC_RELAXED) copyIdx = 0 work = min(oldLen, minCopyWork) @@ -324,54 +324,54 @@ proc helpCopy[K,V](table: var PConcTable[K,V]): PConcTable[K,V] = if copyDone < oldLen: var ok: bool while not ok: - ok = atomic_compare_exchange_n(table.copyIdx.addr, copyIdx.addr, + ok = atomic_compare_exchange_n(table.copyIdx.addr, copyIdx.addr, copyIdx + work, false, ATOMIC_RELAXED, ATOMIC_RELAXED) - #echo("copy idx = ", copyIdx) + #echo("copy idx = ", copyIdx) for i in 0..work-1: - var idx = (copyIdx + i) and (oldLen - 1) + var idx = (copyIdx + i) and (oldLen - 1) if copySlot(idx, table, newTable): workDone += 1 if workDone > 0: #echo("did work ", workDone, " on thread ", cast[int](myThreadID[pointer]())) if checkAndPromote(table, workDone): return table - # In case a thread finished all the work then got stalled before promotion + # In case a thread finished all the work then got stalled before promotion if checkAndPromote(table, 0): return table - - + + #------------------------------------------------------------------------------ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, expVal: int, match: bool): int = - #echo("-try set- in table ", " key = ", (popPtr[K](key)[]), " val = ", val) - when K is Raw: - var idx = hashInt(key) + #echo("-try set- in table ", " key = ", (popPtr[K](key)[]), " val = ", val) + when K is Raw: + var idx = hashInt(key) else: - var idx = popPtr[K](key)[].hash - var - nextTable: PConcTable[K,V] + var idx = popPtr[K](key)[].hash + var + nextTable: PConcTable[K,V] probes = 1 - # spin until we find a key slot or build and jump to next table - while true: - idx = idx and (table.len - 1) + # spin until we find a key slot or build and jump to next table + while true: + idx = idx and (table.len - 1) #echo("try set idx = " & $idx & "for" & $key) var - probedKey = 0 - openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr, - key, false, ATOMIC_RELAXED, ATOMIC_RELAXED) + probedKey = 0 + openKey = atomic_compare_exchange_n(table[idx].key.addr, probedKey.addr, + key, false, ATOMIC_RELAXED, ATOMIC_RELAXED) if openKey: if val.isTomb: #echo("val was tomb, bail, no reason to set an open slot to tomb") return val - #increment used slots - #echo("found an open slot, total used = " & + #increment used slots + #echo("found an open slot, total used = " & #$atomic_add_fetch(table.used.addr, 1, ATOMIC_RELAXED)) discard atomic_add_fetch(table.used.addr, 1, ATOMIC_RELAXED) - break # We found an open slot - #echo("set idx ", idx, " key = ", key, " probed = ", probedKey) + break # We found an open slot + #echo("set idx ", idx, " key = ", key, " probed = ", probedKey) if keyEQ[K](probedKey, key): - #echo("we found the matching slot") - break # We found a matching slot + #echo("we found the matching slot") + break # We found a matching slot if (not(expVal != 0 and match)) and (probes >= reProbeLimit or key.isTomb): if key.isTomb: echo("Key is Tombstone") #if probes >= reProbeLimit: echo("Too much probing " & $probes) @@ -379,22 +379,22 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, #create next bigger table nextTable = resize(table) #help do some copying - #echo("help copy old table to new") - nextTable = helpCopy(table) + #echo("help copy old table to new") + nextTable = helpCopy(table) #now setVal in the new table instead - #echo("jumping to next table to set val") - return setVal(nextTable, key, val, expVal, match) + #echo("jumping to next table to set val") + return setVal(nextTable, key, val, expVal, match) else: idx += 1 probes += 1 # Done spinning for a new slot - var oldVal = atomic_load_n(table[idx].value.addr, ATOMIC_RELAXED) + var oldVal = atomic_load_n(table[idx].value.addr, ATOMIC_RELAXED) if val == oldVal: - #echo("this val is alredy in the slot") + #echo("this val is alredy in the slot") return oldVal - nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST) - if nextTable == nil and - ((oldVal == 0 and + nextTable = atomic_load_n(table.next.addr, ATOMIC_SEQ_CST) + if nextTable == nil and + ((oldVal == 0 and (probes >= reProbeLimit or table.used / table.len > 0.8)) or (isPrime(oldVal))): if table.used / table.len > 0.8: echo("resize because usage ratio = " & @@ -402,7 +402,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if isPrime(oldVal): echo("old val isPrime, should be a rare mem ordering event") nextTable = resize(table) if nextTable != nil: - #echo("tomb old slot then set in new table") + #echo("tomb old slot then set in new table") nextTable = copySlotAndCheck(table,idx) return setVal(nextTable, key, val, expVal, match) # Finally ready to add new val to table @@ -410,7 +410,7 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, if match and oldVal != expVal: #echo("set failed, no match oldVal= " & $oldVal & " expVal= " & $expVal) return oldVal - if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr, + if atomic_compare_exchange_n(table[idx].value.addr, oldVal.addr, val, false, ATOMIC_RELEASE, ATOMIC_RELAXED): #echo("val set at table " & $cast[int](table)) if expVal != 0: @@ -427,48 +427,48 @@ proc setVal[K,V](table: var PConcTable[K,V], key: int, val: int, #------------------------------------------------------------------------------ -proc getVal[K,V](table: var PConcTable[K,V], key: int): int = +proc getVal[K,V](table: var PConcTable[K,V], key: int): int = #echo("-try get- key = " & $key) - when K is Raw: + when K is Raw: var idx = hashInt(key) else: - var idx = popPtr[K](key)[].hash - #echo("get idx ", idx) - var + var idx = popPtr[K](key)[].hash + #echo("get idx ", idx) + var probes = 0 - val: int + val: int while true: - idx = idx and (table.len - 1) - var + idx = idx and (table.len - 1) + var newTable: PConcTable[K,V] # = atomic_load_n(table.next.addr, ATOMIC_ACQUIRE) - probedKey = atomic_load_n(table[idx].key.addr, ATOMIC_SEQ_CST) + probedKey = atomic_load_n(table[idx].key.addr, ATOMIC_SEQ_CST) if keyEQ[K](probedKey, key): #echo("found key after ", probes+1) val = atomic_load_n(table[idx].value.addr, ATOMIC_ACQUIRE) if not isPrime(val): if isTomb(val): - #echo("val was tomb but not prime") + #echo("val was tomb but not prime") return 0 else: - #echo("-GotIt- idx = ", idx, " key = ", key, " val ", val ) + #echo("-GotIt- idx = ", idx, " key = ", key, " val ", val ) return val else: newTable = copySlotAndCheck(table, idx) - return getVal(newTable, key) + return getVal(newTable, key) else: - #echo("probe ", probes, " idx = ", idx, " key = ", key, " found ", probedKey ) + #echo("probe ", probes, " idx = ", idx, " key = ", key, " found ", probedKey ) if probes >= reProbeLimit*4 or key.isTomb: if newTable == nil: #echo("too many probes and no new table ", key, " ", idx ) return 0 - else: + else: newTable = helpCopy(table) return getVal(newTable, key) idx += 1 probes += 1 #------------------------------------------------------------------------------ - + #proc set*(table: var PConcTable[Raw,Raw], key: Raw, val: Raw) = # discard setVal(table, pack(key), pack(key), 0, false) @@ -476,33 +476,34 @@ proc getVal[K,V](table: var PConcTable[K,V], key: int): int = # discard setVal(table, pack(key), cast[int](val), 0, false) proc set*[K,V](table: var PConcTable[K,V], key: var K, val: var V) = - when not (K is Raw): + when not (K is Raw): var newKey = cast[int](copyShared(key)) - else: + else: var newKey = pack(key) - when not (V is Raw): + when not (V is Raw): var newVal = cast[int](copyShared(val)) - else: + else: var newVal = pack(val) var oldPtr = pop(setVal(table, newKey, newVal, 0, false)) #echo("oldPtr = ", cast[int](oldPtr), " newPtr = ", cast[int](newPtr)) - when not (V is Raw): - if newVal != oldPtr and oldPtr != 0: + when not (V is Raw): + if newVal != oldPtr and oldPtr != 0: deallocShared(cast[ptr V](oldPtr)) - - + + proc get*[K,V](table: var PConcTable[K,V], key: var K): V = when not (V is Raw): when not (K is Raw): return popPtr[V](getVal(table, cast[int](key.addr)))[] - else: + else: return popPtr[V](getVal(table, pack(key)))[] else: when not (K is Raw): return popRaw(getVal(table, cast[int](key.addr))) - else: - return popRaw(getVal(table, pack(key))) + else: + return popRaw(getVal(table, pack(key))) + @@ -512,7 +513,6 @@ proc get*[K,V](table: var PConcTable[K,V], key: var K): V = - #proc `[]`[K,V](table: var PConcTable[K,V], key: K): PEntry[K,V] {.inline.} = # getVal(table, key) @@ -528,16 +528,16 @@ proc get*[K,V](table: var PConcTable[K,V], key: var K): V = #Tests ---------------------------- when not defined(testing) and isMainModule: import locks, times, mersenne - - const + + const numTests = 100000 numThreads = 10 - + type TestObj = tuple - thr: int + thr: int f0: int f1: int @@ -545,63 +545,63 @@ when not defined(testing) and isMainModule: PDataArr = array[0..numTests-1, Data] Dict = PConcTable[string,TestObj] {.deprecated: [TTestObj: TestObj, TData: Data].} - - var + + var thr: array[0..numThreads-1, Thread[Dict]] - - table = newLFTable[string,TestObj](8) + + table = newLFTable[string,TestObj](8) rand = newMersenneTwister(2525) - proc createSampleData(len: int): PDataArr = - #result = cast[PDataArr](allocShared0(sizeof(Data)*numTests)) + proc createSampleData(len: int): PDataArr = + #result = cast[PDataArr](allocShared0(sizeof(Data)*numTests)) for i in 0..len-1: result[i].k = "mark" & $(i+1) - #echo("mark" & $(i+1), " ", hash("mark" & $(i+1))) + #echo("mark" & $(i+1), " ", hash("mark" & $(i+1))) result[i].v.thr = 0 - result[i].v.f0 = i+1 - result[i].v.f1 = 0 + result[i].v.f0 = i+1 + result[i].v.f1 = 0 #echo("key = " & $(i+1) & " Val ptr = " & $cast[int](result[i].v.addr)) - proc threadProc(tp: Dict) {.thread.} = - var t = cpuTime(); + proc threadProc(tp: Dict) {.thread.} = + var t = cpuTime(); for i in 1..numTests: var key = "mark" & $(i) - var got = table.get(key) + var got = table.get(key) got.thr = cast[int](myThreadID[pointer]()) - got.f1 = got.f1 + 1 + got.f1 = got.f1 + 1 table.set(key, got) t = cpuTime() - t - echo t - + echo t + var testData = createSampleData(numTests) for i in 0..numTests-1: table.set(testData[i].k, testData[i].v) - + var i = 0 while i < numThreads: createThread(thr[i], threadProc, table) i += 1 - joinThreads(thr) + joinThreads(thr) + - var fails = 0 - for i in 0..numTests-1: - var got = table.get(testData[i].k) + for i in 0..numTests-1: + var got = table.get(testData[i].k) if got.f0 != i+1 or got.f1 != numThreads: fails += 1 echo(got) echo("Failed read or write = ", fails) - + #for i in 1..numTests: # echo(i, " = ", hashInt(i) and 8191) diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 7e3f23851..424bcdcca 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -17,11 +17,11 @@ type otherbits: char case isLeaf: bool of false: child: array[0..1, ref NodeObj[T]] - of true: + of true: key: string when T isnot void: val: T - + Node[T] = ref NodeObj[T] CritBitTree*[T] = object ## The crit bit tree can either be used ## as a mapping from strings to @@ -66,7 +66,7 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = let ch = if it.byte < key.len: key[it.byte] else: '\0' let dir = (1 + (ch.ord or it.otherBits.ord)) shr 8 it = it.child[dir] - + var newOtherBits = 0 var newByte = 0 block blockX: @@ -84,7 +84,7 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = newOtherBits = newOtherBits xor 255 let ch = it.key[newByte] let dir = (1 + (ord(ch) or newOtherBits)) shr 8 - + var inner: Node[T] new inner new result @@ -93,7 +93,7 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = inner.otherBits = chr(newOtherBits) inner.byte = newByte inner.child[1 - dir] = result - + var wherep = addr(c.root) while true: var p = wherep[] @@ -176,7 +176,7 @@ iterator leaves[T](n: Node[T]): Node[T] = # XXX actually we could compute the necessary stack size in advance: # it's roughly log2(c.count). var stack = @[n] - while stack.len > 0: + while stack.len > 0: var it = stack.pop while not it.isLeaf: stack.add(it.child[1]) @@ -205,7 +205,7 @@ iterator items*[T](c: CritBitTree[T]): string = iterator pairs*[T](c: CritBitTree[T]): tuple[key: string, val: T] = ## yields all (key, value)-pairs of `c`. for x in leaves(c.root): yield (x.key, x.val) - + iterator mpairs*[T](c: var CritBitTree[T]): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c`. The yielded values can be modified. for x in leaves(c.root): yield (x.key, x.val) @@ -251,7 +251,7 @@ iterator pairsWithPrefix*[T](c: CritBitTree[T], ## yields all (key, value)-pairs of `c` starting with `prefix`. let top = allprefixedAux(c, prefix) for x in leaves(top): yield (x.key, x.val) - + iterator mpairsWithPrefix*[T](c: var CritBitTree[T], prefix: string): tuple[key: string, val: var T] = ## yields all (key, value)-pairs of `c` starting with `prefix`. diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index 535d5e21d..f847ddd58 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -27,18 +27,18 @@ type SinglyLinkedList*[T] = object ## a singly linked list head*, tail*: SinglyLinkedNode[T] - + DoublyLinkedList*[T] = object ## a doubly linked list head*, tail*: DoublyLinkedNode[T] SinglyLinkedRing*[T] = object ## a singly linked ring head*, tail*: SinglyLinkedNode[T] - + DoublyLinkedRing*[T] = object ## a doubly linked ring head*: DoublyLinkedNode[T] {.deprecated: [TDoublyLinkedNode: DoublyLinkedNodeObj, - PDoublyLinkedNode: DoublyLinkedNode, + PDoublyLinkedNode: DoublyLinkedNode, TSinglyLinkedNode: SinglyLinkedNodeObj, PSinglyLinkedNode: SinglyLinkedNode, TDoublyLinkedList: DoublyLinkedList, @@ -106,19 +106,19 @@ template findImpl() {.dirty.} = for x in nodes(L): if x.value == value: return x -iterator items*[T](L: DoublyLinkedList[T]): T = +iterator items*[T](L: DoublyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: SinglyLinkedList[T]): T = +iterator items*[T](L: SinglyLinkedList[T]): T = ## yields every value of `L`. itemsListImpl() -iterator items*[T](L: SinglyLinkedRing[T]): T = +iterator items*[T](L: SinglyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() -iterator items*[T](L: DoublyLinkedRing[T]): T = +iterator items*[T](L: DoublyLinkedRing[T]): T = ## yields every value of `L`. itemsRingImpl() @@ -138,22 +138,22 @@ iterator mitems*[T](L: var DoublyLinkedRing[T]): var T = ## yields every value of `L` so that you can modify it. itemsRingImpl() -iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedList[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: DoublyLinkedList[T]): DoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedList[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesListImpl() -iterator nodes*[T](L: SinglyLinkedRing[T]): SinglyLinkedNode[T] = +iterator nodes*[T](L: SinglyLinkedRing[T]): SinglyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() -iterator nodes*[T](L: DoublyLinkedRing[T]): DoublyLinkedNode[T] = +iterator nodes*[T](L: DoublyLinkedRing[T]): DoublyLinkedNode[T] = ## iterates over every node of `x`. Removing the current node from the ## list during traversal is supported. nodesRingImpl() @@ -165,87 +165,87 @@ template dollarImpl() {.dirty.} = result.add($x.value) result.add("]") -proc `$`*[T](L: SinglyLinkedList[T]): string = +proc `$`*[T](L: SinglyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: DoublyLinkedList[T]): string = +proc `$`*[T](L: DoublyLinkedList[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: SinglyLinkedRing[T]): string = +proc `$`*[T](L: SinglyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc `$`*[T](L: DoublyLinkedRing[T]): string = +proc `$`*[T](L: DoublyLinkedRing[T]): string = ## turns a list into its string representation. dollarImpl() -proc find*[T](L: SinglyLinkedList[T], value: T): SinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedList[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: DoublyLinkedList[T], value: T): DoublyLinkedNode[T] = +proc find*[T](L: DoublyLinkedList[T], value: T): DoublyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: SinglyLinkedRing[T], value: T): SinglyLinkedNode[T] = +proc find*[T](L: SinglyLinkedRing[T], value: T): SinglyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc find*[T](L: DoublyLinkedRing[T], value: T): DoublyLinkedNode[T] = +proc find*[T](L: DoublyLinkedRing[T], value: T): DoublyLinkedNode[T] = ## searches in the list for a value. Returns nil if the value does not ## exist. findImpl() -proc contains*[T](L: SinglyLinkedList[T], value: T): bool {.inline.} = +proc contains*[T](L: SinglyLinkedList[T], value: T): bool {.inline.} = ## searches in the list for a value. Returns false if the value does not ## exist, true otherwise. result = find(L, value) != nil -proc contains*[T](L: DoublyLinkedList[T], value: T): bool {.inline.} = +proc contains*[T](L: DoublyLinkedList[T], value: T): bool {.inline.} = ## searches in the list for a value. Returns false if the value does not ## exist, true otherwise. result = find(L, value) != nil -proc contains*[T](L: SinglyLinkedRing[T], value: T): bool {.inline.} = +proc contains*[T](L: SinglyLinkedRing[T], value: T): bool {.inline.} = ## searches in the list for a value. Returns false if the value does not ## exist, true otherwise. result = find(L, value) != nil -proc contains*[T](L: DoublyLinkedRing[T], value: T): bool {.inline.} = +proc contains*[T](L: DoublyLinkedRing[T], value: T): bool {.inline.} = ## searches in the list for a value. Returns false if the value does not ## exist, true otherwise. result = find(L, value) != nil -proc prepend*[T](L: var SinglyLinkedList[T], - n: SinglyLinkedNode[T]) {.inline.} = +proc prepend*[T](L: var SinglyLinkedList[T], + n: SinglyLinkedNode[T]) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). n.next = L.head L.head = n -proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = +proc prepend*[T](L: var SinglyLinkedList[T], value: T) {.inline.} = ## prepends a node to `L`. Efficiency: O(1). prepend(L, newSinglyLinkedNode(value)) - -proc append*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = + +proc append*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## appends a node `n` to `L`. Efficiency: O(1). n.next = nil n.prev = L.tail - if L.tail != nil: + if L.tail != nil: assert(L.tail.next == nil) L.tail.next = n L.tail = n if L.head == nil: L.head = n -proc append*[T](L: var DoublyLinkedList[T], value: T) = +proc append*[T](L: var DoublyLinkedList[T], value: T) = ## appends a value to `L`. Efficiency: O(1). append(L, newDoublyLinkedNode(value)) -proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = +proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## prepends a node `n` to `L`. Efficiency: O(1). n.prev = nil n.next = L.head @@ -255,11 +255,11 @@ proc prepend*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = L.head = n if L.tail == nil: L.tail = n -proc prepend*[T](L: var DoublyLinkedList[T], value: T) = +proc prepend*[T](L: var DoublyLinkedList[T], value: T) = ## prepends a value to `L`. Efficiency: O(1). prepend(L, newDoublyLinkedNode(value)) - -proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = + +proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = ## removes `n` from `L`. Efficiency: O(1). if n == L.tail: L.tail = n.prev if n == L.head: L.head = n.next @@ -267,7 +267,7 @@ proc remove*[T](L: var DoublyLinkedList[T], n: DoublyLinkedNode[T]) = if n.prev != nil: n.prev.next = n.next -proc append*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = +proc append*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = ## appends a node `n` to `L`. Efficiency: O(1). if L.head != nil: n.next = L.head @@ -279,11 +279,11 @@ proc append*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = L.head = n L.tail = n -proc append*[T](L: var SinglyLinkedRing[T], value: T) = +proc append*[T](L: var SinglyLinkedRing[T], value: T) = ## appends a value to `L`. Efficiency: O(1). append(L, newSinglyLinkedNode(value)) -proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = +proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = ## prepends a node `n` to `L`. Efficiency: O(1). if L.head != nil: n.next = L.head @@ -294,11 +294,11 @@ proc prepend*[T](L: var SinglyLinkedRing[T], n: SinglyLinkedNode[T]) = L.tail = n L.head = n -proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = +proc prepend*[T](L: var SinglyLinkedRing[T], value: T) = ## prepends a value to `L`. Efficiency: O(1). prepend(L, newSinglyLinkedNode(value)) -proc append*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = +proc append*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## appends a node `n` to `L`. Efficiency: O(1). if L.head != nil: n.next = L.head @@ -310,13 +310,13 @@ proc append*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = n.next = n L.head = n -proc append*[T](L: var DoublyLinkedRing[T], value: T) = +proc append*[T](L: var DoublyLinkedRing[T], value: T) = ## appends a value to `L`. Efficiency: O(1). append(L, newDoublyLinkedNode(value)) -proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = +proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## prepends a node `n` to `L`. Efficiency: O(1). - if L.head != nil: + if L.head != nil: n.next = L.head n.prev = L.head.prev L.head.prev.next = n @@ -326,17 +326,17 @@ proc prepend*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = n.next = n L.head = n -proc prepend*[T](L: var DoublyLinkedRing[T], value: T) = +proc prepend*[T](L: var DoublyLinkedRing[T], value: T) = ## prepends a value to `L`. Efficiency: O(1). prepend(L, newDoublyLinkedNode(value)) - -proc remove*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = + +proc remove*[T](L: var DoublyLinkedRing[T], n: DoublyLinkedNode[T]) = ## removes `n` from `L`. Efficiency: O(1). n.next.prev = n.prev n.prev.next = n.next - if n == L.head: + if n == L.head: var p = L.head.prev - if p == L.head: + if p == L.head: # only one element left: L.head = nil else: diff --git a/lib/pure/collections/queues.nim b/lib/pure/collections/queues.nim index af5e7b6cd..c35a2dc29 100644 --- a/lib/pure/collections/queues.nim +++ b/lib/pure/collections/queues.nim @@ -77,7 +77,7 @@ proc dequeue*[T](q: var Queue[T]): T = result = q.data[q.rd] q.rd = (q.rd + 1) and q.mask -proc `$`*[T](q: Queue[T]): string = +proc `$`*[T](q: Queue[T]): string = ## turns a queue into its string representation. result = "[" for x in items(q): @@ -95,7 +95,7 @@ when isMainModule: q.add(6) var second = q.dequeue q.add(789) - + assert first == 123 assert second == 9 assert($q == "[4, 56, 6, 789]") diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index f24cc0072..7328f7c24 100644 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -6,7 +6,7 @@ # distribution, for details about the copyright. # -## This module implements color handling for Nimrod. It is used by +## This module implements color handling for Nimrod. It is used by ## the ``graphics`` module. import strutils @@ -18,15 +18,15 @@ type proc `==` *(a, b: Color): bool {.borrow.} ## compares two colors. - + template extract(a: Color, r, g, b: expr) {.immediate.}= var r = a.int shr 16 and 0xff var g = a.int shr 8 and 0xff var b = a.int and 0xff - + template rawRGB(r, g, b: int): expr = Color(r shl 16 or g shl 8 or b) - + template colorOp(op: expr) {.immediate.} = extract(a, ar, ag, ab) extract(b, br, bg, bb) @@ -39,24 +39,24 @@ proc satPlus(a, b: int): int {.inline.} = proc satMinus(a, b: int): int {.inline.} = result = a -% b if result < 0: result = 0 - + proc `+`*(a, b: Color): Color = ## adds two colors: This uses saturated artithmetic, so that each color ## component cannot overflow (255 is used as a maximum). colorOp(satPlus) - + proc `-`*(a, b: Color): Color = ## subtracts two colors: This uses saturated artithmetic, so that each color ## component cannot overflow (255 is used as a maximum). colorOp(satMinus) - + proc extractRGB*(a: Color): tuple[r, g, b: range[0..255]] = ## extracts the red/green/blue components of the color `a`. result.r = a.int shr 16 and 0xff result.g = a.int shr 8 and 0xff result.b = a.int and 0xff - -proc intensity*(a: Color, f: float): Color = + +proc intensity*(a: Color, f: float): Color = ## returns `a` with intensity `f`. `f` should be a float from 0.0 (completely ## dark) to 1.0 (full color intensity). var r = toInt(toFloat(a.int shr 16 and 0xff) * f) @@ -66,7 +66,7 @@ proc intensity*(a: Color, f: float): Color = if g >% 255: g = 255 if b >% 255: b = 255 result = rawRGB(r, g, b) - + template mix*(a, b: Color, fn: expr): expr = ## uses `fn` to mix the colors `a` and `b`. `fn` is invoked for each component ## R, G, and B. This is a template because `fn` should be inlined and the @@ -79,7 +79,7 @@ template mix*(a, b: Color, fn: expr): expr = if y >% 255: y = if y < 0: 0 else: 255 y - + (bind extract)(a, ar, ag, ab) (bind extract)(b, br, bg, bb) (bind rawRGB)(><fn(ar, br), ><fn(ag, bg), ><fn(ab, bb)) @@ -226,7 +226,7 @@ const colWhiteSmoke* = Color(0xF5F5F5) colYellow* = Color(0xFFFF00) colYellowGreen* = Color(0x9ACD32) - + colorNames = [ ("aliceblue", colAliceBlue), ("antiquewhite", colAntiqueWhite), @@ -369,24 +369,24 @@ const ("yellow", colYellow), ("yellowgreen", colYellowGreen)] -proc `$`*(c: Color): string = +proc `$`*(c: Color): string = ## converts a color into its textual representation. Example: ``#00FF00``. result = '#' & toHex(int(c), 6) -proc binaryStrSearch(x: openArray[tuple[name: string, col: Color]], - y: string): int = +proc binaryStrSearch(x: openArray[tuple[name: string, col: Color]], + y: string): int = var a = 0 var b = len(x) - 1 - while a <= b: + while a <= b: var mid = (a + b) div 2 var c = cmp(x[mid].name, y) if c < 0: a = mid + 1 elif c > 0: b = mid - 1 else: return mid result = - 1 - -proc parseColor*(name: string): Color = - ## parses `name` to a color value. If no valid color could be + +proc parseColor*(name: string): Color = + ## parses `name` to a color value. If no valid color could be ## parsed ``EInvalidValue`` is raised. if name[0] == '#': result = Color(parseHexInt(name)) @@ -396,10 +396,10 @@ proc parseColor*(name: string): Color = result = colorNames[idx][1] proc isColor*(name: string): bool = - ## returns true if `name` is a known color name or a hexadecimal color + ## returns true if `name` is a known color name or a hexadecimal color ## prefixed with ``#``. - if name[0] == '#': - for i in 1 .. name.len-1: + if name[0] == '#': + for i in 1 .. name.len-1: if name[i] notin {'0'..'9', 'a'..'f', 'A'..'F'}: return false result = true else: diff --git a/lib/pure/complex.nim b/lib/pure/complex.nim index 8577bf7a1..ccde5ee0a 100644 --- a/lib/pure/complex.nim +++ b/lib/pure/complex.nim @@ -17,7 +17,7 @@ import math - + const EPS = 1.0e-7 ## Epsilon used for float comparisons. @@ -248,7 +248,7 @@ proc pow*(x, y: Complex): Complex = var r = y.re*theta + y.im*ln(rho) result.re = s*cos(r) result.im = s*sin(r) - + proc sin*(z: Complex): Complex = ## Returns the sine of `z`. @@ -387,7 +387,7 @@ when isMainModule: var one = (1.0,0.0) var tt = (10.0, 20.0) var ipi = (0.0, -PI) - + assert( a == a ) assert( (a-a) == z ) assert( (a+b) == z ) @@ -403,7 +403,7 @@ when isMainModule: assert( conjugate(a) == (1.0, -2.0) ) assert( sqrt(m1) == i ) assert( exp(ipi) =~ m1 ) - + assert( pow(a,b) =~ (-3.72999124927876, -1.68815826725068) ) assert( pow(z,a) =~ (0.0, 0.0) ) assert( pow(z,z) =~ (1.0, 0.0) ) diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index 6f2bc4491..8c87c77df 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -18,7 +18,7 @@ when not defined(windows): when defined(linux): import linux - + when defined(freebsd) or defined(macosx): {.emit:"#include <sys/types.h>".} diff --git a/lib/pure/cookies.nim b/lib/pure/cookies.nim index 9983c4a04..8090cd49d 100644 --- a/lib/pure/cookies.nim +++ b/lib/pure/cookies.nim @@ -11,7 +11,7 @@ import strtabs, times -proc parseCookies*(s: string): StringTableRef = +proc parseCookies*(s: string): StringTableRef = ## parses cookies into a string table. result = newStringTable(modeCaseInsensitive) var i = 0 @@ -31,7 +31,7 @@ proc parseCookies*(s: string): StringTableRef = proc setCookie*(key, value: string, domain = "", path = "", expires = "", noName = false, secure = false, httpOnly = false): string = - ## Creates a command in the format of + ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` result = "" if not noName: result.add("Set-Cookie: ") @@ -45,10 +45,10 @@ proc setCookie*(key, value: string, domain = "", path = "", proc setCookie*(key, value: string, expires: TimeInfo, domain = "", path = "", noName = false, secure = false, httpOnly = false): string = - ## Creates a command in the format of + ## Creates a command in the format of ## ``Set-Cookie: key=value; Domain=...; ...`` ## - ## **Note:** UTC is assumed as the timezone for ``expires``. + ## **Note:** UTC is assumed as the timezone for ``expires``. return setCookie(key, value, domain, path, format(expires, "ddd',' dd MMM yyyy HH:mm:ss 'UTC'"), noname, secure, httpOnly) @@ -61,7 +61,7 @@ when isMainModule: echo cookie let start = "Set-Cookie: test=value; Expires=" assert cookie[0..start.high] == start - + let table = parseCookies("uid=1; kp=2") assert table["uid"] == "1" assert table["kp"] == "2" diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index e427b585d..2d305ea42 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## Converts between different character encodings. On UNIX, this uses +## Converts between different character encodings. On UNIX, this uses ## the `iconv`:idx: library, on Windows the Windows API. import os, parseutils, strutils @@ -41,173 +41,173 @@ when defined(windows): inc j result = i == a.len and j == b.len - const + const winEncodings = [ (1, "OEMCP"), # current OEM codepage - (037, "IBM037"), # IBM EBCDIC US-Canada - (437, "IBM437"), # OEM United States - (500, "IBM500"), # IBM EBCDIC International - (708, "ASMO-708"), # Arabic (ASMO 708) - (709, "ASMO_449"), # Arabic (ASMO-449+, BCON V4) - (710, ""), # Arabic - Transparent Arabic - (720, "DOS-720"), # Arabic (Transparent ASMO); Arabic (DOS) - (737, "ibm737"), # OEM Greek (formerly 437G); Greek (DOS) - (775, "ibm775"), # OEM Baltic; Baltic (DOS) - (850, "ibm850"), # OEM Multilingual Latin 1; Western European (DOS) - (852, "ibm852"), # OEM Latin 2; Central European (DOS) - (855, "IBM855"), # OEM Cyrillic (primarily Russian) - (857, "ibm857"), # OEM Turkish; Turkish (DOS) - (858, "IBM00858"), # OEM Multilingual Latin 1 + Euro symbol - (860, "IBM860"), # OEM Portuguese; Portuguese (DOS) - (861, "ibm861"), # OEM Icelandic; Icelandic (DOS) - (862, "DOS-862"), # OEM Hebrew; Hebrew (DOS) - (863, "IBM863"), # OEM French Canadian; French Canadian (DOS) - (864, "IBM864"), # OEM Arabic; Arabic (864) - (865, "IBM865"), # OEM Nordic; Nordic (DOS) - (866, "cp866"), # OEM Russian; Cyrillic (DOS) - (869, "ibm869"), # OEM Modern Greek; Greek, Modern (DOS) - (870, "IBM870"), # IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 - (874, "windows-874"), # ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) - (875, "cp875"), # IBM EBCDIC Greek Modern - (932, "shift_jis"), # ANSI/OEM Japanese; Japanese (Shift-JIS) - (936, "gb2312"), # ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) - (949, "ks_c_5601-1987"), # ANSI/OEM Korean (Unified Hangul Code) - (950, "big5"), # ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) - (1026, "IBM1026"), # IBM EBCDIC Turkish (Latin 5) - (1047, "IBM01047"), # IBM EBCDIC Latin 1/Open System - (1140, "IBM01140"), # IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) - (1141, "IBM01141"), # IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) - (1142, "IBM01142"), # IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) - (1143, "IBM01143"), # IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) - (1144, "IBM01144"), # IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) - (1145, "IBM01145"), # IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) - (1146, "IBM01146"), # IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) - (1147, "IBM01147"), # IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) - (1148, "IBM01148"), # IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) - (1149, "IBM01149"), # IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) - (1200, "utf-16"), # Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications - (1201, "unicodeFFFE"), # Unicode UTF-16, big endian byte order; available only to managed applications - (1250, "windows-1250"), # ANSI Central European; Central European (Windows) - (1251, "windows-1251"), # ANSI Cyrillic; Cyrillic (Windows) - (1252, "windows-1252"), # ANSI Latin 1; Western European (Windows) - (1253, "windows-1253"), # ANSI Greek; Greek (Windows) - (1254, "windows-1254"), # ANSI Turkish; Turkish (Windows) - (1255, "windows-1255"), # ANSI Hebrew; Hebrew (Windows) - (1256, "windows-1256"), # ANSI Arabic; Arabic (Windows) - (1257, "windows-1257"), # ANSI Baltic; Baltic (Windows) - (1258, "windows-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows) - - (1250, "cp-1250"), # ANSI Central European; Central European (Windows) - (1251, "cp-1251"), # ANSI Cyrillic; Cyrillic (Windows) - (1252, "cp-1252"), # ANSI Latin 1; Western European (Windows) - (1253, "cp-1253"), # ANSI Greek; Greek (Windows) - (1254, "cp-1254"), # ANSI Turkish; Turkish (Windows) - (1255, "cp-1255"), # ANSI Hebrew; Hebrew (Windows) - (1256, "cp-1256"), # ANSI Arabic; Arabic (Windows) - (1257, "cp-1257"), # ANSI Baltic; Baltic (Windows) - (1258, "cp-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows) - - (1361, "Johab"), # Korean (Johab) - (10000, "macintosh"), # MAC Roman; Western European (Mac) - (10001, "x-mac-japanese"), # Japanese (Mac) - (10002, "x-mac-chinesetrad"), # MAC Traditional Chinese (Big5); Chinese Traditional (Mac) - (10003, "x-mac-korean"), # Korean (Mac) - (10004, "x-mac-arabic"), # Arabic (Mac) - (10005, "x-mac-hebrew"), # Hebrew (Mac) - (10006, "x-mac-greek"), # Greek (Mac) - (10007, "x-mac-cyrillic"), # Cyrillic (Mac) - (10008, "x-mac-chinesesimp"), # MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) - (10010, "x-mac-romanian"), # Romanian (Mac) - (10017, "x-mac-ukrainian"), # Ukrainian (Mac) - (10021, "x-mac-thai"), # Thai (Mac) - (10029, "x-mac-ce"), # MAC Latin 2; Central European (Mac) - (10079, "x-mac-icelandic"), # Icelandic (Mac) - (10081, "x-mac-turkish"), # Turkish (Mac) - (10082, "x-mac-croatian"), # Croatian (Mac) - (12000, "utf-32"), # Unicode UTF-32, little endian byte order; available only to managed applications - (12001, "utf-32BE"), # Unicode UTF-32, big endian byte order; available only to managed applications - (20000, "x-Chinese_CNS"), # CNS Taiwan; Chinese Traditional (CNS) - (20001, "x-cp20001"), # TCA Taiwan - (20002, "x_Chinese-Eten"), # Eten Taiwan; Chinese Traditional (Eten) - (20003, "x-cp20003"), # IBM5550 Taiwan - (20004, "x-cp20004"), # TeleText Taiwan - (20005, "x-cp20005"), # Wang Taiwan - (20105, "x-IA5"), # IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) - (20106, "x-IA5-German"), # IA5 German (7-bit) - (20107, "x-IA5-Swedish"), # IA5 Swedish (7-bit) - (20108, "x-IA5-Norwegian"), # IA5 Norwegian (7-bit) - (20127, "us-ascii"), # US-ASCII (7-bit) - (20261, "x-cp20261"), # T.61 - (20269, "x-cp20269"), # ISO 6937 Non-Spacing Accent - (20273, "IBM273"), # IBM EBCDIC Germany - (20277, "IBM277"), # IBM EBCDIC Denmark-Norway - (20278, "IBM278"), # IBM EBCDIC Finland-Sweden - (20280, "IBM280"), # IBM EBCDIC Italy - (20284, "IBM284"), # IBM EBCDIC Latin America-Spain - (20285, "IBM285"), # IBM EBCDIC United Kingdom - (20290, "IBM290"), # IBM EBCDIC Japanese Katakana Extended - (20297, "IBM297"), # IBM EBCDIC France - (20420, "IBM420"), # IBM EBCDIC Arabic - (20423, "IBM423"), # IBM EBCDIC Greek - (20424, "IBM424"), # IBM EBCDIC Hebrew - (20833, "x-EBCDIC-KoreanExtended"), # IBM EBCDIC Korean Extended - (20838, "IBM-Thai"), # IBM EBCDIC Thai - (20866, "koi8-r"), # Russian (KOI8-R); Cyrillic (KOI8-R) - (20871, "IBM871"), # IBM EBCDIC Icelandic - (20880, "IBM880"), # IBM EBCDIC Cyrillic Russian - (20905, "IBM905"), # IBM EBCDIC Turkish - (20924, "IBM00924"), # IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) - (20932, "EUC-JP"), # Japanese (JIS 0208-1990 and 0121-1990) - (20936, "x-cp20936"), # Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) - (20949, "x-cp20949"), # Korean Wansung - (21025, "cp1025"), # IBM EBCDIC Cyrillic Serbian-Bulgarian - (21027, ""), # (deprecated) - (21866, "koi8-u"), # Ukrainian (KOI8-U); Cyrillic (KOI8-U) - (28591, "iso-8859-1"), # ISO 8859-1 Latin 1; Western European (ISO) - (28592, "iso-8859-2"), # ISO 8859-2 Central European; Central European (ISO) - (28593, "iso-8859-3"), # ISO 8859-3 Latin 3 - (28594, "iso-8859-4"), # ISO 8859-4 Baltic - (28595, "iso-8859-5"), # ISO 8859-5 Cyrillic - (28596, "iso-8859-6"), # ISO 8859-6 Arabic - (28597, "iso-8859-7"), # ISO 8859-7 Greek - (28598, "iso-8859-8"), # ISO 8859-8 Hebrew; Hebrew (ISO-Visual) - (28599, "iso-8859-9"), # ISO 8859-9 Turkish - (28603, "iso-8859-13"), # ISO 8859-13 Estonian - (28605, "iso-8859-15"), # ISO 8859-15 Latin 9 - (29001, "x-Europa"), # Europa 3 - (38598, "iso-8859-8-i"), # ISO 8859-8 Hebrew; Hebrew (ISO-Logical) - (50220, "iso-2022-jp"), # ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) - (50221, "csISO2022JP"), # ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) - (50222, "iso-2022-jp"), # ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) - (50225, "iso-2022-kr"), # ISO 2022 Korean - (50227, "x-cp50227"), # ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) - (50229, ""), # ISO 2022 Traditional Chinese - (50930, ""), # EBCDIC Japanese (Katakana) Extended - (50931, ""), # EBCDIC US-Canada and Japanese - (50933, ""), # EBCDIC Korean Extended and Korean - (50935, ""), # EBCDIC Simplified Chinese Extended and Simplified Chinese - (50936, ""), # EBCDIC Simplified Chinese - (50937, ""), # EBCDIC US-Canada and Traditional Chinese - (50939, ""), # EBCDIC Japanese (Latin) Extended and Japanese - (51932, "euc-jp"), # EUC Japanese - (51936, "EUC-CN"), # EUC Simplified Chinese; Chinese Simplified (EUC) - (51949, "euc-kr"), # EUC Korean - (51950, ""), # EUC Traditional Chinese - (52936, "hz-gb-2312"), # HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) - (54936, "GB18030"), # Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) - (57002, "x-iscii-de"), # ISCII Devanagari - (57003, "x-iscii-be"), # ISCII Bengali - (57004, "x-iscii-ta"), # ISCII Tamil - (57005, "x-iscii-te"), # ISCII Telugu - (57006, "x-iscii-as"), # ISCII Assamese - (57007, "x-iscii-or"), # ISCII Oriya - (57008, "x-iscii-ka"), # ISCII Kannada - (57009, "x-iscii-ma"), # ISCII Malayalam - (57010, "x-iscii-gu"), # ISCII Gujarati - (57011, "x-iscii-pa"), # ISCII Punjabi - (65000, "utf-7"), # Unicode (UTF-7) - (65001, "utf-8")] # Unicode (UTF-8) - + (037, "IBM037"), # IBM EBCDIC US-Canada + (437, "IBM437"), # OEM United States + (500, "IBM500"), # IBM EBCDIC International + (708, "ASMO-708"), # Arabic (ASMO 708) + (709, "ASMO_449"), # Arabic (ASMO-449+, BCON V4) + (710, ""), # Arabic - Transparent Arabic + (720, "DOS-720"), # Arabic (Transparent ASMO); Arabic (DOS) + (737, "ibm737"), # OEM Greek (formerly 437G); Greek (DOS) + (775, "ibm775"), # OEM Baltic; Baltic (DOS) + (850, "ibm850"), # OEM Multilingual Latin 1; Western European (DOS) + (852, "ibm852"), # OEM Latin 2; Central European (DOS) + (855, "IBM855"), # OEM Cyrillic (primarily Russian) + (857, "ibm857"), # OEM Turkish; Turkish (DOS) + (858, "IBM00858"), # OEM Multilingual Latin 1 + Euro symbol + (860, "IBM860"), # OEM Portuguese; Portuguese (DOS) + (861, "ibm861"), # OEM Icelandic; Icelandic (DOS) + (862, "DOS-862"), # OEM Hebrew; Hebrew (DOS) + (863, "IBM863"), # OEM French Canadian; French Canadian (DOS) + (864, "IBM864"), # OEM Arabic; Arabic (864) + (865, "IBM865"), # OEM Nordic; Nordic (DOS) + (866, "cp866"), # OEM Russian; Cyrillic (DOS) + (869, "ibm869"), # OEM Modern Greek; Greek, Modern (DOS) + (870, "IBM870"), # IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2 + (874, "windows-874"), # ANSI/OEM Thai (same as 28605, ISO 8859-15); Thai (Windows) + (875, "cp875"), # IBM EBCDIC Greek Modern + (932, "shift_jis"), # ANSI/OEM Japanese; Japanese (Shift-JIS) + (936, "gb2312"), # ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312) + (949, "ks_c_5601-1987"), # ANSI/OEM Korean (Unified Hangul Code) + (950, "big5"), # ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5) + (1026, "IBM1026"), # IBM EBCDIC Turkish (Latin 5) + (1047, "IBM01047"), # IBM EBCDIC Latin 1/Open System + (1140, "IBM01140"), # IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro) + (1141, "IBM01141"), # IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro) + (1142, "IBM01142"), # IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro) + (1143, "IBM01143"), # IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro) + (1144, "IBM01144"), # IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro) + (1145, "IBM01145"), # IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro) + (1146, "IBM01146"), # IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro) + (1147, "IBM01147"), # IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro) + (1148, "IBM01148"), # IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro) + (1149, "IBM01149"), # IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro) + (1200, "utf-16"), # Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications + (1201, "unicodeFFFE"), # Unicode UTF-16, big endian byte order; available only to managed applications + (1250, "windows-1250"), # ANSI Central European; Central European (Windows) + (1251, "windows-1251"), # ANSI Cyrillic; Cyrillic (Windows) + (1252, "windows-1252"), # ANSI Latin 1; Western European (Windows) + (1253, "windows-1253"), # ANSI Greek; Greek (Windows) + (1254, "windows-1254"), # ANSI Turkish; Turkish (Windows) + (1255, "windows-1255"), # ANSI Hebrew; Hebrew (Windows) + (1256, "windows-1256"), # ANSI Arabic; Arabic (Windows) + (1257, "windows-1257"), # ANSI Baltic; Baltic (Windows) + (1258, "windows-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows) + + (1250, "cp-1250"), # ANSI Central European; Central European (Windows) + (1251, "cp-1251"), # ANSI Cyrillic; Cyrillic (Windows) + (1252, "cp-1252"), # ANSI Latin 1; Western European (Windows) + (1253, "cp-1253"), # ANSI Greek; Greek (Windows) + (1254, "cp-1254"), # ANSI Turkish; Turkish (Windows) + (1255, "cp-1255"), # ANSI Hebrew; Hebrew (Windows) + (1256, "cp-1256"), # ANSI Arabic; Arabic (Windows) + (1257, "cp-1257"), # ANSI Baltic; Baltic (Windows) + (1258, "cp-1258"), # ANSI/OEM Vietnamese; Vietnamese (Windows) + + (1361, "Johab"), # Korean (Johab) + (10000, "macintosh"), # MAC Roman; Western European (Mac) + (10001, "x-mac-japanese"), # Japanese (Mac) + (10002, "x-mac-chinesetrad"), # MAC Traditional Chinese (Big5); Chinese Traditional (Mac) + (10003, "x-mac-korean"), # Korean (Mac) + (10004, "x-mac-arabic"), # Arabic (Mac) + (10005, "x-mac-hebrew"), # Hebrew (Mac) + (10006, "x-mac-greek"), # Greek (Mac) + (10007, "x-mac-cyrillic"), # Cyrillic (Mac) + (10008, "x-mac-chinesesimp"), # MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac) + (10010, "x-mac-romanian"), # Romanian (Mac) + (10017, "x-mac-ukrainian"), # Ukrainian (Mac) + (10021, "x-mac-thai"), # Thai (Mac) + (10029, "x-mac-ce"), # MAC Latin 2; Central European (Mac) + (10079, "x-mac-icelandic"), # Icelandic (Mac) + (10081, "x-mac-turkish"), # Turkish (Mac) + (10082, "x-mac-croatian"), # Croatian (Mac) + (12000, "utf-32"), # Unicode UTF-32, little endian byte order; available only to managed applications + (12001, "utf-32BE"), # Unicode UTF-32, big endian byte order; available only to managed applications + (20000, "x-Chinese_CNS"), # CNS Taiwan; Chinese Traditional (CNS) + (20001, "x-cp20001"), # TCA Taiwan + (20002, "x_Chinese-Eten"), # Eten Taiwan; Chinese Traditional (Eten) + (20003, "x-cp20003"), # IBM5550 Taiwan + (20004, "x-cp20004"), # TeleText Taiwan + (20005, "x-cp20005"), # Wang Taiwan + (20105, "x-IA5"), # IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5) + (20106, "x-IA5-German"), # IA5 German (7-bit) + (20107, "x-IA5-Swedish"), # IA5 Swedish (7-bit) + (20108, "x-IA5-Norwegian"), # IA5 Norwegian (7-bit) + (20127, "us-ascii"), # US-ASCII (7-bit) + (20261, "x-cp20261"), # T.61 + (20269, "x-cp20269"), # ISO 6937 Non-Spacing Accent + (20273, "IBM273"), # IBM EBCDIC Germany + (20277, "IBM277"), # IBM EBCDIC Denmark-Norway + (20278, "IBM278"), # IBM EBCDIC Finland-Sweden + (20280, "IBM280"), # IBM EBCDIC Italy + (20284, "IBM284"), # IBM EBCDIC Latin America-Spain + (20285, "IBM285"), # IBM EBCDIC United Kingdom + (20290, "IBM290"), # IBM EBCDIC Japanese Katakana Extended + (20297, "IBM297"), # IBM EBCDIC France + (20420, "IBM420"), # IBM EBCDIC Arabic + (20423, "IBM423"), # IBM EBCDIC Greek + (20424, "IBM424"), # IBM EBCDIC Hebrew + (20833, "x-EBCDIC-KoreanExtended"), # IBM EBCDIC Korean Extended + (20838, "IBM-Thai"), # IBM EBCDIC Thai + (20866, "koi8-r"), # Russian (KOI8-R); Cyrillic (KOI8-R) + (20871, "IBM871"), # IBM EBCDIC Icelandic + (20880, "IBM880"), # IBM EBCDIC Cyrillic Russian + (20905, "IBM905"), # IBM EBCDIC Turkish + (20924, "IBM00924"), # IBM EBCDIC Latin 1/Open System (1047 + Euro symbol) + (20932, "EUC-JP"), # Japanese (JIS 0208-1990 and 0121-1990) + (20936, "x-cp20936"), # Simplified Chinese (GB2312); Chinese Simplified (GB2312-80) + (20949, "x-cp20949"), # Korean Wansung + (21025, "cp1025"), # IBM EBCDIC Cyrillic Serbian-Bulgarian + (21027, ""), # (deprecated) + (21866, "koi8-u"), # Ukrainian (KOI8-U); Cyrillic (KOI8-U) + (28591, "iso-8859-1"), # ISO 8859-1 Latin 1; Western European (ISO) + (28592, "iso-8859-2"), # ISO 8859-2 Central European; Central European (ISO) + (28593, "iso-8859-3"), # ISO 8859-3 Latin 3 + (28594, "iso-8859-4"), # ISO 8859-4 Baltic + (28595, "iso-8859-5"), # ISO 8859-5 Cyrillic + (28596, "iso-8859-6"), # ISO 8859-6 Arabic + (28597, "iso-8859-7"), # ISO 8859-7 Greek + (28598, "iso-8859-8"), # ISO 8859-8 Hebrew; Hebrew (ISO-Visual) + (28599, "iso-8859-9"), # ISO 8859-9 Turkish + (28603, "iso-8859-13"), # ISO 8859-13 Estonian + (28605, "iso-8859-15"), # ISO 8859-15 Latin 9 + (29001, "x-Europa"), # Europa 3 + (38598, "iso-8859-8-i"), # ISO 8859-8 Hebrew; Hebrew (ISO-Logical) + (50220, "iso-2022-jp"), # ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS) + (50221, "csISO2022JP"), # ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana) + (50222, "iso-2022-jp"), # ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI) + (50225, "iso-2022-kr"), # ISO 2022 Korean + (50227, "x-cp50227"), # ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022) + (50229, ""), # ISO 2022 Traditional Chinese + (50930, ""), # EBCDIC Japanese (Katakana) Extended + (50931, ""), # EBCDIC US-Canada and Japanese + (50933, ""), # EBCDIC Korean Extended and Korean + (50935, ""), # EBCDIC Simplified Chinese Extended and Simplified Chinese + (50936, ""), # EBCDIC Simplified Chinese + (50937, ""), # EBCDIC US-Canada and Traditional Chinese + (50939, ""), # EBCDIC Japanese (Latin) Extended and Japanese + (51932, "euc-jp"), # EUC Japanese + (51936, "EUC-CN"), # EUC Simplified Chinese; Chinese Simplified (EUC) + (51949, "euc-kr"), # EUC Korean + (51950, ""), # EUC Traditional Chinese + (52936, "hz-gb-2312"), # HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ) + (54936, "GB18030"), # Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030) + (57002, "x-iscii-de"), # ISCII Devanagari + (57003, "x-iscii-be"), # ISCII Bengali + (57004, "x-iscii-ta"), # ISCII Tamil + (57005, "x-iscii-te"), # ISCII Telugu + (57006, "x-iscii-as"), # ISCII Assamese + (57007, "x-iscii-or"), # ISCII Oriya + (57008, "x-iscii-ka"), # ISCII Kannada + (57009, "x-iscii-ma"), # ISCII Malayalam + (57010, "x-iscii-gu"), # ISCII Gujarati + (57011, "x-iscii-pa"), # ISCII Punjabi + (65000, "utf-7"), # Unicode (UTF-7) + (65001, "utf-8")] # Unicode (UTF-8) + when false: # not needed yet: type @@ -219,22 +219,22 @@ when defined(windows): proc getCPInfo(codePage: CodePage, lpCPInfo: var CpInfo): int32 {. stdcall, importc: "GetCPInfo", dynlib: "kernel32".} - + proc nameToCodePage(name: string): CodePage = var nameAsInt: int if parseInt(name, nameAsInt) == 0: nameAsInt = -1 for no, na in items(winEncodings): if no == nameAsInt or eqEncodingNames(na, name): return CodePage(no) result = CodePage(-1) - + proc codePageToName(c: CodePage): string = for no, na in items(winEncodings): if no == int(c): return if na.len != 0: na else: $no result = "" - + proc getACP(): CodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".} - + proc multiByteToWideChar( codePage: CodePage, dwFlags: int32, @@ -254,7 +254,7 @@ when defined(windows): lpDefaultChar: cstring=nil, lpUsedDefaultChar: pointer=nil): cint {. stdcall, importc: "WideCharToMultiByte", dynlib: "kernel32".} - + else: when defined(haiku): const iconvDll = "(libc.so.6|libiconv.so|libtextencoding.so)" @@ -292,31 +292,31 @@ else: proc iconv(c: EncodingConverter, inbuf: pointer, inbytesLeft: pointer, outbuf: var cstring, outbytesLeft: var int): int {. importc: prefix & "iconv", cdecl, dynlib: iconvDll.} - + proc getCurrentEncoding*(): string = ## retrieves the current encoding. On Unix, always "UTF-8" is returned. when defined(windows): result = codePageToName(getACP()) else: result = "UTF-8" - + proc open*(destEncoding = "UTF-8", srcEncoding = "CP1252"): EncodingConverter = ## opens a converter that can convert from `srcEncoding` to `destEncoding`. ## Raises `EIO` if it cannot fulfill the request. when not defined(windows): result = iconvOpen(destEncoding, srcEncoding) if result == nil: - raise newException(EncodingError, - "cannot create encoding converter from " & + raise newException(EncodingError, + "cannot create encoding converter from " & srcEncoding & " to " & destEncoding) else: result.dest = nameToCodePage(destEncoding) result.src = nameToCodePage(srcEncoding) if int(result.dest) == -1: - raise newException(EncodingError, + raise newException(EncodingError, "cannot find encoding " & destEncoding) if int(result.src) == -1: - raise newException(EncodingError, + raise newException(EncodingError, "cannot find encoding " & srcEncoding) proc close*(c: EncodingConverter) = @@ -328,7 +328,7 @@ when defined(windows): proc convert*(c: EncodingConverter, s: string): string = ## converts `s` to `destEncoding` that was given to the converter `c`. It ## assumed that `s` is in `srcEncoding`. - + # special case: empty string: needed because MultiByteToWideChar # return 0 in case of error: if s.len == 0: return "" @@ -336,21 +336,21 @@ when defined(windows): var cap = s.len + s.len shr 2 result = newStringOfCap(cap*2) # convert to utf-16 LE - var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, + var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = cstring(result), cchWideChar = cint(cap)) - if m == 0: + if m == 0: # try again; ask for capacity: - cap = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, + cap = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = nil, cchWideChar = cint(0)) # and do the conversion properly: result = newStringOfCap(cap*2) - m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, + m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = cstring(result), @@ -361,7 +361,7 @@ when defined(windows): setLen(result, m*2) else: assert(false) # cannot happen - + # if already utf-16 LE, no further need to do something: if int(c.dest) == 1200: return # otherwise the fun starts again: @@ -428,7 +428,7 @@ else: outLen = len(result) - offset else: raiseOSError(lerr.OSErrorCode) - # iconv has a buffer that needs flushing, specially if the last char is + # iconv has a buffer that needs flushing, specially if the last char is # not '\0' discard iconv(c, nil, nil, dst, outLen) if iconvres == cint(-1) and errno == E2BIG: @@ -441,7 +441,7 @@ else: # trim output buffer setLen(result, len(result) - outLen) -proc convert*(s: string, destEncoding = "UTF-8", +proc convert*(s: string, destEncoding = "UTF-8", srcEncoding = "CP1252"): string = ## converts `s` to `destEncoding`. It assumed that `s` is in `srcEncoding`. ## This opens a converter, uses it and closes it again and is thus more diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim index 6e33d4624..5a23169d4 100644 --- a/lib/pure/endians.nim +++ b/lib/pure/endians.nim @@ -24,7 +24,7 @@ proc swapEndian64*(outp, inp: pointer) = o[6] = i[1] o[7] = i[0] -proc swapEndian32*(outp, inp: pointer) = +proc swapEndian32*(outp, inp: pointer) = ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to ## contain at least 4 bytes. var i = cast[cstring](inp) @@ -34,7 +34,7 @@ proc swapEndian32*(outp, inp: pointer) = o[2] = i[1] o[3] = i[0] -proc swapEndian16*(outp, inp: pointer) = +proc swapEndian16*(outp, inp: pointer) = ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to ## contain at least 2 bytes. var @@ -50,7 +50,7 @@ when system.cpuEndian == bigEndian: proc bigEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8) proc bigEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4) proc bigEndian16*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 2) -else: +else: proc littleEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8) proc littleEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4) proc littleEndian16*(outp, inp: pointer){.inline.} = copyMem(outp, inp, 2) diff --git a/lib/pure/etcpriv.nim b/lib/pure/etcpriv.nim index e7a525e4d..5b785b051 100644 --- a/lib/pure/etcpriv.nim +++ b/lib/pure/etcpriv.nim @@ -18,6 +18,6 @@ const magicIdentSeparatorRuneByteWidth* = 3 # Used by pure/hashes.nim, and the compiler parsing proc isMagicIdentSeparatorRune*(cs: cstring, i: int): bool {. inline } = - result = cs[i] == '\226' and + result = cs[i] == '\226' and cs[i + 1] == '\128' and cs[i + 2] == '\147' # en-dash # 145 = nb-hyphen diff --git a/lib/pure/events.nim b/lib/pure/events.nim index 44e9ed286..01b64c545 100644 --- a/lib/pure/events.nim +++ b/lib/pure/events.nim @@ -10,7 +10,7 @@ ## :Author: Alex Mitchell ## ## This module implements an event system that is not dependent on external -## graphical toolkits. It was originally called ``NimEE`` because +## graphical toolkits. It was originally called ``NimEE`` because ## it was inspired by Python's PyEE module. There are two ways you can use ## events: one is a python-inspired way; the other is more of a C-style way. ## @@ -23,7 +23,7 @@ ## # Python way ## ee.on("EventName", handleevent) ## ee.emit("EventName", genericargs) -## +## ## # C/Java way ## # Declare a type ## type @@ -45,7 +45,7 @@ type {.deprecated: [TEventArgs: EventArgs, TEventHandler: EventHandler, TEventEmitter: EventEmitter, EInvalidEvent: EventError].} - + proc initEventHandler*(name: string): EventHandler = ## Initializes an EventHandler with the specified name and returns it. result.handlers = @[] @@ -61,7 +61,7 @@ proc removeHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure. if fn == handler.handlers[i]: handler.handlers.del(i) break - + proc containsHandler*(handler: var EventHandler, fn: proc(e: EventArgs) {.closure.}): bool = ## Checks if a callback is registered to this event handler. return handler.handlers.contains(fn) @@ -86,8 +86,8 @@ proc on*(emitter: var EventEmitter, event: string, fn: proc(e: EventArgs) {.clos emitter.s.add(eh) else: addHandler(emitter.s[i], fn) - -proc emit*(emitter: var EventEmitter, eventhandler: var EventHandler, + +proc emit*(emitter: var EventEmitter, eventhandler: var EventHandler, args: EventArgs) = ## Fires an event handler with specified event arguments. for fn in items(eventhandler.handlers): fn(args) diff --git a/lib/pure/fsmonitor.nim b/lib/pure/fsmonitor.nim index 229df80b5..787acb5d4 100644 --- a/lib/pure/fsmonitor.nim +++ b/lib/pure/fsmonitor.nim @@ -30,7 +30,7 @@ type fd: cint handleEvent: proc (m: FSMonitor, ev: MonitorEvent) {.closure.} targets: Table[cint, string] - + MonitorEventType* = enum ## Monitor event type MonitorAccess, ## File was accessed. MonitorAttrib, ## Metadata changed. @@ -44,7 +44,7 @@ type MonitorMoved, ## File was moved. MonitorOpen, ## File was opened. MonitorAll ## Filter for all event types. - + MonitorEvent* = object case kind*: MonitorEventType ## Type of the event. of MonitorMoveSelf, MonitorMoved: @@ -77,7 +77,7 @@ proc add*(monitor: FSMonitor, target: string, ## Adds ``target`` which may be a directory or a file to the list of ## watched paths of ``monitor``. ## You can specify the events to report using the ``filters`` parameter. - + var INFilter = -1 for f in filters: case f @@ -93,7 +93,7 @@ proc add*(monitor: FSMonitor, target: string, of MonitorMoved: INFilter = INFilter and IN_MOVED_FROM and IN_MOVED_TO of MonitorOpen: INFilter = INFilter and IN_OPEN of MonitorAll: INFilter = INFilter and IN_ALL_EVENTS - + result = inotifyAddWatch(monitor.fd, target, INFilter.uint32) if result < 0: raiseOSError(osLastError()) @@ -125,13 +125,13 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = mev.name = $cstr else: mev.name = "" - - if (event.mask.int and IN_MOVED_FROM) != 0: + + if (event.mask.int and IN_MOVED_FROM) != 0: # Moved from event, add to m's collection movedFrom.add(event.cookie.cint, (mev.wd, mev.name)) inc(i, sizeof(INotifyEvent) + event.len.int) continue - elif (event.mask.int and IN_MOVED_TO) != 0: + elif (event.mask.int and IN_MOVED_TO) != 0: mev.kind = MonitorMoved assert movedFrom.hasKey(event.cookie.cint) # Find the MovedFrom event. @@ -141,23 +141,23 @@ proc getEvent(m: FSMonitor, fd: cint): seq[MonitorEvent] = movedFrom.del(event.cookie.cint) elif (event.mask.int and IN_ACCESS) != 0: mev.kind = MonitorAccess elif (event.mask.int and IN_ATTRIB) != 0: mev.kind = MonitorAttrib - elif (event.mask.int and IN_CLOSE_WRITE) != 0: + elif (event.mask.int and IN_CLOSE_WRITE) != 0: mev.kind = MonitorCloseWrite - elif (event.mask.int and IN_CLOSE_NOWRITE) != 0: + elif (event.mask.int and IN_CLOSE_NOWRITE) != 0: mev.kind = MonitorCloseNoWrite elif (event.mask.int and IN_CREATE) != 0: mev.kind = MonitorCreate - elif (event.mask.int and IN_DELETE) != 0: + elif (event.mask.int and IN_DELETE) != 0: mev.kind = MonitorDelete - elif (event.mask.int and IN_DELETE_SELF) != 0: + elif (event.mask.int and IN_DELETE_SELF) != 0: mev.kind = MonitorDeleteSelf elif (event.mask.int and IN_MODIFY) != 0: mev.kind = MonitorModify - elif (event.mask.int and IN_MOVE_SELF) != 0: + elif (event.mask.int and IN_MOVE_SELF) != 0: mev.kind = MonitorMoveSelf elif (event.mask.int and IN_OPEN) != 0: mev.kind = MonitorOpen - + if mev.kind != MonitorMoved: mev.fullname = "" - + result.add(mev) inc(i, sizeof(INotifyEvent) + event.len.int) @@ -211,7 +211,7 @@ when not defined(testing) and isMainModule: echo("Name is ", ev.name) else: echo("Name ", ev.name, " fullname ", ev.fullName)) - + while true: if not disp.poll(): break main() diff --git a/lib/pure/httpserver.nim b/lib/pure/httpserver.nim index 981891227..71ba04991 100644 --- a/lib/pure/httpserver.nim +++ b/lib/pure/httpserver.nim @@ -142,7 +142,7 @@ when false: if meth == reqPost: # get from client and post to CGI program: var buf = alloc(contentLength) - if recv(client, buf, contentLength) != contentLength: + if recv(client, buf, contentLength) != contentLength: dealloc(buf) raiseOSError() var inp = process.inputStream @@ -177,7 +177,7 @@ when false: else: path = "." & data[1] # path starts with "/", by adding "." in front of it we serve files from cwd - + if cmpIgnoreCase(data[0], "GET") == 0: if q >= 0: cgi = true @@ -218,12 +218,12 @@ type headers*: StringTableRef ## headers with which the client made the request body*: string ## only set with POST requests ip*: string ## ip address of the requesting client - + PAsyncHTTPServer* = ref AsyncHTTPServer AsyncHTTPServer = object of Server asyncSocket: AsyncSocket {.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].} - + proc open*(s: var Server, port = Port(80), reuseAddr = false) = ## creates a new server at port `port`. If ``port == 0`` a free port is ## acquired that can be accessed later by the ``port`` proc. @@ -262,7 +262,7 @@ proc next*(s: var Server) = var data = "" s.client.readLine(data) if data == "": - # Socket disconnected + # Socket disconnected s.client.close() next(s) return @@ -283,9 +283,9 @@ proc next*(s: var Server) = s.client.close() next(s) return - + var i = skipWhitespace(data) - if skipIgnoreCase(data, "GET") > 0: + if skipIgnoreCase(data, "GET") > 0: s.reqMethod = "GET" inc(i, 3) elif skipIgnoreCase(data, "POST") > 0: @@ -296,7 +296,7 @@ proc next*(s: var Server) = s.client.close() next(s) return - + if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): @@ -304,7 +304,7 @@ proc next*(s: var Server) = s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") - + # Read the body # - Check for Content-length header if s.headers.hasKey("Content-Length"): @@ -340,13 +340,13 @@ proc next*(s: var Server) = s.client.close() next(s) return - + var L = skipWhitespace(data, i) inc(i, L) # XXX we ignore "HTTP/1.1" etc. for now here var query = 0 var last = i - while last < data.len and data[last] notin Whitespace: + while last < data.len and data[last] notin Whitespace: if data[last] == '?' and query == 0: query = last inc(last) if query > 0: @@ -360,7 +360,7 @@ proc close*(s: Server) = ## closes the server (and the socket the server uses). close(s.socket) -proc run*(handleRequest: proc (client: Socket, +proc run*(handleRequest: proc (client: Socket, path, query: string): bool {.closure.}, port = Port(80)) = ## encapsulates the server object and main loop @@ -388,7 +388,7 @@ proc nextAsync(s: PAsyncHTTPServer) = var data = "" s.client.readLine(data) if data == "": - # Socket disconnected + # Socket disconnected s.client.close() return var header = "" @@ -408,9 +408,9 @@ proc nextAsync(s: PAsyncHTTPServer) = else: s.client.close() return - + var i = skipWhitespace(data) - if skipIgnoreCase(data, "GET") > 0: + if skipIgnoreCase(data, "GET") > 0: s.reqMethod = "GET" inc(i, 3) elif skipIgnoreCase(data, "POST") > 0: @@ -420,7 +420,7 @@ proc nextAsync(s: PAsyncHTTPServer) = unimplemented(s.client) s.client.close() return - + if s.reqMethod == "POST": # Check for Expect header if s.headers.hasKey("Expect"): @@ -428,7 +428,7 @@ proc nextAsync(s: PAsyncHTTPServer) = s.client.sendStatus("100 Continue") else: s.client.sendStatus("417 Expectation Failed") - + # Read the body # - Check for Content-length header if s.headers.hasKey("Content-Length"): @@ -460,13 +460,13 @@ proc nextAsync(s: PAsyncHTTPServer) = badRequest(s.client) s.client.close() return - + var L = skipWhitespace(data, i) inc(i, L) # XXX we ignore "HTTP/1.1" etc. for now here var query = 0 var last = i - while last < data.len and data[last] notin Whitespace: + while last < data.len and data[last] notin Whitespace: if data[last] == '?' and query == 0: query = last inc(last) if query > 0: @@ -476,7 +476,7 @@ proc nextAsync(s: PAsyncHTTPServer) = s.query = "" s.path = data.substr(i, last-1) -proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Socket, +proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Socket, path, query: string): bool {.closure, gcsafe.}, port = Port(80), address = "", reuseAddr = false): PAsyncHTTPServer = @@ -492,14 +492,14 @@ proc asyncHTTPServer*(handleRequest: proc (server: PAsyncHTTPServer, client: Soc if quit: capturedRet.asyncSocket.close() if reuseAddr: capturedRet.asyncSocket.setSockOpt(OptReuseAddr, true) - + capturedRet.asyncSocket.bindAddr(port, address) capturedRet.asyncSocket.listen() if port == Port(0): capturedRet.port = getSockName(capturedRet.asyncSocket) else: capturedRet.port = port - + capturedRet.client = invalidSocket capturedRet.reqMethod = "" capturedRet.body = "" @@ -524,11 +524,11 @@ when not defined(testing) and isMainModule: echo("httpserver running on port ", s.port) while true: next(s) - + inc(counter) s.client.send("Hello, Andreas, for the $#th time. $# ? $#" % [ $counter, s.path, s.query] & wwwNL) - + close(s.client) close(s) diff --git a/lib/pure/matchers.nim b/lib/pure/matchers.nim index d55963c15..5c28f65a0 100644 --- a/lib/pure/matchers.nim +++ b/lib/pure/matchers.nim @@ -18,15 +18,15 @@ include "system/inclrtl" import parseutils, strutils proc validEmailAddress*(s: string): bool {.noSideEffect, - rtl, extern: "nsuValidEmailAddress".} = - ## returns true if `s` seems to be a valid e-mail address. + rtl, extern: "nsuValidEmailAddress".} = + ## returns true if `s` seems to be a valid e-mail address. ## The checking also uses a domain list. const chars = Letters + Digits + {'!','#','$','%','&', '\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'} var i = 0 if s[i] notin chars or s[i] == '.': return false - while s[i] in chars: + while s[i] in chars: if s[i] == '.' and s[i+1] == '.': return false inc(i) if s[i] != '@': return false @@ -34,9 +34,9 @@ proc validEmailAddress*(s: string): bool {.noSideEffect, if s[j] notin Letters: return false while j >= i and s[j] in Letters: dec(j) inc(i) # skip '@' - while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) + while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i) if s[i] != '\0': return false - + var x = substr(s, j+1) if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true case toLower(x) @@ -59,6 +59,6 @@ proc parseInt*(s: string, value: var int, validRange: Slice[int]) {. when isMainModule: doAssert "wuseldusel@codehome.com".validEmailAddress - + {.pop.} diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 00929eaa2..27b989597 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -33,7 +33,7 @@ type when defined(windows): fHandle: int - mapHandle: int + mapHandle: int else: handle: cint @@ -131,7 +131,7 @@ proc open*(filename: string, mode: FileMode = fmRead, fail(osLastError(), "error opening file") if newFileSize != -1: - var + var sizeHigh = int32(newFileSize shr 32) sizeLow = int32(newFileSize and 0xffffffff) @@ -177,7 +177,7 @@ proc open*(filename: string, mode: FileMode = fmRead, rollback() if result.handle != 0: discard close(result.handle) raiseOSError(errCode) - + var flags = if readonly: O_RDONLY else: O_RDWR if newFileSize != -1: @@ -221,7 +221,7 @@ proc open*(filename: string, mode: FileMode = fmRead, proc close*(f: var MemFile) = ## closes the memory mapped file `f`. All changes are written back to the ## file system, if `f` was opened with write access. - + var error = false var lastErr: OSErrorCode @@ -245,7 +245,7 @@ proc close*(f: var MemFile) = f.mapHandle = 0 else: f.handle = 0 - + if error: raiseOSError(lastErr) type MemSlice* = object ## represent slice of a MemFile for iteration over delimited lines/records diff --git a/lib/pure/mersenne.nim b/lib/pure/mersenne.nim index 74112e304..c8090dc6a 100644 --- a/lib/pure/mersenne.nim +++ b/lib/pure/mersenne.nim @@ -7,7 +7,7 @@ type {.deprecated: [TMersenneTwister: MersenneTwister].} -proc newMersenneTwister*(seed: int): MersenneTwister = +proc newMersenneTwister*(seed: int): MersenneTwister = result.index = 0 result.mt[0]= uint32(seed) for i in 1..623'u32: diff --git a/lib/pure/numeric.nim b/lib/pure/numeric.nim index 9b298c0a0..71adf19b3 100644 --- a/lib/pure/numeric.nim +++ b/lib/pure/numeric.nim @@ -11,23 +11,23 @@ type OneVarFunction* = proc (x: float): float {.deprecated: [TOneVarFunction: OneVarFunction].} -proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000): +proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000): tuple[rootx, rooty: float, success: bool]= - ## Searches `function` for a root between `xmin` and `xmax` + ## Searches `function` for a root between `xmin` and `xmax` ## using brents method. If the function value at `xmin`and `xmax` has the ## same sign, `rootx`/`rooty` is set too the extrema value closest to x-axis ## and succes is set to false. ## Otherwise there exists at least one root and success is set to true. ## This root is searched for at most `maxiter` iterations. - ## If `tol` tolerance is reached within `maxiter` iterations + ## If `tol` tolerance is reached within `maxiter` iterations ## the root refinement stops and success=true. # see http://en.wikipedia.org/wiki/Brent%27s_method - var + var a=xmin b=xmax c=a - d=1.0e308 + d=1.0e308 fa=function(a) fb=function(b) fc=fa @@ -42,19 +42,19 @@ proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000): return (a,fa,false) else: return (b,fb,false) - + if abs(fa)<abs(fb): swap(fa,fb) swap(a,b) - + while fb!=0.0 and abs(a-b)>tol: if fa!=fc and fb!=fc: # inverse quadratic interpolation s = a * fb * fc / (fa - fb) / (fa - fc) + b * fa * fc / (fb - fa) / (fb - fc) + c * fa * fb / (fc - fa) / (fc - fb) else: #secant rule s = b - fb * (b - a) / (fb - fa) tmp2 = (3.0 * a + b) / 4.0 - if not((s > tmp2 and s < b) or (s < tmp2 and s > b)) or - (mflag and abs(s - b) >= (abs(b - c) / 2.0)) or + if not((s > tmp2 and s < b) or (s < tmp2 and s > b)) or + (mflag and abs(s - b) >= (abs(b - c) / 2.0)) or (not mflag and abs(s - b) >= abs(c - d) / 2.0): s=(a+b)/2.0 mflag=true @@ -80,5 +80,5 @@ proc brent*(xmin,xmax:float, function:OneVarFunction, tol:float,maxiter=1000): inc i if i>maxiter: break - + return (b,fb,true) diff --git a/lib/pure/oids.nim b/lib/pure/oids.nim index ac90dd16b..174922223 100644 --- a/lib/pure/oids.nim +++ b/lib/pure/oids.nim @@ -8,7 +8,7 @@ # ## Nim OID support. An OID is a global ID that consists of a timestamp, -## a unique counter and a random value. This combination should suffice to +## a unique counter and a random value. This combination should suffice to ## produce a globally distributed unique ID. This implementation was extracted ## from the Mongodb interface and it thus binary compatible with a Mongo OID. ## @@ -19,13 +19,13 @@ import times, endians type Oid* = object ## an OID - time: int32 ## - fuzz: int32 ## - count: int32 ## + time: int32 ## + fuzz: int32 ## + count: int32 ## {.deprecated: [Toid: Oid].} -proc hexbyte*(hex: char): int = +proc hexbyte*(hex: char): int = case hex of '0'..'9': result = (ord(hex) - ord('0')) of 'a'..'f': result = (ord(hex) - ord('a') + 10) @@ -40,7 +40,7 @@ proc parseOid*(str: cstring): Oid = bytes[i] = chr((hexbyte(str[2 * i]) shl 4) or hexbyte(str[2 * i + 1])) inc(i) -proc oidToString*(oid: Oid, str: cstring) = +proc oidToString*(oid: Oid, str: cstring) = const hex = "0123456789abcdef" # work around a compiler bug: var str = str @@ -59,7 +59,7 @@ proc `$`*(oid: Oid): string = oidToString(oid, result) var - incr: int + incr: int fuzz: int32 proc genOid*(): Oid = @@ -69,10 +69,10 @@ proc genOid*(): Oid = proc srand(seed: cint) {.importc: "srand", header: "<stdlib.h>", nodecl.} var t = gettime(nil) - + var i = int32(incr) atomicInc(incr) - + if fuzz == 0: # racy, but fine semantically: srand(t) diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index bb64c8134..f680d4fef 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -7,17 +7,17 @@ # distribution, for details about the copyright. # -## The ``parsecfg`` module implements a high performance configuration file -## parser. The configuration file's syntax is similar to the Windows ``.ini`` -## format, but much more powerful, as it is not a line based parser. String -## literals, raw string literals and triple quoted string literals are supported +## The ``parsecfg`` module implements a high performance configuration file +## parser. The configuration file's syntax is similar to the Windows ``.ini`` +## format, but much more powerful, as it is not a line based parser. String +## literals, raw string literals and triple quoted string literals are supported ## as in the Nim programming language. ## This is an example of how a configuration file may look like: ## ## .. include:: doc/mytest.cfg ## :literal: -## The file ``examples/parsecfgex.nim`` demonstrates how to use the +## The file ``examples/parsecfgex.nim`` demonstrates how to use the ## configuration file parser: ## ## .. code-block:: nim @@ -36,14 +36,14 @@ type cfgKeyValuePair, ## a ``key=value`` pair has been detected cfgOption, ## a ``--key=value`` command line option cfgError ## an error occurred during parsing - + CfgEvent* = object of RootObj ## describes a parsing event case kind*: CfgEventKind ## the kind of the event of cfgEof: nil - of cfgSectionStart: - section*: string ## `section` contains the name of the + of cfgSectionStart: + section*: string ## `section` contains the name of the ## parsed section start (syntax: ``[section]``) - of cfgKeyValuePair, cfgOption: + of cfgKeyValuePair, cfgOption: key*, value*: string ## contains the (key, value) pair if an option ## of the form ``--key: value`` or an ordinary ## ``key= value`` pair has been parsed. @@ -52,14 +52,14 @@ type of cfgError: ## the parser encountered an error: `msg` msg*: string ## contains the error message. No exceptions ## are thrown if a parse error occurs. - - TokKind = enum - tkInvalid, tkEof, + + TokKind = enum + tkInvalid, tkEof, tkSymbol, tkEquals, tkColon, tkBracketLe, tkBracketRi, tkDashDash Token = object # a token kind: TokKind # the type of the token literal: string # the parsed (string) literal - + CfgParser* = object of BaseLexer ## the parser object. tok: Token filename: string @@ -69,12 +69,12 @@ type # implementation -const - SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', '/', '\\'} - +const + SymChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\x80'..'\xFF', '.', '/', '\\'} + proc rawGetTok(c: var CfgParser, tok: var Token) {.gcsafe.} -proc open*(c: var CfgParser, input: Stream, filename: string, +proc open*(c: var CfgParser, input: Stream, filename: string, lineOffset = 0) {.rtl, extern: "npc$1".} = ## initializes the parser with an input stream. `Filename` is only used ## for nice error messages. `lineOffset` can be used to influence the line @@ -85,7 +85,7 @@ proc open*(c: var CfgParser, input: Stream, filename: string, c.tok.literal = "" inc(c.lineNumber, lineOffset) rawGetTok(c, c.tok) - + proc close*(c: var CfgParser) {.rtl, extern: "npc$1".} = ## closes the parser `c` and its associated input stream. lexbase.close(c) @@ -102,260 +102,260 @@ proc getFilename*(c: CfgParser): string {.rtl, extern: "npc$1".} = ## get the filename of the file that the parser processes. result = c.filename -proc handleHexChar(c: var CfgParser, xi: var int) = +proc handleHexChar(c: var CfgParser, xi: var int) = case c.buf[c.bufpos] - of '0'..'9': + of '0'..'9': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) inc(c.bufpos) - of 'a'..'f': + of 'a'..'f': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10) inc(c.bufpos) - of 'A'..'F': + of 'A'..'F': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) inc(c.bufpos) - else: + else: discard -proc handleDecChars(c: var CfgParser, xi: var int) = - while c.buf[c.bufpos] in {'0'..'9'}: +proc handleDecChars(c: var CfgParser, xi: var int) = + while c.buf[c.bufpos] in {'0'..'9'}: xi = (xi * 10) + (ord(c.buf[c.bufpos]) - ord('0')) inc(c.bufpos) -proc getEscapedChar(c: var CfgParser, tok: var Token) = +proc getEscapedChar(c: var CfgParser, tok: var Token) = inc(c.bufpos) # skip '\' case c.buf[c.bufpos] - of 'n', 'N': + of 'n', 'N': add(tok.literal, "\n") inc(c.bufpos) - of 'r', 'R', 'c', 'C': + of 'r', 'R', 'c', 'C': add(tok.literal, '\c') inc(c.bufpos) - of 'l', 'L': + of 'l', 'L': add(tok.literal, '\L') inc(c.bufpos) - of 'f', 'F': + of 'f', 'F': add(tok.literal, '\f') inc(c.bufpos) - of 'e', 'E': + of 'e', 'E': add(tok.literal, '\e') inc(c.bufpos) - of 'a', 'A': + of 'a', 'A': add(tok.literal, '\a') inc(c.bufpos) - of 'b', 'B': + of 'b', 'B': add(tok.literal, '\b') inc(c.bufpos) - of 'v', 'V': + of 'v', 'V': add(tok.literal, '\v') inc(c.bufpos) - of 't', 'T': + of 't', 'T': add(tok.literal, '\t') inc(c.bufpos) - of '\'', '"': + of '\'', '"': add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) - of '\\': + of '\\': add(tok.literal, '\\') inc(c.bufpos) - of 'x', 'X': + of 'x', 'X': inc(c.bufpos) var xi = 0 handleHexChar(c, xi) handleHexChar(c, xi) add(tok.literal, chr(xi)) - of '0'..'9': + of '0'..'9': var xi = 0 handleDecChars(c, xi) if (xi <= 255): add(tok.literal, chr(xi)) else: tok.kind = tkInvalid else: tok.kind = tkInvalid - -proc handleCRLF(c: var CfgParser, pos: int): int = + +proc handleCRLF(c: var CfgParser, pos: int): int = case c.buf[pos] of '\c': result = lexbase.handleCR(c, pos) of '\L': result = lexbase.handleLF(c, pos) else: result = pos - -proc getString(c: var CfgParser, tok: var Token, rawMode: bool) = + +proc getString(c: var CfgParser, tok: var Token, rawMode: bool) = var pos = c.bufpos + 1 # skip " var buf = c.buf # put `buf` in a register tok.kind = tkSymbol - if (buf[pos] == '"') and (buf[pos + 1] == '"'): + if (buf[pos] == '"') and (buf[pos + 1] == '"'): # long string literal: inc(pos, 2) # skip "" # skip leading newline: pos = handleCRLF(c, pos) buf = c.buf - while true: + while true: case buf[pos] - of '"': - if (buf[pos + 1] == '"') and (buf[pos + 2] == '"'): break + of '"': + if (buf[pos + 1] == '"') and (buf[pos + 2] == '"'): break add(tok.literal, '"') inc(pos) - of '\c', '\L': + of '\c', '\L': pos = handleCRLF(c, pos) buf = c.buf add(tok.literal, "\n") - of lexbase.EndOfFile: + of lexbase.EndOfFile: tok.kind = tkInvalid - break - else: + break + else: add(tok.literal, buf[pos]) inc(pos) c.bufpos = pos + 3 # skip the three """ - else: + else: # ordinary string literal - while true: + while true: var ch = buf[pos] - if ch == '"': + if ch == '"': inc(pos) # skip '"' - break - if ch in {'\c', '\L', lexbase.EndOfFile}: + break + if ch in {'\c', '\L', lexbase.EndOfFile}: tok.kind = tkInvalid - break - if (ch == '\\') and not rawMode: + break + if (ch == '\\') and not rawMode: c.bufpos = pos getEscapedChar(c, tok) pos = c.bufpos - else: + else: add(tok.literal, ch) inc(pos) c.bufpos = pos -proc getSymbol(c: var CfgParser, tok: var Token) = +proc getSymbol(c: var CfgParser, tok: var Token) = var pos = c.bufpos var buf = c.buf - while true: + while true: add(tok.literal, buf[pos]) inc(pos) - if not (buf[pos] in SymChars): break + if not (buf[pos] in SymChars): break c.bufpos = pos tok.kind = tkSymbol -proc skip(c: var CfgParser) = +proc skip(c: var CfgParser) = var pos = c.bufpos var buf = c.buf - while true: + while true: case buf[pos] - of ' ', '\t': + of ' ', '\t': inc(pos) - of '#', ';': + of '#', ';': while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos) - of '\c', '\L': + of '\c', '\L': pos = handleCRLF(c, pos) buf = c.buf - else: + else: break # EndOfFile also leaves the loop c.bufpos = pos -proc rawGetTok(c: var CfgParser, tok: var Token) = +proc rawGetTok(c: var CfgParser, tok: var Token) = tok.kind = tkInvalid setLen(tok.literal, 0) skip(c) case c.buf[c.bufpos] - of '=': + of '=': tok.kind = tkEquals inc(c.bufpos) tok.literal = "=" - of '-': + of '-': inc(c.bufpos) if c.buf[c.bufpos] == '-': inc(c.bufpos) tok.kind = tkDashDash tok.literal = "--" - of ':': + of ':': tok.kind = tkColon inc(c.bufpos) tok.literal = ":" - of 'r', 'R': - if c.buf[c.bufpos + 1] == '\"': + of 'r', 'R': + if c.buf[c.bufpos + 1] == '\"': inc(c.bufpos) getString(c, tok, true) - else: + else: getSymbol(c, tok) - of '[': + of '[': tok.kind = tkBracketLe inc(c.bufpos) tok.literal = "]" - of ']': + of ']': tok.kind = tkBracketRi inc(c.bufpos) tok.literal = "]" - of '"': + of '"': getString(c, tok, false) - of lexbase.EndOfFile: + of lexbase.EndOfFile: tok.kind = tkEof tok.literal = "[EOF]" else: getSymbol(c, tok) - + proc errorStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = ## returns a properly formated error message containing current line and ## column information. - result = `%`("$1($2, $3) Error: $4", + result = `%`("$1($2, $3) Error: $4", [c.filename, $getLine(c), $getColumn(c), msg]) - + proc warningStr*(c: CfgParser, msg: string): string {.rtl, extern: "npc$1".} = ## returns a properly formated warning message containing current line and ## column information. - result = `%`("$1($2, $3) Warning: $4", + result = `%`("$1($2, $3) Warning: $4", [c.filename, $getLine(c), $getColumn(c), msg]) proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} = ## returns a properly formated warning message containing that ## an entry is ignored. - case e.kind + case e.kind of cfgSectionStart: result = c.warningStr("section ignored: " & e.section) of cfgKeyValuePair: result = c.warningStr("key ignored: " & e.key) - of cfgOption: + of cfgOption: result = c.warningStr("command ignored: " & e.key & ": " & e.value) of cfgError: result = e.msg of cfgEof: result = "" -proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = - if c.tok.kind == tkSymbol: +proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = + if c.tok.kind == tkSymbol: result.kind = kind result.key = c.tok.literal result.value = "" rawGetTok(c, c.tok) - if c.tok.kind in {tkEquals, tkColon}: + if c.tok.kind in {tkEquals, tkColon}: rawGetTok(c, c.tok) - if c.tok.kind == tkSymbol: + if c.tok.kind == tkSymbol: result.value = c.tok.literal - else: + else: reset result result.kind = cfgError result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) rawGetTok(c, c.tok) - else: + else: result.kind = cfgError result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) rawGetTok(c, c.tok) proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = ## retrieves the first/next event. This controls the parser. - case c.tok.kind - of tkEof: + case c.tok.kind + of tkEof: result.kind = cfgEof - of tkDashDash: + of tkDashDash: rawGetTok(c, c.tok) result = getKeyValPair(c, cfgOption) - of tkSymbol: + of tkSymbol: result = getKeyValPair(c, cfgKeyValuePair) - of tkBracketLe: + of tkBracketLe: rawGetTok(c, c.tok) - if c.tok.kind == tkSymbol: + if c.tok.kind == tkSymbol: result.kind = cfgSectionStart result.section = c.tok.literal - else: + else: result.kind = cfgError result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) rawGetTok(c, c.tok) - if c.tok.kind == tkBracketRi: + if c.tok.kind == tkBracketRi: rawGetTok(c, c.tok) else: reset(result) result.kind = cfgError result.msg = errorStr(c, "']' expected, but found: " & c.tok.literal) - of tkInvalid, tkEquals, tkColon, tkBracketRi: + of tkInvalid, tkEquals, tkColon, tkBracketRi: result.kind = cfgError result.msg = errorStr(c, "invalid token: " & c.tok.literal) rawGetTok(c, c.tok) diff --git a/lib/pure/parsecsv.nim b/lib/pure/parsecsv.nim index 117d75cfa..af51e1201 100644 --- a/lib/pure/parsecsv.nim +++ b/lib/pure/parsecsv.nim @@ -8,7 +8,7 @@ # ## This module implements a simple high performance `CSV`:idx: -## (`comma separated value`:idx:) parser. +## (`comma separated value`:idx:) parser. ## ## Example: How to use the parser ## ============================== @@ -43,7 +43,7 @@ type {.deprecated: [TCsvRow: CsvRow, TCsvParser: CsvParser, EInvalidCsv: CsvError].} -proc raiseEInvalidCsv(filename: string, line, col: int, +proc raiseEInvalidCsv(filename: string, line, col: int, msg: string) {.noreturn.} = var e: ref CsvError new(e) @@ -60,13 +60,13 @@ proc open*(my: var CsvParser, input: Stream, filename: string, ## for nice error messages. The parser's behaviour can be controlled by ## the diverse optional parameters: ## - `separator`: character used to separate fields - ## - `quote`: Used to quote fields containing special characters like + ## - `quote`: Used to quote fields containing special characters like ## `separator`, `quote` or new-line characters. '\0' disables the parsing ## of quotes. - ## - `escape`: removes any special meaning from the following character; + ## - `escape`: removes any special meaning from the following character; ## '\0' disables escaping; if escaping is disabled and `quote` is not '\0', ## two `quote` characters are parsed one literal `quote` character. - ## - `skipInitialSpace`: If true, whitespace immediately following the + ## - `skipInitialSpace`: If true, whitespace immediately following the ## `separator` is ignored. lexbase.open(my, input) my.filename = filename @@ -77,13 +77,13 @@ proc open*(my: var CsvParser, input: Stream, filename: string, my.row = @[] my.currRow = 0 -proc parseField(my: var CsvParser, a: var string) = +proc parseField(my: var CsvParser, a: var string) = var pos = my.bufpos var buf = my.buf if my.skipWhite: while buf[pos] in {' ', '\t'}: inc(pos) setLen(a, 0) # reuse memory - if buf[pos] == my.quote and my.quote != '\0': + if buf[pos] == my.quote and my.quote != '\0': inc(pos) while true: var c = buf[pos] @@ -91,7 +91,7 @@ proc parseField(my: var CsvParser, a: var string) = my.bufpos = pos # can continue after exception? error(my, pos, my.quote & " expected") break - elif c == my.quote: + elif c == my.quote: if my.esc == '\0' and buf[pos+1] == my.quote: add(a, my.quote) inc(pos, 2) @@ -103,11 +103,11 @@ proc parseField(my: var CsvParser, a: var string) = inc(pos, 2) else: case c - of '\c': + of '\c': pos = handleCR(my, pos) buf = my.buf add(a, "\n") - of '\l': + of '\l': pos = handleLF(my, pos) buf = my.buf add(a, "\n") @@ -123,11 +123,11 @@ proc parseField(my: var CsvParser, a: var string) = inc(pos) my.bufpos = pos -proc processedRows*(my: var CsvParser): int = +proc processedRows*(my: var CsvParser): int = ## returns number of the processed rows return my.currRow -proc readRow*(my: var CsvParser, columns = 0): bool = +proc readRow*(my: var CsvParser, columns = 0): bool = ## reads the next row; if `columns` > 0, it expects the row to have ## exactly this many columns. Returns false if the end of the file ## has been encountered else true. @@ -140,13 +140,13 @@ proc readRow*(my: var CsvParser, columns = 0): bool = my.row[col] = "" parseField(my, my.row[col]) inc(col) - if my.buf[my.bufpos] == my.sep: + if my.buf[my.bufpos] == my.sep: inc(my.bufpos) else: case my.buf[my.bufpos] - of '\c', '\l': + of '\c', '\l': # skip empty lines: - while true: + while true: case my.buf[my.bufpos] of '\c': my.bufpos = handleCR(my, my.bufpos) of '\l': my.bufpos = handleLF(my, my.bufpos) @@ -154,15 +154,15 @@ proc readRow*(my: var CsvParser, columns = 0): bool = of '\0': discard else: error(my, my.bufpos, my.sep & " expected") break - + setLen(my.row, col) result = col > 0 - if result and col != columns and columns > 0: - error(my, oldpos+1, $columns & " columns expected, but found " & + if result and col != columns and columns > 0: + error(my, oldpos+1, $columns & " columns expected, but found " & $col & " columns") inc(my.currRow) - -proc close*(my: var CsvParser) {.inline.} = + +proc close*(my: var CsvParser) {.inline.} = ## closes the parser `my` and its associated input stream. lexbase.close(my) diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim index cfa60094d..d6fafec08 100644 --- a/lib/pure/parsesql.nim +++ b/lib/pure/parsesql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## The ``parsesql`` module implements a high performance SQL file +## The ``parsesql`` module implements a high performance SQL file ## parser. It parses PostgreSQL syntax and the SQL ANSI standard. import @@ -37,11 +37,11 @@ type tkBracketLe, ## '[' tkBracketRi, ## ']' tkDot ## '.' - + Token = object # a token kind: TokKind # the type of the token literal: string # the parsed (string) literal - + SqlLexer* = object of BaseLexer ## the parser object. filename: string @@ -55,82 +55,82 @@ const ";", ":", ",", "(", ")", "[", "]", "." ] -proc open(L: var SqlLexer, input: Stream, filename: string) = +proc open(L: var SqlLexer, input: Stream, filename: string) = lexbase.open(L, input) L.filename = filename - -proc close(L: var SqlLexer) = + +proc close(L: var SqlLexer) = lexbase.close(L) -proc getColumn(L: SqlLexer): int = +proc getColumn(L: SqlLexer): int = ## get the current column the parser has arrived at. result = getColNumber(L, L.bufpos) -proc getLine(L: SqlLexer): int = +proc getLine(L: SqlLexer): int = result = L.lineNumber -proc handleHexChar(c: var SqlLexer, xi: var int) = +proc handleHexChar(c: var SqlLexer, xi: var int) = case c.buf[c.bufpos] - of '0'..'9': + of '0'..'9': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('0')) inc(c.bufpos) - of 'a'..'f': + of 'a'..'f': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('a') + 10) inc(c.bufpos) - of 'A'..'F': + of 'A'..'F': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) inc(c.bufpos) - else: + else: discard -proc handleOctChar(c: var SqlLexer, xi: var int) = +proc handleOctChar(c: var SqlLexer, xi: var int) = if c.buf[c.bufpos] in {'0'..'7'}: xi = (xi shl 3) or (ord(c.buf[c.bufpos]) - ord('0')) inc(c.bufpos) -proc getEscapedChar(c: var SqlLexer, tok: var Token) = +proc getEscapedChar(c: var SqlLexer, tok: var Token) = inc(c.bufpos) case c.buf[c.bufpos] - of 'n', 'N': + of 'n', 'N': add(tok.literal, '\L') inc(c.bufpos) - of 'r', 'R', 'c', 'C': + of 'r', 'R', 'c', 'C': add(tok.literal, '\c') inc(c.bufpos) - of 'l', 'L': + of 'l', 'L': add(tok.literal, '\L') inc(c.bufpos) - of 'f', 'F': + of 'f', 'F': add(tok.literal, '\f') inc(c.bufpos) - of 'e', 'E': + of 'e', 'E': add(tok.literal, '\e') inc(c.bufpos) - of 'a', 'A': + of 'a', 'A': add(tok.literal, '\a') inc(c.bufpos) - of 'b', 'B': + of 'b', 'B': add(tok.literal, '\b') inc(c.bufpos) - of 'v', 'V': + of 'v', 'V': add(tok.literal, '\v') inc(c.bufpos) - of 't', 'T': + of 't', 'T': add(tok.literal, '\t') inc(c.bufpos) - of '\'', '\"': + of '\'', '\"': add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) - of '\\': + of '\\': add(tok.literal, '\\') inc(c.bufpos) - of 'x', 'X': + of 'x', 'X': inc(c.bufpos) var xi = 0 handleHexChar(c, xi) handleHexChar(c, xi) add(tok.literal, chr(xi)) - of '0'..'7': + of '0'..'7': var xi = 0 handleOctChar(c, xi) handleOctChar(c, xi) @@ -138,20 +138,20 @@ proc getEscapedChar(c: var SqlLexer, tok: var Token) = if (xi <= 255): add(tok.literal, chr(xi)) else: tok.kind = tkInvalid else: tok.kind = tkInvalid - -proc handleCRLF(c: var SqlLexer, pos: int): int = + +proc handleCRLF(c: var SqlLexer, pos: int): int = case c.buf[pos] of '\c': result = lexbase.handleCR(c, pos) of '\L': result = lexbase.handleLF(c, pos) else: result = pos -proc skip(c: var SqlLexer) = +proc skip(c: var SqlLexer) = var pos = c.bufpos var buf = c.buf var nested = 0 - while true: + while true: case buf[pos] - of ' ', '\t': + of ' ', '\t': inc(pos) of '-': if buf[pos+1] == '-': @@ -164,7 +164,7 @@ proc skip(c: var SqlLexer) = while true: case buf[pos] of '\0': break - of '\c', '\L': + of '\c', '\L': pos = handleCRLF(c, pos) buf = c.buf of '*': @@ -182,20 +182,20 @@ proc skip(c: var SqlLexer) = inc(pos) else: inc(pos) else: break - of '\c', '\L': + of '\c', '\L': pos = handleCRLF(c, pos) buf = c.buf - else: + else: break # EndOfFile also leaves the loop c.bufpos = pos - -proc getString(c: var SqlLexer, tok: var Token, kind: TokKind) = + +proc getString(c: var SqlLexer, tok: var Token, kind: TokKind) = var pos = c.bufpos + 1 var buf = c.buf tok.kind = kind block parseLoop: while true: - while true: + while true: var ch = buf[pos] if ch == '\'': if buf[pos+1] == '\'': @@ -203,15 +203,15 @@ proc getString(c: var SqlLexer, tok: var Token, kind: TokKind) = add(tok.literal, '\'') else: inc(pos) - break - elif ch in {'\c', '\L', lexbase.EndOfFile}: + break + elif ch in {'\c', '\L', lexbase.EndOfFile}: tok.kind = tkInvalid break parseLoop - elif (ch == '\\') and kind == tkEscapeConstant: + elif (ch == '\\') and kind == tkEscapeConstant: c.bufpos = pos getEscapedChar(c, tok) pos = c.bufpos - else: + else: add(tok.literal, ch) inc(pos) c.bufpos = pos @@ -227,7 +227,7 @@ proc getString(c: var SqlLexer, tok: var Token, kind: TokKind) = else: break parseLoop c.bufpos = pos -proc getDollarString(c: var SqlLexer, tok: var Token) = +proc getDollarString(c: var SqlLexer, tok: var Token) = var pos = c.bufpos + 1 var buf = c.buf tok.kind = tkDollarQuotedConstant @@ -241,7 +241,7 @@ proc getDollarString(c: var SqlLexer, tok: var Token) = return while true: case buf[pos] - of '\c', '\L': + of '\c', '\L': pos = handleCRLF(c, pos) buf = c.buf add(tok.literal, "\L") @@ -263,10 +263,10 @@ proc getDollarString(c: var SqlLexer, tok: var Token) = inc(pos) c.bufpos = pos -proc getSymbol(c: var SqlLexer, tok: var Token) = +proc getSymbol(c: var SqlLexer, tok: var Token) = var pos = c.bufpos var buf = c.buf - while true: + while true: add(tok.literal, buf[pos]) inc(pos) if buf[pos] notin {'a'..'z','A'..'Z','0'..'9','_','$', '\128'..'\255'}: @@ -274,7 +274,7 @@ proc getSymbol(c: var SqlLexer, tok: var Token) = c.bufpos = pos tok.kind = tkIdentifier -proc getQuotedIdentifier(c: var SqlLexer, tok: var Token) = +proc getQuotedIdentifier(c: var SqlLexer, tok: var Token) = var pos = c.bufpos + 1 var buf = c.buf tok.kind = tkQuotedIdentifier @@ -287,7 +287,7 @@ proc getQuotedIdentifier(c: var SqlLexer, tok: var Token) = else: inc(pos) break - elif ch in {'\c', '\L', lexbase.EndOfFile}: + elif ch in {'\c', '\L', lexbase.EndOfFile}: tok.kind = tkInvalid break else: @@ -300,15 +300,15 @@ proc getBitHexString(c: var SqlLexer, tok: var Token, validChars: set[char]) = var buf = c.buf block parseLoop: while true: - while true: + while true: var ch = buf[pos] if ch in validChars: add(tok.literal, ch) - inc(pos) + inc(pos) elif ch == '\'': inc(pos) break - else: + else: tok.kind = tkInvalid break parseLoop c.bufpos = pos @@ -353,7 +353,7 @@ proc getNumeric(c: var SqlLexer, tok: var Token) = inc(pos) else: tok.kind = tkInvalid - c.bufpos = pos + c.bufpos = pos proc getOperator(c: var SqlLexer, tok: var Token) = const operators = {'+', '-', '*', '/', '<', '>', '=', '~', '!', '@', '#', '%', @@ -381,12 +381,12 @@ proc getOperator(c: var SqlLexer, tok: var Token) = inc(pos) c.bufpos = pos -proc getTok(c: var SqlLexer, tok: var Token) = +proc getTok(c: var SqlLexer, tok: var Token) = tok.kind = tkInvalid setLen(tok.literal, 0) skip(c) case c.buf[c.bufpos] - of ';': + of ';': tok.kind = tkSemicolon inc(c.bufpos) add(tok.literal, ';') @@ -394,15 +394,15 @@ proc getTok(c: var SqlLexer, tok: var Token) = tok.kind = tkComma inc(c.bufpos) add(tok.literal, ',') - of ':': + of ':': tok.kind = tkColon inc(c.bufpos) add(tok.literal, ':') - of 'e', 'E': - if c.buf[c.bufpos + 1] == '\'': + of 'e', 'E': + if c.buf[c.bufpos + 1] == '\'': inc(c.bufpos) getString(c, tok, tkEscapeConstant) - else: + else: getSymbol(c, tok) of 'b', 'B': if c.buf[c.bufpos + 1] == '\'': @@ -417,11 +417,11 @@ proc getTok(c: var SqlLexer, tok: var Token) = else: getSymbol(c, tok) of '$': getDollarString(c, tok) - of '[': + of '[': tok.kind = tkBracketLe inc(c.bufpos) add(tok.literal, '[') - of ']': + of ']': tok.kind = tkBracketRi inc(c.bufpos) add(tok.literal, ']') @@ -433,7 +433,7 @@ proc getTok(c: var SqlLexer, tok: var Token) = tok.kind = tkParRi inc(c.bufpos) add(tok.literal, ')') - of '.': + of '.': if c.buf[c.bufpos + 1] in Digits: getNumeric(c, tok) else: @@ -443,7 +443,7 @@ proc getTok(c: var SqlLexer, tok: var Token) = of '0'..'9': getNumeric(c, tok) of '\'': getString(c, tok, tkStringConstant) of '"': getQuotedIdentifier(c, tok) - of lexbase.EndOfFile: + of lexbase.EndOfFile: tok.kind = tkEof tok.literal = "[EOF]" of 'a', 'c', 'd', 'f'..'w', 'y', 'z', 'A', 'C', 'D', 'F'..'W', 'Y', 'Z', '_', @@ -455,8 +455,8 @@ proc getTok(c: var SqlLexer, tok: var Token) = else: add(tok.literal, c.buf[c.bufpos]) inc(c.bufpos) - -proc errorStr(L: SqlLexer, msg: string): string = + +proc errorStr(L: SqlLexer, msg: string): string = result = "$1($2, $3) Error: $4" % [L.filename, $getLine(L), $getColumn(L), msg] @@ -496,7 +496,7 @@ type nkPrimaryKey, nkForeignKey, nkNotNull, - + nkStmtList, nkDot, nkDotDot, @@ -530,13 +530,13 @@ type nkValueList, nkWhere, nkCreateTable, - nkCreateTableIfNotExists, + nkCreateTableIfNotExists, nkCreateType, nkCreateTypeIfNotExists, nkCreateIndex, nkCreateIndexIfNotExists, nkEnumDef - + type SqlParseError* = object of ValueError ## Invalid SQL encountered SqlNode* = ref SqlNodeObj ## an SQL abstract syntax tree node @@ -563,11 +563,11 @@ proc newNode(k: SqlNodeKind, s: string): SqlNode = new(result) result.kind = k result.strVal = s - + proc len*(n: SqlNode): int = if isNil(n.sons): result = 0 else: result = n.sons.len - + proc add*(father, n: SqlNode) = if isNil(father.sons): father.sons = @[] add(father.sons, n) @@ -641,11 +641,11 @@ proc parseDataType(p: var SqlParser): SqlNode = getTok(p) eat(p, tkParRi) -proc getPrecedence(p: SqlParser): int = +proc getPrecedence(p: SqlParser): int = if isOpr(p, "*") or isOpr(p, "/") or isOpr(p, "%"): result = 6 elif isOpr(p, "+") or isOpr(p, "-"): - result = 5 + result = 5 elif isOpr(p, "=") or isOpr(p, "<") or isOpr(p, ">") or isOpr(p, ">=") or isOpr(p, "<=") or isOpr(p, "<>") or isOpr(p, "!=") or isKeyw(p, "is") or isKeyw(p, "like"): @@ -664,7 +664,7 @@ proc parseExpr(p: var SqlParser): SqlNode proc identOrLiteral(p: var SqlParser): SqlNode = case p.tok.kind - of tkIdentifier, tkQuotedIdentifier: + of tkIdentifier, tkQuotedIdentifier: result = newNode(nkIdent, p.tok.literal) getTok(p) of tkStringConstant, tkEscapeConstant, tkDollarQuotedConstant: @@ -686,21 +686,21 @@ proc identOrLiteral(p: var SqlParser): SqlNode = getTok(p) result = parseExpr(p) eat(p, tkParRi) - else: + else: sqlError(p, "expression expected") getTok(p) # we must consume a token here to prevend endless loops! -proc primary(p: var SqlParser): SqlNode = - if p.tok.kind == tkOperator or isKeyw(p, "not"): +proc primary(p: var SqlParser): SqlNode = + if p.tok.kind == tkOperator or isKeyw(p, "not"): result = newNode(nkPrefix) result.add(newNode(nkIdent, p.tok.literal)) getTok(p) result.add(primary(p)) return result = identOrLiteral(p) - while true: + while true: case p.tok.kind - of tkParLe: + of tkParLe: var a = result result = newNode(nkCall) result.add(a) @@ -710,7 +710,7 @@ proc primary(p: var SqlParser): SqlNode = if p.tok.kind == tkComma: getTok(p) else: break eat(p, tkParRi) - of tkDot: + of tkDot: getTok(p) var a = result if p.tok.kind == tkDot: @@ -727,14 +727,14 @@ proc primary(p: var SqlParser): SqlNode = sqlError(p, "identifier expected") getTok(p) else: break - -proc lowestExprAux(p: var SqlParser, v: var SqlNode, limit: int): int = + +proc lowestExprAux(p: var SqlParser, v: var SqlNode, limit: int): int = var v2, node, opNode: SqlNode v = primary(p) # expand while operators have priorities higher than 'limit' var opPred = getPrecedence(p) result = opPred - while opPred > limit: + while opPred > limit: node = newNode(nkInfix) opNode = newNode(nkIdent, p.tok.literal) getTok(p) @@ -744,8 +744,8 @@ proc lowestExprAux(p: var SqlParser, v: var SqlNode, limit: int): int = node.add(v2) v = node opPred = getPrecedence(p) - -proc parseExpr(p: var SqlParser): SqlNode = + +proc parseExpr(p: var SqlParser): SqlNode = discard lowestExprAux(p, result, - 1) proc parseTableName(p: var SqlParser): SqlNode = @@ -765,7 +765,7 @@ proc parseColumnReference(p: var SqlParser): SqlNode = result.add(parseTableName(p)) eat(p, tkParRi) -proc parseCheck(p: var SqlParser): SqlNode = +proc parseCheck(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkCheck) result.add(parseExpr(p)) @@ -817,9 +817,9 @@ proc parseColumnDef(p: var SqlParser): SqlNode = result.add(newNode(nkIdent, p.tok.literal)) getTok(p) result.add(parseDataType(p)) - parseColumnConstraints(p, result) + parseColumnConstraints(p, result) -proc parseIfNotExists(p: var SqlParser, k: SqlNodeKind): SqlNode = +proc parseIfNotExists(p: var SqlParser, k: SqlNodeKind): SqlNode = getTok(p) if isKeyw(p, "if"): getTok(p) @@ -880,7 +880,7 @@ proc parseTableDef(p: var SqlParser): SqlNode = result.add(parseTableConstraint(p)) if p.tok.kind != tkComma: break eat(p, tkParRi) - + proc parseTypeDef(p: var SqlParser): SqlNode = result = parseIfNotExists(p, nkCreateType) expectIdent(p) @@ -966,7 +966,7 @@ proc parseUpdate(p: var SqlParser): SqlNode = result.add(parseWhere(p)) else: result.add(nil) - + proc parseDelete(p: var SqlParser): SqlNode = getTok(p) result = newNode(nkDelete) @@ -1018,14 +1018,14 @@ proc parseSelect(p: var SqlParser): SqlNode = while true: getTok(p) h.add(parseExpr(p)) - if p.tok.kind != tkComma: break + if p.tok.kind != tkComma: break result.add(h) if isKeyw(p, "union"): result.add(newNode(nkUnion)) getTok(p) elif isKeyw(p, "intersect"): result.add(newNode(nkIntersect)) - getTok(p) + getTok(p) elif isKeyw(p, "except"): result.add(newNode(nkExcept)) getTok(p) @@ -1083,7 +1083,7 @@ proc open(p: var SqlParser, input: Stream, filename: string) = p.tok.kind = tkInvalid p.tok.literal = "" getTok(p) - + proc parse(p: var SqlParser): SqlNode = ## parses the content of `p`'s input stream and returns the SQL AST. ## Syntax errors raise an `EInvalidSql` exception. @@ -1094,13 +1094,13 @@ proc parse(p: var SqlParser): SqlNode = result.add(s) if result.len == 1: result = result.sons[0] - + proc close(p: var SqlParser) = ## closes the parser `p`. The associated input stream is closed too. close(SqlLexer(p)) proc parseSQL*(input: Stream, filename: string): SqlNode = - ## parses the SQL from `input` into an AST and returns the AST. + ## parses the SQL from `input` into an AST and returns the AST. ## `filename` is only used for error messages. ## Syntax errors raise an `EInvalidSql` exception. var p: SqlParser @@ -1114,7 +1114,7 @@ proc ra(n: SqlNode, s: var string, indent: int) proc rs(n: SqlNode, s: var string, indent: int, prefix = "(", suffix = ")", - sep = ", ") = + sep = ", ") = if n.len > 0: s.add(prefix) for i in 0 .. n.len-1: @@ -1162,7 +1162,7 @@ proc ra(n: SqlNode, s: var string, indent: int) = ra(n.sons[1], s, indent) s.add(')') of nkInfix: - s.add('(') + s.add('(') ra(n.sons[1], s, indent) s.add(' ') ra(n.sons[0], s, indent) @@ -1207,13 +1207,13 @@ proc ra(n: SqlNode, s: var string, indent: int) = s.add("insert into ") ra(n.sons[0], s, indent) ra(n.sons[1], s, indent) - if n.sons[2].kind == nkDefault: + if n.sons[2].kind == nkDefault: s.add("default values") else: s.add("\nvalues ") ra(n.sons[2], s, indent) s.add(';') - of nkUpdate: + of nkUpdate: s.add("update ") ra(n.sons[0], s, indent) s.add(" set ") @@ -1225,7 +1225,7 @@ proc ra(n: SqlNode, s: var string, indent: int) = ra(it, s, indent) ra(n.sons[L-1], s, indent) s.add(';') - of nkDelete: + of nkDelete: s.add("delete from ") ra(n.sons[0], s, indent) ra(n.sons[1], s, indent) @@ -1237,12 +1237,12 @@ proc ra(n: SqlNode, s: var string, indent: int) = rs(n.sons[0], s, indent, "", "", ", ") for i in 1 .. n.len-1: ra(n.sons[i], s, indent) s.add(';') - of nkSelectColumns: + of nkSelectColumns: assert(false) of nkAsgn: ra(n.sons[0], s, indent) s.add(" = ") - ra(n.sons[1], s, indent) + ra(n.sons[1], s, indent) of nkFrom: s.add("\nfrom ") rs(n, s, indent, "", "", ", ") @@ -1306,23 +1306,23 @@ proc ra(n: SqlNode, s: var string, indent: int) = s.add("enum ") rs(n, s, indent) -# What I want: +# What I want: # -#select(columns = [T1.all, T2.name], +#select(columns = [T1.all, T2.name], # fromm = [T1, T2], # where = T1.name ==. T2.name, # orderby = [name]): -# -#for row in dbQuery(db, """select x, y, z -# from a, b +# +#for row in dbQuery(db, """select x, y, z +# from a, b # where a.name = b.name"""): -# +# #select x, y, z: # fromm: Table1, Table2 # where: x.name == y.name #db.select(fromm = [t1, t2], where = t1.name == t2.name): -#for x, y, z in db.select(fromm = a, b where = a.name == b.name): +#for x, y, z in db.select(fromm = a, b where = a.name == b.name): # writeLine x, y, z proc renderSQL*(n: SqlNode): string = @@ -1338,7 +1338,7 @@ when not defined(testing) and isMainModule: happiness happiness ); CREATE INDEX table1_attr1 ON table1(attr1); - + SELECT * FROM myTab WHERE col1 = 'happy'; """), "stdin"))) diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim index 56bf10768..6d58e8a73 100644 --- a/lib/pure/parseurl.nim +++ b/lib/pure/parseurl.nim @@ -19,7 +19,7 @@ import strutils type Url* = tuple[ ## represents a *Uniform Resource Locator* (URL) ## any optional component is "" if it does not exist - scheme, username, password, + scheme, username, password, hostname, port, path, query, anchor: string] {.deprecated: [TUrl: Url].} @@ -31,7 +31,7 @@ proc parseUrl*(url: string): Url {.deprecated.} = var hostname, port, path, query, anchor: string = "" var temp = "" - + if url[i] != '/': # url isn't a relative path while true: # Scheme @@ -48,7 +48,7 @@ proc parseUrl*(url: string): Url {.deprecated.} = password = username.substr(colon+1) username = username.substr(0, colon-1) temp.setLen(0) - inc(i) #Skip the @ + inc(i) #Skip the @ # hostname(subdomain, domain, port) if url[i] == '/' or url[i] == '\0': hostname = temp @@ -56,10 +56,10 @@ proc parseUrl*(url: string): Url {.deprecated.} = if colon >= 0: port = hostname.substr(colon+1) hostname = hostname.substr(0, colon-1) - + temp.setLen(0) break - + temp.add(url[i]) inc(i) @@ -75,7 +75,7 @@ proc parseUrl*(url: string): Url {.deprecated.} = else: path = temp temp.setLen(0) - + if url[i] == '\0': if temp[0] == '?': query = temp @@ -84,10 +84,10 @@ proc parseUrl*(url: string): Url {.deprecated.} = else: path = temp break - + temp.add(url[i]) inc(i) - + return (scheme, username, password, hostname, port, path, query, anchor) proc `$`*(u: Url): string {.deprecated.} = @@ -103,12 +103,12 @@ proc `$`*(u: Url): string {.deprecated.} = result.add(u.password) result.add("@") result.add(u.hostname) - if u.port.len > 0: + if u.port.len > 0: result.add(":") result.add(u.port) - if u.path.len > 0: + if u.path.len > 0: result.add("/") result.add(u.path) result.add(u.query) result.add(u.anchor) - + diff --git a/lib/pure/poly.nim b/lib/pure/poly.nim index 58dcdc1ad..c52300400 100644 --- a/lib/pure/poly.nim +++ b/lib/pure/poly.nim @@ -11,7 +11,7 @@ import math import strutils import numeric -type +type Poly* = object cofs:seq[float] @@ -40,7 +40,7 @@ proc `[]` *(p:Poly;idx:int):float= if idx<0 or idx>p.degree: return 0.0 return p.cofs[idx] - + proc `[]=` *(p:var Poly;idx:int,v:float)= ## Sets an coefficient of the polynomial by index. ## p[2] set the quadric term, p[3] the cubic etc. @@ -55,15 +55,15 @@ proc `[]=` *(p:var Poly;idx:int,v:float)= p.cofs[q]=0.0 #new-grown coefficients set to zero p.cofs[idx]=v - - + + iterator items*(p:Poly):float= ## Iterates through the coefficients of the polynomial. var i=p.degree while i>=0: yield p[i] - dec i - + dec i + proc clean*(p:var Poly;zerotol=0.0)= ## Removes leading zero coefficients of the polynomial. ## An optional tolerance can be given for what's considered zero. @@ -77,19 +77,19 @@ proc clean*(p:var Poly;zerotol=0.0)= if relen: p.cofs.setLen(n+1) -proc `$` *(p:Poly):string = +proc `$` *(p:Poly):string = ## Gets a somewhat reasonable string representation of the polynomial ## The format should be compatible with most online function plotters, ## for example directly in google search result="" var first=true #might skip + sign if first coefficient - + for idx in countdown(p.degree,0): let a=p[idx] - + if a==0.0: continue - + if a>= 0.0 and not first: result.add('+') first=false @@ -103,14 +103,14 @@ proc `$` *(p:Poly):string = if result=="": result="0" - + proc derivative*(p: Poly): Poly= ## Returns a new polynomial, which is the derivative of `p` newSeq[float](result.cofs,p.degree) for idx in 0..high(result.cofs): result.cofs[idx]=p.cofs[idx+1]*float(idx+1) - + proc diff*(p:Poly,x:float):float= ## Evaluates the differentiation of a polynomial with ## respect to `x` quickly using a modifed Horners method @@ -128,7 +128,7 @@ proc integral*(p:Poly):Poly= result.cofs[0]=0.0 #constant arbitrary term, use 0.0 for i in 1..high(result.cofs): result.cofs[i]=p.cofs[i-1]/float(i) - + proc integrate*(p:Poly;xmin,xmax:float):float= ## Computes the definite integral of `p` between `xmin` and `xmax` @@ -145,9 +145,9 @@ proc integrate*(p:Poly;xmin,xmax:float):float= s1 = s1*xmin+fac s2 = s2*xmax+fac dec n - + result=s2*xmax-s1*xmin - + proc initPoly*(cofs:varargs[float]):Poly= ## Initializes a polynomial with given coefficients. ## The most significant coefficient is first, so to create x^2-2x+3: @@ -158,7 +158,7 @@ proc initPoly*(cofs:varargs[float]):Poly= # reverse order of coefficients so indexing matches degree of # coefficient... result.cofs= @[] - for idx in countdown(cofs.len-1,0): + for idx in countdown(cofs.len-1,0): result.cofs.add(cofs[idx]) result.clean #remove leading zero terms @@ -167,49 +167,49 @@ proc initPoly*(cofs:varargs[float]):Poly= proc divMod*(p,d:Poly;q,r:var Poly)= ## Divides `p` with `d`, and stores the quotinent in `q` and ## the remainder in `d` - var + var pdeg=p.degree ddeg=d.degree power=p.degree-d.degree ratio:float - + r.cofs = p.cofs #initial remainder=numerator if power<0: #denominator is larger than numerator q.cofs= @ [0.0] #quotinent is 0.0 return # keep remainder as numerator - + q.cofs=newSeq[float](power+1) - + for i in countdown(pdeg,ddeg): ratio=r.cofs[i]/d.cofs[ddeg] - + q.cofs[i-ddeg]=ratio r.cofs[i]=0.0 - + for j in countup(0,<ddeg): var idx=i-ddeg+j r.cofs[idx] = r.cofs[idx] - d.cofs[j]*ratio - + r.clean # drop zero coefficients in remainder proc `+` *(p1:Poly,p2:Poly):Poly= ## Adds two polynomials var n=max(p1.cofs.len,p2.cofs.len) newSeq(result.cofs,n) - + for idx in countup(0,n-1): result[idx]=p1[idx]+p2[idx] - + result.clean # drop zero coefficients in remainder - + proc `*` *(p1:Poly,p2:Poly):Poly= ## Multiplies the polynomial `p1` with `p2` - var + var d1=p1.degree d2=p2.degree n=d1+d2 idx:int - + newSeq(result.cofs,n) for i1 in countup(0,d1): @@ -225,38 +225,38 @@ proc `*` *(p:Poly,f:float):Poly= for i in 0..high(p.cofs): result[i]=p.cofs[i]*f result.clean - + proc `*` *(f:float,p:Poly):Poly= ## Multiplies a real number with a polynomial return p*f - + proc `-`*(p:Poly):Poly= ## Negates a polynomial result=p for i in countup(0,<result.cofs.len): result.cofs[i]= -result.cofs[i] - + proc `-` *(p1:Poly,p2:Poly):Poly= ## Subtract `p1` with `p2` var n=max(p1.cofs.len,p2.cofs.len) newSeq(result.cofs,n) - + for idx in countup(0,n-1): result[idx]=p1[idx]-p2[idx] - + result.clean # drop zero coefficients in remainder - + proc `/`*(p:Poly,f:float):Poly= ## Divides polynomial `p` with a real number `f` newSeq(result.cofs,p.cofs.len) for i in 0..high(p.cofs): result[i]=p.cofs[i]/f result.clean - + proc `/` *(p,q:Poly):Poly= ## Divides polynomial `p` with polynomial `q` var dummy:Poly - p.divMod(q,result,dummy) + p.divMod(q,result,dummy) proc `mod` *(p,q:Poly):Poly= ## Computes the polynomial modulo operation, @@ -277,20 +277,20 @@ proc solveQuadric*(a,b,c:float;zerotol=0.0):seq[float]= ## Solves the quadric equation `ax^2+bx+c`, with a possible ## tolerance `zerotol` to find roots of curves just 'touching' ## the x axis. Returns sequence with 0,1 or 2 solutions. - + var p,q,d:float - + p=b/(2.0*a) - + if p==Inf or p==NegInf: #linear equation.. var linrt= -c/b if linrt==Inf or linrt==NegInf: #constant only return @[] return @[linrt] - + q=c/a d=p*p-q - + if d<0.0: #check for inside zerotol range for neg. roots var err=a*p*p-b*p+c #evaluate error at parabola center axis @@ -309,12 +309,12 @@ proc getRangeForRoots(p:Poly):tuple[xmin,xmax:float]= var deg=p.degree var d=p[deg] var bound1,bound2:float - + for i in countup(0,deg): var c=abs(p.cofs[i]/d) bound1=max(bound1,c+1.0) bound2=bound2+c - + bound2=max(1.0,bound2) result.xmax=min(bound1,bound2) result.xmin= -result.xmax @@ -327,13 +327,13 @@ proc addRoot(p:Poly,res:var seq[float],xp0,xp1,tol,zerotol,mergetol:float,maxite var br=brent(xp0,xp1, proc(x:float):float=p.eval(x),tol) if br.success: if res.len==0 or br.rootx>=res[high(res)]+mergetol: #dont add equal roots. - res.add(br.rootx) + res.add(br.rootx) else: #this might be a 'touching' case, check function value against #zero tolerance if abs(br.rooty)<=zerotol: if res.len==0 or br.rootx>=res[high(res)]+mergetol: #dont add equal roots. - res.add(br.rootx) + res.add(br.rootx) proc roots*(p:Poly,tol=1.0e-9,zerotol=1.0e-6,mergetol=1.0e-12,maxiter=1000):seq[float]= diff --git a/lib/pure/rationals.nim b/lib/pure/rationals.nim index 8e1dbe464..60d09c71a 100644 --- a/lib/pure/rationals.nim +++ b/lib/pure/rationals.nim @@ -216,7 +216,7 @@ proc hash*[T](x: Rational[T]): Hash = h = h !& hash(copy.num) h = h !& hash(copy.den) result = !$h - + when isMainModule: var z = Rational[int](num: 0, den: 1) diff --git a/lib/pure/redis.nim b/lib/pure/redis.nim index b738e4094..e3f18a496 100644 --- a/lib/pure/redis.nim +++ b/lib/pure/redis.nim @@ -11,7 +11,7 @@ ## redis-server instance, send commands and receive replies. ## ## **Beware**: Most (if not all) functions that return a ``RedisString`` may -## return ``redisNil``, and functions which return a ``RedisList`` +## return ``redisNil``, and functions which return a ``RedisList`` ## may return ``nil``. import sockets, os, strutils, parseutils @@ -19,7 +19,7 @@ import sockets, os, strutils, parseutils const redisNil* = "\0\0" -type +type Pipeline = ref object enabled: bool buffer: string @@ -34,7 +34,7 @@ type socket: Socket connected: bool pipeline: Pipeline - + RedisStatus* = string RedisInteger* = BiggestInt RedisString* = string ## Bulk reply @@ -59,10 +59,10 @@ proc open*(host = "localhost", port = 6379.Port): Redis = if result.socket == invalidSocket: raiseOSError(osLastError()) result.socket.connect(host, port) - result.pipeline = newPipeline() + result.pipeline = newPipeline() proc raiseInvalidReply(expected, got: char) = - raise newException(ReplyError, + raise newException(ReplyError, "Expected '$1' at the beginning of a status reply got '$2'" % [$expected, $got]) @@ -90,16 +90,16 @@ proc parseStatus(r: Redis, line: string = ""): RedisStatus = raise newException(RedisError, strip(line)) if line[0] != '+': raiseInvalidReply('+', line[0]) - + return line.substr(1) # Strip '+' proc readStatus(r:Redis): RedisStatus = r.readSocket("PIPELINED") return r.parseStatus(line) - + proc parseInteger(r: Redis, line: string = ""): RedisInteger = if r.pipeline.enabled: return -1 - + #if line == "+QUEUED": # inside of multi # return -1 @@ -110,10 +110,10 @@ proc parseInteger(r: Redis, line: string = ""): RedisInteger = raise newException(RedisError, strip(line)) if line[0] != ':': raiseInvalidReply(':', line[0]) - + # Strip ':' if parseBiggestInt(line, result, 1) == 0: - raise newException(ReplyError, "Unable to parse integer.") + raise newException(ReplyError, "Unable to parse integer.") proc readInteger(r: Redis): RedisInteger = r.readSocket(-1) @@ -126,19 +126,19 @@ proc recv(sock: Socket, size: int): TaintedString = proc parseSingleString(r: Redis, line:string, allowMBNil = false): RedisString = if r.pipeline.enabled: return "" - + # Error. if line[0] == '-': raise newException(RedisError, strip(line)) - + # Some commands return a /bulk/ value or a /multi-bulk/ nil. Odd. if allowMBNil: if line == "*-1": return redisNil - + if line[0] != '$': raiseInvalidReply('$', line[0]) - + var numBytes = parseInt(line.substr(1)) if numBytes == -1: return redisNil @@ -168,7 +168,7 @@ proc parseArrayLines(r: Redis, countLine:string): RedisList = proc readArrayLines(r: Redis): RedisList = r.readSocket(nil) - return r.parseArrayLines(line) + return r.parseArrayLines(line) proc parseBulkString(r: Redis, allowMBNil = false, line:string = ""): RedisString = if r.pipeline.enabled: return "" @@ -191,7 +191,7 @@ proc readNext(r: Redis): RedisList = of ':': @[$(r.parseInteger(line))] of '$': @[r.parseBulkString(true,line)] of '*': r.parseArrayLines(line) - else: + else: raise newException(ReplyError, "readNext failed on line: " & line) nil r.pipeline.expected -= 1 @@ -202,10 +202,10 @@ proc flushPipeline*(r: Redis, wasMulti = false): RedisList = if r.pipeline.buffer.len > 0: r.socket.send(r.pipeline.buffer) r.pipeline.buffer = "" - + r.pipeline.enabled = false result = @[] - + var tot = r.pipeline.expected for i in 0..tot-1: @@ -232,7 +232,7 @@ proc sendCommand(r: Redis, cmd: string, args: varargs[string]) = for i in items(args): request.add("$" & $i.len() & "\c\L") request.add(i & "\c\L") - + if r.pipeline.enabled: r.pipeline.buffer.add(request) r.pipeline.expected += 1 @@ -249,7 +249,7 @@ proc sendCommand(r: Redis, cmd: string, arg1: string, for i in items(args): request.add("$" & $i.len() & "\c\L") request.add(i & "\c\L") - + if r.pipeline.enabled: r.pipeline.expected += 1 r.pipeline.buffer.add(request) @@ -275,7 +275,7 @@ proc expire*(r: Redis, key: string, seconds: int): bool = return r.readInteger() == 1 proc expireAt*(r: Redis, key: string, timestamp: int): bool = - ## Set the expiration for a key as a UNIX timestamp. Returns `false` + ## Set the expiration for a key as a UNIX timestamp. Returns `false` ## if the key could not be found or the timeout could not be set. r.sendCommand("EXPIREAT", key, $timestamp) return r.readInteger() == 1 @@ -301,7 +301,7 @@ proc scan*(r: Redis, cursor: var BiggestInt, pattern: string): RedisList = cursor = strutils.parseBiggestInt(reply[0]) return reply[1..high(reply)] -proc scan*(r: Redis, cursor: var BiggestInt, pattern: string, count: int): RedisList = +proc scan*(r: Redis, cursor: var BiggestInt, pattern: string, count: int): RedisList = ## Find all keys matching the given pattern and yield it to client in portions ## using cursor as a client query identifier. r.sendCommand("SCAN", $cursor, ["MATCH", pattern, "COUNT", $count]) @@ -315,11 +315,11 @@ proc move*(r: Redis, key: string, db: int): bool = return r.readInteger() == 1 proc persist*(r: Redis, key: string): bool = - ## Remove the expiration from a key. + ## Remove the expiration from a key. ## Returns `true` when the timeout was removed. r.sendCommand("PERSIST", key) return r.readInteger() == 1 - + proc randomKey*(r: Redis): RedisString = ## Return a random key from the keyspace r.sendCommand("RANDOMKEY") @@ -327,11 +327,11 @@ proc randomKey*(r: Redis): RedisString = proc rename*(r: Redis, key, newkey: string): RedisStatus = ## Rename a key. - ## + ## ## **WARNING:** Overwrites `newkey` if it exists! r.sendCommand("RENAME", key, newkey) raiseNoOK(r.readStatus(), r.pipeline.enabled) - + proc renameNX*(r: Redis, key, newkey: string): bool = ## Same as ``rename`` but doesn't continue if `newkey` exists. ## Returns `true` if key was renamed. @@ -342,12 +342,12 @@ proc ttl*(r: Redis, key: string): RedisInteger = ## Get the time to live for a key r.sendCommand("TTL", key) return r.readInteger() - + proc keyType*(r: Redis, key: string): RedisStatus = ## Determine the type stored at key r.sendCommand("TYPE", key) return r.readStatus() - + # Strings @@ -360,12 +360,12 @@ proc decr*(r: Redis, key: string): RedisInteger = ## Decrement the integer value of a key by one r.sendCommand("DECR", key) return r.readInteger() - + proc decrBy*(r: Redis, key: string, decrement: int): RedisInteger = ## Decrement the integer value of a key by the given number r.sendCommand("DECRBY", key, $decrement) return r.readInteger() - + proc get*(r: Redis, key: string): RedisString = ## Get the value of a key. Returns `redisNil` when `key` doesn't exist. r.sendCommand("GET", key) @@ -397,7 +397,7 @@ proc incrBy*(r: Redis, key: string, increment: int): RedisInteger = r.sendCommand("INCRBY", key, $increment) return r.readInteger() -proc setk*(r: Redis, key, value: string) = +proc setk*(r: Redis, key, value: string) = ## Set the string value of a key. ## ## NOTE: This function had to be renamed due to a clash with the `set` type. @@ -410,18 +410,18 @@ proc setNX*(r: Redis, key, value: string): bool = r.sendCommand("SETNX", key, value) return r.readInteger() == 1 -proc setBit*(r: Redis, key: string, offset: int, +proc setBit*(r: Redis, key: string, offset: int, value: string): RedisInteger = ## Sets or clears the bit at offset in the string value stored at key r.sendCommand("SETBIT", key, $offset, value) return r.readInteger() - + proc setEx*(r: Redis, key: string, seconds: int, value: string): RedisStatus = ## Set the value and expiration of a key r.sendCommand("SETEX", key, $seconds, value) raiseNoOK(r.readStatus(), r.pipeline.enabled) -proc setRange*(r: Redis, key: string, offset: int, +proc setRange*(r: Redis, key: string, offset: int, value: string): RedisInteger = ## Overwrite part of a string at key starting at the specified offset r.sendCommand("SETRANGE", key, $offset, value) @@ -474,7 +474,7 @@ proc hMGet*(r: Redis, key: string, fields: varargs[string]): RedisList = r.sendCommand("HMGET", key, fields) return r.readArray() -proc hMSet*(r: Redis, key: string, +proc hMSet*(r: Redis, key: string, fieldValues: openArray[tuple[field, value: string]]) = ## Set multiple hash fields to multiple values var args = @[key] @@ -488,7 +488,7 @@ proc hSet*(r: Redis, key, field, value: string): RedisInteger = ## Set the string value of a hash field r.sendCommand("HSET", key, field, value) return r.readInteger() - + proc hSetNX*(r: Redis, key, field, value: string): RedisInteger = ## Set the value of a hash field, only if the field does **not** exist r.sendCommand("HSETNX", key, field, value) @@ -498,11 +498,11 @@ proc hVals*(r: Redis, key: string): RedisList = ## Get all the values in a hash r.sendCommand("HVALS", key) return r.readArray() - + # Lists proc bLPop*(r: Redis, keys: varargs[string], timeout: int): RedisList = - ## Remove and get the *first* element in a list, or block until + ## Remove and get the *first* element in a list, or block until ## one is available var args: seq[string] = @[] for i in items(keys): args.add(i) @@ -511,7 +511,7 @@ proc bLPop*(r: Redis, keys: varargs[string], timeout: int): RedisList = return r.readArray() proc bRPop*(r: Redis, keys: varargs[string], timeout: int): RedisList = - ## Remove and get the *last* element in a list, or block until one + ## Remove and get the *last* element in a list, or block until one ## is available. var args: seq[string] = @[] for i in items(keys): args.add(i) @@ -539,7 +539,7 @@ proc lInsert*(r: Redis, key: string, before: bool, pivot, value: string): var pos = if before: "BEFORE" else: "AFTER" r.sendCommand("LINSERT", key, pos, pivot, value) return r.readInteger() - + proc lLen*(r: Redis, key: string): RedisInteger = ## Get the length of a list r.sendCommand("LLEN", key) @@ -553,7 +553,7 @@ proc lPop*(r: Redis, key: string): RedisString = proc lPush*(r: Redis, key, value: string, create: bool = true): RedisInteger = ## Prepend a value to a list. Returns the length of the list after the push. ## The ``create`` param specifies whether a list should be created if it - ## doesn't exist at ``key``. More specifically if ``create`` is true, `LPUSH` + ## doesn't exist at ``key``. More specifically if ``create`` is true, `LPUSH` ## will be used, otherwise `LPUSHX`. if create: r.sendCommand("LPUSH", key, value) @@ -562,7 +562,7 @@ proc lPush*(r: Redis, key, value: string, create: bool = true): RedisInteger = return r.readInteger() proc lRange*(r: Redis, key: string, start, stop: int): RedisList = - ## Get a range of elements from a list. Returns `nil` when `key` + ## Get a range of elements from a list. Returns `nil` when `key` ## doesn't exist. r.sendCommand("LRANGE", key, $start, $stop) return r.readArray() @@ -587,16 +587,16 @@ proc rPop*(r: Redis, key: string): RedisString = ## Remove and get the last element in a list r.sendCommand("RPOP", key) return r.readBulkString() - + proc rPopLPush*(r: Redis, source, destination: string): RedisString = ## Remove the last element in a list, append it to another list and return it r.sendCommand("RPOPLPUSH", source, destination) return r.readBulkString() - + proc rPush*(r: Redis, key, value: string, create: bool = true): RedisInteger = ## Append a value to a list. Returns the length of the list after the push. ## The ``create`` param specifies whether a list should be created if it - ## doesn't exist at ``key``. More specifically if ``create`` is true, `RPUSH` + ## doesn't exist at ``key``. More specifically if ``create`` is true, `RPUSH` ## will be used, otherwise `RPUSHX`. if create: r.sendCommand("RPUSH", key, value) @@ -676,7 +676,7 @@ proc sunion*(r: Redis, keys: varargs[string]): RedisList = proc sunionstore*(r: Redis, destination: string, key: varargs[string]): RedisInteger = - ## Add multiple sets and store the resulting set in a key + ## Add multiple sets and store the resulting set in a key r.sendCommand("SUNIONSTORE", destination, key) return r.readInteger() @@ -710,16 +710,16 @@ proc zinterstore*(r: Redis, destination: string, numkeys: string, ## a new key var args = @[destination, numkeys] for i in items(keys): args.add(i) - + if weights.len != 0: args.add("WITHSCORE") for i in items(weights): args.add(i) if aggregate.len != 0: args.add("AGGREGATE") args.add(aggregate) - + r.sendCommand("ZINTERSTORE", args) - + return r.readInteger() proc zrange*(r: Redis, key: string, start: string, stop: string, @@ -731,18 +731,18 @@ proc zrange*(r: Redis, key: string, start: string, stop: string, r.sendCommand("ZRANGE", "WITHSCORES", key, start, stop) return r.readArray() -proc zrangebyscore*(r: Redis, key: string, min: string, max: string, +proc zrangebyscore*(r: Redis, key: string, min: string, max: string, withScore: bool = false, limit: bool = false, limitOffset: int = 0, limitCount: int = 0): RedisList = ## Return a range of members in a sorted set, by score var args = @[key, min, max] - + if withScore: args.add("WITHSCORE") - if limit: + if limit: args.add("LIMIT") args.add($limitOffset) args.add($limitCount) - + r.sendCommand("ZRANGEBYSCORE", args) return r.readArray() @@ -770,26 +770,26 @@ proc zremrangebyscore*(r: Redis, key: string, min: string, proc zrevrange*(r: Redis, key: string, start: string, stop: string, withScore: bool): RedisList = - ## Return a range of members in a sorted set, by index, + ## Return a range of members in a sorted set, by index, ## with scores ordered from high to low if withScore: r.sendCommand("ZREVRANGE", "WITHSCORE", key, start, stop) else: r.sendCommand("ZREVRANGE", key, start, stop) return r.readArray() -proc zrevrangebyscore*(r: Redis, key: string, min: string, max: string, +proc zrevrangebyscore*(r: Redis, key: string, min: string, max: string, withScore: bool = false, limit: bool = false, limitOffset: int = 0, limitCount: int = 0): RedisList = ## Return a range of members in a sorted set, by score, with ## scores ordered from high to low var args = @[key, min, max] - + if withScore: args.add("WITHSCORE") - if limit: + if limit: args.add("LIMIT") args.add($limitOffset) args.add($limitCount) - + r.sendCommand("ZREVRANGEBYSCORE", args) return r.readArray() @@ -807,24 +807,24 @@ proc zscore*(r: Redis, key: string, member: string): RedisString = proc zunionstore*(r: Redis, destination: string, numkeys: string, keys: openArray[string], weights: openArray[string] = [], aggregate: string = ""): RedisInteger = - ## Add multiple sorted sets and store the resulting sorted set in a new key + ## Add multiple sorted sets and store the resulting sorted set in a new key var args = @[destination, numkeys] for i in items(keys): args.add(i) - + if weights.len != 0: args.add("WEIGHTS") for i in items(weights): args.add(i) if aggregate.len != 0: args.add("AGGREGATE") args.add(aggregate) - + r.sendCommand("ZUNIONSTORE", args) - + return r.readInteger() # HyperLogLog -proc pfadd*(r: Redis, key: string, elements: varargs[string]): RedisInteger = +proc pfadd*(r: Redis, key: string, elements: varargs[string]): RedisInteger = ## Add variable number of elements into special 'HyperLogLog' set type r.sendCommand("PFADD", key, elements) return r.readInteger() @@ -864,7 +864,7 @@ proc subscribe*(r: Redis, channel: openarray[string]): ???? = return ??? proc unsubscribe*(r: Redis, [channel: openarray[string], : string): ???? = - ## Stop listening for messages posted to the given channels + ## Stop listening for messages posted to the given channels r.socket.send("UNSUBSCRIBE $# $#\c\L" % [[channel.join(), ]) return ??? @@ -879,12 +879,12 @@ proc discardMulti*(r: Redis) = proc exec*(r: Redis): RedisList = ## Execute all commands issued after MULTI - r.sendCommand("EXEC") + r.sendCommand("EXEC") r.pipeline.enabled = false # Will reply with +OK for MULTI/EXEC and +QUEUED for every command # between, then with the results return r.flushPipeline(true) - + proc multi*(r: Redis) = ## Mark the start of a transaction block @@ -898,7 +898,7 @@ proc unwatch*(r: Redis) = raiseNoOK(r.readStatus(), r.pipeline.enabled) proc watch*(r: Redis, key: varargs[string]) = - ## Watch the given keys to determine execution of the MULTI/EXEC block + ## Watch the given keys to determine execution of the MULTI/EXEC block r.sendCommand("WATCH", key) raiseNoOK(r.readStatus(), r.pipeline.enabled) @@ -925,7 +925,7 @@ proc quit*(r: Redis) = raiseNoOK(r.readStatus(), r.pipeline.enabled) proc select*(r: Redis, index: int): RedisStatus = - ## Change the selected database for the current connection + ## Change the selected database for the current connection r.sendCommand("SELECT", $index) return r.readStatus() @@ -1016,7 +1016,7 @@ proc slaveof*(r: Redis, host: string, port: string) = iterator hPairs*(r: Redis, key: string): tuple[key, value: string] = ## Iterator for keys and values in a hash. - var + var contents = r.hGetAll(key) k = "" for i in items(contents): @@ -1031,9 +1031,9 @@ proc someTests(r: Redis, how: SendMode):seq[string] = if how == pipelined: r.startPipelining() - elif how == multiple: + elif how == multiple: r.multi() - + r.setk("nim:test", "Testing something.") r.setk("nim:utf8", "こんにちは") r.setk("nim:esc", "\\ths ągt\\") @@ -1054,7 +1054,7 @@ proc someTests(r: Redis, how: SendMode):seq[string] = for i in items(p): if not isNil(i): - list.add(i) + list.add(i) list.add(r.debugObject("mylist")) @@ -1079,7 +1079,7 @@ proc assertListsIdentical(listA, listB: seq[string]) = for item in listA: assert(item == listB[i]) i = i + 1 - + when not defined(testing) and isMainModule: when false: var r = open() diff --git a/lib/pure/romans.nim b/lib/pure/romans.nim index 0c182843a..18c04ef58 100644 --- a/lib/pure/romans.nim +++ b/lib/pure/romans.nim @@ -11,7 +11,7 @@ ## See http://en.wikipedia.org/wiki/Roman_numerals for reference. const - RomanNumeralDigits* = {'I', 'i', 'V', 'v', 'X', 'x', 'L', 'l', 'C', 'c', + RomanNumeralDigits* = {'I', 'i', 'V', 'v', 'X', 'x', 'L', 'l', 'C', 'c', 'D', 'd', 'M', 'm'} ## set of all characters a Roman numeral may consist of proc romanToDecimal*(romanVal: string): int = @@ -28,7 +28,7 @@ proc romanToDecimal*(romanVal: string): int = of 'C', 'c': val = 100 of 'D', 'd': val = 500 of 'M', 'm': val = 1000 - else: + else: raise newException(EInvalidValue, "invalid roman numeral: " & $romanVal) if val >= prevVal: inc(result, val) diff --git a/lib/pure/ropes.nim b/lib/pure/ropes.nim index 5c7fedfe3..df7071642 100644 --- a/lib/pure/ropes.nim +++ b/lib/pure/ropes.nim @@ -29,7 +29,7 @@ const var cacheEnabled = false -type +type Rope* = ref RopeObj ## empty rope is represented by nil RopeObj {.acyclic.} = object left, right: Rope @@ -59,7 +59,7 @@ proc newRope(data: string): Rope = result.length = len(data) result.data = data -var +var cache {.threadvar.}: Rope # the root of the cache tree N {.threadvar.}: Rope # dummy rope needed for splay algorithm @@ -81,7 +81,7 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope = t.left = y.right y.right = t t = y - if t.left == nil: break + if t.left == nil: break r.left = t r = t t = t.left @@ -91,7 +91,7 @@ proc splay(s: string, tree: Rope, cmpres: var int): Rope = t.right = y.left y.left = t t = y - if t.right == nil: break + if t.right == nil: break le.right = t le = t t = t.right @@ -109,7 +109,7 @@ proc insertInCache(s: string, tree: Rope): Rope = if t == nil: result = newRope(s) when countCacheMisses: inc(misses) - return + return var cmp: int t = splay(s, t, cmp) if cmp == 0: @@ -197,7 +197,7 @@ proc add*(a: var Rope, b: Rope) {.rtl, extern: "nro$1Rope".} = proc add*(a: var Rope, b: string) {.rtl, extern: "nro$1Str".} = ## adds `b` to the rope `a`. a = a & b - + proc `[]`*(r: Rope, i: int): char {.rtl, extern: "nroCharAt".} = ## returns the character at position `i` in the rope `r`. This is quite ## expensive! Worst-case: O(n). If ``i >= r.len``, ``\0`` is returned. @@ -250,7 +250,7 @@ when false: proc compiledArg(idx: int): Rope = new(result) result.length = -idx - + proc compileFrmt(frmt: string): Rope = var i = 0 var length = len(frmt) @@ -272,7 +272,7 @@ when false: while true: j = j * 10 + ord(frmt[i]) - ord('0') inc(i) - if frmt[i] notin {'0'..'9'}: break + if frmt[i] notin {'0'..'9'}: break add(s, compiledArg(j)) of '{': inc(i) @@ -345,7 +345,7 @@ const proc equalsFile*(r: Rope, f: File): bool {.rtl, extern: "nro$1File".} = ## returns true if the contents of the file `f` equal `r`. - var + var buf: array[bufSize, char] bpos = buf.len blen = buf.len @@ -363,7 +363,7 @@ proc equalsFile*(r: Rope, f: File): bool {.rtl, extern: "nro$1File".} = return let n = min(blen - bpos, slen - spos) # TODO There's gotta be a better way of comparing here... - if not equalMem(addr(buf[bpos]), + if not equalMem(addr(buf[bpos]), cast[pointer](cast[int](cstring(s))+spos), n): result = false return diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim index 3de422c87..1d54b4591 100644 --- a/lib/pure/scgi.nim +++ b/lib/pure/scgi.nim @@ -8,13 +8,13 @@ # ## This module implements helper procs for SCGI applications. Example: -## +## ## .. code-block:: Nim ## ## import strtabs, sockets, scgi ## ## var counter = 0 -## proc handleRequest(client: Socket, input: string, +## proc handleRequest(client: Socket, input: string, ## headers: StringTableRef): bool {.procvar.} = ## inc(counter) ## client.writeStatusOkTextContent() @@ -37,19 +37,19 @@ import sockets, strutils, os, strtabs, asyncio type ScgiError* = object of IOError ## the exception that is raised, if a SCGI error occurs -proc raiseScgiError*(msg: string) {.noreturn.} = +proc raiseScgiError*(msg: string) {.noreturn.} = ## raises an ScgiError exception with message `msg`. var e: ref ScgiError new(e) e.msg = msg raise e -proc parseWord(inp: string, outp: var string, start: int): int = +proc parseWord(inp: string, outp: var string, start: int): int = result = start while inp[result] != '\0': inc(result) outp = substr(inp, start, result-1) -proc parseHeaders(s: string, L: int): StringTableRef = +proc parseHeaders(s: string, L: int): StringTableRef = result = newStringTable() var i = 0 while i < L: @@ -59,12 +59,12 @@ proc parseHeaders(s: string, L: int): StringTableRef = result[key] = val if s[i] == ',': inc(i) else: raiseScgiError("',' after netstring expected") - -proc recvChar(s: Socket): char = + +proc recvChar(s: Socket): char = var c: char - if recv(s, addr(c), sizeof(c)) == sizeof(c): + if recv(s, addr(c), sizeof(c)) == sizeof(c): result = c - + type ScgiState* = object of RootObj ## SCGI state object server: Socket @@ -72,22 +72,22 @@ type client*: Socket ## the client socket to send data to headers*: StringTableRef ## the parsed headers input*: string ## the input buffer - - + + # Async - + ClientMode = enum ClientReadChar, ClientReadHeaders, ClientReadContent - + AsyncClient = ref object c: AsyncSocket mode: ClientMode dataLen: int headers: StringTableRef ## the parsed headers input: string ## the input buffer - + AsyncScgiStateObj = object - handleRequest: proc (client: AsyncSocket, + handleRequest: proc (client: AsyncSocket, input: string, headers: StringTableRef) {.closure, gcsafe.} asyncServer: AsyncSocket @@ -98,19 +98,19 @@ type PAsyncScgiState: AsyncScgiState, scgiError: raiseScgiError].} proc recvBuffer(s: var ScgiState, L: int) = - if L > s.bufLen: + if L > s.bufLen: s.bufLen = L s.input = newString(L) - if L > 0 and recv(s.client, cstring(s.input), L) != L: + if L > 0 and recv(s.client, cstring(s.input), L) != L: raiseScgiError("could not read all data") setLen(s.input, L) - + proc open*(s: var ScgiState, port = Port(4000), address = "127.0.0.1", - reuseAddr = false) = + reuseAddr = false) = ## opens a connection. s.bufLen = 4000 s.input = newString(s.bufLen) # will be reused - + s.server = socket() if s.server == invalidSocket: raiseOSError(osLastError()) new(s.client) # Initialise s.client for `next` @@ -120,12 +120,12 @@ proc open*(s: var ScgiState, port = Port(4000), address = "127.0.0.1", s.server.setSockOpt(OptReuseAddr, true) bindAddr(s.server, port, address) listen(s.server) - -proc close*(s: var ScgiState) = + +proc close*(s: var ScgiState) = ## closes the connection. s.server.close() -proc next*(s: var ScgiState, timeout: int = -1): bool = +proc next*(s: var ScgiState, timeout: int = -1): bool = ## proceed to the first/next request. Waits ``timeout`` milliseconds for a ## request, if ``timeout`` is `-1` then this function will never time out. ## Returns `true` if a new request has been processed. @@ -139,18 +139,18 @@ proc next*(s: var ScgiState, timeout: int = -1): bool = if d == '\0': s.client.close() return false - if d notin strutils.Digits: + if d notin strutils.Digits: if d != ':': raiseScgiError("':' after length expected") break - L = L * 10 + ord(d) - ord('0') + L = L * 10 + ord(d) - ord('0') recvBuffer(s, L+1) s.headers = parseHeaders(s.input, L) if s.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected") L = parseInt(s.headers["CONTENT_LENGTH"]) recvBuffer(s, L) return true - -proc writeStatusOkTextContent*(c: Socket, contentType = "text/html") = + +proc writeStatusOkTextContent*(c: Socket, contentType = "text/html") = ## sends the following string to the socket `c`:: ## ## Status: 200 OK\r\LContent-Type: text/html\r\L\r\L @@ -159,9 +159,9 @@ proc writeStatusOkTextContent*(c: Socket, contentType = "text/html") = c.send("Status: 200 OK\r\L" & "Content-Type: $1\r\L\r\L" % contentType) -proc run*(handleRequest: proc (client: Socket, input: string, +proc run*(handleRequest: proc (client: Socket, input: string, headers: StringTableRef): bool {.nimcall,gcsafe.}, - port = Port(4000)) = + port = Port(4000)) = ## encapsulates the SCGI object and main loop. var s: ScgiState s.open(port) @@ -197,7 +197,7 @@ proc checkCloseSocket(client: AsyncClient) = s.close() s.delHandleWrite() else: client.c.close() - + proc handleClientRead(client: AsyncClient, s: AsyncScgiState) = case client.mode of ClientReadChar: @@ -223,7 +223,7 @@ proc handleClientRead(client: AsyncClient, s: AsyncScgiState) = client.headers = parseHeaders(client.input, client.input.len-1) if client.headers["SCGI"] != "1": raiseScgiError("SCGI Version 1 expected") client.input = "" # For next part - + let contentLen = parseInt(client.headers["CONTENT_LENGTH"]) if contentLen > 0: client.mode = ClientReadContent @@ -250,12 +250,12 @@ proc handleAccept(sock: AsyncSocket, s: AsyncScgiState) = accept(s.asyncServer, client) var asyncClient = AsyncClient(c: client, mode: ClientReadChar, dataLen: 0, headers: newStringTable(), input: "") - client.handleRead = + client.handleRead = proc (sock: AsyncSocket) = handleClientRead(asyncClient, s) s.disp.register(client) -proc open*(handleRequest: proc (client: AsyncSocket, +proc open*(handleRequest: proc (client: AsyncSocket, input: string, headers: StringTableRef) {. closure, gcsafe.}, port = Port(4000), address = "127.0.0.1", @@ -286,7 +286,7 @@ proc close*(s: AsyncScgiState) = when false: var counter = 0 - proc handleRequest(client: Socket, input: string, + proc handleRequest(client: Socket, input: string, headers: StringTableRef): bool {.procvar.} = inc(counter) client.writeStatusOkTextContent() diff --git a/lib/pure/smtp.nim b/lib/pure/smtp.nim index c1bc259a5..b2adac2f3 100644 --- a/lib/pure/smtp.nim +++ b/lib/pure/smtp.nim @@ -7,25 +7,25 @@ # distribution, for details about the copyright. # -## This module implements the SMTP client protocol as specified by RFC 5321, +## This module implements the SMTP client protocol as specified by RFC 5321, ## this can be used to send mail to any SMTP Server. -## -## This module also implements the protocol used to format messages, +## +## This module also implements the protocol used to format messages, ## as specified by RFC 2822. -## +## ## Example gmail use: -## -## +## +## ## .. code-block:: Nim -## var msg = createMessage("Hello from Nim's SMTP", -## "Hello!.\n Is this awesome or what?", +## var msg = createMessage("Hello from Nim's SMTP", +## "Hello!.\n Is this awesome or what?", ## @["foo@gmail.com"]) ## var smtp = connect("smtp.gmail.com", 465, true, true) ## smtp.auth("username", "password") ## smtp.sendmail("username@gmail.com", @["foo@gmail.com"], $msg) -## -## -## For SSL support this module relies on OpenSSL. If you want to +## +## +## For SSL support this module relies on OpenSSL. If you want to ## enable SSL, compile with ``-d:ssl``. import net, strutils, strtabs, base64, os @@ -35,14 +35,14 @@ type Smtp* = object sock: Socket debug: bool - + Message* = object msgTo: seq[string] msgCc: seq[string] msgSubject: string msgOtherHeaders: StringTableRef msgBody: string - + ReplyError* = object of IOError AsyncSmtp* = ref object @@ -84,7 +84,7 @@ when not defined(ssl): else: let defaultSSLContext = newContext(verifyMode = CVerifyNone) -proc connect*(address: string, port = Port(25), +proc connect*(address: string, port = Port(25), ssl = false, debug = false, sslContext = defaultSSLContext): Smtp = ## Establishes a connection with a SMTP server. @@ -94,17 +94,17 @@ proc connect*(address: string, port = Port(25), when compiledWithSsl: sslContext.wrapSocket(result.sock) else: - raise newException(ESystem, + raise newException(ESystem, "SMTP module compiled without SSL support") result.sock.connect(address, port) result.debug = debug - + result.checkReply("220") result.debugSend("HELO " & address & "\c\L") result.checkReply("250") proc auth*(smtp: var Smtp, username, password: string) = - ## Sends an AUTH command to the server to login as the `username` + ## Sends an AUTH command to the server to login as the `username` ## using `password`. ## May fail with ReplyError. @@ -113,13 +113,13 @@ proc auth*(smtp: var Smtp, username, password: string) = # i.e "334 VXNlcm5hbWU6" smtp.debugSend(encode(username) & "\c\L") smtp.checkReply("334") # TODO: Same as above, only "Password:" (I think?) - + smtp.debugSend(encode(password) & "\c\L") smtp.checkReply("235") # Check whether the authentification was successful. proc sendmail*(smtp: var Smtp, fromaddr: string, toaddrs: seq[string], msg: string) = - ## Sends `msg` from `fromaddr` to `toaddr`. + ## Sends `msg` from `fromaddr` to `toaddr`. ## Messages may be formed using ``createMessage`` by converting the ## Message into a string. @@ -128,7 +128,7 @@ proc sendmail*(smtp: var Smtp, fromaddr: string, for address in items(toaddrs): smtp.debugSend("RCPT TO:<" & address & ">\c\L") smtp.checkReply("250") - + # Send the message smtp.debugSend("DATA " & "\c\L") smtp.checkReply("354") @@ -175,7 +175,7 @@ proc `$`*(msg: Message): string = result.add("\c\L") result.add(msg.msgBody) - + proc newAsyncSmtp*(address: string, port: Port, useSsl = false, sslContext = defaultSslContext): AsyncSmtp = ## Creates a new ``AsyncSmtp`` instance. @@ -189,7 +189,7 @@ proc newAsyncSmtp*(address: string, port: Port, useSsl = false, when compiledWithSsl: sslContext.wrapSocket(result.sock) else: - raise newException(ESystem, + raise newException(ESystem, "SMTP module compiled without SSL support") proc quitExcpt(smtp: AsyncSmtp, msg: string): Future[void] = @@ -216,7 +216,7 @@ proc connect*(smtp: AsyncSmtp) {.async.} = await smtp.checkReply("250") proc auth*(smtp: AsyncSmtp, username, password: string) {.async.} = - ## Sends an AUTH command to the server to login as the `username` + ## Sends an AUTH command to the server to login as the `username` ## using `password`. ## May fail with ReplyError. @@ -225,7 +225,7 @@ proc auth*(smtp: AsyncSmtp, username, password: string) {.async.} = # i.e "334 VXNlcm5hbWU6" await smtp.sock.send(encode(username) & "\c\L") await smtp.checkReply("334") # TODO: Same as above, only "Password:" (I think?) - + await smtp.sock.send(encode(password) & "\c\L") await smtp.checkReply("235") # Check whether the authentification was successful. @@ -240,7 +240,7 @@ proc sendMail*(smtp: AsyncSmtp, fromAddr: string, for address in items(toAddrs): await smtp.sock.send("RCPT TO:<" & address & ">\c\L") await smtp.checkReply("250") - + # Send the message await smtp.sock.send("DATA " & "\c\L") await smtp.checkReply("354") @@ -254,24 +254,24 @@ proc close*(smtp: AsyncSmtp) {.async.} = smtp.sock.close() when not defined(testing) and isMainModule: - #var msg = createMessage("Test subject!", + #var msg = createMessage("Test subject!", # "Hello, my name is dom96.\n What\'s yours?", @["dominik@localhost"]) #echo(msg) #var smtp = connect("localhost", 25, False, True) #smtp.sendmail("root@localhost", @["dominik@localhost"], $msg) - + #echo(decode("a17sm3701420wbe.12")) proc main() {.async.} = var client = newAsyncSmtp("smtp.gmail.com", Port(465), true) await client.connect() await client.auth("johndoe", "foo") - var msg = createMessage("Hello from Nim's SMTP!", - "Hello!!!!.\n Is this awesome or what?", + var msg = createMessage("Hello from Nim's SMTP!", + "Hello!!!!.\n Is this awesome or what?", @["blah@gmail.com"]) echo(msg) await client.sendMail("blah@gmail.com", @["blah@gmail.com"], $msg) await client.close() - + waitFor main() diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 18b2ab1e9..29f0bf87d 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -51,17 +51,17 @@ else: # Note: The enumerations are mapped to Window's constants. -when defined(ssl): +when defined(ssl): type SSLError* = object of Exception SSLCVerifyMode* = enum CVerifyNone, CVerifyPeer - + SSLProtVersion* = enum protSSLv2, protSSLv3, protTLSv1, protSSLv23 - + SSLContext* = distinct SSLCTX SSLAcceptResult* = enum @@ -93,11 +93,11 @@ type sslPeekChar: char of false: nil nonblocking: bool - + Socket* = ref SocketImpl - + Port* = distinct uint16 ## port type - + Domain* = enum ## domain, which specifies the protocol family of the ## created socket. Other domains than those that are listed ## here are unsupported. @@ -112,7 +112,7 @@ type SOCK_SEQPACKET = 5 ## reliable sequenced packet service Protocol* = enum ## third argument to `socket` proc - IPPROTO_TCP = 6, ## Transmission control protocol. + IPPROTO_TCP = 6, ## Transmission control protocol. IPPROTO_UDP = 17, ## User datagram protocol. IPPROTO_IP, ## Internet protocol. Unsupported on Windows. IPPROTO_IPV6, ## Internet Protocol Version 6. Unsupported on Windows. @@ -178,7 +178,7 @@ proc `==`*(a, b: Port): bool {.borrow.} proc `$`*(p: Port): string {.borrow.} ## returns the port number as a string -proc ntohl*(x: int32): int32 = +proc ntohl*(x: int32): int32 = ## Converts 32-bit integers from network to host byte order. ## On machines where the host byte order is the same as network byte order, ## this is a no-op; otherwise, it performs a 4-byte swap operation. @@ -206,7 +206,7 @@ proc htons*(x: int16): int16 = ## On machines where the host byte order is the same as network byte ## order, this is a no-op; otherwise, it performs a 2-byte swap operation. result = sockets.ntohs(x) - + when defined(Posix): proc toInt(domain: Domain): cint = case domain @@ -234,19 +234,19 @@ when defined(Posix): else: discard else: - proc toInt(domain: Domain): cint = + proc toInt(domain: Domain): cint = result = toU16(ord(domain)) proc toInt(typ: SockType): cint = result = cint(ord(typ)) - + proc toInt(p: Protocol): cint = result = cint(ord(p)) proc socket*(domain: Domain = AF_INET, typ: SockType = SOCK_STREAM, protocol: Protocol = IPPROTO_TCP, buffered = true): Socket = ## Creates a new socket; returns `InvalidSocket` if an error occurs. - + # TODO: Perhaps this should just raise EOS when an error occurs. when defined(Windows): result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered) @@ -277,27 +277,27 @@ when defined(ssl): raise newException(system.IOError, "Certificate file could not be found: " & certFile) if keyFile != "" and not existsFile(keyFile): raise newException(system.IOError, "Key file could not be found: " & keyFile) - + if certFile != "": var ret = SSLCTXUseCertificateChainFile(ctx, certFile) if ret != 1: raiseSslError() - + # TODO: Password? www.rtfm.com/openssl-examples/part1.pdf if keyFile != "": if SSL_CTX_use_PrivateKey_file(ctx, keyFile, SSL_FILETYPE_PEM) != 1: raiseSslError() - + if SSL_CTX_check_private_key(ctx) != 1: raiseSslError("Verification of private key file failed.") proc newContext*(protVersion = protSSLv23, verifyMode = CVerifyPeer, certFile = "", keyFile = ""): SSLContext = ## Creates an SSL context. - ## - ## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are - ## are available with the addition of ``ProtSSLv23`` which allows for + ## + ## Protocol version specifies the protocol to use. SSLv2, SSLv3, TLSv1 are + ## are available with the addition of ``ProtSSLv23`` which allows for ## compatibility with all of them. ## ## There are currently only two options for verify mode; @@ -322,7 +322,7 @@ when defined(ssl): newCTX = SSL_CTX_new(SSLv3_method()) of protTLSv1: newCTX = SSL_CTX_new(TLSv1_method()) - + if newCTX.SSLCTXSetCipherList("ALL") != 1: raiseSslError() case verifyMode @@ -343,7 +343,7 @@ when defined(ssl): ## ## **Disclaimer**: This code is not well tested, may be very unsafe and ## prone to security vulnerabilities. - + socket.isSSL = true socket.sslContext = ctx socket.sslHandle = SSLNew(SSLCTX(socket.sslContext)) @@ -351,7 +351,7 @@ when defined(ssl): socket.sslHasPeekChar = false if socket.sslHandle == nil: raiseSslError() - + if SSLSetFd(socket.sslHandle, socket.fd) != 1: raiseSslError() @@ -382,7 +382,7 @@ proc raiseSocketError*(socket: Socket, err: int = -1, async = false) = of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: raiseSslError() else: raiseSslError("Unknown Error") - + if err == -1 and not (when defined(ssl): socket.isSSL else: false): let lastError = osLastError() if async: @@ -397,15 +397,15 @@ proc raiseSocketError*(socket: Socket, err: int = -1, async = false) = else: raiseOSError(lastError) proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} = - ## Marks ``socket`` as accepting connections. - ## ``Backlog`` specifies the maximum length of the + ## Marks ``socket`` as accepting connections. + ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. if listen(socket.fd, cint(backlog)) < 0'i32: raiseOSError(osLastError()) proc invalidIp4(s: string) {.noreturn, noinline.} = raise newException(ValueError, "invalid ip4 address: " & s) -proc parseIp4*(s: string): BiggestInt = +proc parseIp4*(s: string): BiggestInt = ## parses an IP version 4 in dotted decimal form like "a.b.c.d". ## ## This is equivalent to `inet_ntoa`:idx:. @@ -469,8 +469,8 @@ proc bindAddr*(socket: Socket, port = Port(0), address = "") {. gaiNim(address, port, hints, aiList) if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrlen.SockLen) < 0'i32: raiseOSError(osLastError()) - -proc getSockName*(socket: Socket): Port = + +proc getSockName*(socket: Socket): Port = ## returns the socket's associated port number. var name: Sockaddr_in when defined(Windows): @@ -485,14 +485,14 @@ proc getSockName*(socket: Socket): Port = raiseOSError(osLastError()) result = Port(sockets.ntohs(name.sin_port)) -template acceptAddrPlain(noClientRet, successRet: expr, +template acceptAddrPlain(noClientRet, successRet: expr, sslImplementation: stmt): stmt {.immediate.} = assert(client != nil) var sockAddress: Sockaddr_in var addrLen = sizeof(sockAddress).SockLen var sock = accept(server.fd, cast[ptr SockAddr](addr(sockAddress)), addr(addrLen)) - + if sock == osInvalidSocket: let err = osLastError() when defined(windows): @@ -537,7 +537,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string) {. ## The resulting client will inherit any properties of the server socket. For ## example: whether the socket is buffered or not. ## - ## **Note**: ``client`` must be initialised (with ``new``), this function + ## **Note**: ``client`` must be initialised (with ``new``), this function ## makes no effort to initialise the ``client`` variable. ## ## **Warning:** When using SSL with non-blocking sockets, it is best to use @@ -546,7 +546,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string) {. when defined(ssl): if server.isSSL: # We must wrap the client sock in a ssl context. - + server.sslContext.wrapSocket(client) let ret = SSLAccept(client.sslHandle) while ret <= 0: @@ -572,9 +572,9 @@ when defined(ssl): proc acceptAddrSSL*(server: Socket, client: var Socket, address: var string): SSLAcceptResult {. tags: [ReadIOEffect].} = - ## This procedure should only be used for non-blocking **SSL** sockets. + ## This procedure should only be used for non-blocking **SSL** sockets. ## It will immediately return with one of the following values: - ## + ## ## ``AcceptSuccess`` will be returned when a client has been successfully ## accepted and the handshake has been successfully performed between ## ``server`` and the newly connected client. @@ -591,7 +591,7 @@ when defined(ssl): if server.isSSL: client.setBlocking(false) # We must wrap the client sock in a ssl context. - + if not client.isSSL or client.sslHandle == nil: server.sslContext.wrapSocket(client) let ret = SSLAccept(client.sslHandle) @@ -623,10 +623,10 @@ when defined(ssl): proc accept*(server: Socket, client: var Socket) {.tags: [ReadIOEffect].} = ## Equivalent to ``acceptAddr`` but doesn't return the address, only the ## socket. - ## + ## ## **Note**: ``client`` must be initialised (with ``new``), this function ## makes no effort to initialise the ``client`` variable. - + var addrDummy = "" acceptAddr(server, client, addrDummy) @@ -662,7 +662,7 @@ proc close*(socket: Socket) = socket.sslHandle = nil proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} = - ## Searches the database from the beginning and finds the first entry for + ## Searches the database from the beginning and finds the first entry for ## which the service name specified by ``name`` matches the s_name member ## and the protocol name specified by ``proto`` matches the s_proto member. ## @@ -676,10 +676,10 @@ proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} = result.aliases = cstringArrayToSeq(s.s_aliases) result.port = Port(s.s_port) result.proto = $s.s_proto - -proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} = - ## Searches the database from the beginning and finds the first entry for - ## which the port specified by ``port`` matches the s_port member and the + +proc getServByPort*(port: Port, proto: string): Servent {.tags: [ReadIOEffect].} = + ## Searches the database from the beginning and finds the first entry for + ## which the port specified by ``port`` matches the s_port member and the ## protocol name specified by ``proto`` matches the s_proto member. ## ## On posix this will search through the ``/etc/services`` file. @@ -697,20 +697,20 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} = ## This function will lookup the hostname of an IP Address. var myaddr: InAddr myaddr.s_addr = inet_addr(ip) - + when defined(windows): var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, cint(sockets.AF_INET)) if s == nil: raiseOSError(osLastError()) else: - var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, + var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen, cint(posix.AF_INET)) if s == nil: raiseOSError(osLastError(), $hstrerror(h_errno)) - + result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) - when defined(windows): + when defined(windows): result.addrtype = Domain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: @@ -722,7 +722,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = +proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = ## This function will lookup the IP address of a hostname. when defined(Windows): var s = winlean.gethostbyname(name) @@ -731,7 +731,7 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = if s == nil: raiseOSError(osLastError()) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) - when defined(windows): + when defined(windows): result.addrtype = Domain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: @@ -744,11 +744,11 @@ proc getHostByName*(name: string): Hostent {.tags: [ReadIOEffect].} = result.length = int(s.h_length) proc getSockOptInt*(socket: Socket, level, optname: int): int {. - tags: [ReadIOEffect].} = + tags: [ReadIOEffect].} = ## getsockopt for integer options. var res: cint var size = sizeof(res).SockLen - if getsockopt(socket.fd, cint(level), cint(optname), + if getsockopt(socket.fd, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: raiseOSError(osLastError()) result = int(res) @@ -757,7 +757,7 @@ proc setSockOptInt*(socket: Socket, level, optname, optval: int) {. tags: [WriteIOEffect].} = ## setsockopt for integer options. var value = cint(optval) - if setsockopt(socket.fd, cint(level), cint(optname), addr(value), + if setsockopt(socket.fd, cint(level), cint(optname), addr(value), sizeof(value).SockLen) < 0'i32: raiseOSError(osLastError()) @@ -776,7 +776,7 @@ proc getSockOpt*(socket: Socket, opt: SOBool, level = SOL_SOCKET): bool {. ## Retrieves option ``opt`` as a boolean value. var res: cint var size = sizeof(res).SockLen - if getsockopt(socket.fd, cint(level), toCInt(opt), + if getsockopt(socket.fd, cint(level), toCInt(opt), addr(res), addr(size)) < 0'i32: raiseOSError(osLastError()) result = res != 0 @@ -785,11 +785,11 @@ proc setSockOpt*(socket: Socket, opt: SOBool, value: bool, level = SOL_SOCKET) { tags: [WriteIOEffect].} = ## Sets option ``opt`` to a boolean value specified by ``value``. var valuei = cint(if value: 1 else: 0) - if setsockopt(socket.fd, cint(level), toCInt(opt), addr(valuei), + if setsockopt(socket.fd, cint(level), toCInt(opt), addr(valuei), sizeof(valuei).SockLen) < 0'i32: raiseOSError(osLastError()) -proc connect*(socket: Socket, address: string, port = Port(0), +proc connect*(socket: Socket, address: string, port = Port(0), af: Domain = AF_INET) {.tags: [ReadIOEffect].} = ## Connects socket to ``address``:``port``. ``Address`` can be an IP address or a ## host name. If ``address`` is a host name, this function will try each IP @@ -816,7 +816,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), freeaddrinfo(aiList) if not success: raiseOSError(lastError) - + when defined(ssl): if socket.isSSL: let ret = SSLConnect(socket.sslHandle) @@ -825,7 +825,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), case err of SSL_ERROR_ZERO_RETURN: raiseSslError("TLS/SSL connection failed to initiate, socket closed prematurely.") - of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT, + of SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE, SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT: raiseSslError("The operation did not complete. Perhaps you should use connectAsync?") of SSL_ERROR_WANT_X509_LOOKUP: @@ -834,7 +834,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), raiseSslError() else: raiseSslError("Unknown error") - + when false: var s: TSockAddrIn s.sin_addr.s_addr = inet_addr(address) @@ -842,7 +842,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), when defined(windows): s.sin_family = toU16(ord(af)) else: - case af + case af of AF_UNIX: s.sin_family = posix.AF_UNIX of AF_INET: s.sin_family = posix.AF_INET of AF_INET6: s.sin_family = posix.AF_INET6 @@ -886,7 +886,7 @@ proc connectAsync*(socket: Socket, name: string, port = Port(0), if lastError.int32 == EINTR or lastError.int32 == EINPROGRESS: success = true break - + it = it.ai_next freeaddrinfo(aiList) @@ -942,12 +942,12 @@ proc timeValFromMilliseconds(timeout = 500): Timeval = result.tv_sec = seconds.int32 result.tv_usec = ((timeout - seconds * 1000) * 1000).int32 -proc createFdSet(fd: var TFdSet, s: seq[Socket], m: var int) = +proc createFdSet(fd: var TFdSet, s: seq[Socket], m: var int) = FD_ZERO(fd) - for i in items(s): + for i in items(s): m = max(m, int(i.fd)) FD_SET(i.fd, fd) - + proc pruneSocketSet(s: var seq[Socket], fd: var TFdSet) = var i = 0 var L = s.len @@ -982,13 +982,13 @@ proc checkBuffer(readfds: var seq[Socket]): int = if result > 0: readfds = res -proc select*(readfds, writefds, exceptfds: var seq[Socket], - timeout = 500): int {.tags: [ReadIOEffect].} = +proc select*(readfds, writefds, exceptfds: var seq[Socket], + timeout = 500): int {.tags: [ReadIOEffect].} = ## Traditional select function. This function will return the number of ## sockets that are ready to be read from, written to, or which have errors. - ## If there are none; 0 is returned. + ## If there are none; 0 is returned. ## ``Timeout`` is in milliseconds and -1 can be specified for no timeout. - ## + ## ## Sockets which are **not** ready for reading, writing or which don't have ## errors waiting on them are removed from the ``readfds``, ``writefds``, ## ``exceptfds`` sequences respectively. @@ -997,44 +997,44 @@ proc select*(readfds, writefds, exceptfds: var seq[Socket], return buffersFilled var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) - + var rd, wr, ex: TFdSet var m = 0 createFdSet((rd), readfds, m) createFdSet((wr), writefds, m) createFdSet((ex), exceptfds, m) - + if timeout != -1: result = int(select(cint(m+1), addr(rd), addr(wr), addr(ex), addr(tv))) else: result = int(select(cint(m+1), addr(rd), addr(wr), addr(ex), nil)) - + pruneSocketSet(readfds, (rd)) pruneSocketSet(writefds, (wr)) pruneSocketSet(exceptfds, (ex)) -proc select*(readfds, writefds: var seq[Socket], +proc select*(readfds, writefds: var seq[Socket], timeout = 500): int {.tags: [ReadIOEffect].} = ## Variant of select with only a read and write list. let buffersFilled = checkBuffer(readfds) if buffersFilled > 0: return buffersFilled var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) - + var rd, wr: TFdSet var m = 0 createFdSet((rd), readfds, m) createFdSet((wr), writefds, m) - + if timeout != -1: result = int(select(cint(m+1), addr(rd), addr(wr), nil, addr(tv))) else: result = int(select(cint(m+1), addr(rd), addr(wr), nil, nil)) - + pruneSocketSet(readfds, (rd)) pruneSocketSet(writefds, (wr)) -proc selectWrite*(writefds: var seq[Socket], +proc selectWrite*(writefds: var seq[Socket], timeout = 500): int {.tags: [ReadIOEffect].} = ## When a socket in ``writefds`` is ready to be written to then a non-zero ## value will be returned specifying the count of the sockets which can be @@ -1044,16 +1044,16 @@ proc selectWrite*(writefds: var seq[Socket], ## ``timeout`` is specified in milliseconds and ``-1`` can be specified for ## an unlimited time. var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) - + var wr: TFdSet var m = 0 createFdSet((wr), writefds, m) - + if timeout != -1: result = int(select(cint(m+1), nil, addr(wr), nil, addr(tv))) else: result = int(select(cint(m+1), nil, addr(wr), nil, nil)) - + pruneSocketSet(writefds, (wr)) proc select*(readfds: var seq[Socket], timeout = 500): int = @@ -1062,16 +1062,16 @@ proc select*(readfds: var seq[Socket], timeout = 500): int = if buffersFilled > 0: return buffersFilled var tv {.noInit.}: Timeval = timeValFromMilliseconds(timeout) - + var rd: TFdSet var m = 0 createFdSet((rd), readfds, m) - + if timeout != -1: result = int(select(cint(m+1), addr(rd), nil, nil, addr(tv))) else: result = int(select(cint(m+1), addr(rd), nil, nil, nil)) - + pruneSocketSet(readfds, (rd)) proc readIntoBuf(socket: Socket, flags: int32): int = @@ -1107,12 +1107,12 @@ proc recv*(socket: Socket, data: pointer, size: int): int {.tags: [ReadIOEffect] if socket.isBuffered: if socket.bufLen == 0: retRead(0'i32, 0) - + var read = 0 while read < size: if socket.currPos >= socket.bufLen: retRead(0'i32, read) - + let chunk = min(socket.bufLen-socket.currPos, size-read) var d = cast[cstring](data) copyMem(addr(d[read]), addr(socket.buffer[socket.currPos]), chunk) @@ -1155,7 +1155,7 @@ proc waitFor(socket: Socket, waited: var float, timeout, size: int, else: if timeout - int(waited * 1000.0) < 1: raise newException(TimeoutError, "Call to '" & funcName & "' timed out.") - + when defined(ssl): if socket.isSSL: if socket.hasDataBuffered: @@ -1164,7 +1164,7 @@ proc waitFor(socket: Socket, waited: var float, timeout, size: int, let sslPending = SSLPending(socket.sslHandle) if sslPending != 0: return sslPending - + var s = @[socket] var startTime = epochTime() let selRet = select(s, timeout - int(waited * 1000.0)) @@ -1176,8 +1176,8 @@ proc waitFor(socket: Socket, waited: var float, timeout, size: int, proc recv*(socket: Socket, data: pointer, size: int, timeout: int): int {. tags: [ReadIOEffect, TimeEffect].} = ## overload with a ``timeout`` parameter in milliseconds. - var waited = 0.0 # number of seconds already waited - + var waited = 0.0 # number of seconds already waited + var read = 0 while read < size: let avail = waitFor(socket, waited, timeout, size-read, "recv") @@ -1187,7 +1187,7 @@ proc recv*(socket: Socket, data: pointer, size: int, timeout: int): int {. if result < 0: return result inc(read, result) - + result = read proc recv*(socket: Socket, data: var string, size: int, timeout = -1): int = @@ -1231,7 +1231,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} = var res = socket.readIntoBuf(0'i32) if res <= 0: result = res - + c = socket.buffer[socket.currPos] else: when defined(ssl): @@ -1239,7 +1239,7 @@ proc peekChar(socket: Socket, c: var char): int {.tags: [ReadIOEffect].} = if not socket.sslHasPeekChar: result = SSLRead(socket.sslHandle, addr(socket.sslPeekChar), 1) socket.sslHasPeekChar = true - + c = socket.sslPeekChar return result = recv(socket.fd, addr(c), 1, MSG_PEEK) @@ -1251,11 +1251,11 @@ proc recvLine*(socket: Socket, line: var TaintedString, timeout = -1): bool {. ## If a full line is received ``\r\L`` is not ## added to ``line``, however if solely ``\r\L`` is received then ``line`` ## will be set to it. - ## + ## ## ``True`` is returned if data is available. ``False`` suggests an ## error, EOS exceptions are not raised and ``False`` is simply returned ## instead. - ## + ## ## If the socket is disconnected, ``line`` will be set to ``""`` and ``True`` ## will be returned. ## @@ -1264,7 +1264,7 @@ proc recvLine*(socket: Socket, line: var TaintedString, timeout = -1): bool {. ## ## **Deprecated since version 0.9.2**: This function has been deprecated in ## favour of readLine. - + template addNLIfEmpty(): stmt = if line.len == 0: line.add("\c\L") @@ -1286,7 +1286,7 @@ proc recvLine*(socket: Socket, line: var TaintedString, timeout = -1): bool {. elif n <= 0: return false addNLIfEmpty() return true - elif c == '\L': + elif c == '\L': addNLIfEmpty() return true add(line.string, c) @@ -1298,14 +1298,14 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1) {. ## If a full line is read ``\r\L`` is not ## added to ``line``, however if solely ``\r\L`` is read then ``line`` ## will be set to it. - ## + ## ## If the socket is disconnected, ``line`` will be set to ``""``. ## ## An EOS exception will be raised in the case of a socket error. ## ## A timeout can be specified in milliseconds, if data is not received within ## the specified time an ETimeout exception will be raised. - + template addNLIfEmpty(): stmt = if line.len == 0: line.add("\c\L") @@ -1327,12 +1327,12 @@ proc readLine*(socket: Socket, line: var TaintedString, timeout = -1) {. elif n <= 0: socket.raiseSocketError() addNLIfEmpty() return - elif c == '\L': + elif c == '\L': addNLIfEmpty() return add(line.string, c) -proc recvLineAsync*(socket: Socket, +proc recvLineAsync*(socket: Socket, line: var TaintedString): RecvLineResult {.tags: [ReadIOEffect], deprecated.} = ## Similar to ``recvLine`` but designed for non-blocking sockets. ## @@ -1350,21 +1350,21 @@ proc recvLineAsync*(socket: Socket, while true: var c: char var n = recv(socket, addr(c), 1) - if n < 0: + if n < 0: return (if line.len == 0: RecvFail else: RecvPartialLine) - elif n == 0: + elif n == 0: return (if line.len == 0: RecvDisconnected else: RecvPartialLine) if c == '\r': n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) - elif n <= 0: + elif n <= 0: return (if line.len == 0: RecvFail else: RecvPartialLine) return RecvFullLine elif c == '\L': return RecvFullLine add(line.string, c) -proc readLineAsync*(socket: Socket, +proc readLineAsync*(socket: Socket, line: var TaintedString): ReadLineResult {.tags: [ReadIOEffect].} = ## Similar to ``recvLine`` but designed for non-blocking sockets. ## @@ -1376,24 +1376,24 @@ proc readLineAsync*(socket: Socket, ## * If no data could be retrieved; ``ReadNone`` is returned. ## * If call to ``recv`` failed; **an EOS exception is raised.** setLen(line.string, 0) - + template errorOrNone = socket.raiseSocketError(async = true) return ReadNone - + while true: var c: char var n = recv(socket, addr(c), 1) #echo(n) if n < 0: if line.len == 0: errorOrNone else: return ReadPartialLine - elif n == 0: + elif n == 0: return (if line.len == 0: ReadDisconnected else: ReadPartialLine) if c == '\r': n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) - elif n <= 0: + elif n <= 0: if line.len == 0: errorOrNone else: return ReadPartialLine return ReadFullLine elif c == '\L': return ReadFullLine @@ -1424,7 +1424,7 @@ proc recv*(socket: Socket): TaintedString {.tags: [ReadIOEffect], deprecated.} = var bytesRead = recv(socket, cstring(buf), bufSize-1) # Error if bytesRead == -1: OSError(osLastError()) - + buf[bytesRead] = '\0' # might not be necessary setLen(buf, bytesRead) add(result.string, buf) @@ -1442,13 +1442,13 @@ proc recvTimeout*(socket: Socket, timeout: int): TaintedString {. var s = @[socket] if s.select(timeout) != 1: raise newException(TimeoutError, "Call to recv() timed out.") - + return socket.recv {.pop.} proc recvAsync*(socket: Socket, s: var TaintedString): bool {. tags: [ReadIOEffect], deprecated.} = - ## receives all the data from a non-blocking socket. If socket is non-blocking + ## receives all the data from a non-blocking socket. If socket is non-blocking ## and there are no messages available, `False` will be returned. ## Other socket errors will result in an ``EOS`` error. ## If socket is not a connectionless socket and socket is not connected @@ -1478,7 +1478,7 @@ proc recvAsync*(socket: Socket, s: var TaintedString): bool {. of SSL_ERROR_SYSCALL, SSL_ERROR_SSL: raiseSslError() else: raiseSslError("Unknown Error") - + if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false): let err = osLastError() when defined(windows): @@ -1510,7 +1510,7 @@ proc recvFrom*(socket: Socket, data: var string, length: int, ## so when ``socket`` is buffered the non-buffered implementation will be ## used. Therefore if ``socket`` contains something in its buffer this ## function will make no effort to return it. - + # TODO: Buffered sockets data.setLen(length) var sockAddress: Sockaddr_in @@ -1524,7 +1524,7 @@ proc recvFrom*(socket: Socket, data: var string, length: int, port = ntohs(sockAddress.sin_port).Port proc recvFromAsync*(socket: Socket, data: var string, length: int, - address: var string, port: var Port, + address: var string, port: var Port, flags = 0'i32): bool {.tags: [ReadIOEffect].} = ## Variant of ``recvFrom`` for non-blocking sockets. Unlike ``recvFrom``, ## this function will raise an EOS error whenever a socket error occurs. @@ -1573,11 +1573,11 @@ proc send*(socket: Socket, data: pointer, size: int): int {. when defined(ssl): if socket.isSSL: return SSLWrite(socket.sslHandle, cast[cstring](data), size) - + when defined(windows) or defined(macosx): result = send(socket.fd, data, size.cint, 0'i32) else: - when defined(solaris): + when defined(solaris): const MSG_NOSIGNAL = 0 result = send(socket.fd, data, size, int32(MSG_NOSIGNAL)) @@ -1590,7 +1590,7 @@ proc send*(socket: Socket, data: string) {.tags: [WriteIOEffect].} = when defined(ssl): if socket.isSSL: raiseSslError() - + raiseOSError(osLastError()) if sent != data.len: @@ -1633,7 +1633,7 @@ proc sendAsync*(socket: Socket, data: string): int {.tags: [WriteIOEffect].} = if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: return 0 else: raiseOSError(err) - + proc trySend*(socket: Socket, data: string): bool {.tags: [WriteIOEffect].} = ## safe alternative to ``send``. Does not raise an EOS when an error occurs, @@ -1644,7 +1644,7 @@ proc sendTo*(socket: Socket, address: string, port: Port, data: pointer, size: int, af: Domain = AF_INET, flags = 0'i32): int {. tags: [WriteIOEffect].} = ## low-level sendTo proc. This proc sends ``data`` to the specified ``address``, - ## which may be an IP address or a hostname, if a hostname is specified + ## which may be an IP address or a hostname, if a hostname is specified ## this function will try each IP of that hostname. ## ## **Note:** This proc is not available for SSL sockets. @@ -1654,7 +1654,7 @@ proc sendTo*(socket: Socket, address: string, port: Port, data: pointer, hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) gaiNim(address, port, hints, aiList) - + # try all possibilities: var success = false var it = aiList @@ -1668,7 +1668,7 @@ proc sendTo*(socket: Socket, address: string, port: Port, data: pointer, freeaddrinfo(aiList) -proc sendTo*(socket: Socket, address: string, port: Port, +proc sendTo*(socket: Socket, address: string, port: Port, data: string): int {.tags: [WriteIOEffect].} = ## Friendlier version of the low-level ``sendTo``. result = socket.sendTo(address, port, cstring(data), data.len) @@ -1677,10 +1677,10 @@ when defined(Windows): const IOCPARM_MASK = 127 IOC_IN = int(-2147483648) - FIONBIO = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or + FIONBIO = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or (102 shl 8) or 126 - proc ioctlsocket(s: SocketHandle, cmd: clong, + proc ioctlsocket(s: SocketHandle, cmd: clong, argptr: ptr clong): cint {. stdcall, importc:"ioctlsocket", dynlib: "ws2_32.dll".} @@ -1713,7 +1713,7 @@ proc connect*(socket: Socket, address: string, port = Port(0), timeout: int, ## the connection to the server to be made. let originalStatus = not socket.nonblocking socket.setBlocking(false) - + socket.connectAsync(address, port, af) var s: seq[Socket] = @[socket] if selectWrite(s, timeout) != 1: diff --git a/lib/pure/subexes.nim b/lib/pure/subexes.nim index 46824645d..2d1adc0eb 100644 --- a/lib/pure/subexes.nim +++ b/lib/pure/subexes.nim @@ -77,7 +77,7 @@ proc getFormatArg(p: var FormatParser, a: openArray[string]): int = result = if not negative: j-1 else: a.len-j of 'a'..'z', 'A'..'Z', '\128'..'\255', '_': var name = "" - while f[i] in PatternChars: + while f[i] in PatternChars: name.add(f[i]) inc(i) result = findNormalized(name, a)+1 @@ -131,7 +131,7 @@ proc scanBranch(p: var FormatParser, a: openArray[string], while true: case f[i] of ']': break - of '|': + of '|': inc i elsePart = i inc c @@ -172,7 +172,7 @@ proc scanSlice(p: var FormatParser, a: openarray[string]): tuple[x, y: int] = var slice = false var i = p.i var f = p.f - + if f[i] == '{': inc i else: raiseInvalidFormat("'{' expected") if f[i] == '.' and f[i+1] == '.': @@ -193,12 +193,12 @@ proc scanSlice(p: var FormatParser, a: openarray[string]): tuple[x, y: int] = if f[i] != '}': raiseInvalidFormat("'}' expected") inc i p.i = i - + proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = var i = p.i var f = p.f case f[i] - of '$': + of '$': emitChar p, s, '$' inc i of '*': @@ -232,7 +232,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = # $' '~{1..3} # insert space followed by 1..3 if not empty inc i - call: + call: let (x, y) = scanSlice(p, a) var L = 0 for j in x..y: inc L, a[j].len @@ -258,7 +258,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = of 'i': inc i callNoLineLenTracking: scanQuote(p, indent, true) - + call: let (x, y) = scanSlice(p, a) if maxLen < 1: emitStrLinear(p, s, indent) @@ -266,7 +266,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = emitStr p, s, a[x] for j in x+1..y: emitStr p, s, sep - if items >= maxLen: + if items >= maxLen: emitStrLinear p, s, indent items = 0 emitStr p, s, a[j] @@ -274,7 +274,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = of 'c': inc i callNoLineLenTracking: scanQuote(p, indent, true) - + call: let (x, y) = scanSlice(p, a) if p.lineLen + a[x].len > maxLen: emitStrLinear(p, s, indent) @@ -283,7 +283,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = emitStr p, s, sep if p.lineLen + a[j].len > maxLen: emitStrLinear(p, s, indent) emitStr p, s, a[j] - + else: raiseInvalidFormat("unit 'c' (chars) or 'i' (items) expected") break StringJoin @@ -294,7 +294,7 @@ proc scanDollar(p: var FormatParser, a: openarray[string], s: var string) = emitStr p, s, sep emitStr p, s, a[j] else: - call: + call: var x = getFormatArg(p, a) emitStr p, s, a[x] p.i = i @@ -375,38 +375,38 @@ when isMainModule: doAssert "$1($', '{2..})" % ["f", "a", "b"] == "f(a, b)" doAssert "$[$1($', '{2..})|''''|fg'$3']1" % ["7", "a", "b"] == "fg$3" - + doAssert "$[$#($', '{#..})|''''|$3]1" % ["0", "a", "b"] == "0(a, b)" doAssert "$' '~{..}" % "" == "" doAssert "$' '~{..}" % "P0" == " P0" doAssert "${$1}" % "1" == "1" doAssert "${$$-1} $$1" % "1" == "1 $1" - + doAssert "$#($', '10c'\n '{#..})" % ["doAssert", "longishA", "longish"] == """doAssert( - longishA, + longishA, longish)""" - + assert "type MyEnum* = enum\n $', '2i'\n '{..}" % ["fieldA", "fieldB", "FiledClkad", "fieldD", "fieldE", "longishFieldName"] == strutils.unindent """ type MyEnum* = enum - fieldA, fieldB, - FiledClkad, fieldD, + fieldA, fieldB, + FiledClkad, fieldD, fieldE, longishFieldName""" - + doAssert subex"$1($', '{2..})" % ["f", "a", "b", "c"] == "f(a, b, c)" - + doAssert subex"$1 $[files|file|files]{1} copied" % ["1"] == "1 file copied" - + doAssert subex"$['''|'|''''|']']#" % "0" == "'|" - + assert subex("type\n Enum = enum\n $', '40c'\n '{..}") % [ "fieldNameA", "fieldNameB", "fieldNameC", "fieldNameD"] == strutils.unindent """ type Enum = enum - fieldNameA, fieldNameB, fieldNameC, + fieldNameA, fieldNameB, fieldNameC, fieldNameD""" - - + + diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 5e20db32b..396957f6c 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -1285,7 +1285,7 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} = result = a.len - b.len proc reversed*(s: string): string = - ## Returns the reverse of ``s``, interpreting it as Unicode characters. + ## Returns the reverse of ``s``, interpreting it as Unicode characters. ## Unicode combining characters are correctly interpreted as well: ## ## .. code-block:: nim diff --git a/lib/pure/unidecode/unidecode.nim b/lib/pure/unidecode/unidecode.nim index a83b9be0f..9d8843f06 100644 --- a/lib/pure/unidecode/unidecode.nim +++ b/lib/pure/unidecode/unidecode.nim @@ -7,19 +7,19 @@ # distribution, for details about the copyright. # -## This module is based on Python's Unidecode module by Tomaz Solc, -## which in turn is based on the ``Text::Unidecode`` Perl module by -## Sean M. Burke +## This module is based on Python's Unidecode module by Tomaz Solc, +## which in turn is based on the ``Text::Unidecode`` Perl module by +## Sean M. Burke ## (http://search.cpan.org/~sburke/Text-Unidecode-0.04/lib/Text/Unidecode.pm ). ## ## It provides a single proc that does Unicode to ASCII transliterations: ## It finds the sequence of ASCII characters that is the closest approximation ## to the Unicode string. ## -## For example, the closest to string "Äußerst" in ASCII is "Ausserst". Some -## information is lost in this transformation, of course, since several Unicode +## For example, the closest to string "Äußerst" in ASCII is "Ausserst". Some +## information is lost in this transformation, of course, since several Unicode ## strings can be transformed in the same ASCII representation. So this is a -## strictly one-way transformation. However a human reader will probably +## strictly one-way transformation. However a human reader will probably ## still be able to guess what original string was meant from the context. ## ## This module needs the data file "unidecode.dat" to work: You can either @@ -31,7 +31,7 @@ import unicode when defined(embedUnidecodeTable): import strutils - + const translationTable = splitLines(slurp"unidecode/unidecode.dat") else: # shared is fine for threading: @@ -49,12 +49,12 @@ proc loadUnidecodeTable*(datafile = "unidecode.dat") = translationTable[i] = line.string inc(i) -proc unidecode*(s: string): string = +proc unidecode*(s: string): string = ## Finds the sequence of ASCII characters that is the closest approximation ## to the UTF-8 string `s`. ## - ## Example: - ## + ## Example: + ## ## ..code-block:: nim ## ## unidecode("\x53\x17\x4E\xB0") @@ -63,7 +63,7 @@ proc unidecode*(s: string): string = ## assert(not isNil(translationTable)) result = "" - for r in runes(s): + for r in runes(s): var c = int(r) if c <=% 127: add(result, chr(c)) elif c <% translationTable.len: add(result, translationTable[c-128]) diff --git a/lib/pure/xmldomparser.nim b/lib/pure/xmldomparser.nim index 050362435..7c7f7b99c 100644 --- a/lib/pure/xmldomparser.nim +++ b/lib/pure/xmldomparser.nim @@ -30,19 +30,19 @@ proc getNS(prefix: string): string = if ":" in key: if key.split(':')[1] == prefix: return value - + if key == "xmlns": defaultNS.add(value) - + # Don't return the default namespaces # in the loop, because then they would have a precedence # over normal namespaces if defaultNS.len() > 0: return defaultNS[0] # Return the first found default namespace # if none are specified for this prefix - + return "" - + proc parseText(x: var XmlParser, doc: var PDocument): PText = result = doc.createTextNode(x.charData()) @@ -58,19 +58,19 @@ proc parseElement(x: var XmlParser, doc: var PDocument): PElement = n.appendChild(parseElement(x, doc)) else: n = doc.createElementNS("", x.elementName) - + of xmlElementEnd: if x.elementName == n.nodeName: # n.normalize() # Remove any whitespace etc. - + var ns: string if x.elementName.contains(':'): ns = getNS(x.elementName.split(':')[0]) else: ns = getNS("") - + n.namespaceURI = ns - + # Remove any namespaces this element declared var count = 0 # Variable which keeps the index # We need to edit it.. @@ -82,15 +82,15 @@ proc parseElement(x: var XmlParser, doc: var PDocument): PElement = return n else: #The wrong element is ended - raise newException(EMismatchedTag, "Mismatched tag at line " & + raise newException(EMismatchedTag, "Mismatched tag at line " & $x.getLine() & " column " & $x.getColumn) - + of xmlCharData: n.appendChild(parseText(x, doc)) of xmlAttribute: if x.attrKey == "xmlns" or x.attrKey.startsWith("xmlns:"): nsList.add((x.attrKey, x.attrValue, n)) - + if x.attrKey.contains(':'): var ns = getNS(x.attrKey) n.setAttributeNS(ns, x.attrKey, x.attrValue) @@ -103,7 +103,7 @@ proc parseElement(x: var XmlParser, doc: var PDocument): PElement = n.appendChild(doc.createComment(x.charData())) of xmlPI: n.appendChild(doc.createProcessingInstruction(x.piName(), x.piRest())) - + of xmlWhitespace, xmlElementClose, xmlEntity, xmlSpecial: discard " Unused \'events\'" @@ -111,19 +111,19 @@ proc parseElement(x: var XmlParser, doc: var PDocument): PElement = raise newException(EParserError, "Unexpected XML Parser event") x.next() - raise newException(EMismatchedTag, + raise newException(EMismatchedTag, "Mismatched tag at line " & $x.getLine() & " column " & $x.getColumn) proc loadXMLStream*(stream: Stream): PDocument = - ## Loads and parses XML from a stream specified by ``stream``, and returns + ## Loads and parses XML from a stream specified by ``stream``, and returns ## a ``PDocument`` var x: XmlParser open(x, stream, nil, {reportComments}) - + var xmlDoc: PDocument var dom: PDOMImplementation = getDOM() - + while true: x.next() case x.kind() @@ -140,16 +140,16 @@ proc loadXMLStream*(stream: Stream): PDocument = return xmlDoc proc loadXML*(xml: string): PDocument = - ## Loads and parses XML from a string specified by ``xml``, and returns + ## Loads and parses XML from a string specified by ``xml``, and returns ## a ``PDocument`` var s = newStringStream(xml) return loadXMLStream(s) - - + + proc loadXMLFile*(path: string): PDocument = - ## Loads and parses XML from a file specified by ``path``, and returns + ## Loads and parses XML from a file specified by ``path``, and returns ## a ``PDocument`` - + var s = newFileStream(path, fmRead) if s == nil: raise newException(IOError, "Unable to read file " & path) return loadXMLStream(s) @@ -164,5 +164,5 @@ when not defined(testing) and isMainModule: if i.namespaceURI != nil: echo(i.nodeName, "=", i.namespaceURI) - + echo($xml) diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim index 840cae734..56b122000 100644 --- a/lib/pure/xmlparser.nim +++ b/lib/pure/xmlparser.nim @@ -18,24 +18,24 @@ type {.deprecated: [EInvalidXml: XmlError].} -proc raiseInvalidXml(errors: seq[string]) = +proc raiseInvalidXml(errors: seq[string]) = var e: ref XmlError new(e) e.msg = errors[0] e.errors = errors raise e -proc addNode(father, son: XmlNode) = +proc addNode(father, son: XmlNode) = if son != nil: add(father, son) proc parse(x: var XmlParser, errors: var seq[string]): XmlNode -proc untilElementEnd(x: var XmlParser, result: XmlNode, +proc untilElementEnd(x: var XmlParser, result: XmlNode, errors: var seq[string]) = while true: case x.kind - of xmlElementEnd: - if x.elementName == result.tag: + of xmlElementEnd: + if x.elementName == result.tag: next(x) else: errors.add(errorMsg(x, "</" & result.tag & "> expected")) @@ -49,7 +49,7 @@ proc untilElementEnd(x: var XmlParser, result: XmlNode, proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = case x.kind - of xmlComment: + of xmlComment: result = newComment(x.charData) next(x) of xmlCharData, xmlWhitespace: @@ -67,11 +67,11 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = untilElementEnd(x, result, errors) of xmlElementEnd: errors.add(errorMsg(x, "unexpected ending tag: " & x.elementName)) - of xmlElementOpen: + of xmlElementOpen: result = newElement(x.elementName) next(x) result.attrs = newStringTable() - while true: + while true: case x.kind of xmlAttribute: result.attrs[x.attrKey] = x.attrValue @@ -91,7 +91,7 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = of xmlAttribute, xmlElementClose: errors.add(errorMsg(x, "<some_tag> expected")) next(x) - of xmlCData: + of xmlCData: result = newCData(x.charData) next(x) of xmlEntity: @@ -100,8 +100,8 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode = next(x) of xmlEof: discard -proc parseXml*(s: Stream, filename: string, - errors: var seq[string]): XmlNode = +proc parseXml*(s: Stream, filename: string, + errors: var seq[string]): XmlNode = ## parses the XML from stream `s` and returns a ``PXmlNode``. Every ## occurred parsing error is added to the `errors` sequence. var x: XmlParser @@ -109,7 +109,7 @@ proc parseXml*(s: Stream, filename: string, while true: x.next() case x.kind - of xmlElementOpen, xmlElementStart: + of xmlElementOpen, xmlElementStart: result = parse(x, errors) break of xmlComment, xmlWhitespace, xmlSpecial, xmlPI: discard # just skip it @@ -120,7 +120,7 @@ proc parseXml*(s: Stream, filename: string, break close(x) -proc parseXml*(s: Stream): XmlNode = +proc parseXml*(s: Stream): XmlNode = ## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing ## errors are turned into an ``EInvalidXML`` exception. var errors: seq[string] = @[] @@ -128,7 +128,7 @@ proc parseXml*(s: Stream): XmlNode = if errors.len > 0: raiseInvalidXml(errors) proc loadXml*(path: string, errors: var seq[string]): XmlNode = - ## Loads and parses XML from file specified by ``path``, and returns + ## Loads and parses XML from file specified by ``path``, and returns ## a ``PXmlNode``. Every occurred parsing error is added to the `errors` ## sequence. var s = newFileStream(path, fmRead) @@ -136,9 +136,9 @@ proc loadXml*(path: string, errors: var seq[string]): XmlNode = result = parseXml(s, path, errors) proc loadXml*(path: string): XmlNode = - ## Loads and parses XML from file specified by ``path``, and returns + ## Loads and parses XML from file specified by ``path``, and returns ## a ``PXmlNode``. All parsing errors are turned into an ``EInvalidXML`` - ## exception. + ## exception. var errors: seq[string] = @[] result = loadXml(path, errors) if errors.len > 0: raiseInvalidXml(errors) @@ -146,14 +146,14 @@ proc loadXml*(path: string): XmlNode = when not defined(testing) and isMainModule: import os - var errors: seq[string] = @[] + var errors: seq[string] = @[] var x = loadXml(paramStr(1), errors) for e in items(errors): echo e - + var f: File if open(f, "xmltest.txt", fmWrite): f.write($x) f.close() else: quit("cannot write test.txt") - + diff --git a/lib/system/ansi_c.nim b/lib/system/ansi_c.nim index 9406f26c9..702559034 100644 --- a/lib/system/ansi_c.nim +++ b/lib/system/ansi_c.nim @@ -13,20 +13,20 @@ {.push hints:off} -proc c_strcmp(a, b: cstring): cint {.header: "<string.h>", +proc c_strcmp(a, b: cstring): cint {.header: "<string.h>", noSideEffect, importc: "strcmp".} -proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>", +proc c_memcmp(a, b: cstring, size: int): cint {.header: "<string.h>", noSideEffect, importc: "memcmp".} proc c_memcpy(a, b: cstring, size: int) {.header: "<string.h>", importc: "memcpy".} -proc c_strlen(a: cstring): int {.header: "<string.h>", +proc c_strlen(a: cstring): int {.header: "<string.h>", noSideEffect, importc: "strlen".} proc c_memset(p: pointer, value: cint, size: int) {. header: "<string.h>", importc: "memset".} type - C_TextFile {.importc: "FILE", header: "<stdio.h>", + C_TextFile {.importc: "FILE", header: "<stdio.h>", final, incompleteStruct.} = object - C_BinaryFile {.importc: "FILE", header: "<stdio.h>", + C_BinaryFile {.importc: "FILE", header: "<stdio.h>", final, incompleteStruct.} = object C_TextFileStar = ptr C_TextFile C_BinaryFileStar = ptr C_BinaryFile @@ -101,15 +101,15 @@ proc c_signal(sig: cint, handler: proc (a: cint) {.noconv.}) {. importc: "signal", header: "<signal.h>".} proc c_raise(sig: cint) {.importc: "raise", header: "<signal.h>".} -proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", +proc c_fputs(c: cstring, f: C_TextFileStar) {.importc: "fputs", header: "<stdio.h>".} proc c_fgets(c: cstring, n: int, f: C_TextFileStar): cstring {. importc: "fgets", header: "<stdio.h>".} -proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", +proc c_fgetc(stream: C_TextFileStar): int {.importc: "fgetc", header: "<stdio.h>".} -proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", +proc c_ungetc(c: int, f: C_TextFileStar) {.importc: "ungetc", header: "<stdio.h>".} -proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc", +proc c_putc(c: char, stream: C_TextFileStar) {.importc: "putc", header: "<stdio.h>".} proc c_fprintf(f: C_TextFileStar, frmt: cstring) {. importc: "fprintf", header: "<stdio.h>", varargs.} @@ -120,7 +120,7 @@ proc c_fopen(filename, mode: cstring): C_TextFileStar {. importc: "fopen", header: "<stdio.h>".} proc c_fclose(f: C_TextFileStar) {.importc: "fclose", header: "<stdio.h>".} -proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", +proc c_sprintf(buf, frmt: cstring): cint {.header: "<stdio.h>", importc: "sprintf", varargs, noSideEffect.} # we use it only in a way that cannot lead to security issues @@ -149,7 +149,7 @@ when hostOS != "standalone": when not declared(errno): when defined(NimrodVM): var vmErrnoWrapper {.importc.}: ptr cint - template errno: expr = + template errno: expr = bind vmErrnoWrapper vmErrnoWrapper[] else: diff --git a/lib/system/avltree.nim b/lib/system/avltree.nim index 5ee37d3eb..d5c901542 100644 --- a/lib/system/avltree.nim +++ b/lib/system/avltree.nim @@ -16,7 +16,7 @@ proc lowGauge(n: PAvlNode): int = while not isBottom(it): result = it.key it = it.link[0] - + proc highGauge(n: PAvlNode): int = result = -1 var it = n @@ -24,7 +24,7 @@ proc highGauge(n: PAvlNode): int = result = it.upperBound it = it.link[1] -proc find(root: PAvlNode, key: int): PAvlNode = +proc find(root: PAvlNode, key: int): PAvlNode = var it = root while not isBottom(it): if it.key == key: return it diff --git a/lib/system/cellsets.nim b/lib/system/cellsets.nim index 93c49483b..bb5de6f42 100644 --- a/lib/system/cellsets.nim +++ b/lib/system/cellsets.nim @@ -65,7 +65,7 @@ proc init(s: var CellSeq, cap: int = 1024) = s.cap = cap s.d = cast[PCellArray](alloc0(cap * sizeof(PCell))) -proc deinit(s: var CellSeq) = +proc deinit(s: var CellSeq) = dealloc(s.d) s.d = nil s.len = 0 @@ -98,7 +98,7 @@ proc nextTry(h, maxHash: int): int {.inline.} = # For any initial h in range(maxHash), repeating that maxHash times # generates each int in range(maxHash) exactly once (see any text on # random-number generation for proof). - + proc cellSetGet(t: CellSet, key: ByteAddress): PPageDesc = var h = cast[int](key) and t.max while t.data[h] != nil: @@ -170,16 +170,16 @@ proc excl(s: var CellSet, cell: PCell) = t.bits[u shr IntShift] = (t.bits[u shr IntShift] and not (1 shl (u and IntMask))) -proc containsOrIncl(s: var CellSet, cell: PCell): bool = +proc containsOrIncl(s: var CellSet, cell: PCell): bool = var u = cast[ByteAddress](cell) var t = cellSetGet(s, u shr PageShift) if t != nil: u = (u %% PageSize) /% MemAlign result = (t.bits[u shr IntShift] and (1 shl (u and IntMask))) != 0 - if not result: + if not result: t.bits[u shr IntShift] = t.bits[u shr IntShift] or (1 shl (u and IntMask)) - else: + else: incl(s, cell) result = false diff --git a/lib/system/channels.nim b/lib/system/channels.nim index 6739fb83e..68c0e32d2 100644 --- a/lib/system/channels.nim +++ b/lib/system/channels.nim @@ -1,267 +1,267 @@ -# -# -# Nim's Runtime Library +# +# +# Nim's Runtime Library # (c) Copyright 2015 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## Channel support for threads. **Note**: This is part of the system module. -## Do not import it directly. To activate thread support you need to compile -## with the ``--threads:on`` command line switch. -## -## **Note:** The current implementation of message passing is slow and does -## not work with cyclic data structures. - -when not declared(NimString): - {.error: "You must not import this module explicitly".} - -type - pbytes = ptr array[0.. 0xffff, byte] - RawChannel {.pure, final.} = object ## msg queue for a thread - rd, wr, count, mask: int - data: pbytes - lock: SysLock - cond: SysCond - elemType: PNimType - ready: bool - region: MemRegion - PRawChannel = ptr RawChannel - LoadStoreMode = enum mStore, mLoad +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Channel support for threads. **Note**: This is part of the system module. +## Do not import it directly. To activate thread support you need to compile +## with the ``--threads:on`` command line switch. +## +## **Note:** The current implementation of message passing is slow and does +## not work with cyclic data structures. + +when not declared(NimString): + {.error: "You must not import this module explicitly".} + +type + pbytes = ptr array[0.. 0xffff, byte] + RawChannel {.pure, final.} = object ## msg queue for a thread + rd, wr, count, mask: int + data: pbytes + lock: SysLock + cond: SysCond + elemType: PNimType + ready: bool + region: MemRegion + PRawChannel = ptr RawChannel + LoadStoreMode = enum mStore, mLoad Channel* {.gcsafe.}[TMsg] = RawChannel ## a channel for thread communication {.deprecated: [TRawChannel: RawChannel, TLoadStoreMode: LoadStoreMode, TChannel: Channel].} -const ChannelDeadMask = -2 - -proc initRawChannel(p: pointer) = - var c = cast[PRawChannel](p) - initSysLock(c.lock) - initSysCond(c.cond) - c.mask = -1 - -proc deinitRawChannel(p: pointer) = - var c = cast[PRawChannel](p) - # we need to grab the lock to be safe against sending threads! - acquireSys(c.lock) - c.mask = ChannelDeadMask - deallocOsPages(c.region) - deinitSys(c.lock) - deinitSysCond(c.cond) - -proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, - mode: LoadStoreMode) {.benign.} -proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel, - mode: LoadStoreMode) {.benign.} = - var - d = cast[ByteAddress](dest) - s = cast[ByteAddress](src) - case n.kind - of nkSlot: storeAux(cast[pointer](d +% n.offset), - cast[pointer](s +% n.offset), n.typ, t, mode) - of nkList: - for i in 0..n.len-1: storeAux(dest, src, n.sons[i], t, mode) - of nkCase: - copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset), - n.typ.size) - var m = selectBranch(src, n) - if m != nil: storeAux(dest, src, m, t, mode) - of nkNone: sysAssert(false, "storeAux") - -proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, - mode: LoadStoreMode) = - var - d = cast[ByteAddress](dest) - s = cast[ByteAddress](src) - sysAssert(mt != nil, "mt == nil") - case mt.kind - of tyString: - if mode == mStore: - var x = cast[PPointer](dest) - var s2 = cast[PPointer](s)[] - if s2 == nil: - x[] = nil - else: - var ss = cast[NimString](s2) - var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize)) - copyMem(ns, ss, ss.len+1 + GenericSeqSize) - x[] = ns - else: - var x = cast[PPointer](dest) - var s2 = cast[PPointer](s)[] - if s2 == nil: - unsureAsgnRef(x, s2) - else: - unsureAsgnRef(x, copyString(cast[NimString](s2))) - dealloc(t.region, s2) - of tySequence: - var s2 = cast[PPointer](src)[] - var seq = cast[PGenericSeq](s2) - var x = cast[PPointer](dest) - if s2 == nil: - if mode == mStore: - x[] = nil - else: - unsureAsgnRef(x, nil) - else: - sysAssert(dest != nil, "dest == nil") - if mode == mStore: - x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize) - else: - unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize)) - var dst = cast[ByteAddress](cast[PPointer](dest)[]) - for i in 0..seq.len-1: - storeAux( - cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), - cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +% - GenericSeqSize), - mt.base, t, mode) - var dstseq = cast[PGenericSeq](dst) - dstseq.len = seq.len - dstseq.reserved = seq.len - if mode != mStore: dealloc(t.region, s2) - of tyObject: - # copy type field: - var pint = cast[ptr PNimType](dest) - # XXX use dynamic type here! - pint[] = mt - if mt.base != nil: - storeAux(dest, src, mt.base, t, mode) - storeAux(dest, src, mt.node, t, mode) - of tyTuple: - storeAux(dest, src, mt.node, t, mode) - of tyArray, tyArrayConstr: - for i in 0..(mt.size div mt.base.size)-1: - storeAux(cast[pointer](d +% i*% mt.base.size), - cast[pointer](s +% i*% mt.base.size), mt.base, t, mode) - of tyRef: - var s = cast[PPointer](src)[] - var x = cast[PPointer](dest) - if s == nil: - if mode == mStore: - x[] = nil - else: - unsureAsgnRef(x, nil) - else: - if mode == mStore: - x[] = alloc(t.region, mt.base.size) - else: - # XXX we should use the dynamic type here too, but that is not stored - # in the inbox at all --> use source[]'s object type? but how? we need - # a tyRef to the object! - var obj = newObj(mt, mt.base.size) - unsureAsgnRef(x, obj) - storeAux(x[], s, mt.base, t, mode) - if mode != mStore: dealloc(t.region, s) - else: - copyMem(dest, src, mt.size) # copy raw bits - -proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) = - ## adds an `item` to the end of the queue `q`. - var cap = q.mask+1 - if q.count >= cap: - # start with capacity for 2 entries in the queue: - if cap == 0: cap = 1 - var n = cast[pbytes](alloc0(q.region, cap*2*typ.size)) - var z = 0 - var i = q.rd - var c = q.count - while c > 0: - dec c - copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size) - i = (i + 1) and q.mask - inc z - if q.data != nil: dealloc(q.region, q.data) - q.data = n - q.mask = cap*2 - 1 - q.wr = q.count - q.rd = 0 - storeAux(addr(q.data[q.wr * typ.size]), data, typ, q, mStore) - inc q.count - q.wr = (q.wr + 1) and q.mask - -proc rawRecv(q: PRawChannel, data: pointer, typ: PNimType) = - sysAssert q.count > 0, "rawRecv" - dec q.count - storeAux(data, addr(q.data[q.rd * typ.size]), typ, q, mLoad) - q.rd = (q.rd + 1) and q.mask - -template lockChannel(q: expr, action: stmt) {.immediate.} = - acquireSys(q.lock) - action - releaseSys(q.lock) - -template sendImpl(q: expr) {.immediate.} = - if q.mask == ChannelDeadMask: - sysFatal(DeadThreadError, "cannot send message; thread died") - acquireSys(q.lock) - var m: TMsg - shallowCopy(m, msg) - var typ = cast[PNimType](getTypeInfo(msg)) - rawSend(q, addr(m), typ) - q.elemType = typ - releaseSys(q.lock) - signalSysCond(q.cond) - -proc send*[TMsg](c: var Channel[TMsg], msg: TMsg) = - ## sends a message to a thread. `msg` is deeply copied. - var q = cast[PRawChannel](addr(c)) - sendImpl(q) - -proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) = - # to save space, the generic is as small as possible - q.ready = true - while q.count <= 0: - waitSysCond(q.cond, q.lock) - q.ready = false - if typ != q.elemType: - releaseSys(q.lock) - sysFatal(ValueError, "cannot receive message of wrong type") - rawRecv(q, res, typ) - -proc recv*[TMsg](c: var Channel[TMsg]): TMsg = - ## receives a message from the channel `c`. This blocks until - ## a message has arrived! You may use ``peek`` to avoid the blocking. - var q = cast[PRawChannel](addr(c)) - acquireSys(q.lock) - llRecv(q, addr(result), cast[PNimType](getTypeInfo(result))) - releaseSys(q.lock) - -proc tryRecv*[TMsg](c: var Channel[TMsg]): tuple[dataAvailable: bool, - msg: TMsg] = - ## try to receives a message from the channel `c` if available. Otherwise - ## it returns ``(false, default(msg))``. - var q = cast[PRawChannel](addr(c)) - if q.mask != ChannelDeadMask: +const ChannelDeadMask = -2 + +proc initRawChannel(p: pointer) = + var c = cast[PRawChannel](p) + initSysLock(c.lock) + initSysCond(c.cond) + c.mask = -1 + +proc deinitRawChannel(p: pointer) = + var c = cast[PRawChannel](p) + # we need to grab the lock to be safe against sending threads! + acquireSys(c.lock) + c.mask = ChannelDeadMask + deallocOsPages(c.region) + deinitSys(c.lock) + deinitSysCond(c.cond) + +proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, + mode: LoadStoreMode) {.benign.} +proc storeAux(dest, src: pointer, n: ptr TNimNode, t: PRawChannel, + mode: LoadStoreMode) {.benign.} = + var + d = cast[ByteAddress](dest) + s = cast[ByteAddress](src) + case n.kind + of nkSlot: storeAux(cast[pointer](d +% n.offset), + cast[pointer](s +% n.offset), n.typ, t, mode) + of nkList: + for i in 0..n.len-1: storeAux(dest, src, n.sons[i], t, mode) + of nkCase: + copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset), + n.typ.size) + var m = selectBranch(src, n) + if m != nil: storeAux(dest, src, m, t, mode) + of nkNone: sysAssert(false, "storeAux") + +proc storeAux(dest, src: pointer, mt: PNimType, t: PRawChannel, + mode: LoadStoreMode) = + var + d = cast[ByteAddress](dest) + s = cast[ByteAddress](src) + sysAssert(mt != nil, "mt == nil") + case mt.kind + of tyString: + if mode == mStore: + var x = cast[PPointer](dest) + var s2 = cast[PPointer](s)[] + if s2 == nil: + x[] = nil + else: + var ss = cast[NimString](s2) + var ns = cast[NimString](alloc(t.region, ss.len+1 + GenericSeqSize)) + copyMem(ns, ss, ss.len+1 + GenericSeqSize) + x[] = ns + else: + var x = cast[PPointer](dest) + var s2 = cast[PPointer](s)[] + if s2 == nil: + unsureAsgnRef(x, s2) + else: + unsureAsgnRef(x, copyString(cast[NimString](s2))) + dealloc(t.region, s2) + of tySequence: + var s2 = cast[PPointer](src)[] + var seq = cast[PGenericSeq](s2) + var x = cast[PPointer](dest) + if s2 == nil: + if mode == mStore: + x[] = nil + else: + unsureAsgnRef(x, nil) + else: + sysAssert(dest != nil, "dest == nil") + if mode == mStore: + x[] = alloc(t.region, seq.len *% mt.base.size +% GenericSeqSize) + else: + unsureAsgnRef(x, newObj(mt, seq.len * mt.base.size + GenericSeqSize)) + var dst = cast[ByteAddress](cast[PPointer](dest)[]) + for i in 0..seq.len-1: + storeAux( + cast[pointer](dst +% i*% mt.base.size +% GenericSeqSize), + cast[pointer](cast[ByteAddress](s2) +% i *% mt.base.size +% + GenericSeqSize), + mt.base, t, mode) + var dstseq = cast[PGenericSeq](dst) + dstseq.len = seq.len + dstseq.reserved = seq.len + if mode != mStore: dealloc(t.region, s2) + of tyObject: + # copy type field: + var pint = cast[ptr PNimType](dest) + # XXX use dynamic type here! + pint[] = mt + if mt.base != nil: + storeAux(dest, src, mt.base, t, mode) + storeAux(dest, src, mt.node, t, mode) + of tyTuple: + storeAux(dest, src, mt.node, t, mode) + of tyArray, tyArrayConstr: + for i in 0..(mt.size div mt.base.size)-1: + storeAux(cast[pointer](d +% i*% mt.base.size), + cast[pointer](s +% i*% mt.base.size), mt.base, t, mode) + of tyRef: + var s = cast[PPointer](src)[] + var x = cast[PPointer](dest) + if s == nil: + if mode == mStore: + x[] = nil + else: + unsureAsgnRef(x, nil) + else: + if mode == mStore: + x[] = alloc(t.region, mt.base.size) + else: + # XXX we should use the dynamic type here too, but that is not stored + # in the inbox at all --> use source[]'s object type? but how? we need + # a tyRef to the object! + var obj = newObj(mt, mt.base.size) + unsureAsgnRef(x, obj) + storeAux(x[], s, mt.base, t, mode) + if mode != mStore: dealloc(t.region, s) + else: + copyMem(dest, src, mt.size) # copy raw bits + +proc rawSend(q: PRawChannel, data: pointer, typ: PNimType) = + ## adds an `item` to the end of the queue `q`. + var cap = q.mask+1 + if q.count >= cap: + # start with capacity for 2 entries in the queue: + if cap == 0: cap = 1 + var n = cast[pbytes](alloc0(q.region, cap*2*typ.size)) + var z = 0 + var i = q.rd + var c = q.count + while c > 0: + dec c + copyMem(addr(n[z*typ.size]), addr(q.data[i*typ.size]), typ.size) + i = (i + 1) and q.mask + inc z + if q.data != nil: dealloc(q.region, q.data) + q.data = n + q.mask = cap*2 - 1 + q.wr = q.count + q.rd = 0 + storeAux(addr(q.data[q.wr * typ.size]), data, typ, q, mStore) + inc q.count + q.wr = (q.wr + 1) and q.mask + +proc rawRecv(q: PRawChannel, data: pointer, typ: PNimType) = + sysAssert q.count > 0, "rawRecv" + dec q.count + storeAux(data, addr(q.data[q.rd * typ.size]), typ, q, mLoad) + q.rd = (q.rd + 1) and q.mask + +template lockChannel(q: expr, action: stmt) {.immediate.} = + acquireSys(q.lock) + action + releaseSys(q.lock) + +template sendImpl(q: expr) {.immediate.} = + if q.mask == ChannelDeadMask: + sysFatal(DeadThreadError, "cannot send message; thread died") + acquireSys(q.lock) + var m: TMsg + shallowCopy(m, msg) + var typ = cast[PNimType](getTypeInfo(msg)) + rawSend(q, addr(m), typ) + q.elemType = typ + releaseSys(q.lock) + signalSysCond(q.cond) + +proc send*[TMsg](c: var Channel[TMsg], msg: TMsg) = + ## sends a message to a thread. `msg` is deeply copied. + var q = cast[PRawChannel](addr(c)) + sendImpl(q) + +proc llRecv(q: PRawChannel, res: pointer, typ: PNimType) = + # to save space, the generic is as small as possible + q.ready = true + while q.count <= 0: + waitSysCond(q.cond, q.lock) + q.ready = false + if typ != q.elemType: + releaseSys(q.lock) + sysFatal(ValueError, "cannot receive message of wrong type") + rawRecv(q, res, typ) + +proc recv*[TMsg](c: var Channel[TMsg]): TMsg = + ## receives a message from the channel `c`. This blocks until + ## a message has arrived! You may use ``peek`` to avoid the blocking. + var q = cast[PRawChannel](addr(c)) + acquireSys(q.lock) + llRecv(q, addr(result), cast[PNimType](getTypeInfo(result))) + releaseSys(q.lock) + +proc tryRecv*[TMsg](c: var Channel[TMsg]): tuple[dataAvailable: bool, + msg: TMsg] = + ## try to receives a message from the channel `c` if available. Otherwise + ## it returns ``(false, default(msg))``. + var q = cast[PRawChannel](addr(c)) + if q.mask != ChannelDeadMask: if tryAcquireSys(q.lock): - if q.count > 0: - llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) - result.dataAvailable = true - releaseSys(q.lock) - -proc peek*[TMsg](c: var Channel[TMsg]): int = - ## returns the current number of messages in the channel `c`. Returns -1 - ## if the channel has been closed. **Note**: This is dangerous to use - ## as it encourages races. It's much better to use ``tryRecv`` instead. - var q = cast[PRawChannel](addr(c)) - if q.mask != ChannelDeadMask: - lockChannel(q): - result = q.count - else: - result = -1 - -proc open*[TMsg](c: var Channel[TMsg]) = - ## opens a channel `c` for inter thread communication. - initRawChannel(addr(c)) - -proc close*[TMsg](c: var Channel[TMsg]) = - ## closes a channel `c` and frees its associated resources. - deinitRawChannel(addr(c)) - -proc ready*[TMsg](c: var Channel[TMsg]): bool = - ## returns true iff some thread is waiting on the channel `c` for - ## new messages. - var q = cast[PRawChannel](addr(c)) - result = q.ready - + if q.count > 0: + llRecv(q, addr(result.msg), cast[PNimType](getTypeInfo(result.msg))) + result.dataAvailable = true + releaseSys(q.lock) + +proc peek*[TMsg](c: var Channel[TMsg]): int = + ## returns the current number of messages in the channel `c`. Returns -1 + ## if the channel has been closed. **Note**: This is dangerous to use + ## as it encourages races. It's much better to use ``tryRecv`` instead. + var q = cast[PRawChannel](addr(c)) + if q.mask != ChannelDeadMask: + lockChannel(q): + result = q.count + else: + result = -1 + +proc open*[TMsg](c: var Channel[TMsg]) = + ## opens a channel `c` for inter thread communication. + initRawChannel(addr(c)) + +proc close*[TMsg](c: var Channel[TMsg]) = + ## closes a channel `c` and frees its associated resources. + deinitRawChannel(addr(c)) + +proc ready*[TMsg](c: var Channel[TMsg]): bool = + ## returns true iff some thread is waiting on the channel `c` for + ## new messages. + var q = cast[PRawChannel](addr(c)) + result = q.ready + diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index 093c0f3a7..03230e541 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -14,7 +14,7 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} = s = cast[ByteAddress](src) case n.kind of nkSlot: - genericDeepCopyAux(cast[pointer](d +% n.offset), + genericDeepCopyAux(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset), n.typ) of nkList: for i in 0..n.len-1: @@ -24,7 +24,7 @@ proc genericDeepCopyAux(dest, src: pointer, n: ptr TNimNode) {.benign.} = var m = selectBranch(src, n) # reset if different branches are in use; note different branches also # imply that's not self-assignment (``x = x``)! - if m != dd and dd != nil: + if m != dd and dd != nil: genericResetAux(dest, dd) copyMem(cast[pointer](d +% n.offset), cast[pointer](s +% n.offset), n.typ.size) @@ -103,16 +103,16 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType) = else: let realType = x.typ let z = newObj(realType, realType.base.size) - + unsureAsgnRef(cast[PPointer](dest), z) x.typ = cast[PNimType](cast[int](z) or 1) genericDeepCopyAux(z, s2, realType.base) x.typ = realType else: let realType = mt - let z = newObj(realType, realType.base.size) + let z = newObj(realType, realType.base.size) unsureAsgnRef(cast[PPointer](dest), z) - genericDeepCopyAux(z, s2, realType.base) + genericDeepCopyAux(z, s2, realType.base) of tyPtr: # no cycle check here, but also not really required let s2 = cast[PPointer](src)[] diff --git a/lib/system/gc2.nim b/lib/system/gc2.nim index 015e08c9e..4ca0d144f 100644 --- a/lib/system/gc2.nim +++ b/lib/system/gc2.nim @@ -37,19 +37,19 @@ const rcAlive = 0b00000 # object is reachable. # color *black* in the original paper - + rcCycleCandidate = 0b00001 # possible root of a cycle. *purple* rcDecRefApplied = 0b00010 # the first dec-ref phase of the # collector was already applied to this # object. *gray* - + rcMaybeDead = 0b00011 # this object is a candidate for deletion # during the collect cycles algorithm. # *white*. - + rcReallyDead = 0b00100 # this is proved to be garbage - + rcRetiredBuffer = 0b00101 # this is a seq or string buffer that # was replaced by a resize operation. # see growObj for details @@ -80,14 +80,14 @@ const # The bit must also be set for new objects that are not rc1 and it must be # examined in the decref loop in collectCycles. # XXX: not implemented yet as tests didn't show any improvement from this - + MarkingSkipsAcyclicObjects = true - # Acyclic objects can be safely ignored in the mark and scan phases, + # Acyclic objects can be safely ignored in the mark and scan phases, # because they cannot contribute to the internal count. # XXX: if we generate specialized `markCyclic` and `markAcyclic` # procs we can further optimize this as there won't be need for any # checks in the code - + MinimumStackMarking = false # Try to scan only the user stack and ignore the part of the stack # belonging to the GC itself. see setStackTop for further info. @@ -110,9 +110,9 @@ type maxThreshold: int # max threshold that has been set maxStackSize: int # max stack size maxStackCells: int # max stack cells in ``decStack`` - cycleTableSize: int # max entries in cycle table + cycleTableSize: int # max entries in cycle table maxPause: int64 # max measured GC pause in nanoseconds - + GcHeap {.final, pure.} = object # this contains the zero count and # non-zero count table stackBottom: pointer @@ -124,7 +124,7 @@ type tempStack: CellSeq # temporary stack for recursion elimination freeStack: CellSeq # objects ready to be freed recGcLock: int # prevent recursion via finalizers; no thread lock - cycleRootsTrimIdx: int # Trimming is a light-weight collection of the + cycleRootsTrimIdx: int # Trimming is a light-weight collection of the # cycle roots table that uses a cheap linear scan # to find only possitively dead objects. # One strategy is to perform it only for new objects @@ -143,11 +143,11 @@ var when not defined(useNimRtl): instantiateForRegion(gch.region) -template acquire(gch: GcHeap) = +template acquire(gch: GcHeap) = when hasThreadSupport and hasSharedHeap: AcquireSys(HeapLock) -template release(gch: GcHeap) = +template release(gch: GcHeap) = when hasThreadSupport and hasSharedHeap: releaseSys(HeapLock) @@ -185,7 +185,7 @@ when debugGC: of rcRetiredBuffer: return "retired" of rcReallyDead: return "dead" else: return "unknown?" - + proc inCycleRootsStr(c: PCell): cstring = if c.isBitUp(rcInCycleRoots): result = "cycleroot" else: result = "" @@ -225,7 +225,7 @@ template setStackTop(gch) = template addCycleRoot(cycleRoots: var CellSeq, c: PCell) = if c.color != rcCycleCandidate: c.setColor rcCycleCandidate - + # the object may be buffered already. for example, consider: # decref; incref; decref if c.isBitDown(rcInCycleRoots): @@ -307,7 +307,7 @@ when traceGC: let startLen = gch.tempStack.len c.forAllChildren waPush - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] @@ -331,7 +331,7 @@ when traceGC: if c.isBitUp(rcMarkBit) and not isMarked: writecell("cyclic cell", cell) cprintf "Weight %d\n", cell.computeCellWeight - + proc writeLeakage(onlyRoots: bool) = if onlyRoots: for c in elements(states[csAllocated]): @@ -356,7 +356,7 @@ template WithHeapLock(blk: stmt): stmt = blk when hasThreadSupport and hasSharedHeap: ReleaseSys(HeapLock) -proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = +proc rtlAddCycleRoot(c: PCell) {.rtl, inl.} = # we MUST access gch as a global here, because this crosses DLL boundaries! WithHeapLock: addCycleRoot(gch.cycleRoots, c) @@ -423,7 +423,7 @@ template doIncRef(cc: PCell, elif IncRefRemovesCandidates: c.setColor rcAlive # XXX: this is not really atomic enough! - + proc nimGCref(p: pointer) {.compilerProc, inline.} = doIncRef(usrToCell(p)) proc nimGCunref(p: pointer) {.compilerProc, inline.} = doDecRef(usrToCell(p)) @@ -449,7 +449,7 @@ proc asgnRef(dest: PPointer, src: pointer) {.compilerProc, inline.} = doAsgnRef(dest, src, LocalHeap, MaybeCyclic) proc asgnRefNoCycle(dest: PPointer, src: pointer) {.compilerProc, inline.} = - # the code generator calls this proc if it is known at compile time that no + # the code generator calls this proc if it is known at compile time that no # cycle is possible. doAsgnRef(dest, src, LocalHeap, Acyclic) @@ -509,7 +509,7 @@ proc forAllSlotsAux(dest: pointer, n: ptr TNimNode, op: WalkOp) = if n.sons[i].typ.kind in {tyRef, tyString, tySequence}: doOperation(cast[PPointer](d +% n.sons[i].offset)[], op) else: - forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), + forAllChildrenAux(cast[pointer](d +% n.sons[i].offset), n.sons[i].typ, op) else: forAllSlotsAux(dest, n.sons[i], op) @@ -557,7 +557,7 @@ proc addNewObjToZCT(res: PCell, gch: var GcHeap) {.inline.} = # we check the last 8 entries (cache line) for a slot that could be reused. # In 63% of all cases we succeed here! But we have to optimize the heck # out of this small linear search so that ``newObj`` is not slowed down. - # + # # Slots to try cache hit # 1 32% # 4 59% @@ -602,7 +602,7 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap, rc1 = false): pointer acquire(gch) sysAssert(allocInv(gch.region), "rawNewObj begin") sysAssert(typ.kind in {tyRef, tyString, tySequence}, "newObj: 1") - + collectCT(gch) sysAssert(allocInv(gch.region), "rawNewObj after collect") @@ -610,16 +610,16 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap, rc1 = false): pointer sysAssert(allocInv(gch.region), "rawNewObj after rawAlloc") sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "newObj: 2") - + res.typ = typ - + when trackAllocationSource and not hasThreadSupport: if framePtr != nil and framePtr.prev != nil and framePtr.prev.prev != nil: res.filename = framePtr.prev.prev.filename res.line = framePtr.prev.prev.line else: res.filename = "nofile" - + if rc1: res.refcount = rcIncrement # refcount is 1 else: @@ -631,9 +631,9 @@ proc rawNewObj(typ: PNimType, size: int, gch: var GcHeap, rc1 = false): pointer res.setBit(rcInCycleRoots) res.setColor rcCycleCandidate gch.cycleRoots.add res - + sysAssert(isAllocatedPtr(gch.region, res), "newObj: 3") - + when logGC: writeCell("new cell", res) gcTrace(res, csAllocated) release(gch) @@ -711,9 +711,9 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = var res = cast[PCell](rawAlloc(gch.region, newsize + sizeof(Cell))) var elemSize = if ol.typ.kind != tyString: ol.typ.base.size else: 1 - + var oldsize = cast[PGenericSeq](old).len*elemSize + GenericSeqSize - + # XXX: This should happen outside # call user-defined move code # call user-defined default constructor @@ -723,24 +723,24 @@ proc growObj(old: pointer, newsize: int, gch: var GcHeap): pointer = sysAssert((cast[ByteAddress](res) and (MemAlign-1)) == 0, "growObj: 3") sysAssert(res.refcount shr rcShift <=% 1, "growObj: 4") - + when false: if ol.isBitUp(rcZct): var j = gch.zct.len-1 var d = gch.zct.d - while j >= 0: + while j >= 0: if d[j] == ol: d[j] = res break dec(j) - + if ol.isBitUp(rcInCycleRoots): for i in 0 .. <gch.cycleRoots.len: if gch.cycleRoots.d[i] == ol: eraseAt(gch.cycleRoots, i) freeCell(gch, ol) - + else: # the new buffer inherits the GC state of the old one if res.isBitUp(rcZct): gch.zct.add res @@ -787,12 +787,12 @@ proc doOperation(p: pointer, op: WalkOp) = var c: PCell = usrToCell(p) sysAssert(c != nil, "doOperation: 1") gch.tempStack.add c - + proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} = doOperation(d, WalkOp(op)) type - RecursionType = enum + RecursionType = enum FromChildren, FromRoot {.deprecated: [TRecursionType: RecursionType].} @@ -838,14 +838,14 @@ proc collectCycles(gch: var GcHeap) = let startLen = gch.tempStack.len cell.setColor rcAlive cell.forAllChildren waPush - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] if c.color != rcAlive: c.setColor rcAlive c.forAllChildren waPush - + template earlyMarkAlive(stackRoots) = # This marks all objects reachable from the stack as alive before any # of the other stages is executed. Such objects cannot be garbage and @@ -856,7 +856,7 @@ proc collectCycles(gch: var GcHeap) = earlyMarkAliveRec(c) earlyMarkAlive(gch.decStack) - + when CollectCyclesStats: let tAfterEarlyMarkAlive = getTicks() @@ -864,7 +864,7 @@ proc collectCycles(gch: var GcHeap) = let startLen = gch.tempStack.len cell.setColor rcDecRefApplied cell.forAllChildren waPush - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] @@ -876,7 +876,7 @@ proc collectCycles(gch: var GcHeap) = if c.color != rcDecRefApplied: c.setColor rcDecRefApplied c.forAllChildren waPush - + template markRoots(roots) = var i = 0 while i < roots.len: @@ -885,34 +885,34 @@ proc collectCycles(gch: var GcHeap) = inc i else: roots.trimAt i - + markRoots(gch.cycleRoots) - + when CollectCyclesStats: let tAfterMark = getTicks() c_printf "COLLECT CYCLES %d: %d/%d\n", gcCollectionIdx, gch.cycleRoots.len, l0 - + template recursiveMarkAlive(cell) = let startLen = gch.tempStack.len cell.setColor rcAlive cell.forAllChildren waPush - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] if ignoreObject(c): continue inc c.refcount, rcIncrement inc increfs - + if c.color != rcAlive: c.setColor rcAlive c.forAllChildren waPush - + template scanRoots(roots) = for i in 0 .. <roots.len: let startLen = gch.tempStack.len gch.tempStack.add roots.d[i] - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] @@ -928,9 +928,9 @@ proc collectCycles(gch: var GcHeap) = c.setColor rcMaybeDead inc maybedeads c.forAllChildren waPush - + scanRoots(gch.cycleRoots) - + when CollectCyclesStats: let tAfterScan = getTicks() @@ -941,7 +941,7 @@ proc collectCycles(gch: var GcHeap) = let startLen = gch.tempStack.len gch.tempStack.add c - + while startLen != gch.tempStack.len: dec gch.tempStack.len var c = gch.tempStack.d[gch.tempStack.len] @@ -965,7 +965,7 @@ proc collectCycles(gch: var GcHeap) = freeCell(gch, gch.freeStack.d[i]) collectDead(gch.cycleRoots) - + when CollectCyclesStats: let tFinal = getTicks() cprintf "times:\n early mark alive: %d ms\n mark: %d ms\n scan: %d ms\n collect: %d ms\n decrefs: %d\n increfs: %d\n marked dead: %d\n collected: %d\n", @@ -986,7 +986,7 @@ proc collectCycles(gch: var GcHeap) = when MarkingSkipsAcyclicObjects: # Collect the acyclic objects that became unreachable due to collected - # cyclic objects. + # cyclic objects. discard collectZCT(gch) # collectZCT may add new cycle candidates and we may decide to loop here # if gch.cycleRoots.len > 0: repeat @@ -1030,12 +1030,12 @@ proc gcMark(gch: var GcHeap, p: pointer) {.inline.} = add(gch.decStack, cell) sysAssert(allocInv(gch.region), "gcMark end") -proc markThreadStacks(gch: var GcHeap) = +proc markThreadStacks(gch: var GcHeap) = when hasThreadSupport and hasSharedHeap: {.error: "not fully implemented".} var it = threadList while it != nil: - # mark registers: + # mark registers: for i in 0 .. high(it.registers): gcMark(gch, it.registers[i]) var sp = cast[ByteAddress](it.stackBottom) var max = cast[ByteAddress](it.stackTop) @@ -1121,7 +1121,7 @@ elif stackIncreases: var b = cast[ByteAddress](stackTop) var x = cast[ByteAddress](p) result = a <=% x and x <=% b - + proc markStackAndRegisters(gch: var GcHeap) {.noinline, cdecl.} = var registers: C_JmpBuf if c_setjmp(registers) == 0'i32: # To fill the C stack with registers. @@ -1156,7 +1156,7 @@ else: # mark the registers var jmpbufPtr = cast[ByteAddress](addr(registers)) var jmpbufEnd = jmpbufPtr +% jmpbufSize - + while jmpbufPtr <=% jmpbufEnd: gcMark(gch, cast[PPointer](jmpbufPtr)[]) jmpbufPtr = jmpbufPtr +% sizeof(pointer) @@ -1218,18 +1218,18 @@ proc releaseCell(gch: var GcHeap, cell: PCell) = proc collectZCT(gch: var GcHeap): bool = const workPackage = 100 var L = addr(gch.zct.len) - + when withRealtime: var steps = workPackage var t0: Ticks if gch.maxPause > 0: t0 = getticks() - + while L[] > 0: var c = gch.zct.d[0] sysAssert c.isBitUp(rcZct), "collectZCT: rcZct missing!" sysAssert(isAllocatedPtr(gch.region, c), "collectZCT: isAllocatedPtr") - - # remove from ZCT: + + # remove from ZCT: c.clearBit(rcZct) gch.zct.d[0] = gch.zct.d[L[] - 1] dec(L[]) @@ -1237,7 +1237,7 @@ proc collectZCT(gch: var GcHeap): bool = if c.refcount <% rcIncrement: # It may have a RC > 0, if it is in the hardware stack or # it has not been removed yet from the ZCT. This is because - # ``incref`` does not bother to remove the cell from the ZCT + # ``incref`` does not bother to remove the cell from the ZCT # as this might be too slow. # In any case, it should be removed from the ZCT. But not # freed. **KEEP THIS IN MIND WHEN MAKING THIS INCREMENTAL!** @@ -1252,7 +1252,7 @@ proc collectZCT(gch: var GcHeap): bool = steps = workPackage if gch.maxPause > 0: let duration = getticks() - t0 - # the GC's measuring is not accurate and needs some cleanup actions + # the GC's measuring is not accurate and needs some cleanup actions # (stack unmarking), so subtract some short amount of time in to # order to miss deadlines less often: if duration >= gch.maxPause - 50_000: @@ -1269,7 +1269,7 @@ proc unmarkStackAndRegisters(gch: var GcHeap) = # XXX: just call doDecRef? var c = d[i] sysAssert c.typ != nil, "unmarkStackAndRegisters 2" - + if c.color == rcRetiredBuffer: continue @@ -1278,7 +1278,7 @@ proc unmarkStackAndRegisters(gch: var GcHeap) = # the object survived only because of a stack reference # it still doesn't have heap references addZCT(gch.zct, c) - + if canbeCycleRoot(c): # any cyclic object reachable from the stack can be turned into # a leak if it's orphaned through the stack reference @@ -1293,7 +1293,7 @@ proc collectCTBody(gch: var GcHeap) = let t0 = getticks() when debugGC: inc gcCollectionIdx sysAssert(allocInv(gch.region), "collectCT: begin") - + gch.stat.maxStackSize = max(gch.stat.maxStackSize, stackSize()) sysAssert(gch.decStack.len == 0, "collectCT") prepareForInteriorPointerChecking(gch.region) @@ -1312,7 +1312,7 @@ proc collectCTBody(gch: var GcHeap) = gch.stat.maxThreshold = max(gch.stat.maxThreshold, gch.cycleThreshold) unmarkStackAndRegisters(gch) sysAssert(allocInv(gch.region), "collectCT: end") - + when withRealtime: let duration = getticks() - t0 gch.stat.maxPause = max(gch.stat.maxPause, duration) @@ -1322,7 +1322,7 @@ proc collectCTBody(gch: var GcHeap) = proc collectCT(gch: var GcHeap) = if (gch.zct.len >= ZctThreshold or (cycleGC and - getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and + getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) and gch.recGcLock == 0: collectCTBody(gch) @@ -1337,7 +1337,7 @@ when withRealtime: acquire(gch) gch.maxPause = us.toNano if (gch.zct.len >= ZctThreshold or (cycleGC and - getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or + getOccupiedMem(gch.region)>=gch.cycleThreshold) or alwaysGC) or strongAdvice: collectCTBody(gch) release(gch) @@ -1345,13 +1345,13 @@ when withRealtime: proc GC_step*(us: int, strongAdvice = false) = GC_step(gch, us, strongAdvice) when not defined(useNimRtl): - proc GC_disable() = + proc GC_disable() = when hasThreadSupport and hasSharedHeap: discard atomicInc(gch.recGcLock, 1) else: inc(gch.recGcLock) proc GC_enable() = - if gch.recGcLock > 0: + if gch.recGcLock > 0: when hasThreadSupport and hasSharedHeap: discard atomicDec(gch.recGcLock, 1) else: diff --git a/lib/system/gc_common.nim b/lib/system/gc_common.nim index c7dd667e4..ceb362378 100644 --- a/lib/system/gc_common.nim +++ b/lib/system/gc_common.nim @@ -197,7 +197,7 @@ else: var x = cast[ByteAddress](p) if a <=% x and x <=% b: return true - + template forEachStackSlot(gch, gcMark: expr) {.immediate, dirty.} = # We use a jmp_buf buffer that is in the C stack. # Used to traverse the stack and registers assuming @@ -207,7 +207,7 @@ else: getRegisters(registers) for i in registers.low .. registers.high: gcMark(gch, cast[PPointer](registers[i])) - + for stack in items(gch.stack): stack.maxStackSize = max(stack.maxStackSize, stackSize(stack.starts)) var max = cast[ByteAddress](stack.starts) diff --git a/lib/system/inclrtl.nim b/lib/system/inclrtl.nim index d0dc38284..201a99ca7 100644 --- a/lib/system/inclrtl.nim +++ b/lib/system/inclrtl.nim @@ -20,21 +20,21 @@ when not defined(nimNewShared): {.pragma: gcsafe.} when defined(createNimRtl): - when defined(useNimRtl): + when defined(useNimRtl): {.error: "Cannot create and use nimrtl at the same time!".} elif appType != "lib": {.error: "nimrtl must be built as a library!".} -when defined(createNimRtl): +when defined(createNimRtl): {.pragma: rtl, exportc: "nimrtl_$1", dynlib, gcsafe.} {.pragma: inl.} {.pragma: compilerRtl, compilerproc, exportc: "nimrtl_$1", dynlib.} elif defined(useNimRtl): - when defined(windows): + when defined(windows): const nimrtl* = "nimrtl.dll" elif defined(macosx): const nimrtl* = "libnimrtl.dylib" - else: + else: const nimrtl* = "libnimrtl.so" {.pragma: rtl, importc: "nimrtl_$1", dynlib: nimrtl, gcsafe.} {.pragma: inl.} diff --git a/lib/system/profiler.nim b/lib/system/profiler.nim index c93456fb3..4f600417e 100644 --- a/lib/system/profiler.nim +++ b/lib/system/profiler.nim @@ -40,7 +40,7 @@ proc captureStackTrace(f: PFrame, st: var StackTrace) = while it != nil: inc(total) it = it.prev - for j in 1..total-i-(firstCalls-1): + for j in 1..total-i-(firstCalls-1): if b != nil: b = b.prev if total != i: st[i] = "..." diff --git a/lib/system/syslocks.nim b/lib/system/syslocks.nim index ec8c26275..7a113b9d4 100644 --- a/lib/system/syslocks.nim +++ b/lib/system/syslocks.nim @@ -23,7 +23,7 @@ when defined(Windows): SysCond = Handle {.deprecated: [THandle: Handle, TSysLock: SysLock, TSysCond: SysCond].} - + proc initSysLock(L: var SysLock) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "InitializeCriticalSection".} ## Initializes the lock `L`. @@ -31,14 +31,14 @@ when defined(Windows): proc tryAcquireSysAux(L: var SysLock): int32 {.stdcall, noSideEffect, dynlib: "kernel32", importc: "TryEnterCriticalSection".} ## Tries to acquire the lock `L`. - - proc tryAcquireSys(L: var SysLock): bool {.inline.} = + + proc tryAcquireSys(L: var SysLock): bool {.inline.} = result = tryAcquireSysAux(L) != 0'i32 proc acquireSys(L: var SysLock) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "EnterCriticalSection".} ## Acquires the lock `L`. - + proc releaseSys(L: var SysLock) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "LeaveCriticalSection".} ## Releases the lock `L`. @@ -46,11 +46,11 @@ when defined(Windows): proc deinitSys(L: var SysLock) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "DeleteCriticalSection".} - proc createEvent(lpEventAttributes: pointer, + proc createEvent(lpEventAttributes: pointer, bManualReset, bInitialState: int32, lpName: cstring): SysCond {.stdcall, noSideEffect, dynlib: "kernel32", importc: "CreateEventA".} - + proc closeHandle(hObject: Handle) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "CloseHandle".} proc waitForSingleObject(hHandle: Handle, dwMilliseconds: int32): int32 {. @@ -58,7 +58,7 @@ when defined(Windows): proc signalSysCond(hEvent: SysCond) {.stdcall, noSideEffect, dynlib: "kernel32", importc: "SetEvent".} - + proc initSysCond(cond: var SysCond) {.inline.} = cond = createEvent(nil, 0'i32, 0'i32, nil) proc deinitSysCond(cond: var SysCond) {.inline.} = @@ -86,7 +86,7 @@ else: proc tryAcquireSysAux(L: var SysLock): cint {.noSideEffect, importc: "pthread_mutex_trylock", header: "<pthread.h>".} - proc tryAcquireSys(L: var SysLock): bool {.inline.} = + proc tryAcquireSys(L: var SysLock): bool {.inline.} = result = tryAcquireSysAux(L) == 0'i32 proc releaseSys(L: var SysLock) {.noSideEffect, @@ -100,7 +100,7 @@ else: importc: "pthread_cond_wait", header: "<pthread.h>", noSideEffect.} proc signalSysCond(cond: var SysCond) {. importc: "pthread_cond_signal", header: "<pthread.h>", noSideEffect.} - + proc deinitSysCond(cond: var SysCond) {.noSideEffect, importc: "pthread_cond_destroy", header: "<pthread.h>".} - + diff --git a/lib/system/sysspawn.nim b/lib/system/sysspawn.nim index 5f8f2b2c5..7aef86df9 100644 --- a/lib/system/sysspawn.nim +++ b/lib/system/sysspawn.nim @@ -9,7 +9,7 @@ ## Implements Nim's 'spawn'. -when not declared(NimString): +when not declared(NimString): {.error: "You must not import this module explicitly".} {.push stackTrace:off.} diff --git a/lib/system/timers.nim b/lib/system/timers.nim index 74748c541..ac8418824 100644 --- a/lib/system/timers.nim +++ b/lib/system/timers.nim @@ -34,8 +34,8 @@ when defined(windows): elif defined(macosx): type - MachTimebaseInfoData {.pure, final, - importc: "mach_timebase_info_data_t", + MachTimebaseInfoData {.pure, final, + importc: "mach_timebase_info_data_t", header: "<mach/mach_time.h>".} = object numer, denom: int32 {.deprecated: [TMachTimebaseInfoData: MachTimebaseInfoData].} @@ -46,10 +46,10 @@ elif defined(macosx): proc getTicks(): Ticks {.inline.} = result = Ticks(mach_absolute_time()) - + var timeBaseInfo: MachTimebaseInfoData mach_timebase_info(timeBaseInfo) - + proc `-`(a, b: Ticks): Nanos = result = (a.int64 - b.int64) * timeBaseInfo.numer div timeBaseInfo.denom @@ -57,10 +57,10 @@ elif defined(posixRealtime): type Clockid {.importc: "clockid_t", header: "<time.h>", final.} = object - TimeSpec {.importc: "struct timespec", header: "<time.h>", + TimeSpec {.importc: "struct timespec", header: "<time.h>", final, pure.} = object ## struct timespec - tv_sec: int ## Seconds. - tv_nsec: int ## Nanoseconds. + tv_sec: int ## Seconds. + tv_nsec: int ## Nanoseconds. {.deprecated: [TClockid: Clickid, TTimeSpec: TimeSpec].} var @@ -77,12 +77,12 @@ elif defined(posixRealtime): proc `-`(a, b: Ticks): Nanos {.borrow.} else: - # fallback Posix implementation: + # fallback Posix implementation: type - Timeval {.importc: "struct timeval", header: "<sys/select.h>", + Timeval {.importc: "struct timeval", header: "<sys/select.h>", final, pure.} = object ## struct timeval - tv_sec: int ## Seconds. - tv_usec: int ## Microseconds. + tv_sec: int ## Seconds. + tv_usec: int ## Microseconds. {.deprecated: [Ttimeval: Timeval].} proc posix_gettimeofday(tp: var Timeval, unused: pointer = nil) {. importc: "gettimeofday", header: "<sys/time.h>".} @@ -90,7 +90,7 @@ else: proc getTicks(): Ticks = var t: Timeval posix_gettimeofday(t) - result = Ticks(int64(t.tv_sec) * 1000_000_000'i64 + + result = Ticks(int64(t.tv_sec) * 1000_000_000'i64 + int64(t.tv_usec) * 1000'i64) proc `-`(a, b: Ticks): Nanos {.borrow.} diff --git a/lib/system/widestrs.nim b/lib/system/widestrs.nim index 77310b289..5a30a7c0f 100644 --- a/lib/system/widestrs.nim +++ b/lib/system/widestrs.nim @@ -124,7 +124,7 @@ proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string = if ch >= UNI_SUR_HIGH_START and ch <= UNI_SUR_HIGH_END: # If the 16 bits following the high surrogate are in the source buffer... let ch2 = int(cast[uint16](w[i])) - + # If it's a low surrogate, convert to UTF32: if ch2 >= UNI_SUR_LOW_START and ch2 <= UNI_SUR_LOW_END: ch = (((ch and halfMask) shl halfShift) + (ch2 and halfMask)) + halfBase @@ -135,7 +135,7 @@ proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string = elif ch >= UNI_SUR_LOW_START and ch <= UNI_SUR_LOW_END: #invalid UTF-16 ch = replacement - + if ch < 0x80: result.add chr(ch) elif ch < 0x800: @@ -155,6 +155,6 @@ proc `$`*(w: WideCString, estimate: int, replacement: int = 0xFFFD): string = result.add chr(0xFFFD shr 12 or 0b1110_0000) result.add chr(0xFFFD shr 6 and ones(6) or 0b10_0000_00) result.add chr(0xFFFD and ones(6) or 0b10_0000_00) - + proc `$`*(s: WideCString): string = result = s $ 80 diff --git a/lib/wrappers/libsvm.nim b/lib/wrappers/libsvm.nim index 8cc314412..ac5889410 100644 --- a/lib/wrappers/libsvm.nim +++ b/lib/wrappers/libsvm.nim @@ -10,9 +10,9 @@ ## This module is a low level wrapper for `libsvm`:idx:. {.deadCodeElim: on.} -const +const LIBSVM_VERSION* = 312 - + when defined(windows): const svmdll* = "libsvm.dll" elif defined(macosx): @@ -20,97 +20,97 @@ elif defined(macosx): else: const svmdll* = "libsvm.so" -type - Node*{.pure, final.} = object +type + Node*{.pure, final.} = object index*: cint value*: cdouble - Problem*{.pure, final.} = object + Problem*{.pure, final.} = object L*: cint y*: ptr cdouble x*: ptr ptr Node - Type*{.size: sizeof(cint).} = enum + Type*{.size: sizeof(cint).} = enum C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR - - KernelType*{.size: sizeof(cint).} = enum + + KernelType*{.size: sizeof(cint).} = enum LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED - - Parameter*{.pure, final.} = object + + Parameter*{.pure, final.} = object typ*: Type kernelType*: KernelType - degree*: cint # for poly - gamma*: cdouble # for poly/rbf/sigmoid - coef0*: cdouble # for poly/sigmoid - # these are for training only - cache_size*: cdouble # in MB - eps*: cdouble # stopping criteria - C*: cdouble # for C_SVC, EPSILON_SVR and NU_SVR - nr_weight*: cint # for C_SVC - weight_label*: ptr cint # for C_SVC - weight*: ptr cdouble # for C_SVC - nu*: cdouble # for NU_SVC, ONE_CLASS, and NU_SVR - p*: cdouble # for EPSILON_SVR - shrinking*: cint # use the shrinking heuristics - probability*: cint # do probability estimates + degree*: cint # for poly + gamma*: cdouble # for poly/rbf/sigmoid + coef0*: cdouble # for poly/sigmoid + # these are for training only + cache_size*: cdouble # in MB + eps*: cdouble # stopping criteria + C*: cdouble # for C_SVC, EPSILON_SVR and NU_SVR + nr_weight*: cint # for C_SVC + weight_label*: ptr cint # for C_SVC + weight*: ptr cdouble # for C_SVC + nu*: cdouble # for NU_SVC, ONE_CLASS, and NU_SVR + p*: cdouble # for EPSILON_SVR + shrinking*: cint # use the shrinking heuristics + probability*: cint # do probability estimates {.deprecated: [Tnode: Node, Tproblem: Problem, Ttype: Type, TKernelType: KernelType, Tparameter: Parameter].} # # svm_model -# +# -type - Model*{.pure, final.} = object - param*: Parameter # parameter - nr_class*: cint # number of classes, = 2 in regression/one class svm - L*: cint # total #SV +type + Model*{.pure, final.} = object + param*: Parameter # parameter + nr_class*: cint # number of classes, = 2 in regression/one class svm + L*: cint # total #SV SV*: ptr ptr Node # SVs (SV[l]) - sv_coef*: ptr ptr cdouble # coefficients for SVs in decision functions (sv_coef[k-1][l]) - rho*: ptr cdouble # constants in decision functions (rho[k*(k-1)/2]) - probA*: ptr cdouble # pariwise probability information - probB*: ptr cdouble # for classification only - label*: ptr cint # label of each class (label[k]) - nSV*: ptr cint # number of SVs for each class (nSV[k]) - # nSV[0] + nSV[1] + ... + nSV[k-1] = l - # XXX + sv_coef*: ptr ptr cdouble # coefficients for SVs in decision functions (sv_coef[k-1][l]) + rho*: ptr cdouble # constants in decision functions (rho[k*(k-1)/2]) + probA*: ptr cdouble # pariwise probability information + probB*: ptr cdouble # for classification only + label*: ptr cint # label of each class (label[k]) + nSV*: ptr cint # number of SVs for each class (nSV[k]) + # nSV[0] + nSV[1] + ... + nSV[k-1] = l + # XXX free_sv*: cint # 1 if svm_model is created by svm_load_model # 0 if svm_model is created by svm_train {.deprecated: [TModel: Model].} -proc train*(prob: ptr Problem, param: ptr Parameter): ptr Model{.cdecl, +proc train*(prob: ptr Problem, param: ptr Parameter): ptr Model{.cdecl, importc: "svm_train", dynlib: svmdll.} -proc cross_validation*(prob: ptr Problem, param: ptr Parameter, nr_fold: cint, - target: ptr cdouble){.cdecl, +proc cross_validation*(prob: ptr Problem, param: ptr Parameter, nr_fold: cint, + target: ptr cdouble){.cdecl, importc: "svm_cross_validation", dynlib: svmdll.} -proc save_model*(model_file_name: cstring, model: ptr Model): cint{.cdecl, +proc save_model*(model_file_name: cstring, model: ptr Model): cint{.cdecl, importc: "svm_save_model", dynlib: svmdll.} -proc load_model*(model_file_name: cstring): ptr Model{.cdecl, +proc load_model*(model_file_name: cstring): ptr Model{.cdecl, importc: "svm_load_model", dynlib: svmdll.} -proc get_svm_type*(model: ptr Model): cint{.cdecl, importc: "svm_get_svm_type", +proc get_svm_type*(model: ptr Model): cint{.cdecl, importc: "svm_get_svm_type", dynlib: svmdll.} -proc get_nr_class*(model: ptr Model): cint{.cdecl, importc: "svm_get_nr_class", +proc get_nr_class*(model: ptr Model): cint{.cdecl, importc: "svm_get_nr_class", dynlib: svmdll.} -proc get_labels*(model: ptr Model, label: ptr cint){.cdecl, +proc get_labels*(model: ptr Model, label: ptr cint){.cdecl, importc: "svm_get_labels", dynlib: svmdll.} -proc get_svr_probability*(model: ptr Model): cdouble{.cdecl, +proc get_svr_probability*(model: ptr Model): cdouble{.cdecl, importc: "svm_get_svr_probability", dynlib: svmdll.} proc predict_values*(model: ptr Model, x: ptr Node, dec_values: ptr cdouble): cdouble{. cdecl, importc: "svm_predict_values", dynlib: svmdll.} -proc predict*(model: ptr Model, x: ptr Node): cdouble{.cdecl, +proc predict*(model: ptr Model, x: ptr Node): cdouble{.cdecl, importc: "svm_predict", dynlib: svmdll.} -proc predict_probability*(model: ptr Model, x: ptr Node, - prob_estimates: ptr cdouble): cdouble{.cdecl, +proc predict_probability*(model: ptr Model, x: ptr Node, + prob_estimates: ptr cdouble): cdouble{.cdecl, importc: "svm_predict_probability", dynlib: svmdll.} -proc free_model_content*(model_ptr: ptr Model){.cdecl, +proc free_model_content*(model_ptr: ptr Model){.cdecl, importc: "svm_free_model_content", dynlib: svmdll.} -proc free_and_destroy_model*(model_ptr_ptr: ptr ptr Model){.cdecl, +proc free_and_destroy_model*(model_ptr_ptr: ptr ptr Model){.cdecl, importc: "svm_free_and_destroy_model", dynlib: svmdll.} -proc destroy_param*(param: ptr Parameter){.cdecl, importc: "svm_destroy_param", +proc destroy_param*(param: ptr Parameter){.cdecl, importc: "svm_destroy_param", dynlib: svmdll.} proc check_parameter*(prob: ptr Problem, param: ptr Parameter): cstring{. cdecl, importc: "svm_check_parameter", dynlib: svmdll.} -proc check_probability_model*(model: ptr Model): cint{.cdecl, +proc check_probability_model*(model: ptr Model): cint{.cdecl, importc: "svm_check_probability_model", dynlib: svmdll.} proc set_print_string_function*(print_func: proc (arg: cstring) {.cdecl.}){. diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim index 73b82b5c6..8253e53a5 100644 --- a/lib/wrappers/mysql.nim +++ b/lib/wrappers/mysql.nim @@ -20,7 +20,7 @@ when defined(Unix): when defined(Windows): const lib = "libmysql.dll" -type +type my_bool* = bool Pmy_bool* = ptr my_bool PVIO* = pointer @@ -31,13 +31,13 @@ type PPByte* = pointer cuint* = cint -# ------------ Start of declaration in "mysql_com.h" --------------------- +# ------------ Start of declaration in "mysql_com.h" --------------------- # # ** Common definition between mysql server & client -# +# # Field/table name length -const +const NAME_LEN* = 64 HOSTNAME_LENGTH* = 60 USERNAME_LENGTH* = 16 @@ -46,27 +46,27 @@ const LOCAL_HOST* = "localhost" LOCAL_HOST_NAMEDPIPE* = '.' -const +const NAMEDPIPE* = "MySQL" SERVICENAME* = "MySQL" -type - Enum_server_command* = enum - COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST, COM_CREATE_DB, - COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS, COM_PROCESS_INFO, - COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, COM_TIME, - COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TABLE_DUMP, - COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_STMT_PREPARE, COM_STMT_EXECUTE, - COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, COM_STMT_RESET, COM_SET_OPTION, +type + Enum_server_command* = enum + COM_SLEEP, COM_QUIT, COM_INIT_DB, COM_QUERY, COM_FIELD_LIST, COM_CREATE_DB, + COM_DROP_DB, COM_REFRESH, COM_SHUTDOWN, COM_STATISTICS, COM_PROCESS_INFO, + COM_CONNECT, COM_PROCESS_KILL, COM_DEBUG, COM_PING, COM_TIME, + COM_DELAYED_INSERT, COM_CHANGE_USER, COM_BINLOG_DUMP, COM_TABLE_DUMP, + COM_CONNECT_OUT, COM_REGISTER_SLAVE, COM_STMT_PREPARE, COM_STMT_EXECUTE, + COM_STMT_SEND_LONG_DATA, COM_STMT_CLOSE, COM_STMT_RESET, COM_SET_OPTION, COM_STMT_FETCH, COM_END {.deprecated: [Tenum_server_command: Enum_server_command].} -const - SCRAMBLE_LENGTH* = 20 # Length of random string sent by server on handshake; - # this is also length of obfuscated password, +const + SCRAMBLE_LENGTH* = 20 # Length of random string sent by server on handshake; + # this is also length of obfuscated password, # received from client - SCRAMBLE_LENGTH_323* = 8 # length of password stored in the db: - # new passwords are preceded with '*' + SCRAMBLE_LENGTH_323* = 8 # length of password stored in the db: + # new passwords are preceded with '*' SCRAMBLED_PASSWORD_CHAR_LENGTH* = SCRAMBLE_LENGTH * 2 + 1 SCRAMBLED_PASSWORD_CHAR_LENGTH_323* = SCRAMBLE_LENGTH_323 * 2 NOT_NULL_FLAG* = 1 # Field can't be NULL @@ -77,7 +77,7 @@ const UNSIGNED_FLAG* = 32 # Field is unsigned ZEROFILL_FLAG* = 64 # Field is zerofill BINARY_FLAG* = 128 # Field is binary - # The following are only sent to new clients + # The following are only sent to new clients ENUM_FLAG* = 256 # field is an enum AUTO_INCREMENT_FLAG* = 512 # field is a autoincrement field TIMESTAMP_FLAG* = 1024 # Field is a timestamp @@ -96,7 +96,7 @@ const REFRESH_THREADS* = 32 # Flush thread cache REFRESH_SLAVE* = 64 # Reset master info and restart slave thread REFRESH_MASTER* = 128 # Remove all bin logs in the index and truncate the index - # The following can't be set with mysql_refresh() + # The following can't be set with mysql_refresh() REFRESH_READ_LOCK* = 16384 # Lock tables for read REFRESH_FAST* = 32768 # Intern flag REFRESH_QUERY_CACHE* = 65536 # RESET (remove all queries) from query cache @@ -129,9 +129,9 @@ const SERVER_QUERY_NO_GOOD_INDEX_USED* = 16 SERVER_QUERY_NO_INDEX_USED* = 32 # The server was able to fulfill the clients request and opened a # read-only non-scrollable cursor for a query. This flag comes - # in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. + # in reply to COM_STMT_EXECUTE and COM_STMT_FETCH commands. SERVER_STATUS_CURSOR_EXISTS* = 64 # This flag is sent when a read-only cursor is exhausted, in reply to - # COM_STMT_FETCH command. + # COM_STMT_FETCH command. SERVER_STATUS_LAST_ROW_SENT* = 128 SERVER_STATUS_DB_DROPPED* = 256 # A database was dropped SERVER_STATUS_NO_BACKSLASH_ESCAPES* = 512 @@ -141,7 +141,7 @@ const NET_WAIT_TIMEOUT* = 8 * 60 * 60 # Wait for new query ONLY_KILL_QUERY* = 1 -const +const MAX_TINYINT_WIDTH* = 3 # Max width for a TINY w.o. sign MAX_SMALLINT_WIDTH* = 5 # Max width for a SHORT w.o. sign MAX_MEDIUMINT_WIDTH* = 8 # Max width for a INT24 w.o. sign @@ -150,9 +150,9 @@ const MAX_CHAR_WIDTH* = 255 # Max length for a CHAR column MAX_BLOB_WIDTH* = 8192 # Default width for blob -type +type Pst_net* = ptr St_net - St_net*{.final.} = object + St_net*{.final.} = object vio*: PVio buff*: cstring buff_end*: cstring @@ -169,7 +169,7 @@ type fcntl*: cint compress*: my_bool # The following variable is set if we are doing several queries in one # command ( as in LOAD TABLE ... FROM MASTER ), - # and do not want to confuse the client with OK at the wrong time + # and do not want to confuse the client with OK at the wrong time remain_in_buf*: int len*: int buf_length*: int @@ -182,7 +182,7 @@ type no_send_error*: my_bool # Set if OK packet is already sent, and # we do not need to send error messages # Pointer to query object in query cache, do not equal NULL (0) for - # queries in cache that have not stored its results yet + # queries in cache that have not stored its results yet # $endif last_error*: array[0..(ERRMSG_SIZE) - 1, char] sqlstate*: array[0..(SQLSTATE_LENGTH + 1) - 1, char] @@ -196,21 +196,21 @@ type PNET* = ptr NET {.deprecated: [Tst_net: St_net, TNET: NET].} -const +const packet_error* = - 1 -type - Enum_field_types* = enum # For backward compatibility - TYPE_DECIMAL, TYPE_TINY, TYPE_SHORT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, - TYPE_NULL, TYPE_TIMESTAMP, TYPE_LONGLONG, TYPE_INT24, TYPE_DATE, TYPE_TIME, - TYPE_DATETIME, TYPE_YEAR, TYPE_NEWDATE, TYPE_VARCHAR, TYPE_BIT, - TYPE_NEWDECIMAL = 246, TYPE_ENUM = 247, TYPE_SET = 248, - TYPE_TINY_BLOB = 249, TYPE_MEDIUM_BLOB = 250, TYPE_LONG_BLOB = 251, - TYPE_BLOB = 252, TYPE_VAR_STRING = 253, TYPE_STRING = 254, +type + Enum_field_types* = enum # For backward compatibility + TYPE_DECIMAL, TYPE_TINY, TYPE_SHORT, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, + TYPE_NULL, TYPE_TIMESTAMP, TYPE_LONGLONG, TYPE_INT24, TYPE_DATE, TYPE_TIME, + TYPE_DATETIME, TYPE_YEAR, TYPE_NEWDATE, TYPE_VARCHAR, TYPE_BIT, + TYPE_NEWDECIMAL = 246, TYPE_ENUM = 247, TYPE_SET = 248, + TYPE_TINY_BLOB = 249, TYPE_MEDIUM_BLOB = 250, TYPE_LONG_BLOB = 251, + TYPE_BLOB = 252, TYPE_VAR_STRING = 253, TYPE_STRING = 254, TYPE_GEOMETRY = 255 {.deprecated: [Tenum_field_types: Enum_field_types].} -const +const CLIENT_MULTI_QUERIES* = CLIENT_MULTI_STATEMENTS FIELD_TYPE_DECIMAL* = TYPE_DECIMAL FIELD_TYPE_NEWDECIMAL* = TYPE_NEWDECIMAL @@ -239,67 +239,67 @@ const FIELD_TYPE_CHAR* = TYPE_TINY FIELD_TYPE_INTERVAL* = TYPE_ENUM FIELD_TYPE_GEOMETRY* = TYPE_GEOMETRY - FIELD_TYPE_BIT* = TYPE_BIT # Shutdown/kill enums and constants - # Bits for THD::killable. + FIELD_TYPE_BIT* = TYPE_BIT # Shutdown/kill enums and constants + # Bits for THD::killable. SHUTDOWN_KILLABLE_CONNECT* = chr(1 shl 0) SHUTDOWN_KILLABLE_TRANS* = chr(1 shl 1) SHUTDOWN_KILLABLE_LOCK_TABLE* = chr(1 shl 2) SHUTDOWN_KILLABLE_UPDATE* = chr(1 shl 3) -type - Enum_shutdown_level* = enum - SHUTDOWN_DEFAULT = 0, SHUTDOWN_WAIT_CONNECTIONS = 1, - SHUTDOWN_WAIT_TRANSACTIONS = 2, SHUTDOWN_WAIT_UPDATES = 8, - SHUTDOWN_WAIT_ALL_BUFFERS = 16, SHUTDOWN_WAIT_CRITICAL_BUFFERS = 17, +type + Enum_shutdown_level* = enum + SHUTDOWN_DEFAULT = 0, SHUTDOWN_WAIT_CONNECTIONS = 1, + SHUTDOWN_WAIT_TRANSACTIONS = 2, SHUTDOWN_WAIT_UPDATES = 8, + SHUTDOWN_WAIT_ALL_BUFFERS = 16, SHUTDOWN_WAIT_CRITICAL_BUFFERS = 17, KILL_QUERY = 254, KILL_CONNECTION = 255 - Enum_cursor_type* = enum # options for mysql_set_option - CURSOR_TYPE_NO_CURSOR = 0, CURSOR_TYPE_READ_ONLY = 1, + Enum_cursor_type* = enum # options for mysql_set_option + CURSOR_TYPE_NO_CURSOR = 0, CURSOR_TYPE_READ_ONLY = 1, CURSOR_TYPE_FOR_UPDATE = 2, CURSOR_TYPE_SCROLLABLE = 4 - Enum_mysql_set_option* = enum + Enum_mysql_set_option* = enum OPTION_MULTI_STATEMENTS_ON, OPTION_MULTI_STATEMENTS_OFF {.deprecated: [Tenum_shutdown_level: Enum_shutdown_level, Tenum_cursor_type: Enum_cursor_type, Tenum_mysql_set_option: Enum_mysql_set_option].} -proc my_net_init*(net: PNET, vio: PVio): my_bool{.cdecl, dynlib: lib, +proc my_net_init*(net: PNET, vio: PVio): my_bool{.cdecl, dynlib: lib, importc: "my_net_init".} -proc my_net_local_init*(net: PNET){.cdecl, dynlib: lib, +proc my_net_local_init*(net: PNET){.cdecl, dynlib: lib, importc: "my_net_local_init".} proc net_end*(net: PNET){.cdecl, dynlib: lib, importc: "net_end".} proc net_clear*(net: PNET){.cdecl, dynlib: lib, importc: "net_clear".} -proc net_realloc*(net: PNET, len: int): my_bool{.cdecl, dynlib: lib, +proc net_realloc*(net: PNET, len: int): my_bool{.cdecl, dynlib: lib, importc: "net_realloc".} proc net_flush*(net: PNET): my_bool{.cdecl, dynlib: lib, importc: "net_flush".} -proc my_net_write*(net: PNET, packet: cstring, length: int): my_bool{.cdecl, +proc my_net_write*(net: PNET, packet: cstring, length: int): my_bool{.cdecl, dynlib: lib, importc: "my_net_write".} -proc net_write_command*(net: PNET, command: char, header: cstring, +proc net_write_command*(net: PNET, command: char, header: cstring, head_len: int, packet: cstring, length: int): my_bool{. cdecl, dynlib: lib, importc: "net_write_command".} -proc net_real_write*(net: PNET, packet: cstring, length: int): cint{.cdecl, +proc net_real_write*(net: PNET, packet: cstring, length: int): cint{.cdecl, dynlib: lib, importc: "net_real_write".} proc my_net_read*(net: PNET): int{.cdecl, dynlib: lib, importc: "my_net_read".} # The following function is not meant for normal usage - # Currently it's used internally by manager.c -type + # Currently it's used internally by manager.c +type Psockaddr* = ptr Sockaddr Sockaddr*{.final.} = object # undefined structure {.deprecated: [Tsockaddr: Sockaddr].} proc my_connect*(s: my_socket, name: Psockaddr, namelen: cuint, timeout: cuint): cint{. cdecl, dynlib: lib, importc: "my_connect".} -type +type Prand_struct* = ptr Rand_struct - Rand_struct*{.final.} = object # The following is for user defined functions + Rand_struct*{.final.} = object # The following is for user defined functions seed1*: int seed2*: int max_value*: int max_value_dbl*: cdouble - Item_result* = enum + Item_result* = enum STRING_RESULT, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT PItem_result* = ptr Item_result Pst_udf_args* = ptr St_udf_args - St_udf_args*{.final.} = object + St_udf_args*{.final.} = object arg_count*: cuint # Number of arguments arg_type*: PItem_result # Pointer to item_results args*: cstringArray # Pointer to item_results @@ -307,82 +307,82 @@ type maybe_null*: cstring # Length of string arguments attributes*: cstringArray # Pointer to attribute name attribute_lengths*: ptr int # Length of attribute arguments - + UDF_ARGS* = St_udf_args - PUDF_ARGS* = ptr UDF_ARGS # This holds information about the result + PUDF_ARGS* = ptr UDF_ARGS # This holds information about the result Pst_udf_init* = ptr St_udf_init - St_udf_init*{.final.} = object + St_udf_init*{.final.} = object maybe_null*: my_bool # 1 if function can return NULL decimals*: cuint # for real functions max_length*: int # For string functions theptr*: cstring # free pointer for function data const_item*: my_bool # free pointer for function data - + UDF_INIT* = St_udf_init - PUDF_INIT* = ptr UDF_INIT # Constants when using compression + PUDF_INIT* = ptr UDF_INIT # Constants when using compression {.deprecated: [Trand_stuct: Rand_struct, TItem_result: Item_result, Tst_udf_args: St_udf_args, TUDF_ARGS: UDF_ARGS, Tst_udf_init: St_udf_init, TUDF_INIT: UDF_INIT].} -const +const NET_HEADER_SIZE* = 4 # standard header size COMP_HEADER_SIZE* = 3 # compression header extra size - # Prototypes to password functions + # Prototypes to password functions # These functions are used for authentication by client and server and - # implemented in sql/password.c + # implemented in sql/password.c -proc randominit*(para1: Prand_struct, seed1: int, seed2: int){.cdecl, +proc randominit*(para1: Prand_struct, seed1: int, seed2: int){.cdecl, dynlib: lib, importc: "randominit".} -proc my_rnd*(para1: Prand_struct): cdouble{.cdecl, dynlib: lib, +proc my_rnd*(para1: Prand_struct): cdouble{.cdecl, dynlib: lib, importc: "my_rnd".} proc create_random_string*(fto: cstring, len: cuint, rand_st: Prand_struct){. cdecl, dynlib: lib, importc: "create_random_string".} -proc hash_password*(fto: int, password: cstring, password_len: cuint){.cdecl, +proc hash_password*(fto: int, password: cstring, password_len: cuint){.cdecl, dynlib: lib, importc: "hash_password".} -proc make_scrambled_password_323*(fto: cstring, password: cstring){.cdecl, +proc make_scrambled_password_323*(fto: cstring, password: cstring){.cdecl, dynlib: lib, importc: "make_scrambled_password_323".} -proc scramble_323*(fto: cstring, message: cstring, password: cstring){.cdecl, +proc scramble_323*(fto: cstring, message: cstring, password: cstring){.cdecl, dynlib: lib, importc: "scramble_323".} proc check_scramble_323*(para1: cstring, message: cstring, salt: int): my_bool{. cdecl, dynlib: lib, importc: "check_scramble_323".} -proc get_salt_from_password_323*(res: ptr int, password: cstring){.cdecl, +proc get_salt_from_password_323*(res: ptr int, password: cstring){.cdecl, dynlib: lib, importc: "get_salt_from_password_323".} -proc make_password_from_salt_323*(fto: cstring, salt: ptr int){.cdecl, +proc make_password_from_salt_323*(fto: cstring, salt: ptr int){.cdecl, dynlib: lib, importc: "make_password_from_salt_323".} -proc octet2hex*(fto: cstring, str: cstring, length: cuint): cstring{.cdecl, +proc octet2hex*(fto: cstring, str: cstring, length: cuint): cstring{.cdecl, dynlib: lib, importc: "octet2hex".} -proc make_scrambled_password*(fto: cstring, password: cstring){.cdecl, +proc make_scrambled_password*(fto: cstring, password: cstring){.cdecl, dynlib: lib, importc: "make_scrambled_password".} -proc scramble*(fto: cstring, message: cstring, password: cstring){.cdecl, +proc scramble*(fto: cstring, message: cstring, password: cstring){.cdecl, dynlib: lib, importc: "scramble".} proc check_scramble*(reply: cstring, message: cstring, hash_stage2: pointer): my_bool{. cdecl, dynlib: lib, importc: "check_scramble".} -proc get_salt_from_password*(res: pointer, password: cstring){.cdecl, +proc get_salt_from_password*(res: pointer, password: cstring){.cdecl, dynlib: lib, importc: "get_salt_from_password".} -proc make_password_from_salt*(fto: cstring, hash_stage2: pointer){.cdecl, +proc make_password_from_salt*(fto: cstring, hash_stage2: pointer){.cdecl, dynlib: lib, importc: "make_password_from_salt".} - # end of password.c -proc get_tty_password*(opt_message: cstring): cstring{.cdecl, dynlib: lib, + # end of password.c +proc get_tty_password*(opt_message: cstring): cstring{.cdecl, dynlib: lib, importc: "get_tty_password".} -proc errno_to_sqlstate*(errno: cuint): cstring{.cdecl, dynlib: lib, +proc errno_to_sqlstate*(errno: cuint): cstring{.cdecl, dynlib: lib, importc: "mysql_errno_to_sqlstate".} - # Some other useful functions -proc modify_defaults_file*(file_location: cstring, option: cstring, - option_value: cstring, section_name: cstring, - remove_option: cint): cint{.cdecl, dynlib: lib, + # Some other useful functions +proc modify_defaults_file*(file_location: cstring, option: cstring, + option_value: cstring, section_name: cstring, + remove_option: cint): cint{.cdecl, dynlib: lib, importc: "load_defaults".} -proc load_defaults*(conf_file: cstring, groups: cstringArray, argc: ptr cint, - argv: ptr cstringArray): cint{.cdecl, dynlib: lib, +proc load_defaults*(conf_file: cstring, groups: cstringArray, argc: ptr cint, + argv: ptr cstringArray): cint{.cdecl, dynlib: lib, importc: "load_defaults".} proc my_init*(): my_bool{.cdecl, dynlib: lib, importc: "my_init".} proc my_thread_init*(): my_bool{.cdecl, dynlib: lib, importc: "my_thread_init".} proc my_thread_end*(){.cdecl, dynlib: lib, importc: "my_thread_end".} -const +const NULL_LENGTH*: int = int(not (0)) # For net_store_length -const +const STMT_HEADER* = 4 - LONG_DATA_HEADER* = 6 # ------------ Stop of declaration in "mysql_com.h" ----------------------- + LONG_DATA_HEADER* = 6 # ------------ Stop of declaration in "mysql_com.h" ----------------------- # $include "mysql_time.h" # $include "mysql_version.h" # $include "typelib.h" @@ -391,13 +391,13 @@ const # mysql_port : cuint;cvar;external; # mysql_unix_port : Pchar;cvar;external; -const +const CLIENT_NET_READ_TIMEOUT* = 365 * 24 * 3600 # Timeout on read CLIENT_NET_WRITE_TIMEOUT* = 365 * 24 * 3600 # Timeout on write -type +type Pst_mysql_field* = ptr St_mysql_field - St_mysql_field*{.final.} = object + St_mysql_field*{.final.} = object name*: cstring # Name of column org_name*: cstring # Original column name, if an alias table*: cstring # Table of column if column was a field @@ -418,7 +418,7 @@ type decimals*: cuint # Number of decimals in field charsetnr*: cuint # Character set ftype*: Enum_field_types # Type of field. See mysql_com.h for types - + FIELD* = St_mysql_field PFIELD* = ptr FIELD PROW* = ptr ROW # return data as array of strings @@ -434,16 +434,16 @@ proc IS_BLOB*(n: int32): bool proc IS_NUM*(t: Enum_field_types): bool proc INTERNAL_NUM_FIELD*(f: Pst_mysql_field): bool proc IS_NUM_FIELD*(f: Pst_mysql_field): bool -type +type my_ulonglong* = int64 Pmy_ulonglong* = ptr my_ulonglong -const +const COUNT_ERROR* = not (my_ulonglong(0)) -type +type Pst_mysql_rows* = ptr St_mysql_rows - St_mysql_rows*{.final.} = object + St_mysql_rows*{.final.} = object next*: Pst_mysql_rows # list of rows data*: ROW len*: int @@ -451,25 +451,25 @@ type ROWS* = St_mysql_rows PROWS* = ptr ROWS PROW_OFFSET* = ptr ROW_OFFSET # offset to current row - ROW_OFFSET* = ROWS + ROW_OFFSET* = ROWS {.deprecated: [Tst_mysql_rows: St_mysql_rows, TROWS: ROWS, TROW_OFFSET: ROW_OFFSET].} - -const + +const ALLOC_MAX_BLOCK_TO_DROP* = 4096 - ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP* = 10 # struct for once_alloc (block) + ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP* = 10 # struct for once_alloc (block) -type +type Pst_used_mem* = ptr St_used_mem - St_used_mem*{.final.} = object + St_used_mem*{.final.} = object next*: Pst_used_mem # Next block in use left*: cuint # memory left in block size*: cuint # size of block - + USED_MEM* = St_used_mem PUSED_MEM* = ptr USED_MEM Pst_mem_root* = ptr St_mem_root - St_mem_root*{.final.} = object + St_mem_root*{.final.} = object free*: PUSED_MEM # blocks with free memory in it used*: PUSED_MEM # blocks almost without free memory pre_alloc*: PUSED_MEM # preallocated block @@ -477,18 +477,18 @@ type block_size*: cuint # initial block size block_num*: cuint # allocated blocks counter # first free block in queue test counter (if it exceed - # MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) + # MAX_BLOCK_USAGE_BEFORE_DROP block will be dropped in 'used' list) first_block_usage*: cuint error_handler*: proc (){.cdecl.} MEM_ROOT* = St_mem_root - PMEM_ROOT* = ptr MEM_ROOT # ------------ Stop of declaration in "my_alloc.h" ---------------------- + PMEM_ROOT* = ptr MEM_ROOT # ------------ Stop of declaration in "my_alloc.h" ---------------------- {.deprecated: [Tst_used_mem: St_used_mem, TUSED_MEM: USED_MEM, Tst_mem_root: St_mem_root, TMEM_ROOT: MEM_ROOT].} -type +type Pst_mysql_data* = ptr St_mysql_data - St_mysql_data*{.final.} = object + St_mysql_data*{.final.} = object rows*: my_ulonglong fields*: cuint data*: PROWS @@ -497,16 +497,16 @@ type DATA* = St_mysql_data PDATA* = ptr DATA - Option* = enum - OPT_CONNECT_TIMEOUT, OPT_COMPRESS, OPT_NAMED_PIPE, INIT_COMMAND, - READ_DEFAULT_FILE, READ_DEFAULT_GROUP, SET_CHARSET_DIR, SET_CHARSET_NAME, - OPT_LOCAL_INFILE, OPT_PROTOCOL, SHARED_MEMORY_BASE_NAME, OPT_READ_TIMEOUT, - OPT_WRITE_TIMEOUT, OPT_USE_RESULT, OPT_USE_REMOTE_CONNECTION, - OPT_USE_EMBEDDED_CONNECTION, OPT_GUESS_CONNECTION, SET_CLIENT_IP, + Option* = enum + OPT_CONNECT_TIMEOUT, OPT_COMPRESS, OPT_NAMED_PIPE, INIT_COMMAND, + READ_DEFAULT_FILE, READ_DEFAULT_GROUP, SET_CHARSET_DIR, SET_CHARSET_NAME, + OPT_LOCAL_INFILE, OPT_PROTOCOL, SHARED_MEMORY_BASE_NAME, OPT_READ_TIMEOUT, + OPT_WRITE_TIMEOUT, OPT_USE_RESULT, OPT_USE_REMOTE_CONNECTION, + OPT_USE_EMBEDDED_CONNECTION, OPT_GUESS_CONNECTION, SET_CLIENT_IP, SECURE_AUTH, REPORT_DATA_TRUNCATION, OPT_RECONNECT {.deprecated: [Tst_mysql_data: St_mysql_data, TDATA: DATA, Toption: Option].} -const +const MAX_MYSQL_MANAGER_ERR* = 256 MAX_MYSQL_MANAGER_MSG* = 256 MANAGER_OK* = 200 @@ -515,8 +515,8 @@ const MANAGER_CLIENT_ERR* = 450 MANAGER_INTERNAL_ERR* = 500 -type - St_dynamic_array*{.final.} = object +type + St_dynamic_array*{.final.} = object buffer*: cstring elements*: cuint max_element*: cuint @@ -526,7 +526,7 @@ type DYNAMIC_ARRAY* = St_dynamic_array Pst_dynamic_array* = ptr St_dynamic_array Pst_mysql_options* = ptr St_mysql_options - St_mysql_options*{.final.} = object + St_mysql_options*{.final.} = object connect_timeout*: cuint read_timeout*: cuint write_timeout*: cuint @@ -553,18 +553,18 @@ type use_ssl*: my_bool # if to use SSL or not compress*: my_bool named_pipe*: my_bool # On connect, find out the replication role of the server, and - # establish connections to all the peers + # establish connections to all the peers rpl_probe*: my_bool # Each call to mysql_real_query() will parse it to tell if it is a read - # or a write, and direct it to the slave or the master + # or a write, and direct it to the slave or the master rpl_parse*: my_bool # If set, never read from a master, only from slave, when doing - # a read that is replication-aware + # a read that is replication-aware no_master_reads*: my_bool separate_thread*: my_bool methods_to_use*: Option client_ip*: cstring secure_auth*: my_bool # Refuse client connecting to server if it uses old (pre-4.1.1) protocol report_data_truncation*: my_bool # 0 - never report, 1 - always report (default) - # function pointers for local infile support + # function pointers for local infile support local_infile_init*: proc (para1: var pointer, para2: cstring, para3: pointer): cint{. cdecl.} local_infile_read*: proc (para1: pointer, para2: cstring, para3: cuint): cint @@ -572,16 +572,16 @@ type local_infile_error*: proc (para1: pointer, para2: cstring, para3: cuint): cint local_infile_userdata*: pointer - Status* = enum + Status* = enum STATUS_READY, STATUS_GET_RESULT, STATUS_USE_RESULT Protocol_type* = enum # There are three types of queries - the ones that have to go to # the master, the ones that go to a slave, and the administrative - # type which must happen on the pivot connectioin - PROTOCOL_DEFAULT, PROTOCOL_TCP, PROTOCOL_SOCKET, PROTOCOL_PIPE, + # type which must happen on the pivot connectioin + PROTOCOL_DEFAULT, PROTOCOL_TCP, PROTOCOL_SOCKET, PROTOCOL_PIPE, PROTOCOL_MEMORY - Rpl_type* = enum + Rpl_type* = enum RPL_MASTER, RPL_SLAVE, RPL_ADMIN - Charset_info_st*{.final.} = object + Charset_info_st*{.final.} = object number*: cuint primary_number*: cuint binary_number*: cuint @@ -608,11 +608,11 @@ type escape_with_backslash_is_dangerous*: my_bool cset*: pointer # was ^MY_CHARSET_HANDLER coll*: pointer # was ^MY_COLLATION_HANDLER; - + CHARSET_INFO* = Charset_info_st Pcharset_info_st* = ptr Charset_info_st Pcharacter_set* = ptr Character_set - Character_set*{.final.} = object + Character_set*{.final.} = object number*: cuint state*: cuint csname*: cstring @@ -626,7 +626,7 @@ type PMY_CHARSET_INFO* = ptr MY_CHARSET_INFO Pst_mysql_methods* = ptr St_mysql_methods Pst_mysql* = ptr St_mysql - St_mysql*{.final.} = object + St_mysql*{.final.} = object net*: NET # Communication parameters connector_fd*: gptr # ConnectorFd for SSL host*: cstring @@ -659,9 +659,9 @@ type reconnect*: my_bool # set to 1 if automatic reconnect scramble*: array[0..(SCRAMBLE_LENGTH + 1) - 1, char] # session-wide random string # Set if this is the original connection, not a master or a slave we have - # added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave() + # added though mysql_rpl_probe() or mysql_set_master()/ mysql_add_slave() rpl_pivot*: my_bool # Pointers to the master, and the next slave connections, points to - # itself if lone connection. + # itself if lone connection. master*: Pst_mysql next_slave*: Pst_mysql last_used_slave*: Pst_mysql # needed for round-robin slave pick @@ -669,13 +669,13 @@ type stmts*: pointer # was PList, list of all statements methods*: Pst_mysql_methods thd*: pointer # Points to boolean flag in MYSQL_RES or MYSQL_STMT. We set this flag - # from mysql_stmt_close if close had to cancel result set of this object. + # from mysql_stmt_close if close had to cancel result set of this object. unbuffered_fetch_owner*: Pmy_bool MySQL* = St_mysql PMySQL* = ptr MySQL Pst_mysql_res* = ptr St_mysql_res - St_mysql_res*{.final.} = object + St_mysql_res*{.final.} = object row_count*: my_ulonglong fields*: PFIELD data*: PDATA @@ -695,10 +695,10 @@ type PRES* = ptr RES Pst_mysql_stmt* = ptr St_mysql_stmt PSTMT* = ptr STMT - St_mysql_methods*{.final.} = object + St_mysql_methods*{.final.} = object read_query_result*: proc (MySQL: PMySQL): my_bool{.cdecl.} - advanced_command*: proc (MySQL: PMySQL, command: Enum_server_command, header: cstring, - header_length: int, arg: cstring, arg_length: int, + advanced_command*: proc (MySQL: PMySQL, command: Enum_server_command, header: cstring, + header_length: int, arg: cstring, arg_length: int, skip_check: my_bool): my_bool read_rows*: proc (MySQL: PMySQL, fields: PFIELD, fields_count: cuint): PDATA use_result*: proc (MySQL: PMySQL): PRES @@ -718,7 +718,7 @@ type METHODS* = St_mysql_methods PMETHODS* = ptr METHODS Pst_mysql_manager* = ptr St_mysql_manager - St_mysql_manager*{.final.} = object + St_mysql_manager*{.final.} = object net*: NET host*: cstring user*: cstring @@ -737,23 +737,23 @@ type MANAGER* = St_mysql_manager PMANAGER* = ptr MANAGER Pst_mysql_parameters* = ptr St_mysql_parameters - St_mysql_parameters*{.final.} = object + St_mysql_parameters*{.final.} = object p_max_allowed_packet*: ptr int p_net_buffer_length*: ptr int PARAMETERS* = St_mysql_parameters PPARAMETERS* = ptr PARAMETERS - Enum_mysql_stmt_state* = enum + Enum_mysql_stmt_state* = enum STMT_INIT_DONE = 1, STMT_PREPARE_DONE, STMT_EXECUTE_DONE, STMT_FETCH_DONE Pst_mysql_bind* = ptr St_mysql_bind - St_mysql_bind*{.final.} = object + St_mysql_bind*{.final.} = object len*: int # output length pointer is_null*: Pmy_bool # Pointer to null indicator buffer*: pointer # buffer to get/put data error*: PMy_bool # set this if you want to track data truncations happened during fetch buffer_type*: Enum_field_types # buffer type buffer_length*: int # buffer length, must be set for str/binary - # Following are for internal use. Set by mysql_stmt_bind_param + # Following are for internal use. Set by mysql_stmt_bind_param row_ptr*: ptr byte # for the current data position offset*: int # offset position for char/binary fetch length_value*: int # Used if length is 0 @@ -768,8 +768,8 @@ type skip_result*: proc (para1: Pst_mysql_bind, para2: PFIELD, row: PPbyte) BIND* = St_mysql_bind - PBIND* = ptr BIND # statement handler - St_mysql_stmt*{.final.} = object + PBIND* = ptr BIND # statement handler + St_mysql_stmt*{.final.} = object mem_root*: MEM_ROOT # root allocations mysql*: PMySQL # connection handle params*: PBIND # input parameters @@ -797,9 +797,9 @@ type unbuffered_fetch_cancelled*: my_bool update_max_length*: my_bool - STMT* = St_mysql_stmt - - Enum_stmt_attr_type* = enum + STMT* = St_mysql_stmt + + Enum_stmt_attr_type* = enum STMT_ATTR_UPDATE_MAX_LENGTH, STMT_ATTR_CURSOR_TYPE, STMT_ATTR_PREFETCH_ROWS {.deprecated: [Tst_dynamic_array: St_dynamic_array, Tst_mysql_options: St_mysql_options, TDYNAMIC_ARRAY: DYNAMIC_ARRAY, Tprotocol_type: Protocol_type, @@ -824,283 +824,283 @@ proc server_end*(){.cdecl, dynlib: lib, importc: "mysql_server_end".} # mysql_server_end() to free memory). The names are a bit misleading # (mysql_SERVER* to be used when using libmysqlCLIENT). So we add more general # names which suit well whether you're using libmysqld or libmysqlclient. We - # intend to promote these aliases over the mysql_server* ones. + # intend to promote these aliases over the mysql_server* ones. proc library_init*(argc: cint, argv: cstringArray, groups: cstringArray): cint{. cdecl, dynlib: lib, importc: "mysql_server_init".} proc library_end*(){.cdecl, dynlib: lib, importc: "mysql_server_end".} -proc get_parameters*(): PPARAMETERS{.stdcall, dynlib: lib, +proc get_parameters*(): PPARAMETERS{.stdcall, dynlib: lib, importc: "mysql_get_parameters".} # Set up and bring down a thread; these function should be called # for each thread in an application which opens at least one MySQL # connection. All uses of the connection(s) should be between these - # function calls. + # function calls. proc thread_init*(): my_bool{.stdcall, dynlib: lib, importc: "mysql_thread_init".} proc thread_end*(){.stdcall, dynlib: lib, importc: "mysql_thread_end".} # Functions to get information from the MYSQL and MYSQL_RES structures - # Should definitely be used if one uses shared libraries. -proc num_rows*(res: PRES): my_ulonglong{.stdcall, dynlib: lib, + # Should definitely be used if one uses shared libraries. +proc num_rows*(res: PRES): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_num_rows".} -proc num_fields*(res: PRES): cuint{.stdcall, dynlib: lib, +proc num_fields*(res: PRES): cuint{.stdcall, dynlib: lib, importc: "mysql_num_fields".} proc eof*(res: PRES): my_bool{.stdcall, dynlib: lib, importc: "mysql_eof".} -proc fetch_field_direct*(res: PRES, fieldnr: cuint): PFIELD{.stdcall, +proc fetch_field_direct*(res: PRES, fieldnr: cuint): PFIELD{.stdcall, dynlib: lib, importc: "mysql_fetch_field_direct".} -proc fetch_fields*(res: PRES): PFIELD{.stdcall, dynlib: lib, +proc fetch_fields*(res: PRES): PFIELD{.stdcall, dynlib: lib, importc: "mysql_fetch_fields".} -proc row_tell*(res: PRES): ROW_OFFSET{.stdcall, dynlib: lib, +proc row_tell*(res: PRES): ROW_OFFSET{.stdcall, dynlib: lib, importc: "mysql_row_tell".} -proc field_tell*(res: PRES): FIELD_OFFSET{.stdcall, dynlib: lib, +proc field_tell*(res: PRES): FIELD_OFFSET{.stdcall, dynlib: lib, importc: "mysql_field_tell".} -proc field_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, +proc field_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, importc: "mysql_field_count".} -proc affected_rows*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib, +proc affected_rows*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_affected_rows".} -proc insert_id*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib, +proc insert_id*(MySQL: PMySQL): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_insert_id".} proc errno*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, importc: "mysql_errno".} proc error*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_error".} proc sqlstate*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_sqlstate".} -proc warning_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, +proc warning_count*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, importc: "mysql_warning_count".} proc info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_info".} proc thread_id*(MySQL: PMySQL): int{.stdcall, dynlib: lib, importc: "mysql_thread_id".} -proc character_set_name*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, +proc character_set_name*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_character_set_name".} -proc set_character_set*(MySQL: PMySQL, csname: cstring): int32{.stdcall, dynlib: lib, +proc set_character_set*(MySQL: PMySQL, csname: cstring): int32{.stdcall, dynlib: lib, importc: "mysql_set_character_set".} proc init*(MySQL: PMySQL): PMySQL{.stdcall, dynlib: lib, importc: "mysql_init".} -proc ssl_set*(MySQL: PMySQL, key: cstring, cert: cstring, ca: cstring, capath: cstring, - cipher: cstring): my_bool{.stdcall, dynlib: lib, +proc ssl_set*(MySQL: PMySQL, key: cstring, cert: cstring, ca: cstring, capath: cstring, + cipher: cstring): my_bool{.stdcall, dynlib: lib, importc: "mysql_ssl_set".} proc change_user*(MySQL: PMySQL, user: cstring, passwd: cstring, db: cstring): my_bool{. stdcall, dynlib: lib, importc: "mysql_change_user".} -proc real_connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring, - db: cstring, port: cuint, unix_socket: cstring, - clientflag: int): PMySQL{.stdcall, dynlib: lib, +proc real_connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring, + db: cstring, port: cuint, unix_socket: cstring, + clientflag: int): PMySQL{.stdcall, dynlib: lib, importc: "mysql_real_connect".} -proc select_db*(MySQL: PMySQL, db: cstring): cint{.stdcall, dynlib: lib, +proc select_db*(MySQL: PMySQL, db: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_select_db".} proc query*(MySQL: PMySQL, q: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_query".} -proc send_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib, +proc send_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib, importc: "mysql_send_query".} -proc real_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib, +proc real_query*(MySQL: PMySQL, q: cstring, len: int): cint{.stdcall, dynlib: lib, importc: "mysql_real_query".} -proc store_result*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, +proc store_result*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, importc: "mysql_store_result".} proc use_result*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, importc: "mysql_use_result".} - # perform query on master -proc master_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, + # perform query on master +proc master_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, importc: "mysql_master_query".} -proc master_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, +proc master_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, importc: "mysql_master_send_query".} - # perform query on slave -proc slave_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, + # perform query on slave +proc slave_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, importc: "mysql_slave_query".} -proc slave_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, +proc slave_send_query*(MySQL: PMySQL, q: cstring, len: int): my_bool{.stdcall, dynlib: lib, importc: "mysql_slave_send_query".} -proc get_character_set_info*(MySQL: PMySQL, charset: PMY_CHARSET_INFO){.stdcall, +proc get_character_set_info*(MySQL: PMySQL, charset: PMY_CHARSET_INFO){.stdcall, dynlib: lib, importc: "mysql_get_character_set_info".} - # local infile support -const + # local infile support +const LOCAL_INFILE_ERROR_LEN* = 512 # procedure mysql_set_local_infile_handler(mysql:PMYSQL; local_infile_init:function (para1:Ppointer; para2:Pchar; para3:pointer):longint; local_infile_read:function (para1:pointer; para2:Pchar; para3:dword):longint; local_infile_end:procedure (_pa # para6:pointer);cdecl;external mysqllib name 'mysql_set_local_infile_handler'; -proc set_local_infile_default*(MySQL: PMySQL){.cdecl, dynlib: lib, +proc set_local_infile_default*(MySQL: PMySQL){.cdecl, dynlib: lib, importc: "mysql_set_local_infile_default".} # enable/disable parsing of all queries to decide if they go on master or - # slave -proc enable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib, + # slave +proc enable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib, importc: "mysql_enable_rpl_parse".} -proc disable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib, +proc disable_rpl_parse*(MySQL: PMySQL){.stdcall, dynlib: lib, importc: "mysql_disable_rpl_parse".} - # get the value of the parse flag -proc rpl_parse_enabled*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, + # get the value of the parse flag +proc rpl_parse_enabled*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_rpl_parse_enabled".} - # enable/disable reads from master -proc enable_reads_from_master*(MySQL: PMySQL){.stdcall, dynlib: lib, + # enable/disable reads from master +proc enable_reads_from_master*(MySQL: PMySQL){.stdcall, dynlib: lib, importc: "mysql_enable_reads_from_master".} proc disable_reads_from_master*(MySQL: PMySQL){.stdcall, dynlib: lib, importc: "mysql_disable_reads_from_master".} - # get the value of the master read flag -proc reads_from_master_enabled*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, + # get the value of the master read flag +proc reads_from_master_enabled*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_reads_from_master_enabled".} -proc rpl_query_type*(q: cstring, length: cint): Rpl_type{.stdcall, dynlib: lib, +proc rpl_query_type*(q: cstring, length: cint): Rpl_type{.stdcall, dynlib: lib, importc: "mysql_rpl_query_type".} - # discover the master and its slaves + # discover the master and its slaves proc rpl_probe*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_rpl_probe".} - # set the master, close/free the old one, if it is not a pivot + # set the master, close/free the old one, if it is not a pivot proc set_master*(MySQL: PMySQL, host: cstring, port: cuint, user: cstring, passwd: cstring): cint{. stdcall, dynlib: lib, importc: "mysql_set_master".} proc add_slave*(MySQL: PMySQL, host: cstring, port: cuint, user: cstring, passwd: cstring): cint{. stdcall, dynlib: lib, importc: "mysql_add_slave".} -proc shutdown*(MySQL: PMySQL, shutdown_level: Enum_shutdown_level): cint{.stdcall, +proc shutdown*(MySQL: PMySQL, shutdown_level: Enum_shutdown_level): cint{.stdcall, dynlib: lib, importc: "mysql_shutdown".} -proc dump_debug_info*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, +proc dump_debug_info*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_dump_debug_info".} -proc refresh*(sql: PMySQL, refresh_options: cuint): cint{.stdcall, dynlib: lib, +proc refresh*(sql: PMySQL, refresh_options: cuint): cint{.stdcall, dynlib: lib, importc: "mysql_refresh".} proc kill*(MySQL: PMySQL, pid: int): cint{.stdcall, dynlib: lib, importc: "mysql_kill".} -proc set_server_option*(MySQL: PMySQL, option: Enum_mysql_set_option): cint{.stdcall, +proc set_server_option*(MySQL: PMySQL, option: Enum_mysql_set_option): cint{.stdcall, dynlib: lib, importc: "mysql_set_server_option".} proc ping*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_ping".} proc stat*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_stat".} -proc get_server_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, +proc get_server_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_get_server_info".} -proc get_client_info*(): cstring{.stdcall, dynlib: lib, +proc get_client_info*(): cstring{.stdcall, dynlib: lib, importc: "mysql_get_client_info".} -proc get_client_version*(): int{.stdcall, dynlib: lib, +proc get_client_version*(): int{.stdcall, dynlib: lib, importc: "mysql_get_client_version".} -proc get_host_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, +proc get_host_info*(MySQL: PMySQL): cstring{.stdcall, dynlib: lib, importc: "mysql_get_host_info".} -proc get_server_version*(MySQL: PMySQL): int{.stdcall, dynlib: lib, +proc get_server_version*(MySQL: PMySQL): int{.stdcall, dynlib: lib, importc: "mysql_get_server_version".} -proc get_proto_info*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, +proc get_proto_info*(MySQL: PMySQL): cuint{.stdcall, dynlib: lib, importc: "mysql_get_proto_info".} -proc list_dbs*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib, +proc list_dbs*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib, importc: "mysql_list_dbs".} -proc list_tables*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib, +proc list_tables*(MySQL: PMySQL, wild: cstring): PRES{.stdcall, dynlib: lib, importc: "mysql_list_tables".} -proc list_processes*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, +proc list_processes*(MySQL: PMySQL): PRES{.stdcall, dynlib: lib, importc: "mysql_list_processes".} -proc options*(MySQL: PMySQL, option: Option, arg: cstring): cint{.stdcall, dynlib: lib, +proc options*(MySQL: PMySQL, option: Option, arg: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_options".} -proc free_result*(result: PRES){.stdcall, dynlib: lib, +proc free_result*(result: PRES){.stdcall, dynlib: lib, importc: "mysql_free_result".} -proc data_seek*(result: PRES, offset: my_ulonglong){.stdcall, dynlib: lib, +proc data_seek*(result: PRES, offset: my_ulonglong){.stdcall, dynlib: lib, importc: "mysql_data_seek".} -proc row_seek*(result: PRES, offset: ROW_OFFSET): ROW_OFFSET{.stdcall, +proc row_seek*(result: PRES, offset: ROW_OFFSET): ROW_OFFSET{.stdcall, dynlib: lib, importc: "mysql_row_seek".} -proc field_seek*(result: PRES, offset: FIELD_OFFSET): FIELD_OFFSET{.stdcall, +proc field_seek*(result: PRES, offset: FIELD_OFFSET): FIELD_OFFSET{.stdcall, dynlib: lib, importc: "mysql_field_seek".} -proc fetch_row*(result: PRES): ROW{.stdcall, dynlib: lib, +proc fetch_row*(result: PRES): ROW{.stdcall, dynlib: lib, importc: "mysql_fetch_row".} -proc fetch_lengths*(result: PRES): ptr int{.stdcall, dynlib: lib, +proc fetch_lengths*(result: PRES): ptr int{.stdcall, dynlib: lib, importc: "mysql_fetch_lengths".} -proc fetch_field*(result: PRES): PFIELD{.stdcall, dynlib: lib, +proc fetch_field*(result: PRES): PFIELD{.stdcall, dynlib: lib, importc: "mysql_fetch_field".} -proc list_fields*(MySQL: PMySQL, table: cstring, wild: cstring): PRES{.stdcall, +proc list_fields*(MySQL: PMySQL, table: cstring, wild: cstring): PRES{.stdcall, dynlib: lib, importc: "mysql_list_fields".} proc escape_string*(fto: cstring, `from`: cstring, from_length: int): int{. stdcall, dynlib: lib, importc: "mysql_escape_string".} -proc hex_string*(fto: cstring, `from`: cstring, from_length: int): int{.stdcall, +proc hex_string*(fto: cstring, `from`: cstring, from_length: int): int{.stdcall, dynlib: lib, importc: "mysql_hex_string".} proc real_escape_string*(MySQL: PMySQL, fto: cstring, `from`: cstring, len: int): int{. stdcall, dynlib: lib, importc: "mysql_real_escape_string".} proc debug*(debug: cstring){.stdcall, dynlib: lib, importc: "mysql_debug".} # function mysql_odbc_escape_string(mysql:PMYSQL; fto:Pchar; to_length:dword; from:Pchar; from_length:dword; # param:pointer; extend_buffer:function (para1:pointer; to:Pchar; length:Pdword):Pchar):Pchar;stdcall;external mysqllib name 'mysql_odbc_escape_string'; -proc myodbc_remove_escape*(MySQL: PMySQL, name: cstring){.stdcall, dynlib: lib, +proc myodbc_remove_escape*(MySQL: PMySQL, name: cstring){.stdcall, dynlib: lib, importc: "myodbc_remove_escape".} proc thread_safe*(): cuint{.stdcall, dynlib: lib, importc: "mysql_thread_safe".} proc embedded*(): my_bool{.stdcall, dynlib: lib, importc: "mysql_embedded".} -proc manager_init*(con: PMANAGER): PMANAGER{.stdcall, dynlib: lib, +proc manager_init*(con: PMANAGER): PMANAGER{.stdcall, dynlib: lib, importc: "mysql_manager_init".} -proc manager_connect*(con: PMANAGER, host: cstring, user: cstring, - passwd: cstring, port: cuint): PMANAGER{.stdcall, +proc manager_connect*(con: PMANAGER, host: cstring, user: cstring, + passwd: cstring, port: cuint): PMANAGER{.stdcall, dynlib: lib, importc: "mysql_manager_connect".} -proc manager_close*(con: PMANAGER){.stdcall, dynlib: lib, +proc manager_close*(con: PMANAGER){.stdcall, dynlib: lib, importc: "mysql_manager_close".} proc manager_command*(con: PMANAGER, cmd: cstring, cmd_len: cint): cint{. stdcall, dynlib: lib, importc: "mysql_manager_command".} proc manager_fetch_line*(con: PMANAGER, res_buf: cstring, res_buf_size: cint): cint{. stdcall, dynlib: lib, importc: "mysql_manager_fetch_line".} -proc read_query_result*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, +proc read_query_result*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_read_query_result".} proc stmt_init*(MySQL: PMySQL): PSTMT{.stdcall, dynlib: lib, importc: "mysql_stmt_init".} -proc stmt_prepare*(stmt: PSTMT, query: cstring, len: int): cint{.stdcall, +proc stmt_prepare*(stmt: PSTMT, query: cstring, len: int): cint{.stdcall, dynlib: lib, importc: "mysql_stmt_prepare".} -proc stmt_execute*(stmt: PSTMT): cint{.stdcall, dynlib: lib, +proc stmt_execute*(stmt: PSTMT): cint{.stdcall, dynlib: lib, importc: "mysql_stmt_execute".} -proc stmt_fetch*(stmt: PSTMT): cint{.stdcall, dynlib: lib, +proc stmt_fetch*(stmt: PSTMT): cint{.stdcall, dynlib: lib, importc: "mysql_stmt_fetch".} proc stmt_fetch_column*(stmt: PSTMT, `bind`: PBIND, column: cuint, offset: int): cint{. stdcall, dynlib: lib, importc: "mysql_stmt_fetch_column".} -proc stmt_store_result*(stmt: PSTMT): cint{.stdcall, dynlib: lib, +proc stmt_store_result*(stmt: PSTMT): cint{.stdcall, dynlib: lib, importc: "mysql_stmt_store_result".} -proc stmt_param_count*(stmt: PSTMT): int{.stdcall, dynlib: lib, +proc stmt_param_count*(stmt: PSTMT): int{.stdcall, dynlib: lib, importc: "mysql_stmt_param_count".} proc stmt_attr_set*(stmt: PSTMT, attr_type: Enum_stmt_attr_type, attr: pointer): my_bool{. stdcall, dynlib: lib, importc: "mysql_stmt_attr_set".} proc stmt_attr_get*(stmt: PSTMT, attr_type: Enum_stmt_attr_type, attr: pointer): my_bool{. stdcall, dynlib: lib, importc: "mysql_stmt_attr_get".} -proc stmt_bind_param*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib, +proc stmt_bind_param*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_bind_param".} -proc stmt_bind_result*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib, +proc stmt_bind_result*(stmt: PSTMT, bnd: PBIND): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_bind_result".} -proc stmt_close*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, +proc stmt_close*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_close".} -proc stmt_reset*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, +proc stmt_reset*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_reset".} -proc stmt_free_result*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, +proc stmt_free_result*(stmt: PSTMT): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_free_result".} -proc stmt_send_long_data*(stmt: PSTMT, param_number: cuint, data: cstring, - len: int): my_bool{.stdcall, dynlib: lib, +proc stmt_send_long_data*(stmt: PSTMT, param_number: cuint, data: cstring, + len: int): my_bool{.stdcall, dynlib: lib, importc: "mysql_stmt_send_long_data".} -proc stmt_result_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib, +proc stmt_result_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib, importc: "mysql_stmt_result_metadata".} -proc stmt_param_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib, +proc stmt_param_metadata*(stmt: PSTMT): PRES{.stdcall, dynlib: lib, importc: "mysql_stmt_param_metadata".} -proc stmt_errno*(stmt: PSTMT): cuint{.stdcall, dynlib: lib, +proc stmt_errno*(stmt: PSTMT): cuint{.stdcall, dynlib: lib, importc: "mysql_stmt_errno".} -proc stmt_error*(stmt: PSTMT): cstring{.stdcall, dynlib: lib, +proc stmt_error*(stmt: PSTMT): cstring{.stdcall, dynlib: lib, importc: "mysql_stmt_error".} -proc stmt_sqlstate*(stmt: PSTMT): cstring{.stdcall, dynlib: lib, +proc stmt_sqlstate*(stmt: PSTMT): cstring{.stdcall, dynlib: lib, importc: "mysql_stmt_sqlstate".} -proc stmt_row_seek*(stmt: PSTMT, offset: ROW_OFFSET): ROW_OFFSET{.stdcall, +proc stmt_row_seek*(stmt: PSTMT, offset: ROW_OFFSET): ROW_OFFSET{.stdcall, dynlib: lib, importc: "mysql_stmt_row_seek".} -proc stmt_row_tell*(stmt: PSTMT): ROW_OFFSET{.stdcall, dynlib: lib, +proc stmt_row_tell*(stmt: PSTMT): ROW_OFFSET{.stdcall, dynlib: lib, importc: "mysql_stmt_row_tell".} -proc stmt_data_seek*(stmt: PSTMT, offset: my_ulonglong){.stdcall, dynlib: lib, +proc stmt_data_seek*(stmt: PSTMT, offset: my_ulonglong){.stdcall, dynlib: lib, importc: "mysql_stmt_data_seek".} -proc stmt_num_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, +proc stmt_num_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_stmt_num_rows".} -proc stmt_affected_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, +proc stmt_affected_rows*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_stmt_affected_rows".} -proc stmt_insert_id*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, +proc stmt_insert_id*(stmt: PSTMT): my_ulonglong{.stdcall, dynlib: lib, importc: "mysql_stmt_insert_id".} -proc stmt_field_count*(stmt: PSTMT): cuint{.stdcall, dynlib: lib, +proc stmt_field_count*(stmt: PSTMT): cuint{.stdcall, dynlib: lib, importc: "mysql_stmt_field_count".} proc commit*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_commit".} proc rollback*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_rollback".} -proc autocommit*(MySQL: PMySQL, auto_mode: my_bool): my_bool{.stdcall, dynlib: lib, +proc autocommit*(MySQL: PMySQL, auto_mode: my_bool): my_bool{.stdcall, dynlib: lib, importc: "mysql_autocommit".} -proc more_results*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, +proc more_results*(MySQL: PMySQL): my_bool{.stdcall, dynlib: lib, importc: "mysql_more_results".} proc next_result*(MySQL: PMySQL): cint{.stdcall, dynlib: lib, importc: "mysql_next_result".} proc close*(sock: PMySQL){.stdcall, dynlib: lib, importc: "mysql_close".} - # status return codes -const + # status return codes +const NO_DATA* = 100 DATA_TRUNCATED* = 101 proc reload*(x: PMySQL): cint -when defined(USE_OLD_FUNCTIONS): - proc connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring): PMySQL{.stdcall, +when defined(USE_OLD_FUNCTIONS): + proc connect*(MySQL: PMySQL, host: cstring, user: cstring, passwd: cstring): PMySQL{.stdcall, dynlib: lib, importc: "mysql_connect".} - proc create_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib, + proc create_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_create_db".} - proc drop_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib, + proc drop_db*(MySQL: PMySQL, DB: cstring): cint{.stdcall, dynlib: lib, importc: "mysql_drop_db".} proc net_safe_read*(MySQL: PMySQL): cuint{.cdecl, dynlib: lib, importc: "net_safe_read".} -proc IS_PRI_KEY(n: int32): bool = +proc IS_PRI_KEY(n: int32): bool = result = (n and PRI_KEY_FLAG) != 0 -proc IS_NOT_NULL(n: int32): bool = +proc IS_NOT_NULL(n: int32): bool = result = (n and NOT_NULL_FLAG) != 0 -proc IS_BLOB(n: int32): bool = +proc IS_BLOB(n: int32): bool = result = (n and BLOB_FLAG) != 0 -proc IS_NUM_FIELD(f: Pst_mysql_field): bool = +proc IS_NUM_FIELD(f: Pst_mysql_field): bool = result = (f.flags and NUM_FLAG) != 0 -proc IS_NUM(t: Enum_field_types): bool = +proc IS_NUM(t: Enum_field_types): bool = result = (t <= FIELD_TYPE_INT24) or (t == FIELD_TYPE_YEAR) or (t == FIELD_TYPE_NEWDECIMAL) -proc INTERNAL_NUM_FIELD(f: Pst_mysql_field): bool = +proc INTERNAL_NUM_FIELD(f: Pst_mysql_field): bool = result = (f.ftype <= FIELD_TYPE_INT24) and ((f.ftype != FIELD_TYPE_TIMESTAMP) or (f.len == 14) or (f.len == 8)) or (f.ftype == FIELD_TYPE_YEAR) diff --git a/lib/wrappers/sqlite3.nim b/lib/wrappers/sqlite3.nim index bd107b0bc..24c271ab7 100644 --- a/lib/wrappers/sqlite3.nim +++ b/lib/wrappers/sqlite3.nim @@ -8,17 +8,17 @@ # {.deadCodeElim: on.} -when defined(windows): - const +when defined(windows): + const Lib = "sqlite3.dll" -elif defined(macosx): - const +elif defined(macosx): + const Lib = "libsqlite3(|.0).dylib" -else: - const +else: + const Lib = "libsqlite3.so(|.0)" - -const + +const SQLITE_INTEGER* = 1 SQLITE_FLOAT* = 2 SQLITE_BLOB* = 4 @@ -26,38 +26,38 @@ const SQLITE_TEXT* = 3 SQLITE_UTF8* = 1 SQLITE_UTF16LE* = 2 - SQLITE_UTF16BE* = 3 # Use native byte order - SQLITE_UTF16* = 4 # sqlite3_create_function only + SQLITE_UTF16BE* = 3 # Use native byte order + SQLITE_UTF16* = 4 # sqlite3_create_function only SQLITE_ANY* = 5 #sqlite_exec return values SQLITE_OK* = 0 - SQLITE_ERROR* = 1 # SQL error or missing database - SQLITE_INTERNAL* = 2 # An internal logic error in SQLite - SQLITE_PERM* = 3 # Access permission denied - SQLITE_ABORT* = 4 # Callback routine requested an abort - SQLITE_BUSY* = 5 # The database file is locked - SQLITE_LOCKED* = 6 # A table in the database is locked - SQLITE_NOMEM* = 7 # A malloc() failed - SQLITE_READONLY* = 8 # Attempt to write a readonly database - SQLITE_INTERRUPT* = 9 # Operation terminated by sqlite3_interrupt() - SQLITE_IOERR* = 10 # Some kind of disk I/O error occurred - SQLITE_CORRUPT* = 11 # The database disk image is malformed - SQLITE_NOTFOUND* = 12 # (Internal Only) Table or record not found - SQLITE_FULL* = 13 # Insertion failed because database is full - SQLITE_CANTOPEN* = 14 # Unable to open the database file - SQLITE_PROTOCOL* = 15 # Database lock protocol error - SQLITE_EMPTY* = 16 # Database is empty - SQLITE_SCHEMA* = 17 # The database schema changed - SQLITE_TOOBIG* = 18 # Too much data for one row of a table - SQLITE_CONSTRAINT* = 19 # Abort due to contraint violation - SQLITE_MISMATCH* = 20 # Data type mismatch - SQLITE_MISUSE* = 21 # Library used incorrectly - SQLITE_NOLFS* = 22 # Uses OS features not supported on host - SQLITE_AUTH* = 23 # Authorization denied - SQLITE_FORMAT* = 24 # Auxiliary database format error - SQLITE_RANGE* = 25 # 2nd parameter to sqlite3_bind out of range - SQLITE_NOTADB* = 26 # File opened that is not a database file - SQLITE_ROW* = 100 # sqlite3_step() has another row ready - SQLITE_DONE* = 101 # sqlite3_step() has finished executing + SQLITE_ERROR* = 1 # SQL error or missing database + SQLITE_INTERNAL* = 2 # An internal logic error in SQLite + SQLITE_PERM* = 3 # Access permission denied + SQLITE_ABORT* = 4 # Callback routine requested an abort + SQLITE_BUSY* = 5 # The database file is locked + SQLITE_LOCKED* = 6 # A table in the database is locked + SQLITE_NOMEM* = 7 # A malloc() failed + SQLITE_READONLY* = 8 # Attempt to write a readonly database + SQLITE_INTERRUPT* = 9 # Operation terminated by sqlite3_interrupt() + SQLITE_IOERR* = 10 # Some kind of disk I/O error occurred + SQLITE_CORRUPT* = 11 # The database disk image is malformed + SQLITE_NOTFOUND* = 12 # (Internal Only) Table or record not found + SQLITE_FULL* = 13 # Insertion failed because database is full + SQLITE_CANTOPEN* = 14 # Unable to open the database file + SQLITE_PROTOCOL* = 15 # Database lock protocol error + SQLITE_EMPTY* = 16 # Database is empty + SQLITE_SCHEMA* = 17 # The database schema changed + SQLITE_TOOBIG* = 18 # Too much data for one row of a table + SQLITE_CONSTRAINT* = 19 # Abort due to contraint violation + SQLITE_MISMATCH* = 20 # Data type mismatch + SQLITE_MISUSE* = 21 # Library used incorrectly + SQLITE_NOLFS* = 22 # Uses OS features not supported on host + SQLITE_AUTH* = 23 # Authorization denied + SQLITE_FORMAT* = 24 # Auxiliary database format error + SQLITE_RANGE* = 25 # 2nd parameter to sqlite3_bind out of range + SQLITE_NOTADB* = 26 # File opened that is not a database file + SQLITE_ROW* = 100 # sqlite3_step() has another row ready + SQLITE_DONE* = 101 # sqlite3_step() has finished executing SQLITE_COPY* = 0 SQLITE_CREATE_INDEX* = 1 SQLITE_CREATE_TABLE* = 2 @@ -87,39 +87,39 @@ const SQLITE_ALTER_TABLE* = 26 SQLITE_REINDEX* = 27 SQLITE_DENY* = 1 - SQLITE_IGNORE* = 2 # Original from sqlite3.h: + SQLITE_IGNORE* = 2 # Original from sqlite3.h: #define SQLITE_STATIC ((void(*)(void *))0) #define SQLITE_TRANSIENT ((void(*)(void *))-1) SQLITE_DETERMINISTIC* = 0x800 -const +const SQLITE_STATIC* = nil SQLITE_TRANSIENT* = cast[pointer](- 1) -type - Sqlite3 {.pure, final.} = object +type + Sqlite3 {.pure, final.} = object PSqlite3* = ptr Sqlite3 PPSqlite3* = ptr PSqlite3 - Context{.pure, final.} = object + Context{.pure, final.} = object Pcontext* = ptr Context - Tstmt{.pure, final.} = object + Tstmt{.pure, final.} = object Pstmt* = ptr Tstmt - Value{.pure, final.} = object + Value{.pure, final.} = object Pvalue* = ptr Value PValueArg* = array[0..127, Pvalue] - - Callback* = proc (para1: pointer, para2: int32, para3, + + Callback* = proc (para1: pointer, para2: int32, para3, para4: cstringArray): int32{.cdecl.} Tbind_destructor_func* = proc (para1: pointer){.cdecl.} - Create_function_step_func* = proc (para1: Pcontext, para2: int32, + Create_function_step_func* = proc (para1: Pcontext, para2: int32, para3: PValueArg){.cdecl.} - Create_function_func_func* = proc (para1: Pcontext, para2: int32, + Create_function_func_func* = proc (para1: Pcontext, para2: int32, para3: PValueArg){.cdecl.} Create_function_final_func* = proc (para1: Pcontext){.cdecl.} Result_func* = proc (para1: pointer){.cdecl.} - Create_collation_func* = proc (para1: pointer, para2: int32, para3: pointer, + Create_collation_func* = proc (para1: pointer, para2: int32, para3: pointer, para4: int32, para5: pointer): int32{.cdecl.} - Collation_needed_func* = proc (para1: pointer, para2: PSqlite3, eTextRep: int32, + Collation_needed_func* = proc (para1: pointer, para2: PSqlite3, eTextRep: int32, para4: cstring){.cdecl.} {.deprecated: [TSqlite3: Sqlite3, TContext: Context, Tvalue: Value, Tcallback: Callback, Tcreate_function_step_func: Create_function_step_func, @@ -129,220 +129,220 @@ type Tcollation_needed_func: Collation_needed_func].} proc close*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_close".} -proc exec*(para1: PSqlite3, sql: cstring, para3: Callback, para4: pointer, - errmsg: var cstring): int32{.cdecl, dynlib: Lib, +proc exec*(para1: PSqlite3, sql: cstring, para3: Callback, para4: pointer, + errmsg: var cstring): int32{.cdecl, dynlib: Lib, importc: "sqlite3_exec".} -proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, dynlib: Lib, +proc last_insert_rowid*(para1: PSqlite3): int64{.cdecl, dynlib: Lib, importc: "sqlite3_last_insert_rowid".} proc changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_changes".} -proc total_changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, +proc total_changes*(para1: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_total_changes".} proc interrupt*(para1: PSqlite3){.cdecl, dynlib: Lib, importc: "sqlite3_interrupt".} -proc complete*(sql: cstring): int32{.cdecl, dynlib: Lib, +proc complete*(sql: cstring): int32{.cdecl, dynlib: Lib, importc: "sqlite3_complete".} -proc complete16*(sql: pointer): int32{.cdecl, dynlib: Lib, +proc complete16*(sql: pointer): int32{.cdecl, dynlib: Lib, importc: "sqlite3_complete16".} -proc busy_handler*(para1: PSqlite3, - para2: proc (para1: pointer, para2: int32): int32{.cdecl.}, - para3: pointer): int32{.cdecl, dynlib: Lib, +proc busy_handler*(para1: PSqlite3, + para2: proc (para1: pointer, para2: int32): int32{.cdecl.}, + para3: pointer): int32{.cdecl, dynlib: Lib, importc: "sqlite3_busy_handler".} -proc busy_timeout*(para1: PSqlite3, ms: int32): int32{.cdecl, dynlib: Lib, +proc busy_timeout*(para1: PSqlite3, ms: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_busy_timeout".} -proc get_table*(para1: PSqlite3, sql: cstring, resultp: var cstringArray, - nrow, ncolumn: var cint, errmsg: ptr cstring): int32{.cdecl, +proc get_table*(para1: PSqlite3, sql: cstring, resultp: var cstringArray, + nrow, ncolumn: var cint, errmsg: ptr cstring): int32{.cdecl, dynlib: Lib, importc: "sqlite3_get_table".} -proc free_table*(result: cstringArray){.cdecl, dynlib: Lib, +proc free_table*(result: cstringArray){.cdecl, dynlib: Lib, importc: "sqlite3_free_table".} # Todo: see how translate sqlite3_mprintf, sqlite3_vmprintf, sqlite3_snprintf # function sqlite3_mprintf(_para1:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_mprintf'; -proc mprintf*(para1: cstring): cstring{.cdecl, varargs, dynlib: Lib, +proc mprintf*(para1: cstring): cstring{.cdecl, varargs, dynlib: Lib, importc: "sqlite3_mprintf".} #function sqlite3_vmprintf(_para1:Pchar; _para2:va_list):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_vmprintf'; proc free*(z: cstring){.cdecl, dynlib: Lib, importc: "sqlite3_free".} #function sqlite3_snprintf(_para1:longint; _para2:Pchar; _para3:Pchar; args:array of const):Pchar;cdecl; external Sqlite3Lib name 'sqlite3_snprintf'; -proc snprintf*(para1: int32, para2: cstring, para3: cstring): cstring{.cdecl, +proc snprintf*(para1: int32, para2: cstring, para3: cstring): cstring{.cdecl, dynlib: Lib, varargs, importc: "sqlite3_snprintf".} -proc set_authorizer*(para1: PSqlite3, xAuth: proc (para1: pointer, para2: int32, +proc set_authorizer*(para1: PSqlite3, xAuth: proc (para1: pointer, para2: int32, para3: cstring, para4: cstring, para5: cstring, para6: cstring): int32{. - cdecl.}, pUserData: pointer): int32{.cdecl, dynlib: Lib, + cdecl.}, pUserData: pointer): int32{.cdecl, dynlib: Lib, importc: "sqlite3_set_authorizer".} -proc trace*(para1: PSqlite3, xTrace: proc (para1: pointer, para2: cstring){.cdecl.}, - para3: pointer): pointer{.cdecl, dynlib: Lib, +proc trace*(para1: PSqlite3, xTrace: proc (para1: pointer, para2: cstring){.cdecl.}, + para3: pointer): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_trace".} -proc progress_handler*(para1: PSqlite3, para2: int32, - para3: proc (para1: pointer): int32{.cdecl.}, - para4: pointer){.cdecl, dynlib: Lib, +proc progress_handler*(para1: PSqlite3, para2: int32, + para3: proc (para1: pointer): int32{.cdecl.}, + para4: pointer){.cdecl, dynlib: Lib, importc: "sqlite3_progress_handler".} -proc commit_hook*(para1: PSqlite3, para2: proc (para1: pointer): int32{.cdecl.}, - para3: pointer): pointer{.cdecl, dynlib: Lib, +proc commit_hook*(para1: PSqlite3, para2: proc (para1: pointer): int32{.cdecl.}, + para3: pointer): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_commit_hook".} -proc open*(filename: cstring, ppDb: var PSqlite3): int32{.cdecl, dynlib: Lib, +proc open*(filename: cstring, ppDb: var PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_open".} -proc open16*(filename: pointer, ppDb: var PSqlite3): int32{.cdecl, dynlib: Lib, +proc open16*(filename: pointer, ppDb: var PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_open16".} proc errcode*(db: PSqlite3): int32{.cdecl, dynlib: Lib, importc: "sqlite3_errcode".} proc errmsg*(para1: PSqlite3): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_errmsg".} -proc errmsg16*(para1: PSqlite3): pointer{.cdecl, dynlib: Lib, +proc errmsg16*(para1: PSqlite3): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_errmsg16".} -proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var Pstmt, - pzTail: ptr cstring): int32{.cdecl, dynlib: Lib, +proc prepare*(db: PSqlite3, zSql: cstring, nBytes: int32, ppStmt: var Pstmt, + pzTail: ptr cstring): int32{.cdecl, dynlib: Lib, importc: "sqlite3_prepare".} - + proc prepare_v2*(db: PSqlite3, zSql: cstring, nByte: cint, ppStmt: var Pstmt, pzTail: ptr cstring): cint {. importc: "sqlite3_prepare_v2", cdecl, dynlib: Lib.} - -proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var Pstmt, - pzTail: var pointer): int32{.cdecl, dynlib: Lib, + +proc prepare16*(db: PSqlite3, zSql: pointer, nBytes: int32, ppStmt: var Pstmt, + pzTail: var pointer): int32{.cdecl, dynlib: Lib, importc: "sqlite3_prepare16".} -proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32, - para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, +proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32, + para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_blob".} -proc bind_double*(para1: Pstmt, para2: int32, para3: float64): int32{.cdecl, +proc bind_double*(para1: Pstmt, para2: int32, para3: float64): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_double".} -proc bind_int*(para1: Pstmt, para2: int32, para3: int32): int32{.cdecl, +proc bind_int*(para1: Pstmt, para2: int32, para3: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_int".} -proc bind_int64*(para1: Pstmt, para2: int32, para3: int64): int32{.cdecl, +proc bind_int64*(para1: Pstmt, para2: int32, para3: int64): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_int64".} -proc bind_null*(para1: Pstmt, para2: int32): int32{.cdecl, dynlib: Lib, +proc bind_null*(para1: Pstmt, para2: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_null".} -proc bind_text*(para1: Pstmt, para2: int32, para3: cstring, n: int32, - para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, +proc bind_text*(para1: Pstmt, para2: int32, para3: cstring, n: int32, + para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_text".} -proc bind_text16*(para1: Pstmt, para2: int32, para3: pointer, para4: int32, - para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, +proc bind_text16*(para1: Pstmt, para2: int32, para3: pointer, para4: int32, + para5: Tbind_destructor_func): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_text16".} #function sqlite3_bind_value(_para1:Psqlite3_stmt; _para2:longint; _para3:Psqlite3_value):longint;cdecl; external Sqlite3Lib name 'sqlite3_bind_value'; #These overloaded functions were introduced to allow the use of SQLITE_STATIC and SQLITE_TRANSIENT #It's the c world man ;-) -proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32, - para5: int32): int32{.cdecl, dynlib: Lib, +proc bind_blob*(para1: Pstmt, para2: int32, para3: pointer, n: int32, + para5: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_blob".} -proc bind_text*(para1: Pstmt, para2: int32, para3: cstring, n: int32, - para5: int32): int32{.cdecl, dynlib: Lib, +proc bind_text*(para1: Pstmt, para2: int32, para3: cstring, n: int32, + para5: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_text".} -proc bind_text16*(para1: Pstmt, para2: int32, para3: pointer, para4: int32, - para5: int32): int32{.cdecl, dynlib: Lib, +proc bind_text16*(para1: Pstmt, para2: int32, para3: pointer, para4: int32, + para5: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_text16".} -proc bind_parameter_count*(para1: Pstmt): int32{.cdecl, dynlib: Lib, +proc bind_parameter_count*(para1: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_parameter_count".} -proc bind_parameter_name*(para1: Pstmt, para2: int32): cstring{.cdecl, +proc bind_parameter_name*(para1: Pstmt, para2: int32): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_bind_parameter_name".} -proc bind_parameter_index*(para1: Pstmt, zName: cstring): int32{.cdecl, +proc bind_parameter_index*(para1: Pstmt, zName: cstring): int32{.cdecl, dynlib: Lib, importc: "sqlite3_bind_parameter_index".} #function sqlite3_clear_bindings(_para1:Psqlite3_stmt):longint;cdecl; external Sqlite3Lib name 'sqlite3_clear_bindings'; -proc column_count*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, +proc column_count*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_column_count".} -proc column_name*(para1: Pstmt, para2: int32): cstring{.cdecl, dynlib: Lib, +proc column_name*(para1: Pstmt, para2: int32): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_column_name".} -proc column_name16*(para1: Pstmt, para2: int32): pointer{.cdecl, dynlib: Lib, +proc column_name16*(para1: Pstmt, para2: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_column_name16".} -proc column_decltype*(para1: Pstmt, i: int32): cstring{.cdecl, dynlib: Lib, +proc column_decltype*(para1: Pstmt, i: int32): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_column_decltype".} -proc column_decltype16*(para1: Pstmt, para2: int32): pointer{.cdecl, +proc column_decltype16*(para1: Pstmt, para2: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_column_decltype16".} proc step*(para1: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_step".} -proc data_count*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, +proc data_count*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_data_count".} -proc column_blob*(para1: Pstmt, iCol: int32): pointer{.cdecl, dynlib: Lib, +proc column_blob*(para1: Pstmt, iCol: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_column_blob".} -proc column_bytes*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, +proc column_bytes*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_column_bytes".} -proc column_bytes16*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, +proc column_bytes16*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_column_bytes16".} -proc column_double*(para1: Pstmt, iCol: int32): float64{.cdecl, dynlib: Lib, +proc column_double*(para1: Pstmt, iCol: int32): float64{.cdecl, dynlib: Lib, importc: "sqlite3_column_double".} -proc column_int*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, +proc column_int*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_column_int".} -proc column_int64*(para1: Pstmt, iCol: int32): int64{.cdecl, dynlib: Lib, +proc column_int64*(para1: Pstmt, iCol: int32): int64{.cdecl, dynlib: Lib, importc: "sqlite3_column_int64".} -proc column_text*(para1: Pstmt, iCol: int32): cstring{.cdecl, dynlib: Lib, +proc column_text*(para1: Pstmt, iCol: int32): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_column_text".} -proc column_text16*(para1: Pstmt, iCol: int32): pointer{.cdecl, dynlib: Lib, +proc column_text16*(para1: Pstmt, iCol: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_column_text16".} -proc column_type*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, +proc column_type*(para1: Pstmt, iCol: int32): int32{.cdecl, dynlib: Lib, importc: "sqlite3_column_type".} -proc finalize*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, +proc finalize*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_finalize".} proc reset*(pStmt: Pstmt): int32{.cdecl, dynlib: Lib, importc: "sqlite3_reset".} -proc create_function*(para1: PSqlite3, zFunctionName: cstring, nArg: int32, - eTextRep: int32, para5: pointer, - xFunc: Create_function_func_func, - xStep: Create_function_step_func, - xFinal: Create_function_final_func): int32{.cdecl, +proc create_function*(para1: PSqlite3, zFunctionName: cstring, nArg: int32, + eTextRep: int32, para5: pointer, + xFunc: Create_function_func_func, + xStep: Create_function_step_func, + xFinal: Create_function_final_func): int32{.cdecl, dynlib: Lib, importc: "sqlite3_create_function".} -proc create_function16*(para1: PSqlite3, zFunctionName: pointer, nArg: int32, - eTextRep: int32, para5: pointer, - xFunc: Create_function_func_func, - xStep: Create_function_step_func, - xFinal: Create_function_final_func): int32{.cdecl, +proc create_function16*(para1: PSqlite3, zFunctionName: pointer, nArg: int32, + eTextRep: int32, para5: pointer, + xFunc: Create_function_func_func, + xStep: Create_function_step_func, + xFinal: Create_function_final_func): int32{.cdecl, dynlib: Lib, importc: "sqlite3_create_function16".} -proc aggregate_count*(para1: Pcontext): int32{.cdecl, dynlib: Lib, +proc aggregate_count*(para1: Pcontext): int32{.cdecl, dynlib: Lib, importc: "sqlite3_aggregate_count".} -proc value_blob*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, +proc value_blob*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_value_blob".} -proc value_bytes*(para1: Pvalue): int32{.cdecl, dynlib: Lib, +proc value_bytes*(para1: Pvalue): int32{.cdecl, dynlib: Lib, importc: "sqlite3_value_bytes".} -proc value_bytes16*(para1: Pvalue): int32{.cdecl, dynlib: Lib, +proc value_bytes16*(para1: Pvalue): int32{.cdecl, dynlib: Lib, importc: "sqlite3_value_bytes16".} -proc value_double*(para1: Pvalue): float64{.cdecl, dynlib: Lib, +proc value_double*(para1: Pvalue): float64{.cdecl, dynlib: Lib, importc: "sqlite3_value_double".} -proc value_int*(para1: Pvalue): int32{.cdecl, dynlib: Lib, +proc value_int*(para1: Pvalue): int32{.cdecl, dynlib: Lib, importc: "sqlite3_value_int".} -proc value_int64*(para1: Pvalue): int64{.cdecl, dynlib: Lib, +proc value_int64*(para1: Pvalue): int64{.cdecl, dynlib: Lib, importc: "sqlite3_value_int64".} -proc value_text*(para1: Pvalue): cstring{.cdecl, dynlib: Lib, +proc value_text*(para1: Pvalue): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_value_text".} -proc value_text16*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, +proc value_text16*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_value_text16".} -proc value_text16le*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, +proc value_text16le*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_value_text16le".} -proc value_text16be*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, +proc value_text16be*(para1: Pvalue): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_value_text16be".} -proc value_type*(para1: Pvalue): int32{.cdecl, dynlib: Lib, +proc value_type*(para1: Pvalue): int32{.cdecl, dynlib: Lib, importc: "sqlite3_value_type".} -proc aggregate_context*(para1: Pcontext, nBytes: int32): pointer{.cdecl, +proc aggregate_context*(para1: Pcontext, nBytes: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_aggregate_context".} -proc user_data*(para1: Pcontext): pointer{.cdecl, dynlib: Lib, +proc user_data*(para1: Pcontext): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_user_data".} -proc get_auxdata*(para1: Pcontext, para2: int32): pointer{.cdecl, dynlib: Lib, +proc get_auxdata*(para1: Pcontext, para2: int32): pointer{.cdecl, dynlib: Lib, importc: "sqlite3_get_auxdata".} -proc set_auxdata*(para1: Pcontext, para2: int32, para3: pointer, - para4: proc (para1: pointer){.cdecl.}){.cdecl, dynlib: Lib, +proc set_auxdata*(para1: Pcontext, para2: int32, para3: pointer, + para4: proc (para1: pointer){.cdecl.}){.cdecl, dynlib: Lib, importc: "sqlite3_set_auxdata".} -proc result_blob*(para1: Pcontext, para2: pointer, para3: int32, - para4: Result_func){.cdecl, dynlib: Lib, +proc result_blob*(para1: Pcontext, para2: pointer, para3: int32, + para4: Result_func){.cdecl, dynlib: Lib, importc: "sqlite3_result_blob".} -proc result_double*(para1: Pcontext, para2: float64){.cdecl, dynlib: Lib, +proc result_double*(para1: Pcontext, para2: float64){.cdecl, dynlib: Lib, importc: "sqlite3_result_double".} -proc result_error*(para1: Pcontext, para2: cstring, para3: int32){.cdecl, +proc result_error*(para1: Pcontext, para2: cstring, para3: int32){.cdecl, dynlib: Lib, importc: "sqlite3_result_error".} -proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl, +proc result_error16*(para1: Pcontext, para2: pointer, para3: int32){.cdecl, dynlib: Lib, importc: "sqlite3_result_error16".} -proc result_int*(para1: Pcontext, para2: int32){.cdecl, dynlib: Lib, +proc result_int*(para1: Pcontext, para2: int32){.cdecl, dynlib: Lib, importc: "sqlite3_result_int".} -proc result_int64*(para1: Pcontext, para2: int64){.cdecl, dynlib: Lib, +proc result_int64*(para1: Pcontext, para2: int64){.cdecl, dynlib: Lib, importc: "sqlite3_result_int64".} -proc result_null*(para1: Pcontext){.cdecl, dynlib: Lib, +proc result_null*(para1: Pcontext){.cdecl, dynlib: Lib, importc: "sqlite3_result_null".} -proc result_text*(para1: Pcontext, para2: cstring, para3: int32, - para4: Result_func){.cdecl, dynlib: Lib, +proc result_text*(para1: Pcontext, para2: cstring, para3: int32, + para4: Result_func){.cdecl, dynlib: Lib, importc: "sqlite3_result_text".} -proc result_text16*(para1: Pcontext, para2: pointer, para3: int32, - para4: Result_func){.cdecl, dynlib: Lib, +proc result_text16*(para1: Pcontext, para2: pointer, para3: int32, + para4: Result_func){.cdecl, dynlib: Lib, importc: "sqlite3_result_text16".} -proc result_text16le*(para1: Pcontext, para2: pointer, para3: int32, - para4: Result_func){.cdecl, dynlib: Lib, +proc result_text16le*(para1: Pcontext, para2: pointer, para3: int32, + para4: Result_func){.cdecl, dynlib: Lib, importc: "sqlite3_result_text16le".} -proc result_text16be*(para1: Pcontext, para2: pointer, para3: int32, - para4: Result_func){.cdecl, dynlib: Lib, +proc result_text16be*(para1: Pcontext, para2: pointer, para3: int32, + para4: Result_func){.cdecl, dynlib: Lib, importc: "sqlite3_result_text16be".} -proc result_value*(para1: Pcontext, para2: Pvalue){.cdecl, dynlib: Lib, +proc result_value*(para1: Pcontext, para2: Pvalue){.cdecl, dynlib: Lib, importc: "sqlite3_result_value".} -proc create_collation*(para1: PSqlite3, zName: cstring, eTextRep: int32, +proc create_collation*(para1: PSqlite3, zName: cstring, eTextRep: int32, para4: pointer, xCompare: Create_collation_func): int32{. cdecl, dynlib: Lib, importc: "sqlite3_create_collation".} -proc create_collation16*(para1: PSqlite3, zName: cstring, eTextRep: int32, +proc create_collation16*(para1: PSqlite3, zName: cstring, eTextRep: int32, para4: pointer, xCompare: Create_collation_func): int32{. cdecl, dynlib: Lib, importc: "sqlite3_create_collation16".} proc collation_needed*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{. @@ -350,10 +350,10 @@ proc collation_needed*(para1: PSqlite3, para2: pointer, para3: Collation_needed_ proc collation_needed16*(para1: PSqlite3, para2: pointer, para3: Collation_needed_func): int32{. cdecl, dynlib: Lib, importc: "sqlite3_collation_needed16".} proc libversion*(): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_libversion".} - #Alias for allowing better code portability (win32 is not working with external variables) + #Alias for allowing better code portability (win32 is not working with external variables) proc version*(): cstring{.cdecl, dynlib: Lib, importc: "sqlite3_libversion".} # Not published functions -proc libversion_number*(): int32{.cdecl, dynlib: Lib, +proc libversion_number*(): int32{.cdecl, dynlib: Lib, importc: "sqlite3_libversion_number".} #function sqlite3_key(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_key'; #function sqlite3_rekey(db:Psqlite3; pKey:pointer; nKey:longint):longint;cdecl; external Sqlite3Lib name 'sqlite3_rekey'; diff --git a/lib/wrappers/tinyc.nim b/lib/wrappers/tinyc.nim index 05c65b12f..47b505abc 100644 --- a/lib/wrappers/tinyc.nim +++ b/lib/wrappers/tinyc.nim @@ -10,7 +10,7 @@ type CcState {.pure, final.} = object PccState* = ptr CcState - + ErrorFunc* = proc (opaque: pointer, msg: cstring) {.cdecl.} {.deprecated: [TccState: CcState, TErrorFunc: ErrorFunc].} @@ -31,33 +31,33 @@ proc setWarning*(s: PccState, warningName: cstring, value: int) {.cdecl, importc: "tcc_set_warning".} ## set/reset a warning -# preprocessor +# preprocessor -proc addIncludePath*(s: PccState, pathname: cstring) {.cdecl, +proc addIncludePath*(s: PccState, pathname: cstring) {.cdecl, importc: "tcc_add_include_path".} ## add include path -proc addSysincludePath*(s: PccState, pathname: cstring) {.cdecl, +proc addSysincludePath*(s: PccState, pathname: cstring) {.cdecl, importc: "tcc_add_sysinclude_path".} ## add in system include path -proc defineSymbol*(s: PccState, sym, value: cstring) {.cdecl, +proc defineSymbol*(s: PccState, sym, value: cstring) {.cdecl, importc: "tcc_define_symbol".} ## define preprocessor symbol 'sym'. Can put optional value -proc undefineSymbol*(s: PccState, sym: cstring) {.cdecl, +proc undefineSymbol*(s: PccState, sym: cstring) {.cdecl, importc: "tcc_undefine_symbol".} ## undefine preprocess symbol 'sym' -# compiling +# compiling -proc addFile*(s: PccState, filename: cstring): cint {.cdecl, +proc addFile*(s: PccState, filename: cstring): cint {.cdecl, importc: "tcc_add_file".} ## add a file (either a C file, dll, an object, a library or an ld ## script). Return -1 if error. -proc compileString*(s: PccState, buf: cstring): cint {.cdecl, +proc compileString*(s: PccState, buf: cstring): cint {.cdecl, importc: "tcc_compile_string".} ## compile a string containing a C source. Return non zero if error. @@ -71,12 +71,12 @@ const OutputDll*: cint = 2 ## dynamic library OutputObj*: cint = 3 ## object file OutputPreprocess*: cint = 4 ## preprocessed file (used internally) - + OutputFormatElf*: cint = 0 ## default output format: ELF OutputFormatBinary*: cint = 1 ## binary image output OutputFormatCoff*: cint = 2 ## COFF -proc setOutputType*(s: PCCState, outputType: cint): cint {.cdecl, +proc setOutputType*(s: PCCState, outputType: cint): cint {.cdecl, importc: "tcc_set_output_type".} ## set output type. MUST BE CALLED before any compilation @@ -115,5 +115,5 @@ proc getSymbol*(s: PccState, name: cstring): pointer {.cdecl, proc setLibPath*(s: PccState, path: cstring) {.cdecl, importc: "tcc_set_lib_path".} ## set CONFIG_TCCDIR at runtime - + |