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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 487ee8d85ce8eac0225f08b86d21dd815aff1f09
4
- data.tar.gz: 3eb23b598b95eab8155d6a3aaabfb8a1f16766c5
3
+ metadata.gz: 832c9ff0fe7496bfe3c6f5a93cc7b959e8889cb2
4
+ data.tar.gz: 05dd1ba7428b883dc2fe7669ae70fa180f14c383
5
5
  SHA512:
6
- metadata.gz: 87ed111e0c4a50bcce9a9220e76c42b94ca1146ffed4d956914d26342ee041efb037e7050e9195fad1776cec93b191137174cd493451852ec656a378aedc80eb
7
- data.tar.gz: 88e51aa82458c196d912d80c4f705d3403cb3991e0b75e50948ea2d6a6375ce7b6a1037d0bb8e77378d9debfab4214f25c5416401aeab06221b5e3af82479257
6
+ metadata.gz: 2ec2564e05c43f19bd5897d58cf7bda7392817ce7bcb738e44abec846deccc332893d292565b9855605385462383d7309164ee52729f3060ccd7808cdfbbf28c
7
+ data.tar.gz: 2f00b76e616acf6177ca67558004c89545fb9adb0a616fac958f3eabc9c28db556ac626cb36bc563bc02f12fb0d37dffa6ec2d5d7f09c4fcdd7e3b176fd9a761
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kvn (0.1.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.10)
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
- A [KVN](https://github.com/hopsoft/bighorn#kvn) parser.
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/illegal_character_error"
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
- class << self
8
-
9
- def parse(value)
10
- raise ArgumentError.new("Value is not a valid KVN string!") unless valid?(value)
11
- pairs = standardize(value).split(";")
12
- pairs.each_with_object({}) do |pair, memo|
13
- parts = pair.split(":")
14
- memo[parts.first] = parts.last
15
- end
16
- end
17
-
18
- def valid?(value)
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
@@ -9,14 +9,14 @@ module Kvn
9
9
  :PARTDELIM
10
10
  )
11
11
 
12
- rule :KEY, /(\w|\s)+(?=:)/
13
- rule :VALUE, /(\w|\s)+(?=;)/
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} #{token.value}"
19
- raise Kvn::IllegalCharacterError.new(message)
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
@@ -1,28 +1,56 @@
1
1
  module Kvn
2
2
  class Parser
3
+ attr_reader :value
3
4
 
4
- def parse(value)
5
- parsed = {}
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(standardize_value(value))
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
- begin
10
- key = nil
11
- while output.peek
12
- token = output.next
13
- key = token.value if token.name == :KEY
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 standardize_value(value)
25
- value.to_s.strip
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,4 @@
1
+ module Kvn
2
+ class UnsupportedHashError < StandardError
3
+ end
4
+ 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
@@ -1,3 +1,3 @@
1
1
  module Kvn
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
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.1.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/illegal_character_error.rb
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 (kevin) parser
125
+ summary: KVN key/value notation converter & parser
124
126
  test_files: []
@@ -1,4 +0,0 @@
1
- module Kvn
2
- class IllegalCharacterError < StandardError
3
- end
4
- end