[Ruby] Ini Parser

Started by ForeverZer0, January 09, 2011, 03:01:27 am

Previous topic - Next topic

ForeverZer0

Here's a script I wrote for a few projects I got going on.  It simply parses a configuration file, but in a different way than any that I have seen. Instead of referencing them by hash keys, they stored as methods and structs.

So instead of, for instance, getting the font name this way:
my_font = @config['FONT']['name']

You can use this:
my_font = @config.font.name


Here it is. Sorry for using quote tags. It wouldn't display properly with code tags because of the encoding, and I'm not sure which one I need for posting here.
Spoiler: ShowHide
Quote# Ini.rb  - parses and reads .ini files
#
# Author: Eric "ForeverZer0" Freed
#
# Overview:
#
#      Class with methods to parse and read from .ini files.
#   Different method to store data within methods of the same name, as
#   opposed to referencing with hash keys.
#
#         ex.   @config = Ini.new('C:/Users/User/Documents/config.ini')
#
#               Instead of other Ini docs that you would have to get values from
#             with this method:
#
#                        size = @config['FONT']['size']
#
#               You can simply use this:
#
#                        size = @config.font.size
#
#      This keeps things a little easier to use and over-view.
#

class Ini

   attr_accessor :path

   def initialize(path)
      @path = path
      parse_file
   end
   
   def parse_file
      data, header = {}, nil
      # Create array of lines and iterate over them
      IO.readlines(@path).each {|line|
         # Remove all comment lines
         line = line.strip.split("#")[0]
         # Find lines that are words contained in brackets
         if line[0] == '[' && line[line.length - 1, line.length] == "]"
            # Remove brackets and unnecessary spaces, then store as header
            header = line[1, line.length - 2 ].strip.downcase
            data[header] = {}
         else
            # Split line into two element array, parameters and values.
            parameter, value = line.split('=', 2)
            # Remove spaces of the parameters and values.
            [parameter, value].collect! {|string| string.split if string != nil }
            # Add data to the last defined header if it is defined.
            if header != nil
               data[header][parameter] = value
            end
         end
      }
      structure_data(data)
   end
   
   def structure_data(data)
      # Iterate through the defined headers.
      data.each_pair {|header, parameters|   
         # Create a struct, using the paramter names as instance variables.
         struct = Struct.new(*(parameters.keys.collect {|para| para.downcase.to_sym } ))
         # Set method with header name, using created struct, which will be
         # instantized with the respective values.
         self.define_method(header) { struct.new(*parameters.values) }
      }
   end
end   
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

G_G

Dude. No more win32 api calls. <3.

Blizzard

Actually it would have been better if you wrapped the WinAPI calls than writing your own parser from scratch. After all, INI may have more features than you think and you only implemented the basics that you know of.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

ForeverZer0

Honestly, I never even looked up Win32 functions to see what they can do. I didn't even knew there was any.  :wacko:

I'm gonna look into it. I wrote this script to provide a function I needed, but I suppose it is worthless if I can make Win32 calls that are already there and have more ability. Oh, well.  :P I suppose it was good practice.

Thanks for the advice.  ;)
I am done scripting for RMXP. I will likely not offer support for even my own scripts anymore, but feel free to ask on the forum, there are plenty of other talented scripters that can help you.

Blizzard

The functions were ReadIni and stuff like that. Just look them up.
Check out Daygames and our games:

King of Booze 2      King of Booze: Never Ever
Drinking Game for Android      Never have I ever for Android
Drinking Game for iOS      Never have I ever for iOS


Quote from: winkioI do not speak to bricks, either as individuals or in wall form.

Quote from: Barney StinsonWhen I get sad, I stop being sad and be awesome instead. True story.

Zeriab

January 11, 2011, 03:33:10 pm #5 Last Edit: January 11, 2011, 04:45:12 pm by Zeriab
There is not only the possibility of extra features. There are also seems to be certain permissions stuff allowed like a game placed in the Program Files folder on Windows 6.x being allow to write to an .ini file there. Here is something I wrote some times ago which hopefully will help you create a nice wrapper :3
  READ_INI         = Win32API.new('kernel32',  'GetPrivateProfileStringA', 
                                 %w(p p p p l p), 'l')
 WRITE_INI        = Win32API.new('kernel32',  'WritePrivateProfileStringA',
                                 %w(p p p p), 'l')
 ##
 # Read from system ini
 #
 def read_ini(key_name, app_name = 'Game', buffer_size = 256, default = '')
   buffer = "\0" * buffer_size
   READ_INI.call(app_name, key_name, default, buffer, buffer_size - 1,
                 ".\\" + System::INI_FILENAME)
   return buffer.delete("\0")
 end
 
 ##
 # Write to system ini
 #
 def write_ini(key_name, value, app_name = 'Game')
   return WRITE_INI.call(app_name, key_name, value.to_s, ".\\" + System::INI_FILENAME)
 end


Anyway, good work on the script :3

*hugs*