37 lines
1.0 KiB
Nim
37 lines
1.0 KiB
Nim
|
import hashtable
|
||
|
import ndstring
|
||
|
|
||
|
# string extension, NOTE identical implementation in ndstring.nim
|
||
|
proc fnv1a*(str: string): int =
|
||
|
var hash = 2166136261'u32
|
||
|
for i in countup(0, str.len - 1):
|
||
|
hash = hash xor (str[i]).uint32
|
||
|
hash *= 16777619
|
||
|
return hash.int
|
||
|
|
||
|
var ndStrings = newTable[NdString, NdString]()
|
||
|
|
||
|
proc newString*(str: string): NdString =
|
||
|
let strlen = str.len()
|
||
|
let hash = str.fnv1a()
|
||
|
|
||
|
let interned = ndStrings.tableFindString(str[0].unsafeAddr, strlen, hash)
|
||
|
if interned != nil:
|
||
|
return interned
|
||
|
|
||
|
let len = 4 + strlen
|
||
|
result = cast[NdString](alloc(len))
|
||
|
result.len = strlen.uint32
|
||
|
result.hash = hash.uint32
|
||
|
copyMem(result.chars[0].unsafeAddr, str[0].unsafeAddr, strlen)
|
||
|
|
||
|
discard ndStrings.tableSet(result, nil)
|
||
|
|
||
|
proc `$`*(ndStr: NdString): string =
|
||
|
result = newString(ndStr.len.int)
|
||
|
copyMem(result[0].unsafeAddr, ndStr.chars[0].unsafeAddr, ndStr.len.int)
|
||
|
|
||
|
proc `&`*(left, right: NdString): NdString =
|
||
|
# TODO optimize this later when strings will be benchmarked
|
||
|
newString($left & $right)
|