2015-04-09 20:01:23 +00:00
|
|
|
# encoding: utf-8
|
|
|
|
# copyright: 2015, Dominik Richter
|
|
|
|
# license: All rights reserved
|
|
|
|
|
|
|
|
class SimpleConfig
|
|
|
|
attr_reader :params
|
2015-09-03 18:43:58 +00:00
|
|
|
def initialize(raw_data, opts = {})
|
2015-04-09 20:01:23 +00:00
|
|
|
parse(raw_data, opts)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Parse some data
|
|
|
|
# quotes: quoting characters, which are parsed, so everything inside
|
|
|
|
# it will be part of a string
|
|
|
|
# multiline: allow quoted text to span multiple lines
|
|
|
|
# comment_char: char which identifies comments
|
|
|
|
# standalone_comments: comments must appear alone in a line; if set to true,
|
|
|
|
# no comments can be added to the end of an assignment/statement line
|
2015-09-03 18:43:58 +00:00
|
|
|
def parse(raw_data, opts = {})
|
2015-04-09 20:01:23 +00:00
|
|
|
@params = {}
|
|
|
|
options = default_options.merge(opts)
|
|
|
|
rest = raw_data
|
|
|
|
rest = parse_rest(rest, options) while rest.length > 0
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2015-09-03 18:43:58 +00:00
|
|
|
def parse_values(match, values)
|
2015-07-26 10:30:46 +00:00
|
|
|
start_idx = 2
|
|
|
|
i = 0
|
|
|
|
count = values - 1
|
|
|
|
if (values == 1) then
|
|
|
|
return match[start_idx]
|
|
|
|
else
|
|
|
|
# iterate over expected parameters
|
2015-09-04 07:59:30 +00:00
|
|
|
values = []
|
2015-07-26 10:30:46 +00:00
|
|
|
begin
|
|
|
|
values.push(match[start_idx+i])
|
|
|
|
i +=1;
|
|
|
|
end until i > count
|
|
|
|
return values
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-09-03 18:43:58 +00:00
|
|
|
def parse_rest(rest, opts)
|
2015-04-09 20:01:23 +00:00
|
|
|
idx_nl = rest.index("\n")
|
2015-08-01 07:23:52 +00:00
|
|
|
idx_comment = rest.index(opts[:comment_char])
|
2015-04-09 20:01:23 +00:00
|
|
|
idx_nl = rest.length if idx_nl.nil?
|
|
|
|
idx_comment = idx_nl+1 if idx_comment.nil?
|
|
|
|
# is a comment inside this line
|
|
|
|
if idx_comment < idx_nl
|
|
|
|
if idx_comment == 0
|
|
|
|
line = ''
|
|
|
|
else
|
|
|
|
line = rest[0..(idx_comment-1)]
|
|
|
|
# in case we don't allow comments at the end
|
|
|
|
# of an assignment/statement, ignore it and fall
|
|
|
|
# back to treating this as a regular line
|
|
|
|
if opts[:standalone_comments] && !is_empty_line(line)
|
|
|
|
line = rest[0..(idx_nl-1)]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
# if there is no comment in this line
|
|
|
|
else
|
|
|
|
if idx_nl == 0
|
|
|
|
line = ''
|
|
|
|
else
|
|
|
|
line = rest[0..(idx_nl-1)]
|
|
|
|
end
|
|
|
|
end
|
|
|
|
# now line contains what we are interested in parsing
|
|
|
|
# check if it is an assignment
|
|
|
|
m = opts[:assignment_re].match(line)
|
|
|
|
if !m.nil?
|
2015-04-17 13:36:18 +00:00
|
|
|
if opts[:multiple_values]
|
|
|
|
@params[m[1]] ||= []
|
2015-07-26 10:30:46 +00:00
|
|
|
@params[m[1]].push(parse_values(m, opts[:key_vals]))
|
2015-04-17 13:36:18 +00:00
|
|
|
else
|
2015-07-26 10:30:46 +00:00
|
|
|
@params[m[1]] = parse_values(m, opts[:key_vals])
|
2015-04-17 13:36:18 +00:00
|
|
|
end
|
2015-04-09 20:01:23 +00:00
|
|
|
elsif !is_empty_line(line)
|
2015-04-17 13:36:18 +00:00
|
|
|
if opts[:multiple_values]
|
|
|
|
@params[line.strip] ||= []
|
|
|
|
else
|
|
|
|
@params[line.strip] = ''
|
|
|
|
end
|
2015-04-09 20:01:23 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# return whatever is left
|
|
|
|
return rest[(idx_nl+1)..-1] || ''
|
|
|
|
end
|
|
|
|
|
|
|
|
def is_empty_line l
|
|
|
|
l =~ /^\s*$/
|
|
|
|
end
|
|
|
|
|
|
|
|
def default_options
|
|
|
|
{
|
|
|
|
quotes: '',
|
|
|
|
multiline: false,
|
|
|
|
comment_char: '#',
|
|
|
|
assignment_re: /^\s*([^=]*?)\s*=\s*(.*?)\s*$/,
|
2015-09-03 18:43:58 +00:00
|
|
|
key_vals: 1, # default for key=value, may require for 'key val1 val2 val3'
|
2015-04-17 13:36:18 +00:00
|
|
|
standalone_comments: false,
|
2015-08-01 07:23:02 +00:00
|
|
|
multiple_values: false
|
2015-04-09 20:01:23 +00:00
|
|
|
}
|
|
|
|
end
|
|
|
|
|
2015-09-03 18:43:58 +00:00
|
|
|
end
|