newStringOfCap implemented and used to optimize some procs
This commit is contained in:
parent
1893f4101a
commit
d2e2d71d05
10 changed files with 53 additions and 21 deletions
|
|
@ -337,7 +337,9 @@ type
|
||||||
mFields, mFieldPairs,
|
mFields, mFieldPairs,
|
||||||
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
mAppendStrCh, mAppendStrStr, mAppendSeqElem,
|
||||||
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert,
|
mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, mAssert,
|
||||||
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, mNewString, mReset,
|
mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast,
|
||||||
|
mNewString, mNewStringOfCap,
|
||||||
|
mReset,
|
||||||
mArray, mOpenArray, mRange, mSet, mSeq,
|
mArray, mOpenArray, mRange, mSet, mSeq,
|
||||||
mOrdinal, mInt, mInt8, mInt16, mInt32,
|
mOrdinal, mInt, mInt8, mInt16, mInt32,
|
||||||
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
|
mInt64, mFloat, mFloat32, mFloat64, mBool, mChar, mString, mCstring,
|
||||||
|
|
|
||||||
|
|
@ -1457,7 +1457,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||||
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
of mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet, mMinusSet,
|
||||||
mInSet:
|
mInSet:
|
||||||
genSetOp(p, e, d, op)
|
genSetOp(p, e, d, op)
|
||||||
of mNewString, mCopyStr, mCopyStrLast, mExit: genCall(p, e, d)
|
of mNewString, mNewStringOfCap, mCopyStr, mCopyStrLast, mExit:
|
||||||
|
genCall(p, e, d)
|
||||||
of mReset: genReset(p, e)
|
of mReset: genReset(p, e)
|
||||||
of mEcho: genEcho(p, e)
|
of mEcho: genEcho(p, e)
|
||||||
of mArrToSeq: genArrToSeq(p, e, d)
|
of mArrToSeq: genArrToSeq(p, e, d)
|
||||||
|
|
|
||||||
|
|
@ -990,6 +990,12 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
||||||
var a = result
|
var a = result
|
||||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||||
result.strVal = newString(int(getOrdValue(a)))
|
result.strVal = newString(int(getOrdValue(a)))
|
||||||
|
of mNewStringOfCap:
|
||||||
|
result = evalAux(c, n.sons[1], {})
|
||||||
|
if isSpecial(result): return
|
||||||
|
var a = result
|
||||||
|
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||||
|
result.strVal = newString(0)
|
||||||
else:
|
else:
|
||||||
result = evalAux(c, n.sons[1], {})
|
result = evalAux(c, n.sons[1], {})
|
||||||
if isSpecial(result): return
|
if isSpecial(result): return
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2010 Andreas Rumpf
|
# (c) Copyright 2011 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -205,7 +205,8 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
|
||||||
of mCompileOptionArg:
|
of mCompileOptionArg:
|
||||||
result = newIntNodeT(Ord(
|
result = newIntNodeT(Ord(
|
||||||
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
|
||||||
of mNewString, mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh,
|
of mNewString, mNewStringOfCap,
|
||||||
|
mExit, mInc, ast.mDec, mEcho, mAssert, mSwap, mAppendStrCh,
|
||||||
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
|
||||||
mNLen..mNError, mEqRef:
|
mNLen..mNError, mEqRef:
|
||||||
nil
|
nil
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,7 @@ get get, ``[]`` consider overloading ``[]`` for get;
|
||||||
prefix: ``len`` instead of ``getLen``
|
prefix: ``len`` instead of ``getLen``
|
||||||
length len also used for *number of elements*
|
length len also used for *number of elements*
|
||||||
size size, len size should refer to a byte size
|
size size, len size should refer to a byte size
|
||||||
|
capacity cap
|
||||||
memory mem implies a low-level operation
|
memory mem implies a low-level operation
|
||||||
items items default iterator over a collection
|
items items default iterator over a collection
|
||||||
pairs pairs iterator over (key, value) pairs
|
pairs pairs iterator over (key, value) pairs
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ proc URLencode*(s: string): string =
|
||||||
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
|
## ``{'A'..'Z', 'a'..'z', '0'..'9', '_'}`` are carried over to the result,
|
||||||
## a space is converted to ``'+'`` and every other character is encoded as
|
## a space is converted to ``'+'`` and every other character is encoded as
|
||||||
## ``'%xx'`` where ``xx`` denotes its hexadecimal value.
|
## ``'%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:
|
for i in 0..s.len-1:
|
||||||
case s[i]
|
case s[i]
|
||||||
of 'a'..'z', 'A'..'Z', '0'..'9', '_': add(result, 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
|
## is converted to a space, ``'%xx'`` (where ``xx`` denotes a hexadecimal
|
||||||
## value) is converted to the character with ordinal number ``xx``, and
|
## value) is converted to the character with ordinal number ``xx``, and
|
||||||
## and every other character is carried over.
|
## and every other character is carried over.
|
||||||
result = ""
|
result = newString(s.len)
|
||||||
var i = 0
|
var i = 0
|
||||||
|
var j = 0
|
||||||
while i < s.len:
|
while i < s.len:
|
||||||
case s[i]
|
case s[i]
|
||||||
of '%':
|
of '%':
|
||||||
|
|
@ -66,10 +67,12 @@ proc URLdecode*(s: string): string =
|
||||||
handleHexChar(s[i+1], x)
|
handleHexChar(s[i+1], x)
|
||||||
handleHexChar(s[i+2], x)
|
handleHexChar(s[i+2], x)
|
||||||
inc(i, 2)
|
inc(i, 2)
|
||||||
add(result, chr(x))
|
result[j] = chr(x)
|
||||||
of '+': add(result, ' ')
|
of '+': result[j] = ' '
|
||||||
else: add(result, s[i])
|
else: result[j] = s[i]
|
||||||
inc(i)
|
inc(i)
|
||||||
|
inc(j)
|
||||||
|
setLen(result, j)
|
||||||
|
|
||||||
proc addXmlChar(dest: var string, c: Char) {.inline.} =
|
proc addXmlChar(dest: var string, c: Char) {.inline.} =
|
||||||
case c
|
case c
|
||||||
|
|
@ -86,7 +89,7 @@ proc XMLencode*(s: string): string =
|
||||||
## * ``>`` is replaced by ``>``
|
## * ``>`` is replaced by ``>``
|
||||||
## * ``&`` is replaced by ``&``
|
## * ``&`` is replaced by ``&``
|
||||||
## * every other character is carried over.
|
## * 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])
|
for i in 0..len(s)-1: addXmlChar(result, s[i])
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
@ -367,4 +370,8 @@ proc existsCookie*(name: string): bool =
|
||||||
if gcookies == nil: gcookies = parseCookies(getHttpCookie())
|
if gcookies == nil: gcookies = parseCookies(getHttpCookie())
|
||||||
result = hasKey(gcookies, name)
|
result = hasKey(gcookies, name)
|
||||||
|
|
||||||
|
when isMainModule:
|
||||||
|
const test1 = "abc\L+def xyz"
|
||||||
|
assert UrlEncode(test1) == "abc%0A%2Bdef+xyz"
|
||||||
|
assert UrlDecode(UrlEncode(test1)) == test1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -620,7 +620,8 @@ proc nl(s: var string, ml: bool) =
|
||||||
|
|
||||||
proc escapeJson*(s: string): string =
|
proc escapeJson*(s: string): string =
|
||||||
## Converts a string `s` to its JSON representation.
|
## Converts a string `s` to its JSON representation.
|
||||||
result = "\""
|
result = newStringOfCap(s.len + s.len shr 3)
|
||||||
|
result.add("\"")
|
||||||
for x in runes(s):
|
for x in runes(s):
|
||||||
var r = int(x)
|
var r = int(x)
|
||||||
if r >= 32 and r <= 127:
|
if r >= 32 and r <= 127:
|
||||||
|
|
|
||||||
|
|
@ -89,12 +89,16 @@ proc normalize*(s: string): string {.noSideEffect, procvar,
|
||||||
rtl, extern: "nsuNormalize".} =
|
rtl, extern: "nsuNormalize".} =
|
||||||
## Normalizes the string `s`. That means to convert it to lower case and
|
## Normalizes the string `s`. That means to convert it to lower case and
|
||||||
## remove any '_'. This is needed for Nimrod identifiers for example.
|
## 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:
|
for i in 0..len(s) - 1:
|
||||||
if s[i] in {'A'..'Z'}:
|
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] != '_':
|
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,
|
proc cmpIgnoreCase*(a, b: string): int {.noSideEffect,
|
||||||
rtl, extern: "nsuCmpIgnoreCase", procvar.} =
|
rtl, extern: "nsuCmpIgnoreCase", procvar.} =
|
||||||
|
|
@ -226,13 +230,14 @@ proc `%` *(formatstr: string, a: openarray[string]): string {.noSideEffect,
|
||||||
##
|
##
|
||||||
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
|
## The variables are compared with `cmpIgnoreStyle`. `EInvalidValue` is
|
||||||
## raised if an ill-formed format string has been passed to the `%` operator.
|
## 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)
|
addf(result, formatstr, a)
|
||||||
|
|
||||||
proc `%` *(formatstr, a: string): string {.noSideEffect,
|
proc `%` *(formatstr, a: string): string {.noSideEffect,
|
||||||
rtl, extern: "nsuFormatSingleElem".} =
|
rtl, extern: "nsuFormatSingleElem".} =
|
||||||
## This is the same as ``formatstr % [a]``.
|
## 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,
|
proc strip*(s: string, leading = true, trailing = true): string {.noSideEffect,
|
||||||
rtl, extern: "nsuStrip".} =
|
rtl, extern: "nsuStrip".} =
|
||||||
|
|
@ -510,7 +515,7 @@ proc wordWrap*(s: string, maxLineWidth = 80,
|
||||||
newLine = "\n"): string {.
|
newLine = "\n"): string {.
|
||||||
noSideEffect, rtl, extern: "nsuWordWrap".} =
|
noSideEffect, rtl, extern: "nsuWordWrap".} =
|
||||||
## word wraps `s`.
|
## word wraps `s`.
|
||||||
result = ""
|
result = newStringOfCap(s.len + s.len shr 6)
|
||||||
var SpaceLeft = maxLineWidth
|
var SpaceLeft = maxLineWidth
|
||||||
for word, isSep in tokenize(s, seps):
|
for word, isSep in tokenize(s, seps):
|
||||||
if len(word) > SpaceLeft:
|
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
|
## The procedure has been designed so that its output is usable for many
|
||||||
## different common syntaxes. The resulting string is prefixed with
|
## different common syntaxes. The resulting string is prefixed with
|
||||||
## `prefix` and suffixed with `suffix`. Both may be empty strings.
|
## `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):
|
for c in items(s):
|
||||||
case c
|
case c
|
||||||
of '\0'..'\31', '\128'..'\255':
|
of '\0'..'\31', '\128'..'\255':
|
||||||
|
|
|
||||||
|
|
@ -685,7 +685,13 @@ proc newString*(len: int): string {.
|
||||||
## content. One needs to fill the string character after character
|
## content. One needs to fill the string character after character
|
||||||
## with the index operator ``s[i]``. This procedure exists only for
|
## with the index operator ``s[i]``. This procedure exists only for
|
||||||
## optimization purposes; the same effect can be achieved with the
|
## 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 {.
|
proc `&` * (x: string, y: char): string {.
|
||||||
magic: "ConStrStr", noSideEffect, merge.}
|
magic: "ConStrStr", noSideEffect, merge.}
|
||||||
|
|
|
||||||
|
|
@ -74,10 +74,11 @@ Additions
|
||||||
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
|
- Added the ``linearScanEnd``, ``unroll``, ``shallow`` pragmas.
|
||||||
- Added ``system.reset`` and a version of ``system.open`` that
|
- Added ``system.reset`` and a version of ``system.open`` that
|
||||||
returns a ``TFile`` and raises an exception in case of an error.
|
returns a ``TFile`` and raises an exception in case of an error.
|
||||||
- The compiler now might use a hashing for string case statements depending
|
- The compiler now might use hashing for string case statements depending
|
||||||
on the number of string literals in the case statement.
|
on the number of string literals in the case statement.
|
||||||
- Added a wrapper for ``redis``.
|
- Added a wrapper for ``redis``.
|
||||||
- The compiler now supports array, sequence and string slicing.
|
- The compiler now supports array, sequence and string slicing.
|
||||||
|
- Added ``system.newStringOfCap``.
|
||||||
|
|
||||||
|
|
||||||
2010-10-20 Version 0.8.10 released
|
2010-10-20 Version 0.8.10 released
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue