Merge branch 'araq-strings-v1' into devel
This commit is contained in:
commit
f74f485bf7
30 changed files with 156 additions and 1928 deletions
|
|
@ -83,6 +83,9 @@
|
||||||
|
|
||||||
- ``nil`` for strings/seqs is finally gone. Instead the default value for
|
- ``nil`` for strings/seqs is finally gone. Instead the default value for
|
||||||
these is ``"" / @[]``.
|
these is ``"" / @[]``.
|
||||||
|
- Accessing the binary zero terminator in Nim's native strings
|
||||||
|
is now invalid. Internally a Nim string still has the trailing zero for
|
||||||
|
zero-copy interoperability with ``cstring``.
|
||||||
|
|
||||||
### Tool changes
|
### Tool changes
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1471,7 +1471,7 @@ mysterious crashes.
|
||||||
|
|
||||||
**Note**: The example only works because the memory is initialized to zero
|
**Note**: The example only works because the memory is initialized to zero
|
||||||
(``alloc0`` instead of ``alloc`` does this): ``d.s`` is thus initialized to
|
(``alloc0`` instead of ``alloc`` does this): ``d.s`` is thus initialized to
|
||||||
``nil`` which the string assignment can handle. One needs to know low level
|
binary zero which the string assignment can handle. One needs to know low level
|
||||||
details like this when mixing garbage collected data with unmanaged memory.
|
details like this when mixing garbage collected data with unmanaged memory.
|
||||||
|
|
||||||
.. XXX finalizers for traced objects
|
.. XXX finalizers for traced objects
|
||||||
|
|
@ -2512,8 +2512,8 @@ char '\\0'
|
||||||
bool false
|
bool false
|
||||||
ref or pointer type nil
|
ref or pointer type nil
|
||||||
procedural type nil
|
procedural type nil
|
||||||
sequence nil (*not* ``@[]``)
|
sequence ``@[]``
|
||||||
string nil (*not* "")
|
string ``""``
|
||||||
tuple[x: A, y: B, ...] (default(A), default(B), ...)
|
tuple[x: A, y: B, ...] (default(A), default(B), ...)
|
||||||
(analogous for objects)
|
(analogous for objects)
|
||||||
array[0..., T] [default(T), ...]
|
array[0..., T] [default(T), ...]
|
||||||
|
|
@ -4270,7 +4270,7 @@ therefore very useful for type specialization within generic code:
|
||||||
Table[Key, Value] = object
|
Table[Key, Value] = object
|
||||||
keys: seq[Key]
|
keys: seq[Key]
|
||||||
values: seq[Value]
|
values: seq[Value]
|
||||||
when not (Key is string): # nil value for strings used for optimization
|
when not (Key is string): # empty value for strings used for optimization
|
||||||
deletedKeys: seq[bool]
|
deletedKeys: seq[bool]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -7434,8 +7434,8 @@ code generation directly, but their presence can be detected by macros.
|
||||||
Custom pragmas are defined using templates annotated with pragma ``pragma``:
|
Custom pragmas are defined using templates annotated with pragma ``pragma``:
|
||||||
|
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
template dbTable(name: string, table_space: string = nil) {.pragma.}
|
template dbTable(name: string, table_space: string = "") {.pragma.}
|
||||||
template dbKey(name: string = nil, primary_key: bool = false) {.pragma.}
|
template dbKey(name: string = "", primary_key: bool = false) {.pragma.}
|
||||||
template dbForeignKey(t: typedesc) {.pragma.}
|
template dbForeignKey(t: typedesc) {.pragma.}
|
||||||
template dbIgnore {.pragma.}
|
template dbIgnore {.pragma.}
|
||||||
|
|
||||||
|
|
|
||||||
18
doc/tut1.rst
18
doc/tut1.rst
|
|
@ -960,11 +960,7 @@ enforced. For example, when reading strings from binary files, they are merely
|
||||||
a sequence of bytes. The index operation ``s[i]`` means the i-th *char* of
|
a sequence of bytes. The index operation ``s[i]`` means the i-th *char* of
|
||||||
``s``, not the i-th *unichar*.
|
``s``, not the i-th *unichar*.
|
||||||
|
|
||||||
String variables are initialized with a special value, called ``nil``. However,
|
String variables are initialized with the empty strings ``""``.
|
||||||
most string operations cannot deal with ``nil`` (leading to an exception being
|
|
||||||
raised) for performance reasons. It is best to use empty strings ``""``
|
|
||||||
rather than ``nil`` as the *empty* value. But ``""`` often creates a string
|
|
||||||
object on the heap, so there is a trade-off to be made here.
|
|
||||||
|
|
||||||
|
|
||||||
Integers
|
Integers
|
||||||
|
|
@ -1309,11 +1305,7 @@ Example:
|
||||||
x: seq[int] # a reference to a sequence of integers
|
x: seq[int] # a reference to a sequence of integers
|
||||||
x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap
|
x = @[1, 2, 3, 4, 5, 6] # the @ turns the array into a sequence allocated on the heap
|
||||||
|
|
||||||
Sequence variables are initialized with ``nil``. However, most sequence
|
Sequence variables are initialized with ``@[]``.
|
||||||
operations cannot deal with ``nil`` (leading to an exception being
|
|
||||||
raised) for performance reasons. Thus one should use empty sequences ``@[]``
|
|
||||||
rather than ``nil`` as the *empty* value. But ``@[]`` creates a sequence
|
|
||||||
object on the heap, so there is a trade-off to be made here.
|
|
||||||
|
|
||||||
The ``for`` statement can be used with one or two variables when used with a
|
The ``for`` statement can be used with one or two variables when used with a
|
||||||
sequence. When you use the one variable form, the variable will hold the value
|
sequence. When you use the one variable form, the variable will hold the value
|
||||||
|
|
@ -1355,11 +1347,9 @@ type does not matter.
|
||||||
.. code-block:: nim
|
.. code-block:: nim
|
||||||
:test: "nim c $1"
|
:test: "nim c $1"
|
||||||
var
|
var
|
||||||
fruits: seq[string] # reference to a sequence of strings that is initialized with 'nil'
|
fruits: seq[string] # reference to a sequence of strings that is initialized with '@[]'
|
||||||
capitals: array[3, string] # array of strings with a fixed size
|
capitals: array[3, string] # array of strings with a fixed size
|
||||||
|
|
||||||
fruits = @[] # creates an empty sequence on the heap that will be referenced by 'fruits'
|
|
||||||
|
|
||||||
capitals = ["New York", "London", "Berlin"] # array 'capitals' allows assignment of only three elements
|
capitals = ["New York", "London", "Berlin"] # array 'capitals' allows assignment of only three elements
|
||||||
fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime
|
fruits.add("Banana") # sequence 'fruits' is dynamically expandable during runtime
|
||||||
fruits.add("Mango")
|
fruits.add("Mango")
|
||||||
|
|
@ -1691,7 +1681,7 @@ rules apply:
|
||||||
write(stdout, x(3)) # no error: A.x is called
|
write(stdout, x(3)) # no error: A.x is called
|
||||||
write(stdout, x("")) # no error: B.x is called
|
write(stdout, x("")) # no error: B.x is called
|
||||||
|
|
||||||
proc x*(a: int): string = nil
|
proc x*(a: int): string = discard
|
||||||
write(stdout, x(3)) # ambiguous: which `x` is to call?
|
write(stdout, x(3)) # ambiguous: which `x` is to call?
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ proc executeCgi(server: var TServer, client: Socket, path, query: string,
|
||||||
dataAvail = recvLine(client, buf)
|
dataAvail = recvLine(client, buf)
|
||||||
if buf.len == 0:
|
if buf.len == 0:
|
||||||
break
|
break
|
||||||
var L = toLower(buf)
|
var L = toLowerAscii(buf)
|
||||||
if L.startsWith("content-length:"):
|
if L.startsWith("content-length:"):
|
||||||
var i = len("content-length:")
|
var i = len("content-length:")
|
||||||
while L[i] in Whitespace: inc(i)
|
while L[i] in Whitespace: inc(i)
|
||||||
|
|
@ -205,7 +205,7 @@ proc acceptRequest(server: var TServer, client: Socket) =
|
||||||
client.close()
|
client.close()
|
||||||
else:
|
else:
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
var ext = splitFile(path).ext.toLower
|
var ext = splitFile(path).ext.toLowerAscii
|
||||||
if ext == ".exe" or ext == ".cgi":
|
if ext == ".exe" or ext == ".cgi":
|
||||||
# XXX: extract interpreter information here?
|
# XXX: extract interpreter information here?
|
||||||
cgi = true
|
cgi = true
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
from pcre import nil
|
from pcre import nil
|
||||||
import nre.private.util
|
import nre.private.util
|
||||||
import tables
|
import tables
|
||||||
from strutils import toLower, `%`
|
from strutils import `%`
|
||||||
from math import ceil
|
from math import ceil
|
||||||
import options
|
import options
|
||||||
from unicode import runeLenAt
|
from unicode import runeLenAt
|
||||||
|
|
@ -326,15 +326,15 @@ proc `$`*(pattern: RegexMatch): string =
|
||||||
|
|
||||||
proc `==`*(a, b: Regex): bool =
|
proc `==`*(a, b: Regex): bool =
|
||||||
if not a.isNil and not b.isNil:
|
if not a.isNil and not b.isNil:
|
||||||
return a.pattern == b.pattern and
|
return a.pattern == b.pattern and
|
||||||
a.pcreObj == b.pcreObj and
|
a.pcreObj == b.pcreObj and
|
||||||
a.pcreExtra == b.pcreExtra
|
a.pcreExtra == b.pcreExtra
|
||||||
else:
|
else:
|
||||||
return system.`==`(a, b)
|
return system.`==`(a, b)
|
||||||
|
|
||||||
proc `==`*(a, b: RegexMatch): bool =
|
proc `==`*(a, b: RegexMatch): bool =
|
||||||
return a.pattern == b.pattern and
|
return a.pattern == b.pattern and
|
||||||
a.str == b.str
|
a.str == b.str
|
||||||
# }}}
|
# }}}
|
||||||
|
|
||||||
# Creation & Destruction {{{
|
# Creation & Destruction {{{
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ when defineSsl:
|
||||||
flags: set[SocketFlag]) {.async.} =
|
flags: set[SocketFlag]) {.async.} =
|
||||||
let len = bioCtrlPending(socket.bioOut)
|
let len = bioCtrlPending(socket.bioOut)
|
||||||
if len > 0:
|
if len > 0:
|
||||||
var data = newStringOfCap(len)
|
var data = newString(len)
|
||||||
let read = bioRead(socket.bioOut, addr data[0], len)
|
let read = bioRead(socket.bioOut, addr data[0], len)
|
||||||
assert read != 0
|
assert read != 0
|
||||||
if read < 0:
|
if read < 0:
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped =
|
||||||
if numLines > 0: inc(total, (numLines - 1) * newLine.len)
|
if numLines > 0: inc(total, (numLines - 1) * newLine.len)
|
||||||
|
|
||||||
result = newString(total)
|
result = newString(total)
|
||||||
var
|
var
|
||||||
i = 0
|
i = 0
|
||||||
r = 0
|
r = 0
|
||||||
currLine = 0
|
currLine = 0
|
||||||
|
|
@ -76,7 +76,7 @@ template encodeInternal(s: typed, lineLen: int, newLine: string): untyped =
|
||||||
currLine = 0
|
currLine = 0
|
||||||
|
|
||||||
if i < s.len-1:
|
if i < s.len-1:
|
||||||
let
|
let
|
||||||
a = ord(s[i])
|
a = ord(s[i])
|
||||||
b = ord(s[i+1])
|
b = ord(s[i+1])
|
||||||
result[r] = cb64[a shr 2]
|
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:
|
# total is an upper bound, as we will skip arbitrary whitespace:
|
||||||
result = newString(total)
|
result = newString(total)
|
||||||
|
|
||||||
var
|
var
|
||||||
i = 0
|
i = 0
|
||||||
r = 0
|
r = 0
|
||||||
while true:
|
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:
|
if i < s.len-3:
|
||||||
let
|
let
|
||||||
a = s[i].decodeByte
|
a = s[i].decodeByte
|
||||||
|
|
|
||||||
|
|
@ -74,18 +74,19 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] =
|
||||||
var newByte = 0
|
var newByte = 0
|
||||||
block blockX:
|
block blockX:
|
||||||
while newbyte < key.len:
|
while newbyte < key.len:
|
||||||
if it.key[newbyte] != key[newbyte]:
|
let ch = if newbyte < it.key.len: it.key[newbyte] else: '\0'
|
||||||
newotherbits = it.key[newbyte].ord xor key[newbyte].ord
|
if ch != key[newbyte]:
|
||||||
|
newotherbits = ch.ord xor key[newbyte].ord
|
||||||
break blockX
|
break blockX
|
||||||
inc newbyte
|
inc newbyte
|
||||||
if it.key[newbyte] != '\0':
|
if newbyte < it.key.len:
|
||||||
newotherbits = it.key[newbyte].ord
|
newotherbits = it.key[newbyte].ord
|
||||||
else:
|
else:
|
||||||
return it
|
return it
|
||||||
while (newOtherBits and (newOtherBits-1)) != 0:
|
while (newOtherBits and (newOtherBits-1)) != 0:
|
||||||
newOtherBits = newOtherBits and (newOtherBits-1)
|
newOtherBits = newOtherBits and (newOtherBits-1)
|
||||||
newOtherBits = newOtherBits xor 255
|
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
|
let dir = (1 + (ord(ch) or newOtherBits)) shr 8
|
||||||
|
|
||||||
var inner: Node[T]
|
var inner: Node[T]
|
||||||
|
|
|
||||||
|
|
@ -25,16 +25,16 @@ proc parseCookies*(s: string): StringTableRef =
|
||||||
result = newStringTable(modeCaseInsensitive)
|
result = newStringTable(modeCaseInsensitive)
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
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
|
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
|
var keyend = i-1
|
||||||
if s[i] == '\0': break
|
if i >= s.len: break
|
||||||
inc(i) # skip '='
|
inc(i) # skip '='
|
||||||
var valstart = i
|
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)
|
result[substr(s, keystart, keyend)] = substr(s, valstart, i-1)
|
||||||
if s[i] == '\0': break
|
if i >= s.len: break
|
||||||
inc(i) # skip ';'
|
inc(i) # skip ';'
|
||||||
|
|
||||||
proc setCookie*(key, value: string, domain = "", path = "",
|
proc setCookie*(key, value: string, domain = "", path = "",
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ when defined(windows):
|
||||||
while i < a.len and j < b.len:
|
while i < a.len and j < b.len:
|
||||||
if a[i] in {'-', '_'}: inc i
|
if a[i] in {'-', '_'}: inc i
|
||||||
if b[j] in {'-', '_'}: inc j
|
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 i
|
||||||
inc j
|
inc j
|
||||||
result = i == a.len and j == b.len
|
result = i == a.len and j == b.len
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@
|
||||||
##
|
##
|
||||||
## .. code-block:: Nim
|
## .. code-block:: Nim
|
||||||
## import asyncdispatch, httpclient
|
## import asyncdispatch, httpclient
|
||||||
##
|
##
|
||||||
## proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
|
## proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
|
||||||
## echo("Downloaded ", progress, " of ", total)
|
## echo("Downloaded ", progress, " of ", total)
|
||||||
## echo("Current rate: ", speed div 1000, "kb/s")
|
## echo("Current rate: ", speed div 1000, "kb/s")
|
||||||
|
|
@ -247,7 +247,7 @@ proc parseChunks(s: Socket, timeout: int): string =
|
||||||
var i = 0
|
var i = 0
|
||||||
if chunkSizeStr == "":
|
if chunkSizeStr == "":
|
||||||
httpError("Server terminated connection prematurely")
|
httpError("Server terminated connection prematurely")
|
||||||
while true:
|
while i < chunkSizeStr.len:
|
||||||
case chunkSizeStr[i]
|
case chunkSizeStr[i]
|
||||||
of '0'..'9':
|
of '0'..'9':
|
||||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
|
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)
|
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
|
||||||
of 'A'..'F':
|
of 'A'..'F':
|
||||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
|
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
|
||||||
of '\0':
|
|
||||||
break
|
|
||||||
of ';':
|
of ';':
|
||||||
# http://tools.ietf.org/html/rfc2616#section-3.6.1
|
# http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||||
# We don't care about chunk-extensions.
|
# We don't care about chunk-extensions.
|
||||||
|
|
@ -938,7 +936,7 @@ proc parseChunks(client: HttpClient | AsyncHttpClient): Future[void]
|
||||||
var i = 0
|
var i = 0
|
||||||
if chunkSizeStr == "":
|
if chunkSizeStr == "":
|
||||||
httpError("Server terminated connection prematurely")
|
httpError("Server terminated connection prematurely")
|
||||||
while true:
|
while i < chunkSizeStr.len:
|
||||||
case chunkSizeStr[i]
|
case chunkSizeStr[i]
|
||||||
of '0'..'9':
|
of '0'..'9':
|
||||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('0'))
|
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)
|
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('a') + 10)
|
||||||
of 'A'..'F':
|
of 'A'..'F':
|
||||||
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
|
chunkSize = chunkSize shl 4 or (ord(chunkSizeStr[i]) - ord('A') + 10)
|
||||||
of '\0':
|
|
||||||
break
|
|
||||||
of ';':
|
of ';':
|
||||||
# http://tools.ietf.org/html/rfc2616#section-3.6.1
|
# http://tools.ietf.org/html/rfc2616#section-3.6.1
|
||||||
# We don't care about chunk-extensions.
|
# We don't care about chunk-extensions.
|
||||||
|
|
|
||||||
|
|
@ -190,11 +190,11 @@ proc len*(headers: HttpHeaders): int = return headers.table.len
|
||||||
proc parseList(line: string, list: var seq[string], start: int): int =
|
proc parseList(line: string, list: var seq[string], start: int): int =
|
||||||
var i = 0
|
var i = 0
|
||||||
var current = ""
|
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.skipWhitespace(start + i)
|
||||||
i += line.parseUntil(current, {'\c', '\l', ','}, start + i)
|
i += line.parseUntil(current, {'\c', '\l', ','}, start + i)
|
||||||
list.add(current)
|
list.add(current)
|
||||||
if line[start + i] == ',':
|
if start+i < line.len and line[start + i] == ',':
|
||||||
i.inc # Skip ,
|
i.inc # Skip ,
|
||||||
current.setLen(0)
|
current.setLen(0)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ when false:
|
||||||
var dataAvail = false
|
var dataAvail = false
|
||||||
while dataAvail:
|
while dataAvail:
|
||||||
dataAvail = recvLine(client, buf) # TODO: This is incorrect.
|
dataAvail = recvLine(client, buf) # TODO: This is incorrect.
|
||||||
var L = toLower(buf.string)
|
var L = toLowerAscii(buf.string)
|
||||||
if L.startsWith("content-length:"):
|
if L.startsWith("content-length:"):
|
||||||
var i = len("content-length:")
|
var i = len("content-length:")
|
||||||
while L[i] in Whitespace: inc(i)
|
while L[i] in Whitespace: inc(i)
|
||||||
|
|
@ -199,7 +199,7 @@ when false:
|
||||||
notFound(client)
|
notFound(client)
|
||||||
else:
|
else:
|
||||||
when defined(Windows):
|
when defined(Windows):
|
||||||
var ext = splitFile(path).ext.toLower
|
var ext = splitFile(path).ext.toLowerAscii
|
||||||
if ext == ".exe" or ext == ".cgi":
|
if ext == ".exe" or ext == ".cgi":
|
||||||
# XXX: extract interpreter information here?
|
# XXX: extract interpreter information here?
|
||||||
cgi = true
|
cgi = true
|
||||||
|
|
@ -303,7 +303,7 @@ proc next*(s: var Server) =
|
||||||
if s.reqMethod == "POST":
|
if s.reqMethod == "POST":
|
||||||
# Check for Expect header
|
# Check for Expect header
|
||||||
if s.headers.hasKey("Expect"):
|
if s.headers.hasKey("Expect"):
|
||||||
if s.headers["Expect"].toLower == "100-continue":
|
if s.headers["Expect"].toLowerAscii == "100-continue":
|
||||||
s.client.sendStatus("100 Continue")
|
s.client.sendStatus("100 Continue")
|
||||||
else:
|
else:
|
||||||
s.client.sendStatus("417 Expectation Failed")
|
s.client.sendStatus("417 Expectation Failed")
|
||||||
|
|
@ -427,7 +427,7 @@ proc nextAsync(s: PAsyncHTTPServer) =
|
||||||
if s.reqMethod == "POST":
|
if s.reqMethod == "POST":
|
||||||
# Check for Expect header
|
# Check for Expect header
|
||||||
if s.headers.hasKey("Expect"):
|
if s.headers.hasKey("Expect"):
|
||||||
if s.headers["Expect"].toLower == "100-continue":
|
if s.headers["Expect"].toLowerAscii == "100-continue":
|
||||||
s.client.sendStatus("100 Continue")
|
s.client.sendStatus("100 Continue")
|
||||||
else:
|
else:
|
||||||
s.client.sendStatus("417 Expectation Failed")
|
s.client.sendStatus("417 Expectation Failed")
|
||||||
|
|
|
||||||
|
|
@ -126,7 +126,7 @@ proc substituteLog*(frmt: string, level: Level, args: varargs[string, `$`]): str
|
||||||
var v = ""
|
var v = ""
|
||||||
let app = when defined(js): "" else: getAppFilename()
|
let app = when defined(js): "" else: getAppFilename()
|
||||||
while frmt[i] in IdentChars:
|
while frmt[i] in IdentChars:
|
||||||
v.add(toLower(frmt[i]))
|
v.add(toLowerAscii(frmt[i]))
|
||||||
inc(i)
|
inc(i)
|
||||||
case v
|
case v
|
||||||
of "date": result.add(getDateStr())
|
of "date": result.add(getDateStr())
|
||||||
|
|
|
||||||
|
|
@ -29,21 +29,21 @@ proc validEmailAddress*(s: string): bool {.noSideEffect,
|
||||||
chars = Letters + Digits + {'!','#','$','%','&',
|
chars = Letters + Digits + {'!','#','$','%','&',
|
||||||
'\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'}
|
'\'','*','+','/','=','?','^','_','`','{','}','|','~','-','.'}
|
||||||
var i = 0
|
var i = 0
|
||||||
if s[i] notin chars or s[i] == '.': return false
|
if i >= s.len or s[i] notin chars or s[i] == '.': return false
|
||||||
while s[i] in chars:
|
while i < s.len and s[i] in chars:
|
||||||
if s[i] == '.' and s[i+1] == '.': return false
|
if i+1 < s.len and s[i] == '.' and s[i+1] == '.': return false
|
||||||
inc(i)
|
inc(i)
|
||||||
if s[i] != '@': return false
|
if i >= s.len or s[i] != '@': return false
|
||||||
var j = len(s)-1
|
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)
|
while j >= i and s[j] in Letters: dec(j)
|
||||||
inc(i) # skip '@'
|
inc(i) # skip '@'
|
||||||
while s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i)
|
while i < s.len and s[i] in {'0'..'9', 'a'..'z', '-', '.'}: inc(i)
|
||||||
if s[i] != '\0': return false
|
if i != s.len: return false
|
||||||
|
|
||||||
var x = substr(s, j+1)
|
var x = substr(s, j+1)
|
||||||
if len(x) == 2 and x[0] in Letters and x[1] in Letters: return true
|
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",
|
of "com", "org", "net", "gov", "mil", "biz", "info", "mobi", "name",
|
||||||
"aero", "jobs", "museum": return true
|
"aero", "jobs", "museum": return true
|
||||||
else: return false
|
else: return false
|
||||||
|
|
|
||||||
|
|
@ -1060,18 +1060,17 @@ proc parseCmdLine*(c: string): seq[string] {.
|
||||||
while true:
|
while true:
|
||||||
setLen(a, 0)
|
setLen(a, 0)
|
||||||
# eat all delimiting whitespace
|
# 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):
|
when defined(windows):
|
||||||
# parse a single argument according to the above rules:
|
# parse a single argument according to the above rules:
|
||||||
if c[i] == '\0': break
|
|
||||||
var inQuote = false
|
var inQuote = false
|
||||||
while true:
|
while i < c.len:
|
||||||
case c[i]
|
case c[i]
|
||||||
of '\0': break
|
|
||||||
of '\\':
|
of '\\':
|
||||||
var j = i
|
var j = i
|
||||||
while c[j] == '\\': inc(j)
|
while j < c.len and c[j] == '\\': inc(j)
|
||||||
if c[j] == '"':
|
if j < c.len and c[j] == '"':
|
||||||
for k in 1..(j-i) div 2: a.add('\\')
|
for k in 1..(j-i) div 2: a.add('\\')
|
||||||
if (j-i) mod 2 == 0:
|
if (j-i) mod 2 == 0:
|
||||||
i = j
|
i = j
|
||||||
|
|
@ -1084,7 +1083,7 @@ proc parseCmdLine*(c: string): seq[string] {.
|
||||||
of '"':
|
of '"':
|
||||||
inc(i)
|
inc(i)
|
||||||
if not inQuote: inQuote = true
|
if not inQuote: inQuote = true
|
||||||
elif c[i] == '"':
|
elif i < c.len and c[i] == '"':
|
||||||
a.add(c[i])
|
a.add(c[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
else:
|
else:
|
||||||
|
|
@ -1102,13 +1101,12 @@ proc parseCmdLine*(c: string): seq[string] {.
|
||||||
of '\'', '\"':
|
of '\'', '\"':
|
||||||
var delim = c[i]
|
var delim = c[i]
|
||||||
inc(i) # skip ' or "
|
inc(i) # skip ' or "
|
||||||
while c[i] != '\0' and c[i] != delim:
|
while i < c.len and c[i] != delim:
|
||||||
add a, c[i]
|
add a, c[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
if c[i] != '\0': inc(i)
|
if i < c.len: inc(i)
|
||||||
of '\0': break
|
|
||||||
else:
|
else:
|
||||||
while c[i] > ' ':
|
while i < c.len and c[i] > ' ':
|
||||||
add(a, c[i])
|
add(a, c[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
add(result, a)
|
add(result, a)
|
||||||
|
|
|
||||||
|
|
@ -196,7 +196,7 @@ proc joinPath*(head, tail: string): string {.
|
||||||
else:
|
else:
|
||||||
result = head & tail
|
result = head & tail
|
||||||
else:
|
else:
|
||||||
if tail[0] in {DirSep, AltSep}:
|
if tail.len > 0 and tail[0] in {DirSep, AltSep}:
|
||||||
result = head & tail
|
result = head & tail
|
||||||
else:
|
else:
|
||||||
result = head & DirSep & tail
|
result = head & DirSep & tail
|
||||||
|
|
@ -477,7 +477,7 @@ proc unixToNativePath*(path: string, drive=""): string {.
|
||||||
|
|
||||||
var i = start
|
var i = start
|
||||||
while i < len(path): # ../../../ --> ::::
|
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
|
# parent directory
|
||||||
when defined(macos):
|
when defined(macos):
|
||||||
if result[high(result)] == ':':
|
if result[high(result)] == ':':
|
||||||
|
|
|
||||||
|
|
@ -534,15 +534,15 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
case p.kind
|
case p.kind
|
||||||
of pkEmpty: result = 0 # match of length 0
|
of pkEmpty: result = 0 # match of length 0
|
||||||
of pkAny:
|
of pkAny:
|
||||||
if s[start] != '\0': result = 1
|
if start < s.len: result = 1
|
||||||
else: result = -1
|
else: result = -1
|
||||||
of pkAnyRune:
|
of pkAnyRune:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
result = runeLenAt(s, start)
|
result = runeLenAt(s, start)
|
||||||
else:
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
of pkLetter:
|
of pkLetter:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
var a: Rune
|
var a: Rune
|
||||||
result = start
|
result = start
|
||||||
fastRuneAt(s, result, a)
|
fastRuneAt(s, result, a)
|
||||||
|
|
@ -551,7 +551,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
else:
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
of pkLower:
|
of pkLower:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
var a: Rune
|
var a: Rune
|
||||||
result = start
|
result = start
|
||||||
fastRuneAt(s, result, a)
|
fastRuneAt(s, result, a)
|
||||||
|
|
@ -560,7 +560,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
else:
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
of pkUpper:
|
of pkUpper:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
var a: Rune
|
var a: Rune
|
||||||
result = start
|
result = start
|
||||||
fastRuneAt(s, result, a)
|
fastRuneAt(s, result, a)
|
||||||
|
|
@ -569,7 +569,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
else:
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
of pkTitle:
|
of pkTitle:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
var a: Rune
|
var a: Rune
|
||||||
result = start
|
result = start
|
||||||
fastRuneAt(s, result, a)
|
fastRuneAt(s, result, a)
|
||||||
|
|
@ -578,7 +578,7 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
else:
|
else:
|
||||||
result = -1
|
result = -1
|
||||||
of pkWhitespace:
|
of pkWhitespace:
|
||||||
if s[start] != '\0':
|
if start < s.len:
|
||||||
var a: Rune
|
var a: Rune
|
||||||
result = start
|
result = start
|
||||||
fastRuneAt(s, result, a)
|
fastRuneAt(s, result, a)
|
||||||
|
|
@ -589,15 +589,15 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
of pkGreedyAny:
|
of pkGreedyAny:
|
||||||
result = len(s) - start
|
result = len(s) - start
|
||||||
of pkNewLine:
|
of pkNewLine:
|
||||||
if s[start] == '\L': result = 1
|
if start < s.len and s[start] == '\L': result = 1
|
||||||
elif s[start] == '\C':
|
elif start < s.len and s[start] == '\C':
|
||||||
if s[start+1] == '\L': result = 2
|
if start+1 < s.len and s[start+1] == '\L': result = 2
|
||||||
else: result = 1
|
else: result = 1
|
||||||
else: result = -1
|
else: result = -1
|
||||||
of pkTerminal:
|
of pkTerminal:
|
||||||
result = len(p.term)
|
result = len(p.term)
|
||||||
for i in 0..result-1:
|
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
|
result = -1
|
||||||
break
|
break
|
||||||
of pkTerminalIgnoreCase:
|
of pkTerminalIgnoreCase:
|
||||||
|
|
@ -606,6 +606,9 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
a, b: Rune
|
a, b: Rune
|
||||||
result = start
|
result = start
|
||||||
while i < len(p.term):
|
while i < len(p.term):
|
||||||
|
if result >= s.len:
|
||||||
|
result = -1
|
||||||
|
break
|
||||||
fastRuneAt(p.term, i, a)
|
fastRuneAt(p.term, i, a)
|
||||||
fastRuneAt(s, result, b)
|
fastRuneAt(s, result, b)
|
||||||
if toLower(a) != toLower(b):
|
if toLower(a) != toLower(b):
|
||||||
|
|
@ -621,18 +624,23 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
while true:
|
while true:
|
||||||
fastRuneAt(p.term, i, a)
|
fastRuneAt(p.term, i, a)
|
||||||
if a != Rune('_'): break
|
if a != Rune('_'): break
|
||||||
while true:
|
while result < s.len:
|
||||||
fastRuneAt(s, result, b)
|
fastRuneAt(s, result, b)
|
||||||
if b != Rune('_'): break
|
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
|
result = -1
|
||||||
break
|
break
|
||||||
dec(result, start)
|
dec(result, start)
|
||||||
of pkChar:
|
of pkChar:
|
||||||
if p.ch == s[start]: result = 1
|
if start < s.len and p.ch == s[start]: result = 1
|
||||||
else: result = -1
|
else: result = -1
|
||||||
of pkCharChoice:
|
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
|
else: result = -1
|
||||||
of pkNonTerminal:
|
of pkNonTerminal:
|
||||||
var oldMl = c.ml
|
var oldMl = c.ml
|
||||||
|
|
@ -695,10 +703,10 @@ proc rawMatch*(s: string, p: Peg, start: int, c: var Captures): int {.
|
||||||
of pkGreedyRepChar:
|
of pkGreedyRepChar:
|
||||||
result = 0
|
result = 0
|
||||||
var ch = p.ch
|
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:
|
of pkGreedyRepSet:
|
||||||
result = 0
|
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:
|
of pkOption:
|
||||||
result = max(0, rawMatch(s, p.sons[0], start, c))
|
result = max(0, rawMatch(s, p.sons[0], start, c))
|
||||||
of pkAndPredicate:
|
of pkAndPredicate:
|
||||||
|
|
|
||||||
|
|
@ -1126,7 +1126,7 @@ proc unindent*(s: string, count: Natural, padding: string = " "): string
|
||||||
var indentCount = 0
|
var indentCount = 0
|
||||||
for j in 0..<count.int:
|
for j in 0..<count.int:
|
||||||
indentCount.inc
|
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
|
indentCount = j
|
||||||
break
|
break
|
||||||
result.add(line[indentCount*padding.len .. ^1])
|
result.add(line[indentCount*padding.len .. ^1])
|
||||||
|
|
|
||||||
|
|
@ -1318,24 +1318,23 @@ proc format*(dt: DateTime, f: string): string {.tags: [].}=
|
||||||
result = ""
|
result = ""
|
||||||
var i = 0
|
var i = 0
|
||||||
var currentF = ""
|
var currentF = ""
|
||||||
while true:
|
while i < f.len:
|
||||||
case f[i]
|
case f[i]
|
||||||
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
|
of ' ', '-', '/', ':', '\'', '(', ')', '[', ']', ',':
|
||||||
formatToken(dt, currentF, result)
|
formatToken(dt, currentF, result)
|
||||||
|
|
||||||
currentF = ""
|
currentF = ""
|
||||||
if f[i] == '\0': break
|
|
||||||
|
|
||||||
if f[i] == '\'':
|
if f[i] == '\'':
|
||||||
inc(i) # Skip '
|
inc(i) # Skip '
|
||||||
while f[i] != '\'' and f.len-1 > i:
|
while i < f.len-1 and f[i] != '\'':
|
||||||
result.add(f[i])
|
result.add(f[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
else: result.add(f[i])
|
else: result.add(f[i])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
# Check if the letter being added matches previous accumulated buffer.
|
# 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])
|
currentF.add(f[i])
|
||||||
else:
|
else:
|
||||||
formatToken(dt, currentF, result)
|
formatToken(dt, currentF, result)
|
||||||
|
|
@ -1343,6 +1342,7 @@ proc format*(dt: DateTime, f: string): string {.tags: [].}=
|
||||||
currentF = ""
|
currentF = ""
|
||||||
|
|
||||||
inc(i)
|
inc(i)
|
||||||
|
formatToken(dt, currentF, result)
|
||||||
|
|
||||||
proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} =
|
proc `$`*(dt: DateTime): string {.tags: [], raises: [], benign.} =
|
||||||
## Converts a `DateTime` object to a string representation.
|
## 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
|
dt.month = month.Month
|
||||||
of "MMM":
|
of "MMM":
|
||||||
case value[j..j+2].toLowerAscii():
|
case value[j..j+2].toLowerAscii():
|
||||||
of "jan": dt.month = mJan
|
of "jan": dt.month = mJan
|
||||||
of "feb": dt.month = mFeb
|
of "feb": dt.month = mFeb
|
||||||
of "mar": dt.month = mMar
|
of "mar": dt.month = mMar
|
||||||
of "apr": dt.month = mApr
|
of "apr": dt.month = mApr
|
||||||
of "may": dt.month = mMay
|
of "may": dt.month = mMay
|
||||||
of "jun": dt.month = mJun
|
of "jun": dt.month = mJun
|
||||||
of "jul": dt.month = mJul
|
of "jul": dt.month = mJul
|
||||||
of "aug": dt.month = mAug
|
of "aug": dt.month = mAug
|
||||||
of "sep": dt.month = mSep
|
of "sep": dt.month = mSep
|
||||||
of "oct": dt.month = mOct
|
of "oct": dt.month = mOct
|
||||||
of "nov": dt.month = mNov
|
of "nov": dt.month = mNov
|
||||||
of "dec": dt.month = mDec
|
of "dec": dt.month = mDec
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"Couldn't parse month (MMM), got: " & value)
|
"Couldn't parse month (MMM), got: " & value)
|
||||||
j += 3
|
j += 3
|
||||||
of "MMMM":
|
of "MMMM":
|
||||||
if value.len >= j+7 and value[j..j+6].cmpIgnoreCase("january") == 0:
|
if value.len >= j+7 and value[j..j+6].cmpIgnoreCase("january") == 0:
|
||||||
dt.month = mJan
|
dt.month = mJan
|
||||||
j += 7
|
j += 7
|
||||||
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("february") == 0:
|
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("february") == 0:
|
||||||
dt.month = mFeb
|
dt.month = mFeb
|
||||||
j += 8
|
j += 8
|
||||||
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("march") == 0:
|
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("march") == 0:
|
||||||
dt.month = mMar
|
dt.month = mMar
|
||||||
j += 5
|
j += 5
|
||||||
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("april") == 0:
|
elif value.len >= j+5 and value[j..j+4].cmpIgnoreCase("april") == 0:
|
||||||
dt.month = mApr
|
dt.month = mApr
|
||||||
j += 5
|
j += 5
|
||||||
elif value.len >= j+3 and value[j..j+2].cmpIgnoreCase("may") == 0:
|
elif value.len >= j+3 and value[j..j+2].cmpIgnoreCase("may") == 0:
|
||||||
dt.month = mMay
|
dt.month = mMay
|
||||||
j += 3
|
j += 3
|
||||||
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("june") == 0:
|
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("june") == 0:
|
||||||
dt.month = mJun
|
dt.month = mJun
|
||||||
j += 4
|
j += 4
|
||||||
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("july") == 0:
|
elif value.len >= j+4 and value[j..j+3].cmpIgnoreCase("july") == 0:
|
||||||
dt.month = mJul
|
dt.month = mJul
|
||||||
j += 4
|
j += 4
|
||||||
elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("august") == 0:
|
elif value.len >= j+6 and value[j..j+5].cmpIgnoreCase("august") == 0:
|
||||||
dt.month = mAug
|
dt.month = mAug
|
||||||
j += 6
|
j += 6
|
||||||
elif value.len >= j+9 and value[j..j+8].cmpIgnoreCase("september") == 0:
|
elif value.len >= j+9 and value[j..j+8].cmpIgnoreCase("september") == 0:
|
||||||
dt.month = mSep
|
dt.month = mSep
|
||||||
j += 9
|
j += 9
|
||||||
elif value.len >= j+7 and value[j..j+6].cmpIgnoreCase("october") == 0:
|
elif value.len >= j+7 and value[j..j+6].cmpIgnoreCase("october") == 0:
|
||||||
dt.month = mOct
|
dt.month = mOct
|
||||||
j += 7
|
j += 7
|
||||||
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("november") == 0:
|
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("november") == 0:
|
||||||
dt.month = mNov
|
dt.month = mNov
|
||||||
j += 8
|
j += 8
|
||||||
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("december") == 0:
|
elif value.len >= j+8 and value[j..j+7].cmpIgnoreCase("december") == 0:
|
||||||
dt.month = mDec
|
dt.month = mDec
|
||||||
j += 8
|
j += 8
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
|
|
@ -1521,44 +1521,47 @@ proc parseToken(dt: var DateTime; token, value: string; j: var int) =
|
||||||
j += 4
|
j += 4
|
||||||
of "z":
|
of "z":
|
||||||
dt.isDst = false
|
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
|
dt.utcOffset = 0 - parseInt($value[j+1]) * secondsInHour
|
||||||
elif value[j] == '-':
|
elif ch == '-':
|
||||||
dt.utcOffset = parseInt($value[j+1]) * secondsInHour
|
dt.utcOffset = parseInt($value[j+1]) * secondsInHour
|
||||||
elif value[j] == 'Z':
|
elif ch == 'Z':
|
||||||
dt.utcOffset = 0
|
dt.utcOffset = 0
|
||||||
j += 1
|
j += 1
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"Couldn't parse timezone offset (z), got: " & value[j])
|
"Couldn't parse timezone offset (z), got: " & ch)
|
||||||
j += 2
|
j += 2
|
||||||
of "zz":
|
of "zz":
|
||||||
dt.isDst = false
|
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
|
dt.utcOffset = 0 - value[j+1..j+2].parseInt() * secondsInHour
|
||||||
elif value[j] == '-':
|
elif ch == '-':
|
||||||
dt.utcOffset = value[j+1..j+2].parseInt() * secondsInHour
|
dt.utcOffset = value[j+1..j+2].parseInt() * secondsInHour
|
||||||
elif value[j] == 'Z':
|
elif ch == 'Z':
|
||||||
dt.utcOffset = 0
|
dt.utcOffset = 0
|
||||||
j += 1
|
j += 1
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"Couldn't parse timezone offset (zz), got: " & value[j])
|
"Couldn't parse timezone offset (zz), got: " & ch)
|
||||||
j += 3
|
j += 3
|
||||||
of "zzz":
|
of "zzz":
|
||||||
dt.isDst = false
|
dt.isDst = false
|
||||||
var factor = 0
|
var factor = 0
|
||||||
if value[j] == '+': factor = -1
|
let ch = if j < value.len: value[j] else: '\0'
|
||||||
elif value[j] == '-': factor = 1
|
if ch == '+': factor = -1
|
||||||
elif value[j] == 'Z':
|
elif ch == '-': factor = 1
|
||||||
|
elif ch == 'Z':
|
||||||
dt.utcOffset = 0
|
dt.utcOffset = 0
|
||||||
j += 1
|
j += 1
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
raise newException(ValueError,
|
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
|
dt.utcOffset = factor * value[j+1..j+2].parseInt() * secondsInHour
|
||||||
j += 4
|
j += 4
|
||||||
dt.utcOffset += factor * value[j..j+1].parseInt() * 60
|
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.nanosecond = 0
|
||||||
dt.isDst = true # using this is flag for checking whether a timezone has \
|
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)
|
# been read (because DST is always false when a tz is parsed)
|
||||||
while true:
|
while i < layout.len:
|
||||||
case layout[i]
|
case layout[i]
|
||||||
of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',':
|
of ' ', '-', '/', ':', '\'', '(', ')', '[', ']', ',':
|
||||||
if token.len > 0:
|
if token.len > 0:
|
||||||
parseToken(dt, token, value, j)
|
parseToken(dt, token, value, j)
|
||||||
# Reset token
|
# Reset token
|
||||||
token = ""
|
token = ""
|
||||||
# Break if at end of line
|
|
||||||
if layout[i] == '\0': break
|
|
||||||
# Skip separator and everything between single quotes
|
# Skip separator and everything between single quotes
|
||||||
# These are literals in both the layout and the value string
|
# These are literals in both the layout and the value string
|
||||||
if layout[i] == '\'':
|
if layout[i] == '\'':
|
||||||
inc(i)
|
inc(i)
|
||||||
while layout[i] != '\'' and layout.len-1 > i:
|
while i < layout.len-1 and layout[i] != '\'':
|
||||||
inc(i)
|
inc(i)
|
||||||
inc(j)
|
inc(j)
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
@ -1642,13 +1643,15 @@ proc parse*(value, layout: string, zone: Timezone = local()): DateTime =
|
||||||
inc(j)
|
inc(j)
|
||||||
else:
|
else:
|
||||||
# Check if the letter being added matches previous accumulated buffer.
|
# 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])
|
token.add(layout[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
else:
|
else:
|
||||||
parseToken(dt, token, value, j)
|
parseToken(dt, token, value, j)
|
||||||
token = ""
|
token = ""
|
||||||
|
|
||||||
|
if i >= layout.len and token.len > 0:
|
||||||
|
parseToken(dt, token, value, j)
|
||||||
if dt.isDst:
|
if dt.isDst:
|
||||||
# No timezone parsed - assume timezone is `zone`
|
# No timezone parsed - assume timezone is `zone`
|
||||||
result = initDateTime(zone.zoneInfoFromTz(dt.toAdjTime), zone)
|
result = initDateTime(zone.zoneInfoFromTz(dt.toAdjTime), zone)
|
||||||
|
|
|
||||||
|
|
@ -232,10 +232,10 @@ proc createAttributeNS*(doc: PDocument, namespaceURI: string, qualifiedName: str
|
||||||
raise newException(EInvalidCharacterErr, "Invalid character")
|
raise newException(EInvalidCharacterErr, "Invalid character")
|
||||||
# Exceptions
|
# Exceptions
|
||||||
if qualifiedName.contains(':'):
|
if qualifiedName.contains(':'):
|
||||||
let qfnamespaces = qualifiedName.toLower().split(':')
|
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
|
||||||
if isNil(namespaceURI):
|
if isNil(namespaceURI):
|
||||||
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
|
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
|
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
|
||||||
qfnamespaces[1] notin stdattrnames:
|
qfnamespaces[1] notin stdattrnames:
|
||||||
raise newException(ENamespaceErr,
|
raise newException(ENamespaceErr,
|
||||||
|
|
@ -311,10 +311,10 @@ proc createElement*(doc: PDocument, tagName: string): PElement =
|
||||||
proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
|
proc createElementNS*(doc: PDocument, namespaceURI: string, qualifiedName: string): PElement =
|
||||||
## Creates an element of the given qualified name and namespace URI.
|
## Creates an element of the given qualified name and namespace URI.
|
||||||
if qualifiedName.contains(':'):
|
if qualifiedName.contains(':'):
|
||||||
let qfnamespaces = qualifiedName.toLower().split(':')
|
let qfnamespaces = qualifiedName.toLowerAscii().split(':')
|
||||||
if isNil(namespaceURI):
|
if isNil(namespaceURI):
|
||||||
raise newException(ENamespaceErr, "When qualifiedName contains a prefix namespaceURI cannot be nil")
|
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
|
namespaceURI != "http://www.w3.org/XML/1998/namespace" and
|
||||||
qfnamespaces[1] notin stdattrnames:
|
qfnamespaces[1] notin stdattrnames:
|
||||||
raise newException(ENamespaceErr,
|
raise newException(ENamespaceErr,
|
||||||
|
|
@ -533,13 +533,13 @@ proc `prefix=`*(n: PNode, value: string) =
|
||||||
|
|
||||||
if isNil(n.fNamespaceURI):
|
if isNil(n.fNamespaceURI):
|
||||||
raise newException(ENamespaceErr, "namespaceURI cannot be nil")
|
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,
|
raise newException(ENamespaceErr,
|
||||||
"When the namespace prefix is \"xml\" namespaceURI has to be \"http://www.w3.org/XML/1998/namespace\"")
|
"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,
|
raise newException(ENamespaceErr,
|
||||||
"When the namespace prefix is \"xmlns\" namespaceURI has to be \"http://www.w3.org/2000/xmlns/\"")
|
"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\"")
|
raise newException(ENamespaceErr, "An AttributeNode cannot have a prefix of \"xmlns\"")
|
||||||
|
|
||||||
n.fNodeName = value & ":" & n.fLocalName
|
n.fNodeName = value & ":" & n.fLocalName
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
# bug 2007
|
# bug 2007
|
||||||
|
|
||||||
import asyncdispatch, asyncnet, logging, json, uri, strutils, future
|
import asyncdispatch, asyncnet, logging, json, uri, strutils, sugar
|
||||||
|
|
||||||
type
|
type
|
||||||
Builder = ref object
|
Builder = ref object
|
||||||
|
|
@ -27,7 +27,7 @@ proc newBuild*(onProgress: ProgressCB): Build =
|
||||||
result.onProgress = onProgress
|
result.onProgress = onProgress
|
||||||
|
|
||||||
proc start(build: Build, repo, hash: string) {.async.} =
|
proc start(build: Build, repo, hash: string) {.async.} =
|
||||||
let path = repo.parseUri().path.toLower()
|
let path = repo.parseUri().path.toLowerAscii()
|
||||||
|
|
||||||
proc onProgress(builder: Builder, message: string) {.async.} =
|
proc onProgress(builder: Builder, message: string) {.async.} =
|
||||||
debug($message)
|
debug($message)
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ type
|
||||||
s.pop() is T
|
s.pop() is T
|
||||||
|
|
||||||
type ValueType = T
|
type ValueType = T
|
||||||
const ValueTypeName = T.name.toUpper
|
const ValueTypeName = T.name.toUpperAscii
|
||||||
|
|
||||||
proc genericAlgorithm[T](s: var Stack[T], y: T) =
|
proc genericAlgorithm[T](s: var Stack[T], y: T) =
|
||||||
static:
|
static:
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ task "install", "compile and install nake binary":
|
||||||
for index, dir in pairs(path):
|
for index, dir in pairs(path):
|
||||||
echo " ", index, ". ", dir
|
echo " ", index, ". ", dir
|
||||||
echo "Where to install nake binary? (quit with ^C or quit or exit)"
|
echo "Where to install nake binary? (quit with ^C or quit or exit)"
|
||||||
let ans = stdin.readLine().toLower
|
let ans = stdin.readLine().toLowerAscii
|
||||||
var index = 0
|
var index = 0
|
||||||
case ans
|
case ans
|
||||||
of "q", "quit", "x", "exit":
|
of "q", "quit", "x", "exit":
|
||||||
|
|
|
||||||
|
|
@ -562,7 +562,7 @@ proc importItem(data: PJsonNode; errors: var seq[string]): PItemRecord =
|
||||||
|
|
||||||
result.useSound = importSound(data[2], errors, "useSound")
|
result.useSound = importSound(data[2], errors, "useSound")
|
||||||
|
|
||||||
case data[1].str.toLower
|
case data[1].str.toLowerAscii
|
||||||
of "projectile":
|
of "projectile":
|
||||||
result.kind = Projectile
|
result.kind = Projectile
|
||||||
if data[2]["bullet"].kind == JString:
|
if data[2]["bullet"].kind == JString:
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ task "download", "download game assets":
|
||||||
if existsFile(path):
|
if existsFile(path):
|
||||||
echo "The file already exists\n",
|
echo "The file already exists\n",
|
||||||
"[R]emove [M]ove [Q]uit [S]kip Source: ", GameAssets
|
"[R]emove [M]ove [Q]uit [S]kip Source: ", GameAssets
|
||||||
case stdin.readLine.toLower
|
case stdin.readLine.toLowerAscii
|
||||||
of "r":
|
of "r":
|
||||||
removeFile path
|
removeFile path
|
||||||
of "m":
|
of "m":
|
||||||
|
|
@ -120,7 +120,7 @@ task "download", "download game assets":
|
||||||
|
|
||||||
echo "Download binary libs? Only libs for linux are available currently, enjoy the irony.\n",
|
echo "Download binary libs? Only libs for linux are available currently, enjoy the irony.\n",
|
||||||
"[Y]es [N]o Source: ", BinLibs
|
"[Y]es [N]o Source: ", BinLibs
|
||||||
case stdin.readline.toLower
|
case stdin.readline.toLowerAscii
|
||||||
of "y", "yes":
|
of "y", "yes":
|
||||||
discard ## o_O
|
discard ## o_O
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ discard """
|
||||||
|
|
||||||
import strutils
|
import strutils
|
||||||
|
|
||||||
var x = "hello world!".toLower.toUpper
|
var x = "hello world!".toLowerAscii.toUpperAscii
|
||||||
x.echo()
|
x.echo()
|
||||||
#OUT HELLO WORLD!
|
#OUT HELLO WORLD!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import strutils
|
||||||
proc foo(s: static[string]): string =
|
proc foo(s: static[string]): string =
|
||||||
static: echo s
|
static: echo s
|
||||||
|
|
||||||
const R = s.toUpper
|
const R = s.toUpperAscii
|
||||||
return R
|
return R
|
||||||
|
|
||||||
echo foo("test 1")
|
echo foo("test 1")
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -30,7 +30,6 @@ else:
|
||||||
result = newString(size)
|
result = newString(size)
|
||||||
let res = WideCharToMultiByte(CP_UTF8, 0'i32, cast[LPWCSTR](addr(wc[0])), wclen,
|
let res = WideCharToMultiByte(CP_UTF8, 0'i32, cast[LPWCSTR](addr(wc[0])), wclen,
|
||||||
cstring(result), size, cstring(nil), LPBOOL(nil))
|
cstring(result), size, cstring(nil), LPBOOL(nil))
|
||||||
result[size] = chr(0)
|
|
||||||
doAssert size == res
|
doAssert size == res
|
||||||
|
|
||||||
proc testCP(wc: WideCString, lo, hi: int) =
|
proc testCP(wc: WideCString, lo, hi: int) =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue