|
| 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 | +} |
0 commit comments