stdlib work

This commit is contained in:
Zahary Karadjov
2018-06-09 11:52:03 +03:00
parent ee16e62061
commit 7ab1aafc6b
3 changed files with 66 additions and 9 deletions

View File

@@ -38,7 +38,7 @@
## Note: For inter thread communication use
## a `Channel <channels.html>`_ instead.
import math
import math, typetraits
type
Deque*[T] = object
@@ -160,16 +160,18 @@ proc peekLast*[T](deq: Deque[T]): T {.inline.} =
emptyCheck(deq)
result = deq.data[(deq.tail - 1) and deq.mask]
template default[T](t: typedesc[T]): T =
var v: T
v
template destroy(x: untyped) =
when defined(nimNewRuntime) and not supportsCopyMem(type(x)):
`=destroy`(x)
else:
reset(x)
proc popFirst*[T](deq: var Deque[T]): T {.inline, discardable.} =
## Remove and returns the first element of the `deq`.
emptyCheck(deq)
dec deq.count
result = deq.data[deq.head]
deq.data[deq.head] = default(type(result))
destroy(deq.data[deq.head])
deq.head = (deq.head + 1) and deq.mask
proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
@@ -178,7 +180,34 @@ proc popLast*[T](deq: var Deque[T]): T {.inline, discardable.} =
dec deq.count
deq.tail = (deq.tail - 1) and deq.mask
result = deq.data[deq.tail]
deq.data[deq.tail] = default(type(result))
destroy(deq.data[deq.tail])
proc clear*[T](deq: var Deque[T]) {.inline.} =
## Resets the deque so that it is empty.
for el in mitems(deq): destroy(el)
deq.count = 0
deq.tail = deq.head
proc shrink*[T](deq: var Deque[T], fromFirst = 0, fromLast = 0) =
## Remove `fromFirst` elements from the front of the deque and
## `fromLast` elements from the back. If the supplied number of
## elements exceeds the total number of elements in the deque,
## the deque will remain empty.
##
## Any user defined destructors
if fromFirst + fromLast > deq.count:
clear(deq)
return
for i in 0 ..< fromFirst:
destroy(deq.data[deq.head])
deq.head = (deq.head + 1) and deq.mask
for i in 0 ..< fromLast:
destroy(deq.data[deq.tail])
deq.tail = (deq.tail - 1) and deq.mask
dec deq.count, fromFirst + fromLast
proc `$`*[T](deq: Deque[T]): string =
## Turn a deque into its string representation.
@@ -215,6 +244,22 @@ when isMainModule:
assert deq.find(6) >= 0
assert deq.find(789) < 0
block:
var d = initDeque[int](1)
d.addLast 7
d.addLast 8
d.addLast 10
d.addFirst 5
d.addFirst 2
d.addFirst 1
d.addLast 20
d.shrink(fromLast = 2)
doAssert($d == "[1, 2, 5, 7, 8]")
d.shrink(2, 1)
doAssert($d == "[5, 7]")
d.shrink(2, 2)
doAssert d.len == 0
for i in -2 .. 10:
if i in deq:
assert deq.contains(i) and deq.find(i) >= 0

View File

@@ -135,6 +135,11 @@ proc write*(s: Stream, x: string) =
else:
if x.len > 0: writeData(s, cstring(x), x.len)
proc write*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream. No length fields or
## terminating zeros are written.
for str in args: write(s, str)
proc writeLine*(s: Stream, args: varargs[string, `$`]) =
## writes one or more strings to the the stream `s` followed
## by a new line. No length field or terminating zero is written.
@@ -266,8 +271,8 @@ proc peekStr*(s: Stream, length: int): TaintedString =
proc readLine*(s: Stream, line: var TaintedString): bool =
## reads a line of text from the stream `s` into `line`. `line` must not be
## ``nil``! May throw an IO exception.
## A line of text may be delimited by ``CR``, ``LF`` or
## ``CRLF``. The newline character(s) are not part of the returned string.
## A line of text may be delimited by ```LF`` or ``CRLF``.
## The newline character(s) are not part of the returned string.
## Returns ``false`` if the end of the file has been reached, ``true``
## otherwise. If ``false`` is returned `line` contains no new data.
line.string.setLen(0)
@@ -317,6 +322,13 @@ proc peekLine*(s: Stream): TaintedString =
defer: setPosition(s, pos)
result = readLine(s)
iterator lines*(s: Stream): TaintedString =
## Iterates over every line in the stream.
## The iteration is based on ``readLine``.
var line: TaintedString
while s.readLine(line):
yield line
when not defined(js):
type

View File

@@ -182,7 +182,7 @@ template checkOsError =
if err.len > 0: raise newException(OSError, err)
template log(msg: string, body: untyped) =
if mode == ScriptMode.Verbose or mode == ScriptMode.Whatif:
if mode in {ScriptMode.Verbose, ScriptMode.Whatif}:
echo "[NimScript] ", msg
if mode != ScriptMode.WhatIf:
body