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