java-properties 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +20 -0
- data/README.md +88 -0
- data/Rakefile +12 -0
- data/java-properties.gemspec +23 -0
- data/lib/java-properties.rb +43 -0
- data/lib/java-properties/encoding.rb +44 -0
- data/lib/java-properties/encoding/separators.rb +51 -0
- data/lib/java-properties/encoding/special_chars.rb +47 -0
- data/lib/java-properties/encoding/unicode.rb +60 -0
- data/lib/java-properties/generating.rb +1 -0
- data/lib/java-properties/generating/generator.rb +34 -0
- data/lib/java-properties/parsing.rb +2 -0
- data/lib/java-properties/parsing/normalizer.rb +74 -0
- data/lib/java-properties/parsing/parser.rb +64 -0
- data/lib/java-properties/properties.rb +6 -0
- data/lib/java-properties/version.rb +7 -0
- data/spec/fixtures/test.properties +33 -0
- data/spec/fixtures/test_normalized.properties +11 -0
- data/spec/fixtures/test_out.properties +11 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 574e7ba19cb13bc15df2a6adbe13d7980568d441
|
4
|
+
data.tar.gz: 91a7367ff442648a2761b29c0d74ea7cc5457f0e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2f7def4045006710af040db297a36b065c24e82d727101cf2a48917362e7a5822757534d957c9a453821a3abd394187f8562c54e608897756b190e33f33a092d
|
7
|
+
data.tar.gz: 1d4808985ac4a0b5c3a5e631b484a1c5d03f9feeca981e01cc296d1c44fcbeed7e4f73dd0892909bbc3f4c65b44f3f7331fd77cdd82cd52b9ce181c2a62608a7
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2014 Jonas Thiel
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# JavaProperties
|
2
|
+
|
3
|
+
[![Build Status](http://img.shields.io/travis/jnbt/java-properties.png)](https://travis-ci.org/jnbt/jnbt/java-properties)
|
4
|
+
[![Code Climate](http://img.shields.io/codeclimate/github/jnbt/java-properties.png)](https://codeclimate.com/github/jnbt/java-properties)
|
5
|
+
[![Coveralls](http://img.shields.io/coveralls/jnbt/java-properties.png)](https://coveralls.io/r/jnbt/java-properties)
|
6
|
+
[![RubyGems](http://img.shields.io/gem/v/java-properties.png)](http://rubygems.org/gems/java-properties)
|
7
|
+
|
8
|
+
A ruby library to read and write [Java properties files](http://en.wikipedia.org/wiki/.properties).
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Install via Rubygems
|
13
|
+
|
14
|
+
gem install java-properties
|
15
|
+
|
16
|
+
... or add to your Gemfile
|
17
|
+
|
18
|
+
gem "java-properties"
|
19
|
+
|
20
|
+
## Loading files
|
21
|
+
|
22
|
+
You can load a valid Java properties file from the file system using a path:
|
23
|
+
|
24
|
+
properties = JavaProperties.load("path/to/my.properties")
|
25
|
+
properties[:foo] # => "bar"
|
26
|
+
|
27
|
+
If have already the content of the properties file at hand than parse the content as:
|
28
|
+
|
29
|
+
properties = JavaProperties.load("foo=bar")
|
30
|
+
properties[:foo] # => "bar"
|
31
|
+
|
32
|
+
## Writing files
|
33
|
+
|
34
|
+
You can write any Hash-like structure as a properties file:
|
35
|
+
|
36
|
+
hash = {:foo => "bar"}
|
37
|
+
JavaProperties.write(hash, "path/to/my.properties")
|
38
|
+
|
39
|
+
Or if you want to omit the file you can receive the content directly:
|
40
|
+
|
41
|
+
hash = {:foo => "bar"}
|
42
|
+
JavaProperties.generate(hash) # => "foo=bar"
|
43
|
+
|
44
|
+
## Encodings and special chars
|
45
|
+
|
46
|
+
As Java properties files normally hold UTF-8 chars in their escaped representation this tool tries to convert them:
|
47
|
+
|
48
|
+
"ה" <=> "\u05d4"
|
49
|
+
|
50
|
+
The tool also escaped every '=', ' ' and ':' in the name part of a property line:
|
51
|
+
|
52
|
+
JavaProperties.generate({"i : like=strange" => "bar"})
|
53
|
+
# => "i\ \:\ like\=strange=bar"
|
54
|
+
|
55
|
+
## Multi line and line breaks
|
56
|
+
|
57
|
+
In Java properties files a string can be multi line but line breaks have to be escaped.
|
58
|
+
|
59
|
+
Assume the following input:
|
60
|
+
|
61
|
+
my=This is a multi \
|
62
|
+
line content with only \n one line break
|
63
|
+
|
64
|
+
The parses would read:
|
65
|
+
|
66
|
+
{:my => "This is a multi line content which only \n one line break"}
|
67
|
+
|
68
|
+
In the opposite direction line breaks will be correctly escaped but the generator will never use multi line values.
|
69
|
+
|
70
|
+
## Contributing
|
71
|
+
|
72
|
+
1. [Fork it!](https://github.com/jnbt/java-properties/fork)
|
73
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
74
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
75
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
76
|
+
5. Create new Pull Request
|
77
|
+
|
78
|
+
## Author
|
79
|
+
|
80
|
+
Jonas Thiel (@jonasthiel)
|
81
|
+
|
82
|
+
## References
|
83
|
+
|
84
|
+
For more information about the properties file format have a look at the [Java Plattform documenation](http://docs.oracle.com/javase/6/docs/api/java/util/Properties.html).
|
85
|
+
|
86
|
+
## License
|
87
|
+
|
88
|
+
This gem is released under the MIT License. See the LICENSE file for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# coding: utf-8
|
3
|
+
lib = File.expand_path('../lib', __FILE__)
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
|
+
require 'java-properties/version'
|
6
|
+
|
7
|
+
Gem::Specification.new do |spec|
|
8
|
+
spec.name = "java-properties"
|
9
|
+
spec.version = JavaProperties::VERSION.dup
|
10
|
+
spec.authors = ["Jonas Thiel"]
|
11
|
+
spec.email = ["jonas@thiel.io"]
|
12
|
+
spec.summary = %q{Loader and writer for *.properties files}
|
13
|
+
spec.description = %q{Tool for loading and writing Java properties files}
|
14
|
+
spec.homepage = "https://github.com/jnbt/java-properties"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = %w(LICENSE README.md Rakefile java-properties.gemspec)
|
18
|
+
spec.files += Dir.glob("lib/**/*.rb")
|
19
|
+
spec.test_files = Dir.glob("spec/**/*.rb")
|
20
|
+
spec.test_files = Dir.glob("spec/fixtures/**/*.properties")
|
21
|
+
|
22
|
+
spec.required_rubygems_version = '>= 1.3.5'
|
23
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'java-properties/version'
|
3
|
+
require 'java-properties/properties'
|
4
|
+
require 'java-properties/encoding'
|
5
|
+
require 'java-properties/parsing'
|
6
|
+
require 'java-properties/generating'
|
7
|
+
|
8
|
+
# A module to read and write Java properties files
|
9
|
+
module JavaProperties
|
10
|
+
|
11
|
+
# Parses the content of a Java properties file
|
12
|
+
# @see Parsing::Parser
|
13
|
+
# @param text [String]
|
14
|
+
# @return [Properties]
|
15
|
+
def self.parse(text)
|
16
|
+
Parsing::Parser.parse(text)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Generates the content of a Java properties file
|
20
|
+
# @see Generating::Generator
|
21
|
+
# @param hash [Hash]
|
22
|
+
# @return [String]
|
23
|
+
def self.generate(hash)
|
24
|
+
Generating::Generator.generate(hash)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Loads and parses a Java properties file
|
28
|
+
# @see Parsing::Parser
|
29
|
+
# @param path [String]
|
30
|
+
# @return [Properties]
|
31
|
+
def self.load(path)
|
32
|
+
parse(File.read(path))
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generates a Java properties file
|
36
|
+
# @see Generating::Generator
|
37
|
+
# @param hash [Hash]
|
38
|
+
# @param path [String]
|
39
|
+
def self.write(hash, path)
|
40
|
+
File.write(path, generate(hash))
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'java-properties/encoding/special_chars'
|
2
|
+
require 'java-properties/encoding/separators'
|
3
|
+
require 'java-properties/encoding/unicode'
|
4
|
+
|
5
|
+
module JavaProperties
|
6
|
+
# Module to encode and decode
|
7
|
+
module Encoding
|
8
|
+
|
9
|
+
# Flag for skipping separators encodings / decoding
|
10
|
+
# @return [Symbol]
|
11
|
+
SKIP_SEPARATORS=:skip_separators
|
12
|
+
|
13
|
+
# Flag for skipping separators encodings / decoding
|
14
|
+
# @return [Symbol]
|
15
|
+
SKIP_UNICODE=:skip_unicode
|
16
|
+
|
17
|
+
# Flag for skipping separators encodings / decoding
|
18
|
+
# @return [Symbol]
|
19
|
+
SKIP_SPECIAL_CHARS=:skip_special_chars
|
20
|
+
|
21
|
+
# Encode a given text in place
|
22
|
+
# @param text [String]
|
23
|
+
# @param flags [Symbol] Optional flags to skip encoding steps
|
24
|
+
# @return [String]
|
25
|
+
def self.encode!(text, *flags)
|
26
|
+
SpecialChars.encode!(text) unless flags.include?(SKIP_SPECIAL_CHARS)
|
27
|
+
Separators.encode!(text) unless flags.include?(SKIP_SEPARATORS)
|
28
|
+
Unicode.encode!(text) unless flags.include?(SKIP_UNICODE)
|
29
|
+
text
|
30
|
+
end
|
31
|
+
|
32
|
+
# Decodes a given text in place
|
33
|
+
# @param text [String]
|
34
|
+
# @param flags [Symbol] Optional flags to skip decoding steps
|
35
|
+
# @return [String]
|
36
|
+
def self.decode!(text, *flags)
|
37
|
+
Unicode.decode!(text) unless flags.include?(SKIP_UNICODE)
|
38
|
+
Separators.decode!(text) unless flags.include?(SKIP_SEPARATORS)
|
39
|
+
SpecialChars.decode!(text) unless flags.include?(SKIP_SPECIAL_CHARS)
|
40
|
+
text
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module JavaProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to escape separators as : or =
|
4
|
+
module Separators
|
5
|
+
|
6
|
+
# Marker for all separators
|
7
|
+
# @return [Regexp]
|
8
|
+
ENCODE_SEPARATOR_MARKER = /[ :=]/
|
9
|
+
|
10
|
+
# Marker for already escaped separators
|
11
|
+
# @return [Regexp]
|
12
|
+
ESCAPING_MARKER = /\\/
|
13
|
+
|
14
|
+
# Char to use for escaping
|
15
|
+
# @return [String]
|
16
|
+
ESCAPE = "\\"
|
17
|
+
|
18
|
+
# Marker for all escaped separators
|
19
|
+
# @return [Regexp]
|
20
|
+
DECODE_SEPARATOR_MARKER = /\\([ :=])/
|
21
|
+
|
22
|
+
# Escapes all not already escaped separators
|
23
|
+
# @param text [text]
|
24
|
+
# @return [String]
|
25
|
+
def self.encode!(text)
|
26
|
+
buffer = StringIO.new
|
27
|
+
last_token = ''
|
28
|
+
text.each_char do |char|
|
29
|
+
if char =~ ENCODE_SEPARATOR_MARKER && last_token !~ ESCAPING_MARKER
|
30
|
+
buffer << ESCAPE
|
31
|
+
end
|
32
|
+
buffer << char
|
33
|
+
last_token = char
|
34
|
+
end
|
35
|
+
text.replace buffer.string
|
36
|
+
text
|
37
|
+
end
|
38
|
+
|
39
|
+
# Removes escapes from escaped separators
|
40
|
+
# @param text [text]
|
41
|
+
# @return [String]
|
42
|
+
def self.decode!(text)
|
43
|
+
text.gsub!(DECODE_SEPARATOR_MARKER) do
|
44
|
+
$1
|
45
|
+
end
|
46
|
+
text
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module JavaProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to escape and unescape special chars
|
4
|
+
module SpecialChars
|
5
|
+
|
6
|
+
# Lookup table for escaping special chars
|
7
|
+
# @return [Hash]
|
8
|
+
ESCAPING = {
|
9
|
+
"\t" => '\\t',
|
10
|
+
"\r" => '\\r',
|
11
|
+
"\n" => '\\n',
|
12
|
+
"\f" => '\\f'
|
13
|
+
}.freeze
|
14
|
+
|
15
|
+
# Lookup table to remove escaping from special chars
|
16
|
+
# @return [Hash]
|
17
|
+
DESCAPING = ESCAPING.invert.freeze
|
18
|
+
|
19
|
+
# Marks a segment which has is an encoding special char
|
20
|
+
# @return [Regexp]
|
21
|
+
DESCAPING_MARKER = /\\./
|
22
|
+
|
23
|
+
# Encodes the content a text by escaping all special chars
|
24
|
+
# @param text [String]
|
25
|
+
# @return [String]
|
26
|
+
def self.encode!(text)
|
27
|
+
buffer = StringIO.new
|
28
|
+
text.each_char do |char|
|
29
|
+
buffer << ESCAPING.fetch(char, char)
|
30
|
+
end
|
31
|
+
text.replace buffer.string
|
32
|
+
text
|
33
|
+
end
|
34
|
+
|
35
|
+
# Decodes the content a text by removing all escaping from special chars
|
36
|
+
# @param text [String]
|
37
|
+
# @return [String]
|
38
|
+
def self.decode!(text)
|
39
|
+
text.gsub!(DESCAPING_MARKER) do |match|
|
40
|
+
DESCAPING.fetch(match, match)
|
41
|
+
end
|
42
|
+
text
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module JavaProperties
|
2
|
+
module Encoding
|
3
|
+
# Module to encode and decode unicode chars
|
4
|
+
module Unicode
|
5
|
+
|
6
|
+
# Marker for encoded unicode chars
|
7
|
+
# @return [Regexp]
|
8
|
+
UNICODE_MARKER = /\\[uU]([0-9a-fA-F]{4,5}|10[0-9a-fA-F]{4})/
|
9
|
+
|
10
|
+
# Escape char for unicode chars
|
11
|
+
# @return [String]
|
12
|
+
UNICODE_ESCAPE = "\\u"
|
13
|
+
|
14
|
+
# Decodes all unicode chars from escape sequences in place
|
15
|
+
# @param text [String]
|
16
|
+
# @return [String]
|
17
|
+
def self.decode!(text)
|
18
|
+
text.gsub!(UNICODE_MARKER) do
|
19
|
+
unicode($1.hex)
|
20
|
+
end
|
21
|
+
text
|
22
|
+
end
|
23
|
+
|
24
|
+
# Decodes all unicode chars into escape sequences in place
|
25
|
+
# @param text [String]
|
26
|
+
# @return [String]
|
27
|
+
def self.encode!(text)
|
28
|
+
buffer = StringIO.new
|
29
|
+
text.each_char do |char|
|
30
|
+
if char.ascii_only?
|
31
|
+
buffer << char
|
32
|
+
else
|
33
|
+
buffer << UNICODE_ESCAPE
|
34
|
+
buffer << hex(char.codepoints.first)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
text.replace buffer.string
|
38
|
+
text
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def self.unicode(code)
|
44
|
+
[code].pack("U")
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.hex(codepoint)
|
48
|
+
hex = codepoint.to_s(16)
|
49
|
+
size = hex.size
|
50
|
+
# padding the hex value for uneven digest
|
51
|
+
if (size % 2) == 1
|
52
|
+
"0#{hex}"
|
53
|
+
else
|
54
|
+
hex
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'java-properties/generating/generator'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module JavaProperties
|
2
|
+
module Generating
|
3
|
+
# This module allows generating the content of a properties file
|
4
|
+
# base on a {Properties} object (or any other hash like structure)
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# Generator.generate({:item => "something ה"}) => "item=something \u05d4"
|
8
|
+
#
|
9
|
+
module Generator
|
10
|
+
# Character used for key-value separation
|
11
|
+
# @return [String]
|
12
|
+
KEY_VALUE_SEPARATOR = '='
|
13
|
+
|
14
|
+
# Generates a properties file content based on a hash
|
15
|
+
# @param properties [Properties] or simple hash
|
16
|
+
# @return [String]
|
17
|
+
def self.generate(properties)
|
18
|
+
lines = []
|
19
|
+
properties.each do |key, value|
|
20
|
+
lines << build_line(key, value)
|
21
|
+
end
|
22
|
+
lines.join("\n")
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def self.build_line(key, value = '')
|
28
|
+
Encoding.encode!(key.to_s.dup) +
|
29
|
+
KEY_VALUE_SEPARATOR +
|
30
|
+
Encoding.encode!(value.to_s.dup, Encoding::SKIP_SEPARATORS)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module JavaProperties
|
2
|
+
module Parsing
|
3
|
+
# Module to normalize the content of a properties file
|
4
|
+
#
|
5
|
+
# @example Normalizes:
|
6
|
+
# # Comment 1
|
7
|
+
# ! Comment 2
|
8
|
+
# item0
|
9
|
+
# item1 = item1
|
10
|
+
# item2 : item2
|
11
|
+
# item3=line 1 \
|
12
|
+
# line 2
|
13
|
+
#
|
14
|
+
# @example Into:
|
15
|
+
#
|
16
|
+
# item0
|
17
|
+
# item1=item1
|
18
|
+
# item2=item2
|
19
|
+
# item3=line 1 line 2
|
20
|
+
#
|
21
|
+
module Normalizer
|
22
|
+
|
23
|
+
# Describes a single normalization rule by replacing content
|
24
|
+
class Rule
|
25
|
+
# Initializes a new rules base on a matching regexp
|
26
|
+
# and a replacement as substitution
|
27
|
+
# @param matcher [Regexp]
|
28
|
+
# @param replacement [String]
|
29
|
+
def initialize(matcher, replacement = '')
|
30
|
+
@matcher = matcher
|
31
|
+
@replacement = replacement
|
32
|
+
end
|
33
|
+
|
34
|
+
# Apply the substitution to the text in place
|
35
|
+
# @param text [string]
|
36
|
+
# @return [String]
|
37
|
+
def apply!(text)
|
38
|
+
text.gsub!(@matcher, @replacement)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Collection of ordered rules
|
43
|
+
RULES = []
|
44
|
+
|
45
|
+
# Removes comments
|
46
|
+
RULES << Rule.new(/^\s*[!\#].*$/)
|
47
|
+
|
48
|
+
# Removes leading whitepsace
|
49
|
+
RULES << Rule.new(/^\s+/)
|
50
|
+
|
51
|
+
# Removes tailing whitepsace
|
52
|
+
RULES << Rule.new(/\s+$/)
|
53
|
+
|
54
|
+
# Strings ending with \ are concatenated
|
55
|
+
RULES << Rule.new(/\\\s*$[\n\r]+/)
|
56
|
+
|
57
|
+
# Remove whitespace around delimiters and replace with =
|
58
|
+
RULES << Rule.new(/^((?:(?:\\[=: \t])|[^=: \t])+)[ \t]*[=: \t][ \t]*/, '\1=')
|
59
|
+
|
60
|
+
RULES.freeze
|
61
|
+
|
62
|
+
# Normalizes the content of a properties file content by applying the RULES
|
63
|
+
# @param text [String]
|
64
|
+
# @return [String]
|
65
|
+
def self.normalize!(text)
|
66
|
+
RULES.each do |rule|
|
67
|
+
rule.apply!(text)
|
68
|
+
end
|
69
|
+
text
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
module JavaProperties
|
3
|
+
module Parsing
|
4
|
+
# This module allows parsing of a properties file content string
|
5
|
+
# into a {Properties} object
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Parser.parse("item=something \u05d4") => {:item => "something ה"}
|
9
|
+
#
|
10
|
+
module Parser
|
11
|
+
|
12
|
+
# Symbol which separates key from value after normalization
|
13
|
+
# @return [String]
|
14
|
+
KEY_VALUE_MARKER = '='
|
15
|
+
|
16
|
+
# Symbol which escapes a KEY_VALUE_MARKER in the key name
|
17
|
+
# @return [String]
|
18
|
+
KEY_ESCAPE = '\\'
|
19
|
+
|
20
|
+
# Marker for a line which only consists of an key w/o value
|
21
|
+
# @return [Regexp]
|
22
|
+
KEY_ONLY_MARKER = /^(\S+)$/
|
23
|
+
|
24
|
+
# Parses a string into a {Properties} object
|
25
|
+
# @param text [String]
|
26
|
+
# @return [Properties]
|
27
|
+
def self.parse(text)
|
28
|
+
properties = Properties.new
|
29
|
+
Normalizer.normalize!(text)
|
30
|
+
text.each_line do |line|
|
31
|
+
key, value = extract_key_and_value(line.chomp)
|
32
|
+
append_to_properties(properties, key, value)
|
33
|
+
end
|
34
|
+
properties
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def self.extract_key_and_value(line)
|
40
|
+
# A line must be handled char by char to handled escaped '=' chars in the key name
|
41
|
+
key = StringIO.new
|
42
|
+
value = StringIO.new
|
43
|
+
key_complete = false
|
44
|
+
last_token = ''
|
45
|
+
line.each_char do |char|
|
46
|
+
if !key_complete && char == KEY_VALUE_MARKER && last_token != KEY_ESCAPE
|
47
|
+
key_complete = true
|
48
|
+
else
|
49
|
+
(key_complete ? value : key) << char
|
50
|
+
end
|
51
|
+
last_token = char
|
52
|
+
end
|
53
|
+
[key.string, value.string]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.append_to_properties(properties, key, value)
|
57
|
+
unless key.nil? && value.nil?
|
58
|
+
properties[Encoding.decode!(key).to_sym] = Encoding.decode!(value, Encoding::SKIP_SEPARATORS)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Comment 1
|
2
|
+
! Comment 2
|
3
|
+
item0
|
4
|
+
item1 = item1
|
5
|
+
item2 : item2
|
6
|
+
item3 item3
|
7
|
+
|
8
|
+
#Comment 3
|
9
|
+
! Comment 4
|
10
|
+
|
11
|
+
it\ em4=item4
|
12
|
+
it\=em5:item5
|
13
|
+
item6 item6
|
14
|
+
|
15
|
+
!Comment 4
|
16
|
+
# Comment 5
|
17
|
+
|
18
|
+
item7 = line 1 \
|
19
|
+
line 2 \
|
20
|
+
line 3
|
21
|
+
|
22
|
+
item8 : line 1 \
|
23
|
+
line 2 \
|
24
|
+
line 3
|
25
|
+
|
26
|
+
item9 line 1 \
|
27
|
+
line 2 \
|
28
|
+
line 3
|
29
|
+
|
30
|
+
item10=test\n\ttest\u0050 \
|
31
|
+
test\n\ttest \
|
32
|
+
test\n\ttest = test
|
33
|
+
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: java-properties
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jonas Thiel
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Tool for loading and writing Java properties files
|
14
|
+
email:
|
15
|
+
- jonas@thiel.io
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENSE
|
21
|
+
- README.md
|
22
|
+
- Rakefile
|
23
|
+
- java-properties.gemspec
|
24
|
+
- lib/java-properties/encoding/separators.rb
|
25
|
+
- lib/java-properties/encoding/special_chars.rb
|
26
|
+
- lib/java-properties/encoding/unicode.rb
|
27
|
+
- lib/java-properties/encoding.rb
|
28
|
+
- lib/java-properties/generating/generator.rb
|
29
|
+
- lib/java-properties/generating.rb
|
30
|
+
- lib/java-properties/parsing/normalizer.rb
|
31
|
+
- lib/java-properties/parsing/parser.rb
|
32
|
+
- lib/java-properties/parsing.rb
|
33
|
+
- lib/java-properties/properties.rb
|
34
|
+
- lib/java-properties/version.rb
|
35
|
+
- lib/java-properties.rb
|
36
|
+
- spec/fixtures/test.properties
|
37
|
+
- spec/fixtures/test_normalized.properties
|
38
|
+
- spec/fixtures/test_out.properties
|
39
|
+
homepage: https://github.com/jnbt/java-properties
|
40
|
+
licenses:
|
41
|
+
- MIT
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.3.5
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.1.11
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Loader and writer for *.properties files
|
63
|
+
test_files:
|
64
|
+
- spec/fixtures/test.properties
|
65
|
+
- spec/fixtures/test_normalized.properties
|
66
|
+
- spec/fixtures/test_out.properties
|
67
|
+
has_rdoc:
|