// ParseNumber parses and returns a positive integer. // Leading spaces are ignored. // If EOF is reached before any digits are encountered, 1 is returned. func parseNumber(rs io.RuneScanner) (int, error) { if err := skipSpace(rs); err != nil { return 0, err } var s string for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: break case err != nil: return 0, err case unicode.IsDigit(r): s += string(r) continue default: if err := rs.UnreadRune(); err != nil { return 0, err } } if len(s) == 0 { return 1, nil } return strconv.Atoi(s) } }
// ParseDelimited returns the string // up to the first unescaped delimiter, // raw newline (rune 0xA), // or the end of input. // A delimiter preceeded by \ is escaped and is non-terminating. // The letter n preceeded by \ is a newline literal. func parseDelimited(delim rune, rs io.RuneScanner) (string, error) { var s string var esc bool for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return s, nil case err != nil: return "", err case esc && r == delim: s += string(delim) esc = false case r == delim || r == '\n': return s, nil case !esc && r == '\\': esc = true case esc && r == 'n': s += "\n" esc = false default: if esc { s += "\\" } s += string(r) esc = false } } }
// readStructuredData reads a STRUCTURED-DATA (as defined in RFC-5424) // from `r` and assigns the StructuredData member. // // STRUCTURED-DATA = NILVALUE / 1*SD-ELEMENT // SD-ELEMENT = "[" SD-ID *(SP SD-PARAM) "]" // SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34 // SD-ID = SD-NAME // PARAM-NAME = SD-NAME // PARAM-VALUE = UTF-8-STRING ; characters '"', '\' and ']' MUST be escaped. // SD-NAME = 1*32PRINTUSASCII except '=', SP, ']', %d34 (") func (m *Message) readStructuredData(r io.RuneScanner) (err error) { m.StructuredData = []StructuredData{} ch, _, err := r.ReadRune() if err != nil { return err } if ch == '-' { return nil } r.UnreadRune() for { ch, _, err := r.ReadRune() if err == io.EOF { return nil } else if err != nil { return err // hard to reach without underlying IO error } else if ch == ' ' { r.UnreadRune() return nil } else if ch == '[' { r.UnreadRune() sde, err := readSDElement(r) if err != nil { return err } m.StructuredData = append(m.StructuredData, sde) } else { return BadFormat("StructuredData") } } }
func parseCmd(rs io.RuneScanner) (string, error) { if err := skipSpace(rs); err != nil { return "", err } var esc bool var cmd string for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return cmd, nil case err != nil: return "", nil case r == '\n': return cmd, nil case r == '\\': esc = true case esc && r == 'n': cmd += "\n" esc = false default: if esc { cmd += "\\" } cmd += string(r) esc = false } } }
// like in.ReadRune() but ignore all leading whitespace. func ReadChar(in io.RuneScanner) (r rune, size int, err error) { r, size, err = in.ReadRune() for unicode.IsSpace(r) && err == nil { r, size, err = in.ReadRune() } return }
// readSDElement reads an SD-ELEMENT as defined by RFC-5424 // // SD-ELEMENT = "[" SD-ID *(SP SD-PARAM) "]" // SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34 // SD-ID = SD-NAME // PARAM-NAME = SD-NAME // PARAM-VALUE = UTF-8-STRING ; characters '"', '\' and ']' MUST be escaped. // SD-NAME = 1*32PRINTUSASCII except '=', SP, ']', %d34 (") func readSDElement(r io.RuneScanner) (element StructuredData, err error) { ch, _, err := r.ReadRune() if err != nil { return element, err // hard to reach without underlying IO error } if ch != '[' { return element, BadFormat("StructuredData[]") // unreachable } element.ID, err = readSdID(r) if err != nil { return element, err } for { ch, _, err := r.ReadRune() if err != nil { return element, err } else if ch == ']' { return element, nil } else if ch == ' ' { param, err := readSdParam(r) if err != nil { return element, err } element.Parameters = append(element.Parameters, *param) } else { return element, BadFormat("StructuredData[]") } } }
// readPriority reads the PRI as defined in RFC-5424 and assigns Severity and // Facility accordingly. func (m *Message) readPriority(r io.RuneScanner) error { ch, _, err := r.ReadRune() if err != nil { return err } if ch != '<' { return BadFormat("Priority") } rv := &bytes.Buffer{} for { ch, _, err := r.ReadRune() if err != nil { return err } if unicode.IsDigit(ch) { rv.WriteRune(ch) continue } if ch != '>' { return BadFormat("Priority") } // We have a complete integer expression priority, err := strconv.ParseInt(string(rv.Bytes()), 10, 32) if err != nil { return BadFormat("Priority") } m.Priority = int(priority) return nil } }
func readRune(r io.RuneScanner) int { rune, _, err := r.ReadRune() if err != nil { return -1 } return rune }
func parseCompoundAddr(rs io.RuneScanner) (Address, error) { var a1 Address for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return a1, nil case err != nil: return nil, err case strings.ContainsRune(simpleFirst, r): if err := rs.UnreadRune(); err != nil { return nil, err } switch a2, err := parseSimpleAddr(rs); { case err != nil: return nil, err case a1 != nil: a1 = a1.Plus(a2) default: a1 = a2 } case r == '+' || r == '-': if a1 == nil { a1 = Dot } a2, err := parseSimpleAddr(rs) if a2 == nil { a2 = Line(1) } switch { case err != nil: return nil, err case r == '+': a1 = a1.Plus(a2) default: a1 = a1.Minus(a2) } case r == ',' || r == ';': if a1 == nil { a1 = Line(0) } a2, err := parseCompoundAddr(rs) if a2 == nil { a2 = End } switch { case err != nil: return nil, err case r == ',': a1 = a1.To(a2) default: a1 = a1.Then(a2) } case unicode.IsSpace(r) && r != '\n': continue default: return a1, rs.UnreadRune() } } }
// readSpace reads a single space func readSpace(r io.RuneScanner) error { ch, _, err := r.ReadRune() if err != nil { return err } if ch != ' ' { return BadFormat("expected space") } return nil }
// readVersion reads the version string fails if it isn't `1` func (m *Message) readVersion(r io.RuneScanner) error { ch, _, err := r.ReadRune() if err != nil { return err } if ch != '1' { return BadFormat("Version") } return nil }
func chompBOM(r io.RuneScanner) (err error) { for { c, _, err := r.ReadRune() if err != nil { return err } if c != BOM { r.UnreadRune() return nil } } }
func chompWhitespace(r io.RuneScanner) (err error) { for { c, _, err := r.ReadRune() if err != nil { return err } if !unicode.IsSpace(c) { r.UnreadRune() return nil } } }
func skipSingleNewline(rs io.RuneScanner) error { // Eat a single trailing newline. switch r, _, err := rs.ReadRune(); { case err == io.EOF: return nil case err != nil: return err case r == '\n': return nil default: return rs.UnreadRune() } }
func readNumber(b int, r io.RuneScanner) string { s := string(b) rune, _, err := r.ReadRune() for err == nil && string(rune) != " " && string(rune) != "(" && string(rune) != ")" { s = s + string(rune) rune, _, err = r.ReadRune() } if err == nil { r.UnreadRune() } return s }
func (d *Dec) scan(r io.RuneScanner) error { d.coef.hi = 0 d.coef.lo = 0 d.scale = 0 ch, _, err := r.ReadRune() if err != nil { return err } var neg bool switch ch { case '-': neg = true case '+': default: r.UnreadRune() } var dec bool for { ch, _, err = r.ReadRune() if err == io.EOF { goto ExitLoop } if err != nil { return err } switch { case ch == '.': if dec { r.UnreadRune() goto ExitLoop } dec = true case ch >= '0' && ch <= '9': d.coef.Mul(&d.coef, intTen) var z Int128 z.SetInt64(int64(ch - '0')) d.coef.Add(&d.coef, &z) if dec { d.scale++ } default: r.UnreadRune() goto ExitLoop } } ExitLoop: if neg { d.Neg(d) } return nil }
// readSdParam reads a PARAM-NAME as defined by RFC-5424 // SD-PARAM = PARAM-NAME "=" %d34 PARAM-VALUE %d34 // PARAM-NAME = SD-NAME // SD-NAME = 1*32PRINTUSASCII except '=', SP, ']', %d34 (") func readSdParamName(r io.RuneScanner) (string, error) { rv := &bytes.Buffer{} for { ch, _, err := r.ReadRune() if err != nil { return "", err } if ch == '=' { r.UnreadRune() return string(rv.Bytes()), nil } rv.WriteRune(ch) } }
func parseNegation(r io.RuneScanner, glob *globImpl) error { for { char, _, err := r.ReadRune() if err != nil { return err } else if char == '!' { glob.negated = !glob.negated } else { r.UnreadRune() return nil } } }
// SkipSpace consumes and ignores non-newline whitespace. // Terminates if a newline is encountered. // The terminating newline remains consumed. func skipSpace(rs io.RuneScanner) error { for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return nil case err != nil: return err case r != '\n' && unicode.IsSpace(r): continue default: return rs.UnreadRune() } } }
func readword(f *Xfile, isnum bool) string { var ( barr [512]rune sp int c rune err error sc io.RuneScanner ) if f.isgraphic() { sc = f.graph } else { sc = f.b } buf := barr[0:0] sp = 0 for { c, _, err = sc.ReadRune() if err!=nil || !unicode.IsSpace(c) { break } } for { if err!=nil && sp==0 { panic("read: eof met") } buf = append(buf, c) sp++ c, _, err = sc.ReadRune() if err!=nil || (isnum && !strings.ContainsRune("0123456789+-eE.", c)) { break } if err!=nil || unicode.IsSpace(c) { break } } if err != nil { if iseof(c, err) { f.eof = true } } else { f.eol = (c == rune(paminstr.EOL[0])) if !f.eol { sc.UnreadRune() } } if len(buf) == 0 { panic("read: eof met") } return string(buf) }
func parseMarkRune(rs io.RuneScanner) (rune, error) { for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return '.', nil case err != nil: return 0, err case unicode.IsSpace(r): continue default: return r, nil } } }
func stringReader(flag int, r io.RuneScanner) interface{} { var s string = "" for { rune, _, err := r.ReadRune() if err != nil { panic("err") } if rune == '"' { return s } s = s + string(rune) } return s }
func (z *Dec) scan(r io.RuneScanner) (*Dec, error) { unscaled := make([]byte, 0, 256) // collects chars of unscaled as bytes dp, dg := -1, -1 // indexes of decimal point, first digit loop: for { ch, _, err := r.ReadRune() if err == io.EOF { break loop } if err != nil { return nil, err } switch { case ch == '+' || ch == '-': if len(unscaled) > 0 || dp >= 0 { // must be first character r.UnreadRune() break loop } case ch == '.': if dp >= 0 { r.UnreadRune() break loop } dp = len(unscaled) continue // don't add to unscaled case ch >= '0' && ch <= '9': if dg == -1 { dg = len(unscaled) } default: r.UnreadRune() break loop } unscaled = append(unscaled, byte(ch)) } if dg == -1 { return nil, fmt.Errorf("no digits read") } if dp >= 0 { z.SetScale(Scale(len(unscaled) - dp)) } else { z.SetScale(0) } _, ok := z.UnscaledBig().SetString(string(unscaled), 10) if !ok { return nil, fmt.Errorf("invalid decimal: %s", string(unscaled)) } return z, nil }
func parseMarkAddr(rs io.RuneScanner) (SimpleAddress, error) { for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return nil, errors.New("bad mark: EOF") case err != nil: return nil, err case !unicode.IsSpace(r) || r == '\n': if !isMarkRune(r) { return nil, errors.New("bad mark: " + string(r)) } return Mark(r), nil } } }
func scanDigits(rs io.RuneScanner) (string, error) { var s string for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return s, nil case err != nil: return "", err case !unicode.IsDigit(r): return s, rs.UnreadRune() default: s += string(r) } } }
func parseText(rs io.RuneScanner) (string, error) { for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return "", nil case err != nil: return "", err case r == '\n': return parseLines(rs) case unicode.IsSpace(r): continue default: return parseDelimited(r, rs) } } }
func seqReader(rune int, r io.RuneScanner) interface{} { seq := make([]interface{}, 0) for { nrune, _, err := r.ReadRune() for isWhiteSpace(nrune) { nrune, _, err = r.ReadRune() } if err != nil || string(nrune) == ")" { return seq } r.UnreadRune() fmt.Println(seq) seq = append(seq, read(r)) } return seq }
// ScanBareIdent reads bare identifier from a rune reader. func ScanBareIdent(r io.RuneScanner) string { // Read every ident character into the buffer. // Non-ident characters and EOF will cause the loop to exit. var buf bytes.Buffer for { ch, _, err := r.ReadRune() if err != nil { break } else if !isIdentChar(ch) { r.UnreadRune() break } else { _, _ = buf.WriteRune(ch) } } return buf.String() }
func parseLines(rs io.RuneScanner) (string, error) { var s string var nl bool for { switch r, _, err := rs.ReadRune(); { case err == io.EOF: return s, nil case err != nil: return "", err case nl && r == '.': return s, nil default: s += string(r) nl = r == '\n' } } }
// readWord reads `r` until it encounters a space (0x20) func readWord(r io.RuneScanner) (string, error) { rv := &bytes.Buffer{} for { ch, _, err := r.ReadRune() if err != nil { return "", err } else if ch != ' ' { rv.WriteRune(ch) } else { r.UnreadRune() rvString := string(rv.Bytes()) if rvString == "-" { rvString = "" } return rvString, nil } } }