diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:19:13 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:19:13 +0000 |
commit | ccd992355df7192993c666236047820244914598 (patch) | |
tree | f00fea65147227b7743083c6148396f74cd66935 /src/internal/coverage/slicereader/slicereader.go | |
parent | Initial commit. (diff) | |
download | golang-1.21-ccd992355df7192993c666236047820244914598.tar.xz golang-1.21-ccd992355df7192993c666236047820244914598.zip |
Adding upstream version 1.21.8.upstream/1.21.8
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/internal/coverage/slicereader/slicereader.go')
-rw-r--r-- | src/internal/coverage/slicereader/slicereader.go | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/internal/coverage/slicereader/slicereader.go b/src/internal/coverage/slicereader/slicereader.go new file mode 100644 index 0000000..d9f2a7e --- /dev/null +++ b/src/internal/coverage/slicereader/slicereader.go @@ -0,0 +1,123 @@ +// Copyright 2021 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package slicereader + +import ( + "encoding/binary" + "fmt" + "io" + "unsafe" +) + +// This file contains the helper "SliceReader", a utility for +// reading values from a byte slice that may or may not be backed +// by a read-only mmap'd region. + +type Reader struct { + b []byte + readonly bool + off int64 +} + +func NewReader(b []byte, readonly bool) *Reader { + r := Reader{ + b: b, + readonly: readonly, + } + return &r +} + +func (r *Reader) Read(b []byte) (int, error) { + amt := len(b) + toread := r.b[r.off:] + if len(toread) < amt { + amt = len(toread) + } + copy(b, toread) + r.off += int64(amt) + return amt, nil +} + +func (r *Reader) Seek(offset int64, whence int) (ret int64, err error) { + switch whence { + case io.SeekStart: + if offset < 0 || offset > int64(len(r.b)) { + return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", offset, len(r.b)) + } + r.off = offset + return offset, nil + case io.SeekCurrent: + newoff := r.off + offset + if newoff < 0 || newoff > int64(len(r.b)) { + return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b)) + } + r.off = newoff + return r.off, nil + case io.SeekEnd: + newoff := int64(len(r.b)) + offset + if newoff < 0 || newoff > int64(len(r.b)) { + return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b)) + } + r.off = newoff + return r.off, nil + } + // other modes are not supported + return 0, fmt.Errorf("unsupported seek mode %d", whence) +} + +func (r *Reader) Offset() int64 { + return r.off +} + +func (r *Reader) ReadUint8() uint8 { + rv := uint8(r.b[int(r.off)]) + r.off += 1 + return rv +} + +func (r *Reader) ReadUint32() uint32 { + end := int(r.off) + 4 + rv := binary.LittleEndian.Uint32(r.b[int(r.off):end:end]) + r.off += 4 + return rv +} + +func (r *Reader) ReadUint64() uint64 { + end := int(r.off) + 8 + rv := binary.LittleEndian.Uint64(r.b[int(r.off):end:end]) + r.off += 8 + return rv +} + +func (r *Reader) ReadULEB128() (value uint64) { + var shift uint + + for { + b := r.b[r.off] + r.off++ + value |= (uint64(b&0x7F) << shift) + if b&0x80 == 0 { + break + } + shift += 7 + } + return +} + +func (r *Reader) ReadString(len int64) string { + b := r.b[r.off : r.off+len] + r.off += len + if r.readonly { + return toString(b) // backed by RO memory, ok to make unsafe string + } + return string(b) +} + +func toString(b []byte) string { + if len(b) == 0 { + return "" + } + return unsafe.String(&b[0], len(b)) +} |