Newer
Older
pokemon-go-trade / vendor / github.com / go-pg / pg / internal / buf_reader.go
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package internal

import (
	"bufio"
	"bytes"
	"io"
)

const defaultBufSize = 65536

type BufReader struct {
	Columns [][]byte

	rd io.Reader // reader provided by the client

	buf      []byte
	r, w     int // buf read and write positions
	lastByte int
	err      error

	available int // bytes available for reading
	bytesRd   BytesReader
}

func NewBufReader(rd io.Reader) *BufReader {
	return &BufReader{
		rd:        rd,
		buf:       make([]byte, defaultBufSize),
		available: -1,
	}
}

func (b *BufReader) BytesReader(n int) *BytesReader {
	if b.Buffered() < n {
		return nil
	}
	buf := b.buf[b.r : b.r+n]
	b.r += n
	b.bytesRd.Reset(buf)
	return &b.bytesRd
}

func (b *BufReader) SetAvailable(n int) {
	b.available = n
}

func (b *BufReader) Available() int {
	return b.available
}

func (b *BufReader) changeAvailable(n int) {
	if b.available != -1 {
		b.available += n
	}
}

func (b *BufReader) Reset(rd io.Reader) {
	b.rd = rd
	b.r, b.w = 0, 0
	b.err = nil
}

// Buffered returns the number of bytes that can be read from the current buffer.
func (b *BufReader) Buffered() int {
	d := b.w - b.r
	if b.available != -1 && d > b.available {
		return b.available
	}
	return d
}

func (b *BufReader) Bytes() []byte {
	if b.available == -1 {
		return b.buf[b.r:b.w]
	}
	w := b.r + b.available
	if w > b.w {
		w = b.w
	}
	return b.buf[b.r:w]
}

func (b *BufReader) flush() []byte {
	if b.available == -1 {
		buf := b.buf[b.r:b.w]
		b.r = b.w
		return buf
	}

	w := b.r + b.available
	if w > b.w {
		w = b.w
	}
	buf := b.buf[b.r:w]
	b.r = w
	b.changeAvailable(-len(buf))
	return buf
}

// fill reads a new chunk into the buffer.
func (b *BufReader) fill() {
	// Slide existing data to beginning.
	if b.r > 0 {
		copy(b.buf, b.buf[b.r:b.w])
		b.w -= b.r
		b.r = 0
	}

	if b.w >= len(b.buf) {
		panic("bufio: tried to fill full buffer")
	}
	if b.available == 0 {
		b.err = io.EOF
		return
	}

	// Read new data: try a limited number of times.
	const maxConsecutiveEmptyReads = 100
	for i := maxConsecutiveEmptyReads; i > 0; i-- {
		n, err := b.rd.Read(b.buf[b.w:])
		b.w += n
		if err != nil {
			b.err = err
			return
		}
		if n > 0 {
			return
		}
	}
	b.err = io.ErrNoProgress
}

func (b *BufReader) readErr() error {
	err := b.err
	b.err = nil
	return err
}

func (b *BufReader) Read(p []byte) (n int, err error) {
	if len(p) == 0 {
		return 0, b.readErr()
	}

	if b.available != -1 {
		if b.available == 0 {
			return 0, io.EOF
		}
		if len(p) > b.available {
			p = p[:b.available]
		}
	}

	if b.r == b.w {
		if b.err != nil {
			return 0, b.readErr()
		}

		if len(p) >= len(b.buf) {
			// Large read, empty buffer.
			// Read directly into p to avoid copy.
			n, b.err = b.rd.Read(p)
			if n > 0 {
				b.changeAvailable(-n)
				b.lastByte = int(p[n-1])
			}
			return n, b.readErr()
		}

		// One read.
		// Do not use b.fill, which will loop.
		b.r = 0
		b.w = 0
		n, b.err = b.rd.Read(b.buf)
		if n == 0 {
			return 0, b.readErr()
		}
		b.w += n
	}

	// copy as much as we can
	n = copy(p, b.Bytes())
	b.r += n
	b.changeAvailable(-n)
	b.lastByte = int(b.buf[b.r-1])
	return n, nil
}

// ReadSlice reads until the first occurrence of delim in the input,
// returning a slice pointing at the bytes in the buffer.
// The bytes stop being valid at the next read.
// If ReadSlice encounters an error before finding a delimiter,
// it returns all the data in the buffer and the error itself (often io.EOF).
// ReadSlice fails with error ErrBufferFull if the buffer fills without a delim.
// Because the data returned from ReadSlice will be overwritten
// by the next I/O operation, most clients should use
// ReadBytes or ReadString instead.
// ReadSlice returns err != nil if and only if line does not end in delim.
func (b *BufReader) ReadSlice(delim byte) (line []byte, err error) {
	for {
		// Search buffer.
		if i := bytes.IndexByte(b.Bytes(), delim); i >= 0 {
			i++
			line = b.buf[b.r : b.r+i]
			b.r += i
			b.changeAvailable(-i)
			break
		}

		// Pending error?
		if b.err != nil {
			line = b.flush()
			err = b.readErr()
			break
		}

		buffered := b.Buffered()

		// Out of available.
		if b.available != -1 && buffered >= b.available {
			line = b.flush()
			err = io.EOF
			break
		}

		// Buffer full?
		if buffered >= len(b.buf) {
			line = b.flush()
			err = bufio.ErrBufferFull
			break
		}

		b.fill() // buffer is not full
	}

	// Handle last byte, if any.
	if i := len(line) - 1; i >= 0 {
		b.lastByte = int(line[i])
	}

	return
}

func (b *BufReader) ReadBytes(fn func(byte) bool) (line []byte, err error) {
	for {
		for i, c := range b.Bytes() {
			if !fn(c) {
				i--
				line = b.buf[b.r : b.r+i]
				b.r += i
				b.changeAvailable(-i)
				break
			}
		}

		// Pending error?
		if b.err != nil {
			line = b.flush()
			err = b.readErr()
			break
		}

		buffered := b.Buffered()

		// Out of available.
		if b.available != -1 && buffered >= b.available {
			line = b.flush()
			err = io.EOF
			break
		}

		// Buffer full?
		if buffered >= len(b.buf) {
			line = b.flush()
			err = bufio.ErrBufferFull
			break
		}

		b.fill() // buffer is not full
	}

	// Handle last byte, if any.
	if i := len(line) - 1; i >= 0 {
		b.lastByte = int(line[i])
	}

	return
}

func (b *BufReader) ReadByte() (byte, error) {
	if b.available == 0 {
		return 0, io.EOF
	}
	for b.r == b.w {
		if b.err != nil {
			return 0, b.readErr()
		}
		b.fill() // buffer is empty
	}
	c := b.buf[b.r]
	b.r++
	b.lastByte = int(c)
	b.changeAvailable(-1)
	return c, nil
}

func (b *BufReader) UnreadByte() error {
	if b.lastByte < 0 || b.r == 0 && b.w > 0 {
		return bufio.ErrInvalidUnreadByte
	}
	// b.r > 0 || b.w == 0
	if b.r > 0 {
		b.r--
	} else {
		// b.r == 0 && b.w == 0
		b.w = 1
	}
	b.buf[b.r] = byte(b.lastByte)
	b.lastByte = -1
	b.changeAvailable(+1)
	return nil
}

// Discard skips the next n bytes, returning the number of bytes discarded.
//
// If Discard skips fewer than n bytes, it also returns an error.
// If 0 <= n <= b.Buffered(), Discard is guaranteed to succeed without
// reading from the underlying io.BufReader.
func (b *BufReader) Discard(n int) (discarded int, err error) {
	if n < 0 {
		return 0, bufio.ErrNegativeCount
	}
	if n == 0 {
		return
	}
	remain := n
	for {
		skip := b.Buffered()
		if skip == 0 {
			b.fill()
			skip = b.Buffered()
		}
		if skip > remain {
			skip = remain
		}
		b.r += skip
		b.changeAvailable(-skip)
		remain -= skip
		if remain == 0 {
			return n, nil
		}
		if b.err != nil {
			return n - remain, b.readErr()
		}
	}
}

func (b *BufReader) ReadN(n int) (line []byte, err error) {
	if n < 0 {
		return nil, bufio.ErrNegativeCount
	}
	if n == 0 {
		return
	}

	nn := n
	if b.available != -1 && nn > b.available {
		nn = b.available
	}

	for {
		buffered := b.Buffered()

		if buffered >= nn {
			line = b.buf[b.r : b.r+nn]
			b.r += nn
			b.changeAvailable(-nn)
			if n > nn {
				err = io.EOF
			}
			break
		}

		// Pending error?
		if b.err != nil {
			line = b.flush()
			err = b.readErr()
			break
		}

		// Buffer full?
		if buffered >= len(b.buf) {
			line = b.flush()
			err = bufio.ErrBufferFull
			break
		}

		b.fill() // buffer is not full
	}

	// Handle last byte, if any.
	if i := len(line) - 1; i >= 0 {
		b.lastByte = int(line[i])
	}

	return
}

func (b *BufReader) ReadFull() ([]byte, error) {
	if b.available == -1 {
		panic("not reached")
	}
	buf := make([]byte, b.available)
	_, err := io.ReadFull(b, buf)
	return buf, err
}

func (b *BufReader) ReadFullTemp() ([]byte, error) {
	if b.available == -1 {
		panic("not reached")
	}
	if b.available <= len(b.buf) {
		return b.ReadN(b.available)
	}
	return b.ReadFull()
}