blob: 7a872fbcb088732de99fbec36dcaf88a5e715136 [file] [log] [blame]
Russ Cox10c7d192009-10-12 10:09:35 -07001// 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
Kyle Consalusd7b48512010-04-20 22:18:26 -07007import (
Russ Coxeb692922011-11-01 22:05:34 -04008 "errors"
9 "io"
Rob Pike45e3bcb2011-11-08 15:41:54 -080010 "unicode/utf8"
Kyle Consalusd7b48512010-04-20 22:18:26 -070011)
Russ Cox10c7d192009-10-12 10:09:35 -070012
Evan Shaweae25d42012-10-12 14:43:50 +110013// A Reader implements the io.Reader, io.ReaderAt, io.Seeker, io.WriterTo,
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110014// io.ByteScanner, and io.RuneScanner interfaces by reading
15// from a string.
Robert Griesemer9cd33722011-05-26 11:02:07 -070016type Reader struct {
17 s string
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070018 i int64 // current reading index
19 prevRune int // index of previous rune; or < 0
Robert Griesemer9cd33722011-05-26 11:02:07 -070020}
Russ Cox10c7d192009-10-12 10:09:35 -070021
Brad Fitzpatrick21980502011-05-31 08:47:03 -070022// Len returns the number of bytes of the unread portion of the
23// string.
24func (r *Reader) Len() int {
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070025 if r.i >= int64(len(r.s)) {
Brad Fitzpatrick396170d2012-02-09 17:28:41 +110026 return 0
27 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070028 return int(int64(len(r.s)) - r.i)
Brad Fitzpatrick21980502011-05-31 08:47:03 -070029}
30
Brad Fitzpatrickc264c872015-01-22 14:15:47 -080031// 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
Russ Coxeb692922011-11-01 22:05:34 -040037func (r *Reader) Read(b []byte) (n int, err error) {
Brad Fitzpatrick396170d2012-02-09 17:28:41 +110038 if len(b) == 0 {
39 return 0, nil
40 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070041 if r.i >= int64(len(r.s)) {
Russ Coxeb692922011-11-01 22:05:34 -040042 return 0, io.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070043 }
Brad Fitzpatrick13ea1fd2014-04-25 06:44:51 -070044 r.prevRune = -1
Robert Griesemer9cd33722011-05-26 11:02:07 -070045 n = copy(b, r.s[r.i:])
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070046 r.i += int64(n)
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080047 return
Russ Cox10c7d192009-10-12 10:09:35 -070048}
49
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110050func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
Brad Fitzpatrick2dbc5d22014-04-10 15:46:07 -070051 // cannot modify state - see io.ReaderAt
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110052 if off < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070053 return 0, errors.New("strings.Reader.ReadAt: negative offset")
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110054 }
55 if off >= int64(len(r.s)) {
56 return 0, io.EOF
57 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070058 n = copy(b, r.s[off:])
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110059 if n < len(b) {
60 err = io.EOF
61 }
62 return
63}
64
Russ Coxeb692922011-11-01 22:05:34 -040065func (r *Reader) ReadByte() (b byte, err error) {
Rui Ueyamaa5090262014-03-19 09:00:58 -070066 r.prevRune = -1
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070067 if r.i >= int64(len(r.s)) {
Russ Coxeb692922011-11-01 22:05:34 -040068 return 0, io.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070069 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070070 b = r.s[r.i]
71 r.i++
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080072 return
Russ Cox10c7d192009-10-12 10:09:35 -070073}
74
Russ Coxeb692922011-11-01 22:05:34 -040075func (r *Reader) UnreadByte() error {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070076 r.prevRune = -1
Robert Griesemer9cd33722011-05-26 11:02:07 -070077 if r.i <= 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070078 return errors.New("strings.Reader.UnreadByte: at beginning of string")
Robert Griesemer9cd33722011-05-26 11:02:07 -070079 }
80 r.i--
Robert Griesemer9cd33722011-05-26 11:02:07 -070081 return nil
82}
83
Russ Coxeb692922011-11-01 22:05:34 -040084func (r *Reader) ReadRune() (ch rune, size int, err error) {
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070085 if r.i >= int64(len(r.s)) {
Rui Ueyamaa5090262014-03-19 09:00:58 -070086 r.prevRune = -1
Russ Coxeb692922011-11-01 22:05:34 -040087 return 0, 0, io.EOF
Kyle Consalusd7b48512010-04-20 22:18:26 -070088 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070089 r.prevRune = int(r.i)
Robert Griesemer9cd33722011-05-26 11:02:07 -070090 if c := r.s[r.i]; c < utf8.RuneSelf {
91 r.i++
Russ Cox8f571812011-10-25 22:22:09 -070092 return rune(c), 1, nil
Kyle Consalusd7b48512010-04-20 22:18:26 -070093 }
Russ Cox8f571812011-10-25 22:22:09 -070094 ch, size = utf8.DecodeRuneInString(r.s[r.i:])
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070095 r.i += int64(size)
Kyle Consalusd7b48512010-04-20 22:18:26 -070096 return
97}
98
Russ Coxeb692922011-11-01 22:05:34 -040099func (r *Reader) UnreadRune() error {
Robert Griesemer9cd33722011-05-26 11:02:07 -0700100 if r.prevRune < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -0700101 return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
Robert Griesemer9cd33722011-05-26 11:02:07 -0700102 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700103 r.i = int64(r.prevRune)
Robert Griesemer9cd33722011-05-26 11:02:07 -0700104 r.prevRune = -1
105 return nil
106}
107
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100108// Seek implements the io.Seeker interface.
109func (r *Reader) Seek(offset int64, whence int) (int64, error) {
Rui Ueyamaa5090262014-03-19 09:00:58 -0700110 r.prevRune = -1
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100111 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:
Robert Griesemer08d8eca2014-04-10 21:45:41 -0700120 return 0, errors.New("strings.Reader.Seek: invalid whence")
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100121 }
122 if abs < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -0700123 return 0, errors.New("strings.Reader.Seek: negative position")
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100124 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700125 r.i = abs
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100126 return abs, nil
127}
128
Evan Shaweae25d42012-10-12 14:43:50 +1100129// WriteTo implements the io.WriterTo interface.
130func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
131 r.prevRune = -1
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700132 if r.i >= int64(len(r.s)) {
Brad Fitzpatrickc8fa7dc2012-11-25 09:04:13 -0800133 return 0, nil
Evan Shaweae25d42012-10-12 14:43:50 +1100134 }
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 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700140 r.i += int64(m)
Evan Shaweae25d42012-10-12 14:43:50 +1100141 n = int64(m)
142 if m != len(s) && err == nil {
143 err = io.ErrShortWrite
144 }
145 return
146}
147
Russ Cox10c7d192009-10-12 10:09:35 -0700148// NewReader returns a new Reader reading from s.
149// It is similar to bytes.NewBufferString but more efficient and read-only.
Robert Griesemer9cd33722011-05-26 11:02:07 -0700150func NewReader(s string) *Reader { return &Reader{s, 0, -1} }