mirror of
https://github.com/nim-lang/Nim.git
synced 2026-05-25 22:38:15 +00:00
SSO strings: bugfix (#25810)
This commit is contained in:
@@ -2694,7 +2694,9 @@ when hasAlloc or defined(nimscript):
|
||||
setLen(x, xl+item.len)
|
||||
var j = xl-1
|
||||
while j >= i:
|
||||
when defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc):
|
||||
when defined(nimsso):
|
||||
x[j+item.len] = x[j]
|
||||
elif defined(gcArc) or defined(gcOrc) or defined(gcYrc) or defined(gcAtomicArc):
|
||||
x[j+item.len] = move x[j]
|
||||
else:
|
||||
shallowCopy(x[j+item.len], x[j])
|
||||
|
||||
@@ -59,16 +59,35 @@ template `[]=`*(s: string; i: int; val: char) = arrPut(s, i, val)
|
||||
template `^^`(s, i: untyped): untyped =
|
||||
(when i is BackwardsIndex: s.len - int(i) else: int(i))
|
||||
|
||||
template spliceImpl(s, a, L, b: typed): untyped =
|
||||
template spliceStringImpl(s, a, L, b: typed): untyped =
|
||||
# make room for additional elements or cut:
|
||||
var shift = b.len - max(0,L) # ignore negative slice size
|
||||
var newLen = s.len + shift
|
||||
if shift > 0:
|
||||
# enlarge:
|
||||
setLen(s, newLen)
|
||||
for i in countdown(newLen-1, a+b.len): movingCopy(s[i], s[i-shift])
|
||||
for i in countdown(newLen-1, a+b.len):
|
||||
s[i] = s[i-shift]
|
||||
else:
|
||||
for i in countup(a+b.len, newLen-1): movingCopy(s[i], s[i-shift])
|
||||
for i in countup(a+b.len, newLen-1):
|
||||
s[i] = s[i-shift]
|
||||
# cut down:
|
||||
setLen(s, newLen)
|
||||
# fill the hole:
|
||||
for i in 0 ..< b.len: s[a+i] = b[i]
|
||||
|
||||
template spliceSeqImpl(s, a, L, b: typed): untyped =
|
||||
# make room for additional elements or cut:
|
||||
var shift = b.len - max(0,L) # ignore negative slice size
|
||||
var newLen = s.len + shift
|
||||
if shift > 0:
|
||||
# enlarge:
|
||||
setLen(s, newLen)
|
||||
for i in countdown(newLen-1, a+b.len):
|
||||
movingCopy(s[i], s[i-shift])
|
||||
else:
|
||||
for i in countup(a+b.len, newLen-1):
|
||||
movingCopy(s[i], s[i-shift])
|
||||
# cut down:
|
||||
setLen(s, newLen)
|
||||
# fill the hole:
|
||||
@@ -102,7 +121,7 @@ proc `[]=`*[T, U: Ordinal](s: var string, x: HSlice[T, U], b: string) {.systemRa
|
||||
if L == b.len:
|
||||
for i in 0..<L: s[i+a] = b[i]
|
||||
else:
|
||||
spliceImpl(s, a, L, b)
|
||||
spliceStringImpl(s, a, L, b)
|
||||
|
||||
proc `[]`*[Idx, T; U, V: Ordinal](a: array[Idx, T], x: HSlice[U, V]): seq[T] {.systemRaisesDefect.} =
|
||||
## Slice operation for arrays.
|
||||
@@ -162,4 +181,4 @@ proc `[]=`*[T; U, V: Ordinal](s: var seq[T], x: HSlice[U, V], b: openArray[T]) {
|
||||
if L == b.len:
|
||||
for i in 0 ..< L: s[i+a] = b[i]
|
||||
else:
|
||||
spliceImpl(s, a, L, b)
|
||||
spliceSeqImpl(s, a, L, b)
|
||||
|
||||
@@ -224,13 +224,14 @@ proc cmpStringPtrs(a, b: ptr SmallString): int {.inline.} =
|
||||
minLen - AlwaysAvail)
|
||||
if result == 0: result = aslen - bslen
|
||||
return
|
||||
# At least one is long. Hot prefix: inlinePtr[0..AlwaysAvail-1] mirrors heap data.
|
||||
let pfxLen = min(min(aslen, bslen), AlwaysAvail)
|
||||
result = cmpInlineBytes(inlinePtrOf(a), inlinePtrOf(b), pfxLen)
|
||||
if result != 0: return
|
||||
# At least one is long. Hot prefix mirrors heap data, but only up to fullLen:
|
||||
# shrinking can leave stale bytes in the inline cache past the logical length.
|
||||
let la = if aslen > PayloadSize: a.more.fullLen else: aslen
|
||||
let lb = if bslen > PayloadSize: b.more.fullLen else: bslen
|
||||
let minLen = min(la, lb)
|
||||
let pfxLen = min(minLen, AlwaysAvail)
|
||||
result = cmpInlineBytes(inlinePtrOf(a), inlinePtrOf(b), pfxLen)
|
||||
if result != 0: return
|
||||
if minLen <= AlwaysAvail:
|
||||
result = la - lb
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user