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 5package strings 6 7import ( 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. 16type 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. 24func (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. 35func (r *Reader) Size() int64 { return int64(len(r.s)) } 36 37func (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 47func (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 62func (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 72func (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 81func (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 96func (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. 106func (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. 127func (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. 146func (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. 150func NewReader(s string) *Reader { return &Reader{s, 0, -1} } 151