summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorDmitry Atamanov <data-man@users.noreply.github.com>2018-01-05 19:36:56 +0300
committerAndreas Rumpf <rumpf_a@web.de>2018-01-05 17:36:56 +0100
commit6ca563dd2e6380e4e2062b9129f582a4910baf68 (patch)
tree07352b88c2baaf7012906f12d74e33ccf1afe09d
parent6cf8a72d498f5cb8a532c2ff3259bc7aecf474ef (diff)
downloadNim-6ca563dd2e6380e4e2062b9129f582a4910baf68.tar.gz
Add a more number parsers to the scanf macro (#6985)
-rw-r--r--lib/pure/parseutils.nim17
-rw-r--r--lib/pure/strscans.nim33
2 files changed, 48 insertions, 2 deletions
diff --git a/lib/pure/parseutils.nim b/lib/pure/parseutils.nim
index a602b0e1b..57387e62e 100644
--- a/lib/pure/parseutils.nim
+++ b/lib/pure/parseutils.nim
@@ -87,6 +87,23 @@ proc parseOct*(s: string, number: var int, start = 0): int  {.
     inc(i)
   if foundDigit: result = i-start
 
+proc parseBin*(s: string, number: var int, start = 0): int  {.
+  rtl, extern: "npuParseBin", noSideEffect.} =
+  ## parses an binary number and stores its value in ``number``. Returns
+  ## the number of the parsed characters or 0 in case of an error.
+  var i = start
+  var foundDigit = false
+  if s[i] == '0' and (s[i+1] == 'b' or s[i+1] == 'B'): inc(i, 2)
+  while true:
+    case s[i]
+    of '_': discard
+    of '0'..'1':
+      number = number shl 1 or (ord(s[i]) - ord('0'))
+      foundDigit = true
+    else: break
+    inc(i)
+  if foundDigit: result = i-start
+
 proc parseIdent*(s: string, ident: var string, start = 0): int =
   ## parses an identifier and stores it in ``ident``. Returns
   ## the number of the parsed characters or 0 in case of an error.
diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim
index f33e7451f..42bb281eb 100644
--- a/lib/pure/strscans.nim
+++ b/lib/pure/strscans.nim
@@ -31,7 +31,10 @@ As can be seen from the examples, strings are matched verbatim except for
 substrings starting with ``$``. These constructions are available:
 
 =================   ========================================================
-``$i``              Matches an integer. This uses ``parseutils.parseInt``.
+``$b``              Matches an decimal integer. This uses ``parseutils.parseBin``.
+``$o``              Matches an octal integer. This uses ``parseutils.parseOct``.
+``$i``              Matches an decimal integer. This uses ``parseutils.parseInt``.
+``$h``              Matches an hex integer. This uses ``parseutils.parseHex``.
 ``$f``              Matches a floating pointer number. Uses ``parseFloat``.
 ``$w``              Matches an ASCII identifier: ``[A-Z-a-z_][A-Za-z_0-9]*``.
 ``$s``              Skips optional whitespace.
@@ -335,11 +338,29 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
         else:
           error("no string var given for $w")
         inc i
+      of 'b':
+        if i < results.len or getType(results[i]).typeKind != ntyInt:
+          matchBind "parseBin"
+        else:
+          error("no int var given for $b")
+        inc i
+      of 'o':
+        if i < results.len or getType(results[i]).typeKind != ntyInt:
+          matchBind "parseOct"
+        else:
+          error("no int var given for $o")
+        inc i
       of 'i':
         if i < results.len or getType(results[i]).typeKind != ntyInt:
           matchBind "parseInt"
         else:
-          error("no int var given for $d")
+          error("no int var given for $i")
+        inc i
+      of 'h':
+        if i < results.len or getType(results[i]).typeKind != ntyInt:
+          matchBind "parseHex"
+        else:
+          error("no int var given for $h")
         inc i
       of 'f':
         if i < results.len or getType(results[i]).typeKind != ntyFloat:
@@ -645,6 +666,14 @@ when isMainModule:
   doAssert intval == 89
   doAssert floatVal == 33.25
 
+  var binval: int
+  var octval: int
+  var hexval: int
+  doAssert scanf("0b0101 0o1234 0xabcd", "$b$s$o$s$h", binval, octval, hexval)
+  doAssert binval == 0b0101
+  doAssert octval == 0o1234
+  doAssert hexval == 0xabcd
+
   let xx = scanf("$abc", "$$$i", intval)
   doAssert xx == false