diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim index 46a9177ad9..ff8f768bd3 100644 --- a/compiler/ccgutils.nim +++ b/compiler/ccgutils.nim @@ -181,7 +181,7 @@ proc mangle*(name: string): string = of '_': # we generate names like 'foo_9' for scope disambiguations and so # disallow this here: - if i < name.len-1 and name[i+1] in Digits: + if i > 0 and i < name.len-1 and name[i+1] in Digits: discard else: add(result, c) diff --git a/compiler/vmdeps.nim b/compiler/vmdeps.nim index ebd2f557f6..779d6d2a49 100644 --- a/compiler/vmdeps.nim +++ b/compiler/vmdeps.nim @@ -218,8 +218,13 @@ proc mapTypeToAstX(t: PType; info: TLineInfo; of tyTuple: if inst: result = newNodeX(nkTupleTy) - for s in t.n.sons: - result.add newIdentDefs(s) + # only named tuples have a node, unnamed tuples don't + if t.n.isNil: + for subType in t.sons: + result.add mapTypeToAst(subType, info) + else: + for s in t.n.sons: + result.add newIdentDefs(s) else: result = mapTypeToBracket("tuple", mTuple, t, info) of tySet: result = mapTypeToBracket("set", mSet, t, info) diff --git a/lib/impure/nre.nim b/lib/impure/nre.nim index dda4b033fb..4013182af6 100644 --- a/lib/impure/nre.nim +++ b/lib/impure/nre.nim @@ -516,23 +516,23 @@ iterator findIter*(str: string, pattern: Regex, start = 0, endpos = int.high): R let unicode = uint32(getinfo[culong](pattern, pcre.INFO_OPTIONS) and pcre.UTF8) > 0u32 let strlen = if endpos == int.high: str.len else: endpos+1 - var offset = start var match: Option[RegexMatch] + var neverMatched = true + while true: var flags = 0 - if match.isSome and match.get.matchBounds.a > match.get.matchBounds.b: # 0-len match flags = pcre.NOTEMPTY_ATSTART - match = str.matchImpl(pattern, offset, endpos, flags) if match.isNone: # either the end of the input or the string - # cannot be split here - if offset >= strlen: + # cannot be split here - we also need to bail + # if we've never matched and we've already tried to... + if offset >= strlen or neverMatched: break if matchesCrLf and offset < (str.len - 1) and @@ -546,11 +546,11 @@ iterator findIter*(str: string, pattern: Regex, start = 0, endpos = int.high): R else: offset += 1 else: + neverMatched = false offset = match.get.matchBounds.b + 1 yield match.get - proc find*(str: string, pattern: Regex, start = 0, endpos = int.high): Option[RegexMatch] = ## Finds the given pattern in the string between the end and start ## positions. diff --git a/lib/nimbase.h b/lib/nimbase.h index a5d2616e71..d6763f8ff5 100644 --- a/lib/nimbase.h +++ b/lib/nimbase.h @@ -39,6 +39,7 @@ __clang__ # pragma GCC diagnostic ignored "-Wswitch-bool" # pragma GCC diagnostic ignored "-Wmacro-redefined" # pragma GCC diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers" +# pragma GCC diagnostic ignored "-Wpointer-bool-conversion" #endif #if defined(_MSC_VER) diff --git a/lib/packages/docutils/rstgen.nim b/lib/packages/docutils/rstgen.nim index 47247dd7cf..ce63d780c8 100644 --- a/lib/packages/docutils/rstgen.nim +++ b/lib/packages/docutils/rstgen.nim @@ -870,7 +870,7 @@ proc buildLinesHTMLTable(d: PDoc; params: CodeBlockParams, code: string): d.config.getOrDefault"doc.listing_end" % id) return - var codeLines = 1 + code.strip.countLines + var codeLines = code.strip.countLines assert codeLines > 0 result.beginTable = """
"""
var line = params.startLine
diff --git a/lib/pure/asyncdispatch.nim b/lib/pure/asyncdispatch.nim
index 7fa686f00f..1696c4ed94 100644
--- a/lib/pure/asyncdispatch.nim
+++ b/lib/pure/asyncdispatch.nim
@@ -167,8 +167,12 @@ type
callbacks: Deque[proc ()]
proc processTimers(p: PDispatcherBase) {.inline.} =
- while p.timers.len > 0 and epochTime() >= p.timers[0].finishAt:
+ #Process just part if timers at a step
+ var count = p.timers.len
+ let t = epochTime()
+ while count > 0 and t >= p.timers[0].finishAt:
p.timers.pop().fut.complete()
+ dec count
proc processPendingCallbacks(p: PDispatcherBase) =
while p.callbacks.len > 0:
diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim
index 672eb34a0f..80aa8bb2ce 100644
--- a/lib/pure/asynchttpserver.nim
+++ b/lib/pure/asynchttpserver.nim
@@ -31,7 +31,7 @@
##
## waitFor server.serve(Port(8080), cb)
-import tables, asyncnet, asyncdispatch, parseutils, uri, strutils, nativesockets
+import tables, asyncnet, asyncdispatch, parseutils, uri, strutils
import httpcore
export httpcore except parseHeader
@@ -209,7 +209,9 @@ proc processClient(client: AsyncSocket, address: string,
continue
else:
request.body = await client.recv(contentLength)
- assert request.body.len == contentLength
+ if request.body.len != contentLength:
+ await request.respond(Http400, "Bad Request. Content-Length does not match actual.")
+ continue
elif request.reqMethod == HttpPost:
await request.respond(Http400, "Bad Request. No Content-Length.")
continue
@@ -241,7 +243,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(AF_INET6)
+ server.socket = newAsyncSocket()
if server.reuseAddr:
server.socket.setSockOpt(OptReuseAddr, true)
if server.reusePort:
diff --git a/lib/pure/base64.nim b/lib/pure/base64.nim
index 2fc0b1c5ef..eee03d7ae7 100644
--- a/lib/pure/base64.nim
+++ b/lib/pure/base64.nim
@@ -49,7 +49,7 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat
## `newline` is added.
var total = ((len(s) + 2) div 3) * 4
var numLines = (total + lineLen - 1) div lineLen
- if numLines > 0: inc(total, (numLines-1) * newLine.len)
+ if numLines > 0: inc(total, (numLines - 1) * newLine.len)
result = newString(total)
var i = 0
@@ -66,7 +66,8 @@ template encodeInternal(s: expr, lineLen: int, newLine: string): stmt {.immediat
inc(r, 4)
inc(i, 3)
inc(currLine, 4)
- if currLine >= lineLen and i != s.len-2:
+ # avoid index out of bounds when lineLen == encoded length
+ if currLine >= lineLen and i != s.len-2 and r < total:
for x in items(newLine):
result[r] = x
inc(r)
@@ -155,12 +156,17 @@ when isMainModule:
assert encode("asure.") == "YXN1cmUu"
assert encode("sure.") == "c3VyZS4="
+ const testInputExpandsTo76 = "+++++++++++++++++++++++++++++++++++++++++++++++++++++++++"
+ const testInputExpands = "++++++++++++++++++++++++++++++"
const longText = """Man is distinguished, not only by his reason, but by this
singular passion from other animals, which is a lust of the mind,
that by a perseverance of delight in the continued and indefatigable
generation of knowledge, exceeds the short vehemence of any carnal
pleasure."""
const tests = ["", "abc", "xyz", "man", "leasure.", "sure.", "easure.",
- "asure.", longText]
+ "asure.", longText, testInputExpandsTo76, testInputExpands]
+
for t in items(tests):
assert decode(encode(t)) == t
+ assert decode(encode(t, lineLen=40)) == t
+ assert decode(encode(t, lineLen=76)) == t
\ No newline at end of file
diff --git a/lib/pure/collections/sharedtables.nim b/lib/pure/collections/sharedtables.nim
index 28509caa1e..de573bcb2b 100644
--- a/lib/pure/collections/sharedtables.nim
+++ b/lib/pure/collections/sharedtables.nim
@@ -130,6 +130,52 @@ proc hasKeyOrPut*[A, B](t: var SharedTable[A, B], key: A, val: B): bool =
withLock t:
hasKeyOrPutImpl(enlarge)
+proc withKey*[A, B](t: var SharedTable[A, B], key: A,
+ mapper: proc(key: A, val: var B, pairExists: var bool)) =
+ ## Computes a new mapping for the ``key`` with the specified ``mapper``
+ ## procedure.
+ ##
+ ## The ``mapper`` takes 3 arguments:
+ ## #. ``key`` - the current key, if it exists, or the key passed to
+ ## ``withKey`` otherwise;
+ ## #. ``val`` - the current value, if the key exists, or default value
+ ## of the type otherwise;
+ ## #. ``pairExists`` - ``true`` if the key exists, ``false`` otherwise.
+ ## The ``mapper`` can can modify ``val`` and ``pairExists`` values to change
+ ## the mapping of the key or delete it from the table.
+ ## When adding a value, make sure to set ``pairExists`` to ``true`` along
+ ## with modifying the ``val``.
+ ##
+ ## The operation is performed atomically and other operations on the table
+ ## will be blocked while the ``mapper`` is invoked, so it should be short and
+ ## simple.
+ ##
+ ## Example usage:
+ ##
+ ## .. code-block:: nim
+ ##
+ ## # If value exists, decrement it.
+ ## # If it becomes zero or less, delete the key
+ ## t.withKey(1'i64) do (k: int64, v: var int, pairExists: var bool):
+ ## if pairExists:
+ ## dec v
+ ## if v <= 0:
+ ## pairExists = false
+ withLock t:
+ var hc: Hash
+ var index = rawGet(t, key, hc)
+
+ var pairExists = index >= 0
+ if pairExists:
+ mapper(t.data[index].key, t.data[index].val, pairExists)
+ if not pairExists:
+ delImplIdx(t, index)
+ else:
+ var val: B
+ mapper(key, val, pairExists)
+ if pairExists:
+ maybeRehashPutImpl(enlarge)
+
proc `[]=`*[A, B](t: var SharedTable[A, B], key: A, val: B) =
## puts a (key, value)-pair into `t`.
withLock t:
diff --git a/lib/pure/collections/tableimpl.nim b/lib/pure/collections/tableimpl.nim
index 5e871f08b1..c0d45c3928 100644
--- a/lib/pure/collections/tableimpl.nim
+++ b/lib/pure/collections/tableimpl.nim
@@ -120,9 +120,7 @@ template default[T](t: typedesc[T]): T =
var v: T
v
-template delImpl() {.dirty.} =
- var hc: Hash
- var i = rawGet(t, key, hc)
+template delImplIdx(t, i) =
let msk = maxHash(t)
if i >= 0:
dec(t.counter)
@@ -145,6 +143,11 @@ template delImpl() {.dirty.} =
else:
shallowCopy(t.data[j], t.data[i]) # data[j] will be marked EMPTY next loop
+template delImpl() {.dirty.} =
+ var hc: Hash
+ var i = rawGet(t, key, hc)
+ delImplIdx(t, i)
+
template clearImpl() {.dirty.} =
for i in 0 .. |