blob: 10b0278e1c4413a11217244449c1ad641179054f [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 (
8 "os"
9 "utf8"
10)
Russ Cox10c7d192009-10-12 10:09:35 -070011
Robert Griesemer9cd33722011-05-26 11:02:07 -070012// A Reader implements the io.Reader, io.ByteScanner, and
13// io.RuneScanner interfaces by reading from a string.
14type Reader struct {
15 s string
16 i int // current reading index
17 prevRune int // index of previous rune; or < 0
18}
Russ Cox10c7d192009-10-12 10:09:35 -070019
Brad Fitzpatrick21980502011-05-31 08:47:03 -070020// Len returns the number of bytes of the unread portion of the
21// string.
22func (r *Reader) Len() int {
23 return len(r.s) - r.i
24}
25
Russ Cox10c7d192009-10-12 10:09:35 -070026func (r *Reader) Read(b []byte) (n int, err os.Error) {
Robert Griesemer9cd33722011-05-26 11:02:07 -070027 if r.i >= len(r.s) {
Robert Griesemer40621d52009-11-09 12:07:39 -080028 return 0, os.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070029 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070030 n = copy(b, r.s[r.i:])
31 r.i += n
32 r.prevRune = -1
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080033 return
Russ Cox10c7d192009-10-12 10:09:35 -070034}
35
36func (r *Reader) ReadByte() (b byte, err os.Error) {
Robert Griesemer9cd33722011-05-26 11:02:07 -070037 if r.i >= len(r.s) {
Robert Griesemer40621d52009-11-09 12:07:39 -080038 return 0, os.EOF
Russ Cox10c7d192009-10-12 10:09:35 -070039 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070040 b = r.s[r.i]
41 r.i++
42 r.prevRune = -1
Robert Griesemerd65a5cc2009-12-15 15:40:16 -080043 return
Russ Cox10c7d192009-10-12 10:09:35 -070044}
45
Robert Griesemer9cd33722011-05-26 11:02:07 -070046
47// UnreadByte moves the reading position back by one byte.
48// It is an error to call UnreadByte if nothing has been
49// read yet.
50func (r *Reader) UnreadByte() os.Error {
51 if r.i <= 0 {
52 return os.ErrorString("strings.Reader: at beginning of string")
53 }
54 r.i--
55 r.prevRune = -1
56 return nil
57}
58
Kyle Consalusd7b48512010-04-20 22:18:26 -070059// ReadRune reads and returns the next UTF-8-encoded
60// Unicode code point from the buffer.
61// If no bytes are available, the error returned is os.EOF.
62// If the bytes are an erroneous UTF-8 encoding, it
63// consumes one byte and returns U+FFFD, 1.
64func (r *Reader) ReadRune() (rune int, size int, err os.Error) {
Robert Griesemer9cd33722011-05-26 11:02:07 -070065 if r.i >= len(r.s) {
Kyle Consalusd7b48512010-04-20 22:18:26 -070066 return 0, 0, os.EOF
67 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070068 r.prevRune = r.i
69 if c := r.s[r.i]; c < utf8.RuneSelf {
70 r.i++
Kyle Consalusd7b48512010-04-20 22:18:26 -070071 return int(c), 1, nil
72 }
Robert Griesemer9cd33722011-05-26 11:02:07 -070073 rune, size = utf8.DecodeRuneInString(r.s[r.i:])
74 r.i += size
Kyle Consalusd7b48512010-04-20 22:18:26 -070075 return
76}
77
Robert Griesemer9cd33722011-05-26 11:02:07 -070078// UnreadRune causes the next call to ReadRune to return the same rune
79// as the previous call to ReadRune.
80// The last method called on r must have been ReadRune.
81func (r *Reader) UnreadRune() os.Error {
82 if r.prevRune < 0 {
83 return os.ErrorString("strings.Reader: previous operation was not ReadRune")
84 }
85 r.i = r.prevRune
86 r.prevRune = -1
87 return nil
88}
89
Russ Cox10c7d192009-10-12 10:09:35 -070090// NewReader returns a new Reader reading from s.
91// It is similar to bytes.NewBufferString but more efficient and read-only.
Robert Griesemer9cd33722011-05-26 11:02:07 -070092func NewReader(s string) *Reader { return &Reader{s, 0, -1} }