package logfmtimport ()// A Decoder reads and decodes logfmt records from an input stream.typeDecoderstruct { pos int key []byte value []byte lineNum int s *bufio.Scanner err error}// NewDecoder returns a new decoder that reads from r.//// The decoder introduces its own buffering and may read data from r beyond// the logfmt records requested.func ( io.Reader) *Decoder { := &Decoder{s: bufio.NewScanner(), }return}// NewDecoderSize returns a new decoder that reads from r.//// The decoder introduces its own buffering and may read data from r beyond// the logfmt records requested.// The size argument specifies the size of the initial buffer that the// Decoder will use to read records from r.// If a log line is longer than the size argument, the Decoder will return// a bufio.ErrTooLong error.func ( io.Reader, int) *Decoder { := bufio.NewScanner() .Buffer(make([]byte, 0, ), ) := &Decoder{s: , }return}// ScanRecord advances the Decoder to the next record, which can then be// parsed with the ScanKeyval method. It returns false when decoding stops,// either by reaching the end of the input or an error. After ScanRecord// returns false, the Err method will return any error that occurred during// decoding, except that if it was io.EOF, Err will return nil.func ( *Decoder) () bool {if .err != nil {returnfalse }if !.s.Scan() { .err = .s.Err()returnfalse } .lineNum++ .pos = 0returntrue}// ScanKeyval advances the Decoder to the next key/value pair of the current// record, which can then be retrieved with the Key and Value methods. It// returns false when decoding stops, either by reaching the end of the// current record or an error.func ( *Decoder) () bool { .key, .value = nil, nilif .err != nil {returnfalse } := .s.Bytes()// garbagefor , := range [.pos:] {if > ' ' { .pos += goto } } .pos = len()returnfalse:const = "invalid key" , := .pos, falsefor , := range [.pos:] {switch {case == '=': .pos += if .pos > { .key = [:.pos]if && bytes.ContainsRune(.key, utf8.RuneError) { .syntaxError()returnfalse } }if .key == nil { .unexpectedByte()returnfalse }gotocase == '"': .pos += .unexpectedByte()returnfalsecase <= ' ': .pos += if .pos > { .key = [:.pos]if && bytes.ContainsRune(.key, utf8.RuneError) { .syntaxError()returnfalse } }returntruecase >= utf8.RuneSelf: = true } } .pos = len()if .pos > { .key = [:.pos]if && bytes.ContainsRune(.key, utf8.RuneError) { .syntaxError()returnfalse } }returntrue: .pos++if .pos >= len() {returntrue }switch := [.pos]; {case <= ' ':returntruecase == '"':goto }// value = .posfor , := range [.pos:] {switch {case == '=' || == '"': .pos += .unexpectedByte()returnfalsecase <= ' ': .pos += if .pos > { .value = [:.pos] }returntrue } } .pos = len()if .pos > { .value = [:.pos] }returntrue:const ( = "unterminated quoted value" = "invalid quoted value" ) , := false, false = .posfor , := range [.pos+1:] {switch {case : = falsecase == '\\': , = true, truecase == '"': .pos += + 2if { , := unquoteBytes([:.pos])if ! { .syntaxError()returnfalse } .value = } else { ++ := .pos - 1if > { .value = [:] } }returntrue } } .pos = len() .syntaxError()returnfalse}// Key returns the most recent key found by a call to ScanKeyval. The returned// slice may point to internal buffers and is only valid until the next call// to ScanRecord. It does no allocation.func ( *Decoder) () []byte {return .key}// Value returns the most recent value found by a call to ScanKeyval. The// returned slice may point to internal buffers and is only valid until the// next call to ScanRecord. It does no allocation when the value has no// escape sequences.func ( *Decoder) () []byte {return .value}// Err returns the first non-EOF error that was encountered by the Scanner.func ( *Decoder) () error {return .err}func ( *Decoder) ( string) { .err = &SyntaxError{Msg: ,Line: .lineNum,Pos: .pos + 1, }}func ( *Decoder) ( byte) { .err = &SyntaxError{Msg: fmt.Sprintf("unexpected %q", ),Line: .lineNum,Pos: .pos + 1, }}// A SyntaxError represents a syntax error in the logfmt input stream.typeSyntaxErrorstruct { Msg string Line int Pos int}func ( *SyntaxError) () string {returnfmt.Sprintf("logfmt syntax error at pos %d on line %d: %s", .Pos, .Line, .Msg)}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.