newStringOfCap implemented and used to optimize some procs

This commit is contained in:
Araq
2011-05-08 17:38:34 +02:00
parent 1893f4101a
commit d2e2d71d05
10 changed files with 53 additions and 21 deletions

View File

@@ -36,7 +36,7 @@ proc URLencode*(s: string): string =
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
## a space is converted to ``'+'`` and every other character is encoded as
## ``'%xx'`` where ``xx`` denotes its hexadecimal value.
result = ""
result = newStringOfCap(s.len + s.len shr 2) # assume 12% non-alnum-chars
for i in 0..s.len-1:
case s[i]
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, s[i])
@@ -57,8 +57,9 @@ proc URLdecode*(s: string): string =
## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
## value) is converted to the character with ordinal number ``xx``, and
## and every other character is carried over.
result = ""
result = newString(s.len)
var i = 0
var j = 0
while i < s.len:
case s[i]
of '%':
@@ -66,10 +67,12 @@ proc URLdecode*(s: string): string =
handleHexChar(s[i+1], x)
handleHexChar(s[i+2], x)
inc(i, 2)
add(result, chr(x))
of '+': add(result, ' ')
else: add(result, s[i])
result[j] = chr(x)
of '+': result[j] = ' '
else: result[j] = s[i]
inc(i)
inc(j)
setLen(result, j)
proc addXmlChar(dest: var string, c: Char) {.inline.} =
case c
@@ -86,7 +89,7 @@ proc XMLencode*(s: string): string =
## * ``>`` is replaced by ``&gt;``
## * ``&`` is replaced by ``&amp;``
## * every other character is carried over.
result = ""
result = newStringOfCap(s.len + s.len shr 2)
for i in 0..len(s)-1: addXmlChar(result, s[i])
type
@@ -367,4 +370,8 @@ proc existsCookie*(name: string): bool =
if gcookies == nil: gcookies = parseCookies(getHttpCookie())
result = hasKey(gcookies, name)
when isMainModule:
const test1 = "abc\L+def xyz"
assert UrlEncode(test1) == "abc%0A%2Bdef+xyz"
assert UrlDecode(UrlEncode(test1)) == test1

View File

@@ -620,7 +620,8 @@ proc nl(s: var string, ml: bool) =
proc escapeJson*(s: string): string =
## Converts a string `s` to its JSON representation.
result = "\""
result = newStringOfCap(s.len + s.len shr 3)
result.add("\"")
for x in runes(s):
var r = int(x)
if r >= 32 and r <= 127:

View File

@@ -89,12 +89,16 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
rtl, extern: "nsuNormalize".} =
## Normalizes the string `s`. That means to convert it to lower case and
## remove any '_'. This is needed for Nimrod identifiers for example.
result = ""
result = newString(s.len)
var j = 0
for i in 0..len(s) - 1:
if s[i] in {'A'..'Z'}:
add result, Chr(Ord(s[i]) + (Ord('a') - Ord('A')))
result[j] = Chr(Ord(s[i]) + (Ord('a') - Ord('A')))
inc j
elif s[i] != '_':
add result, s[i]
result[j] = s[i]
inc j
if j != s.len: setLen(result, j)
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
rtl, extern: "nsuCmpIgnoreCase", procvar.} =
@@ -226,13 +230,14 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
##
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
## raised if an ill-formed format string has been passed to the `%` operator.
result = ""
result = newStringOfCap(formatstr.len + a.len shl 4)
addf(result, formatstr, a)
proc `%` *(formatstr, a: string): string {.noSideEffect,
rtl, extern: "nsuFormatSingleElem".} =
## This is the same as ``formatstr % [a]``.
return formatstr % [a]
result = newStringOfCap(formatstr.len + a.len)
addf(result, formatstr, [a])
proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
rtl, extern: "nsuStrip".} =
@@ -510,7 +515,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
newLine = "\n"): string {.
noSideEffect, rtl, extern: "nsuWordWrap".} =
## word wraps `s`.
result = ""
result = newStringOfCap(s.len + s.len shr 6)
var SpaceLeft = maxLineWidth
for word, isSep in tokenize(s, seps):
if len(word) > SpaceLeft:
@@ -804,7 +809,8 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
## The procedure has been designed so that its output is usable for many
## different common syntaxes. The resulting string is prefixed with
## `prefix` and suffixed with `suffix`. Both may be empty strings.
result = prefix
result = newStringOfCap(s.len + s.len shr 2)
result.add(prefix)
for c in items(s):
case c
of '\0'..'\31', '\128'..'\255':

View File

@@ -685,7 +685,13 @@ proc newString*(len: int): string {.
## content. One needs to fill the string character after character
## with the index operator ``s[i]``. This procedure exists only for
## optimization purposes; the same effect can be achieved with the
## ``&`` operator.
## ``&`` operator or with ``add``.
proc newStringOfCap*(cap: int): string {.
magic: "NewStringOfCap", importc: "rawNewString", noSideEffect.}
## returns a new string of length ``0`` but with capacity `cap`.This
## procedure exists only for optimization purposes; the same effect can
## be achieved with the ``&`` operator or with ``add``.
proc `&` * (x: string, y: char): string {.
magic: "ConStrStr", noSideEffect, merge.}