diff options
-rw-r--r-- | src/nre.nim | 33 | ||||
-rw-r--r-- | test/captures.nim | 7 |
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()) |