Untitled

Run Settings
LanguageNim
Language Version
Run Command
type StringSlice* = ref object str: ref string start: int stop: int proc `$`*(str: StringSlice): string = str.str[str.start .. str.stop] proc newStringSlice*(str: string): StringSlice = new result new result.str # result.str = new(ref string) result.str[] = str result.start = 0 result.stop = str.len-1 converter toStringSlice*(str: string): StringSlice = newStringSlice(str) proc `[]`*(str: StringSlice, slc: HSlice[int, int or BackwardsIndex]): StringSlice = if slc.a < 0: raise newException(IndexError, "index out of bounds") new result result.str = str.str result.start = str.start + slc.a when slc.b is BackwardsIndex: if slc.b.int > str.len + 1: raise newException(RangeError, "value out of range: " & $(str.len + 1 - slc.b.int)) result.stop = str.stop - slc.b.int + 1 else: if slc.b + 1 < slc.a or slc.b > str.high: raise newException(IndexError, "index out of bounds") result.stop = str.start + slc.b proc high*(str: StringSlice): int = str.stop - str.start proc len*(str: StringSlice): int = str.high + 1 proc `&`*(sl1, sl2: StringSlice): StringSlice = newStringSlice($sl1 & $sl2) proc startsWith*[T: StringSlice or string](str: StringSlice, sub: T): bool = if sub.len > str.len: return false when T is StringSlice: for i in sub.start..sub.stop: if str.str[i + str.start - sub.start] != sub.str[i]: return false else: for idx, c in sub: if str.str[idx + str.start] != c: return false return true proc `==`*[T: StringSlice or string](str: StringSlice, cmp: T): bool = if cmp.isNil(): return false if str.len != cmp.len: return false when T is StringSlice: for i in cmp.start..cmp.stop: if str.str[i + str.start - cmp.start] != cmp.str[i]: return false return true else: return str.startsWith(cmp) import strutils proc find*(a: SkipTable, s: StringSlice, sub: string, start: Natural = 0, last: Natural = 0): int = ## Searches for `sub` in `s` inside range `start`..`last` using preprocessed table `a`. ## If `last` is unspecified, it defaults to `s.high`. ## ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. let last = if last==0: s.high else: last m = len(sub) n = last + 1 # search: var j = start while j <= n - m: block match: for k in 0..m-1: if sub[k] != s.str[s.start + k+j]: break match return j inc(j, a[s.str[s.start + j+m]]) return -1 when not (defined(js) or defined(nimdoc) or defined(nimscript)): proc c_memchr(cstr: pointer, c: char, n: csize): pointer {. importc: "memchr", header: "<string.h>" .} const hasCStringBuiltin = true else: const hasCStringBuiltin = false proc find*(s: StringSlice, sub: char, start: Natural = 0, last: Natural = 0): int = ## Searches for `sub` in `s` inside range `start`..`last`. ## If `last` is unspecified, it defaults to `s.high`. ## ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. let last = if last==0: s.high else: last when nimvm: for i in start..last: if sub == s.str[s.start + i]: return i else: when hasCStringBuiltin: let found = c_memchr(s.str[s.start + start].unsafeAddr, sub, last-start+1) if not found.isNil: return cast[ByteAddress](found) -% cast[ByteAddress](s.str[s.start]) else: for i in start..last: if sub == s.str[s.start + i]: return i return -1 proc find*(s: StringSlice, sub: string, start: Natural = 0, last: Natural = 0): int = ## Searches for `sub` in `s` inside range `start`..`last`. ## If `last` is unspecified, it defaults to `s.high`. ## ## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned. if sub.len > s.len: return -1 if sub.len == 1: return find(s, sub[0], start, last) var a {.noinit.}: SkipTable initSkipTable(a, sub) result = find(a, s, sub, start, last) proc find*(s, sub: StringSlice): int = s.find($sub) proc strip*(s: StringSlice, first = true, last = true): StringSlice = new result result.str = s.str result.start = s.start result.stop = s.stop if first: for i in result.start..result.stop: if not (result.str[i] in Whitespace): break result.start += 1 if last: for i in countdown(result.stop, result.start): if not (result.str[i] in Whitespace): break result.stop -= 1 iterator items*(a: StringSlice): char = for i in a.start..a.stop: yield a.str[i] proc testStuff() = var s = newStringSlice("Hello world") var x = s[0 .. ^1][1 .. ^2][0 .. ^1] s.str[][5] = 'c' echo x echo x.startsWith("elloc") echo s.high echo s.find("worl") echo x.find("work") static: echo("--compiletime--") teststuff() echo("--runtime--") testStuff()
Editor Settings
Theme
Key bindings
Full width
Lines