strutils: code cleanups and do not rely on the terminating binary zero anymore
This commit is contained in:
parent
9d77f61038
commit
9b8603adcd
2 changed files with 101 additions and 297 deletions
|
|
@ -63,6 +63,10 @@ proc genLiteral(p: BProc, n: PNode, ty: PType): Rope =
|
||||||
of tyNil:
|
of tyNil:
|
||||||
result = genNilStringLiteral(p.module, n.info)
|
result = genNilStringLiteral(p.module, n.info)
|
||||||
of tyString:
|
of tyString:
|
||||||
|
# with the new semantics for 'nil' strings, we can map "" to nil and
|
||||||
|
# save tons of allocations:
|
||||||
|
#if n.strVal.len == 0: result = genNilStringLiteral(p.module, n.info)
|
||||||
|
#else:
|
||||||
result = genStringLiteral(p.module, n)
|
result = genStringLiteral(p.module, n)
|
||||||
else:
|
else:
|
||||||
if n.strVal.isNil: result = rope("NIM_NIL")
|
if n.strVal.isNil: result = rope("NIM_NIL")
|
||||||
|
|
@ -905,14 +909,9 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||||
if ty.kind in {tyRef, tyPtr}:
|
if ty.kind in {tyRef, tyPtr}:
|
||||||
ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
|
ty = skipTypes(ty.lastSon, abstractVarRange) # emit range check:
|
||||||
if optBoundsCheck in p.options:
|
if optBoundsCheck in p.options:
|
||||||
if ty.kind == tyString:
|
linefmt(p, cpsStmts,
|
||||||
linefmt(p, cpsStmts,
|
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
||||||
"if (!$2 || (NU)($1) > (NU)($2->$3)) #raiseIndexError();$n",
|
rdLoc(b), rdLoc(a), lenField(p))
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
|
||||||
else:
|
|
||||||
linefmt(p, cpsStmts,
|
|
||||||
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
|
|
||||||
rdLoc(b), rdLoc(a), lenField(p))
|
|
||||||
if d.k == locNone: d.storage = OnHeap
|
if d.k == locNone: d.storage = OnHeap
|
||||||
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
if skipTypes(a.t, abstractVar).kind in {tyRef, tyPtr}:
|
||||||
a.r = rfmt(nil, "(*$1)", a.r)
|
a.r = rfmt(nil, "(*$1)", a.r)
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,12 @@ proc isUpperAscii*(c: char): bool {.noSideEffect, procvar,
|
||||||
## This checks ASCII characters only.
|
## This checks ASCII characters only.
|
||||||
return c in {'A'..'Z'}
|
return c in {'A'..'Z'}
|
||||||
|
|
||||||
|
template isImpl(call) =
|
||||||
|
if s.len == 0: return false
|
||||||
|
result = true
|
||||||
|
for c in s:
|
||||||
|
if not call(c): return false
|
||||||
|
|
||||||
proc isAlphaAscii*(s: string): bool {.noSideEffect, procvar,
|
proc isAlphaAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsAlphaAsciiStr".} =
|
rtl, extern: "nsuIsAlphaAsciiStr".} =
|
||||||
## Checks whether or not `s` is alphabetical.
|
## Checks whether or not `s` is alphabetical.
|
||||||
|
|
@ -114,12 +120,7 @@ proc isAlphaAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
## Returns true if all characters in `s` are
|
## Returns true if all characters in `s` are
|
||||||
## alphabetic and there is at least one character
|
## alphabetic and there is at least one character
|
||||||
## in `s`.
|
## in `s`.
|
||||||
if s.len() == 0:
|
isImpl isAlphaAscii
|
||||||
return false
|
|
||||||
|
|
||||||
result = true
|
|
||||||
for c in s:
|
|
||||||
if not c.isAlphaAscii(): return false
|
|
||||||
|
|
||||||
proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
|
proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsAlphaNumericStr".} =
|
rtl, extern: "nsuIsAlphaNumericStr".} =
|
||||||
|
|
@ -129,13 +130,7 @@ proc isAlphaNumeric*(s: string): bool {.noSideEffect, procvar,
|
||||||
## Returns true if all characters in `s` are
|
## Returns true if all characters in `s` are
|
||||||
## alpanumeric and there is at least one character
|
## alpanumeric and there is at least one character
|
||||||
## in `s`.
|
## in `s`.
|
||||||
if s.len() == 0:
|
isImpl isAlphaNumeric
|
||||||
return false
|
|
||||||
|
|
||||||
result = true
|
|
||||||
for c in s:
|
|
||||||
if not c.isAlphaNumeric():
|
|
||||||
return false
|
|
||||||
|
|
||||||
proc isDigit*(s: string): bool {.noSideEffect, procvar,
|
proc isDigit*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsDigitStr".} =
|
rtl, extern: "nsuIsDigitStr".} =
|
||||||
|
|
@ -145,13 +140,7 @@ proc isDigit*(s: string): bool {.noSideEffect, procvar,
|
||||||
## Returns true if all characters in `s` are
|
## Returns true if all characters in `s` are
|
||||||
## numeric and there is at least one character
|
## numeric and there is at least one character
|
||||||
## in `s`.
|
## in `s`.
|
||||||
if s.len() == 0:
|
isImpl isDigit
|
||||||
return false
|
|
||||||
|
|
||||||
result = true
|
|
||||||
for c in s:
|
|
||||||
if not c.isDigit():
|
|
||||||
return false
|
|
||||||
|
|
||||||
proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
|
proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsSpaceAsciiStr".} =
|
rtl, extern: "nsuIsSpaceAsciiStr".} =
|
||||||
|
|
@ -159,13 +148,7 @@ proc isSpaceAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
##
|
##
|
||||||
## Returns true if all characters in `s` are whitespace
|
## Returns true if all characters in `s` are whitespace
|
||||||
## characters and there is at least one character in `s`.
|
## characters and there is at least one character in `s`.
|
||||||
if s.len() == 0:
|
isImpl isSpaceAscii
|
||||||
return false
|
|
||||||
|
|
||||||
result = true
|
|
||||||
for c in s:
|
|
||||||
if not c.isSpaceAscii():
|
|
||||||
return false
|
|
||||||
|
|
||||||
proc isLowerAscii*(s: string): bool {.noSideEffect, procvar,
|
proc isLowerAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsLowerAsciiStr".} =
|
rtl, extern: "nsuIsLowerAsciiStr".} =
|
||||||
|
|
@ -174,13 +157,7 @@ proc isLowerAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
## This checks ASCII characters only.
|
## This checks ASCII characters only.
|
||||||
## Returns true if all characters in `s` are lower case
|
## Returns true if all characters in `s` are lower case
|
||||||
## and there is at least one character in `s`.
|
## and there is at least one character in `s`.
|
||||||
if s.len() == 0:
|
isImpl isLowerAscii
|
||||||
return false
|
|
||||||
|
|
||||||
for c in s:
|
|
||||||
if not c.isLowerAscii():
|
|
||||||
return false
|
|
||||||
true
|
|
||||||
|
|
||||||
proc isUpperAscii*(s: string): bool {.noSideEffect, procvar,
|
proc isUpperAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuIsUpperAsciiStr".} =
|
rtl, extern: "nsuIsUpperAsciiStr".} =
|
||||||
|
|
@ -189,13 +166,7 @@ proc isUpperAscii*(s: string): bool {.noSideEffect, procvar,
|
||||||
## This checks ASCII characters only.
|
## This checks ASCII characters only.
|
||||||
## Returns true if all characters in `s` are upper case
|
## Returns true if all characters in `s` are upper case
|
||||||
## and there is at least one character in `s`.
|
## and there is at least one character in `s`.
|
||||||
if s.len() == 0:
|
isImpl isUpperAscii
|
||||||
return false
|
|
||||||
|
|
||||||
for c in s:
|
|
||||||
if not c.isUpperAscii():
|
|
||||||
return false
|
|
||||||
true
|
|
||||||
|
|
||||||
proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
|
proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuToLowerAsciiChar".} =
|
rtl, extern: "nsuToLowerAsciiChar".} =
|
||||||
|
|
@ -209,6 +180,11 @@ proc toLowerAscii*(c: char): char {.noSideEffect, procvar,
|
||||||
else:
|
else:
|
||||||
result = c
|
result = c
|
||||||
|
|
||||||
|
template toImpl(call) =
|
||||||
|
result = newString(len(s))
|
||||||
|
for i in 0..len(s) - 1:
|
||||||
|
result[i] = call(s[i])
|
||||||
|
|
||||||
proc toLowerAscii*(s: string): string {.noSideEffect, procvar,
|
proc toLowerAscii*(s: string): string {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuToLowerAsciiStr".} =
|
rtl, extern: "nsuToLowerAsciiStr".} =
|
||||||
## Converts `s` into lower case.
|
## Converts `s` into lower case.
|
||||||
|
|
@ -216,9 +192,7 @@ proc toLowerAscii*(s: string): string {.noSideEffect, procvar,
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toLower
|
## This works only for the letters ``A-Z``. See `unicode.toLower
|
||||||
## <unicode.html#toLower>`_ for a version that works for any Unicode
|
## <unicode.html#toLower>`_ for a version that works for any Unicode
|
||||||
## character.
|
## character.
|
||||||
result = newString(len(s))
|
toImpl toLowerAscii
|
||||||
for i in 0..len(s) - 1:
|
|
||||||
result[i] = toLowerAscii(s[i])
|
|
||||||
|
|
||||||
proc toUpperAscii*(c: char): char {.noSideEffect, procvar,
|
proc toUpperAscii*(c: char): char {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuToUpperAsciiChar".} =
|
rtl, extern: "nsuToUpperAsciiChar".} =
|
||||||
|
|
@ -239,147 +213,15 @@ proc toUpperAscii*(s: string): string {.noSideEffect, procvar,
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toUpper
|
## This works only for the letters ``A-Z``. See `unicode.toUpper
|
||||||
## <unicode.html#toUpper>`_ for a version that works for any Unicode
|
## <unicode.html#toUpper>`_ for a version that works for any Unicode
|
||||||
## character.
|
## character.
|
||||||
result = newString(len(s))
|
toImpl toUpperAscii
|
||||||
for i in 0..len(s) - 1:
|
|
||||||
result[i] = toUpperAscii(s[i])
|
|
||||||
|
|
||||||
proc capitalizeAscii*(s: string): string {.noSideEffect, procvar,
|
proc capitalizeAscii*(s: string): string {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuCapitalizeAscii".} =
|
rtl, extern: "nsuCapitalizeAscii".} =
|
||||||
## Converts the first character of `s` into upper case.
|
## Converts the first character of `s` into upper case.
|
||||||
##
|
##
|
||||||
## This works only for the letters ``A-Z``.
|
## This works only for the letters ``A-Z``.
|
||||||
result = toUpperAscii(s[0]) & substr(s, 1)
|
if s.len == 0: result = ""
|
||||||
|
else: result = toUpperAscii(s[0]) & substr(s, 1)
|
||||||
proc isSpace*(c: char): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsSpaceChar".}=
|
|
||||||
## Checks whether or not `c` is a whitespace character.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isSpaceAscii`` instead.
|
|
||||||
isSpaceAscii(c)
|
|
||||||
|
|
||||||
proc isLower*(c: char): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsLowerChar".}=
|
|
||||||
## Checks whether or not `c` is a lower case character.
|
|
||||||
##
|
|
||||||
## This checks ASCII characters only.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isLowerAscii`` instead.
|
|
||||||
isLowerAscii(c)
|
|
||||||
|
|
||||||
proc isUpper*(c: char): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsUpperChar".}=
|
|
||||||
## Checks whether or not `c` is an upper case character.
|
|
||||||
##
|
|
||||||
## This checks ASCII characters only.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isUpperAscii`` instead.
|
|
||||||
isUpperAscii(c)
|
|
||||||
|
|
||||||
proc isAlpha*(c: char): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsAlphaChar".}=
|
|
||||||
## Checks whether or not `c` is alphabetical.
|
|
||||||
##
|
|
||||||
## This checks a-z, A-Z ASCII characters only.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isAlphaAscii`` instead.
|
|
||||||
isAlphaAscii(c)
|
|
||||||
|
|
||||||
proc isAlpha*(s: string): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsAlphaStr".}=
|
|
||||||
## Checks whether or not `s` is alphabetical.
|
|
||||||
##
|
|
||||||
## This checks a-z, A-Z ASCII characters only.
|
|
||||||
## Returns true if all characters in `s` are
|
|
||||||
## alphabetic and there is at least one character
|
|
||||||
## in `s`.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isAlphaAscii`` instead.
|
|
||||||
isAlphaAscii(s)
|
|
||||||
|
|
||||||
proc isSpace*(s: string): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsSpaceStr".}=
|
|
||||||
## Checks whether or not `s` is completely whitespace.
|
|
||||||
##
|
|
||||||
## Returns true if all characters in `s` are whitespace
|
|
||||||
## characters and there is at least one character in `s`.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isSpaceAscii`` instead.
|
|
||||||
isSpaceAscii(s)
|
|
||||||
|
|
||||||
proc isLower*(s: string): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsLowerStr".}=
|
|
||||||
## Checks whether or not `s` contains all lower case characters.
|
|
||||||
##
|
|
||||||
## This checks ASCII characters only.
|
|
||||||
## Returns true if all characters in `s` are lower case
|
|
||||||
## and there is at least one character in `s`.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isLowerAscii`` instead.
|
|
||||||
isLowerAscii(s)
|
|
||||||
|
|
||||||
proc isUpper*(s: string): bool {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuIsUpperStr".}=
|
|
||||||
## Checks whether or not `s` contains all upper case characters.
|
|
||||||
##
|
|
||||||
## This checks ASCII characters only.
|
|
||||||
## Returns true if all characters in `s` are upper case
|
|
||||||
## and there is at least one character in `s`.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``isUpperAscii`` instead.
|
|
||||||
isUpperAscii(s)
|
|
||||||
|
|
||||||
proc toLower*(c: char): char {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuToLowerChar".} =
|
|
||||||
## Converts `c` into lower case.
|
|
||||||
##
|
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toLower
|
|
||||||
## <unicode.html#toLower>`_ for a version that works for any Unicode
|
|
||||||
## character.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``toLowerAscii`` instead.
|
|
||||||
toLowerAscii(c)
|
|
||||||
|
|
||||||
proc toLower*(s: string): string {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuToLowerStr".} =
|
|
||||||
## Converts `s` into lower case.
|
|
||||||
##
|
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toLower
|
|
||||||
## <unicode.html#toLower>`_ for a version that works for any Unicode
|
|
||||||
## character.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``toLowerAscii`` instead.
|
|
||||||
toLowerAscii(s)
|
|
||||||
|
|
||||||
proc toUpper*(c: char): char {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuToUpperChar".} =
|
|
||||||
## Converts `c` into upper case.
|
|
||||||
##
|
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toUpper
|
|
||||||
## <unicode.html#toUpper>`_ for a version that works for any Unicode
|
|
||||||
## character.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``toUpperAscii`` instead.
|
|
||||||
toUpperAscii(c)
|
|
||||||
|
|
||||||
proc toUpper*(s: string): string {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuToUpperStr".} =
|
|
||||||
## Converts `s` into upper case.
|
|
||||||
##
|
|
||||||
## This works only for the letters ``A-Z``. See `unicode.toUpper
|
|
||||||
## <unicode.html#toUpper>`_ for a version that works for any Unicode
|
|
||||||
## character.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``toUpperAscii`` instead.
|
|
||||||
toUpperAscii(s)
|
|
||||||
|
|
||||||
proc capitalize*(s: string): string {.noSideEffect, procvar,
|
|
||||||
rtl, deprecated, extern: "nsuCapitalize".} =
|
|
||||||
## Converts the first character of `s` into upper case.
|
|
||||||
##
|
|
||||||
## This works only for the letters ``A-Z``.
|
|
||||||
##
|
|
||||||
## **Deprecated since version 0.15.0**: use ``capitalizeAscii`` instead.
|
|
||||||
capitalizeAscii(s)
|
|
||||||
|
|
||||||
proc normalize*(s: string): string {.noSideEffect, procvar,
|
proc normalize*(s: string): string {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuNormalize".} =
|
rtl, extern: "nsuNormalize".} =
|
||||||
|
|
@ -419,9 +261,9 @@ proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
|
||||||
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
|
proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
|
||||||
rtl, extern: "nsuCmpIgnoreStyle", procvar.} =
|
rtl, extern: "nsuCmpIgnoreStyle", procvar.} =
|
||||||
## Semantically the same as ``cmp(normalize(a), normalize(b))``. It
|
## Semantically the same as ``cmp(normalize(a), normalize(b))``. It
|
||||||
## is just optimized to not allocate temporary strings. This should
|
## is just optimized to not allocate temporary strings. This should
|
||||||
## NOT be used to compare Nim identifier names. use `macros.eqIdent`
|
## NOT be used to compare Nim identifier names. use `macros.eqIdent`
|
||||||
## for that. Returns:
|
## for that. Returns:
|
||||||
##
|
##
|
||||||
## | 0 iff a == b
|
## | 0 iff a == b
|
||||||
## | < 0 iff a < b
|
## | < 0 iff a < b
|
||||||
|
|
@ -429,14 +271,22 @@ proc cmpIgnoreStyle*(a, b: string): int {.noSideEffect,
|
||||||
var i = 0
|
var i = 0
|
||||||
var j = 0
|
var j = 0
|
||||||
while true:
|
while true:
|
||||||
while a[i] == '_': inc(i)
|
while i < a.len and a[i] == '_': inc i
|
||||||
while b[j] == '_': inc(j) # BUGFIX: typo
|
while j < b.len and b[j] == '_': inc j
|
||||||
var aa = toLowerAscii(a[i])
|
var aa = if i < a.len: toLowerAscii(a[i]) else: '\0'
|
||||||
var bb = toLowerAscii(b[j])
|
var bb = if j < b.len: toLowerAscii(b[j]) else: '\0'
|
||||||
result = ord(aa) - ord(bb)
|
result = ord(aa) - ord(bb)
|
||||||
if result != 0 or aa == '\0': break
|
if result != 0: return result
|
||||||
inc(i)
|
# the characters are identical:
|
||||||
inc(j)
|
if i >= a.len:
|
||||||
|
# both cursors at the end:
|
||||||
|
if j >= b.len: return 0
|
||||||
|
# not yet at the end of 'b':
|
||||||
|
return -1
|
||||||
|
elif j >= b.len:
|
||||||
|
return 1
|
||||||
|
inc i
|
||||||
|
inc j
|
||||||
|
|
||||||
proc strip*(s: string, leading = true, trailing = true,
|
proc strip*(s: string, leading = true, trailing = true,
|
||||||
chars: set[char] = Whitespace): string
|
chars: set[char] = Whitespace): string
|
||||||
|
|
@ -451,7 +301,7 @@ proc strip*(s: string, leading = true, trailing = true,
|
||||||
first = 0
|
first = 0
|
||||||
last = len(s)-1
|
last = len(s)-1
|
||||||
if leading:
|
if leading:
|
||||||
while s[first] in chars: inc(first)
|
while first <= last and s[first] in chars: inc(first)
|
||||||
if trailing:
|
if trailing:
|
||||||
while last >= 0 and s[last] in chars: dec(last)
|
while last >= 0 and s[last] in chars: dec(last)
|
||||||
result = substr(s, first, last)
|
result = substr(s, first, last)
|
||||||
|
|
@ -467,7 +317,9 @@ proc toOctal*(c: char): string {.noSideEffect, rtl, extern: "nsuToOctal".} =
|
||||||
result[i] = chr(val mod 8 + ord('0'))
|
result[i] = chr(val mod 8 + ord('0'))
|
||||||
val = val div 8
|
val = val div 8
|
||||||
|
|
||||||
proc isNilOrEmpty*(s: string): bool {.noSideEffect, procvar, rtl, extern: "nsuIsNilOrEmpty".} =
|
proc isNilOrEmpty*(s: string): bool {.noSideEffect, procvar, rtl,
|
||||||
|
extern: "nsuIsNilOrEmpty",
|
||||||
|
deprecated: "use 'x.len == 0' instead".} =
|
||||||
## Checks if `s` is nil or empty.
|
## Checks if `s` is nil or empty.
|
||||||
result = len(s) == 0
|
result = len(s) == 0
|
||||||
|
|
||||||
|
|
@ -486,7 +338,6 @@ proc substrEq(s: string, pos: int, substr: string): bool =
|
||||||
var length = substr.len
|
var length = substr.len
|
||||||
while i < length and s[pos+i] == substr[i]:
|
while i < length and s[pos+i] == substr[i]:
|
||||||
inc i
|
inc i
|
||||||
|
|
||||||
return i == length
|
return i == length
|
||||||
|
|
||||||
# --------- Private templates for different split separators -----------
|
# --------- Private templates for different split separators -----------
|
||||||
|
|
@ -520,7 +371,7 @@ template oldSplit(s, seps, maxsplit) =
|
||||||
var splits = maxsplit
|
var splits = maxsplit
|
||||||
assert(not ('\0' in seps))
|
assert(not ('\0' in seps))
|
||||||
while last < len(s):
|
while last < len(s):
|
||||||
while s[last] in seps: inc(last)
|
while last < len(s) and s[last] in seps: inc(last)
|
||||||
var first = last
|
var first = last
|
||||||
while last < len(s) and s[last] notin seps: inc(last)
|
while last < len(s) and s[last] notin seps: inc(last)
|
||||||
if first <= last-1:
|
if first <= last-1:
|
||||||
|
|
@ -571,10 +422,7 @@ iterator split*(s: string, seps: set[char] = Whitespace,
|
||||||
## "08"
|
## "08"
|
||||||
## "08.398990"
|
## "08.398990"
|
||||||
##
|
##
|
||||||
when defined(nimOldSplit):
|
splitCommon(s, seps, maxsplit, 1)
|
||||||
oldSplit(s, seps, maxsplit)
|
|
||||||
else:
|
|
||||||
splitCommon(s, seps, maxsplit, 1)
|
|
||||||
|
|
||||||
iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
|
iterator splitWhitespace*(s: string, maxsplit: int = -1): string =
|
||||||
## Splits the string ``s`` at whitespace stripping leading and trailing
|
## Splits the string ``s`` at whitespace stripping leading and trailing
|
||||||
|
|
@ -660,7 +508,6 @@ iterator split*(s: string, sep: string, maxsplit: int = -1): string =
|
||||||
## "is"
|
## "is"
|
||||||
## "corrupted"
|
## "corrupted"
|
||||||
##
|
##
|
||||||
|
|
||||||
splitCommon(s, sep, maxsplit, sep.len)
|
splitCommon(s, sep, maxsplit, sep.len)
|
||||||
|
|
||||||
template rsplitCommon(s, sep, maxsplit, sepLen) =
|
template rsplitCommon(s, sep, maxsplit, sepLen) =
|
||||||
|
|
@ -670,29 +517,21 @@ template rsplitCommon(s, sep, maxsplit, sepLen) =
|
||||||
first = last
|
first = last
|
||||||
splits = maxsplit
|
splits = maxsplit
|
||||||
startPos = 0
|
startPos = 0
|
||||||
|
|
||||||
# go to -1 in order to get separators at the beginning
|
# go to -1 in order to get separators at the beginning
|
||||||
while first >= -1:
|
while first >= -1:
|
||||||
while first >= 0 and not stringHasSep(s, first, sep):
|
while first >= 0 and not stringHasSep(s, first, sep):
|
||||||
dec(first)
|
dec(first)
|
||||||
|
|
||||||
if splits == 0:
|
if splits == 0:
|
||||||
# No more splits means set first to the beginning
|
# No more splits means set first to the beginning
|
||||||
first = -1
|
first = -1
|
||||||
|
|
||||||
if first == -1:
|
if first == -1:
|
||||||
startPos = 0
|
startPos = 0
|
||||||
else:
|
else:
|
||||||
startPos = first + sepLen
|
startPos = first + sepLen
|
||||||
|
|
||||||
yield substr(s, startPos, last)
|
yield substr(s, startPos, last)
|
||||||
|
if splits == 0: break
|
||||||
if splits == 0:
|
|
||||||
break
|
|
||||||
|
|
||||||
dec(splits)
|
dec(splits)
|
||||||
dec(first)
|
dec(first)
|
||||||
|
|
||||||
last = first
|
last = first
|
||||||
|
|
||||||
iterator rsplit*(s: string, seps: set[char] = Whitespace,
|
iterator rsplit*(s: string, seps: set[char] = Whitespace,
|
||||||
|
|
@ -712,7 +551,6 @@ iterator rsplit*(s: string, seps: set[char] = Whitespace,
|
||||||
## "foo"
|
## "foo"
|
||||||
##
|
##
|
||||||
## Substrings are separated from the right by the set of chars `seps`
|
## Substrings are separated from the right by the set of chars `seps`
|
||||||
|
|
||||||
rsplitCommon(s, seps, maxsplit, 1)
|
rsplitCommon(s, seps, maxsplit, 1)
|
||||||
|
|
||||||
iterator rsplit*(s: string, sep: char,
|
iterator rsplit*(s: string, sep: char,
|
||||||
|
|
@ -779,14 +617,14 @@ iterator splitLines*(s: string): string =
|
||||||
var first = 0
|
var first = 0
|
||||||
var last = 0
|
var last = 0
|
||||||
while true:
|
while true:
|
||||||
while s[last] notin {'\0', '\c', '\l'}: inc(last)
|
while last < s.len and s[last] notin {'\c', '\l'}: inc(last)
|
||||||
yield substr(s, first, last-1)
|
yield substr(s, first, last-1)
|
||||||
# skip newlines:
|
# skip newlines:
|
||||||
|
if last >= s.len: break
|
||||||
if s[last] == '\l': inc(last)
|
if s[last] == '\l': inc(last)
|
||||||
elif s[last] == '\c':
|
elif s[last] == '\c':
|
||||||
inc(last)
|
inc(last)
|
||||||
if s[last] == '\l': inc(last)
|
if last < s.len and s[last] == '\l': inc(last)
|
||||||
else: break # was '\0'
|
|
||||||
first = last
|
first = last
|
||||||
|
|
||||||
proc splitLines*(s: string): seq[string] {.noSideEffect,
|
proc splitLines*(s: string): seq[string] {.noSideEffect,
|
||||||
|
|
@ -811,7 +649,7 @@ proc countLines*(s: string): int {.noSideEffect,
|
||||||
while i < s.len:
|
while i < s.len:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '\c':
|
of '\c':
|
||||||
if s[i+1] == '\l': inc i
|
if i+1 < s.len and s[i+1] == '\l': inc i
|
||||||
inc result
|
inc result
|
||||||
of '\l': inc result
|
of '\l': inc result
|
||||||
else: discard
|
else: discard
|
||||||
|
|
@ -1025,9 +863,9 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||||
## of the following optional prefixes: ``0x``, ``0X``, ``#``. Underscores
|
## of the following optional prefixes: ``0x``, ``0X``, ``#``. Underscores
|
||||||
## within `s` are ignored.
|
## within `s` are ignored.
|
||||||
var i = 0
|
var i = 0
|
||||||
if s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'x' or s[i+1] == 'X'): inc(i, 2)
|
||||||
elif s[i] == '#': inc(i)
|
elif i < s.len and s[i] == '#': inc(i)
|
||||||
while true:
|
while i < s.len:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '_': inc(i)
|
of '_': inc(i)
|
||||||
of '0'..'9':
|
of '0'..'9':
|
||||||
|
|
@ -1039,7 +877,6 @@ proc parseHexInt*(s: string): int {.noSideEffect, procvar,
|
||||||
of 'A'..'F':
|
of 'A'..'F':
|
||||||
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
result = result shl 4 or (ord(s[i]) - ord('A') + 10)
|
||||||
inc(i)
|
inc(i)
|
||||||
of '\0': break
|
|
||||||
else: raise newException(ValueError, "invalid integer: " & s)
|
else: raise newException(ValueError, "invalid integer: " & s)
|
||||||
|
|
||||||
proc generateHexCharToValueMap(): string =
|
proc generateHexCharToValueMap(): string =
|
||||||
|
|
@ -1148,14 +985,6 @@ template spaces*(n: Natural): string = repeat(' ', n)
|
||||||
## echo text1 & spaces(max(0, width - text1.len)) & "|"
|
## echo text1 & spaces(max(0, width - text1.len)) & "|"
|
||||||
## echo text2 & spaces(max(0, width - text2.len)) & "|"
|
## echo text2 & spaces(max(0, width - text2.len)) & "|"
|
||||||
|
|
||||||
proc repeatChar*(count: Natural, c: char = ' '): string {.deprecated.} =
|
|
||||||
## deprecated: use repeat() or spaces()
|
|
||||||
repeat(c, count)
|
|
||||||
|
|
||||||
proc repeatStr*(count: Natural, s: string): string {.deprecated.} =
|
|
||||||
## deprecated: use repeat(string, count) or string.repeat(count)
|
|
||||||
repeat(s, count)
|
|
||||||
|
|
||||||
proc align*(s: string, count: Natural, padding = ' '): string {.
|
proc align*(s: string, count: Natural, padding = ' '): string {.
|
||||||
noSideEffect, rtl, extern: "nsuAlignString".} =
|
noSideEffect, rtl, extern: "nsuAlignString".} =
|
||||||
## Aligns a string `s` with `padding`, so that it is of length `count`.
|
## Aligns a string `s` with `padding`, so that it is of length `count`.
|
||||||
|
|
@ -1226,7 +1055,7 @@ iterator tokenize*(s: string, seps: set[char] = Whitespace): tuple[
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while true:
|
||||||
var j = i
|
var j = i
|
||||||
var isSep = s[j] in seps
|
var isSep = j < s.len and s[j] in seps
|
||||||
while j < s.len and (s[j] in seps) == isSep: inc(j)
|
while j < s.len and (s[j] in seps) == isSep: inc(j)
|
||||||
if j > i:
|
if j > i:
|
||||||
yield (substr(s, i, j-1), isSep)
|
yield (substr(s, i, j-1), isSep)
|
||||||
|
|
@ -1325,13 +1154,13 @@ proc startsWith*(s, prefix: string): bool {.noSideEffect,
|
||||||
## If ``prefix == ""`` true is returned.
|
## If ``prefix == ""`` true is returned.
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while true:
|
||||||
if prefix[i] == '\0': return true
|
if i >= prefix.len: return true
|
||||||
if s[i] != prefix[i]: return false
|
if i >= s.len or s[i] != prefix[i]: return false
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc startsWith*(s: string, prefix: char): bool {.noSideEffect, inline.} =
|
proc startsWith*(s: string, prefix: char): bool {.noSideEffect, inline.} =
|
||||||
## Returns true iff ``s`` starts with ``prefix``.
|
## Returns true iff ``s`` starts with ``prefix``.
|
||||||
result = s[0] == prefix
|
result = s.len > 0 and s[0] == prefix
|
||||||
|
|
||||||
proc endsWith*(s, suffix: string): bool {.noSideEffect,
|
proc endsWith*(s, suffix: string): bool {.noSideEffect,
|
||||||
rtl, extern: "nsuEndsWith".} =
|
rtl, extern: "nsuEndsWith".} =
|
||||||
|
|
@ -1343,11 +1172,11 @@ proc endsWith*(s, suffix: string): bool {.noSideEffect,
|
||||||
while i+j <% s.len:
|
while i+j <% s.len:
|
||||||
if s[i+j] != suffix[i]: return false
|
if s[i+j] != suffix[i]: return false
|
||||||
inc(i)
|
inc(i)
|
||||||
if suffix[i] == '\0': return true
|
if i >= suffix.len: return true
|
||||||
|
|
||||||
proc endsWith*(s: string, suffix: char): bool {.noSideEffect, inline.} =
|
proc endsWith*(s: string, suffix: char): bool {.noSideEffect, inline.} =
|
||||||
## Returns true iff ``s`` ends with ``suffix``.
|
## Returns true iff ``s`` ends with ``suffix``.
|
||||||
result = s[s.high] == suffix
|
result = s.len > 0 and s[s.high] == suffix
|
||||||
|
|
||||||
proc continuesWith*(s, substr: string, start: Natural): bool {.noSideEffect,
|
proc continuesWith*(s, substr: string, start: Natural): bool {.noSideEffect,
|
||||||
rtl, extern: "nsuContinuesWith".} =
|
rtl, extern: "nsuContinuesWith".} =
|
||||||
|
|
@ -1356,8 +1185,8 @@ proc continuesWith*(s, substr: string, start: Natural): bool {.noSideEffect,
|
||||||
## If ``substr == ""`` true is returned.
|
## If ``substr == ""`` true is returned.
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while true:
|
||||||
if substr[i] == '\0': return true
|
if i >= substr.len: return true
|
||||||
if s[i+start] != substr[i]: return false
|
if i+start >= s.len or s[i+start] != substr[i]: return false
|
||||||
inc(i)
|
inc(i)
|
||||||
|
|
||||||
proc addSep*(dest: var string, sep = ", ", startLen: Natural = 0)
|
proc addSep*(dest: var string, sep = ", ", startLen: Natural = 0)
|
||||||
|
|
@ -1502,12 +1331,8 @@ proc find*(s, sub: string, start: Natural = 0, last: Natural = 0): int {.noSideE
|
||||||
## If `last` is unspecified, it defaults to `s.high`.
|
## If `last` is unspecified, it defaults to `s.high`.
|
||||||
##
|
##
|
||||||
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
|
## Searching is case-sensitive. If `sub` is not in `s`, -1 is returned.
|
||||||
if sub.len > s.len:
|
if sub.len > s.len: return -1
|
||||||
return -1
|
if sub.len == 1: return find(s, sub[0], start, last)
|
||||||
|
|
||||||
if sub.len == 1:
|
|
||||||
return find(s, sub[0], start, last)
|
|
||||||
|
|
||||||
var a {.noinit.}: SkipTable
|
var a {.noinit.}: SkipTable
|
||||||
initSkipTable(a, sub)
|
initSkipTable(a, sub)
|
||||||
result = find(a, s, sub, start, last)
|
result = find(a, s, sub, start, last)
|
||||||
|
|
@ -1564,18 +1389,14 @@ proc center*(s: string, width: int, fillChar: char = ' '): string {.
|
||||||
##
|
##
|
||||||
## The original string is returned if `width` is less than or equal
|
## The original string is returned if `width` is less than or equal
|
||||||
## to `s.len`.
|
## to `s.len`.
|
||||||
if width <= s.len:
|
if width <= s.len: return s
|
||||||
return s
|
|
||||||
|
|
||||||
result = newString(width)
|
result = newString(width)
|
||||||
|
|
||||||
# Left padding will be one fillChar
|
# Left padding will be one fillChar
|
||||||
# smaller if there are an odd number
|
# smaller if there are an odd number
|
||||||
# of characters
|
# of characters
|
||||||
let
|
let
|
||||||
charsLeft = (width - s.len)
|
charsLeft = (width - s.len)
|
||||||
leftPadding = charsLeft div 2
|
leftPadding = charsLeft div 2
|
||||||
|
|
||||||
for i in 0 ..< width:
|
for i in 0 ..< width:
|
||||||
if i >= leftPadding and i < leftPadding + s.len:
|
if i >= leftPadding and i < leftPadding + s.len:
|
||||||
# we are where the string should be located
|
# we are where the string should be located
|
||||||
|
|
@ -1593,27 +1414,22 @@ proc count*(s: string, sub: string, overlapping: bool = false): int {.
|
||||||
var i = 0
|
var i = 0
|
||||||
while true:
|
while true:
|
||||||
i = s.find(sub, i)
|
i = s.find(sub, i)
|
||||||
if i < 0:
|
if i < 0: break
|
||||||
break
|
if overlapping: inc i
|
||||||
if overlapping:
|
else: i += sub.len
|
||||||
inc i
|
|
||||||
else:
|
|
||||||
i += sub.len
|
|
||||||
inc result
|
inc result
|
||||||
|
|
||||||
proc count*(s: string, sub: char): int {.noSideEffect,
|
proc count*(s: string, sub: char): int {.noSideEffect,
|
||||||
rtl, extern: "nsuCountChar".} =
|
rtl, extern: "nsuCountChar".} =
|
||||||
## Count the occurrences of the character `sub` in the string `s`.
|
## Count the occurrences of the character `sub` in the string `s`.
|
||||||
for c in s:
|
for c in s:
|
||||||
if c == sub:
|
if c == sub: inc result
|
||||||
inc result
|
|
||||||
|
|
||||||
proc count*(s: string, subs: set[char]): int {.noSideEffect,
|
proc count*(s: string, subs: set[char]): int {.noSideEffect,
|
||||||
rtl, extern: "nsuCountCharSet".} =
|
rtl, extern: "nsuCountCharSet".} =
|
||||||
## Count the occurrences of the group of character `subs` in the string `s`.
|
## Count the occurrences of the group of character `subs` in the string `s`.
|
||||||
for c in s:
|
for c in s:
|
||||||
if c in subs:
|
if c in subs: inc result
|
||||||
inc result
|
|
||||||
|
|
||||||
proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
|
proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
|
||||||
## Returns ``'"' & s & '"'`` if `s` contains a space and does not
|
## Returns ``'"' & s & '"'`` if `s` contains a space and does not
|
||||||
|
|
@ -1621,10 +1437,8 @@ proc quoteIfContainsWhite*(s: string): string {.deprecated.} =
|
||||||
##
|
##
|
||||||
## **DEPRECATED** as it was confused for shell quoting function. For this
|
## **DEPRECATED** as it was confused for shell quoting function. For this
|
||||||
## application use `osproc.quoteShell <osproc.html#quoteShell>`_.
|
## application use `osproc.quoteShell <osproc.html#quoteShell>`_.
|
||||||
if find(s, {' ', '\t'}) >= 0 and s[0] != '"':
|
if find(s, {' ', '\t'}) >= 0 and s[0] != '"': result = '"' & s & '"'
|
||||||
result = '"' & s & '"'
|
else: result = s
|
||||||
else:
|
|
||||||
result = s
|
|
||||||
|
|
||||||
proc contains*(s: string, c: char): bool {.noSideEffect.} =
|
proc contains*(s: string, c: char): bool {.noSideEffect.} =
|
||||||
## Same as ``find(s, c) >= 0``.
|
## Same as ``find(s, c) >= 0``.
|
||||||
|
|
@ -1704,9 +1518,8 @@ proc multiReplace*(s: string, replacements: varargs[(string, string)]): string {
|
||||||
## Same as replace, but specialized for doing multiple replacements in a single
|
## Same as replace, but specialized for doing multiple replacements in a single
|
||||||
## pass through the input string.
|
## pass through the input string.
|
||||||
##
|
##
|
||||||
## Calling replace multiple times after each other is inefficient and result in too many allocations
|
## multiReplace performs all replacements in a single pass, this means it can be used
|
||||||
## follwed by immediate deallocations as portions of the string gets replaced.
|
## to swap the occurences of "a" and "b", for instance.
|
||||||
## multiReplace performs all replacements in a single pass.
|
|
||||||
##
|
##
|
||||||
## If the resulting string is not longer than the original input string, only a single
|
## If the resulting string is not longer than the original input string, only a single
|
||||||
## memory allocation is required.
|
## memory allocation is required.
|
||||||
|
|
@ -1753,14 +1566,13 @@ proc parseOctInt*(s: string): int {.noSideEffect,
|
||||||
## of the following optional prefixes: ``0o``, ``0O``. Underscores within
|
## of the following optional prefixes: ``0o``, ``0O``. Underscores within
|
||||||
## `s` are ignored.
|
## `s` are ignored.
|
||||||
var i = 0
|
var i = 0
|
||||||
if s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
if i+1 < s.len and s[i] == '0' and (s[i+1] == 'o' or s[i+1] == 'O'): inc(i, 2)
|
||||||
while true:
|
while i < s.len:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '_': inc(i)
|
of '_': inc(i)
|
||||||
of '0'..'7':
|
of '0'..'7':
|
||||||
result = result shl 3 or (ord(s[i]) - ord('0'))
|
result = result shl 3 or (ord(s[i]) - ord('0'))
|
||||||
inc(i)
|
inc(i)
|
||||||
of '\0': break
|
|
||||||
else: raise newException(ValueError, "invalid integer: " & s)
|
else: raise newException(ValueError, "invalid integer: " & s)
|
||||||
|
|
||||||
proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
proc toOct*(x: BiggestInt, len: Positive): string {.noSideEffect,
|
||||||
|
|
@ -1849,16 +1661,18 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
|
||||||
## If `s` does not begin with ``prefix`` and end with ``suffix`` a
|
## If `s` does not begin with ``prefix`` and end with ``suffix`` a
|
||||||
## ValueError exception will be raised.
|
## ValueError exception will be raised.
|
||||||
##
|
##
|
||||||
## **Warning:** This procedure is deprecated because it's to easy to missuse.
|
## **Warning:** This procedure is deprecated because it's to easy to missuse.
|
||||||
result = newStringOfCap(s.len)
|
result = newStringOfCap(s.len)
|
||||||
var i = prefix.len
|
var i = prefix.len
|
||||||
if not s.startsWith(prefix):
|
if not s.startsWith(prefix):
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"String does not start with a prefix of: " & prefix)
|
"String does not start with: " & prefix)
|
||||||
while true:
|
while true:
|
||||||
if i == s.len-suffix.len: break
|
if i >= s.len-suffix.len: break
|
||||||
case s[i]
|
if s[i] == '\\':
|
||||||
of '\\':
|
if i+1 >= s.len:
|
||||||
|
result.add('\\')
|
||||||
|
break
|
||||||
case s[i+1]:
|
case s[i+1]:
|
||||||
of 'x':
|
of 'x':
|
||||||
inc i, 2
|
inc i, 2
|
||||||
|
|
@ -1872,15 +1686,15 @@ proc unescape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
|
||||||
result.add('\'')
|
result.add('\'')
|
||||||
of '\"':
|
of '\"':
|
||||||
result.add('\"')
|
result.add('\"')
|
||||||
else: result.add("\\" & s[i+1])
|
else:
|
||||||
inc(i)
|
result.add("\\" & s[i+1])
|
||||||
of '\0': break
|
inc(i, 2)
|
||||||
else:
|
else:
|
||||||
result.add(s[i])
|
result.add(s[i])
|
||||||
inc(i)
|
inc(i)
|
||||||
if not s.endsWith(suffix):
|
if not s.endsWith(suffix):
|
||||||
raise newException(ValueError,
|
raise newException(ValueError,
|
||||||
"String does not end with a suffix of: " & suffix)
|
"String does not end in: " & suffix)
|
||||||
|
|
||||||
proc validIdentifier*(s: string): bool {.noSideEffect,
|
proc validIdentifier*(s: string): bool {.noSideEffect,
|
||||||
rtl, extern: "nsuValidIdentifier".} =
|
rtl, extern: "nsuValidIdentifier".} =
|
||||||
|
|
@ -1890,7 +1704,7 @@ proc validIdentifier*(s: string): bool {.noSideEffect,
|
||||||
## and is followed by any number of characters of the set `IdentChars`.
|
## and is followed by any number of characters of the set `IdentChars`.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert "abc_def08".validIdentifier
|
doAssert "abc_def08".validIdentifier
|
||||||
if s[0] in IdentStartChars:
|
if s.len > 0 and s[0] in IdentStartChars:
|
||||||
for i in 1..s.len-1:
|
for i in 1..s.len-1:
|
||||||
if s[i] notin IdentChars: return false
|
if s[i] notin IdentChars: return false
|
||||||
return true
|
return true
|
||||||
|
|
@ -1909,7 +1723,7 @@ proc editDistance*(a, b: string): int {.noSideEffect,
|
||||||
|
|
||||||
# strip common prefix:
|
# strip common prefix:
|
||||||
var s = 0
|
var s = 0
|
||||||
while a[s] == b[s] and a[s] != '\0':
|
while s < len1 and a[s] == b[s]:
|
||||||
inc(s)
|
inc(s)
|
||||||
dec(len1)
|
dec(len1)
|
||||||
dec(len2)
|
dec(len2)
|
||||||
|
|
@ -1982,8 +1796,6 @@ proc editDistance*(a, b: string): int {.noSideEffect,
|
||||||
if x > c3: x = c3
|
if x > c3: x = c3
|
||||||
row[p] = x
|
row[p] = x
|
||||||
result = row[e]
|
result = row[e]
|
||||||
#dealloc(row)
|
|
||||||
|
|
||||||
|
|
||||||
# floating point formating:
|
# floating point formating:
|
||||||
when not defined(js):
|
when not defined(js):
|
||||||
|
|
@ -2092,7 +1904,7 @@ proc trimZeros*(x: var string) {.noSideEffect.} =
|
||||||
var spl: seq[string]
|
var spl: seq[string]
|
||||||
if x.contains('.') or x.contains(','):
|
if x.contains('.') or x.contains(','):
|
||||||
if x.contains('e'):
|
if x.contains('e'):
|
||||||
spl= x.split('e')
|
spl = x.split('e')
|
||||||
x = spl[0]
|
x = spl[0]
|
||||||
while x[x.high] == '0':
|
while x[x.high] == '0':
|
||||||
x.setLen(x.len-1)
|
x.setLen(x.len-1)
|
||||||
|
|
@ -2310,9 +2122,8 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
|
||||||
var i = 0
|
var i = 0
|
||||||
var num = 0
|
var num = 0
|
||||||
while i < len(formatstr):
|
while i < len(formatstr):
|
||||||
if formatstr[i] == '$':
|
if formatstr[i] == '$' and i+1 < len(formatstr):
|
||||||
case formatstr[i+1] # again we use the fact that strings
|
case formatstr[i+1]
|
||||||
# are zero-terminated here
|
|
||||||
of '#':
|
of '#':
|
||||||
if num > a.high: invalidFormatString()
|
if num > a.high: invalidFormatString()
|
||||||
add s, a[num]
|
add s, a[num]
|
||||||
|
|
@ -2326,7 +2137,7 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
|
||||||
inc(i) # skip $
|
inc(i) # skip $
|
||||||
var negative = formatstr[i] == '-'
|
var negative = formatstr[i] == '-'
|
||||||
if negative: inc i
|
if negative: inc i
|
||||||
while formatstr[i] in Digits:
|
while i < formatstr.len and formatstr[i] in Digits:
|
||||||
j = j * 10 + ord(formatstr[i]) - ord('0')
|
j = j * 10 + ord(formatstr[i]) - ord('0')
|
||||||
inc(i)
|
inc(i)
|
||||||
let idx = if not negative: j-1 else: a.len-j
|
let idx = if not negative: j-1 else: a.len-j
|
||||||
|
|
@ -2338,7 +2149,7 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
|
||||||
var negative = formatstr[j] == '-'
|
var negative = formatstr[j] == '-'
|
||||||
if negative: inc j
|
if negative: inc j
|
||||||
var isNumber = 0
|
var isNumber = 0
|
||||||
while formatstr[j] notin {'\0', '}'}:
|
while j < formatstr.len and formatstr[j] notin {'\0', '}'}:
|
||||||
if formatstr[j] in Digits:
|
if formatstr[j] in Digits:
|
||||||
k = k * 10 + ord(formatstr[j]) - ord('0')
|
k = k * 10 + ord(formatstr[j]) - ord('0')
|
||||||
if isNumber == 0: isNumber = 1
|
if isNumber == 0: isNumber = 1
|
||||||
|
|
@ -2356,7 +2167,7 @@ proc addf*(s: var string, formatstr: string, a: varargs[string, `$`]) {.
|
||||||
i = j+1
|
i = j+1
|
||||||
of 'a'..'z', 'A'..'Z', '\128'..'\255', '_':
|
of 'a'..'z', 'A'..'Z', '\128'..'\255', '_':
|
||||||
var j = i+1
|
var j = i+1
|
||||||
while formatstr[j] in PatternChars: inc(j)
|
while j < formatstr.len and formatstr[j] in PatternChars: inc(j)
|
||||||
var x = findNormalized(substr(formatstr, i+1, j-1), a)
|
var x = findNormalized(substr(formatstr, i+1, j-1), a)
|
||||||
if x >= 0 and x < high(a): add s, a[x+1]
|
if x >= 0 and x < high(a): add s, a[x+1]
|
||||||
else: invalidFormatString()
|
else: invalidFormatString()
|
||||||
|
|
@ -2628,13 +2439,7 @@ when isMainModule:
|
||||||
doAssert isSpaceAscii(" ")
|
doAssert isSpaceAscii(" ")
|
||||||
doAssert(not isSpaceAscii("ABc \td"))
|
doAssert(not isSpaceAscii("ABc \td"))
|
||||||
|
|
||||||
doAssert(isNilOrEmpty(""))
|
|
||||||
doAssert(isNilOrEmpty(nil))
|
|
||||||
doAssert(not isNilOrEmpty("test"))
|
|
||||||
doAssert(not isNilOrEmpty(" "))
|
|
||||||
|
|
||||||
doAssert(isNilOrWhitespace(""))
|
doAssert(isNilOrWhitespace(""))
|
||||||
doAssert(isNilOrWhitespace(nil))
|
|
||||||
doAssert(isNilOrWhitespace(" "))
|
doAssert(isNilOrWhitespace(" "))
|
||||||
doAssert(isNilOrWhitespace("\t\l \v\r\f"))
|
doAssert(isNilOrWhitespace("\t\l \v\r\f"))
|
||||||
doAssert(not isNilOrWhitespace("ABc \td"))
|
doAssert(not isNilOrWhitespace("ABc \td"))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue