Skip to content

Commit 67e9eed

Browse files
committed
write tuples/objects
1 parent 66771c0 commit 67e9eed

File tree

3 files changed

+72
-12
lines changed

3 files changed

+72
-12
lines changed

lib/system/dollars.nim

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -49,18 +49,8 @@ proc `$`*(t: typedesc): string {.magic: "TypeTrait".}
4949
## doAssert $(type("Foo")) == "string"
5050
## static: doAssert $(type(@['A', 'B'])) == "seq[char]"
5151

52-
53-
proc isNamedTuple(T: typedesc): bool =
52+
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
5453
# Taken from typetraits.
55-
when T isnot tuple: result = false
56-
else:
57-
var t: T
58-
for name, _ in t.fieldPairs:
59-
when name == "Field0":
60-
return compiles(t.Field0)
61-
else:
62-
return true
63-
return false
6454

6555
proc `$`*[T: tuple|object](x: T): string =
6656
## Generic ``$`` operator for tuples that is lifted from the components

lib/system/io.nim

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,76 @@ proc write*(f: File, r: BiggestFloat) {.tags: [WriteIOEffect], benign.} =
376376
proc write*(f: File, c: char) {.tags: [WriteIOEffect], benign.} =
377377
discard c_putc(cint(c), f)
378378

379+
proc isNamedTuple(T: typedesc): bool {.magic: "TypeTrait".}
380+
# Taken from typetraits.
381+
382+
proc writeEscapedChar(f: File, c: char) {.inline.} =
383+
# Analogue to `sysetm.addEscapedChar`.
384+
case c
385+
of '\a': f.write "\\a" # \x07
386+
of '\b': f.write "\\b" # \x08
387+
of '\t': f.write "\\t" # \x09
388+
of '\L': f.write "\\n" # \x0A
389+
of '\v': f.write "\\v" # \x0B
390+
of '\f': f.write "\\f" # \x0C
391+
of '\c': f.write "\\c" # \x0D
392+
of '\e': f.write "\\e" # \x1B
393+
of '\\': f.write("\\\\")
394+
of '\'': f.write("\\'")
395+
of '\"': f.write("\\\"")
396+
of {'\32'..'\126'} - {'\\', '\'', '\"'}: f.write(c)
397+
else:
398+
f.write("\\x")
399+
const HexChars = "0123456789ABCDEF"
400+
let n = ord(c)
401+
f.write(HexChars[int((n and 0xF0) shr 4)])
402+
f.write(HexChars[int(n and 0xF)])
403+
404+
proc writeQuoted[T](f: File, arg: T) =
405+
# analogue to `addQuoted` in `system`
406+
when T is string or T is cstring:
407+
f.write("\"")
408+
for c in arg:
409+
# Only ASCII chars are escaped to avoid butchering
410+
# multibyte UTF-8 characters.
411+
if c <= 127.char:
412+
f.writeEscapedChar(c)
413+
else:
414+
f.write c
415+
f.write("\"")
416+
elif T is char:
417+
f.write("'")
418+
f.addEscapedChar(x)
419+
f.write("'")
420+
# prevent temporary string allocation
421+
else:
422+
f.write(x)
423+
424+
proc write*[T: tuple|object](f: File; arg: T) =
425+
f.write "("
426+
const isNamed = isNamedTuple(T)
427+
var count = 0
428+
for name, value in fieldPairs(arg):
429+
if count != 0:
430+
f.write(", ")
431+
432+
when isNamed:
433+
f.write(name, ": ")
434+
435+
when compiles($value):
436+
when value isnot string and value isnot seq and compiles(value.isNil):
437+
if value.isNil: result.add "nil"
438+
else: f.writeQuoted(value)
439+
else:
440+
f.writeQuoted(value)
441+
else:
442+
f.write("...")
443+
inc count
444+
445+
if not isNamed and count == 1:
446+
f.write(",") # one tuple needs post comma, e.g. ``("abc",)``
447+
f.write(")")
448+
379449
when defined(harmfulOverloadOfWrite):
380450
proc write*(f: File, a: varargs[string, `$`]) {.tags: [WriteIOEffect], benign.} =
381451
for x in items(a): write(f, x)

lib/system/strmantle.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ proc hashString(s: string): int {.compilerproc.} =
4040
h = h + h shl 15
4141
result = cast[int](h)
4242

43-
proc addInt*(result: var string; x: int64) =
43+
proc addInt*(result: var string; x: int64) = # #10963
4444
## Converts integer to its string representation and appends it to `result`.
4545
##
4646
## .. code-block:: Nim

0 commit comments

Comments
 (0)