OSDN Git Service

Remove the types float and complex.
[pf3gnuchains/gcc-fork.git] / libgo / go / encoding / line / line.go
1 // Copyright 2010 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 // This package implements a Reader which handles reading \r and \r\n
6 // deliminated lines.
7 package line
8
9 import (
10         "io"
11         "os"
12 )
13
14 // Reader reads lines from an io.Reader (which may use either '\n' or
15 // '\r\n').
16 type Reader struct {
17         buf      []byte
18         consumed int
19         in       io.Reader
20         err      os.Error
21 }
22
23 func NewReader(in io.Reader, maxLineLength int) *Reader {
24         return &Reader{
25                 buf:      make([]byte, 0, maxLineLength),
26                 consumed: 0,
27                 in:       in,
28         }
29 }
30
31 // ReadLine tries to return a single line, not including the end-of-line bytes.
32 // If the line was found to be longer than the maximum length then isPrefix is
33 // set and the beginning of the line is returned. The rest of the line will be
34 // returned from future calls. isPrefix will be false when returning the last
35 // fragment of the line.  The returned buffer points into the internal state of
36 // the Reader and is only valid until the next call to ReadLine. ReadLine
37 // either returns a non-nil line or it returns an error, never both.
38 func (l *Reader) ReadLine() (line []byte, isPrefix bool, err os.Error) {
39         if l.consumed > 0 {
40                 n := copy(l.buf, l.buf[l.consumed:])
41                 l.buf = l.buf[:n]
42                 l.consumed = 0
43         }
44
45         if len(l.buf) == 0 && l.err != nil {
46                 err = l.err
47                 return
48         }
49
50         scannedTo := 0
51
52         for {
53                 i := scannedTo
54                 for ; i < len(l.buf); i++ {
55                         if l.buf[i] == '\r' && len(l.buf) > i+1 && l.buf[i+1] == '\n' {
56                                 line = l.buf[:i]
57                                 l.consumed = i + 2
58                                 return
59                         } else if l.buf[i] == '\n' {
60                                 line = l.buf[:i]
61                                 l.consumed = i + 1
62                                 return
63                         }
64                 }
65
66                 if i == cap(l.buf) {
67                         line = l.buf[:i]
68                         l.consumed = i
69                         isPrefix = true
70                         return
71                 }
72
73                 if l.err != nil {
74                         line = l.buf
75                         l.consumed = i
76                         return
77                 }
78
79                 // We don't want to rescan the input that we just scanned.
80                 // However, we need to back up one byte because the last byte
81                 // could have been a '\r' and we do need to rescan that.
82                 scannedTo = i
83                 if scannedTo > 0 {
84                         scannedTo--
85                 }
86                 oldLen := len(l.buf)
87                 l.buf = l.buf[:cap(l.buf)]
88                 n, readErr := l.in.Read(l.buf[oldLen:])
89                 l.buf = l.buf[:oldLen+n]
90                 if readErr != nil {
91                         l.err = readErr
92                 }
93         }
94         panic("unreachable")
95 }