1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
|
#
# Author:: BJ Dierkes <derks@datafolklabs.com>
# Copyright:: Copyright (c) 2006,2016 Data Folk Labs, LLC
# License:: MIT
# URL:: https://github.com/datafolklabs/ruby-parseconfig
#
# This class was written to simplify the parsing of configuration
# files in the format of "param = value". Please review the
# demo files included with this package.
#
# For further information please refer to the './doc' directory
# as well as the ChangeLog and README files included.
#
# Note: A group is a set of parameters defined for a subpart of a
# config file
class ParseConfig
Version = '1.0.8'
attr_accessor :config_file, :params, :groups
# Initialize the class with the path to the 'config_file'
# The class objects are dynamically generated by the
# name of the 'param' in the config file. Therefore, if
# the config file is 'param = value' then the itializer
# will eval "@param = value"
#
def initialize(config_file=nil, separator='=', comments=['#', ';'])
@config_file = config_file
@params = {}
@groups = []
@splitRegex = '\s*' + separator + '\s*'
@comments = comments
if(self.config_file)
self.validate_config()
self.import_config()
end
end
# Validate the config file, and contents
def validate_config()
unless File.readable?(self.config_file)
raise Errno::EACCES, "#{self.config_file} is not readable"
end
# FIX ME: need to validate contents/structure?
end
# Import data from the config to our config object.
def import_config()
# The config is top down.. anything after a [group] gets added as part
# of that group until a new [group] is found.
group = nil
open(self.config_file) { |f| f.each_with_index do |line, i|
line.strip!
# force_encoding not available in all versions of ruby
begin
if i.eql? 0 and line.include?("\xef\xbb\xbf".force_encoding("UTF-8"))
line.delete!("\xef\xbb\xbf".force_encoding("UTF-8"))
end
rescue NoMethodError
end
is_comment = false
@comments.each do |comment|
if (/^#{comment}/.match(line))
is_comment = true
break
end
end
unless is_comment
if(/#{@splitRegex}/.match(line))
param, value = line.split(/#{@splitRegex}/, 2)
var_name = "#{param}".chomp.strip
value = value.chomp.strip
new_value = ''
if (value)
if value =~ /^['"](.*)['"]$/
new_value = $1
else
new_value = value
end
else
new_value = ''
end
if group
self.add_to_group(group, var_name, new_value)
else
self.add(var_name, new_value)
end
elsif(/^\[(.+)\]$/.match(line).to_a != [])
group = /^\[(.+)\]$/.match(line).to_a[1]
self.add(group, {})
end
end
end }
end
# This method will provide the value held by the object "@param"
# where "@param" is actually the name of the param in the config
# file.
#
# DEPRECATED - will be removed in future versions
#
def get_value(param)
puts "ParseConfig Deprecation Warning: get_value() is deprecated. Use " + \
"config['param'] or config['group']['param'] instead."
return self.params[param]
end
# This method is a shortcut to accessing the @params variable
def [](param)
return self.params[param]
end
# This method returns all parameters/groups defined in a config file.
def get_params()
return self.params.keys
end
# List available sub-groups of the config.
def get_groups()
return self.groups
end
# This method adds an element to the config object (not the config file)
# By adding a Hash, you create a new group
def add(param_name, value, override = false)
if value.class == Hash
if self.params.has_key?(param_name)
if self.params[param_name].class == Hash
if override
self.params[param_name] = value
else
self.params[param_name].merge!(value)
end
elsif self.params.has_key?(param_name)
if self.params[param_name].class != value.class
raise ArgumentError, "#{param_name} already exists, and is of different type!"
end
end
else
self.params[param_name] = value
end
if ! self.groups.include?(param_name)
self.groups.push(param_name)
end
else
self.params[param_name] = value
end
end
# Add parameters to a group. Note that parameters with the same name
# could be placed in different groups
def add_to_group(group, param_name, value)
if ! self.groups.include?(group)
self.add(group, {})
end
self.params[group][param_name] = value
end
# Writes out the config file to output_stream
def write(output_stream=STDOUT, quoted=true)
self.params.each do |name,value|
if value.class.to_s != 'Hash'
if quoted == true
output_stream.puts "#{name} = \"#{value}\""
else
output_stream.puts "#{name} = #{value}"
end
end
end
output_stream.puts "\n"
self.groups.each do |group|
output_stream.puts "[#{group}]"
self.params[group].each do |param, value|
if quoted == true
output_stream.puts "#{param} = \"#{value}\""
else
output_stream.puts "#{param} = #{value}"
end
end
output_stream.puts "\n"
end
end
# Public: Compare this ParseConfig to some other ParseConfig. For two config to
# be equivalent, they must have the same sections with the same parameters
#
# other - The other ParseConfig.
#
# Returns true if ParseConfig are equivalent and false if they differ.
def eql?(other)
self.params == other.params && self.groups == other.groups
end
alias == eql?
end
|