blob: b5d7453c1ba7879495e97c914109afd062646f87 [file] [log] [blame]
Russ Cox7c9e2c22008-09-12 16:42:53 -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
5// $G $F.go && $L $F.$A && ./$A.out
6
7package main
8
9import (
10 "os";
11 "io";
12 "bufio";
13 "syscall";
14 "rand"
15)
16
17func StringToBytes(s string) *[]byte {
18 b := new([]byte, len(s));
19 for i := 0; i < len(s); i++ {
20 b[i] = s[i]
21 }
22 return b
23}
24
25// Should be in language!
26func Copy(p *[]byte, q *[]byte) {
27 for i := 0; i < len(p); i++ {
28 p[i] = q[i]
29 }
30}
31
32// Reads from p.
33type ByteReader struct {
34 p *[]byte
35}
36
37func NewByteReader(p *[]byte) io.Read {
38 b := new(ByteReader);
39 b.p = p
40 return b
41}
42
43func (b *ByteReader) Read(p *[]byte) (int, *os.Error) {
44 n := len(p)
45 if n > len(b.p) {
46 n = len(b.p)
47 }
48 Copy(p[0:n], b.p[0:n]);
49 b.p = b.p[n:len(b.p)]
50 return n, nil
51}
52
53
54// Reads from p but only returns half of what you asked for.
55type HalfByteReader struct {
56 p *[]byte
57}
58
59func NewHalfByteReader(p *[]byte) io.Read {
60 b := new(HalfByteReader);
61 b.p = p
62 return b
63}
64
65func (b *HalfByteReader) Read(p *[]byte) (int, *os.Error) {
66 n := len(p)/2
67 if n == 0 && len(p) > 0 {
68 n = 1
69 }
70 if n > len(b.p) {
71 n = len(b.p)
72 }
73 Copy(p[0:n], b.p[0:n]);
74 b.p = b.p[n:len(b.p)]
75 return n, nil
76}
77
78// Reads from a reader and rot13s the result.
79type Rot13Reader struct {
80 r io.Read
81}
82
83func NewRot13Reader(r io.Read) *Rot13Reader {
84 r13 := new(Rot13Reader);
85 r13.r = r
86 return r13
87}
88
89func (r13 *Rot13Reader) Read(p *[]byte) (int, *os.Error) {
90 n, e := r13.r.Read(p)
91 if e != nil {
92 return n, e
93 }
94 for i := 0; i < n; i++ {
95 if 'a' <= p[i] && p[i] <= 'z' || 'A' <= p[i] && p[i] <= 'Z' {
96 if 'a' <= p[i] && p[i] <= 'm' || 'A' <= p[i] && p[i] <= 'M' {
97 p[i] += 13;
98 } else {
99 p[i] -= 13;
100 }
101 }
102 }
103 return n, nil
104}
105
106func MakeByteReader(p *[]byte) io.Read {
107 return NewByteReader(p)
108}
109func MakeHalfByteReader(p *[]byte) io.Read {
110 return NewHalfByteReader(p)
111}
112
113var readmakers = []*(p *[]byte) io.Read {
114 &NewByteReader,
115 &NewHalfByteReader
116}
117
118
119// Call ReadLineString (which ends up calling everything else)
120// to accumulate the text of a file.
121func ReadLines(b *bufio.BufRead) string {
122 s := ""
123 for {
124 s1, e := b.ReadLineString('\n', false)
125 if e == bufio.EndOfFile {
126 break
127 }
128 if e != nil {
129 panic("GetLines: "+e.String())
130 }
131 s += s1
132 }
133 return s
134}
135
136// Call ReadByte to accumulate the text of a file
137func ReadBytes(buf *bufio.BufRead) string {
138 var b [1000]byte;
139 nb := 0
140 for {
141 c, e := buf.ReadByte()
142 if e == bufio.EndOfFile {
143 break
144 }
145 if e != nil {
146 panic("GetBytes: "+e.String())
147 }
148 b[nb] = c;
149 nb++
150 }
151 // BUG return string(b[0:nb]) ?
152 return string(b)[0:nb]
153}
154
155// Call Read to accumulate the text of a file
156func Reads(buf *bufio.BufRead, m int) string {
157 var b [1000]byte;
158 nb := 0
159 for {
160 // BUG parens around (&b) should not be needed
161 n, e := buf.Read((&b)[nb:nb+m]);
162 nb += n
163 if e == bufio.EndOfFile {
164 break
165 }
166 }
167 // BUG 6g bug102 - out of bounds error on empty byte array -> string
168 if nb == 0 { return "" }
169 return string((&b)[0:nb])
170}
171
172func Read1(b *bufio.BufRead) string { return Reads(b, 1) }
173func Read2(b *bufio.BufRead) string { return Reads(b, 2) }
174func Read3(b *bufio.BufRead) string { return Reads(b, 3) }
175func Read4(b *bufio.BufRead) string { return Reads(b, 4) }
176func Read5(b *bufio.BufRead) string { return Reads(b, 5) }
177func Read7(b *bufio.BufRead) string { return Reads(b, 7) }
178
179var bufreaders = []*(b *bufio.BufRead) string {
180 &Read1, &Read2, &Read3, &Read4, &Read5, &Read7,
181 &ReadBytes, &ReadLines
182}
183
184var bufsizes = []int {
185 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
186 23, 32, 46, 64, 93, 128, 1024, 4096
187}
188
189func TestBufRead() {
190 // work around 6g bug101
191 readmakers[0] = &NewByteReader;
192 readmakers[1] = &NewHalfByteReader;
193
194 bufreaders[0] = &Read1;
195 bufreaders[1] = &Read2;
196 bufreaders[2] = &Read3;
197 bufreaders[3] = &Read4;
198 bufreaders[4] = &Read5;
199 bufreaders[5] = &Read7;
200 bufreaders[6] = &ReadBytes;
201 bufreaders[7] = &ReadLines;
202
203 bufsizes[0] = 1;
204 bufsizes[1] = 2;
205 bufsizes[2] = 3;
206 bufsizes[3] = 4;
207 bufsizes[4] = 5;
208 bufsizes[5] = 6;
209 bufsizes[6] = 7;
210 bufsizes[7] = 8;
211 bufsizes[8] = 9;
212 bufsizes[9] = 10;
213 bufsizes[10] = 23;
214 bufsizes[11] = 32;
215 bufsizes[12] = 46;
216 bufsizes[13] = 64;
217 bufsizes[14] = 93;
218 bufsizes[15] = 128;
219 bufsizes[16] = 1024;
220 bufsizes[17] = 4096;
221
222 var texts [31]string
223 str := "";
224 all := ""
225 for i := 0; i < len(texts)-1; i++ {
226 texts[i] = str + "\n";
227 all += texts[i];
228 str += string(i%26+'a')
229 }
230 texts[len(texts)-1] = all;
231
232 // BUG 6g should not need nbr temporary (bug099)
233 nbr := NewByteReader(StringToBytes("hello world"));
234 b, e := bufio.NewBufRead(nbr);
235 if ReadBytes(b) != "hello world" { panic("hello world") }
236
237 // BUG 6g should not need nbr nor nbr1 (bug009)
238 nbr = NewByteReader(StringToBytes("hello world"));
239 nbr1 := NewRot13Reader(nbr);
240 b, e = bufio.NewBufRead(nbr1);
241 if ReadBytes(b) != "uryyb jbeyq" { panic("hello world") }
242
243 for h := 0; h < len(texts); h++ {
244 text := texts[h];
245 textbytes := StringToBytes(text)
246 for i := 0; i < len(readmakers); i++ {
247 readmaker := readmakers[i]
248 for j := 0; j < len(bufreaders); j++ {
249 bufreader := bufreaders[j]
250 for k := 0; k < len(bufsizes); k++ {
251 bufsize := bufsizes[k];
252 read := readmaker(textbytes);
253 buf, e := bufio.NewBufReadSize(read, bufsize);
254 s := bufreader(buf);
255 if s != text {
256 print("Failed: ", h, " ", i, " ", j, " ", k, " ", len(s), " ", len(text), "\n");
257 print("<", s, ">\nshould be <", text, ">\n");
258 panic("bufio result")
259 }
260 }
261 }
262 }
263 }
264}
265
266
267type WriteBuffer interface {
268 Write(p *[]byte) (int, *os.Error);
269 GetBytes() *[]byte
270}
271
272// Accumulates bytes into a byte array.
273type ByteWriter struct {
274 p *[]byte;
275 n int
276}
277
278func NewByteWriter() WriteBuffer {
279 return new(ByteWriter)
280}
281
282func (w *ByteWriter) Write(p *[]byte) (int, *os.Error) {
283 if w.p == nil {
284 w.p = new([]byte, len(p)+100)
285 } else if w.n + len(p) >= len(w.p) {
286 newp := new([]byte, len(w.p)*2 + len(p));
287 Copy(newp[0:w.n], w.p[0:w.n]);
288 w.p = newp
289 }
290 Copy(w.p[w.n:w.n+len(p)], p);
291 w.n += len(p)
292 return len(p), nil
293}
294
295func (w *ByteWriter) GetBytes() *[]byte {
296 return w.p[0:w.n]
297}
298
299// Accumulates bytes written into a byte array
300// but Write only takes half of what you give it.
301type HalfByteWriter struct {
302 bw WriteBuffer
303}
304
305func NewHalfByteWriter() WriteBuffer {
306 w := new(HalfByteWriter);
307 w.bw = NewByteWriter()
308 return w
309}
310
311func (w *HalfByteWriter) Write(p *[]byte) (int, *os.Error) {
312 n := (len(p)+1) / 2;
313 // BUG return w.bw.Write(p[0:n])
314 r, e := w.bw.Write(p[0:n])
315 return r, e
316}
317
318func (w *HalfByteWriter) GetBytes() *[]byte {
319 return w.bw.GetBytes()
320}
321
322func TestBufWrite() {
323 var data [8192]byte
324
325 var writers [2]*()WriteBuffer;
326 writers[0] = &NewByteWriter;
327 writers[1] = &NewHalfByteWriter;
328
329 for i := 0; i < len(data); i++ {
330 data[i] = byte(rand.rand())
331 }
332 for i := 0; i < len(bufsizes); i++ {
333 for j := 0; j < len(bufsizes); j++ {
334 for k := 0; k < len(writers); k++ {
335 nwrite := bufsizes[i];
336 bs := bufsizes[j];
337
338 // Write nwrite bytes using buffer size bs.
339 // Check that the right amount makes it out
340 // and that the data is correct.
341
342 write := writers[k]();
343 buf, e := bufio.NewBufWriteSize(write, bs);
344 if e != nil {
345 panic("NewBufWriteSize error: "+e.String())
346 }
347 n, e1 := buf.Write((&data)[0:nwrite])
348 if e1 != nil {
349 panic("buf.Write error "+e1.String())
350 }
351 if n != nwrite {
352 panic("buf.Write wrong count")
353 }
354 e = buf.Flush()
355 if e != nil {
356 panic("buf.Flush error "+e.String())
357 }
358
359 written := write.GetBytes();
360 if len(written) != nwrite {
361 panic("wrong amount written")
362 }
363 for l := 0; l < len(written); l++ {
364 if written[i] != data[i] {
365 panic("wrong bytes written")
366 }
367 }
368 }
369 }
370 }
371}
372
373
374func main() {
375 TestBufRead();
376 TestBufWrite()
377}