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 len(b) == 0 { 39 return 0, nil 40 } 41 if r.i >= int64(len(r.s)) { 42 return 0, io.EOF 43 } 44 r.prevRune = -1 45 n = copy(b, r.s[r.i:]) 46 r.i += int64(n) 47 return 48 } 49 50 func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { 51 // cannot modify state - see io.ReaderAt 52 if off < 0 { 53 return 0, errors.New("strings.Reader.ReadAt: negative offset") 54 } 55 if off >= int64(len(r.s)) { 56 return 0, io.EOF 57 } 58 n = copy(b, r.s[off:]) 59 if n < len(b) { 60 err = io.EOF 61 } 62 return 63 } 64 65 func (r *Reader) ReadByte() (b byte, err error) { 66 r.prevRune = -1 67 if r.i >= int64(len(r.s)) { 68 return 0, io.EOF 69 } 70 b = r.s[r.i] 71 r.i++ 72 return 73 } 74 75 func (r *Reader) UnreadByte() error { 76 r.prevRune = -1 77 if r.i <= 0 { 78 return errors.New("strings.Reader.UnreadByte: at beginning of string") 79 } 80 r.i-- 81 return nil 82 } 83 84 func (r *Reader) ReadRune() (ch rune, size int, err error) { 85 if r.i >= int64(len(r.s)) { 86 r.prevRune = -1 87 return 0, 0, io.EOF 88 } 89 r.prevRune = int(r.i) 90 if c := r.s[r.i]; c < utf8.RuneSelf { 91 r.i++ 92 return rune(c), 1, nil 93 } 94 ch, size = utf8.DecodeRuneInString(r.s[r.i:]) 95 r.i += int64(size) 96 return 97 } 98 99 func (r *Reader) UnreadRune() error { 100 if r.prevRune < 0 { 101 return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune") 102 } 103 r.i = int64(r.prevRune) 104 r.prevRune = -1 105 return nil 106 } 107 108 // Seek implements the io.Seeker interface. 109 func (r *Reader) Seek(offset int64, whence int) (int64, error) { 110 r.prevRune = -1 111 var abs int64 112 switch whence { 113 case 0: 114 abs = offset 115 case 1: 116 abs = int64(r.i) + offset 117 case 2: 118 abs = int64(len(r.s)) + offset 119 default: 120 return 0, errors.New("strings.Reader.Seek: invalid whence") 121 } 122 if abs < 0 { 123 return 0, errors.New("strings.Reader.Seek: negative position") 124 } 125 r.i = abs 126 return abs, nil 127 } 128 129 // WriteTo implements the io.WriterTo interface. 130 func (r *Reader) WriteTo(w io.Writer) (n int64, err error) { 131 r.prevRune = -1 132 if r.i >= int64(len(r.s)) { 133 return 0, nil 134 } 135 s := r.s[r.i:] 136 m, err := io.WriteString(w, s) 137 if m > len(s) { 138 panic("strings.Reader.WriteTo: invalid WriteString count") 139 } 140 r.i += int64(m) 141 n = int64(m) 142 if m != len(s) && err == nil { 143 err = io.ErrShortWrite 144 } 145 return 146 } 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} } 151