...
Run Format

Source file src/pkg/strings/reader.go

     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} }
   145	

View as plain text