unixconfigstyle 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,418 @@
1
+ ###############################################################################
2
+ ## Author: Erwan SEITE
3
+ ## Aim: Read or Write config files written in Unix Style
4
+ ## Licence : GPL v2
5
+ ## Source : https://github.com/wanix/ruby-UnixConfigStyle
6
+ ## The section name "[-UnixConfigStyle-]" is reserved for the global one
7
+ ###############################################################################
8
+ class UnixConfigStyle
9
+
10
+ Version = '1.0'
11
+
12
+ @@rootsection="[-UnixConfigStyle-]"
13
+
14
+ @@regexpStruct={}
15
+ #Empty line definition
16
+ @@regexpStruct[:emptyline] = /^\s*$/
17
+ #Comment line definition
18
+ @@regexpStruct[:commentline] = /^\s*[#;]/
19
+ #Section Line definition
20
+ @@regexpStruct[:sectionline] = /^\s*\[(.+?)\]\s*([#;].*)?$/
21
+ #Parameter line definition
22
+ @@regexpStruct[:paramline] = /^\s*([\d\w\-]+)\s*=.*$/
23
+ @@regexpStruct[:paramlinequote] = /^\s*([\d\w\-]+)\s*=\s*('.*')\s*([#;].*)?$/
24
+ @@regexpStruct[:paramline2quote] = /^\s*([\d\w\-]+)\s*=\s*(".*")\s*([#;].*)?$/
25
+ @@regexpStruct[:paramlinenormal] = /^\s*([\d\w\-]+)\s*=\s*(.*?)\s*([#;].*)?$/
26
+
27
+ #(private) Initialise the class and read the file
28
+ #Parameters:
29
+ # config_file: String (path to a readable unix config file) (optionnal)
30
+ def initialize(config_file=nil)
31
+ @sections = {}
32
+
33
+ if(config_file)
34
+ push_unix_config_file(config_file)
35
+ end
36
+ end #initialize
37
+ private :initialize
38
+
39
+ #(private) Validate a file is readable
40
+ #Parameters:
41
+ # fileToRead: String (path to a readable file)
42
+ def validate(fileToRead)
43
+ unless File.readable?(fileToRead)
44
+ raise Errno::EACCES, "Can't read #{fileToRead}"
45
+ end
46
+ end #validate
47
+ private :validate
48
+
49
+ #Read a config file and add its properties to the end of the object ones
50
+ #Parameters:
51
+ # config_file: String (path to a readable unix config file)
52
+ def push_unix_config_file(config_file)
53
+ add_unix_config_file(config_file,"push")
54
+ end #push_unix_config_file
55
+
56
+ #Read a config file and add its properties to the start of the object ones
57
+ #Parameters:
58
+ # config_file: String (path to a readable unix config file)
59
+ def insert_unix_config_file(config_file)
60
+ add_unix_config_file(config_file,"insert")
61
+ end #insert_unix_config_file
62
+
63
+ #(private) read a config file and add its properties to the current object
64
+ #Parameters:
65
+ # config_file: String (path to a readable unix config file)
66
+ # operation: String [push|insert]
67
+ def add_unix_config_file(config_file, operation="push")
68
+ if operation != "push" and operation != "insert"
69
+ raise ArgumentError, "operation #{operation} not allowed", caller
70
+ end
71
+ validate(config_file)
72
+
73
+ file = File.open(config_file, 'r')
74
+
75
+ @sections[@@rootsection]={} unless @sections.key?(@@rootsection)
76
+ currentSection=@@rootsection
77
+
78
+ while !file.eof?
79
+ line = file.readline
80
+ #We ignore the empty lines
81
+ next if @@regexpStruct[:emptyline].match(line)
82
+ #We ignore the comment lines
83
+ next if @@regexpStruct[:commentline].match(line)
84
+ #Change the current section if a new line section is matched
85
+ sectionmatch = @@regexpStruct[:sectionline].match(line)
86
+ if sectionmatch
87
+ currentSection=sectionmatch[1]
88
+ #If this section is seen for the first time, initialise the hash
89
+ @sections[currentSection]={} unless @sections.key?(currentSection)
90
+ next
91
+ end
92
+ #Now we have to recognize the line or there is an error in the file ... or a bug here :)
93
+ paramlinematch = @@regexpStruct[:paramline].match(line)
94
+ if paramlinematch
95
+ #First time this param is seen ?
96
+ @sections[currentSection][paramlinematch[1]]=[] unless @sections[currentSection].key?(paramlinematch[1])
97
+ parammatch = @@regexpStruct[:paramlinequote].match(line)
98
+ if parammatch
99
+ if operation == "push"
100
+ @sections[currentSection][paramlinematch[1]].push(parammatch[2])
101
+ elsif operation == "insert"
102
+ @sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
103
+ end
104
+ next
105
+ end
106
+ parammatch = @@regexpStruct[:paramline2quote].match(line)
107
+ if parammatch
108
+ if operation == "push"
109
+ @sections[currentSection][paramlinematch[1]].push(parammatch[2])
110
+ elsif operation == "insert"
111
+ @sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
112
+ end
113
+ next
114
+ end
115
+ parammatch = @@regexpStruct[:paramlinenormal].match(line)
116
+ if parammatch
117
+ if operation == "push"
118
+ @sections[currentSection][paramlinematch[1]].push(parammatch[2])
119
+ elsif operation == "insert"
120
+ @sections[currentSection][paramlinematch[1]].insert(0,parammatch[2])
121
+ end
122
+ next
123
+ end
124
+ else
125
+ warn("[warning] unrecognized line "+file.lineno.to_s+" in "+@unix_config_file+" : "+line)
126
+ end
127
+ end
128
+ file.close()
129
+ end
130
+ private :add_unix_config_file
131
+
132
+ #Write the object in a file
133
+ #Parameters:
134
+ # fileToWrite : String, path to a file
135
+ # comment: String (optionnal)
136
+ def write (fileToWrite, comment=nil)
137
+ File.open(fileToWrite,'w') do |file|
138
+ self.print(comment, file)
139
+ end
140
+ end #def write
141
+
142
+ #Print the object in a unix config style into an IO obj
143
+ #Parameters:
144
+ # comment: String
145
+ # io_obj : IO (default stdout)
146
+ def print (comment=nil, io_obj=$stdout)
147
+ raise ArgumentError, 'the argument "comment" must be a String' unless (comment.is_a? String or comment == nil)
148
+ raise ArgumentError, 'the argument "io_obj" must be an IO class or an IO inherited class' unless io_obj.is_a? IO
149
+ if comment
150
+ io_obj.puts "##{comment}"
151
+ end
152
+ if @sections.key?(@@rootsection)
153
+ @sections[@@rootsection].keys.each do |param_key|
154
+ @sections[@@rootsection][param_key].each do |param_value|
155
+ io_obj.puts "#{param_key}=#{param_value}"
156
+ end
157
+ end
158
+ end
159
+ @sections.keys.each do |section_key|
160
+ if section_key == @@rootsection
161
+ next
162
+ end
163
+ io_obj.puts "[#{section_key}]"
164
+ @sections[section_key].keys.each do |param_key|
165
+ @sections[section_key][param_key].each do |param_value|
166
+ io_obj.puts "#{param_key}=#{param_value}"
167
+ end
168
+ end
169
+ end
170
+ end #def print
171
+
172
+ #Get all avalaibles sections (all but root one)
173
+ #return an array
174
+ def getSections ()
175
+ allsections = @sections.keys
176
+ if allsections
177
+ allsections.delete(@@rootsection)
178
+ end
179
+ return allsections
180
+ end #def getSections
181
+
182
+ #Get all avalaibles keys for this section
183
+ #return an array (or nil if no keys found)
184
+ #Parameters:
185
+ # section: String (optionnal)
186
+ def getKeys (section=@@rootsection)
187
+ if @sections.key?(section)
188
+ return @sections[section].keys
189
+ end
190
+ return nil
191
+ end #def getKeys
192
+
193
+ #Get all differents keys in the object
194
+ # if section is defined, return a merged array for keys in the section and keys in root section
195
+ # if section is not defined, return a a merged array for all keys in the object
196
+ #return an array (or nil if no keys found)
197
+ def getAllKeys (section=nil)
198
+ allKeys=[]
199
+ #Get keys from root section
200
+ allKeys.concat(@sections[@@rootsection].keys) if @sections.key?(@@rootsection)
201
+ if ( section == nil )
202
+ #Get keys from the others sections if exists and are not empty
203
+ if self.haveSections?()
204
+ self.getSections().each do |subsection|
205
+ allKeys.concat(@sections[subsection].keys) if @sections.key?(subsection)
206
+ end
207
+ end
208
+ else
209
+ #get keys for this specific section
210
+ allKeys.concat(@sections[section].keys) if self.sectionExists?(section)
211
+ end
212
+ return nil if allKeys.empty?()
213
+ allKeys.uniq!
214
+ return allKeys
215
+ end #getAllKeys
216
+
217
+ #Add values for a key
218
+ #Parameters:
219
+ # values: Array or String
220
+ # key: String
221
+ # section: String (optionnal)
222
+ def addValues (values, key, section=@@rootsection)
223
+ @sections[section]={} unless @sections.key?(section)
224
+ @sections[section][key]=[] unless @sections[section].key?(key)
225
+ if values.is_a? Array
226
+ return true if @sections[section][key].concat(values)
227
+ else
228
+ #String
229
+ return true if @sections[section][key].push(values)
230
+ end
231
+ return false
232
+ end #def addValues
233
+
234
+ #Insert values for a key
235
+ #Parameters:
236
+ # values: Array or String
237
+ # key: String
238
+ # section: String (optionnal)
239
+ def insertValues (values, key, section=@@rootsection)
240
+ @sections[section]={} unless @sections.key?(section)
241
+ @sections[section][key]=[] unless @sections[section].key?(key)
242
+ if @sections[section][key].insert(0,values)
243
+ return true
244
+ else
245
+ return false
246
+ end
247
+ end #insertValues
248
+
249
+ #Get all values for a key (in a section if given, else in root one)
250
+ #Parameters:
251
+ # key: String
252
+ # section: String (optionnal)
253
+ # globalSearch: boolean, if true, insert the results from the root section (default false)
254
+ def getValues (key, section=@@rootsection, globalSearch=false)
255
+ resultArray=[]
256
+ if (globalSearch == true and section != @@rootsection)
257
+ #We put first the result form the root section
258
+ resultArray.concat(@sections[@@rootsection][key]) if ( @sections.key?(@@rootsection) and @sections[@@rootsection].key?(key) )
259
+ end
260
+ resultArray.concat(@sections[section][key]) if ( @sections.key?(section) and @sections[section].key?(key) )
261
+ return nil if resultArray.empty?()
262
+ return resultArray
263
+ end #getValues
264
+
265
+ #Get the first value for a key (config first win)
266
+ #Parameters:
267
+ # key: String
268
+ # section: String (optionnal)
269
+ def getFirstValue (key, section=@@rootsection)
270
+ if @sections.key?(section)
271
+ if @sections[section].key?(key)
272
+ return @sections[section][key].first
273
+ end
274
+ end
275
+ return nil
276
+ end #getFirstValue
277
+
278
+ #Get the last value for a key (config last win)
279
+ #Parameters:
280
+ # key: String
281
+ # section: String (optionnal)
282
+ def getLastValue (key, section=@@rootsection)
283
+ if @sections.key?(section)
284
+ if @sections[section].key?(key)
285
+ return @sections[section][key].last
286
+ end
287
+ end
288
+ return nil
289
+ end #getLastValue
290
+
291
+ #Get the value with the given index for a key
292
+ #Parameters:
293
+ # key: String
294
+ # index :Integer (default 0)
295
+ # section: String (optionnal)
296
+ def getValue (key, index=0, section=@@rootsection)
297
+ if @sections.key?(section)
298
+ if @sections[section].key?(key)
299
+ return @sections[section][key][index]
300
+ end
301
+ end
302
+ return nil
303
+ end #getValue
304
+
305
+ #Replace the first value by the given one
306
+ #Parameters:
307
+ # newvalue : string
308
+ # key: String
309
+ # section: String (optionnal)
310
+ def replaceFirstValue (newvalue, key, section=@@rootsection)
311
+ if @sections.key?(section)
312
+ if @sections[section].key?(key)
313
+ @sections[section][key].first.replace(newvalue)
314
+ end
315
+ end
316
+ return nil
317
+ end #replaceFirstValue
318
+
319
+ #Replace the last value by the given one
320
+ #Parameters:
321
+ # newvalue : string
322
+ # key: String
323
+ # section: String (optionnal)
324
+ def replaceLastValue (newvalue, key, section=@@rootsection)
325
+ if @sections.key?(section)
326
+ if @sections[section].key?(key)
327
+ @sections[section][key].last.replace(newvalue)
328
+ end
329
+ end
330
+ return nil
331
+ end #replaceLastValue
332
+
333
+ #Replace the value by the given one
334
+ #Parameters:
335
+ # newvalue : string
336
+ # key: String
337
+ # index :Integer (default 0)
338
+ # section: String (optionnal)
339
+ def replaceValue (newvalue, key, index=0, section=@@rootsection)
340
+ if @sections.key?(section)
341
+ if @sections[section].key?(key)
342
+ @sections[section][key][index].replace(newvalue)
343
+ end
344
+ end
345
+ return nil
346
+ end #replaceValue
347
+
348
+ #Replace all the value array by the given one
349
+ #Parameters:
350
+ # newvalues : Array
351
+ # key: String
352
+ # section: String (optionnal)
353
+ def replaceValues (newvalues, key, section=@@rootsection)
354
+ if @sections.key?(section)
355
+ if @sections[section].key?(key)
356
+ @sections[section][key].replace(newvalues)
357
+ end
358
+ end
359
+ return nil
360
+ end #replaceValues
361
+
362
+ #Return true if the key exists for the section "section"
363
+ #if global search is set to true, return true if the key exists in the root section and not in the section itself
364
+ #Parameters:
365
+ # key : string, the key to search
366
+ # section: string, the section where to search the key (default the root one)
367
+ # globalSearch: boolean, if the section is not the root one, return true if the key is found in the root section even if it not exists in the given section
368
+ def keyExists?(key, section, globalSearch=false)
369
+ return false if @sections.empty?
370
+ if ( section == nil)
371
+ return false unless @sections.has_key?(@@rootsection)
372
+ return @sections[@@rootsection].has_key?(key)
373
+ else
374
+ return false unless @sections.has_key?(section)
375
+ if (globalSearch == true and @sections.has_key?(@@rootsection))
376
+ return ( @sections[section].has_key?(key) || @sections[@@rootsection].has_key?(key) )
377
+ else
378
+ return @sections[section].has_key?(key)
379
+ end
380
+ end
381
+ end
382
+
383
+ #Return true if the specific section is found
384
+ def sectionExists? (section)
385
+ return false if section == nil
386
+ return false if @sections.empty?
387
+ return @sections.has_key?(section)
388
+ end
389
+
390
+ #Return true if at list one key is present
391
+ def haveKeys? (section=@@rootsection)
392
+ return false if @sections.empty?
393
+ return true unless @sections[section].empty?
394
+ return false
395
+ end #haveKeys?
396
+
397
+ #Return true if at list one section is present
398
+ def haveSections? ()
399
+ return true unless self.getSections().empty?
400
+ return false
401
+ end #haveSections?
402
+
403
+ #Return false if at list one key is found, whatever its section, global or not
404
+ def isEmpty?()
405
+ return false if self.haveKeys?
406
+ if self.haveSections?
407
+ self.getSections().each do |section|
408
+ return false if self.haveKeys?(section)
409
+ end
410
+ end
411
+ return true
412
+ end #isEmpty?()
413
+
414
+ #Return the root section name (for loops with sections?)
415
+ def getRootSectionName
416
+ return @@rootsection
417
+ end
418
+ end
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env rspec
2
+ ###############################################################################
3
+ ## Author: Erwan SEITE
4
+ ## Aim: Read or Write config files written in Unix Style
5
+ ## Licence : GPL v2
6
+ ## Source : https://github.com/wanix/ruby-UnixConfigStyle
7
+ ## Help : http://betterspecs.org/fr/
8
+ ###############################################################################
9
+ require 'rspec'
10
+ $: << File.join(File.dirname(__FILE__), "..", "lib")
11
+ require 'unixconfigstyle.rb'
12
+
13
+ describe 'ruby-UnixConfigStyle' do
14
+
15
+ unix_config_file1=File.dirname(__FILE__)+"/configfiles/conf_unix1.cfg"
16
+ context "The file "+unix_config_file1+" should be parsed" do
17
+ it "Should give you an array of sections (Section1, Section2, newsection)" do
18
+ objUnixConfFile1 = UnixConfigStyle.new(unix_config_file1)
19
+ objUnixConfFile1.getSections().should eq(["Section1","Section2","newsection"])
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,49 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unixconfigstyle
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Erwan SEITE
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-05-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: ! " This library manage config file written in Unix style\n Can manage
15
+ multi-values, concat multiple files, use it as a config object (see easyfpm)\n"
16
+ email: wanix.fr@gmail.com
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - lib/unixconfigstyle.rb
22
+ - tests/test-unixconfigstyle.rb
23
+ homepage: https://github.com/wanix/ruby-UnixConfigStyle
24
+ licenses:
25
+ - GPLv2
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ none: false
32
+ requirements:
33
+ - - ! '>='
34
+ - !ruby/object:Gem::Version
35
+ version: 1.8.7
36
+ required_rubygems_version: !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ! '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ requirements: []
43
+ rubyforge_project:
44
+ rubygems_version: 1.8.23
45
+ signing_key:
46
+ specification_version: 3
47
+ summary: Parse, Write and manage config files in Unix Format
48
+ test_files:
49
+ - tests/test-unixconfigstyle.rb