renamed optional to discardable
This commit is contained in:
parent
72ceda98cb
commit
485c371942
15 changed files with 72 additions and 63 deletions
|
|
@ -30,7 +30,7 @@ type
|
|||
pos: int
|
||||
inShortState: bool
|
||||
kind*: TCmdLineKind ## the dected command line token
|
||||
key*, val*: string ## key and value pair; ``key`` is the option
|
||||
key*, val*: TaintedString ## key and value pair; ``key`` is the option
|
||||
## or the argument, ``value`` is not "" if
|
||||
## the option was given a value
|
||||
|
||||
|
|
@ -50,8 +50,8 @@ when defined(os.ParamCount):
|
|||
for i in countup(1, ParamCount()):
|
||||
result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' '
|
||||
result.kind = cmdEnd
|
||||
result.key = ""
|
||||
result.val = ""
|
||||
result.key = TaintedString""
|
||||
result.val = TaintedString""
|
||||
|
||||
proc parseWord(s: string, i: int, w: var string,
|
||||
delim: TCharSet = {'\x09', ' ', '\0'}): int =
|
||||
|
|
@ -70,7 +70,7 @@ proc parseWord(s: string, i: int, w: var string,
|
|||
proc handleShortOption(p: var TOptParser) =
|
||||
var i = p.pos
|
||||
p.kind = cmdShortOption
|
||||
add(p.key, p.cmd[i])
|
||||
add(p.key.string, p.cmd[i])
|
||||
inc(i)
|
||||
p.inShortState = true
|
||||
while p.cmd[i] in {'\x09', ' '}:
|
||||
|
|
@ -80,7 +80,7 @@ proc handleShortOption(p: var TOptParser) =
|
|||
inc(i)
|
||||
p.inShortState = false
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
i = parseWord(p.cmd, i, p.val)
|
||||
i = parseWord(p.cmd, i, p.val.string)
|
||||
if p.cmd[i] == '\0': p.inShortState = false
|
||||
p.pos = i
|
||||
|
||||
|
|
@ -91,8 +91,8 @@ proc next*(p: var TOptParser) {.
|
|||
var i = p.pos
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
p.pos = i
|
||||
setlen(p.key, 0)
|
||||
setlen(p.val, 0)
|
||||
setlen(p.key.string, 0)
|
||||
setlen(p.val.string, 0)
|
||||
if p.inShortState:
|
||||
handleShortOption(p)
|
||||
return
|
||||
|
|
@ -104,29 +104,29 @@ proc next*(p: var TOptParser) {.
|
|||
if p.cmd[i] == '-':
|
||||
p.kind = cmdLongOption
|
||||
inc(i)
|
||||
i = parseWord(p.cmd, i, p.key, {'\0', ' ', '\x09', ':', '='})
|
||||
i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='})
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
if p.cmd[i] in {':', '='}:
|
||||
inc(i)
|
||||
while p.cmd[i] in {'\x09', ' '}: inc(i)
|
||||
p.pos = parseWord(p.cmd, i, p.val)
|
||||
p.pos = parseWord(p.cmd, i, p.val.string)
|
||||
else:
|
||||
p.pos = i
|
||||
else:
|
||||
p.pos = i
|
||||
handleShortOption(p)
|
||||
else:
|
||||
else:
|
||||
p.kind = cmdArgument
|
||||
p.pos = parseWord(p.cmd, i, p.key)
|
||||
p.pos = parseWord(p.cmd, i, p.key.string)
|
||||
|
||||
proc cmdLineRest*(p: TOptParser): string {.
|
||||
proc cmdLineRest*(p: TOptParser): TaintedString {.
|
||||
rtl, extern: "npo$1".} =
|
||||
## retrieves the rest of the command line that has not been parsed yet.
|
||||
result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1))
|
||||
result = strip(substr(p.cmd, p.pos, len(p.cmd) - 1)).TaintedString
|
||||
|
||||
when defined(initOptParser):
|
||||
|
||||
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: string] =
|
||||
iterator getopt*(): tuple[kind: TCmdLineKind, key, val: TaintedString] =
|
||||
## This is an convenience iterator for iterating over the command line.
|
||||
## This uses the TOptParser object. Example:
|
||||
##
|
||||
|
|
|
|||
|
|
@ -525,11 +525,11 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int =
|
|||
pruneSocketSet(readfds, (rd))
|
||||
|
||||
|
||||
proc recvLine*(socket: TSocket, line: var string): bool =
|
||||
proc recvLine*(socket: TSocket, line: var TaintedString): bool =
|
||||
## returns false if no further data is available. `Line` must be initialized
|
||||
## and not nil! This does not throw an EOS exception, therefore
|
||||
## it can be used in both blocking and non-blocking sockets.
|
||||
setLen(line, 0)
|
||||
setLen(line.string, 0)
|
||||
while true:
|
||||
var c: char
|
||||
var n = recv(cint(socket), addr(c), 1, 0'i32)
|
||||
|
|
@ -541,20 +541,20 @@ proc recvLine*(socket: TSocket, line: var string): bool =
|
|||
elif n <= 0: return false
|
||||
return true
|
||||
elif c == '\L': return true
|
||||
add(line, c)
|
||||
add(line.string, c)
|
||||
|
||||
proc recv*(socket: TSocket, data: pointer, size: int): int =
|
||||
## receives data from a socket
|
||||
result = recv(cint(socket), data, size, 0'i32)
|
||||
|
||||
proc recv*(socket: TSocket): string =
|
||||
proc recv*(socket: TSocket): TaintedString =
|
||||
## receives all the data from the socket.
|
||||
## Socket errors will result in an ``EOS`` error.
|
||||
## If socket is not a connectionless socket and socket is not connected
|
||||
## ``""`` will be returned.
|
||||
const bufSize = 200
|
||||
const bufSize = 1000
|
||||
var buf = newString(bufSize)
|
||||
result = ""
|
||||
result = TaintedString""
|
||||
while true:
|
||||
var bytesRead = recv(socket, cstring(buf), bufSize-1)
|
||||
# Error
|
||||
|
|
@ -562,16 +562,16 @@ proc recv*(socket: TSocket): string =
|
|||
|
||||
buf[bytesRead] = '\0' # might not be necessary
|
||||
setLen(buf, bytesRead)
|
||||
add(result, buf)
|
||||
add(result.string, buf)
|
||||
if bytesRead != bufSize-1: break
|
||||
|
||||
proc recvAsync*(socket: TSocket, s: var string): bool =
|
||||
proc recvAsync*(socket: TSocket, s: var TaintedString): bool =
|
||||
## 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.
|
||||
## If socket is not a connectionless socket and socket is not connected
|
||||
## ``s`` will be set to ``""``.
|
||||
const bufSize = 200
|
||||
const bufSize = 1000
|
||||
var buf = newString(bufSize)
|
||||
s = ""
|
||||
while true:
|
||||
|
|
@ -597,7 +597,7 @@ proc recvAsync*(socket: TSocket, s: var string): bool =
|
|||
|
||||
proc skip*(socket: TSocket) =
|
||||
## skips all the data that is pending for the socket
|
||||
const bufSize = 200
|
||||
const bufSize = 1000
|
||||
var buf = alloc(bufSize)
|
||||
while recv(socket, buf, bufSize) == bufSize: nil
|
||||
dealloc(buf)
|
||||
|
|
|
|||
|
|
@ -80,24 +80,24 @@ proc readFloat64*(s: PStream): float64 =
|
|||
## reads a float64 from the stream `s`. Raises `EIO` if an error occured.
|
||||
read(s, result)
|
||||
|
||||
proc readStr*(s: PStream, length: int): string =
|
||||
proc readStr*(s: PStream, length: int): TaintedString =
|
||||
## reads a string of length `length` from the stream `s`. Raises `EIO` if
|
||||
## an error occured.
|
||||
result = newString(length)
|
||||
var L = s.readData(s, addr(result[0]), length)
|
||||
if L != length: setLen(result, L)
|
||||
result = newString(length).TaintedString
|
||||
var L = s.readData(s, addr(string(result)[0]), length)
|
||||
if L != length: setLen(result.string, L)
|
||||
|
||||
proc readLine*(s: PStream): string =
|
||||
proc readLine*(s: PStream): TaintedString =
|
||||
## Reads a line from a stream `s`. Note: This is not very efficient. Raises
|
||||
## `EIO` if an error occured.
|
||||
result = ""
|
||||
result = TaintedString""
|
||||
while not s.atEnd(s):
|
||||
var c = readChar(s)
|
||||
if c == '\c':
|
||||
c = readChar(s)
|
||||
break
|
||||
elif c == '\L' or c == '\0': break
|
||||
result.add(c)
|
||||
result.string.add(c)
|
||||
|
||||
type
|
||||
PStringStream* = ref TStringStream ## a stream that encapsulates a string
|
||||
|
|
|
|||
|
|
@ -136,7 +136,8 @@ proc RaiseFormatException(s: string) =
|
|||
|
||||
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
|
||||
if hasKey(t, key): return t[key]
|
||||
if useEnvironment in flags: result = os.getEnv(key)
|
||||
# hm difficult: assume safety in taint mode here. XXX This is dangerous!
|
||||
if useEnvironment in flags: result = os.getEnv(key).string
|
||||
else: result = ""
|
||||
if result.len == 0:
|
||||
if useKey in flags: result = '$' & key
|
||||
|
|
|
|||
|
|
@ -787,9 +787,9 @@ proc compileOption*(option, arg: string): bool {.
|
|||
const
|
||||
hasThreadSupport = compileOption("threads")
|
||||
hasSharedHeap = defined(boehmgc) # don't share heaps; every thread has its own
|
||||
# taintMode = compileOption("taintmode")
|
||||
taintMode = compileOption("taintmode")
|
||||
|
||||
when defined(taintMode):
|
||||
when taintMode:
|
||||
# XXX use a compile time option for it!
|
||||
type TaintedString* = distinct string ## a distinct string type that
|
||||
## is `tainted`:idx:. It is an alias for
|
||||
|
|
|
|||
|
|
@ -56,8 +56,12 @@ proc rawReadLine(f: TFile, result: var string) =
|
|||
add result, chr(int(c))
|
||||
|
||||
proc readLine(f: TFile): TaintedString =
|
||||
result = TaintedString("")
|
||||
rawReadLine(f, result)
|
||||
when taintMode:
|
||||
result = TaintedString""
|
||||
rawReadLine(f, result.string)
|
||||
else:
|
||||
result = ""
|
||||
rawReadLine(f, result)
|
||||
|
||||
proc write(f: TFile, i: int) =
|
||||
when sizeof(int) == 8:
|
||||
|
|
@ -86,9 +90,14 @@ proc readFile(filename: string): TaintedString =
|
|||
try:
|
||||
var len = getFileSize(f)
|
||||
if len < high(int):
|
||||
result = newString(int(len))
|
||||
if readBuffer(f, addr(result[0]), int(len)) != len:
|
||||
raiseEIO("error while reading from file")
|
||||
when taintMode:
|
||||
result = newString(int(len)).TaintedString
|
||||
if readBuffer(f, addr(string(result)[0]), int(len)) != len:
|
||||
raiseEIO("error while reading from file")
|
||||
else:
|
||||
result = newString(int(len))
|
||||
if readBuffer(f, addr(result[0]), int(len)) != len:
|
||||
raiseEIO("error while reading from file")
|
||||
else:
|
||||
raiseEIO("file too big to fit in memory")
|
||||
finally:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue