Skip to content

Commit 8530ade

Browse files
committed
Update
1 parent 14f587b commit 8530ade

4 files changed

Lines changed: 151 additions & 94 deletions

File tree

binary.go

Lines changed: 145 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,6 @@ type IBinaryReader interface {
1717
Close() error
1818
}
1919

20-
type binaryReaderFile struct {
21-
f *os.File
22-
size int64
23-
}
24-
25-
func newBinaryReaderFile(filename string) (*binaryReaderFile, error) {
26-
f, err := os.Open(filename)
27-
if err != nil {
28-
return nil, err
29-
}
30-
fi, err := f.Stat()
31-
if err != nil {
32-
f.Close()
33-
return nil, err
34-
}
35-
return &binaryReaderFile{f, fi.Size()}, nil
36-
}
37-
38-
// Close closes the reader.
39-
func (r *binaryReaderFile) Close() error {
40-
return r.f.Close()
41-
}
42-
43-
// Len returns the length of the underlying memory-mapped file.
44-
func (r *binaryReaderFile) Len() int64 {
45-
return r.size
46-
}
47-
48-
func (r *binaryReaderFile) Bytes(b []byte, n, off int64) ([]byte, error) {
49-
if b == nil {
50-
b = make([]byte, n)
51-
}
52-
if m, err := r.f.ReadAt(b, off); err != nil {
53-
return b[:m], err
54-
} else if off+int64(m) == r.size {
55-
return b[:m], io.EOF
56-
} else if int64(m) != n {
57-
return b[:m], errors.New("file: could not read all bytes")
58-
}
59-
return b, nil
60-
}
61-
6220
type binaryReaderBytes struct {
6321
data []byte
6422
}
@@ -97,17 +55,12 @@ func (r *binaryReaderBytes) Bytes(b []byte, n, off int64) ([]byte, error) {
9755
}
9856

9957
type binaryReaderReader struct {
100-
r io.Reader
101-
size int64
102-
readerAt bool
103-
seeker bool
104-
mu sync.Mutex
58+
r io.Reader
59+
pos, size int64
10560
}
10661

10762
func newBinaryReaderReader(r io.Reader, n int64) *binaryReaderReader {
108-
_, readerAt := r.(io.ReaderAt)
109-
_, seeker := r.(io.Seeker)
110-
return &binaryReaderReader{r, n, readerAt, seeker, sync.Mutex{}}
63+
return &binaryReaderReader{r, 0, n}
11164
}
11265

11366
// Close closes the reader.
@@ -118,46 +71,118 @@ func (r *binaryReaderReader) Close() error {
11871
return nil
11972
}
12073

121-
// Len returns the length of the underlying memory-mapped file.
74+
// Len returns the length of the file.
12275
func (r *binaryReaderReader) Len() int64 {
12376
return r.size
12477
}
12578

12679
func (r *binaryReaderReader) Bytes(b []byte, n, off int64) ([]byte, error) {
127-
if b == nil {
80+
if off != r.pos {
81+
return nil, errors.New("reader: does not implement io.Seeker or io.ReaderAt")
82+
} else if b == nil {
12883
b = make([]byte, n)
12984
}
13085

131-
// seeker seems faster than readerAt by 10%
132-
if r.seeker {
133-
r.mu.Lock()
134-
if _, err := r.r.(io.Seeker).Seek(off, 0); err != nil {
135-
r.mu.Unlock()
136-
return nil, err
86+
for i := 0; i < int(n); {
87+
m, err := r.r.Read(b[i:])
88+
r.pos += int64(m)
89+
i += m
90+
if err != nil {
91+
return b[:i], err
92+
} else if m == 0 {
93+
return b[:i], errors.New("reader: could not read all bytes")
13794
}
95+
}
96+
if off+n == r.size {
97+
return b, io.EOF
98+
}
99+
return b, nil
100+
}
101+
102+
type binaryReaderSeeker struct {
103+
r io.ReadSeeker
104+
size int64
105+
mu sync.Mutex
106+
}
138107

139-
m, err := r.r.Read(b)
108+
func newBinaryReaderSeeker(r io.ReadSeeker, n int64) *binaryReaderSeeker {
109+
return &binaryReaderSeeker{r, n, sync.Mutex{}}
110+
}
111+
112+
// Close closes the reader.
113+
func (r *binaryReaderSeeker) Close() error {
114+
if closer, ok := r.r.(io.Closer); ok {
115+
return closer.Close()
116+
}
117+
return nil
118+
}
119+
120+
// Len returns the length of the file.
121+
func (r *binaryReaderSeeker) Len() int64 {
122+
return r.size
123+
}
124+
125+
func (r *binaryReaderSeeker) Bytes(b []byte, n, off int64) ([]byte, error) {
126+
if b == nil {
127+
b = make([]byte, n)
128+
}
129+
130+
r.mu.Lock()
131+
if _, err := r.r.Seek(off, 0); err != nil {
140132
r.mu.Unlock()
133+
return nil, err
134+
}
135+
for i := 0; i < int(n); {
136+
m, err := r.r.Read(b[i:])
137+
i += m
141138
if err != nil {
142-
return b[:m], err
143-
} else if off+int64(m) == r.size {
144-
return b[:m], io.EOF
145-
} else if int64(m) != n {
146-
return b[:m], errors.New("reader: could not read all bytes")
147-
}
148-
return b, nil
149-
} else if r.readerAt {
150-
m, err := r.r.(io.ReaderAt).ReadAt(b, off)
151-
if err != nil {
152-
return b[:m], err
153-
} else if off+int64(m) == r.size {
154-
return b[:m], io.EOF
155-
} else if int64(m) != n {
156-
return b[:m], errors.New("reader: could not read all bytes")
139+
return b[:i], err
140+
} else if m == 0 {
141+
return b[:i], errors.New("reader: could not read all bytes")
157142
}
158-
return b, nil
159143
}
160-
return nil, errors.New("io.Seeker and io.ReaderAt not implemented")
144+
r.mu.Unlock()
145+
146+
if off+n == r.size {
147+
return b, io.EOF
148+
}
149+
return b, nil
150+
}
151+
152+
type binaryReaderReaderAt struct {
153+
r io.ReaderAt
154+
size int64
155+
}
156+
157+
func newBinaryReaderReaderAt(r io.ReaderAt, n int64) *binaryReaderReaderAt {
158+
return &binaryReaderReaderAt{r, n}
159+
}
160+
161+
// Close closes the reader.
162+
func (r *binaryReaderReaderAt) Close() error {
163+
if closer, ok := r.r.(io.Closer); ok {
164+
return closer.Close()
165+
}
166+
return nil
167+
}
168+
169+
// Len returns the length of the file.
170+
func (r *binaryReaderReaderAt) Len() int64 {
171+
return r.size
172+
}
173+
174+
func (r *binaryReaderReaderAt) Bytes(b []byte, n, off int64) ([]byte, error) {
175+
if b == nil {
176+
b = make([]byte, n)
177+
}
178+
if m, err := r.r.ReadAt(b, off); err != nil {
179+
return b[:m], err
180+
} else if off+int64(m) == r.size {
181+
return b[:m], io.EOF
182+
} else if int64(m) != n {
183+
return b[:m], errors.New("reader: could not read all bytes")
184+
}
185+
return b, nil
161186
}
162187

163188
type BinaryReader struct {
@@ -175,19 +200,36 @@ func NewBinaryReader(f IBinaryReader) *BinaryReader {
175200
}
176201
}
177202

203+
// Will use Bytes when interface { Bytes() []byte } is implemented (n not used), Seeker when io.Seeker is implemented (negative n tolerated), ReaderAt when io.ReaderAt is implemented, otherwise it will read all bytes if n is negative or returns a non-Seeking/non-ReaderAt reader that does not allow Seek.
178204
func NewBinaryReaderReader(r io.Reader, n int64) (*BinaryReader, error) {
179-
_, isReaderAt := r.(io.ReaderAt)
180-
_, isSeeker := r.(io.Seeker)
181-
182205
var f IBinaryReader
183-
if isReaderAt || isSeeker {
184-
f = newBinaryReaderReader(r, n)
185-
} else {
186-
b := make([]byte, n)
187-
if _, err := io.ReadFull(r, b); err != nil {
206+
if b, ok := r.(interface{ Bytes() []byte }); ok {
207+
f = newBinaryReaderBytes(b.Bytes())
208+
} else if seeker, ok := r.(io.ReadSeeker); ok {
209+
// seeker seems faster than readerAt by 10%
210+
if n < 0 {
211+
if offset, err := seeker.Seek(0, os.SEEK_CUR); err != nil {
212+
return nil, err
213+
} else if n, err = seeker.Seek(0, os.SEEK_END); err != nil {
214+
return nil, err
215+
} else if _, err = seeker.Seek(offset, os.SEEK_SET); err != nil {
216+
return nil, err
217+
}
218+
}
219+
f = newBinaryReaderSeeker(seeker, n)
220+
} else if readerAt, ok := r.(io.ReaderAt); ok {
221+
if n < 0 {
222+
return nil, fmt.Errorf("invalid negative size")
223+
}
224+
f = newBinaryReaderReaderAt(readerAt, n)
225+
} else if n < 0 {
226+
b, err := io.ReadAll(r)
227+
if err != nil {
188228
return nil, err
189229
}
190230
f = newBinaryReaderBytes(b)
231+
} else {
232+
f = newBinaryReaderReader(r, n)
191233
}
192234
return NewBinaryReader(f), nil
193235
}
@@ -197,12 +239,25 @@ func NewBinaryReaderBytes(data []byte) *BinaryReader {
197239
return NewBinaryReader(f)
198240
}
199241

200-
func NewBinaryReaderFile(filename string) (*BinaryReader, error) {
201-
f, err := newBinaryReaderFile(filename)
242+
func NewBinaryReaderFile(f *os.File) (*BinaryReader, error) {
243+
info, err := f.Stat()
202244
if err != nil {
203245
return nil, err
204246
}
205-
return NewBinaryReader(f), nil
247+
return NewBinaryReader(newBinaryReaderSeeker(f, info.Size())), nil
248+
}
249+
250+
func NewBinaryReaderPath(filename string) (*BinaryReader, error) {
251+
f, err := os.Open(filename)
252+
if err != nil {
253+
return nil, err
254+
}
255+
r, err := NewBinaryReaderFile(f)
256+
if err != nil {
257+
f.Close()
258+
return nil, err
259+
}
260+
return r, nil
206261
}
207262

208263
func (r *BinaryReader) IBinaryReader() IBinaryReader {
@@ -285,7 +340,9 @@ func (r *BinaryReader) ReadAt(b []byte, off int64) (int, error) {
285340
func (r *BinaryReader) ReadBytes(n int64) []byte {
286341
data, err := r.f.Bytes(nil, n, r.pos)
287342
r.pos += int64(len(data))
288-
r.err = err
343+
if r.err == nil {
344+
r.err = err
345+
}
289346
return data
290347
}
291348

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ module github.com/tdewolff/parse/v2
22

33
go 1.11
44

5-
require github.com/tdewolff/test v1.0.11
5+
require github.com/tdewolff/test v1.0.12

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github.com/tdewolff/test v1.0.11 h1:FdLbwQVHxqG16SlkGveC0JVyrJN62COWTRyUFzfbtBE=
2-
github.com/tdewolff/test v1.0.11/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=
1+
github.com/tdewolff/test v1.0.12 h1:7F21DqIajswxuche0geHdrUZRCWE4oko4b7bcmkkrxk=
2+
github.com/tdewolff/test v1.0.12/go.mod h1:XPuWBzvdUzhCuxWO1ojpXsyzsA5bFoS3tO/Q3kFuTG8=

strconv/float_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func TestAppendFloat(t *testing.T) {
105105
}
106106
for _, tt := range floatTests {
107107
t.Run(fmt.Sprint(tt.f), func(t *testing.T) {
108-
f, _ := AppendFloat([]byte{}, tt.f, tt.prec)
108+
f := AppendFloat([]byte{}, tt.f, tt.prec)
109109
test.String(t, string(f), tt.expected)
110110
})
111111
}
@@ -188,7 +188,7 @@ func TestAppendFloatRandom(t *testing.T) {
188188
f := r.ExpFloat64()
189189
//f = math.Floor(f*float64(prec)) / float64(prec)
190190

191-
b, _ := AppendFloat([]byte{}, f, -1)
191+
b := AppendFloat([]byte{}, f, -1)
192192
f2, _ := strconv.ParseFloat(string(b), 64)
193193
if math.Abs(f-f2) > 1e-6 {
194194
fmt.Println("Bad:", f, "!=", f2, "in", string(b))
@@ -208,7 +208,7 @@ func BenchmarkFloatToBytes2(b *testing.B) {
208208
r := make([]byte, 10)
209209
f := 123.456
210210
for i := 0; i < b.N; i++ {
211-
r, _ = AppendFloat(r[:0], f, 6)
211+
r = AppendFloat(r[:0], f, 6)
212212
}
213213
}
214214

0 commit comments

Comments
 (0)