kvn 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +2 -16
- data/README.md +44 -1
- data/lib/kvn.rb +15 -28
- data/lib/kvn/converter.rb +38 -0
- data/lib/kvn/lexer.rb +4 -4
- data/lib/kvn/parser.rb +42 -14
- data/lib/kvn/unsupported_hash_error.rb +4 -0
- data/lib/kvn/value_lexer.rb +21 -0
- data/lib/kvn/version.rb +1 -1
- metadata +5 -3
- data/lib/kvn/illegal_character_error.rb +0 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 832c9ff0fe7496bfe3c6f5a93cc7b959e8889cb2
|
4
|
+
data.tar.gz: 05dd1ba7428b883dc2fe7669ae70fa180f14c383
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ec2564e05c43f19bd5897d58cf7bda7392817ce7bcb738e44abec846deccc332893d292565b9855605385462383d7309164ee52729f3060ccd7808cdfbbf28c
|
7
|
+
data.tar.gz: 2f00b76e616acf6177ca67558004c89545fb9adb0a616fac958f3eabc9c28db556ac626cb36bc563bc02f12fb0d37dffa6ec2d5d7f09c4fcdd7e3b176fd9a761
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
kvn (0.
|
4
|
+
kvn (0.2.0)
|
5
5
|
lex (= 0.1.0)
|
6
6
|
|
7
7
|
GEM
|
@@ -11,25 +11,18 @@ GEM
|
|
11
11
|
debug_inspector (>= 0.0.1)
|
12
12
|
byebug (8.2.2)
|
13
13
|
coderay (1.1.1)
|
14
|
-
coveralls (0.8.
|
14
|
+
coveralls (0.8.13)
|
15
15
|
json (~> 1.8)
|
16
|
-
rest-client (>= 1.6.8, < 2)
|
17
16
|
simplecov (~> 0.11.0)
|
18
17
|
term-ansicolor (~> 1.3)
|
19
18
|
thor (~> 0.19.1)
|
20
19
|
tins (~> 1.6.0)
|
21
20
|
debug_inspector (0.0.2)
|
22
21
|
docile (1.1.5)
|
23
|
-
domain_name (0.5.20160128)
|
24
|
-
unf (>= 0.0.5, < 1.0.0)
|
25
|
-
http-cookie (1.0.2)
|
26
|
-
domain_name (~> 0.5)
|
27
22
|
interception (0.5)
|
28
23
|
json (1.8.3)
|
29
24
|
lex (0.1.0)
|
30
25
|
method_source (0.8.2)
|
31
|
-
mime-types (2.99.1)
|
32
|
-
netrc (0.11.0)
|
33
26
|
os (0.9.6)
|
34
27
|
pry (0.10.3)
|
35
28
|
coderay (~> 1.1.0)
|
@@ -51,10 +44,6 @@ GEM
|
|
51
44
|
pry-rescue
|
52
45
|
pry-stack_explorer
|
53
46
|
rake (10.5.0)
|
54
|
-
rest-client (1.8.0)
|
55
|
-
http-cookie (>= 1.0.2, < 2.0)
|
56
|
-
mime-types (>= 1.16, < 3.0)
|
57
|
-
netrc (~> 0.7)
|
58
47
|
simplecov (0.11.2)
|
59
48
|
docile (~> 1.1.0)
|
60
49
|
json (~> 1.8)
|
@@ -65,9 +54,6 @@ GEM
|
|
65
54
|
tins (~> 1.0)
|
66
55
|
thor (0.19.1)
|
67
56
|
tins (1.6.0)
|
68
|
-
unf (0.1.4)
|
69
|
-
unf_ext
|
70
|
-
unf_ext (0.0.7.2)
|
71
57
|
|
72
58
|
PLATFORMS
|
73
59
|
ruby
|
data/README.md
CHANGED
@@ -1,4 +1,47 @@
|
|
1
|
+
[![Lines of Code](http://img.shields.io/badge/lines_of_code-145-brightgreen.svg?style=flat)](http://blog.codinghorror.com/the-best-code-is-no-code-at-all/)
|
2
|
+
[![Code Status](http://img.shields.io/codeclimate/github/hopsoft/kvn.svg?style=flat)](https://codeclimate.com/github/hopsoft/kvn)
|
3
|
+
[![Dependency Status](http://img.shields.io/gemnasium/hopsoft/kvn.svg?style=flat)](https://gemnasium.com/hopsoft/kvn)
|
4
|
+
[![Build Status](http://img.shields.io/travis/hopsoft/kvn.svg?style=flat)](https://travis-ci.org/hopsoft/kvn)
|
5
|
+
[![Coverage Status](https://img.shields.io/coveralls/hopsoft/kvn.svg?style=flat)](https://coveralls.io/r/hopsoft/kvn?branch=master)
|
6
|
+
[![Downloads](http://img.shields.io/gem/dt/kvn.svg?style=flat)](http://rubygems.org/gems/kvn)
|
7
|
+
|
1
8
|
# KVN (kevin)
|
2
9
|
|
3
|
-
|
10
|
+
## Key/Value Notation
|
11
|
+
|
12
|
+
Similar to JSON but more limited in scope.
|
13
|
+
Can be used to represent basic key/value data structures as (human readable) strings.
|
14
|
+
|
15
|
+
Useful when working with limited storage options
|
16
|
+
to capture additional (human readable) data in a single field.
|
17
|
+
|
18
|
+
## Rules
|
19
|
+
|
20
|
+
* Data structures should be flat (i.e. 1 level deep, no nesting)
|
21
|
+
* Keys & values are limited to primitive types
|
22
|
+
|
23
|
+
* String
|
24
|
+
* Numeric
|
25
|
+
* Boolean
|
26
|
+
* Null
|
27
|
+
|
28
|
+
* Colons & semicolons are prohibited in keys & values
|
29
|
+
* Keys are sorted alphabetically
|
30
|
+
|
31
|
+
## Examples
|
32
|
+
|
33
|
+
### Convert a Hash to a KVN string
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
data = { d: "example with whitespace", a: true, c: "example", b: 1, e: nil }
|
37
|
+
Kvn::Converter.new(data).convert
|
38
|
+
# => "a:true; b:1; c:example; d:example with whitespace; e:null;"
|
39
|
+
```
|
40
|
+
|
41
|
+
### Parse a KVN string into a Hash
|
4
42
|
|
43
|
+
```ruby
|
44
|
+
value = "a:true; b:1; c:example; d:example with whitespace; e:null;"
|
45
|
+
Kvn::Parser.new(value).parse
|
46
|
+
# => {"a"=>true, "b"=>1, "c"=>"example", "d"=>"example with whitespace", "e"=>nil}
|
47
|
+
```
|
data/lib/kvn.rb
CHANGED
@@ -1,34 +1,21 @@
|
|
1
1
|
require "kvn/version"
|
2
|
-
require "kvn/
|
2
|
+
require "kvn/unsupported_hash_error"
|
3
|
+
require "kvn/value_lexer"
|
3
4
|
require "kvn/lexer"
|
5
|
+
require "kvn/converter"
|
4
6
|
require "kvn/parser"
|
5
7
|
|
6
8
|
module Kvn
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
value = standardize(value)
|
20
|
-
semicolon_count = value.scan(";").size
|
21
|
-
colon_count = value.scan(":").size
|
22
|
-
return false unless semicolon_count > 0
|
23
|
-
return false unless colon_count > 0
|
24
|
-
return false unless semicolon_count == colon_count
|
25
|
-
end
|
26
|
-
|
27
|
-
private
|
28
|
-
|
29
|
-
def standardize(value)
|
30
|
-
value.to_s.strip
|
31
|
-
end
|
32
|
-
|
33
|
-
end
|
9
|
+
SUPPORTED_VALUE_TYPES = [
|
10
|
+
NilClass,
|
11
|
+
TrueClass,
|
12
|
+
FalseClass,
|
13
|
+
Symbol,
|
14
|
+
String,
|
15
|
+
Integer,
|
16
|
+
Fixnum,
|
17
|
+
Bignum,
|
18
|
+
Float,
|
19
|
+
Rational
|
20
|
+
]
|
34
21
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Kvn
|
2
|
+
class Converter
|
3
|
+
attr_reader :value
|
4
|
+
|
5
|
+
def initialize(value)
|
6
|
+
@value = (value ||= {}).to_h rescue {}
|
7
|
+
|
8
|
+
if invalid_values_present?
|
9
|
+
message = "All values must be a supported type! #{Kvn::SUPPORTED_VALUE_TYPES.join ", "}"
|
10
|
+
raise Kvn::UnsupportedHashError.new(message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def convert
|
15
|
+
value.keys.sort.each_with_object([]) do |key, memo|
|
16
|
+
v = value[key]
|
17
|
+
v = "null" if v.nil?
|
18
|
+
next if v.to_s.strip.empty?
|
19
|
+
memo << "#{key}:#{v};"
|
20
|
+
end.join(" ")
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def standardize_value(value)
|
26
|
+
value.to_s.strip
|
27
|
+
end
|
28
|
+
|
29
|
+
def value_types
|
30
|
+
value.values.map(&:class).uniq
|
31
|
+
end
|
32
|
+
|
33
|
+
def invalid_values_present?
|
34
|
+
!(value_types - Kvn::SUPPORTED_VALUE_TYPES).empty?
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
data/lib/kvn/lexer.rb
CHANGED
@@ -9,14 +9,14 @@ module Kvn
|
|
9
9
|
:PARTDELIM
|
10
10
|
)
|
11
11
|
|
12
|
-
rule :KEY,
|
13
|
-
rule :VALUE, /(\
|
12
|
+
rule :KEY, /\w+(?=:)/
|
13
|
+
rule :VALUE, /[\w+(\s|\.)]+(?=;)/
|
14
14
|
rule :PAIRDELIM, /;\s*/
|
15
15
|
rule :PARTDELIM, /:/
|
16
16
|
|
17
17
|
error do |lexer, token|
|
18
|
-
message = "Illegal character in KVN string! #{token.line}:#{token.column}
|
19
|
-
raise
|
18
|
+
message = "Illegal character in KVN string! #{token.line}:#{token.column} <#{token.value}>"
|
19
|
+
raise SyntaxError.new(message)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
data/lib/kvn/parser.rb
CHANGED
@@ -1,28 +1,56 @@
|
|
1
1
|
module Kvn
|
2
2
|
class Parser
|
3
|
+
attr_reader :value
|
3
4
|
|
4
|
-
def
|
5
|
-
|
5
|
+
def initialize(value)
|
6
|
+
@value = value.to_s.strip
|
7
|
+
end
|
8
|
+
|
9
|
+
def parse
|
6
10
|
lexer = Kvn::Lexer.new
|
7
|
-
output = lexer.lex(
|
11
|
+
output = lexer.lex(value)
|
12
|
+
{}.tap do |parsed|
|
13
|
+
begin
|
14
|
+
key = nil
|
15
|
+
key_found = false
|
16
|
+
value_found = false
|
17
|
+
while output.peek
|
18
|
+
token = output.next
|
19
|
+
if token.name == :KEY
|
20
|
+
key = token.value
|
21
|
+
key_found = true
|
22
|
+
value_found = false
|
23
|
+
end
|
24
|
+
|
25
|
+
if token.name == :VALUE
|
26
|
+
raise SyntaxError.new("Empty key detected for value! <#{token.value}>") unless key_found
|
27
|
+
parsed[key] = parse_value(token.value)
|
28
|
+
value_found = true
|
29
|
+
key_found = false
|
30
|
+
end
|
8
31
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
parsed[key] = token.value if token.name == :VALUE
|
32
|
+
if token.name == :PAIRDELIM && !value_found
|
33
|
+
raise SyntaxError.new("Empty value detected for key! <#{key}>")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
rescue StopIteration
|
15
37
|
end
|
16
|
-
rescue StopIteration
|
17
38
|
end
|
18
|
-
|
19
|
-
parsed
|
20
39
|
end
|
21
40
|
|
22
41
|
private
|
23
42
|
|
24
|
-
def
|
25
|
-
|
43
|
+
def parse_value(value)
|
44
|
+
lexer = Kvn::ValueLexer.new
|
45
|
+
token = lexer.lex(value).next
|
46
|
+
case token.name
|
47
|
+
when :NIL then value = nil
|
48
|
+
when :TRUE then value = true
|
49
|
+
when :FALSE then value = false
|
50
|
+
when :FLOAT then value = value.to_f
|
51
|
+
when :INTEGER then value = value.to_i
|
52
|
+
else value.to_s
|
53
|
+
end
|
26
54
|
end
|
27
55
|
|
28
56
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "lex"
|
2
|
+
|
3
|
+
module Kvn
|
4
|
+
class ValueLexer < Lex::Lexer
|
5
|
+
tokens(
|
6
|
+
:NIL,
|
7
|
+
:TRUE,
|
8
|
+
:FALSE,
|
9
|
+
:FLOAT,
|
10
|
+
:INTEGER,
|
11
|
+
:STRING
|
12
|
+
)
|
13
|
+
|
14
|
+
rule :NIL, /null/
|
15
|
+
rule :TRUE, /true/
|
16
|
+
rule :FALSE, /false/
|
17
|
+
rule :FLOAT, /\d+\.\d+/
|
18
|
+
rule :INTEGER, /\d+/
|
19
|
+
rule :STRING, /.*/
|
20
|
+
end
|
21
|
+
end
|
data/lib/kvn/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: kvn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Nathan Hopkins
|
@@ -93,9 +93,11 @@ files:
|
|
93
93
|
- README.md
|
94
94
|
- Rakefile
|
95
95
|
- lib/kvn.rb
|
96
|
-
- lib/kvn/
|
96
|
+
- lib/kvn/converter.rb
|
97
97
|
- lib/kvn/lexer.rb
|
98
98
|
- lib/kvn/parser.rb
|
99
|
+
- lib/kvn/unsupported_hash_error.rb
|
100
|
+
- lib/kvn/value_lexer.rb
|
99
101
|
- lib/kvn/version.rb
|
100
102
|
homepage: https://github.com/hopsoft/kvn
|
101
103
|
licenses:
|
@@ -120,5 +122,5 @@ rubyforge_project:
|
|
120
122
|
rubygems_version: 2.5.1
|
121
123
|
signing_key:
|
122
124
|
specification_version: 4
|
123
|
-
summary: KVN
|
125
|
+
summary: KVN key/value notation converter & parser
|
124
126
|
test_files: []
|