summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2023-09-29 00:08:31 +0800
committerGitHub <noreply@github.com>2023-09-28 18:08:31 +0200
commit285cbcb6aa36147e9b9c024ceed78e46526dd1ea (patch)
treef42ae1f52f808579b5ab6efa7125d9ca6134e639
parent4bf0f846df3bdeeeeff288f1d28688ee4852bc71 (diff)
downloadNim-285cbcb6aa36147e9b9c024ceed78e46526dd1ea.tar.gz
ref #19727; implement `setLenUninit` for seqsv2 (#22767)
ref #19727
-rw-r--r--changelog.md2
-rw-r--r--lib/system/seqs_v2.nim24
2 files changed, 26 insertions, 0 deletions
diff --git a/changelog.md b/changelog.md
index b661226be..e0eb34470 100644
--- a/changelog.md
+++ b/changelog.md
@@ -12,6 +12,8 @@
 [//]: # "Additions:"
 
 - Added `newStringUninit` to system, which creates a new string of length `len` like `newString` but with uninitialized content.
+- Added `setLenUninit` to system, which doesn't initalize
+slots when enlarging a sequence.
 - Added `hasDefaultValue` to `std/typetraits` to check if a type has a valid default value.
 - Added Viewport API for the JavaScript targets in the `dom` module.
 
diff --git a/lib/system/seqs_v2.nim b/lib/system/seqs_v2.nim
index c4e3e3e6b..7ce8de054 100644
--- a/lib/system/seqs_v2.nim
+++ b/lib/system/seqs_v2.nim
@@ -195,5 +195,29 @@ func capacity*[T](self: seq[T]): int {.inline.} =
   let sek = cast[ptr NimSeqV2[T]](unsafeAddr self)
   result = if sek.p != nil: sek.p.cap and not strlitFlag else: 0
 
+func setLenUninit*[T](s: var seq[T], newlen: Natural) {.nodestroy.} =
+  ## Sets the length of seq `s` to `newlen`. `T` may be any sequence type.
+  ## New slots will not be initialized.
+  ##
+  ## If the current length is greater than the new length,
+  ## `s` will be truncated.
+  ##   ```nim
+  ##   var x = @[10, 20]
+  ##   x.setLenUninit(5)
+  ##   x[4] = 50
+  ##   assert x[4] == 50
+  ##   x.setLenUninit(1)
+  ##   assert x == @[10]
+  ##   ```
+  {.noSideEffect.}:
+    if newlen < s.len:
+      shrink(s, newlen)
+    else:
+      let oldLen = s.len
+      if newlen <= oldLen: return
+      var xu = cast[ptr NimSeqV2[T]](addr s)
+      if xu.p == nil or (xu.p.cap and not strlitFlag) < newlen:
+        xu.p = cast[typeof(xu.p)](prepareSeqAddUninit(oldLen, xu.p, newlen - oldLen, sizeof(T), alignof(T)))
+      xu.len = newlen
 
 {.pop.}  # See https://github.com/nim-lang/Nim/issues/21401