blob: 2abcfecdc24d7b23f304938aead9d60f0dbf2f8d [file] [log] [blame] [edit]
/*
* Copyright 2020 Dgraph Labs, Inc. and Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package y
import (
"encoding/binary"
"github.com/dgraph-io/ristretto/z"
)
type Buffer struct {
buf []byte
offset int
}
func NewBuffer(sz int) *Buffer {
return &Buffer{
buf: z.Calloc(sz),
offset: 0,
}
}
func (b *Buffer) Len() int {
return b.offset
}
func (b *Buffer) Bytes() []byte {
return b.buf[0:b.offset]
}
// smallBufferSize is an initial allocation minimal capacity.
const smallBufferSize = 64
func (b *Buffer) Grow(n int) {
// In this case, len and cap are the same.
if len(b.buf) == 0 && n <= smallBufferSize {
b.buf = z.Calloc(smallBufferSize)
return
} else if b.buf == nil {
b.buf = z.Calloc(n)
return
}
if b.offset+n < len(b.buf) {
return
}
sz := 2*len(b.buf) + n
newBuf := z.Calloc(sz)
copy(newBuf, b.buf[:b.offset])
z.Free(b.buf)
b.buf = newBuf
}
// Allocate is not thread-safe. The byte slice returned MUST be used before further calls to Buffer.
func (b *Buffer) Allocate(n int) []byte {
b.Grow(n)
off := b.offset
b.offset += n
return b.buf[off:b.offset]
}
func (b *Buffer) writeLen(sz int) {
buf := b.Allocate(4)
binary.BigEndian.PutUint32(buf, uint32(sz))
}
func (b *Buffer) SliceAllocate(sz int) []byte {
b.Grow(4 + sz)
b.writeLen(sz)
return b.Allocate(sz)
}
func (b *Buffer) SliceOffsets(offsets []int) []int {
start := 0
for start < b.offset {
offsets = append(offsets, start)
sz := binary.BigEndian.Uint32(b.buf[start:])
start += 4 + int(sz)
}
return offsets
}
func (b *Buffer) Slice(offset int) []byte {
sz := binary.BigEndian.Uint32(b.buf[offset:])
start := offset + 4
return b.buf[start : start+int(sz)]
}
func (b *Buffer) Write(p []byte) (n int, err error) {
b.Grow(len(p))
n = copy(b.buf[b.offset:], p)
b.offset += n
return n, nil
}
func (b *Buffer) Reset() {
b.offset = 0
}
func (b *Buffer) Release() {
z.Free(b.buf)
}