diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/nimbase.h | 2 | ||||
-rw-r--r-- | lib/pure/asyncdispatch.nim | 13 | ||||
-rw-r--r-- | lib/pure/asynchttpserver.nim | 2 | ||||
-rw-r--r-- | lib/pure/asyncnet.nim | 38 | ||||
-rw-r--r-- | lib/pure/httpclient.nim | 35 | ||||
-rw-r--r-- | lib/pure/math.nim | 26 | ||||
-rw-r--r-- | lib/pure/net.nim | 11 | ||||
-rw-r--r-- | lib/pure/parseurl.nim | 5 | ||||
-rw-r--r-- | lib/pure/selectors.nim | 6 | ||||
-rw-r--r-- | lib/pure/uri.nim | 8 |
10 files changed, 117 insertions, 29 deletions
diff --git a/lib/nimbase.h b/lib/nimbase.h index b16b27b2c..cfd33dca1 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -376,7 +376,7 @@ static inline void GCGuard (void *ptr) { asm volatile ("" :: "X" (ptr)); } # define GC_GUARD #endif -/* Test to see if nimrod and the C compiler agrees on the size of a pointer. +/* Test to see if nimrod and the C compiler agree on the size of a pointer. On disagreement, your C compiler will say something like: "error: 'assert_numbits' declared as an array with a negative size" */ typedef int assert_numbits[sizeof(NI) == sizeof(void*) && NIM_INTBITS == sizeof(NI)*8 ? 1 : -1]; diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim index f37ae79e3..2c0f5ee61 100644 --- a/lib/pure/asyncdispatch.nim +++ b/lib/pure/asyncdispatch.nim @@ -13,13 +13,19 @@ import rawsockets export TPort ## AsyncDispatch -## -------- +## ------------- ## ## This module implements a brand new dispatcher based on Futures. -## On Windows IOCP is used and on other operating systems the selectors module -## is used instead. +## On Windows IOCP is used and on other operating systems the ``selectors`` +## module is used instead. +## +## **Note:** This module is still largely experimental. + # TODO: Discarded void PFutures need to checked for exception. +# TODO: Exceptions are currently uncatchable due to the limitation that +# you cannot have yield in a try stmt. Perhaps I can get the macro to put +# a user's try except around ``future.read``. # -- Futures @@ -394,7 +400,6 @@ when defined(windows) or defined(nimdoc): size else: bytesReceived - assert dataBuf.buf[0] != '\0' var data = newString(realSize) copyMem(addr data[0], addr dataBuf.buf[0], realSize) retFuture.complete($data) diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index 2f33cf4ab..74b044e05 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -8,6 +8,8 @@ # ## This module implements a high performance asynchronous HTTP server. +## +## **Note:** This module is still largely experimental. import strtabs, asyncnet, asyncdispatch, parseutils, parseurl, strutils type diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index 748566aaa..daa6c8839 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -6,6 +6,44 @@ # See the file "copying.txt", included in this # distribution, for details about the copyright. # + +## This module implements a high-level asynchronous sockets API based on the +## asynchronous dispatcher defined in the ``asyncdispatch`` module. +## +## Example +## ======= +## +## The following example demonstrates a simple chat server. +## +## .. code-block::nimrod +## +## import asyncnet, asyncdispatch +## +## var clients: seq[PAsyncSocket] = @[] +## +## proc processClient(client: PAsyncSocket) {.async.} = +## while true: +## let line = await client.recvLine() +## for c in clients: +## await c.send(line & "\c\L") +## +## proc serve() {.async.} = +## var server = newAsyncSocket() +## server.bindAddr(TPort(12345)) +## server.listen() +## +## while true: +## let client = await server.accept() +## clients.add client +## +## processClient(client) +## +## serve() +## runForever() +## +## +## **Note:** This module is still largely experimental. + import asyncdispatch import rawsockets import net diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 415775583..1e3a1032c 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -435,15 +435,25 @@ type connected: bool currentURL: TURL ## Where we are currently connected. headers: PStringTable + maxRedirects: int userAgent: string -proc newAsyncHttpClient*(): PAsyncHttpClient = +proc newAsyncHttpClient*(userAgent = defUserAgent, + maxRedirects = 5): PAsyncHttpClient = + ## Creates a new PAsyncHttpClient instance. + ## + ## ``userAgent`` specifies the user agent that will be used when making + ## requests. + ## + ## ``maxRedirects`` specifies the maximum amount of redirects to follow, + ## default is 5. new result result.headers = newStringTable(modeCaseInsensitive) result.userAgent = defUserAgent + result.maxRedirects = maxRedirects proc close*(client: PAsyncHttpClient) = - ## Closes any connections held by the HttpClient. + ## Closes any connections held by the HTTP client. if client.connected: client.socket.close() client.connected = false @@ -588,6 +598,14 @@ proc newConnection(client: PAsyncHttpClient, url: TURL) {.async.} = proc request*(client: PAsyncHttpClient, url: string, httpMethod = httpGET, body = ""): PFuture[TResponse] {.async.} = + ## Connects to the hostname specified by the URL and performs a request + ## using the method specified. + ## + ## Connection will kept alive. Further requests on the same ``client`` to + ## the same hostname will not require a new connection to be made. The + ## connection can be closed by using the ``close`` procedure. + ## + ## The returned future will complete once the request is completed. let r = parseUrl(url) await newConnection(client, r) @@ -602,6 +620,19 @@ proc request*(client: PAsyncHttpClient, url: string, httpMethod = httpGET, result = await parseResponse(client, httpMethod != httpHEAD) +proc get*(client: PAsyncHttpClient, url: string): PFuture[TResponse] {.async.} = + ## Connects to the hostname specified by the URL and performs a GET request. + ## + ## This procedure will follow redirects up to a maximum number of redirects + ## specified in ``newAsyncHttpClient``. + result = await client.request(url, httpGET) + var lastURL = url + for i in 1..client.maxRedirects: + if result.status.redirection(): + let redirectTo = getNewLocation(lastURL, result.headers) + result = await client.request(redirectTo, httpGET) + lastUrl = redirectTo + when isMainModule: when true: # Async diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 94570fc68..d258e9a7c 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -75,28 +75,30 @@ proc binom*(n, k: int): int {.noSideEffect.} = result = (result * (n + 1 - i)) div i proc fac*(n: int): int {.noSideEffect.} = - ## computes the faculty function + ## computes the faculty/factorial function. result = 1 for i in countup(2, n): result = result * i proc isPowerOfTwo*(x: int): bool {.noSideEffect.} = - ## returns true, if x is a power of two, false otherwise. - ## Negative numbers are not a power of two. - return (x and -x) == x - -proc nextPowerOfTwo*(x: int): int = - ## returns the nearest power of two, so that - ## result**2 >= x > (result-1)**2. - result = x - 1 + ## returns true, if `x` is a power of two, false otherwise. + ## Zero and negative numbers are not a power of two. + return (x != 0) and ((x and (x - 1)) == 0) + +proc nextPowerOfTwo*(x: int): int {.noSideEffect.} = + ## returns `x` rounded up to the nearest power of two. + ## Zero and negative numbers get rounded up to 1. + result = x - 1 when defined(cpu64): result = result or (result shr 32) - result = result or (result shr 16) - result = result or (result shr 8) + when sizeof(int) > 16: + result = result or (result shr 16) + when sizeof(int) > 8: + result = result or (result shr 8) result = result or (result shr 4) result = result or (result shr 2) result = result or (result shr 1) - inc(result) + result += 1 + ord(x<=0) proc countBits32*(n: int32): int {.noSideEffect.} = ## counts the set bits in `n`. diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 4afb5c6ab..74739630b 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -12,6 +12,9 @@ {.deadCodeElim: on.} import rawsockets, os, strutils, unsigned, parseutils, times export TPort + +const useWinVersion = defined(Windows) or defined(nimdoc) + type IpAddressFamily* {.pure.} = enum ## Describes the type of an IP address IPv6, ## IPv6 address @@ -499,7 +502,7 @@ proc socketError*(socket: PSocket, err: int = -1, async = false) = if err == -1 and not (when defined(ssl): socket.isSSL else: false): let lastError = osLastError() if async: - when defined(windows): + when useWinVersion: if lastError.int32 == WSAEWOULDBLOCK: return else: osError(lastError) @@ -525,7 +528,7 @@ proc bindAddr*(socket: PSocket, port = TPort(0), address = "") {. if address == "": var name: TSockaddr_in - when defined(windows): + when useWinVersion: name.sin_family = toInt(AF_INET).int16 else: name.sin_family = toInt(AF_INET) @@ -1009,7 +1012,7 @@ proc send*(socket: PSocket, data: pointer, size: int): int {. if socket.isSSL: return SSLWrite(socket.sslHandle, cast[cstring](data), size) - when defined(windows) or defined(macosx): + when useWinVersion or defined(macosx): result = send(socket.fd, data, size.cint, 0'i32) else: when defined(solaris): @@ -1088,7 +1091,7 @@ proc connectAsync(socket: PSocket, name: string, port = TPort(0), break else: lastError = osLastError() - when defined(windows): + when useWinVersion: # Windows EINTR doesn't behave same as POSIX. if lastError.int32 == WSAEWOULDBLOCK: success = true diff --git a/lib/pure/parseurl.nim b/lib/pure/parseurl.nim index 937f26f6f..357d1df0f 100644 --- a/lib/pure/parseurl.nim +++ b/lib/pure/parseurl.nim @@ -1,13 +1,16 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2010 Dominik Picheta +# (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## Parses & constructs URLs. +## +## **Note**: This module will be deprecated in the future and merged into a +## new ``url`` module. import strutils diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 085344e3e..454e77234 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -204,9 +204,9 @@ elif defined(windows): var retCode = 0 if timeout != -1: - retCode = int(select(TSocketHandle(m+1), addr(rd), addr(wr), nil, addr(tv))) + retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, addr(tv))) else: - retCode = int(select(TSocketHandle(m+1), addr(rd), addr(wr), nil, nil)) + retCode = int(select(cint(m+1), addr(rd), addr(wr), nil, nil)) if retCode < 0: OSError(OSLastError()) @@ -242,7 +242,7 @@ when isMainModule: sock: TSocket var sock = socket() - sock.setBlocking(false) + #sock.setBlocking(false) sock.connect("irc.freenode.net", TPort(6667)) var selector = newSelector() diff --git a/lib/pure/uri.nim b/lib/pure/uri.nim index 18afd4af6..ee1226a35 100644 --- a/lib/pure/uri.nim +++ b/lib/pure/uri.nim @@ -1,11 +1,15 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2012 Dominik Picheta +# (c) Copyright 2014 Dominik Picheta # # See the file "copying.txt", included in this # distribution, for details about the copyright. # + +## **Note**: This module will be deprecated in the future and merged into a +## new ``url`` module. + import strutils type TUrl* = distinct string @@ -30,4 +34,4 @@ proc add*(url: var TUrl, a: TUrl) = url = url / a when isMainModule: - assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000") \ No newline at end of file + assert($("http://".TUrl / "localhost:5000".TUrl) == "http://localhost:5000") |