From 22f714585b943d0b2457c66a78917113072f4503 Mon Sep 17 00:00:00 2001 From: Emery Hemingway Date: Thu, 17 May 2018 12:56:18 +0200 Subject: Native access to Genode environment Add a 'GenodeEnv' type and a 'componentConstructHook' to the system module. The 'componentConstructHook' allows for detection of POSIX style programs that exit implicitly or native Genode components that initialize to serve RPC requests and OS signals. This hook takes a 'GenodeEnv' argument so that the environment interface is passed cleanly to application code after globals are initialized. This is an typed pointer to a C++ object, procedures for accessing the environment will be available from a Nimble library and not included in the standard library. The standard library has an internal pointer to the environment object but this is not for external use, the undocumented global environment pointer has been removed. --- lib/pure/concurrency/cpuinfo.nim | 8 +++++--- lib/pure/os.nim | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/concurrency/cpuinfo.nim b/lib/pure/concurrency/cpuinfo.nim index f01488811..6d41aa1b2 100644 --- a/lib/pure/concurrency/cpuinfo.nim +++ b/lib/pure/concurrency/cpuinfo.nim @@ -38,8 +38,10 @@ when defined(macosx) or defined(bsd): importc: "sysctl", nodecl.} when defined(genode): - proc affinitySpaceTotal(): cuint {. - importcpp: "genodeEnv->cpu().affinity_space().total()".} + include genode/env + + proc affinitySpaceTotal(env: GenodeEnvPtr): cuint {. + importcpp: "@->cpu().affinity_space().total()".} proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = ## returns the numer of the processors/cores the machine has. @@ -83,7 +85,7 @@ proc countProcessors*(): int {.rtl, extern: "ncpi$1".} = var SC_NPROC_ONLN {.importc: "_SC_NPROC_ONLN", header: "".}: cint result = sysconf(SC_NPROC_ONLN) elif defined(genode): - result = affinitySpaceTotal().int + result = runtimeEnv.affinitySpaceTotal().int else: result = sysconf(SC_NPROCESSORS_ONLN) if result <= 0: result = 0 diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 04afb1eff..5008b904c 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -1440,7 +1440,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [ReadIOEffect].} = elif defined(solaris): result = getApplAux("/proc/" & $getpid() & "/path/a.out") elif defined(genode): - raiseOSError("POSIX command line not supported") + raiseOSError(OSErrorCode(-1), "POSIX command line not supported") elif defined(freebsd) or defined(dragonfly): result = getApplFreebsd() # little heuristic that may work on other POSIX-like systems: -- cgit 1.4.1-2-gfad0 From b2323de9140dfa3a1cbe007274970457bb1ecc76 Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Thu, 7 Jun 2018 21:10:00 +0300 Subject: Fixed compilation error when Sockaddr_in4 or Sockaddr_in6 passed to fromSockAddr --- lib/pure/net.nim | 2 +- tests/stdlib/tnet.nim | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'lib/pure') diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 60817484a..5d2efebee 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -447,7 +447,7 @@ proc fromSockAddr*(sa: Sockaddr_storage | SockAddr | Sockaddr_in | Sockaddr_in6, sl: Socklen, address: var IpAddress, port: var Port) {.inline.} = ## Converts `SockAddr` and `Socklen` to `IpAddress` and `Port`. Raises ## `ObjectConversionError` in case of invalid `sa` and `sl` arguments. - fromSockAddrAux(unsafeAddr sa, sl, address, port) + fromSockAddrAux(cast[ptr Sockaddr_storage](unsafeAddr sa), sl, address, port) when defineSsl: CRYPTO_malloc_init() diff --git a/tests/stdlib/tnet.nim b/tests/stdlib/tnet.nim index 64d690fc9..d364447da 100644 --- a/tests/stdlib/tnet.nim +++ b/tests/stdlib/tnet.nim @@ -66,6 +66,18 @@ block: # "IpAddress/Sockaddr conversion" doAssert(ipaddr_1 == ipaddr_2) doAssert($ipaddr_1 == $ipaddr_2) + if sockaddr.ss_family == AF_INET.toInt: + var sockaddr4: Sockaddr_in + copyMem(addr sockaddr4, addr sockaddr, sizeof(sockaddr4)) + fromSockAddr(sockaddr4, socklen, ipaddr_2, port_2) + elif sockaddr.ss_family == AF_INET6.toInt: + var sockaddr6: Sockaddr_in6 + copyMem(addr sockaddr6, addr sockaddr, sizeof(sockaddr6)) + fromSockAddr(sockaddr6, socklen, ipaddr_2, port_2) + + doAssert(ipaddr_1 == ipaddr_2) + doAssert($ipaddr_1 == $ipaddr_2) + # ipv6 address of example.com test("2606:2800:220:1:248:1893:25c8:1946") -- cgit 1.4.1-2-gfad0 From fbd91a474a86a5a52fe495df00e9a0e1bfa000df Mon Sep 17 00:00:00 2001 From: Dmitry Atamanov Date: Fri, 8 Jun 2018 19:01:40 +0300 Subject: Add the val parameter for CritBitTree[T].incl (#7988) * Add the val parameter for CritBitTree[T].incl * Updated changelog --- changelog.md | 1 + lib/pure/collections/critbits.nim | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) (limited to 'lib/pure') diff --git a/changelog.md b/changelog.md index 6fd12e62f..aae275c1c 100644 --- a/changelog.md +++ b/changelog.md @@ -85,6 +85,7 @@ - The `terminal` module now exports additional procs for generating ANSI color codes as strings. - Added the parameter ``val`` for the ``CritBitTree[int].inc`` proc. +- Added the parameter ``val`` for the ``CritBitTree[T].incl`` proc. - An exception raised from ``test`` block of ``unittest`` now shows its type in the error message - The proc ``tgamma`` was renamed to ``gamma``. ``tgamma`` is deprecated. diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index eaba257ae..2ab65f002 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -175,6 +175,11 @@ proc incl*(c: var CritBitTree[void], key: string) = ## includes `key` in `c`. discard rawInsert(c, key) +proc incl*[T](c: var CritBitTree[T], key: string, val: T) = + ## inserts `key` with value `val` into `c`. + var n = rawInsert(c, key) + n.val = val + proc `[]=`*[T](c: var CritBitTree[T], key: string, val: T) = ## puts a (key, value)-pair into `t`. var n = rawInsert(c, key) @@ -375,3 +380,18 @@ when isMainModule: c.inc("a", 1) assert c["a"] == 1 + + var cf = CritBitTree[float]() + + cf.incl("a", 1.0) + assert cf["a"] == 1.0 + + cf.incl("b", 2.0) + assert cf["b"] == 2.0 + + cf.incl("c", 3.0) + assert cf["c"] == 3.0 + + assert cf.len == 3 + cf.excl("c") + assert cf.len == 2 -- cgit 1.4.1-2-gfad0 From 3e799d7876110d970c365d61c05e887729488e2f Mon Sep 17 00:00:00 2001 From: data-man Date: Fri, 8 Jun 2018 19:29:19 +0300 Subject: Removed redundant conditions in CritBitTree.inc, speedup it. --- lib/pure/collections/critbits.nim | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index 2ab65f002..c94e08098 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -165,11 +165,8 @@ proc containsOrIncl*(c: var CritBitTree[void], key: string): bool = proc inc*(c: var CritBitTree[int]; key: string, val: int = 1) = ## increments `c[key]` by `val`. - let oldCount = c.count var n = rawInsert(c, key) - if c.count >= oldCount or oldCount == 0: - # not a new key: - inc n.val, val + inc n.val, val proc incl*(c: var CritBitTree[void], key: string) = ## includes `key` in `c`. -- cgit 1.4.1-2-gfad0 From 24df909d8a953f2b7ba0e0d1adf3a256042cd9bc Mon Sep 17 00:00:00 2001 From: Kaushal Modi Date: Wed, 6 Jun 2018 17:44:11 -0400 Subject: Make isUpper (and variants) work for strings with non-alpha chars The other variants are isLower, isUpperAscii and isLowerAscii Fixes https://github.com/nim-lang/Nim/issues/7963. This commit changes the behavior and signatures of: - isUpper, isLower in the unicode module - isUpperAscii, isLowerAscii in the strutils module A second mandatory parameter skipNonAlpha is added to these 4 procs. (This change affects only for the case where the input is a *string*.) --- With skipNonAlpha set to true, the behavior mimics the Python isupper and islower behavior i.e. non-alphabetic chars/runes are ignored when checking if the string is upper-case or lower-case. Before this commit: doAssert(not isUpper("A B")) After this commit: doAssert(not isUpper("A B", false)) <-- old behavior doAssert isUpper("A B", true) Below two are equivalent: isUpper("A B", true) isAlpha("A B") and isUpper("A B", false) .. and the similar for other 3 procs. --- changelog.md | 6 +++ lib/pure/strutils.nim | 81 ++++++++++++++++++++++++++--------- lib/pure/unicode.nim | 114 +++++++++++++++++++++++++++++++++++++------------- 3 files changed, 152 insertions(+), 49 deletions(-) (limited to 'lib/pure') diff --git a/changelog.md b/changelog.md index aae275c1c..cb2a4b91d 100644 --- a/changelog.md +++ b/changelog.md @@ -42,6 +42,12 @@ - ``math.`mod` `` for floats now behaves the same as ``mod`` for integers (previously it used floor division like Python). Use ``math.floorMod`` for the old behavior. +- For string inputs, ``unicode.isUpper`` and ``unicode.isLower`` now require a + second mandatory parameter ``skipNonAlpha``. + +- For string inputs, ``strutils.isUpperAscii`` and ``strutils.isLowerAscii`` now + require a second mandatory parameter ``skipNonAlpha``. + #### Breaking changes in the compiler - The undocumented ``#? braces`` parsing mode was removed. diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index a4fd20fdb..bea0a0243 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -150,23 +150,52 @@ proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar, ## characters and there is at least one character in `s`. isImpl isSpaceAscii -proc isLowerAscii*(s: string): bool {.noSideEffect, procvar, - rtl, extern: "nsuIsLowerAsciiStr".} = - ## Checks whether or not `s` contains all lower case characters. +template isCaseImpl(s, charProc, skipNonAlpha) = + var hasAtleastOneAlphaChar = false + if s.len == 0: return false + for c in s: + if skipNonAlpha: + var charIsAlpha = c.isAlphaAscii() + if not hasAtleastOneAlphaChar: + hasAtleastOneAlphaChar = charIsAlpha + if charIsAlpha and (not charProc(c)): + return false + else: + if not charProc(c): + return false + return if skipNonAlpha: hasAtleastOneAlphaChar else: true + +proc isLowerAscii*(s: string, skipNonAlpha: bool): bool = + ## Checks whether ``s`` is lower case. ## ## This checks ASCII characters only. - ## Returns true if all characters in `s` are lower case - ## and there is at least one character in `s`. - isImpl isLowerAscii + ## + ## If ``skipNonAlpha`` is true, returns true if all alphabetical + ## characters in ``s`` are lower case. Returns false if none of the + ## characters in ``s`` are alphabetical. + ## + ## If ``skipNonAlpha`` is false, returns true only if all characters + ## in ``s`` are alphabetical and lower case. + ## + ## For either value of ``skipNonAlpha``, returns false if ``s`` is + ## an empty string. + isCaseImpl(s, isLowerAscii, skipNonAlpha) -proc isUpperAscii*(s: string): bool {.noSideEffect, procvar, - rtl, extern: "nsuIsUpperAsciiStr".} = - ## Checks whether or not `s` contains all upper case characters. +proc isUpperAscii*(s: string, skipNonAlpha: bool): bool = + ## Checks whether ``s`` is upper case. ## ## This checks ASCII characters only. - ## Returns true if all characters in `s` are upper case - ## and there is at least one character in `s`. - isImpl isUpperAscii + ## + ## If ``skipNonAlpha`` is true, returns true if all alphabetical + ## characters in ``s`` are upper case. Returns false if none of the + ## characters in ``s`` are alphabetical. + ## + ## If ``skipNonAlpha`` is false, returns true only if all characters + ## in ``s`` are alphabetical and upper case. + ## + ## For either value of ``skipNonAlpha``, returns false if ``s`` is + ## an empty string. + isCaseImpl(s, isUpperAscii, skipNonAlpha) proc toLowerAscii*(c: char): char {.noSideEffect, procvar, rtl, extern: "nsuToLowerAsciiChar".} = @@ -2516,19 +2545,34 @@ when isMainModule: doAssert(not isLowerAscii('A')) doAssert(not isLowerAscii('5')) doAssert(not isLowerAscii('&')) + doAssert(not isLowerAscii(' ')) - doAssert isLowerAscii("abcd") - doAssert(not isLowerAscii("abCD")) - doAssert(not isLowerAscii("33aa")) + doAssert isLowerAscii("abcd", false) + doAssert(not isLowerAscii("33aa", false)) + doAssert(not isLowerAscii("a b", false)) + + doAssert(not isLowerAscii("abCD", true)) + doAssert isLowerAscii("33aa", true) + doAssert isLowerAscii("a b", true) + doAssert isLowerAscii("1, 2, 3 go!", true) + doAssert(not isLowerAscii(" ", true)) + doAssert(not isLowerAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets doAssert isUpperAscii('A') doAssert(not isUpperAscii('b')) doAssert(not isUpperAscii('5')) doAssert(not isUpperAscii('%')) - doAssert isUpperAscii("ABC") - doAssert(not isUpperAscii("AAcc")) - doAssert(not isUpperAscii("A#$")) + doAssert isUpperAscii("ABC", false) + doAssert(not isUpperAscii("A#$", false)) + doAssert(not isUpperAscii("A B", false)) + + doAssert(not isUpperAscii("AAcc", true)) + doAssert isUpperAscii("A#$", true) + doAssert isUpperAscii("A B", true) + doAssert isUpperAscii("1, 2, 3 GO!", true) + doAssert(not isUpperAscii(" ", true)) + doAssert(not isUpperAscii("(*&#@(^#$ ", true)) # None of the string chars are alphabets doAssert rsplit("foo bar", seps=Whitespace) == @["foo", "bar"] doAssert rsplit(" foo bar", seps=Whitespace, maxsplit=1) == @[" foo", "bar"] @@ -2601,4 +2645,3 @@ bar nonStaticTests() staticTests() static: staticTests() - diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index bfd01be55..978f569ac 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -1392,7 +1392,7 @@ proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} = (c >= 0xfe20 and c <= 0xfe2f)) template runeCheck(s, runeProc) = - ## Common code for rune.isLower, rune.isUpper, etc + ## Common code for isAlpha and isSpace. result = if len(s) == 0: false else: true var @@ -1403,16 +1403,6 @@ template runeCheck(s, runeProc) = fastRuneAt(s, i, rune, doInc=true) result = runeProc(rune) and result -proc isUpper*(s: string): bool {.noSideEffect, procvar, - rtl, extern: "nuc$1Str".} = - ## Returns true iff `s` contains all upper case unicode characters. - runeCheck(s, isUpper) - -proc isLower*(s: string): bool {.noSideEffect, procvar, - rtl, extern: "nuc$1Str".} = - ## Returns true iff `s` contains all lower case unicode characters. - runeCheck(s, isLower) - proc isAlpha*(s: string): bool {.noSideEffect, procvar, rtl, extern: "nuc$1Str".} = ## Returns true iff `s` contains all alphabetic unicode characters. @@ -1423,6 +1413,56 @@ proc isSpace*(s: string): bool {.noSideEffect, procvar, ## Returns true iff `s` contains all whitespace unicode characters. runeCheck(s, isWhiteSpace) +template runeCaseCheck(s, runeProc, skipNonAlpha) = + ## Common code for rune.isLower and rune.isUpper. + if len(s) == 0: return false + + var + i = 0 + rune: Rune + hasAtleastOneAlphaRune = false + + while i < len(s): + fastRuneAt(s, i, rune, doInc=true) + if skipNonAlpha: + var runeIsAlpha = isAlpha(rune) + if not hasAtleastOneAlphaRune: + hasAtleastOneAlphaRune = runeIsAlpha + if runeIsAlpha and (not runeProc(rune)): + return false + else: + if not runeProc(rune): + return false + return if skipNonAlpha: hasAtleastOneAlphaRune else: true + +proc isLower*(s: string, skipNonAlpha: bool): bool = + ## Checks whether ``s`` is lower case. + ## + ## If ``skipNonAlpha`` is true, returns true if all alphabetical + ## runes in ``s`` are lower case. Returns false if none of the + ## runes in ``s`` are alphabetical. + ## + ## If ``skipNonAlpha`` is false, returns true only if all runes in + ## ``s`` are alphabetical and lower case. + ## + ## For either value of ``skipNonAlpha``, returns false if ``s`` is + ## an empty string. + runeCaseCheck(s, isLower, skipNonAlpha) + +proc isUpper*(s: string, skipNonAlpha: bool): bool = + ## Checks whether ``s`` is upper case. + ## + ## If ``skipNonAlpha`` is true, returns true if all alphabetical + ## runes in ``s`` are upper case. Returns false if none of the + ## runes in ``s`` are alphabetical. + ## + ## If ``skipNonAlpha`` is false, returns true only if all runes in + ## ``s`` are alphabetical and upper case. + ## + ## For either value of ``skipNonAlpha``, returns false if ``s`` is + ## an empty string. + runeCaseCheck(s, isUpper, skipNonAlpha) + template convertRune(s, runeProc) = ## Convert runes in `s` using `runeProc` as the converter. result = newString(len(s)) @@ -1755,25 +1795,39 @@ when isMainModule: doAssert(not isSpace("")) doAssert(not isSpace("ΑΓc \td")) - doAssert isLower("a") - doAssert isLower("γ") - doAssert(not isLower("Γ")) - doAssert(not isLower("4")) - doAssert(not isLower("")) - - doAssert isLower("abcdγ") - doAssert(not isLower("abCDΓ")) - doAssert(not isLower("33aaΓ")) - - doAssert isUpper("Γ") - doAssert(not isUpper("b")) - doAssert(not isUpper("α")) - doAssert(not isUpper("✓")) - doAssert(not isUpper("")) - - doAssert isUpper("ΑΒΓ") - doAssert(not isUpper("AAccβ")) - doAssert(not isUpper("A#$β")) + doAssert(not isLower(' '.Rune)) + + doAssert isLower("a", false) + doAssert isLower("γ", true) + doAssert(not isLower("Γ", false)) + doAssert(not isLower("4", true)) + doAssert(not isLower("", false)) + doAssert isLower("abcdγ", false) + doAssert(not isLower("33aaΓ", false)) + doAssert(not isLower("a b", false)) + + doAssert(not isLower("abCDΓ", true)) + doAssert isLower("a b", true) + doAssert isLower("1, 2, 3 go!", true) + doAssert(not isLower(" ", true)) + doAssert(not isLower("(*&#@(^#$✓ ", true)) # None of the string runes are alphabets + + doAssert(not isUpper(' '.Rune)) + + doAssert isUpper("Γ", false) + doAssert(not isUpper("α", false)) + doAssert(not isUpper("", false)) + doAssert isUpper("ΑΒΓ", false) + doAssert(not isUpper("A#$β", false)) + doAssert(not isUpper("A B", false)) + + doAssert(not isUpper("b", true)) + doAssert(not isUpper("✓", true)) + doAssert(not isUpper("AAccβ", true)) + doAssert isUpper("A B", true) + doAssert isUpper("1, 2, 3 GO!", true) + doAssert(not isUpper(" ", true)) + doAssert(not isUpper("(*&#@(^#$✓ ", true)) # None of the string runes are alphabets doAssert toUpper("Γ") == "Γ" doAssert toUpper("b") == "B" -- cgit 1.4.1-2-gfad0 From c2aec1b6c19af8ee24b9da2bedb67836064199a0 Mon Sep 17 00:00:00 2001 From: hlaaf Date: Fri, 8 Jun 2018 23:34:19 +0300 Subject: Change parseEnum to something faster for method parsing in asynchttpserver (#7682) * Add faster method parsing to asynchttpserver * Make it readable * Align case statement --- lib/pure/asynchttpserver.nim | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/asynchttpserver.nim b/lib/pure/asynchttpserver.nim index fe5a835d7..d27c2fb9c 100644 --- a/lib/pure/asynchttpserver.nim +++ b/lib/pure/asynchttpserver.nim @@ -129,6 +129,20 @@ proc parseProtocol(protocol: string): tuple[orig: string, major, minor: int] = proc sendStatus(client: AsyncSocket, status: string): Future[void] = client.send("HTTP/1.1 " & status & "\c\L\c\L") +proc parseUppercaseMethod(name: string): HttpMethod = + result = + case name + of "GET": HttpGet + of "POST": HttpPost + of "HEAD": HttpHead + of "PUT": HttpPut + of "DELETE": HttpDelete + of "PATCH": HttpPatch + of "OPTIONS": HttpOptions + of "CONNECT": HttpConnect + of "TRACE": HttpTrace + else: raise newException(ValueError, "Invalid HTTP method " & name) + proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], client: AsyncSocket, address: string, lineFut: FutureVar[string], @@ -172,8 +186,7 @@ proc processRequest(server: AsyncHttpServer, req: FutureVar[Request], case i of 0: try: - # TODO: this is likely slow. - request.reqMethod = parseEnum[HttpMethod]("http" & linePart) + request.reqMethod = parseUppercaseMethod(linePart) except ValueError: asyncCheck request.respondError(Http400) return -- cgit 1.4.1-2-gfad0