| | |
| | |
| | |
| |
|
| | package slicereader |
| |
|
| | import ( |
| | "encoding/binary" |
| | "fmt" |
| | "io" |
| | "unsafe" |
| | ) |
| |
|
| | |
| | |
| | |
| |
|
| | 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 |
| | } |
| | |
| | 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) |
| | } |
| | return string(b) |
| | } |
| |
|
| | func toString(b []byte) string { |
| | if len(b) == 0 { |
| | return "" |
| | } |
| | return unsafe.String(&b[0], len(b)) |
| | } |
| |
|