even more strict isNil handling for strings/seqs in order to detect bugs

This commit is contained in:
Araq
2018-08-22 12:35:46 +02:00
parent 9047c3f582
commit 64517445ea
36 changed files with 193 additions and 245 deletions

View File

@@ -1387,7 +1387,7 @@ proc parseSectionWrapper(p: var RstParser): PRstNode =
result = result.sons[0]
proc `$`(t: Token): string =
result = $t.kind & ' ' & (if isNil(t.symbol): "NIL" else: t.symbol)
result = $t.kind & ' ' & t.symbol
proc parseDoc(p: var RstParser): PRstNode =
result = parseSectionWrapper(p)

View File

@@ -243,7 +243,7 @@ proc dispA(target: OutputTarget, dest: var string,
else: addf(dest, tex, args)
proc `or`(x, y: string): string {.inline.} =
result = if x.isNil: y else: x
result = if x.len == 0: y else: x
proc renderRstToOut*(d: var RstGenerator, n: PRstNode, result: var string)
## Writes into ``result`` the rst ast ``n`` using the ``d`` configuration.
@@ -387,20 +387,16 @@ proc hash(x: IndexEntry): Hash =
## Returns the hash for the combined fields of the type.
##
## The hash is computed as the chained hash of the individual string hashes.
assert(not x.keyword.isNil)
assert(not x.link.isNil)
result = x.keyword.hash !& x.link.hash
result = result !& (x.linkTitle or "").hash
result = result !& (x.linkDesc or "").hash
result = result !& x.linkTitle.hash
result = result !& x.linkDesc.hash
result = !$result
proc `<-`(a: var IndexEntry, b: IndexEntry) =
shallowCopy a.keyword, b.keyword
shallowCopy a.link, b.link
if b.linkTitle.isNil: a.linkTitle = ""
else: shallowCopy a.linkTitle, b.linkTitle
if b.linkDesc.isNil: a.linkDesc = ""
else: shallowCopy a.linkDesc, b.linkDesc
shallowCopy a.linkTitle, b.linkTitle
shallowCopy a.linkDesc, b.linkDesc
proc sortIndex(a: var openArray[IndexEntry]) =
# we use shellsort here; fast and simple
@@ -444,8 +440,8 @@ proc generateSymbolIndex(symbols: seq[IndexEntry]): string =
while j < symbols.len and keyword == symbols[j].keyword:
let
url = symbols[j].link.escapeLink
text = if not symbols[j].linkTitle.isNil: symbols[j].linkTitle else: url
desc = if not symbols[j].linkDesc.isNil: symbols[j].linkDesc else: ""
text = if symbols[j].linkTitle.len > 0: symbols[j].linkTitle else: url
desc = if symbols[j].linkDesc.len > 0: symbols[j].linkDesc else: ""
if desc.len > 0:
result.addf("""<li><a class="reference external"
title="$3" data-doc-search-tag="$2" href="$1">$2</a></li>
@@ -528,8 +524,6 @@ proc generateDocumentationTOC(entries: seq[IndexEntry]): string =
""", [titleTag & " : " & levels[L].text, link, levels[L].text])
inc L
result.add(level.indentToLevel(1) & "</ul>\n")
assert(not titleRef.isNil,
"Can't use this proc on an API index, docs always have a title entry")
proc generateDocumentationIndex(docs: IndexedDocs): string =
## Returns all the documentation TOCs in an HTML hierarchical list.
@@ -596,7 +590,7 @@ proc readIndexDir(dir: string):
fileEntries[F].keyword = line.substr(0, s-1)
fileEntries[F].link = line.substr(s+1)
# See if we detect a title, a link without a `#foobar` trailing part.
if title.keyword.isNil and fileEntries[F].link.isDocumentationTitle:
if title.keyword.len == 0 and fileEntries[F].link.isDocumentationTitle:
title.keyword = fileEntries[F].keyword
title.link = fileEntries[F].link
@@ -611,11 +605,11 @@ proc readIndexDir(dir: string):
fileEntries[F].linkDesc = ""
inc F
# Depending on type add this to the list of symbols or table of APIs.
if title.keyword.isNil:
if title.keyword.len == 0:
for i in 0 .. <F:
# Don't add to symbols TOC entries (they start with a whitespace).
let toc = fileEntries[i].linkTitle
if not toc.isNil and toc.len > 0 and toc[0] == ' ':
if toc.len > 0 and toc[0] == ' ':
continue
# Ok, non TOC entry, add it.
setLen(result.symbols, L + 1)

View File

@@ -135,10 +135,9 @@ iterator decodeData*(allowedMethods: set[RequestMethod] =
## Reads and decodes CGI data and yields the (name, value) pairs the
## data consists of. If the client does not use a method listed in the
## `allowedMethods` set, an `ECgi` exception is raised.
var data = getEncodedData(allowedMethods)
if not isNil(data):
for key, value in decodeData(data):
yield (key, value)
let data = getEncodedData(allowedMethods)
for key, value in decodeData(data):
yield (key, value)
proc readData*(allowedMethods: set[RequestMethod] =
{methodNone, methodPost, methodGet}): StringTableRef =

View File

@@ -74,7 +74,7 @@ proc isValid*[A](s: HashSet[A]): bool =
## proc savePreferences(options: HashSet[string]) =
## assert options.isValid, "Pass an initialized set!"
## # Do stuff here, may crash in release builds!
result = not s.data.isNil
result = s.data.len > 0
proc len*[A](s: HashSet[A]): int =
## Returns the number of keys in `s`.

View File

@@ -185,7 +185,7 @@ proc body*(response: Response): string =
## Retrieves the specified response's body.
##
## The response's body stream is read synchronously.
if response.body.isNil():
if response.body.len == 0:
response.body = response.bodyStream.readAll()
return response.body
@@ -198,7 +198,7 @@ proc `body=`*(response: Response, value: string) {.deprecated.} =
proc body*(response: AsyncResponse): Future[string] {.async.} =
## Reads the response's body and caches it. The read is performed only
## once.
if response.body.isNil:
if response.body.len == 0:
response.body = await readAll(response.bodyStream)
return response.body

View File

@@ -256,7 +256,6 @@ proc add*(obj: JsonNode, key: string, val: JsonNode) =
proc `%`*(s: string): JsonNode =
## Generic constructor for JSON data. Creates a new `JString JsonNode`.
new(result)
if s.isNil: return
result.kind = JString
result.str = s

View File

@@ -103,14 +103,9 @@ var
proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): string =
## Format a log message using the ``frmt`` format string, ``level`` and varargs.
## See the module documentation for the format string syntax.
const nilString = "nil"
var msgLen = 0
for arg in args:
if arg.isNil:
msgLen += nilString.len
else:
msgLen += arg.len
msgLen += arg.len
result = newStringOfCap(frmt.len + msgLen + 20)
var i = 0
while i < frmt.len:
@@ -137,10 +132,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
of "levelname": result.add(LevelNames[level])
else: discard
for arg in args:
if arg.isNil:
result.add(nilString)
else:
result.add(arg)
result.add(arg)
method log*(logger: Logger, level: Level, args: varargs[string, `$`]) {.
raises: [Exception], gcsafe,
@@ -338,7 +330,6 @@ template fatal*(args: varargs[string, `$`]) =
proc addHandler*(handler: Logger) =
## Adds ``handler`` to the list of handlers.
if handlers.isNil: handlers = @[]
handlers.add(handler)
proc getHandlers*(): seq[Logger] =

View File

@@ -98,8 +98,7 @@ proc storeAny(s: Stream, a: Any, stored: var IntSet) =
of akProc, akPointer, akCString: s.write($a.getPointer.ptrToInt)
of akString:
var x = getString(a)
if isNil(x): s.write("null")
elif x.validateUtf8() == -1: s.write(escapeJson(x))
if x.validateUtf8() == -1: s.write(escapeJson(x))
else:
s.write("[")
var i = 0

View File

@@ -233,7 +233,7 @@ proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} =
## modification time is later than `b`'s.
when defined(posix):
# If we don't have access to nanosecond resolution, use '>='
when not StatHasNanoseconds:
when not StatHasNanoseconds:
result = getLastModificationTime(a) >= getLastModificationTime(b)
else:
result = getLastModificationTime(a) > getLastModificationTime(b)
@@ -1343,16 +1343,21 @@ elif defined(windows):
# is always the same -- independent of the used C compiler.
var
ownArgv {.threadvar.}: seq[string]
ownParsedArgv {.threadvar.}: bool
proc paramCount*(): int {.rtl, extern: "nos$1", tags: [ReadIOEffect].} =
# Docstring in nimdoc block.
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
if not ownParsedArgv:
ownArgv = parseCmdLine($getCommandLine())
ownParsedArgv = true
result = ownArgv.len-1
proc paramStr*(i: int): TaintedString {.rtl, extern: "nos$1",
tags: [ReadIOEffect].} =
# Docstring in nimdoc block.
if isNil(ownArgv): ownArgv = parseCmdLine($getCommandLine())
if not ownParsedArgv:
ownArgv = parseCmdLine($getCommandLine())
ownParsedArgv = true
if i < ownArgv.len and i >= 0: return TaintedString(ownArgv[i])
raise newException(IndexError, "invalid index")

View File

@@ -593,7 +593,6 @@ proc len*(n: SqlNode): int =
proc `[]`*(n: SqlNode; i: int): SqlNode = n.sons[i]
proc add*(father, n: SqlNode) =
if isNil(father.sons): father.sons = @[]
add(father.sons, n)
proc getTok(p: var SqlParser) =

View File

@@ -61,7 +61,6 @@ proc unidecode*(s: string): string =
##
## Results in: "Bei Jing"
##
assert(not isNil(translationTable))
result = ""
for r in runes(s):
var c = int(r)

View File

@@ -172,34 +172,30 @@ proc documentElement*(doc: PDocument): PElement =
proc findNodes(nl: PNode, name: string): seq[PNode] =
# Made for getElementsByTagName
var r: seq[PNode] = @[]
if isNil(nl.childNodes): return @[]
if nl.childNodes.len() == 0: return @[]
if nl.childNodes.len == 0: return @[]
for i in items(nl.childNodes):
if i.fNodeType == ElementNode:
if i.fNodeName == name or name == "*":
r.add(i)
if not isNil(i.childNodes):
if i.childNodes.len() != 0:
r.add(findNodes(i, name))
if i.childNodes.len() != 0:
r.add(findNodes(i, name))
return r
proc findNodesNS(nl: PNode, namespaceURI: string, localName: string): seq[PNode] =
# Made for getElementsByTagNameNS
var r: seq[PNode] = @[]
if isNil(nl.childNodes): return @[]
if nl.childNodes.len() == 0: return @[]
if nl.childNodes.len == 0: return @[]
for i in items(nl.childNodes):
if i.fNodeType == ElementNode:
if (i.fNamespaceURI == namespaceURI or namespaceURI == "*") and (i.fLocalName == localName or localName == "*"):
r.add(i)
if not isNil(i.childNodes):
if i.childNodes.len() != 0:
r.add(findNodesNS(i, namespaceURI, localName))
if i.childNodes.len != 0:
r.add(findNodesNS(i, namespaceURI, localName))
return r
@@ -233,8 +229,8 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
# Exceptions
if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI):
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
if namespaceURI.len == 0:
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames:
@@ -312,8 +308,8 @@ proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: strin
## Creates an element of the given qualified name and namespace URI.
if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI):
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
if namespaceURI.len == 0:
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be empty")
elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames:
@@ -453,7 +449,7 @@ proc importNode*(doc: PDocument, importedNode: PNode, deep: bool): PNode =
proc firstChild*(n: PNode): PNode =
## Returns this node's first child
if not isNil(n.childNodes) and n.childNodes.len() > 0:
if n.childNodes.len > 0:
return n.childNodes[0]
else:
return nil
@@ -461,8 +457,8 @@ proc firstChild*(n: PNode): PNode =
proc lastChild*(n: PNode): PNode =
## Returns this node's last child
if not isNil(n.childNodes) and n.childNodes.len() > 0:
return n.childNodes[n.childNodes.len() - 1]
if n.childNodes.len > 0:
return n.childNodes[n.childNodes.len - 1]
else:
return nil
@@ -482,7 +478,7 @@ proc `namespaceURI=`*(n: PNode, value: string) =
proc nextSibling*(n: PNode): PNode =
## Returns the next sibling of this node
if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes):
if isNil(n.fParentNode):
return nil
var nLow: int = low(n.fParentNode.childNodes)
var nHigh: int = high(n.fParentNode.childNodes)
@@ -514,7 +510,7 @@ proc parentNode*(n: PNode): PNode =
proc previousSibling*(n: PNode): PNode =
## Returns the previous sibling of this node
if isNil(n.fParentNode) or isNil(n.fParentNode.childNodes):
if isNil(n.fParentNode):
return nil
var nLow: int = low(n.fParentNode.childNodes)
var nHigh: int = high(n.fParentNode.childNodes)
@@ -531,8 +527,8 @@ proc `prefix=`*(n: PNode, value: string) =
if illegalChars in value:
raise newException(EInvalidCharacterErr, "Invalid character")
if isNil(n.fNamespaceURI):
raise newException(ENamespaceErr, "namespaceURI cannot be nil")
if n.fNamespaceURI.len == 0:
raise newException(ENamespaceErr, "namespaceURI cannot be empty")
elif value.toLowerAscii() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace":
raise newException(ENamespaceErr,
"When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
@@ -557,10 +553,9 @@ proc appendChild*(n: PNode, newChild: PNode) =
## If the newChild is already in the tree, it is first removed.
# Check if n contains newChild
if not isNil(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == newChild:
raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == newChild:
raise newException(EHierarchyRequestErr, "The node to append is already in this nodes children.")
# Check if newChild is from this nodes document
if n.fOwnerDocument != newChild.fOwnerDocument:
@@ -572,7 +567,8 @@ proc appendChild*(n: PNode, newChild: PNode) =
if n.nodeType in childlessObjects:
raise newException(ENoModificationAllowedErr, "Cannot append children to a childless node")
if isNil(n.childNodes): n.childNodes = @[]
when not defined(nimNoNilSeqs):
if isNil(n.childNodes): n.childNodes = @[]
newChild.fParentNode = n
for i in low(n.childNodes)..high(n.childNodes):
@@ -597,10 +593,10 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
newNode = PElement(n)
# Import the childNodes
var tmp: seq[PNode] = n.childNodes
n.childNodes = @[]
if deep and not isNil(tmp):
for i in low(tmp.len())..high(tmp.len()):
n.childNodes.add(cloneNode(tmp[i], deep))
newNode.childNodes = @[]
if deep:
for i in low(n.childNodes)..high(n.childNodes):
newNode.childNodes.add(cloneNode(n.childNodes[i], deep))
return newNode
else:
var newNode: PNode
@@ -610,11 +606,11 @@ proc cloneNode*(n: PNode, deep: bool): PNode =
proc hasAttributes*(n: PNode): bool =
## Returns whether this node (if it is an element) has any attributes.
return not isNil(n.attributes) and n.attributes.len() > 0
return n.attributes.len > 0
proc hasChildNodes*(n: PNode): bool =
## Returns whether this node has any children.
return not isNil(n.childNodes) and n.childNodes.len() > 0
return n.childNodes.len > 0
proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
## Inserts the node ``newChild`` before the existing child node ``refChild``.
@@ -624,9 +620,6 @@ proc insertBefore*(n: PNode, newChild: PNode, refChild: PNode): PNode =
if n.fOwnerDocument != newChild.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if isNil(n.childNodes):
n.childNodes = @[]
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == refChild:
n.childNodes.insert(newChild, i - 1)
@@ -641,7 +634,7 @@ proc isSupported*(n: PNode, feature: string, version: string): bool =
proc isEmpty(s: string): bool =
if isNil(s) or s == "":
if s == "":
return true
for i in items(s):
if i != ' ':
@@ -655,7 +648,7 @@ proc normalize*(n: PNode) =
var newChildNodes: seq[PNode] = @[]
while true:
if isNil(n.childNodes) or i >= n.childNodes.len:
if i >= n.childNodes.len:
break
if n.childNodes[i].nodeType == TextNode:
@@ -679,12 +672,11 @@ proc normalize*(n: PNode) =
proc removeChild*(n: PNode, oldChild: PNode): PNode =
## Removes the child node indicated by ``oldChild`` from the list of children, and returns it.
if not isNil(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == oldChild:
result = n.childNodes[i]
n.childNodes.delete(i)
return
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == oldChild:
result = n.childNodes[i]
n.childNodes.delete(i)
return
raise newException(ENotFoundErr, "Node not found")
@@ -695,12 +687,11 @@ proc replaceChild*(n: PNode, newChild: PNode, oldChild: PNode): PNode =
if n.fOwnerDocument != newChild.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(n.childNodes):
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == oldChild:
result = n.childNodes[i]
n.childNodes[i] = newChild
return
for i in low(n.childNodes)..high(n.childNodes):
if n.childNodes[i] == oldChild:
result = n.childNodes[i]
n.childNodes[i] = newChild
return
raise newException(ENotFoundErr, "Node not found")
@@ -764,11 +755,10 @@ proc removeNamedItemNS*(nList: var seq[PNode], namespaceURI: string, localName:
proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
## Adds ``arg`` as a ``Node`` to the ``NList``
## If a node with the same name is already present in this map, it is replaced by the new one.
if not isNil(nList):
if nList.len() > 0:
#Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if nList.len > 0:
#Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
#Exceptions End
var item: PNode = nList.getNamedItem(arg.nodeName())
@@ -788,11 +778,10 @@ proc setNamedItem*(nList: var seq[PNode], arg: PNode): PNode =
proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
## Adds ``arg`` as a ``Node`` to the ``NList``
## If a node with the same name is already present in this map, it is replaced by the new one.
if not isNil(nList):
if nList.len() > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if nList.len > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(arg.fOwnerElement):
raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@@ -814,11 +803,10 @@ proc setNamedItem*(nList: var seq[PAttr], arg: PAttr): PAttr =
proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
## Adds a node using its ``namespaceURI`` and ``localName``
if not isNil(nList):
if nList.len() > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if nList.len > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
#Exceptions end
var item: PNode = nList.getNamedItemNS(arg.namespaceURI(), arg.localName())
@@ -837,11 +825,10 @@ proc setNamedItemNS*(nList: var seq[PNode], arg: PNode): PNode =
proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
## Adds a node using its ``namespaceURI`` and ``localName``
if not isNil(nList):
if nList.len() > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if nList.len > 0:
# Check if newChild is from this nodes document
if nList[0].fOwnerDocument != arg.fOwnerDocument:
raise newException(EWrongDocumentErr, "This node belongs to a different document, use importNode.")
if not isNil(arg.fOwnerElement):
raise newException(EInuseAttributeErr, "This attribute is in use by another element, use cloneNode")
@@ -868,17 +855,14 @@ proc setNamedItemNS*(nList: var seq[PAttr], arg: PAttr): PAttr =
# Attributes
proc name*(a: PAttr): string =
## Returns the name of the Attribute
return a.fName
proc specified*(a: PAttr): bool =
## Specifies whether this attribute was specified in the original document
return a.fSpecified
proc ownerElement*(a: PAttr): PElement =
## Returns this Attributes owner element
return a.fOwnerElement
# Element
@@ -886,14 +870,11 @@ proc ownerElement*(a: PAttr): PElement =
proc tagName*(el: PElement): string =
## Returns the Element Tag Name
return el.fTagName
# Procedures
proc getAttribute*(el: PNode, name: string): string =
## Retrieves an attribute value by ``name``
if isNil(el.attributes):
return ""
var attribute = el.attributes.getNamedItem(name)
if not isNil(attribute):
return attribute.value
@@ -902,8 +883,6 @@ proc getAttribute*(el: PNode, name: string): string =
proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string =
## Retrieves an attribute value by ``localName`` and ``namespaceURI``
if isNil(el.attributes):
return ""
var attribute = el.attributes.getNamedItemNS(namespaceURI, localName)
if not isNil(attribute):
return attribute.value
@@ -913,14 +892,10 @@ proc getAttributeNS*(el: PNode, namespaceURI: string, localName: string): string
proc getAttributeNode*(el: PElement, name: string): PAttr =
## Retrieves an attribute node by ``name``
## To retrieve an attribute node by qualified name and namespace URI, use the `getAttributeNodeNS` method
if isNil(el.attributes):
return nil
return el.attributes.getNamedItem(name)
proc getAttributeNodeNS*(el: PElement, namespaceURI: string, localName: string): PAttr =
## Retrieves an `Attr` node by ``localName`` and ``namespaceURI``
if isNil(el.attributes):
return nil
return el.attributes.getNamedItemNS(namespaceURI, localName)
proc getElementsByTagName*(el: PElement, name: string): seq[PNode] =
@@ -938,41 +913,34 @@ proc getElementsByTagNameNS*(el: PElement, namespaceURI: string, localName: stri
proc hasAttribute*(el: PElement, name: string): bool =
## Returns ``true`` when an attribute with a given ``name`` is specified
## on this element , ``false`` otherwise.
if isNil(el.attributes):
return false
return not isNil(el.attributes.getNamedItem(name))
proc hasAttributeNS*(el: PElement, namespaceURI: string, localName: string): bool =
## Returns ``true`` when an attribute with a given ``localName`` and
## ``namespaceURI`` is specified on this element , ``false`` otherwise
if isNil(el.attributes):
return false
return not isNil(el.attributes.getNamedItemNS(namespaceURI, localName))
proc removeAttribute*(el: PElement, name: string) =
## Removes an attribute by ``name``
if not isNil(el.attributes):
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i].fName == name:
el.attributes.delete(i)
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i].fName == name:
el.attributes.delete(i)
proc removeAttributeNS*(el: PElement, namespaceURI: string, localName: string) =
## Removes an attribute by ``localName`` and ``namespaceURI``
if not isNil(el.attributes):
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i].fNamespaceURI == namespaceURI and
el.attributes[i].fLocalName == localName:
el.attributes.delete(i)
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i].fNamespaceURI == namespaceURI and
el.attributes[i].fLocalName == localName:
el.attributes.delete(i)
proc removeAttributeNode*(el: PElement, oldAttr: PAttr): PAttr =
## Removes the specified attribute node
## If the attribute node cannot be found raises ``ENotFoundErr``
if not isNil(el.attributes):
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i] == oldAttr:
result = el.attributes[i]
el.attributes.delete(i)
return
for i in low(el.attributes)..high(el.attributes):
if el.attributes[i] == oldAttr:
result = el.attributes[i]
el.attributes.delete(i)
return
raise newException(ENotFoundErr, "oldAttr is not a member of el's Attributes")
@@ -991,7 +959,6 @@ proc setAttributeNode*(el: PElement, newAttr: PAttr): PAttr =
"This attribute is in use by another element, use cloneNode")
# Exceptions end
if isNil(el.attributes): el.attributes = @[]
return el.attributes.setNamedItem(newAttr)
proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
@@ -1009,7 +976,6 @@ proc setAttributeNodeNS*(el: PElement, newAttr: PAttr): PAttr =
"This attribute is in use by another element, use cloneNode")
# Exceptions end
if isNil(el.attributes): el.attributes = @[]
return el.attributes.setNamedItemNS(newAttr)
proc setAttribute*(el: PElement, name: string, value: string) =
@@ -1057,9 +1023,9 @@ proc splitData*(textNode: PText, offset: int): PText =
var left: string = textNode.data.substr(0, offset)
textNode.data = left
var right: string = textNode.data.substr(offset, textNode.data.len())
var right: string = textNode.data.substr(offset, textNode.data.len)
if not isNil(textNode.fParentNode) and not isNil(textNode.fParentNode.childNodes):
if not isNil(textNode.fParentNode) and textNode.fParentNode.childNodes.len > 0:
for i in low(textNode.fParentNode.childNodes)..high(textNode.fParentNode.childNodes):
if textNode.fParentNode.childNodes[i] == textNode:
var newNode: PText = textNode.fOwnerDocument.createTextNode(right)
@@ -1098,11 +1064,10 @@ proc escapeXml*(s: string): string =
proc nodeToXml(n: PNode, indent: int = 0): string =
result = spaces(indent) & "<" & n.nodeName
if not isNil(n.attributes):
for i in items(n.attributes):
result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
for i in items(n.attributes):
result.add(" " & i.name & "=\"" & escapeXml(i.value) & "\"")
if isNil(n.childNodes) or n.childNodes.len() == 0:
if n.childNodes.len == 0:
result.add("/>") # No idea why this doesn't need a \n :O
else:
# End the beginning of this tag
@@ -1134,3 +1099,4 @@ proc `$`*(doc: PDocument): string =
## Converts a PDocument object into a string representation of it's XML
result = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
result.add(nodeToXml(doc.documentElement))

View File

@@ -2292,9 +2292,18 @@ iterator mpairs*(a: var cstring): tuple[key: int, val: var char] {.inline.} =
inc(i)
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil", deprecated.}
when defined(nimNoNilSeqs2):
when not compileOption("nilseqs"):
{.pragma: nilError, error.}
else:
{.pragma: nilError.}
else:
{.pragma: nilError.}
proc isNil*[T](x: seq[T]): bool {.noSideEffect, magic: "IsNil", nilError.}
proc isNil*[T](x: ref T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil", deprecated.}
proc isNil*(x: string): bool {.noSideEffect, magic: "IsNil", nilError.}
proc isNil*[T](x: ptr T): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: pointer): bool {.noSideEffect, magic: "IsNil".}
proc isNil*(x: cstring): bool {.noSideEffect, magic: "IsNil".}

View File

@@ -213,7 +213,7 @@ proc auxWriteStackTrace(f: PFrame; s: var seq[StackTraceEntry]) =
inc(i)
it = it.prev
var last = i-1
if s.isNil:
if s.len == 0:
s = newSeq[StackTraceEntry](i)
else:
last = s.len + i - 1
@@ -361,10 +361,10 @@ proc raiseExceptionAux(e: ref Exception) =
else:
when hasSomeStackTrace:
var buf = newStringOfCap(2000)
if isNil(e.trace): rawWriteStackTrace(buf)
if e.trace.len == 0: rawWriteStackTrace(buf)
else: add(buf, $e.trace)
add(buf, "Error: unhandled exception: ")
if not isNil(e.msg): add(buf, e.msg)
add(buf, e.msg)
add(buf, " [")
add(buf, $e.name)
add(buf, "]\n")
@@ -382,7 +382,7 @@ proc raiseExceptionAux(e: ref Exception) =
var buf: array[0..2000, char]
var L = 0
add(buf, "Error: unhandled exception: ")
if not isNil(e.msg): add(buf, e.msg)
add(buf, e.msg)
add(buf, " [")
xadd(buf, e.name, e.name.len)
add(buf, "]\n")
@@ -397,7 +397,7 @@ proc raiseExceptionAux(e: ref Exception) =
proc raiseException(e: ref Exception, ename: cstring) {.compilerRtl.} =
if e.name.isNil: e.name = ename
when hasSomeStackTrace:
if e.trace.isNil:
if e.trace.len == 0:
rawWriteStackTrace(e.trace)
elif framePtr != nil:
e.trace.add reraisedFrom(reraisedFromBegin)
@@ -427,7 +427,7 @@ proc getStackTrace(): string =
result = "No stack traceback available\n"
proc getStackTrace(e: ref Exception): string =
if not isNil(e) and not isNil(e.trace):
if not isNil(e):
result = $e.trace
else:
result = ""

View File

@@ -266,7 +266,7 @@ when not defined(useNimRtl):
of tyChar: add result, reprChar(cast[ptr char](p)[])
of tyString:
let sp = cast[ptr string](p)
reprStrAux(result, if sp[].isNil: nil else: sp[].cstring, sp[].len)
reprStrAux(result, sp[].cstring, sp[].len)
of tyCString:
let cs = cast[ptr cstring](p)[]
if cs.isNil: add result, "nil"

View File

@@ -232,10 +232,7 @@ proc reprAux(result: var string, p: pointer, typ: PNimType,
of tyString:
var fp: int
{. emit: "`fp` = `p`;\n" .}
if cast[string](fp).isNil:
add(result, "nil")
else:
add( result, reprStr(cast[string](p)) )
add( result, reprStr(cast[string](p)) )
of tyCString:
var fp: cstring
{. emit: "`fp` = `p`;\n" .}

View File

@@ -144,13 +144,7 @@ proc getFileHandle*(f: File): FileHandle = c_fileno(f)
proc readLine(f: File, line: var TaintedString): bool =
var pos = 0
var sp: cint = 80
# Use the currently reserved space for a first try
if line.string.isNil:
line = TaintedString(newStringOfCap(80))
else:
when not defined(nimscript) and not defined(gcDestructors):
sp = cint(cast[PGenericSeq](line.string).space)
line.string.setLen(sp)
line.string.setLen(sp)
while true:
# memset to \L so that we can tell how far fgets wrote, even on EOF, where
# fgets doesn't append an \L

View File

@@ -393,8 +393,9 @@ proc onThreadDestruction*(handler: proc () {.closure, gcsafe.}) =
## A thread is destructed when the ``.thread`` proc returns
## normally or when it raises an exception. Note that unhandled exceptions
## in a thread nevertheless cause the whole process to die.
if threadDestructionHandlers.isNil:
threadDestructionHandlers = @[]
when not defined(nimNoNilSeqs):
if threadDestructionHandlers.isNil:
threadDestructionHandlers = @[]
threadDestructionHandlers.add handler
template afterThreadRuns() =