tstrutils.nim 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846
  1. discard """
  2. targets: "c cpp js"
  3. """
  4. import std/strutils
  5. from stdtest/testutils import disableVm
  6. # xxx each instance of `disableVm` and `when not defined js:` should eventually be fixed
  7. template rejectParse(e) =
  8. try:
  9. discard e
  10. raise newException(AssertionDefect, "This was supposed to fail: $#!" % astToStr(e))
  11. except ValueError: discard
  12. template main() =
  13. block: # strip
  14. doAssert strip(" ha ") == "ha"
  15. doAssert strip(" foofoofoo ") == "foofoofoo"
  16. doAssert strip("sfoofoofoos", chars = {'s'}) == "foofoofoo"
  17. doAssert strip("barfoofoofoobar", chars = {'b', 'a', 'r'}) == "foofoofoo"
  18. doAssert strip("stripme but don't strip this stripme",
  19. chars = {'s', 't', 'r', 'i', 'p', 'm', 'e'}) ==
  20. " but don't strip this "
  21. doAssert strip("sfoofoofoos", leading = false, chars = {'s'}) == "sfoofoofoo"
  22. doAssert strip("sfoofoofoos", trailing = false, chars = {'s'}) == "foofoofoos"
  23. block:
  24. let a = "xxxxxx"
  25. doAssert a.strip(chars={'x'}).len == 0
  26. doAssert "".strip(chars={'x'}).len == 0
  27. doAssert " ".strip(chars={'x'}) == " "
  28. doAssert "xxx xxx".strip(chars={'x'}) == " "
  29. doAssert "xxx wind".strip(chars={'x'}) == " wind"
  30. doAssert "xxx iii".strip(chars={'i'}) == "xxx "
  31. doAssert "x".strip(leading = false, chars={'x'}).len == 0
  32. doAssert "x".strip(trailing = false, chars={'x'}).len == 0
  33. doAssert "x".strip(leading = false, trailing = false, chars={'x'}) == "x"
  34. block: # split
  35. var ret: seq[string] # or use `toSeq` or `collect`
  36. for p in split("/home/a1:xyz:/usr/bin", {':'}): ret.add p
  37. doAssert ret == @["/home/a1", "xyz", "/usr/bin"]
  38. let s = " this is an example "
  39. let s2 = ":this;is;an:example;;"
  40. doAssert s.split() == @["", "this", "is", "an", "example", "", ""]
  41. doAssert s2.split(seps = {':', ';'}) == @["", "this", "is", "an", "example",
  42. "", ""]
  43. doAssert s.split(maxsplit = 4) == @["", "this", "is", "an", "example "]
  44. doAssert s.split(' ', maxsplit = 1) == @["", "this is an example "]
  45. doAssert s.split(" ", maxsplit = 4) == @["", "this", "is", "an", "example "]
  46. block: # splitLines
  47. let fixture = "a\nb\rc\r\nd"
  48. doAssert len(fixture.splitLines) == 4
  49. doAssert splitLines(fixture) == @["a", "b", "c", "d"]
  50. doAssert splitLines(fixture, keepEol=true) == @["a\n", "b\r", "c\r\n", "d"]
  51. block: # rsplit
  52. doAssert rsplit("foo bar", seps = Whitespace) == @["foo", "bar"]
  53. doAssert rsplit(" foo bar", seps = Whitespace, maxsplit = 1) == @[" foo", "bar"]
  54. doAssert rsplit(" foo bar ", seps = Whitespace, maxsplit = 1) == @[
  55. " foo bar", ""]
  56. doAssert rsplit(":foo:bar", sep = ':') == @["", "foo", "bar"]
  57. doAssert rsplit(":foo:bar", sep = ':', maxsplit = 2) == @["", "foo", "bar"]
  58. doAssert rsplit(":foo:bar", sep = ':', maxsplit = 3) == @["", "foo", "bar"]
  59. doAssert rsplit("foothebar", sep = "the") == @["foo", "bar"]
  60. block: # splitWhitespace
  61. let s = " this is an example "
  62. doAssert s.splitWhitespace() == @["this", "is", "an", "example"]
  63. doAssert s.splitWhitespace(maxsplit = 1) == @["this", "is an example "]
  64. doAssert s.splitWhitespace(maxsplit = 2) == @["this", "is", "an example "]
  65. doAssert s.splitWhitespace(maxsplit = 3) == @["this", "is", "an", "example "]
  66. doAssert s.splitWhitespace(maxsplit = 4) == @["this", "is", "an", "example"]
  67. block: # removeSuffix
  68. var s = "hello\n\r"
  69. s.removeSuffix
  70. doAssert s == "hello"
  71. s.removeSuffix
  72. doAssert s == "hello"
  73. s = "hello\n\n"
  74. s.removeSuffix
  75. doAssert s == "hello"
  76. s = "hello\r"
  77. s.removeSuffix
  78. doAssert s == "hello"
  79. s = "hello \n there"
  80. s.removeSuffix
  81. doAssert s == "hello \n there"
  82. s = "hello"
  83. s.removeSuffix("llo")
  84. doAssert s == "he"
  85. s.removeSuffix('e')
  86. doAssert s == "h"
  87. s = "hellos"
  88. s.removeSuffix({'s','z'})
  89. doAssert s == "hello"
  90. s.removeSuffix({'l','o'})
  91. doAssert s == "he"
  92. s = "aeiou"
  93. s.removeSuffix("")
  94. doAssert s == "aeiou"
  95. s = ""
  96. s.removeSuffix("")
  97. doAssert s == ""
  98. s = " "
  99. s.removeSuffix
  100. doAssert s == " "
  101. s = " "
  102. s.removeSuffix("")
  103. doAssert s == " "
  104. s = " "
  105. s.removeSuffix(" ")
  106. doAssert s == " "
  107. s = " "
  108. s.removeSuffix(' ')
  109. doAssert s == ""
  110. # Contrary to Chomp in other languages
  111. # empty string does not change behaviour
  112. s = "hello\r\n\r\n"
  113. s.removeSuffix("")
  114. doAssert s == "hello\r\n\r\n"
  115. block: # removePrefix
  116. var s = "\n\rhello"
  117. s.removePrefix
  118. doAssert s == "hello"
  119. s.removePrefix
  120. doAssert s == "hello"
  121. s = "\n\nhello"
  122. s.removePrefix
  123. doAssert s == "hello"
  124. s = "\rhello"
  125. s.removePrefix
  126. doAssert s == "hello"
  127. s = "hello \n there"
  128. s.removePrefix
  129. doAssert s == "hello \n there"
  130. s = "hello"
  131. s.removePrefix("hel")
  132. doAssert s == "lo"
  133. s.removePrefix('l')
  134. doAssert s == "o"
  135. s = "hellos"
  136. s.removePrefix({'h','e'})
  137. doAssert s == "llos"
  138. s.removePrefix({'l','o'})
  139. doAssert s == "s"
  140. s = "aeiou"
  141. s.removePrefix("")
  142. doAssert s == "aeiou"
  143. s = ""
  144. s.removePrefix("")
  145. doAssert s == ""
  146. s = " "
  147. s.removePrefix
  148. doAssert s == " "
  149. s = " "
  150. s.removePrefix("")
  151. doAssert s == " "
  152. s = " "
  153. s.removePrefix(" ")
  154. doAssert s == " "
  155. s = " "
  156. s.removePrefix(' ')
  157. doAssert s == ""
  158. # Contrary to Chomp in other languages
  159. # empty string does not change behaviour
  160. s = "\r\n\r\nhello"
  161. s.removePrefix("")
  162. doAssert s == "\r\n\r\nhello"
  163. block: # delete(slice)
  164. var s = "0123456789ABCDEFGH"
  165. delete(s, 4 .. 5)
  166. doAssert s == "01236789ABCDEFGH"
  167. delete(s, s.len-1 .. s.len-1)
  168. doAssert s == "01236789ABCDEFG"
  169. delete(s, 0..0)
  170. doAssert s == "1236789ABCDEFG"
  171. s = ""
  172. doAssertRaises(IndexDefect): delete(s, 0..0)
  173. doAssert s == ""
  174. s = "abc"
  175. doAssertRaises(IndexDefect): delete(s, -1 .. -2)
  176. doAssertRaises(IndexDefect): delete(s, 2..3)
  177. doAssertRaises(IndexDefect): delete(s, 3..2)
  178. delete(s, 2..2)
  179. doAssert s == "ab"
  180. delete(s, 1..0)
  181. doAssert s == "ab"
  182. delete(s, 0..0)
  183. doAssert s == "b"
  184. block: # delete(first, last)
  185. {.push warning[deprecated]:off.}
  186. var s = "0123456789ABCDEFGH"
  187. delete(s, 4, 5)
  188. doAssert s == "01236789ABCDEFGH"
  189. delete(s, s.len-1, s.len-1)
  190. doAssert s == "01236789ABCDEFG"
  191. delete(s, 0, 0)
  192. doAssert s == "1236789ABCDEFG"
  193. {.pop.}
  194. block: # find
  195. doAssert "0123456789ABCDEFGH".find('A') == 10
  196. doAssert "0123456789ABCDEFGH".find('A', 5) == 10
  197. doAssert "0123456789ABCDEFGH".find('A', 5, 10) == 10
  198. doAssert "0123456789ABCDEFGH".find('A', 5, 9) == -1
  199. doAssert "0123456789ABCDEFGH".find("A") == 10
  200. doAssert "0123456789ABCDEFGH".find("A", 5) == 10
  201. doAssert "0123456789ABCDEFGH".find("A", 5, 10) == 10
  202. doAssert "0123456789ABCDEFGH".find("A", 5, 9) == -1
  203. doAssert "0123456789ABCDEFGH".find({'A'..'C'}) == 10
  204. doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5) == 10
  205. doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 10) == 10
  206. doAssert "0123456789ABCDEFGH".find({'A'..'C'}, 5, 9) == -1
  207. block:
  208. const haystack: string = "ABCABABABABCAB"
  209. doAssert haystack.len == 14
  210. # only last argument
  211. doAssert haystack.find("ABC") == 0
  212. doAssert haystack.find("ABC", last=13) == 0 # after the second ABC
  213. doAssert haystack.find("ABC", last=5) == 0 # before the second ABC
  214. # only start argument
  215. doAssert haystack.find("ABC", start=0) == 0
  216. doAssert haystack.find("ABC", start=1) == 9
  217. doAssert haystack.find("ABC", start=9) == 9
  218. doAssert haystack.find("ABC", start=10) == -1
  219. # both start and last arguments
  220. doAssert haystack.find("ABC", start=0, last=14) == 0
  221. doAssert haystack.find("ABC", start=0, last=13) == 0
  222. doAssert haystack.find("ABC", start=0, last=12) == 0
  223. doAssert haystack.find("ABC", start=1, last=13) == 9
  224. doAssert haystack.find("ABC", start=1, last=12) == 9
  225. doAssert haystack.find("ABC", start=1, last=11) == 9
  226. doAssert haystack.find("ABC", start=1, last=10) == -1
  227. doAssert "".find("/") == -1
  228. doAssert "/".find("/") == 0
  229. doAssert "/".find("//") == -1
  230. doAssert "///".find("//", start=3) == -1
  231. # searching for empty string
  232. doAssert "".find("") == 0
  233. doAssert "abc".find("") == 0
  234. doAssert "abc".find("", start=1) == 1
  235. doAssert "abc".find("", start=2) == 2
  236. doAssert "abc".find("", start=3) == 3
  237. doAssert "abc".find("", start=4) == -1
  238. doAssert "abc".find("", start=400) == -1
  239. doAssert "abc".find("", start=1, last=3) == 1
  240. doAssert "abc".find("", start=1, last=2) == 1
  241. doAssert "abc".find("", start=1, last=1) == 1
  242. doAssert "abc".find("", start=1, last=0) == 1
  243. doAssert "abc".find("", start=1, last = -1) == 1
  244. # when last <= start, searching for non-empty string
  245. block:
  246. let last: int = -1
  247. doAssert "abcd".find("ab", start=0, last=last) == -1
  248. doAssert "abcd".find("ab", start=1, last=last) == -1
  249. doAssert "abcd".find("bc", start=1, last=last) == -1
  250. doAssert "abcd".find("bc", start=2, last=last) == -1
  251. block:
  252. let last: int = 0
  253. doAssert "abcd".find("ab", start=0, last=last) == 0
  254. doAssert "abcd".find("ab", start=1, last=last) == -1
  255. doAssert "abcd".find("bc", start=1, last=last) == 1
  256. doAssert "abcd".find("bc", start=2, last=last) == -1
  257. block:
  258. let last: int = 1
  259. doAssert "abcd".find("ab", start=0, last=last) == 0
  260. doAssert "abcd".find("ab", start=1, last=last) == -1
  261. doAssert "abcd".find("bc", start=1, last=last) == -1
  262. doAssert "abcd".find("bc", start=2, last=last) == -1
  263. block: # rfind
  264. doAssert "0123456789ABCDEFGAH".rfind('A') == 17
  265. doAssert "0123456789ABCDEFGAH".rfind('A', last=13) == 10
  266. doAssert "0123456789ABCDEFGAH".rfind('H', last=13) == -1
  267. doAssert "0123456789ABCDEFGAH".rfind("A") == 17
  268. doAssert "0123456789ABCDEFGAH".rfind("A", last=13) == 10
  269. doAssert "0123456789ABCDEFGAH".rfind("H", last=13) == -1
  270. doAssert "0123456789ABCDEFGAH".rfind({'A'..'C'}) == 17
  271. doAssert "0123456789ABCDEFGAH".rfind({'A'..'C'}, last=13) == 12
  272. doAssert "0123456789ABCDEFGAH".rfind({'G'..'H'}, last=13) == -1
  273. doAssert "0123456789ABCDEFGAH".rfind('A', start=18) == -1
  274. doAssert "0123456789ABCDEFGAH".rfind('A', start=11, last=17) == 17
  275. doAssert "0123456789ABCDEFGAH".rfind("0", start=0) == 0
  276. doAssert "0123456789ABCDEFGAH".rfind("0", start=1) == -1
  277. doAssert "0123456789ABCDEFGAH".rfind("H", start=11) == 18
  278. doAssert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=5) == 9
  279. doAssert "0123456789ABCDEFGAH".rfind({'0'..'9'}, start=10) == -1
  280. doAssert "/1/2/3".rfind('/') == 4
  281. doAssert "/1/2/3".rfind('/', last=1) == 0
  282. doAssert "/1/2/3".rfind('0') == -1
  283. block:
  284. const haystack: string = "ABCABABABABCAB"
  285. doAssert haystack.len == 14
  286. doAssert haystack.rfind("ABC") == 9
  287. doAssert haystack.rfind("ABC", last=13) == 9
  288. doAssert haystack.rfind("ABC", last=12) == 9
  289. doAssert haystack.rfind("ABC", last=11) == 9
  290. doAssert haystack.rfind("ABC", last=10) == 0
  291. doAssert haystack.rfind("ABC", start=0) == 9
  292. doAssert haystack.rfind("ABC", start=1) == 9
  293. doAssert haystack.rfind("ABC", start=9) == 9
  294. doAssert haystack.rfind("ABC", start=10) == -1
  295. doAssert haystack.rfind("ABC", start=0, last=13) == 9
  296. doAssert haystack.rfind("ABC", start=0, last=12) == 9
  297. doAssert haystack.rfind("ABC", start=0, last=11) == 9
  298. doAssert haystack.rfind("ABC", start=0, last=10) == 0
  299. doAssert haystack.rfind("ABC", start=1, last=10) == -1
  300. doAssert "".rfind("/") == -1
  301. doAssert "/".rfind("/") == 0
  302. doAssert "/".rfind("//") == -1
  303. doAssert "///".rfind("//", start=3) == -1
  304. # searching for empty string
  305. doAssert "".rfind("") == -1
  306. doAssert "abc".rfind("") == -1
  307. doAssert "abc".rfind("", start=1) == -1
  308. doAssert "abc".rfind("", start=2) == -1
  309. doAssert "abc".rfind("", start=3) == -1
  310. doAssert "abc".rfind("", start=4) == -1
  311. doAssert "abc".rfind("", start=400) == -1
  312. doAssert "abc".rfind("", start=1, last=3) == -1
  313. doAssert "abc".rfind("", start=1, last=2) == -1
  314. doAssert "abc".rfind("", start=1, last=1) == -1
  315. doAssert "abc".rfind("", start=1, last=0) == -1
  316. doAssert "abc".rfind("", start=1, last = -1) == -1
  317. # when last <= start, searching for non-empty string
  318. block:
  319. let last: int = -1
  320. doAssert "abcd".rfind("ab", start=0, last=last) == 0
  321. doAssert "abcd".rfind("ab", start=1, last=last) == -1
  322. doAssert "abcd".rfind("bc", start=1, last=last) == 1
  323. doAssert "abcd".rfind("bc", start=2, last=last) == -1
  324. block:
  325. let last: int = 0
  326. doAssert "abcd".rfind("ab", start=0, last=last) == -1
  327. doAssert "abcd".rfind("ab", start=1, last=last) == -1
  328. doAssert "abcd".rfind("bc", start=1, last=last) == -1
  329. doAssert "abcd".rfind("bc", start=2, last=last) == -1
  330. block:
  331. let last: int = 1
  332. doAssert "abcd".rfind("ab", start=0, last=last) == 0
  333. doAssert "abcd".rfind("ab", start=1, last=last) == -1
  334. doAssert "abcd".rfind("bc", start=1, last=last) == -1
  335. doAssert "abcd".rfind("bc", start=2, last=last) == -1
  336. block: # trimZeros
  337. var x = "1200"
  338. x.trimZeros()
  339. doAssert x == "1200"
  340. x = "120.0"
  341. x.trimZeros()
  342. doAssert x == "120"
  343. x = "0."
  344. x.trimZeros()
  345. doAssert x == "0"
  346. x = "1.0e2"
  347. x.trimZeros()
  348. doAssert x == "1e2"
  349. x = "78.90"
  350. x.trimZeros()
  351. doAssert x == "78.9"
  352. x = "1.23e4"
  353. x.trimZeros()
  354. doAssert x == "1.23e4"
  355. x = "1.01"
  356. x.trimZeros()
  357. doAssert x == "1.01"
  358. x = "1.1001"
  359. x.trimZeros()
  360. doAssert x == "1.1001"
  361. x = "0.0"
  362. x.trimZeros()
  363. doAssert x == "0"
  364. x = "0.01"
  365. x.trimZeros()
  366. doAssert x == "0.01"
  367. x = "1e0"
  368. x.trimZeros()
  369. doAssert x == "1e0"
  370. block: # countLines
  371. proc assertCountLines(s: string) = doAssert s.countLines == s.splitLines.len
  372. assertCountLines("")
  373. assertCountLines("\n")
  374. assertCountLines("\n\n")
  375. assertCountLines("abc")
  376. assertCountLines("abc\n123")
  377. assertCountLines("abc\n123\n")
  378. assertCountLines("\nabc\n123")
  379. assertCountLines("\nabc\n123\n")
  380. block: # parseBinInt, parseHexInt, parseOctInt
  381. # binary
  382. doAssert "0b1111".parseBinInt == 15
  383. doAssert "0B1111".parseBinInt == 15
  384. doAssert "1111".parseBinInt == 15
  385. doAssert "1110".parseBinInt == 14
  386. doAssert "1_1_1_1".parseBinInt == 15
  387. doAssert "0b1_1_1_1".parseBinInt == 15
  388. rejectParse "".parseBinInt
  389. rejectParse "_".parseBinInt
  390. rejectParse "0b".parseBinInt
  391. rejectParse "0b1234".parseBinInt
  392. # hex
  393. doAssert "0x72".parseHexInt == 114
  394. doAssert "0X72".parseHexInt == 114
  395. doAssert "#72".parseHexInt == 114
  396. doAssert "72".parseHexInt == 114
  397. doAssert "FF".parseHexInt == 255
  398. doAssert "ff".parseHexInt == 255
  399. doAssert "fF".parseHexInt == 255
  400. doAssert "0x7_2".parseHexInt == 114
  401. rejectParse "".parseHexInt
  402. rejectParse "_".parseHexInt
  403. rejectParse "0x".parseHexInt
  404. rejectParse "0xFFG".parseHexInt
  405. rejectParse "reject".parseHexInt
  406. # octal
  407. doAssert "0o17".parseOctInt == 15
  408. doAssert "0O17".parseOctInt == 15
  409. doAssert "17".parseOctInt == 15
  410. doAssert "10".parseOctInt == 8
  411. doAssert "0o1_0_0".parseOctInt == 64
  412. rejectParse "".parseOctInt
  413. rejectParse "_".parseOctInt
  414. rejectParse "0o".parseOctInt
  415. rejectParse "9".parseOctInt
  416. rejectParse "0o9".parseOctInt
  417. rejectParse "reject".parseOctInt
  418. block: # parseHexStr
  419. doAssert "".parseHexStr == ""
  420. doAssert "00Ff80".parseHexStr == "\0\xFF\x80"
  421. try:
  422. discard "00Ff8".parseHexStr
  423. doAssert false, "Should raise ValueError"
  424. except ValueError:
  425. discard
  426. try:
  427. discard "0k".parseHexStr
  428. doAssert false, "Should raise ValueError"
  429. except ValueError:
  430. discard
  431. doAssert "".toHex == ""
  432. doAssert "\x00\xFF\x80".toHex == "00FF80"
  433. doAssert "0123456789abcdef".parseHexStr.toHex == "0123456789ABCDEF"
  434. block: # toHex
  435. doAssert(toHex(100i16, 32) == "00000000000000000000000000000064")
  436. doAssert(toHex(-100i16, 32) == "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFF9C")
  437. when not defined js:
  438. doAssert(toHex(high(uint64)) == "FFFFFFFFFFFFFFFF")
  439. doAssert(toHex(high(uint64), 16) == "FFFFFFFFFFFFFFFF")
  440. doAssert(toHex(high(uint64), 32) == "0000000000000000FFFFFFFFFFFFFFFF")
  441. block: # insertSep
  442. doAssert(insertSep($1000_000) == "1_000_000")
  443. doAssert(insertSep($232) == "232")
  444. doAssert(insertSep($12345, ',') == "12,345")
  445. doAssert(insertSep($0) == "0")
  446. block: # repeat, spaces
  447. doAssert(' '.repeat(8) == " ")
  448. doAssert(" ".repeat(8) == " ")
  449. doAssert(spaces(8) == " ")
  450. doAssert(' '.repeat(0) == "")
  451. doAssert(" ".repeat(0) == "")
  452. doAssert(spaces(0) == "")
  453. block: # toBin, toOct
  454. block:# bug #11369
  455. var num: int64 = -1
  456. when not defined js:
  457. doAssert num.toBin(64) == "1111111111111111111111111111111111111111111111111111111111111111"
  458. doAssert num.toOct(24) == "001777777777777777777777"
  459. block: # replace
  460. doAssert "oo".replace("", "abc") == "oo"
  461. # bug #8911
  462. static:
  463. let a = ""
  464. let a2 = a.replace("\n", "\\n")
  465. static:
  466. let b = "b"
  467. let b2 = b.replace("\n", "\\n")
  468. block:
  469. let c = ""
  470. let c2 = c.replace("\n", "\\n")
  471. block: # replaceWord
  472. doAssert "-ld a-ldz -ld".replaceWord("-ld") == " a-ldz "
  473. doAssert "-lda-ldz -ld abc".replaceWord("-ld") == "-lda-ldz abc"
  474. doAssert "-lda-ldz -ld abc".replaceWord("") == "-lda-ldz -ld abc"
  475. block: # multiReplace
  476. doAssert "abba".multiReplace(("a", "b"), ("b", "a")) == "baab"
  477. doAssert "Hello World.".multiReplace(("ello", "ELLO"), ("World.",
  478. "PEOPLE!")) == "HELLO PEOPLE!"
  479. doAssert "aaaa".multiReplace(("a", "aa"), ("aa", "bb")) == "aaaaaaaa"
  480. # `parseEnum`, ref issue #14030
  481. # check enum defined at top level # xxx this is probably irrelevant, and pollutes scope
  482. # for remaining tests
  483. type
  484. Foo = enum
  485. A = -10
  486. B = "bb"
  487. C = (-5, "ccc")
  488. D = 15
  489. E = "ee" # check that we count enum fields correctly
  490. block: # parseEnum
  491. block:
  492. let a = parseEnum[Foo]("A")
  493. let b = parseEnum[Foo]("bb")
  494. let c = parseEnum[Foo]("ccc")
  495. let d = parseEnum[Foo]("D")
  496. let e = parseEnum[Foo]("ee")
  497. doAssert a == A
  498. doAssert b == B
  499. doAssert c == C
  500. doAssert d == D
  501. doAssert e == E
  502. try:
  503. let f = parseEnum[Foo]("Bar")
  504. doAssert false
  505. except ValueError:
  506. discard
  507. # finally using default
  508. let g = parseEnum[Foo]("Bar", A)
  509. doAssert g == A
  510. block: # check enum defined in block
  511. type
  512. Bar = enum
  513. V
  514. W = "ww"
  515. X = (3, "xx")
  516. Y = 10
  517. Z = "zz" # check that we count enum fields correctly
  518. let a = parseEnum[Bar]("V")
  519. let b = parseEnum[Bar]("ww")
  520. let c = parseEnum[Bar]("xx")
  521. let d = parseEnum[Bar]("Y")
  522. let e = parseEnum[Bar]("zz")
  523. doAssert a == V
  524. doAssert b == W
  525. doAssert c == X
  526. doAssert d == Y
  527. doAssert e == Z
  528. try:
  529. let f = parseEnum[Bar]("Baz")
  530. doAssert false
  531. except ValueError:
  532. discard
  533. # finally using default
  534. let g = parseEnum[Bar]("Baz", V)
  535. doAssert g == V
  536. block: # check ambiguous enum fails to parse
  537. type
  538. Ambig = enum
  539. f1 = "A"
  540. f2 = "B"
  541. f3 = "A"
  542. doAssert not compiles((let a = parseEnum[Ambig]("A")))
  543. block: # check almost ambiguous enum
  544. type
  545. AlmostAmbig = enum
  546. f1 = "someA"
  547. f2 = "someB"
  548. f3 = "SomeA"
  549. let a = parseEnum[AlmostAmbig]("someA")
  550. let b = parseEnum[AlmostAmbig]("someB")
  551. let c = parseEnum[AlmostAmbig]("SomeA")
  552. doAssert a == f1
  553. doAssert b == f2
  554. doAssert c == f3
  555. block: # parseEnum TODO: merge above
  556. type MyEnum = enum enA, enB, enC, enuD, enE
  557. doAssert parseEnum[MyEnum]("enu_D") == enuD
  558. doAssert parseEnum("invalid enum value", enC) == enC
  559. block: # indentation
  560. doAssert 0 == indentation """
  561. hey
  562. low
  563. there
  564. """
  565. doAssert 2 == indentation """
  566. hey
  567. low
  568. there
  569. """
  570. doAssert 2 == indentation """ hey
  571. low
  572. there
  573. """
  574. doAssert 2 == indentation """ hey
  575. low
  576. there"""
  577. doAssert 0 == indentation ""
  578. doAssert 0 == indentation " \n \n"
  579. doAssert 0 == indentation " "
  580. block: # indent
  581. doAssert " foo\n bar".indent(4, "Q") == "QQQQ foo\nQQQQ bar"
  582. block: # unindent
  583. doAssert """~~!!foo
  584. ~~!!bar
  585. ~~!!baz""".unindent(2, "~~!!") == "foo\nbar\nbaz"
  586. doAssert """~~!!foo
  587. ~~!!bar
  588. ~~!!baz""".unindent(2, "~~!!aa") == "~~!!foo\n~~!!bar\n~~!!baz"
  589. doAssert """~~foo
  590. ~~ bar
  591. ~~ baz""".unindent(4, "~") == "foo\n bar\n baz"
  592. doAssert """foo
  593. bar
  594. baz
  595. """.unindent(4) == "foo\nbar\nbaz\n"
  596. doAssert """foo
  597. bar
  598. baz
  599. """.unindent(2) == "foo\n bar\n baz\n"
  600. doAssert """foo
  601. bar
  602. baz
  603. """.unindent(100) == "foo\nbar\nbaz\n"
  604. doAssert """foo
  605. foo
  606. bar
  607. """.unindent() == "foo\nfoo\nbar\n"
  608. block: # formatBiggestFloat
  609. disableVm:
  610. doAssert formatBiggestFloat(1234.567, ffDecimal, -1) == "1234.567000"
  611. when not defined(js):
  612. doAssert formatBiggestFloat(1234.567, ffDecimal, 0) == "1235." # bugs 8242, 12586
  613. doAssert formatBiggestFloat(1234.567, ffDecimal, 1) == "1234.6"
  614. doAssert formatBiggestFloat(0.00000000001, ffDecimal, 11) == "0.00000000001"
  615. doAssert formatBiggestFloat(0.00000000001, ffScientific, 1, ',') in
  616. ["1,0e-11", "1,0e-011"]
  617. block: # formatFloat
  618. disableVm:
  619. # bug #6589
  620. when not defined(js):
  621. doAssert formatFloat(123.456, ffScientific, precision = -1) == "1.234560e+02"
  622. block: # `%`
  623. doAssert "$# $3 $# $#" % ["a", "b", "c"] == "a c b c"
  624. doAssert "${1}12 ${-1}$2" % ["a", "b"] == "a12 bb"
  625. doAssert "$animal eats $food." % ["animal", "The cat", "food", "fish"] ==
  626. "The cat eats fish."
  627. block: # formatSize
  628. disableVm:
  629. when not defined(js):
  630. doAssert formatSize((1'i64 shl 31) + (300'i64 shl 20)) == "2.293GiB" # <=== bug #8231
  631. doAssert formatSize((2.234*1024*1024).int) == "2.234MiB"
  632. doAssert formatSize(4096) == "4KiB"
  633. doAssert formatSize(4096, prefix = bpColloquial, includeSpace = true) == "4 kB"
  634. doAssert formatSize(4096, includeSpace = true) == "4 KiB"
  635. doAssert formatSize(5_378_934, prefix = bpColloquial, decimalSep = ',') == "5,13MB"
  636. block: # formatEng
  637. disableVm:
  638. doAssert formatEng(0, 2, trim = false) == "0.00"
  639. doAssert formatEng(0, 2) == "0"
  640. doAssert formatEng(53, 2, trim = false) == "53.00"
  641. doAssert formatEng(0.053, 2, trim = false) == "53.00e-3"
  642. doAssert formatEng(0.053, 4, trim = false) == "53.0000e-3"
  643. doAssert formatEng(0.053, 4, trim = true) == "53e-3"
  644. doAssert formatEng(0.053, 0) == "53e-3"
  645. doAssert formatEng(52731234) == "52.731234e6"
  646. doAssert formatEng(-52731234) == "-52.731234e6"
  647. doAssert formatEng(52731234, 1) == "52.7e6"
  648. doAssert formatEng(-52731234, 1) == "-52.7e6"
  649. doAssert formatEng(52731234, 1, decimalSep = ',') == "52,7e6"
  650. doAssert formatEng(-52731234, 1, decimalSep = ',') == "-52,7e6"
  651. doAssert formatEng(4100, siPrefix = true, unit = "V") == "4.1 kV"
  652. doAssert formatEng(4.1, siPrefix = true, unit = "V",
  653. useUnitSpace = true) == "4.1 V"
  654. doAssert formatEng(4.1, siPrefix = true) == "4.1" # Note lack of space
  655. doAssert formatEng(4100, siPrefix = true) == "4.1 k"
  656. doAssert formatEng(4.1, siPrefix = true, unit = "",
  657. useUnitSpace = true) == "4.1 " # Includes space
  658. doAssert formatEng(4100, siPrefix = true, unit = "") == "4.1 k"
  659. doAssert formatEng(4100) == "4.1e3"
  660. doAssert formatEng(4100, unit = "V", useUnitSpace = true) == "4.1e3 V"
  661. doAssert formatEng(4100, unit = "", useUnitSpace = true) == "4.1e3 "
  662. # Don't use SI prefix as number is too big
  663. doAssert formatEng(3.1e22, siPrefix = true, unit = "a",
  664. useUnitSpace = true) == "31e21 a"
  665. # Don't use SI prefix as number is too small
  666. doAssert formatEng(3.1e-25, siPrefix = true, unit = "A",
  667. useUnitSpace = true) == "310e-27 A"
  668. block: # align
  669. doAssert align("abc", 4) == " abc"
  670. doAssert align("a", 0) == "a"
  671. doAssert align("1232", 6) == " 1232"
  672. doAssert align("1232", 6, '#') == "##1232"
  673. block: # alignLeft
  674. doAssert alignLeft("abc", 4) == "abc "
  675. doAssert alignLeft("a", 0) == "a"
  676. doAssert alignLeft("1232", 6) == "1232 "
  677. doAssert alignLeft("1232", 6, '#') == "1232##"
  678. block: # center
  679. doAssert center("foo", 13) == " foo "
  680. doAssert center("foo", 0) == "foo"
  681. doAssert center("foo", 3, fillChar = 'a') == "foo"
  682. doAssert center("foo", 10, fillChar = '\t') == "\t\t\tfoo\t\t\t\t"
  683. block: # count
  684. doAssert count("foofoofoo", "foofoo") == 1
  685. doAssert count("foofoofoo", "foofoo", overlapping = true) == 2
  686. doAssert count("foofoofoo", 'f') == 3
  687. doAssert count("foofoofoobar", {'f', 'b'}) == 4
  688. block: # isAlphaAscii
  689. doAssert isAlphaAscii('r')
  690. doAssert isAlphaAscii('A')
  691. doAssert(not isAlphaAscii('$'))
  692. block: # isAlphaNumeric
  693. doAssert isAlphaNumeric('3')
  694. doAssert isAlphaNumeric('R')
  695. doAssert(not isAlphaNumeric('!'))
  696. block: # isDigit
  697. doAssert isDigit('3')
  698. doAssert(not isDigit('a'))
  699. doAssert(not isDigit('%'))
  700. block: # isSpaceAscii
  701. doAssert isSpaceAscii('\t')
  702. doAssert isSpaceAscii('\l')
  703. doAssert(not isSpaceAscii('A'))
  704. block: # isEmptyOrWhitespace
  705. doAssert(isEmptyOrWhitespace(""))
  706. doAssert(isEmptyOrWhitespace(" "))
  707. doAssert(isEmptyOrWhitespace("\t\l \v\r\f"))
  708. doAssert(not isEmptyOrWhitespace("ABc \td"))
  709. block: # isLowerAscii
  710. doAssert isLowerAscii('a')
  711. doAssert isLowerAscii('z')
  712. doAssert(not isLowerAscii('A'))
  713. doAssert(not isLowerAscii('5'))
  714. doAssert(not isLowerAscii('&'))
  715. doAssert(not isLowerAscii(' '))
  716. block: # isUpperAscii
  717. doAssert isUpperAscii('A')
  718. doAssert(not isUpperAscii('b'))
  719. doAssert(not isUpperAscii('5'))
  720. doAssert(not isUpperAscii('%'))
  721. block: # unescape
  722. doAssert(unescape(r"\x013", "", "") == "\x013")
  723. block: # join
  724. doAssert join(["foo", "bar", "baz"]) == "foobarbaz"
  725. doAssert join(@["foo", "bar", "baz"], ", ") == "foo, bar, baz"
  726. doAssert join([1, 2, 3]) == "123"
  727. doAssert join(@[1, 2, 3], ", ") == "1, 2, 3"
  728. block: # startsWith / endsWith
  729. var s = "abcdef"
  730. doAssert s.startsWith('a')
  731. doAssert s.startsWith('b') == false
  732. doAssert s.endsWith('f')
  733. doAssert s.endsWith('a') == false
  734. doAssert s.endsWith('\0') == false
  735. static: main()
  736. main()