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 }