1
2
3
4
5 package slicereader
6
7 import (
8 "encoding/binary"
9 "fmt"
10 "io"
11 "unsafe"
12 )
13
14
15
16
17
18 type Reader struct {
19 b []byte
20 readonly bool
21 off int64
22 }
23
24 func NewReader(b []byte, readonly bool) *Reader {
25 r := Reader{
26 b: b,
27 readonly: readonly,
28 }
29 return &r
30 }
31
32 func (r *Reader) Read(b []byte) (int, error) {
33 amt := len(b)
34 toread := r.b[r.off:]
35 if len(toread) < amt {
36 amt = len(toread)
37 }
38 copy(b, toread)
39 r.off += int64(amt)
40 return amt, nil
41 }
42
43 func (r *Reader) Seek(offset int64, whence int) (ret int64, err error) {
44 switch whence {
45 case io.SeekStart:
46 if offset < 0 || offset > int64(len(r.b)) {
47 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", offset, len(r.b))
48 }
49 r.off = offset
50 return offset, nil
51 case io.SeekCurrent:
52 newoff := r.off + offset
53 if newoff < 0 || newoff > int64(len(r.b)) {
54 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b))
55 }
56 r.off = newoff
57 return r.off, nil
58 case io.SeekEnd:
59 newoff := int64(len(r.b)) + offset
60 if newoff < 0 || newoff > int64(len(r.b)) {
61 return 0, fmt.Errorf("invalid seek: new offset %d (out of range [0 %d]", newoff, len(r.b))
62 }
63 r.off = newoff
64 return r.off, nil
65 }
66
67 return 0, fmt.Errorf("unsupported seek mode %d", whence)
68 }
69
70 func (r *Reader) Offset() int64 {
71 return r.off
72 }
73
74 func (r *Reader) ReadUint8() uint8 {
75 rv := uint8(r.b[int(r.off)])
76 r.off += 1
77 return rv
78 }
79
80 func (r *Reader) ReadUint32() uint32 {
81 end := int(r.off) + 4
82 rv := binary.LittleEndian.Uint32(r.b[int(r.off):end:end])
83 r.off += 4
84 return rv
85 }
86
87 func (r *Reader) ReadUint64() uint64 {
88 end := int(r.off) + 8
89 rv := binary.LittleEndian.Uint64(r.b[int(r.off):end:end])
90 r.off += 8
91 return rv
92 }
93
94 func (r *Reader) ReadULEB128() (value uint64) {
95 var shift uint
96
97 for {
98 b := r.b[r.off]
99 r.off++
100 value |= (uint64(b&0x7F) << shift)
101 if b&0x80 == 0 {
102 break
103 }
104 shift += 7
105 }
106 return
107 }
108
109 func (r *Reader) ReadString(len int64) string {
110 b := r.b[r.off : r.off+len]
111 r.off += len
112 if r.readonly {
113 return toString(b)
114 }
115 return string(b)
116 }
117
118 func toString(b []byte) string {
119 if len(b) == 0 {
120 return ""
121 }
122 return unsafe.String(&b[0], len(b))
123 }
124
View as plain text