]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/slices/slices.go
slices: update doc for Delete and Replace
[gostls13.git] / src / slices / slices.go
index afeed0afb522ceafe29a63aaa0194ae7b9e2d46b..4c398557ff4241565f5ac776d28561cc53913abb 100644 (file)
@@ -130,11 +130,14 @@ func ContainsFunc[S ~[]E, E any](s S, f func(E) bool) bool {
 // Insert panics if i is out of range.
 // This function is O(len(s) + len(v)).
 func Insert[S ~[]E, E any](s S, i int, v ...E) S {
+       n := len(s)
        m := len(v)
        if m == 0 {
+               // Panic if i is not in the range [0:n] inclusive.
+               // See issue 63913.
+               _ = s[:n:n][i:]
                return s
        }
-       n := len(s)
        if i == n {
                return append(s, v...)
        }
@@ -209,7 +212,7 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
 }
 
 // Delete removes the elements s[i:j] from s, returning the modified slice.
-// Delete panics if s[i:j] is not a valid slice of s.
+// Delete panics if j > len(s) or s[i:j] is not a valid slice of s.
 // Delete is O(len(s)-j), so if many items must be deleted, it is better to
 // make a single call deleting them all together than to delete one at a time.
 // Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those
@@ -228,27 +231,25 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
 // zeroing those elements so that objects they reference can be garbage
 // collected.
 func DeleteFunc[S ~[]E, E any](s S, del func(E) bool) S {
+       i := IndexFunc(s, del)
+       if i == -1 {
+               return s
+       }
        // Don't start copying elements until we find one to delete.
-       for i, v := range s {
-               if del(v) {
-                       j := i
-                       for i++; i < len(s); i++ {
-                               v = s[i]
-                               if !del(v) {
-                                       s[j] = v
-                                       j++
-                               }
-                       }
-                       return s[:j]
+       for j := i + 1; j < len(s); j++ {
+               if v := s[j]; !del(v) {
+                       s[i] = v
+                       i++
                }
        }
-       return s
+       return s[:i]
 }
 
 // Replace replaces the elements s[i:j] by the given v, and returns the
-// modified slice. Replace panics if s[i:j] is not a valid slice of s.
+// modified slice.
+// Replace panics if j > len(s) or s[i:j] is not a valid slice of s.
 func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
-       _ = s[i:j] // verify that i:j is a valid subslice
+       _ = s[i:j] // bounds check
 
        if i == j {
                return Insert(s, i, v...)
@@ -271,9 +272,7 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
        if i+len(v) <= j {
                // Easy, as v fits in the deleted portion.
                copy(r[i:], v)
-               if i+len(v) != j {
-                       copy(r[i+len(v):], s[j:])
-               }
+               copy(r[i+len(v):], s[j:])
                return r
        }
 
@@ -336,11 +335,8 @@ func Replace[S ~[]E, E any](s S, i, j int, v ...E) S {
 // Clone returns a copy of the slice.
 // The elements are copied using assignment, so this is a shallow clone.
 func Clone[S ~[]E, E any](s S) S {
-       // Preserve nil in case it matters.
-       if s == nil {
-               return nil
-       }
-       return append(S([]E{}), s...)
+       // The s[:0:0] preserves nil in case it matters.
+       return append(s[:0:0], s...)
 }
 
 // Compact replaces consecutive runs of equal elements with a single copy.
@@ -496,3 +492,19 @@ func Reverse[S ~[]E, E any](s S) {
                s[i], s[j] = s[j], s[i]
        }
 }
+
+// Concat returns a new slice concatenating the passed in slices.
+func Concat[S ~[]E, E any](slices ...S) S {
+       size := 0
+       for _, s := range slices {
+               size += len(s)
+               if size < 0 {
+                       panic("len out of range")
+               }
+       }
+       newslice := Grow[S](nil, size)
+       for _, s := range slices {
+               newslice = append(newslice, s...)
+       }
+       return newslice
+}