summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--src/nre.nim33
-rw-r--r--test/captures.nim7
2 files changed, 39 insertions, 1 deletions
diff --git a/src/nre.nim b/src/nre.nim
index feae0c228..3f06d33bb 100644
--- a/src/nre.nim
+++ b/src/nre.nim
@@ -2,7 +2,7 @@ import private.pcre as pcre
 import private.util
 import tables
 import unsigned
-from strutils import toLower
+from strutils import toLower, `%`
 
 # PCRE Options {{{
 
@@ -100,3 +100,34 @@ proc initRegex*(pattern: string, options = "Sx"): Regex =
     result.pcreExtra = pcre.study(result.pcreObj, 0x0, addr errorMsg)
     if result.pcreExtra == nil:
       raise StudyError(msg: $errorMsg)
+
+proc getinfo[T](self: Regex, opt: cint): T =
+  let retcode = pcre.fullinfo(self.pcreObj, self.pcreExtra, opt, addr result)
+
+  if retcode < 0:
+    raise newException(FieldError, "Invalid getinfo for $1, errno $2" % [$opt, $retcode])
+
+proc getCaptureCount(self: Regex): int =
+  # get the maximum number of captures
+  return getinfo[int](self, pcre.INFO_CAPTURECOUNT)
+
+type UncheckedArray {.unchecked.}[T] = array[0 .. 0, T]
+proc getNameToNumberTable(self: Regex): Table[string, int] =
+  let entryCount = getinfo[cint](self, pcre.INFO_NAMECOUNT)
+  let entrySize = getinfo[cint](self, pcre.INFO_NAMEENTRYSIZE)
+  let table = cast[ptr UncheckedArray[uint8]](
+                getinfo[int](self, pcre.INFO_NAMETABLE))
+
+  result = initTable[string, int]()
+
+  for i in 0 .. <entryCount:
+    let pos = i * entrySize
+    let num = (int(table[pos]) shl 8) or int(table[pos + 1])
+    var name = ""
+
+    var idx = 2
+    while table[pos + idx] != 0:
+      name.add(char(table[pos + idx]))
+      idx += 1
+
+    result[name] = num
diff --git a/test/captures.nim b/test/captures.nim
new file mode 100644
index 000000000..769e9e4f0
--- /dev/null
+++ b/test/captures.nim
@@ -0,0 +1,7 @@
+import unittest
+include nre
+
+suite "captures":
+  test "map capture names to numbers":
+    check(getNameToNumberTable(initRegex("(?<v1>1(?<v2>2(?<v3>3))(?'v4'4))()")) == 
+      { "v1" : 1, "v2" : 2, "v3" : 3, "v4" : 4 }.toTable())