logfmt 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
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