renamed optional to discardable

This commit is contained in:
Araq 2011-09-24 19:18:08 +02:00
commit 485c371942
15 changed files with 72 additions and 63 deletions

View file

@ -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:
##

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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: