Russ Cox | 7c9e2c2 | 2008-09-12 16:42:53 -0700 | [diff] [blame^] | 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 | // $G $F.go && $L $F.$A && ./$A.out |
| 6 | |
| 7 | package main |
| 8 | |
| 9 | import ( |
| 10 | "os"; |
| 11 | "io"; |
| 12 | "bufio"; |
| 13 | "syscall"; |
| 14 | "rand" |
| 15 | ) |
| 16 | |
| 17 | func 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! |
| 26 | func 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. |
| 33 | type ByteReader struct { |
| 34 | p *[]byte |
| 35 | } |
| 36 | |
| 37 | func NewByteReader(p *[]byte) io.Read { |
| 38 | b := new(ByteReader); |
| 39 | b.p = p |
| 40 | return b |
| 41 | } |
| 42 | |
| 43 | func (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. |
| 55 | type HalfByteReader struct { |
| 56 | p *[]byte |
| 57 | } |
| 58 | |
| 59 | func NewHalfByteReader(p *[]byte) io.Read { |
| 60 | b := new(HalfByteReader); |
| 61 | b.p = p |
| 62 | return b |
| 63 | } |
| 64 | |
| 65 | func (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. |
| 79 | type Rot13Reader struct { |
| 80 | r io.Read |
| 81 | } |
| 82 | |
| 83 | func NewRot13Reader(r io.Read) *Rot13Reader { |
| 84 | r13 := new(Rot13Reader); |
| 85 | r13.r = r |
| 86 | return r13 |
| 87 | } |
| 88 | |
| 89 | func (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 | |
| 106 | func MakeByteReader(p *[]byte) io.Read { |
| 107 | return NewByteReader(p) |
| 108 | } |
| 109 | func MakeHalfByteReader(p *[]byte) io.Read { |
| 110 | return NewHalfByteReader(p) |
| 111 | } |
| 112 | |
| 113 | var 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. |
| 121 | func 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 |
| 137 | func 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 |
| 156 | func 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 | |
| 172 | func Read1(b *bufio.BufRead) string { return Reads(b, 1) } |
| 173 | func Read2(b *bufio.BufRead) string { return Reads(b, 2) } |
| 174 | func Read3(b *bufio.BufRead) string { return Reads(b, 3) } |
| 175 | func Read4(b *bufio.BufRead) string { return Reads(b, 4) } |
| 176 | func Read5(b *bufio.BufRead) string { return Reads(b, 5) } |
| 177 | func Read7(b *bufio.BufRead) string { return Reads(b, 7) } |
| 178 | |
| 179 | var bufreaders = []*(b *bufio.BufRead) string { |
| 180 | &Read1, &Read2, &Read3, &Read4, &Read5, &Read7, |
| 181 | &ReadBytes, &ReadLines |
| 182 | } |
| 183 | |
| 184 | var bufsizes = []int { |
| 185 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, |
| 186 | 23, 32, 46, 64, 93, 128, 1024, 4096 |
| 187 | } |
| 188 | |
| 189 | func 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 | |
| 267 | type WriteBuffer interface { |
| 268 | Write(p *[]byte) (int, *os.Error); |
| 269 | GetBytes() *[]byte |
| 270 | } |
| 271 | |
| 272 | // Accumulates bytes into a byte array. |
| 273 | type ByteWriter struct { |
| 274 | p *[]byte; |
| 275 | n int |
| 276 | } |
| 277 | |
| 278 | func NewByteWriter() WriteBuffer { |
| 279 | return new(ByteWriter) |
| 280 | } |
| 281 | |
| 282 | func (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 | |
| 295 | func (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. |
| 301 | type HalfByteWriter struct { |
| 302 | bw WriteBuffer |
| 303 | } |
| 304 | |
| 305 | func NewHalfByteWriter() WriteBuffer { |
| 306 | w := new(HalfByteWriter); |
| 307 | w.bw = NewByteWriter() |
| 308 | return w |
| 309 | } |
| 310 | |
| 311 | func (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 | |
| 318 | func (w *HalfByteWriter) GetBytes() *[]byte { |
| 319 | return w.bw.GetBytes() |
| 320 | } |
| 321 | |
| 322 | func 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 | |
| 374 | func main() { |
| 375 | TestBufRead(); |
| 376 | TestBufWrite() |
| 377 | } |