logfmt 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ea9ce7afd32bfdaa73e9399460c34f6c5cf2a60
4
- data.tar.gz: c54d8967a623133fbabfbf50d160fb284e62a207
3
+ metadata.gz: ebbeb9a0b99c4d279a682953bd40f6585acfc8ff
4
+ data.tar.gz: 0c24353022ea70cf672b07cc9126de375b0400d2
5
5
  SHA512:
6
- metadata.gz: 451bd0bc7ab6db03156c1bcd16277af82f36a597eef4d2a8e5ec7a989cbeb1224662a497918523478dc64850f868afb242a954453a882165027e27387ae186ae
7
- data.tar.gz: 38780bd602894e7a57800ec52bbbe0325d476f155f5e09de3964232268d1906932576f576ce5d0d797dc34840d221e616f046a48330e19d40df4f0c94574a91f
6
+ metadata.gz: a14c02145816f5ec84487ef96b4fff690c6d1692bd3209c59eb58db7bf1af5b20148e19c6d56d4b99eb6ba8175e540b61852ddac2748441552fcc9d4faf7f4b8
7
+ data.tar.gz: 5db326288526225bd1084acaf9ef2fb57a785de7b0f6f7086c92b0e0a4eae58252f052632897f49d60dca488b03f5bd68c4cebe8d263e086cb5a94ada3774c6d
data/bench.rb ADDED
@@ -0,0 +1,15 @@
1
+ $:.unshift File.expand_path('../lib', __FILE__)
2
+
3
+ require 'benchmark'
4
+ require 'logfmt'
5
+
6
+ N = 1_000
7
+ line = 'foo=bar a=14 baz="hello kitty" ƒ=2h3s cool%story=bro f %^asdf'
8
+
9
+ Benchmark.bm(20) do |x|
10
+ x.report('char-by-char') do
11
+ N.times do
12
+ Logfmt.parse(line)
13
+ end
14
+ end
15
+ end
data/lib/logfmt/parser.rb CHANGED
@@ -1,49 +1,88 @@
1
- require "parslet"
2
-
3
1
  module Logfmt
4
- class Parser < Parslet::Parser
5
- rule(:ident_byte) { match['^\s"='] }
6
- rule(:string_byte) { match['^\\\\"'] }
7
- rule(:garbage) { match['\s"='].repeat }
8
- rule(:ident) { ident_byte >> ident_byte.repeat }
9
- rule(:key) { ident }
10
- rule(:value) {
11
- ident.as(:value) |
12
- str('"') >> (string_byte | str('\"')).repeat.as(:value) >> str('"')
13
- }
14
- rule(:pair) {
15
- (key.as(:key) >> str('=') >> value) |
16
- (key.as(:key) >> str('=')) |
17
- key.as(:key)
18
- }
19
- rule(:message) {
20
- (garbage >> pair.as(:pair)).repeat.as(:message) >> garbage
21
- }
22
- root(:message)
23
- end
24
-
25
- class Transformer < Parslet::Transform
26
- class Pair < Struct.new(:key, :val); end
27
-
28
- rule(:message => subtree(:ob)) {
29
- (ob.is_a?(Array) ? ob : [ ob ]).inject({}) { |h, p| h[p.key] = p.val; h }
30
- }
31
- rule(:pair => { :key => simple(:key), :value => simple(:val) }) {
32
- Pair.new(key.to_s, val.to_s)
33
- }
34
- rule(:pair => { :key => simple(:key), :value => sequence(:val) }) {
35
- Pair.new(key.to_s, "")
36
- }
37
- rule(:pair => { :key => simple(:key) }) {
38
- Pair.new(key.to_s, true)
39
- }
40
- end
41
-
42
- def self.parse(logs)
43
- parser = Parser.new
44
- transformer = Transformer.new
2
+ GARBAGE = 0
3
+ KEY = 1
4
+ EQUAL = 2
5
+ IVALUE = 3
6
+ QVALUE = 4
45
7
 
46
- tree = parser.parse(logs)
47
- transformer.apply(tree)
8
+ def self.parse(line)
9
+ output = {}
10
+ key, value = "", ""
11
+ escaped = false
12
+ state = GARBAGE
13
+ i = 0
14
+ line.each_char do |c|
15
+ i += 1
16
+ if state == GARBAGE
17
+ if c > ' ' && c != '"' && c != '='
18
+ key = c
19
+ state = KEY
20
+ end
21
+ next
22
+ end
23
+ if state == KEY
24
+ if c > ' ' && c != '"' && c != '='
25
+ state = KEY
26
+ key << c
27
+ elsif c == '='
28
+ output[key.strip()] = true
29
+ state = EQUAL
30
+ else
31
+ output[key.strip()] = true
32
+ state = GARBAGE
33
+ end
34
+ if i >= line.length
35
+ output[key.strip()] = true
36
+ end
37
+ next
38
+ end
39
+ if state == EQUAL
40
+ if c > ' ' && c != '"' && c != '='
41
+ value = c
42
+ state = IVALUE
43
+ elsif c == '"'
44
+ value = ""
45
+ escaped = false
46
+ state = QVALUE
47
+ else
48
+ state = GARBAGE
49
+ end
50
+ if i >= line.length
51
+ output[key.strip()] = true
52
+ end
53
+ next
54
+ end
55
+ if state == IVALUE
56
+ if not (c > ' ' && c != '"' && c != '=')
57
+ output[key.strip()] = value
58
+ state = GARBAGE
59
+ else
60
+ value << c
61
+ end
62
+ if i >= line.length
63
+ output[key.strip()] = value
64
+ end
65
+ next
66
+ end
67
+ if state == QVALUE
68
+ if c == '\\'
69
+ escaped = true
70
+ value << "\\"
71
+ elsif c == '"'
72
+ if escaped
73
+ escaped = false
74
+ value << c
75
+ next
76
+ end
77
+ output[key.strip()] = value
78
+ state = GARBAGE
79
+ else
80
+ escaped = false
81
+ value << c
82
+ end
83
+ next
84
+ end
85
+ end
86
+ output
48
87
  end
49
88
  end
@@ -1,3 +1,3 @@
1
1
  module Logfmt
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.4"
3
3
  end
@@ -2,7 +2,7 @@
2
2
  require 'spec_helper'
3
3
  require 'logfmt/parser'
4
4
 
5
- describe Logfmt::Parser do
5
+ describe Logfmt do
6
6
  it 'parse empty log line' do
7
7
  data = Logfmt.parse("")
8
8
  expect(data).to eq({})
@@ -55,12 +55,12 @@ describe Logfmt::Parser do
55
55
 
56
56
  it 'parse escaped quote value ' do
57
57
  data = Logfmt.parse('key="quoted \" value" r="esc\t"')
58
- expect(data).to eq({"key" => 'quoted " value', "r" => "esc\t"})
58
+ expect(data).to eq({"key" => 'quoted \" value', "r" => "esc\\t"})
59
59
  end
60
60
 
61
61
  it 'parse mixed pairs' do
62
62
  data = Logfmt.parse('key1="quoted \" value" key2 key3=value3')
63
- expect(data).to eq({"key1" => 'quoted " value', "key2" => true, "key3" => "value3"})
63
+ expect(data).to eq({"key1" => 'quoted \" value', "key2" => true, "key3" => "value3"})
64
64
  end
65
65
 
66
66
  it 'parse mixed characters pairs' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: logfmt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Timothée Peignier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-15 00:00:00.000000000 Z
11
+ date: 2014-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: parslet
@@ -65,6 +65,7 @@ files:
65
65
  - Gemfile
66
66
  - README.md
67
67
  - Rakefile
68
+ - bench.rb
68
69
  - lib/logfmt.rb
69
70
  - lib/logfmt/parser.rb
70
71
  - lib/logfmt/version.rb