Project

General

Profile

Feature #6515 » add_ini_support.diff

INI file parser - Alessio Caiazza, 2010-09-28 10:13

View differences:

lib/ini.rb
1
#
2
# ini.rb - read and write ini files
3
#
4
# Copyright (C) 2007 Jeena Paradies
5
# License: GPL
6
# Author: Jeena Paradies (info@jeenaparadies.net)
7
#
8
# == Overview
9
#
10
# This file provides a read-wite handling for ini files.
11
# The data of a ini file is represented by a object which
12
# is populated with strings.
13

  
14
class Ini
15
  
16
  # Class with methods to read from and write into ini files.
17
  #
18
  # A ini file is a text file in a specific format,
19
  # it may include several fields which are sparated by
20
  # field headlines which are enclosured by "[]".
21
  # Each field may include several key-value pairs.
22
  #
23
  # Each key-value pair is represented by one line and
24
  # the value is sparated from the key by a "=".
25
  #
26
  # == Examples
27
  #
28
  # === Example ini file
29
  #
30
  #   # this is the first comment which will be saved in the comment attribute
31
  #   mail=info@example.com
32
  #   domain=example.com # this is a comment which will not be saved
33
  #   [database]
34
  #   db=example
35
  #   user=john
36
  #   passwd=very-secure
37
  #   host=localhost
38
  #   # this is another comment
39
  #   [filepaths]
40
  #   tmp=/tmp/example
41
  #   lib=/home/john/projects/example/lib
42
  #   htdocs=/home/john/projects/example/htdocs
43
  #   [ texts ]
44
  #   wellcome=Wellcome on my new website!
45
  #   Website description = This is only a example. # and another comment
46
  #
47
  # === Example object
48
  #
49
  #   A Ini#comment stores:
50
  #   "this is the first comment which will be saved in the comment attribute"
51
  #
52
  #   A Ini object stores:
53
  #
54
  #   {
55
  #    "mail" => "info@example.com",
56
  #    "domain" => "example.com",
57
  #    "database" => {
58
  #     "db" => "example",
59
  #     "user" => "john",
60
  #     "passwd" => "very-secure",
61
  #     "host" => "localhost"
62
  #    },
63
  #    "filepaths" => {
64
  #     "tmp" => "/tmp/example",
65
  #     "lib" => "/home/john/projects/example/lib",
66
  #     "htdocs" => "/home/john/projects/example/htdocs"
67
  #    }
68
  #    "texts" => {
69
  #     "wellcome" => "Wellcome on my new website!",
70
  #     "Website description" => "This is only a example."
71
  #    }
72
  #   }
73
  #
74
  # As you can see this module gets rid of all comments, linebreaks
75
  # and unnecessary spaces at the beginning and the end of each
76
  # field headline, key or value.
77
  #
78
  # === Using the object
79
  #
80
  # Using the object is stright forward:
81
  #
82
  #   ini = Ini.new("path/settings.ini")
83
  #   ini["mail"] = "info@example.com"
84
  #   ini["filepaths"] = { "tmp" => "/tmp/example" }
85
  #   ini.comment = "This is\na comment"
86
  #   puts ini["filepaths"]["tmp"]
87
  #   # => /tmp/example
88
  #   ini.update()
89
  # 
90
  
91
  #
92
  # :inihash is a hash which holds all ini data
93
  # :comment is a string which holds the comments on the top of the file
94
  #
95
  attr_accessor :inihash, :comment
96

  
97
  #
98
  # Creating a new Ini object
99
  #
100
  # +path+ is a path to the ini file
101
  # +load+ if nil restores the data if possible
102
  #        if true restores the data, if not possible raises an error
103
  #        if false does not resotre the data
104
  #
105
  def initialize(path, load=nil)
106
    @path = path
107
    @inihash = {}
108
    
109
    if load or ( load.nil? and FileTest.readable_real? @path )
110
      restore()
111
    end
112
  end
113
  
114
  #
115
  # Retrive the ini data for the key +key+
116
  #
117
  def [](key)
118
    @inihash[key]
119
  end
120
  
121
  #
122
  # Set the ini data for the key +key+
123
  #
124
  def []=(key, value)
125
    raise TypeError, "String expected" unless key.is_a? String
126
    raise TypeError, "String or Hash expected" unless value.is_a? String or value.is_a? Hash
127
    
128
    @inihash[key] = value
129
  end
130
  
131
  #
132
  # Restores the data from file into the object
133
  #
134
  def restore()
135
    @inihash = Ini.read_from_file(@path)
136
    @comment = Ini.read_comment_from_file(@path)
137
  end
138
  
139
  #
140
  # Store data from the object in the file
141
  #
142
  def update()
143
    Ini.write_to_file(@path, @inihash, @comment)
144
  end
145

  
146
  #
147
  # Reading data from file
148
  #
149
  # +path+ is a path to the ini file
150
  #
151
  # returns a hash which represents the data from the file
152
  #
153
  def Ini.read_from_file(path)
154
        
155
    inihash = {}
156
    headline = nil
157
    
158
    IO.foreach(path) do |line|
159

  
160
      line = line.strip.split(/#/)[0]
161
      
162
      # read it only if the line doesn't begin with a "=" and is long enough
163
      unless line.length < 2 and line[0,1] == "="
164
        
165
        # it's a headline if the line begins with a "[" and ends with a "]"
166
        if line[0,1] == "[" and line[line.length - 1, line.length] == "]"
167
          
168
          # get rid of the [] and unnecessary spaces
169
          headline = line[1, line.length - 2 ].strip
170
          inihash[headline] = {}
171
        else
172
        
173
          key, value = line.split(/=/, 2)
174
          
175
          key = key.strip unless key.nil?
176
          value = value.strip unless value.nil?
177
          
178
          unless headline.nil?
179
            inihash[headline][key] = value
180
          else
181
            inihash[key] = value unless key.nil?
182
          end
183
        end        
184
      end
185
    end
186
    
187
    inihash
188
  end
189
  
190
  #
191
  # Reading comments from file
192
  #
193
  # +path+ is a path to the ini file
194
  #
195
  # Returns a string with comments from the beginning of the
196
  # ini file.
197
  #
198
  def Ini.read_comment_from_file(path)
199
    comment = ""
200
    
201
    IO.foreach(path) do |line|
202
      line.strip!
203
      break unless line[0,1] == "#" or line == ""
204
      
205
      comment << "#{line[1, line.length ].strip}\n"
206
    end
207
    
208
    comment
209
  end
210
  
211
  #
212
  # Writing a ini hash into a file
213
  #
214
  # +path+ is a path to the ini file
215
  # +inihash+ is a hash representing the ini File. Default is a empty hash.
216
  # +comment+ is a string with comments which appear on the
217
  #           top of the file. Each line will get a "#" before.
218
  #           Default is no comment.
219
  #
220
  def Ini.write_to_file(path, inihash={}, comment=nil)
221
    raise TypeError, "String expected" unless comment.is_a? String or comment.nil?
222
    
223
    raise TypeError, "Hash expected" unless inihash.is_a? Hash
224
    File.open(path, "w") { |file|
225
      
226
      unless comment.nil?
227
        comment.each do |line|
228
          file << "# #{line}"
229
        end
230
      end
231
      
232
      file << Ini.to_s(inihash)
233
    }
234
  end
235
  
236
  #
237
  # Turn a hash (up to 2 levels deepness) into a ini string
238
  #
239
  # +inihash+ is a hash representing the ini File. Default is a empty hash.
240
  #
241
  # Returns a string in the ini file format.
242
  #
243
  def Ini.to_s(inihash={})
244
    str = ""
245
    
246
    inihash.each do |key, value|
247

  
248
      if value.is_a? Hash
249
        str << "[#{key.to_s}]\n"
250
        
251
        value.each do |under_key, under_value|
252
          str << "#{under_key.to_s}=#{under_value.to_s unless under_value.nil?}\n"
253
        end
254

  
255
      else
256
        str << "#{key.to_s}=#{value.to_s unless value.nil?}\n"
257
      end
258
    end
259
    
260
    str
261
  end
262
  
263
end
(1-1/4)