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