actionio-inifile 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/README.md +193 -0
  2. data/lib/inifile.rb +554 -0
  3. metadata +64 -0
data/README.md ADDED
@@ -0,0 +1,193 @@
1
+ inifile [![Build Status](https://secure.travis-ci.org/TwP/inifile.png)](http://travis-ci.org/TwP/inifile)
2
+ =======
3
+
4
+ This is a native Ruby package for reading and writing INI files.
5
+
6
+
7
+ Description
8
+ -----------
9
+
10
+ Although made popular by Windows, INI files can be used on any system thanks
11
+ to their flexibility. They allow a program to store configuration data, which
12
+ can then be easily parsed and changed. Two notable systems that use the INI
13
+ format are Samba and Trac.
14
+
15
+ More information about INI files can be found on the [Wikipedia Page](http://en.wikipedia.org/wiki/INI_file).
16
+
17
+ ### Properties
18
+
19
+ The basic element contained in an INI file is the property. Every property has
20
+ a name and a value, delimited by an equals sign *=*. The name appears to the
21
+ left of the equals sign and the value to the right.
22
+
23
+ name=value
24
+
25
+ ### Sections
26
+
27
+ Section declarations start with *[* and end with *]* as in `[section1]` and
28
+ `[section2]` shown in the example below. The section declaration marks the
29
+ beginning of a section. All properties after the section declaration will be
30
+ associated with that section.
31
+
32
+ ### Comments
33
+
34
+ All lines beginning with a semicolon *;* or a number sign *#* are considered
35
+ to be comments. Comment lines are ignored when parsing INI files.
36
+
37
+ ### Example File Format
38
+
39
+ A typical INI file might look like this:
40
+
41
+ [section1]
42
+ ; some comment on section1
43
+ var1 = foo
44
+ var2 = doodle
45
+ var3 = multiline values \
46
+ are also possible
47
+
48
+ [section2]
49
+ # another comment
50
+ var1 = baz
51
+ var2 = shoodle
52
+
53
+
54
+ Implementation
55
+ --------------
56
+
57
+ The format of INI files is not well defined. Several assumptions are made by
58
+ the **inifile** gem when parsing INI files. Most of these assumptions can be
59
+ modified at, but the defaults are listed below.
60
+
61
+ ### Global Properties
62
+
63
+ If the INI file lacks any section declarations, or if there are properties
64
+ decalared before the first section, then these properties will be placed into
65
+ a default "global" section. The name of this section can be configured when
66
+ creating an `IniFile` instance.
67
+
68
+ ### Duplicate Properties
69
+
70
+ Duplicate properties are allowed in a single section. The last property value
71
+ set is the one that will be stored in the `IniFile` instance.
72
+
73
+ [section1]
74
+ var1 = foo
75
+ var2 = bar
76
+ var1 = poodle
77
+
78
+ The resulting value of `var1` will be `poodle`.
79
+
80
+ ### Duplicate Sections
81
+
82
+ If you have more than one section with the same name then the sections will be
83
+ merged. Duplicate properties between the two sections will follow the rules
84
+ discussed above. Properties in the latter section will override properties in
85
+ the earlier section.
86
+
87
+ ### Comments
88
+
89
+ The comment character can be either a semicolon *;* or a number sign *#*. The
90
+ comment character can appear anywhere on a line including at the end of a
91
+ name/value pair declaration. If you wish to use a comment character in your
92
+ value then you will need to either escape the character or put the value in
93
+ double quotations.
94
+
95
+ [section1]
96
+ var1 = foo # a comment
97
+ var2 = "foo # this is not a comment"
98
+ var3 = foo \# this is not a comment either
99
+
100
+ ### Multi-Line Values
101
+
102
+ Values can be continued onto multiple lines in two separate ways. Putting a
103
+ slash at the end of a line will continue the value declaration to the next
104
+ line. When parsing, the trailing slash will be consumed and **will not**
105
+ appear in the resulting value. Comments can appear to the right of the
106
+ trailing slash.
107
+
108
+ var1 = this is a \ # these comments will
109
+ multiline value # be ignored by the parser
110
+
111
+ In the above example the resulting value for `var1` will be `this is a
112
+ multiline value`. If you want to preserve newline characters in the value then
113
+ quotations should be used.
114
+
115
+ var2 = "this is a
116
+ multiline value"
117
+
118
+ The resulting value for `var2` will be `this is a\nmultiline value`.
119
+
120
+ ### Escape Characters
121
+
122
+ Several escape characters are supported within the **value** for a property.
123
+ These escape sequences will be applied to quoted and unquoted values alike.
124
+ You can enable or disable escaping by setting the **escape** flag to true or
125
+ false when creating an IniFile instance.
126
+
127
+ * \0 -- null character
128
+ * \n -- newline character
129
+ * \r -- carriage return character
130
+ * \t -- tab character
131
+ * \\\\ -- backslash character
132
+
133
+ The backslash escape sequence is only needed if you want one of the escape
134
+ sequences to appear literally in your value. For example:
135
+
136
+ property = this is not a tab \\t character
137
+
138
+
139
+ Install
140
+ -------
141
+
142
+ gem install inifile
143
+
144
+
145
+ Testing
146
+ -------
147
+
148
+ To run the tests:
149
+
150
+ $ rake
151
+
152
+
153
+ Contributing
154
+ ------------
155
+
156
+ Contributions are gladly welcome! For small modifications (fixing typos,
157
+ improving documentation) you can use GitHub's in-browser editing capabilities
158
+ to create a pull request. For larger modifications I would recommend forking
159
+ the project, creating your patch, and then submitting a pull request.
160
+
161
+ Mr Bones is used to manage rake tasks and to install dependent files. To setup
162
+ your environment ...
163
+
164
+ $ gem install bones
165
+ $ rake gem:install_dependencies
166
+
167
+ And always remember that `rake -T` will show you the list of available tasks.
168
+
169
+
170
+ License
171
+ -------
172
+
173
+ MIT License
174
+ Copyright (c) 2006 - 2012
175
+
176
+ Permission is hereby granted, free of charge, to any person obtaining
177
+ a copy of this software and associated documentation files (the
178
+ 'Software'), to deal in the Software without restriction, including
179
+ without limitation the rights to use, copy, modify, merge, publish,
180
+ distribute, sublicense, and/or sell copies of the Software, and to
181
+ permit persons to whom the Software is furnished to do so, subject to
182
+ the following conditions:
183
+
184
+ The above copyright notice and this permission notice shall be
185
+ included in all copies or substantial portions of the Software.
186
+
187
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
188
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
189
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
190
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
191
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
192
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
193
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/lib/inifile.rb ADDED
@@ -0,0 +1,554 @@
1
+ #encoding: UTF-8
2
+ require 'strscan'
3
+
4
+ # This class represents the INI file and can be used to parse, modify,
5
+ # and write INI files.
6
+ #
7
+ class IniFile
8
+ include Enumerable
9
+
10
+ class Error < StandardError; end
11
+ VERSION = '2.0.2'
12
+
13
+ # Public: Open an INI file and load the contents.
14
+ #
15
+ # filename - The name of the fiel as a String
16
+ # opts - The Hash of options (default: {})
17
+ # :comment - String containing the comment character(s)
18
+ # :parameter - String used to separate parameter and value
19
+ # :encoding - Encoding String for reading / writing (Ruby 1.9)
20
+ # :escape - Boolean used to control character escaping
21
+ # :default - The String name of the default global section
22
+ #
23
+ # Examples
24
+ #
25
+ # IniFile.load('file.ini')
26
+ # #=> IniFile instance
27
+ #
28
+ # IniFile.load('does/not/exist.ini')
29
+ # #=> nil
30
+ #
31
+ # Returns an IniFile intsnace or nil if the file could not be opened.
32
+ #
33
+ def self.load( filename, opts = {} )
34
+ return unless File.file? filename
35
+ new(opts.merge(:filename => filename))
36
+ end
37
+
38
+ # Get and set the filename
39
+ attr_accessor :filename
40
+
41
+ # Get and set the encoding (Ruby 1.9)
42
+ attr_accessor :encoding
43
+
44
+ # Enable or disable character escaping
45
+ attr_accessor :escape
46
+
47
+ # Public: Create a new INI file from the given content String which
48
+ # contains the INI file lines. If the content are omitted, then the
49
+ # :filename option is used to read in the content of the INI file. If
50
+ # neither the content for a filename is provided then an empty INI file is
51
+ # created.
52
+ #
53
+ # content - The String containing the INI file contents
54
+ # opts - The Hash of options (default: {})
55
+ # :comment - String containing the comment character(s)
56
+ # :parameter - String used to separate parameter and value
57
+ # :encoding - Encoding String for reading / writing (Ruby 1.9)
58
+ # :escape - Boolean used to control character escaping
59
+ # :default - The String name of the default global section
60
+ # :filename - The filename as a String
61
+ #
62
+ # Examples
63
+ #
64
+ # IniFile.new
65
+ # #=> an empty IniFile instance
66
+ #
67
+ # IniFile.new( "[global]\nfoo=bar" )
68
+ # #=> an IniFile instance
69
+ #
70
+ # IniFile.new( :filename => 'file.ini', :encoding => 'UTF-8' )
71
+ # #=> an IniFile instance
72
+ #
73
+ # IniFile.new( "[global]\nfoo=bar", :comment => '#' )
74
+ # #=> an IniFile instance
75
+ #
76
+ def initialize( content = nil, opts = {} )
77
+ opts, content = content, nil if Hash === content
78
+
79
+ @content = content
80
+
81
+ @comment = opts.fetch(:comment, ';#')
82
+ @param = opts.fetch(:parameter, '=')
83
+ @encoding = opts.fetch(:encoding, nil)
84
+ @escape = opts.fetch(:escape, true)
85
+ @default = opts.fetch(:default, 'global')
86
+ @filename = opts.fetch(:filename, nil)
87
+
88
+ @ini = Hash.new {|h,k| h[k] = Hash.new}
89
+
90
+ if @content then parse!
91
+ elsif @filename then read
92
+ end
93
+ end
94
+
95
+ # Public: Write the contents of this IniFile to the file system. If left
96
+ # unspecified, the currently configured filename and encoding will be used.
97
+ # Otherwise the filename and encoding can be specified in the options hash.
98
+ #
99
+ # opts - The default options Hash
100
+ # :filename - The filename as a String
101
+ # :encoding - The encoding as a String (Ruby 1.9)
102
+ #
103
+ # Returns this IniFile instance.
104
+ #
105
+ def write( opts = {} )
106
+ filename = opts.fetch(:filename, @filename)
107
+ encoding = opts.fetch(:encoding, @encoding)
108
+ mode = (RUBY_VERSION >= '1.9' && encoding) ?
109
+ "w:#{encoding.to_s}" :
110
+ 'w'
111
+
112
+ File.open(filename, mode) do |f|
113
+ @ini.each do |section,hash|
114
+ f.puts "[#{section}]"
115
+ hash.each {|param,val| f.puts "#{param} #{@param} #{escape_value val}"}
116
+ f.puts
117
+ end
118
+ end
119
+
120
+ self
121
+ end
122
+ alias :save :write
123
+
124
+ # Public: Read the contents of the INI file from the file system and replace
125
+ # and set the state of this IniFile instance. If left unspecified the
126
+ # currently configured filename and encoding will be used when reading from
127
+ # the file system. Otherwise the filename and encoding can be specified in
128
+ # the options hash.
129
+ #
130
+ # opts - The default options Hash
131
+ # :filename - The filename as a String
132
+ # :encoding - The encoding as a String (Ruby 1.9)
133
+ #
134
+ # Returns this IniFile instance if the read was successful; nil is returned
135
+ # if the file could not be read.
136
+ #
137
+ def read( opts = {} )
138
+ filename = opts.fetch(:filename, @filename)
139
+ encoding = opts.fetch(:encoding, @encoding)
140
+ return unless File.file? filename
141
+
142
+ mode = (RUBY_VERSION >= '1.9' && encoding) ?
143
+ "r:#{encoding.to_s}" :
144
+ 'r'
145
+ fd = File.open(filename, mode)
146
+ @content = fd.read
147
+
148
+ parse!
149
+ self
150
+ ensure
151
+ fd.close if fd && !fd.closed?
152
+ end
153
+ alias :restore :read
154
+
155
+ # Returns this IniFile converted to a String.
156
+ #
157
+ def to_s
158
+ s = []
159
+ @ini.each do |section,hash|
160
+ s << "[#{section}]"
161
+ hash.each {|param,val| s << "#{param} #{@param} #{escape_value val}"}
162
+ s << ""
163
+ end
164
+ s.join("\n")
165
+ end
166
+
167
+ # Returns this IniFile converted to a Hash.
168
+ #
169
+ def to_h
170
+ @ini.dup
171
+ end
172
+
173
+ # Public: Creates a copy of this inifile with the entries from the
174
+ # other_inifile merged into the copy.
175
+ #
176
+ # other - The other IniFile.
177
+ #
178
+ # Returns a new IniFile.
179
+ #
180
+ def merge( other )
181
+ self.dup.merge!(other)
182
+ end
183
+
184
+ # Public: Merges other_inifile into this inifile, overwriting existing
185
+ # entries. Useful for having a system inifile with user over-ridable settings
186
+ # elsewhere.
187
+ #
188
+ # other - The other IniFile.
189
+ #
190
+ # Returns this IniFile.
191
+ #
192
+ def merge!( other )
193
+ my_keys = @ini.keys
194
+ other_keys =
195
+ case other
196
+ when IniFile; other.instance_variable_get(:@ini).keys
197
+ when Hash; other.keys
198
+ else raise "cannot merge contents from '#{other.class.name}'" end
199
+
200
+ (my_keys & other_keys).each do |key|
201
+ @ini[key].merge!(other[key])
202
+ end
203
+
204
+ (other_keys - my_keys).each do |key|
205
+ @ini[key] = other[key]
206
+ end
207
+
208
+ self
209
+ end
210
+
211
+ # Public: Yield each INI file section, parameter, and value in turn to the
212
+ # given block.
213
+ #
214
+ # block - The block that will be iterated by the each method. The block will
215
+ # be passed the current section and the parameter / value pair.
216
+ #
217
+ # Examples
218
+ #
219
+ # inifile.each do |section, parameter, value|
220
+ # puts "#{parameter} = #{value} [in section - #{section}]"
221
+ # end
222
+ #
223
+ # Returns this IniFile.
224
+ #
225
+ def each
226
+ return unless block_given?
227
+ @ini.each do |section,hash|
228
+ hash.each do |param,val|
229
+ yield section, param, val
230
+ end
231
+ end
232
+ self
233
+ end
234
+
235
+ # Public: Yield each section in turn to the given block.
236
+ #
237
+ # block - The block that will be iterated by the each method. The block will
238
+ # be passed the current section as a Hash.
239
+ #
240
+ # Examples
241
+ #
242
+ # inifile.each_section do |section|
243
+ # puts section.inspect
244
+ # end
245
+ #
246
+ # Returns this IniFile.
247
+ #
248
+ def each_section
249
+ return unless block_given?
250
+ @ini.each_key {|section| yield section}
251
+ self
252
+ end
253
+
254
+ # Public: Remove a section identified by name from the IniFile.
255
+ #
256
+ # section - The section name as a String.
257
+ #
258
+ # Returns the deleted section Hash.
259
+ #
260
+ def delete_section( section )
261
+ @ini.delete section.to_s
262
+ end
263
+
264
+ # Public: Get the section Hash by name. If the section does not exist, then
265
+ # it will be created.
266
+ #
267
+ # section - The section name as a String.
268
+ #
269
+ # Examples
270
+ #
271
+ # inifile['global']
272
+ # #=> global section Hash
273
+ #
274
+ # Returns the Hash of parameter/value pairs for this section.
275
+ #
276
+ def []( section )
277
+ return nil if section.nil?
278
+ @ini[section.to_s]
279
+ end
280
+
281
+ # Public: Set the section to a hash of parameter/value pairs.
282
+ #
283
+ # section - The section name as a String.
284
+ # value - The Hash of parameter/value pairs.
285
+ #
286
+ # Examples
287
+ #
288
+ # inifile['tenderloin'] = { 'gritty' => 'yes' }
289
+ # #=> { 'gritty' => 'yes' }
290
+ #
291
+ # Returns the value Hash.
292
+ #
293
+ def []=( section, value )
294
+ @ini[section.to_s] = value
295
+ end
296
+
297
+ # Public: Create a Hash containing only those INI file sections whose names
298
+ # match the given regular expression.
299
+ #
300
+ # regex - The Regexp used to match section names.
301
+ #
302
+ # Examples
303
+ #
304
+ # inifile.match(/^tree_/)
305
+ # #=> Hash of matching sections
306
+ #
307
+ # Return a Hash containing only those sections that match the given regular
308
+ # expression.
309
+ #
310
+ def match( regex )
311
+ @ini.dup.delete_if { |section, _| section !~ regex }
312
+ end
313
+
314
+ # Public: Check to see if the IniFile contains the section.
315
+ #
316
+ # section - The section name as a String.
317
+ #
318
+ # Returns true if the section exists in the IniFile.
319
+ #
320
+ def has_section?( section )
321
+ @ini.has_key? section.to_s
322
+ end
323
+
324
+ # Returns an Array of section names contained in this IniFile.
325
+ #
326
+ def sections
327
+ @ini.keys
328
+ end
329
+
330
+ # Public: Freeze the state of this IniFile object. Any attempts to change
331
+ # the object will raise an error.
332
+ #
333
+ # Returns this IniFile.
334
+ #
335
+ def freeze
336
+ super
337
+ @ini.each_value {|h| h.freeze}
338
+ @ini.freeze
339
+ self
340
+ end
341
+
342
+ # Public: Mark this IniFile as tainted -- this will traverse each section
343
+ # marking each as tainted.
344
+ #
345
+ # Returns this IniFile.
346
+ #
347
+ def taint
348
+ super
349
+ @ini.each_value {|h| h.taint}
350
+ @ini.taint
351
+ self
352
+ end
353
+
354
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
355
+ # of the original -- i.e. the duplicate can be modified without changing the
356
+ # original. The tainted state of the original is copied to the duplicate.
357
+ #
358
+ # Returns a new IniFile.
359
+ #
360
+ def dup
361
+ other = super
362
+ other.instance_variable_set(:@ini, Hash.new {|h,k| h[k] = Hash.new})
363
+ @ini.each_pair {|s,h| other[s].merge! h}
364
+ other.taint if self.tainted?
365
+ other
366
+ end
367
+
368
+ # Public: Produces a duplicate of this IniFile. The duplicate is independent
369
+ # of the original -- i.e. the duplicate can be modified without changing the
370
+ # original. The tainted state and the frozen state of the original is copied
371
+ # to the duplicate.
372
+ #
373
+ # Returns a new IniFile.
374
+ #
375
+ def clone
376
+ other = dup
377
+ other.freeze if self.frozen?
378
+ other
379
+ end
380
+
381
+ # Public: Compare this IniFile to some other IniFile. For two INI files to
382
+ # be equivalent, they must have the same sections with the same parameter /
383
+ # value pairs in each section.
384
+ #
385
+ # other - The other IniFile.
386
+ #
387
+ # Returns true if the INI files are equivalent and false if they differ.
388
+ #
389
+ def eql?( other )
390
+ return true if equal? other
391
+ return false unless other.instance_of? self.class
392
+ @ini == other.instance_variable_get(:@ini)
393
+ end
394
+ alias :== :eql?
395
+
396
+
397
+ private
398
+
399
+ # Parse the ini file contents. This will clear any values currently stored
400
+ # in the ini hash.
401
+ #
402
+ def parse!
403
+ return unless @content
404
+
405
+ string = ''
406
+ property = ''
407
+
408
+ @ini.clear
409
+ @_line = nil
410
+ @_section = nil
411
+
412
+ scanner = StringScanner.new(@content)
413
+ until scanner.eos?
414
+
415
+ # keep track of the current line for error messages
416
+ @_line = scanner.check(%r/\A.*$/) if scanner.bol?
417
+
418
+ # look for escaped special characters \# \" etc
419
+ if scanner.scan(%r/\\([\[\]#{@param}#{@comment}"])/)
420
+ string << scanner[1]
421
+
422
+ # look for quoted strings
423
+ elsif scanner.scan(%r/"/)
424
+ quote = scanner.scan_until(/(?:\A|[^\\])"/)
425
+ parse_error('Unmatched quote') if quote.nil?
426
+
427
+ quote.chomp!('"')
428
+ string << quote
429
+
430
+ # look for comments, empty strings, end of lines
431
+ elsif scanner.skip(%r/\A\s*(?:[#{@comment}].*)?$/)
432
+ string << scanner.getch unless scanner.eos?
433
+
434
+ process_property(property, string)
435
+
436
+ # look for the separator between property name and value
437
+ elsif scanner.scan(%r/#{@param}/)
438
+ if property.empty?
439
+ property = string.strip
440
+ string.slice!(0, string.length)
441
+ else
442
+ parse_error
443
+ end
444
+
445
+ # look for the start of a new section
446
+ elsif scanner.scan(%r/\A\s*\[([^\]]+)\]/)
447
+ @_section = @ini[scanner[1]]
448
+
449
+ # otherwise scan and store characters till we hit the start of some
450
+ # special section like a quote, newline, comment, etc.
451
+ else
452
+ tmp = scanner.scan_until(%r/([\n"#{@param}#{@comment}] | \z | \\[\[\]#{@param}#{@comment}"])/mx)
453
+ parse_error if tmp.nil?
454
+
455
+ len = scanner[1].length
456
+ tmp.slice!(tmp.length - len, len)
457
+
458
+ scanner.pos = scanner.pos - len
459
+ string << tmp
460
+ end
461
+ end
462
+
463
+ process_property(property, string)
464
+ end
465
+
466
+ # Store the property / value pair in the currently active section. This
467
+ # method checks for continuation of the value to the next line.
468
+ #
469
+ # property - The property name as a String.
470
+ # value - The property value as a String.
471
+ #
472
+ # Returns nil.
473
+ #
474
+ def process_property( property, value )
475
+ value.chomp!
476
+ return if property.empty? and value.empty?
477
+ return if value.sub!(%r/\\\s*\z/, '')
478
+
479
+ property.strip!
480
+ value.strip!
481
+
482
+ if property.empty?
483
+ current_section['values'] ||= []
484
+ current_section['values'] << value
485
+ else
486
+ current_section[property.dup] = unescape_value(value.dup)
487
+ end
488
+
489
+ property.slice!(0, property.length)
490
+ value.slice!(0, value.length)
491
+
492
+ nil
493
+ end
494
+
495
+ # Returns the current section Hash.
496
+ #
497
+ def current_section
498
+ @_section ||= @ini[@default]
499
+ end
500
+
501
+ # Raise a parse error using the given message and appending the current line
502
+ # being parsed.
503
+ #
504
+ # msg - The message String to use.
505
+ #
506
+ # Raises IniFile::Error
507
+ #
508
+ def parse_error( msg = 'Could not parse line' )
509
+ raise Error, "#{msg}: #{@_line.inspect}"
510
+ end
511
+
512
+ # Unescape special characters found in the value string. This will convert
513
+ # escaped null, tab, carriage return, newline, and backslash into their
514
+ # literal equivalents.
515
+ #
516
+ # value - The String value to unescape.
517
+ #
518
+ # Returns the unescaped value.
519
+ #
520
+ def unescape_value( value )
521
+ return value unless @escape
522
+
523
+ value = value.to_s
524
+ value.gsub!(%r/\\[0nrt\\]/) { |char|
525
+ case char
526
+ when '\0'; "\0"
527
+ when '\n'; "\n"
528
+ when '\r'; "\r"
529
+ when '\t'; "\t"
530
+ when '\\\\'; "\\"
531
+ end
532
+ }
533
+ value
534
+ end
535
+
536
+ # Escape special characters.
537
+ #
538
+ # value - The String value to escape.
539
+ #
540
+ # Returns the escaped value.
541
+ #
542
+ def escape_value( value )
543
+ return value unless @escape
544
+
545
+ value = value.to_s.dup
546
+ value.gsub!(%r/\\([0nrt])/, '\\\\\1')
547
+ value.gsub!(%r/\n/, '\n')
548
+ value.gsub!(%r/\r/, '\r')
549
+ value.gsub!(%r/\t/, '\t')
550
+ value.gsub!(%r/\0/, '\0')
551
+ value
552
+ end
553
+
554
+ end # IniFile
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: actionio-inifile
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tim Pease
9
+ - Wong Liang Zan
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-10-09 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: bones-git
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
22
+ version: '0'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: '0'
31
+ description: Parses ansible ini files
32
+ email:
33
+ - zan@liangzan.net
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - lib/inifile.rb
39
+ - README.md
40
+ homepage: http://github.com/action-io/inifile
41
+ licenses: []
42
+ post_install_message:
43
+ rdoc_options: []
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ none: false
48
+ requirements:
49
+ - - ! '>='
50
+ - !ruby/object:Gem::Version
51
+ version: '0'
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: 1.3.6
58
+ requirements: []
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.24
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: Parses ansible ini files.
64
+ test_files: []