// Looks ahead to see if the next character completes the entry. Does not read // any characters from the reader. func entryCompleted(r *strings.Reader) bool { if r.Len() > 0 { b, _ := r.ReadByte() r.UnreadByte() return b == lineSeparator || b == entrySeparator } return true }
func sum(stream *strings.Reader) (s int) { v, err := stream.ReadByte() for ; v != 0 && err != os.EOF; v, err = stream.ReadByte() { s += int(v) } return }
// Attempts to consume the wanted character from the reader. Returns true if // character was read successfully, false otherwise. If the character could // not be read, then no characters are consumed from the reader. func consume(r *strings.Reader, wanted byte) bool { if r.Len() > 0 { b, _ := r.ReadByte() if b == wanted { return true } r.UnreadByte() } return false }
// field is of form: key="value" func lexField(r *strings.Reader) (string, string, error) { key := make([]byte, 0, 5) val := make([]byte, 0, 32) // read the key for { ch, _ := r.ReadByte() if ch == '=' { break } if ch < 'a' || ch > 'z' { // fail if not ASCII lowercase letter return "", "", AuthFormatError{"header", "cannot parse header field"} } key = append(key, ch) } if ch, _ := r.ReadByte(); ch != '"' { return "", "", AuthFormatError{string(key), "cannot parse value"} } // read the value for { ch, _ := r.ReadByte() if ch == '"' { break } // character class is ASCII printable [\x20-\x7E] without \ and " if ch < 0x20 || ch > 0x7E || ch == '\\' { return "", "", AuthFormatError{string(key), "cannot parse value"} } val = append(val, ch) } return string(key), string(val), nil }
// Tear apart the Authorization header value. // PAY ATTENTION: this is large and complicated relative to other ones I've seen // based on Split() using ',', ' ', and '=' in various orders. It is also probably // correct even if the realm contains a '=', ' ', or '"' character, or if the // sender uses HT, CR, or LF in their whitespace. // // The map that comes back looks like { "qop": "auth", "ns":"00000001", etc... } func parseAuthorization(auth *strings.Reader) (map[string]string, error) { parts := map[string]string{} skipLWS := func(r *strings.Reader) error { for { ch, err := r.ReadByte() if err == io.EOF { return nil } if err != nil { return err } if ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' { // its white, we skip it and stay in loop } else { if err := r.UnreadByte(); err != nil { return err } break } } return nil } readName := func(r *strings.Reader) (string, error) { name := []byte{} for { ch, err := r.ReadByte() if err == io.EOF { break } if err != nil { return "", err } if (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '-' { name = append(name, ch) } else { if err := r.UnreadByte(); err != nil { return "", err } break } } if len(name) == 0 { return "", fmt.Errorf("expected name, got didn't get one") } return string(name), nil } readValue := func(r *strings.Reader) (string, error) { ch, err := r.ReadByte() if err != nil { return "", err } if ch == '"' { v := []byte{} for { ch, err := r.ReadByte() if err != nil { return "", fmt.Errorf("premature end of value: %s", err.Error()) } if ch == '\\' { ch2, err := r.ReadByte() if err != nil { return "", fmt.Errorf("premature end of value: %s", err.Error()) } v = append(v, ch2) } else if ch == '"' { break } else { v = append(v, ch) } } return string(v), nil } else { r.UnreadByte() return readName(r) // handles unquoted values, like true/false in the "stale" paramter } } for { name, err := readName(auth) if err == io.EOF { break } if err != nil { return nil, err } if err := skipLWS(auth); err != nil { return nil, err } eq, err := auth.ReadByte() if err == io.EOF || eq != '=' { return nil, fmt.Errorf("Malformed %s parameter, no equals", name) } if err := skipLWS(auth); err != nil { return nil, err } val, err := readValue(auth) if err != nil { return nil, err } parts[name] = val comma, err := auth.ReadByte() if err == io.EOF { break // our exit } if err != nil { return nil, err } if comma != ',' { return nil, fmt.Errorf("expected comma, got %v", comma) } if err := skipLWS(auth); err != nil { if err == io.EOF { break // our exit, finding an EOF after a value and some whitespace } return nil, err } } if testing.Verbose() { log.Printf("auth header = %#v", parts) } return parts, nil }
// initw read a file .LIF and configure the world with it func initw(f *os.File) bool { var r *strings.Reader var b byte var x, y, oldy int input := bufio.NewScanner(f) input.Scan() if input.Text() != "#Life 1.05" { fmt.Fprintf(os.Stderr, "ERROR: The file for initialization the world is not a valid .LIF format\n") return false } header: // Read header of .LIF for input.Scan() { r = strings.NewReader(input.Text()) b, _ = r.ReadByte() if b != '#' { fmt.Println(input.Text()) } else { b, _ = r.ReadByte() switch b { case 'D': { fmt.Println("Description") } case 'N': { fmt.Println("Rules Conway R 23/3") } case 'R': { fmt.Fprintf(os.Stderr, "ERROR: 'R' option not implemented\n") return false } case 'P': { s := strings.Split(input.Text(), " ") x, _ = strconv.Atoi(s[1]) y, _ = strconv.Atoi(s[2]) x += (M / 2) y += (N / 2) oldy = y break header // Exit loop, now only blocks of position and cells } default: { fmt.Fprintf(os.Stderr, "ERROR: Option in header not implemented\n") return false } } } } var p Point m := map[Point]int{} // Read patterns and positions for input.Scan() { r = strings.NewReader(input.Text()) b, _ = r.ReadByte() if b == '#' { b, _ = r.ReadByte() if b == 'P' { s := strings.Split(input.Text(), " ") x, _ = strconv.Atoi(s[1]) y, _ = strconv.Atoi(s[2]) x += (M / 2) y += (N / 2) oldy = y } else { fmt.Fprintf(os.Stderr, "ERROR: Expected Position or blocks not config parameters\n") return false } } else { p.x = x for cells := int(r.Size()); cells > 0; cells-- { p.y = y switch b { case '.': { //m[p] = 0 } case '*': { m[p] = 1 } default: { fmt.Fprintf(os.Stderr, "ERROR: Character not valid, only '.' or '*'\n") return false } } b, _ = r.ReadByte() y++ } } x++ y = oldy } w.Matrix[0] = m return true // NOTE: ignoring potential errors from input.Err() }