Improved collection-to-string behavior (#6825)

This commit is contained in:
Fabian Keller
2017-12-14 14:02:13 +01:00
committed by Andreas Rumpf
parent bc1123536e
commit 6df6ec27ec
33 changed files with 226 additions and 74 deletions

View File

@@ -141,8 +141,8 @@ proc excl*[T](c: var CritBitTree[T], key: string) =
proc missingOrExcl*[T](c: var CritBitTree[T], key: string): bool =
## Returns true iff `c` does not contain the given `key`. If the key
## does exist, c.excl(key) is performed.
let oldCount = c.count
## does exist, c.excl(key) is performed.
let oldCount = c.count
var n = exclImpl(c, key)
result = c.count == oldCount
@@ -326,7 +326,7 @@ proc `$`*[T](c: CritBitTree[T]): string =
result.add($key)
when T isnot void:
result.add(": ")
result.add($val)
result.addQuoted(val)
result.add("}")
when isMainModule:

View File

@@ -185,7 +185,7 @@ proc `$`*[T](deq: Deque[T]): string =
result = "["
for x in deq:
if result.len > 1: result.add(", ")
result.add($x)
result.addQuoted(x)
result.add("]")
when isMainModule:

View File

@@ -135,7 +135,7 @@ proc `$`*[T](L: SomeLinkedCollection[T]): string =
result = "["
for x in nodes(L):
if result.len > 1: result.add(", ")
result.add($x.value)
result.addQuoted(x.value)
result.add("]")
proc find*[T](L: SomeLinkedCollection[T], value: T): SomeLinkedNode[T] =

View File

@@ -406,7 +406,7 @@ template dollarImpl() {.dirty.} =
result = "{"
for key in items(s):
if result.len > 1: result.add(", ")
result.add($key)
result.addQuoted(key)
result.add("}")
proc `$`*[A](s: HashSet[A]): string =

View File

@@ -338,9 +338,9 @@ template dollarImpl(): untyped {.dirty.} =
result = "{"
for key, val in pairs(t):
if result.len > 1: result.add(", ")
result.add($key)
result.addQuoted(key)
result.add(": ")
result.add($val)
result.addQuoted(val)
result.add("}")
proc `$`*[A, B](t: Table[A, B]): string =

View File

@@ -1761,29 +1761,15 @@ proc insertSep*(s: string, sep = '_', digits = 3): string {.noSideEffect,
proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
rtl, extern: "nsuEscape".} =
## Escapes a string `s`.
## Escapes a string `s`. See `system.addEscapedChar <system.html#addEscapedChar>`_
## for the escaping scheme.
##
## 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', '\127'..'\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.
## **Note**: This is not correct for producing Ansi C code!
## 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', '\127'..'\255':
add(result, "\\x")
add(result, toHex(ord(c), 2))
of '\\': add(result, "\\\\")
of '\'': add(result, "\\'")
of '\"': add(result, "\\\"")
else: add(result, c)
result.addEscapedChar(c)
add(result, suffix)
proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,

View File

@@ -1325,6 +1325,7 @@ proc add*(x: var string, y: string) {.magic: "AppendStrStr", noSideEffect.}
## tmp.add("cd")
## assert(tmp == "abcd")
type
Endianness* = enum ## is a type describing the endianness of a processor.
littleEndian, bigEndian
@@ -2503,9 +2504,9 @@ proc `$`*[T: tuple|object](x: T): string =
when compiles($value):
when compiles(value.isNil):
if value.isNil: result.add "nil"
else: result.add($value)
else: result.addQuoted(value)
else:
result.add($value)
result.addQuoted(value)
firstElement = false
else:
result.add("...")
@@ -2525,12 +2526,9 @@ proc collectionToString[T](x: T, prefix, separator, suffix: string): string =
if value.isNil:
result.add "nil"
else:
result.add($value)
# prevent temporary string allocation
elif compiles(result.add(value)):
result.add(value)
result.addQuoted(value)
else:
result.add($value)
result.addQuoted(value)
result.add(suffix)
@@ -3893,6 +3891,65 @@ proc compiles*(x: untyped): bool {.magic: "Compiles", noSideEffect, compileTime.
when declared(initDebugger):
initDebugger()
proc addEscapedChar*(s: var string, c: char) {.noSideEffect, inline.} =
## Adds a char to string `s` and applies the following escaping:
##
## * replaces any ``\`` by ``\\``
## * replaces any ``'`` by ``\'``
## * replaces any ``"`` by ``\"``
## * replaces any other character in the set ``{'\0'..'\31', '\127'..'\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.
## **Note**: This is not correct for producing Ansi C code!
case c
of '\0'..'\31', '\127'..'\255':
add(s, "\\x")
const HexChars = "0123456789ABCDEF"
let n = ord(c)
s.add(HexChars[int((n and 0xF0) shr 4)])
s.add(HexChars[int(n and 0xF)])
of '\\': add(s, "\\\\")
of '\'': add(s, "\\'")
of '\"': add(s, "\\\"")
else: add(s, c)
proc addQuoted*[T](s: var string, x: T) =
## Appends `x` to string `s` in place, applying quoting and escaping
## if `x` is a string or char. See
## `addEscapedChar <system.html#addEscapedChar>`_
## for the escaping scheme.
##
## The Nim standard library uses this function on the elements of
## collections when producing a string representation of a collection.
## It is recommended to use this function as well for user-side collections.
## Users may overload `addQuoted` for custom (string-like) types if
## they want to implement a customized element representation.
##
## .. code-block:: Nim
## var tmp = ""
## tmp.addQuoted(1)
## tmp.add(", ")
## tmp.addQuoted("string")
## tmp.add(", ")
## tmp.addQuoted('c')
## assert(tmp == """1, "string", 'c'""")
when T is string:
s.add("\"")
for c in x:
s.addEscapedChar(c)
s.add("\"")
elif T is char:
s.add("'")
s.addEscapedChar(x)
s.add("'")
# prevent temporary string allocation
elif compiles(s.add(x)):
s.add(x)
else:
s.add($x)
when hasAlloc:
# XXX: make these the default (or implement the NilObject optimization)
proc safeAdd*[T](x: var seq[T], y: T) {.noSideEffect.} =
@@ -4034,4 +4091,4 @@ template doAssertRaises*(exception, code: untyped): typed =
except Exception as exc:
raiseAssert(astToStr(exception) &
" wasn't raised, another error was raised instead by:\n"&
astToStr(code))
astToStr(code))