lib/pure/e-o - Dropped 'T' from types

This commit is contained in:
pdw 2015-05-24 22:33:34 -05:00 • committed by Araq
commit 6914244f30
13 changed files with 202 additions and 185 deletions

View file

@ -211,12 +211,13 @@ when defined(windows):
when false: when false:
# not needed yet: # not needed yet:
type type
TCpInfo = object CpInfo = object
maxCharSize: int32 maxCharSize: int32
defaultChar: array[0..1, char] defaultChar: array[0..1, char]
leadByte: array[0..12-1, char] leadByte: array[0..12-1, char]
{.deprecated: [TCpInfo: CpInfo].}
proc getCPInfo(codePage: CodePage, lpCPInfo: var TCpInfo): int32 {. proc getCPInfo(codePage: CodePage, lpCPInfo: var CpInfo): int32 {.
stdcall, importc: "GetCPInfo", dynlib: "kernel32".} stdcall, importc: "GetCPInfo", dynlib: "kernel32".}
proc nameToCodePage(name: string): CodePage = proc nameToCodePage(name: string): CodePage =

View file

@ -18,20 +18,22 @@ import
os, hashes, strutils os, hashes, strutils
type type
TGenTableMode* = enum ## describes the table's key matching mode GenTableMode* = enum ## describes the table's key matching mode
modeCaseSensitive, ## case sensitive matching of keys modeCaseSensitive, ## case sensitive matching of keys
modeCaseInsensitive, ## case insensitive matching of keys modeCaseInsensitive, ## case insensitive matching of keys
modeStyleInsensitive ## style sensitive matching of keys modeStyleInsensitive ## style sensitive matching of keys
TGenKeyValuePair[T] = tuple[key: string, val: T] GenKeyValuePair[T] = tuple[key: string, val: T]
TGenKeyValuePairSeq[T] = seq[TGenKeyValuePair[T]] GenKeyValuePairSeq[T] = seq[GenKeyValuePair[T]]
TGenTable*[T] = object of RootObj GenTable*[T] = object of RootObj
counter: int counter: int
data: TGenKeyValuePairSeq[T] data: GenKeyValuePairSeq[T]
mode: TGenTableMode mode: GenTableMode
PGenTable*[T] = ref TGenTable[T] ## use this type to declare hash tables PGenTable*[T] = ref GenTable[T] ## use this type to declare hash tables
{.deprecated: [TGenTableMode: GenTableMode, TGenKeyValuePair: GenKeyValuePair,
TGenKeyValuePairSeq: GenKeyValuePairSeq, TGenTable: GenTable].}
const const
growthFactor = 2 growthFactor = 2
@ -48,7 +50,7 @@ iterator pairs*[T](tbl: PGenTable[T]): tuple[key: string, value: T] =
if not isNil(tbl.data[h].key): if not isNil(tbl.data[h].key):
yield (tbl.data[h].key, tbl.data[h].val) yield (tbl.data[h].key, tbl.data[h].val)
proc myhash[T](tbl: PGenTable[T], key: string): THash = proc myhash[T](tbl: PGenTable[T], key: string): Hash =
case tbl.mode case tbl.mode
of modeCaseSensitive: result = hashes.hash(key) of modeCaseSensitive: result = hashes.hash(key)
of modeCaseInsensitive: result = hashes.hashIgnoreCase(key) of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
@ -64,18 +66,18 @@ proc mustRehash(length, counter: int): bool =
assert(length > counter) assert(length > counter)
result = (length * 2 < counter * 3) or (length - counter < 4) result = (length * 2 < counter * 3) or (length - counter < 4)
proc newGenTable*[T](mode: TGenTableMode): PGenTable[T] = proc newGenTable*[T](mode: GenTableMode): PGenTable[T] =
## creates a new generic hash table that is empty. ## creates a new generic hash table that is empty.
new(result) new(result)
result.mode = mode result.mode = mode
result.counter = 0 result.counter = 0
newSeq(result.data, startSize) newSeq(result.data, startSize)
proc nextTry(h, maxHash: THash): THash {.inline.} = proc nextTry(h, maxHash: Hash): Hash {.inline.} =
result = ((5 * h) + 1) and maxHash result = ((5 * h) + 1) and maxHash
proc rawGet[T](tbl: PGenTable[T], key: string): int = proc rawGet[T](tbl: PGenTable[T], key: string): int =
var h: THash var h: Hash
h = myhash(tbl, key) and high(tbl.data) # start with real hash value h = myhash(tbl, key) and high(tbl.data) # start with real hash value
while not isNil(tbl.data[h].key): while not isNil(tbl.data[h].key):
if myCmp(tbl, tbl.data[h].key, key): if myCmp(tbl, tbl.data[h].key, key):
@ -83,9 +85,9 @@ proc rawGet[T](tbl: PGenTable[T], key: string): int =
h = nextTry(h, high(tbl.data)) h = nextTry(h, high(tbl.data))
result = - 1 result = - 1
proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T], proc rawInsert[T](tbl: PGenTable[T], data: var GenKeyValuePairSeq[T],
key: string, val: T) = key: string, val: T) =
var h: THash var h: Hash
h = myhash(tbl, key) and high(data) h = myhash(tbl, key) and high(data)
while not isNil(data[h].key): while not isNil(data[h].key):
h = nextTry(h, high(data)) h = nextTry(h, high(data))
@ -93,7 +95,7 @@ proc rawInsert[T](tbl: PGenTable[T], data: var TGenKeyValuePairSeq[T],
data[h].val = val data[h].val = val
proc enlarge[T](tbl: PGenTable[T]) = proc enlarge[T](tbl: PGenTable[T]) =
var n: TGenKeyValuePairSeq[T] var n: GenKeyValuePairSeq[T]
newSeq(n, len(tbl.data) * growthFactor) newSeq(n, len(tbl.data) * growthFactor)
for i in countup(0, high(tbl.data)): for i in countup(0, high(tbl.data)):
if not isNil(tbl.data[i].key): if not isNil(tbl.data[i].key):
@ -146,19 +148,20 @@ when isMainModule:
# Verify a table of user-defined types # Verify a table of user-defined types
# #
type type
TMyType = tuple[first, second: string] # a pair of strings MyType = tuple[first, second: string] # a pair of strings
{.deprecated: [TMyType: MyType].}
var y = newGenTable[TMyType](modeCaseInsensitive) # hash table where each var y = newGenTable[MyType](modeCaseInsensitive) # hash table where each
# value is TMyType tuple # value is MyType tuple
#var junk: TMyType = ("OK", "Here") #var junk: MyType = ("OK", "Here")
#echo junk.first, " ", junk.second #echo junk.first, " ", junk.second
y["Hello"] = ("Hello", "World") y["Hello"] = ("Hello", "World")
y["Goodbye"] = ("Goodbye", "Everyone") y["Goodbye"] = ("Goodbye", "Everyone")
#y["Hello"] = TMyType( ("Hello", "World") ) #y["Hello"] = MyType( ("Hello", "World") )
#y["Goodbye"] = TMyType( ("Goodbye", "Everyone") ) #y["Goodbye"] = MyType( ("Goodbye", "Everyone") )
assert( not isNil(y["Hello"].first) ) assert( not isNil(y["Hello"].first) )
assert( y["Hello"].first == "Hello" ) assert( y["Hello"].first == "Hello" )

View file

@ -15,9 +15,9 @@
## code: ## code:
## ##
## .. code-block:: Nim ## .. code-block:: Nim
## proc hash(x: Something): THash = ## proc hash(x: Something): Hash =
## ## Computes a THash from `x`. ## ## Computes a Hash from `x`.
## var h: THash = 0 ## var h: Hash = 0
## # Iterate over parts of `x`. ## # Iterate over parts of `x`.
## for xAtom in x: ## for xAtom in x:
## # Mix the atom with the partial hash. ## # Mix the atom with the partial hash.
@ -30,9 +30,9 @@
## together the hash value of the individual fields: ## together the hash value of the individual fields:
## ##
## .. code-block:: Nim ## .. code-block:: Nim
## proc hash(x: Something): THash = ## proc hash(x: Something): Hash =
## ## Computes a THash from `x`. ## ## Computes a Hash from `x`.
## var h: THash = 0 ## var h: Hash = 0
## h = h !& hash(x.foo) ## h = h !& hash(x.foo)
## h = h !& hash(x.bar) ## h = h !& hash(x.bar)
## result = !$h ## result = !$h
@ -41,27 +41,28 @@ import
strutils, etcpriv strutils, etcpriv
type type
THash* = int ## a hash value; hash tables using these values should Hash* = int ## a hash value; hash tables using these values should
## always have a size of a power of two and can use the ``and`` ## always have a size of a power of two and can use the ``and``
## operator instead of ``mod`` for truncation of the hash value. ## operator instead of ``mod`` for truncation of the hash value.
{.deprecated: [THash: Hash].}
proc `!&`*(h: THash, val: int): THash {.inline.} = proc `!&`*(h: Hash, val: int): Hash {.inline.} =
## mixes a hash value `h` with `val` to produce a new hash value. This is ## mixes a hash value `h` with `val` to produce a new hash value. This is
## only needed if you need to implement a hash proc for a new datatype. ## only needed if you need to implement a hash proc for a new datatype.
result = h +% val result = h +% val
result = result +% result shl 10 result = result +% result shl 10
result = result xor (result shr 6) result = result xor (result shr 6)
proc `!$`*(h: THash): THash {.inline.} = proc `!$`*(h: Hash): Hash {.inline.} =
## finishes the computation of the hash value. This is ## finishes the computation of the hash value. This is
## only needed if you need to implement a hash proc for a new datatype. ## only needed if you need to implement a hash proc for a new datatype.
result = h +% h shl 3 result = h +% h shl 3
result = result xor (result shr 11) result = result xor (result shr 11)
result = result +% result shl 15 result = result +% result shl 15
proc hashData*(data: pointer, size: int): THash = proc hashData*(data: pointer, size: int): Hash =
## hashes an array of bytes of size `size` ## hashes an array of bytes of size `size`
var h: THash = 0 var h: Hash = 0
when defined(js): when defined(js):
var p: cstring var p: cstring
asm """`p` = `Data`;""" asm """`p` = `Data`;"""
@ -78,7 +79,7 @@ proc hashData*(data: pointer, size: int): THash =
when defined(js): when defined(js):
var objectID = 0 var objectID = 0
proc hash*(x: pointer): THash {.inline.} = proc hash*(x: pointer): Hash {.inline.} =
## efficient hashing of pointers ## efficient hashing of pointers
when defined(js): when defined(js):
asm """ asm """
@ -92,38 +93,38 @@ proc hash*(x: pointer): THash {.inline.} =
} }
""" """
else: else:
result = (cast[THash](x)) shr 3 # skip the alignment result = (cast[Hash](x)) shr 3 # skip the alignment
when not defined(booting): when not defined(booting):
proc hash*[T: proc](x: T): THash {.inline.} = proc hash*[T: proc](x: T): Hash {.inline.} =
## efficient hashing of proc vars; closures are supported too. ## efficient hashing of proc vars; closures are supported too.
when T is "closure": when T is "closure":
result = hash(rawProc(x)) !& hash(rawEnv(x)) result = hash(rawProc(x)) !& hash(rawEnv(x))
else: else:
result = hash(pointer(x)) result = hash(pointer(x))
proc hash*(x: int): THash {.inline.} = proc hash*(x: int): Hash {.inline.} =
## efficient hashing of integers ## efficient hashing of integers
result = x result = x
proc hash*(x: int64): THash {.inline.} = proc hash*(x: int64): Hash {.inline.} =
## efficient hashing of integers ## efficient hashing of integers
result = toU32(x) result = toU32(x)
proc hash*(x: char): THash {.inline.} = proc hash*(x: char): Hash {.inline.} =
## efficient hashing of characters ## efficient hashing of characters
result = ord(x) result = ord(x)
proc hash*(x: string): THash = proc hash*(x: string): Hash =
## efficient hashing of strings ## efficient hashing of strings
var h: THash = 0 var h: Hash = 0
for i in 0..x.len-1: for i in 0..x.len-1:
h = h !& ord(x[i]) h = h !& ord(x[i])
result = !$h result = !$h
proc hashIgnoreStyle*(x: string): THash = proc hashIgnoreStyle*(x: string): Hash =
## efficient hashing of strings; style is ignored ## efficient hashing of strings; style is ignored
var h: THash = 0 var h: Hash = 0
var i = 0 var i = 0
let xLen = x.len let xLen = x.len
while i < xLen: while i < xLen:
@ -140,9 +141,9 @@ proc hashIgnoreStyle*(x: string): THash =
result = !$h result = !$h
proc hashIgnoreCase*(x: string): THash = proc hashIgnoreCase*(x: string): Hash =
## efficient hashing of strings; case is ignored ## efficient hashing of strings; case is ignored
var h: THash = 0 var h: Hash = 0
for i in 0..x.len-1: for i in 0..x.len-1:
var c = x[i] var c = x[i]
if c in {'A'..'Z'}: if c in {'A'..'Z'}:
@ -150,28 +151,28 @@ proc hashIgnoreCase*(x: string): THash =
h = h !& ord(c) h = h !& ord(c)
result = !$h result = !$h
proc hash*(x: float): THash {.inline.} = proc hash*(x: float): Hash {.inline.} =
var y = x + 1.0 var y = x + 1.0
result = cast[ptr THash](addr(y))[] result = cast[ptr Hash](addr(y))[]
# Forward declarations before methods that hash containers. This allows # Forward declarations before methods that hash containers. This allows
# containers to contain other containers # containers to contain other containers
proc hash*[A](x: openArray[A]): THash proc hash*[A](x: openArray[A]): Hash
proc hash*[A](x: set[A]): THash proc hash*[A](x: set[A]): Hash
proc hash*[T: tuple](x: T): THash = proc hash*[T: tuple](x: T): Hash =
## efficient hashing of tuples. ## efficient hashing of tuples.
for f in fields(x): for f in fields(x):
result = result !& hash(f) result = result !& hash(f)
result = !$result result = !$result
proc hash*[A](x: openArray[A]): THash = proc hash*[A](x: openArray[A]): Hash =
for it in items(x): result = result !& hash(it) for it in items(x): result = result !& hash(it)
result = !$result result = !$result
proc hash*[A](x: set[A]): THash = proc hash*[A](x: set[A]): Hash =
for it in items(x): result = result !& hash(it) for it in items(x): result = result !& hash(it)
result = !$result result = !$result

View file

@ -52,7 +52,7 @@
import strutils, streams, parsexml, xmltree, unicode, strtabs import strutils, streams, parsexml, xmltree, unicode, strtabs
type type
THtmlTag* = enum ## list of all supported HTML tags; order will always be HtmlTag* = enum ## list of all supported HTML tags; order will always be
## alphabetically ## alphabetically
tagUnknown, ## unknown HTML element tagUnknown, ## unknown HTML element
tagA, ## the HTML ``a`` element tagA, ## the HTML ``a`` element
@ -178,6 +178,7 @@ type
tagVar, ## the HTML ``var`` element tagVar, ## the HTML ``var`` element
tagVideo, ## the HTML ``video`` element tagVideo, ## the HTML ``video`` element
tagWbr ## the HTML ``wbr`` element tagWbr ## the HTML ``wbr`` element
{.deprecated: [THtmlTag: HtmlTag].}
const const
tagToStr* = [ tagToStr* = [
@ -295,7 +296,7 @@ proc allLower(s: string): bool =
if c < 'a' or c > 'z': return false if c < 'a' or c > 'z': return false
return true return true
proc toHtmlTag(s: string): THtmlTag = proc toHtmlTag(s: string): HtmlTag =
case s case s
of "a": tagA of "a": tagA
of "abbr": tagAbbr of "abbr": tagAbbr
@ -422,14 +423,14 @@ proc toHtmlTag(s: string): THtmlTag =
of "wbr": tagWbr of "wbr": tagWbr
else: tagUnknown else: tagUnknown
proc htmlTag*(n: XmlNode): THtmlTag = proc htmlTag*(n: XmlNode): HtmlTag =
## gets `n`'s tag as a ``THtmlTag``. ## gets `n`'s tag as a ``HtmlTag``.
if n.clientData == 0: if n.clientData == 0:
n.clientData = toHtmlTag(n.tag).ord n.clientData = toHtmlTag(n.tag).ord
result = THtmlTag(n.clientData) result = HtmlTag(n.clientData)
proc htmlTag*(s: string): THtmlTag = proc htmlTag*(s: string): HtmlTag =
## converts `s` to a ``THtmlTag``. If `s` is no HTML tag, ``tagUnknown`` is ## converts `s` to a ``HtmlTag``. If `s` is no HTML tag, ``tagUnknown`` is
## returned. ## returned.
let s = if allLower(s): s else: s.toLower let s = if allLower(s): s else: s.toLower
result = toHtmlTag(s) result = toHtmlTag(s)

View file

@ -106,9 +106,10 @@ proc serveFile*(client: Socket, filename: string) =
when false: when false:
# TODO: Fix this, or get rid of it. # TODO: Fix this, or get rid of it.
type type
TRequestMethod = enum reqGet, reqPost RequestMethod = enum reqGet, reqPost
{.deprecated: [TRequestMethod: RequestMethod].}
proc executeCgi(client: Socket, path, query: string, meth: TRequestMethod) = proc executeCgi(client: Socket, path, query: string, meth: RequestMethod) =
var env = newStringTable(modeCaseInsensitive) var env = newStringTable(modeCaseInsensitive)
var contentLength = -1 var contentLength = -1
case meth case meth
@ -208,7 +209,7 @@ when false:
executeCgi(client, path, query, meth) executeCgi(client, path, query, meth)
type type
TServer* = object of RootObj ## contains the current server state Server* = object of RootObj ## contains the current server state
socket: Socket socket: Socket
port: Port port: Port
client*: Socket ## the socket to write the file data to client*: Socket ## the socket to write the file data to
@ -218,11 +219,12 @@ type
body*: string ## only set with POST requests body*: string ## only set with POST requests
ip*: string ## ip address of the requesting client ip*: string ## ip address of the requesting client
PAsyncHTTPServer* = ref TAsyncHTTPServer PAsyncHTTPServer* = ref AsyncHTTPServer
TAsyncHTTPServer = object of TServer AsyncHTTPServer = object of Server
asyncSocket: AsyncSocket asyncSocket: AsyncSocket
{.deprecated: [TAsyncHTTPServer: AsyncHTTPServer, TServer: Server].}
proc open*(s: var TServer, port = Port(80), reuseAddr = false) = proc open*(s: var Server, port = Port(80), reuseAddr = false) =
## creates a new server at port `port`. If ``port == 0`` a free port is ## creates a new server at port `port`. If ``port == 0`` a free port is
## acquired that can be accessed later by the ``port`` proc. ## acquired that can be accessed later by the ``port`` proc.
s.socket = socket(AF_INET) s.socket = socket(AF_INET)
@ -243,11 +245,11 @@ proc open*(s: var TServer, port = Port(80), reuseAddr = false) =
s.query = "" s.query = ""
s.headers = {:}.newStringTable() s.headers = {:}.newStringTable()
proc port*(s: var TServer): Port = proc port*(s: var Server): Port =
## get the port number the server has acquired. ## get the port number the server has acquired.
result = s.port result = s.port
proc next*(s: var TServer) = proc next*(s: var Server) =
## proceed to the first/next request. ## proceed to the first/next request.
var client: Socket var client: Socket
new(client) new(client)
@ -354,7 +356,7 @@ proc next*(s: var TServer) =
s.query = "" s.query = ""
s.path = data.substr(i, last-1) s.path = data.substr(i, last-1)
proc close*(s: TServer) = proc close*(s: Server) =
## closes the server (and the socket the server uses). ## closes the server (and the socket the server uses).
close(s.socket) close(s.socket)
@ -362,7 +364,7 @@ proc run*(handleRequest: proc (client: Socket,
path, query: string): bool {.closure.}, path, query: string): bool {.closure.},
port = Port(80)) = port = Port(80)) =
## encapsulates the server object and main loop ## encapsulates the server object and main loop
var s: TServer var s: Server
open(s, port, reuseAddr = true) open(s, port, reuseAddr = true)
#echo("httpserver running on port ", s.port) #echo("httpserver running on port ", s.port)
while true: while true:
@ -517,7 +519,7 @@ proc close*(h: PAsyncHTTPServer) =
when not defined(testing) and isMainModule: when not defined(testing) and isMainModule:
var counter = 0 var counter = 0
var s: TServer var s: Server
open(s, Port(0)) open(s, Port(0))
echo("httpserver running on port ", s.port) echo("httpserver running on port ", s.port)
while true: while true:

View file

@ -68,7 +68,7 @@ type
jsonArrayStart, ## start of an array: the ``[`` token jsonArrayStart, ## start of an array: the ``[`` token
jsonArrayEnd ## start of an array: the ``]`` token jsonArrayEnd ## start of an array: the ``]`` token
TTokKind = enum # must be synchronized with TJsonEventKind! TokKind = enum # must be synchronized with TJsonEventKind!
tkError, tkError,
tkEof, tkEof,
tkString, tkString,
@ -103,14 +103,14 @@ type
JsonParser* = object of BaseLexer ## the parser object. JsonParser* = object of BaseLexer ## the parser object.
a: string a: string
tok: TTokKind tok: TokKind
kind: JsonEventKind kind: JsonEventKind
err: JsonError err: JsonError
state: seq[ParserState] state: seq[ParserState]
filename: string filename: string
{.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError, {.deprecated: [TJsonEventKind: JsonEventKind, TJsonError: JsonError,
TJsonParser: JsonParser].} TJsonParser: JsonParser, TTokKind: TokKind].}
const const
errorMessages: array [JsonError, string] = [ errorMessages: array [JsonError, string] = [
@ -126,7 +126,7 @@ const
"EOF expected", "EOF expected",
"expression expected" "expression expected"
] ]
tokToStr: array [TTokKind, string] = [ tokToStr: array [TokKind, string] = [
"invalid token", "invalid token",
"EOF", "EOF",
"string literal", "string literal",
@ -203,7 +203,7 @@ proc handleHexChar(c: char, x: var int): bool =
of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10) of 'A'..'F': x = (x shl 4) or (ord(c) - ord('A') + 10)
else: result = false # error else: result = false # error
proc parseString(my: var JsonParser): TTokKind = proc parseString(my: var JsonParser): TokKind =
result = tkString result = tkString
var pos = my.bufpos + 1 var pos = my.bufpos + 1
var buf = my.buf var buf = my.buf
@ -359,7 +359,7 @@ proc parseName(my: var JsonParser) =
inc(pos) inc(pos)
my.bufpos = pos my.bufpos = pos
proc getTok(my: var JsonParser): TTokKind = proc getTok(my: var JsonParser): TokKind =
setLen(my.a, 0) setLen(my.a, 0)
skip(my) # skip whitespace, comments skip(my) # skip whitespace, comments
case my.buf[my.bufpos] case my.buf[my.bufpos]
@ -734,7 +734,7 @@ proc `==`* (a,b: JsonNode): bool =
of JObject: of JObject:
a.fields == b.fields a.fields == b.fields
proc hash* (n:JsonNode): THash = proc hash* (n:JsonNode): Hash =
## Compute the hash for a JSON node ## Compute the hash for a JSON node
case n.kind case n.kind
of JArray: of JArray:
@ -1016,7 +1016,7 @@ iterator mpairs*(node: var JsonNode): var tuple[key: string, val: JsonNode] =
for keyVal in mitems(node.fields): for keyVal in mitems(node.fields):
yield keyVal yield keyVal
proc eat(p: var JsonParser, tok: TTokKind) = proc eat(p: var JsonParser, tok: TokKind) =
if p.tok == tok: discard getTok(p) if p.tok == tok: discard getTok(p)
else: raiseParseErr(p, tokToStr[tok]) else: raiseParseErr(p, tokToStr[tok])
@ -1091,8 +1091,10 @@ when not defined(js):
else: else:
from math import `mod` from math import `mod`
type type
TJSObject = object JSObject = object
proc parseNativeJson(x: cstring): TJSObject {.importc: "JSON.parse".} {.deprecated: [TJSObject: JSObject].}
proc parseNativeJson(x: cstring): JSObject {.importc: "JSON.parse".}
proc getVarType(x): JsonNodeKind = proc getVarType(x): JsonNodeKind =
result = JNull result = JNull
@ -1111,25 +1113,25 @@ else:
of "[object String]": return JString of "[object String]": return JString
else: assert false else: assert false
proc len(x: TJSObject): int = proc len(x: JSObject): int =
assert x.getVarType == JArray assert x.getVarType == JArray
asm """ asm """
return `x`.length; return `x`.length;
""" """
proc `[]`(x: TJSObject, y: string): TJSObject = proc `[]`(x: JSObject, y: string): JSObject =
assert x.getVarType == JObject assert x.getVarType == JObject
asm """ asm """
return `x`[`y`]; return `x`[`y`];
""" """
proc `[]`(x: TJSObject, y: int): TJSObject = proc `[]`(x: JSObject, y: int): JSObject =
assert x.getVarType == JArray assert x.getVarType == JArray
asm """ asm """
return `x`[`y`]; return `x`[`y`];
""" """
proc convertObject(x: TJSObject): JsonNode = proc convertObject(x: JSObject): JsonNode =
case getVarType(x) case getVarType(x)
of JArray: of JArray:
result = newJArray() result = newJArray()
@ -1141,7 +1143,7 @@ else:
if (`x`.hasOwnProperty(property)) { if (`x`.hasOwnProperty(property)) {
""" """
var nimProperty: cstring var nimProperty: cstring
var nimValue: TJSObject var nimValue: JSObject
asm "`nimProperty` = property; `nimValue` = `x`[property];" asm "`nimProperty` = property; `nimValue` = `x`[property];"
result[$nimProperty] = nimValue.convertObject() result[$nimProperty] = nimValue.convertObject()
asm "}}" asm "}}"

View file

@ -39,7 +39,7 @@ type
{.deprecated: [TBaseLexer: BaseLexer].} {.deprecated: [TBaseLexer: BaseLexer].}
proc open*(L: var BaseLexer, input: Stream, bufLen: int = 8192) proc open*(L: var BaseLexer, input: Stream, bufLen: int = 8192)
## inits the TBaseLexer with a stream to read from ## inits the BaseLexer with a stream to read from
proc close*(L: var BaseLexer) proc close*(L: var BaseLexer)
## closes the base lexer. This closes `L`'s associated stream too. ## closes the base lexer. This closes `L`'s associated stream too.

View file

@ -17,13 +17,13 @@
## .. code-block:: nim ## .. code-block:: nim
## ##
## type ## type
## TA = object ## A = object
## TB = object of TA ## B = object of A
## f: int ## f: int
## ##
## var ## var
## a: ref TA ## a: ref A
## b: ref TB ## b: ref B
## ##
## new(b) ## new(b)
## a = b ## a = b
@ -36,7 +36,7 @@ import streams, typeinfo, json, intsets, tables
proc ptrToInt(x: pointer): int {.inline.} = proc ptrToInt(x: pointer): int {.inline.} =
result = cast[int](x) # don't skip alignment result = cast[int](x) # don't skip alignment
proc storeAny(s: Stream, a: TAny, stored: var IntSet) = proc storeAny(s: Stream, a: Any, stored: var IntSet) =
case a.kind case a.kind
of akNone: assert false of akNone: assert false
of akBool: s.write($getBool(a)) of akBool: s.write($getBool(a))
@ -96,7 +96,7 @@ proc storeAny(s: Stream, a: TAny, stored: var IntSet) =
of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a)) of akInt..akInt64, akUInt..akUInt64: s.write($getBiggestInt(a))
of akFloat..akFloat128: s.write($getBiggestFloat(a)) of akFloat..akFloat128: s.write($getBiggestFloat(a))
proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) = proc loadAny(p: var JsonParser, a: Any, t: var Table[BiggestInt, pointer]) =
case a.kind case a.kind
of akNone: assert false of akNone: assert false
of akBool: of akBool:
@ -222,7 +222,7 @@ proc loadAny(p: var JsonParser, a: TAny, t: var Table[BiggestInt, pointer]) =
raiseParseErr(p, "float expected") raiseParseErr(p, "float expected")
of akRange: loadAny(p, a.skipRange, t) of akRange: loadAny(p, a.skipRange, t)
proc loadAny(s: Stream, a: TAny, t: var Table[BiggestInt, pointer]) = proc loadAny(s: Stream, a: Any, t: var Table[BiggestInt, pointer]) =
var p: JsonParser var p: JsonParser
open(p, s, "unknown file") open(p, s, "unknown file")
next(p) next(p)
@ -278,10 +278,11 @@ when not defined(testing) and isMainModule:
else: else:
nil nil
PNode = ref TNode PNode = ref Node
TNode = object Node = object
next, prev: PNode next, prev: PNode
data: string data: string
{.deprecated: [TNode: Node].}
proc buildList(): PNode = proc buildList(): PNode =
new(result) new(result)
@ -317,14 +318,15 @@ when not defined(testing) and isMainModule:
testit(test7) testit(test7)
type type
TA {.inheritable.} = object A {.inheritable.} = object
TB = object of TA B = object of A
f: int f: int
var var
a: ref TA a: ref A
b: ref TB b: ref B
new(b) new(b)
a = b a = b
echo($$a[]) # produces "{}", not "{f: 0}" echo($$a[]) # produces "{}", not "{f: 0}"

View file

@ -196,7 +196,7 @@ proc open*(filename: string, mode: FileMode = fmRead,
if mappedSize != -1: if mappedSize != -1:
result.size = mappedSize result.size = mappedSize
else: else:
var stat: TStat var stat: Stat
if fstat(result.handle, stat) != -1: if fstat(result.handle, stat) != -1:
# XXX: Hmm, this could be unsafe # XXX: Hmm, this could be unsafe
# Why is mmap taking int anyway? # Why is mmap taking int anyway?

View file

@ -86,7 +86,7 @@ type
IPv6, ## IPv6 address IPv6, ## IPv6 address
IPv4 ## IPv4 address IPv4 ## IPv4 address
TIpAddress* = object ## stores an arbitrary IP address IpAddress* = object ## stores an arbitrary IP address
case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6) case family*: IpAddressFamily ## the type of the IP address (IPv4 or IPv6)
of IpAddressFamily.IPv6: of IpAddressFamily.IPv6:
address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in address_v6*: array[0..15, uint8] ## Contains the IP address in bytes in
@ -94,9 +94,10 @@ type
of IpAddressFamily.IPv4: of IpAddressFamily.IPv4:
address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in address_v4*: array[0..3, uint8] ## Contains the IP address in bytes in
## case of IPv4 ## case of IPv4
{.deprecated: [TIpAddress: IpAddress].}
proc isIpAddress*(address_str: string): bool {.tags: [].} proc isIpAddress*(address_str: string): bool {.tags: [].}
proc parseIpAddress*(address_str: string): TIpAddress proc parseIpAddress*(address_str: string): IpAddress
proc isDisconnectionError*(flags: set[SocketFlag], proc isDisconnectionError*(flags: set[SocketFlag],
lastError: OSErrorCode): bool = lastError: OSErrorCode): bool =
@ -395,7 +396,7 @@ proc acceptAddr*(server: Socket, client: var Socket, address: var string,
when false: #defined(ssl): when false: #defined(ssl):
proc acceptAddrSSL*(server: Socket, client: var Socket, proc acceptAddrSSL*(server: Socket, client: var Socket,
address: var string): TSSLAcceptResult {. address: var string): SSLAcceptResult {.
tags: [ReadIOEffect].} = 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: ## It will immediately return with one of the following values:
@ -992,39 +993,39 @@ proc isSsl*(socket: Socket): bool =
proc getFd*(socket: Socket): SocketHandle = return socket.fd proc getFd*(socket: Socket): SocketHandle = return socket.fd
## Returns the socket's file descriptor ## Returns the socket's file descriptor
proc IPv4_any*(): TIpAddress = proc IPv4_any*(): IpAddress =
## Returns the IPv4 any address, which can be used to listen on all available ## Returns the IPv4 any address, which can be used to listen on all available
## network adapters ## network adapters
result = TIpAddress( result = IpAddress(
family: IpAddressFamily.IPv4, family: IpAddressFamily.IPv4,
address_v4: [0'u8, 0, 0, 0]) address_v4: [0'u8, 0, 0, 0])
proc IPv4_loopback*(): TIpAddress = proc IPv4_loopback*(): IpAddress =
## Returns the IPv4 loopback address (127.0.0.1) ## Returns the IPv4 loopback address (127.0.0.1)
result = TIpAddress( result = IpAddress(
family: IpAddressFamily.IPv4, family: IpAddressFamily.IPv4,
address_v4: [127'u8, 0, 0, 1]) address_v4: [127'u8, 0, 0, 1])
proc IPv4_broadcast*(): TIpAddress = proc IPv4_broadcast*(): IpAddress =
## Returns the IPv4 broadcast address (255.255.255.255) ## Returns the IPv4 broadcast address (255.255.255.255)
result = TIpAddress( result = IpAddress(
family: IpAddressFamily.IPv4, family: IpAddressFamily.IPv4,
address_v4: [255'u8, 255, 255, 255]) address_v4: [255'u8, 255, 255, 255])
proc IPv6_any*(): TIpAddress = proc IPv6_any*(): IpAddress =
## Returns the IPv6 any address (::0), which can be used ## Returns the IPv6 any address (::0), which can be used
## to listen on all available network adapters ## to listen on all available network adapters
result = TIpAddress( result = IpAddress(
family: IpAddressFamily.IPv6, family: IpAddressFamily.IPv6,
address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
proc IPv6_loopback*(): TIpAddress = proc IPv6_loopback*(): IpAddress =
## Returns the IPv6 loopback address (::1) ## Returns the IPv6 loopback address (::1)
result = TIpAddress( result = IpAddress(
family: IpAddressFamily.IPv6, family: IpAddressFamily.IPv6,
address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]) address_v6: [0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
proc `==`*(lhs, rhs: TIpAddress): bool = proc `==`*(lhs, rhs: IpAddress): bool =
## Compares two IpAddresses for Equality. Returns two if the addresses are equal ## Compares two IpAddresses for Equality. Returns two if the addresses are equal
if lhs.family != rhs.family: return false if lhs.family != rhs.family: return false
if lhs.family == IpAddressFamily.IPv4: if lhs.family == IpAddressFamily.IPv4:
@ -1035,8 +1036,8 @@ proc `==`*(lhs, rhs: TIpAddress): bool =
if lhs.address_v6[i] != rhs.address_v6[i]: return false if lhs.address_v6[i] != rhs.address_v6[i]: return false
return true return true
proc `$`*(address: TIpAddress): string = proc `$`*(address: IpAddress): string =
## Converts an TIpAddress into the textual representation ## Converts an IpAddress into the textual representation
result = "" result = ""
case address.family case address.family
of IpAddressFamily.IPv4: of IpAddressFamily.IPv4:
@ -1095,7 +1096,7 @@ proc `$`*(address: TIpAddress): string =
mask = mask shr 4 mask = mask shr 4
printedLastGroup = true printedLastGroup = true
proc parseIPv4Address(address_str: string): TIpAddress = proc parseIPv4Address(address_str: string): IpAddress =
## Parses IPv4 adresses ## Parses IPv4 adresses
## Raises EInvalidValue on errors ## Raises EInvalidValue on errors
var var
@ -1129,7 +1130,7 @@ proc parseIPv4Address(address_str: string): TIpAddress =
raise newException(ValueError, "Invalid IP Address") raise newException(ValueError, "Invalid IP Address")
result.address_v4[byteCount] = cast[uint8](currentByte) result.address_v4[byteCount] = cast[uint8](currentByte)
proc parseIPv6Address(address_str: string): TIpAddress = proc parseIPv6Address(address_str: string): IpAddress =
## Parses IPv6 adresses ## Parses IPv6 adresses
## Raises EInvalidValue on errors ## Raises EInvalidValue on errors
result.family = IpAddressFamily.IPv6 result.family = IpAddressFamily.IPv6
@ -1250,7 +1251,7 @@ proc parseIPv6Address(address_str: string): TIpAddress =
raise newException(ValueError, raise newException(ValueError,
"Invalid IP Address. The address consists of too many groups") "Invalid IP Address. The address consists of too many groups")
proc parseIpAddress(address_str: string): TIpAddress = proc parseIpAddress(address_str: string): IpAddress =
## Parses an IP address ## Parses an IP address
## Raises EInvalidValue on error ## Raises EInvalidValue on error
if address_str == nil: if address_str == nil:

View file

@ -26,17 +26,19 @@ const
withThreads = compileOption("threads") withThreads = compileOption("threads")
tickCountCorrection = 50_000 tickCountCorrection = 50_000
when not declared(system.TStackTrace): when not declared(system.StackTrace):
type TStackTrace = array [0..20, cstring] type StackTrace = array [0..20, cstring]
{.deprecated: [TStackTrace: StackTrace].}
# We use a simple hash table of bounded size to keep track of the stack traces: # We use a simple hash table of bounded size to keep track of the stack traces:
type type
TProfileEntry = object ProfileEntry = object
total: int total: int
st: TStackTrace st: StackTrace
TProfileData = array [0..64*1024-1, ptr TProfileEntry] ProfileData = array [0..64*1024-1, ptr ProfileEntry]
{.deprecated: [TProfileEntry: ProfileEntry, TProfileData: ProfileData].}
proc `==`(a, b: TStackTrace): bool = proc `==`(a, b: StackTrace): bool =
for i in 0 .. high(a): for i in 0 .. high(a):
if a[i] != b[i]: return false if a[i] != b[i]: return false
result = true result = true
@ -44,13 +46,13 @@ proc `==`(a, b: TStackTrace): bool =
# XXX extract this data structure; it is generally useful ;-) # XXX extract this data structure; it is generally useful ;-)
# However a chain length of over 3000 is suspicious... # However a chain length of over 3000 is suspicious...
var var
profileData: TProfileData profileData: ProfileData
emptySlots = profileData.len * 3 div 2 emptySlots = profileData.len * 3 div 2
maxChainLen = 0 maxChainLen = 0
totalCalls = 0 totalCalls = 0
when not defined(memProfiler): when not defined(memProfiler):
var interval: TNanos = 5_000_000 - tickCountCorrection # 5ms var interval: Nanos = 5_000_000 - tickCountCorrection # 5ms
proc setSamplingFrequency*(intervalInUs: int) = proc setSamplingFrequency*(intervalInUs: int) =
## set this to change the sampling frequency. Default value is 5ms. ## set this to change the sampling frequency. Default value is 5ms.
@ -62,11 +64,11 @@ when not defined(memProfiler):
when withThreads: when withThreads:
import locks import locks
var var
profilingLock: TLock profilingLock: Lock
initLock profilingLock initLock profilingLock
proc hookAux(st: TStackTrace, costs: int) = proc hookAux(st: StackTrace, costs: int) =
# this is quite performance sensitive! # this is quite performance sensitive!
when withThreads: acquire profilingLock when withThreads: acquire profilingLock
inc totalCalls inc totalCalls
@ -94,8 +96,8 @@ proc hookAux(st: TStackTrace, costs: int) =
var chain = 0 var chain = 0
while true: while true:
if profileData[h] == nil: if profileData[h] == nil:
profileData[h] = cast[ptr TProfileEntry]( profileData[h] = cast[ptr ProfileEntry](
allocShared0(sizeof(TProfileEntry))) allocShared0(sizeof(ProfileEntry)))
profileData[h].total = costs profileData[h].total = costs
profileData[h].st = st profileData[h].st = st
dec emptySlots dec emptySlots
@ -115,7 +117,7 @@ when defined(memProfiler):
var var
gTicker {.threadvar.}: int gTicker {.threadvar.}: int
proc hook(st: TStackTrace, size: int) {.nimcall.} = proc hook(st: StackTrace, size: int) {.nimcall.} =
if gTicker == 0: if gTicker == 0:
gTicker = -1 gTicker = -1
when defined(ignoreAllocationSize): when defined(ignoreAllocationSize):
@ -127,26 +129,26 @@ when defined(memProfiler):
else: else:
var var
t0 {.threadvar.}: TTicks t0 {.threadvar.}: Ticks
proc hook(st: TStackTrace) {.nimcall.} = proc hook(st: StackTrace) {.nimcall.} =
if interval == 0: if interval == 0:
hookAux(st, 1) hookAux(st, 1)
elif int64(t0) == 0 or getTicks() - t0 > interval: elif int64(t0) == 0 or getTicks() - t0 > interval:
hookAux(st, 1) hookAux(st, 1)
t0 = getTicks() t0 = getTicks()
proc getTotal(x: ptr TProfileEntry): int = proc getTotal(x: ptr ProfileEntry): int =
result = if isNil(x): 0 else: x.total result = if isNil(x): 0 else: x.total
proc cmpEntries(a, b: ptr TProfileEntry): int = proc cmpEntries(a, b: ptr ProfileEntry): int =
result = b.getTotal - a.getTotal result = b.getTotal - a.getTotal
proc `//`(a, b: int): string = proc `//`(a, b: int): string =
result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2)) result = format("$1/$2 = $3%", a, b, formatFloat(a / b * 100.0, ffDefault, 2))
proc writeProfile() {.noconv.} = proc writeProfile() {.noconv.} =
when declared(system.TStackTrace): when declared(system.StackTrace):
system.profilerHook = nil system.profilerHook = nil
const filename = "profile_results.txt" const filename = "profile_results.txt"
echo "writing " & filename & "..." echo "writing " & filename & "..."
@ -161,7 +163,7 @@ proc writeProfile() {.noconv.} =
var perProc = initCountTable[string]() var perProc = initCountTable[string]()
for i in 0..entries-1: for i in 0..entries-1:
var dups = initSet[string]() var dups = initSet[string]()
for ii in 0..high(TStackTrace): for ii in 0..high(StackTrace):
let procname = profileData[i].st[ii] let procname = profileData[i].st[ii]
if isNil(procname): break if isNil(procname): break
let p = $procname let p = $procname
@ -176,7 +178,7 @@ proc writeProfile() {.noconv.} =
writeln(f, "Entry: ", i+1, "/", entries, " Calls: ", writeln(f, "Entry: ", i+1, "/", entries, " Calls: ",
profileData[i].total // totalCalls, " [sum: ", sum, "; ", profileData[i].total // totalCalls, " [sum: ", sum, "; ",
sum // totalCalls, "]") sum // totalCalls, "]")
for ii in 0..high(TStackTrace): for ii in 0..high(StackTrace):
let procname = profileData[i].st[ii] let procname = profileData[i].st[ii]
if isNil(procname): break if isNil(procname): break
writeln(f, " ", procname, " ", perProc[$procname] // totalCalls) writeln(f, " ", procname, " ", perProc[$procname] // totalCalls)
@ -189,16 +191,16 @@ var
disabled: int disabled: int
proc disableProfiling*() = proc disableProfiling*() =
when declared(system.TStackTrace): when declared(system.StackTrace):
atomicDec disabled atomicDec disabled
system.profilerHook = nil system.profilerHook = nil
proc enableProfiling*() = proc enableProfiling*() =
when declared(system.TStackTrace): when declared(system.StackTrace):
if atomicInc(disabled) >= 0: if atomicInc(disabled) >= 0:
system.profilerHook = hook system.profilerHook = hook
when declared(system.TStackTrace): when declared(system.StackTrace):
system.profilerHook = hook system.profilerHook = hook
addQuitProc(writeProfile) addQuitProc(writeProfile)

View file

@ -359,7 +359,7 @@ when defined(windows):
template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} =
var varname = winApiProc(newWideCString(arg), arg2) var varname = winApiProc(newWideCString(arg), arg2)
proc findFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle = proc findFirstFile(a: string, b: var TWIN32_FIND_DATA): Handle =
result = findFirstFileW(newWideCString(a), b) result = findFirstFileW(newWideCString(a), b)
template findNextFile(a, b: expr): expr = findNextFileW(a, b) template findNextFile(a, b: expr): expr = findNextFileW(a, b)
template getCommandLine(): expr = getCommandLineW() template getCommandLine(): expr = getCommandLineW()
@ -390,7 +390,7 @@ proc existsFile*(filename: string): bool {.rtl, extern: "nos$1",
if a != -1'i32: if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32 result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32
else: else:
var res: TStat var res: Stat
return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode) return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode)
proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect].} = proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect].} =
@ -404,7 +404,7 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [ReadDirEffect]
if a != -1'i32: if a != -1'i32:
result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32 result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32
else: else:
var res: TStat var res: Stat
return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode) return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode)
proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1", proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
@ -419,7 +419,7 @@ proc symlinkExists*(link: string): bool {.rtl, extern: "nos$1",
if a != -1'i32: if a != -1'i32:
result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32 result = (a and FILE_ATTRIBUTE_REPARSE_POINT) != 0'i32
else: else:
var res: TStat var res: Stat
return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode) return lstat(link, res) >= 0'i32 and S_ISLNK(res.st_mode)
proc fileExists*(filename: string): bool {.inline.} = proc fileExists*(filename: string): bool {.inline.} =
@ -433,7 +433,7 @@ proc dirExists*(dir: string): bool {.inline.} =
proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} = proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} =
## Returns the `file`'s last modification time. ## Returns the `file`'s last modification time.
when defined(posix): when defined(posix):
var res: TStat var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError()) if stat(file, res) < 0'i32: raiseOSError(osLastError())
return res.st_mtime return res.st_mtime
else: else:
@ -446,7 +446,7 @@ proc getLastModificationTime*(file: string): Time {.rtl, extern: "nos$1".} =
proc getLastAccessTime*(file: string): Time {.rtl, extern: "nos$1".} = proc getLastAccessTime*(file: string): Time {.rtl, extern: "nos$1".} =
## Returns the `file`'s last read or write access time. ## Returns the `file`'s last read or write access time.
when defined(posix): when defined(posix):
var res: TStat var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError()) if stat(file, res) < 0'i32: raiseOSError(osLastError())
return res.st_atime return res.st_atime
else: else:
@ -461,7 +461,7 @@ proc getCreationTime*(file: string): Time {.rtl, extern: "nos$1".} =
## Note that under posix OS's, the returned time may actually be the time at ## Note that under posix OS's, the returned time may actually be the time at
## which the file's attribute's were last modified. ## which the file's attribute's were last modified.
when defined(posix): when defined(posix):
var res: TStat var res: Stat
if stat(file, res) < 0'i32: raiseOSError(osLastError()) if stat(file, res) < 0'i32: raiseOSError(osLastError())
return res.st_ctime return res.st_ctime
else: else:
@ -794,7 +794,7 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} =
result = path[0] == '/' result = path[0] == '/'
when defined(Windows): when defined(Windows):
proc openHandle(path: string, followSymlink=true): THandle = proc openHandle(path: string, followSymlink=true): Handle =
var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL var flags = FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL
if not followSymlink: if not followSymlink:
flags = flags or FILE_FLAG_OPEN_REPARSE_POINT flags = flags or FILE_FLAG_OPEN_REPARSE_POINT
@ -846,7 +846,7 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1",
if not success: raiseOSError(lastErr) if not success: raiseOSError(lastErr)
else: else:
var a, b: TStat var a, b: Stat
if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32: if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
else: else:
@ -903,7 +903,7 @@ proc getFilePermissions*(filename: string): set[FilePermission] {.
## an error. On Windows, only the ``readonly`` flag is checked, every other ## an error. On Windows, only the ``readonly`` flag is checked, every other
## permission is available in any case. ## permission is available in any case.
when defined(posix): when defined(posix):
var a: TStat var a: Stat
if stat(filename, a) < 0'i32: raiseOSError(osLastError()) if stat(filename, a) < 0'i32: raiseOSError(osLastError())
result = {} result = {}
if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead) if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead)
@ -1232,7 +1232,7 @@ iterator walkFiles*(pattern: string): string {.tags: [ReadDirEffect].} =
findClose(res) findClose(res)
else: # here we use glob else: # here we use glob
var var
f: TGlob f: Glob
res: int res: int
f.gl_offs = 0 f.gl_offs = 0
f.gl_pathc = 0 f.gl_pathc = 0
@ -1297,7 +1297,7 @@ iterator walkDir*(dir: string): tuple[kind: PathComponent, path: string] {.
if x == nil: break if x == nil: break
var y = $x.d_name var y = $x.d_name
if y != "." and y != "..": if y != "." and y != "..":
var s: TStat var s: Stat
y = dir / y y = dir / y
var k = pcFile var k = pcFile
@ -1842,7 +1842,7 @@ proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [TimeEffect].} =
when defined(windows): when defined(windows):
winlean.sleep(int32(milsecs)) winlean.sleep(int32(milsecs))
else: else:
var a, b: Ttimespec var a, b: Timespec
a.tv_sec = Time(milsecs div 1000) a.tv_sec = Time(milsecs div 1000)
a.tv_nsec = (milsecs mod 1000) * 1000 * 1000 a.tv_nsec = (milsecs mod 1000) * 1000 * 1000
discard posix.nanosleep(a, b) discard posix.nanosleep(a, b)
@ -1907,8 +1907,8 @@ when defined(Windows):
FileId* = int64 FileId* = int64
else: else:
type type
DeviceId* = TDev DeviceId* = Dev
FileId* = Tino FileId* = Ino
type type
FileInfo* = object FileInfo* = object
@ -1925,7 +1925,7 @@ type
template rawToFormalFileInfo(rawInfo, formalInfo): expr = template rawToFormalFileInfo(rawInfo, formalInfo): expr =
## Transforms the native file info structure into the one nim uses. ## Transforms the native file info structure into the one nim uses.
## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows, ## 'rawInfo' is either a 'TBY_HANDLE_FILE_INFORMATION' structure on Windows,
## or a 'TStat' structure on posix ## or a 'Stat' structure on posix
when defined(Windows): when defined(Windows):
template toTime(e): expr = winTimeToUnixTime(rdFileTime(e)) template toTime(e): expr = winTimeToUnixTime(rdFileTime(e))
template merge(a, b): expr = a or (b shl 32) template merge(a, b): expr = a or (b shl 32)
@ -1996,7 +1996,7 @@ proc getFileInfo*(handle: FileHandle): FileInfo =
raiseOSError(osLastError()) raiseOSError(osLastError())
rawToFormalFileInfo(rawInfo, result) rawToFormalFileInfo(rawInfo, result)
else: else:
var rawInfo: TStat var rawInfo: Stat
if fstat(handle, rawInfo) < 0'i32: if fstat(handle, rawInfo) < 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
rawToFormalFileInfo(rawInfo, result) rawToFormalFileInfo(rawInfo, result)
@ -2031,7 +2031,7 @@ proc getFileInfo*(path: string, followSymlink = true): FileInfo =
rawToFormalFileInfo(rawInfo, result) rawToFormalFileInfo(rawInfo, result)
discard closeHandle(handle) discard closeHandle(handle)
else: else:
var rawInfo: TStat var rawInfo: Stat
if followSymlink: if followSymlink:
if stat(path, rawInfo) < 0'i32: if stat(path, rawInfo) < 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())

View file

@ -26,13 +26,13 @@ when defined(linux):
type type
ProcessObj = object of RootObj ProcessObj = object of RootObj
when defined(windows): when defined(windows):
fProcessHandle: THandle fProcessHandle: Handle
inHandle, outHandle, errHandle: FileHandle inHandle, outHandle, errHandle: FileHandle
id: THandle id: Handle
else: else:
inHandle, outHandle, errHandle: FileHandle inHandle, outHandle, errHandle: FileHandle
inStream, outStream, errStream: Stream inStream, outStream, errStream: Stream
id: TPid id: Pid
exitCode: cint exitCode: cint
Process* = ref ProcessObj ## represents an operating system process Process* = ref ProcessObj ## represents an operating system process
@ -334,10 +334,11 @@ when not defined(useNimRtl):
when defined(Windows) and not defined(useNimRtl): when defined(Windows) and not defined(useNimRtl):
# We need to implement a handle stream for Windows: # We need to implement a handle stream for Windows:
type type
PFileHandleStream = ref TFileHandleStream PFileHandleStream = ref FileHandleStream
TFileHandleStream = object of StreamObj FileHandleStream = object of StreamObj
handle: THandle handle: Handle
atTheEnd: bool atTheEnd: bool
{.deprecated: [TFileHandleStream: FileHandleStream].}
proc hsClose(s: Stream) = discard # nothing to do here proc hsClose(s: Stream) = discard # nothing to do here
proc hsAtEnd(s: Stream): bool = return PFileHandleStream(s).atTheEnd proc hsAtEnd(s: Stream): bool = return PFileHandleStream(s).atTheEnd
@ -361,7 +362,7 @@ when defined(Windows) and not defined(useNimRtl):
addr bytesWritten, nil) addr bytesWritten, nil)
if a == 0: raiseOSError(osLastError()) if a == 0: raiseOSError(osLastError())
proc newFileHandleStream(handle: THandle): PFileHandleStream = proc newFileHandleStream(handle: Handle): PFileHandleStream =
new(result) new(result)
result.handle = handle result.handle = handle
result.closeImpl = hsClose result.closeImpl = hsClose
@ -387,14 +388,14 @@ when defined(Windows) and not defined(useNimRtl):
copyMem(addr(result[L]), cstring(x), x.len+1) # copy \0 copyMem(addr(result[L]), cstring(x), x.len+1) # copy \0
inc(L, x.len+1) inc(L, x.len+1)
#proc open_osfhandle(osh: THandle, mode: int): int {. #proc open_osfhandle(osh: Handle, mode: int): int {.
# importc: "_open_osfhandle", header: "<fcntl.h>".} # importc: "_open_osfhandle", header: "<fcntl.h>".}
#var #var
# O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int # O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int
# O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int # O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int
proc createPipeHandles(rdHandle, wrHandle: var THandle) = proc createPipeHandles(rdHandle, wrHandle: var Handle) =
var piInheritablePipe: TSECURITY_ATTRIBUTES var piInheritablePipe: TSECURITY_ATTRIBUTES
piInheritablePipe.nLength = sizeof(TSECURITY_ATTRIBUTES).cint piInheritablePipe.nLength = sizeof(TSECURITY_ATTRIBUTES).cint
piInheritablePipe.lpSecurityDescriptor = nil piInheritablePipe.lpSecurityDescriptor = nil
@ -402,7 +403,7 @@ when defined(Windows) and not defined(useNimRtl):
if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32: if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32:
raiseOSError(osLastError()) raiseOSError(osLastError())
proc fileClose(h: THandle) {.inline.} = proc fileClose(h: Handle) {.inline.} =
if h > 4: discard closeHandle(h) if h > 4: discard closeHandle(h)
proc startProcess(command: string, proc startProcess(command: string,
@ -414,7 +415,7 @@ when defined(Windows) and not defined(useNimRtl):
si: TSTARTUPINFO si: TSTARTUPINFO
procInfo: TPROCESS_INFORMATION procInfo: TPROCESS_INFORMATION
success: int success: int
hi, ho, he: THandle hi, ho, he: Handle
new(result) new(result)
si.cb = sizeof(si).cint si.cb = sizeof(si).cint
if poParentStreams notin options: if poParentStreams notin options:
@ -527,7 +528,7 @@ when defined(Windows) and not defined(useNimRtl):
var var
si: TSTARTUPINFO si: TSTARTUPINFO
procInfo: TPROCESS_INFORMATION procInfo: TPROCESS_INFORMATION
process: THandle process: Handle
L: int32 L: int32
si.cb = sizeof(si).cint si.cb = sizeof(si).cint
si.hStdError = getStdHandle(STD_ERROR_HANDLE) si.hStdError = getStdHandle(STD_ERROR_HANDLE)
@ -595,7 +596,7 @@ elif not defined(useNimRtl):
copyMem(result[i], addr(x[0]), x.len+1) copyMem(result[i], addr(x[0]), x.len+1)
inc(i) inc(i)
type TStartProcessData = object type StartProcessData = object
sysCommand: cstring sysCommand: cstring
sysArgs: cstringArray sysArgs: cstringArray
sysEnv: cstringArray sysEnv: cstringArray
@ -604,14 +605,15 @@ elif not defined(useNimRtl):
optionPoUsePath: bool optionPoUsePath: bool
optionPoParentStreams: bool optionPoParentStreams: bool
optionPoStdErrToStdOut: bool optionPoStdErrToStdOut: bool
{.deprecated: [TStartProcessData: StartProcessData].}
when not defined(useFork): when not defined(useFork):
proc startProcessAuxSpawn(data: TStartProcessData): TPid {. proc startProcessAuxSpawn(data: StartProcessData): Pid {.
tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} tags: [ExecIOEffect, ReadEnvEffect], gcsafe.}
proc startProcessAuxFork(data: TStartProcessData): TPid {. proc startProcessAuxFork(data: StartProcessData): Pid {.
tags: [ExecIOEffect, ReadEnvEffect], gcsafe.} tags: [ExecIOEffect, ReadEnvEffect], gcsafe.}
{.push stacktrace: off, profiler: off.} {.push stacktrace: off, profiler: off.}
proc startProcessAfterFork(data: ptr TStartProcessData) {. proc startProcessAfterFork(data: ptr StartProcessData) {.
tags: [ExecIOEffect, ReadEnvEffect], cdecl, gcsafe.} tags: [ExecIOEffect, ReadEnvEffect], cdecl, gcsafe.}
{.pop.} {.pop.}
@ -641,7 +643,7 @@ elif not defined(useNimRtl):
for arg in args.items: for arg in args.items:
sysArgsRaw.add arg sysArgsRaw.add arg
var pid: TPid var pid: Pid
var sysArgs = allocCStringArray(sysArgsRaw) var sysArgs = allocCStringArray(sysArgsRaw)
defer: deallocCStringArray(sysArgs) defer: deallocCStringArray(sysArgs)
@ -653,7 +655,7 @@ elif not defined(useNimRtl):
defer: deallocCStringArray(sysEnv) defer: deallocCStringArray(sysEnv)
var data: TStartProcessData var data: StartProcessData
data.sysCommand = sysCommand data.sysCommand = sysCommand
data.sysArgs = sysArgs data.sysArgs = sysArgs
data.sysEnv = sysEnv data.sysEnv = sysEnv
@ -698,7 +700,7 @@ elif not defined(useNimRtl):
discard close(pStdout[writeIdx]) discard close(pStdout[writeIdx])
when not defined(useFork): when not defined(useFork):
proc startProcessAuxSpawn(data: TStartProcessData): TPid = proc startProcessAuxSpawn(data: StartProcessData): Pid =
var attr: Tposix_spawnattr var attr: Tposix_spawnattr
var fops: Tposix_spawn_file_actions var fops: Tposix_spawn_file_actions
@ -708,7 +710,7 @@ elif not defined(useNimRtl):
chck posix_spawn_file_actions_init(fops) chck posix_spawn_file_actions_init(fops)
chck posix_spawnattr_init(attr) chck posix_spawnattr_init(attr)
var mask: Tsigset var mask: Sigset
chck sigemptyset(mask) chck sigemptyset(mask)
chck posix_spawnattr_setsigmask(attr, mask) chck posix_spawnattr_setsigmask(attr, mask)
chck posix_spawnattr_setpgroup(attr, 0'i32) chck posix_spawnattr_setpgroup(attr, 0'i32)
@ -732,7 +734,7 @@ elif not defined(useNimRtl):
# FIXME: chdir is global to process # FIXME: chdir is global to process
if data.workingDir.len > 0: if data.workingDir.len > 0:
setCurrentDir($data.workingDir) setCurrentDir($data.workingDir)
var pid: TPid var pid: Pid
if data.optionPoUsePath: if data.optionPoUsePath:
res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv) res = posix_spawnp(pid, data.sysCommand, fops, attr, data.sysArgs, data.sysEnv)
@ -744,14 +746,14 @@ elif not defined(useNimRtl):
chck res chck res
return pid return pid
proc startProcessAuxFork(data: TStartProcessData): TPid = proc startProcessAuxFork(data: StartProcessData): Pid =
if pipe(data.pErrorPipe) != 0: if pipe(data.pErrorPipe) != 0:
raiseOSError(osLastError()) raiseOSError(osLastError())
defer: defer:
discard close(data.pErrorPipe[readIdx]) discard close(data.pErrorPipe[readIdx])
var pid: TPid var pid: Pid
var dataCopy = data var dataCopy = data
when defined(useClone): when defined(useClone):
@ -781,7 +783,7 @@ elif not defined(useNimRtl):
return pid return pid
{.push stacktrace: off, profiler: off.} {.push stacktrace: off, profiler: off.}
proc startProcessFail(data: ptr TStartProcessData) = proc startProcessFail(data: ptr StartProcessData) =
var error: cint = errno var error: cint = errno
discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error)) discard write(data.pErrorPipe[writeIdx], addr error, sizeof(error))
exitnow(1) exitnow(1)
@ -789,7 +791,7 @@ elif not defined(useNimRtl):
when defined(macosx) or defined(freebsd): when defined(macosx) or defined(freebsd):
var environ {.importc.}: cstringArray var environ {.importc.}: cstringArray
proc startProcessAfterFork(data: ptr TStartProcessData) = proc startProcessAfterFork(data: ptr StartProcessData) =
# Warning: no GC here! # Warning: no GC here!
# Or anything that touches global structures - all called nim procs # Or anything that touches global structures - all called nim procs
# must be marked with stackTrace:off. Inspect C code after making changes. # must be marked with stackTrace:off. Inspect C code after making changes.