tstrscans.nim 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. discard """
  2. matrix: "--mm:refc; --mm:orc"
  3. """
  4. import std/[strscans, strutils, assertions]
  5. block ParsePasswd:
  6. proc parsePasswd(content: string): seq[string] =
  7. result = @[]
  8. var idx = 0
  9. while true:
  10. var entry = ""
  11. if scanp(content, idx, +(~{'\L', '\0'} -> entry.add($_)), '\L'):
  12. result.add entry
  13. else:
  14. break
  15. const etcPasswd = """root:x:0:0:root:/root:/bin/bash
  16. daemon:x:1:1:daemon:/usr/sbin:/bin/sh
  17. bin:x:2:2:bin:/bin:/bin/sh
  18. sys:x:3:3:sys:/dev:/bin/sh
  19. nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
  20. messagebus:x:103:107::/var/run/dbus:/bin/false
  21. """
  22. const parsedEtcPasswd = @[
  23. "root:x:0:0:root:/root:/bin/bash",
  24. "daemon:x:1:1:daemon:/usr/sbin:/bin/sh",
  25. "bin:x:2:2:bin:/bin:/bin/sh",
  26. "sys:x:3:3:sys:/dev:/bin/sh",
  27. "nobody:x:65534:65534:nobody:/nonexistent:/bin/sh",
  28. "messagebus:x:103:107::/var/run/dbus:/bin/false",
  29. ]
  30. doAssert etcPasswd.parsePasswd == parsedEtcPasswd
  31. block LastNot:
  32. var idx : int
  33. idx = 0
  34. doAssert scanp("foo", idx, 'f', 'o', ~'a')
  35. idx = 0
  36. doAssert scanp("foo", idx, 'f', 'o', ~'o') == false
  37. idx = 0
  38. doAssert scanp("foox", idx, 'f', 'o', ~'o') == false
  39. idx = 0
  40. doAssert scanp("foox", idx, 'f', 'o', ~'a')
  41. block LastOptional:
  42. var idx = 0
  43. doAssert scanp("foo", idx, 'f', 'o', 'o', ?'o')
  44. block Tuple:
  45. var idx = 0
  46. doAssert scanp("foo", idx, ('f', 'o', 'o'))
  47. block NotWithOptional:
  48. var idx : int
  49. idx = 0
  50. doAssert scanp("bc", idx, ~(?'b', 'c')) == false
  51. idx = 0
  52. doAssert scanp("c", idx, ~(?'b', 'c')) == false
  53. idx = 0
  54. doAssert scanp("b", idx, ~(?'b', 'c'))
  55. block NotEmpty:
  56. var idx = 0
  57. doAssert scanp("", idx, ~()) == false
  58. block EmptyTuple:
  59. var idx = 0
  60. doAssert scanp("ab", idx, 'a', (), 'b')
  61. block Arrow:
  62. let text = "foo;bar;baz;"
  63. var idx = 0
  64. doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
  65. doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
  66. doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';')
  67. doAssert scanp(text, idx, +(~{';','\0'} -> (discard $_)), ';') == false
  68. block issue15064:
  69. var nick1, msg1: string
  70. doAssert scanf("<abcd> a", "<$+> $+", nick1, msg1)
  71. doAssert nick1 == "abcd"
  72. doAssert msg1 == "a"
  73. var nick2, msg2: string
  74. doAssert(not scanf("<abcd> ", "<$+> $+", nick2, msg2))
  75. var nick3, msg3: string
  76. doAssert scanf("<abcd> ", "<$+> $*", nick3, msg3)
  77. doAssert nick3 == "abcd"
  78. doAssert msg3 == ""
  79. block:
  80. proc twoDigits(input: string; x: var int; start: int): int =
  81. if start+1 < input.len and input[start] == '0' and input[start+1] == '0':
  82. result = 2
  83. x = 13
  84. else:
  85. result = 0
  86. proc someSep(input: string; start: int; seps: set[char] = {';', ',', '-', '.'}): int =
  87. result = 0
  88. while start+result < input.len and input[start+result] in seps: inc result
  89. proc demangle(s: string; res: var string; start: int): int =
  90. result = 0
  91. while result+start < s.len and s[result+start] in {'_', '@'}: inc result
  92. res = ""
  93. while result+start < s.len and s[result+start] > ' ' and s[result+start] != '_':
  94. res.add s[result+start]
  95. inc result
  96. while result+start < s.len and s[result+start] > ' ':
  97. inc result
  98. proc parseGDB(resp: string): seq[string] =
  99. const
  100. digits = {'0'..'9'}
  101. hexdigits = digits + {'a'..'f', 'A'..'F'}
  102. whites = {' ', '\t', '\C', '\L'}
  103. result = @[]
  104. var idx = 0
  105. while true:
  106. var prc = ""
  107. var info = ""
  108. if scanp(resp, idx, *`whites`, '#', *`digits`, +`whites`, ?("0x", *`hexdigits`, " in "),
  109. demangle($input, prc, $index), *`whites`, '(', * ~ ')', ')',
  110. *`whites`, "at ", +(~{'\C', '\L'} -> info.add($_))):
  111. result.add prc & " " & info
  112. else:
  113. break
  114. var key, val: string
  115. var intVal: int
  116. var floatVal: float
  117. doAssert scanf("abc:: xyz 89 33.25", "$w$s::$s$w$s$i $f", key, val, intVal, floatVal)
  118. doAssert key == "abc"
  119. doAssert val == "xyz"
  120. doAssert intVal == 89
  121. doAssert floatVal == 33.25
  122. var binVal: int
  123. var octVal: int
  124. var hexVal: int
  125. doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binVal, octVal, hexVal)
  126. doAssert binVal == 0b0101
  127. doAssert octVal == 0o1234
  128. doAssert hexVal == 0xabcd
  129. let xx = scanf("$abc", "$$$i", intVal)
  130. doAssert xx == false
  131. let xx2 = scanf("$1234", "$$$i", intVal)
  132. doAssert xx2
  133. let yy = scanf(";.--Breakpoint00 [output]",
  134. "$[someSep]Breakpoint${twoDigits}$[someSep({';','.','-'})] [$+]$.",
  135. intVal, key)
  136. doAssert yy
  137. doAssert key == "output"
  138. doAssert intVal == 13
  139. var ident = ""
  140. var idx = 0
  141. let zz = scanp("foobar x x x xWZ", idx, +{'a'..'z'} -> add(ident, $_), *(*{
  142. ' ', '\t'}, "x"), ~'U', "Z")
  143. doAssert zz
  144. doAssert ident == "foobar"
  145. const digits = {'0'..'9'}
  146. var year = 0
  147. var idx2 = 0
  148. if scanp("201655-8-9", idx2, `digits`{4, 6} -> (year = year * 10 + ord($_) -
  149. ord('0')), "-8", "-9"):
  150. doAssert year == 201655
  151. const gdbOut = """
  152. #0 @foo_96013_1208911747@8 (x0=...)
  153. at c:/users/anwender/projects/nim/temp.nim:11
  154. #1 0x00417754 in tempInit000 () at c:/users/anwender/projects/nim/temp.nim:13
  155. #2 0x0041768d in NimMainInner ()
  156. at c:/users/anwender/projects/nim/lib/system.nim:2605
  157. #3 0x004176b1 in NimMain ()
  158. at c:/users/anwender/projects/nim/lib/system.nim:2613
  159. #4 0x004176db in main (argc=1, args=0x712cc8, env=0x711ca8)
  160. at c:/users/anwender/projects/nim/lib/system.nim:2620"""
  161. const result = @["foo c:/users/anwender/projects/nim/temp.nim:11",
  162. "tempInit000 c:/users/anwender/projects/nim/temp.nim:13",
  163. "NimMainInner c:/users/anwender/projects/nim/lib/system.nim:2605",
  164. "NimMain c:/users/anwender/projects/nim/lib/system.nim:2613",
  165. "main c:/users/anwender/projects/nim/lib/system.nim:2620"]
  166. doAssert parseGDB(gdbOut) == result
  167. # bug #6487
  168. var count = 0
  169. proc test(): string =
  170. inc count
  171. result = ",123123"
  172. var a: int
  173. discard scanf(test(), ",$i", a)
  174. doAssert count == 1
  175. block:
  176. let input = """1-3 s: abc
  177. 15-18 9: def
  178. 15-18 A: ghi
  179. 15-18 _: jkl
  180. """
  181. var
  182. lo, hi: int
  183. w: string
  184. c: char
  185. res: int
  186. for line in input.splitLines:
  187. if line.scanf("$i-$i $c: $w", lo, hi, c, w):
  188. inc res
  189. doAssert res == 4
  190. block:
  191. #whenscanf testing
  192. let input = """1-3 s: abc
  193. 15-18 9: def
  194. 15-18 A: ghi
  195. 15-18 _: jkl
  196. """
  197. proc twoDigits(input: string; x: var int; start: int): int =
  198. if start+1 < input.len and input[start] == '0' and input[start+1] == '0':
  199. result = 2
  200. x = 13
  201. else:
  202. result = 0
  203. proc someSep(input: string; start: int; seps: set[char] = {';', ',', '-', '.'}): int =
  204. result = 0
  205. while start+result < input.len and input[start+result] in seps: inc result
  206. type
  207. ScanRetType = tuple
  208. success: bool
  209. lo: int
  210. hi: int
  211. ch: char
  212. word: string
  213. var res = 0
  214. for line in input.splitLines:
  215. let ret: ScanRetType = scanTuple(line, "$i-$i $c: $w")
  216. if ret.success:
  217. inc res
  218. doAssert res == 4
  219. let (_, key, val, intVal, floatVal) = scanTuple("abc:: xyz 89 33.25", "$w$s::$s$w$s$i $f")
  220. doAssert key == "abc"
  221. doAssert val == "xyz"
  222. doAssert intVal == 89
  223. doAssert floatVal == 33.25
  224. let (_, binVal, octVal, hexVal) = scanTuple("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binVal, octVal, hexVal)
  225. doAssert binVal == 0b0101
  226. doAssert octVal == 0o1234
  227. doAssert hexVal == 0xabcd
  228. var (xx,_) = scanTuple("$abc", "$$$i")
  229. doAssert xx == false
  230. let (xx2, _) = block: scanTuple("$1234", "$$$i")
  231. doAssert xx2
  232. var (yy, intVal2, key2) = scanTuple(";.--Breakpoint00 [output]",
  233. "$[someSep]Breakpoint${twoDigits}$[someSep({';','.','-'})] [$+]$.",
  234. int)
  235. doAssert yy
  236. doAssert key2 == "output"
  237. doAssert intVal2 == 13