buffer.go

 1// Copyright 2011 The Go Authors. All rights reserved.
 2// Use of this source code is governed by a BSD-style
 3// license that can be found in the LICENSE file.
 4
 5package tiff
 6
 7import "io"
 8
 9// buffer buffers an io.Reader to satisfy io.ReaderAt.
10type buffer struct {
11	r   io.Reader
12	buf []byte
13}
14
15// fill reads data from b.r until the buffer contains at least end bytes.
16func (b *buffer) fill(end int) error {
17	m := len(b.buf)
18	if end > m {
19		if end > cap(b.buf) {
20			newcap := 1024
21			for newcap < end {
22				newcap *= 2
23			}
24			newbuf := make([]byte, end, newcap)
25			copy(newbuf, b.buf)
26			b.buf = newbuf
27		} else {
28			b.buf = b.buf[:end]
29		}
30		if n, err := io.ReadFull(b.r, b.buf[m:end]); err != nil {
31			end = m + n
32			b.buf = b.buf[:end]
33			return err
34		}
35	}
36	return nil
37}
38
39func (b *buffer) ReadAt(p []byte, off int64) (int, error) {
40	o := int(off)
41	end := o + len(p)
42	if int64(end) != off+int64(len(p)) {
43		return 0, io.ErrUnexpectedEOF
44	}
45
46	err := b.fill(end)
47	return copy(p, b.buf[o:end]), err
48}
49
50// Slice returns a slice of the underlying buffer. The slice contains
51// n bytes starting at offset off.
52func (b *buffer) Slice(off, n int) ([]byte, error) {
53	end := off + n
54	if err := b.fill(end); err != nil {
55		return nil, err
56	}
57	return b.buf[off:end], nil
58}
59
60// newReaderAt converts an io.Reader into an io.ReaderAt.
61func newReaderAt(r io.Reader) io.ReaderAt {
62	if ra, ok := r.(io.ReaderAt); ok {
63		return ra
64	}
65	return &buffer{
66		r:   r,
67		buf: make([]byte, 0, 1024),
68	}
69}