Merge branch 'devel' into feature/async-streams
This commit is contained in:
commit
1961e444c3
115 changed files with 2208 additions and 877 deletions
|
|
@ -46,7 +46,7 @@ proc reverse*[T](a: var openArray[T], first, last: Natural) =
|
|||
|
||||
proc reverse*[T](a: var openArray[T]) =
|
||||
## reverses the array `a`.
|
||||
reverse(a, 0, a.high)
|
||||
reverse(a, 0, max(0, a.high))
|
||||
|
||||
proc reversed*[T](a: openArray[T], first: Natural, last: int): seq[T] =
|
||||
## returns the reverse of the array `a[first..last]`.
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
##
|
||||
## waitFor server.serve(Port(8080), cb)
|
||||
|
||||
import tables, asyncnet, asyncdispatch, parseutils, uri, strutils
|
||||
import tables, asyncnet, asyncdispatch, parseutils, uri, strutils, nativesockets
|
||||
import httpcore
|
||||
|
||||
export httpcore except parseHeader
|
||||
|
|
@ -241,7 +241,7 @@ proc serve*(server: AsyncHttpServer, port: Port,
|
|||
## specified address and port.
|
||||
##
|
||||
## When a request is made by a client the specified callback will be called.
|
||||
server.socket = newAsyncSocket()
|
||||
server.socket = newAsyncSocket(AF_INET6)
|
||||
if server.reuseAddr:
|
||||
server.socket.setSockOpt(OptReuseAddr, true)
|
||||
if server.reusePort:
|
||||
|
|
|
|||
|
|
@ -77,8 +77,10 @@ proc pop*[T](heap: var HeapQueue[T]): T =
|
|||
proc del*[T](heap: var HeapQueue[T], index: int) =
|
||||
## Removes element at `index`, maintaining the heap invariant.
|
||||
swap(seq[T](heap)[^1], seq[T](heap)[index])
|
||||
seq[T](heap).setLen(heap.len - 1)
|
||||
heap.siftup(index)
|
||||
let newLen = heap.len - 1
|
||||
seq[T](heap).setLen(newLen)
|
||||
if index < newLen:
|
||||
heap.siftup(index)
|
||||
|
||||
proc replace*[T](heap: var HeapQueue[T], item: T): T =
|
||||
## Pop and return the current smallest value, and add the new item.
|
||||
|
|
@ -101,16 +103,19 @@ proc pushpop*[T](heap: var HeapQueue[T], item: T): T =
|
|||
return item
|
||||
|
||||
when isMainModule:
|
||||
proc toSortedSeq[T](h: HeapQueue[T]): seq[T] =
|
||||
var tmp = h
|
||||
result = @[]
|
||||
while tmp.len > 0:
|
||||
result.add(pop(tmp))
|
||||
|
||||
block: # Simple sanity test
|
||||
var heap = newHeapQueue[int]()
|
||||
let data = [1, 3, 5, 7, 9, 2, 4, 6, 8, 0]
|
||||
for item in data:
|
||||
push(heap, item)
|
||||
doAssert(heap[0] == 0)
|
||||
var sort = newSeq[int]()
|
||||
while heap.len > 0:
|
||||
sort.add(pop(heap))
|
||||
doAssert(sort == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
doAssert(heap.toSortedSeq == @[0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
|
||||
|
||||
block: # Test del
|
||||
var heap = newHeapQueue[int]()
|
||||
|
|
@ -121,11 +126,27 @@ when isMainModule:
|
|||
doAssert(heap[0] == 1)
|
||||
|
||||
heap.del(seq[int](heap).find(7))
|
||||
heap.del(seq[int](heap).find(5))
|
||||
heap.del(seq[int](heap).find(6))
|
||||
heap.del(seq[int](heap).find(2))
|
||||
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 5, 6, 8, 9])
|
||||
|
||||
var sort = newSeq[int]()
|
||||
while heap.len > 0:
|
||||
sort.add(pop(heap))
|
||||
doAssert(sort == @[1, 3, 4, 8, 9])
|
||||
heap.del(seq[int](heap).find(5))
|
||||
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 6, 8, 9])
|
||||
|
||||
heap.del(seq[int](heap).find(6))
|
||||
doAssert(heap.toSortedSeq == @[1, 2, 3, 4, 8, 9])
|
||||
|
||||
heap.del(seq[int](heap).find(2))
|
||||
doAssert(heap.toSortedSeq == @[1, 3, 4, 8, 9])
|
||||
|
||||
block: # Test del last
|
||||
var heap = newHeapQueue[int]()
|
||||
let data = [1, 2, 3]
|
||||
for item in data: push(heap, item)
|
||||
|
||||
heap.del(2)
|
||||
doAssert(heap.toSortedSeq == @[1, 2])
|
||||
|
||||
heap.del(1)
|
||||
doAssert(heap.toSortedSeq == @[1])
|
||||
|
||||
heap.del(0)
|
||||
doAssert(heap.toSortedSeq == @[])
|
||||
|
|
|
|||
|
|
@ -225,7 +225,7 @@ proc foreignDepInstallCmd*(foreignPackageName: string): (string, bool) =
|
|||
else:
|
||||
result = ("<your package manager here> install " & p, true)
|
||||
else:
|
||||
result = ("brew install " & p, true)
|
||||
result = ("brew install " & p, false)
|
||||
|
||||
proc foreignDep*(foreignPackageName: string) =
|
||||
## Registers 'foreignPackageName' to the internal list of foreign deps.
|
||||
|
|
|
|||
|
|
@ -127,6 +127,15 @@ proc hash*(x: string): Hash =
|
|||
h = h !& ord(x[i])
|
||||
result = !$h
|
||||
|
||||
proc hash*(x: cstring): Hash =
|
||||
## efficient hashing of null-terminated strings
|
||||
var h: Hash = 0
|
||||
var i = 0
|
||||
while x[i] != 0.char:
|
||||
h = h !& ord(x[i])
|
||||
inc i
|
||||
result = !$h
|
||||
|
||||
proc hash*(sBuf: string, sPos, ePos: int): Hash =
|
||||
## efficient hashing of a string buffer, from starting
|
||||
## position `sPos` to ending position `ePos`
|
||||
|
|
@ -239,6 +248,7 @@ proc hash*[A](x: set[A]): Hash =
|
|||
|
||||
when isMainModule:
|
||||
doAssert( hash("aa bb aaaa1234") == hash("aa bb aaaa1234", 0, 13) )
|
||||
doAssert( hash("aa bb aaaa1234") == hash(cstring("aa bb aaaa1234")) )
|
||||
doAssert( hashIgnoreCase("aa bb aaaa1234") == hash("aa bb aaaa1234") )
|
||||
doAssert( hashIgnoreStyle("aa bb aaaa1234") == hashIgnoreCase("aa bb aaaa1234") )
|
||||
let xx = @['H','e','l','l','o']
|
||||
|
|
|
|||
|
|
@ -206,6 +206,8 @@ proc parseHeader*(line: string): tuple[key: string, value: seq[string]] =
|
|||
inc(i) # skip :
|
||||
if i < len(line):
|
||||
i += parseList(line, result.value, i)
|
||||
elif result.key.len > 0:
|
||||
result.value = @[""]
|
||||
else:
|
||||
result.value = @[]
|
||||
|
||||
|
|
@ -318,4 +320,6 @@ when isMainModule:
|
|||
let (key, value) = parseHeader("foobar: ")
|
||||
test = newHttpHeaders()
|
||||
test[key] = value
|
||||
doAssert test["foobar"] == ""
|
||||
doAssert test["foobar"] == ""
|
||||
|
||||
doAssert parseHeader("foobar:") == ("foobar", @[""])
|
||||
|
|
@ -952,7 +952,7 @@ proc newIndent(curr, indent: int, ml: bool): int =
|
|||
else: return indent
|
||||
|
||||
proc nl(s: var string, ml: bool) =
|
||||
if ml: s.add("\n")
|
||||
s.add(if ml: "\n" else: " ")
|
||||
|
||||
proc escapeJson*(s: string; result: var string) =
|
||||
## Converts a string `s` to its JSON representation.
|
||||
|
|
@ -986,15 +986,14 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
|
|||
lstArr = false, currIndent = 0) =
|
||||
case node.kind
|
||||
of JObject:
|
||||
if currIndent != 0 and not lstArr: result.nl(ml)
|
||||
result.indent(currIndent) # Indentation
|
||||
if lstArr: result.indent(currIndent) # Indentation
|
||||
if node.fields.len > 0:
|
||||
result.add("{")
|
||||
result.nl(ml) # New line
|
||||
var i = 0
|
||||
for key, val in pairs(node.fields):
|
||||
if i > 0:
|
||||
result.add(", ")
|
||||
result.add(",")
|
||||
result.nl(ml) # New Line
|
||||
inc i
|
||||
# Need to indent more than {
|
||||
|
|
@ -1030,7 +1029,7 @@ proc toPretty(result: var string, node: JsonNode, indent = 2, ml = true,
|
|||
result.nl(ml)
|
||||
for i in 0..len(node.elems)-1:
|
||||
if i > 0:
|
||||
result.add(", ")
|
||||
result.add(",")
|
||||
result.nl(ml) # New Line
|
||||
toPretty(result, node.elems[i], indent, ml,
|
||||
true, newIndent(currIndent, indent, ml))
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@
|
|||
##
|
||||
## **Warning:** The global list of handlers is a thread var, this means that
|
||||
## the handlers must be re-added in each thread.
|
||||
## **Warning:** When logging on disk or console, only error and fatal messages
|
||||
## are flushed out immediately. Use flushFile() where needed.
|
||||
|
||||
import strutils, times
|
||||
when not defined(js):
|
||||
|
|
|
|||
|
|
@ -1002,8 +1002,8 @@ iterator walkDir*(dir: string; relative=false): tuple[kind: PathComponent, path:
|
|||
|
||||
iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {.
|
||||
tags: [ReadDirEffect].} =
|
||||
## walks over the directory `dir` and yields for each file in `dir`. The
|
||||
## full path for each file is returned.
|
||||
## Recursively walks over the directory `dir` and yields for each file in `dir`.
|
||||
## The full path for each file is returned. Directories are not returned.
|
||||
## **Warning**:
|
||||
## Modifying the directory structure while the iterator
|
||||
## is traversing may result in undefined behavior!
|
||||
|
|
@ -1185,7 +1185,7 @@ proc createHardlink*(src, dest: string) =
|
|||
|
||||
proc parseCmdLine*(c: string): seq[string] {.
|
||||
noSideEffect, rtl, extern: "nos$1".} =
|
||||
## Splits a command line into several components;
|
||||
## Splits a `command line`:idx: into several components;
|
||||
## This proc is only occasionally useful, better use the `parseopt` module.
|
||||
##
|
||||
## On Windows, it uses the following parsing rules
|
||||
|
|
|
|||
|
|
@ -250,18 +250,18 @@ proc parseInt*(s: string, number: var int, start = 0): int {.
|
|||
elif result != 0:
|
||||
number = int(res)
|
||||
|
||||
# overflowChecks doesn't work with uint64
|
||||
proc rawParseUInt(s: string, b: var uint64, start = 0): int =
|
||||
# overflowChecks doesn't work with BiggestUInt
|
||||
proc rawParseUInt(s: string, b: var BiggestUInt, start = 0): int =
|
||||
var
|
||||
res = 0'u64
|
||||
prev = 0'u64
|
||||
res = 0.BiggestUInt
|
||||
prev = 0.BiggestUInt
|
||||
i = start
|
||||
if s[i] == '+': inc(i) # Allow
|
||||
if s[i] in {'0'..'9'}:
|
||||
b = 0
|
||||
while s[i] in {'0'..'9'}:
|
||||
prev = res
|
||||
res = res * 10 + (ord(s[i]) - ord('0')).uint64
|
||||
res = res * 10 + (ord(s[i]) - ord('0')).BiggestUInt
|
||||
if prev > res:
|
||||
return 0 # overflowChecks emulation
|
||||
inc(i)
|
||||
|
|
@ -269,13 +269,13 @@ proc rawParseUInt(s: string, b: var uint64, start = 0): int =
|
|||
b = res
|
||||
result = i - start
|
||||
|
||||
proc parseBiggestUInt*(s: string, number: var uint64, start = 0): int {.
|
||||
proc parseBiggestUInt*(s: string, number: var BiggestUInt, start = 0): int {.
|
||||
rtl, extern: "npuParseBiggestUInt", noSideEffect.} =
|
||||
## parses an unsigned integer starting at `start` and stores the value
|
||||
## into `number`.
|
||||
## Result is the number of processed chars or 0 if there is no integer
|
||||
## or overflow detected.
|
||||
var res: uint64
|
||||
var res: BiggestUInt
|
||||
# use 'res' for exception safety (don't write to 'number' in case of an
|
||||
# overflow exception):
|
||||
result = rawParseUInt(s, res, start)
|
||||
|
|
@ -287,12 +287,12 @@ proc parseUInt*(s: string, number: var uint, start = 0): int {.
|
|||
## into `number`.
|
||||
## Result is the number of processed chars or 0 if there is no integer or
|
||||
## overflow detected.
|
||||
var res: uint64
|
||||
var res: BiggestUInt
|
||||
result = parseBiggestUInt(s, res, start)
|
||||
if (sizeof(uint) <= 4) and
|
||||
(res > 0xFFFF_FFFF'u64):
|
||||
raise newException(OverflowError, "overflow")
|
||||
elif result != 0:
|
||||
when sizeof(BiggestUInt) > sizeof(uint) and sizeof(uint) <= 4:
|
||||
if res > 0xFFFF_FFFF'u64:
|
||||
raise newException(OverflowError, "overflow")
|
||||
if result != 0:
|
||||
number = uint(res)
|
||||
|
||||
proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {.
|
||||
|
|
|
|||
|
|
@ -898,7 +898,7 @@ proc toHex*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
|||
|
||||
proc toHex*[T](x: T): string =
|
||||
## Shortcut for ``toHex(x, T.sizeOf * 2)``
|
||||
toHex(x, T.sizeOf * 2)
|
||||
toHex(BiggestInt(x), T.sizeOf * 2)
|
||||
|
||||
proc intToStr*(x: int, minchars: Positive = 1): string {.noSideEffect,
|
||||
rtl, extern: "nsuIntToStr".} =
|
||||
|
|
@ -939,7 +939,7 @@ proc parseUInt*(s: string): uint {.noSideEffect, procvar,
|
|||
if L != s.len or L == 0:
|
||||
raise newException(ValueError, "invalid unsigned integer: " & s)
|
||||
|
||||
proc parseBiggestUInt*(s: string): uint64 {.noSideEffect, procvar,
|
||||
proc parseBiggestUInt*(s: string): BiggestUInt {.noSideEffect, procvar,
|
||||
rtl, extern: "nsuParseBiggestUInt".} =
|
||||
## Parses a decimal unsigned integer value contained in `s`.
|
||||
##
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
## echo "run before each test"
|
||||
##
|
||||
## teardown:
|
||||
## echo "run after each test":
|
||||
## echo "run after each test"
|
||||
##
|
||||
## test "essential truths":
|
||||
## # give up and stop if this fails
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue