github.com/alexflint/go-memdump@v1.1.0/delim.go (about)

     1  package memdump
     2  
     3  import (
     4  	"errors"
     5  	"io"
     6  )
     7  
     8  // delim is used to recognize the end of the memory dump
     9  var delim = []byte{
    10  	130, 14, 133, 49, 108, 178, 125, 95,
    11  	35, 126, 41, 129, 229, 48, 16, 94,
    12  }
    13  
    14  // ErrBufferTooSmall is returned by delimetedReader if the input buffer
    15  // is smaller than the length of the delimeter
    16  var ErrBufferTooSmall = errors.New(
    17  	"cannot read into buffer of size less than 16 bytes (due to delim)")
    18  
    19  // ErrUnexpectedEOF is returned by delimetedReader if EOF is reached
    20  // before finding a delimeter
    21  var ErrUnexpectedEOF = errors.New(
    22  	"got EOF before finding the delimeter")
    23  
    24  // DelimitedReader reads delimited segments
    25  type DelimitedReader struct {
    26  	r     io.Reader
    27  	buf   []byte
    28  	begin int
    29  	end   int
    30  }
    31  
    32  // NewDelimitedReader creates a reader for delimited segments
    33  func NewDelimitedReader(r io.Reader) *DelimitedReader {
    34  	return &DelimitedReader{
    35  		r: r,
    36  	}
    37  }
    38  
    39  // Next returns the next segment, or (nil, io.EOF) if there are no more segments.
    40  // The data is only valid until the next call to Next().
    41  func (r *DelimitedReader) Next() ([]byte, error) {
    42  	var state, offset int
    43  	for {
    44  		// look for the next delimiter
    45  		for i, b := range r.buf[r.begin+offset : r.end] {
    46  			if b != delim[state] {
    47  				state = 0
    48  			}
    49  			// do not use "else" here because we updated state above
    50  			if b == delim[state] {
    51  				state++
    52  				if state == len(delim) {
    53  					out := r.buf[r.begin : r.begin+offset+i-len(delim)+1]
    54  					r.begin = r.begin + offset + i + 1
    55  					return out, nil
    56  				}
    57  			}
    58  		}
    59  		offset = r.end - r.begin
    60  
    61  		// allocate a larger buffer
    62  		if r.buf == nil {
    63  			r.buf = make([]byte, 16384)
    64  		} else {
    65  			var newbuf []byte
    66  			newbuf = make([]byte, 4*len(r.buf))
    67  			copy(newbuf, r.buf[r.begin:r.end])
    68  			r.end -= r.begin
    69  			r.begin = 0
    70  			r.buf = newbuf
    71  		}
    72  
    73  		// fill the rest of the buffer
    74  		n, err := r.r.Read(r.buf[r.end:])
    75  		r.end += n
    76  
    77  		// check for exit conditions
    78  		if n == 0 && err == io.EOF {
    79  			if offset == 0 {
    80  				return nil, io.EOF
    81  			}
    82  			return nil, ErrUnexpectedEOF
    83  		} else if err != nil {
    84  			return nil, err
    85  		}
    86  	}
    87  }