tomlib 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 16903f85ce6caa68598bf97a4e631d2f69312a7019cb0901d668c40fafa24fb6
4
+ data.tar.gz: 8fc0cf9b86b65dc8e3a455ffdbca94151a1ca74b1252e72600edcb872338de06
5
+ SHA512:
6
+ metadata.gz: ddd0190b6aa540128cafa6fdf20bcd16b7a7e0d6c4eaa1cbb65f993708388bedea553f0deda33884b26cb93996dd7ddc4825c7bc36b2223eb21eb43fcae6b2aa
7
+ data.tar.gz: 65e1c88710a7a3f5ca65ca75026e59b64a525d5232c063359c976259ab8e7b10eac503a6aa665d7a2cbe21f7106a8573b9a3faf361b88a121c6a3af46269a744
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## [0.1.0] - 2022-08-02
2
+
3
+ Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Kamil Giszczak
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,136 @@
1
+ # Tomlib
2
+
3
+ Tomlib is a TOML parser and generator for Ruby. It is fast and standards-compliant by relying
4
+ on native [tomlc99](https://github.com/cktan/tomlc99) parser.
5
+
6
+ Tomlib is TOML v1.0 compliant.
7
+
8
+ ## Installation
9
+
10
+ Tomlib supports Ruby (MRI) 2.7+
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ ```ruby
15
+ gem 'tomlib'
16
+ ```
17
+
18
+ And then execute:
19
+
20
+ ```
21
+ $ bundle install
22
+ ```
23
+
24
+ Or install it yourself as:
25
+
26
+ ```
27
+ $ gem install tomlib
28
+ ```
29
+
30
+ ## Usage
31
+
32
+ To parse a TOML document use:
33
+
34
+ ```ruby
35
+ require 'tomlib'
36
+
37
+ Tomlib.parse(<<~TOML)
38
+ firstName = "John"
39
+ lastName = "Doe"
40
+ hobbies = [ "Singing", "Dancing" ]
41
+
42
+ [address]
43
+ firstName = "John"
44
+ lastName = "Doe"
45
+ hobbies = [ "Singing", "Dancing" ]
46
+
47
+ [address]
48
+ city = "London"
49
+ zip = "E1 6AN"
50
+
51
+ [address.street]
52
+ name = "Oxford Street"
53
+ TOML
54
+
55
+ # =>
56
+ #
57
+ # {
58
+ # "firstName" => "John",
59
+ # "lastName" => "Doe",
60
+ # "hobbies" => ["Singing", "Dancing"],
61
+ # "address" => {
62
+ # "city"=>"London",
63
+ # "zip"=>"E1 6AN",
64
+ # "street"=>{ "name"=>"Oxford Street" }
65
+ # }
66
+ # }
67
+ ```
68
+
69
+ To generate a TOML document from Ruby Hash use:
70
+
71
+ ```ruby
72
+ require 'tomlib'
73
+
74
+ Tomlib.dump({
75
+ "firstName" => "John",
76
+ "lastName" => "Doe",
77
+ "hobbies" => ["Singing", "Dancing"],
78
+ "address" => {
79
+ "city"=>"London",
80
+ "zip"=>"E1 6AN",
81
+ "street"=>{ "name"=>"Oxford Street" }
82
+ }
83
+ })
84
+
85
+ # =>
86
+ #
87
+ # firstName = "John"
88
+ # lastName = "Doe"
89
+ # hobbies = [ "Singing", "Dancing" ]
90
+ #
91
+ # [address]
92
+ # city = "London"
93
+ # zip = "E1 6AN"
94
+ #
95
+ # [address.street]
96
+ # name = "Oxford Street"
97
+ ```
98
+
99
+ If you don't need indentation use:
100
+
101
+ ```ruby
102
+ require 'tomlib'
103
+
104
+ Tomlib.dump(hash, indent: false)
105
+
106
+ # =>
107
+ #
108
+ # firstName = "John"
109
+ # lastName = "Doe"
110
+ # hobbies = [ "Singing", "Dancing" ]
111
+ #
112
+ # [address]
113
+ # city = "London"
114
+ # zip = "E1 6AN"
115
+ #
116
+ # [address.street]
117
+ # name = "Oxford Street"
118
+ ```
119
+
120
+ ## Performance
121
+
122
+ `Tomlib` parsing is ~300x faster than `toml-rb` and ~15x faster than `Tomlrb`
123
+ for usual use case (~5KB TOML document size).
124
+
125
+ Generating TOML document is about 1.7x faster than `toml-rb`.
126
+
127
+ For full comparison take a look at
128
+ [benchmarks](https://github.com/kgiszczak/tomlib/tree/master/benchmarks)
129
+
130
+ ## Contributing
131
+
132
+ Bug reports and pull requests are welcome on GitHub at https://github.com/kgiszczak/tomlib.
133
+
134
+ ## License
135
+
136
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mkmf'
4
+
5
+ CONFIG['warnflags'].slice!(/ -Wshorten-64-to-32/)
6
+
7
+ create_makefile('tomlib/tomlib')
@@ -0,0 +1,152 @@
1
+ # frozen_string_literal: false
2
+
3
+ require 'bigdecimal'
4
+ require 'date'
5
+ require 'time'
6
+
7
+ require_relative 'error'
8
+
9
+ module Tomlib
10
+ # TOML generator
11
+ #
12
+ # @api private
13
+ class Dumper
14
+ # Indent characters
15
+ # @api private
16
+ INDENT = ' '.freeze
17
+
18
+ # Representation of Infinity in TOML
19
+ # @api private
20
+ INF_POSITIVE = 'inf'.freeze
21
+
22
+ # Representation of negative Infinity in TOML
23
+ # @api private
24
+ INF_NEGATIVE = '-inf'.freeze
25
+
26
+ # Representation of NaN in TOML
27
+ # @api private
28
+ NAN = 'nan'.freeze
29
+
30
+ # Generate TOML string from ruby Hash
31
+ #
32
+ # @param [Hash] hash
33
+ # @param [String, nil] base_key
34
+ # @param [String] indent
35
+ # @param [true, false] use_indent
36
+ #
37
+ # @return [String]
38
+ #
39
+ # @api private
40
+ def dump(hash, base_key = nil, indent = '', use_indent: true)
41
+ header = ''
42
+ footer = ''
43
+
44
+ hash.each do |key, value|
45
+ toml_key = to_toml_key(key)
46
+
47
+ if value.is_a?(Hash)
48
+ compound_key = to_toml_compound_key(base_key, toml_key)
49
+ next_indent = use_indent && base_key ? indent + INDENT : indent
50
+
51
+ footer << "\n".freeze << next_indent << '['.freeze << compound_key << "]\n".freeze
52
+ footer << dump(value, compound_key, next_indent, use_indent: use_indent)
53
+ elsif value.is_a?(Array) && value.all? { |e| e.is_a?(Hash) }
54
+ compound_key = to_toml_compound_key(base_key, toml_key)
55
+ next_indent = use_indent && base_key ? indent + INDENT : indent
56
+
57
+ value.each do |el|
58
+ footer << "\n".freeze << next_indent << '[['.freeze << compound_key << "]]\n".freeze
59
+ footer << dump(el, compound_key, next_indent, use_indent: use_indent)
60
+ end
61
+ else
62
+ header << indent << toml_key << ' = '.freeze << to_toml_value(value) << "\n".freeze
63
+ end
64
+ end
65
+
66
+ footer.gsub!(/\A\n/, ''.freeze) if header.empty?
67
+ header << footer
68
+ end
69
+
70
+ private
71
+
72
+ # Generate TOML key from Hash key
73
+ #
74
+ # @param [String] key
75
+ # @param [true, false] use_indent
76
+ #
77
+ # @return [String]
78
+ #
79
+ # @api private
80
+ def to_toml_key(key)
81
+ raise DumpError, "'nil' can't be used as a key" if key.nil?
82
+
83
+ key = key.to_s
84
+
85
+ case key_type(key)
86
+ when :quoted
87
+ key.inspect
88
+ when :escape
89
+ key.dump.gsub('\n', '\\\\\n')
90
+ else
91
+ key
92
+ end
93
+ end
94
+
95
+ # Concatenate key with base_key
96
+ #
97
+ # @param [String, nil] base_key
98
+ # @param [String] key
99
+ #
100
+ # @return [String]
101
+ #
102
+ # @api private
103
+ def to_toml_compound_key(base, key)
104
+ return key unless base
105
+
106
+ '' << base << '.'.freeze << key
107
+ end
108
+
109
+ # Generate TOML value from Ruby object
110
+ #
111
+ # @param [Object] value
112
+ #
113
+ # @return [String]
114
+ #
115
+ # @api private
116
+ def to_toml_value(value)
117
+ case value
118
+ when String
119
+ value.inspect
120
+ when Float, BigDecimal
121
+ to_toml_float(value)
122
+ when Time, DateTime
123
+ value.iso8601(3)
124
+ when Date
125
+ value.iso8601
126
+ when Hash
127
+ "{ #{value.map { |k, v| "#{to_toml_key(k)} = #{to_toml_value(v)}" }.join(', ')} }"
128
+ when Array
129
+ "[ #{value.map { |e| to_toml_value(e) }.join(', ')} ]"
130
+ when nil
131
+ '""'.freeze
132
+ else
133
+ value.to_s
134
+ end
135
+ end
136
+
137
+ # Generate TOML float value from Ruby Float or BigDecimal
138
+ #
139
+ # @param [Float, BigDecimal] value
140
+ #
141
+ # @return [String]
142
+ #
143
+ # @api private
144
+ def to_toml_float(value)
145
+ return INF_POSITIVE if value.infinite? && value.positive?
146
+ return INF_NEGATIVE if value.infinite? && value.negative?
147
+ return NAN if value.nan?
148
+
149
+ value.to_s
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: false
2
+
3
+ module Tomlib
4
+ # Error during TOML document generation
5
+ #
6
+ # @api private
7
+ class DumpError < StandardError
8
+ end
9
+ end
Binary file
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tomlib
4
+ # @api private
5
+ VERSION = '0.1.0'
6
+ end
data/lib/tomlib.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tomlib/dumper'
4
+ require_relative 'tomlib/tomlib'
5
+ require_relative 'tomlib/version'
6
+
7
+ # Main library namespace
8
+ #
9
+ # @example parsing TOML data into Ruby Hash
10
+ #
11
+ # puts Tomlib.load(<<~TOML)
12
+ # firstName = "John"
13
+ # lastName = "Doe"
14
+ # TOML
15
+ #
16
+ # # => { 'firstName' => 'John', 'lastName' => 'Doe' }
17
+ #
18
+ # @example generating TOML from Ruby Hash
19
+ #
20
+ # puts Tomlib.dump({ 'firstName' => 'John', 'lastName' => 'Doe' })
21
+ #
22
+ # # =>
23
+ # firstName = "John"
24
+ # lastName = "Doe"
25
+ #
26
+ # @api public
27
+ module Tomlib
28
+ # Dump Ruby Hash into TOML format
29
+ #
30
+ # @param [Hash] hash
31
+ # @param [true, false] indent (default: true)
32
+ #
33
+ # @return [String]
34
+ #
35
+ # @example
36
+ # puts Tomlib.dump({ 'firstName' => 'John', 'lastName' => 'Doe' })
37
+ # # =>
38
+ # firstName = "John"
39
+ # lastName = "Doe"
40
+ #
41
+ # @api public
42
+ def self.dump(hash, indent: true)
43
+ Dumper.new.dump(hash, use_indent: indent)
44
+ end
45
+ end
data/tomlib.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/tomlib/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'tomlib'
7
+ spec.version = Tomlib::VERSION
8
+ spec.authors = ['Kamil Giszczak']
9
+ spec.email = ['beerkg@gmail.com']
10
+
11
+ spec.summary = 'Fast TOML parser and generator with native extension.'
12
+ spec.description = 'Fast TOML parser and generator with native extension.'
13
+ spec.homepage = 'https://github.com/kgiszczak/tomlib'
14
+ spec.license = 'MIT'
15
+
16
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
17
+
18
+ spec.metadata['homepage_uri'] = 'https://github.com/kgiszczak/tomlib'
19
+ spec.metadata['source_code_uri'] = 'https://github.com/kgiszczak/tomlib'
20
+ spec.metadata['changelog_uri'] = 'https://github.com/kgiszczak/tomlib/blob/master/CHANGELOG.md'
21
+ spec.metadata['bug_tracker_uri'] = 'https://github.com/kgiszczak/tomlib/issues'
22
+
23
+ spec.files = Dir['CHANGELOG.md', 'LICENSE.txt', 'README.md', 'tomlib.gemspec', 'lib/**/*']
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.extensions = ['ext/tomlib/extconf.rb']
27
+
28
+ spec.required_ruby_version = '>= 2.7.0'
29
+ end
metadata ADDED
@@ -0,0 +1,59 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tomlib
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kamil Giszczak
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-08-02 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Fast TOML parser and generator with native extension.
14
+ email:
15
+ - beerkg@gmail.com
16
+ executables: []
17
+ extensions:
18
+ - ext/tomlib/extconf.rb
19
+ extra_rdoc_files: []
20
+ files:
21
+ - CHANGELOG.md
22
+ - LICENSE.txt
23
+ - README.md
24
+ - ext/tomlib/extconf.rb
25
+ - lib/tomlib.rb
26
+ - lib/tomlib/dumper.rb
27
+ - lib/tomlib/error.rb
28
+ - lib/tomlib/tomlib.bundle
29
+ - lib/tomlib/version.rb
30
+ - tomlib.gemspec
31
+ homepage: https://github.com/kgiszczak/tomlib
32
+ licenses:
33
+ - MIT
34
+ metadata:
35
+ allowed_push_host: https://rubygems.org
36
+ homepage_uri: https://github.com/kgiszczak/tomlib
37
+ source_code_uri: https://github.com/kgiszczak/tomlib
38
+ changelog_uri: https://github.com/kgiszczak/tomlib/blob/master/CHANGELOG.md
39
+ bug_tracker_uri: https://github.com/kgiszczak/tomlib/issues
40
+ post_install_message:
41
+ rdoc_options: []
42
+ require_paths:
43
+ - lib
44
+ required_ruby_version: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ version: 2.7.0
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ requirements: []
55
+ rubygems_version: 3.3.7
56
+ signing_key:
57
+ specification_version: 4
58
+ summary: Fast TOML parser and generator with native extension.
59
+ test_files: []