diff options
author | Araq <rumpf_a@web.de> | 2012-11-18 13:34:48 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-11-18 13:34:48 +0100 |
commit | ec9b1f78e1d574017ec7372eb6acf1e7078053f9 (patch) | |
tree | 060804c9f5a490580a5c29e7c7fa3760c5b70ad2 /lib | |
parent | 1c17d3e84158dc6c88a92af690fddd2c3f921c34 (diff) | |
download | Nim-ec9b1f78e1d574017ec7372eb6acf1e7078053f9.tar.gz |
annotated effects of modules: os, sockets, times
Diffstat (limited to 'lib')
-rwxr-xr-x | lib/pure/os.nim | 100 | ||||
-rwxr-xr-x | lib/pure/osproc.nim | 7 | ||||
-rwxr-xr-x | lib/pure/sockets.nim | 119 | ||||
-rwxr-xr-x | lib/pure/times.nim | 16 |
4 files changed, 142 insertions, 100 deletions
diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 68634e4ca..a220c1da4 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -28,6 +28,17 @@ else: include "system/ansi_c" +type + FReadEnv* = object of FReadIO ## effect that denotes a read + ## from an environment variable + FWriteEnv* = object of FWriteIO ## effect that denotes a write + ## to an environment variable + + FReadDir* = object of FReadIO ## effect that denotes a write operation to + ## the directory structure + FWriteDir* = object of FWriteIO ## effect that denotes a write operation to + ## the directory structure + const doslike = defined(windows) or defined(OS2) or defined(DOS) # DOS-like filesystem @@ -275,7 +286,8 @@ when defined(windows): template getFilename(f: expr): expr = $f.cFilename -proc existsFile*(filename: string): bool {.rtl, extern: "nos$1".} = +proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", + tags: [FReadDir].} = ## Returns true if the file exists, false otherwise. when defined(windows): when useWinUnicode: @@ -288,7 +300,7 @@ proc existsFile*(filename: string): bool {.rtl, extern: "nos$1".} = var res: TStat return stat(filename, res) >= 0'i32 and S_ISREG(res.st_mode) -proc existsDir*(dir: string): bool {.rtl, extern: "nos$1".} = +proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = ## Returns true iff the directory `dir` exists. If `dir` is a file, false ## is returned. when defined(windows): @@ -346,7 +358,7 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} = ## modification time is later than `b`'s. result = getLastModificationTime(a) - getLastModificationTime(b) > 0 -proc getCurrentDir*(): string {.rtl, extern: "nos$1".} = +proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} = ## Returns the `current working directory`:idx:. const bufsize = 512 # should be enough when defined(windows): @@ -368,7 +380,7 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1".} = else: OSError() -proc setCurrentDir*(newDir: string) {.inline.} = +proc setCurrentDir*(newDir: string) {.inline, tags: [].} = ## Sets the `current working directory`:idx:; `EOS` is raised if ## `newDir` cannot been set. when defined(Windows): @@ -559,7 +571,8 @@ proc extractFilename*(path: string): string {. else: result = splitPath(path).tail -proc expandFilename*(filename: string): string {.rtl, extern: "nos$1".} = +proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", + tags: [FReadDir].} = ## Returns the full path of `filename`, raises EOS in case of an error. when defined(windows): const bufsize = 3072'i32 @@ -647,7 +660,8 @@ proc isAbsolute*(path: string): bool {.rtl, noSideEffect, extern: "nos$1".} = elif defined(posix): result = path[0] == '/' -proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} = +proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", + tags: [FReadDir].} = ## Returns True if both pathname arguments refer to the same physical ## file or directory. Raises an exception if any of the files does not ## exist or information about it can not be obtained. @@ -702,7 +716,8 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1".} = else: result = a.st_dev == b.st_dev and a.st_ino == b.st_ino -proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1".} = +proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1", + tags: [FReadIO].} = ## Returns True if both pathname arguments refer to files with identical ## binary content. const @@ -732,7 +747,8 @@ proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1".} = close(a) close(b) -proc copyFile*(source, dest: string) {.rtl, extern: "nos$1".} = +proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", + tags: [FReadIO, FWriteIO].} = ## Copies a file from `source` to `dest`. If this fails, ## `EOS` is raised. when defined(Windows): @@ -768,19 +784,21 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1".} = close(s) close(d) -proc moveFile*(source, dest: string) {.rtl, extern: "nos$1".} = +proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", + tags: [FReadIO, FWriteIO].} = ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised. if crename(source, dest) != 0'i32: OSError() when not defined(ENOENT): - var ENOENT* {.importc, header: "<errno.h>".}: cint + var ENOENT {.importc, header: "<errno.h>".}: cint -proc removeFile*(file: string) {.rtl, extern: "nos$1".} = +proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail ## if the file never existed in the first place. if cremove(file) != 0'i32 and errno != ENOENT: OSError() -proc execShellCmd*(command: string): int {.rtl, extern: "nos$1".} = +proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", + tags: [FExecIO].} = ## Executes a `shell command`:idx:. ## ## Command has the form 'program args' where args are the command @@ -873,7 +891,7 @@ proc findEnvVar(key: string): int = if startsWith(environment[i], temp): return i return -1 -proc getEnv*(key: string): TaintedString = +proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} = ## Returns the value of the `environment variable`:idx: named `key`. ## ## If the variable does not exist, "" is returned. To distinguish @@ -887,13 +905,13 @@ proc getEnv*(key: string): TaintedString = if env == nil: return TaintedString("") result = TaintedString($env) -proc existsEnv*(key: string): bool = +proc existsEnv*(key: string): bool {.tags: [FReadEnv].} = ## Checks whether the environment variable named `key` exists. ## Returns true if it exists, false otherwise. if cgetenv(key) != nil: return true else: return findEnvVar(key) >= 0 -proc putEnv*(key, val: string) = +proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = ## Sets the value of the `environment variable`:idx: named `key` to `val`. ## If an error occurs, `EInvalidEnvVar` is raised. @@ -921,7 +939,7 @@ proc putEnv*(key, val: string) = else: if SetEnvironmentVariableA(key, val) == 0'i32: OSError() -iterator envPairs*(): tuple[key, value: TaintedString] = +iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} = ## Iterate over all `environments variables`:idx:. In the first component ## of the tuple is the name of the current variable stored, in the second ## its value. @@ -931,7 +949,7 @@ iterator envPairs*(): tuple[key, value: TaintedString] = yield (TaintedString(substr(environment[i], 0, p-1)), TaintedString(substr(environment[i], p+1))) -iterator walkFiles*(pattern: string): string = +iterator walkFiles*(pattern: string): string {.tags: [FReadDir].} = ## Iterate over all the files that match the `pattern`. On POSIX this uses ## the `glob`:idx: call. ## @@ -969,7 +987,8 @@ type pcDir, ## path refers to a directory pcLinkToDir ## path refers to a symbolic link to a directory -iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] = +iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. + tags: [FReadDir].} = ## walks over the directory `dir` and yields for each directory or file in ## `dir`. The component type and full path for each item is returned. ## Walking is not recursive. @@ -1019,7 +1038,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] = yield (k, y) discard closeDir(d) -iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string = +iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. + tags: [FReadDir].} = ## walks over the directory `dir` and yields for each file in `dir`. The ## full path for each file is returned. ## Walking is recursive. `filter` controls the behaviour of the iterator: @@ -1052,7 +1072,8 @@ proc rawRemoveDir(dir: string) = else: if rmdir(dir) != 0'i32 and errno != ENOENT: OSError() -proc removeDir*(dir: string) {.rtl, extern: "nos$1".} = +proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ + FWriteDir, FReadDir].} = ## Removes the directory `dir` including all subdirectories and files ## in `dir` (recursively). If this fails, `EOS` is raised. This does not fail ## if the directory never existed in the first place. @@ -1074,7 +1095,7 @@ proc rawCreateDir(dir: string) = if res == 0'i32 and GetLastError() != 183'i32: OSError() -proc createDir*(dir: string) {.rtl, extern: "nos$1".} = +proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Creates the `directory`:idx: `dir`. ## ## The directory may contain several subdirectories that do not exist yet. @@ -1085,7 +1106,8 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1".} = if dir[i] in {dirsep, altsep}: rawCreateDir(substr(dir, 0, i-1)) rawCreateDir(dir) -proc copyDir*(source, dest: string) {.rtl, extern: "nos$1".} = +proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", + tags: [FWriteIO, FReadIO].} = ## Copies a directory from `source` to `dest`. If this fails, `EOS` is raised. createDir(dest) for kind, path in walkDir(source): @@ -1199,7 +1221,7 @@ type fpOthersRead ## read access for others proc getFilePermissions*(filename: string): set[TFilePermission] {. - rtl, extern: "nos$1".} = + rtl, extern: "nos$1", tags: [FReadDir].} = ## retrieves file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is checked, every other ## permission is available in any case. @@ -1231,7 +1253,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {. result = {fpUserExec..fpOthersRead} proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1".} = + rtl, extern: "nos$1", tags: [FWriteDir].} = ## sets the file permissions for `filename`. `OSError` is raised in case of ## an error. On Windows, only the ``readonly`` flag is changed, depending on ## ``fpUserWrite``. @@ -1268,7 +1290,7 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {. proc inclFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1".} = + rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} = ## a convenience procedure for: ## ## .. code-block:: nimrod @@ -1277,24 +1299,24 @@ proc inclFilePermissions*(filename: string, proc exclFilePermissions*(filename: string, permissions: set[TFilePermission]) {. - rtl, extern: "nos$1".} = + rtl, extern: "nos$1", tags: [FReadDir, FWriteDir].} = ## a convenience procedure for: ## ## .. code-block:: nimrod ## setFilePermissions(filename, getFilePermissions(filename)-permissions) setFilePermissions(filename, getFilePermissions(filename)-permissions) -proc getHomeDir*(): string {.rtl, extern: "nos$1".} = +proc getHomeDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = ## Returns the home directory of the current user. when defined(windows): return string(getEnv("USERPROFILE")) & "\\" else: return string(getEnv("HOME")) & "/" -proc getConfigDir*(): string {.rtl, extern: "nos$1".} = +proc getConfigDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = ## Returns the config directory of the current user for applications. when defined(windows): return string(getEnv("APPDATA")) & "\\" else: return string(getEnv("HOME")) & "/.config/" -proc getTempDir*(): string {.rtl, extern: "nos$1".} = +proc getTempDir*(): string {.rtl, extern: "nos$1", tags: [FReadEnv].} = ## Returns the temporary directory of the current user for applications to ## save temporary files in. when defined(windows): return string(getEnv("TEMP")) & "\\" @@ -1309,13 +1331,14 @@ when defined(windows): var ownArgv: seq[string] - proc paramCount*(): int {.rtl, extern: "nos$1".} = + proc paramCount*(): int {.rtl, extern: "nos$1", tags: [FReadIO].} = ## Returns the number of `command line arguments`:idx: given to the ## application. if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine()) result = ownArgv.len-1 - proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1".} = + proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1", + tags: [FReadIO].} = ## Returns the `i`-th `command line argument`:idx: given to the ## application. ## @@ -1330,11 +1353,11 @@ elif not defined(createNimRtl): cmdCount {.importc: "cmdCount".}: cint cmdLine {.importc: "cmdLine".}: cstringArray - proc paramStr*(i: int): TaintedString = + proc paramStr*(i: int): TaintedString {.tags: [FReadIO].} = if i < cmdCount and i >= 0: return TaintedString($cmdLine[i]) raise newException(EInvalidIndex, "invalid index") - proc paramCount*(): int = return cmdCount-1 + proc paramCount*(): int {.tags: [FReadIO].} = return cmdCount-1 when defined(linux) or defined(solaris) or defined(bsd) or defined(aix): proc getApplAux(procPath: string): string = @@ -1357,7 +1380,7 @@ when defined(macosx): proc getExecPath2(c: cstring, size: var cuint32): bool {. importc: "_NSGetExecutablePath", header: "<mach-o/dyld.h>".} -proc getAppFilename*(): string {.rtl, extern: "nos$1".} = +proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} = ## Returns the filename of the application's executable. ## **Note**: This does not work reliably on BSD. @@ -1413,12 +1436,12 @@ proc getApplicationDir*(): string {.rtl, extern: "nos$1", deprecated.} = ## instead. result = splitFile(getAppFilename()).dir -proc getAppDir*(): string {.rtl, extern: "nos$1".} = +proc getAppDir*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} = ## Returns the directory of the application's executable. ## **Note**: This does not work reliably on BSD. result = splitFile(getAppFilename()).dir -proc sleep*(milsecs: int) {.rtl, extern: "nos$1".} = +proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [FTime].} = ## sleeps `milsecs` milliseconds. when defined(windows): winlean.sleep(int32(milsecs)) @@ -1428,7 +1451,8 @@ proc sleep*(milsecs: int) {.rtl, extern: "nos$1".} = a.tv_nsec = (milsecs mod 1000) * 1000 discard posix.nanosleep(a, b) -proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1".} = +proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1", + tags: [FReadIO].} = ## returns the file size of `file`. Can raise ``EOS``. when defined(windows): var a: TWin32FindData @@ -1443,7 +1467,7 @@ proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1".} = close(f) else: OSError() -proc findExe*(exe: string): string = +proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} = ## Searches for `exe` in the current working directory and then ## in directories listed in the ``PATH`` environment variable. ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe` diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 46b35cb10..a8c0ea809 100755 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -58,7 +58,7 @@ proc startProcess*(command: string, args: openarray[string] = [], env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut}): - PProcess {.rtl, extern: "nosp$1", tags: [FExecIO].} + PProcess {.rtl, extern: "nosp$1", tags: [FExecIO, FReadEnv].} ## Starts a process. `Command` is the executable file, `workingDir` is the ## process's working directory. If ``workingDir == ""`` the current directory ## is used. `args` are the command line arguments that are passed to the @@ -74,7 +74,8 @@ proc startProcess*(command: string, ## but ``EOS`` is raised in case of an error. proc startCmd*(command: string, options: set[TProcessOption] = { - poStdErrToStdOut, poUseShell}): PProcess {.tags: [FExecIO].} = + poStdErrToStdOut, poUseShell}): PProcess {. + tags: [FExecIO, FReadEnv].} = ## a simpler version of `startProcess` that parses the command line into ## program and arguments and then calls `startProcess` with the empty string ## for `workingDir` and the nil string table for `env`. @@ -159,7 +160,7 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} = proc execProcesses*(cmds: openArray[string], options = {poStdErrToStdOut, poParentStreams}, n = countProcessors()): int {.rtl, extern: "nosp$1", - tags: [FExecIO].} = + tags: [FExecIO, FTime, FReadEnv].} = ## executes the commands `cmds` in parallel. Creates `n` processes ## that execute in parallel. The highest return value of all processes ## is returned. diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 6e0574e85..328f9cb9e 100755 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -242,9 +242,10 @@ when defined(ssl): ## are available with the addition of ``ProtSSLv23`` which allows for ## compatibility with all of them. ## - ## There are currently only two options for verify mode; one is ``CVerifyNone`` - ## and with it certificates will not be verified the other is ``CVerifyPeer`` - ## and certificates will be verified for it, ``CVerifyPeer`` is the safest choice. + ## There are currently only two options for verify mode; + ## one is ``CVerifyNone`` and with it certificates will not be verified + ## the other is ``CVerifyPeer`` and certificates will be verified for + ## it, ``CVerifyPeer`` is the safest choice. ## ## The last two parameters specify the certificate file path and the key file ## path, a server socket will most likely not work without these. @@ -291,7 +292,7 @@ when defined(ssl): if SSLSetFd(socket.sslHandle, socket.fd) != 1: SSLError() -proc listen*(socket: TSocket, backlog = SOMAXCONN) = +proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [FReadIO].} = ## Marks ``socket`` as accepting connections. ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. @@ -335,7 +336,8 @@ template gaiNim(a, p, h, list: expr): stmt = else: OSError($gai_strerror(gaiResult)) -proc bindAddr*(socket: TSocket, port = TPort(0), address = "") = +proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {. + tags: [FReadIO].} = ## binds an address/port number to a socket. ## Use address string in dotted decimal form like "a.b.c.d" ## or leave "" for any address. @@ -390,15 +392,6 @@ proc getSockName*(socket: TSocket): TPort = OSError() result = TPort(sockets.ntohs(name.sin_port)) -proc selectWrite*(writefds: var seq[TSocket], timeout = 500): int - ## When a socket in ``writefds`` is ready to be written to then a non-zero - ## value will be returned specifying the count of the sockets which can be - ## written to. The sockets which can be written to will also be removed - ## from ``writefds``. - ## - ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for - ## an unlimited time. - template acceptAddrPlain(noClientRet, successRet: expr, sslImplementation: stmt): stmt {.immediate.} = assert(client != nil) @@ -439,7 +432,8 @@ template acceptAddrPlain(noClientRet, successRet: expr, else: return successRet -proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) = +proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) {. + tags: [FReadIO].} = ## Blocks until a connection is being made from a client. When a connection ## is made sets ``client`` to the client socket and ``address`` to the address ## of the connecting client. @@ -482,7 +476,8 @@ proc acceptAddr*(server: TSocket, client: var TSocket, address: var string) = proc setBlocking*(s: TSocket, blocking: bool) when defined(ssl): proc acceptAddrSSL*(server: TSocket, client: var TSocket, - address: var string): TSSLAcceptResult = + address: var string): TSSLAcceptResult {. + tags: [FReadIO].} = ## This procedure should only be used for non-blocking **SSL** sockets. ## It will immediately return with one of the following values: ## @@ -531,7 +526,7 @@ when defined(ssl): acceptAddrPlain(AcceptNoClient, AcceptSuccess): doHandshake() -proc accept*(server: TSocket, client: var TSocket) = +proc accept*(server: TSocket, client: var TSocket) {.tags: [FReadIO].} = ## Equivalent to ``acceptAddr`` but doesn't return the address, only the ## socket. ## @@ -541,7 +536,8 @@ proc accept*(server: TSocket, client: var TSocket) = var addrDummy = "" acceptAddr(server, client, addrDummy) -proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {.deprecated.} = +proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {. + deprecated, tags: [FReadIO].} = ## Slightly different version of ``acceptAddr``. ## ## **Deprecated since version 0.9.0:** Please use the function above. @@ -551,7 +547,7 @@ proc acceptAddr*(server: TSocket): tuple[client: TSocket, address: string] {.dep acceptAddr(server, client, address) return (client, address) -proc accept*(server: TSocket): TSocket {.deprecated.} = +proc accept*(server: TSocket): TSocket {.deprecated, tags: [FReadIO].} = ## **Deprecated since version 0.9.0:** Please use the function above. new(result) var address = "" @@ -568,7 +564,7 @@ proc close*(socket: TSocket) = if socket.isSSL: discard SSLShutdown(socket.sslHandle) -proc getServByName*(name, proto: string): TServent = +proc getServByName*(name, proto: string): TServent {.tags: [FReadIO].} = ## well-known getservbyname proc. when defined(Windows): var s = winlean.getservbyname(name, proto) @@ -580,7 +576,7 @@ proc getServByName*(name, proto: string): TServent = result.port = TPort(s.s_port) result.proto = $s.s_proto -proc getServByPort*(port: TPort, proto: string): TServent = +proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} = ## well-known getservbyport proc. when defined(Windows): var s = winlean.getservbyport(ze(int16(port)).cint, proto) @@ -592,7 +588,7 @@ proc getServByPort*(port: TPort, proto: string): TServent = result.port = TPort(s.s_port) result.proto = $s.s_proto -proc getHostByAddr*(ip: string): THostEnt = +proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} = ## This function will lookup the hostname of an IP Address. var myaddr: TInAddr myaddr.s_addr = inet_addr(ip) @@ -621,7 +617,7 @@ proc getHostByAddr*(ip: string): THostEnt = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getHostByName*(name: string): THostEnt = +proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} = ## well-known gethostbyname proc. when defined(Windows): var s = winlean.gethostbyname(name) @@ -642,7 +638,8 @@ proc getHostByName*(name: string): THostEnt = result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getSockOptInt*(socket: TSocket, level, optname: int): int = +proc getSockOptInt*(socket: TSocket, level, optname: int): int {. + tags: [FReadIO].} = ## getsockopt for integer options. var res: cint var size = sizeof(res).TSockLen @@ -651,7 +648,8 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int = OSError() result = int(res) -proc setSockOptInt*(socket: TSocket, level, optname, optval: int) = +proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {. + tags: [FWriteIO].} = ## setsockopt for integer options. var value = cint(optval) if setsockopt(socket.fd, cint(level), cint(optname), addr(value), @@ -659,7 +657,7 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) = OSError() proc connect*(socket: TSocket, name: string, port = TPort(0), - af: TDomain = AF_INET) = + af: TDomain = AF_INET) {.tags: [FReadIO].} = ## Connects socket to ``name``:``port``. ``Name`` can be an IP address or a ## host name. If ``name`` is a host name, this function will try each IP ## of that host name. ``htons`` is already performed on ``port`` so you must @@ -719,7 +717,7 @@ proc connect*(socket: TSocket, name: string, port = TPort(0), OSError() proc connectAsync*(socket: TSocket, name: string, port = TPort(0), - af: TDomain = AF_INET) = + af: TDomain = AF_INET) {.tags: [FReadIO].} = ## A variant of ``connect`` for non-blocking sockets. ## ## This procedure will immediatelly return, it will not block until a connection @@ -764,7 +762,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), socket.sslNoHandshake = true when defined(ssl): - proc handshake*(socket: TSocket): bool = + proc handshake*(socket: TSocket): bool {.tags: [FReadIO, RWriteIO].} = ## This proc needs to be called on a socket after it connects. This is ## only applicable when using ``connectAsync``. ## This proc performs the SSL handshake. @@ -854,7 +852,7 @@ proc checkBuffer(readfds: var seq[TSocket]): int = readfds = res proc select*(readfds, writefds, exceptfds: var seq[TSocket], - timeout = 500): int = + timeout = 500): int {.tags: [FReadIO].} = ## Traditional select function. This function will return the number of ## sockets that are ready to be read from, written to, or which have errors ## if there are none; 0 is returned. @@ -884,7 +882,7 @@ proc select*(readfds, writefds, exceptfds: var seq[TSocket], pruneSocketSet(exceptfds, (ex)) proc select*(readfds, writefds: var seq[TSocket], - timeout = 500): int = + timeout = 500): int {.tags: [FReadIO].} = ## variant of select with only a read and write list. let buffersFilled = checkBuffer(readfds) if buffersFilled > 0: @@ -905,7 +903,14 @@ proc select*(readfds, writefds: var seq[TSocket], pruneSocketSet(writefds, (wr)) proc selectWrite*(writefds: var seq[TSocket], - timeout = 500): int = + timeout = 500): int {.tags: [FReadIO].} = + ## When a socket in ``writefds`` is ready to be written to then a non-zero + ## value will be returned specifying the count of the sockets which can be + ## written to. The sockets which can be written to will also be removed + ## from ``writefds``. + ## + ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for + ## an unlimited time. var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) var wr: TFdSet @@ -961,7 +966,7 @@ template retRead(flags, readBytes: int) = else: return res -proc recv*(socket: TSocket, data: pointer, size: int): int = +proc recv*(socket: TSocket, data: pointer, size: int): int {.tags: [FReadIO].} = ## receives data from a socket if socket.isBuffered: if socket.bufLen == 0: @@ -999,7 +1004,8 @@ proc recv*(socket: TSocket, data: pointer, size: int): int = else: result = recv(socket.fd, data, size.cint, 0'i32) -proc waitFor(socket: TSocket, waited: var float, timeout: int): int = +proc waitFor(socket: TSocket, waited: var float, timeout: int): int {. + tags: [FTime].} = ## returns the number of characters available to be read. In unbuffered ## sockets this is always 1, otherwise this may as big as the buffer, currently ## 4000. @@ -1015,7 +1021,8 @@ proc waitFor(socket: TSocket, waited: var float, timeout: int): int = raise newException(ETimeout, "Call to recv() timed out.") waited += (epochTime() - startTime) -proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int = +proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int {. + tags: [FReadIO, FTime].} = ## overload with a ``timeout`` parameter in miliseconds. var waited = 0.0 # number of seconds already waited @@ -1031,7 +1038,7 @@ proc recv*(socket: TSocket, data: pointer, size: int, timeout: int): int = result = read -proc peekChar(socket: TSocket, c: var char): int = +proc peekChar(socket: TSocket, c: var char): int {.tags: [FReadIO].} = if socket.isBuffered: result = 1 if socket.bufLen == 0 or socket.currPos > socket.bufLen-1: @@ -1047,7 +1054,8 @@ proc peekChar(socket: TSocket, c: var char): int = result = recv(socket.fd, addr(c), 1, MSG_PEEK) -proc recvLine*(socket: TSocket, line: var TaintedString): bool = +proc recvLine*(socket: TSocket, line: var TaintedString): bool {. + tags: [FReadIO].} = ## retrieves a line from ``socket``. If a full line is received ``\r\L`` is not ## added to ``line``, however if solely ``\r\L`` is received then ``line`` ## will be set to it. @@ -1082,7 +1090,8 @@ proc recvLine*(socket: TSocket, line: var TaintedString): bool = return true add(line.string, c) -proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool = +proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool {. + tags: [FReadIO, FTime].} = ## variant with a ``timeout`` parameter, the timeout parameter specifies ## how many miliseconds to wait for data. template addNLIfEmpty(): stmt = @@ -1111,7 +1120,8 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout: int): bool = return true add(line.string, c) -proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult = +proc recvLineAsync*(socket: TSocket, + line: var TaintedString): TRecvLineResult {.tags: [FReadIO].} = ## similar to ``recvLine`` but for non-blocking sockets. ## The values of the returned enum should be pretty self explanatory: ## If a full line has been retrieved; ``RecvFullLine`` is returned. @@ -1136,7 +1146,7 @@ proc recvLineAsync*(socket: TSocket, line: var TaintedString): TRecvLineResult = elif c == '\L': return RecvFullLine add(line.string, c) -proc recv*(socket: TSocket): TaintedString = +proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO].} = ## receives all the available data from the socket. ## Socket errors will result in an ``EOS`` error. ## If socket is not a connectionless socket and socket is not connected @@ -1165,7 +1175,8 @@ proc recv*(socket: TSocket): TaintedString = add(result.string, buf) if bytesRead != bufSize-1: break -proc recvTimeout*(socket: TSocket, timeout: int): TaintedString = +proc recvTimeout*(socket: TSocket, timeout: int): TaintedString {. + tags: [FReadIO].} = ## overloaded variant to support a ``timeout`` parameter, the ``timeout`` ## parameter specifies the amount of miliseconds to wait for data on the ## socket. @@ -1176,7 +1187,8 @@ proc recvTimeout*(socket: TSocket, timeout: int): TaintedString = return socket.recv -proc recvAsync*(socket: TSocket, s: var TaintedString): bool = +proc recvAsync*(socket: TSocket, s: var TaintedString): bool {. + tags: [FReadIO].} = ## receives all the data from a non-blocking socket. If socket is non-blocking ## and there are no messages available, `False` will be returned. ## Other socket errors will result in an ``EOS`` error. @@ -1226,7 +1238,8 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool = result = True proc recvFrom*(socket: TSocket, data: var string, length: int, - address: var string, port: var TPort, flags = 0'i32): int = + address: var string, port: var TPort, flags = 0'i32): int {. + tags: [FReadIO].} = ## Receives data from ``socket``. This function should normally be used with ## connection-less sockets (UDP sockets). ## @@ -1248,7 +1261,8 @@ proc recvFrom*(socket: TSocket, data: var string, length: int, port = ntohs(sockAddress.sin_port).TPort proc recvFromAsync*(socket: TSocket, data: var String, length: int, - address: var string, port: var TPort, flags = 0'i32): bool = + address: var string, port: var TPort, + flags = 0'i32): bool {.tags: [FReadIO].} = ## Similar to ``recvFrom`` but raises an EOS error when an error occurs and ## is also meant for non-blocking sockets. ## Returns False if no messages could be received from ``socket``. @@ -1266,14 +1280,15 @@ proc recvFromAsync*(socket: TSocket, data: var String, length: int, return False else: OSError() -proc skip*(socket: TSocket) = +proc skip*(socket: TSocket) {.tags: [FReadIO].} = ## skips all the data that is pending for the socket const bufSize = 1000 var buf = alloc(bufSize) while recv(socket, buf, bufSize) == bufSize: nil dealloc(buf) -proc send*(socket: TSocket, data: pointer, size: int): int = +proc send*(socket: TSocket, data: pointer, size: int): int {. + tags: [FWriteIO].} = ## sends data to a socket. when defined(ssl): if socket.isSSL: @@ -1284,7 +1299,7 @@ proc send*(socket: TSocket, data: pointer, size: int): int = else: result = send(socket.fd, data, size, int32(MSG_NOSIGNAL)) -proc send*(socket: TSocket, data: string) = +proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} = ## sends data to a socket. if send(socket, cstring(data), data.len) != data.len: when defined(ssl): @@ -1293,7 +1308,7 @@ proc send*(socket: TSocket, data: string) = OSError() -proc sendAsync*(socket: TSocket, data: string): bool = +proc sendAsync*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} = ## sends data to a non-blocking socket. Returns whether ``data`` was sent. result = true var bytesSent = send(socket, cstring(data), data.len) @@ -1327,13 +1342,14 @@ proc sendAsync*(socket: TSocket, data: string): bool = return false else: OSError() -proc trySend*(socket: TSocket, data: string): bool = +proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} = ## safe alternative to ``send``. Does not raise an EOS when an error occurs, ## and instead returns ``false`` on failure. result = send(socket, cstring(data), data.len) == data.len proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer, - size: int, af: TDomain = AF_INET, flags = 0'i32): int = + size: int, af: TDomain = AF_INET, flags = 0'i32): int {. + tags: [FWriteIO].} = ## low-level sendTo proc. This proc sends ``data`` to the specified ``address``, ## which may be an IP address or a hostname, if a hostname is specified ## this function will try each IP of that hostname. @@ -1359,7 +1375,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer, freeaddrinfo(aiList) -proc sendTo*(socket: TSocket, address: string, port: TPort, data: string): int = +proc sendTo*(socket: TSocket, address: string, port: TPort, + data: string): int {.tags: [FWriteIO].} = ## Friendlier version of the low-level ``sendTo``. result = socket.sendTo(address, port, cstring(data), data.len) @@ -1391,7 +1408,7 @@ proc setBlocking*(s: TSocket, blocking: bool) = OSError() proc connect*(socket: TSocket, timeout: int, name: string, port = TPort(0), - af: TDomain = AF_INET) = + af: TDomain = AF_INET) {.tags: [FReadIO].} = ## Overload for ``connect`` to support timeouts. The ``timeout`` parameter ## specifies the time in miliseconds of how long to wait for a connection ## to be made. diff --git a/lib/pure/times.nim b/lib/pure/times.nim index 8e2d10a98..b0ce2454c 100755 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -131,7 +131,7 @@ type months*: int ## The number of months years*: int ## The number of years -proc getTime*(): TTime ## gets the current calendar time +proc getTime*(): TTime {.tags: [FTime].} ## gets the current calendar time proc getLocalTime*(t: TTime): TTimeInfo ## converts the calendar time `t` to broken-time representation, ## expressed relative to the user's specified time zone. @@ -164,14 +164,14 @@ proc `<=` * (a, b: TTime): bool {. ## returns true iff ``a <= b``. result = a - b <= 0 -proc getTzname*(): tuple[nonDST, DST: string] +proc getTzname*(): tuple[nonDST, DST: string] {.tags: [FTime].} ## returns the local timezone; ``nonDST`` is the name of the local non-DST ## timezone, ``DST`` is the name of the local DST timezone. -proc getTimezone*(): int +proc getTimezone*(): int {.tags: [FTime].} ## returns the offset of the local (non-DST) timezone in seconds west of UTC. -proc getStartMilsecs*(): int {.deprecated.} +proc getStartMilsecs*(): int {.deprecated, tags: [FTime].} ## get the miliseconds from the start of the program. **Deprecated since ## version 0.8.10.** Use ``epochTime`` or ``cpuTime`` instead. @@ -247,12 +247,12 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = result = getLocalTime(TTime(float(t) - secs)) when not defined(ECMAScript): - proc epochTime*(): float {.rtl, extern: "nt$1".} + proc epochTime*(): float {.rtl, extern: "nt$1", tags: [FTime].} ## gets time after the UNIX epoch (1970) in seconds. It is a float ## because sub-second resolution is likely to be supported (depending ## on the hardware/OS). - proc cpuTime*(): float {.rtl, extern: "nt$1".} + proc cpuTime*(): float {.rtl, extern: "nt$1", tags: [FTime].} ## gets time spent that the CPU spent to run the current process in ## seconds. This may be more useful for benchmarking than ``epochTime``. ## However, it may measure the real time instead (depending on the OS). @@ -478,13 +478,13 @@ else: return int(getTime() - startMilsecs) -proc getDateStr*(): string {.rtl, extern: "nt$1".} = +proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} = ## gets the current date as a string of the format ``YYYY-MM-DD``. var ti = getLocalTime(getTime()) result = $ti.year & '-' & intToStr(ord(ti.month)+1, 2) & '-' & intToStr(ti.monthDay, 2) -proc getClockStr*(): string {.rtl, extern: "nt$1".} = +proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} = ## gets the current clock time as a string of the format ``HH:MM:SS``. var ti = getLocalTime(getTime()) result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) & |