more modules updated

This commit is contained in:
Araq 2014-08-28 01:30:12 +02:00
commit bae9a0ceac
3 changed files with 70 additions and 70 deletions

View file

@ -103,12 +103,12 @@ type
proc cgiError*(msg: string) {.noreturn.} = proc cgiError*(msg: string) {.noreturn.} =
## raises an ECgi exception with message `msg`. ## raises an ECgi exception with message `msg`.
var e: ref ECgi var e: ref CgiError
new(e) new(e)
e.msg = msg e.msg = msg
raise e raise e
proc getEncodedData(allowedMethods: set[TRequestMethod]): string = proc getEncodedData(allowedMethods: set[RequestMethod]): string =
case getEnv("REQUEST_METHOD").string case getEnv("REQUEST_METHOD").string
of "POST": of "POST":
if methodPost notin allowedMethods: if methodPost notin allowedMethods:
@ -167,7 +167,7 @@ iterator decodeData*(data: string): tuple[key, value: TaintedString] =
elif data[i] == '\0': break elif data[i] == '\0': break
else: cgiError("'&' expected") else: cgiError("'&' expected")
iterator decodeData*(allowedMethods: set[TRequestMethod] = iterator decodeData*(allowedMethods: set[RequestMethod] =
{methodNone, methodPost, methodGet}): tuple[key, value: TaintedString] = {methodNone, methodPost, methodGet}): tuple[key, value: TaintedString] =
## Reads and decodes CGI data and yields the (name, value) pairs the ## Reads and decodes CGI data and yields the (name, value) pairs the
## data consists of. If the client does not use a method listed in the ## data consists of. If the client does not use a method listed in the
@ -177,15 +177,15 @@ iterator decodeData*(allowedMethods: set[TRequestMethod] =
for key, value in decodeData(data): for key, value in decodeData(data):
yield (key, value) yield (key, value)
proc readData*(allowedMethods: set[TRequestMethod] = proc readData*(allowedMethods: set[RequestMethod] =
{methodNone, methodPost, methodGet}): PStringTable = {methodNone, methodPost, methodGet}): StringTableRef =
## Read CGI data. If the client does not use a method listed in the ## Read CGI data. If the client does not use a method listed in the
## `allowedMethods` set, an `ECgi` exception is raised. ## `allowedMethods` set, an `ECgi` exception is raised.
result = newStringTable() result = newStringTable()
for name, value in decodeData(allowedMethods): for name, value in decodeData(allowedMethods):
result[name.string] = value.string result[name.string] = value.string
proc validateData*(data: PStringTable, validKeys: varargs[string]) = proc validateData*(data: StringTableRef, validKeys: varargs[string]) =
## validates data; raises `ECgi` if this fails. This checks that each variable ## validates data; raises `ECgi` if this fails. This checks that each variable
## name of the CGI `data` occurs in the `validKeys` array. ## name of the CGI `data` occurs in the `validKeys` array.
for key, val in pairs(data): for key, val in pairs(data):
@ -393,5 +393,5 @@ proc existsCookie*(name: string): bool =
when isMainModule: when isMainModule:
const test1 = "abc\L+def xyz" const test1 = "abc\L+def xyz"
assert UrlEncode(test1) == "abc%0A%2Bdef+xyz" assert URLencode(test1) == "abc%0A%2Bdef+xyz"
assert UrlDecode(UrlEncode(test1)) == test1 assert URLdecode(URLencode(test1)) == test1

View file

@ -30,50 +30,50 @@ type
{.deprecated: [TComplex: Complex].} {.deprecated: [TComplex: Complex].}
proc `==` *(x, y: TComplex): bool = proc `==` *(x, y: Complex): bool =
## Compare two complex numbers `x` and `y` for equality. ## Compare two complex numbers `x` and `y` for equality.
result = x.re == y.re and x.im == y.im result = x.re == y.re and x.im == y.im
proc `=~` *(x, y: TComplex): bool = proc `=~` *(x, y: Complex): bool =
## Compare two complex numbers `x` and `y` approximately. ## Compare two complex numbers `x` and `y` approximately.
result = abs(x.re-y.re)<EPS and abs(x.im-y.im)<EPS result = abs(x.re-y.re)<EPS and abs(x.im-y.im)<EPS
proc `+` *(x, y: TComplex): TComplex = proc `+` *(x, y: Complex): Complex =
## Add two complex numbers. ## Add two complex numbers.
result.re = x.re + y.re result.re = x.re + y.re
result.im = x.im + y.im result.im = x.im + y.im
proc `+` *(x: TComplex, y: float): TComplex = proc `+` *(x: Complex, y: float): Complex =
## Add complex `x` to float `y`. ## Add complex `x` to float `y`.
result.re = x.re + y result.re = x.re + y
result.im = x.im result.im = x.im
proc `+` *(x: float, y: TComplex): TComplex = proc `+` *(x: float, y: Complex): Complex =
## Add float `x` to complex `y`. ## Add float `x` to complex `y`.
result.re = x + y.re result.re = x + y.re
result.im = y.im result.im = y.im
proc `-` *(z: TComplex): TComplex = proc `-` *(z: Complex): Complex =
## Unary minus for complex numbers. ## Unary minus for complex numbers.
result.re = -z.re result.re = -z.re
result.im = -z.im result.im = -z.im
proc `-` *(x, y: TComplex): TComplex = proc `-` *(x, y: Complex): Complex =
## Subtract two complex numbers. ## Subtract two complex numbers.
result.re = x.re - y.re result.re = x.re - y.re
result.im = x.im - y.im result.im = x.im - y.im
proc `-` *(x: TComplex, y: float): TComplex = proc `-` *(x: Complex, y: float): Complex =
## Subtracts float `y` from complex `x`. ## Subtracts float `y` from complex `x`.
result = x + (-y) result = x + (-y)
proc `-` *(x: float, y: TComplex): TComplex = proc `-` *(x: float, y: Complex): Complex =
## Subtracts complex `y` from float `x`. ## Subtracts complex `y` from float `x`.
result = x + (-y) result = x + (-y)
proc `/` *(x, y: TComplex): TComplex = proc `/` *(x, y: Complex): Complex =
## Divide `x` by `y`. ## Divide `x` by `y`.
var var
r, den: float r, den: float
@ -88,73 +88,73 @@ proc `/` *(x, y: TComplex): TComplex =
result.re = (x.re + r * x.im) / den result.re = (x.re + r * x.im) / den
result.im = (x.im - r * x.re) / den result.im = (x.im - r * x.re) / den
proc `/` *(x : TComplex, y: float ): TComplex = proc `/` *(x : Complex, y: float ): Complex =
## Divide complex `x` by float `y`. ## Divide complex `x` by float `y`.
result.re = x.re/y result.re = x.re/y
result.im = x.im/y result.im = x.im/y
proc `/` *(x : float, y: TComplex ): TComplex = proc `/` *(x : float, y: Complex ): Complex =
## Divide float `x` by complex `y`. ## Divide float `x` by complex `y`.
var num : TComplex = (x, 0.0) var num : Complex = (x, 0.0)
result = num/y result = num/y
proc `*` *(x, y: TComplex): TComplex = proc `*` *(x, y: Complex): Complex =
## Multiply `x` with `y`. ## Multiply `x` with `y`.
result.re = x.re * y.re - x.im * y.im result.re = x.re * y.re - x.im * y.im
result.im = x.im * y.re + x.re * y.im result.im = x.im * y.re + x.re * y.im
proc `*` *(x: float, y: TComplex): TComplex = proc `*` *(x: float, y: Complex): Complex =
## Multiply float `x` with complex `y`. ## Multiply float `x` with complex `y`.
result.re = x * y.re result.re = x * y.re
result.im = x * y.im result.im = x * y.im
proc `*` *(x: TComplex, y: float): TComplex = proc `*` *(x: Complex, y: float): Complex =
## Multiply complex `x` with float `y`. ## Multiply complex `x` with float `y`.
result.re = x.re * y result.re = x.re * y
result.im = x.im * y result.im = x.im * y
proc `+=` *(x: var TComplex, y: TComplex) = proc `+=` *(x: var Complex, y: Complex) =
## Add `y` to `x`. ## Add `y` to `x`.
x.re += y.re x.re += y.re
x.im += y.im x.im += y.im
proc `+=` *(x: var TComplex, y: float) = proc `+=` *(x: var Complex, y: float) =
## Add `y` to the complex number `x`. ## Add `y` to the complex number `x`.
x.re += y x.re += y
proc `-=` *(x: var TComplex, y: TComplex) = proc `-=` *(x: var Complex, y: Complex) =
## Subtract `y` from `x`. ## Subtract `y` from `x`.
x.re -= y.re x.re -= y.re
x.im -= y.im x.im -= y.im
proc `-=` *(x: var TComplex, y: float) = proc `-=` *(x: var Complex, y: float) =
## Subtract `y` from the complex number `x`. ## Subtract `y` from the complex number `x`.
x.re -= y x.re -= y
proc `*=` *(x: var TComplex, y: TComplex) = proc `*=` *(x: var Complex, y: Complex) =
## Multiply `y` to `x`. ## Multiply `y` to `x`.
let im = x.im * y.re + x.re * y.im let im = x.im * y.re + x.re * y.im
x.re = x.re * y.re - x.im * y.im x.re = x.re * y.re - x.im * y.im
x.im = im x.im = im
proc `*=` *(x: var TComplex, y: float) = proc `*=` *(x: var Complex, y: float) =
## Multiply `y` to the complex number `x`. ## Multiply `y` to the complex number `x`.
x.re *= y x.re *= y
x.im *= y x.im *= y
proc `/=` *(x: var TComplex, y: TComplex) = proc `/=` *(x: var Complex, y: Complex) =
## Divide `x` by `y` in place. ## Divide `x` by `y` in place.
x = x / y x = x / y
proc `/=` *(x : var TComplex, y: float) = proc `/=` *(x : var Complex, y: float) =
## Divide complex `x` by float `y` in place. ## Divide complex `x` by float `y` in place.
x.re /= y x.re /= y
x.im /= y x.im /= y
proc abs*(z: TComplex): float = proc abs*(z: Complex): float =
## Return the distance from (0,0) to `z`. ## Return the distance from (0,0) to `z`.
# optimized by checking special cases (sqrt is expensive) # optimized by checking special cases (sqrt is expensive)
@ -174,7 +174,7 @@ proc abs*(z: TComplex): float =
result = y * sqrt(1.0 + temp * temp) result = y * sqrt(1.0 + temp * temp)
proc sqrt*(z: TComplex): TComplex = proc sqrt*(z: Complex): Complex =
## Square root for a complex number `z`. ## Square root for a complex number `z`.
var x, y, w, r: float var x, y, w, r: float
@ -198,7 +198,7 @@ proc sqrt*(z: TComplex): TComplex =
result.re = z.im / (result.im + result.im) result.re = z.im / (result.im + result.im)
proc exp*(z: TComplex): TComplex = proc exp*(z: Complex): Complex =
## e raised to the power `z`. ## e raised to the power `z`.
var rho = exp(z.re) var rho = exp(z.re)
var theta = z.im var theta = z.im
@ -206,21 +206,21 @@ proc exp*(z: TComplex): TComplex =
result.im = rho*sin(theta) result.im = rho*sin(theta)
proc ln*(z: TComplex): TComplex = proc ln*(z: Complex): Complex =
## Returns the natural log of `z`. ## Returns the natural log of `z`.
result.re = ln(abs(z)) result.re = ln(abs(z))
result.im = arctan2(z.im,z.re) result.im = arctan2(z.im,z.re)
proc log10*(z: TComplex): TComplex = proc log10*(z: Complex): Complex =
## Returns the log base 10 of `z`. ## Returns the log base 10 of `z`.
result = ln(z)/ln(10.0) result = ln(z)/ln(10.0)
proc log2*(z: TComplex): TComplex = proc log2*(z: Complex): Complex =
## Returns the log base 2 of `z`. ## Returns the log base 2 of `z`.
result = ln(z)/ln(2.0) result = ln(z)/ln(2.0)
proc pow*(x, y: TComplex): TComplex = proc pow*(x, y: Complex): Complex =
## `x` raised to the power `y`. ## `x` raised to the power `y`.
if x.re == 0.0 and x.im == 0.0: if x.re == 0.0 and x.im == 0.0:
if y.re == 0.0 and y.im == 0.0: if y.re == 0.0 and y.im == 0.0:
@ -242,53 +242,53 @@ proc pow*(x, y: TComplex): TComplex =
result.im = s*sin(r) result.im = s*sin(r)
proc sin*(z: TComplex): TComplex = proc sin*(z: Complex): Complex =
## Returns the sine of `z`. ## Returns the sine of `z`.
result.re = sin(z.re)*cosh(z.im) result.re = sin(z.re)*cosh(z.im)
result.im = cos(z.re)*sinh(z.im) result.im = cos(z.re)*sinh(z.im)
proc arcsin*(z: TComplex): TComplex = proc arcsin*(z: Complex): Complex =
## Returns the inverse sine of `z`. ## Returns the inverse sine of `z`.
var i: TComplex = (0.0,1.0) var i: Complex = (0.0,1.0)
result = -i*ln(i*z + sqrt(1.0-z*z)) result = -i*ln(i*z + sqrt(1.0-z*z))
proc cos*(z: TComplex): TComplex = proc cos*(z: Complex): Complex =
## Returns the cosine of `z`. ## Returns the cosine of `z`.
result.re = cos(z.re)*cosh(z.im) result.re = cos(z.re)*cosh(z.im)
result.im = -sin(z.re)*sinh(z.im) result.im = -sin(z.re)*sinh(z.im)
proc arccos*(z: TComplex): TComplex = proc arccos*(z: Complex): Complex =
## Returns the inverse cosine of `z`. ## Returns the inverse cosine of `z`.
var i: TComplex = (0.0,1.0) var i: Complex = (0.0,1.0)
result = -i*ln(z + sqrt(z*z-1.0)) result = -i*ln(z + sqrt(z*z-1.0))
proc tan*(z: TComplex): TComplex = proc tan*(z: Complex): Complex =
## Returns the tangent of `z`. ## Returns the tangent of `z`.
result = sin(z)/cos(z) result = sin(z)/cos(z)
proc cot*(z: TComplex): TComplex = proc cot*(z: Complex): Complex =
## Returns the cotangent of `z`. ## Returns the cotangent of `z`.
result = cos(z)/sin(z) result = cos(z)/sin(z)
proc sec*(z: TComplex): TComplex = proc sec*(z: Complex): Complex =
## Returns the secant of `z`. ## Returns the secant of `z`.
result = 1.0/cos(z) result = 1.0/cos(z)
proc csc*(z: TComplex): TComplex = proc csc*(z: Complex): Complex =
## Returns the cosecant of `z`. ## Returns the cosecant of `z`.
result = 1.0/sin(z) result = 1.0/sin(z)
proc sinh*(z: TComplex): TComplex = proc sinh*(z: Complex): Complex =
## Returns the hyperbolic sine of `z`. ## Returns the hyperbolic sine of `z`.
result = 0.5*(exp(z)-exp(-z)) result = 0.5*(exp(z)-exp(-z))
proc cosh*(z: TComplex): TComplex = proc cosh*(z: Complex): Complex =
## Returns the hyperbolic cosine of `z`. ## Returns the hyperbolic cosine of `z`.
result = 0.5*(exp(z)+exp(-z)) result = 0.5*(exp(z)+exp(-z))
proc `$`*(z: TComplex): string = proc `$`*(z: Complex): string =
## Returns `z`'s string representation as ``"(re, im)"``. ## Returns `z`'s string representation as ``"(re, im)"``.
result = "(" & $z.re & ", " & $z.im & ")" result = "(" & $z.re & ", " & $z.im & ")"

View file

@ -38,19 +38,19 @@ proc len*(t: StringTableRef): int {.rtl, extern: "nst$1".} =
## returns the number of keys in `t`. ## returns the number of keys in `t`.
result = t.counter result = t.counter
iterator pairs*(t: PStringTable): tuple[key, value: string] = iterator pairs*(t: StringTableRef): tuple[key, value: string] =
## iterates over every (key, value) pair in the table `t`. ## iterates over every (key, value) pair in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if not isNil(t.data[h].key): if not isNil(t.data[h].key):
yield (t.data[h].key, t.data[h].val) yield (t.data[h].key, t.data[h].val)
iterator keys*(t: PStringTable): string = iterator keys*(t: StringTableRef): string =
## iterates over every key in the table `t`. ## iterates over every key in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if not isNil(t.data[h].key): if not isNil(t.data[h].key):
yield t.data[h].key yield t.data[h].key
iterator values*(t: PStringTable): string = iterator values*(t: StringTableRef): string =
## iterates over every value in the table `t`. ## iterates over every value in the table `t`.
for h in 0..high(t.data): for h in 0..high(t.data):
if not isNil(t.data[h].key): if not isNil(t.data[h].key):
@ -74,13 +74,13 @@ const
growthFactor = 2 growthFactor = 2
startSize = 64 startSize = 64
proc myhash(t: PStringTable, key: string): THash = proc myhash(t: StringTableRef, key: string): THash =
case t.mode case t.mode
of modeCaseSensitive: result = hashes.hash(key) of modeCaseSensitive: result = hashes.hash(key)
of modeCaseInsensitive: result = hashes.hashIgnoreCase(key) of modeCaseInsensitive: result = hashes.hashIgnoreCase(key)
of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key) of modeStyleInsensitive: result = hashes.hashIgnoreStyle(key)
proc myCmp(t: PStringTable, a, b: string): bool = proc myCmp(t: StringTableRef, a, b: string): bool =
case t.mode case t.mode
of modeCaseSensitive: result = cmp(a, b) == 0 of modeCaseSensitive: result = cmp(a, b) == 0
of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0 of modeCaseInsensitive: result = cmpIgnoreCase(a, b) == 0
@ -93,7 +93,7 @@ proc mustRehash(length, counter: int): bool =
proc nextTry(h, maxHash: THash): THash {.inline.} = proc nextTry(h, maxHash: THash): THash {.inline.} =
result = ((5 * h) + 1) and maxHash result = ((5 * h) + 1) and maxHash
proc rawGet(t: PStringTable, key: string): int = proc rawGet(t: StringTableRef, key: string): int =
var h: THash = myhash(t, key) and high(t.data) # start with real hash value var h: THash = myhash(t, key) and high(t.data) # start with real hash value
while not isNil(t.data[h].key): while not isNil(t.data[h].key):
if myCmp(t, t.data[h].key, key): if myCmp(t, t.data[h].key, key):
@ -101,7 +101,7 @@ proc rawGet(t: PStringTable, key: string): int =
h = nextTry(h, high(t.data)) h = nextTry(h, high(t.data))
result = - 1 result = - 1
proc `[]`*(t: PStringTable, key: string): string {.rtl, extern: "nstGet".} = proc `[]`*(t: StringTableRef, key: string): string {.rtl, extern: "nstGet".} =
## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned ## retrieves the value at ``t[key]``. If `key` is not in `t`, "" is returned
## and no exception is raised. One can check with ``hasKey`` whether the key ## and no exception is raised. One can check with ``hasKey`` whether the key
## exists. ## exists.
@ -109,7 +109,7 @@ proc `[]`*(t: PStringTable, key: string): string {.rtl, extern: "nstGet".} =
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
else: result = "" else: result = ""
proc mget*(t: PStringTable, key: string): var string {. proc mget*(t: StringTableRef, key: string): var string {.
rtl, extern: "nstTake".} = rtl, extern: "nstTake".} =
## retrieves the location at ``t[key]``. If `key` is not in `t`, the ## retrieves the location at ``t[key]``. If `key` is not in `t`, the
## ``EInvalidKey`` exception is raised. ## ``EInvalidKey`` exception is raised.
@ -117,25 +117,25 @@ proc mget*(t: PStringTable, key: string): var string {.
if index >= 0: result = t.data[index].val if index >= 0: result = t.data[index].val
else: raise newException(KeyError, "key does not exist: " & key) else: raise newException(KeyError, "key does not exist: " & key)
proc hasKey*(t: PStringTable, key: string): bool {.rtl, extern: "nst$1".} = proc hasKey*(t: StringTableRef, key: string): bool {.rtl, extern: "nst$1".} =
## returns true iff `key` is in the table `t`. ## returns true iff `key` is in the table `t`.
result = rawGet(t, key) >= 0 result = rawGet(t, key) >= 0
proc rawInsert(t: PStringTable, data: var KeyValuePairSeq, key, val: string) = proc rawInsert(t: StringTableRef, data: var KeyValuePairSeq, key, val: string) =
var h: THash = myhash(t, key) and high(data) var h: THash = myhash(t, key) and high(data)
while not isNil(data[h].key): while not isNil(data[h].key):
h = nextTry(h, high(data)) h = nextTry(h, high(data))
data[h].key = key data[h].key = key
data[h].val = val data[h].val = val
proc enlarge(t: PStringTable) = proc enlarge(t: StringTableRef) =
var n: KeyValuePairSeq var n: KeyValuePairSeq
newSeq(n, len(t.data) * growthFactor) newSeq(n, len(t.data) * growthFactor)
for i in countup(0, high(t.data)): for i in countup(0, high(t.data)):
if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val) if not isNil(t.data[i].key): rawInsert(t, n, t.data[i].key, t.data[i].val)
swap(t.data, n) swap(t.data, n)
proc `[]=`*(t: PStringTable, key, val: string) {.rtl, extern: "nstPut".} = proc `[]=`*(t: StringTableRef, key, val: string) {.rtl, extern: "nstPut".} =
## puts a (key, value)-pair into `t`. ## puts a (key, value)-pair into `t`.
var index = rawGet(t, key) var index = rawGet(t, key)
if index >= 0: if index >= 0:
@ -151,7 +151,7 @@ proc raiseFormatException(s: string) =
e.msg = "format string: key not found: " & s e.msg = "format string: key not found: " & s
raise e raise e
proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string = proc getValue(t: StringTableRef, flags: set[FormatFlag], key: string): string =
if hasKey(t, key): return t[key] if hasKey(t, key): return t[key]
# hm difficult: assume safety in taint mode here. XXX This is dangerous! # hm difficult: assume safety in taint mode here. XXX This is dangerous!
if useEnvironment in flags: result = os.getEnv(key).string if useEnvironment in flags: result = os.getEnv(key).string
@ -160,7 +160,7 @@ proc getValue(t: PStringTable, flags: set[TFormatFlag], key: string): string =
if useKey in flags: result = '$' & key if useKey in flags: result = '$' & key
elif not (useEmpty in flags): raiseFormatException(key) elif not (useEmpty in flags): raiseFormatException(key)
proc newStringTable*(mode: TStringTableMode): PStringTable {. proc newStringTable*(mode: StringTableMode): StringTableRef {.
rtl, extern: "nst$1".} = rtl, extern: "nst$1".} =
## creates a new string table that is empty. ## creates a new string table that is empty.
new(result) new(result)
@ -169,7 +169,7 @@ proc newStringTable*(mode: TStringTableMode): PStringTable {.
newSeq(result.data, startSize) newSeq(result.data, startSize)
proc newStringTable*(keyValuePairs: varargs[string], proc newStringTable*(keyValuePairs: varargs[string],
mode: TStringTableMode): PStringTable {. mode: StringTableMode): StringTableRef {.
rtl, extern: "nst$1WithPairs".} = rtl, extern: "nst$1WithPairs".} =
## creates a new string table with given key value pairs. ## creates a new string table with given key value pairs.
## Example:: ## Example::
@ -182,7 +182,7 @@ proc newStringTable*(keyValuePairs: varargs[string],
inc(i, 2) inc(i, 2)
proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]], proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]],
mode: StringTableMode = modeCaseSensitive): PStringTable {. mode: StringTableMode = modeCaseSensitive): StringTableRef {.
rtl, extern: "nst$1WithTableConstr".} = rtl, extern: "nst$1WithTableConstr".} =
## creates a new string table with given key value pairs. ## creates a new string table with given key value pairs.
## Example:: ## Example::
@ -191,7 +191,7 @@ proc newStringTable*(keyValuePairs: varargs[tuple[key, val: string]],
result = newStringTable(mode) result = newStringTable(mode)
for key, val in items(keyValuePairs): result[key] = val for key, val in items(keyValuePairs): result[key] = val
proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {. proc `%`*(f: string, t: StringTableRef, flags: set[FormatFlag] = {}): string {.
rtl, extern: "nstFormat".} = rtl, extern: "nstFormat".} =
## The `%` operator for string tables. ## The `%` operator for string tables.
const const
@ -221,7 +221,7 @@ proc `%`*(f: string, t: PStringTable, flags: set[TFormatFlag] = {}): string {.
add(result, f[i]) add(result, f[i])
inc(i) inc(i)
proc `$`*(t: PStringTable): string {.rtl, extern: "nstDollar".} = proc `$`*(t: StringTableRef): string {.rtl, extern: "nstDollar".} =
## The `$` operator for string tables. ## The `$` operator for string tables.
if t.len == 0: if t.len == 0:
result = "{:}" result = "{:}"