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