github.com/goproxy0/go@v0.0.0-20171111080102-49cc0c489d2c/src/strings/reader.go (about) 1 // Copyright 2009 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 5 package strings 6 7 import ( 8 "errors" 9 "io" 10 "unicode/utf8" 11 ) 12 13 // A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo, 14 // io.ByteScanner, and io.RuneScanner interfaces by reading 15 // from a string. 16 type Reader struct { 17 s string 18 i int64 // current reading index 19 prevRune int // index of previous rune; or < 0 20 } 21 22 // Len returns the number of bytes of the unread portion of the 23 // string. 24 func (r *Reader) Len() int { 25 if r.i >= int64(len(r.s)) { 26 return 0 27 } 28 return int(int64(len(r.s)) - r.i) 29 } 30 31 // Size returns the original length of the underlying string. 32 // Size is the number of bytes available for reading via ReadAt. 33 // The returned value is always the same and is not affected by calls 34 // to any other method. 35 func (r *Reader) Size() int64 { return int64(len(r.s)) } 36 37 func (r *Reader) Read(b []byte) (n int, err error) { 38 if r.i >= int64(len(r.s)) { 39 return 0, io.EOF 40 } 41 r.prevRune = -1 42 n = copy(b, r.s[r.i:]) 43 r.i += int64(n) 44 return 45 } 46 47 func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { 48 // cannot modify state - see io.ReaderAt 49 if off < 0 { 50 return 0, errors.New("strings.Reader.ReadAt: negative offset") 51 } 52 if off >= int64(len(r.s)) { 53 return 0, io.EOF 54 } 55 n = copy(b, r.s[off:]) 56 if n < len(b) { 57 err = io.EOF 58 } 59 return 60 } 61 62 func (r *Reader) ReadByte() (byte, error) { 63 r.prevRune = -1 64 if r.i >= int64(len(r.s)) { 65 return 0, io.EOF 66 } 67 b := r.s[r.i] 68 r.i++ 69 return b, nil 70 } 71 72 func (r *Reader) UnreadByte() error { 73 r.prevRune = -1 74 if r.i <= 0 { 75 return errors.New("strings.Reader.UnreadByte: at beginning of string") 76 } 77 r.i-- 78 return nil 79 } 80 81 func (r *Reader) ReadRune() (ch rune, size int, err error) { 82 if r.i >= int64(len(r.s)) { 83 r.prevRune = -1 84 return 0, 0, io.EOF 85 } 86 r.prevRune = int(r.i) 87 if c := r.s[r.i]; c < utf8.RuneSelf { 88 r.i++ 89 return rune(c), 1, nil 90 } 91 ch, size = utf8.DecodeRuneInString(r.s[r.i:]) 92 r.i += int64(size) 93 return 94 } 95 96 func (r *Reader) UnreadRune() error { 97 if r.prevRune < 0 { 98 return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune") 99 } 100 r.i = int64(r.prevRune) 101 r.prevRune = -1 102 return nil 103 } 104 105 // Seek implements the io.Seeker interface. 106 func (r *Reader) Seek(offset int64, whence int) (int64, error) { 107 r.prevRune = -1 108 var abs int64 109 switch whence { 110 case io.SeekStart: 111 abs = offset 112 case io.SeekCurrent: 113 abs = r.i + offset 114 case io.SeekEnd: 115 abs = int64(len(r.s)) + offset 116 default: 117 return 0, errors.New("strings.Reader.Seek: invalid whence") 118 } 119 if abs < 0 { 120 return 0, errors.New("strings.Reader.Seek: negative position") 121 } 122 r.i = abs 123 return abs, nil 124 } 125 126 // WriteTo implements the io.WriterTo interface. 127 func (r *Reader) WriteTo(w io.Writer) (n int64, err error) { 128 r.prevRune = -1 129 if r.i >= int64(len(r.s)) { 130 return 0, nil 131 } 132 s := r.s[r.i:] 133 m, err := io.WriteString(w, s) 134 if m > len(s) { 135 panic("strings.Reader.WriteTo: invalid WriteString count") 136 } 137 r.i += int64(m) 138 n = int64(m) 139 if m != len(s) && err == nil { 140 err = io.ErrShortWrite 141 } 142 return 143 } 144 145 // Reset resets the Reader to be reading from s. 146 func (r *Reader) Reset(s string) { *r = Reader{s, 0, -1} } 147 148 // NewReader returns a new Reader reading from s. 149 // It is similar to bytes.NewBufferString but more efficient and read-only. 150 func NewReader(s string) *Reader { return &Reader{s, 0, -1} }