lib/pure/e-o - Dropped 'T' from types
This commit is contained in:
parent
192ba3bbc0
commit
6914244f30
13 changed files with 202 additions and 185 deletions
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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" )
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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 "}}"
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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}"
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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?
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue