blob: ee83ceb505f86062866e3467dd9340cac3cdadea [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
Russ Coxeb692922011-11-01 22:05:34 -040031func (r *Reader) Read(b []byte) (n int, err error) {
Rui Ueyamaa5090262014-03-19 09:00:58 -070032 r.prevRune = -1
Brad Fitzpatrick396170d2012-02-09 17:28:41 +110033 if len(b) == 0 {
34 return 0, nil
35 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070036 if r.i >= int64(len(r.s)) {
Russ Coxeb692922011-11-01 22:05:34 -040037 return 0, io.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070038 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070039 n = copy(b, r.s[r.i:])
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070040 r.i += int64(n)
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080041 return
Russ Cox10c7d192009-10-12 10:09:35 -070042}
43
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110044func (r *Reader) ReadAt(b []byte, off int64) (n int, err error) {
Brad Fitzpatrick2dbc5d22014-04-10 15:46:07 -070045 // cannot modify state - see io.ReaderAt
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110046 if off < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070047 return 0, errors.New("strings.Reader.ReadAt: negative offset")
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110048 }
49 if off >= int64(len(r.s)) {
50 return 0, io.EOF
51 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070052 n = copy(b, r.s[off:])
Brad Fitzpatrick7127b6f2012-02-15 12:58:00 +110053 if n < len(b) {
54 err = io.EOF
55 }
56 return
57}
58
Russ Coxeb692922011-11-01 22:05:34 -040059func (r *Reader) ReadByte() (b byte, err error) {
Rui Ueyamaa5090262014-03-19 09:00:58 -070060 r.prevRune = -1
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070061 if r.i >= int64(len(r.s)) {
Russ Coxeb692922011-11-01 22:05:34 -040062 return 0, io.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070063 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070064 b = r.s[r.i]
65 r.i++
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080066 return
Russ Cox10c7d192009-10-12 10:09:35 -070067}
68
Russ Coxeb692922011-11-01 22:05:34 -040069func (r *Reader) UnreadByte() error {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070070 r.prevRune = -1
Robert Griesemer9cd33722011-05-26 11:02:07 -070071 if r.i <= 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070072 return errors.New("strings.Reader.UnreadByte: at beginning of string")
Robert Griesemer9cd33722011-05-26 11:02:07 -070073 }
74 r.i--
Robert Griesemer9cd33722011-05-26 11:02:07 -070075 return nil
76}
77
Russ Coxeb692922011-11-01 22:05:34 -040078func (r *Reader) ReadRune() (ch rune, size int, err error) {
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070079 if r.i >= int64(len(r.s)) {
Rui Ueyamaa5090262014-03-19 09:00:58 -070080 r.prevRune = -1
Russ Coxeb692922011-11-01 22:05:34 -040081 return 0, 0, io.EOF
Kyle Consalusd7b48512010-04-20 22:18:26 -070082 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070083 r.prevRune = int(r.i)
Robert Griesemer9cd33722011-05-26 11:02:07 -070084 if c := r.s[r.i]; c < utf8.RuneSelf {
85 r.i++
Russ Cox8f571812011-10-25 22:22:09 -070086 return rune(c), 1, nil
Kyle Consalusd7b48512010-04-20 22:18:26 -070087 }
Russ Cox8f571812011-10-25 22:22:09 -070088 ch, size = utf8.DecodeRuneInString(r.s[r.i:])
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070089 r.i += int64(size)
Kyle Consalusd7b48512010-04-20 22:18:26 -070090 return
91}
92
Russ Coxeb692922011-11-01 22:05:34 -040093func (r *Reader) UnreadRune() error {
Robert Griesemer9cd33722011-05-26 11:02:07 -070094 if r.prevRune < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -070095 return errors.New("strings.Reader.UnreadRune: previous operation was not ReadRune")
Robert Griesemer9cd33722011-05-26 11:02:07 -070096 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -070097 r.i = int64(r.prevRune)
Robert Griesemer9cd33722011-05-26 11:02:07 -070098 r.prevRune = -1
99 return nil
100}
101
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100102// Seek implements the io.Seeker interface.
103func (r *Reader) Seek(offset int64, whence int) (int64, error) {
Rui Ueyamaa5090262014-03-19 09:00:58 -0700104 r.prevRune = -1
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100105 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:
Robert Griesemer08d8eca2014-04-10 21:45:41 -0700114 return 0, errors.New("strings.Reader.Seek: invalid whence")
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100115 }
116 if abs < 0 {
Robert Griesemer08d8eca2014-04-10 21:45:41 -0700117 return 0, errors.New("strings.Reader.Seek: negative position")
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100118 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700119 r.i = abs
Brad Fitzpatrick396170d2012-02-09 17:28:41 +1100120 return abs, nil
121}
122
Evan Shaweae25d42012-10-12 14:43:50 +1100123// WriteTo implements the io.WriterTo interface.
124func (r *Reader) WriteTo(w io.Writer) (n int64, err error) {
125 r.prevRune = -1
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700126 if r.i >= int64(len(r.s)) {
Brad Fitzpatrickc8fa7dc2012-11-25 09:04:13 -0800127 return 0, nil
Evan Shaweae25d42012-10-12 14:43:50 +1100128 }
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 }
Brad Fitzpatrickf0745652014-03-28 12:23:51 -0700134 r.i += int64(m)
Evan Shaweae25d42012-10-12 14:43:50 +1100135 n = int64(m)
136 if m != len(s) && err == nil {
137 err = io.ErrShortWrite
138 }
139 return
140}
141
Russ Cox10c7d192009-10-12 10:09:35 -0700142// NewReader returns a new Reader reading from s.
143// It is similar to bytes.NewBufferString but more efficient and read-only.
Robert Griesemer9cd33722011-05-26 11:02:07 -0700144func NewReader(s string) *Reader { return &Reader{s, 0, -1} }