Merge pull request #1842 from def-/unicode-reversed

Add reversed proc to unicode module
This commit is contained in:
Varriount
2015-01-17 18:53:46 -05:00

View File

@@ -1194,6 +1194,17 @@ proc isWhiteSpace*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
if p >= 0 and c >= spaceRanges[p] and c <= spaceRanges[p+1]:
return true
proc isCombining*(c: Rune): bool {.rtl, extern: "nuc$1", procvar.} =
## returns true iff `c` is a Unicode combining character
var c = RuneImpl(c)
# Optimized to return false immediately for ASCII
return c >= 0x0300 and (c <= 0x036f or
(c >= 0x1ab0 and c <= 0x1aff) or
(c >= 0x1dc0 and c <= 0x1dff) or
(c >= 0x20d0 and c <= 0x20ff) or
(c >= 0xfe20 and c <= 0xfe2f))
iterator runes*(s: string): Rune =
## iterates over any unicode character of the string `s`.
var
@@ -1220,9 +1231,48 @@ proc cmpRunesIgnoreCase*(a, b: string): int {.rtl, extern: "nuc$1", procvar.} =
if result != 0: return
result = a.len - b.len
proc reversed*(s: string): string =
## returns the reverse of `s`, interpreting it as unicode characters. Unicode
## combining characters are correctly interpreted as well:
##
## .. code-block:
## assert reversed("Reverse this!") == "!siht esreveR"
## assert reversed("先秦兩漢") == "漢兩秦先"
## assert reversed("as⃝df̅") == "f̅ds⃝a"
## assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"
var
i = 0
lastI = 0
newPos = len(s) - 1
blockPos = 0
r: Rune
template reverseUntil(pos): stmt =
var j = pos - 1
while j > blockPos:
result[newPos] = s[j]
dec j
dec newPos
blockPos = pos - 1
result = newString(len(s))
while i < len(s):
lastI = i
fastRuneAt(s, i, r, true)
if not isCombining(r):
reverseUntil(lastI)
reverseUntil(len(s))
when isMainModule:
let
someString = "öÑ"
someRunes = @[runeAt(someString, 0), runeAt(someString, 2)]
compared = (someString == $someRunes)
assert compared == true
assert reversed("Reverse this!") == "!siht esreveR"
assert reversed("先秦兩漢") == "漢兩秦先"
assert reversed("as⃝df̅") == "f̅ds⃝a"
assert reversed("a⃞b⃞c⃞") == "c⃞b⃞a⃞"