Merge branch 'araq-strings-v1' into devel

This commit is contained in:
Araq 2018-04-30 19:25:04 +02:00
commit f74f485bf7
30 changed files with 156 additions and 1928 deletions

View file

@ -10,7 +10,7 @@
from pcre import nil
import nre.private.util
import tables
from strutils import toLower, `%`
from strutils import `%`
from math import ceil
import options
from unicode import runeLenAt
@ -326,15 +326,15 @@ proc `$`*(pattern: RegexMatch): string =
proc `==`*(a, b: Regex): bool =
if not a.isNil and not b.isNil:
return a.pattern == b.pattern and
a.pcreObj == b.pcreObj and
return a.pattern == b.pattern and
a.pcreObj == b.pcreObj and
a.pcreExtra == b.pcreExtra
else:
return system.`==`(a, b)
proc `==`*(a, b: RegexMatch): bool =
return a.pattern == b.pattern and
a.str == b.str
a.str == b.str
# }}}
# Creation & Destruction {{{

View file

@ -201,7 +201,7 @@ when defineSsl:
flags: set[SocketFlag]) {.async.} =
let len = bioCtrlPending(socket.bioOut)
if len > 0:
var data = newStringOfCap(len)
var data = newString(len)
let read = bioRead(socket.bioOut, addr data[0], len)
assert read != 0
if read < 0:

View file

@ -52,7 +52,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped =
if numLines > 0: inc(total, (numLines - 1) * newLine.len)
result = newString(total)
var
var
i = 0
r = 0
currLine = 0
@ -76,7 +76,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped =
currLine = 0
if i < s.len-1:
let
let
a = ord(s[i])
b = ord(s[i+1])
result[r] = cb64[a shr 2]
@ -130,11 +130,11 @@ proc decode*(s: string): string =
# total is an upper bound, as we will skip arbitrary whitespace:
result = newString(total)
var
var
i = 0
r = 0
while true:
while s[i] in Whitespace: inc(i)
while i < s.len and s[i] in Whitespace: inc(i)
if i < s.len-3:
let
a = s[i].decodeByte

View file

@ -74,18 +74,19 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] =
var newByte = 0
block blockX:
while newbyte < key.len:
if it.key[newbyte] != key[newbyte]:
newotherbits = it.key[newbyte].ord xor key[newbyte].ord
let ch = if newbyte < it.key.len: it.key[newbyte] else: '\0'
if ch != key[newbyte]:
newotherbits = ch.ord xor key[newbyte].ord
break blockX
inc newbyte
if it.key[newbyte] != '\0':
if newbyte < it.key.len:
newotherbits = it.key[newbyte].ord
else:
return it
while (newOtherBits and (newOtherBits-1)) != 0:
newOtherBits = newOtherBits and (newOtherBits-1)
newOtherBits = newOtherBits xor 255
let ch = it.key[newByte]
let ch = if newByte < it.key.len: it.key[newByte] else: '\0'
let dir = (1 + (ord(ch) or newOtherBits)) shr 8
var inner: Node[T]

View file

@ -25,16 +25,16 @@ proc parseCookies*(s: string): StringTableRef =
result = newStringTable(modeCaseInsensitive)
var i = 0
while true:
while s[i] == ' ' or s[i] == '\t': inc(i)
while i < s.len and (s[i] == ' ' or s[i] == '\t'): inc(i)
var keystart = i
while s[i] != '=' and s[i] != '\0': inc(i)
while i < s.len and s[i] != '=': inc(i)
var keyend = i-1
if s[i] == '\0': break
if i >= s.len: break
inc(i) # skip '='
var valstart = i
while s[i] != ';' and s[i] != '\0': inc(i)
while i < s.len and s[i] != ';': inc(i)
result[substr(s, keystart, keyend)] = substr(s, valstart, i-1)
if s[i] == '\0': break
if i >= s.len: break
inc(i) # skip ';'
proc setCookie*(key, value: string, domain = "", path = "",

View file

@ -36,7 +36,7 @@ when defined(windows):
while i < a.len and j < b.len:
if a[i] in {'-', '_'}: inc i
if b[j] in {'-', '_'}: inc j
if a[i].toLower != b[j].toLower: return false
if i < a.len and j < b.len and a[i].toLowerAscii != b[j].toLowerAscii: return false
inc i
inc j
result = i == a.len and j == b.len

View file

@ -74,7 +74,7 @@
##
## .. code-block:: Nim
## import asyncdispatch, httpclient
##
##
## proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
## echo("Downloaded ", progress, " of ", total)
## echo("Current rate: ", speed div 1000, "kb/s")
@ -247,7 +247,7 @@ proc parseChunks(s: Socket, timeout: int): string =
var i = 0
if chunkSizeStr == "":
httpError("Server terminated connection prematurely")
while true:
while i < chunkSizeStr.len:
case chunkSizeStr[i]
of '0'..'9':
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
@ -255,8 +255,6 @@ proc parseChunks(s: Socket, timeout: int): string =
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
of 'A'..'F':
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
of '\0':
break
of ';':
# http://tools.ietf.org/html/rfc2616#section-3.6.1
# We don't care about chunk-extensions.
@ -938,7 +936,7 @@ proc parseChunks(client: HttpClient | AsyncHttpClient): Future[void]
var i = 0
if chunkSizeStr == "":
httpError("Server terminated connection prematurely")
while true:
while i < chunkSizeStr.len:
case chunkSizeStr[i]
of '0'..'9':
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
@ -946,8 +944,6 @@ proc parseChunks(client: HttpClient | AsyncHttpClient): Future[void]
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
of 'A'..'F':
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
of '\0':
break
of ';':
# http://tools.ietf.org/html/rfc2616#section-3.6.1
# We don't care about chunk-extensions.

View file

@ -190,11 +190,11 @@ proc len*(headers: HttpHeaders): int = return headers.table.len
proc parseList(line: string, list: var seq[string], start: int): int =
var i = 0
var current = ""
while line[start + i] notin {'\c', '\l', '\0'}:
while start+i < line.len and line[start + i] notin {'\c', '\l'}:
i += line.skipWhitespace(start + i)
i += line.parseUntil(current, {'\c', '\l', ','}, start + i)
list.add(current)
if line[start + i] == ',':
if start+i < line.len and line[start + i] == ',':
i.inc # Skip ,
current.setLen(0)

View file

@ -126,7 +126,7 @@ when false:
var dataAvail = false
while dataAvail:
dataAvail = recvLine(client, buf) # TODO: This is incorrect.
var L = toLower(buf.string)
var L = toLowerAscii(buf.string)
if L.startsWith("content-length:"):
var i = len("content-length:")
while L[i] in Whitespace: inc(i)
@ -199,7 +199,7 @@ when false:
notFound(client)
else:
when defined(Windows):
var ext = splitFile(path).ext.toLower
var ext = splitFile(path).ext.toLowerAscii
if ext == ".exe" or ext == ".cgi":
# XXX: extract interpreter information here?
cgi = true
@ -303,7 +303,7 @@ proc next*(s: var Server) =
if s.reqMethod == "POST":
# Check for Expect header
if s.headers.hasKey("Expect"):
if s.headers["Expect"].toLower == "100-continue":
if s.headers["Expect"].toLowerAscii == "100-continue":
s.client.sendStatus("100 Continue")
else:
s.client.sendStatus("417 Expectation Failed")
@ -427,7 +427,7 @@ proc nextAsync(s: PAsyncHTTPServer) =
if s.reqMethod == "POST":
# Check for Expect header
if s.headers.hasKey("Expect"):
if s.headers["Expect"].toLower == "100-continue":
if s.headers["Expect"].toLowerAscii == "100-continue":
s.client.sendStatus("100 Continue")
else:
s.client.sendStatus("417 Expectation Failed")

View file

@ -126,7 +126,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
var v = ""
let app = when defined(js): "" else: getAppFilename()
while frmt[i] in IdentChars:
v.add(toLower(frmt[i]))
v.add(toLowerAscii(frmt[i]))
inc(i)
case v
of "date": result.add(getDateStr())

View file

@ -29,21 +29,21 @@ proc validEmailAddress*(s: string): bool {.noSideEffect,
chars = Letters + Digits + {'!','#','$','%','&',
'\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'}
var i = 0
if s[i] notin chars or s[i] == '.': return false
while s[i] in chars:
if s[i] == '.' and s[i+1] == '.': return false
if i >= s.len or s[i] notin chars or s[i] == '.': return false
while i < s.len and s[i] in chars:
if i+1 < s.len and s[i] == '.' and s[i+1] == '.': return false
inc(i)
if s[i] != '@': return false
if i >= s.len or s[i] != '@': return false
var j = len(s)-1
if s[j] notin Letters: return false
if j >= 0 and s[j] notin Letters: return false
while j >= i and s[j] in Letters: dec(j)
inc(i) # skip '@'
while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i)
if s[i] != '\0': return false
while i < s.len and s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i)
if i != s.len: return false
var x = substr(s, j+1)
if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true
case toLower(x)
case toLowerAscii(x)
of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name",
"aero", "jobs", "museum": return true
else: return false

View file

@ -1060,18 +1060,17 @@ proc parseCmdLine*(c: string): seq[string] {.
while true:
setLen(a, 0)
# eat all delimiting whitespace
while c[i] == ' ' or c[i] == '\t' or c[i] == '\l' or c[i] == '\r' : inc(i)
while i < c.len and c[i] in {' ', '\t', '\l', '\r'}: inc(i)
if i >= c.len: break
when defined(windows):
# parse a single argument according to the above rules:
if c[i] == '\0': break
var inQuote = false
while true:
while i < c.len:
case c[i]
of '\0': break
of '\\':
var j = i
while c[j] == '\\': inc(j)
if c[j] == '"':
while j < c.len and c[j] == '\\': inc(j)
if j < c.len and c[j] == '"':
for k in 1..(j-i) div 2: a.add('\\')
if (j-i) mod 2 == 0:
i = j
@ -1084,7 +1083,7 @@ proc parseCmdLine*(c: string): seq[string] {.
of '"':
inc(i)
if not inQuote: inQuote = true
elif c[i] == '"':
elif i < c.len and c[i] == '"':
a.add(c[i])
inc(i)
else:
@ -1102,13 +1101,12 @@ proc parseCmdLine*(c: string): seq[string] {.
of '\'', '\"':
var delim = c[i]
inc(i) # skip ' or "
while c[i] != '\0' and c[i] != delim:
while i < c.len and c[i] != delim:
add a, c[i]
inc(i)
if c[i] != '\0': inc(i)
of '\0': break
if i < c.len: inc(i)
else:
while c[i] > ' ':
while i < c.len and c[i] > ' ':
add(a, c[i])
inc(i)
add(result, a)

View file

@ -196,7 +196,7 @@ proc joinPath*(head, tail: string): string {.
else:
result = head & tail
else:
if tail[0] in {DirSep, AltSep}:
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
result = head & tail
else:
result = head & DirSep & tail
@ -477,7 +477,7 @@ proc unixToNativePath*(path: string, drive=""): string {.
var i = start
while i < len(path): # ../../../ --> ::::
if path[i] == '.' and path[i+1] == '.' and path[i+2] == '/':
if i+2 < path.len and path[i] == '.' and path[i+1] == '.' and path[i+2] == '/':
# parent directory
when defined(macos):
if result[high(result)] == ':':

View file

@ -534,15 +534,15 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
case p.kind
of pkEmpty: result = 0 # match of length 0
of pkAny:
if s[start] != '\0': result = 1
if start < s.len: result = 1
else: result = -1
of pkAnyRune:
if s[start] != '\0':
if start < s.len:
result = runeLenAt(s, start)
else:
result = -1
of pkLetter:
if s[start] != '\0':
if start < s.len:
var a: Rune
result = start
fastRuneAt(s, result, a)
@ -551,7 +551,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
else:
result = -1
of pkLower:
if s[start] != '\0':
if start < s.len:
var a: Rune
result = start
fastRuneAt(s, result, a)
@ -560,7 +560,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
else:
result = -1
of pkUpper:
if s[start] != '\0':
if start < s.len:
var a: Rune
result = start
fastRuneAt(s, result, a)
@ -569,7 +569,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
else:
result = -1
of pkTitle:
if s[start] != '\0':
if start < s.len:
var a: Rune
result = start
fastRuneAt(s, result, a)
@ -578,7 +578,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
else:
result = -1
of pkWhitespace:
if s[start] != '\0':
if start < s.len:
var a: Rune
result = start
fastRuneAt(s, result, a)
@ -589,15 +589,15 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
of pkGreedyAny:
result = len(s) - start
of pkNewLine:
if s[start] == '\L': result = 1
elif s[start] == '\C':
if s[start+1] == '\L': result = 2
if start < s.len and s[start] == '\L': result = 1
elif start < s.len and s[start] == '\C':
if start+1 < s.len and s[start+1] == '\L': result = 2
else: result = 1
else: result = -1
of pkTerminal:
result = len(p.term)
for i in 0..result-1:
if p.term[i] != s[start+i]:
if start+i >= s.len or p.term[i] != s[start+i]:
result = -1
break
of pkTerminalIgnoreCase:
@ -606,6 +606,9 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
a, b: Rune
result = start
while i < len(p.term):
if result >= s.len:
result = -1
break
fastRuneAt(p.term, i, a)
fastRuneAt(s, result, b)
if toLower(a) != toLower(b):
@ -621,18 +624,23 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
while true:
fastRuneAt(p.term, i, a)
if a != Rune('_'): break
while true:
while result < s.len:
fastRuneAt(s, result, b)
if b != Rune('_'): break
if toLower(a) != toLower(b):
if result >= s.len:
if i >= p.term.len: break
else:
result = -1
break
elif toLower(a) != toLower(b):
result = -1
break
dec(result, start)
of pkChar:
if p.ch == s[start]: result = 1
if start < s.len and p.ch == s[start]: result = 1
else: result = -1
of pkCharChoice:
if contains(p.charChoice[], s[start]): result = 1
if start < s.len and contains(p.charChoice[], s[start]): result = 1
else: result = -1
of pkNonTerminal:
var oldMl = c.ml
@ -695,10 +703,10 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
of pkGreedyRepChar:
result = 0
var ch = p.ch
while ch == s[start+result]: inc(result)
while start+result < s.len and ch == s[start+result]: inc(result)
of pkGreedyRepSet:
result = 0
while contains(p.charChoice[], s[start+result]): inc(result)
while start+result < s.len and contains(p.charChoice[], s[start+result]): inc(result)
of pkOption:
result = max(0, rawMatch(s, p.sons[0], start, c))
of pkAndPredicate:

View file

@ -1126,7 +1126,7 @@ proc unindent*(s: string, count: Natural, padding: string = " "): string
var indentCount = 0
for j in 0..<count.int:
indentCount.inc
if line[j .. j + padding.len-1] != padding:
if j + padding.len-1 >= line.len or line[j .. j + padding.len-1] != padding:
indentCount = j
break
result.add(line[indentCount*padding.len .. ^1])

View file

@ -1318,24 +1318,23 @@ proc format*(dt: DateTime, f: string): string {.tags: [].}=
result = ""
var i = 0
var currentF = ""
while true:
while i < f.len:
case f[i]
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
of ' ', '-', '/', ':', '\'', '(', ')', '[', ']', ',':
formatToken(dt, currentF, result)
currentF = ""
if f[i] == '\0': break
if f[i] == '\'':
inc(i) # Skip '
while f[i] != '\'' and f.len-1 > i:
while i < f.len-1 and f[i] != '\'':
result.add(f[i])
inc(i)
else: result.add(f[i])
else:
# Check if the letter being added matches previous accumulated buffer.
if currentF.len < 1 or currentF[high(currentF)] == f[i]:
if currentF.len == 0 or currentF[high(currentF)] == f[i]:
currentF.add(f[i])
else:
formatToken(dt, currentF, result)
@ -1343,6 +1342,7 @@ proc format*(dt: DateTime, f: string): string {.tags: [].}=
currentF = ""
inc(i)
formatToken(dt, currentF, result)
proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} =
## Converts a `DateTime` object to a string representation.
@ -1439,58 +1439,58 @@ proc parseToken(dt: var DateTime; token, value: string; j: var int) =
dt.month = month.Month
of "MMM":
case value[j..j+2].toLowerAscii():
of "jan": dt.month = mJan
of "feb": dt.month = mFeb
of "mar": dt.month = mMar
of "apr": dt.month = mApr
of "may": dt.month = mMay
of "jun": dt.month = mJun
of "jul": dt.month = mJul
of "aug": dt.month = mAug
of "sep": dt.month = mSep
of "oct": dt.month = mOct
of "nov": dt.month = mNov
of "dec": dt.month = mDec
of "jan": dt.month = mJan
of "feb": dt.month = mFeb
of "mar": dt.month = mMar
of "apr": dt.month = mApr
of "may": dt.month = mMay
of "jun": dt.month = mJun
of "jul": dt.month = mJul
of "aug": dt.month = mAug
of "sep": dt.month = mSep
of "oct": dt.month = mOct
of "nov": dt.month = mNov
of "dec": dt.month = mDec
else:
raise newException(ValueError,
"Couldn't parse month (MMM), got: " & value)
j += 3
of "MMMM":
if value.len >= j+7 and value[j..j+6].cmpIgnoreCase("january") == 0:
dt.month = mJan
dt.month = mJan
j += 7
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("february") == 0:
dt.month = mFeb
dt.month = mFeb
j += 8
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("march") == 0:
dt.month = mMar
dt.month = mMar
j += 5
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("april") == 0:
dt.month = mApr
dt.month = mApr
j += 5
elif value.len >= j+3 and value[j..j+2].cmpIgnoreCase("may") == 0:
dt.month = mMay
dt.month = mMay
j += 3
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("june") == 0:
dt.month = mJun
dt.month = mJun
j += 4
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("july") == 0:
dt.month = mJul
dt.month = mJul
j += 4
elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("august") == 0:
dt.month = mAug
dt.month = mAug
j += 6
elif value.len >= j+9 and value[j..j+8].cmpIgnoreCase("september") == 0:
dt.month = mSep
dt.month = mSep
j += 9
elif value.len >= j+7 and value[j..j+6].cmpIgnoreCase("october") == 0:
dt.month = mOct
dt.month = mOct
j += 7
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("november") == 0:
dt.month = mNov
dt.month = mNov
j += 8
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("december") == 0:
dt.month = mDec
dt.month = mDec
j += 8
else:
raise newException(ValueError,
@ -1521,44 +1521,47 @@ proc parseToken(dt: var DateTime; token, value: string; j: var int) =
j += 4
of "z":
dt.isDst = false
if value[j] == '+':
let ch = if j < value.len: value[j] else: '\0'
if ch == '+':
dt.utcOffset = 0 - parseInt($value[j+1]) * secondsInHour
elif value[j] == '-':
elif ch == '-':
dt.utcOffset = parseInt($value[j+1]) * secondsInHour
elif value[j] == 'Z':
elif ch == 'Z':
dt.utcOffset = 0
j += 1
return
else:
raise newException(ValueError,
"Couldn't parse timezone offset (z), got: " & value[j])
"Couldn't parse timezone offset (z), got: " & ch)
j += 2
of "zz":
dt.isDst = false
if value[j] == '+':
let ch = if j < value.len: value[j] else: '\0'
if ch == '+':
dt.utcOffset = 0 - value[j+1..j+2].parseInt() * secondsInHour
elif value[j] == '-':
elif ch == '-':
dt.utcOffset = value[j+1..j+2].parseInt() * secondsInHour
elif value[j] == 'Z':
elif ch == 'Z':
dt.utcOffset = 0
j += 1
return
else:
raise newException(ValueError,
"Couldn't parse timezone offset (zz), got: " & value[j])
"Couldn't parse timezone offset (zz), got: " & ch)
j += 3
of "zzz":
dt.isDst = false
var factor = 0
if value[j] == '+': factor = -1
elif value[j] == '-': factor = 1
elif value[j] == 'Z':
let ch = if j < value.len: value[j] else: '\0'
if ch == '+': factor = -1
elif ch == '-': factor = 1
elif ch == 'Z':
dt.utcOffset = 0
j += 1
return
else:
raise newException(ValueError,
"Couldn't parse timezone offset (zzz), got: " & value[j])
"Couldn't parse timezone offset (zzz), got: " & ch)
dt.utcOffset = factor * value[j+1..j+2].parseInt() * secondsInHour
j += 4
dt.utcOffset += factor * value[j..j+1].parseInt() * 60
@ -1620,20 +1623,18 @@ proc parse*(value, layout: string, zone: Timezone = local()): DateTime =
dt.nanosecond = 0
dt.isDst = true # using this is flag for checking whether a timezone has \
# been read (because DST is always false when a tz is parsed)
while true:
while i < layout.len:
case layout[i]
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
of ' ', '-', '/', ':', '\'', '(', ')', '[', ']', ',':
if token.len > 0:
parseToken(dt, token, value, j)
# Reset token
token = ""
# Break if at end of line
if layout[i] == '\0': break
# Skip separator and everything between single quotes
# These are literals in both the layout and the value string
if layout[i] == '\'':
inc(i)
while layout[i] != '\'' and layout.len-1 > i:
while i < layout.len-1 and layout[i] != '\'':
inc(i)
inc(j)
inc(i)
@ -1642,13 +1643,15 @@ proc parse*(value, layout: string, zone: Timezone = local()): DateTime =
inc(j)
else:
# Check if the letter being added matches previous accumulated buffer.
if token.len < 1 or token[high(token)] == layout[i]:
if token.len == 0 or token[high(token)] == layout[i]:
token.add(layout[i])
inc(i)
else:
parseToken(dt, token, value, j)
token = ""
if i >= layout.len and token.len > 0:
parseToken(dt, token, value, j)
if dt.isDst:
# No timezone parsed - assume timezone is `zone`
result = initDateTime(zone.zoneInfoFromTz(dt.toAdjTime), zone)

View file

@ -232,10 +232,10 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
raise newException(EInvalidCharacterErr, "Invalid character")
# Exceptions
if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLower().split(':')
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI):
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
elif qfnamespaces[0] == "xml" and
elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames:
raise newException(ENamespaceErr,
@ -311,10 +311,10 @@ proc createElement*(doc: PDocument, tagName: string): PElement =
proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
## Creates an element of the given qualified name and namespace URI.
if qualifiedName.contains(':'):
let qfnamespaces = qualifiedName.toLower().split(':')
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
if isNil(namespaceURI):
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
elif qfnamespaces[0] == "xml" and
elif qfnamespaces[0] == "xml" and
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
qfnamespaces[1] notin stdattrnames:
raise newException(ENamespaceErr,
@ -533,13 +533,13 @@ proc `prefix=`*(n: PNode, value: string) =
if isNil(n.fNamespaceURI):
raise newException(ENamespaceErr, "namespaceURI cannot be nil")
elif value.toLower() == "xml" and n.fNamespaceURI != "http://www.w3.org/XML/1998/namespace":
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\"")
elif value.toLower() == "xmlns" and n.fNamespaceURI != "http://www.w3.org/2000/xmlns/":
elif value.toLowerAscii() == "xmlns" and n.fNamespaceURI != "http://www.w3.org/2000/xmlns/":
raise newException(ENamespaceErr,
"When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
elif value.toLower() == "xmlns" and n.fNodeType == AttributeNode:
elif value.toLowerAscii() == "xmlns" and n.fNodeType == AttributeNode:
raise newException(ENamespaceErr, "An AttributeNode cannot have a prefix of \"xmlns\"")
n.fNodeName = value & ":" & n.fLocalName