Merge remote-tracking branch 'origin/devel' into fix-test-failures

This commit is contained in:
Aman Gupta
2015-10-06 11:06:41 -07:00
41 changed files with 358 additions and 163 deletions

View File

@@ -11,7 +11,7 @@ include "system/inclrtl"
import sockets, strutils, parseutils, times, os, asyncio
from asyncnet import nil
from rawsockets import nil
from nativesockets import nil
from asyncdispatch import PFuture
## **Note**: This module is deprecated since version 0.11.3.
## You should use the async version of this module
@@ -55,7 +55,7 @@ type
user*, pass*: string
address*: string
when SockType is asyncnet.AsyncSocket:
port*: rawsockets.Port
port*: nativesockets.Port
else:
port*: Port

View File

@@ -0,0 +1,14 @@
import nativesockets
export nativesockets
{.warning: "rawsockets module is deprecated, use nativesockets instead".}
template newRawSocket*(domain, sockType, protocol: cint): expr =
{.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
newNativeSocket(domain, sockType, protocol)
template newRawSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): expr =
{.warning: "newRawSocket is deprecated, use newNativeSocket instead".}
newNativeSocket(domain, sockType, protocol)

View File

@@ -9,7 +9,7 @@
## **Warning:** Since version 0.10.2 this module is deprecated.
## Use the `net <net.html>`_ or the
## `rawsockets <rawsockets.html>`_ module instead.
## `nativesockets <nativesockets.html>`_ module instead.
##
## This module implements portable sockets, it supports a mix of different types
## of sockets. Sockets are buffered by default meaning that data will be

View File

@@ -11,7 +11,7 @@ include "system/inclrtl"
import os, oids, tables, strutils, macros, times
import rawsockets, net
import nativesockets, net
export Port, SocketFlag
@@ -475,7 +475,7 @@ when defined(windows) or defined(nimdoc):
addr bytesRet, nil, nil) == 0
proc initAll() =
let dummySock = newRawSocket()
let dummySock = newNativeSocket()
if not initPointer(dummySock, connectExPtr, WSAID_CONNECTEX):
raiseOSError(osLastError())
if not initPointer(dummySock, acceptExPtr, WSAID_ACCEPTEX):
@@ -528,7 +528,7 @@ when defined(windows) or defined(nimdoc):
RemoteSockaddr, RemoteSockaddrLength)
proc connect*(socket: AsyncFD, address: string, port: Port,
domain = rawsockets.AF_INET): Future[void] =
domain = nativesockets.AF_INET): Future[void] =
## Connects ``socket`` to server at ``address:port``.
##
## Returns a ``Future`` which will complete when the connection succeeds
@@ -827,7 +827,7 @@ when defined(windows) or defined(nimdoc):
verifyPresence(socket)
var retFuture = newFuture[tuple[address: string, client: AsyncFD]]("acceptAddr")
var clientSock = newRawSocket()
var clientSock = newNativeSocket()
if clientSock == osInvalidSocket: raiseOSError(osLastError())
const lpOutputLen = 1024
@@ -900,17 +900,17 @@ when defined(windows) or defined(nimdoc):
return retFuture
proc newAsyncRawSocket*(domain, sockType, protocol: cint): AsyncFD =
proc newAsyncNativeSocket*(domain, sockType, protocol: cint): AsyncFD =
## Creates a new socket and registers it with the dispatcher implicitly.
result = newRawSocket(domain, sockType, protocol).AsyncFD
result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false)
register(result)
proc newAsyncRawSocket*(domain: Domain = rawsockets.AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD =
proc newAsyncNativeSocket*(domain: Domain = nativesockets.AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD =
## Creates a new socket and registers it with the dispatcher implicitly.
result = newRawSocket(domain, sockType, protocol).AsyncFD
result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false)
register(result)
@@ -973,18 +973,18 @@ else:
var data = PData(fd: fd, readCBs: @[], writeCBs: @[])
p.selector.register(fd.SocketHandle, {}, data.RootRef)
proc newAsyncRawSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD =
result = newRawSocket(domain, sockType, protocol).AsyncFD
proc newAsyncNativeSocket*(domain: cint, sockType: cint,
protocol: cint): AsyncFD =
result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false)
when defined(macosx):
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)
register(result)
proc newAsyncRawSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD =
result = newRawSocket(domain, sockType, protocol).AsyncFD
proc newAsyncNativeSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): AsyncFD =
result = newNativeSocket(domain, sockType, protocol).AsyncFD
result.SocketHandle.setBlocking(false)
when defined(macosx):
result.SocketHandle.setSockOptInt(SOL_SOCKET, SO_NOSIGPIPE, 1)

View File

@@ -56,7 +56,7 @@
##
import asyncdispatch
import rawsockets
import nativesockets
import net
import os
@@ -112,8 +112,8 @@ proc newAsyncSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
##
## This procedure will also create a brand new file descriptor for
## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol), domain,
sockType, protocol, buffered)
result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
domain, sockType, protocol, buffered)
proc newAsyncSocket*(domain, sockType, protocol: cint,
buffered = true): AsyncSocket =
@@ -121,8 +121,9 @@ proc newAsyncSocket*(domain, sockType, protocol: cint,
##
## This procedure will also create a brand new file descriptor for
## this socket.
result = newAsyncSocket(newAsyncRawSocket(domain, sockType, protocol),
Domain(domain), SockType(sockType), Protocol(protocol), buffered)
result = newAsyncSocket(newAsyncNativeSocket(domain, sockType, protocol),
Domain(domain), SockType(sockType),
Protocol(protocol), buffered)
when defined(ssl):
proc getSslError(handle: SslPtr, err: cint): cint =

View File

@@ -123,6 +123,14 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool =
var n = rawInsert(c, key)
result = c.count == oldCount
proc inc*(c: var CritBitTree[int]; key: string) =
## counts the 'key'.
let oldCount = c.count
var n = rawInsert(c, key)
if c.count == oldCount:
# not a new key:
inc n.val
proc incl*(c: var CritBitTree[void], key: string) =
## includes `key` in `c`.
discard rawInsert(c, key)

View File

@@ -81,7 +81,7 @@
import net, strutils, uri, parseutils, strtabs, base64, os, mimetypes, math
import asyncnet, asyncdispatch
import rawsockets
import nativesockets
type
Response* = tuple[
@@ -764,10 +764,10 @@ proc newConnection(client: AsyncHttpClient, url: Uri) {.async.} =
let port =
if url.port == "":
if url.scheme.toLower() == "https":
rawsockets.Port(443)
nativesockets.Port(443)
else:
rawsockets.Port(80)
else: rawsockets.Port(url.port.parseInt)
nativesockets.Port(80)
else: nativesockets.Port(url.port.parseInt)
if url.scheme.toLower() == "https":
when defined(ssl):

View File

@@ -93,8 +93,8 @@ when useWinVersion:
IOC_IN* = int(-2147483648)
FIONBIO* = IOC_IN.int32 or ((sizeof(int32) and IOCPARM_MASK) shl 16) or
(102 shl 8) or 126
rawAfInet = winlean.AF_INET
rawAfInet6 = winlean.AF_INET6
nativeAfInet = winlean.AF_INET
nativeAfInet6 = winlean.AF_INET6
proc ioctlsocket*(s: SocketHandle, cmd: clong,
argptr: ptr clong): cint {.
@@ -102,8 +102,8 @@ when useWinVersion:
else:
let
osInvalidSocket* = posix.INVALID_SOCKET
rawAfInet = posix.AF_INET
rawAfInet6 = posix.AF_INET6
nativeAfInet = posix.AF_INET
nativeAfInet6 = posix.AF_INET6
proc `==`*(a, b: Port): bool {.borrow.}
## ``==`` for ports.
@@ -157,12 +157,14 @@ else:
result = cint(ord(p))
proc newRawSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): SocketHandle =
proc newNativeSocket*(domain: Domain = AF_INET,
sockType: SockType = SOCK_STREAM,
protocol: Protocol = IPPROTO_TCP): SocketHandle =
## Creates a new socket; returns `InvalidSocket` if an error occurs.
socket(toInt(domain), toInt(sockType), toInt(protocol))
proc newRawSocket*(domain: cint, sockType: cint, protocol: cint): SocketHandle =
proc newNativeSocket*(domain: cint, sockType: cint,
protocol: cint): SocketHandle =
## Creates a new socket; returns `InvalidSocket` if an error occurs.
##
## Use this overload if one of the enums specified above does
@@ -201,7 +203,9 @@ proc getAddrInfo*(address: string, port: Port, domain: Domain = AF_INET,
hints.ai_family = toInt(domain)
hints.ai_socktype = toInt(sockType)
hints.ai_protocol = toInt(protocol)
hints.ai_flags = AI_V4MAPPED
# https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=198092
when not defined(freebsd):
hints.ai_flags = AI_V4MAPPED
var gaiResult = getaddrinfo(address, $port, addr(hints), result)
if gaiResult != 0'i32:
when useWinVersion:
@@ -229,17 +233,17 @@ proc ntohs*(x: int16): int16 =
when cpuEndian == bigEndian: result = x
else: result = (x shr 8'i16) or (x shl 8'i16)
proc htonl*(x: int32): int32 =
template htonl*(x: int32): expr =
## Converts 32-bit integers from host to network byte order. On machines
## where the host byte order is the same as network byte order, this is
## a no-op; otherwise, it performs a 4-byte swap operation.
result = rawsockets.ntohl(x)
nativesockets.ntohl(x)
proc htons*(x: int16): int16 =
template htons*(x: int16): expr =
## Converts 16-bit positive integers from host to network byte order.
## On machines where the host byte order is the same as network byte
## order, this is a no-op; otherwise, it performs a 2-byte swap operation.
result = rawsockets.ntohs(x)
nativesockets.ntohs(x)
proc getServByName*(name, proto: string): Servent {.tags: [ReadIOEffect].} =
## Searches the database from the beginning and finds the first entry for
@@ -280,7 +284,7 @@ proc getHostByAddr*(ip: string): Hostent {.tags: [ReadIOEffect].} =
when useWinVersion:
var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint,
cint(rawsockets.AF_INET))
cint(AF_INET))
if s == nil: raiseOSError(osLastError())
else:
var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).Socklen,
@@ -330,9 +334,9 @@ proc getSockDomain*(socket: SocketHandle): Domain =
if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
if name.sa_family == rawAfInet:
if name.sa_family == nativeAfInet:
result = AF_INET
elif name.sa_family == rawAfInet6:
elif name.sa_family == nativeAfInet6:
result = AF_INET6
else:
raiseOSError(osLastError(), "unknown socket family in getSockFamily")
@@ -340,9 +344,9 @@ proc getSockDomain*(socket: SocketHandle): Domain =
proc getAddrString*(sockAddr: ptr SockAddr): string =
## return the string representation of address within sockAddr
if sockAddr.sa_family == rawAfInet:
if sockAddr.sa_family == nativeAfInet:
result = $inet_ntoa(cast[ptr Sockaddr_in](sockAddr).sin_addr)
elif sockAddr.sa_family == rawAfInet6:
elif sockAddr.sa_family == nativeAfInet6:
when not useWinVersion:
# TODO: Windows
result = newString(posix.INET6_ADDRSTRLEN)
@@ -368,7 +372,7 @@ proc getSockName*(socket: SocketHandle): Port =
if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
result = Port(rawsockets.ntohs(name.sin_port))
result = Port(nativesockets.ntohs(name.sin_port))
proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
## returns the socket's local address and port number.
@@ -385,7 +389,8 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if getsockname(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
result = ($inet_ntoa(name.sin_addr),
Port(nativesockets.ntohs(name.sin_port)))
of AF_INET6:
var name: Sockaddr_in6
when useWinVersion:
@@ -401,7 +406,7 @@ proc getLocalAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")
@@ -420,7 +425,8 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if getpeername(socket, cast[ptr SockAddr](addr(name)),
addr(namelen)) == -1'i32:
raiseOSError(osLastError())
result = ($inet_ntoa(name.sin_addr), Port(rawsockets.ntohs(name.sin_port)))
result = ($inet_ntoa(name.sin_addr),
Port(nativesockets.ntohs(name.sin_port)))
of AF_INET6:
var name: Sockaddr_in6
when useWinVersion:
@@ -436,7 +442,7 @@ proc getPeerAddr*(socket: SocketHandle, domain: Domain): (string, Port) =
if inet_ntop(name.sin6_family.cint,
addr name, buf.cstring, sizeof(buf).int32).isNil:
raiseOSError(osLastError())
result = ($buf, Port(rawsockets.ntohs(name.sin6_port)))
result = ($buf, Port(nativesockets.ntohs(name.sin6_port)))
else:
raiseOSError(OSErrorCode(-1), "invalid socket family in getLocalAddr")

View File

@@ -10,7 +10,7 @@
## This module implements a high-level cross-platform sockets interface.
{.deadCodeElim: on.}
import rawsockets, os, strutils, unsigned, parseutils, times
import nativesockets, os, strutils, unsigned, parseutils, times
export Port, `$`, `==`
const useWinVersion = defined(Windows) or defined(nimdoc)
@@ -145,7 +145,7 @@ proc newSocket*(domain, sockType, protocol: cint, buffered = true): Socket =
## Creates a new socket.
##
## If an error occurs EOS will be raised.
let fd = newRawSocket(domain, sockType, protocol)
let fd = newNativeSocket(domain, sockType, protocol)
if fd == osInvalidSocket:
raiseOSError(osLastError())
result = newSocket(fd, domain.Domain, sockType.SockType, protocol.Protocol,
@@ -156,7 +156,7 @@ proc newSocket*(domain: Domain = AF_INET, sockType: SockType = SOCK_STREAM,
## Creates a new socket.
##
## If an error occurs EOS will be raised.
let fd = newRawSocket(domain, sockType, protocol)
let fd = newNativeSocket(domain, sockType, protocol)
if fd == osInvalidSocket:
raiseOSError(osLastError())
result = newSocket(fd, domain, sockType, protocol, buffered)
@@ -354,7 +354,7 @@ proc listen*(socket: Socket, backlog = SOMAXCONN) {.tags: [ReadIOEffect].} =
## queue of pending connections.
##
## Raises an EOS error upon failure.
if rawsockets.listen(socket.fd, backlog) < 0'i32:
if nativesockets.listen(socket.fd, backlog) < 0'i32:
raiseOSError(osLastError())
proc bindAddr*(socket: Socket, port = Port(0), address = "") {.

View File

@@ -39,6 +39,63 @@ proc toRational*[T:SomeInteger](x: T): Rational[T] =
result.num = x
result.den = 1
proc toRationalSub(x: float, n: int): Rational[int] =
var
a = 0
b, c, d = 1
result = 0 // 1 # rational 0
while b <= n and d <= n:
let ac = (a+c)
let bd = (b+d)
# scale by 1000 so not overflow for high precision
let mediant = (ac/1000) / (bd/1000)
if x == mediant:
if bd <= n:
result.num = ac
result.den = bd
return result
elif d > b:
result.num = c
result.den = d
return result
else:
result.num = a
result.den = b
return result
elif x > mediant:
a = ac
b = bd
else:
c = ac
d = bd
if (b > n):
return initRational(c, d)
return initRational(a, b)
proc toRational*(x: float, n: int = high(int)): Rational[int] =
## Calculate the best rational numerator and denominator
## that approximates to `x`, where the denominator is
## smaller than `n` (default is the largest possible
## int to give maximum resolution)
##
## The algorithm is based on the Farey sequence named
## after John Farey
##
## .. code-block:: Nim
## import math, rationals
## for i in 1..10:
## let t = (10 ^ (i+3)).int
## let x = toRational(PI, t)
## let newPI = x.num / x.den
## echo x, " ", newPI, " error: ", PI - newPI, " ", t
if x > 1:
result = toRationalSub(1.0/x, n)
swap(result.num, result.den)
elif x == 1.0:
result = 1 // 1
else:
result = toRationalSub(x, n)
proc toFloat*[T](x: Rational[T]): float =
## Convert a rational number `x` to a float.
x.num / x.den
@@ -288,3 +345,8 @@ when isMainModule:
assert toRational(5) == 5//1
assert abs(toFloat(y) - 0.4814814814814815) < 1.0e-7
assert toInt(z) == 0
assert toRational(0.98765432) == 12345679 // 12500000
assert toRational(0.1, 1000000) == 1 // 10
assert toRational(0.9, 1000000) == 9 // 10
assert toRational(PI) == 80143857 // 25510582

View File

@@ -173,6 +173,9 @@ proc clear*(s: StringTableRef, mode: StringTableMode) =
s.mode = mode
s.counter = 0
s.data.setLen(startSize)
for i in 0..<s.data.len:
if not isNil(s.data[i].key):
s.data[i].key = nil
proc newStringTable*(keyValuePairs: varargs[string],
mode: StringTableMode): StringTableRef {.
@@ -248,3 +251,6 @@ when isMainModule:
x.mget("11") = "23"
assert x["11"] == "23"
x.clear(modeCaseInsensitive)
x["11"] = "22"
assert x["11"] == "22"

View File

@@ -169,7 +169,8 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
inc(j)
proc strip*(s: string, leading = true, trailing = true, chars: set[char] = Whitespace): string
proc strip*(s: string, leading = true, trailing = true,
chars: set[char] = Whitespace): string
{.noSideEffect, rtl, extern: "nsuStrip".} =
## Strips `chars` from `s` and returns the resulting string.
##
@@ -504,7 +505,8 @@ proc repeat*(c: char, count: Natural): string {.noSideEffect,
##
## .. code-block:: nim
## proc tabexpand(indent: int, text: string, tabsize: int = 4) =
## echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize), text
## echo '\t'.repeat(indent div tabsize), ' '.repeat(indent mod tabsize),
## text
##
## tabexpand(4, "At four")
## tabexpand(5, "At five")
@@ -533,11 +535,13 @@ template spaces*(n: Natural): string = repeat(' ',n)
## echo text1 & spaces(max(0, width - text1.len)) & "|"
## echo text2 & spaces(max(0, width - text2.len)) & "|"
proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} = repeat(c, count)
proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} =
## deprecated: use repeat() or spaces()
repeat(c, count)
proc repeatStr*(count: Natural, s: string): string {.deprecated.} = repeat(s, count)
proc repeatStr*(count: Natural, s: string): string {.deprecated.} =
## deprecated: use repeat(string, count) or string.repeat(count)
repeat(s, count)
proc align*(s: string, count: Natural, padding = ' '): string {.
noSideEffect, rtl, extern: "nsuAlignString".} =
@@ -850,8 +854,8 @@ proc rfind*(s: string, sub: char, start: int = -1): int {.noSideEffect,
if sub == s[i]: return i
return -1
proc count*(s: string, sub: string, overlapping: bool = false): int {.noSideEffect,
rtl, extern: "nsuCountString".} =
proc count*(s: string, sub: string, overlapping: bool = false): int {.
noSideEffect, rtl, extern: "nsuCountString".} =
## Count the occurrences of a substring `sub` in the string `s`.
## Overlapping occurrences of `sub` only count when `overlapping`
## is set to true.
@@ -1449,7 +1453,8 @@ proc removeSuffix*(s: var string, chars: set[char] = Newlines) {.
s.setLen(last + 1)
proc removeSuffix*(s: var string, c: char) {.rtl, extern: "nsuRemoveSuffixChar".} =
proc removeSuffix*(s: var string, c: char) {.
rtl, extern: "nsuRemoveSuffixChar".} =
## Removes a single character (in-place) from a string.
## .. code-block:: nim
## var
@@ -1515,7 +1520,8 @@ when isMainModule:
doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
doAssert strip("stripme but don't strip this stripme",
chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) == " but don't strip this "
chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) ==
" but don't strip this "
doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo"
doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"

View File

@@ -31,7 +31,8 @@ proc moveFile(src, dest: string) {.
tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
proc copyFile(src, dest: string) {.
tags: [ReadIOEffect, WriteIOEffect], raises: [OSError].} = builtin
proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} = builtin
proc createDir(dir: string) {.tags: [WriteIOEffect], raises: [OSError].} =
builtin
proc getOsError: string = builtin
proc setCurrentDir(dir: string) = builtin
proc getCurrentDir(): string = builtin

View File

@@ -18,7 +18,7 @@ const
type
Handle* = int
LONG* = int32
ULONG* = int
ULONG* = int32
PULONG* = ptr int
WINBOOL* = int32
DWORD* = int32