summary refs log tree commit diff stats
path: root/lib/system/sysstr.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/system/sysstr.nim')
-rw-r--r--lib/system/sysstr.nim115
1 files changed, 70 insertions, 45 deletions
diff --git a/lib/system/sysstr.nim b/lib/system/sysstr.nim
index 4c5f3d9a1..7b81f54da 100644
--- a/lib/system/sysstr.nim
+++ b/lib/system/sysstr.nim
@@ -22,18 +22,34 @@ proc resize(old: int): int {.inline.} =
 
 proc cmpStrings(a, b: NimString): int {.inline, compilerProc.} =
   if a == b: return 0
-  if a == nil: return -1
-  if b == nil: return 1
-  let minlen = min(a.len, b.len)
-  result = c_memcmp(addr a.data, addr b.data, minlen.csize)
-  if result == 0:
-    result = a.len - b.len
+  when defined(nimNoNil):
+    let alen = if a == nil: 0 else: a.len
+    let blen = if b == nil: 0 else: b.len
+  else:
+    if a == nil: return -1
+    if b == nil: return 1
+    let alen = a.len
+    let blen = b.len
+  let minlen = min(alen, blen)
+  if minlen > 0:
+    result = c_memcmp(addr a.data, addr b.data, minlen.csize)
+    if result == 0:
+      result = alen - blen
+  else:
+    result = alen - blen
 
 proc eqStrings(a, b: NimString): bool {.inline, compilerProc.} =
   if a == b: return true
-  if a == nil or b == nil: return false
-  return a.len == b.len and
-    equalMem(addr(a.data), addr(b.data), a.len)
+  when defined(nimNoNil):
+    let alen = if a == nil: 0 else: a.len
+    let blen = if b == nil: 0 else: b.len
+  else:
+    if a == nil or b == nil: return false
+    let alen = a.len
+    let blen = b.len
+  if alen == blen:
+    if alen == 0: return true
+    return equalMem(addr(a.data), addr(b.data), alen)
 
 when declared(allocAtomic):
   template allocStr(size: untyped): untyped =
@@ -60,6 +76,7 @@ proc rawNewStringNoInit(space: int): NimString {.compilerProc.} =
   if s < 7: s = 7
   result = allocStrNoInit(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
+  result.len = 0
   when defined(gogc):
     result.elemSize = 1
 
@@ -68,6 +85,7 @@ proc rawNewString(space: int): NimString {.compilerProc.} =
   if s < 7: s = 7
   result = allocStr(sizeof(TGenericSeq) + s + 1)
   result.reserved = s
+  result.len = 0
   when defined(gogc):
     result.elemSize = 1
 
@@ -98,9 +116,6 @@ proc cstrToNimstr(str: cstring): NimString {.compilerRtl.} =
   if str == nil: NimString(nil)
   else: toNimStr(str, str.len)
 
-template wasMoved(x: NimString): bool = false
-# (x.reserved and seqShallowFlag) != 0
-
 proc copyString(src: NimString): NimString {.compilerRtl.} =
   if src != nil:
     if (src.reserved and seqShallowFlag) != 0:
@@ -158,14 +173,16 @@ proc hashString(s: string): int {.compilerproc.} =
 
 proc addChar(s: NimString, c: char): NimString =
   # is compilerproc!
-  result = s
-  if result.len >= result.space:
-    let r = resize(result.space)
-    result = cast[NimString](growObj(result,
-      sizeof(TGenericSeq) + r + 1))
-    result.reserved = r
-  elif wasMoved(s):
-    result = newOwnedString(s, s.len)
+  if s == nil:
+    result = rawNewStringNoInit(1)
+    result.len = 0
+  else:
+    result = s
+    if result.len >= result.space:
+      let r = resize(result.space)
+      result = cast[NimString](growObj(result,
+        sizeof(TGenericSeq) + r + 1))
+      result.reserved = r
   result.data[result.len] = c
   result.data[result.len+1] = '\0'
   inc(result.len)
@@ -202,7 +219,9 @@ proc addChar(s: NimString, c: char): NimString =
 #   s = rawNewString(0);
 
 proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
-  if dest.len + addlen <= dest.space and not wasMoved(dest):
+  if dest == nil:
+    result = rawNewStringNoInit(addlen)
+  elif dest.len + addlen <= dest.space:
     result = dest
   else: # slow path:
     var sp = max(resize(dest.space), dest.len + addlen)
@@ -213,8 +232,9 @@ proc resizeString(dest: NimString, addlen: int): NimString {.compilerRtl.} =
     # DO NOT UPDATE LEN YET: dest.len = newLen
 
 proc appendString(dest, src: NimString) {.compilerproc, inline.} =
-  copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1)
-  inc(dest.len, src.len)
+  if src != nil:
+    copyMem(addr(dest.data[dest.len]), addr(src.data), src.len + 1)
+    inc(dest.len, src.len)
 
 proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
   dest.data[dest.len] = c
@@ -223,8 +243,8 @@ proc appendChar(dest: NimString, c: char) {.compilerproc, inline.} =
 
 proc setLengthStr(s: NimString, newLen: int): NimString {.compilerRtl.} =
   var n = max(newLen, 0)
-  if wasMoved(s):
-    result = newOwnedString(s, n)
+  if s == nil:
+    result = mnewString(newLen)
   elif n <= s.space:
     result = s
   else:
@@ -258,6 +278,18 @@ proc incrSeqV2(seq: PGenericSeq, elemSize: int): PGenericSeq {.compilerProc.} =
                                GenericSeqSize))
     result.reserved = r
 
+proc incrSeqV3(s: PGenericSeq, typ: PNimType): PGenericSeq {.compilerProc.} =
+  if s == nil:
+    result = cast[PGenericSeq](newSeq(typ, 1))
+    result.len = 0
+  else:
+    result = s
+    if result.len >= result.space:
+      let r = resize(result.space)
+      result = cast[PGenericSeq](growObj(result, typ.base.size * r +
+                                GenericSeqSize))
+      result.reserved = r
+
 proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
     compilerRtl, inl.} =
   result = seq
@@ -290,7 +322,7 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
 
     # XXX: zeroing out the memory can still result in crashes if a wiped-out
     # cell is aliased by another pointer (ie proc parameter or a let variable).
-    # This is a tought problem, because even if we don't zeroMem here, in the
+    # This is a tough problem, because even if we don't zeroMem here, in the
     # presence of user defined destructors, the user will expect the cell to be
     # "destroyed" thus creating the same problem. We can destoy the cell in the
     # finalizer of the sequence, but this makes destruction non-deterministic.
@@ -298,6 +330,13 @@ proc setLengthSeq(seq: PGenericSeq, elemSize, newLen: int): PGenericSeq {.
            (newLen*%elemSize)), (result.len-%newLen) *% elemSize)
   result.len = newLen
 
+proc setLengthSeqV2(s: PGenericSeq, typ: PNimType, newLen: int): PGenericSeq {.
+    compilerRtl.} =
+  if s == nil:
+    result = cast[PGenericSeq](newSeq(typ, newLen))
+  else:
+    result = setLengthSeq(s, typ.base.size, newLen)
+
 # --------------- other string routines ----------------------------------
 proc add*(result: var string; x: int64) =
   let base = result.len
@@ -386,8 +425,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
     kdigits, fdigits = 0
     exponent: int
     integer: uint64
-    fraction: uint64
-    frac_exponent= 0
+    frac_exponent = 0
     exp_sign = 1
     first_digit = -1
     has_sign = false
@@ -418,7 +456,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
     return 0
 
   if s[i] in {'0'..'9'}:
-      first_digit = (s[i].ord - '0'.ord)
+    first_digit = (s[i].ord - '0'.ord)
   # Integer part?
   while s[i] in {'0'..'9'}:
     inc(kdigits)
@@ -480,7 +518,8 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
 
   # if integer is representable in 53 bits:  fast path
   # max fast path integer is  1<<53 - 1 or  8999999999999999 (16 digits)
-  if kdigits + fdigits <= 16 and first_digit <= 8:
+  let digits = kdigits + fdigits
+  if digits <= 15 or (digits <= 16 and first_digit <= 8):
     # max float power of ten with set bits above the 53th bit is 10^22
     if abs_exponent <= 22:
       if exp_negative:
@@ -504,6 +543,7 @@ proc nimParseBiggestFloat(s: string, number: var BiggestFloat,
   result = i - start
   i = start
   # re-parse without error checking, any error should be handled by the code above.
+  if s[i] == '.': i.inc
   while s[i] in {'0'..'9','+','-'}:
     if ti < maxlen:
       t[ti] = s[i]; inc(ti)
@@ -536,18 +576,3 @@ proc nimBoolToStr(x: bool): string {.compilerRtl.} =
 proc nimCharToStr(x: char): string {.compilerRtl.} =
   result = newString(1)
   result[0] = x
-
-proc binaryStrSearch(x: openArray[string], y: string): int {.compilerproc.} =
-  var
-    a = 0
-    b = len(x)
-  while a < b:
-    var mid = (a + b) div 2
-    if x[mid] < y:
-      a = mid + 1
-    else:
-      b = mid
-  if a < len(x) and x[a] == y:
-    result = a
-  else:
-    result = -1