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.
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
Dude. No more win32 api calls. <3.
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.
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. ;)
The functions were ReadIni and stuff like that. Just look them up.
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*