...

Source file src/github.com/go-logfmt/logfmt/decode.go

Documentation: github.com/go-logfmt/logfmt

     1  package logfmt
     2  
     3  import (
     4  	"bufio"
     5  	"bytes"
     6  	"fmt"
     7  	"io"
     8  	"unicode/utf8"
     9  )
    10  
    11  // A Decoder reads and decodes logfmt records from an input stream.
    12  type Decoder struct {
    13  	pos     int
    14  	key     []byte
    15  	value   []byte
    16  	lineNum int
    17  	s       *bufio.Scanner
    18  	err     error
    19  }
    20  
    21  // NewDecoder returns a new decoder that reads from r.
    22  //
    23  // The decoder introduces its own buffering and may read data from r beyond
    24  // the logfmt records requested.
    25  func NewDecoder(r io.Reader) *Decoder {
    26  	dec := &Decoder{
    27  		s: bufio.NewScanner(r),
    28  	}
    29  	return dec
    30  }
    31  
    32  // NewDecoderSize returns a new decoder that reads from r.
    33  //
    34  // The decoder introduces its own buffering and may read data from r beyond
    35  // the logfmt records requested.
    36  // The size argument specifies the size of the initial buffer that the
    37  // Decoder will use to read records from r.
    38  // If a log line is longer than the size argument, the Decoder will return
    39  // a bufio.ErrTooLong error.
    40  func NewDecoderSize(r io.Reader, size int) *Decoder {
    41  	scanner := bufio.NewScanner(r)
    42  	scanner.Buffer(make([]byte, 0, size), size)
    43  	dec := &Decoder{
    44  		s: scanner,
    45  	}
    46  	return dec
    47  }
    48  
    49  // ScanRecord advances the Decoder to the next record, which can then be
    50  // parsed with the ScanKeyval method. It returns false when decoding stops,
    51  // either by reaching the end of the input or an error. After ScanRecord
    52  // returns false, the Err method will return any error that occurred during
    53  // decoding, except that if it was io.EOF, Err will return nil.
    54  func (dec *Decoder) ScanRecord() bool {
    55  	if dec.err != nil {
    56  		return false
    57  	}
    58  	if !dec.s.Scan() {
    59  		dec.err = dec.s.Err()
    60  		return false
    61  	}
    62  	dec.lineNum++
    63  	dec.pos = 0
    64  	return true
    65  }
    66  
    67  // ScanKeyval advances the Decoder to the next key/value pair of the current
    68  // record, which can then be retrieved with the Key and Value methods. It
    69  // returns false when decoding stops, either by reaching the end of the
    70  // current record or an error.
    71  func (dec *Decoder) ScanKeyval() bool {
    72  	dec.key, dec.value = nil, nil
    73  	if dec.err != nil {
    74  		return false
    75  	}
    76  
    77  	line := dec.s.Bytes()
    78  
    79  	// garbage
    80  	for p, c := range line[dec.pos:] {
    81  		if c > ' ' {
    82  			dec.pos += p
    83  			goto key
    84  		}
    85  	}
    86  	dec.pos = len(line)
    87  	return false
    88  
    89  key:
    90  	const invalidKeyError = "invalid key"
    91  
    92  	start, multibyte := dec.pos, false
    93  	for p, c := range line[dec.pos:] {
    94  		switch {
    95  		case c == '=':
    96  			dec.pos += p
    97  			if dec.pos > start {
    98  				dec.key = line[start:dec.pos]
    99  				if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
   100  					dec.syntaxError(invalidKeyError)
   101  					return false
   102  				}
   103  			}
   104  			if dec.key == nil {
   105  				dec.unexpectedByte(c)
   106  				return false
   107  			}
   108  			goto equal
   109  		case c == '"':
   110  			dec.pos += p
   111  			dec.unexpectedByte(c)
   112  			return false
   113  		case c <= ' ':
   114  			dec.pos += p
   115  			if dec.pos > start {
   116  				dec.key = line[start:dec.pos]
   117  				if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
   118  					dec.syntaxError(invalidKeyError)
   119  					return false
   120  				}
   121  			}
   122  			return true
   123  		case c >= utf8.RuneSelf:
   124  			multibyte = true
   125  		}
   126  	}
   127  	dec.pos = len(line)
   128  	if dec.pos > start {
   129  		dec.key = line[start:dec.pos]
   130  		if multibyte && bytes.ContainsRune(dec.key, utf8.RuneError) {
   131  			dec.syntaxError(invalidKeyError)
   132  			return false
   133  		}
   134  	}
   135  	return true
   136  
   137  equal:
   138  	dec.pos++
   139  	if dec.pos >= len(line) {
   140  		return true
   141  	}
   142  	switch c := line[dec.pos]; {
   143  	case c <= ' ':
   144  		return true
   145  	case c == '"':
   146  		goto qvalue
   147  	}
   148  
   149  	// value
   150  	start = dec.pos
   151  	for p, c := range line[dec.pos:] {
   152  		switch {
   153  		case c == '=' || c == '"':
   154  			dec.pos += p
   155  			dec.unexpectedByte(c)
   156  			return false
   157  		case c <= ' ':
   158  			dec.pos += p
   159  			if dec.pos > start {
   160  				dec.value = line[start:dec.pos]
   161  			}
   162  			return true
   163  		}
   164  	}
   165  	dec.pos = len(line)
   166  	if dec.pos > start {
   167  		dec.value = line[start:dec.pos]
   168  	}
   169  	return true
   170  
   171  qvalue:
   172  	const (
   173  		untermQuote  = "unterminated quoted value"
   174  		invalidQuote = "invalid quoted value"
   175  	)
   176  
   177  	hasEsc, esc := false, false
   178  	start = dec.pos
   179  	for p, c := range line[dec.pos+1:] {
   180  		switch {
   181  		case esc:
   182  			esc = false
   183  		case c == '\\':
   184  			hasEsc, esc = true, true
   185  		case c == '"':
   186  			dec.pos += p + 2
   187  			if hasEsc {
   188  				v, ok := unquoteBytes(line[start:dec.pos])
   189  				if !ok {
   190  					dec.syntaxError(invalidQuote)
   191  					return false
   192  				}
   193  				dec.value = v
   194  			} else {
   195  				start++
   196  				end := dec.pos - 1
   197  				if end > start {
   198  					dec.value = line[start:end]
   199  				}
   200  			}
   201  			return true
   202  		}
   203  	}
   204  	dec.pos = len(line)
   205  	dec.syntaxError(untermQuote)
   206  	return false
   207  }
   208  
   209  // Key returns the most recent key found by a call to ScanKeyval. The returned
   210  // slice may point to internal buffers and is only valid until the next call
   211  // to ScanRecord.  It does no allocation.
   212  func (dec *Decoder) Key() []byte {
   213  	return dec.key
   214  }
   215  
   216  // Value returns the most recent value found by a call to ScanKeyval. The
   217  // returned slice may point to internal buffers and is only valid until the
   218  // next call to ScanRecord.  It does no allocation when the value has no
   219  // escape sequences.
   220  func (dec *Decoder) Value() []byte {
   221  	return dec.value
   222  }
   223  
   224  // Err returns the first non-EOF error that was encountered by the Scanner.
   225  func (dec *Decoder) Err() error {
   226  	return dec.err
   227  }
   228  
   229  func (dec *Decoder) syntaxError(msg string) {
   230  	dec.err = &SyntaxError{
   231  		Msg:  msg,
   232  		Line: dec.lineNum,
   233  		Pos:  dec.pos + 1,
   234  	}
   235  }
   236  
   237  func (dec *Decoder) unexpectedByte(c byte) {
   238  	dec.err = &SyntaxError{
   239  		Msg:  fmt.Sprintf("unexpected %q", c),
   240  		Line: dec.lineNum,
   241  		Pos:  dec.pos + 1,
   242  	}
   243  }
   244  
   245  // A SyntaxError represents a syntax error in the logfmt input stream.
   246  type SyntaxError struct {
   247  	Msg  string
   248  	Line int
   249  	Pos  int
   250  }
   251  
   252  func (e *SyntaxError) Error() string {
   253  	return fmt.Sprintf("logfmt syntax error at pos %d on line %d: %s", e.Pos, e.Line, e.Msg)
   254  }
   255  

View as plain text