# # # Nim's Runtime Library # (c) Copyright 2012 Andreas Rumpf # # See the file "copying.txt", included in this # distribution, for details about the copyright. # ## A simple XML tree generator. ## runnableExamples: var g = newElement("myTag") g.add newText("some text") g.add newComment("this is comment") var h = newElement("secondTag") h.add newEntity("some entity") let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes let k = newXmlTree("treeTag", [g, h], att) doAssert $k == """ some text &some entity; """ ## **See also:** ## * `xmlparser module `_ for high-level XML parsing ## * `parsexml module `_ for low-level XML parsing ## * `htmlgen module `_ for html code generator import std/private/since import macros, strtabs, strutils, sequtils when defined(nimPreviewSlimSystem): import std/assertions type XmlNode* = ref XmlNodeObj ## An XML tree consisting of XML nodes. ## ## Use `newXmlTree proc <#newXmlTree,string,openArray[XmlNode],XmlAttributes>`_ ## for creating a new tree. XmlNodeKind* = enum ## Different kinds of XML nodes. xnText, ## a text element xnVerbatimText, ## xnElement, ## an element with 0 or more children xnCData, ## a CDATA node xnEntity, ## an entity (like ``&thing;``) xnComment ## an XML comment XmlAttributes* = StringTableRef ## An alias for a string to string mapping. ## ## Use `toXmlAttributes proc <#toXmlAttributes,varargs[tuple[string,string]]>`_ ## to create `XmlAttributes`. XmlNodeObj {.acyclic.} = object case k: XmlNodeKind # private, use the kind() proc to read this field. of xnText, xnVerbatimText, xnComment, xnCData, xnEntity: fText: string of xnElement: fTag: string s: seq[XmlNode] fAttr: XmlAttributes fClientData: int ## for other clients const xmlHeader* = "\n" ## Header to use for complete XML output. template expect(node: XmlNode, kind: set[XmlNodeKind]) = ## Check the node's kind is within a set of values assert node.k in kind, "Got " & $node.k template expect(node: XmlNode, kind: XmlNodeKind) = ## Check the node's kind equals a value assert node.k == kind, "Got " & $node.k proc newXmlNode(kind: XmlNodeKind): XmlNode = ## Creates a new ``XmlNode``. result = XmlNode(k: kind) proc newElement*(tag: sink string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnElement`` with the given `tag`. ## ## See also: ## * `newXmlTree proc <#newXmlTree,string,openArray[XmlNode],XmlAttributes>`_ ## * [<> macro](#<>.m,untyped) runnableExamples: var a = newElement("firstTag") a.add newElement("childTag") assert a.kind == xnElement assert $a == """ """ result = newXmlNode(xnElement) result.fTag = tag result.s = @[] # init attributes lazily to save memory proc newText*(text: sink string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnText`` with the text `text`. runnableExamples: var b = newText("my text") assert b.kind == xnText assert $b == "my text" result = newXmlNode(xnText) result.fText = text proc newVerbatimText*(text: sink string): XmlNode {.since: (1, 3).} = ## Creates a new ``XmlNode`` of kind ``xnVerbatimText`` with the text `text`. ## **Since**: Version 1.3. result = newXmlNode(xnVerbatimText) result.fText = text proc newComment*(comment: sink string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnComment`` with the text `comment`. runnableExamples: var c = newComment("my comment") assert c.kind == xnComment assert $c == "" result = newXmlNode(xnComment) result.fText = comment proc newCData*(cdata: sink string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnCData`` with the text `cdata`. runnableExamples: var d = newCData("my cdata") assert d.kind == xnCData assert $d == "" result = newXmlNode(xnCData) result.fText = cdata proc newEntity*(entity: string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnEntity`` with the text `entity`. runnableExamples: var e = newEntity("my entity") assert e.kind == xnEntity assert $e == "&my entity;" result = newXmlNode(xnEntity) result.fText = entity proc newXmlTree*(tag: sink string, children: openArray[XmlNode], attributes: XmlAttributes = nil): XmlNode = ## Creates a new XML tree with `tag`, `children` and `attributes`. ## ## See also: ## * `newElement proc <#newElement,string>`_ ## * [<> macro](#<>.m,untyped) runnableExamples: var g = newElement("myTag") g.add newText("some text") g.add newComment("this is comment") var h = newElement("secondTag") h.add newEntity("some entity") let att = {"key1": "first value", "key2": "second value"}.toXmlAttributes let k = newXmlTree("treeTag", [g, h], att) doAssert $k == """ some text &some entity; """ result = newXmlNode(xnElement) result.fTag = tag newSeq(result.s, children.len) for i in 0..children.len-1: result.s[i] = children[i] result.fAttr = attributes proc text*(n: XmlNode): lent string {.inline.} = ## Gets the associated text with the node `n`. ## ## `n` can be a CDATA, Text, comment, or entity node. ## ## See also: ## * `text= proc <#text=,XmlNode,string>`_ for text setter ## * `tag proc <#tag,XmlNode>`_ for tag getter ## * `tag= proc <#tag=,XmlNode,string>`_ for tag setter ## * `innerText proc <#innerText,XmlNode>`_ runnableExamples: var c = newComment("my comment") assert $c == "" assert c.text == "my comment" n.expect {xnText, xnComment, xnCData, xnEntity} result = n.fText proc `text=`*(n: XmlNode, text: sink string) {.inline.} = ## Sets the associated text with the node `n`. ## ## `n` can be a CDATA, Text, comment, or entity node. ## ## See also: ## * `text proc <#text,XmlNode>`_ for text getter ## * `tag proc <#tag,XmlNode>`_ for tag getter ## * `tag= proc <#tag=,XmlNode,string>`_ for tag setter runnableExamples: var e = newEntity("my entity") assert $e == "&my entity;" e.text = "a new entity text" assert $e == "&a new entity text;" n.expect {xnText, xnComment, xnCData, xnEntity} n.fText = text proc tag*(n: XmlNode): lent string {.inline.} = ## Gets the tag name of `n`. ## ## `n` has to be an ``xnElement`` node. ## ## See also: ## * `text proc <#text,XmlNode>`_ for text getter ## * `text= proc <#text=,XmlNode,string>`_ for text setter ## * `tag= proc <#tag=,XmlNode,string>`_ for tag setter ## * `innerText proc <#innerText,XmlNode>`_ runnableExamples: var a = newElement("firstTag") a.add newElement("childTag") assert $a == """ """ assert a.tag == "firstTag" n.expect xnElement result = n.fTag proc `tag=`*(n: XmlNode, tag: sink string) {.inline.} = ## Sets the tag name of `n`. ## ## `n` has to be an ``xnElement`` node. ## ## See also: ## * `text proc <#text,XmlNode>`_ for text getter ## * `text= proc <#text=,XmlNode,string>`_ for text setter ## * `tag proc <#tag,XmlNode>`_ for tag getter runnableExamples: var a = newElement("firstTag") a.add newElement("childTag") assert $a == """ """ a.tag = "newTag" assert $a == """ """ n.expect xnElement n.fTag = tag proc rawText*(n: XmlNode): string {.inline.} = ## Returns the underlying 'text' string by reference. ## ## This is only used for speed hacks. when defined(gcDestructors): result = move(n.fText) else: shallowCopy(result, n.fText) proc rawTag*(n: XmlNode): string {.inline.} = ## Returns the underlying 'tag' string by reference. ## ## This is only used for speed hacks. when defined(gcDestructors): result = move(n.fTag) else: shallowCopy(result, n.fTag) proc innerText*(n: XmlNode): string = ## Gets the inner text of `n`: ## ## - If `n` is `xnText` or `xnEntity`, returns its content. ## - If `n` is `xnElement`, runs recursively on each child node and ## concatenates the results. ## - Otherwise returns an empty string. ## ## See also: ## * `text proc <#text,XmlNode>`_ runnableExamples: var f = newElement("myTag") f.add newText("my text") f.add newComment("my comment") f.add newEnt
discard """
  output: '''true'''
"""

import hashes, tables, sequtils

const
  data = {
    "34": 123456, "12": 789,
    "90": 343, "0": 34404,
    "1": 344004, "2": 344774,
    "3": 342244, "4": 3412344,
    "5": 341232144, "6": 34214544,
    "7": 3434544, "8": 344544,
    "9": 34435644, "---00": 346677844,
    "10": 34484, "11": 34474, "19": 34464,
    "20": 34454, "30": 34141244, "40": 344114,
    "50": 344490, "60": 344491, "70": 344492,
    "80": 344497}

  sorteddata = {
    "---00": 346677844,
    "0": 34404,
    "1": 344004,
    "10": 34484,
    "11": 34474,
    "12": 789,
    "19": 34464,
    "2": 344774, "20": 34454,
    "3": 342244, "30": 34141244,
    "34": 123456,
    "4": 3412344, "40": 344114,
    "5": 341232144, "50": 344490,
    "6": 34214544, "60": 344491,
    "7": 3434544, "70": 344492,
    "8": 344544, "80": 344497,
    "9": 34435644,
    "90": 343}

block tableTest1:
  var t = newTable[tuple[x, y: int], string]()
  t[(0,0)] = "00"
  t[(1,0)] = "10"
  t[(0,1)] = "01"
  t[(1,1)] = "11"
  for x in 0..1:
    for y in 0..1:
      assert t[(x,y)] == $x & $y
  assert($t ==
    "{(x: 0, y: 1): 01, (x: 0, y: 0): 00, (x: 1, y: 0): 10, (x: 1, y: 1): 11}")

block tableTest2:
  var t = newTable[string, float]()
  t["test"] = 1.2345
  t["111"] = 1.000043
  t["123"] = 1.23
  t.del("111")

  t["012"] = 67.9
  t["123"] = 1.5 # test overwriting

  assert t["123"] == 1.5
  try:
    echo t["111"] # deleted
  except KeyError:
    discard
  assert(not hasKey(t, "111"))