github.com/varialus/godfly@v0.0.0-20130904042352-1934f9f095ab/src/pkg/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 int // 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 >= len(r.s) { 26 return 0 27 } 28 return 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 >= len(r.s) { 36 return 0, io.EOF 37 } 38 n = copy(b, r.s[r.i:]) 39 r.i += n 40 r.prevRune = -1 41 return 42 } 43 44 func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) { 45 if off < 0 { 46 return 0, errors.New("strings: invalid offset") 47 } 48 if off >= int64(len(r.s)) { 49 return 0, io.EOF 50 } 51 n = copy(b, r.s[int(off):]) 52 if n < len(b) { 53 err = io.EOF 54 } 55 return 56 } 57 58 func (r *Reader) ReadByte() (b byte, err error) { 59 if r.i >= len(r.s) { 60 return 0, io.EOF 61 } 62 b = r.s[r.i] 63 r.i++ 64 r.prevRune = -1 65 return 66 } 67 68 func (r *Reader) UnreadByte() error { 69 if r.i <= 0 { 70 return errors.New("strings.Reader: at beginning of string") 71 } 72 r.i-- 73 r.prevRune = -1 74 return nil 75 } 76 77 func (r *Reader) ReadRune() (ch rune, size int, err error) { 78 if r.i >= len(r.s) { 79 return 0, 0, io.EOF 80 } 81 r.prevRune = r.i 82 if c := r.s[r.i]; c < utf8.RuneSelf { 83 r.i++ 84 return rune(c), 1, nil 85 } 86 ch, size = utf8.DecodeRuneInString(r.s[r.i:]) 87 r.i += size 88 return 89 } 90 91 func (r *Reader) UnreadRune() error { 92 if r.prevRune < 0 { 93 return errors.New("strings.Reader: previous operation was not ReadRune") 94 } 95 r.i = r.prevRune 96 r.prevRune = -1 97 return nil 98 } 99 100 // Seek implements the io.Seeker interface. 101 func (r *Reader) Seek(offset int64, whence int) (int64, error) { 102 var abs int64 103 switch whence { 104 case 0: 105 abs = offset 106 case 1: 107 abs = int64(r.i) + offset 108 case 2: 109 abs = int64(len(r.s)) + offset 110 default: 111 return 0, errors.New("strings: invalid whence") 112 } 113 if abs < 0 { 114 return 0, errors.New("strings: negative position") 115 } 116 if abs >= 1<<31 { 117 return 0, errors.New("strings: position out of range") 118 } 119 r.i = int(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 >= 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 += 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} }