精简后的项目:仅保留 api/ui 源码、文档、构建依赖
This commit is contained in:
@@ -0,0 +1,116 @@
|
||||
package exiftool
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// MarkReader reads from upstream and stops at marker boundaries.
|
||||
type MarkReader struct {
|
||||
upstream io.Reader
|
||||
buf []byte
|
||||
mark []byte
|
||||
|
||||
// valid data: buf[start:pending]
|
||||
// pending, need to check if contains mark: buf[pending:end]
|
||||
start int
|
||||
pending int
|
||||
end int
|
||||
|
||||
// if true, mark begins from buf[pending]
|
||||
hasMark bool
|
||||
// if true, upstream is EOF
|
||||
upstreamEOF bool
|
||||
// if true, this reader returns EOF
|
||||
paused bool
|
||||
}
|
||||
|
||||
// NewMarkReader creates a reader that stops at each marker and requires Reset to continue.
|
||||
func NewMarkReader(upstream io.Reader, bufferSize int, mark string) (*MarkReader, error) {
|
||||
if bufferSize < 2*len(mark) {
|
||||
return nil, errors.New("buffer too small")
|
||||
}
|
||||
|
||||
return &MarkReader{
|
||||
upstream: upstream,
|
||||
buf: make([]byte, bufferSize),
|
||||
mark: []byte(mark),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Reset resumes reading after a previously encountered marker boundary.
|
||||
func (r *MarkReader) Reset() {
|
||||
r.paused = false
|
||||
}
|
||||
|
||||
// Read returns bytes up to (but excluding) the next marker, then reports EOF until Reset.
|
||||
func (r *MarkReader) Read(p []byte) (int, error) {
|
||||
if len(p) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if r.paused {
|
||||
return 0, io.EOF
|
||||
}
|
||||
|
||||
if r.start == r.pending {
|
||||
// compact buffer
|
||||
copy(r.buf[0:], r.buf[r.start:r.end])
|
||||
r.end -= r.start
|
||||
r.pending -= r.start
|
||||
r.start = 0
|
||||
|
||||
// fill buffer
|
||||
n, err := io.ReadAtLeast(r.upstream, r.buf[r.end:], len(r.mark))
|
||||
r.end += n
|
||||
if err == io.EOF || err == io.ErrUnexpectedEOF {
|
||||
r.upstreamEOF = true
|
||||
err = nil
|
||||
}
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
r.checkMarkInPending()
|
||||
}
|
||||
|
||||
// read from valid data
|
||||
n := copy(p, r.buf[r.start:r.pending])
|
||||
r.start += n
|
||||
|
||||
if r.start == r.pending {
|
||||
switch {
|
||||
case r.hasMark:
|
||||
r.pending += len(r.mark)
|
||||
r.start += len(r.mark)
|
||||
r.hasMark = false
|
||||
r.paused = true
|
||||
|
||||
r.checkMarkInPending()
|
||||
case r.upstreamEOF:
|
||||
r.paused = r.start == r.end
|
||||
}
|
||||
}
|
||||
|
||||
if r.paused {
|
||||
return n, io.EOF
|
||||
}
|
||||
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func (r *MarkReader) checkMarkInPending() {
|
||||
if markAt := bytes.Index(r.buf[r.pending:r.end], r.mark); markAt >= 0 {
|
||||
r.hasMark = true
|
||||
r.pending = r.pending + markAt
|
||||
return
|
||||
}
|
||||
|
||||
if r.upstreamEOF {
|
||||
r.pending = r.end
|
||||
return
|
||||
}
|
||||
|
||||
r.pending = max(r.pending, r.end-len(r.mark)+1)
|
||||
}
|
||||
Reference in New Issue
Block a user