/ yaml / private / internal.nim
internal.nim
 1  #            NimYAML - YAML implementation in Nim
 2  #        (c) Copyright 2015-2023 Felix Krause
 3  #
 4  #    See the file "copying.txt", included in this
 5  #    distribution, for details about the copyright.
 6  
 7  import tables
 8  import ../data
 9  
10  template internalError*(s: string) =
11    # Note: to get the internal stacktrace that caused the error
12    # compile with the `d:debug` flag.
13    when not defined(release):
14      let ii = instantiationInfo()
15      echo "[NimYAML] Error in file ", ii.filename, " at line ", ii.line, ":"
16      echo s
17      when not defined(JS):
18        try:
19          var exc = getCurrentException()
20          while not isNil(exc):
21            echo "… stacktrace [", exc.name, ": ", exc.msg, "]"
22            echo getStackTrace(exc)
23            exc = exc.parent
24        except CatchableError: discard
25      echo "[NimYAML] Please report this bug."
26      quit 1
27  
28  template yAssert*(e: typed) =
29    when not defined(release):
30      if not e:
31        let ii = instantiationInfo()
32        echo "[NimYAML] Error in file ", ii.filename, " at line ", ii.line, ":"
33        echo "assertion failed!"
34        when not defined(JS):
35          echo "[NimYAML] Stacktrace:"
36          try:
37            writeStackTrace()
38            let exc = getCurrentException()
39            if not isNil(exc.parent):
40              echo "Internal stacktrace:"
41              echo getStackTrace(exc.parent)
42          except CatchableError: discard
43        echo "[NimYAML] Please report this bug."
44        quit 1
45  
46  proc nextAnchor*(s: var string, i: int) =
47    if s[i] == 'z':
48      s[i] = 'a'
49      if i == 0:
50        s.add('a')
51      else:
52        s[i] = 'a'
53        nextAnchor(s, i - 1)
54    else:
55      s[i] = char(int(s[i]) + 1)
56  
57  template resetHandles*(handles: var seq[tuple[handle, uriPrefix: string]]) {.dirty.} =
58    handles.setLen(0)
59    handles.add(("!", "!"))
60    handles.add(("!!", yamlTagRepositoryPrefix))
61  
62  proc registerHandle*(handles: var seq[tuple[handle, uriPrefix: string]], handle, uriPrefix: string): bool =
63    for i in countup(0, len(handles)-1):
64      if handles[i].handle == handle:
65        handles[i].uriPrefix = uriPrefix
66        return false
67    handles.add((handle, uriPrefix))
68    return false
69  
70  type
71    AnchorContext* = object
72      nextAnchorId: string
73      mapping: Table[Anchor, Anchor]
74  
75  proc initAnchorContext*(): AnchorContext =
76    return AnchorContext(nextAnchorId: "a", mapping: initTable[Anchor, Anchor]())
77  
78  proc process*(context: var AnchorContext,
79      target: var Properties, refs: Table[pointer, tuple[a: Anchor, referenced: bool]]) =
80    if target.anchor == yAnchorNone: return
81    for key, val in refs:
82      if val.a == target.anchor:
83        if not val.referenced:
84          target.anchor = yAnchorNone
85          return
86        break
87    if context.mapping.hasKey(target.anchor):
88      target.anchor = context.mapping.getOrDefault(target.anchor)
89    else:
90      let old = move(target.anchor)
91      target.anchor = context.nextAnchorId.Anchor
92      nextAnchor(context.nextAnchorId, len(context.nextAnchorId)-1)
93      context.mapping[old] = target.anchor
94  
95  proc map*(context: AnchorContext, anchor: Anchor): Anchor =
96    return context.mapping.getOrDefault(anchor)