SSO for strings (#25593)

This commit is contained in:
Andreas Rumpf
2026-04-02 07:19:43 +02:00
committed by GitHub
parent be29bcd402
commit d389d4fb2f
29 changed files with 2235 additions and 171 deletions

View File

@@ -19,7 +19,12 @@ proc addCstringN(result: var string, buf: cstring; buflen: int) =
let oldLen = result.len
let newLen = oldLen + buflen
result.setLen newLen
c_memcpy(result[oldLen].addr, buf, buflen.csize_t)
{.cast(noSideEffect).}:
when declared(completeStore):
c_memcpy(beginStore(result, buflen, oldLen), buf, buflen.csize_t)
endStore(result)
else:
discard c_memcpy(result[oldLen].addr, buf, buflen.csize_t)
import std/private/[dragonbox, schubfach]

View File

@@ -52,7 +52,7 @@ func addChars[T](result: var string, x: T, start: int, n: int) {.inline, enforce
for i in 0..<n: result[old + i] = x[start + i]
when nimvm: impl
else:
when defined(js) or defined(nimscript): impl
when defined(js) or defined(nimscript) or defined(nimsso): impl
else:
{.noSideEffect.}:
copyMem result[old].addr, x[start].unsafeAddr, n

View File

@@ -84,9 +84,9 @@ func setSlice*(s: var string, slice: Slice[int]) =
when not declared(moveMem):
impl()
else:
when defined(nimSeqsV2):
prepareMutation(s)
moveMem(addr s[0], addr s[first], last - first + 1)
let p = beginStore(s, last - first + 1)
moveMem(p, addr p[first], last - first + 1)
endStore(s)
s.setLen(last - first + 1)
func strip*(a: var string, leading = true, trailing = true, chars: set[char] = whitespaces) {.inline.} =

View File

@@ -485,7 +485,8 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
while true:
# fixes #9634; this pattern may need to be abstracted as a template if reused;
# likely other io procs need this for correctness.
fgetsSuccess = c_fgets(cast[cstring](addr line[pos]), sp.cint, f) != nil
fgetsSuccess = c_fgets(cast[cstring](beginStore(line, sp, pos)), sp.cint, f) != nil
endStore(line)
if fgetsSuccess: break
when not defined(nimscript):
if errno == EINTR:
@@ -495,10 +496,11 @@ proc readLine*(f: File, line: var string): bool {.tags: [ReadIOEffect],
checkErr(f)
break
let m = c_memchr(addr line[pos], cint('\L'), cast[csize_t](sp))
let lineData = readRawData(line)
let m = c_memchr(addr lineData[pos], cint('\L'), cast[csize_t](sp))
if m != nil:
# \l found: Could be our own or the one by fgets, in any case, we're done
var last = cast[int](m) - cast[int](addr line[0])
var last = cast[int](m) - cast[int](lineData)
if last > 0 and line[last-1] == '\c':
line.setLen(last-1)
return last > 1 or fgetsSuccess
@@ -564,7 +566,8 @@ proc readAllBuffer(file: File): string =
result = ""
var buffer = newString(BufSize)
while true:
var bytesRead = readBuffer(file, addr(buffer[0]), BufSize)
var bytesRead = readBuffer(file, beginStore(buffer, BufSize), BufSize)
endStore(buffer)
if bytesRead == BufSize:
result.add(buffer)
else:
@@ -590,7 +593,8 @@ proc readAllFile(file: File, len: int64): string =
# We acquire the filesize beforehand and hope it doesn't change.
# Speeds things up.
result = newString(len)
let bytes = readBuffer(file, addr(result[0]), len)
let bytes = readBuffer(file, beginStore(result, len.int), len.int)
endStore(result)
if endOfFile(file):
if bytes.int64 < len:
result.setLen(bytes)