diff options
Diffstat (limited to 'lib/pure')
36 files changed, 2108 insertions, 2090 deletions
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim index 8b44e69d9..df7ae6d17 100644 --- a/lib/pure/algorithm.nim +++ b/lib/pure/algorithm.nim @@ -34,7 +34,7 @@ proc reverse*[T](a: var openArray[T]) = ## reverses the array `a`. reverse(a, 0, a.high) -proc binarySearch*[T](a: openarray[T], key: T): int = +proc binarySearch*[T](a: openArray[T], key: T): int = ## binary search for `key` in `a`. Returns -1 if not found. var b = len(a) while result < b: @@ -79,7 +79,7 @@ proc merge[T](a, b: var openArray[T], lo, m, hi: int, inc(bb) inc(j) else: - CopyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1)) + copyMem(addr(b[0]), addr(a[j]), sizeof(T)*(m-j+1)) j = m+1 var i = 0 var k = lo diff --git a/lib/pure/asyncio.nim b/lib/pure/asyncio.nim index c4a07d751..f13cadaa2 100644 --- a/lib/pure/asyncio.nim +++ b/lib/pure/asyncio.nim @@ -139,27 +139,27 @@ type proc newDelegate*(): PDelegate = ## Creates a new delegate. new(result) - result.handleRead = (proc (h: PObject) = nil) - result.handleWrite = (proc (h: PObject) = nil) - result.handleError = (proc (h: PObject) = nil) + result.handleRead = (proc (h: PObject) = discard) + result.handleWrite = (proc (h: PObject) = discard) + result.handleError = (proc (h: PObject) = discard) result.hasDataBuffered = (proc (h: PObject): bool = return false) - result.task = (proc (h: PObject) = nil) + result.task = (proc (h: PObject) = discard) result.mode = fmRead proc newAsyncSocket(): PAsyncSocket = new(result) result.info = SockIdle - result.handleRead = (proc (s: PAsyncSocket) = nil) + result.handleRead = (proc (s: PAsyncSocket) = discard) result.handleWrite = nil - result.handleConnect = (proc (s: PAsyncSocket) = nil) - result.handleAccept = (proc (s: PAsyncSocket) = nil) - result.handleTask = (proc (s: PAsyncSocket) = nil) + result.handleConnect = (proc (s: PAsyncSocket) = discard) + result.handleAccept = (proc (s: PAsyncSocket) = discard) + result.handleTask = (proc (s: PAsyncSocket) = discard) result.lineBuffer = "".TaintedString result.sendBuffer = "" -proc AsyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, +proc asyncSocket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, protocol: TProtocol = IPPROTO_TCP, buffered = true): PAsyncSocket = ## Initialises an AsyncSocket object. If a socket cannot be initialised @@ -233,8 +233,11 @@ proc asyncSockHandleWrite(h: PObject) = let sock = PAsyncSocket(h) try: let bytesSent = sock.socket.sendAsync(sock.sendBuffer) - assert bytesSent > 0 - if bytesSent != sock.sendBuffer.len: + if bytesSent == 0: + # Apparently the socket cannot be written to. Even though select + # just told us that it can be... This used to be an assert. Just + # do nothing instead. + elif bytesSent != sock.sendBuffer.len: sock.sendBuffer = sock.sendBuffer[bytesSent .. -1] elif bytesSent == sock.sendBuffer.len: sock.sendBuffer = "" diff --git a/lib/pure/browsers.nim b/lib/pure/browsers.nim index b44f406c5..3a8429f81 100644 --- a/lib/pure/browsers.nim +++ b/lib/pure/browsers.nim @@ -29,9 +29,9 @@ proc openDefaultBrowser*(url: string) = when useWinUnicode: var o = newWideCString("open") var u = newWideCString(url) - discard ShellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL) + discard shellExecuteW(0'i32, o, u, nil, nil, SW_SHOWNORMAL) else: - discard ShellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL) + discard shellExecuteA(0'i32, "open", url, nil, nil, SW_SHOWNORMAL) elif defined(macosx): discard execShellCmd("open " & quoteShell(url)) else: @@ -45,4 +45,4 @@ proc openDefaultBrowser*(url: string) = discard startProcess(command=b, args=[url], options={poUseShell}) return except EOS: - nil + discard diff --git a/lib/pure/collections/LockFreeHash.nim b/lib/pure/collections/LockFreeHash.nim index d3a91763a..b94b542ff 100644 --- a/lib/pure/collections/LockFreeHash.nim +++ b/lib/pure/collections/LockFreeHash.nim @@ -23,7 +23,8 @@ elif sizeof(int) == 8: # 64bit TRaw = range[0..4611686018427387903] ## The range of uint values that can be stored directly in a value slot ## when on a 64 bit platform -else: echo("unsupported platform") +else: + {.error: "unsupported platform".} type TEntry = tuple diff --git a/lib/pure/collections/intsets.nim b/lib/pure/collections/intsets.nim index 2a8d7eec2..f1e67fc0e 100644 --- a/lib/pure/collections/intsets.nim +++ b/lib/pure/collections/intsets.nim @@ -50,7 +50,7 @@ proc mustRehash(length, counter: int): bool {.inline.} = proc nextTry(h, maxHash: THash): THash {.inline.} = result = ((5 * h) + 1) and maxHash -proc IntSetGet(t: TIntSet, key: int): PTrunk = +proc intSetGet(t: TIntSet, key: int): PTrunk = var h = key and t.max while t.data[h] != nil: if t.data[h].key == key: @@ -58,7 +58,7 @@ proc IntSetGet(t: TIntSet, key: int): PTrunk = h = nextTry(h, t.max) result = nil -proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) = +proc intSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) = var h = desc.key and t.max while data[h] != nil: assert(data[h] != desc) @@ -66,22 +66,22 @@ proc IntSetRawInsert(t: TIntSet, data: var TTrunkSeq, desc: PTrunk) = assert(data[h] == nil) data[h] = desc -proc IntSetEnlarge(t: var TIntSet) = +proc intSetEnlarge(t: var TIntSet) = var n: TTrunkSeq var oldMax = t.max t.max = ((t.max + 1) * 2) - 1 newSeq(n, t.max + 1) - for i in countup(0, oldmax): - if t.data[i] != nil: IntSetRawInsert(t, n, t.data[i]) + for i in countup(0, oldMax): + if t.data[i] != nil: intSetRawInsert(t, n, t.data[i]) swap(t.data, n) -proc IntSetPut(t: var TIntSet, key: int): PTrunk = +proc intSetPut(t: var TIntSet, key: int): PTrunk = var h = key and t.max while t.data[h] != nil: if t.data[h].key == key: return t.data[h] h = nextTry(h, t.max) - if mustRehash(t.max + 1, t.counter): IntSetEnlarge(t) + if mustRehash(t.max + 1, t.counter): intSetEnlarge(t) inc(t.counter) h = key and t.max while t.data[h] != nil: h = nextTry(h, t.max) @@ -94,7 +94,7 @@ proc IntSetPut(t: var TIntSet, key: int): PTrunk = proc contains*(s: TIntSet, key: int): bool = ## returns true iff `key` is in `s`. - var t = IntSetGet(s, `shr`(key, TrunkShift)) + var t = intSetGet(s, `shr`(key, TrunkShift)) if t != nil: var u = key and TrunkMask result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0 @@ -103,14 +103,14 @@ proc contains*(s: TIntSet, key: int): bool = proc incl*(s: var TIntSet, key: int) = ## includes an element `key` in `s`. - var t = IntSetPut(s, `shr`(key, TrunkShift)) + var t = intSetPut(s, `shr`(key, TrunkShift)) var u = key and TrunkMask t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] or `shl`(1, u and IntMask) proc excl*(s: var TIntSet, key: int) = ## excludes `key` from the set `s`. - var t = IntSetGet(s, `shr`(key, TrunkShift)) + var t = intSetGet(s, `shr`(key, TrunkShift)) if t != nil: var u = key and TrunkMask t.bits[`shr`(u, IntShift)] = t.bits[`shr`(u, IntShift)] and @@ -119,7 +119,7 @@ proc excl*(s: var TIntSet, key: int) = proc containsOrIncl*(s: var TIntSet, key: int): bool = ## returns true if `s` contains `key`, otherwise `key` is included in `s` ## and false is returned. - var t = IntSetGet(s, `shr`(key, TrunkShift)) + var t = intSetGet(s, `shr`(key, TrunkShift)) if t != nil: var u = key and TrunkMask result = (t.bits[`shr`(u, IntShift)] and `shl`(1, u and IntMask)) != 0 diff --git a/lib/pure/collections/lists.nim b/lib/pure/collections/lists.nim index ad8eca6a9..b8f8d20b5 100644 --- a/lib/pure/collections/lists.nim +++ b/lib/pure/collections/lists.nim @@ -41,19 +41,19 @@ type proc initSinglyLinkedList*[T](): TSinglyLinkedList[T] = ## creates a new singly linked list that is empty. - nil + discard proc initDoublyLinkedList*[T](): TDoublyLinkedList[T] = ## creates a new doubly linked list that is empty. - nil + discard proc initSinglyLinkedRing*[T](): TSinglyLinkedRing[T] = ## creates a new singly linked ring that is empty. - nil + discard proc initDoublyLinkedRing*[T](): TDoublyLinkedRing[T] = ## creates a new doubly linked ring that is empty. - nil + discard proc newDoublyLinkedNode*[T](value: T): PDoublyLinkedNode[T] = ## creates a new doubly linked node with the given `value`. diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index 3a009a8cb..3993f1ccc 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -136,7 +136,7 @@ proc delete*[T](s: var seq[T], first=0, last=0) = s[i].shallowCopy(s[j]) inc(i) inc(j) - setlen(s, newLen) + setLen(s, newLen) proc insert*[T](dest: var seq[T], src: openArray[T], pos=0) = ## Inserts items from `src` into `dest` at position `pos`. This modifies diff --git a/lib/pure/collections/sets.nim b/lib/pure/collections/sets.nim index 42b77d427..7259772aa 100644 --- a/lib/pure/collections/sets.nim +++ b/lib/pure/collections/sets.nim @@ -65,38 +65,38 @@ template rawInsertImpl() {.dirty.} = data[h].key = key data[h].slot = seFilled -proc RawGet[A](s: TSet[A], key: A): int = +proc rawGet[A](s: TSet[A], key: A): int = rawGetImpl() proc contains*[A](s: TSet[A], key: A): bool = ## returns true iff `key` is in `s`. - var index = RawGet(s, key) + var index = rawGet(s, key) result = index >= 0 -proc RawInsert[A](s: var TSet[A], data: var TKeyValuePairSeq[A], key: A) = +proc rawInsert[A](s: var TSet[A], data: var TKeyValuePairSeq[A], key: A) = rawInsertImpl() -proc Enlarge[A](s: var TSet[A]) = +proc enlarge[A](s: var TSet[A]) = var n: TKeyValuePairSeq[A] newSeq(n, len(s.data) * growthFactor) for i in countup(0, high(s.data)): - if s.data[i].slot == seFilled: RawInsert(s, n, s.data[i].key) + if s.data[i].slot == seFilled: rawInsert(s, n, s.data[i].key) swap(s.data, n) template inclImpl() {.dirty.} = - var index = RawGet(s, key) + var index = rawGet(s, key) if index < 0: - if mustRehash(len(s.data), s.counter): Enlarge(s) - RawInsert(s, s.data, key) + if mustRehash(len(s.data), s.counter): enlarge(s) + rawInsert(s, s.data, key) inc(s.counter) template containsOrInclImpl() {.dirty.} = - var index = RawGet(s, key) + var index = rawGet(s, key) if index >= 0: result = true else: - if mustRehash(len(s.data), s.counter): Enlarge(s) - RawInsert(s, s.data, key) + if mustRehash(len(s.data), s.counter): enlarge(s) + rawInsert(s, s.data, key) inc(s.counter) proc incl*[A](s: var TSet[A], key: A) = @@ -105,7 +105,7 @@ proc incl*[A](s: var TSet[A], key: A) = proc excl*[A](s: var TSet[A], key: A) = ## excludes `key` from the set `s`. - var index = RawGet(s, key) + var index = rawGet(s, key) if index >= 0: s.data[index].slot = seDeleted dec(s.counter) @@ -122,7 +122,7 @@ proc initSet*[A](initialSize=64): TSet[A] = result.counter = 0 newSeq(result.data, initialSize) -proc toSet*[A](keys: openarray[A]): TSet[A] = +proc toSet*[A](keys: openArray[A]): TSet[A] = ## creates a new hash set that contains the given `keys`. result = initSet[A](nextPowerOfTwo(keys.len+10)) for key in items(keys): result.incl(key) @@ -169,15 +169,15 @@ iterator items*[A](s: TOrderedSet[A]): A = forAllOrderedPairs: yield s.data[h].key -proc RawGet[A](s: TOrderedSet[A], key: A): int = +proc rawGet[A](s: TOrderedSet[A], key: A): int = rawGetImpl() proc contains*[A](s: TOrderedSet[A], key: A): bool = ## returns true iff `key` is in `s`. - var index = RawGet(s, key) + var index = rawGet(s, key) result = index >= 0 -proc RawInsert[A](s: var TOrderedSet[A], +proc rawInsert[A](s: var TOrderedSet[A], data: var TOrderedKeyValuePairSeq[A], key: A) = rawInsertImpl() data[h].next = -1 @@ -185,7 +185,7 @@ proc RawInsert[A](s: var TOrderedSet[A], if s.last >= 0: data[s.last].next = h s.last = h -proc Enlarge[A](s: var TOrderedSet[A]) = +proc enlarge[A](s: var TOrderedSet[A]) = var n: TOrderedKeyValuePairSeq[A] newSeq(n, len(s.data) * growthFactor) var h = s.first @@ -194,7 +194,7 @@ proc Enlarge[A](s: var TOrderedSet[A]) = while h >= 0: var nxt = s.data[h].next if s.data[h].slot == seFilled: - RawInsert(s, n, s.data[h].key) + rawInsert(s, n, s.data[h].key) h = nxt swap(s.data, n) @@ -216,7 +216,7 @@ proc initOrderedSet*[A](initialSize=64): TOrderedSet[A] = result.last = -1 newSeq(result.data, initialSize) -proc toOrderedSet*[A](keys: openarray[A]): TOrderedSet[A] = +proc toOrderedSet*[A](keys: openArray[A]): TOrderedSet[A] = ## creates a new ordered hash set that contains the given `keys`. result = initOrderedSet[A](nextPowerOfTwo(keys.len+10)) for key in items(keys): result.incl(key) @@ -224,5 +224,3 @@ proc toOrderedSet*[A](keys: openarray[A]): TOrderedSet[A] = proc `$`*[A](s: TOrderedSet[A]): string = ## The `$` operator for ordered hash sets. dollarImpl() - - diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 02d099c1f..73da274b9 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -85,7 +85,7 @@ template rawInsertImpl() {.dirty.} = data[h].val = val data[h].slot = seFilled -proc RawGet[A, B](t: TTable[A, B], key: A): int = +proc rawGet[A, B](t: TTable[A, B], key: A): int = rawGetImpl() proc `[]`*[A, B](t: TTable[A, B], key: A): B = @@ -93,13 +93,13 @@ proc `[]`*[A, B](t: TTable[A, B], key: A): B = ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key ## exists. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val proc mget*[A, B](t: var TTable[A, B], key: A): var B = ## retrieves the value at ``t[key]``. The value can be modified. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: raise newException(EInvalidKey, "key not found: " & $key) @@ -107,39 +107,39 @@ proc hasKey*[A, B](t: TTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc RawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B], +proc rawInsert[A, B](t: var TTable[A, B], data: var TKeyValuePairSeq[A, B], key: A, val: B) = rawInsertImpl() -proc Enlarge[A, B](t: var TTable[A, B]) = +proc enlarge[A, B](t: var TTable[A, B]) = var n: TKeyValuePairSeq[A, B] newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): - if t.data[i].slot == seFilled: RawInsert(t, n, t.data[i].key, t.data[i].val) + if t.data[i].slot == seFilled: rawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) -template AddImpl() {.dirty.} = - if mustRehash(len(t.data), t.counter): Enlarge(t) - RawInsert(t, t.data, key, val) +template addImpl() {.dirty.} = + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) inc(t.counter) -template PutImpl() {.dirty.} = - var index = RawGet(t, key) +template putImpl() {.dirty.} = + var index = rawGet(t, key) if index >= 0: t.data[index].val = val else: - AddImpl() + addImpl() when false: # not yet used: - template HasKeyOrPutImpl() {.dirty.} = - var index = RawGet(t, key) + template hasKeyOrPutImpl() {.dirty.} = + var index = rawGet(t, key) if index >= 0: t.data[index].val = val result = true else: - if mustRehash(len(t.data), t.counter): Enlarge(t) - RawInsert(t, t.data, key, val) + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) inc(t.counter) result = false @@ -149,11 +149,11 @@ proc `[]=`*[A, B](t: var TTable[A, B], key: A, val: B) = proc add*[A, B](t: var TTable[A, B], key: A, val: B) = ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists. - AddImpl() + addImpl() proc del*[A, B](t: var TTable[A, B], key: A) = ## deletes `key` from hash table `t`. - var index = RawGet(t, key) + let index = rawGet(t, key) if index >= 0: t.data[index].slot = seDeleted dec(t.counter) @@ -168,7 +168,7 @@ proc initTable*[A, B](initialSize=64): TTable[A, B] = result.counter = 0 newSeq(result.data, initialSize) -proc toTable*[A, B](pairs: openarray[tuple[key: A, +proc toTable*[A, B](pairs: openArray[tuple[key: A, val: B]]): TTable[A, B] = ## creates a new hash table that contains the given `pairs`. result = initTable[A, B](nextPowerOfTwo(pairs.len+10)) @@ -240,7 +240,7 @@ iterator mvalues*[A, B](t: var TOrderedTable[A, B]): var B = forAllOrderedPairs: yield t.data[h].val -proc RawGet[A, B](t: TOrderedTable[A, B], key: A): int = +proc rawGet[A, B](t: TOrderedTable[A, B], key: A): int = rawGetImpl() proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B = @@ -248,13 +248,13 @@ proc `[]`*[A, B](t: TOrderedTable[A, B], key: A): B = ## default empty value for the type `B` is returned ## and no exception is raised. One can check with ``hasKey`` whether the key ## exists. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val proc mget*[A, B](t: var TOrderedTable[A, B], key: A): var B = ## retrieves the value at ``t[key]``. The value can be modified. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: raise newException(EInvalidKey, "key not found: " & $key) @@ -262,7 +262,7 @@ proc hasKey*[A, B](t: TOrderedTable[A, B], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc RawInsert[A, B](t: var TOrderedTable[A, B], +proc rawInsert[A, B](t: var TOrderedTable[A, B], data: var TOrderedKeyValuePairSeq[A, B], key: A, val: B) = rawInsertImpl() @@ -271,7 +271,7 @@ proc RawInsert[A, B](t: var TOrderedTable[A, B], if t.last >= 0: data[t.last].next = h t.last = h -proc Enlarge[A, B](t: var TOrderedTable[A, B]) = +proc enlarge[A, B](t: var TOrderedTable[A, B]) = var n: TOrderedKeyValuePairSeq[A, B] newSeq(n, len(t.data) * growthFactor) var h = t.first @@ -280,7 +280,7 @@ proc Enlarge[A, B](t: var TOrderedTable[A, B]) = while h >= 0: var nxt = t.data[h].next if t.data[h].slot == seFilled: - RawInsert(t, n, t.data[h].key, t.data[h].val) + rawInsert(t, n, t.data[h].key, t.data[h].val) h = nxt swap(t.data, n) @@ -290,7 +290,7 @@ proc `[]=`*[A, B](t: var TOrderedTable[A, B], key: A, val: B) = proc add*[A, B](t: var TOrderedTable[A, B], key: A, val: B) = ## puts a new (key, value)-pair into `t` even if ``t[key]`` already exists. - AddImpl() + addImpl() proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] = ## creates a new ordered hash table that is empty. @@ -304,7 +304,7 @@ proc initOrderedTable*[A, B](initialSize=64): TOrderedTable[A, B] = result.last = -1 newSeq(result.data, initialSize) -proc toOrderedTable*[A, B](pairs: openarray[tuple[key: A, +proc toOrderedTable*[A, B](pairs: openArray[tuple[key: A, val: B]]): TOrderedTable[A, B] = ## creates a new ordered hash table that contains the given `pairs`. result = initOrderedTable[A, B](nextPowerOfTwo(pairs.len+10)) @@ -398,7 +398,7 @@ iterator mvalues*[A](t: TCountTable[A]): var int = for h in 0..high(t.data): if t.data[h].val != 0: yield t.data[h].val -proc RawGet[A](t: TCountTable[A], key: A): int = +proc rawGet[A](t: TCountTable[A], key: A): int = var h: THash = hash(key) and high(t.data) # start with real hash value while t.data[h].val != 0: if t.data[h].key == key: return h @@ -409,13 +409,13 @@ proc `[]`*[A](t: TCountTable[A], key: A): int = ## retrieves the value at ``t[key]``. If `key` is not in `t`, ## 0 is returned. One can check with ``hasKey`` whether the key ## exists. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val proc mget*[A](t: var TCountTable[A], key: A): var int = ## retrieves the value at ``t[key]``. The value can be modified. ## If `key` is not in `t`, the ``EInvalidKey`` exception is raised. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: raise newException(EInvalidKey, "key not found: " & $key) @@ -423,24 +423,24 @@ proc hasKey*[A](t: TCountTable[A], key: A): bool = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc RawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]], +proc rawInsert[A](t: TCountTable[A], data: var seq[tuple[key: A, val: int]], key: A, val: int) = var h: THash = hash(key) and high(data) while data[h].val != 0: h = nextTry(h, high(data)) data[h].key = key data[h].val = val -proc Enlarge[A](t: var TCountTable[A]) = +proc enlarge[A](t: var TCountTable[A]) = var n: seq[tuple[key: A, val: int]] newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): - if t.data[i].val != 0: RawInsert(t, n, t.data[i].key, t.data[i].val) + if t.data[i].val != 0: rawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) proc `[]=`*[A](t: var TCountTable[A], key: A, val: int) = ## puts a (key, value)-pair into `t`. `val` has to be positive. assert val > 0 - PutImpl() + putImpl() proc initCountTable*[A](initialSize=64): TCountTable[A] = ## creates a new count table that is empty. @@ -463,15 +463,15 @@ proc `$`*[A](t: TCountTable[A]): string = proc inc*[A](t: var TCountTable[A], key: A, val = 1) = ## increments `t[key]` by `val`. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: inc(t.data[index].val, val) else: - if mustRehash(len(t.data), t.counter): Enlarge(t) - RawInsert(t, t.data, key, val) + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) inc(t.counter) -proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] = +proc smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] = ## returns the largest (key,val)-pair. Efficiency: O(n) assert t.len > 0 var minIdx = 0 @@ -480,7 +480,7 @@ proc Smallest*[A](t: TCountTable[A]): tuple[key: A, val: int] = result.key = t.data[minIdx].key result.val = t.data[minIdx].val -proc Largest*[A](t: TCountTable[A]): tuple[key: A, val: int] = +proc largest*[A](t: TCountTable[A]): tuple[key: A, val: int] = ## returns the (key,val)-pair with the largest `val`. Efficiency: O(n) assert t.len > 0 var maxIdx = 0 diff --git a/lib/pure/encodings.nim b/lib/pure/encodings.nim index ce4238409..94d21ed4e 100644 --- a/lib/pure/encodings.nim +++ b/lib/pure/encodings.nim @@ -1,7 +1,7 @@ # # # Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf +# (c) Copyright 2014 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. @@ -14,21 +14,21 @@ import os, parseutils, strutils when not defined(windows): type - TConverter = object {.pure, final.} + TConverter = object PConverter* = ptr TConverter ## can convert between two character sets - + else: type TCodePage = distinct int32 - PConverter* = object {.pure.} + PConverter* = object dest, src: TCodePage - + type EInvalidEncoding* = object of EInvalidValue ## exception that is raised ## for encoding errors when defined(windows): - proc EqEncodingNames(a, b: string): bool = + proc eqEncodingNames(a, b: string): bool = var i = 0 var j = 0 while i < a.len and j < b.len: @@ -208,31 +208,31 @@ when defined(windows): when false: # not needed yet: type - TCpInfo = object {.pure.} - MaxCharSize: int32 - DefaultChar: array[0..1, char] - LeadByte: array[0..12-1, char] + TCpInfo = object + maxCharSize: int32 + defaultChar: array[0..1, char] + leadByte: array[0..12-1, char] - proc GetCPInfo(CodePage: TCodePage, lpCPInfo: var TCpInfo): int32 {. + proc getCPInfo(codePage: TCodePage, lpCPInfo: var TCpInfo): int32 {. stdcall, importc: "GetCPInfo", dynlib: "kernel32".} proc nameToCodePage(name: string): TCodePage = var nameAsInt: int if parseInt(name, nameAsInt) == 0: nameAsInt = -1 for no, na in items(winEncodings): - if no == nameAsInt or EqEncodingNames(na, name): return TCodePage(no) + if no == nameAsInt or eqEncodingNames(na, name): return TCodePage(no) result = TCodePage(-1) proc codePageToName(c: TCodePage): string = for no, na in items(winEncodings): - if no == int(c): + if no == int(c): return if na.len != 0: na else: $no result = "" - proc GetACP(): TCodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".} + proc getACP(): TCodePage {.stdcall, importc: "GetACP", dynlib: "kernel32".} - proc MultiByteToWideChar( - CodePage: TCodePage, + proc multiByteToWideChar( + codePage: TCodePage, dwFlags: int32, lpMultiByteStr: cstring, cbMultiByte: cint, @@ -240,8 +240,8 @@ when defined(windows): cchWideChar: cint): cint {. stdcall, importc: "MultiByteToWideChar", dynlib: "kernel32".} - proc WideCharToMultiByte( - CodePage: TCodePage, + proc wideCharToMultiByte( + codePage: TCodePage, dwFlags: int32, lpWideCharStr: cstring, cchWideChar: cint, @@ -321,7 +321,6 @@ proc close*(c: PConverter) = iconvClose(c) when defined(windows): - proc convert*(c: PConverter, s: string): string = ## converts `s` to `destEncoding` that was given to the converter `c`. It ## assumed that `s` is in `srcEncoding`. @@ -333,26 +332,26 @@ when defined(windows): var cap = s.len + s.len shr 2 result = newStringOfCap(cap*2) # convert to utf-16 LE - var m = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32, + var m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = cstring(result), cchWideChar = cint(cap)) if m == 0: # try again; ask for capacity: - cap = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32, + cap = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = nil, cchWideChar = cint(0)) # and do the conversion properly: result = newStringOfCap(cap*2) - m = MultiByteToWideChar(CodePage = c.src, dwFlags = 0'i32, + m = multiByteToWideChar(codePage = c.src, dwFlags = 0'i32, lpMultiByteStr = cstring(s), cbMultiByte = cint(s.len), lpWideCharStr = cstring(result), cchWideChar = cint(cap)) - if m == 0: OSError() + if m == 0: osError(osLastError()) setLen(result, m*2) elif m <= cap: setLen(result, m*2) @@ -364,8 +363,8 @@ when defined(windows): # otherwise the fun starts again: cap = s.len + s.len shr 2 var res = newStringOfCap(cap) - m = WideCharToMultiByte( - CodePage = c.dest, + m = wideCharToMultiByte( + codePage = c.dest, dwFlags = 0'i32, lpWideCharStr = cstring(result), cchWideChar = cint(result.len div 2), @@ -373,8 +372,8 @@ when defined(windows): cbMultiByte = cap.cint) if m == 0: # try again; ask for capacity: - cap = WideCharToMultiByte( - CodePage = c.dest, + cap = wideCharToMultiByte( + codePage = c.dest, dwFlags = 0'i32, lpWideCharStr = cstring(result), cchWideChar = cint(result.len div 2), @@ -382,14 +381,14 @@ when defined(windows): cbMultiByte = cint(0)) # and do the conversion properly: res = newStringOfCap(cap) - m = WideCharToMultiByte( - CodePage = c.dest, + m = wideCharToMultiByte( + codePage = c.dest, dwFlags = 0'i32, lpWideCharStr = cstring(result), cchWideChar = cint(result.len div 2), lpMultiByteStr = cstring(res), cbMultiByte = cap.cint) - if m == 0: OSError() + if m == 0: osError(osLastError()) setLen(res, m) result = res elif m <= cap: @@ -399,15 +398,14 @@ when defined(windows): assert(false) # cannot happen else: - proc convert*(c: PConverter, s: string): string = result = newString(s.len) - var inLen = len(S) + var inLen = len(s) var outLen = len(result) - var src = cstring(S) + var src = cstring(s) var dst = cstring(result) var iconvres: int - while InLen > 0: + while inLen > 0: iconvres = iconv(c, src, inLen, dst, outLen) if iconvres == -1: var lerr = errno @@ -425,11 +423,11 @@ else: dst = cast[cstring](cast[int](cstring(result)) + offset) outLen = len(result) - offset else: - OSError() + osError(lerr.TOSErrorCode) # iconv has a buffer that needs flushing, specially if the last char is # not '\0' discard iconv(c, nil, nil, dst, outlen) - if iconvres == Cint(-1) and errno == E2BIG: + if iconvres == cint(-1) and errno == E2BIG: var offset = cast[int](dst) - cast[int](cstring(result)) setLen(result, len(result)+inLen*2+5) # 5 is minimally one utf-8 char @@ -450,7 +448,7 @@ proc convert*(s: string, destEncoding = "UTF-8", finally: close(c) -when IsMainModule: +when isMainModule: let orig = "öäüß" cp1252 = convert(orig, "CP1252", "UTF-8") diff --git a/lib/pure/endians.nim b/lib/pure/endians.nim index 34270b320..73017464d 100644 --- a/lib/pure/endians.nim +++ b/lib/pure/endians.nim @@ -34,14 +34,26 @@ proc swapEndian32*(outp, inp: pointer) = o[2] = i[1] o[3] = i[0] +proc swapEndian16*(outp, inp: pointer) = + ## copies `inp` to `outp` swapping bytes. Both buffers are supposed to + ## contain at least 2 bytes. + var + i = cast[cstring](inp) + o = cast[cstring](outp) + o[0] = i[1] + o[1] = i[0] + when system.cpuEndian == bigEndian: proc littleEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp) proc littleEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp) + proc littleEndian16*(outp, inp: pointer) {.inline.} = swapEndian16(outp, inp) proc bigEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8) proc bigEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4) + proc bigEndian16*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 2) else: proc littleEndian64*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 8) proc littleEndian32*(outp, inp: pointer) {.inline.} = copyMem(outp, inp, 4) + proc littleEndian16*(outp, inp: pointer){.inline.} = copyMem(outp, inp, 2) proc bigEndian64*(outp, inp: pointer) {.inline.} = swapEndian64(outp, inp) proc bigEndian32*(outp, inp: pointer) {.inline.} = swapEndian32(outp, inp) - + proc bigEndian16*(outp, inp: pointer) {.inline.} = swapEndian16(outp, inp) diff --git a/lib/pure/ftpclient.nim b/lib/pure/ftpclient.nim index b6127a9bc..f136e0016 100644 --- a/lib/pure/ftpclient.nim +++ b/lib/pure/ftpclient.nim @@ -95,7 +95,7 @@ type EInvalidReply* = object of ESynch EFTP* = object of ESynch -proc FTPClient*(address: string, port = TPort(21), +proc ftpClient*(address: string, port = TPort(21), user, pass = ""): PFTPClient = ## Create a ``PFTPClient`` object. new(result) @@ -298,7 +298,7 @@ proc getLines(ftp: PFTPClient, async: bool = false): bool = var readSocks: seq[TSocket] = @[ftp.getCSock()] # This is only needed here. Asyncio gets this socket... blockingOperation(ftp.getCSock()): - if readSocks.select(1) != 0 and ftp.getCSock() notin readSocks: + if readSocks.select(1) != 0 and ftp.getCSock() in readSocks: assertReply ftp.expectReply(), "226" return true @@ -315,7 +315,7 @@ proc listDirs*(ftp: PFTPClient, dir: string = "", assertReply ftp.send("NLST " & dir.normalizePathSep), ["125", "150"] if not async: - while not ftp.job.prc(ftp, false): nil + while not ftp.job.prc(ftp, false): discard result = splitLines(ftp.job.lines) ftp.deleteJob() else: return @[] @@ -390,7 +390,7 @@ proc list*(ftp: PFTPClient, dir: string = "", async = false): string = assertReply(ftp.send("LIST" & " " & dir.normalizePathSep), ["125", "150"]) if not async: - while not ftp.job.prc(ftp, false): nil + while not ftp.job.prc(ftp, false): discard result = ftp.job.lines ftp.deleteJob() else: @@ -405,7 +405,7 @@ proc retrText*(ftp: PFTPClient, file: string, async = false): string = assertReply ftp.send("RETR " & file.normalizePathSep), ["125", "150"] if not async: - while not ftp.job.prc(ftp, false): nil + while not ftp.job.prc(ftp, false): discard result = ftp.job.lines ftp.deleteJob() else: @@ -434,7 +434,7 @@ proc getFile(ftp: PFTPClient, async = false): bool = if not async: var readSocks: seq[TSocket] = @[ftp.getCSock()] blockingOperation(ftp.getCSock()): - if readSocks.select(1) != 0 and ftp.getCSock() notin readSocks: + if readSocks.select(1) != 0 and ftp.getCSock() in readSocks: assertReply ftp.expectReply(), "226" return true @@ -460,7 +460,7 @@ proc retrFile*(ftp: PFTPClient, file, dest: string, async = false) = ftp.job.filename = file.normalizePathSep if not async: - while not ftp.job.prc(ftp, false): nil + while not ftp.job.prc(ftp, false): discard ftp.deleteJob() proc doUpload(ftp: PFTPClient, async = false): bool = @@ -518,7 +518,7 @@ proc store*(ftp: PFTPClient, file, dest: string, async = false) = assertReply ftp.send("STOR " & dest.normalizePathSep), ["125", "150"] if not async: - while not ftp.job.prc(ftp, false): nil + while not ftp.job.prc(ftp, false): discard ftp.deleteJob() proc close*(ftp: PFTPClient) = @@ -554,10 +554,10 @@ proc csockHandleRead(s: PAsyncSocket, ftp: PAsyncFTPClient) = ftp.handleEvent(ftp, r) -proc AsyncFTPClient*(address: string, port = TPort(21), +proc asyncFTPClient*(address: string, port = TPort(21), user, pass = "", handleEvent: proc (ftp: PAsyncFTPClient, ev: TFTPEvent) {.closure.} = - (proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = nil)): PAsyncFTPClient = + (proc (ftp: PAsyncFTPClient, ev: TFTPEvent) = discard)): PAsyncFTPClient = ## Create a ``PAsyncFTPClient`` object. ## ## Use this if you want to use asyncio's dispatcher. @@ -604,7 +604,7 @@ when isMainModule: ftp.close() echo d.len else: assert(false) - var ftp = AsyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev) + var ftp = asyncFTPClient("picheta.me", user = "test", pass = "asf", handleEvent = hev) d.register(ftp) d.len.echo() @@ -618,7 +618,7 @@ when isMainModule: when isMainModule and false: - var ftp = FTPClient("picheta.me", user = "asdasd", pass = "asfwq") + var ftp = ftpClient("picheta.me", user = "asdasd", pass = "asfwq") ftp.connect() echo ftp.pwd() echo ftp.list() diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim index 8a3135f89..ee05ad7e2 100644 --- a/lib/pure/hashes.nim +++ b/lib/pure/hashes.nim @@ -32,26 +32,26 @@ proc `!$`*(h: THash): THash {.inline.} = result = result xor (result shr 11) result = result +% result shl 15 -proc hashData*(Data: Pointer, Size: int): THash = +proc hashData*(data: pointer, size: int): THash = ## hashes an array of bytes of size `size` var h: THash = 0 when defined(js): var p: cstring asm """`p` = `Data`;""" else: - var p = cast[cstring](Data) + var p = cast[cstring](data) var i = 0 var s = size while s > 0: h = h !& ord(p[i]) - Inc(i) - Dec(s) + inc(i) + dec(s) result = !$h when defined(js): var objectID = 0 -proc hash*(x: Pointer): THash {.inline.} = +proc hash*(x: pointer): THash {.inline.} = ## efficient hashing of pointers when defined(js): asm """ @@ -126,6 +126,6 @@ proc hash*(x: float): THash {.inline.} = var y = x + 1.0 result = cast[ptr THash](addr(y))[] -proc hash*[A](x: openarray[A]): THash = +proc hash*[A](x: openArray[A]): THash = for it in items(x): result = result !& hash(it) result = !$result diff --git a/lib/pure/htmlgen.nim b/lib/pure/htmlgen.nim index 8d90f8589..63737d583 100644 --- a/lib/pure/htmlgen.nim +++ b/lib/pure/htmlgen.nim @@ -88,7 +88,7 @@ proc xmlCheckedTag*(e: PNimrodNode, tag: string, result.add(newStrLitNode("</")) result.add(newStrLitNode(tag)) result.add(newStrLitNode(">")) - result = NestList(!"&", result) + result = nestList(!"&", result) macro a*(e: expr): expr {.immediate.} = diff --git a/lib/pure/httpclient.nim b/lib/pure/httpclient.nim index 2c0e7b835..bb9835fe7 100644 --- a/lib/pure/httpclient.nim +++ b/lib/pure/httpclient.nim @@ -220,9 +220,8 @@ proc parseResponse(s: TSocket, getBody: bool, timeout: int): TResponse = inc(linei, le) if line[linei] != ':': httpError("invalid headers") inc(linei) # Skip : - linei += skipWhitespace(line, linei) - result.headers[name] = line[linei.. -1] + result.headers[name] = line[linei.. -1].strip() if not fullyRead: httpError("Connection was closed before full request has been made") if getBody: diff --git a/lib/pure/irc.nim b/lib/pure/irc.nim index ee85d9c69..750c98516 100644 --- a/lib/pure/irc.nim +++ b/lib/pure/irc.nim @@ -346,7 +346,7 @@ proc poll*(irc: PIRC, ev: var TIRCEvent, var line = TaintedString"" var socks = @[irc.sock] var ret = socks.select(timeout) - if socks.len() == 0 and ret != 0: + if socks.len() != 0 and ret != 0: irc.sock.readLine(line) ev = irc.processLine(line.string) result = true diff --git a/lib/pure/json.nim b/lib/pure/json.nim index df20bd852..7424bbae9 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -135,7 +135,7 @@ proc str*(my: TJsonParser): string {.inline.} = assert(my.kind in {jsonInt, jsonFloat, jsonString}) return my.a -proc getInt*(my: TJsonParser): biggestInt {.inline.} = +proc getInt*(my: TJsonParser): BiggestInt {.inline.} = ## returns the number for the event: ``jsonInt`` assert(my.kind == jsonInt) return parseBiggestInt(my.a) @@ -151,11 +151,11 @@ proc kind*(my: TJsonParser): TJsonEventKind {.inline.} = proc getColumn*(my: TJsonParser): int {.inline.} = ## get the current column the parser has arrived at. - result = getColNumber(my, my.bufPos) + result = getColNumber(my, my.bufpos) proc getLine*(my: TJsonParser): int {.inline.} = ## get the current line the parser has arrived at. - result = my.linenumber + result = my.lineNumber proc getFilename*(my: TJsonParser): string {.inline.} = ## get the filename of the file that the parser processes. @@ -173,7 +173,7 @@ proc errorMsgExpected*(my: TJsonParser, e: string): string = result = "$1($2, $3) Error: $4" % [ my.filename, $getLine(my), $getColumn(my), e & " expected"] -proc handleHexChar(c: Char, x: var int): bool = +proc handleHexChar(c: char, x: var int): bool = result = true # Success case c of '0'..'9': x = (x shl 4) or (ord(c) - ord('0')) @@ -227,11 +227,11 @@ proc parseString(my: var TJsonParser): TTokKind = add(my.a, buf[pos]) inc(pos) of '\c': - pos = lexbase.HandleCR(my, pos) + pos = lexbase.handleCR(my, pos) buf = my.buf add(my.a, '\c') of '\L': - pos = lexbase.HandleLF(my, pos) + pos = lexbase.handleLF(my, pos) buf = my.buf add(my.a, '\L') else: @@ -253,11 +253,11 @@ proc skip(my: var TJsonParser) = of '\0': break of '\c': - pos = lexbase.HandleCR(my, pos) + pos = lexbase.handleCR(my, pos) buf = my.buf break of '\L': - pos = lexbase.HandleLF(my, pos) + pos = lexbase.handleLF(my, pos) buf = my.buf break else: @@ -271,10 +271,10 @@ proc skip(my: var TJsonParser) = my.err = errEOC_Expected break of '\c': - pos = lexbase.HandleCR(my, pos) + pos = lexbase.handleCR(my, pos) buf = my.buf of '\L': - pos = lexbase.HandleLF(my, pos) + pos = lexbase.handleLF(my, pos) buf = my.buf of '*': inc(pos) @@ -286,12 +286,12 @@ proc skip(my: var TJsonParser) = else: break of ' ', '\t': - Inc(pos) + inc(pos) of '\c': - pos = lexbase.HandleCR(my, pos) + pos = lexbase.handleCR(my, pos) buf = my.buf of '\L': - pos = lexbase.HandleLF(my, pos) + pos = lexbase.handleLF(my, pos) buf = my.buf else: break @@ -517,7 +517,7 @@ type of JString: str*: string of JInt: - num*: biggestInt + num*: BiggestInt of JFloat: fnum*: float of JBool: @@ -535,30 +535,30 @@ proc raiseParseErr*(p: TJsonParser, msg: string) {.noinline, noreturn.} = ## raises an `EJsonParsingError` exception. raise newException(EJsonParsingError, errorMsgExpected(p, msg)) -proc newJString*(s: String): PJsonNode = +proc newJString*(s: string): PJsonNode = ## Creates a new `JString PJsonNode`. new(result) result.kind = JString result.str = s -proc newJStringMove(s: String): PJsonNode = +proc newJStringMove(s: string): PJsonNode = new(result) result.kind = JString shallowCopy(result.str, s) -proc newJInt*(n: biggestInt): PJsonNode = +proc newJInt*(n: BiggestInt): PJsonNode = ## Creates a new `JInt PJsonNode`. new(result) result.kind = JInt result.num = n -proc newJFloat*(n: Float): PJsonNode = +proc newJFloat*(n: float): PJsonNode = ## Creates a new `JFloat PJsonNode`. new(result) result.kind = JFloat result.fnum = n -proc newJBool*(b: Bool): PJsonNode = +proc newJBool*(b: bool): PJsonNode = ## Creates a new `JBool PJsonNode`. new(result) result.kind = JBool @@ -587,7 +587,7 @@ proc `%`*(s: string): PJsonNode = result.kind = JString result.str = s -proc `%`*(n: biggestInt): PJsonNode = +proc `%`*(n: BiggestInt): PJsonNode = ## Generic constructor for JSON data. Creates a new `JInt PJsonNode`. new(result) result.kind = JInt @@ -612,7 +612,7 @@ proc `%`*(keyVals: openArray[tuple[key: string, val: PJsonNode]]): PJsonNode = newSeq(result.fields, keyVals.len) for i, p in pairs(keyVals): result.fields[i] = p -proc `%`*(elements: openArray[PJSonNode]): PJsonNode = +proc `%`*(elements: openArray[PJsonNode]): PJsonNode = ## Generic constructor for JSON data. Creates a new `JArray PJsonNode` new(result) result.kind = JArray @@ -626,9 +626,9 @@ proc len*(n: PJsonNode): int = case n.kind of JArray: result = n.elems.len of JObject: result = n.fields.len - else: nil + else: discard -proc `[]`*(node: PJsonNode, name: String): PJsonNode = +proc `[]`*(node: PJsonNode, name: string): PJsonNode = ## Gets a field from a `JObject`. Returns nil if the key is not found. assert(node.kind == JObject) for key, item in items(node.fields): @@ -636,17 +636,18 @@ proc `[]`*(node: PJsonNode, name: String): PJsonNode = return item return nil -proc `[]`*(node: PJsonNode, index: Int): PJsonNode = +proc `[]`*(node: PJsonNode, index: int): PJsonNode = ## Gets the node at `index` in an Array. assert(node.kind == JArray) return node.elems[index] -proc hasKey*(node: PJsonNode, key: String): Bool = +proc hasKey*(node: PJsonNode, key: string): bool = ## Checks if `key` exists in `node`. assert(node.kind == JObject) for k, item in items(node.fields): - if k == key: return True -proc existsKey*(node: PJsonNode, key: String): Bool {.deprecated.} = node.hasKey(key) + if k == key: return true + +proc existsKey*(node: PJsonNode, key: string): bool {.deprecated.} = node.hasKey(key) ## Deprecated for `hasKey` proc add*(father, child: PJsonNode) = @@ -661,7 +662,7 @@ proc add*(obj: PJsonNode, key: string, val: PJsonNode) = assert obj.kind == JObject obj.fields.add((key, val)) -proc `[]=`*(obj: PJsonNode, key: String, val: PJsonNode) = +proc `[]=`*(obj: PJsonNode, key: string, val: PJsonNode) = ## Sets a field from a `JObject`. Performs a check for duplicate keys. assert(obj.kind == JObject) for i in 0..obj.fields.len-1: @@ -706,7 +707,7 @@ proc copy*(p: PJsonNode): PJsonNode = proc indent(s: var string, i: int) = s.add(repeatChar(i)) -proc newIndent(curr, indent: int, ml: bool): Int = +proc newIndent(curr, indent: int, ml: bool): int = if ml: return curr + indent else: return indent @@ -730,8 +731,8 @@ proc escapeJson*(s: string): string = result.add(toHex(r, 4)) result.add("\"") -proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True, - lstArr = False, currIndent = 0) = +proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = true, + lstArr = false, currIndent = 0) = case node.kind of JObject: if currIndent != 0 and not lstArr: result.nl(ml) @@ -747,7 +748,7 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True, result.indent(newIndent(currIndent, indent, ml)) result.add(escapeJson(node.fields[i].key)) result.add(": ") - toPretty(result, node.fields[i].val, indent, ml, False, + toPretty(result, node.fields[i].val, indent, ml, false, newIndent(currIndent, indent, ml)) result.nl(ml) result.indent(currIndent) # indent the same as { @@ -776,7 +777,7 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True, result.add(", ") result.nl(ml) # New Line toPretty(result, node.elems[i], indent, ml, - True, newIndent(currIndent, indent, ml)) + true, newIndent(currIndent, indent, ml)) result.nl(ml) result.indent(currIndent) result.add("]") @@ -785,18 +786,18 @@ proc toPretty(result: var string, node: PJsonNode, indent = 2, ml = True, if lstArr: result.indent(currIndent) result.add("null") -proc pretty*(node: PJsonNode, indent = 2): String = +proc pretty*(node: PJsonNode, indent = 2): string = ## Converts `node` to its JSON Representation, with indentation and ## on multiple lines. result = "" toPretty(result, node, indent) -proc `$`*(node: PJsonNode): String = +proc `$`*(node: PJsonNode): string = ## Converts `node` to its JSON Representation on one line. result = "" - toPretty(result, node, 1, False) + toPretty(result, node, 1, false) -iterator items*(node: PJsonNode): PJSonNode = +iterator items*(node: PJsonNode): PJsonNode = ## Iterator for the items of `node`. `node` has to be a JArray. assert node.kind == JArray for i in items(node.elems): diff --git a/lib/pure/lexbase.nim b/lib/pure/lexbase.nim index 2756290d8..eee95e2e6 100644 --- a/lib/pure/lexbase.nim +++ b/lib/pure/lexbase.nim @@ -31,7 +31,7 @@ type buf*: cstring ## the buffer itself bufLen*: int ## length of buffer in characters input: PStream ## the input stream - LineNumber*: int ## the current line number + lineNumber*: int ## the current line number sentinel: int lineStart: int # index of last line start in buffer fileOpened: bool @@ -48,11 +48,11 @@ proc getCurrentLine*(L: TBaseLexer, marker: bool = true): string proc getColNumber*(L: TBaseLexer, pos: int): int ## retrieves the current column. -proc HandleCR*(L: var TBaseLexer, pos: int): int +proc handleCR*(L: var TBaseLexer, pos: int): int ## Call this if you scanned over '\c' in the buffer; it returns the the ## position to continue the scanning from. `pos` must be the position ## of the '\c'. -proc HandleLF*(L: var TBaseLexer, pos: int): int +proc handleLF*(L: var TBaseLexer, pos: int): int ## Call this if you scanned over '\L' in the buffer; it returns the the ## position to continue the scanning from. `pos` must be the position ## of the '\L'. @@ -66,7 +66,7 @@ proc close(L: var TBaseLexer) = dealloc(L.buf) close(L.input) -proc FillBuffer(L: var TBaseLexer) = +proc fillBuffer(L: var TBaseLexer) = var charsRead, toCopy, s: int # all are in characters, # not bytes (in case this @@ -75,10 +75,10 @@ proc FillBuffer(L: var TBaseLexer) = # we know here that pos == L.sentinel, but not if this proc # is called the first time by initBaseLexer() assert(L.sentinel < L.bufLen) - toCopy = L.BufLen - L.sentinel - 1 + toCopy = L.bufLen - L.sentinel - 1 assert(toCopy >= 0) if toCopy > 0: - MoveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) + moveMem(L.buf, addr(L.buf[L.sentinel + 1]), toCopy * chrSize) # "moveMem" handles overlapping regions charsRead = readData(L.input, addr(L.buf[toCopy]), (L.sentinel + 1) * chrSize) div chrSize @@ -91,7 +91,7 @@ proc FillBuffer(L: var TBaseLexer) = dec(s) # BUGFIX (valgrind) while true: assert(s < L.bufLen) - while (s >= 0) and not (L.buf[s] in NewLines): Dec(s) + while (s >= 0) and not (L.buf[s] in NewLines): dec(s) if s >= 0: # we found an appropriate character for a sentinel: L.sentinel = s @@ -99,11 +99,11 @@ proc FillBuffer(L: var TBaseLexer) = else: # rather than to give up here because the line is too long, # double the buffer's size and try again: - oldBufLen = L.BufLen - L.bufLen = L.BufLen * 2 + oldBufLen = L.bufLen + L.bufLen = L.bufLen * 2 L.buf = cast[cstring](realloc(L.buf, L.bufLen * chrSize)) - assert(L.bufLen - oldBuflen == oldBufLen) - charsRead = ReadData(L.input, addr(L.buf[oldBufLen]), + assert(L.bufLen - oldBufLen == oldBufLen) + charsRead = readData(L.input, addr(L.buf[oldBufLen]), oldBufLen * chrSize) div chrSize if charsRead < oldBufLen: L.buf[oldBufLen + charsRead] = EndOfFile @@ -121,19 +121,19 @@ proc fillBaseLexer(L: var TBaseLexer, pos: int): int = result = 0 L.lineStart = result -proc HandleCR(L: var TBaseLexer, pos: int): int = +proc handleCR(L: var TBaseLexer, pos: int): int = assert(L.buf[pos] == '\c') - inc(L.linenumber) + inc(L.lineNumber) result = fillBaseLexer(L, pos) if L.buf[result] == '\L': result = fillBaseLexer(L, result) -proc HandleLF(L: var TBaseLexer, pos: int): int = +proc handleLF(L: var TBaseLexer, pos: int): int = assert(L.buf[pos] == '\L') - inc(L.linenumber) + inc(L.lineNumber) result = fillBaseLexer(L, pos) #L.lastNL := result-1; // BUGFIX: was: result; -proc skip_UTF_8_BOM(L: var TBaseLexer) = +proc skipUtf8Bom(L: var TBaseLexer) = if (L.buf[0] == '\xEF') and (L.buf[1] == '\xBB') and (L.buf[2] == '\xBF'): inc(L.bufpos, 3) inc(L.lineStart, 3) @@ -147,9 +147,9 @@ proc open(L: var TBaseLexer, input: PStream, bufLen: int = 8192) = L.buf = cast[cstring](alloc(bufLen * chrSize)) L.sentinel = bufLen - 1 L.lineStart = 0 - L.linenumber = 1 # lines start at 1 + L.lineNumber = 1 # lines start at 1 fillBuffer(L) - skip_UTF_8_BOM(L) + skipUtf8Bom(L) proc getColNumber(L: TBaseLexer, pos: int): int = result = abs(pos - L.lineStart) @@ -163,5 +163,5 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string = inc(i) add(result, "\n") if marker: - add(result, RepeatChar(getColNumber(L, L.bufpos)) & "^\n") + add(result, repeatChar(getColNumber(L, L.bufpos)) & "^\n") diff --git a/lib/pure/math.nim b/lib/pure/math.nim index 35b9607e0..062cfae25 100644 --- a/lib/pure/math.nim +++ b/lib/pure/math.nim @@ -94,7 +94,7 @@ proc nextPowerOfTwo*(x: int): int = result = result or (result shr 4) result = result or (result shr 2) result = result or (result shr 1) - Inc(result) + inc(result) proc countBits32*(n: int32): int {.noSideEffect.} = ## counts the set bits in `n`. @@ -103,17 +103,17 @@ proc countBits32*(n: int32): int {.noSideEffect.} = v = (v and 0x33333333'i32) +% ((v shr 2'i32) and 0x33333333'i32) result = ((v +% (v shr 4'i32) and 0xF0F0F0F'i32) *% 0x1010101'i32) shr 24'i32 -proc sum*[T](x: openarray[T]): T {.noSideEffect.} = +proc sum*[T](x: openArray[T]): T {.noSideEffect.} = ## computes the sum of the elements in `x`. ## If `x` is empty, 0 is returned. for i in items(x): result = result + i -proc mean*(x: openarray[float]): float {.noSideEffect.} = +proc mean*(x: openArray[float]): float {.noSideEffect.} = ## computes the mean of the elements in `x`. ## If `x` is empty, NaN is returned. result = sum(x) / toFloat(len(x)) -proc variance*(x: openarray[float]): float {.noSideEffect.} = +proc variance*(x: openArray[float]): float {.noSideEffect.} = ## computes the variance of the elements in `x`. ## If `x` is empty, NaN is returned. result = 0.0 diff --git a/lib/pure/md5.nim b/lib/pure/md5.nim index e75f80b4c..0328932fd 100644 --- a/lib/pure/md5.nim +++ b/lib/pure/md5.nim @@ -16,9 +16,9 @@ type MD5Digest* = array[0..15, int8] MD5Buffer = array[0..63, int8] MD5Context* {.final.} = object - State: MD5State - Count: array[0..1, int32] - Buffer: MD5Buffer + state: MD5State + count: array[0..1, int32] + buffer: MD5Buffer const padding: cstring = "\x80\0\0\0" & @@ -32,16 +32,16 @@ const "\0\0\0\0" proc F(x, y, z: int32): int32 {.inline.} = - Result = (x and y) or ((not x) and z) + result = (x and y) or ((not x) and z) proc G(x, y, z: int32): int32 {.inline.} = - Result = (x and z) or (y and (not z)) + result = (x and z) or (y and (not z)) proc H(x, y, z: int32): int32 {.inline.} = - Result = x xor y xor z + result = x xor y xor z proc I(x, y, z: int32): int32 {.inline.} = - Result = y xor (x or (not z)) + result = y xor (x or (not z)) proc rot(x: var int32, n: int8) {.inline.} = x = toU32(x shl ze(n)) or (x shr toU32(32 -% ze(n))) @@ -75,7 +75,7 @@ proc encode(dest: var MD5Block, src: cstring) = ord(src[j+3]) shl 24) inc(j, 4) -proc decode(dest: var openarray[int8], src: openarray[int32]) = +proc decode(dest: var openArray[int8], src: openArray[int32]) = var i = 0 for j in 0..high(src): dest[i] = toU8(src[j] and 0xff'i32) @@ -87,7 +87,7 @@ proc decode(dest: var openarray[int8], src: openarray[int32]) = proc transform(Buffer: pointer, State: var MD5State) = var myBlock: MD5Block - encode(myBlock, cast[cstring](buffer)) + encode(myBlock, cast[cstring](Buffer)) var a = State[0] var b = State[1] var c = State[2] @@ -161,7 +161,7 @@ proc transform(Buffer: pointer, State: var MD5State) = State[2] = State[2] +% c State[3] = State[3] +% d -proc MD5Init*(c: var MD5Context) = +proc md5Init*(c: var MD5Context) = ## initializes a MD5Context c.State[0] = 0x67452301'i32 c.State[1] = 0xEFCDAB89'i32 @@ -169,64 +169,64 @@ proc MD5Init*(c: var MD5Context) = c.State[3] = 0x10325476'i32 c.Count[0] = 0'i32 c.Count[1] = 0'i32 - ZeroMem(addr(c.Buffer), SizeOf(MD5Buffer)) + zeroMem(addr(c.Buffer), sizeof(MD5Buffer)) -proc MD5Update*(c: var MD5Context, input: cstring, len: int) = +proc md5Update*(c: var MD5Context, input: cstring, len: int) = ## updates the MD5Context with the `input` data of length `len` var input = input - var Index = (c.Count[0] shr 3) and 0x3F + var Index = (c.count[0] shr 3) and 0x3F c.Count[0] = c.count[0] +% toU32(len shl 3) if c.Count[0] < (len shl 3): c.Count[1] = c.count[1] +% 1'i32 c.Count[1] = c.count[1] +% toU32(len shr 29) var PartLen = 64 - Index if len >= PartLen: - CopyMem(addr(c.Buffer[Index]), Input, PartLen) + copyMem(addr(c.Buffer[Index]), input, PartLen) transform(addr(c.Buffer), c.State) var i = PartLen while i + 63 < len: - Transform(addr(Input[I]), c.State) + transform(addr(input[i]), c.State) inc(i, 64) - CopyMem(addr(c.Buffer[0]), addr(Input[i]), len-i) + copyMem(addr(c.Buffer[0]), addr(input[i]), len-i) else: - CopyMem(addr(c.Buffer[Index]), addr(Input[0]), len) + copyMem(addr(c.Buffer[Index]), addr(input[0]), len) -proc MD5Final*(c: var MD5Context, digest: var MD5Digest) = +proc md5Final*(c: var MD5Context, digest: var MD5Digest) = ## finishes the MD5Context and stores the result in `digest` var Bits: MD5CBits PadLen: int - decode(bits, c.Count) + decode(Bits, c.Count) var Index = (c.Count[0] shr 3) and 0x3F if Index < 56: PadLen = 56 - Index else: PadLen = 120 - Index - MD5Update(c, padding, PadLen) - MD5Update(c, cast[cstring](addr(Bits)), 8) + md5Update(c, padding, PadLen) + md5Update(c, cast[cstring](addr(Bits)), 8) decode(digest, c.State) - ZeroMem(addr(c), SizeOf(MD5Context)) + zeroMem(addr(c), sizeof(MD5Context)) proc toMD5*(s: string): MD5Digest = ## computes the MD5Digest value for a string `s` var c: MD5Context - MD5Init(c) - MD5Update(c, cstring(s), len(s)) - MD5Final(c, result) + md5Init(c) + md5Update(c, cstring(s), len(s)) + md5Final(c, result) proc `$`*(D: MD5Digest): string = ## converts a MD5Digest value into its string representation const digits = "0123456789abcdef" result = "" for i in 0..15: - add(result, Digits[(D[I] shr 4) and 0xF]) - add(result, Digits[D[I] and 0xF]) + add(result, Digits[(D[i] shr 4) and 0xF]) + add(result, Digits[D[i] and 0xF]) proc getMD5*(s: string): string = ## computes an MD5 value of `s` and returns its string representation var c: MD5Context d: MD5Digest - MD5Init(c) - MD5Update(c, cstring(s), len(s)) - MD5Final(c, d) + md5Init(c) + md5Update(c, cstring(s), len(s)) + md5Final(c, d) result = $d proc `==`*(D1, D2: MD5Digest): bool = diff --git a/lib/pure/memfiles.nim b/lib/pure/memfiles.nim index 9f4094b40..8c404abe8 100644 --- a/lib/pure/memfiles.nim +++ b/lib/pure/memfiles.nim @@ -52,9 +52,9 @@ proc open*(filename: string, mode: TFileMode = fmRead, when defined(windows): template fail(errCode: TOSErrorCode, msg: expr) = rollback() - if result.fHandle != 0: discard CloseHandle(result.fHandle) - if result.mapHandle != 0: discard CloseHandle(result.mapHandle) - OSError(errCode) + if result.fHandle != 0: discard closeHandle(result.fHandle) + if result.mapHandle != 0: discard closeHandle(result.mapHandle) + osError(errCode) # return false #raise newException(EIO, msg) @@ -69,36 +69,36 @@ proc open*(filename: string, mode: TFileMode = fmRead, 0) when useWinUnicode: - result.fHandle = callCreateFile(CreateFileW, newWideCString(filename)) + result.fHandle = callCreateFile(createFileW, newWideCString(filename)) else: result.fHandle = callCreateFile(CreateFileA, filename) if result.fHandle == INVALID_HANDLE_VALUE: - fail(OSLastError(), "error opening file") + fail(osLastError(), "error opening file") if newFileSize != -1: var sizeHigh = int32(newFileSize shr 32) sizeLow = int32(newFileSize and 0xffffffff) - var status = SetFilePointer(result.fHandle, sizeLow, addr(sizeHigh), + var status = setFilePointer(result.fHandle, sizeLow, addr(sizeHigh), FILE_BEGIN) - let lastErr = OSLastError() + let lastErr = osLastError() if (status == INVALID_SET_FILE_POINTER and lastErr.int32 != NO_ERROR) or - (SetEndOfFile(result.fHandle) == 0): + (setEndOfFile(result.fHandle) == 0): fail(lastErr, "error setting file size") # since the strings are always 'nil', we simply always call # CreateFileMappingW which should be slightly faster anyway: - result.mapHandle = CreateFileMappingW( + result.mapHandle = createFileMappingW( result.fHandle, nil, if readonly: PAGE_READONLY else: PAGE_READWRITE, 0, 0, nil) if result.mapHandle == 0: - fail(OSLastError(), "error creating mapping") + fail(osLastError(), "error creating mapping") - result.mem = MapViewOfFileEx( + result.mem = mapViewOfFileEx( result.mapHandle, if readonly: FILE_MAP_READ else: FILE_MAP_WRITE, int32(offset shr 32), @@ -107,12 +107,12 @@ proc open*(filename: string, mode: TFileMode = fmRead, nil) if result.mem == nil: - fail(OSLastError(), "error mapping view") + fail(osLastError(), "error mapping view") var hi, low: int32 - low = GetFileSize(result.fHandle, addr(hi)) + low = getFileSize(result.fHandle, addr(hi)) if low == INVALID_FILE_SIZE: - fail(OSLastError(), "error getting file size") + fail(osLastError(), "error getting file size") else: var fileSize = (int64(hi) shr 32) or low if mappedSize != -1: result.size = min(fileSize, mappedSize).int @@ -122,7 +122,7 @@ proc open*(filename: string, mode: TFileMode = fmRead, template fail(errCode: TOSErrorCode, msg: expr) = rollback() if result.handle != 0: discard close(result.handle) - OSError(errCode) + osError(errCode) var flags = if readonly: O_RDONLY else: O_RDWR @@ -133,22 +133,22 @@ proc open*(filename: string, mode: TFileMode = fmRead, if result.handle == -1: # XXX: errno is supposed to be set here # Is there an exception that wraps it? - fail(OSLastError(), "error opening file") + fail(osLastError(), "error opening file") if newFileSize != -1: if ftruncate(result.handle, newFileSize) == -1: - fail(OSLastError(), "error setting file size") + fail(osLastError(), "error setting file size") if mappedSize != -1: result.size = mappedSize else: - var stat: Tstat + var stat: TStat if fstat(result.handle, stat) != -1: # XXX: Hmm, this could be unsafe # Why is mmap taking int anyway? result.size = int(stat.st_size) else: - fail(OSLastError(), "error getting file size") + fail(osLastError(), "error getting file size") result.mem = mmap( nil, @@ -159,7 +159,7 @@ proc open*(filename: string, mode: TFileMode = fmRead, offset) if result.mem == cast[pointer](MAP_FAILED): - fail(OSLastError(), "file mapping failed") + fail(osLastError(), "file mapping failed") proc close*(f: var TMemFile) = ## closes the memory mapped file `f`. All changes are written back to the @@ -170,13 +170,13 @@ proc close*(f: var TMemFile) = when defined(windows): if f.fHandle != INVALID_HANDLE_VALUE: - lastErr = OSLastError() - error = UnmapViewOfFile(f.mem) == 0 - error = (CloseHandle(f.mapHandle) == 0) or error - error = (CloseHandle(f.fHandle) == 0) or error + lastErr = osLastError() + error = unmapViewOfFile(f.mem) == 0 + error = (closeHandle(f.mapHandle) == 0) or error + error = (closeHandle(f.fHandle) == 0) or error else: if f.handle != 0: - lastErr = OSLastError() + lastErr = osLastError() error = munmap(f.mem, f.size) != 0 error = (close(f.handle) != 0) or error @@ -189,5 +189,5 @@ proc close*(f: var TMemFile) = else: f.handle = 0 - if error: OSError(lastErr) + if error: osError(lastErr) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index d74cb1fb9..1f42d0d58 100644 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -93,11 +93,11 @@ when defined(Nimdoc): # only for proper documentation: elif defined(macos): const - curdir* = ':' - pardir* = "::" - dirsep* = ':' - altsep* = dirsep - pathsep* = ',' + CurDir* = ':' + ParDir* = "::" + DirSep* = ':' + AltSep* = Dirsep + PathSep* = ',' FileSystemCaseSensitive* = false ExeExt* = "" ScriptExt* = "" @@ -123,57 +123,61 @@ elif defined(macos): # grandparent etc. elif doslike: const - curdir* = '.' - pardir* = ".." - dirsep* = '\\' # seperator within paths - altsep* = '/' - pathSep* = ';' # seperator between paths + CurDir* = '.' + ParDir* = ".." + DirSep* = '\\' # seperator within paths + AltSep* = '/' + PathSep* = ';' # seperator between paths FileSystemCaseSensitive* = false ExeExt* = "exe" ScriptExt* = "bat" DynlibFormat* = "$1.dll" elif defined(PalmOS) or defined(MorphOS): const - dirsep* = '/' - altsep* = dirsep + DirSep* = '/' + AltSep* = Dirsep PathSep* = ';' - pardir* = ".." + ParDir* = ".." FileSystemCaseSensitive* = false ExeExt* = "" ScriptExt* = "" DynlibFormat* = "$1.prc" elif defined(RISCOS): const - dirsep* = '.' - altsep* = '.' - pardir* = ".." # is this correct? - pathSep* = ',' + DirSep* = '.' + AltSep* = '.' + ParDir* = ".." # is this correct? + PathSep* = ',' FileSystemCaseSensitive* = true ExeExt* = "" ScriptExt* = "" DynlibFormat* = "lib$1.so" else: # UNIX-like operating system const - curdir* = '.' - pardir* = ".." - dirsep* = '/' - altsep* = dirsep - pathSep* = ':' + CurDir* = '.' + ParDir* = ".." + DirSep* = '/' + AltSep* = DirSep + PathSep* = ':' FileSystemCaseSensitive* = true ExeExt* = "" ScriptExt* = "" DynlibFormat* = when defined(macosx): "lib$1.dylib" else: "lib$1.so" when defined(posix): - var - pathMax {.importc: "PATH_MAX", header: "<stdlib.h>".}: cint + when NoFakeVars: + const pathMax = 5000 # doesn't matter really. The concept of PATH_MAX + # doesn't work anymore on modern OSes. + else: + var + pathMax {.importc: "PATH_MAX", header: "<stdlib.h>".}: cint const ExtSep* = '.' ## The character which separates the base filename from the extension; ## for example, the '.' in ``os.nim``. -proc OSErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = +proc osErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = ## Retrieves the operating system's error flag, ``errno``. ## On Windows ``GetLastError`` is checked before ``errno``. ## Returns "" if no error occured. @@ -182,25 +186,25 @@ proc OSErrorMsg*(): string {.rtl, extern: "nos$1", deprecated.} = result = "" when defined(Windows): - var err = GetLastError() + var err = getLastError() if err != 0'i32: when useWinUnicode: - var msgbuf: widecstring - if FormatMessageW(0x00000100 or 0x00001000 or 0x00000200, + var msgbuf: WideCString + if formatMessageW(0x00000100 or 0x00001000 or 0x00000200, nil, err, 0, addr(msgbuf), 0, nil) != 0'i32: result = $msgbuf - if msgbuf != nil: LocalFree(cast[pointer](msgbuf)) + if msgbuf != nil: localFree(cast[pointer](msgbuf)) else: var msgbuf: cstring - if FormatMessageA(0x00000100 or 0x00001000 or 0x00000200, + if formatMessageA(0x00000100 or 0x00001000 or 0x00000200, nil, err, 0, addr(msgbuf), 0, nil) != 0'i32: result = $msgbuf - if msgbuf != nil: LocalFree(msgbuf) + if msgbuf != nil: localFree(msgbuf) if errno != 0'i32: result = $os.strerror(errno) {.push warning[deprecated]: off.} -proc OSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = +proc osError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = ## raises an EOS exception with the given message ``msg``. ## If ``msg == ""``, the operating system's error flag ## (``errno``) is converted to a readable error message. On Windows @@ -209,7 +213,7 @@ proc OSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = ## ## **Deprecated since version 0.9.4**: use the other ``OSError`` proc. if len(msg) == 0: - var m = OSErrorMsg() + var m = osErrorMsg() raise newException(EOS, if m.len > 0: m else: "unknown OS error") else: raise newException(EOS, msg) @@ -218,7 +222,7 @@ proc OSError*(msg: string = "") {.noinline, rtl, extern: "nos$1", deprecated.} = proc `==`*(err1, err2: TOSErrorCode): bool {.borrow.} proc `$`*(err: TOSErrorCode): string {.borrow.} -proc OSErrorMsg*(errorCode: TOSErrorCode): string = +proc osErrorMsg*(errorCode: TOSErrorCode): string = ## Converts an OS error code into a human readable string. ## ## The error code can be retrieved using the ``OSLastError`` proc. @@ -233,22 +237,22 @@ proc OSErrorMsg*(errorCode: TOSErrorCode): string = when defined(Windows): if errorCode != TOSErrorCode(0'i32): when useWinUnicode: - var msgbuf: widecstring - if FormatMessageW(0x00000100 or 0x00001000 or 0x00000200, + var msgbuf: WideCString + if formatMessageW(0x00000100 or 0x00001000 or 0x00000200, nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32: result = $msgbuf - if msgbuf != nil: LocalFree(cast[pointer](msgbuf)) + if msgbuf != nil: localFree(cast[pointer](msgbuf)) else: var msgbuf: cstring - if FormatMessageA(0x00000100 or 0x00001000 or 0x00000200, + if formatMessageA(0x00000100 or 0x00001000 or 0x00000200, nil, errorCode.int32, 0, addr(msgbuf), 0, nil) != 0'i32: result = $msgbuf - if msgbuf != nil: LocalFree(msgbuf) + if msgbuf != nil: localFree(msgbuf) else: if errorCode != TOSErrorCode(0'i32): result = $os.strerror(errorCode.int32) -proc OSError*(errorCode: TOSErrorCode) = +proc osError*(errorCode: TOSErrorCode) = ## Raises an ``EOS`` exception. The ``errorCode`` will determine the ## message, ``OSErrorMsg`` will be used to get this message. ## @@ -256,14 +260,14 @@ proc OSError*(errorCode: TOSErrorCode) = ## ## If the error code is ``0`` or an error message could not be retrieved, ## the message ``unknown OS error`` will be used. - let msg = OSErrorMsg(errorCode) + let msg = osErrorMsg(errorCode) if msg == "": raise newException(EOS, "unknown OS error") else: raise newException(EOS, msg) {.push stackTrace:off.} -proc OSLastError*(): TOSErrorCode = +proc osLastError*(): TOSErrorCode = ## Retrieves the last operating system error code. ## ## This procedure is useful in the event when an OS call fails. In that case @@ -278,12 +282,12 @@ proc OSLastError*(): TOSErrorCode = ## immediately after an OS call fails. On POSIX systems this is not a problem. when defined(windows): - result = TOSErrorCode(GetLastError()) + result = TOSErrorCode(getLastError()) else: result = TOSErrorCode(errno) {.pop.} -proc UnixToNativePath*(path: string): string {. +proc unixToNativePath*(path: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Converts an UNIX-like path to a native one. ## @@ -300,11 +304,11 @@ proc UnixToNativePath*(path: string): string {. elif defined(macos): result = "" # must not start with ':' else: - result = $dirSep + result = $DirSep start = 1 elif path[0] == '.' and path[1] == '/': # current directory - result = $curdir + result = $CurDir start = 2 else: result = "" @@ -318,12 +322,12 @@ proc UnixToNativePath*(path: string): string {. if result[high(result)] == ':': add result, ':' else: - add result, pardir + add result, ParDir else: - add result, pardir & dirSep + add result, ParDir & DirSep inc(i, 3) elif path[i] == '/': - add result, dirSep + add result, DirSep inc(i) else: add result, path[i] @@ -336,48 +340,33 @@ when defined(windows): template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = var varname = winApiProc(newWideCString(arg), arg2) - proc FindFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle = - result = FindFirstFileW(newWideCString(a), b) - template FindNextFile(a, b: expr): expr = FindNextFileW(a, b) + proc findFirstFile(a: string, b: var TWIN32_FIND_DATA): THandle = + result = findFirstFileW(newWideCString(a), b) + template findNextFile(a, b: expr): expr = findNextFileW(a, b) template getCommandLine(): expr = getCommandLineW() - proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} = - let - nul = 0 - dot = ord('.') - result = (f.cFilename[0].int == dot) - if result: - result = (f.cFilename[1].int in {dot, nul}) - if result: - result = (f.cFilename[2].int == nul) - template getFilename(f: expr): expr = $cast[WideCString](addr(f.cFilename[0])) else: - template FindFirstFile(a, b: expr): expr = FindFirstFileA(a, b) - template FindNextFile(a, b: expr): expr = FindNextFileA(a, b) + template findFirstFile(a, b: expr): expr = findFirstFileA(a, b) + template findNextFile(a, b: expr): expr = findNextFileA(a, b) template getCommandLine(): expr = getCommandLineA() - proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} = - let - nul = '\0' - dot = '.' - result = (f.cFilename[0] == dot) - if result: - result = (f.cFilename[1] in {dot, nul}) - if result: - result = (f.cFilename[2] == nul) - template getFilename(f: expr): expr = $f.cFilename + proc skipFindData(f: TWIN32_FIND_DATA): bool {.inline.} = + const dot = ord('.') + result = f.cFileName[0].int == dot and(f.cFileName[1].int == 0 or + f.cFileName[1].int == dot and f.cFileName[2].int == 0) + proc existsFile*(filename: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = ## Returns true if the file exists, false otherwise. when defined(windows): when useWinUnicode: - wrapUnary(a, GetFileAttributesW, filename) + wrapUnary(a, getFileAttributesW, filename) else: - var a = GetFileAttributesA(filename) + var a = getFileAttributesA(filename) if a != -1'i32: result = (a and FILE_ATTRIBUTE_DIRECTORY) == 0'i32 else: @@ -389,53 +378,61 @@ proc existsDir*(dir: string): bool {.rtl, extern: "nos$1", tags: [FReadDir].} = ## is returned. when defined(windows): when useWinUnicode: - wrapUnary(a, GetFileAttributesW, dir) + wrapUnary(a, getFileAttributesW, dir) else: - var a = GetFileAttributesA(dir) + var a = getFileAttributesA(dir) if a != -1'i32: result = (a and FILE_ATTRIBUTE_DIRECTORY) != 0'i32 else: var res: TStat return stat(dir, res) >= 0'i32 and S_ISDIR(res.st_mode) +proc fileExists*(filename: string): bool {.inline.} = + ## Synonym for existsFile + existsFile(filename) + +proc dirExists*(dir: string): bool {.inline.} = + ## Synonym for existsDir + existsDir(dir) + proc getLastModificationTime*(file: string): TTime {.rtl, extern: "nos$1".} = ## Returns the `file`'s last modification time. when defined(posix): var res: TStat - if stat(file, res) < 0'i32: OSError(OSLastError()) + if stat(file, res) < 0'i32: osError(osLastError()) return res.st_mtime else: - var f: TWIN32_Find_Data - var h = findfirstFile(file, f) - if h == -1'i32: OSError(OSLastError()) + var f: TWIN32_FIND_DATA + var h = findFirstFile(file, f) + if h == -1'i32: osError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftLastWriteTime)) - findclose(h) + findClose(h) proc getLastAccessTime*(file: string): TTime {.rtl, extern: "nos$1".} = ## Returns the `file`'s last read or write access time. when defined(posix): var res: TStat - if stat(file, res) < 0'i32: OSError(OSLastError()) + if stat(file, res) < 0'i32: osError(osLastError()) return res.st_atime else: - var f: TWIN32_Find_Data - var h = findfirstFile(file, f) - if h == -1'i32: OSError(OSLastError()) + var f: TWIN32_FIND_DATA + var h = findFirstFile(file, f) + if h == -1'i32: osError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftLastAccessTime)) - findclose(h) + findClose(h) proc getCreationTime*(file: string): TTime {.rtl, extern: "nos$1".} = ## Returns the `file`'s creation time. when defined(posix): var res: TStat - if stat(file, res) < 0'i32: OSError(OSLastError()) + if stat(file, res) < 0'i32: osError(osLastError()) return res.st_ctime else: - var f: TWIN32_Find_Data - var h = findfirstFile(file, f) - if h == -1'i32: OSError(OSLastError()) + var f: TWIN32_FIND_DATA + var h = findFirstFile(file, f) + if h == -1'i32: osError(osLastError()) result = winTimeToUnixTime(rdFileTime(f.ftCreationTime)) - findclose(h) + findClose(h) proc fileNewer*(a, b: string): bool {.rtl, extern: "nos$1".} = ## Returns true if the file `a` is newer than file `b`, i.e. if `a`'s @@ -448,40 +445,41 @@ proc getCurrentDir*(): string {.rtl, extern: "nos$1", tags: [].} = when defined(windows): when useWinUnicode: var res = newWideCString("", bufsize) - var L = GetCurrentDirectoryW(bufsize, res) - if L == 0'i32: OSError(OSLastError()) + var L = getCurrentDirectoryW(bufsize, res) + if L == 0'i32: osError(osLastError()) result = res$L else: result = newString(bufsize) - var L = GetCurrentDirectoryA(bufsize, result) - if L == 0'i32: OSError(OSLastError()) + var L = getCurrentDirectoryA(bufsize, result) + if L == 0'i32: osError(osLastError()) setLen(result, L) else: result = newString(bufsize) if getcwd(result, bufsize) != nil: - setlen(result, c_strlen(result)) + setLen(result, c_strlen(result)) else: - OSError(OSLastError()) + osError(osLastError()) proc setCurrentDir*(newDir: string) {.inline, tags: [].} = ## Sets the `current working directory`:idx:; `EOS` is raised if ## `newDir` cannot been set. when defined(Windows): when useWinUnicode: - if SetCurrentDirectoryW(newWideCString(newDir)) == 0'i32: OSError(OSLastError()) + if setCurrentDirectoryW(newWideCString(newDir)) == 0'i32: + osError(osLastError()) else: - if SetCurrentDirectoryA(newDir) == 0'i32: OSError(OSLastError()) + if setCurrentDirectoryA(newDir) == 0'i32: osError(osLastError()) else: - if chdir(newDir) != 0'i32: OSError(OSLastError()) + if chdir(newDir) != 0'i32: osError(osLastError()) -proc JoinPath*(head, tail: string): string {. +proc joinPath*(head, tail: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Joins two directory names to one. ## ## For example on Unix: ## ## .. code-block:: nimrod - ## JoinPath("usr", "lib") + ## joinPath("usr", "lib") ## ## results in: ## @@ -495,10 +493,10 @@ proc JoinPath*(head, tail: string): string {. ## examples on Unix: ## ## .. code-block:: nimrod - ## assert JoinPath("usr", "") == "usr/" - ## assert JoinPath("", "lib") == "lib" - ## assert JoinPath("", "/lib") == "/lib" - ## assert JoinPath("usr/", "/lib") == "usr/lib" + ## assert joinPath("usr", "") == "usr/" + ## assert joinPath("", "lib") == "lib" + ## assert joinPath("", "/lib") == "/lib" + ## assert joinPath("usr/", "/lib") == "usr/lib" if len(head) == 0: result = tail elif head[len(head)-1] in {DirSep, AltSep}: @@ -512,17 +510,17 @@ proc JoinPath*(head, tail: string): string {. else: result = head & DirSep & tail -proc JoinPath*(parts: varargs[string]): string {.noSideEffect, +proc joinPath*(parts: varargs[string]): string {.noSideEffect, rtl, extern: "nos$1OpenArray".} = - ## The same as `JoinPath(head, tail)`, but works with any number of directory + ## The same as `joinPath(head, tail)`, but works with any number of directory ## parts. You need to pass at least one element or the proc will assert in ## debug builds and crash on release builds. result = parts[0] for i in 1..high(parts): - result = JoinPath(result, parts[i]) + result = joinPath(result, parts[i]) proc `/` * (head, tail: string): string {.noSideEffect.} = - ## The same as ``JoinPath(head, tail)`` + ## The same as ``joinPath(head, tail)`` ## ## Here are some examples for Unix: ## @@ -531,24 +529,24 @@ proc `/` * (head, tail: string): string {.noSideEffect.} = ## assert "" / "lib" == "lib" ## assert "" / "/lib" == "/lib" ## assert "usr/" / "/lib" == "usr/lib" - return JoinPath(head, tail) + return joinPath(head, tail) -proc SplitPath*(path: string): tuple[head, tail: string] {. +proc splitPath*(path: string): tuple[head, tail: string] {. noSideEffect, rtl, extern: "nos$1".} = ## Splits a directory into (head, tail), so that - ## ``JoinPath(head, tail) == path``. + ## ``joinPath(head, tail) == path``. ## ## Examples: ## ## .. code-block:: nimrod - ## SplitPath("usr/local/bin") -> ("usr/local", "bin") - ## SplitPath("usr/local/bin/") -> ("usr/local/bin", "") - ## SplitPath("bin") -> ("", "bin") - ## SplitPath("/bin") -> ("", "bin") - ## SplitPath("") -> ("", "") + ## splitPath("usr/local/bin") -> ("usr/local", "bin") + ## splitPath("usr/local/bin/") -> ("usr/local/bin", "") + ## splitPath("bin") -> ("", "bin") + ## splitPath("/bin") -> ("", "bin") + ## splitPath("") -> ("", "") var sepPos = -1 for i in countdown(len(path)-1, 0): - if path[i] in {dirsep, altsep}: + if path[i] in {DirSep, AltSep}: sepPos = i break if sepPos >= 0: @@ -560,9 +558,9 @@ proc SplitPath*(path: string): tuple[head, tail: string] {. proc parentDirPos(path: string): int = var q = 1 - if path[len(path)-1] in {dirsep, altsep}: q = 2 + if path[len(path)-1] in {DirSep, AltSep}: q = 2 for i in countdown(len(path)-q, 0): - if path[i] in {dirsep, altsep}: return i + if path[i] in {DirSep, AltSep}: return i result = -1 proc parentDir*(path: string): string {. @@ -603,8 +601,8 @@ iterator parentDirs*(path: string, fromRoot=false, inclusive=true): string = else: for i in countup(0, path.len - 2): # ignore the last / # deal with non-normalized paths such as /foo//bar//baz - if path[i] in {dirsep, altsep} and - (i == 0 or path[i-1] notin {dirsep, altsep}): + if path[i] in {DirSep, AltSep} and + (i == 0 or path[i-1] notin {DirSep, AltSep}): yield path.substr(0, i) if inclusive: yield path @@ -619,17 +617,17 @@ proc `/../` * (head, tail: string): string {.noSideEffect.} = result = head / tail proc normExt(ext: string): string = - if ext == "" or ext[0] == extSep: result = ext # no copy needed here - else: result = extSep & ext + if ext == "" or ext[0] == ExtSep: result = ext # no copy needed here + else: result = ExtSep & ext proc searchExtPos(s: string): int = # BUGFIX: do not search until 0! .DS_Store is no file extension! result = -1 for i in countdown(len(s)-1, 1): - if s[i] == extsep: + if s[i] == ExtSep: result = i break - elif s[i] in {dirsep, altsep}: + elif s[i] in {DirSep, AltSep}: break # do not skip over path proc splitFile*(path: string): tuple[dir, name, ext: string] {. @@ -649,7 +647,7 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {. ## If `path` has no extension, `ext` is the empty string. ## If `path` has no directory component, `dir` is the empty string. ## If `path` has no filename component, `name` and `ext` are empty strings. - if path.len == 0 or path[path.len-1] in {dirSep, altSep}: + if path.len == 0 or path[path.len-1] in {DirSep, AltSep}: result = (path, "", "") else: var sepPos = -1 @@ -657,8 +655,8 @@ proc splitFile*(path: string): tuple[dir, name, ext: string] {. for i in countdown(len(path)-1, 0): if path[i] == ExtSep: if dotPos == path.len and i > 0 and - path[i-1] notin {dirsep, altsep}: dotPos = i - elif path[i] in {dirsep, altsep}: + path[i-1] notin {DirSep, AltSep}: dotPos = i + elif path[i] in {DirSep, AltSep}: sepPos = i break result.dir = substr(path, 0, sepPos-1) @@ -669,7 +667,7 @@ proc extractFilename*(path: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Extracts the filename of a given `path`. This is the same as ## ``name & ext`` from ``splitFile(path)``. - if path.len == 0 or path[path.len-1] in {dirSep, altSep}: + if path.len == 0 or path[path.len-1] in {DirSep, AltSep}: result = "" else: result = splitPath(path).tail @@ -680,26 +678,26 @@ proc expandFilename*(filename: string): string {.rtl, extern: "nos$1", when defined(windows): const bufsize = 3072'i32 when useWinUnicode: - var unused: widecstring + var unused: WideCString var res = newWideCString("", bufsize div 2) - var L = GetFullPathNameW(newWideCString(filename), bufsize, res, unused) + var L = getFullPathNameW(newWideCString(filename), bufsize, res, unused) if L <= 0'i32 or L >= bufsize: - OSError(OSLastError()) + osError(osLastError()) result = res$L else: var unused: cstring result = newString(bufsize) - var L = GetFullPathNameA(filename, bufsize, result, unused) - if L <= 0'i32 or L >= bufsize: OSError(OSLastError()) + var L = getFullPathNameA(filename, bufsize, result, unused) + if L <= 0'i32 or L >= bufsize: osError(osLastError()) setLen(result, L) else: # careful, realpath needs to take an allocated buffer according to Posix: result = newString(pathMax) var r = realpath(filename, result) - if r.isNil: OSError(OSLastError()) - setlen(result, c_strlen(result)) + if r.isNil: osError(osLastError()) + setLen(result, c_strlen(result)) -proc ChangeFileExt*(filename, ext: string): string {. +proc changeFileExt*(filename, ext: string): string {. noSideEffect, rtl, extern: "nos$1".} = ## Changes the file extension to `ext`. ## @@ -768,47 +766,47 @@ proc sameFile*(path1, path2: string): bool {.rtl, extern: "nos$1", when useWinUnicode: var p1 = newWideCString(path1) var p2 = newWideCString(path2) - template OpenHandle(path: expr): expr = - CreateFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or + template openHandle(path: expr): expr = + createFileW(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0) - var f1 = OpenHandle(p1) - var f2 = OpenHandle(p2) + var f1 = openHandle(p1) + var f2 = openHandle(p2) else: - template OpenHandle(path: expr): expr = - CreateFileA(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or + template openHandle(path: expr): expr = + createFileA(path, 0'i32, FILE_SHARE_DELETE or FILE_SHARE_READ or FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_ATTRIBUTE_NORMAL, 0) - var f1 = OpenHandle(path1) - var f2 = OpenHandle(path2) + var f1 = openHandle(path1) + var f2 = openHandle(path2) var lastErr: TOSErrorCode if f1 != INVALID_HANDLE_VALUE and f2 != INVALID_HANDLE_VALUE: var fi1, fi2: TBY_HANDLE_FILE_INFORMATION - if GetFileInformationByHandle(f1, addr(fi1)) != 0 and - GetFileInformationByHandle(f2, addr(fi2)) != 0: + if getFileInformationByHandle(f1, addr(fi1)) != 0 and + getFileInformationByHandle(f2, addr(fi2)) != 0: result = fi1.dwVolumeSerialNumber == fi2.dwVolumeSerialNumber and fi1.nFileIndexHigh == fi2.nFileIndexHigh and fi1.nFileIndexLow == fi2.nFileIndexLow else: - lastErr = OSLastError() + lastErr = osLastError() success = false else: - lastErr = OSLastError() + lastErr = osLastError() success = false - discard CloseHandle(f1) - discard CloseHandle(f2) + discard closeHandle(f1) + discard closeHandle(f2) - if not success: OSError(lastErr) + if not success: osError(lastErr) else: var a, b: TStat if stat(path1, a) < 0'i32 or stat(path2, b) < 0'i32: - OSError(OSLastError()) + osError(osLastError()) else: result = a.st_dev == b.st_dev and a.st_ino == b.st_ino @@ -824,11 +822,11 @@ proc sameFileContent*(path1, path2: string): bool {.rtl, extern: "nos$1", if not open(b, path2): close(a) return false - var bufA = alloc(bufsize) - var bufB = alloc(bufsize) - while True: - var readA = readBuffer(a, bufA, bufsize) - var readB = readBuffer(b, bufB, bufsize) + var bufA = alloc(bufSize) + var bufB = alloc(bufSize) + while true: + var readA = readBuffer(a, bufA, bufSize) + var readB = readBuffer(b, bufB, bufSize) if readA != readB: result = false break @@ -862,7 +860,7 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {. ## permission is available in any case. when defined(posix): var a: TStat - if stat(filename, a) < 0'i32: OSError(OSLastError()) + if stat(filename, a) < 0'i32: osError(osLastError()) result = {} if (a.st_mode and S_IRUSR) != 0'i32: result.incl(fpUserRead) if (a.st_mode and S_IWUSR) != 0'i32: result.incl(fpUserWrite) @@ -877,10 +875,10 @@ proc getFilePermissions*(filename: string): set[TFilePermission] {. if (a.st_mode and S_IXOTH) != 0'i32: result.incl(fpOthersExec) else: when useWinUnicode: - wrapUnary(res, GetFileAttributesW, filename) + wrapUnary(res, getFileAttributesW, filename) else: - var res = GetFileAttributesA(filename) - if res == -1'i32: OSError(OSLastError()) + var res = getFileAttributesA(filename) + if res == -1'i32: osError(osLastError()) if (res and FILE_ATTRIBUTE_READONLY) != 0'i32: result = {fpUserExec, fpUserRead, fpGroupExec, fpGroupRead, fpOthersExec, fpOthersRead} @@ -906,22 +904,22 @@ proc setFilePermissions*(filename: string, permissions: set[TFilePermission]) {. if fpOthersWrite in permissions: p = p or S_IWOTH if fpOthersExec in permissions: p = p or S_IXOTH - if chmod(filename, p) != 0: OSError(OSLastError()) + if chmod(filename, p) != 0: osError(osLastError()) else: when useWinUnicode: - wrapUnary(res, GetFileAttributesW, filename) + wrapUnary(res, getFileAttributesW, filename) else: - var res = GetFileAttributesA(filename) - if res == -1'i32: OSError(OSLastError()) + var res = getFileAttributesA(filename) + if res == -1'i32: osError(osLastError()) if fpUserWrite in permissions: res = res and not FILE_ATTRIBUTE_READONLY else: res = res or FILE_ATTRIBUTE_READONLY when useWinUnicode: - wrapBinary(res2, SetFileAttributesW, filename, res) + wrapBinary(res2, setFileAttributesW, filename, res) else: - var res2 = SetFileAttributesA(filename, res) - if res2 == - 1'i32: OSError(OSLastError()) + var res2 = setFileAttributesA(filename, res) + if res2 == - 1'i32: osError(osLastError()) proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", tags: [FReadIO, FWriteIO].} = @@ -938,27 +936,27 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", when useWinUnicode: let s = newWideCString(source) let d = newWideCString(dest) - if CopyFileW(s, d, 0'i32) == 0'i32: OSError(OSLastError()) + if copyFileW(s, d, 0'i32) == 0'i32: osError(osLastError()) else: - if CopyFileA(source, dest, 0'i32) == 0'i32: OSError(OSLastError()) + if copyFileA(source, dest, 0'i32) == 0'i32: osError(osLastError()) else: # generic version of copyFile which works for any platform: const bufSize = 8000 # better for memory manager var d, s: TFile - if not open(s, source): OSError(OSLastError()) + if not open(s, source): osError(osLastError()) if not open(d, dest, fmWrite): close(s) - OSError(OSLastError()) - var buf = alloc(bufsize) - while True: - var bytesread = readBuffer(s, buf, bufsize) + osError(osLastError()) + var buf = alloc(bufSize) + while true: + var bytesread = readBuffer(s, buf, bufSize) if bytesread > 0: var byteswritten = writeBuffer(d, buf, bytesread) - if bytesread != bytesWritten: + if bytesread != byteswritten: dealloc(buf) close(s) close(d) - OSError(OSLastError()) + osError(osLastError()) if bytesread != bufSize: break dealloc(buf) close(s) @@ -967,21 +965,24 @@ proc copyFile*(source, dest: string) {.rtl, extern: "nos$1", proc moveFile*(source, dest: string) {.rtl, extern: "nos$1", tags: [FReadIO, FWriteIO].} = ## Moves a file from `source` to `dest`. If this fails, `EOS` is raised. - if crename(source, dest) != 0'i32: + if c_rename(source, dest) != 0'i32: raise newException(EOS, $strerror(errno)) when not defined(ENOENT) and not defined(Windows): - var ENOENT {.importc, header: "<errno.h>".}: cint + when NoFakeVars: + const ENOENT = cint(2) # 2 on most systems including Solaris + else: + var ENOENT {.importc, header: "<errno.h>".}: cint when defined(Windows): when useWinUnicode: - template DeleteFile(file: expr): expr {.immediate.} = DeleteFileW(file) - template SetFileAttributes(file, attrs: expr): expr {.immediate.} = - SetFileAttributesW(file, attrs) + template deleteFile(file: expr): expr {.immediate.} = deleteFileW(file) + template setFileAttributes(file, attrs: expr): expr {.immediate.} = + setFileAttributesW(file, attrs) else: - template DeleteFile(file: expr): expr {.immediate.} = DeleteFileA(file) - template SetFileAttributes(file, attrs: expr): expr {.immediate.} = - SetFileAttributesA(file, attrs) + template deleteFile(file: expr): expr {.immediate.} = deleteFileA(file) + template setFileAttributes(file, attrs: expr): expr {.immediate.} = + setFileAttributesA(file, attrs) proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Removes the `file`. If this fails, `EOS` is raised. This does not fail @@ -992,14 +993,14 @@ proc removeFile*(file: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = let f = newWideCString(file) else: let f = file - if DeleteFile(f) == 0: - if GetLastError() == ERROR_ACCESS_DENIED: - if SetFileAttributes(f, FILE_ATTRIBUTE_NORMAL) == 0: - OSError(OSLastError()) - if DeleteFile(f) == 0: - OSError(OSLastError()) + if deleteFile(f) == 0: + if getLastError() == ERROR_ACCESS_DENIED: + if setFileAttributes(f, FILE_ATTRIBUTE_NORMAL) == 0: + osError(osLastError()) + if deleteFile(f) == 0: + osError(osLastError()) else: - if cremove(file) != 0'i32 and errno != ENOENT: + if c_remove(file) != 0'i32 and errno != ENOENT: raise newException(EOS, $strerror(errno)) proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", @@ -1012,7 +1013,7 @@ proc execShellCmd*(command: string): int {.rtl, extern: "nos$1", ## the process has finished. To execute a program without having a ## shell involved, use the `execProcess` proc of the `osproc` ## module. - result = csystem(command) + result = c_system(command) # Environment handling cannot be put into RTL, because the ``envPairs`` # iterator depends on ``environment``. @@ -1025,10 +1026,10 @@ when defined(windows): # because we support Windows GUI applications, things get really # messy here... when useWinUnicode: - proc strEnd(cstr: wideCString, c = 0'i32): wideCString {. + proc strEnd(cstr: WideCString, c = 0'i32): WideCString {. importc: "wcschr", header: "<string.h>".} else: - proc strEnd(cstr: CString, c = 0'i32): CString {. + proc strEnd(cstr: cstring, c = 0'i32): cstring {. importc: "strchr", header: "<string.h>".} proc getEnvVarsC() = @@ -1039,18 +1040,18 @@ when defined(windows): env = getEnvironmentStringsW() e = env if e == nil: return # an error occured - while True: + while true: var eend = strEnd(e) add(environment, $e) - e = cast[wideCString](cast[TAddress](eend)+2) + e = cast[WideCString](cast[TAddress](eend)+2) if eend[1].int == 0: break - discard FreeEnvironmentStringsW(env) + discard freeEnvironmentStringsW(env) else: var env = getEnvironmentStringsA() e = env if e == nil: return # an error occured - while True: + while true: var eend = strEnd(e) add(environment, $e) e = cast[CString](cast[TAddress](eend)+1) @@ -1083,7 +1084,7 @@ else: when useNSGetEnviron: var gEnv = NSGetEnviron()[] var i = 0 - while True: + while true: if gEnv[i] == nil: break add environment, $gEnv[i] inc(i) @@ -1106,14 +1107,14 @@ proc getEnv*(key: string): TaintedString {.tags: [FReadEnv].} = if i >= 0: return TaintedString(substr(environment[i], find(environment[i], '=')+1)) else: - var env = cgetenv(key) + var env = c_getenv(key) if env == nil: return TaintedString("") result = TaintedString($env) proc existsEnv*(key: string): bool {.tags: [FReadEnv].} = ## Checks whether the environment variable named `key` exists. ## Returns true if it exists, false otherwise. - if cgetenv(key) != nil: return true + if c_getenv(key) != nil: return true else: return findEnvVar(key) >= 0 proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = @@ -1131,15 +1132,15 @@ proc putEnv*(key, val: string) {.tags: [FWriteEnv].} = add environment, (key & '=' & val) indx = high(environment) when defined(unix): - if cputenv(environment[indx]) != 0'i32: - OSError(OSLastError()) + if c_putenv(environment[indx]) != 0'i32: + osError(osLastError()) else: when useWinUnicode: var k = newWideCString(key) var v = newWideCString(val) - if SetEnvironmentVariableW(k, v) == 0'i32: OSError(OSLastError()) + if setEnvironmentVariableW(k, v) == 0'i32: osError(osLastError()) else: - if SetEnvironmentVariableA(key, val) == 0'i32: OSError(OSLastError()) + if setEnvironmentVariableA(key, val) == 0'i32: osError(osLastError()) iterator envPairs*(): tuple[key, value: TaintedString] {.tags: [FReadEnv].} = ## Iterate over all `environments variables`:idx:. In the first component @@ -1159,15 +1160,15 @@ iterator walkFiles*(pattern: string): string {.tags: [FReadDir].} = ## notation is supported. when defined(windows): var - f: TWin32FindData + f: TWIN32_FIND_DATA res: int - res = findfirstFile(pattern, f) + res = findFirstFile(pattern, f) if res != -1: while true: if not skipFindData(f): yield splitFile(pattern).dir / extractFilename(getFilename(f)) - if findnextFile(res, f) == 0'i32: break - findclose(res) + if findNextFile(res, f) == 0'i32: break + findClose(res) else: # here we use glob var f: TGlob @@ -1212,8 +1213,8 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. ## dirA/fileA1.txt ## dirA/fileA2.txt when defined(windows): - var f: TWIN32_Find_Data - var h = findfirstFile(dir / "*", f) + var f: TWIN32_FIND_DATA + var h = findFirstFile(dir / "*", f) if h != -1: while true: var k = pcFile @@ -1221,13 +1222,13 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. if (f.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY) != 0'i32: k = pcDir yield (k, dir / extractFilename(getFilename(f))) - if findnextFile(h, f) == 0'i32: break - findclose(h) + if findNextFile(h, f) == 0'i32: break + findClose(h) else: - var d = openDir(dir) + var d = opendir(dir) if d != nil: while true: - var x = readDir(d) + var x = readdir(d) if x == nil: break var y = $x.d_name if y != "." and y != "..": @@ -1238,7 +1239,7 @@ iterator walkDir*(dir: string): tuple[kind: TPathComponent, path: string] {. if S_ISDIR(s.st_mode): k = pcDir if S_ISLNK(s.st_mode): k = succ(k) yield (k, y) - discard closeDir(d) + discard closedir(d) iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. tags: [FReadDir].} = @@ -1266,15 +1267,15 @@ iterator walkDirRec*(dir: string, filter={pcFile, pcDir}): string {. proc rawRemoveDir(dir: string) = when defined(windows): when useWinUnicode: - wrapUnary(res, RemoveDirectoryW, dir) + wrapUnary(res, removeDirectoryW, dir) else: - var res = RemoveDirectoryA(dir) - let lastError = OSLastError() + var res = removeDirectoryA(dir) + let lastError = osLastError() if res == 0'i32 and lastError.int32 != 3'i32 and lastError.int32 != 18'i32 and lastError.int32 != 2'i32: - OSError(lastError) + osError(lastError) else: - if rmdir(dir) != 0'i32 and errno != ENOENT: OSError(OSLastError()) + if rmdir(dir) != 0'i32 and errno != ENOENT: osError(osLastError()) proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ FWriteDir, FReadDir].} = @@ -1292,17 +1293,17 @@ proc removeDir*(dir: string) {.rtl, extern: "nos$1", tags: [ proc rawCreateDir(dir: string) = when defined(solaris): if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST and errno != ENOSYS: - OSError(OSLastError()) + osError(osLastError()) elif defined(unix): if mkdir(dir, 0o711) != 0'i32 and errno != EEXIST: - OSError(OSLastError()) + osError(osLastError()) else: when useWinUnicode: - wrapUnary(res, CreateDirectoryW, dir) + wrapUnary(res, createDirectoryW, dir) else: - var res = CreateDirectoryA(dir) - if res == 0'i32 and GetLastError() != 183'i32: - OSError(OSLastError()) + var res = createDirectoryA(dir) + if res == 0'i32 and getLastError() != 183'i32: + osError(osLastError()) proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = ## Creates the `directory`:idx: `dir`. @@ -1315,7 +1316,7 @@ proc createDir*(dir: string) {.rtl, extern: "nos$1", tags: [FWriteDir].} = when defined(doslike): omitNext = isAbsolute(dir) for i in 1.. dir.len-1: - if dir[i] in {dirsep, altsep}: + if dir[i] in {DirSep, AltSep}: if omitNext: omitNext = false else: @@ -1333,7 +1334,7 @@ proc copyDir*(source, dest: string) {.rtl, extern: "nos$1", copyFile(path, dest / noSource) of pcDir: copyDir(path, dest / noSource) - else: nil + else: discard proc parseCmdLine*(c: string): seq[string] {. noSideEffect, rtl, extern: "nos$1".} = @@ -1531,7 +1532,7 @@ when defined(linux) or defined(solaris) or defined(bsd) or defined(aix): if len > 256: result = newString(len+1) len = readlink(procPath, result, len) - setlen(result, len) + setLen(result, len) when defined(macosx): type @@ -1560,7 +1561,7 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} = # /proc/<pid>/file when defined(windows): when useWinUnicode: - var buf = cast[wideCString](alloc(256*2)) + var buf = cast[WideCString](alloc(256*2)) var len = getModuleFileNameW(0, buf, 256) result = buf$len else: @@ -1585,14 +1586,14 @@ proc getAppFilename*(): string {.rtl, extern: "nos$1", tags: [FReadIO].} = # little heuristic that may work on other POSIX-like systems: result = string(getEnv("_")) if len(result) == 0: - result = string(ParamStr(0)) + result = string(paramStr(0)) # POSIX guaranties that this contains the executable # as it has been executed by the calling process if len(result) > 0 and result[0] != DirSep: # not an absolute path? # iterate over any path in the $PATH environment variable for p in split(string(getEnv("PATH")), {PathSep}): - var x = JoinPath(p, result) - if ExistsFile(x): return x + var x = joinPath(p, result) + if existsFile(x): return x proc getApplicationFilename*(): string {.rtl, extern: "nos$1", deprecated.} = ## Returns the filename of the application's executable. @@ -1621,33 +1622,33 @@ proc sleep*(milsecs: int) {.rtl, extern: "nos$1", tags: [FTime].} = a.tv_nsec = (milsecs mod 1000) * 1000 * 1000 discard posix.nanosleep(a, b) -proc getFileSize*(file: string): biggestInt {.rtl, extern: "nos$1", +proc getFileSize*(file: string): BiggestInt {.rtl, extern: "nos$1", tags: [FReadIO].} = ## returns the file size of `file`. Can raise ``EOS``. when defined(windows): - var a: TWin32FindData - var resA = findfirstFile(file, a) - if resA == -1: OSError(OSLastError()) + var a: TWIN32_FIND_DATA + var resA = findFirstFile(file, a) + if resA == -1: osError(osLastError()) result = rdFileSize(a) - findclose(resA) + findClose(resA) else: var f: TFile if open(f, file): result = getFileSize(f) close(f) - else: OSError(OSLastError()) + else: osError(osLastError()) proc findExe*(exe: string): string {.tags: [FReadDir, FReadEnv].} = ## Searches for `exe` in the current working directory and then ## in directories listed in the ``PATH`` environment variable. ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe` ## is added an ``.exe`` file extension if it has no extension. - result = addFileExt(exe, os.exeExt) - if ExistsFile(result): return + result = addFileExt(exe, os.ExeExt) + if existsFile(result): return var path = string(os.getEnv("PATH")) - for candidate in split(path, pathSep): + for candidate in split(path, PathSep): var x = candidate / result - if ExistsFile(x): return x + if existsFile(x): return x result = "" proc expandTilde*(path: string): string = diff --git a/lib/pure/osproc.nim b/lib/pure/osproc.nim index 61b940ce8..676707abb 100644 --- a/lib/pure/osproc.nim +++ b/lib/pure/osproc.nim @@ -23,7 +23,7 @@ else: type TProcess = object of TObject when defined(windows): - FProcessHandle: Thandle + fProcessHandle: THandle inHandle, outHandle, errHandle: TFileHandle id: THandle else: @@ -108,7 +108,7 @@ proc execCmd*(command: string): int {.rtl, extern: "nosp$1", tags: [FExecIO].} proc startProcess*(command: string, workingDir: string = "", - args: openarray[string] = [], + args: openArray[string] = [], env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut}): PProcess {.rtl, extern: "nosp$1", tags: [FExecIO, FReadEnv].} @@ -219,7 +219,7 @@ proc countProcessors*(): int {.rtl, extern: "nosp$1".} = ## returns the numer of the processors/cores the machine has. ## Returns 0 if it cannot be detected. when defined(windows): - var x = getenv("NUMBER_OF_PROCESSORS") + var x = getEnv("NUMBER_OF_PROCESSORS") if x.len > 0: result = parseInt(x.string) elif defined(macosx) or defined(bsd): var @@ -329,18 +329,18 @@ when defined(Windows) and not defined(useNimRtl): handle: THandle atTheEnd: bool - proc hsClose(s: PStream) = nil # nothing to do here + proc hsClose(s: PStream) = discard # nothing to do here proc hsAtEnd(s: PStream): bool = return PFileHandleStream(s).atTheEnd proc hsReadData(s: PStream, buffer: pointer, bufLen: int): int = var s = PFileHandleStream(s) if s.atTheEnd: return 0 var br: int32 - var a = winlean.ReadFile(s.handle, buffer, bufLen.cint, br, nil) + var a = winlean.readFile(s.handle, buffer, bufLen.cint, br, nil) # TRUE and zero bytes returned (EOF). # TRUE and n (>0) bytes returned (good data). # FALSE and bytes returned undefined (system error). - if a == 0 and br != 0: OSError(OSLastError()) + if a == 0 and br != 0: osError(osLastError()) s.atTheEnd = br < bufLen result = br @@ -348,7 +348,7 @@ when defined(Windows) and not defined(useNimRtl): var s = PFileHandleStream(s) var bytesWritten: int32 var a = winlean.writeFile(s.handle, buffer, bufLen.cint, bytesWritten, nil) - if a == 0: OSError(OSLastError()) + if a == 0: osError(osLastError()) proc newFileHandleStream(handle: THandle): PFileHandleStream = new(result) @@ -358,7 +358,7 @@ when defined(Windows) and not defined(useNimRtl): result.readDataImpl = hsReadData result.writeDataImpl = hsWriteData - proc buildCommandLine(a: string, args: openarray[string]): cstring = + proc buildCommandLine(a: string, args: openArray[string]): cstring = var res = quoteShell(a) for i in 0..high(args): res.add(' ') @@ -383,45 +383,45 @@ when defined(Windows) and not defined(useNimRtl): # O_WRONLY {.importc: "_O_WRONLY", header: "<fcntl.h>".}: int # O_RDONLY {.importc: "_O_RDONLY", header: "<fcntl.h>".}: int - proc CreatePipeHandles(Rdhandle, WrHandle: var THandle) = - var piInheritablePipe: TSecurityAttributes - piInheritablePipe.nlength = SizeOF(TSecurityAttributes).cint + proc createPipeHandles(rdHandle, wrHandle: var THandle) = + var piInheritablePipe: TSECURITY_ATTRIBUTES + piInheritablePipe.nLength = sizeof(TSECURITY_ATTRIBUTES).cint piInheritablePipe.lpSecurityDescriptor = nil - piInheritablePipe.Binherithandle = 1 - if CreatePipe(Rdhandle, Wrhandle, piInheritablePipe, 1024) == 0'i32: - OSError(OSLastError()) + piInheritablePipe.bInheritHandle = 1 + if createPipe(rdHandle, wrHandle, piInheritablePipe, 1024) == 0'i32: + osError(osLastError()) proc fileClose(h: THandle) {.inline.} = - if h > 4: discard CloseHandle(h) + if h > 4: discard closeHandle(h) proc startProcess(command: string, workingDir: string = "", - args: openarray[string] = [], + args: openArray[string] = [], env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut}): PProcess = var - SI: TStartupInfo - ProcInfo: TProcessInformation + si: TSTARTUPINFO + procInfo: TPROCESS_INFORMATION success: int hi, ho, he: THandle new(result) - SI.cb = SizeOf(SI).cint + si.cb = sizeof(si).cint if poParentStreams notin options: - SI.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or - CreatePipeHandles(SI.hStdInput, HI) - CreatePipeHandles(HO, Si.hStdOutput) + si.dwFlags = STARTF_USESTDHANDLES # STARTF_USESHOWWINDOW or + createPipeHandles(si.hStdInput, hi) + createPipeHandles(ho, si.hStdOutput) if poStdErrToStdOut in options: - SI.hStdError = SI.hStdOutput - HE = HO + si.hStdError = si.hStdOutput + he = ho else: - CreatePipeHandles(HE, Si.hStdError) + createPipeHandles(he, si.hStdError) result.inHandle = TFileHandle(hi) result.outHandle = TFileHandle(ho) result.errHandle = TFileHandle(he) else: - SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) - SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) - SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) + si.hStdError = getStdHandle(STD_ERROR_HANDLE) + si.hStdInput = getStdHandle(STD_INPUT_HANDLE) + si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE) result.inHandle = TFileHandle(si.hStdInput) result.outHandle = TFileHandle(si.hStdOutput) result.errHandle = TFileHandle(si.hStdError) @@ -440,64 +440,64 @@ when defined(Windows) and not defined(useNimRtl): var tmp = newWideCString(cmdl) var ee = newWideCString(e) var wwd = newWideCString(wd) - success = winlean.CreateProcessW(nil, + success = winlean.createProcessW(nil, tmp, nil, nil, 1, NORMAL_PRIORITY_CLASS or CREATE_UNICODE_ENVIRONMENT, - ee, wwd, SI, ProcInfo) + ee, wwd, si, procInfo) else: - success = winlean.CreateProcessA(nil, + success = winlean.createProcessA(nil, cmdl, nil, nil, 1, NORMAL_PRIORITY_CLASS, e, wd, SI, ProcInfo) - let lastError = OSLastError() + let lastError = osLastError() if poParentStreams notin options: - FileClose(si.hStdInput) - FileClose(si.hStdOutput) + fileClose(si.hStdInput) + fileClose(si.hStdOutput) if poStdErrToStdOut notin options: - FileClose(si.hStdError) + fileClose(si.hStdError) if e != nil: dealloc(e) dealloc(cmdl) - if success == 0: OSError(lastError) + if success == 0: osError(lastError) # Close the handle now so anyone waiting is woken: discard closeHandle(procInfo.hThread) - result.FProcessHandle = procInfo.hProcess - result.id = procInfo.dwProcessID + result.fProcessHandle = procInfo.hProcess + result.id = procInfo.dwProcessId proc close(p: PProcess) = when false: # somehow this does not work on Windows: - discard CloseHandle(p.inHandle) - discard CloseHandle(p.outHandle) - discard CloseHandle(p.errHandle) - discard CloseHandle(p.FProcessHandle) + discard closeHandle(p.inHandle) + discard closeHandle(p.outHandle) + discard closeHandle(p.errHandle) + discard closeHandle(p.FProcessHandle) proc suspend(p: PProcess) = - discard SuspendThread(p.FProcessHandle) + discard suspendThread(p.fProcessHandle) proc resume(p: PProcess) = - discard ResumeThread(p.FProcessHandle) + discard resumeThread(p.fProcessHandle) proc running(p: PProcess): bool = - var x = waitForSingleObject(p.FProcessHandle, 50) + var x = waitForSingleObject(p.fProcessHandle, 50) return x == WAIT_TIMEOUT proc terminate(p: PProcess) = if running(p): - discard TerminateProcess(p.FProcessHandle, 0) + discard terminateProcess(p.fProcessHandle, 0) proc waitForExit(p: PProcess, timeout: int = -1): int = - discard WaitForSingleObject(p.FProcessHandle, timeout.int32) + discard waitForSingleObject(p.fProcessHandle, timeout.int32) var res: int32 - discard GetExitCodeProcess(p.FProcessHandle, res) + discard getExitCodeProcess(p.fProcessHandle, res) result = res - discard CloseHandle(p.FProcessHandle) + discard closeHandle(p.fProcessHandle) proc peekExitCode(p: PProcess): int = - var b = waitForSingleObject(p.FProcessHandle, 50) == WAIT_TIMEOUT + var b = waitForSingleObject(p.fProcessHandle, 50) == WAIT_TIMEOUT if b: result = -1 else: var res: int32 - discard GetExitCodeProcess(p.FProcessHandle, res) + discard getExitCodeProcess(p.fProcessHandle, res) return res proc inputStream(p: PProcess): PStream = @@ -511,38 +511,38 @@ when defined(Windows) and not defined(useNimRtl): proc execCmd(command: string): int = var - SI: TStartupInfo - ProcInfo: TProcessInformation + si: TSTARTUPINFO + procInfo: TPROCESS_INFORMATION process: THandle L: int32 - SI.cb = SizeOf(SI).cint - SI.hStdError = GetStdHandle(STD_ERROR_HANDLE) - SI.hStdInput = GetStdHandle(STD_INPUT_HANDLE) - SI.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE) + si.cb = sizeof(si).cint + si.hStdError = getStdHandle(STD_ERROR_HANDLE) + si.hStdInput = getStdHandle(STD_INPUT_HANDLE) + si.hStdOutput = getStdHandle(STD_OUTPUT_HANDLE) when useWinUnicode: var c = newWideCString(command) - var res = winlean.CreateProcessW(nil, c, nil, nil, 0, - NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo) + var res = winlean.createProcessW(nil, c, nil, nil, 0, + NORMAL_PRIORITY_CLASS, nil, nil, si, procInfo) else: - var res = winlean.CreateProcessA(nil, command, nil, nil, 0, + var res = winlean.createProcessA(nil, command, nil, nil, 0, NORMAL_PRIORITY_CLASS, nil, nil, SI, ProcInfo) if res == 0: - OSError(OSLastError()) + osError(osLastError()) else: - Process = ProcInfo.hProcess - discard CloseHandle(ProcInfo.hThread) - if WaitForSingleObject(Process, INFINITE) != -1: - discard GetExitCodeProcess(Process, L) + process = procInfo.hProcess + discard closeHandle(procInfo.hThread) + if waitForSingleObject(process, INFINITE) != -1: + discard getExitCodeProcess(process, L) result = int(L) else: result = -1 - discard CloseHandle(Process) + discard closeHandle(process) proc select(readfds: var seq[PProcess], timeout = 500): int = assert readfds.len <= MAXIMUM_WAIT_OBJECTS var rfds: TWOHandleArray for i in 0..readfds.len()-1: - rfds[i] = readfds[i].FProcessHandle + rfds[i] = readfds[i].fProcessHandle var ret = waitForMultipleObjects(readfds.len.int32, addr(rfds), 0'i32, timeout.int32) @@ -550,7 +550,7 @@ when defined(Windows) and not defined(useNimRtl): of WAIT_TIMEOUT: return 0 of WAIT_FAILED: - OSError(OSLastError()) + osError(osLastError()) else: var i = ret - WAIT_OBJECT_0 readfds.del(i) @@ -561,13 +561,13 @@ elif not defined(useNimRtl): readIdx = 0 writeIdx = 1 - proc addCmdArgs(command: string, args: openarray[string]): string = + proc addCmdArgs(command: string, args: openArray[string]): string = result = quoteShell(command) for i in 0 .. high(args): add(result, " ") add(result, quoteShell(args[i])) - proc toCStringArray(b, a: openarray[string]): cstringArray = + proc toCStringArray(b, a: openArray[string]): cstringArray = result = cast[cstringArray](alloc0((a.len + b.len + 1) * sizeof(cstring))) for i in 0..high(b): result[i] = cast[cstring](alloc(b[i].len+1)) @@ -576,7 +576,7 @@ elif not defined(useNimRtl): result[i+b.len] = cast[cstring](alloc(a[i].len+1)) copyMem(result[i+b.len], cstring(a[i]), a[i].len+1) - proc ToCStringArray(t: PStringTable): cstringArray = + proc toCStringArray(t: PStringTable): cstringArray = result = cast[cstringArray](alloc0((t.len + 1) * sizeof(cstring))) var i = 0 for key, val in pairs(t): @@ -585,7 +585,7 @@ elif not defined(useNimRtl): copyMem(result[i], addr(x[0]), x.len+1) inc(i) - proc EnvToCStringArray(): cstringArray = + proc envToCStringArray(): cstringArray = var counter = 0 for key, val in envPairs(): inc counter result = cast[cstringArray](alloc0((counter + 1) * sizeof(cstring))) @@ -598,17 +598,17 @@ elif not defined(useNimRtl): proc startProcess(command: string, workingDir: string = "", - args: openarray[string] = [], + args: openArray[string] = [], env: PStringTable = nil, options: set[TProcessOption] = {poStdErrToStdOut}): PProcess = var - p_stdin, p_stdout, p_stderr: array [0..1, cint] + pStdin, pStdout, pStderr: array [0..1, cint] new(result) result.exitCode = -3 # for ``waitForExit`` if poParentStreams notin options: - if pipe(p_stdin) != 0'i32 or pipe(p_stdout) != 0'i32 or - pipe(p_stderr) != 0'i32: - OSError(OSLastError()) + if pipe(pStdin) != 0'i32 or pipe(pStdout) != 0'i32 or + pipe(pStderr) != 0'i32: + osError(osLastError()) var pid: TPid when defined(posix_spawn) and not defined(useFork): @@ -616,7 +616,7 @@ elif not defined(useNimRtl): var fops: Tposix_spawn_file_actions template chck(e: expr) = - if e != 0'i32: OSError(OSLastError()) + if e != 0'i32: osError(osLastError()) chck posix_spawn_file_actions_init(fops) chck posix_spawnattr_init(attr) @@ -631,17 +631,17 @@ elif not defined(useNimRtl): POSIX_SPAWN_SETPGROUP) if poParentStreams notin options: - chck posix_spawn_file_actions_addclose(fops, p_stdin[writeIdx]) - chck posix_spawn_file_actions_adddup2(fops, p_stdin[readIdx], readIdx) - chck posix_spawn_file_actions_addclose(fops, p_stdout[readIdx]) - chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], writeIdx) - chck posix_spawn_file_actions_addclose(fops, p_stderr[readIdx]) + chck posix_spawn_file_actions_addclose(fops, pStdin[writeIdx]) + chck posix_spawn_file_actions_adddup2(fops, pStdin[readIdx], readIdx) + chck posix_spawn_file_actions_addclose(fops, pStdout[readIdx]) + chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], writeIdx) + chck posix_spawn_file_actions_addclose(fops, pStderr[readIdx]) if poStdErrToStdOut in options: - chck posix_spawn_file_actions_adddup2(fops, p_stdout[writeIdx], 2) + chck posix_spawn_file_actions_adddup2(fops, pStdout[writeIdx], 2) else: - chck posix_spawn_file_actions_adddup2(fops, p_stderr[writeIdx], 2) + chck posix_spawn_file_actions_adddup2(fops, pStderr[writeIdx], 2) - var e = if env == nil: EnvToCStringArray() else: ToCStringArray(env) + var e = if env == nil: envToCStringArray() else: toCStringArray(env) var a: cstringArray var res: cint if workingDir.len > 0: os.setCurrentDir(workingDir) @@ -660,21 +660,21 @@ elif not defined(useNimRtl): else: - Pid = fork() - if Pid < 0: OSError(OSLastError()) + pid = fork() + if pid < 0: osError(osLastError()) if pid == 0: ## child process: if poParentStreams notin options: discard close(p_stdin[writeIdx]) - if dup2(p_stdin[readIdx], readIdx) < 0: OSError(OSLastError()) + if dup2(p_stdin[readIdx], readIdx) < 0: osError(osLastError()) discard close(p_stdout[readIdx]) - if dup2(p_stdout[writeIdx], writeIdx) < 0: OSError(OSLastError()) + if dup2(p_stdout[writeIdx], writeIdx) < 0: osError(osLastError()) discard close(p_stderr[readIdx]) if poStdErrToStdOut in options: - if dup2(p_stdout[writeIdx], 2) < 0: OSError(OSLastError()) + if dup2(p_stdout[writeIdx], 2) < 0: osError(osLastError()) else: - if dup2(p_stderr[writeIdx], 2) < 0: OSError(OSLastError()) + if dup2(p_stderr[writeIdx], 2) < 0: osError(osLastError()) # Create a new process group if setpgid(0, 0) == -1: quit("setpgid call failed: " & $strerror(errno)) @@ -685,14 +685,14 @@ elif not defined(useNimRtl): if env == nil: discard execv(command, a) else: - discard execve(command, a, ToCStringArray(env)) + discard execve(command, a, toCStringArray(env)) else: var x = addCmdArgs(command, args) var a = toCStringArray(["sh", "-c"], [x]) if env == nil: discard execv("/bin/sh", a) else: - discard execve("/bin/sh", a, ToCStringArray(env)) + discard execve("/bin/sh", a, toCStringArray(env)) # too risky to raise an exception here: quit("execve call failed: " & $strerror(errno)) # Parent process. Copy process information. @@ -709,16 +709,16 @@ elif not defined(useNimRtl): else: result.errHandle = 2 else: - result.inHandle = p_stdin[writeIdx] - result.outHandle = p_stdout[readIdx] + result.inHandle = pStdin[writeIdx] + result.outHandle = pStdout[readIdx] if poStdErrToStdOut in options: result.errHandle = result.outHandle - discard close(p_stderr[readIdx]) + discard close(pStderr[readIdx]) else: - result.errHandle = p_stderr[readIdx] - discard close(p_stderr[writeIdx]) - discard close(p_stdin[readIdx]) - discard close(p_stdout[writeIdx]) + result.errHandle = pStderr[readIdx] + discard close(pStderr[writeIdx]) + discard close(pStdin[readIdx]) + discard close(pStdout[writeIdx]) proc close(p: PProcess) = if p.inStream != nil: close(p.inStream) @@ -729,21 +729,21 @@ elif not defined(useNimRtl): discard close(p.errHandle) proc suspend(p: PProcess) = - if kill(-p.id, SIGSTOP) != 0'i32: OSError(OSLastError()) + if kill(-p.id, SIGSTOP) != 0'i32: osError(osLastError()) proc resume(p: PProcess) = - if kill(-p.id, SIGCONT) != 0'i32: OSError(OSLastError()) + if kill(-p.id, SIGCONT) != 0'i32: osError(osLastError()) proc running(p: PProcess): bool = - var ret = waitPid(p.id, p.exitCode, WNOHANG) + var ret = waitpid(p.id, p.exitCode, WNOHANG) if ret == 0: return true # Can't establish status. Assume running. result = ret == int(p.id) proc terminate(p: PProcess) = if kill(-p.id, SIGTERM) == 0'i32: if p.running(): - if kill(-p.id, SIGKILL) != 0'i32: OSError(OSLastError()) - else: OSError(OSLastError()) + if kill(-p.id, SIGKILL) != 0'i32: osError(osLastError()) + else: osError(osLastError()) proc waitForExit(p: PProcess, timeout: int = -1): int = #if waitPid(p.id, p.exitCode, 0) == int(p.id): @@ -751,14 +751,14 @@ elif not defined(useNimRtl): # ``running`` probably set ``p.exitCode`` for us. Since ``p.exitCode`` is # initialized with -3, wrong success exit codes are prevented. if p.exitCode != -3: return p.exitCode - if waitPid(p.id, p.exitCode, 0) < 0: + if waitpid(p.id, p.exitCode, 0) < 0: p.exitCode = -3 - OSError(OSLastError()) + osError(osLastError()) result = int(p.exitCode) shr 8 proc peekExitCode(p: PProcess): int = if p.exitCode != -3: return p.exitCode - var ret = waitPid(p.id, p.exitCode, WNOHANG) + var ret = waitpid(p.id, p.exitCode, WNOHANG) var b = ret == int(p.id) if b: result = -1 if p.exitCode == -3: result = -1 @@ -767,7 +767,7 @@ elif not defined(useNimRtl): proc createStream(stream: var PStream, handle: var TFileHandle, fileMode: TFileMode) = var f: TFile - if not open(f, handle, fileMode): OSError(OSLastError()) + if not open(f, handle, fileMode): osError(osLastError()) stream = newFileStream(f) proc inputStream(p: PProcess): PStream = @@ -800,7 +800,7 @@ elif not defined(useNimRtl): var i = 0 var L = s.len while i < L: - if FD_ISSET(cint(s[i].outHandle), fd) != 0'i32: + if FD_ISSET(cint(s[i].outHandle), fd) == 0'i32: s[i] = s[L-1] dec(L) else: @@ -808,7 +808,7 @@ elif not defined(useNimRtl): setLen(s, L) proc select(readfds: var seq[PProcess], timeout = 500): int = - var tv: TTimeVal + var tv: Ttimeval tv.tv_sec = 0 tv.tv_usec = timeout * 1000 diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index e8014cece..f3249b107 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -82,7 +82,7 @@ proc open*(c: var TCfgParser, input: PStream, filename: string, c.filename = filename c.tok.kind = tkInvalid c.tok.literal = "" - inc(c.linenumber, lineOffset) + inc(c.lineNumber, lineOffset) rawGetTok(c, c.tok) proc close*(c: var TCfgParser) {.rtl, extern: "npc$1".} = @@ -91,11 +91,11 @@ proc close*(c: var TCfgParser) {.rtl, extern: "npc$1".} = proc getColumn*(c: TCfgParser): int {.rtl, extern: "npc$1".} = ## get the current column the parser has arrived at. - result = getColNumber(c, c.bufPos) + result = getColNumber(c, c.bufpos) proc getLine*(c: TCfgParser): int {.rtl, extern: "npc$1".} = ## get the current line the parser has arrived at. - result = c.linenumber + result = c.lineNumber proc getFilename*(c: TCfgParser): string {.rtl, extern: "npc$1".} = ## get the filename of the file that the parser processes. @@ -113,7 +113,7 @@ proc handleHexChar(c: var TCfgParser, xi: var int) = xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) inc(c.bufpos) else: - nil + discard proc handleDecChars(c: var TCfgParser, xi: var int) = while c.buf[c.bufpos] in {'0'..'9'}: @@ -125,74 +125,74 @@ proc getEscapedChar(c: var TCfgParser, tok: var TToken) = case c.buf[c.bufpos] of 'n', 'N': add(tok.literal, "\n") - Inc(c.bufpos) + inc(c.bufpos) of 'r', 'R', 'c', 'C': add(tok.literal, '\c') - Inc(c.bufpos) + inc(c.bufpos) of 'l', 'L': add(tok.literal, '\L') - Inc(c.bufpos) + inc(c.bufpos) of 'f', 'F': add(tok.literal, '\f') inc(c.bufpos) of 'e', 'E': add(tok.literal, '\e') - Inc(c.bufpos) + inc(c.bufpos) of 'a', 'A': add(tok.literal, '\a') - Inc(c.bufpos) + inc(c.bufpos) of 'b', 'B': add(tok.literal, '\b') - Inc(c.bufpos) + inc(c.bufpos) of 'v', 'V': add(tok.literal, '\v') - Inc(c.bufpos) + inc(c.bufpos) of 't', 'T': add(tok.literal, '\t') - Inc(c.bufpos) + inc(c.bufpos) of '\'', '"': add(tok.literal, c.buf[c.bufpos]) - Inc(c.bufpos) + inc(c.bufpos) of '\\': add(tok.literal, '\\') - Inc(c.bufpos) + inc(c.bufpos) of 'x', 'X': inc(c.bufpos) var xi = 0 handleHexChar(c, xi) handleHexChar(c, xi) - add(tok.literal, Chr(xi)) + add(tok.literal, chr(xi)) of '0'..'9': var xi = 0 handleDecChars(c, xi) - if (xi <= 255): add(tok.literal, Chr(xi)) + if (xi <= 255): add(tok.literal, chr(xi)) else: tok.kind = tkInvalid else: tok.kind = tkInvalid -proc HandleCRLF(c: var TCfgParser, pos: int): int = +proc handleCRLF(c: var TCfgParser, pos: int): int = case c.buf[pos] - of '\c': result = lexbase.HandleCR(c, pos) - of '\L': result = lexbase.HandleLF(c, pos) + of '\c': result = lexbase.handleCR(c, pos) + of '\L': result = lexbase.handleLF(c, pos) else: result = pos proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = - var pos = c.bufPos + 1 # skip " + var pos = c.bufpos + 1 # skip " var buf = c.buf # put `buf` in a register tok.kind = tkSymbol if (buf[pos] == '"') and (buf[pos + 1] == '"'): # long string literal: inc(pos, 2) # skip "" # skip leading newline: - pos = HandleCRLF(c, pos) + pos = handleCRLF(c, pos) buf = c.buf while true: case buf[pos] of '"': if (buf[pos + 1] == '"') and (buf[pos + 2] == '"'): break add(tok.literal, '"') - Inc(pos) + inc(pos) of '\c', '\L': - pos = HandleCRLF(c, pos) + pos = handleCRLF(c, pos) buf = c.buf add(tok.literal, "\n") of lexbase.EndOfFile: @@ -200,7 +200,7 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = break else: add(tok.literal, buf[pos]) - Inc(pos) + inc(pos) c.bufpos = pos + 3 # skip the three """ else: # ordinary string literal @@ -213,12 +213,12 @@ proc getString(c: var TCfgParser, tok: var TToken, rawMode: bool) = tok.kind = tkInvalid break if (ch == '\\') and not rawMode: - c.bufPos = pos + c.bufpos = pos getEscapedChar(c, tok) - pos = c.bufPos + pos = c.bufpos else: add(tok.literal, ch) - Inc(pos) + inc(pos) c.bufpos = pos proc getSymbol(c: var TCfgParser, tok: var TToken) = @@ -226,7 +226,7 @@ proc getSymbol(c: var TCfgParser, tok: var TToken) = var buf = c.buf while true: add(tok.literal, buf[pos]) - Inc(pos) + inc(pos) if not (buf[pos] in SymChars): break c.bufpos = pos tok.kind = tkSymbol @@ -237,11 +237,11 @@ proc skip(c: var TCfgParser) = while true: case buf[pos] of ' ', '\t': - Inc(pos) + inc(pos) of '#', ';': while not (buf[pos] in {'\c', '\L', lexbase.EndOfFile}): inc(pos) of '\c', '\L': - pos = HandleCRLF(c, pos) + pos = handleCRLF(c, pos) buf = c.buf else: break # EndOfFile also leaves the loop @@ -249,7 +249,7 @@ proc skip(c: var TCfgParser) = proc rawGetTok(c: var TCfgParser, tok: var TToken) = tok.kind = tkInvalid - setlen(tok.literal, 0) + setLen(tok.literal, 0) skip(c) case c.buf[c.bufpos] of '=': @@ -257,8 +257,8 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) = inc(c.bufpos) tok.literal = "=" of '-': - inc(c.bufPos) - if c.buf[c.bufPos] == '-': inc(c.bufPos) + inc(c.bufpos) + if c.buf[c.bufpos] == '-': inc(c.bufpos) tok.kind = tkDashDash tok.literal = "--" of ':': @@ -266,8 +266,8 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) = inc(c.bufpos) tok.literal = ":" of 'r', 'R': - if c.buf[c.bufPos + 1] == '\"': - Inc(c.bufPos) + if c.buf[c.bufpos + 1] == '\"': + inc(c.bufpos) getString(c, tok, true) else: getSymbol(c, tok) @@ -277,7 +277,7 @@ proc rawGetTok(c: var TCfgParser, tok: var TToken) = tok.literal = "]" of ']': tok.kind = tkBracketRi - Inc(c.bufpos) + inc(c.bufpos) tok.literal = "]" of '"': getString(c, tok, false) diff --git a/lib/pure/parseopt.nim b/lib/pure/parseopt.nim index fa704bbce..68ae537c7 100644 --- a/lib/pure/parseopt.nim +++ b/lib/pure/parseopt.nim @@ -11,8 +11,8 @@ ## It supports one convenience iterator over all command line options and some ## lower-level features. ## -## DEPRECATED. Use parseopt2 instead as this version has issues with spaces -## in arguments. +## **Deprecated since version 0.9.3:** Use the `parseopt2 <parseopt2.html>`_ +## module instead as this version has issues with spaces in arguments. {.deprecated.} {.push debugger: off.} @@ -37,7 +37,7 @@ type ## or the argument, ``value`` is not "" if ## the option was given a value -when defined(os.ParamCount): +when defined(os.paramCount): # we cannot provide this for NimRtl creation on Posix, because we can't # access the command line arguments then! @@ -50,7 +50,7 @@ when defined(os.ParamCount): result.cmd = cmdline else: result.cmd = "" - for i in countup(1, ParamCount()): + for i in countup(1, paramCount()): result.cmd = result.cmd & quoteIfContainsWhite(paramStr(i).string) & ' ' result.kind = cmdEnd result.key = TaintedString"" @@ -94,8 +94,8 @@ proc next*(p: var TOptParser) {. var i = p.pos while p.cmd[i] in {'\x09', ' '}: inc(i) p.pos = i - setlen(p.key.string, 0) - setlen(p.val.string, 0) + setLen(p.key.string, 0) + setLen(p.val.string, 0) if p.inShortState: handleShortOption(p) return @@ -105,7 +105,7 @@ proc next*(p: var TOptParser) {. of '-': inc(i) if p.cmd[i] == '-': - p.kind = cmdLongOption + p.kind = cmdLongoption inc(i) i = parseWord(p.cmd, i, p.key.string, {'\0', ' ', '\x09', ':', '='}) while p.cmd[i] in {'\x09', ' '}: inc(i) diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim index c11265bfd..484ba5184 100644 --- a/lib/pure/parseutils.nim +++ b/lib/pure/parseutils.nim @@ -51,7 +51,7 @@ proc parseHex*(s: string, number: var int, start = 0): int {. elif s[i] == '#': inc(i) while true: case s[i] - of '_': nil + of '_': discard of '0'..'9': number = number shl 4 or (ord(s[i]) - ord('0')) foundDigit = true @@ -74,7 +74,7 @@ proc parseOct*(s: string, number: var int, start = 0): int {. if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2) while true: case s[i] - of '_': nil + of '_': discard of '0'..'7': number = number shl 3 or (ord(s[i]) - ord('0')) foundDigit = true @@ -189,7 +189,7 @@ proc captureBetween*(s: string, first: char, second = '\0', start = 0): string = {.push overflowChecks: on.} # this must be compiled with overflow checking turned on: -proc rawParseInt(s: string, b: var biggestInt, start = 0): int = +proc rawParseInt(s: string, b: var BiggestInt, start = 0): int = var sign: BiggestInt = -1 i = start @@ -207,12 +207,12 @@ proc rawParseInt(s: string, b: var biggestInt, start = 0): int = result = i - start {.pop.} # overflowChecks -proc parseBiggestInt*(s: string, number: var biggestInt, start = 0): int {. +proc parseBiggestInt*(s: string, number: var BiggestInt, start = 0): int {. rtl, extern: "npuParseBiggestInt", noSideEffect.} = ## parses an integer starting at `start` and stores the value into `number`. ## Result is the number of processed chars or 0 if there is no integer. ## `EOverflow` is raised if an overflow occurs. - var res: biggestInt + var res: BiggestInt # use 'res' for exception safety (don't write to 'number' in case of an # overflow exception: result = rawParseInt(s, res, start) @@ -223,7 +223,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {. ## parses an integer starting at `start` and stores the value into `number`. ## Result is the number of processed chars or 0 if there is no integer. ## `EOverflow` is raised if an overflow occurs. - var res: biggestInt + var res: BiggestInt result = parseBiggestInt(s, res, start) if (sizeof(int) <= 4) and ((res < low(int)) or (res > high(int))): @@ -231,7 +231,7 @@ proc parseInt*(s: string, number: var int, start = 0): int {. else: number = int(res) -proc tenToThePowerOf(b: int): biggestFloat = +proc tenToThePowerOf(b: int): BiggestFloat = var b = b var a = 10.0 result = 1.0 @@ -242,7 +242,7 @@ proc tenToThePowerOf(b: int): biggestFloat = if b == 0: break a *= a -proc parseBiggestFloat*(s: string, number: var biggestFloat, start = 0): int {. +proc parseBiggestFloat*(s: string, number: var BiggestFloat, start = 0): int {. rtl, extern: "npuParseBiggestFloat", noSideEffect.} = ## parses a float starting at `start` and stores the value into `number`. ## Result is the number of processed chars or 0 if there occured a parsing @@ -319,7 +319,7 @@ proc parseFloat*(s: string, number: var float, start = 0): int {. ## parses a float starting at `start` and stores the value into `number`. ## Result is the number of processed chars or 0 if there occured a parsing ## error. - var bf: biggestFloat + var bf: BiggestFloat result = parseBiggestFloat(s, bf, start) number = bf @@ -370,7 +370,7 @@ iterator interpolatedFragments*(s: string): tuple[kind: TInterpolatedKind, of '\0': raise newException(EInvalidValue, "Expected closing '}': " & s[i..s.len]) - else: nil + else: discard inc j inc i, 2 # skip ${ kind = ikExpr diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index d8fed845a..70b617393 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -249,23 +249,23 @@ proc newLine*: TPeg {.inline.} = ## constructs the PEG `newline`:idx: (``\n``) result.kind = pkNewline -proc UnicodeLetter*: TPeg {.inline.} = +proc unicodeLetter*: TPeg {.inline.} = ## constructs the PEG ``\letter`` which matches any Unicode letter. result.kind = pkLetter -proc UnicodeLower*: TPeg {.inline.} = +proc unicodeLower*: TPeg {.inline.} = ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter. result.kind = pkLower -proc UnicodeUpper*: TPeg {.inline.} = +proc unicodeUpper*: TPeg {.inline.} = ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter. result.kind = pkUpper -proc UnicodeTitle*: TPeg {.inline.} = +proc unicodeTitle*: TPeg {.inline.} = ## constructs the PEG ``\title`` which matches any Unicode title letter. result.kind = pkTitle -proc UnicodeWhitespace*: TPeg {.inline.} = +proc unicodeWhitespace*: TPeg {.inline.} = ## constructs the PEG ``\white`` which matches any Unicode ## whitespace character. result.kind = pkWhitespace @@ -306,7 +306,7 @@ proc backrefIgnoreStyle*(index: range[1..MaxSubPatterns]): TPeg {. proc spaceCost(n: TPeg): int = case n.kind - of pkEmpty: nil + of pkEmpty: discard of pkTerminal, pkTerminalIgnoreCase, pkTerminalIgnoreStyle, pkChar, pkGreedyRepChar, pkCharChoice, pkGreedyRepSet, pkAny..pkWhitespace, pkGreedyAny: @@ -340,28 +340,28 @@ proc newNonTerminal*(name: string, line, column: int): PNonTerminal {. template letters*: expr = ## expands to ``charset({'A'..'Z', 'a'..'z'})`` - charset({'A'..'Z', 'a'..'z'}) + charSet({'A'..'Z', 'a'..'z'}) template digits*: expr = ## expands to ``charset({'0'..'9'})`` - charset({'0'..'9'}) + charSet({'0'..'9'}) template whitespace*: expr = ## expands to ``charset({' ', '\9'..'\13'})`` - charset({' ', '\9'..'\13'}) + charSet({' ', '\9'..'\13'}) template identChars*: expr = ## expands to ``charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})`` - charset({'a'..'z', 'A'..'Z', '0'..'9', '_'}) + charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'}) template identStartChars*: expr = ## expands to ``charset({'A'..'Z', 'a'..'z', '_'})`` - charset({'a'..'z', 'A'..'Z', '_'}) + charSet({'a'..'z', 'A'..'Z', '_'}) template ident*: expr = ## same as ``[a-zA-Z_][a-zA-z_0-9]*``; standard identifier - sequence(charset({'a'..'z', 'A'..'Z', '_'}), - *charset({'a'..'z', 'A'..'Z', '0'..'9', '_'})) + sequence(charSet({'a'..'z', 'A'..'Z', '_'}), + *charSet({'a'..'z', 'A'..'Z', '0'..'9', '_'})) template natural*: expr = ## same as ``\d+`` @@ -385,7 +385,7 @@ proc esc(c: char, reserved = {'\0'..'\255'}): string = elif c in reserved: result = '\\' & c else: result = $c -proc singleQuoteEsc(c: Char): string = return "'" & esc(c, {'\''}) & "'" +proc singleQuoteEsc(c: char): string = return "'" & esc(c, {'\''}) & "'" proc singleQuoteEsc(str: string): string = result = "'" @@ -409,11 +409,11 @@ proc charSetEscAux(cc: set[char]): string = c1 = c2 inc(c1) -proc CharSetEsc(cc: set[char]): string = +proc charSetEsc(cc: set[char]): string = if card(cc) >= 128+64: - result = "[^" & CharSetEscAux({'\1'..'\xFF'} - cc) & ']' + result = "[^" & charSetEscAux({'\1'..'\xFF'} - cc) & ']' else: - result = '[' & CharSetEscAux(cc) & ']' + result = '[' & charSetEscAux(cc) & ']' proc toStrAux(r: TPeg, res: var string) = case r.kind @@ -590,7 +590,7 @@ proc rawMatch*(s: string, p: TPeg, start: int, c: var TCaptures): int {. var a: TRune result = start fastRuneAt(s, result, a) - if isWhitespace(a): dec(result, start) + if isWhiteSpace(a): dec(result, start) else: result = -1 else: result = -1 @@ -747,7 +747,7 @@ template fillMatches(s, caps, c: expr) = for k in 0..c.ml-1: caps[k] = substr(s, c.matches[k][0], c.matches[k][1]) -proc match*(s: string, pattern: TPeg, matches: var openarray[string], +proc match*(s: string, pattern: TPeg, matches: var openArray[string], start = 0): bool {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns ``true`` if ``s[start..]`` matches the ``pattern`` and ## the captured substrings in the array ``matches``. If it does not @@ -765,7 +765,7 @@ proc match*(s: string, pattern: TPeg, c.origStart = start result = rawMatch(s, pattern, start, c) == len(s)-start -proc matchLen*(s: string, pattern: TPeg, matches: var openarray[string], +proc matchLen*(s: string, pattern: TPeg, matches: var openArray[string], start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## the same as ``match``, but it returns the length of the match, ## if there is no match, -1 is returned. Note that a match length @@ -786,7 +786,7 @@ proc matchLen*(s: string, pattern: TPeg, c.origStart = start result = rawMatch(s, pattern, start, c) -proc find*(s: string, pattern: TPeg, matches: var openarray[string], +proc find*(s: string, pattern: TPeg, matches: var openArray[string], start = 0): int {.nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns the starting position of ``pattern`` in ``s`` and the captured ## substrings in the array ``matches``. If it does not match, nothing @@ -801,7 +801,7 @@ proc find*(s: string, pattern: TPeg, matches: var openarray[string], return -1 # could also use the pattern here: (!P .)* P -proc findBounds*(s: string, pattern: TPeg, matches: var openarray[string], +proc findBounds*(s: string, pattern: TPeg, matches: var openArray[string], start = 0): tuple[first, last: int] {. nosideEffect, rtl, extern: "npegs$1Capture".} = ## returns the starting position and end position of ``pattern`` in ``s`` @@ -869,7 +869,7 @@ template `=~`*(s: string, pattern: TPeg): bool = ## bind maxSubpatterns when not definedInScope(matches): - var matches {.inject.}: array[0..maxSubpatterns-1, string] + var matches {.inject.}: array[0..MaxSubpatterns-1, string] match(s, pattern, matches) # ------------------------- more string handling ------------------------------ @@ -1074,14 +1074,14 @@ const "@", "built-in", "escaped", "$", "$", "^" ] -proc HandleCR(L: var TPegLexer, pos: int): int = +proc handleCR(L: var TPegLexer, pos: int): int = assert(L.buf[pos] == '\c') inc(L.linenumber) result = pos+1 if L.buf[result] == '\L': inc(result) L.lineStart = result -proc HandleLF(L: var TPegLexer, pos: int): int = +proc handleLF(L: var TPegLexer, pos: int): int = assert(L.buf[pos] == '\L') inc(L.linenumber) result = pos+1 @@ -1117,45 +1117,45 @@ proc handleHexChar(c: var TPegLexer, xi: var int) = of 'A'..'F': xi = (xi shl 4) or (ord(c.buf[c.bufpos]) - ord('A') + 10) inc(c.bufpos) - else: nil + else: discard proc getEscapedChar(c: var TPegLexer, tok: var TToken) = inc(c.bufpos) case c.buf[c.bufpos] of 'r', 'R', 'c', 'C': add(tok.literal, '\c') - Inc(c.bufpos) + inc(c.bufpos) of 'l', 'L': add(tok.literal, '\L') - Inc(c.bufpos) + inc(c.bufpos) of 'f', 'F': add(tok.literal, '\f') inc(c.bufpos) of 'e', 'E': add(tok.literal, '\e') - Inc(c.bufpos) + inc(c.bufpos) of 'a', 'A': add(tok.literal, '\a') - Inc(c.bufpos) + inc(c.bufpos) of 'b', 'B': add(tok.literal, '\b') - Inc(c.bufpos) + inc(c.bufpos) of 'v', 'V': add(tok.literal, '\v') - Inc(c.bufpos) + inc(c.bufpos) of 't', 'T': add(tok.literal, '\t') - Inc(c.bufpos) + inc(c.bufpos) of 'x', 'X': inc(c.bufpos) var xi = 0 handleHexChar(c, xi) handleHexChar(c, xi) if xi == 0: tok.kind = tkInvalid - else: add(tok.literal, Chr(xi)) + else: add(tok.literal, chr(xi)) of '0'..'9': var val = ord(c.buf[c.bufpos]) - ord('0') - Inc(c.bufpos) + inc(c.bufpos) var i = 1 while (i <= 3) and (c.buf[c.bufpos] in {'0'..'9'}): val = val * 10 + ord(c.buf[c.bufpos]) - ord('0') @@ -1169,7 +1169,7 @@ proc getEscapedChar(c: var TPegLexer, tok: var TToken) = tok.kind = tkInvalid else: add(tok.literal, c.buf[c.bufpos]) - Inc(c.bufpos) + inc(c.bufpos) proc skip(c: var TPegLexer) = var pos = c.bufpos @@ -1177,14 +1177,14 @@ proc skip(c: var TPegLexer) = while true: case buf[pos] of ' ', '\t': - Inc(pos) + inc(pos) of '#': while not (buf[pos] in {'\c', '\L', '\0'}): inc(pos) of '\c': - pos = HandleCR(c, pos) + pos = handleCR(c, pos) buf = c.buf of '\L': - pos = HandleLF(c, pos) + pos = handleLF(c, pos) buf = c.buf else: break # EndOfFile also leaves the loop @@ -1209,7 +1209,7 @@ proc getString(c: var TPegLexer, tok: var TToken) = break else: add(tok.literal, buf[pos]) - Inc(pos) + inc(pos) c.bufpos = pos proc getDollar(c: var TPegLexer, tok: var TToken) = @@ -1250,7 +1250,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) = break else: ch = buf[pos] - Inc(pos) + inc(pos) incl(tok.charset, ch) if buf[pos] == '-': if buf[pos+1] == ']': @@ -1270,7 +1270,7 @@ proc getCharSet(c: var TPegLexer, tok: var TToken) = break else: ch2 = buf[pos] - Inc(pos) + inc(pos) for i in ord(ch)+1 .. ord(ch2): incl(tok.charset, chr(i)) c.bufpos = pos @@ -1281,7 +1281,7 @@ proc getSymbol(c: var TPegLexer, tok: var TToken) = var buf = c.buf while true: add(tok.literal, buf[pos]) - Inc(pos) + inc(pos) if buf[pos] notin strutils.IdentChars: break c.bufpos = pos tok.kind = tkIdentifier @@ -1298,7 +1298,7 @@ proc getBuiltin(c: var TPegLexer, tok: var TToken) = proc getTok(c: var TPegLexer, tok: var TToken) = tok.kind = tkInvalid tok.modifier = modNone - setlen(tok.literal, 0) + setLen(tok.literal, 0) skip(c) case c.buf[c.bufpos] of '{': @@ -1315,14 +1315,14 @@ proc getTok(c: var TPegLexer, tok: var TToken) = inc(c.bufpos) add(tok.literal, '}') of '[': - getCharset(c, tok) + getCharSet(c, tok) of '(': tok.kind = tkParLe - Inc(c.bufpos) + inc(c.bufpos) add(tok.literal, '(') of ')': tok.kind = tkParRi - Inc(c.bufpos) + inc(c.bufpos) add(tok.literal, ')') of '.': tok.kind = tkAny @@ -1347,7 +1347,7 @@ proc getTok(c: var TPegLexer, tok: var TToken) = of "i": tok.modifier = modIgnoreCase of "y": tok.modifier = modIgnoreStyle of "v": tok.modifier = modVerbatim - else: nil + else: discard setLen(tok.literal, 0) if c.buf[c.bufpos] == '$': getDollar(c, tok) @@ -1452,28 +1452,28 @@ proc modifiedTerm(s: string, m: TModifier): TPeg = proc modifiedBackref(s: int, m: TModifier): TPeg = case m - of modNone, modVerbatim: result = backRef(s) - of modIgnoreCase: result = backRefIgnoreCase(s) - of modIgnoreStyle: result = backRefIgnoreStyle(s) + of modNone, modVerbatim: result = backref(s) + of modIgnoreCase: result = backrefIgnoreCase(s) + of modIgnoreStyle: result = backrefIgnoreStyle(s) proc builtin(p: var TPegParser): TPeg = # do not use "y", "skip" or "i" as these would be ambiguous case p.tok.literal of "n": result = newLine() - of "d": result = charset({'0'..'9'}) - of "D": result = charset({'\1'..'\xff'} - {'0'..'9'}) - of "s": result = charset({' ', '\9'..'\13'}) - of "S": result = charset({'\1'..'\xff'} - {' ', '\9'..'\13'}) - of "w": result = charset({'a'..'z', 'A'..'Z', '_', '0'..'9'}) - of "W": result = charset({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'}) - of "a": result = charset({'a'..'z', 'A'..'Z'}) - of "A": result = charset({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'}) + of "d": result = charSet({'0'..'9'}) + of "D": result = charSet({'\1'..'\xff'} - {'0'..'9'}) + of "s": result = charSet({' ', '\9'..'\13'}) + of "S": result = charSet({'\1'..'\xff'} - {' ', '\9'..'\13'}) + of "w": result = charSet({'a'..'z', 'A'..'Z', '_', '0'..'9'}) + of "W": result = charSet({'\1'..'\xff'} - {'a'..'z','A'..'Z','_','0'..'9'}) + of "a": result = charSet({'a'..'z', 'A'..'Z'}) + of "A": result = charSet({'\1'..'\xff'} - {'a'..'z', 'A'..'Z'}) of "ident": result = pegs.ident - of "letter": result = UnicodeLetter() - of "upper": result = UnicodeUpper() - of "lower": result = UnicodeLower() - of "title": result = UnicodeTitle() - of "white": result = UnicodeWhitespace() + of "letter": result = unicodeLetter() + of "upper": result = unicodeUpper() + of "lower": result = unicodeLower() + of "title": result = unicodeTitle() + of "white": result = unicodeWhitespace() else: pegError(p, "unknown built-in: " & p.tok.literal) proc token(terminal: TPeg, p: TPegParser): TPeg = @@ -1494,7 +1494,7 @@ proc primary(p: var TPegParser): TPeg = of tkCurlyAt: getTok(p) return !*\primary(p).token(p) - else: nil + else: discard case p.tok.kind of tkIdentifier: if p.identIsVerbatim: @@ -1505,7 +1505,7 @@ proc primary(p: var TPegParser): TPeg = elif not arrowIsNextTok(p): var nt = getNonTerminal(p, p.tok.literal) incl(nt.flags, ntUsed) - result = nonTerminal(nt).token(p) + result = nonterminal(nt).token(p) getTok(p) else: pegError(p, "expression expected, but found: " & p.tok.literal) @@ -1517,7 +1517,7 @@ proc primary(p: var TPegParser): TPeg = of tkCharSet: if '\0' in p.tok.charset: pegError(p, "binary zero ('\\0') not allowed in character class") - result = charset(p.tok.charset).token(p) + result = charSet(p.tok.charset).token(p) getTok(p) of tkParLe: getTok(p) @@ -1549,7 +1549,7 @@ proc primary(p: var TPegParser): TPeg = of tkBackref: var m = p.tok.modifier if m == modNone: m = p.modifier - result = modifiedBackRef(p.tok.index, m).token(p) + result = modifiedBackref(p.tok.index, m).token(p) if p.tok.index < 0 or p.tok.index > p.captures: pegError(p, "invalid back reference index: " & $p.tok.index) getTok(p) diff --git a/lib/pure/scgi.nim b/lib/pure/scgi.nim index b18fe0094..04b77fafe 100644 --- a/lib/pure/scgi.nim +++ b/lib/pure/scgi.nim @@ -119,7 +119,7 @@ proc next*(s: var TScgistate, timeout: int = -1): bool = ## request, if ``timeout`` is `-1` then this function will never time out. ## Returns `True` if a new request has been processed. var rsocks = @[s.server] - if select(rsocks, timeout) == 1 and rsocks.len == 0: + if select(rsocks, timeout) == 1 and rsocks.len == 1: new(s.client) accept(s.server, s.client) var L = 0 diff --git a/lib/pure/sockets.nim b/lib/pure/sockets.nim index 66bb1e6a9..fd6403118 100644 --- a/lib/pure/sockets.nim +++ b/lib/pure/sockets.nim @@ -26,7 +26,7 @@ {.deadCodeElim: on.} -when hostos == "solaris": +when hostOS == "solaris": {.passl: "-lsocket -lnsl".} import os, parseutils @@ -132,17 +132,17 @@ type ETimeout* = object of ESynch let - InvalidSocket*: TSocket = nil ## invalid socket + invalidSocket*: TSocket = nil ## invalid socket when defined(windows): let - OSInvalidSocket = winlean.INVALID_SOCKET + osInvalidSocket = winlean.INVALID_SOCKET else: let - OSInvalidSocket = posix.INVALID_SOCKET + osInvalidSocket = posix.INVALID_SOCKET proc newTSocket(fd: TSocketHandle, isBuff: bool): TSocket = - if fd == OSInvalidSocket: + if fd == osInvalidSocket: return nil new(result) result.fd = fd @@ -187,22 +187,22 @@ proc htons*(x: int16): int16 = result = sockets.ntohs(x) when defined(Posix): - proc ToInt(domain: TDomain): cint = + proc toInt(domain: TDomain): cint = case domain of AF_UNIX: result = posix.AF_UNIX of AF_INET: result = posix.AF_INET of AF_INET6: result = posix.AF_INET6 - else: nil + else: discard - proc ToInt(typ: TType): cint = + proc toInt(typ: TType): cint = case typ of SOCK_STREAM: result = posix.SOCK_STREAM of SOCK_DGRAM: result = posix.SOCK_DGRAM of SOCK_SEQPACKET: result = posix.SOCK_SEQPACKET of SOCK_RAW: result = posix.SOCK_RAW - else: nil + else: discard - proc ToInt(p: TProtocol): cint = + proc toInt(p: TProtocol): cint = case p of IPPROTO_TCP: result = posix.IPPROTO_TCP of IPPROTO_UDP: result = posix.IPPROTO_UDP @@ -210,16 +210,16 @@ when defined(Posix): of IPPROTO_IPV6: result = posix.IPPROTO_IPV6 of IPPROTO_RAW: result = posix.IPPROTO_RAW of IPPROTO_ICMP: result = posix.IPPROTO_ICMP - else: nil + else: discard else: proc toInt(domain: TDomain): cint = result = toU16(ord(domain)) - proc ToInt(typ: TType): cint = + proc toInt(typ: TType): cint = result = cint(ord(typ)) - proc ToInt(p: TProtocol): cint = + proc toInt(p: TProtocol): cint = result = cint(ord(p)) proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, @@ -230,7 +230,7 @@ proc socket*(domain: TDomain = AF_INET, typ: TType = SOCK_STREAM, when defined(Windows): result = newTSocket(winlean.socket(ord(domain), ord(typ), ord(protocol)), buffered) else: - result = newTSocket(posix.socket(ToInt(domain), ToInt(typ), ToInt(protocol)), buffered) + result = newTSocket(posix.socket(toInt(domain), toInt(typ), toInt(protocol)), buffered) when defined(ssl): CRYPTO_malloc_init() @@ -333,7 +333,7 @@ when defined(ssl): if SSLSetFd(socket.sslHandle, socket.fd) != 1: SSLError() -proc SocketError*(socket: TSocket, err: int = -1, async = false) = +proc socketError*(socket: TSocket, err: int = -1, async = false) = ## Raises proper errors based on return values of ``recv`` functions. ## ## If ``async`` is ``True`` no error will be thrown in the case when the @@ -362,28 +362,28 @@ proc SocketError*(socket: TSocket, err: int = -1, async = false) = else: SSLError("Unknown Error") if err == -1 and not (when defined(ssl): socket.isSSL else: false): - let lastError = OSLastError() + let lastError = osLastError() if async: when defined(windows): if lastError.int32 == WSAEWOULDBLOCK: return - else: OSError(lastError) + else: osError(lastError) else: if lastError.int32 == EAGAIN or lastError.int32 == EWOULDBLOCK: return - else: OSError(lastError) - else: OSError(lastError) + else: osError(lastError) + else: osError(lastError) proc listen*(socket: TSocket, backlog = SOMAXCONN) {.tags: [FReadIO].} = ## Marks ``socket`` as accepting connections. ## ``Backlog`` specifies the maximum length of the ## queue of pending connections. - if listen(socket.fd, cint(backlog)) < 0'i32: OSError(OSLastError()) + if listen(socket.fd, cint(backlog)) < 0'i32: osError(osLastError()) proc invalidIp4(s: string) {.noreturn, noinline.} = raise newException(EInvalidValue, "invalid ip4 address: " & s) -proc parseIp4*(s: string): biggestInt = +proc parseIp4*(s: string): BiggestInt = ## parses an IP version 4 in dotted decimal form like "a.b.c.d". ## ## This is equivalent to `inet_ntoa`:idx:. @@ -410,14 +410,14 @@ proc parseIp4*(s: string): biggestInt = if j <= 0: invalidIp4(s) inc(i, j) if s[i] != '\0': invalidIp4(s) - result = biggestInt(a shl 24 or b shl 16 or c shl 8 or d) + result = BiggestInt(a shl 24 or b shl 16 or c shl 8 or d) template gaiNim(a, p, h, list: expr): stmt = block: - var gaiResult = getAddrInfo(a, $p, addr(h), list) + var gaiResult = getaddrinfo(a, $p, addr(h), list) if gaiResult != 0'i32: when defined(windows): - OSError(OSLastError()) + osError(osLastError()) else: raise newException(EOS, $gai_strerror(gaiResult)) @@ -436,17 +436,17 @@ proc bindAddr*(socket: TSocket, port = TPort(0), address = "") {. name.sin_port = sockets.htons(int16(port)) name.sin_addr.s_addr = sockets.htonl(INADDR_ANY) if bindSocket(socket.fd, cast[ptr TSockAddr](addr(name)), - sizeof(name).TSockLen) < 0'i32: - OSError(OSLastError()) + sizeof(name).TSocklen) < 0'i32: + osError(osLastError()) else: - var hints: TAddrInfo - var aiList: ptr TAddrInfo = nil + var hints: Taddrinfo + var aiList: ptr Taddrinfo = nil hints.ai_family = toInt(AF_INET) hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) gaiNim(address, port, hints, aiList) - if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrLen.TSockLen) < 0'i32: - OSError(OSLastError()) + if bindSocket(socket.fd, aiList.ai_addr, aiList.ai_addrlen.TSocklen) < 0'i32: + osError(osLastError()) proc getSockName*(socket: TSocket): TPort = ## returns the socket's associated port number. @@ -457,40 +457,40 @@ proc getSockName*(socket: TSocket): TPort = name.sin_family = posix.AF_INET #name.sin_port = htons(cint16(port)) #name.sin_addr.s_addr = htonl(INADDR_ANY) - var namelen = sizeof(name).TSockLen + var namelen = sizeof(name).TSocklen if getsockname(socket.fd, cast[ptr TSockAddr](addr(name)), addr(namelen)) == -1'i32: - OSError(OSLastError()) + osError(osLastError()) result = TPort(sockets.ntohs(name.sin_port)) template acceptAddrPlain(noClientRet, successRet: expr, sslImplementation: stmt): stmt {.immediate.} = assert(client != nil) var sockAddress: Tsockaddr_in - var addrLen = sizeof(sockAddress).TSockLen + var addrLen = sizeof(sockAddress).TSocklen var sock = accept(server.fd, cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) - if sock == OSInvalidSocket: - let err = OSLastError() + if sock == osInvalidSocket: + let err = osLastError() when defined(windows): if err.int32 == WSAEINPROGRESS: - client = InvalidSocket + client = invalidSocket address = "" when noClientRet.int == -1: return else: return noClientRet - else: OSError(err) + else: osError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: - client = InvalidSocket + client = invalidSocket address = "" when noClientRet.int == -1: return else: return noClientRet - else: OSError(err) + else: osError(err) else: client.fd = sock client.isBuffered = server.isBuffered @@ -628,7 +628,7 @@ proc accept*(server: TSocket): TSocket {.deprecated, tags: [FReadIO].} = proc close*(socket: TSocket) = ## closes a socket. when defined(windows): - discard winlean.closeSocket(socket.fd) + discard winlean.closesocket(socket.fd) else: discard posix.close(socket.fd) # TODO: These values should not be discarded. An EOS should be raised. @@ -669,7 +669,7 @@ proc getServByPort*(port: TPort, proto: string): TServent {.tags: [FReadIO].} = result.port = TPort(s.s_port) result.proto = $s.s_proto -proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} = +proc getHostByAddr*(ip: string): Thostent {.tags: [FReadIO].} = ## This function will lookup the hostname of an IP Address. var myaddr: TInAddr myaddr.s_addr = inet_addr(ip) @@ -677,43 +677,43 @@ proc getHostByAddr*(ip: string): THostEnt {.tags: [FReadIO].} = when defined(windows): var s = winlean.gethostbyaddr(addr(myaddr), sizeof(myaddr).cuint, cint(sockets.AF_INET)) - if s == nil: OSError(OSLastError()) + if s == nil: osError(osLastError()) else: - var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSockLen, + var s = posix.gethostbyaddr(addr(myaddr), sizeof(myaddr).TSocklen, cint(posix.AF_INET)) if s == nil: - raise newException(EOS, $hStrError(h_errno)) + raise newException(EOS, $hstrerror(h_errno)) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) when defined(windows): - result.addrType = TDomain(s.h_addrtype) + result.addrtype = TDomain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: - result.addrType = AF_INET + result.addrtype = AF_INET elif s.h_addrtype == posix.AF_INET6: - result.addrType = AF_INET6 + result.addrtype = AF_INET6 else: raise newException(EOS, "unknown h_addrtype") result.addrList = cstringArrayToSeq(s.h_addr_list) result.length = int(s.h_length) -proc getHostByName*(name: string): THostEnt {.tags: [FReadIO].} = +proc getHostByName*(name: string): Thostent {.tags: [FReadIO].} = ## This function will lookup the IP address of a hostname. when defined(Windows): var s = winlean.gethostbyname(name) else: var s = posix.gethostbyname(name) - if s == nil: OSError(OSLastError()) + if s == nil: osError(osLastError()) result.name = $s.h_name result.aliases = cstringArrayToSeq(s.h_aliases) when defined(windows): - result.addrType = TDomain(s.h_addrtype) + result.addrtype = TDomain(s.h_addrtype) else: if s.h_addrtype == posix.AF_INET: - result.addrType = AF_INET + result.addrtype = AF_INET elif s.h_addrtype == posix.AF_INET6: - result.addrType = AF_INET6 + result.addrtype = AF_INET6 else: raise newException(EOS, "unknown h_addrtype") result.addrList = cstringArrayToSeq(s.h_addr_list) @@ -723,10 +723,10 @@ proc getSockOptInt*(socket: TSocket, level, optname: int): int {. tags: [FReadIO].} = ## getsockopt for integer options. var res: cint - var size = sizeof(res).TSockLen + var size = sizeof(res).TSocklen if getsockopt(socket.fd, cint(level), cint(optname), addr(res), addr(size)) < 0'i32: - OSError(OSLastError()) + osError(osLastError()) result = int(res) proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {. @@ -734,8 +734,8 @@ proc setSockOptInt*(socket: TSocket, level, optname, optval: int) {. ## setsockopt for integer options. var value = cint(optval) if setsockopt(socket.fd, cint(level), cint(optname), addr(value), - sizeof(value).TSockLen) < 0'i32: - OSError(OSLastError()) + sizeof(value).TSocklen) < 0'i32: + osError(osLastError()) proc toCInt(opt: TSOBool): cint = case opt @@ -751,10 +751,10 @@ proc getSockOpt*(socket: TSocket, opt: TSOBool, level = SOL_SOCKET): bool {. tags: [FReadIO].} = ## Retrieves option ``opt`` as a boolean value. var res: cint - var size = sizeof(res).TSockLen + var size = sizeof(res).TSocklen if getsockopt(socket.fd, cint(level), toCInt(opt), addr(res), addr(size)) < 0'i32: - OSError(OSLastError()) + osError(osLastError()) result = res != 0 proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET) {. @@ -762,8 +762,8 @@ proc setSockOpt*(socket: TSocket, opt: TSOBool, value: bool, level = SOL_SOCKET) ## Sets option ``opt`` to a boolean value specified by ``value``. var valuei = cint(if value: 1 else: 0) if setsockopt(socket.fd, cint(level), toCInt(opt), addr(valuei), - sizeof(valuei).TSockLen) < 0'i32: - OSError(OSLastError()) + sizeof(valuei).TSocklen) < 0'i32: + osError(osLastError()) proc connect*(socket: TSocket, address: string, port = TPort(0), af: TDomain = AF_INET) {.tags: [FReadIO].} = @@ -773,8 +773,8 @@ proc connect*(socket: TSocket, address: string, port = TPort(0), ## not do it. ## ## If ``socket`` is an SSL socket a handshake will be automatically performed. - var hints: TAddrInfo - var aiList: ptr TAddrInfo = nil + var hints: Taddrinfo + var aiList: ptr Taddrinfo = nil hints.ai_family = toInt(af) hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) @@ -784,14 +784,14 @@ proc connect*(socket: TSocket, address: string, port = TPort(0), var lastError: TOSErrorCode var it = aiList while it != nil: - if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen) == 0'i32: + if connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) == 0'i32: success = true break - else: lastError = OSLastError() + else: lastError = osLastError() it = it.ai_next freeaddrinfo(aiList) - if not success: OSError(lastError) + if not success: osError(lastError) when defined(ssl): if socket.isSSL: @@ -836,8 +836,8 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), ## ## **Note**: For SSL sockets, the ``handshake`` procedure must be called ## whenever the socket successfully connects to a server. - var hints: TAddrInfo - var aiList: ptr TAddrInfo = nil + var hints: Taddrinfo + var aiList: ptr Taddrinfo = nil hints.ai_family = toInt(af) hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) @@ -847,12 +847,12 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), var lastError: TOSErrorCode var it = aiList while it != nil: - var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSockLen) + var ret = connect(socket.fd, it.ai_addr, it.ai_addrlen.TSocklen) if ret == 0'i32: success = true break else: - lastError = OSLastError() + lastError = osLastError() when defined(windows): # Windows EINTR doesn't behave same as POSIX. if lastError.int32 == WSAEWOULDBLOCK: @@ -866,7 +866,7 @@ proc connectAsync*(socket: TSocket, name: string, port = TPort(0), it = it.ai_next freeaddrinfo(aiList) - if not success: OSError(lastError) + if not success: osError(lastError) when defined(ssl): if socket.isSSL: socket.sslNoHandshake = true @@ -912,7 +912,7 @@ when defined(ssl): else: SSLError("Socket is not an SSL socket.") -proc timeValFromMilliseconds(timeout = 500): TTimeVal = +proc timeValFromMilliseconds(timeout = 500): Ttimeval = if timeout != -1: var seconds = timeout div 1000 result.tv_sec = seconds.int32 @@ -928,7 +928,7 @@ proc pruneSocketSet(s: var seq[TSocket], fd: var TFdSet) = var i = 0 var L = s.len while i < L: - if FD_ISSET(s[i].fd, fd) != 0'i32: + if FD_ISSET(s[i].fd, fd) == 0'i32: s[i] = s[L-1] dec(L) else: @@ -970,7 +970,7 @@ proc select*(readfds, writefds, exceptfds: var seq[TSocket], if buffersFilled > 0: return buffersFilled - var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout) var rd, wr, ex: TFdSet var m = 0 @@ -993,7 +993,7 @@ proc select*(readfds, writefds: var seq[TSocket], let buffersFilled = checkBuffer(readfds) if buffersFilled > 0: return buffersFilled - var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout) var rd, wr: TFdSet var m = 0 @@ -1017,7 +1017,7 @@ proc selectWrite*(writefds: var seq[TSocket], ## ## ``timeout`` is specified in miliseconds and ``-1`` can be specified for ## an unlimited time. - var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout) var wr: TFdSet var m = 0 @@ -1035,7 +1035,7 @@ proc select*(readfds: var seq[TSocket], timeout = 500): int = let buffersFilled = checkBuffer(readfds) if buffersFilled > 0: return buffersFilled - var tv {.noInit.}: TTimeVal = timeValFromMilliseconds(timeout) + var tv {.noInit.}: Ttimeval = timeValFromMilliseconds(timeout) var rd: TFdSet var m = 0 @@ -1058,7 +1058,7 @@ proc readIntoBuf(socket: TSocket, flags: int32): int = else: result = recv(socket.fd, addr(socket.buffer), cint(socket.buffer.high), flags) if result <= 0: - socket.buflen = 0 + socket.bufLen = 0 socket.currPos = 0 return result socket.bufLen = result @@ -1142,7 +1142,7 @@ proc waitFor(socket: TSocket, waited: var float, timeout, size: int, var s = @[socket] var startTime = epochTime() let selRet = select(s, timeout - int(waited * 1000.0)) - if selRet < 0: OSError(OSLastError()) + if selRet < 0: osError(osLastError()) if selRet != 1: raise newException(ETimeout, "Call to '" & funcName & "' timed out.") waited += (epochTime() - startTime) @@ -1180,7 +1180,7 @@ proc recv*(socket: TSocket, data: var string, size: int, timeout = -1): int = result = recv(socket, cstring(data), size, timeout) if result < 0: data.setLen(0) - socket.SocketError(result) + socket.socketError(result) data.setLen(result) proc recvAsync*(socket: TSocket, data: var string, size: int): int = @@ -1194,7 +1194,7 @@ proc recvAsync*(socket: TSocket, data: var string, size: int): int = result = recv(socket, cstring(data), size) if result < 0: data.setLen(0) - socket.SocketError(async = true) + socket.socketError(async = true) result = -1 data.setLen(result) @@ -1258,10 +1258,10 @@ proc recvLine*(socket: TSocket, line: var TaintedString, timeout = -1): bool {. if n > 0 and c == '\L': discard recv(socket, addr(c), 1) elif n <= 0: return false - addNlIfEmpty() + addNLIfEmpty() return true elif c == '\L': - addNlIfEmpty() + addNLIfEmpty() return true add(line.string, c) @@ -1291,18 +1291,18 @@ proc readLine*(socket: TSocket, line: var TaintedString, timeout = -1) {. var c: char discard waitFor(socket, waited, timeout, 1, "readLine") var n = recv(socket, addr(c), 1) - if n < 0: OSError(OSLastError()) + if n < 0: osError(osLastError()) elif n == 0: return if c == '\r': discard waitFor(socket, waited, timeout, 1, "readLine") n = peekChar(socket, c) if n > 0 and c == '\L': discard recv(socket, addr(c), 1) - elif n <= 0: OSError(OSLastError()) - addNlIfEmpty() + elif n <= 0: osError(osLastError()) + addNLIfEmpty() return elif c == '\L': - addNlIfEmpty() + addNLIfEmpty() return add(line.string, c) @@ -1352,7 +1352,7 @@ proc readLineAsync*(socket: TSocket, setLen(line.string, 0) template errorOrNone = - socket.SocketError(async = true) + socket.socketError(async = true) return ReadNone while true: @@ -1385,7 +1385,7 @@ proc recv*(socket: TSocket): TaintedString {.tags: [FReadIO], deprecated.} = var pos = 0 while true: var bytesRead = recv(socket, addr(string(result)[pos]), bufSize-1) - if bytesRead == -1: OSError(OSLastError()) + if bytesRead == -1: osError(osLastError()) setLen(result.string, pos + bytesRead) if bytesRead != bufSize-1: break # increase capacity: @@ -1454,22 +1454,22 @@ proc recvAsync*(socket: TSocket, s: var TaintedString): bool {. else: SSLError("Unknown Error") if bytesRead == -1 and not (when defined(ssl): socket.isSSL else: false): - let err = OSLastError() + let err = osLastError() when defined(windows): if err.int32 == WSAEWOULDBLOCK: - return False - else: OSError(err) + return false + else: osError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: - return False - else: OSError(err) + return false + else: osError(err) setLen(s.string, pos + bytesRead) if bytesRead != bufSize-1: break # increase capacity: setLen(s.string, s.string.len + bufSize) inc(pos, bytesRead) - result = True + result = true proc recvFrom*(socket: TSocket, data: var string, length: int, address: var string, port: var TPort, flags = 0'i32): int {. @@ -1488,8 +1488,8 @@ proc recvFrom*(socket: TSocket, data: var string, length: int, # TODO: Buffered sockets data.setLen(length) var sockAddress: Tsockaddr_in - var addrLen = sizeof(sockAddress).TSockLen - result = recvFrom(socket.fd, cstring(data), length.cint, flags.cint, + var addrLen = sizeof(sockAddress).TSocklen + result = recvfrom(socket.fd, cstring(data), length.cint, flags.cint, cast[ptr TSockAddr](addr(sockAddress)), addr(addrLen)) if result != -1: @@ -1497,7 +1497,7 @@ proc recvFrom*(socket: TSocket, data: var string, length: int, address = $inet_ntoa(sockAddress.sin_addr) port = ntohs(sockAddress.sin_port).TPort -proc recvFromAsync*(socket: TSocket, data: var String, length: int, +proc recvFromAsync*(socket: TSocket, data: var string, length: int, address: var string, port: var TPort, flags = 0'i32): bool {.tags: [FReadIO].} = ## Variant of ``recvFrom`` for non-blocking sockets. Unlike ``recvFrom``, @@ -1507,15 +1507,15 @@ proc recvFromAsync*(socket: TSocket, data: var String, length: int, result = true var callRes = recvFrom(socket, data, length, address, port, flags) if callRes < 0: - let err = OSLastError() + let err = osLastError() when defined(windows): if err.int32 == WSAEWOULDBLOCK: - return False - else: OSError(err) + return false + else: osError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: - return False - else: OSError(err) + return false + else: osError(err) proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} = ## skips all the data that is pending for the socket @@ -1523,7 +1523,7 @@ proc skip*(socket: TSocket) {.tags: [FReadIO], deprecated.} = ## **Deprecated since version 0.9.2**: This function is not safe for use. const bufSize = 1000 var buf = alloc(bufSize) - while recv(socket, buf, bufSize) == bufSize: nil + while recv(socket, buf, bufSize) == bufSize: discard dealloc(buf) proc skip*(socket: TSocket, size: int, timeout = -1) = @@ -1565,7 +1565,7 @@ proc send*(socket: TSocket, data: string) {.tags: [FWriteIO].} = if socket.isSSL: SSLError() - OSError(OSLastError()) + osError(osLastError()) if sent != data.len: raise newException(EOS, "Could not send all data.") @@ -1598,15 +1598,15 @@ proc sendAsync*(socket: TSocket, data: string): int {.tags: [FWriteIO].} = else: return if result == -1: - let err = OSLastError() + let err = osLastError() when defined(windows): if err.int32 == WSAEINPROGRESS: return 0 - else: OSError(err) + else: osError(err) else: if err.int32 == EAGAIN or err.int32 == EWOULDBLOCK: return 0 - else: OSError(err) + else: osError(err) proc trySend*(socket: TSocket, data: string): bool {.tags: [FWriteIO].} = @@ -1622,8 +1622,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer, ## this function will try each IP of that hostname. ## ## **Note:** This proc is not available for SSL sockets. - var hints: TAddrInfo - var aiList: ptr TAddrInfo = nil + var hints: Taddrinfo + var aiList: ptr Taddrinfo = nil hints.ai_family = toInt(af) hints.ai_socktype = toInt(SOCK_STREAM) hints.ai_protocol = toInt(IPPROTO_TCP) @@ -1633,8 +1633,8 @@ proc sendTo*(socket: TSocket, address: string, port: TPort, data: pointer, var success = false var it = aiList while it != nil: - result = sendTo(socket.fd, data, size.cint, flags.cint, it.ai_addr, - it.ai_addrlen.TSockLen) + result = sendto(socket.fd, data, size.cint, flags.cint, it.ai_addr, + it.ai_addrlen.TSocklen) if result != -1'i32: success = true break @@ -1661,16 +1661,16 @@ when defined(Windows): proc setBlocking(s: TSocket, blocking: bool) = when defined(Windows): var mode = clong(ord(not blocking)) # 1 for non-blocking, 0 for blocking - if ioctlsocket(TSocketHandle(s.fd), FIONBIO, addr(mode)) == -1: - OSError(OSLastError()) + if ioctlsocket(s.fd, FIONBIO, addr(mode)) == -1: + osError(osLastError()) else: # BSD sockets var x: int = fcntl(s.fd, F_GETFL, 0) if x == -1: - OSError(OSLastError()) + osError(osLastError()) else: var mode = if blocking: x and not O_NONBLOCK else: x or O_NONBLOCK if fcntl(s.fd, F_SETFL, mode) == -1: - OSError(OSLastError()) + osError(osLastError()) s.nonblocking = not blocking discard """ proc setReuseAddr*(s: TSocket) = @@ -1709,7 +1709,7 @@ proc isBlocking*(socket: TSocket): bool = not socket.nonblocking ## Determines whether ``socket`` is blocking. when defined(Windows): - var wsa: TWSADATA - if WSAStartup(0x0101'i16, addr wsa) != 0: OSError(OSLastError()) + var wsa: TWSAData + if wsaStartup(0x0101'i16, addr wsa) != 0: osError(osLastError()) diff --git a/lib/pure/streams.nim b/lib/pure/streams.nim index 764471b78..e944dd2fc 100644 --- a/lib/pure/streams.nim +++ b/lib/pure/streams.nim @@ -249,7 +249,7 @@ proc fsClose(s: PStream) = close(PFileStream(s).f) PFileStream(s).f = nil proc fsFlush(s: PStream) = flushFile(PFileStream(s).f) -proc fsAtEnd(s: PStream): bool = return EndOfFile(PFileStream(s).f) +proc fsAtEnd(s: PStream): bool = return endOfFile(PFileStream(s).f) proc fsSetPosition(s: PStream, pos: int) = setFilePos(PFileStream(s).f, pos) proc fsGetPosition(s: PStream): int = return int(getFilePos(PFileStream(s).f)) @@ -277,11 +277,11 @@ proc newFileStream*(filename: string, mode: TFileMode): PFileStream = ## If the file cannot be opened, nil is returned. See the `system ## <system.html>`_ module for a list of available TFileMode enums. var f: TFile - if Open(f, filename, mode): result = newFileStream(f) + if open(f, filename, mode): result = newFileStream(f) when true: - nil + discard else: type TFileHandle* = cint ## Operating system file handle diff --git a/lib/pure/strtabs.nim b/lib/pure/strtabs.nim index 77b463fc0..7003acfcf 100644 --- a/lib/pure/strtabs.nim +++ b/lib/pure/strtabs.nim @@ -88,10 +88,10 @@ proc mustRehash(length, counter: int): bool = proc nextTry(h, maxHash: THash): THash {.inline.} = result = ((5 * h) + 1) and maxHash -proc RawGet(t: PStringTable, key: string): int = +proc rawGet(t: PStringTable, key: string): int = var h: THash = myhash(t, key) and high(t.data) # start with real hash value while not isNil(t.data[h].key): - if mycmp(t, t.data[h].key, key): + if myCmp(t, t.data[h].key, key): return h h = nextTry(h, high(t.data)) result = - 1 @@ -100,7 +100,7 @@ proc `[]`*(t: PStringTable, key: string): string {.rtl, extern: "nstGet".} = ## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned ## and no exception is raised. One can check with ``hasKey`` whether the key ## exists. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: result = "" @@ -108,7 +108,7 @@ proc mget*(t: PStringTable, key: string): var string {. rtl, extern: "nstTake".} = ## retrieves the location at ``t[key]``. If `key` is not in `t`, the ## ``EInvalidKey`` exception is raised. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: result = t.data[index].val else: raise newException(EInvalidKey, "key does not exist: " & key) @@ -116,31 +116,31 @@ proc hasKey*(t: PStringTable, key: string): bool {.rtl, extern: "nst$1".} = ## returns true iff `key` is in the table `t`. result = rawGet(t, key) >= 0 -proc RawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) = +proc rawInsert(t: PStringTable, data: var TKeyValuePairSeq, key, val: string) = var h: THash = myhash(t, key) and high(data) while not isNil(data[h].key): h = nextTry(h, high(data)) data[h].key = key data[h].val = val -proc Enlarge(t: PStringTable) = +proc enlarge(t: PStringTable) = var n: TKeyValuePairSeq newSeq(n, len(t.data) * growthFactor) for i in countup(0, high(t.data)): - if not isNil(t.data[i].key): RawInsert(t, n, t.data[i].key, t.data[i].val) + if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val) swap(t.data, n) proc `[]=`*(t: PStringTable, key, val: string) {.rtl, extern: "nstPut".} = ## puts a (key, value)-pair into `t`. - var index = RawGet(t, key) + var index = rawGet(t, key) if index >= 0: t.data[index].val = val else: - if mustRehash(len(t.data), t.counter): Enlarge(t) - RawInsert(t, t.data, key, val) + if mustRehash(len(t.data), t.counter): enlarge(t) + rawInsert(t, t.data, key, val) inc(t.counter) -proc RaiseFormatException(s: string) = +proc raiseFormatException(s: string) = var e: ref EInvalidValue new(e) e.msg = "format string: key not found: " & s @@ -184,7 +184,7 @@ proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]], ## var mytab = newStringTable({"key1": "val1", "key2": "val2"}, ## modeCaseInsensitive) result = newStringTable(mode) - for key, val in items(keyvaluePairs): result[key] = val + for key, val in items(keyValuePairs): result[key] = val proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {. rtl, extern: "nstFormat".} = diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim index fe71cb77b..de8dc5e51 100644 --- a/lib/pure/strutils.nim +++ b/lib/pure/strutils.nim @@ -1,170 +1,170 @@ -# -# -# Nimrod's Runtime Library -# (c) Copyright 2012 Andreas Rumpf -# -# See the file "copying.txt", included in this -# distribution, for details about the copyright. -# - -## This module contains various string utility routines. -## See the module `re <re.html>`_ for regular expression support. -## See the module `pegs <pegs.html>`_ for PEG support. - -import parseutils - -{.deadCodeElim: on.} - -{.push debugger:off .} # the user does not want to trace a part - # of the standard library! - -include "system/inclrtl" - -type - TCharSet* = set[char] # for compatibility with Nim - -const - Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'} - ## All the characters that count as whitespace. - - Letters* = {'A'..'Z', 'a'..'z'} - ## the set of letters - - Digits* = {'0'..'9'} - ## the set of digits - - HexDigits* = {'0'..'9', 'A'..'F', 'a'..'f'} - ## the set of hexadecimal digits - - IdentChars* = {'a'..'z', 'A'..'Z', '0'..'9', '_'} - ## the set of characters an identifier can consist of - - IdentStartChars* = {'a'..'z', 'A'..'Z', '_'} - ## the set of characters an identifier can start with - - NewLines* = {'\13', '\10'} - ## the set of characters a newline terminator can start with - -proc toLower*(c: Char): Char {.noSideEffect, procvar, - rtl, extern: "nsuToLowerChar".} = - ## Converts `c` into lower case. This works only for the letters A-Z. - ## See `unicode.toLower` for a version that works for any Unicode character. - if c in {'A'..'Z'}: - result = chr(ord(c) + (ord('a') - ord('A'))) - else: - result = c - -proc toLower*(s: string): string {.noSideEffect, procvar, - rtl, extern: "nsuToLowerStr".} = - ## Converts `s` into lower case. This works only for the letters A-Z. - ## See `unicode.toLower` for a version that works for any Unicode character. - result = newString(len(s)) - for i in 0..len(s) - 1: - result[i] = toLower(s[i]) - -proc toUpper*(c: Char): Char {.noSideEffect, procvar, - rtl, extern: "nsuToUpperChar".} = - ## Converts `c` into upper case. This works only for the letters a-z. - ## See `unicode.toUpper` for a version that works for any Unicode character. - if c in {'a'..'z'}: - result = Chr(Ord(c) - (Ord('a') - Ord('A'))) - else: - result = c - -proc toUpper*(s: string): string {.noSideEffect, procvar, - rtl, extern: "nsuToUpperStr".} = - ## Converts `s` into upper case. This works only for the letters a-z. - ## See `unicode.toUpper` for a version that works for any Unicode character. - result = newString(len(s)) - for i in 0..len(s) - 1: - result[i] = toUpper(s[i]) - -proc capitalize*(s: string): string {.noSideEffect, procvar, - rtl, extern: "nsuCapitalize".} = - ## Converts the first character of `s` into upper case. - ## This works only for the letters a-z. - result = toUpper(s[0]) & substr(s, 1) - -proc normalize*(s: string): string {.noSideEffect, procvar, - rtl, extern: "nsuNormalize".} = - ## Normalizes the string `s`. That means to convert it to lower case and - ## remove any '_'. This is needed for Nimrod identifiers for example. - result = newString(s.len) - var j = 0 - for i in 0..len(s) - 1: - if s[i] in {'A'..'Z'}: - result[j] = Chr(Ord(s[i]) + (Ord('a') - Ord('A'))) - inc j - elif s[i] != '_': - result[j] = s[i] - inc j - if j != s.len: setLen(result, j) - -proc cmpIgnoreCase*(a, b: string): int {.noSideEffect, - rtl, extern: "nsuCmpIgnoreCase", procvar, operator: 4.} = - ## Compares two strings in a case insensitive manner. Returns: - ## - ## | 0 iff a == b - ## | < 0 iff a < b - ## | > 0 iff a > b - var i = 0 - var m = min(a.len, b.len) - while i < m: - result = ord(toLower(a[i])) - ord(toLower(b[i])) - if result != 0: return - inc(i) - result = a.len - b.len - -{.push checks: off, line_trace: off .} # this is a hot-spot in the compiler! - # thus we compile without checks here - -proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect, - rtl, extern: "nsuCmpIgnoreStyle", procvar, operator: 3.} = - ## Compares two strings normalized (i.e. case and - ## underscores do not matter). Returns: - ## - ## | 0 iff a == b - ## | < 0 iff a < b - ## | > 0 iff a > b - var i = 0 - var j = 0 - while True: - while a[i] == '_': inc(i) - while b[j] == '_': inc(j) # BUGFIX: typo - var aa = toLower(a[i]) - var bb = toLower(b[j]) - result = ord(aa) - ord(bb) - if result != 0 or aa == '\0': break - inc(i) - inc(j) - -{.pop.} - -proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, - rtl, extern: "nsuStrip", operator: 5.} = - ## Strips whitespace from `s` and returns the resulting string. - ## If `leading` is true, leading whitespace is stripped. - ## If `trailing` is true, trailing whitespace is stripped. - const - chars: set[Char] = Whitespace - var - first = 0 - last = len(s)-1 - if leading: - while s[first] in chars: inc(first) - if trailing: - while last >= 0 and s[last] in chars: dec(last) - result = substr(s, first, last) - -proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} = - ## Converts a character `c` to its octal representation. The resulting - ## string may not have a leading zero. Its length is always exactly 3. - result = newString(3) - var val = ord(c) - for i in countdown(2, 0): - result[i] = Chr(val mod 8 + ord('0')) - val = val div 8 - +# +# +# Nimrod's Runtime Library +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## This module contains various string utility routines. +## See the module `re <re.html>`_ for regular expression support. +## See the module `pegs <pegs.html>`_ for PEG support. + +import parseutils + +{.deadCodeElim: on.} + +{.push debugger:off .} # the user does not want to trace a part + # of the standard library! + +include "system/inclrtl" + +type + TCharSet* = set[char] # for compatibility with Nim + +const + Whitespace* = {' ', '\t', '\v', '\r', '\l', '\f'} + ## All the characters that count as whitespace. + + Letters* = {'A'..'Z', 'a'..'z'} + ## the set of letters + + Digits* = {'0'..'9'} + ## the set of digits + + HexDigits* = {'0'..'9', 'A'..'F', 'a'..'f'} + ## the set of hexadecimal digits + + IdentChars* = {'a'..'z', 'A'..'Z', '0'..'9', '_'} + ## the set of characters an identifier can consist of + + IdentStartChars* = {'a'..'z', 'A'..'Z', '_'} + ## the set of characters an identifier can start with + + NewLines* = {'\13', '\10'} + ## the set of characters a newline terminator can start with + +proc toLower*(c: char): char {.noSideEffect, procvar, + rtl, extern: "nsuToLowerChar".} = + ## Converts `c` into lower case. This works only for the letters A-Z. + ## See `unicode.toLower` for a version that works for any Unicode character. + if c in {'A'..'Z'}: + result = chr(ord(c) + (ord('a') - ord('A'))) + else: + result = c + +proc toLower*(s: string): string {.noSideEffect, procvar, + rtl, extern: "nsuToLowerStr".} = + ## Converts `s` into lower case. This works only for the letters A-Z. + ## See `unicode.toLower` for a version that works for any Unicode character. + result = newString(len(s)) + for i in 0..len(s) - 1: + result[i] = toLower(s[i]) + +proc toUpper*(c: char): char {.noSideEffect, procvar, + rtl, extern: "nsuToUpperChar".} = + ## Converts `c` into upper case. This works only for the letters a-z. + ## See `unicode.toUpper` for a version that works for any Unicode character. + if c in {'a'..'z'}: + result = chr(ord(c) - (ord('a') - ord('A'))) + else: + result = c + +proc toUpper*(s: string): string {.noSideEffect, procvar, + rtl, extern: "nsuToUpperStr".} = + ## Converts `s` into upper case. This works only for the letters a-z. + ## See `unicode.toUpper` for a version that works for any Unicode character. + result = newString(len(s)) + for i in 0..len(s) - 1: + result[i] = toUpper(s[i]) + +proc capitalize*(s: string): string {.noSideEffect, procvar, + rtl, extern: "nsuCapitalize".} = + ## Converts the first character of `s` into upper case. + ## This works only for the letters a-z. + result = toUpper(s[0]) & substr(s, 1) + +proc normalize*(s: string): string {.noSideEffect, procvar, + rtl, extern: "nsuNormalize".} = + ## Normalizes the string `s`. That means to convert it to lower case and + ## remove any '_'. This is needed for Nimrod identifiers for example. + result = newString(s.len) + var j = 0 + for i in 0..len(s) - 1: + if s[i] in {'A'..'Z'}: + result[j] = chr(ord(s[i]) + (ord('a') - ord('A'))) + inc j + elif s[i] != '_': + result[j] = s[i] + inc j + if j != s.len: setLen(result, j) + +proc cmpIgnoreCase*(a, b: string): int {.noSideEffect, + rtl, extern: "nsuCmpIgnoreCase", procvar, operator: 4.} = + ## Compares two strings in a case insensitive manner. Returns: + ## + ## | 0 iff a == b + ## | < 0 iff a < b + ## | > 0 iff a > b + var i = 0 + var m = min(a.len, b.len) + while i < m: + result = ord(toLower(a[i])) - ord(toLower(b[i])) + if result != 0: return + inc(i) + result = a.len - b.len + +{.push checks: off, line_trace: off .} # this is a hot-spot in the compiler! + # thus we compile without checks here + +proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect, + rtl, extern: "nsuCmpIgnoreStyle", procvar, operator: 3.} = + ## Compares two strings normalized (i.e. case and + ## underscores do not matter). Returns: + ## + ## | 0 iff a == b + ## | < 0 iff a < b + ## | > 0 iff a > b + var i = 0 + var j = 0 + while true: + while a[i] == '_': inc(i) + while b[j] == '_': inc(j) # BUGFIX: typo + var aa = toLower(a[i]) + var bb = toLower(b[j]) + result = ord(aa) - ord(bb) + if result != 0 or aa == '\0': break + inc(i) + inc(j) + +{.pop.} + +proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect, + rtl, extern: "nsuStrip", operator: 5.} = + ## Strips whitespace from `s` and returns the resulting string. + ## If `leading` is true, leading whitespace is stripped. + ## If `trailing` is true, trailing whitespace is stripped. + const + chars: set[char] = Whitespace + var + first = 0 + last = len(s)-1 + if leading: + while s[first] in chars: inc(first) + if trailing: + while last >= 0 and s[last] in chars: dec(last) + result = substr(s, first, last) + +proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} = + ## Converts a character `c` to its octal representation. The resulting + ## string may not have a leading zero. Its length is always exactly 3. + result = newString(3) + var val = ord(c) + for i in countdown(2, 0): + result[i] = chr(val mod 8 + ord('0')) + val = val div 8 + iterator split*(s: string, seps: set[char] = Whitespace): string = ## Splits the string `s` into substrings using a group of separators. ## @@ -209,199 +209,199 @@ iterator split*(s: string, seps: set[char] = Whitespace): string = ## "08" ## "08.398990" ## - var last = 0 - assert(not ('\0' in seps)) - while last < len(s): - while s[last] in seps: inc(last) - var first = last - while last < len(s) and s[last] not_in seps: inc(last) # BUGFIX! - if first <= last-1: - yield substr(s, first, last-1) - -iterator split*(s: string, sep: char): string = - ## Splits the string `s` into substrings using a single separator. - ## - ## Substrings are separated by the character `sep`. - ## Unlike the version of the iterator which accepts a set of separator - ## characters, this proc will not coalesce groups of the - ## separator, returning a string for each found character. The code: - ## - ## .. code-block:: nimrod - ## for word in split(";;this;is;an;;example;;;", ';'): - ## writeln(stdout, word) - ## - ## Results in: - ## - ## .. code-block:: - ## "" - ## "" - ## "this" - ## "is" - ## "an" - ## "" - ## "example" - ## "" - ## "" - ## "" - ## - var last = 0 - assert('\0' != sep) - if len(s) > 0: - # `<=` is correct here for the edge cases! - while last <= len(s): - var first = last - while last < len(s) and s[last] != sep: inc(last) - yield substr(s, first, last-1) - inc(last) - -iterator splitLines*(s: string): string = - ## Splits the string `s` into its containing lines. Every newline - ## combination (CR, LF, CR-LF) is supported. The result strings contain - ## no trailing ``\n``. - ## - ## Example: - ## - ## .. code-block:: nimrod - ## for line in splitLines("\nthis\nis\nan\n\nexample\n"): - ## writeln(stdout, line) - ## - ## Results in: - ## - ## .. code-block:: nimrod - ## "" - ## "this" - ## "is" - ## "an" - ## "" - ## "example" - ## "" - var first = 0 - var last = 0 - while true: - while s[last] notin {'\0', '\c', '\l'}: inc(last) - yield substr(s, first, last-1) - # skip newlines: - if s[last] == '\l': inc(last) - elif s[last] == '\c': - inc(last) - if s[last] == '\l': inc(last) - else: break # was '\0' - first = last - -proc splitLines*(s: string): seq[string] {.noSideEffect, - rtl, extern: "nsuSplitLines".} = - ## The same as the `splitLines` iterator, but is a proc that returns a - ## sequence of substrings. - accumulateResult(splitLines(s)) - -proc countLines*(s: string): int {.noSideEffect, - rtl, extern: "nsuCountLines".} = - ## same as ``len(splitLines(s))``, but much more efficient. - var i = 0 - while i < s.len: - case s[i] - of '\c': - if s[i+1] == '\l': inc i - inc result - of '\l': inc result - else: nil - inc i - -proc split*(s: string, seps: set[char] = Whitespace): seq[string] {. - noSideEffect, rtl, extern: "nsuSplitCharSet".} = - ## The same as the `split` iterator, but is a proc that returns a - ## sequence of substrings. - accumulateResult(split(s, seps)) - -proc split*(s: string, sep: char): seq[string] {.noSideEffect, - rtl, extern: "nsuSplitChar".} = - ## The same as the `split` iterator, but is a proc that returns a sequence - ## of substrings. - accumulateResult(split(s, sep)) - -proc toHex*(x: BiggestInt, len: int): string {.noSideEffect, - rtl, extern: "nsuToHex".} = - ## Converts `x` to its hexadecimal representation. The resulting string - ## will be exactly `len` characters long. No prefix like ``0x`` - ## is generated. `x` is treated as an unsigned value. - const - HexChars = "0123456789ABCDEF" - var - shift: BiggestInt - result = newString(len) - for j in countdown(len-1, 0): - result[j] = HexChars[toU32(x shr shift) and 0xF'i32] - shift = shift + 4 - -proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect, - rtl, extern: "nsuIntToStr".} = - ## Converts `x` to its decimal representation. The resulting string - ## will be minimally `minchars` characters long. This is achieved by - ## adding leading zeros. - result = $abs(x) - for i in 1 .. minchars - len(result): - result = '0' & result - if x < 0: - result = '-' & result - -proc ParseInt*(s: string): int {.noSideEffect, procvar, - rtl, extern: "nsuParseInt".} = - ## Parses a decimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. - var L = parseutils.parseInt(s, result, 0) - if L != s.len or L == 0: - raise newException(EInvalidValue, "invalid integer: " & s) - -proc ParseBiggestInt*(s: string): biggestInt {.noSideEffect, procvar, - rtl, extern: "nsuParseBiggestInt".} = - ## Parses a decimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. - var L = parseutils.parseBiggestInt(s, result, 0) - if L != s.len or L == 0: - raise newException(EInvalidValue, "invalid integer: " & s) - -proc ParseFloat*(s: string): float {.noSideEffect, procvar, - rtl, extern: "nsuParseFloat".} = - ## Parses a decimal floating point value contained in `s`. If `s` is not - ## a valid floating point number, `EInvalidValue` is raised. ``NAN``, - ## ``INF``, ``-INF`` are also supported (case insensitive comparison). - var L = parseutils.parseFloat(s, result, 0) - if L != s.len or L == 0: - raise newException(EInvalidValue, "invalid float: " & s) - -proc ParseHexInt*(s: string): int {.noSideEffect, procvar, - rtl, extern: "nsuParseHexInt".} = - ## Parses a hexadecimal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. `s` can have one of the - ## following optional prefixes: ``0x``, ``0X``, ``#``. - ## Underscores within `s` are ignored. - var i = 0 - if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2) - elif s[i] == '#': inc(i) - while true: - case s[i] - of '_': inc(i) - of '0'..'9': - result = result shl 4 or (ord(s[i]) - ord('0')) - inc(i) - of 'a'..'f': - result = result shl 4 or (ord(s[i]) - ord('a') + 10) - inc(i) - of 'A'..'F': - result = result shl 4 or (ord(s[i]) - ord('A') + 10) - inc(i) - of '\0': break - else: raise newException(EInvalidValue, "invalid integer: " & s) - -proc parseBool*(s: string): bool = - ## Parses a value into a `bool`. If ``s`` is one of the following values: - ## ``y, yes, true, 1, on``, then returns `true`. If ``s`` is one of the - ## following values: ``n, no, false, 0, off``, then returns `false`. - ## If ``s`` is something else a ``EInvalidValue`` exception is raised. - case normalize(s) - of "y", "yes", "true", "1", "on": result = true - of "n", "no", "false", "0", "off": result = false - else: raise newException(EInvalidValue, "cannot interpret as a bool: " & s) + var last = 0 + assert(not ('\0' in seps)) + while last < len(s): + while s[last] in seps: inc(last) + var first = last + while last < len(s) and s[last] notin seps: inc(last) # BUGFIX! + if first <= last-1: + yield substr(s, first, last-1) + +iterator split*(s: string, sep: char): string = + ## Splits the string `s` into substrings using a single separator. + ## + ## Substrings are separated by the character `sep`. + ## Unlike the version of the iterator which accepts a set of separator + ## characters, this proc will not coalesce groups of the + ## separator, returning a string for each found character. The code: + ## + ## .. code-block:: nimrod + ## for word in split(";;this;is;an;;example;;;", ';'): + ## writeln(stdout, word) + ## + ## Results in: + ## + ## .. code-block:: + ## "" + ## "" + ## "this" + ## "is" + ## "an" + ## "" + ## "example" + ## "" + ## "" + ## "" + ## + var last = 0 + assert('\0' != sep) + if len(s) > 0: + # `<=` is correct here for the edge cases! + while last <= len(s): + var first = last + while last < len(s) and s[last] != sep: inc(last) + yield substr(s, first, last-1) + inc(last) + +iterator splitLines*(s: string): string = + ## Splits the string `s` into its containing lines. Every newline + ## combination (CR, LF, CR-LF) is supported. The result strings contain + ## no trailing ``\n``. + ## + ## Example: + ## + ## .. code-block:: nimrod + ## for line in splitLines("\nthis\nis\nan\n\nexample\n"): + ## writeln(stdout, line) + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## "" + ## "this" + ## "is" + ## "an" + ## "" + ## "example" + ## "" + var first = 0 + var last = 0 + while true: + while s[last] notin {'\0', '\c', '\l'}: inc(last) + yield substr(s, first, last-1) + # skip newlines: + if s[last] == '\l': inc(last) + elif s[last] == '\c': + inc(last) + if s[last] == '\l': inc(last) + else: break # was '\0' + first = last + +proc splitLines*(s: string): seq[string] {.noSideEffect, + rtl, extern: "nsuSplitLines".} = + ## The same as the `splitLines` iterator, but is a proc that returns a + ## sequence of substrings. + accumulateResult(splitLines(s)) + +proc countLines*(s: string): int {.noSideEffect, + rtl, extern: "nsuCountLines".} = + ## same as ``len(splitLines(s))``, but much more efficient. + var i = 0 + while i < s.len: + case s[i] + of '\c': + if s[i+1] == '\l': inc i + inc result + of '\l': inc result + else: discard + inc i + +proc split*(s: string, seps: set[char] = Whitespace): seq[string] {. + noSideEffect, rtl, extern: "nsuSplitCharSet".} = + ## The same as the `split` iterator, but is a proc that returns a + ## sequence of substrings. + accumulateResult(split(s, seps)) + +proc split*(s: string, sep: char): seq[string] {.noSideEffect, + rtl, extern: "nsuSplitChar".} = + ## The same as the `split` iterator, but is a proc that returns a sequence + ## of substrings. + accumulateResult(split(s, sep)) + +proc toHex*(x: BiggestInt, len: int): string {.noSideEffect, + rtl, extern: "nsuToHex".} = + ## Converts `x` to its hexadecimal representation. The resulting string + ## will be exactly `len` characters long. No prefix like ``0x`` + ## is generated. `x` is treated as an unsigned value. + const + HexChars = "0123456789ABCDEF" + var + shift: BiggestInt + result = newString(len) + for j in countdown(len-1, 0): + result[j] = HexChars[toU32(x shr shift) and 0xF'i32] + shift = shift + 4 + +proc intToStr*(x: int, minchars: int = 1): string {.noSideEffect, + rtl, extern: "nsuIntToStr".} = + ## Converts `x` to its decimal representation. The resulting string + ## will be minimally `minchars` characters long. This is achieved by + ## adding leading zeros. + result = $abs(x) + for i in 1 .. minchars - len(result): + result = '0' & result + if x < 0: + result = '-' & result + +proc parseInt*(s: string): int {.noSideEffect, procvar, + rtl, extern: "nsuParseInt".} = + ## Parses a decimal integer value contained in `s`. If `s` is not + ## a valid integer, `EInvalidValue` is raised. + var L = parseutils.parseInt(s, result, 0) + if L != s.len or L == 0: + raise newException(EInvalidValue, "invalid integer: " & s) + +proc parseBiggestInt*(s: string): BiggestInt {.noSideEffect, procvar, + rtl, extern: "nsuParseBiggestInt".} = + ## Parses a decimal integer value contained in `s`. If `s` is not + ## a valid integer, `EInvalidValue` is raised. + var L = parseutils.parseBiggestInt(s, result, 0) + if L != s.len or L == 0: + raise newException(EInvalidValue, "invalid integer: " & s) + +proc parseFloat*(s: string): float {.noSideEffect, procvar, + rtl, extern: "nsuParseFloat".} = + ## Parses a decimal floating point value contained in `s`. If `s` is not + ## a valid floating point number, `EInvalidValue` is raised. ``NAN``, + ## ``INF``, ``-INF`` are also supported (case insensitive comparison). + var L = parseutils.parseFloat(s, result, 0) + if L != s.len or L == 0: + raise newException(EInvalidValue, "invalid float: " & s) + +proc parseHexInt*(s: string): int {.noSideEffect, procvar, + rtl, extern: "nsuParseHexInt".} = + ## Parses a hexadecimal integer value contained in `s`. If `s` is not + ## a valid integer, `EInvalidValue` is raised. `s` can have one of the + ## following optional prefixes: ``0x``, ``0X``, ``#``. + ## Underscores within `s` are ignored. + var i = 0 + if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2) + elif s[i] == '#': inc(i) + while true: + case s[i] + of '_': inc(i) + of '0'..'9': + result = result shl 4 or (ord(s[i]) - ord('0')) + inc(i) + of 'a'..'f': + result = result shl 4 or (ord(s[i]) - ord('a') + 10) + inc(i) + of 'A'..'F': + result = result shl 4 or (ord(s[i]) - ord('A') + 10) + inc(i) + of '\0': break + else: raise newException(EInvalidValue, "invalid integer: " & s) + +proc parseBool*(s: string): bool = + ## Parses a value into a `bool`. If ``s`` is one of the following values: + ## ``y, yes, true, 1, on``, then returns `true`. If ``s`` is one of the + ## following values: ``n, no, false, 0, off``, then returns `false`. + ## If ``s`` is something else a ``EInvalidValue`` exception is raised. + case normalize(s) + of "y", "yes", "true", "1", "on": result = true + of "n", "no", "false", "0", "off": result = false + else: raise newException(EInvalidValue, "cannot interpret as a bool: " & s) proc parseEnum*[T: enum](s: string): T = ## parses an enum ``T``. Raises ``EInvalidValue`` for an invalid value in @@ -418,30 +418,30 @@ proc parseEnum*[T: enum](s: string, default: T): T = if cmpIgnoreStyle(s, $e) == 0: return e result = default - -proc repeatChar*(count: int, c: Char = ' '): string {.noSideEffect, - rtl, extern: "nsuRepeatChar".} = - ## Returns a string of length `count` consisting only of - ## the character `c`. You can use this proc to left align strings. Example: - ## - ## .. code-block:: nimrod - ## let - ## width = 15 - ## text1 = "Hello user!" - ## text2 = "This is a very long string" - ## echo text1 & repeatChar(max(0, width - text1.len)) & "|" - ## echo text2 & repeatChar(max(0, width - text2.len)) & "|" - result = newString(count) - for i in 0..count-1: result[i] = c - -proc repeatStr*(count: int, s: string): string {.noSideEffect, - rtl, extern: "nsuRepeatStr".} = - ## Returns `s` concatenated `count` times. - result = newStringOfCap(count*s.len) - for i in 0..count-1: result.add(s) - -proc align*(s: string, count: int, padding = ' '): string {. - noSideEffect, rtl, extern: "nsuAlignString".} = + +proc repeatChar*(count: int, c: char = ' '): string {.noSideEffect, + rtl, extern: "nsuRepeatChar".} = + ## Returns a string of length `count` consisting only of + ## the character `c`. You can use this proc to left align strings. Example: + ## + ## .. code-block:: nimrod + ## let + ## width = 15 + ## text1 = "Hello user!" + ## text2 = "This is a very long string" + ## echo text1 & repeatChar(max(0, width - text1.len)) & "|" + ## echo text2 & repeatChar(max(0, width - text2.len)) & "|" + result = newString(count) + for i in 0..count-1: result[i] = c + +proc repeatStr*(count: int, s: string): string {.noSideEffect, + rtl, extern: "nsuRepeatStr".} = + ## Returns `s` concatenated `count` times. + result = newStringOfCap(count*s.len) + for i in 0..count-1: result.add(s) + +proc align*(s: string, count: int, padding = ' '): string {. + noSideEffect, rtl, extern: "nsuAlignString".} = ## Aligns a string `s` with `padding`, so that is of length `count`. ## `padding` characters (by default spaces) are added before `s` resulting in ## right alignment. If ``s.len >= count``, no spaces are added and `s` is @@ -453,247 +453,247 @@ proc align*(s: string, count: int, padding = ' '): string {. ## assert align("a", 0) == "a" ## assert align("1232", 6) == " 1232" ## assert align("1232", 6, '#') == "##1232" - if s.len < count: - result = newString(count) - var spaces = count - s.len - for i in 0..spaces-1: result[i] = padding - for i in spaces..count-1: result[i] = s[i-spaces] - else: - result = s - -iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ - token: string, isSep: bool] = - ## Tokenizes the string `s` into substrings. - ## - ## Substrings are separated by a substring containing only `seps`. - ## Examples: - ## - ## .. code-block:: nimrod - ## for word in tokenize(" this is an example "): - ## writeln(stdout, word) - ## - ## Results in: - ## - ## .. code-block:: nimrod - ## (" ", true) - ## ("this", false) - ## (" ", true) - ## ("is", false) - ## (" ", true) - ## ("an", false) - ## (" ", true) - ## ("example", false) - ## (" ", true) - var i = 0 - while true: - var j = i - var isSep = s[j] in seps - while j < s.len and (s[j] in seps) == isSep: inc(j) - if j > i: - yield (substr(s, i, j-1), isSep) - else: - break - i = j - -proc wordWrap*(s: string, maxLineWidth = 80, - splitLongWords = true, - seps: set[char] = whitespace, - newLine = "\n"): string {. - noSideEffect, rtl, extern: "nsuWordWrap".} = - ## word wraps `s`. - result = newStringOfCap(s.len + s.len shr 6) - var SpaceLeft = maxLineWidth - for word, isSep in tokenize(s, seps): - if len(word) > SpaceLeft: - if splitLongWords and len(word) > maxLineWidth: - result.add(substr(word, 0, spaceLeft-1)) - var w = spaceLeft+1 - var wordLeft = len(word) - spaceLeft - while wordLeft > 0: - result.add(newLine) - var L = min(maxLineWidth, wordLeft) - SpaceLeft = maxLineWidth - L - result.add(substr(word, w, w+L-1)) - inc(w, L) - dec(wordLeft, L) - else: - SpaceLeft = maxLineWidth - len(Word) - result.add(newLine) - result.add(word) - else: - SpaceLeft = SpaceLeft - len(Word) - result.add(word) - -proc unindent*(s: string, eatAllIndent = false): string {. - noSideEffect, rtl, extern: "nsuUnindent".} = - ## unindents `s`. - result = newStringOfCap(s.len) - var i = 0 - var pattern = true - var indent = 0 - while s[i] == ' ': inc i - var level = if i == 0: -1 else: i - while i < s.len: - if s[i] == ' ': - if i > 0 and s[i-1] in {'\l', '\c'}: - pattern = true - indent = 0 - if pattern: - inc(indent) - if indent > level and not eatAllIndent: - result.add(s[i]) - if level < 0: level = indent - else: - # a space somewhere: do not delete - result.add(s[i]) - else: - pattern = false - result.add(s[i]) - inc i - -proc startsWith*(s, prefix: string): bool {.noSideEffect, - rtl, extern: "nsuStartsWith".} = - ## Returns true iff ``s`` starts with ``prefix``. - ## If ``prefix == ""`` true is returned. - var i = 0 - while true: - if prefix[i] == '\0': return true - if s[i] != prefix[i]: return false - inc(i) - -proc endsWith*(s, suffix: string): bool {.noSideEffect, - rtl, extern: "nsuEndsWith".} = - ## Returns true iff ``s`` ends with ``suffix``. - ## If ``suffix == ""`` true is returned. - var i = 0 - var j = len(s) - len(suffix) - while i+j <% s.len: - if s[i+j] != suffix[i]: return false - inc(i) - if suffix[i] == '\0': return true + if s.len < count: + result = newString(count) + let spaces = count - s.len + for i in 0..spaces-1: result[i] = padding + for i in spaces..count-1: result[i] = s[i-spaces] + else: + result = s + +iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[ + token: string, isSep: bool] = + ## Tokenizes the string `s` into substrings. + ## + ## Substrings are separated by a substring containing only `seps`. + ## Examples: + ## + ## .. code-block:: nimrod + ## for word in tokenize(" this is an example "): + ## writeln(stdout, word) + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## (" ", true) + ## ("this", false) + ## (" ", true) + ## ("is", false) + ## (" ", true) + ## ("an", false) + ## (" ", true) + ## ("example", false) + ## (" ", true) + var i = 0 + while true: + var j = i + var isSep = s[j] in seps + while j < s.len and (s[j] in seps) == isSep: inc(j) + if j > i: + yield (substr(s, i, j-1), isSep) + else: + break + i = j + +proc wordWrap*(s: string, maxLineWidth = 80, + splitLongWords = true, + seps: set[char] = Whitespace, + newLine = "\n"): string {. + noSideEffect, rtl, extern: "nsuWordWrap".} = + ## word wraps `s`. + result = newStringOfCap(s.len + s.len shr 6) + var spaceLeft = maxLineWidth + for word, isSep in tokenize(s, seps): + if len(word) > spaceLeft: + if splitLongWords and len(word) > maxLineWidth: + result.add(substr(word, 0, spaceLeft-1)) + var w = spaceLeft+1 + var wordLeft = len(word) - spaceLeft + while wordLeft > 0: + result.add(newLine) + var L = min(maxLineWidth, wordLeft) + spaceLeft = maxLineWidth - L + result.add(substr(word, w, w+L-1)) + inc(w, L) + dec(wordLeft, L) + else: + spaceLeft = maxLineWidth - len(word) + result.add(newLine) + result.add(word) + else: + spaceLeft = spaceLeft - len(word) + result.add(word) + +proc unindent*(s: string, eatAllIndent = false): string {. + noSideEffect, rtl, extern: "nsuUnindent".} = + ## unindents `s`. + result = newStringOfCap(s.len) + var i = 0 + var pattern = true + var indent = 0 + while s[i] == ' ': inc i + var level = if i == 0: -1 else: i + while i < s.len: + if s[i] == ' ': + if i > 0 and s[i-1] in {'\l', '\c'}: + pattern = true + indent = 0 + if pattern: + inc(indent) + if indent > level and not eatAllIndent: + result.add(s[i]) + if level < 0: level = indent + else: + # a space somewhere: do not delete + result.add(s[i]) + else: + pattern = false + result.add(s[i]) + inc i + +proc startsWith*(s, prefix: string): bool {.noSideEffect, + rtl, extern: "nsuStartsWith".} = + ## Returns true iff ``s`` starts with ``prefix``. + ## If ``prefix == ""`` true is returned. + var i = 0 + while true: + if prefix[i] == '\0': return true + if s[i] != prefix[i]: return false + inc(i) + +proc endsWith*(s, suffix: string): bool {.noSideEffect, + rtl, extern: "nsuEndsWith".} = + ## Returns true iff ``s`` ends with ``suffix``. + ## If ``suffix == ""`` true is returned. + var i = 0 + var j = len(s) - len(suffix) + while i+j <% s.len: + if s[i+j] != suffix[i]: return false + inc(i) + if suffix[i] == '\0': return true proc continuesWith*(s, substr: string, start: int): bool {.noSideEffect, rtl, extern: "nsuContinuesWith".} = - ## Returns true iff ``s`` continues with ``substr`` at position ``start``. - ## If ``substr == ""`` true is returned. - var i = 0 - while true: - if substr[i] == '\0': return true - if s[i+start] != substr[i]: return false - inc(i) - -proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, - inline.} = - ## A shorthand for: - ## - ## .. code-block:: nimrod - ## if dest.len > startLen: add(dest, sep) - ## - ## This is often useful for generating some code where the items need to - ## be *separated* by `sep`. `sep` is only added if `dest` is longer than - ## `startLen`. The following example creates a string describing - ## an array of integers: - ## - ## .. code-block:: nimrod - ## var arr = "[" - ## for x in items([2, 3, 5, 7, 11]): - ## addSep(arr, startLen=len("[")) - ## add(arr, $x) - ## add(arr, "]") - if dest.len > startLen: add(dest, sep) - -proc allCharsInSet*(s: string, theSet: TCharSet): bool = - ## returns true iff each character of `s` is in the set `theSet`. - for c in items(s): - if c notin theSet: return false - return true - -proc abbrev*(s: string, possibilities: openarray[string]): int = - ## returns the index of the first item in `possibilities` if not - ## ambiguous; -1 if no item has been found; -2 if multiple items - ## match. - result = -1 # none found - for i in 0..possibilities.len-1: - if possibilities[i].startsWith(s): - if possibilities[i] == s: - # special case: exact match shouldn't be ambiguous - return i - if result >= 0: return -2 # ambiguous - result = i - -# --------------------------------------------------------------------------- - -proc join*(a: openArray[string], sep: string): string {. - noSideEffect, rtl, extern: "nsuJoinSep".} = - ## concatenates all strings in `a` separating them with `sep`. - if len(a) > 0: - var L = sep.len * (a.len-1) - for i in 0..high(a): inc(L, a[i].len) - result = newStringOfCap(L) - add(result, a[0]) - for i in 1..high(a): - add(result, sep) - add(result, a[i]) - else: - result = "" - -proc join*(a: openArray[string]): string {. - noSideEffect, rtl, extern: "nsuJoin".} = - ## concatenates all strings in `a`. - if len(a) > 0: - var L = 0 - for i in 0..high(a): inc(L, a[i].len) - result = newStringOfCap(L) - for i in 0..high(a): add(result, a[i]) - else: - result = "" - -type - TSkipTable = array[Char, int] - -proc preprocessSub(sub: string, a: var TSkipTable) = - var m = len(sub) - for i in 0..0xff: a[chr(i)] = m+1 - for i in 0..m-1: a[sub[i]] = m-i - -proc findAux(s, sub: string, start: int, a: TSkipTable): int = - # fast "quick search" algorithm: - var - m = len(sub) - n = len(s) - # search: - var j = start - while j <= n - m: - block match: - for k in 0..m-1: - if sub[k] != s[k+j]: break match - return j - inc(j, a[s[j+m]]) - return -1 - -proc find*(s, sub: string, start: int = 0): int {.noSideEffect, - rtl, extern: "nsuFindStr", operator: 6.} = - ## Searches for `sub` in `s` starting at position `start`. Searching is - ## case-sensitive. If `sub` is not in `s`, -1 is returned. - var a {.noinit.}: TSkipTable - preprocessSub(sub, a) - result = findAux(s, sub, start, a) - -proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect, - rtl, extern: "nsuFindChar".} = - ## Searches for `sub` in `s` starting at position `start`. Searching is - ## case-sensitive. If `sub` is not in `s`, -1 is returned. - for i in start..len(s)-1: - if sub == s[i]: return i - return -1 - -proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect, - rtl, extern: "nsuFindCharSet".} = - ## Searches for `chars` in `s` starting at position `start`. If `s` contains - ## none of the characters in `chars`, -1 is returned. - for i in start..s.len-1: - if s[i] in chars: return i - return -1 + ## Returns true iff ``s`` continues with ``substr`` at position ``start``. + ## If ``substr == ""`` true is returned. + var i = 0 + while true: + if substr[i] == '\0': return true + if s[i+start] != substr[i]: return false + inc(i) + +proc addSep*(dest: var string, sep = ", ", startLen = 0) {.noSideEffect, + inline.} = + ## A shorthand for: + ## + ## .. code-block:: nimrod + ## if dest.len > startLen: add(dest, sep) + ## + ## This is often useful for generating some code where the items need to + ## be *separated* by `sep`. `sep` is only added if `dest` is longer than + ## `startLen`. The following example creates a string describing + ## an array of integers: + ## + ## .. code-block:: nimrod + ## var arr = "[" + ## for x in items([2, 3, 5, 7, 11]): + ## addSep(arr, startLen=len("[")) + ## add(arr, $x) + ## add(arr, "]") + if dest.len > startLen: add(dest, sep) + +proc allCharsInSet*(s: string, theSet: TCharSet): bool = + ## returns true iff each character of `s` is in the set `theSet`. + for c in items(s): + if c notin theSet: return false + return true + +proc abbrev*(s: string, possibilities: openArray[string]): int = + ## returns the index of the first item in `possibilities` if not + ## ambiguous; -1 if no item has been found; -2 if multiple items + ## match. + result = -1 # none found + for i in 0..possibilities.len-1: + if possibilities[i].startsWith(s): + if possibilities[i] == s: + # special case: exact match shouldn't be ambiguous + return i + if result >= 0: return -2 # ambiguous + result = i + +# --------------------------------------------------------------------------- + +proc join*(a: openArray[string], sep: string): string {. + noSideEffect, rtl, extern: "nsuJoinSep".} = + ## concatenates all strings in `a` separating them with `sep`. + if len(a) > 0: + var L = sep.len * (a.len-1) + for i in 0..high(a): inc(L, a[i].len) + result = newStringOfCap(L) + add(result, a[0]) + for i in 1..high(a): + add(result, sep) + add(result, a[i]) + else: + result = "" + +proc join*(a: openArray[string]): string {. + noSideEffect, rtl, extern: "nsuJoin".} = + ## concatenates all strings in `a`. + if len(a) > 0: + var L = 0 + for i in 0..high(a): inc(L, a[i].len) + result = newStringOfCap(L) + for i in 0..high(a): add(result, a[i]) + else: + result = "" + +type + TSkipTable = array[char, int] + +proc preprocessSub(sub: string, a: var TSkipTable) = + var m = len(sub) + for i in 0..0xff: a[chr(i)] = m+1 + for i in 0..m-1: a[sub[i]] = m-i + +proc findAux(s, sub: string, start: int, a: TSkipTable): int = + # fast "quick search" algorithm: + var + m = len(sub) + n = len(s) + # search: + var j = start + while j <= n - m: + block match: + for k in 0..m-1: + if sub[k] != s[k+j]: break match + return j + inc(j, a[s[j+m]]) + return -1 + +proc find*(s, sub: string, start: int = 0): int {.noSideEffect, + rtl, extern: "nsuFindStr", operator: 6.} = + ## Searches for `sub` in `s` starting at position `start`. Searching is + ## case-sensitive. If `sub` is not in `s`, -1 is returned. + var a {.noinit.}: TSkipTable + preprocessSub(sub, a) + result = findAux(s, sub, start, a) + +proc find*(s: string, sub: char, start: int = 0): int {.noSideEffect, + rtl, extern: "nsuFindChar".} = + ## Searches for `sub` in `s` starting at position `start`. Searching is + ## case-sensitive. If `sub` is not in `s`, -1 is returned. + for i in start..len(s)-1: + if sub == s[i]: return i + return -1 + +proc find*(s: string, chars: set[char], start: int = 0): int {.noSideEffect, + rtl, extern: "nsuFindCharSet".} = + ## Searches for `chars` in `s` starting at position `start`. If `s` contains + ## none of the characters in `chars`, -1 is returned. + for i in start..s.len-1: + if s[i] in chars: return i + return -1 proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = ## Searches for `sub` in `s` in reverse, starting at `start` and going @@ -708,180 +708,180 @@ proc rfind*(s, sub: string, start: int = -1): int {.noSideEffect.} = break if result != -1: return return -1 - + proc quoteIfContainsWhite*(s: string): string {.deprecated.} = - ## returns ``'"' & s & '"'`` if `s` contains a space and does not - ## start with a quote, else returns `s` + ## returns ``'"' & s & '"'`` if `s` contains a space and does not + ## start with a quote, else returns `s` ## DEPRECATED as it was confused for shell quoting function. ## For this application use osproc.quoteShell. - if find(s, {' ', '\t'}) >= 0 and s[0] != '"': - result = '"' & s & '"' - else: - result = s - -proc contains*(s: string, c: char): bool {.noSideEffect.} = - ## Same as ``find(s, c) >= 0``. - return find(s, c) >= 0 - -proc contains*(s, sub: string): bool {.noSideEffect.} = - ## Same as ``find(s, sub) >= 0``. - return find(s, sub) >= 0 - -proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} = - ## Same as ``find(s, chars) >= 0``. - return find(s, chars) >= 0 - -proc replace*(s, sub: string, by = ""): string {.noSideEffect, - rtl, extern: "nsuReplaceStr", operator: 1.} = - ## Replaces `sub` in `s` by the string `by`. - var a {.noinit.}: TSkipTable - result = "" - preprocessSub(sub, a) - var i = 0 - while true: - var j = findAux(s, sub, i, a) - if j < 0: break - add result, substr(s, i, j - 1) - add result, by - i = j + len(sub) - # copy the rest: - add result, substr(s, i) - -proc replace*(s: string, sub, by: char): string {.noSideEffect, - rtl, extern: "nsuReplaceChar".} = - ## optimized version for characters. - result = newString(s.len) - var i = 0 - while i < s.len: - if s[i] == sub: result[i] = by - else: result[i] = s[i] - inc(i) - -proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, - rtl, extern: "nsuReplaceWord".} = - ## Replaces `sub` in `s` by the string `by`. Each occurance of `sub` - ## has to be surrounded by word boundaries (comparable to ``\\w`` in - ## regular expressions), otherwise it is not replaced. - const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} - var a {.noinit.}: TSkipTable - result = "" - preprocessSub(sub, a) - var i = 0 - while true: - var j = findAux(s, sub, i, a) - if j < 0: break - # word boundary? - if (j == 0 or s[j-1] notin wordChars) and - (j+sub.len >= s.len or s[j+sub.len] notin wordChars): - add result, substr(s, i, j - 1) - add result, by - i = j + len(sub) - else: - add result, substr(s, i, j) - i = j + 1 - # copy the rest: - add result, substr(s, i) - -proc delete*(s: var string, first, last: int) {.noSideEffect, - rtl, extern: "nsuDelete".} = - ## Deletes in `s` the characters at position `first` .. `last`. This modifies - ## `s` itself, it does not return a copy. - var i = first - var j = last+1 - var newLen = len(s)-j+i - while i < newLen: - s[i] = s[j] - inc(i) - inc(j) - setlen(s, newLen) - -proc ParseOctInt*(s: string): int {.noSideEffect, - rtl, extern: "nsuParseOctInt".} = - ## Parses an octal integer value contained in `s`. If `s` is not - ## a valid integer, `EInvalidValue` is raised. `s` can have one of the - ## following optional prefixes: ``0o``, ``0O``. - ## Underscores within `s` are ignored. - var i = 0 - if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2) - while true: - case s[i] - of '_': inc(i) - of '0'..'7': - result = result shl 3 or (ord(s[i]) - ord('0')) - inc(i) - of '\0': break - else: raise newException(EInvalidValue, "invalid integer: " & s) - -proc toOct*(x: BiggestInt, len: int): string {.noSideEffect, - rtl, extern: "nsuToOct".} = - ## converts `x` into its octal representation. The resulting string is - ## always `len` characters long. No leading ``0o`` prefix is generated. - var - mask: BiggestInt = 7 - shift: BiggestInt = 0 - assert(len > 0) - result = newString(len) - for j in countdown(len-1, 0): - result[j] = chr(int((x and mask) shr shift) + ord('0')) - shift = shift + 3 - mask = mask shl 3 - -proc toBin*(x: BiggestInt, len: int): string {.noSideEffect, - rtl, extern: "nsuToBin".} = - ## converts `x` into its binary representation. The resulting string is - ## always `len` characters long. No leading ``0b`` prefix is generated. - var - mask: BiggestInt = 1 - shift: BiggestInt = 0 - assert(len > 0) - result = newString(len) - for j in countdown(len-1, 0): - result[j] = chr(int((x and mask) shr shift) + ord('0')) - shift = shift + 1 - mask = mask shl 1 - -proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect, - rtl, extern: "nsuInsertSep".} = - ## inserts the separator `sep` after `digits` digits from right to left. - ## Even though the algorithm works with any string `s`, it is only useful - ## if `s` contains a number. - ## Example: ``insertSep("1000000") == "1_000_000"`` - var L = (s.len-1) div digits + s.len - result = newString(L) - var j = 0 - dec(L) - for i in countdown(len(s)-1, 0): - if j == digits: - result[L] = sep - dec(L) - j = 0 - result[L] = s[i] - inc(j) - dec(L) - -proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, - rtl, extern: "nsuEscape".} = - ## Escapes a string `s`. This does these operations (at the same time): - ## * replaces any ``\`` by ``\\`` - ## * replaces any ``'`` by ``\'`` - ## * replaces any ``"`` by ``\"`` - ## * replaces any other character in the set ``{'\0'..'\31', '\128'..'\255'}`` - ## by ``\xHH`` where ``HH`` is its hexadecimal value. - ## The procedure has been designed so that its output is usable for many - ## different common syntaxes. The resulting string is prefixed with - ## `prefix` and suffixed with `suffix`. Both may be empty strings. - result = newStringOfCap(s.len + s.len shr 2) - result.add(prefix) - for c in items(s): - case c - of '\0'..'\31', '\128'..'\255': - add(result, "\\x") - add(result, toHex(ord(c), 2)) - of '\\': add(result, "\\\\") - of '\'': add(result, "\\'") - of '\"': add(result, "\\\"") - else: add(result, c) - add(result, suffix) + if find(s, {' ', '\t'}) >= 0 and s[0] != '"': + result = '"' & s & '"' + else: + result = s + +proc contains*(s: string, c: char): bool {.noSideEffect.} = + ## Same as ``find(s, c) >= 0``. + return find(s, c) >= 0 + +proc contains*(s, sub: string): bool {.noSideEffect.} = + ## Same as ``find(s, sub) >= 0``. + return find(s, sub) >= 0 + +proc contains*(s: string, chars: set[char]): bool {.noSideEffect.} = + ## Same as ``find(s, chars) >= 0``. + return find(s, chars) >= 0 + +proc replace*(s, sub: string, by = ""): string {.noSideEffect, + rtl, extern: "nsuReplaceStr", operator: 1.} = + ## Replaces `sub` in `s` by the string `by`. + var a {.noinit.}: TSkipTable + result = "" + preprocessSub(sub, a) + var i = 0 + while true: + var j = findAux(s, sub, i, a) + if j < 0: break + add result, substr(s, i, j - 1) + add result, by + i = j + len(sub) + # copy the rest: + add result, substr(s, i) + +proc replace*(s: string, sub, by: char): string {.noSideEffect, + rtl, extern: "nsuReplaceChar".} = + ## optimized version for characters. + result = newString(s.len) + var i = 0 + while i < s.len: + if s[i] == sub: result[i] = by + else: result[i] = s[i] + inc(i) + +proc replaceWord*(s, sub: string, by = ""): string {.noSideEffect, + rtl, extern: "nsuReplaceWord".} = + ## Replaces `sub` in `s` by the string `by`. Each occurance of `sub` + ## has to be surrounded by word boundaries (comparable to ``\\w`` in + ## regular expressions), otherwise it is not replaced. + const wordChars = {'a'..'z', 'A'..'Z', '0'..'9', '_', '\128'..'\255'} + var a {.noinit.}: TSkipTable + result = "" + preprocessSub(sub, a) + var i = 0 + while true: + var j = findAux(s, sub, i, a) + if j < 0: break + # word boundary? + if (j == 0 or s[j-1] notin wordChars) and + (j+sub.len >= s.len or s[j+sub.len] notin wordChars): + add result, substr(s, i, j - 1) + add result, by + i = j + len(sub) + else: + add result, substr(s, i, j) + i = j + 1 + # copy the rest: + add result, substr(s, i) + +proc delete*(s: var string, first, last: int) {.noSideEffect, + rtl, extern: "nsuDelete".} = + ## Deletes in `s` the characters at position `first` .. `last`. This modifies + ## `s` itself, it does not return a copy. + var i = first + var j = last+1 + var newLen = len(s)-j+i + while i < newLen: + s[i] = s[j] + inc(i) + inc(j) + setLen(s, newLen) + +proc parseOctInt*(s: string): int {.noSideEffect, + rtl, extern: "nsuParseOctInt".} = + ## Parses an octal integer value contained in `s`. If `s` is not + ## a valid integer, `EInvalidValue` is raised. `s` can have one of the + ## following optional prefixes: ``0o``, ``0O``. + ## Underscores within `s` are ignored. + var i = 0 + if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2) + while true: + case s[i] + of '_': inc(i) + of '0'..'7': + result = result shl 3 or (ord(s[i]) - ord('0')) + inc(i) + of '\0': break + else: raise newException(EInvalidValue, "invalid integer: " & s) + +proc toOct*(x: BiggestInt, len: int): string {.noSideEffect, + rtl, extern: "nsuToOct".} = + ## converts `x` into its octal representation. The resulting string is + ## always `len` characters long. No leading ``0o`` prefix is generated. + var + mask: BiggestInt = 7 + shift: BiggestInt = 0 + assert(len > 0) + result = newString(len) + for j in countdown(len-1, 0): + result[j] = chr(int((x and mask) shr shift) + ord('0')) + shift = shift + 3 + mask = mask shl 3 + +proc toBin*(x: BiggestInt, len: int): string {.noSideEffect, + rtl, extern: "nsuToBin".} = + ## converts `x` into its binary representation. The resulting string is + ## always `len` characters long. No leading ``0b`` prefix is generated. + var + mask: BiggestInt = 1 + shift: BiggestInt = 0 + assert(len > 0) + result = newString(len) + for j in countdown(len-1, 0): + result[j] = chr(int((x and mask) shr shift) + ord('0')) + shift = shift + 1 + mask = mask shl 1 + +proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect, + rtl, extern: "nsuInsertSep".} = + ## inserts the separator `sep` after `digits` digits from right to left. + ## Even though the algorithm works with any string `s`, it is only useful + ## if `s` contains a number. + ## Example: ``insertSep("1000000") == "1_000_000"`` + var L = (s.len-1) div digits + s.len + result = newString(L) + var j = 0 + dec(L) + for i in countdown(len(s)-1, 0): + if j == digits: + result[L] = sep + dec(L) + j = 0 + result[L] = s[i] + inc(j) + dec(L) + +proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, + rtl, extern: "nsuEscape".} = + ## Escapes a string `s`. This does these operations (at the same time): + ## * replaces any ``\`` by ``\\`` + ## * replaces any ``'`` by ``\'`` + ## * replaces any ``"`` by ``\"`` + ## * replaces any other character in the set ``{'\0'..'\31', '\128'..'\255'}`` + ## by ``\xHH`` where ``HH`` is its hexadecimal value. + ## The procedure has been designed so that its output is usable for many + ## different common syntaxes. The resulting string is prefixed with + ## `prefix` and suffixed with `suffix`. Both may be empty strings. + result = newStringOfCap(s.len + s.len shr 2) + result.add(prefix) + for c in items(s): + case c + of '\0'..'\31', '\128'..'\255': + add(result, "\\x") + add(result, toHex(ord(c), 2)) + of '\\': add(result, "\\\\") + of '\'': add(result, "\\'") + of '\"': add(result, "\\\"") + else: add(result, c) + add(result, suffix) proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, rtl, extern: "nsuUnescape".} = @@ -896,7 +896,7 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, raise newException(EInvalidValue, "String does not start with a prefix of: " & prefix) i.inc() - while True: + while true: if i == s.len-suffix.len: break case s[i] of '\\': @@ -920,323 +920,323 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect, if s[i .. -1] != suffix: raise newException(EInvalidValue, "String does not end with a suffix of: " & suffix) - -proc validIdentifier*(s: string): bool {.noSideEffect, - rtl, extern: "nsuValidIdentifier".} = - ## returns true if `s` is a valid identifier. A valid identifier starts - ## with a character of the set `IdentStartChars` and is followed by any - ## number of characters of the set `IdentChars`. - if s[0] in IdentStartChars: - for i in 1..s.len-1: - if s[i] notin IdentChars: return false - return true - -proc editDistance*(a, b: string): int {.noSideEffect, - rtl, extern: "nsuEditDistance".} = - ## returns the edit distance between `a` and `b`. This uses the - ## `Levenshtein`:idx: distance algorithm with only a linear memory overhead. - ## This implementation is highly optimized! - var len1 = a.len - var len2 = b.len - if len1 > len2: - # make `b` the longer string - return editDistance(b, a) - - # strip common prefix: - var s = 0 - while a[s] == b[s] and a[s] != '\0': - inc(s) - dec(len1) - dec(len2) - # strip common suffix: - while len1 > 0 and len2 > 0 and a[s+len1-1] == b[s+len2-1]: - dec(len1) - dec(len2) - # trivial cases: - if len1 == 0: return len2 - if len2 == 0: return len1 - - # another special case: - if len1 == 1: - for j in s..len2-1: - if a[s] == b[j]: return len2 - 1 - return len2 - - inc(len1) - inc(len2) - var half = len1 shr 1 - # initalize first row: - #var row = cast[ptr array[0..high(int) div 8, int]](alloc(len2*sizeof(int))) - var row: seq[int] - newSeq(row, len2) - var e = s + len2 - 1 # end marker - for i in 1..len2 - half - 1: row[i] = i - row[0] = len1 - half - 1 - for i in 1 .. len1 - 1: - var char1 = a[i + s - 1] - var char2p: int - var D, x: int - var p: int - if i >= len1 - half: - # skip the upper triangle: - var offset = i - len1 + half - char2p = offset - p = offset - var c3 = row[p] + ord(char1 != b[s + char2p]) - inc(p) - inc(char2p) - x = row[p] + 1 - D = x - if x > c3: x = c3 - row[p] = x - inc(p) - else: - p = 1 - char2p = 0 - D = i - x = i - if i <= half + 1: - # skip the lower triangle: - e = len2 + i - half - 2 - # main: - while p <= e: - dec(D) - var c3 = D + ord(char1 != b[char2p + s]) - inc(char2p) - inc(x) - if x > c3: x = c3 - D = row[p] + 1 - if x > D: x = D - row[p] = x - inc(p) - # lower triangle sentinel: - if i <= half: - dec(D) - var c3 = D + ord(char1 != b[char2p + s]) - inc(x) - if x > c3: x = c3 - row[p] = x - result = row[e] - #dealloc(row) - - -# floating point formating: - -proc c_sprintf(buf, frmt: CString) {.nodecl, importc: "sprintf", varargs, - noSideEffect.} - -type - TFloatFormat* = enum ## the different modes of floating point formating - ffDefault, ## use the shorter floating point notation - ffDecimal, ## use decimal floating point notation - ffScientific ## use scientific notation (using ``e`` character) - -proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, + +proc validIdentifier*(s: string): bool {.noSideEffect, + rtl, extern: "nsuValidIdentifier".} = + ## returns true if `s` is a valid identifier. A valid identifier starts + ## with a character of the set `IdentStartChars` and is followed by any + ## number of characters of the set `IdentChars`. + if s[0] in IdentStartChars: + for i in 1..s.len-1: + if s[i] notin IdentChars: return false + return true + +proc editDistance*(a, b: string): int {.noSideEffect, + rtl, extern: "nsuEditDistance".} = + ## returns the edit distance between `a` and `b`. This uses the + ## `Levenshtein`:idx: distance algorithm with only a linear memory overhead. + ## This implementation is highly optimized! + var len1 = a.len + var len2 = b.len + if len1 > len2: + # make `b` the longer string + return editDistance(b, a) + + # strip common prefix: + var s = 0 + while a[s] == b[s] and a[s] != '\0': + inc(s) + dec(len1) + dec(len2) + # strip common suffix: + while len1 > 0 and len2 > 0 and a[s+len1-1] == b[s+len2-1]: + dec(len1) + dec(len2) + # trivial cases: + if len1 == 0: return len2 + if len2 == 0: return len1 + + # another special case: + if len1 == 1: + for j in s..len2-1: + if a[s] == b[j]: return len2 - 1 + return len2 + + inc(len1) + inc(len2) + var half = len1 shr 1 + # initalize first row: + #var row = cast[ptr array[0..high(int) div 8, int]](alloc(len2*sizeof(int))) + var row: seq[int] + newSeq(row, len2) + var e = s + len2 - 1 # end marker + for i in 1..len2 - half - 1: row[i] = i + row[0] = len1 - half - 1 + for i in 1 .. len1 - 1: + var char1 = a[i + s - 1] + var char2p: int + var D, x: int + var p: int + if i >= len1 - half: + # skip the upper triangle: + var offset = i - len1 + half + char2p = offset + p = offset + var c3 = row[p] + ord(char1 != b[s + char2p]) + inc(p) + inc(char2p) + x = row[p] + 1 + D = x + if x > c3: x = c3 + row[p] = x + inc(p) + else: + p = 1 + char2p = 0 + D = i + x = i + if i <= half + 1: + # skip the lower triangle: + e = len2 + i - half - 2 + # main: + while p <= e: + dec(D) + var c3 = D + ord(char1 != b[char2p + s]) + inc(char2p) + inc(x) + if x > c3: x = c3 + D = row[p] + 1 + if x > D: x = D + row[p] = x + inc(p) + # lower triangle sentinel: + if i <= half: + dec(D) + var c3 = D + ord(char1 != b[char2p + s]) + inc(x) + if x > c3: x = c3 + row[p] = x + result = row[e] + #dealloc(row) + + +# floating point formating: + +proc c_sprintf(buf, frmt: cstring) {.header: "<stdio.h>", importc: "sprintf", + varargs, noSideEffect.} + +type + TFloatFormat* = enum ## the different modes of floating point formating + ffDefault, ## use the shorter floating point notation + ffDecimal, ## use decimal floating point notation + ffScientific ## use scientific notation (using ``e`` character) + +proc formatBiggestFloat*(f: BiggestFloat, format: TFloatFormat = ffDefault, precision: range[0..32] = 16): string {. - noSideEffect, operator: 2, rtl, extern: "nsu$1".} = - ## converts a floating point value `f` to a string. - ## - ## If ``format == ffDecimal`` then precision is the number of digits to - ## be printed after the decimal point. - ## If ``format == ffScientific`` then precision is the maximum number - ## of significant digits to be printed. - ## `precision`'s default value is the maximum number of meaningful digits + noSideEffect, operator: 2, rtl, extern: "nsu$1".} = + ## converts a floating point value `f` to a string. + ## + ## If ``format == ffDecimal`` then precision is the number of digits to + ## be printed after the decimal point. + ## If ``format == ffScientific`` then precision is the maximum number + ## of significant digits to be printed. + ## `precision`'s default value is the maximum number of meaningful digits ## after the decimal point for Nimrod's ``biggestFloat`` type. ## - ## If ``precision == 0``, it tries to format it nicely. - const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e'] - var - frmtstr {.noinit.}: array[0..5, char] - buf {.noinit.}: array[0..2500, char] - frmtstr[0] = '%' - if precision > 0: - frmtstr[1] = '#' - frmtstr[2] = '.' - frmtstr[3] = '*' - frmtstr[4] = floatFormatToChar[format] - frmtstr[5] = '\0' - c_sprintf(buf, frmtstr, precision, f) - else: - frmtstr[1] = floatFormatToChar[format] - frmtstr[2] = '\0' - c_sprintf(buf, frmtstr, f) - result = $buf - -proc formatFloat*(f: float, format: TFloatFormat = ffDefault, + ## If ``precision == 0``, it tries to format it nicely. + const floatFormatToChar: array[TFloatFormat, char] = ['g', 'f', 'e'] + var + frmtstr {.noinit.}: array[0..5, char] + buf {.noinit.}: array[0..2500, char] + frmtstr[0] = '%' + if precision > 0: + frmtstr[1] = '#' + frmtstr[2] = '.' + frmtstr[3] = '*' + frmtstr[4] = floatFormatToChar[format] + frmtstr[5] = '\0' + c_sprintf(buf, frmtstr, precision, f) + else: + frmtstr[1] = floatFormatToChar[format] + frmtstr[2] = '\0' + c_sprintf(buf, frmtstr, f) + result = $buf + +proc formatFloat*(f: float, format: TFloatFormat = ffDefault, precision: range[0..32] = 16): string {. - noSideEffect, operator: 2, rtl, extern: "nsu$1".} = - ## converts a floating point value `f` to a string. - ## - ## If ``format == ffDecimal`` then precision is the number of digits to - ## be printed after the decimal point. - ## If ``format == ffScientific`` then precision is the maximum number - ## of significant digits to be printed. - ## `precision`'s default value is the maximum number of meaningful digits - ## after the decimal point for Nimrod's ``float`` type. - result = formatBiggestFloat(f, format, precision) - -proc formatSize*(bytes: biggestInt, decimalSep = '.'): string = - ## Rounds and formats `bytes`. Examples: - ## - ## .. code-block:: nimrod - ## - ## formatSize(1'i64 shl 31 + 300'i64) == "2.204GB" - ## formatSize(4096) == "4KB" - ## - template frmt(a, b, c: expr): expr = - let bs = $b - insertSep($a) & decimalSep & bs.substr(0, 2) & c - let gigabytes = bytes shr 30 - let megabytes = bytes shr 20 - let kilobytes = bytes shr 10 - if gigabytes != 0: - result = frmt(gigabytes, megabytes, "GB") - elif megabytes != 0: - result = frmt(megabytes, kilobytes, "MB") - elif kilobytes != 0: - result = frmt(kilobytes, bytes, "KB") - else: - result = insertSep($bytes) & "B" - -proc findNormalized(x: string, inArray: openarray[string]): int = - var i = 0 - while i < high(inArray): - if cmpIgnoreStyle(x, inArray[i]) == 0: return i - inc(i, 2) # incrementing by 1 would probably lead to a - # security hole... - return -1 - -proc invalidFormatString() {.noinline.} = - raise newException(EInvalidValue, "invalid format string") - -proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {. - noSideEffect, rtl, extern: "nsuAddf".} = - ## The same as ``add(s, formatstr % a)``, but more efficient. - const PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'} - var i = 0 - var num = 0 - while i < len(formatstr): - if formatstr[i] == '$': - case formatstr[i+1] # again we use the fact that strings - # are zero-terminated here - of '#': - if num >% a.high: invalidFormatString() - add s, a[num] - inc i, 2 - inc num - of '$': - add s, '$' - inc(i, 2) - of '1'..'9', '-': - var j = 0 - inc(i) # skip $ - var negative = formatstr[i] == '-' - if negative: inc i - while formatstr[i] in Digits: - j = j * 10 + ord(formatstr[i]) - ord('0') - inc(i) - let idx = if not negative: j-1 else: a.len-j - if idx >% a.high: invalidFormatString() - add s, a[idx] - of '{': - var j = i+1 - while formatstr[j] notin {'\0', '}'}: inc(j) - var x = findNormalized(substr(formatstr, i+2, j-1), a) - if x >= 0 and x < high(a): add s, a[x+1] - else: invalidFormatString() - i = j+1 - of 'a'..'z', 'A'..'Z', '\128'..'\255', '_': - var j = i+1 - while formatstr[j] in PatternChars: inc(j) - var x = findNormalized(substr(formatstr, i+1, j-1), a) - if x >= 0 and x < high(a): add s, a[x+1] - else: invalidFormatString() - i = j - else: - invalidFormatString() - else: - add s, formatstr[i] - inc(i) - -proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect, - rtl, extern: "nsuFormatOpenArray".} = - ## The `substitution`:idx: operator performs string substitutions in - ## `formatstr` and returns a modified `formatstr`. This is often called - ## `string interpolation`:idx:. - ## - ## This is best explained by an example: - ## - ## .. code-block:: nimrod - ## "$1 eats $2." % ["The cat", "fish"] - ## - ## Results in: - ## - ## .. code-block:: nimrod - ## "The cat eats fish." - ## - ## The substitution variables (the thing after the ``$``) are enumerated - ## from 1 to ``a.len``. - ## To produce a verbatim ``$``, use ``$$``. - ## The notation ``$#`` can be used to refer to the next substitution - ## variable: - ## - ## .. code-block:: nimrod - ## "$# eats $#." % ["The cat", "fish"] - ## - ## Substitution variables can also be words (that is - ## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even - ## indices are keys and with odd indices are the corresponding values. - ## An example: - ## - ## .. code-block:: nimrod - ## "$animal eats $food." % ["animal", "The cat", "food", "fish"] - ## - ## Results in: - ## - ## .. code-block:: nimrod - ## "The cat eats fish." - ## - ## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is - ## raised if an ill-formed format string has been passed to the `%` operator. - result = newStringOfCap(formatstr.len + a.len shl 4) - addf(result, formatstr, a) - -proc `%` *(formatstr, a: string): string {.noSideEffect, - rtl, extern: "nsuFormatSingleElem".} = - ## This is the same as ``formatstr % [a]``. - result = newStringOfCap(formatstr.len + a.len) - addf(result, formatstr, [a]) - -proc format*(formatstr: string, a: varargs[string, `$`]): string {.noSideEffect, - rtl, extern: "nsuFormatVarargs".} = + noSideEffect, operator: 2, rtl, extern: "nsu$1".} = + ## converts a floating point value `f` to a string. + ## + ## If ``format == ffDecimal`` then precision is the number of digits to + ## be printed after the decimal point. + ## If ``format == ffScientific`` then precision is the maximum number + ## of significant digits to be printed. + ## `precision`'s default value is the maximum number of meaningful digits + ## after the decimal point for Nimrod's ``float`` type. + result = formatBiggestFloat(f, format, precision) + +proc formatSize*(bytes: BiggestInt, decimalSep = '.'): string = + ## Rounds and formats `bytes`. Examples: + ## + ## .. code-block:: nimrod + ## + ## formatSize(1'i64 shl 31 + 300'i64) == "2.204GB" + ## formatSize(4096) == "4KB" + ## + template frmt(a, b, c: expr): expr = + let bs = $b + insertSep($a) & decimalSep & bs.substr(0, 2) & c + let gigabytes = bytes shr 30 + let megabytes = bytes shr 20 + let kilobytes = bytes shr 10 + if gigabytes != 0: + result = frmt(gigabytes, megabytes, "GB") + elif megabytes != 0: + result = frmt(megabytes, kilobytes, "MB") + elif kilobytes != 0: + result = frmt(kilobytes, bytes, "KB") + else: + result = insertSep($bytes) & "B" + +proc findNormalized(x: string, inArray: openArray[string]): int = + var i = 0 + while i < high(inArray): + if cmpIgnoreStyle(x, inArray[i]) == 0: return i + inc(i, 2) # incrementing by 1 would probably lead to a + # security hole... + return -1 + +proc invalidFormatString() {.noinline.} = + raise newException(EInvalidValue, "invalid format string") + +proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {. + noSideEffect, rtl, extern: "nsuAddf".} = + ## The same as ``add(s, formatstr % a)``, but more efficient. + const PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\128'..'\255', '_'} + var i = 0 + var num = 0 + while i < len(formatstr): + if formatstr[i] == '$': + case formatstr[i+1] # again we use the fact that strings + # are zero-terminated here + of '#': + if num >% a.high: invalidFormatString() + add s, a[num] + inc i, 2 + inc num + of '$': + add s, '$' + inc(i, 2) + of '1'..'9', '-': + var j = 0 + inc(i) # skip $ + var negative = formatstr[i] == '-' + if negative: inc i + while formatstr[i] in Digits: + j = j * 10 + ord(formatstr[i]) - ord('0') + inc(i) + let idx = if not negative: j-1 else: a.len-j + if idx >% a.high: invalidFormatString() + add s, a[idx] + of '{': + var j = i+1 + while formatstr[j] notin {'\0', '}'}: inc(j) + var x = findNormalized(substr(formatstr, i+2, j-1), a) + if x >= 0 and x < high(a): add s, a[x+1] + else: invalidFormatString() + i = j+1 + of 'a'..'z', 'A'..'Z', '\128'..'\255', '_': + var j = i+1 + while formatstr[j] in PatternChars: inc(j) + var x = findNormalized(substr(formatstr, i+1, j-1), a) + if x >= 0 and x < high(a): add s, a[x+1] + else: invalidFormatString() + i = j + else: + invalidFormatString() + else: + add s, formatstr[i] + inc(i) + +proc `%` *(formatstr: string, a: openArray[string]): string {.noSideEffect, + rtl, extern: "nsuFormatOpenArray".} = + ## The `substitution`:idx: operator performs string substitutions in + ## `formatstr` and returns a modified `formatstr`. This is often called + ## `string interpolation`:idx:. + ## + ## This is best explained by an example: + ## + ## .. code-block:: nimrod + ## "$1 eats $2." % ["The cat", "fish"] + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## "The cat eats fish." + ## + ## The substitution variables (the thing after the ``$``) are enumerated + ## from 1 to ``a.len``. + ## To produce a verbatim ``$``, use ``$$``. + ## The notation ``$#`` can be used to refer to the next substitution + ## variable: + ## + ## .. code-block:: nimrod + ## "$# eats $#." % ["The cat", "fish"] + ## + ## Substitution variables can also be words (that is + ## ``[A-Za-z_]+[A-Za-z0-9_]*``) in which case the arguments in `a` with even + ## indices are keys and with odd indices are the corresponding values. + ## An example: + ## + ## .. code-block:: nimrod + ## "$animal eats $food." % ["animal", "The cat", "food", "fish"] + ## + ## Results in: + ## + ## .. code-block:: nimrod + ## "The cat eats fish." + ## + ## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is + ## raised if an ill-formed format string has been passed to the `%` operator. + result = newStringOfCap(formatstr.len + a.len shl 4) + addf(result, formatstr, a) + +proc `%` *(formatstr, a: string): string {.noSideEffect, + rtl, extern: "nsuFormatSingleElem".} = + ## This is the same as ``formatstr % [a]``. + result = newStringOfCap(formatstr.len + a.len) + addf(result, formatstr, [a]) + +proc format*(formatstr: string, a: varargs[string, `$`]): string {.noSideEffect, + rtl, extern: "nsuFormatVarargs".} = ## This is the same as ``formatstr % a`` except that it supports - ## auto stringification. - result = newStringOfCap(formatstr.len + a.len) - addf(result, formatstr, a) - -{.pop.} - -when isMainModule: - doAssert align("abc", 4) == " abc" - doAssert align("a", 0) == "a" - doAssert align("1232", 6) == " 1232" - doAssert align("1232", 6, '#') == "##1232" - echo wordWrap(""" this is a long text -- muchlongerthan10chars and here - it goes""", 10, false) - doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001" - doAssert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11" - - doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c" - echo formatSize(1'i64 shl 31 + 300'i64) # == "4,GB" - echo formatSize(1'i64 shl 31) - - doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] == - "The cat eats fish." - - doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz " - doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc" + ## auto stringification. + result = newStringOfCap(formatstr.len + a.len) + addf(result, formatstr, a) + +{.pop.} + +when isMainModule: + doAssert align("abc", 4) == " abc" + doAssert align("a", 0) == "a" + doAssert align("1232", 6) == " 1232" + doAssert align("1232", 6, '#') == "##1232" + echo wordWrap(""" this is a long text -- muchlongerthan10chars and here + it goes""", 10, false) + doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001" + doAssert formatBiggestFloat(0.00000000001, ffScientific, 1) == "1.0e-11" + + doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c" + echo formatSize(1'i64 shl 31 + 300'i64) # == "4,GB" + echo formatSize(1'i64 shl 31) + + doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] == + "The cat eats fish." + + doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz " + doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc" - type TMyEnum = enum enA, enB, enC, enuD, enE - doAssert parseEnum[TMyEnum]("enu_D") == enuD + type TMyEnum = enum enA, enB, enC, enuD, enE + doAssert parseEnum[TMyEnum]("enu_D") == enuD - doAssert parseEnum("invalid enum value", enC) == enC + doAssert parseEnum("invalid enum value", enC) == enC diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 501184aca..20f1d0695 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -27,15 +27,15 @@ when defined(windows): var hTemp = GetStdHandle(STD_OUTPUT_HANDLE) if DuplicateHandle(GetCurrentProcess(), hTemp, GetCurrentProcess(), addr(conHandle), 0, 1, DUPLICATE_SAME_ACCESS) == 0: - OSError(OSLastError()) + osError(osLastError()) proc getCursorPos(): tuple [x,y: int] = - var c: TCONSOLE_SCREEN_BUFFER_INFO - if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: OSError(OSLastError()) + var c: TCONSOLESCREENBUFFERINFO + if GetConsoleScreenBufferInfo(conHandle, addr(c)) == 0: osError(osLastError()) return (int(c.dwCursorPosition.x), int(c.dwCursorPosition.y)) proc getAttributes(): int16 = - var c: TCONSOLE_SCREEN_BUFFER_INFO + var c: TCONSOLESCREENBUFFERINFO # workaround Windows bugs: try several times if GetConsoleScreenBufferInfo(conHandle, addr(c)) != 0: return c.wAttributes @@ -48,10 +48,10 @@ proc setCursorPos*(x, y: int) = ## sets the terminal's cursor to the (x,y) position. (0,0) is the ## upper left of the screen. when defined(windows): - var c: TCoord + var c: TCOORD c.x = int16(x) c.y = int16(y) - if SetConsoleCursorPosition(conHandle, c) == 0: OSError(OSLastError()) + if SetConsoleCursorPosition(conHandle, c) == 0: osError(osLastError()) else: stdout.write("\e[" & $y & ';' & $x & 'f') @@ -59,12 +59,12 @@ proc setCursorXPos*(x: int) = ## sets the terminal's cursor to the x position. The y position is ## not changed. when defined(windows): - var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO + var scrbuf: TCONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) var origin = scrbuf.dwCursorPosition origin.x = int16(x) - if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) else: stdout.write("\e[" & $x & 'G') @@ -73,16 +73,16 @@ when defined(windows): ## sets the terminal's cursor to the y position. The x position is ## not changed. **Warning**: This is not supported on UNIX! when defined(windows): - var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO + var scrbuf: TCONSOLESCREENBUFFERINFO var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) var origin = scrbuf.dwCursorPosition origin.y = int16(y) - if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) else: - nil + discard -proc CursorUp*(count=1) = +proc cursorUp*(count=1) = ## Moves the cursor up by `count` rows. when defined(windows): var p = getCursorPos() @@ -91,7 +91,7 @@ proc CursorUp*(count=1) = else: stdout.write("\e[" & $count & 'A') -proc CursorDown*(count=1) = +proc cursorDown*(count=1) = ## Moves the cursor down by `count` rows. when defined(windows): var p = getCursorPos() @@ -100,7 +100,7 @@ proc CursorDown*(count=1) = else: stdout.write("\e[" & $count & 'B') -proc CursorForward*(count=1) = +proc cursorForward*(count=1) = ## Moves the cursor forward by `count` columns. when defined(windows): var p = getCursorPos() @@ -109,7 +109,7 @@ proc CursorForward*(count=1) = else: stdout.write("\e[" & $count & 'C') -proc CursorBackward*(count=1) = +proc cursorBackward*(count=1) = ## Moves the cursor backward by `count` columns. when defined(windows): var p = getCursorPos() @@ -119,78 +119,78 @@ proc CursorBackward*(count=1) = stdout.write("\e[" & $count & 'D') when true: - nil + discard else: - proc EraseLineEnd* = + proc eraseLineEnd* = ## Erases from the current cursor position to the end of the current line. when defined(windows): - nil + discard else: stdout.write("\e[K") - proc EraseLineStart* = + proc eraseLineStart* = ## Erases from the current cursor position to the start of the current line. when defined(windows): - nil + discard else: stdout.write("\e[1K") - proc EraseDown* = + proc eraseDown* = ## Erases the screen from the current line down to the bottom of the screen. when defined(windows): - nil + discard else: stdout.write("\e[J") - proc EraseUp* = + proc eraseUp* = ## Erases the screen from the current line up to the top of the screen. when defined(windows): - nil + discard else: stdout.write("\e[1J") -proc EraseLine* = +proc eraseLine* = ## Erases the entire current line. when defined(windows): - var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO + var scrbuf: TCONSOLESCREENBUFFERINFO var numwrote: DWORD var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) var origin = scrbuf.dwCursorPosition origin.x = 0'i16 - if SetConsoleCursorPosition(conHandle, origin) == 0: OSError(OSLastError()) + if SetConsoleCursorPosition(conHandle, origin) == 0: osError(osLastError()) var ht = scrbuf.dwSize.Y - origin.Y var wt = scrbuf.dwSize.X - origin.X if FillConsoleOutputCharacter(hStdout,' ', ht*wt, origin, addr(numwrote)) == 0: - OSError(OSLastError()) + osError(osLastError()) if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, ht * wt, scrbuf.dwCursorPosition, addr(numwrote)) == 0: - OSError(OSLastError()) + osError(osLastError()) else: stdout.write("\e[2K") setCursorXPos(0) -proc EraseScreen* = +proc eraseScreen* = ## Erases the screen with the background colour and moves the cursor to home. when defined(windows): - var scrbuf: TCONSOLE_SCREEN_BUFFER_INFO + var scrbuf: TCONSOLESCREENBUFFERINFO var numwrote: DWORD - var origin: TCoord # is inititalized to 0, 0 + var origin: TCOORD # is inititalized to 0, 0 var hStdout = conHandle - if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: OSError(OSLastError()) + if GetConsoleScreenBufferInfo(hStdout, addr(scrbuf)) == 0: osError(osLastError()) if FillConsoleOutputCharacter(hStdout, ' ', scrbuf.dwSize.X*scrbuf.dwSize.Y, origin, addr(numwrote)) == 0: - OSError(OSLastError()) + osError(osLastError()) if FillConsoleOutputAttribute(hStdout, scrbuf.wAttributes, scrbuf.dwSize.X * scrbuf.dwSize.Y, origin, addr(numwrote)) == 0: - OSError(OSLastError()) + osError(osLastError()) setCursorXPos(0) else: stdout.write("\e[2J") -proc ResetAttributes* {.noconv.} = +proc resetAttributes* {.noconv.} = ## resets all attributes; it is advisable to register this as a quit proc ## with ``system.addQuitProc(resetAttributes)``. when defined(windows): @@ -227,7 +227,7 @@ proc setStyle*(style: set[TStyle]) = for s in items(style): stdout.write("\e[" & $ord(s) & 'm') -proc WriteStyled*(txt: string, style: set[TStyle] = {styleBright}) = +proc writeStyled*(txt: string, style: set[TStyle] = {styleBright}) = ## writes the text `txt` in a given `style`. when defined(windows): var old = getAttributes() @@ -320,8 +320,8 @@ proc isatty*(f: TFile): bool = proc styledEchoProcessArg(s: string) = write stdout, s proc styledEchoProcessArg(style: TStyle) = setStyle({style}) proc styledEchoProcessArg(style: set[TStyle]) = setStyle style -proc styledEchoProcessArg(color: TForegroundColor) = setForeGroundColor color -proc styledEchoProcessArg(color: TBackgroundColor) = setBackGroundColor color +proc styledEchoProcessArg(color: TForegroundColor) = setForegroundColor color +proc styledEchoProcessArg(color: TBackgroundColor) = setBackgroundColor color macro styledEcho*(m: varargs[expr]): stmt = ## to be documented. @@ -345,4 +345,4 @@ when isMainModule: writeln(stdout, "ordinary text") styledEcho("styled text ", {styleBright, styleBlink, styleUnderscore}) - \ No newline at end of file + diff --git a/lib/pure/times.nim b/lib/pure/times.nim index e967ef683..6186fcad8 100644 --- a/lib/pure/times.nim +++ b/lib/pure/times.nim @@ -146,7 +146,7 @@ proc getGMTime*(t: TTime): TTimeInfo {.tags: [FTime], raises: [].} ## converts the calendar time `t` to broken-down time representation, ## expressed in Coordinated Universal Time (UTC). -proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].} +proc timeInfoToTime*(timeInfo: TTimeInfo): TTime {.tags: [].} ## converts a broken-down time structure to ## calendar time representation. The function ignores the specified ## contents of the structure members `weekday` and `yearday` and recomputes @@ -256,7 +256,7 @@ proc `+`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = ## ## **Note:** This has been only briefly tested and it may not be ## very accurate. - let t = toSeconds(TimeInfoToTime(a)) + let t = toSeconds(timeInfoToTime(a)) let secs = toSeconds(a, interval) if a.tzname == "UTC": result = getGMTime(fromSeconds(t + secs)) @@ -268,7 +268,7 @@ proc `-`*(a: TTimeInfo, interval: TTimeInterval): TTimeInfo = ## ## **Note:** This has been only briefly tested, it is inaccurate especially ## when you subtract so much that you reach the Julian calendar. - let t = toSeconds(TimeInfoToTime(a)) + let t = toSeconds(timeInfoToTime(a)) let secs = toSeconds(a, interval) if a.tzname == "UTC": result = getGMTime(fromSeconds(t - secs)) @@ -297,7 +297,7 @@ when not defined(JS): when not defined(JS): # C wrapper: type - structTM {.importc: "struct tm", final.} = object + StructTM {.importc: "struct tm", final.} = object second {.importc: "tm_sec".}, minute {.importc: "tm_min".}, hour {.importc: "tm_hour".}, @@ -308,7 +308,7 @@ when not defined(JS): yearday {.importc: "tm_yday".}, isdst {.importc: "tm_isdst".}: cint - PTimeInfo = ptr structTM + PTimeInfo = ptr StructTM PTime = ptr TTime TClock {.importc: "clock_t".} = distinct int @@ -319,11 +319,11 @@ when not defined(JS): importc: "gmtime", header: "<time.h>", tags: [].} proc timec(timer: PTime): TTime {. importc: "time", header: "<time.h>", tags: [].} - proc mktime(t: structTM): TTime {. + proc mktime(t: StructTM): TTime {. importc: "mktime", header: "<time.h>", tags: [].} - proc asctime(tblock: structTM): CString {. + proc asctime(tblock: StructTM): cstring {. importc: "asctime", header: "<time.h>", tags: [].} - proc ctime(time: PTime): CString {. + proc ctime(time: PTime): cstring {. importc: "ctime", header: "<time.h>", tags: [].} # strftime(s: CString, maxsize: int, fmt: CString, t: tm): int {. # importc: "strftime", header: "<time.h>".} @@ -335,7 +335,7 @@ when not defined(JS): clocksPerSec {.importc: "CLOCKS_PER_SEC", nodecl.}: int # our own procs on top of that: - proc tmToTimeInfo(tm: structTM, local: bool): TTimeInfo = + proc tmToTimeInfo(tm: StructTM, local: bool): TTimeInfo = const weekDays: array [0..6, TWeekDay] = [ dSun, dMon, dTue, dWed, dThu, dFri, dSat] @@ -345,11 +345,11 @@ when not defined(JS): monthday: int(tm.monthday), month: TMonth(tm.month), year: tm.year + 1900'i32, - weekday: weekDays[int(tm.weekDay)], + weekday: weekDays[int(tm.weekday)], yearday: int(tm.yearday), - isDST: tm.isDST > 0, + isDST: tm.isdst > 0, tzname: if local: - if tm.isDST > 0: + if tm.isdst > 0: getTzname().DST else: getTzname().nonDST @@ -358,7 +358,7 @@ when not defined(JS): timezone: if local: getTimezone() else: 0 ) - proc timeInfoToTM(t: TTimeInfo): structTM = + proc timeInfoToTM(t: TTimeInfo): StructTM = const weekDays: array [TWeekDay, int8] = [1'i8,2'i8,3'i8,4'i8,5'i8,6'i8,0'i8] result.second = t.second @@ -367,7 +367,7 @@ when not defined(JS): result.monthday = t.monthday result.month = ord(t.month) result.year = t.year - 1900 - result.weekday = weekDays[t.weekDay] + result.weekday = weekDays[t.weekday] result.yearday = t.yearday result.isdst = if t.isDST: 1 else: 0 @@ -401,7 +401,7 @@ when not defined(JS): # copying is needed anyway to provide reentrancity; thus # the conversion is not expensive - proc TimeInfoToTime(timeInfo: TTimeInfo): TTime = + proc timeInfoToTime(timeInfo: TTimeInfo): TTime = var cTimeInfo = timeInfo # for C++ we have to make a copy, # because the header of mktime is broken in my version of libc return mktime(timeInfoToTM(cTimeInfo)) @@ -453,7 +453,7 @@ when not defined(JS): result = toFloat(a.tv_sec) + toFloat(a.tv_usec)*0.00_0001 elif defined(windows): var f: winlean.TFiletime - GetSystemTimeAsFileTime(f) + getSystemTimeAsFileTime(f) var i64 = rdFileTime(f) - epochDiff var secs = i64 div rateDiff var subsecs = i64 mod rateDiff @@ -498,7 +498,7 @@ elif defined(JS): result.weekday = weekDays[t.getUTCDay()] result.yearday = 0 - proc TimeInfoToTime*(timeInfo: TTimeInfo): TTime = + proc timeInfoToTime*(timeInfo: TTimeInfo): TTime = result = internGetTime() result.setSeconds(timeInfo.second) result.setMinutes(timeInfo.minute) @@ -532,7 +532,7 @@ proc getDateStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} = ## gets the current date as a string of the format ``YYYY-MM-DD``. var ti = getLocalTime(getTime()) result = $ti.year & '-' & intToStr(ord(ti.month)+1, 2) & - '-' & intToStr(ti.monthDay, 2) + '-' & intToStr(ti.monthday, 2) proc getClockStr*(): string {.rtl, extern: "nt$1", tags: [FTime].} = ## gets the current clock time as a string of the format ``HH:MM:SS``. @@ -593,7 +593,7 @@ proc format*(info: TTimeInfo, f: string): string = result = "" var i = 0 var currentF = "" - while True: + while true: case f[i] of ' ', '-', '/', ':', '\'', '\0', '(', ')', '[', ']', ',': case currentF @@ -698,7 +698,7 @@ proc format*(info: TTimeInfo, f: string): string = of "ZZZ": result.add(info.tzname) of "": - nil # Do nothing. + discard else: raise newException(EInvalidValue, "Invalid format string: " & currentF) diff --git a/lib/pure/unicode.nim b/lib/pure/unicode.nim index 4aacb2f71..6e73eea3f 100644 --- a/lib/pure/unicode.nim +++ b/lib/pure/unicode.nim @@ -14,8 +14,8 @@ include "system/inclrtl" type - irune = int # underlying type of TRune - TRune* = distinct irune ## type that can hold any Unicode character + IRune = int # underlying type of TRune + TRune* = distinct IRune ## type that can hold any Unicode character TRune16* = distinct int16 ## 16 bit Unicode character proc `<=%`*(a, b: TRune): bool = return int(a) <=% int(b) @@ -109,7 +109,7 @@ proc runeAt*(s: string, i: int): TRune = proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} = ## converts a rune into its UTF8 representation - var i = irune(c) + var i = IRune(c) if i <=% 127: result = newString(1) result[0] = chr(i) @@ -132,6 +132,10 @@ proc toUTF8*(c: TRune): string {.rtl, extern: "nuc$1".} = result = newString(1) result[0] = chr(i) +proc `$`*(rune: TRune): string = + ## converts a rune to a string + rune.toUTF8 + proc `$`*(runes: seq[TRune]): string = ## converts a sequence of runes to a string result = "" @@ -1096,7 +1100,7 @@ const 0x01f1, 501, # 0x01f3, 499] # -proc binarySearch(c: irune, tab: openArray[iRune], len, stride: int): int = +proc binarySearch(c: IRune, tab: openArray[IRune], len, stride: int): int = var n = len var t = 0 while n > 1: @@ -1114,29 +1118,29 @@ proc binarySearch(c: irune, tab: openArray[iRune], len, stride: int): int = proc toLower*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = ## Converts `c` into lower case. This works for any Unicode character. ## If possible, prefer `toLower` over `toUpper`. - var c = irune(c) - var p = binarySearch(c, tolowerRanges, len(toLowerRanges) div 3, 3) + var c = IRune(c) + var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3) if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]: return TRune(c + tolowerRanges[p+2] - 500) - p = binarySearch(c, toLowerSinglets, len(toLowerSinglets) div 2, 2) - if p >= 0 and c == toLowerSinglets[p]: - return TRune(c + toLowerSinglets[p+1] - 500) + p = binarySearch(c, tolowerSinglets, len(tolowerSinglets) div 2, 2) + if p >= 0 and c == tolowerSinglets[p]: + return TRune(c + tolowerSinglets[p+1] - 500) return TRune(c) proc toUpper*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = ## Converts `c` into upper case. This works for any Unicode character. ## If possible, prefer `toLower` over `toUpper`. - var c = irune(c) - var p = binarySearch(c, toUpperRanges, len(toUpperRanges) div 3, 3) - if p >= 0 and c >= toUpperRanges[p] and c <= toUpperRanges[p+1]: - return TRune(c + toUpperRanges[p+2] - 500) - p = binarySearch(c, toUpperSinglets, len(toUpperSinglets) div 2, 2) - if p >= 0 and c == toUpperSinglets[p]: - return TRune(c + toUpperSinglets[p+1] - 500) + var c = IRune(c) + var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3) + if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]: + return TRune(c + toupperRanges[p+2] - 500) + p = binarySearch(c, toupperSinglets, len(toupperSinglets) div 2, 2) + if p >= 0 and c == toupperSinglets[p]: + return TRune(c + toupperSinglets[p+1] - 500) return TRune(c) proc toTitle*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = - var c = irune(c) + var c = IRune(c) var p = binarySearch(c, toTitleSinglets, len(toTitleSinglets) div 2, 2) if p >= 0 and c == toTitleSinglets[p]: return TRune(c + toTitleSinglets[p+1] - 500) @@ -1145,32 +1149,32 @@ proc toTitle*(c: TRune): TRune {.rtl, extern: "nuc$1", procvar.} = proc isLower*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a lower case Unicode character ## If possible, prefer `isLower` over `isUpper`. - var c = irune(c) + var c = IRune(c) # Note: toUpperRanges is correct here! - var p = binarySearch(c, toUpperRanges, len(toUpperRanges) div 3, 3) - if p >= 0 and c >= toUpperRanges[p] and c <= toUpperRanges[p+1]: + var p = binarySearch(c, toupperRanges, len(toupperRanges) div 3, 3) + if p >= 0 and c >= toupperRanges[p] and c <= toupperRanges[p+1]: return true - p = binarySearch(c, toUpperSinglets, len(toUpperSinglets) div 2, 2) - if p >= 0 and c == toUpperSinglets[p]: + p = binarySearch(c, toupperSinglets, len(toupperSinglets) div 2, 2) + if p >= 0 and c == toupperSinglets[p]: return true proc isUpper*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a upper case Unicode character ## If possible, prefer `isLower` over `isUpper`. - var c = irune(c) + var c = IRune(c) # Note: toLowerRanges is correct here! - var p = binarySearch(c, toLowerRanges, len(toLowerRanges) div 3, 3) - if p >= 0 and c >= toLowerRanges[p] and c <= toLowerRanges[p+1]: + var p = binarySearch(c, tolowerRanges, len(tolowerRanges) div 3, 3) + if p >= 0 and c >= tolowerRanges[p] and c <= tolowerRanges[p+1]: return true - p = binarySearch(c, toLowerSinglets, len(toLowerSinglets) div 2, 2) - if p >= 0 and c == toLowerSinglets[p]: + p = binarySearch(c, tolowerSinglets, len(tolowerSinglets) div 2, 2) + if p >= 0 and c == tolowerSinglets[p]: return true proc isAlpha*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is an *alpha* Unicode character (i.e. a letter) if isUpper(c) or isLower(c): return true - var c = irune(c) + var c = IRune(c) var p = binarySearch(c, alphaRanges, len(alphaRanges) div 2, 2) if p >= 0 and c >= alphaRanges[p] and c <= alphaRanges[p+1]: return true @@ -1183,7 +1187,7 @@ proc isTitle*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = proc isWhiteSpace*(c: TRune): bool {.rtl, extern: "nuc$1", procvar.} = ## returns true iff `c` is a Unicode whitespace character - var c = irune(c) + var c = IRune(c) var p = binarySearch(c, spaceRanges, len(spaceRanges) div 2, 2) if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]: return true @@ -1210,7 +1214,7 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} = # slow path: fastRuneAt(a, i, ar) fastRuneAt(b, j, br) - result = irune(toLower(ar)) - irune(toLower(br)) + result = IRune(toLower(ar)) - IRune(toLower(br)) if result != 0: return result = a.len - b.len diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim index f847d24f4..f5640a1b4 100644 --- a/lib/pure/unittest.nim +++ b/lib/pure/unittest.nim @@ -37,8 +37,8 @@ var checkpoints: seq[string] = @[] -template TestSetupIMPL*: stmt {.immediate, dirty.} = nil -template TestTeardownIMPL*: stmt {.immediate, dirty.} = nil +template TestSetupIMPL*: stmt {.immediate, dirty.} = discard +template TestTeardownIMPL*: stmt {.immediate, dirty.} = discard proc shouldRun(testName: string): bool = result = true @@ -126,7 +126,7 @@ macro check*(conditions: stmt): stmt {.immediate.} = for i in 1 .. <exp.len: if exp[i].kind notin nnkLiterals: inc counter - var arg = newIdentNode(":p" & ($counter)) + var arg = newIdentNode(":p" & $counter) var argStr = exp[i].toStrLit if exp[i].kind in nnkCallKinds: inspectArgs(exp[i]) argsAsgns.add getAst(asgn(arg, exp[i])) @@ -146,7 +146,8 @@ macro check*(conditions: stmt): stmt {.immediate.} = var checkedStr = checked.toStrLit inspectArgs(checked) - result = getAst(rewrite(checked, checked.lineinfo, checkedStr, argsAsgns, argsPrintOuts)) + result = getAst(rewrite(checked, checked.lineinfo, checkedStr, + argsAsgns, argsPrintOuts)) of nnkStmtList: result = newNimNode(nnkStmtList) @@ -176,7 +177,7 @@ macro expect*(exceptions: varargs[expr], body: stmt): stmt {.immediate.} = checkpoint(lineInfoLit & ": Expect Failed, no exception was thrown.") fail() except errorTypes: - nil + discard var body = exp[exp.len - 1] |