typesafe_config 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +15 -0
- metadata +3 -40
- data/lib/typesafe/config/config_error.rb +0 -12
- data/lib/typesafe/config/config_factory.rb +0 -9
- data/lib/typesafe/config/config_object.rb +0 -4
- data/lib/typesafe/config/config_parse_options.rb +0 -53
- data/lib/typesafe/config/config_render_options.rb +0 -46
- data/lib/typesafe/config/config_syntax.rb +0 -7
- data/lib/typesafe/config/config_value_type.rb +0 -26
- data/lib/typesafe/config/impl/abstract_config_object.rb +0 -64
- data/lib/typesafe/config/impl/abstract_config_value.rb +0 -130
- data/lib/typesafe/config/impl/config_concatenation.rb +0 -136
- data/lib/typesafe/config/impl/config_float.rb +0 -9
- data/lib/typesafe/config/impl/config_impl.rb +0 -10
- data/lib/typesafe/config/impl/config_impl_util.rb +0 -78
- data/lib/typesafe/config/impl/config_int.rb +0 -31
- data/lib/typesafe/config/impl/config_number.rb +0 -27
- data/lib/typesafe/config/impl/config_string.rb +0 -37
- data/lib/typesafe/config/impl/full_includer.rb +0 -4
- data/lib/typesafe/config/impl/origin_type.rb +0 -9
- data/lib/typesafe/config/impl/parseable.rb +0 -151
- data/lib/typesafe/config/impl/parser.rb +0 -882
- data/lib/typesafe/config/impl/path.rb +0 -59
- data/lib/typesafe/config/impl/path_builder.rb +0 -36
- data/lib/typesafe/config/impl/resolve_status.rb +0 -18
- data/lib/typesafe/config/impl/simple_config.rb +0 -11
- data/lib/typesafe/config/impl/simple_config_list.rb +0 -70
- data/lib/typesafe/config/impl/simple_config_object.rb +0 -178
- data/lib/typesafe/config/impl/simple_config_origin.rb +0 -174
- data/lib/typesafe/config/impl/simple_include_context.rb +0 -7
- data/lib/typesafe/config/impl/simple_includer.rb +0 -19
- data/lib/typesafe/config/impl/token.rb +0 -32
- data/lib/typesafe/config/impl/token_type.rb +0 -42
- data/lib/typesafe/config/impl/tokenizer.rb +0 -370
- data/lib/typesafe/config/impl/tokens.rb +0 -157
- data/lib/typesafe/config/impl/unmergeable.rb +0 -4
- data/lib/typesafe/config/impl.rb +0 -5
- data/lib/typesafe/config.rb +0 -4
- data/lib/typesafe.rb +0 -2
data/README.md
CHANGED
@@ -1,2 +1,17 @@
|
|
1
1
|
ruby-typesafe-config
|
2
2
|
==========
|
3
|
+
|
4
|
+
This is a port of the [Typesafe Config](https://github.com/typesafehub/config) library to Ruby.
|
5
|
+
|
6
|
+
At present, the only features it supports are explicit parsing of config files (.conf/HOCON, .json, .properties) via `ConfigFactory.parse_file`, and rendering a parsed config object back to a String. Testing is minimal and not all data types are supported yet. It also does not yet support `include` or interpolated settings.
|
7
|
+
|
8
|
+
The implementation is intended to be as close to a line-for-line port as the two languages allow, in hopes of making it fairly easy to port over new changesets from the Java code base over time.
|
9
|
+
|
10
|
+
Basic Usage
|
11
|
+
===========
|
12
|
+
|
13
|
+
```rb
|
14
|
+
require 'typesafe/config/config_factory'
|
15
|
+
|
16
|
+
conf = Typesafe::Config::ConfigFactory.parse_file("myapp.conf")
|
17
|
+
conf_map = conf.root.unwrapped
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: typesafe_config
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,50 +11,13 @@ bindir: bin
|
|
11
11
|
cert_chain: []
|
12
12
|
date: 2014-03-14 00:00:00.000000000 Z
|
13
13
|
dependencies: []
|
14
|
-
description: ==
|
15
|
-
|
14
|
+
description: == This gem has been replaced by the {HOCON}[https://rubygems.org/gems/ruby_hocon]
|
15
|
+
gem
|
16
16
|
email: chris@puppetlabs.com
|
17
17
|
executables: []
|
18
18
|
extensions: []
|
19
19
|
extra_rdoc_files: []
|
20
20
|
files:
|
21
|
-
- lib/typesafe/config.rb
|
22
|
-
- lib/typesafe/config/config_object.rb
|
23
|
-
- lib/typesafe/config/config_error.rb
|
24
|
-
- lib/typesafe/config/impl/simple_includer.rb
|
25
|
-
- lib/typesafe/config/impl/config_number.rb
|
26
|
-
- lib/typesafe/config/impl/simple_config.rb
|
27
|
-
- lib/typesafe/config/impl/config_int.rb
|
28
|
-
- lib/typesafe/config/impl/resolve_status.rb
|
29
|
-
- lib/typesafe/config/impl/simple_config_origin.rb
|
30
|
-
- lib/typesafe/config/impl/token.rb
|
31
|
-
- lib/typesafe/config/impl/config_string.rb
|
32
|
-
- lib/typesafe/config/impl/config_float.rb
|
33
|
-
- lib/typesafe/config/impl/full_includer.rb
|
34
|
-
- lib/typesafe/config/impl/parser.rb
|
35
|
-
- lib/typesafe/config/impl/tokens.rb
|
36
|
-
- lib/typesafe/config/impl/tokenizer.rb
|
37
|
-
- lib/typesafe/config/impl/abstract_config_object.rb
|
38
|
-
- lib/typesafe/config/impl/simple_include_context.rb
|
39
|
-
- lib/typesafe/config/impl/token_type.rb
|
40
|
-
- lib/typesafe/config/impl/path_builder.rb
|
41
|
-
- lib/typesafe/config/impl/parseable.rb
|
42
|
-
- lib/typesafe/config/impl/path.rb
|
43
|
-
- lib/typesafe/config/impl/unmergeable.rb
|
44
|
-
- lib/typesafe/config/impl/config_impl_util.rb
|
45
|
-
- lib/typesafe/config/impl/simple_config_object.rb
|
46
|
-
- lib/typesafe/config/impl/simple_config_list.rb
|
47
|
-
- lib/typesafe/config/impl/config_impl.rb
|
48
|
-
- lib/typesafe/config/impl/config_concatenation.rb
|
49
|
-
- lib/typesafe/config/impl/abstract_config_value.rb
|
50
|
-
- lib/typesafe/config/impl/origin_type.rb
|
51
|
-
- lib/typesafe/config/config_factory.rb
|
52
|
-
- lib/typesafe/config/impl.rb
|
53
|
-
- lib/typesafe/config/config_parse_options.rb
|
54
|
-
- lib/typesafe/config/config_render_options.rb
|
55
|
-
- lib/typesafe/config/config_value_type.rb
|
56
|
-
- lib/typesafe/config/config_syntax.rb
|
57
|
-
- lib/typesafe.rb
|
58
21
|
- LICENSE
|
59
22
|
- README.md
|
60
23
|
homepage: https://github.com/cprice404/ruby-typesafe-config
|
@@ -1,9 +0,0 @@
|
|
1
|
-
require 'typesafe/config'
|
2
|
-
require 'typesafe/config/config_parse_options'
|
3
|
-
require 'typesafe/config/impl/parseable'
|
4
|
-
|
5
|
-
class Typesafe::Config::ConfigFactory
|
6
|
-
def self.parse_file(file_path, options = Typesafe::Config::ConfigParseOptions.defaults)
|
7
|
-
Typesafe::Config::Impl::Parseable.new_file(file_path, options).parse.to_config
|
8
|
-
end
|
9
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'typesafe/config'
|
2
|
-
|
3
|
-
class Typesafe::Config::ConfigParseOptions
|
4
|
-
attr_accessor :syntax, :origin_description, :allow_missing, :includer
|
5
|
-
|
6
|
-
def self.defaults
|
7
|
-
self.new(nil, nil, true, nil)
|
8
|
-
end
|
9
|
-
|
10
|
-
def initialize(syntax, origin_description, allow_missing, includer)
|
11
|
-
@syntax = syntax
|
12
|
-
@origin_description = origin_description
|
13
|
-
@allow_missing = allow_missing
|
14
|
-
@includer = includer
|
15
|
-
end
|
16
|
-
|
17
|
-
def allow_missing?
|
18
|
-
@allow_missing
|
19
|
-
end
|
20
|
-
|
21
|
-
def with_syntax(syntax)
|
22
|
-
if @syntax == syntax
|
23
|
-
self
|
24
|
-
else
|
25
|
-
Typesafe::Config::ConfigParseOptions.new(syntax,
|
26
|
-
@origin_description,
|
27
|
-
@allow_missing,
|
28
|
-
@includer)
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def with_includer(includer)
|
33
|
-
if @includer == includer
|
34
|
-
self
|
35
|
-
else
|
36
|
-
Typesafe::Config::ConfigParseOptions.new(@syntax,
|
37
|
-
@origin_description,
|
38
|
-
@allow_missing,
|
39
|
-
includer)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def append_includer(includer)
|
44
|
-
if @includer == includer
|
45
|
-
self
|
46
|
-
elsif @includer
|
47
|
-
with_includer(@includer.with_fallback(includer))
|
48
|
-
else
|
49
|
-
with_includer(includer)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
@@ -1,46 +0,0 @@
|
|
1
|
-
require 'typesafe/config'
|
2
|
-
|
3
|
-
class Typesafe::Config::ConfigRenderOptions
|
4
|
-
def initialize(origin_comments, comments, formatted, json)
|
5
|
-
@origin_comments = origin_comments
|
6
|
-
@comments = comments
|
7
|
-
@formatted = formatted
|
8
|
-
@json = json
|
9
|
-
end
|
10
|
-
|
11
|
-
attr_writer :origin_comments, :comments, :formatted, :json
|
12
|
-
|
13
|
-
def origin_comments?
|
14
|
-
@origin_comments
|
15
|
-
end
|
16
|
-
def comments?
|
17
|
-
@comments
|
18
|
-
end
|
19
|
-
def formatted?
|
20
|
-
@formatted
|
21
|
-
end
|
22
|
-
def json?
|
23
|
-
@json
|
24
|
-
end
|
25
|
-
|
26
|
-
#
|
27
|
-
# Returns the default render options which are verbose (commented and
|
28
|
-
# formatted). See {@link ConfigRenderOptions#concise} for stripped-down
|
29
|
-
# options. This rendering will not be valid JSON since it has comments.
|
30
|
-
#
|
31
|
-
# @return the default render options
|
32
|
-
#
|
33
|
-
def self.defaults
|
34
|
-
Typesafe::Config::ConfigRenderOptions.new(true, true, true, true)
|
35
|
-
end
|
36
|
-
|
37
|
-
#
|
38
|
-
# Returns concise render options (no whitespace or comments). For a
|
39
|
-
# resolved {@link Config}, the concise rendering will be valid JSON.
|
40
|
-
#
|
41
|
-
# @return the concise render options
|
42
|
-
#
|
43
|
-
def self.concise
|
44
|
-
Typesafe::Config::ConfigRenderOptions.new(false, false, false, true)
|
45
|
-
end
|
46
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require 'typesafe/config'
|
2
|
-
|
3
|
-
#
|
4
|
-
# The type of a configuration value (following the <a
|
5
|
-
# href="http://json.org">JSON</a> type schema).
|
6
|
-
#
|
7
|
-
module Typesafe::Config::ConfigValueType
|
8
|
-
OBJECT = 0
|
9
|
-
LIST = 1
|
10
|
-
NUMBER = 2
|
11
|
-
BOOLEAN = 3
|
12
|
-
NULL = 4
|
13
|
-
STRING = 5
|
14
|
-
|
15
|
-
def self.name(config_value_type)
|
16
|
-
case config_value_type
|
17
|
-
when OBJECT then "OBJECT"
|
18
|
-
when LIST then "LIST"
|
19
|
-
when NUMBER then "NUMBER"
|
20
|
-
when BOOLEAN then "BOOLEAN"
|
21
|
-
when NULL then "NULL"
|
22
|
-
when STRING then "STRING"
|
23
|
-
else raise ConfigBugError, "Unrecognized value type '#{config_value_type}'"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,64 +0,0 @@
|
|
1
|
-
require 'typesafe/config/impl'
|
2
|
-
require 'typesafe/config/impl/abstract_config_value'
|
3
|
-
require 'typesafe/config/impl/simple_config'
|
4
|
-
require 'typesafe/config/config_object'
|
5
|
-
require 'typesafe/config/config_value_type'
|
6
|
-
require 'typesafe/config/impl/resolve_status'
|
7
|
-
require 'typesafe/config/impl/simple_config_origin'
|
8
|
-
|
9
|
-
class Typesafe::Config::Impl::AbstractConfigObject < Typesafe::Config::Impl::AbstractConfigValue
|
10
|
-
include Typesafe::Config::ConfigObject
|
11
|
-
|
12
|
-
def initialize(origin)
|
13
|
-
super(origin)
|
14
|
-
@config = Typesafe::Config::Impl::SimpleConfig.new(self)
|
15
|
-
end
|
16
|
-
|
17
|
-
def to_config
|
18
|
-
@config
|
19
|
-
end
|
20
|
-
|
21
|
-
def to_fallback_value
|
22
|
-
self
|
23
|
-
end
|
24
|
-
|
25
|
-
def value_type
|
26
|
-
Typesafe::Config::ConfigValueType::OBJECT
|
27
|
-
end
|
28
|
-
|
29
|
-
def new_copy(origin)
|
30
|
-
new_copy_with_status(resolve_status, origin)
|
31
|
-
end
|
32
|
-
|
33
|
-
def merge_origins(stack)
|
34
|
-
if stack.empty?
|
35
|
-
raise ConfigBugError, "can't merge origins on empty list"
|
36
|
-
end
|
37
|
-
origins = []
|
38
|
-
first_origin = nil
|
39
|
-
num_merged = 0
|
40
|
-
stack.each do |v|
|
41
|
-
if first_origin.nil?
|
42
|
-
first_origin = v.origin
|
43
|
-
end
|
44
|
-
|
45
|
-
if (v.is_a?(Typesafe::Config::Impl::AbstractConfigObject)) &&
|
46
|
-
(v.resolve_status == Typesafe::Config::Impl::ResolveStatus::RESOLVED) &&
|
47
|
-
v.empty?
|
48
|
-
# don't include empty files or the .empty()
|
49
|
-
# config in the description, since they are
|
50
|
-
# likely to be "implementation details"
|
51
|
-
else
|
52
|
-
origins.push(v.origin)
|
53
|
-
num_merged += 1
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
if num_merged == 0
|
58
|
-
# the configs were all empty, so just use the first one
|
59
|
-
origins.push(first_origin)
|
60
|
-
end
|
61
|
-
|
62
|
-
Typesafe::Config::Impl::SimpleConfigOrigin.merge_origins(origins)
|
63
|
-
end
|
64
|
-
end
|
@@ -1,130 +0,0 @@
|
|
1
|
-
require 'typesafe/config/impl'
|
2
|
-
require 'stringio'
|
3
|
-
require 'typesafe/config/config_render_options'
|
4
|
-
require 'typesafe/config/config_object'
|
5
|
-
require 'typesafe/config/impl/resolve_status'
|
6
|
-
require 'typesafe/config/impl/unmergeable'
|
7
|
-
require 'typesafe/config/impl/abstract_config_object'
|
8
|
-
require 'typesafe/config/impl/config_impl_util'
|
9
|
-
|
10
|
-
##
|
11
|
-
## Trying very hard to avoid a parent reference in config values; when you have
|
12
|
-
## a tree like this, the availability of parent() tends to result in a lot of
|
13
|
-
## improperly-factored and non-modular code. Please don't add parent().
|
14
|
-
##
|
15
|
-
class Typesafe::Config::Impl::AbstractConfigValue
|
16
|
-
ConfigImplUtil = Typesafe::Config::Impl::ConfigImplUtil
|
17
|
-
|
18
|
-
def initialize(origin)
|
19
|
-
@origin = origin
|
20
|
-
end
|
21
|
-
|
22
|
-
attr_reader :origin
|
23
|
-
|
24
|
-
def resolve_status
|
25
|
-
Typesafe::Config::Impl::ResolveStatus::RESOLVED
|
26
|
-
end
|
27
|
-
|
28
|
-
# this is virtualized rather than a field because only some subclasses
|
29
|
-
# really need to store the boolean, and they may be able to pack it
|
30
|
-
# with another boolean to save space.
|
31
|
-
def ignores_fallbacks?
|
32
|
-
# if we are not resolved, then somewhere in this value there's
|
33
|
-
# a substitution that may need to look at the fallbacks.
|
34
|
-
resolve_status == Typesafe::Config::Impl::ResolveStatus::RESOLVED
|
35
|
-
end
|
36
|
-
|
37
|
-
# the withFallback() implementation is supposed to avoid calling
|
38
|
-
# mergedWith* if we're ignoring fallbacks.
|
39
|
-
def require_not_ignoring_fallbacks
|
40
|
-
if ignores_fallbacks?
|
41
|
-
raise ConfigBugError, "method should not have been called with ignoresFallbacks=true #{self.class.name}"
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def with_origin(origin)
|
46
|
-
if @origin == origin
|
47
|
-
self
|
48
|
-
else
|
49
|
-
new_copy(origin)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
def with_fallback(mergeable)
|
54
|
-
if ignores_fallbacks?
|
55
|
-
self
|
56
|
-
else
|
57
|
-
other = mergeable.to_fallback_value
|
58
|
-
if other.is_a?(Typesafe::Config::Impl::Unmergeable)
|
59
|
-
merged_with_the_unmergeable(other)
|
60
|
-
elsif other.is_a?(Typesafe::Config::Impl::AbstractConfigObject)
|
61
|
-
merged_with_object(other)
|
62
|
-
else
|
63
|
-
merged_with_non_object(other)
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def to_s
|
69
|
-
sb = StringIO.new
|
70
|
-
render_to_sb(sb, 0, true, nil, Typesafe::Config::ConfigRenderOptions.concise)
|
71
|
-
"#{self.class.name}(#{sb.string})"
|
72
|
-
end
|
73
|
-
|
74
|
-
def indent(sb, indent_size, options)
|
75
|
-
if options.formatted?
|
76
|
-
remaining = indent_size
|
77
|
-
while remaining > 0
|
78
|
-
sb << " "
|
79
|
-
remaining -= 1
|
80
|
-
end
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def render_to_sb(sb, indent, at_root, at_key, options)
|
85
|
-
if !at_key.nil?
|
86
|
-
rendered_key =
|
87
|
-
if options.json?
|
88
|
-
ConfigImplUtil.render_json_string(at_key)
|
89
|
-
else
|
90
|
-
ConfigImplUtil.render_string_unquoted_if_possible(at_key)
|
91
|
-
end
|
92
|
-
|
93
|
-
sb << rendered_key
|
94
|
-
|
95
|
-
if options.json?
|
96
|
-
if options.formatted?
|
97
|
-
sb << " : "
|
98
|
-
else
|
99
|
-
sb << ":"
|
100
|
-
end
|
101
|
-
else
|
102
|
-
# in non-JSON we can omit the colon or equals before an object
|
103
|
-
if self.is_a?(Typesafe::Config::ConfigObject)
|
104
|
-
if options.formatted?
|
105
|
-
sb << ' '
|
106
|
-
end
|
107
|
-
else
|
108
|
-
sb << "="
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
render_value_to_sb(sb, indent, at_root, options)
|
113
|
-
end
|
114
|
-
|
115
|
-
# to be overridden by subclasses
|
116
|
-
def render_value_to_sb(sb, indent, at_root, options)
|
117
|
-
u = unwrapped
|
118
|
-
sb << u.to_s
|
119
|
-
end
|
120
|
-
|
121
|
-
def render(options = Typesafe::Config::ConfigRenderOptions.defaults)
|
122
|
-
sb = StringIO.new
|
123
|
-
render_to_sb(sb, 0, true, nil, options)
|
124
|
-
# We take a substring that ends at sb.pos, because we've been decrementing
|
125
|
-
# sb.pos at various points in the code as a means to remove characters from
|
126
|
-
# the end of the StringIO
|
127
|
-
sb.string[0, sb.pos]
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
@@ -1,136 +0,0 @@
|
|
1
|
-
require 'typesafe/config/impl'
|
2
|
-
require 'typesafe/config/impl/abstract_config_value'
|
3
|
-
require 'typesafe/config/impl/abstract_config_object'
|
4
|
-
require 'typesafe/config/impl/simple_config_list'
|
5
|
-
require 'typesafe/config/config_object'
|
6
|
-
require 'typesafe/config/impl/unmergeable'
|
7
|
-
require 'typesafe/config/impl/simple_config_origin'
|
8
|
-
require 'typesafe/config/impl/config_string'
|
9
|
-
|
10
|
-
class Typesafe::Config::Impl::ConfigConcatenation < Typesafe::Config::Impl::AbstractConfigValue
|
11
|
-
include Typesafe::Config::Impl::Unmergeable
|
12
|
-
|
13
|
-
SimpleConfigList = Typesafe::Config::Impl::SimpleConfigList
|
14
|
-
ConfigObject = Typesafe::Config::ConfigObject
|
15
|
-
Unmergeable = Typesafe::Config::Impl::Unmergeable
|
16
|
-
SimpleConfigOrigin = Typesafe::Config::Impl::SimpleConfigOrigin
|
17
|
-
|
18
|
-
#
|
19
|
-
# Add left and right, or their merger, to builder
|
20
|
-
#
|
21
|
-
def self.join(builder, orig_right)
|
22
|
-
left = builder[builder.size - 1]
|
23
|
-
right = orig_right
|
24
|
-
|
25
|
-
# check for an object which can be converted to a list
|
26
|
-
# (this will be an object with numeric keys, like foo.0, foo.1)
|
27
|
-
if (left.is_a?(ConfigObject)) && (right.is_a?(SimpleConfigList))
|
28
|
-
left = DefaultTransformer.transform(left, ConfigValueType::LIST)
|
29
|
-
elsif (left.is_a?(SimpleConfigList)) && (right.is_a?(ConfigObject))
|
30
|
-
right = DefaultTransformer.transform(right, ConfigValueType::LIST)
|
31
|
-
end
|
32
|
-
|
33
|
-
# Since this depends on the type of two instances, I couldn't think
|
34
|
-
# of much alternative to an instanceof chain. Visitors are sometimes
|
35
|
-
# used for multiple dispatch but seems like overkill.
|
36
|
-
joined = nil
|
37
|
-
if (left.is_a?(ConfigObject)) && (right.is_a?(ConfigObject))
|
38
|
-
joined = right.with_fallback(left)
|
39
|
-
elsif (left.is_a?(SimpleConfigList)) && (right.is_a?(SimpleConfigList))
|
40
|
-
joined = left.concatenate(right)
|
41
|
-
elsif (left.is_a?(Typesafe::Config::Impl::ConfigConcatenation)) ||
|
42
|
-
(right.is_a?(Typesafe::Config::Impl::ConfigConcatenation))
|
43
|
-
raise ConfigBugError, "unflattened ConfigConcatenation"
|
44
|
-
elsif (left.is_a?(Unmergeable)) || (right.is_a?(Unmergeable))
|
45
|
-
# leave joined=null, cannot join
|
46
|
-
else
|
47
|
-
# handle primitive type or primitive type mixed with object or list
|
48
|
-
s1 = left.transform_to_string
|
49
|
-
s2 = right.transform_to_string
|
50
|
-
if s1.nil? || s2.nil?
|
51
|
-
raise ConfigWrongTypeError.new(left.origin,
|
52
|
-
"Cannot concatenate object or list with a non-object-or-list, #{left} " +
|
53
|
-
"and #{right} are not compatible")
|
54
|
-
else
|
55
|
-
joined_origin = SimpleConfigOrigin.merge_origins([left.origin, right.origin])
|
56
|
-
joined = Typesafe::Config::Impl::ConfigString.new(joined_origin, s1 + s2)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
if joined.nil?
|
61
|
-
builder.push(right)
|
62
|
-
else
|
63
|
-
builder.pop
|
64
|
-
builder.push(joined)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def self.consolidate(pieces)
|
69
|
-
if pieces.length < 2
|
70
|
-
pieces
|
71
|
-
else
|
72
|
-
flattened = []
|
73
|
-
pieces.each do |v|
|
74
|
-
if v.is_a?(Typesafe::Config::Impl::ConfigConcatenation)
|
75
|
-
flattened.concat(v.pieces)
|
76
|
-
else
|
77
|
-
flattened.push(v)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
consolidated = []
|
82
|
-
flattened.each do |v|
|
83
|
-
if consolidated.empty?
|
84
|
-
consolidated.push(v)
|
85
|
-
else
|
86
|
-
join(consolidated, v)
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
consolidated
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
def self.concatenate(pieces)
|
95
|
-
consolidated = consolidate(pieces)
|
96
|
-
if consolidated.empty?
|
97
|
-
nil
|
98
|
-
elsif consolidated.length == 1
|
99
|
-
consolidated[0]
|
100
|
-
else
|
101
|
-
merged_origin = SimpleConfigOrigin.merge_origins(consolidated)
|
102
|
-
Typesafe::Config::Impl::ConfigConcatenation.new(merged_origin, consolidated)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
def initialize(origin, pieces)
|
108
|
-
super(origin)
|
109
|
-
@pieces = pieces
|
110
|
-
|
111
|
-
if pieces.size < 2
|
112
|
-
raise ConfigBugError, "Created concatenation with less than 2 items: #{self}"
|
113
|
-
end
|
114
|
-
|
115
|
-
had_unmergeable = false
|
116
|
-
pieces.each do |p|
|
117
|
-
if p.is_a?(Typesafe::Config::Impl::ConfigConcatenation)
|
118
|
-
raise ConfigBugError, "ConfigConcatenation should never be nested: #{self}"
|
119
|
-
end
|
120
|
-
if p.is_a?(Unmergeable)
|
121
|
-
had_unmergeable = true
|
122
|
-
end
|
123
|
-
end
|
124
|
-
|
125
|
-
unless had_unmergeable
|
126
|
-
raise ConfigBugError, "Created concatenation without an unmergeable in it: #{self}"
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
def ignores_fallbacks?
|
131
|
-
# we can never ignore fallbacks because if a child ConfigReference
|
132
|
-
# is self-referential we have to look lower in the merge stack
|
133
|
-
# for its value.
|
134
|
-
false
|
135
|
-
end
|
136
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
require 'typesafe/config/impl'
|
2
|
-
require 'typesafe/config/impl/config_number'
|
3
|
-
|
4
|
-
class Typesafe::Config::Impl::ConfigFloat < Typesafe::Config::Impl::ConfigNumber
|
5
|
-
def initialize(origin, value, original_text)
|
6
|
-
super(origin, original_text)
|
7
|
-
@value = value
|
8
|
-
end
|
9
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'typesafe/config/impl'
|
2
|
-
require 'stringio'
|
3
|
-
|
4
|
-
class Typesafe::Config::Impl::ConfigImplUtil
|
5
|
-
def self.equals_handling_nil?(a, b)
|
6
|
-
# This method probably doesn't make any sense in ruby... not sure
|
7
|
-
if a.nil? && !b.nil?
|
8
|
-
false
|
9
|
-
elsif !a.nil? && b.nil?
|
10
|
-
false
|
11
|
-
# in ruby, the == and .equal? are the opposite of what they are in Java
|
12
|
-
elsif a.equal?(b)
|
13
|
-
true
|
14
|
-
else
|
15
|
-
a == b
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
#
|
20
|
-
# This is public ONLY for use by the "config" package, DO NOT USE this ABI
|
21
|
-
# may change.
|
22
|
-
#
|
23
|
-
def self.render_json_string(s)
|
24
|
-
sb = StringIO.new
|
25
|
-
sb << '"'
|
26
|
-
s.chars.each do |c|
|
27
|
-
case c
|
28
|
-
when '"' then sb << "\\\""
|
29
|
-
when "\\" then sb << "\\\\"
|
30
|
-
when "\n" then sb << "\\n"
|
31
|
-
when "\b" then sb << "\\b"
|
32
|
-
when "\f" then sb << "\\f"
|
33
|
-
when "\r" then sb << "\\r"
|
34
|
-
when "\t" then sb << "\\t"
|
35
|
-
else
|
36
|
-
if c =~ /[[:cntrl:]]/
|
37
|
-
sb << ("\\u%04x" % c)
|
38
|
-
else
|
39
|
-
sb << c
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
sb << '"'
|
44
|
-
sb.string
|
45
|
-
end
|
46
|
-
|
47
|
-
def self.render_string_unquoted_if_possible(s)
|
48
|
-
# this can quote unnecessarily as long as it never fails to quote when
|
49
|
-
# necessary
|
50
|
-
if s.length == 0
|
51
|
-
return render_json_string(s)
|
52
|
-
end
|
53
|
-
|
54
|
-
# if it starts with a hyphen or number, we have to quote
|
55
|
-
# to ensure we end up with a string and not a number
|
56
|
-
first = s.chars.first
|
57
|
-
if (first =~ /[[:digit:]]/) || (first == '-')
|
58
|
-
return render_json_string(s)
|
59
|
-
end
|
60
|
-
|
61
|
-
# only unquote if it's pure alphanumeric
|
62
|
-
s.chars.each do |c|
|
63
|
-
unless (c =~ /[[:alnum:]]/) || (c == '-')
|
64
|
-
return render_json_string(s)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
s
|
69
|
-
end
|
70
|
-
|
71
|
-
def self.whitespace?(c)
|
72
|
-
# this implementation is *not* a port of the java code, because it relied on
|
73
|
-
# the method java.lang.Character#isWhitespace. This is probably
|
74
|
-
# insanely slow (running a regex against every single character in the
|
75
|
-
# file).
|
76
|
-
c =~ /[[:space:]]/
|
77
|
-
end
|
78
|
-
end
|