Merge branch 'devel' of https://github.com/Araq/Nim into devel
Conflicts: compiler/semexprs.nim
This commit is contained in:
commit
65310266d8
46 changed files with 991 additions and 490 deletions
|
|
@ -878,6 +878,10 @@ else:
|
|||
let data = PData(info.key.data)
|
||||
assert data.fd == info.key.fd.TAsyncFD
|
||||
#echo("In poll ", data.fd.cint)
|
||||
if EvError in info.events:
|
||||
closeSocket(data.fd)
|
||||
continue
|
||||
|
||||
if EvRead in info.events:
|
||||
# Callback may add items to ``data.readCBs`` which causes issues if
|
||||
# we are iterating over ``data.readCBs`` at the same time. We therefore
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@
|
|||
## as the response body.
|
||||
##
|
||||
## .. code-block::nim
|
||||
## import asynchttpserver, asyncdispatch
|
||||
##
|
||||
## var server = newAsyncHttpServer()
|
||||
## proc cb(req: Request) {.async.} =
|
||||
## await req.respond(Http200, "Hello World")
|
||||
|
|
|
|||
|
|
@ -32,21 +32,12 @@
|
|||
## the server.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
||||
## var body: string = "--xyz\c\L"
|
||||
## # soap 1.2 output
|
||||
## body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
||||
## body.add("\c\Lsoap12\c\L")
|
||||
## var data = newMultipartData()
|
||||
## data["output"] = "soap12"
|
||||
## data["uploaded_file"] = ("test.html", "text/html",
|
||||
## "<html><head></head><body><p>test</p></body></html>")
|
||||
##
|
||||
## # html
|
||||
## body.add("--xyz\c\L")
|
||||
## body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
||||
## " filename=\"test.html\"\c\L")
|
||||
## body.add("Content-Type: text/html\c\L")
|
||||
## body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
|
||||
## body.add("--xyz--")
|
||||
##
|
||||
## echo(postContent("http://validator.w3.org/check", headers, body))
|
||||
## echo postContent("http://validator.w3.org/check", multipart=data)
|
||||
##
|
||||
## Asynchronous HTTP requests
|
||||
## ==========================
|
||||
|
|
@ -88,7 +79,7 @@
|
|||
## constructor should be used for this purpose. However,
|
||||
## currently only basic authentication is supported.
|
||||
|
||||
import net, strutils, uri, parseutils, strtabs, base64, os
|
||||
import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
|
||||
import asyncnet, asyncdispatch
|
||||
import rawsockets
|
||||
|
||||
|
|
@ -103,6 +94,10 @@ type
|
|||
url*: Uri
|
||||
auth*: string
|
||||
|
||||
MultipartEntries* = openarray[tuple[name, content: string]]
|
||||
MultipartData* = ref object
|
||||
content: seq[string]
|
||||
|
||||
ProtocolError* = object of IOError ## exception that is raised when server
|
||||
## does not conform to the implemented
|
||||
## protocol
|
||||
|
|
@ -282,6 +277,109 @@ proc newProxy*(url: string, auth = ""): Proxy =
|
|||
## Constructs a new ``TProxy`` object.
|
||||
result = Proxy(url: parseUri(url), auth: auth)
|
||||
|
||||
proc newMultipartData*: MultipartData =
|
||||
## Constructs a new ``MultipartData`` object.
|
||||
MultipartData(content: @[])
|
||||
|
||||
proc add*(p: var MultipartData, name, content: string, filename: string = nil,
|
||||
contentType: string = nil) =
|
||||
## Add a value to the multipart data. Raises a `ValueError` exception if
|
||||
## `name`, `filename` or `contentType` contain newline characters.
|
||||
|
||||
if {'\c','\L'} in name:
|
||||
raise newException(ValueError, "name contains a newline character")
|
||||
if filename != nil and {'\c','\L'} in filename:
|
||||
raise newException(ValueError, "filename contains a newline character")
|
||||
if contentType != nil and {'\c','\L'} in contentType:
|
||||
raise newException(ValueError, "contentType contains a newline character")
|
||||
|
||||
var str = "Content-Disposition: form-data; name=\"" & name & "\""
|
||||
if filename != nil:
|
||||
str.add("; filename=\"" & filename & "\"")
|
||||
str.add("\c\L")
|
||||
if contentType != nil:
|
||||
str.add("Content-Type: " & contentType & "\c\L")
|
||||
str.add("\c\L" & content & "\c\L")
|
||||
|
||||
p.content.add(str)
|
||||
|
||||
proc add*(p: var MultipartData, xs: MultipartEntries): MultipartData
|
||||
{.discardable.} =
|
||||
## Add a list of multipart entries to the multipart data `p`. All values are
|
||||
## added without a filename and without a content type.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## data.add({"action": "login", "format": "json"})
|
||||
for name, content in xs.items:
|
||||
p.add(name, content)
|
||||
result = p
|
||||
|
||||
proc newMultipartData*(xs: MultipartEntries): MultipartData =
|
||||
## Create a new multipart data object and fill it with the entries `xs`
|
||||
## directly.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## var data = newMultipartData({"action": "login", "format": "json"})
|
||||
result = MultipartData(content: @[])
|
||||
result.add(xs)
|
||||
|
||||
proc addFiles*(p: var MultipartData, xs: openarray[tuple[name, file: string]]):
|
||||
MultipartData {.discardable.} =
|
||||
## Add files to a multipart data object. The file will be opened from your
|
||||
## disk, read and sent with the automatically determined MIME type. Raises an
|
||||
## `IOError` if the file cannot be opened or reading fails. To manually
|
||||
## specify file content, filename and MIME type, use `[]=` instead.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## data.addFiles({"uploaded_file": "public/test.html"})
|
||||
var m = newMimetypes()
|
||||
for name, file in xs.items:
|
||||
var contentType: string
|
||||
let (dir, fName, ext) = splitFile(file)
|
||||
if ext.len > 0:
|
||||
contentType = m.getMimetype(ext[1..ext.high], nil)
|
||||
p.add(name, readFile(file), fName & ext, contentType)
|
||||
result = p
|
||||
|
||||
proc `[]=`*(p: var MultipartData, name, content: string) =
|
||||
## Add a multipart entry to the multipart data `p`. The value is added
|
||||
## without a filename and without a content type.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## data["username"] = "NimUser"
|
||||
p.add(name, content)
|
||||
|
||||
proc `[]=`*(p: var MultipartData, name: string,
|
||||
file: tuple[name, contentType, content: string]) =
|
||||
## Add a file to the multipart data `p`, specifying filename, contentType and
|
||||
## content manually.
|
||||
##
|
||||
## .. code-block:: Nim
|
||||
## data["uploaded_file"] = ("test.html", "text/html",
|
||||
## "<html><head></head><body><p>test</p></body></html>")
|
||||
p.add(name, file.content, file.name, file.contentType)
|
||||
|
||||
proc format(p: MultipartData): tuple[header, body: string] =
|
||||
if p == nil or p.content == nil or p.content.len == 0:
|
||||
return ("", "")
|
||||
|
||||
# Create boundary that is not in the data to be formatted
|
||||
var bound: string
|
||||
while true:
|
||||
bound = $random(int.high)
|
||||
var found = false
|
||||
for s in p.content:
|
||||
if bound in s:
|
||||
found = true
|
||||
if not found:
|
||||
break
|
||||
|
||||
result.header = "Content-Type: multipart/form-data; boundary=" & bound & "\c\L"
|
||||
result.body = ""
|
||||
for s in p.content:
|
||||
result.body.add("--" & bound & "\c\L" & s)
|
||||
result.body.add("--" & bound & "--\c\L")
|
||||
|
||||
proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
||||
body = "",
|
||||
sslContext: SSLContext = defaultSSLContext,
|
||||
|
|
@ -294,7 +392,9 @@ proc request*(url: string, httpMethod = httpGET, extraHeaders = "",
|
|||
var r = if proxy == nil: parseUri(url) else: proxy.url
|
||||
var headers = substr($httpMethod, len("http"))
|
||||
if proxy == nil:
|
||||
headers.add(" /" & r.path & r.query)
|
||||
headers.add(" " & r.path)
|
||||
if r.query.len > 0:
|
||||
headers.add("?" & r.query)
|
||||
else:
|
||||
headers.add(" " & url)
|
||||
|
||||
|
|
@ -387,15 +487,30 @@ proc post*(url: string, extraHeaders = "", body = "",
|
|||
maxRedirects = 5,
|
||||
sslContext: SSLContext = defaultSSLContext,
|
||||
timeout = -1, userAgent = defUserAgent,
|
||||
proxy: Proxy = nil): Response =
|
||||
proxy: Proxy = nil,
|
||||
multipart: MultipartData = nil): Response =
|
||||
## | POSTs ``body`` to the ``url`` and returns a ``Response`` object.
|
||||
## | This proc adds the necessary Content-Length header.
|
||||
## | This proc also handles redirection.
|
||||
## | Extra headers can be specified and must be separated by ``\c\L``.
|
||||
## | An optional timeout can be specified in miliseconds, if reading from the
|
||||
## server takes longer than specified an ETimeout exception will be raised.
|
||||
var xh = extraHeaders & "Content-Length: " & $len(body) & "\c\L"
|
||||
result = request(url, httpPOST, xh, body, sslContext, timeout, userAgent,
|
||||
## | The optional ``multipart`` parameter can be used to create
|
||||
## ``multipart/form-data`` POSTs comfortably.
|
||||
let (mpHeaders, mpBody) = format(multipart)
|
||||
|
||||
template withNewLine(x): expr =
|
||||
if x.len > 0 and not x.endsWith("\c\L"):
|
||||
x & "\c\L"
|
||||
else:
|
||||
x
|
||||
|
||||
var xb = mpBody.withNewLine() & body.withNewLine()
|
||||
|
||||
var xh = extraHeaders.withNewLine() & mpHeaders.withNewLine() &
|
||||
withNewLine("Content-Length: " & $len(xb))
|
||||
|
||||
result = request(url, httpPOST, xh, xb, sslContext, timeout, userAgent,
|
||||
proxy)
|
||||
var lastUrl = ""
|
||||
for i in 1..maxRedirects:
|
||||
|
|
@ -410,14 +525,17 @@ proc postContent*(url: string, extraHeaders = "", body = "",
|
|||
maxRedirects = 5,
|
||||
sslContext: SSLContext = defaultSSLContext,
|
||||
timeout = -1, userAgent = defUserAgent,
|
||||
proxy: Proxy = nil): string =
|
||||
proxy: Proxy = nil,
|
||||
multipart: MultipartData = nil): string =
|
||||
## | POSTs ``body`` to ``url`` and returns the response's body as a string
|
||||
## | Raises exceptions for the status codes ``4xx`` and ``5xx``
|
||||
## | Extra headers can be specified and must be separated by ``\c\L``.
|
||||
## | An optional timeout can be specified in miliseconds, if reading from the
|
||||
## server takes longer than specified an ETimeout exception will be raised.
|
||||
## | The optional ``multipart`` parameter can be used to create
|
||||
## ``multipart/form-data`` POSTs comfortably.
|
||||
var r = post(url, extraHeaders, body, maxRedirects, sslContext, timeout,
|
||||
userAgent, proxy)
|
||||
userAgent, proxy, multipart)
|
||||
if r.status[0] in {'4','5'}:
|
||||
raise newException(HttpRequestError, r.status)
|
||||
else:
|
||||
|
|
@ -442,7 +560,9 @@ proc generateHeaders(r: Uri, httpMethod: HttpMethod,
|
|||
headers: StringTableRef): string =
|
||||
result = substr($httpMethod, len("http"))
|
||||
# TODO: Proxies
|
||||
result.add(" /" & r.path & r.query)
|
||||
result.add(" " & r.path)
|
||||
if r.query.len > 0:
|
||||
result.add("?" & r.query)
|
||||
result.add(" HTTP/1.1\c\L")
|
||||
|
||||
add(result, "Host: " & r.hostname & "\c\L")
|
||||
|
|
@ -706,18 +826,9 @@ when isMainModule:
|
|||
#var r = get("http://validator.w3.org/check?uri=http%3A%2F%2Fgoogle.com&
|
||||
# charset=%28detect+automatically%29&doctype=Inline&group=0")
|
||||
|
||||
var headers: string = "Content-Type: multipart/form-data; boundary=xyz\c\L"
|
||||
var body: string = "--xyz\c\L"
|
||||
# soap 1.2 output
|
||||
body.add("Content-Disposition: form-data; name=\"output\"\c\L")
|
||||
body.add("\c\Lsoap12\c\L")
|
||||
var data = newMultipartData()
|
||||
data["output"] = "soap12"
|
||||
data["uploaded_file"] = ("test.html", "text/html",
|
||||
"<html><head></head><body><p>test</p></body></html>")
|
||||
|
||||
# html
|
||||
body.add("--xyz\c\L")
|
||||
body.add("Content-Disposition: form-data; name=\"uploaded_file\";" &
|
||||
" filename=\"test.html\"\c\L")
|
||||
body.add("Content-Type: text/html\c\L")
|
||||
body.add("\c\L<html><head></head><body><p>test</p></body></html>\c\L")
|
||||
body.add("--xyz--")
|
||||
|
||||
echo(postContent("http://validator.w3.org/check", headers, body))
|
||||
echo postContent("http://validator.w3.org/check", multipart=data)
|
||||
|
|
|
|||
270
lib/pure/md5.nim
270
lib/pure/md5.nim
|
|
@ -9,18 +9,20 @@
|
|||
|
||||
## Module for computing MD5 checksums.
|
||||
|
||||
type
|
||||
MD5State = array[0..3, int32]
|
||||
MD5Block = array[0..15, int32]
|
||||
MD5CBits = array[0..7, int8]
|
||||
MD5Digest* = array[0..15, int8]
|
||||
MD5Buffer = array[0..63, int8]
|
||||
MD5Context* {.final.} = object
|
||||
import unsigned
|
||||
|
||||
type
|
||||
MD5State = array[0..3, uint32]
|
||||
MD5Block = array[0..15, uint32]
|
||||
MD5CBits = array[0..7, uint8]
|
||||
MD5Digest* = array[0..15, uint8]
|
||||
MD5Buffer = array[0..63, uint8]
|
||||
MD5Context* {.final.} = object
|
||||
state: MD5State
|
||||
count: array[0..1, int32]
|
||||
count: array[0..1, uint32]
|
||||
buffer: MD5Buffer
|
||||
|
||||
const
|
||||
const
|
||||
padding: cstring = "\x80\0\0\0" &
|
||||
"\0\0\0\0\0\0\0\0" &
|
||||
"\0\0\0\0\0\0\0\0" &
|
||||
|
|
@ -31,60 +33,60 @@ const
|
|||
"\0\0\0\0\0\0\0\0" &
|
||||
"\0\0\0\0"
|
||||
|
||||
proc F(x, y, z: int32): int32 {.inline.} =
|
||||
proc F(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = (x and y) or ((not x) and z)
|
||||
|
||||
proc G(x, y, z: int32): int32 {.inline.} =
|
||||
proc G(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = (x and z) or (y and (not z))
|
||||
|
||||
proc H(x, y, z: int32): int32 {.inline.} =
|
||||
proc H(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = x xor y xor z
|
||||
|
||||
proc I(x, y, z: int32): int32 {.inline.} =
|
||||
proc I(x, y, z: uint32): uint32 {.inline.} =
|
||||
result = y xor (x or (not z))
|
||||
|
||||
proc rot(x: var int32, n: int8) {.inline.} =
|
||||
x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n)))
|
||||
proc rot(x: var uint32, n: uint8) {.inline.} =
|
||||
x = (x shl n) or (x shr (32'u32 - n))
|
||||
|
||||
proc FF(a: var int32, b, c, d, x: int32, s: int8, ac: int32) =
|
||||
a = a +% F(b, c, d) +% x +% ac
|
||||
proc FF(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + F(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a +% b
|
||||
a = a + b
|
||||
|
||||
proc GG(a: var int32, b, c, d, x: int32, s: int8, ac: int32) =
|
||||
a = a +% G(b, c, d) +% x +% ac
|
||||
proc GG(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + G(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a +% b
|
||||
a = a + b
|
||||
|
||||
proc HH(a: var int32, b, c, d, x: int32, s: int8, ac: int32) =
|
||||
a = a +% H(b, c, d) +% x +% ac
|
||||
proc HH(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + H(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a +% b
|
||||
a = a + b
|
||||
|
||||
proc II(a: var int32, b, c, d, x: int32, s: int8, ac: int32) =
|
||||
a = a +% I(b, c, d) +% x +% ac
|
||||
proc II(a: var uint32, b, c, d, x: uint32, s: uint8, ac: uint32) =
|
||||
a = a + I(b, c, d) + x + ac
|
||||
rot(a, s)
|
||||
a = a +% b
|
||||
a = a + b
|
||||
|
||||
proc encode(dest: var MD5Block, src: cstring) =
|
||||
proc encode(dest: var MD5Block, src: cstring) =
|
||||
var j = 0
|
||||
for i in 0..high(dest):
|
||||
dest[i] = toU32(ord(src[j]) or
|
||||
ord(src[j+1]) shl 8 or
|
||||
ord(src[j+2]) shl 16 or
|
||||
ord(src[j+3]) shl 24)
|
||||
dest[i] = uint32(ord(src[j])) or
|
||||
uint32(ord(src[j+1])) shl 8 or
|
||||
uint32(ord(src[j+2])) shl 16 or
|
||||
uint32(ord(src[j+3])) shl 24
|
||||
inc(j, 4)
|
||||
|
||||
proc decode(dest: var openArray[int8], src: openArray[int32]) =
|
||||
proc decode(dest: var openArray[uint8], src: openArray[uint32]) =
|
||||
var i = 0
|
||||
for j in 0..high(src):
|
||||
dest[i] = toU8(src[j] and 0xff'i32)
|
||||
dest[i+1] = toU8(src[j] shr 8'i32 and 0xff'i32)
|
||||
dest[i+2] = toU8(src[j] shr 16'i32 and 0xff'i32)
|
||||
dest[i+3] = toU8(src[j] shr 24'i32 and 0xff'i32)
|
||||
dest[i] = src[j] and 0xff'u32
|
||||
dest[i+1] = src[j] shr 8 and 0xff'u32
|
||||
dest[i+2] = src[j] shr 16 and 0xff'u32
|
||||
dest[i+3] = src[j] shr 24 and 0xff'u32
|
||||
inc(i, 4)
|
||||
|
||||
proc transform(buffer: pointer, state: var MD5State) =
|
||||
proc transform(buffer: pointer, state: var MD5State) =
|
||||
var
|
||||
myBlock: MD5Block
|
||||
encode(myBlock, cast[cstring](buffer))
|
||||
|
|
@ -92,111 +94,111 @@ proc transform(buffer: pointer, state: var MD5State) =
|
|||
var b = state[1]
|
||||
var c = state[2]
|
||||
var d = state[3]
|
||||
FF(a, b, c, d, myBlock[0], 7'i8, 0xD76AA478'i32)
|
||||
FF(d, a, b, c, myBlock[1], 12'i8, 0xE8C7B756'i32)
|
||||
FF(c, d, a, b, myBlock[2], 17'i8, 0x242070DB'i32)
|
||||
FF(b, c, d, a, myBlock[3], 22'i8, 0xC1BDCEEE'i32)
|
||||
FF(a, b, c, d, myBlock[4], 7'i8, 0xF57C0FAF'i32)
|
||||
FF(d, a, b, c, myBlock[5], 12'i8, 0x4787C62A'i32)
|
||||
FF(c, d, a, b, myBlock[6], 17'i8, 0xA8304613'i32)
|
||||
FF(b, c, d, a, myBlock[7], 22'i8, 0xFD469501'i32)
|
||||
FF(a, b, c, d, myBlock[8], 7'i8, 0x698098D8'i32)
|
||||
FF(d, a, b, c, myBlock[9], 12'i8, 0x8B44F7AF'i32)
|
||||
FF(c, d, a, b, myBlock[10], 17'i8, 0xFFFF5BB1'i32)
|
||||
FF(b, c, d, a, myBlock[11], 22'i8, 0x895CD7BE'i32)
|
||||
FF(a, b, c, d, myBlock[12], 7'i8, 0x6B901122'i32)
|
||||
FF(d, a, b, c, myBlock[13], 12'i8, 0xFD987193'i32)
|
||||
FF(c, d, a, b, myBlock[14], 17'i8, 0xA679438E'i32)
|
||||
FF(b, c, d, a, myBlock[15], 22'i8, 0x49B40821'i32)
|
||||
GG(a, b, c, d, myBlock[1], 5'i8, 0xF61E2562'i32)
|
||||
GG(d, a, b, c, myBlock[6], 9'i8, 0xC040B340'i32)
|
||||
GG(c, d, a, b, myBlock[11], 14'i8, 0x265E5A51'i32)
|
||||
GG(b, c, d, a, myBlock[0], 20'i8, 0xE9B6C7AA'i32)
|
||||
GG(a, b, c, d, myBlock[5], 5'i8, 0xD62F105D'i32)
|
||||
GG(d, a, b, c, myBlock[10], 9'i8, 0x02441453'i32)
|
||||
GG(c, d, a, b, myBlock[15], 14'i8, 0xD8A1E681'i32)
|
||||
GG(b, c, d, a, myBlock[4], 20'i8, 0xE7D3FBC8'i32)
|
||||
GG(a, b, c, d, myBlock[9], 5'i8, 0x21E1CDE6'i32)
|
||||
GG(d, a, b, c, myBlock[14], 9'i8, 0xC33707D6'i32)
|
||||
GG(c, d, a, b, myBlock[3], 14'i8, 0xF4D50D87'i32)
|
||||
GG(b, c, d, a, myBlock[8], 20'i8, 0x455A14ED'i32)
|
||||
GG(a, b, c, d, myBlock[13], 5'i8, 0xA9E3E905'i32)
|
||||
GG(d, a, b, c, myBlock[2], 9'i8, 0xFCEFA3F8'i32)
|
||||
GG(c, d, a, b, myBlock[7], 14'i8, 0x676F02D9'i32)
|
||||
GG(b, c, d, a, myBlock[12], 20'i8, 0x8D2A4C8A'i32)
|
||||
HH(a, b, c, d, myBlock[5], 4'i8, 0xFFFA3942'i32)
|
||||
HH(d, a, b, c, myBlock[8], 11'i8, 0x8771F681'i32)
|
||||
HH(c, d, a, b, myBlock[11], 16'i8, 0x6D9D6122'i32)
|
||||
HH(b, c, d, a, myBlock[14], 23'i8, 0xFDE5380C'i32)
|
||||
HH(a, b, c, d, myBlock[1], 4'i8, 0xA4BEEA44'i32)
|
||||
HH(d, a, b, c, myBlock[4], 11'i8, 0x4BDECFA9'i32)
|
||||
HH(c, d, a, b, myBlock[7], 16'i8, 0xF6BB4B60'i32)
|
||||
HH(b, c, d, a, myBlock[10], 23'i8, 0xBEBFBC70'i32)
|
||||
HH(a, b, c, d, myBlock[13], 4'i8, 0x289B7EC6'i32)
|
||||
HH(d, a, b, c, myBlock[0], 11'i8, 0xEAA127FA'i32)
|
||||
HH(c, d, a, b, myBlock[3], 16'i8, 0xD4EF3085'i32)
|
||||
HH(b, c, d, a, myBlock[6], 23'i8, 0x04881D05'i32)
|
||||
HH(a, b, c, d, myBlock[9], 4'i8, 0xD9D4D039'i32)
|
||||
HH(d, a, b, c, myBlock[12], 11'i8, 0xE6DB99E5'i32)
|
||||
HH(c, d, a, b, myBlock[15], 16'i8, 0x1FA27CF8'i32)
|
||||
HH(b, c, d, a, myBlock[2], 23'i8, 0xC4AC5665'i32)
|
||||
II(a, b, c, d, myBlock[0], 6'i8, 0xF4292244'i32)
|
||||
II(d, a, b, c, myBlock[7], 10'i8, 0x432AFF97'i32)
|
||||
II(c, d, a, b, myBlock[14], 15'i8, 0xAB9423A7'i32)
|
||||
II(b, c, d, a, myBlock[5], 21'i8, 0xFC93A039'i32)
|
||||
II(a, b, c, d, myBlock[12], 6'i8, 0x655B59C3'i32)
|
||||
II(d, a, b, c, myBlock[3], 10'i8, 0x8F0CCC92'i32)
|
||||
II(c, d, a, b, myBlock[10], 15'i8, 0xFFEFF47D'i32)
|
||||
II(b, c, d, a, myBlock[1], 21'i8, 0x85845DD1'i32)
|
||||
II(a, b, c, d, myBlock[8], 6'i8, 0x6FA87E4F'i32)
|
||||
II(d, a, b, c, myBlock[15], 10'i8, 0xFE2CE6E0'i32)
|
||||
II(c, d, a, b, myBlock[6], 15'i8, 0xA3014314'i32)
|
||||
II(b, c, d, a, myBlock[13], 21'i8, 0x4E0811A1'i32)
|
||||
II(a, b, c, d, myBlock[4], 6'i8, 0xF7537E82'i32)
|
||||
II(d, a, b, c, myBlock[11], 10'i8, 0xBD3AF235'i32)
|
||||
II(c, d, a, b, myBlock[2], 15'i8, 0x2AD7D2BB'i32)
|
||||
II(b, c, d, a, myBlock[9], 21'i8, 0xEB86D391'i32)
|
||||
state[0] = state[0] +% a
|
||||
state[1] = state[1] +% b
|
||||
state[2] = state[2] +% c
|
||||
state[3] = state[3] +% d
|
||||
|
||||
proc md5Init*(c: var MD5Context) =
|
||||
## initializes a MD5Context
|
||||
c.state[0] = 0x67452301'i32
|
||||
c.state[1] = 0xEFCDAB89'i32
|
||||
c.state[2] = 0x98BADCFE'i32
|
||||
c.state[3] = 0x10325476'i32
|
||||
c.count[0] = 0'i32
|
||||
c.count[1] = 0'i32
|
||||
FF(a, b, c, d, myBlock[0], 7'u8, 0xD76AA478'u32)
|
||||
FF(d, a, b, c, myBlock[1], 12'u8, 0xE8C7B756'u32)
|
||||
FF(c, d, a, b, myBlock[2], 17'u8, 0x242070DB'u32)
|
||||
FF(b, c, d, a, myBlock[3], 22'u8, 0xC1BDCEEE'u32)
|
||||
FF(a, b, c, d, myBlock[4], 7'u8, 0xF57C0FAF'u32)
|
||||
FF(d, a, b, c, myBlock[5], 12'u8, 0x4787C62A'u32)
|
||||
FF(c, d, a, b, myBlock[6], 17'u8, 0xA8304613'u32)
|
||||
FF(b, c, d, a, myBlock[7], 22'u8, 0xFD469501'u32)
|
||||
FF(a, b, c, d, myBlock[8], 7'u8, 0x698098D8'u32)
|
||||
FF(d, a, b, c, myBlock[9], 12'u8, 0x8B44F7AF'u32)
|
||||
FF(c, d, a, b, myBlock[10], 17'u8, 0xFFFF5BB1'u32)
|
||||
FF(b, c, d, a, myBlock[11], 22'u8, 0x895CD7BE'u32)
|
||||
FF(a, b, c, d, myBlock[12], 7'u8, 0x6B901122'u32)
|
||||
FF(d, a, b, c, myBlock[13], 12'u8, 0xFD987193'u32)
|
||||
FF(c, d, a, b, myBlock[14], 17'u8, 0xA679438E'u32)
|
||||
FF(b, c, d, a, myBlock[15], 22'u8, 0x49B40821'u32)
|
||||
GG(a, b, c, d, myBlock[1], 5'u8, 0xF61E2562'u32)
|
||||
GG(d, a, b, c, myBlock[6], 9'u8, 0xC040B340'u32)
|
||||
GG(c, d, a, b, myBlock[11], 14'u8, 0x265E5A51'u32)
|
||||
GG(b, c, d, a, myBlock[0], 20'u8, 0xE9B6C7AA'u32)
|
||||
GG(a, b, c, d, myBlock[5], 5'u8, 0xD62F105D'u32)
|
||||
GG(d, a, b, c, myBlock[10], 9'u8, 0x02441453'u32)
|
||||
GG(c, d, a, b, myBlock[15], 14'u8, 0xD8A1E681'u32)
|
||||
GG(b, c, d, a, myBlock[4], 20'u8, 0xE7D3FBC8'u32)
|
||||
GG(a, b, c, d, myBlock[9], 5'u8, 0x21E1CDE6'u32)
|
||||
GG(d, a, b, c, myBlock[14], 9'u8, 0xC33707D6'u32)
|
||||
GG(c, d, a, b, myBlock[3], 14'u8, 0xF4D50D87'u32)
|
||||
GG(b, c, d, a, myBlock[8], 20'u8, 0x455A14ED'u32)
|
||||
GG(a, b, c, d, myBlock[13], 5'u8, 0xA9E3E905'u32)
|
||||
GG(d, a, b, c, myBlock[2], 9'u8, 0xFCEFA3F8'u32)
|
||||
GG(c, d, a, b, myBlock[7], 14'u8, 0x676F02D9'u32)
|
||||
GG(b, c, d, a, myBlock[12], 20'u8, 0x8D2A4C8A'u32)
|
||||
HH(a, b, c, d, myBlock[5], 4'u8, 0xFFFA3942'u32)
|
||||
HH(d, a, b, c, myBlock[8], 11'u8, 0x8771F681'u32)
|
||||
HH(c, d, a, b, myBlock[11], 16'u8, 0x6D9D6122'u32)
|
||||
HH(b, c, d, a, myBlock[14], 23'u8, 0xFDE5380C'u32)
|
||||
HH(a, b, c, d, myBlock[1], 4'u8, 0xA4BEEA44'u32)
|
||||
HH(d, a, b, c, myBlock[4], 11'u8, 0x4BDECFA9'u32)
|
||||
HH(c, d, a, b, myBlock[7], 16'u8, 0xF6BB4B60'u32)
|
||||
HH(b, c, d, a, myBlock[10], 23'u8, 0xBEBFBC70'u32)
|
||||
HH(a, b, c, d, myBlock[13], 4'u8, 0x289B7EC6'u32)
|
||||
HH(d, a, b, c, myBlock[0], 11'u8, 0xEAA127FA'u32)
|
||||
HH(c, d, a, b, myBlock[3], 16'u8, 0xD4EF3085'u32)
|
||||
HH(b, c, d, a, myBlock[6], 23'u8, 0x04881D05'u32)
|
||||
HH(a, b, c, d, myBlock[9], 4'u8, 0xD9D4D039'u32)
|
||||
HH(d, a, b, c, myBlock[12], 11'u8, 0xE6DB99E5'u32)
|
||||
HH(c, d, a, b, myBlock[15], 16'u8, 0x1FA27CF8'u32)
|
||||
HH(b, c, d, a, myBlock[2], 23'u8, 0xC4AC5665'u32)
|
||||
II(a, b, c, d, myBlock[0], 6'u8, 0xF4292244'u32)
|
||||
II(d, a, b, c, myBlock[7], 10'u8, 0x432AFF97'u32)
|
||||
II(c, d, a, b, myBlock[14], 15'u8, 0xAB9423A7'u32)
|
||||
II(b, c, d, a, myBlock[5], 21'u8, 0xFC93A039'u32)
|
||||
II(a, b, c, d, myBlock[12], 6'u8, 0x655B59C3'u32)
|
||||
II(d, a, b, c, myBlock[3], 10'u8, 0x8F0CCC92'u32)
|
||||
II(c, d, a, b, myBlock[10], 15'u8, 0xFFEFF47D'u32)
|
||||
II(b, c, d, a, myBlock[1], 21'u8, 0x85845DD1'u32)
|
||||
II(a, b, c, d, myBlock[8], 6'u8, 0x6FA87E4F'u32)
|
||||
II(d, a, b, c, myBlock[15], 10'u8, 0xFE2CE6E0'u32)
|
||||
II(c, d, a, b, myBlock[6], 15'u8, 0xA3014314'u32)
|
||||
II(b, c, d, a, myBlock[13], 21'u8, 0x4E0811A1'u32)
|
||||
II(a, b, c, d, myBlock[4], 6'u8, 0xF7537E82'u32)
|
||||
II(d, a, b, c, myBlock[11], 10'u8, 0xBD3AF235'u32)
|
||||
II(c, d, a, b, myBlock[2], 15'u8, 0x2AD7D2BB'u32)
|
||||
II(b, c, d, a, myBlock[9], 21'u8, 0xEB86D391'u32)
|
||||
state[0] = state[0] + a
|
||||
state[1] = state[1] + b
|
||||
state[2] = state[2] + c
|
||||
state[3] = state[3] + d
|
||||
|
||||
proc md5Init*(c: var MD5Context) =
|
||||
## initializes a MD5Context
|
||||
c.state[0] = 0x67452301'u32
|
||||
c.state[1] = 0xEFCDAB89'u32
|
||||
c.state[2] = 0x98BADCFE'u32
|
||||
c.state[3] = 0x10325476'u32
|
||||
c.count[0] = 0'u32
|
||||
c.count[1] = 0'u32
|
||||
zeroMem(addr(c.buffer), sizeof(MD5buffer))
|
||||
|
||||
proc md5Update*(c: var MD5Context, input: cstring, len: int) =
|
||||
proc md5Update*(c: var MD5Context, input: cstring, len: int) =
|
||||
## updates the MD5Context with the `input` data of length `len`
|
||||
var input = input
|
||||
var Index = (c.count[0] shr 3) and 0x3F
|
||||
c.count[0] = c.count[0] +% toU32(len shl 3)
|
||||
if c.count[0] < (len shl 3): c.count[1] = c.count[1] +% 1'i32
|
||||
c.count[1] = c.count[1] +% toU32(len shr 29)
|
||||
var Index = int((c.count[0] shr 3) and 0x3F)
|
||||
c.count[0] = c.count[0] + (uint32(len) shl 3)
|
||||
if c.count[0] < (uint32(len) shl 3): c.count[1] = c.count[1] + 1'u32
|
||||
c.count[1] = c.count[1] + (uint32(len) shr 29)
|
||||
var PartLen = 64 - Index
|
||||
if len >= PartLen:
|
||||
if len >= PartLen:
|
||||
copyMem(addr(c.buffer[Index]), input, PartLen)
|
||||
transform(addr(c.buffer), c.state)
|
||||
var i = PartLen
|
||||
while i + 63 < len:
|
||||
while i + 63 < len:
|
||||
transform(addr(input[i]), c.state)
|
||||
inc(i, 64)
|
||||
copyMem(addr(c.buffer[0]), addr(input[i]), len-i)
|
||||
else:
|
||||
copyMem(addr(c.buffer[Index]), addr(input[0]), len)
|
||||
|
||||
proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||
proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
||||
## finishes the MD5Context and stores the result in `digest`
|
||||
var
|
||||
Bits: MD5CBits
|
||||
PadLen: int
|
||||
decode(Bits, c.count)
|
||||
var Index = (c.count[0] shr 3) and 0x3F
|
||||
var Index = int((c.count[0] shr 3) and 0x3F)
|
||||
if Index < 56: PadLen = 56 - Index
|
||||
else: PadLen = 120 - Index
|
||||
md5Update(c, padding, PadLen)
|
||||
|
|
@ -204,34 +206,34 @@ proc md5Final*(c: var MD5Context, digest: var MD5Digest) =
|
|||
decode(digest, c.state)
|
||||
zeroMem(addr(c), sizeof(MD5Context))
|
||||
|
||||
proc toMD5*(s: string): MD5Digest =
|
||||
proc toMD5*(s: string): MD5Digest =
|
||||
## computes the MD5Digest value for a string `s`
|
||||
var c: MD5Context
|
||||
md5Init(c)
|
||||
md5Update(c, cstring(s), len(s))
|
||||
md5Final(c, result)
|
||||
|
||||
proc `$`*(D: MD5Digest): string =
|
||||
|
||||
proc `$`*(D: MD5Digest): string =
|
||||
## converts a MD5Digest value into its string representation
|
||||
const digits = "0123456789abcdef"
|
||||
result = ""
|
||||
for i in 0..15:
|
||||
for i in 0..15:
|
||||
add(result, digits[(D[i] shr 4) and 0xF])
|
||||
add(result, digits[D[i] and 0xF])
|
||||
|
||||
proc getMD5*(s: string): string =
|
||||
proc getMD5*(s: string): string =
|
||||
## computes an MD5 value of `s` and returns its string representation
|
||||
var
|
||||
var
|
||||
c: MD5Context
|
||||
d: MD5Digest
|
||||
md5Init(c)
|
||||
md5Update(c, cstring(s), len(s))
|
||||
md5Final(c, d)
|
||||
result = $d
|
||||
|
||||
proc `==`*(D1, D2: MD5Digest): bool =
|
||||
|
||||
proc `==`*(D1, D2: MD5Digest): bool =
|
||||
## checks if two MD5Digest values are identical
|
||||
for i in 0..15:
|
||||
for i in 0..15:
|
||||
if D1[i] != D2[i]: return false
|
||||
return true
|
||||
|
||||
|
|
@ -241,5 +243,3 @@ when isMainModule:
|
|||
assert(getMD5("Frank jagt im komplett verwahrlosten Taxi quer durch Bayern") ==
|
||||
"7e716d0e702df0505fc72e2b89467910")
|
||||
assert($toMD5("") == "d41d8cd98f00b204e9800998ecf8427e")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ proc `$`*(x: SocketHandle): string {.borrow.}
|
|||
|
||||
type
|
||||
Event* = enum
|
||||
EvRead, EvWrite
|
||||
EvRead, EvWrite, EvError
|
||||
|
||||
SelectorKey* = ref object
|
||||
fd*: SocketHandle
|
||||
|
|
@ -146,12 +146,19 @@ elif defined(linux):
|
|||
## on the ``fd``.
|
||||
result = @[]
|
||||
let evNum = epoll_wait(s.epollFD, addr s.events[0], 64.cint, timeout.cint)
|
||||
if evNum < 0: raiseOSError(osLastError())
|
||||
if evNum < 0:
|
||||
let err = osLastError()
|
||||
if err.cint == EINTR:
|
||||
return @[]
|
||||
raiseOSError(osLastError())
|
||||
if evNum == 0: return @[]
|
||||
for i in 0 .. <evNum:
|
||||
let fd = s.events[i].data.fd.SocketHandle
|
||||
|
||||
var evSet: set[Event] = {}
|
||||
if (s.events[i].events and EPOLLERR) != 0: evSet = evSet + {EvError}
|
||||
if (s.events[i].events and EPOLLHUP) != 0: evSet = evSet + {EvError}
|
||||
if (s.events[i].events and EPOLLRDHUP) != 0: evSet = evSet + {EvError}
|
||||
if (s.events[i].events and EPOLLIN) != 0: evSet = evSet + {EvRead}
|
||||
if (s.events[i].events and EPOLLOUT) != 0: evSet = evSet + {EvWrite}
|
||||
let selectorKey = s.fds[fd]
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#
|
||||
#
|
||||
# Nim's Runtime Library
|
||||
# (c) Copyright 2012 Nim Contributors
|
||||
# (c) Copyright 2015 Nim Contributors
|
||||
#
|
||||
# See the file "copying.txt", included in this
|
||||
# distribution, for details about the copyright.
|
||||
|
|
@ -9,12 +9,27 @@
|
|||
|
||||
## :Author: Zahary Karadjov
|
||||
##
|
||||
## This module implements the standard unit testing facilities such as
|
||||
## suites, fixtures and test cases as well as facilities for combinatorial
|
||||
## and randomzied test case generation (not yet available)
|
||||
## and object mocking (not yet available)
|
||||
## This module implements boilerplate to make testing easy.
|
||||
##
|
||||
## It is loosely based on C++'s boost.test and Haskell's QuickTest
|
||||
## Example:
|
||||
##
|
||||
## .. code:: nim
|
||||
##
|
||||
## suite "description for this stuff":
|
||||
## test "essential truths":
|
||||
## # give up and stop if this fails
|
||||
## require(true)
|
||||
##
|
||||
## test "slightly less obvious stuff":
|
||||
## # print a nasty message and move on, skipping
|
||||
## # the remainder of this block
|
||||
## check(1 != 1)
|
||||
## check("asd"[2] == 'd')
|
||||
##
|
||||
## test "out of bounds error is thrown on bad access":
|
||||
## let v = @[1, 2, 3] # you can do initialization here
|
||||
## expect(IndexError):
|
||||
## discard v[4]
|
||||
|
||||
import
|
||||
macros
|
||||
|
|
@ -209,3 +224,5 @@ if envOutLvl.len > 0:
|
|||
if $opt == envOutLvl:
|
||||
outputLevel = opt
|
||||
break
|
||||
|
||||
system.addQuitProc(resetAttributes)
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ type
|
|||
Uri* = object
|
||||
scheme*, username*, password*: string
|
||||
hostname*, port*, path*, query*, anchor*: string
|
||||
opaque*: bool
|
||||
|
||||
{.deprecated: [TUrl: Url, TUri: Uri].}
|
||||
|
||||
|
|
@ -115,6 +116,8 @@ proc parseUri*(uri: string): Uri =
|
|||
if authority == "":
|
||||
raise newException(ValueError, "Expected authority got nothing.")
|
||||
parseAuthority(authority, result)
|
||||
else:
|
||||
result.opaque = true
|
||||
|
||||
# Path
|
||||
parsePath(uri, i, result)
|
||||
|
|
@ -256,7 +259,10 @@ proc `$`*(u: Uri): string =
|
|||
result = ""
|
||||
if u.scheme.len > 0:
|
||||
result.add(u.scheme)
|
||||
result.add("://")
|
||||
if u.opaque:
|
||||
result.add(":")
|
||||
else:
|
||||
result.add("://")
|
||||
if u.username.len > 0:
|
||||
result.add(u.username)
|
||||
if u.password.len > 0:
|
||||
|
|
@ -268,22 +274,28 @@ proc `$`*(u: Uri): string =
|
|||
result.add(":")
|
||||
result.add(u.port)
|
||||
if u.path.len > 0:
|
||||
if u.path[0] != '/': result.add("/")
|
||||
result.add(u.path)
|
||||
result.add(u.query)
|
||||
result.add(u.anchor)
|
||||
if u.query.len > 0:
|
||||
result.add("?")
|
||||
result.add(u.query)
|
||||
if u.anchor.len > 0:
|
||||
result.add("#")
|
||||
result.add(u.anchor)
|
||||
|
||||
when isMainModule:
|
||||
block:
|
||||
let test = parseUri("http://localhost:8080/test")
|
||||
let str = "http://localhost:8080/test"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == "http"
|
||||
doAssert test.port == "8080"
|
||||
doAssert test.path == "/test"
|
||||
doAssert test.hostname == "localhost"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("foo://username:password@example.com:8042/over/there" &
|
||||
"/index.dtb?type=animal&name=narwhal#nose")
|
||||
let str = "foo://username:password@example.com:8042/over/there" &
|
||||
"/index.dtb?type=animal&name=narwhal#nose"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == "foo"
|
||||
doAssert test.username == "username"
|
||||
doAssert test.password == "password"
|
||||
|
|
@ -292,34 +304,45 @@ when isMainModule:
|
|||
doAssert test.path == "/over/there/index.dtb"
|
||||
doAssert test.query == "type=animal&name=narwhal"
|
||||
doAssert test.anchor == "nose"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("urn:example:animal:ferret:nose")
|
||||
let str = "urn:example:animal:ferret:nose"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == "urn"
|
||||
doAssert test.path == "example:animal:ferret:nose"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("mailto:username@example.com?subject=Topic")
|
||||
let str = "mailto:username@example.com?subject=Topic"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == "mailto"
|
||||
doAssert test.username == "username"
|
||||
doAssert test.hostname == "example.com"
|
||||
doAssert test.query == "subject=Topic"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar")
|
||||
let str = "magnet:?xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == "magnet"
|
||||
doAssert test.query == "xt=urn:sha1:72hsga62ba515sbd62&dn=foobar"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("/test/foo/bar?q=2#asdf")
|
||||
let str = "/test/foo/bar?q=2#asdf"
|
||||
let test = parseUri(str)
|
||||
doAssert test.scheme == ""
|
||||
doAssert test.path == "/test/foo/bar"
|
||||
doAssert test.query == "q=2"
|
||||
doAssert test.anchor == "asdf"
|
||||
doAssert($test == str)
|
||||
|
||||
block:
|
||||
let test = parseUri("test/no/slash")
|
||||
let str = "test/no/slash"
|
||||
let test = parseUri(str)
|
||||
doAssert test.path == "test/no/slash"
|
||||
doAssert($test == str)
|
||||
|
||||
# Remove dot segments tests
|
||||
block:
|
||||
|
|
@ -371,5 +394,3 @@ when isMainModule:
|
|||
block:
|
||||
let test = parseUri("http://example.com/foo/") / "/bar/asd"
|
||||
doAssert test.path == "/foo/bar/asd"
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ type
|
|||
waMarkGlobal, # part of the backup/debug mark&sweep
|
||||
waMarkPrecise, # part of the backup/debug mark&sweep
|
||||
waZctDecRef, waPush, waCycleDecRef, waMarkGray, waScan, waScanBlack,
|
||||
waCollectWhite,
|
||||
waCollectWhite #, waDebug
|
||||
|
||||
TFinalizer {.compilerproc.} = proc (self: pointer) {.nimcall, benign.}
|
||||
# A ref type can have a finalizer that is called before the object's
|
||||
|
|
@ -595,9 +595,15 @@ proc scan(s: PCell) =
|
|||
else:
|
||||
s.setColor(rcWhite)
|
||||
forAllChildren(s, waScan)
|
||||
|
||||
|
||||
proc collectWhite(s: PCell) =
|
||||
if s.color == rcWhite and s notin gch.cycleRoots:
|
||||
# This is a hacky way to deal with the following problem (bug #1796)
|
||||
# Consider this content in cycleRoots:
|
||||
# x -> a; y -> a where 'a' is an acyclic object so not included in
|
||||
# cycleRoots itself. Then 'collectWhite' used to free 'a' twice. The
|
||||
# 'isAllocatedPtr' check prevents this. This also means we do not need
|
||||
# to query 's notin gch.cycleRoots' at all.
|
||||
if isAllocatedPtr(gch.region, s) and s.color == rcWhite:
|
||||
s.setColor(rcBlack)
|
||||
forAllChildren(s, waCollectWhite)
|
||||
freeCyclicCell(gch, s)
|
||||
|
|
@ -648,6 +654,28 @@ when useMarkForDebug or useBackupGc:
|
|||
if objStart != nil:
|
||||
markS(gch, objStart)
|
||||
|
||||
when logGC:
|
||||
var
|
||||
cycleCheckA: array[100, PCell]
|
||||
cycleCheckALen = 0
|
||||
|
||||
proc alreadySeen(c: PCell): bool =
|
||||
for i in 0 .. <cycleCheckALen:
|
||||
if cycleCheckA[i] == c: return true
|
||||
if cycleCheckALen == len(cycleCheckA):
|
||||
gcAssert(false, "cycle detection overflow")
|
||||
quit 1
|
||||
cycleCheckA[cycleCheckALen] = c
|
||||
inc cycleCheckALen
|
||||
|
||||
proc debugGraph(s: PCell) =
|
||||
if alreadySeen(s):
|
||||
writeCell("child cell (already seen) ", s)
|
||||
else:
|
||||
writeCell("cell {", s)
|
||||
forAllChildren(s, waDebug)
|
||||
c_fprintf(c_stdout, "}\n")
|
||||
|
||||
proc doOperation(p: pointer, op: TWalkOp) =
|
||||
if p == nil: return
|
||||
var c: PCell = usrToCell(p)
|
||||
|
|
@ -690,6 +718,7 @@ proc doOperation(p: pointer, op: TWalkOp) =
|
|||
of waMarkPrecise:
|
||||
when useMarkForDebug or useBackupGc:
|
||||
add(gch.tempStack, c)
|
||||
#of waDebug: debugGraph(c)
|
||||
|
||||
proc nimGCvisit(d: pointer, op: int) {.compilerRtl.} =
|
||||
doOperation(d, TWalkOp(op))
|
||||
|
|
@ -702,7 +731,6 @@ when useMarkForDebug or useBackupGc:
|
|||
|
||||
proc collectRoots(gch: var TGcHeap) =
|
||||
for s in elements(gch.cycleRoots):
|
||||
excl(gch.cycleRoots, s)
|
||||
collectWhite(s)
|
||||
|
||||
proc collectCycles(gch: var TGcHeap) =
|
||||
|
|
|
|||
|
|
@ -1344,7 +1344,7 @@ when not defined(useNimRtl):
|
|||
else:
|
||||
dec(gch.recGcLock)
|
||||
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) =
|
||||
proc GC_setStrategy(strategy: GC_Strategy) =
|
||||
case strategy
|
||||
of gcThroughput: nil
|
||||
of gcResponsiveness: nil
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ when defined(boehmgc):
|
|||
proc GC_disable() = boehmGC_disable()
|
||||
proc GC_enable() = boehmGC_enable()
|
||||
proc GC_fullCollect() = boehmGCfullCollect()
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
|
@ -221,7 +221,7 @@ elif defined(nogc) and defined(useMalloc):
|
|||
proc GC_disable() = discard
|
||||
proc GC_enable() = discard
|
||||
proc GC_fullCollect() = discard
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
|
@ -281,7 +281,7 @@ elif defined(nogc):
|
|||
proc GC_disable() = discard
|
||||
proc GC_enable() = discard
|
||||
proc GC_fullCollect() = discard
|
||||
proc GC_setStrategy(strategy: TGC_Strategy) = discard
|
||||
proc GC_setStrategy(strategy: GC_Strategy) = discard
|
||||
proc GC_enableMarkAndSweep() = discard
|
||||
proc GC_disableMarkAndSweep() = discard
|
||||
proc GC_getStatistics(): string = return ""
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
when defined(Unix):
|
||||
const
|
||||
lib = "libmysqlclient.so.15"
|
||||
lib = "libmysqlclient.so.(15|16|17|18)"
|
||||
when defined(Windows):
|
||||
const
|
||||
lib = "libmysql.dll"
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ when useWinVersion:
|
|||
from winlean import SocketHandle
|
||||
else:
|
||||
const
|
||||
versions = "(|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
|
||||
versions = "(.10|.1.0.1|.1.0.0|.0.9.9|.0.9.8|.0.9.7|.0.9.6|.0.9.5|.0.9.4)"
|
||||
when defined(macosx):
|
||||
const
|
||||
DLLSSLName = "libssl" & versions & ".dylib"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue