Commit 64936209 authored by Kirill Smelkov's avatar Kirill Smelkov

xbytes: Additional utilities for working with byte slices

- small addons over std bytes package: xbytes.ContainsByte
- (re)allocation routines for byte slices
parent b1893d27
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Open Source Initiative approved licenses and Convey
// the resulting work. Corresponding source of such a combination shall include
// the source code for all other software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// (re)allocation routines for []byte
package xbytes
import (
"lab.nexedi.com/kirr/go123/xmath"
)
// Grow increases length of byte slice by n elements.
// If there is not enough capacity the slice is reallocated and copied.
// The memory for grown elements is not initialized.
func Grow(b []byte, n int) []byte {
ln := len(b) + n
if ln <= cap(b) {
return b[:ln]
}
bb := make([]byte, ln, xmath.CeilPow2(uint64(ln)))
copy(bb, b)
return bb
}
// MakeRoom makes sure cap(b) - len(b) >= n
// If there is not enough capacity the slice is reallocated and copied.
// Length of the slice remains unchanged.
func MakeRoom(b []byte, n int) []byte {
ln := len(b) + n
if ln <= cap(b) {
return b
}
bb := make([]byte, len(b), xmath.CeilPow2(uint64(ln)))
copy(bb, b)
return bb
}
// Resize resized byte slice to be of length n.
// If slice length is increased and there is not enough capacity the slice is reallocated and copied.
// The memory for grown elements, if any, is not initialized.
func Resize(b []byte, n int) []byte {
if cap(b) >= n {
return b[:n]
}
bb := make([]byte, n, xmath.CeilPow2(uint64(n)))
copy(bb, b)
return bb
}
// Realloc resizes byte slice to be of length n not preserving content.
// If slice length is increased and there is not enough capacity the slice is reallocated but not copied.
// The memory for all elements becomes uninitialized.
//
// NOTE semantic is different from C realloc(3) where content is preserved
// NOTE use Resize when you need to preserve slice content
func Realloc(b []byte, n int) []byte {
return Realloc64(b, int64(n))
}
// Realloc64 is the same as Realloc but for size typed as int64
func Realloc64(b []byte, n int64) []byte {
if int64(cap(b)) >= n {
return b[:n]
}
return make([]byte, n, xmath.CeilPow2(uint64(n)))
}
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Open Source Initiative approved licenses and Convey
// the resulting work. Corresponding source of such a combination shall include
// the source code for all other software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
package xbytes
import (
"bytes"
"reflect"
"testing"
"unsafe"
)
// aliases returns whether two slice memory is aliased
func aliases(b1, b2 []byte) bool {
s1 := (*reflect.SliceHeader)(unsafe.Pointer(&b1))
s2 := (*reflect.SliceHeader)(unsafe.Pointer(&b2))
return s1.Data == s2.Data
}
func TestSlice(t *testing.T) {
s := make([]byte, 0, 10)
testv := []struct {op func([]byte, int) []byte; n, Len, Cap int; aliased bool; content []byte} {
// op, n, Len, Cap, aliased, content
{Grow, 5, 5, 10, true, []byte{0,0,0,0,0}},
// here "Hello" is assigned
{Grow, 6, 11, 16, false, []byte("Hello\x00\x00\x00\x00\x00\x00")},
{MakeRoom, 4, 11, 16, true, []byte("Hello\x00\x00\x00\x00\x00\x00")},
{MakeRoom, 6, 11, 32, false, []byte("Hello\x00\x00\x00\x00\x00\x00")},
{Resize, 8, 8, 32, true, []byte("Hello\x00\x00\x00")},
{Resize, 33, 33, 64, false, append([]byte("Hello"), bytes.Repeat([]byte{0}, 33-5)...)},
{Realloc, 16, 16, 64, true, []byte("Hello\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")},
{Realloc, 65, 65, 128, false, make([]byte, 65)},
}
for i, tt := range testv {
sprev := s
s = tt.op(s, tt.n)
if !(len(s) == tt.Len && cap(s) == tt.Cap && bytes.Equal(s, tt.content)) {
t.Fatalf("step %d: %v: unexpected slice state: %v (cap: %v)", i, tt, s, cap(s))
}
if !(aliases(s, sprev) == tt.aliased) {
t.Fatalf("step %d: %v: unexpected slice aliasing: %v", aliases(s, sprev))
}
// assign data after first iteration
if i == 0 {
copy(s, "Hello")
}
}
}
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Open Source Initiative approved licenses and Convey
// the resulting work. Corresponding source of such a combination shall include
// the source code for all other software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// Package xbytes provides additional utilities for working with byte slices
package xbytes
import (
"bytes"
)
// ContainsByte is like bytes.ContainsRune but a bit faster
func ContainsByte(s []byte, c byte) bool {
return bytes.IndexByte(s, c) >= 0
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment