/**
** Supermodel
** A Sega Model 3 Arcade Emulator.
** Copyright 2011 Bart Trzynadlowski
**
** This file is part of Supermodel.
**
** Supermodel is free software: you can redistribute it and/or modify it under
** the terms of the GNU General Public License as published by the Free
** Software Foundation, either version 3 of the License, or (at your option)
** any later version.
**
** Supermodel is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
** more details.
**
** You should have received a copy of the GNU General Public License along
** with Supermodel. If not, see .
**/
/*
* INIFile.h
*
* Header file for INI file management.
*/
#ifndef INCLUDED_INIFILE_H
#define INCLUDED_INIFILE_H
// Standard C++ and STL headers
#include
#include
#include
using namespace std;
#include "Types.h"
/*
* CINIFile:
*
* INI file parser.
*/
class CINIFile
{
public:
/*
* Get(SectionName, SettingName, value):
* Get(SectionName, SettingName, String):
*
* Obtains the value of a setting associated with a particular section. It
* is assumed that the caller knows whether the setting should be a string
* or an integer value. If the setting was specified as a string in the
* INI file, the value will be set to 0. Otherwise, the string will be set
* to "".
*
* Parameters:
* SectionName String defining the section name.
* SettingName String defining the setting name.
* value Reference to where the setting value will be
* copied.
* String Reference to where the string will be copied.
*
* Returns:
* OKAY if the setting was found, FAIL otherwise. The type is not
* checked.
*/
BOOL Get(string SectionName, string SettingName, int& value);
BOOL Get(string SectionName, string SettingName, unsigned& value);
BOOL Get(string SectionName, string SettingName, string& String);
/*
* Set(SectionName, SettingName, value):
* Set(SectionName, SettingName, String):
*
* Sets a setting associated with a particular section. For each overload
* type (string or integer), the opposite type is cleard (0 is written to
* values when a string is set, "" is written to strings when a value is
* set). If the setting does not exist, it is created. If the section does
* not exist, it will be added as well.
*
* Parameters:
* SectionName String defining the section name.
* SettingName String defining the setting name.
* value Value to write. String will be set to "".
* String String to write. Value will be set to 0.
*/
void Set(string SectionName, string SettingName, int value);
void Set(string SectionName, string SettingName, string String);
/*
* Write(comment):
*
* Outputs the parse tree to the INI file. The current contents of the file
* on the disk are discarded and overwritten. This means that comments are
* lost. The file is also put into write mode and cannot be re-parsed.
*
* Parameters:
* comment An optional C-string containing a comment to insert at
* the beginning of the file, otherwise NULL. The comment
* lines must include semicolons at the beginning, they
* will not be inserted automatically. The string is
* output directly, as-is.
*
* Returns:
* OKAY if successful. FAIL if an error occurred at any point. In
* order to truncate the original contents of the file, this function
* closes the file, reopends it as write-only, then reopens it again
* as a read/write file. If an error occurs during the reopening
* procedure, it is possible that nothing will be output and the
* previous contents will be lost.
*/
BOOL Write(const char *comment);
/*
* Parse(void):
*
* Parses the contents of the file, building the parse tree. Settings
* already present in the parse tree will continue to exist and will be
* overwritten if new, matching settings are found in the file.
*
* This should be done once and at the beginning.
*
* Returns:
* OKAY if successful, FAIL if there was a file or parse error.
*/
BOOL Parse(void);
/*
* SetDefaultSectionName(SectionName):
*
* Sets the default section name. Any settings not associated with a
* particular section (ie. those assigned to a blank section, "") will be
* output under this section when Write() is called.
*
* This should be called before parsing and before adding any settings.
* If the same setting is added to the default section, "", and a section
* named "Global", and afterwards "Global" is set as the default name,
* the setting originally in the default section will be the one that is
* subsequently accessible (the Get()/Set() methods look for the first
* match). However, when the file is written out, the second setting
* will be written out as well using the same section name and, thus,
* when the INI file is re-parsed, its value will be used instead.
*
* Parameters:
* SectionName String defining the section name.
*/
void SetDefaultSectionName(string SectionName);
/*
* Open(fileNameStr):
*
* Opens an INI file. The file must already exist. A new one will not be
* created. Do not open another file before closing the current one!
*
* Parameters:
* fileNameStr File path (C string).
*
* Returns:
* OKAY if successful, FAIL if unable to open for reading and writing.
*/
BOOL Open(const char *fileNameStr);
/*
* OpenAndCreate(fileNameStr):
*
* Opens an INI file and, if it does not exist, creates a new one. Do not
* open another file before closing the current one!
*
* Parameters:
* fileNameStr File path (C string).
*
* Returns:
* OKAY if successful, FAIL if unable to open file.
*/
BOOL OpenAndCreate(const char *fileNameStr);
/*
* Close(void):
*
* Closes the INI file and clears the parse tree.
*/
void Close(void);
private:
// Token
class CToken
{
public:
int type; // token type (defined privately in INIFile.cpp)
int number; // numbers and bools
string String; // strings and identifiers
// Constructor (initialize to null token)
CToken(void);
};
// Parse tree
BOOL LookUpSection(unsigned *idx, string SectionName);
void InitParseTree(void);
// Tokenizer
CToken GetString(void);
CToken GetNumber(void);
CToken GetIdentifier(void);
CToken GetToken(void);
// File state
fstream File;
string FileName; // name of last file opened
// Default section name (name to use for the blank section)
string DefaultSectionName;
// Parser state
char lineBuf[2048]; // holds current line
char *linePtr; // points to current position within line (for tokenization)
unsigned lineNum; // line number
// Parse tree: a list of sections each of which is a list of settings for that section
struct Setting // it is up to caller to determine whether to use value or string
{
string Name; // setting name
BOOL isNumber; // internal flag: true if the setting is a number, false if it is a string
int value; // value of number
string String; // string
Setting(void)
{
value = 0; // initialize value to 0
isNumber = TRUE; // indicate the setting is initially a number
}
};
struct Section
{
string Name; // section name
vector Settings; // list of settings associated w/ this section
};
vector Sections; // a list of sections
};
#endif // INCLUDED_INIFILE_H