From f92d61b1f4e193bd17e1f76722d26f1f0605ad17 Mon Sep 17 00:00:00 2001 From: andri lim Date: Thu, 19 Jul 2018 22:38:40 +0700 Subject: fixes #8037, json.to support object with distinct types (#8086) * add distinct types to json 'to' macro * fix json 'to' macro and add more test --- lib/pure/json.nim | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 67f92dffe..b9279b18c 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -1004,6 +1004,13 @@ proc processElseBranch(recCaseNode, elseBranch, jsonNode, kindType, exprColonExpr.add(ifStmt) proc createConstructor(typeSym, jsonNode: NimNode): NimNode {.compileTime.} + +proc detectDistinctType(typeSym: NimNode): NimNode = + let + typeImpl = getTypeImpl(typeSym) + typeInst = getTypeInst(typeSym) + result = if typeImpl.typeKind == ntyDistinct: typeImpl else: typeInst + proc processObjField(field, jsonNode: NimNode): seq[NimNode] = ## Process a field from a ``RecList``. ## @@ -1022,8 +1029,8 @@ proc processObjField(field, jsonNode: NimNode): seq[NimNode] = # Add the field value. # -> jsonNode["`field`"] let indexedJsonNode = createJsonIndexer(jsonNode, $field) - exprColonExpr.add(createConstructor(getTypeInst(field), indexedJsonNode)) - + let typeNode = detectDistinctType(field) + exprColonExpr.add(createConstructor(typeNode, indexedJsonNode)) of nnkRecCase: # A "case" field that introduces a variant. let exprColonExpr = newNimNode(nnkExprColonExpr) @@ -1248,7 +1255,7 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = let seqT = typeSym[1] let forLoopI = genSym(nskForVar, "i") let indexerNode = createJsonIndexer(jsonNode, forLoopI) - let constructorNode = createConstructor(seqT, indexerNode) + let constructorNode = createConstructor(detectDistinctType(seqT), indexerNode) # Create a statement expression containing a for loop. result = quote do: @@ -1284,7 +1291,10 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = # Handle all other types. let obj = getType(typeSym) - if obj.kind == nnkBracketExpr: + let typeNode = getTypeImpl(typeSym) + if typeNode.typeKind == ntyDistinct: + result = createConstructor(typeNode, jsonNode) + elif obj.kind == nnkBracketExpr: # When `Sym "Foo"` turns out to be a `ref object`. result = createConstructor(obj, jsonNode) else: @@ -1295,6 +1305,21 @@ proc createConstructor(typeSym, jsonNode: NimNode): NimNode = # TODO: The fact that `jsonNode` here works to give a good line number # is weird. Specifying typeSym should work but doesn't. error("Use a named tuple instead of: " & $toStrLit(typeSym), jsonNode) + of nnkDistinctTy: + var baseType = typeSym + # solve nested distinct types + while baseType.typeKind == ntyDistinct: + let impl = getTypeImpl(baseType[0]) + if impl.typeKind != ntyDistinct: + baseType = baseType[0] + break + baseType = impl + let ret = createConstructor(baseType, jsonNode) + let typeInst = getTypeInst(typeSym) + result = quote do: + ( + `typeInst`(`ret`) + ) else: doAssert false, "Unable to create constructor for: " & $typeSym.kind @@ -1418,7 +1443,7 @@ macro to*(node: JsonNode, T: typedesc): untyped = ## doAssert data.person.age == 21 ## doAssert data.list == @[1, 2, 3, 4] - let typeNode = getTypeInst(T) + let typeNode = getTypeImpl(T) expectKind(typeNode, nnkBracketExpr) doAssert(($typeNode[0]).normalize == "typedesc") -- cgit 1.4.1-2-gfad0 From 57f4a5d429b9593791c4544ebdb99ea034c44933 Mon Sep 17 00:00:00 2001 From: skilchen Date: Sat, 21 Jul 2018 19:16:05 +0200 Subject: sequtils: remove some aligning spaces around == to silence warnings --- lib/pure/collections/sequtils.nim | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 44c59c627..db33e41af 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -854,20 +854,20 @@ when isMainModule: doAssert numbers.distribute(6)[0] == @[1, 2] doAssert numbers.distribute(6)[5] == @[7] let a = @[1, 2, 3, 4, 5, 6, 7] - doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]] - doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]] - doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]] - doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]] - doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]] - doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] - doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] - doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] - doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]] - doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]] - doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]] - doAssert a.distribute(6, false) == @[ + doAssert a.distribute(1, true) == @[@[1, 2, 3, 4, 5, 6, 7]] + doAssert a.distribute(1, false) == @[@[1, 2, 3, 4, 5, 6, 7]] + doAssert a.distribute(2, true) == @[@[1, 2, 3, 4], @[5, 6, 7]] + doAssert a.distribute(2, false) == @[@[1, 2, 3, 4], @[5, 6, 7]] + doAssert a.distribute(3, true) == @[@[1, 2, 3], @[4, 5], @[6, 7]] + doAssert a.distribute(3, false) == @[@[1, 2, 3], @[4, 5, 6], @[7]] + doAssert a.distribute(4, true) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] + doAssert a.distribute(4, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7]] + doAssert a.distribute(5, true) == @[@[1, 2], @[3, 4], @[5], @[6], @[7]] + doAssert a.distribute(5, false) == @[@[1, 2], @[3, 4], @[5, 6], @[7], @[]] + doAssert a.distribute(6, true) == @[@[1, 2], @[3], @[4], @[5], @[6], @[7]] + doAssert a.distribute(6, false) == @[ @[1, 2], @[3, 4], @[5, 6], @[7], @[], @[]] - doAssert a.distribute(8, false) == a.distribute(8, true) + doAssert a.distribute(8, false) == a.distribute(8, true) doAssert a.distribute(90, false) == a.distribute(90, true) var b = @[0] for f in 1 .. 25: b.add(f) -- cgit 1.4.1-2-gfad0 From 8fe8bed9c3e94cf5f6068e652b99a050f84d6b3f Mon Sep 17 00:00:00 2001 From: skilchen Date: Sat, 21 Jul 2018 19:51:14 +0200 Subject: add sets.pop procedure (analogue to python) (#8383) --- lib/pure/collections/sets.nim | 12 ++++++++++++ tests/sets/tsetpop.nim | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/sets/tsetpop.nim (limited to 'lib/pure') diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 59c90bc2b..fdc3b4b03 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -347,6 +347,18 @@ proc excl*[A](s: var HashSet[A], other: HashSet[A]) = assert other.isValid, "The set `other` needs to be initialized." for item in other: discard exclImpl(s, item) +proc pop*[A](s: var HashSet[A]): A = + ## Remove and return an arbitrary element from the set `s`. + ## + ## Raises KeyError if the set `s` is empty. + ## + for h in 0..high(s.data): + if isFilled(s.data[h].hcode): + result = s.data[h].key + excl(s, result) + return result + raise newException(KeyError, "set is empty") + proc containsOrIncl*[A](s: var HashSet[A], key: A): bool = ## Includes `key` in the set `s` and tells if `key` was added to `s`. ## diff --git a/tests/sets/tsetpop.nim b/tests/sets/tsetpop.nim new file mode 100644 index 000000000..c37bda57d --- /dev/null +++ b/tests/sets/tsetpop.nim @@ -0,0 +1,22 @@ +discard """ + targets: "c c++ js" + output: '''1000 +0 +set is empty +''' +""" + +import sets + +var a = initSet[int]() +for i in 1..1000: + a.incl(i) +echo len(a) +for i in 1..1000: + discard a.pop() +echo len(a) + +try: + echo a.pop() +except KeyError as e: + echo e.msg \ No newline at end of file -- cgit 1.4.1-2-gfad0 From 9379f9353a73acdb9744ab96c0544fb446b11a6a Mon Sep 17 00:00:00 2001 From: Zachary Carter Date: Sat, 21 Jul 2018 15:42:07 -0400 Subject: Add application/wasm to mimetypes.nim (#8389) ``` To serve wasm in the most efficient way over the network, make sure your web server has the proper MIME time for .wasm files, which is application/wasm. That will allow streaming compilation, where the browser can start to compile code as it downloads. ``` http://kripken.github.io/emscripten-site/docs/compiling/WebAssembly.html#web-server-setup --- lib/pure/mimetypes.nim | 1 + 1 file changed, 1 insertion(+) (limited to 'lib/pure') diff --git a/lib/pure/mimetypes.nim b/lib/pure/mimetypes.nim index ff69ba61e..8f5f3a183 100644 --- a/lib/pure/mimetypes.nim +++ b/lib/pure/mimetypes.nim @@ -231,6 +231,7 @@ const mimes* = { "xcf": "application/x-xcf", "fig": "application/x-xfig", "xpi": "application/x-xpinstall", + "wasm": "application/wasm", "amr": "audio/amr", "awb": "audio/amr-wb", "amr": "audio/amr", -- cgit 1.4.1-2-gfad0 From 503dc222366f7e5d0bbdd7de86a5de1735a17c04 Mon Sep 17 00:00:00 2001 From: Oscar NihlgÄrd Date: Mon, 23 Jul 2018 22:40:39 +0200 Subject: Use enum string values in times.nim (#8413) --- lib/pure/times.nim | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/times.nim b/lib/pure/times.nim index bc4de7ee4..cdb7a4466 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -181,10 +181,27 @@ elif defined(windows): type Month* = enum ## Represents a month. Note that the enum starts at ``1``, so ``ord(month)`` will give ## the month number in the range ``[1..12]``. - mJan = 1, mFeb, mMar, mApr, mMay, mJun, mJul, mAug, mSep, mOct, mNov, mDec + mJan = (1, "January") + mFeb = "February" + mMar = "March" + mApr = "April" + mMay = "May" + mJun = "June" + mJul = "July" + mAug = "August" + mSep = "September" + mOct = "October" + mNov = "November" + mDec = "December" WeekDay* = enum ## Represents a weekday. - dMon, dTue, dWed, dThu, dFri, dSat, dSun + dMon = "Monday" + dTue = "Tuesday" + dWed = "Wednesday" + dThu = "Thursday" + dFri = "Friday" + dSat = "Saturday" + dSun = "Sunday" MonthdayRange* = range[1..31] HourRange* = range[0..23] @@ -1074,20 +1091,6 @@ proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [TimeEffect].} = result = intToStr(ti.hour, 2) & ':' & intToStr(ti.minute, 2) & ':' & intToStr(ti.second, 2) -proc `$`*(day: WeekDay): string = - ## Stringify operator for ``WeekDay``. - const lookup: array[WeekDay, string] = ["Monday", "Tuesday", "Wednesday", - "Thursday", "Friday", "Saturday", "Sunday"] - return lookup[day] - -proc `$`*(m: Month): string = - ## Stringify operator for ``Month``. - const lookup: array[Month, string] = ["January", "February", "March", - "April", "May", "June", "July", "August", "September", "October", - "November", "December"] - return lookup[m] - - proc toParts* (ti: TimeInterval): TimeIntervalParts = ## Converts a `TimeInterval` into an array consisting of its time units, ## starting with nanoseconds and ending with years -- cgit 1.4.1-2-gfad0 From 9249276db0ae2771a5b7fbe32bbe3b751f0a2711 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Mon, 23 Jul 2018 13:58:03 -0700 Subject: addresses issue #8391 show runtime context on some failed operations (#8393) --- lib/pure/includes/oserr.nim | 2 +- lib/pure/os.nim | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/includes/oserr.nim b/lib/pure/includes/oserr.nim index eb350cbd4..493e8e174 100644 --- a/lib/pure/includes/oserr.nim +++ b/lib/pure/includes/oserr.nim @@ -60,7 +60,7 @@ proc raiseOSError*(errorCode: OSErrorCode; additionalInfo = "") {.noinline.} = if additionalInfo.len == 0: e.msg = osErrorMsg(errorCode) else: - e.msg = osErrorMsg(errorCode) & "\nAdditional info: " & additionalInfo + e.msg = osErrorMsg(errorCode) & "\nAdditional info: '" & additionalInfo & "'" if e.msg == "": e.msg = "unknown OS error" raise e diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 84f492c9d..9cc83c372 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -971,7 +971,7 @@ proc rawCreateDir(dir: string): bool = elif errno in {EEXIST, ENOSYS}: result = false else: - raiseOSError(osLastError()) + raiseOSError(osLastError(), dir) elif defined(posix): let res = mkdir(dir, 0o777) if res == 0'i32: @@ -980,7 +980,7 @@ proc rawCreateDir(dir: string): bool = result = false else: #echo res - raiseOSError(osLastError()) + raiseOSError(osLastError(), dir) else: when useWinUnicode: wrapUnary(res, createDirectoryW, dir) @@ -992,7 +992,7 @@ proc rawCreateDir(dir: string): bool = elif getLastError() == 183'i32: result = false else: - raiseOSError(osLastError()) + raiseOSError(osLastError(), dir) proc existsOrCreateDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [WriteDirEffect, ReadDirEffect].} = @@ -1005,7 +1005,7 @@ proc existsOrCreateDir*(dir: string): bool {.rtl, extern: "nos$1", if result: # path already exists - need to check that it is indeed a directory if not existsDir(dir): - raise newException(IOError, "Failed to create the directory") + raise newException(IOError, "Failed to create '" & dir & "'") proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [WriteDirEffect, ReadDirEffect].} = -- cgit 1.4.1-2-gfad0 From 13df8075767c1559f71e7485a23dab3d337ffad1 Mon Sep 17 00:00:00 2001 From: Timothee Cour Date: Mon, 23 Jul 2018 17:26:49 -0700 Subject: fix issue #8349 FileSystemCaseSensitive should be false on OSX (#8411) --- lib/pure/ospaths.nim | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'lib/pure') diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim index 4ae5afd6c..a7ebd9d15 100644 --- a/lib/pure/ospaths.nim +++ b/lib/pure/ospaths.nim @@ -147,7 +147,7 @@ else: # UNIX-like operating system DirSep* = '/' AltSep* = DirSep PathSep* = ':' - FileSystemCaseSensitive* = true + FileSystemCaseSensitive* = when defined(macosx): false else: true ExeExt* = "" ScriptExt* = "" DynlibFormat* = when defined(macosx): "lib$1.dylib" else: "lib$1.so" @@ -410,6 +410,11 @@ proc cmpPaths*(pathA, pathB: string): int {. ## | 0 iff pathA == pathB ## | < 0 iff pathA < pathB ## | > 0 iff pathA > pathB + runnableExamples: + when defined(macosx): + doAssert cmpPaths("foo", "Foo") == 0 + elif defined(posix): + doAssert cmpPaths("foo", "Foo") > 0 if FileSystemCaseSensitive: result = cmp(pathA, pathB) else: -- cgit 1.4.1-2-gfad0 From 34f398d010faa906004fb5802b095a213f083b9c Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Tue, 24 Jul 2018 23:24:14 +0300 Subject: Allow async stdin --- lib/pure/ioselects/ioselectors_epoll.nim | 29 +++++++++++++---------------- lib/pure/ioselects/ioselectors_kqueue.nim | 27 ++++++++++++--------------- lib/pure/ioselects/ioselectors_poll.nim | 25 +++++++++++-------------- lib/pure/ioselects/ioselectors_select.nim | 9 ++++++--- lib/pure/selectors.nim | 9 +++++++++ 5 files changed, 51 insertions(+), 48 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/ioselects/ioselectors_epoll.nim b/lib/pure/ioselects/ioselectors_epoll.nim index 36145abc7..8b3f14f34 100644 --- a/lib/pure/ioselects/ioselectors_epoll.nim +++ b/lib/pure/ioselects/ioselectors_epoll.nim @@ -92,6 +92,9 @@ proc newSelector*[T](): Selector[T] = result.maxFD = maxFD result.fds = newSeq[SelectorKey[T]](maxFD) + for i in 0 ..< maxFD: + result.fds[i].ident = InvalidIdent + proc close*[T](s: Selector[T]) = let res = posix.close(s.epollFD) when hasThreadSupport: @@ -100,12 +103,6 @@ proc close*[T](s: Selector[T]) = if res != 0: raiseIOSelectorsError(osLastError()) -template clearKey[T](key: ptr SelectorKey[T]) = - var empty: T - key.ident = 0 - key.events = {} - key.data = empty - proc newSelectEvent*(): SelectEvent = let fdci = eventfd(0, 0) if fdci == -1: @@ -135,7 +132,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event], data: T) = let fdi = int(fd) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0, "Descriptor $# already registered" % $fdi) + doAssert(s.fds[fdi].ident == InvalidIdent, "Descriptor $# already registered" % $fdi) s.setKey(fdi, events, 0, data) if events != {}: var epv = EpollEvent(events: EPOLLRDHUP) @@ -152,7 +149,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event] let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor $# is not registered in the selector!" % $fdi) doAssert(pkey.events * maskEvents == {}) if pkey.events != events: @@ -180,7 +177,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) = let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor $# is not registered in the selector!" % $fdi) if pkey.events != {}: when not defined(android): @@ -243,7 +240,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) = let fdi = int(ev.efd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, "Event is not registered in the queue!") + doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!") doAssert(Event.User in pkey.events) var epv = EpollEvent() if epoll_ctl(s.epollFD, EPOLL_CTL_DEL, fdi.cint, addr epv) != 0: @@ -262,7 +259,7 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool, setNonBlocking(fdi.cint) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) var events = {Event.Timer} var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP) @@ -307,7 +304,7 @@ when not defined(android): setNonBlocking(fdi.cint) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP) epv.data.u64 = fdi.uint @@ -334,7 +331,7 @@ when not defined(android): setNonBlocking(fdi.cint) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP) epv.data.u64 = fdi.uint @@ -347,7 +344,7 @@ when not defined(android): proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) = let fdi = int(ev.efd) - doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!") + doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!") s.setKey(fdi, {Event.User}, 0, data) var epv = EpollEvent(events: EPOLLIN or EPOLLRDHUP) epv.data.u64 = ev.efd.uint @@ -381,7 +378,7 @@ proc selectInto*[T](s: Selector[T], timeout: int, let fdi = int(resTable[i].data.u64) let pevents = resTable[i].events var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0) + doAssert(pkey.ident != InvalidIdent) var rkey = ReadyKey(fd: fdi, events: {}) if (pevents and EPOLLERR) != 0 or (pevents and EPOLLHUP) != 0: @@ -482,7 +479,7 @@ template isEmpty*[T](s: Selector[T]): bool = (s.count == 0) proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} = - return s.fds[fd.int].ident != 0 + return s.fds[fd.int].ident != InvalidIdent proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T = let fdi = int(fd) diff --git a/lib/pure/ioselects/ioselectors_kqueue.nim b/lib/pure/ioselects/ioselectors_kqueue.nim index 10e23c072..58a381042 100644 --- a/lib/pure/ioselects/ioselectors_kqueue.nim +++ b/lib/pure/ioselects/ioselectors_kqueue.nim @@ -114,6 +114,9 @@ proc newSelector*[T](): Selector[T] = result.fds = newSeq[SelectorKey[T]](maxFD) result.changes = newSeqOfCap[KEvent](MAX_KQUEUE_EVENTS) + for i in 0 ..< MAX_KQUEUE_EVENTS: + result.fds[i].ident = InvalidIdent + result.sock = usock result.kqFD = kqFD result.maxFD = maxFD.int @@ -128,12 +131,6 @@ proc close*[T](s: Selector[T]) = if res1 != 0 or res2 != 0: raiseIOSelectorsError(osLastError()) -template clearKey[T](key: ptr SelectorKey[T]) = - var empty: T - key.ident = 0 - key.events = {} - key.data = empty - proc newSelectEvent*(): SelectEvent = var fds: array[2, cint] if posix.pipe(fds) != 0: @@ -221,7 +218,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event], data: T) = let fdi = int(fd) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) s.setKey(fdi, events, 0, data) if events != {}: @@ -242,7 +239,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor $# is not registered in the queue!" % $fdi) doAssert(pkey.events * maskEvents == {}) @@ -269,7 +266,7 @@ proc registerTimer*[T](s: Selector[T], timeout: int, oneshot: bool, data: T): int {.discardable.} = let fdi = getUnique(s) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) let events = if oneshot: {Event.Timer, Event.Oneshot} else: {Event.Timer} let flags: cushort = if oneshot: EV_ONESHOT or EV_ADD else: EV_ADD @@ -291,7 +288,7 @@ proc registerSignal*[T](s: Selector[T], signal: int, data: T): int {.discardable.} = let fdi = getUnique(s) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) s.setKey(fdi, {Event.Signal}, signal, data) var nmask, omask: Sigset @@ -315,7 +312,7 @@ proc registerProcess*[T](s: Selector[T], pid: int, data: T): int {.discardable.} = let fdi = getUnique(s) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) var kflags: cushort = EV_ONESHOT or EV_ADD setKey(s, fdi, {Event.Process, Event.Oneshot}, pid, data) @@ -331,7 +328,7 @@ proc registerProcess*[T](s: Selector[T], pid: int, proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) = let fdi = ev.rfd.int - doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!") + doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!") setKey(s, fdi, {Event.User}, 0, data) modifyKQueue(s, fdi.uint, EVFILT_READ, EV_ADD, 0, 0, nil) @@ -374,7 +371,7 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) = let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor [" & $fdi & "] is not registered in the queue!") if pkey.events != {}: @@ -434,7 +431,7 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) = let fdi = int(ev.rfd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, "Event is not registered in the queue!") + doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!") doAssert(Event.User in pkey.events) modifyKQueue(s, uint(fdi), EVFILT_READ, EV_DELETE, 0, 0, nil) when not declared(CACHE_EVENTS): @@ -593,7 +590,7 @@ template isEmpty*[T](s: Selector[T]): bool = (s.count == 0) proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} = - return s.fds[fd.int].ident != 0 + return s.fds[fd.int].ident != InvalidIdent proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T = let fdi = int(fd) diff --git a/lib/pure/ioselects/ioselectors_poll.nim b/lib/pure/ioselects/ioselectors_poll.nim index c36750c8d..9d708b0c1 100644 --- a/lib/pure/ioselects/ioselectors_poll.nim +++ b/lib/pure/ioselects/ioselectors_poll.nim @@ -70,6 +70,9 @@ proc newSelector*[T](): Selector[T] = result.fds = newSeq[SelectorKey[T]](maxFD) result.pollfds = newSeq[TPollFd](maxFD) + for i in 0 ..< maxFD: + result.fds[i].ident = InvalidIdent + proc close*[T](s: Selector[T]) = when hasThreadSupport: deinitLock(s.lock) @@ -77,12 +80,6 @@ proc close*[T](s: Selector[T]) = deallocSharedArray(s.pollfds) deallocShared(cast[pointer](s)) -template clearKey[T](key: ptr SelectorKey[T]) = - var empty: T - key.ident = 0 - key.events = {} - key.data = empty - template pollAdd[T](s: Selector[T], sock: cint, events: set[Event]) = withPollLock(s): var pollev: cshort = 0 @@ -135,7 +132,7 @@ proc registerHandle*[T](s: Selector[T], fd: int | SocketHandle, events: set[Event], data: T) = var fdi = int(fd) s.checkFd(fdi) - doAssert(s.fds[fdi].ident == 0) + doAssert(s.fds[fdi].ident == InvalidIdent) setKey(s, fdi, events, 0, data) if events != {}: s.pollAdd(fdi.cint, events) @@ -146,7 +143,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor [" & $fdi & "] is not registered in the queue!") doAssert(pkey.events * maskEvents == {}) @@ -162,7 +159,7 @@ proc updateHandle*[T](s: Selector[T], fd: int | SocketHandle, proc registerEvent*[T](s: Selector[T], ev: SelectEvent, data: T) = var fdi = int(ev.rfd) - doAssert(s.fds[fdi].ident == 0, "Event is already registered in the queue!") + doAssert(s.fds[fdi].ident == InvalidIdent, "Event is already registered in the queue!") var events = {Event.User} setKey(s, fdi, events, 0, data) events.incl(Event.Read) @@ -172,9 +169,9 @@ proc unregister*[T](s: Selector[T], fd: int|SocketHandle) = let fdi = int(fd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, + doAssert(pkey.ident != InvalidIdent, "Descriptor [" & $fdi & "] is not registered in the queue!") - pkey.ident = 0 + pkey.ident = InvalidIdent pkey.events = {} s.pollRemove(fdi.cint) @@ -182,9 +179,9 @@ proc unregister*[T](s: Selector[T], ev: SelectEvent) = let fdi = int(ev.rfd) s.checkFd(fdi) var pkey = addr(s.fds[fdi]) - doAssert(pkey.ident != 0, "Event is not registered in the queue!") + doAssert(pkey.ident != InvalidIdent, "Event is not registered in the queue!") doAssert(Event.User in pkey.events) - pkey.ident = 0 + pkey.ident = InvalidIdent pkey.events = {} s.pollRemove(fdi.cint) @@ -270,7 +267,7 @@ template isEmpty*[T](s: Selector[T]): bool = (s.count == 0) proc contains*[T](s: Selector[T], fd: SocketHandle|int): bool {.inline.} = - return s.fds[fd.int].ident != 0 + return s.fds[fd.int].ident != InvalidIdent proc getData*[T](s: Selector[T], fd: SocketHandle|int): var T = let fdi = int(fd) diff --git a/lib/pure/ioselects/ioselectors_select.nim b/lib/pure/ioselects/ioselectors_select.nim index 7ed250307..cd6a72b44 100644 --- a/lib/pure/ioselects/ioselectors_select.nim +++ b/lib/pure/ioselects/ioselectors_select.nim @@ -99,6 +99,9 @@ proc newSelector*[T](): Selector[T] = result = Selector[T]() result.fds = newSeq[SelectorKey[T]](FD_SETSIZE) + for i in 0 ..< FD_SETSIZE: + result.fds[i].ident = InvalidIdent + IOFD_ZERO(addr result.rSet) IOFD_ZERO(addr result.wSet) IOFD_ZERO(addr result.eSet) @@ -195,7 +198,7 @@ proc setSelectKey[T](s: Selector[T], fd: SocketHandle, events: set[Event], var i = 0 let fdi = int(fd) while i < FD_SETSIZE: - if s.fds[i].ident == 0: + if s.fds[i].ident == InvalidIdent: var pkey = addr(s.fds[i]) pkey.ident = fdi pkey.events = events @@ -221,7 +224,7 @@ proc delKey[T](s: Selector[T], fd: SocketHandle) = var i = 0 while i < FD_SETSIZE: if s.fds[i].ident == fd.int: - s.fds[i].ident = 0 + s.fds[i].ident = InvalidIdent s.fds[i].events = {} s.fds[i].data = empty break @@ -335,7 +338,7 @@ proc selectInto*[T](s: Selector[T], timeout: int, var k = 0 while (i < FD_SETSIZE) and (k < count): - if s.fds[i].ident != 0: + if s.fds[i].ident != InvalidIdent: var flag = false var pkey = addr(s.fds[i]) var rkey = ReadyKey(fd: int(pkey.ident), events: {}) diff --git a/lib/pure/selectors.nim b/lib/pure/selectors.nim index 935250e08..e4c2b2124 100644 --- a/lib/pure/selectors.nim +++ b/lib/pure/selectors.nim @@ -261,6 +261,9 @@ else: param: int data: T + const + InvalidIdent = -1 + proc raiseIOSelectorsError[T](message: T) = var msg = "" when T is string: @@ -302,6 +305,12 @@ else: if posix.sigprocmask(SIG_UNBLOCK, newmask, oldmask) == -1: raiseIOSelectorsError(osLastError()) + template clearKey[T](key: ptr SelectorKey[T]) = + var empty: T + key.ident = InvalidIdent + key.events = {} + key.data = empty + when defined(linux): include ioselects/ioselectors_epoll elif bsdPlatform: -- cgit 1.4.1-2-gfad0 From 57c3b807d0fdfa61f89a8a8ed61d705cc1a2c2ca Mon Sep 17 00:00:00 2001 From: Yuriy Glukhov Date: Mon, 30 Jul 2018 09:54:52 +0300 Subject: Fixed typo introduced in #8428 that leads to InvalidIdent assertion failure (#8464) --- lib/pure/ioselects/ioselectors_kqueue.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pure') diff --git a/lib/pure/ioselects/ioselectors_kqueue.nim b/lib/pure/ioselects/ioselectors_kqueue.nim index 58a381042..142e988d0 100644 --- a/lib/pure/ioselects/ioselectors_kqueue.nim +++ b/lib/pure/ioselects/ioselectors_kqueue.nim @@ -114,7 +114,7 @@ proc newSelector*[T](): Selector[T] = result.fds = newSeq[SelectorKey[T]](maxFD) result.changes = newSeqOfCap[KEvent](MAX_KQUEUE_EVENTS) - for i in 0 ..< MAX_KQUEUE_EVENTS: + for i in 0 ..< maxFD: result.fds[i].ident = InvalidIdent result.sock = usock -- cgit 1.4.1-2-gfad0 From a4c244aef08b25542323fed1da9d7dfa8f230cf1 Mon Sep 17 00:00:00 2001 From: Quelklef Date: Mon, 30 Jul 2018 04:19:11 -0400 Subject: Add checks for random.rand() (#8431) --- lib/pure/random.nim | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'lib/pure') diff --git a/lib/pure/random.nim b/lib/pure/random.nim index 01ea9c845..e565fccf8 100644 --- a/lib/pure/random.nim +++ b/lib/pure/random.nim @@ -110,7 +110,7 @@ proc random*[T](a: openArray[T]): T {.deprecated.} = ## Use ``rand`` instead. result = a[random(a.low..a.len)] -proc rand*(r: var Rand; max: int): int {.benign.} = +proc rand*(r: var Rand; max: Natural): int {.benign.} = ## Returns a random number in the range 0..max. The sequence of ## random number is always the same, unless `randomize` is called ## which initializes the random number generator with a "random" @@ -128,7 +128,7 @@ proc rand*(max: int): int {.benign.} = ## number, i.e. a tickcount. rand(state, max) -proc rand*(r: var Rand; max: float): float {.benign.} = +proc rand*(r: var Rand; max: range[0.0 .. high(float)]): float {.benign.} = ## Returns a random number in the range 0..max. The sequence of ## random number is always the same, unless `randomize` is called ## which initializes the random number generator with a "random" @@ -218,4 +218,17 @@ when isMainModule: doAssert rand(0) == 0 doAssert rand("a") == 'a' + when compileOption("rangeChecks"): + try: + discard rand(-1) + doAssert false + except RangeError: + discard + + try: + discard rand(-1.0) + doAssert false + except RangeError: + discard + main() -- cgit 1.4.1-2-gfad0 From 2e6d073be11b6d365739f1cccefbcfe3055d8da7 Mon Sep 17 00:00:00 2001 From: andri lim Date: Mon, 30 Jul 2018 17:04:49 +0700 Subject: fixes #8468, stdlib.encodings.convert not crash anymore on windows (#8470) --- lib/pure/encodings.nim | 8 ++++---- tests/stdlib/tencoding.nim | 21 +++++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 tests/stdlib/tencoding.nim (limited to 'lib/pure') diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index c67cd7579..3c1cf73f4 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -332,7 +332,7 @@ when defined(windows): if s.len == 0: return "" # educated guess of capacity: var cap = s.len + s.len shr 2 - result = newStringOfCap(cap*2) + result = newString(cap*2) # convert to utf-16 LE var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), @@ -347,7 +347,7 @@ when defined(windows): lpWideCharStr = nil, cchWideChar = cint(0)) # and do the conversion properly: - result = newStringOfCap(cap*2) + result = newString(cap*2) m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), @@ -364,7 +364,7 @@ when defined(windows): if int(c.dest) == 1200: return # otherwise the fun starts again: cap = s.len + s.len shr 2 - var res = newStringOfCap(cap) + var res = newString(cap) m = wideCharToMultiByte( codePage = c.dest, dwFlags = 0'i32, @@ -382,7 +382,7 @@ when defined(windows): lpMultiByteStr = nil, cbMultiByte = cint(0)) # and do the conversion properly: - res = newStringOfCap(cap) + res = newString(cap) m = wideCharToMultiByte( codePage = c.dest, dwFlags = 0'i32, diff --git a/tests/stdlib/tencoding.nim b/tests/stdlib/tencoding.nim new file mode 100644 index 000000000..d6ff7ab32 --- /dev/null +++ b/tests/stdlib/tencoding.nim @@ -0,0 +1,21 @@ +discard """ + output: '''OK''' +""" + +#bug #8468 + +import encodings, strutils + +when defined(windows): + var utf16to8 = open(destEncoding = "utf-16", srcEncoding = "utf-8") + var s = "some string" + var c = utf16to8.convert(s) + + var z = newStringOfCap(s.len * 2) + for x in s: + z.add x + z.add chr(0) + + doAssert z == c + +echo "OK" -- cgit 1.4.1-2-gfad0 From e11d52a4e8e3b7522a26721f604692691a5fbeca Mon Sep 17 00:00:00 2001 From: Euan T Date: Mon, 30 Jul 2018 13:39:32 +0100 Subject: Update example code for UDP sockets --- lib/pure/net.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/pure') diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 5d2efebee..771e7de10 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -41,7 +41,7 @@ ## immediately. ## ## .. code-block:: Nim -## var socket = newSocket() +## var socket = newSocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) ## socket.sendTo("192.168.0.1", Port(27960), "status\n") ## ## Creating a server -- cgit 1.4.1-2-gfad0