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