Config: Add case-insensitive ini file parser
This commit is contained in:
		
							parent
							
								
									b8c3e74275
								
							
						
					
					
						commit
						eb037a3779
					
				
					 5 changed files with 183 additions and 17 deletions
				
			
		| 
						 | 
					@ -110,6 +110,7 @@ set(MAIN_HEADERS
 | 
				
			||||||
	src/flashable.h
 | 
						src/flashable.h
 | 
				
			||||||
	src/font.h
 | 
						src/font.h
 | 
				
			||||||
	src/input.h
 | 
						src/input.h
 | 
				
			||||||
 | 
						src/iniconfig.h
 | 
				
			||||||
	src/plane.h
 | 
						src/plane.h
 | 
				
			||||||
	src/scene.h
 | 
						src/scene.h
 | 
				
			||||||
	src/sprite.h
 | 
						src/sprite.h
 | 
				
			||||||
| 
						 | 
					@ -167,6 +168,7 @@ set(MAIN_SOURCE
 | 
				
			||||||
	src/filesystem.cpp
 | 
						src/filesystem.cpp
 | 
				
			||||||
	src/font.cpp
 | 
						src/font.cpp
 | 
				
			||||||
	src/input.cpp
 | 
						src/input.cpp
 | 
				
			||||||
 | 
						src/iniconfig.cpp
 | 
				
			||||||
	src/plane.cpp
 | 
						src/plane.cpp
 | 
				
			||||||
	src/scene.cpp
 | 
						src/scene.cpp
 | 
				
			||||||
	src/sprite.cpp
 | 
						src/sprite.cpp
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								mkxp.pro
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								mkxp.pro
									
										
									
									
									
								
							| 
						 | 
					@ -89,6 +89,7 @@ HEADERS += \
 | 
				
			||||||
	src/flashable.h \
 | 
						src/flashable.h \
 | 
				
			||||||
	src/font.h \
 | 
						src/font.h \
 | 
				
			||||||
	src/input.h \
 | 
						src/input.h \
 | 
				
			||||||
 | 
						src/iniconfig.h \
 | 
				
			||||||
	src/plane.h \
 | 
						src/plane.h \
 | 
				
			||||||
	src/scene.h \
 | 
						src/scene.h \
 | 
				
			||||||
	src/sprite.h \
 | 
						src/sprite.h \
 | 
				
			||||||
| 
						 | 
					@ -145,6 +146,7 @@ SOURCES += \
 | 
				
			||||||
	src/filesystem.cpp \
 | 
						src/filesystem.cpp \
 | 
				
			||||||
	src/font.cpp \
 | 
						src/font.cpp \
 | 
				
			||||||
	src/input.cpp \
 | 
						src/input.cpp \
 | 
				
			||||||
 | 
						src/iniconfig.cpp \
 | 
				
			||||||
	src/plane.cpp \
 | 
						src/plane.cpp \
 | 
				
			||||||
	src/scene.cpp \
 | 
						src/scene.cpp \
 | 
				
			||||||
	src/sprite.cpp \
 | 
						src/sprite.cpp \
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -33,6 +33,7 @@
 | 
				
			||||||
#include "debugwriter.h"
 | 
					#include "debugwriter.h"
 | 
				
			||||||
#include "util.h"
 | 
					#include "util.h"
 | 
				
			||||||
#include "sdl-util.h"
 | 
					#include "sdl-util.h"
 | 
				
			||||||
 | 
					#include "iniconfig.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef INI_ENCODING
 | 
					#ifdef INI_ENCODING
 | 
				
			||||||
extern "C" {
 | 
					extern "C" {
 | 
				
			||||||
| 
						 | 
					@ -357,26 +358,32 @@ void Config::readGameINI()
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	po::options_description podesc;
 | 
					 | 
				
			||||||
	podesc.add_options()
 | 
					 | 
				
			||||||
	        ("Game.Title", po::value<std::string>())
 | 
					 | 
				
			||||||
	        ("Game.Scripts", po::value<std::string>())
 | 
					 | 
				
			||||||
	        ;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	po::variables_map vm;
 | 
					 | 
				
			||||||
	std::string iniFilename = execName + ".ini";
 | 
						std::string iniFilename = execName + ".ini";
 | 
				
			||||||
	SDLRWStream iniFile(iniFilename.c_str(), "r");
 | 
						SDLRWStream iniFile(iniFilename.c_str(), "r");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (iniFile)
 | 
						if (iniFile)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		try
 | 
							INIConfiguration ic;
 | 
				
			||||||
 | 
							if(ic.load(iniFile.stream()))
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			po::store(po::parse_config_file(iniFile.stream(), podesc, true), vm);
 | 
								GUARD_ALL( game.title = ic.getStringProperty("Game", "Title"); );
 | 
				
			||||||
			po::notify(vm);
 | 
								GUARD_ALL( game.scripts = ic.getStringProperty("Game", "Scripts"); );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								strReplace(game.scripts, '\\', '/');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (game.title.empty())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Debug() << iniFilename + ": Could not find Game.Title property";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (game.scripts.empty())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Debug() << iniFilename + ": Could not find Game.Scripts property";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		catch (po::error &error)
 | 
							else
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Debug() << iniFilename + ":" << error.what();
 | 
								Debug() << iniFilename + ": Failed to parse ini file";
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
| 
						 | 
					@ -384,11 +391,6 @@ void Config::readGameINI()
 | 
				
			||||||
		Debug() << "FAILED to open" << iniFilename;
 | 
							Debug() << "FAILED to open" << iniFilename;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	GUARD_ALL( game.title = vm["Game.Title"].as<std::string>(); );
 | 
					 | 
				
			||||||
	GUARD_ALL( game.scripts = vm["Game.Scripts"].as<std::string>(); );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	strReplace(game.scripts, '\\', '/');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef INI_ENCODING
 | 
					#ifdef INI_ENCODING
 | 
				
			||||||
	/* Can add more later */
 | 
						/* Can add more later */
 | 
				
			||||||
	const char *languages[] =
 | 
						const char *languages[] =
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										114
									
								
								src/iniconfig.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								src/iniconfig.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,114 @@
 | 
				
			||||||
 | 
					#include "iniconfig.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <algorithm>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string toLowerCase(const std::string& str)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string lower = str;
 | 
				
			||||||
 | 
						std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 | 
				
			||||||
 | 
						return lower;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					std::string trim(const std::string& str, const std::string& chars = "\t\n\v\f\r ")
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						std::string trimmed = str;
 | 
				
			||||||
 | 
						trimmed.erase(trimmed.find_last_not_of(chars) + 1);
 | 
				
			||||||
 | 
						trimmed.erase(0, trimmed.find_first_not_of(chars));
 | 
				
			||||||
 | 
						return trimmed;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INIConfiguration::Section::Section (const std::string& sname) : m_Name (sname), m_PropertyMap()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool INIConfiguration::Section::getStringProperty (const std::string& name, std::string& outPropStr) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						try
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							outPropStr = m_PropertyMap.at(toLowerCase(name)).m_Value;
 | 
				
			||||||
 | 
							return true;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						catch (std::out_of_range& oorexcept)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bool INIConfiguration::load (std::istream& is)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (!is.good())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string currSectionName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string line;
 | 
				
			||||||
 | 
						std::getline (is, line);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						while (!is.eof() && !is.bad())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (line[0] == '[')
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								currSectionName = line.substr (1, line.find_last_of (']') - 1);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else if (line[0] != '#' && line.length() > 2)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								int crloc = line.length() - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (crloc >= 0  && line[crloc] == '\r') //check for Windows-style newline
 | 
				
			||||||
 | 
									line.resize (crloc);                //and correct
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								size_t equalsPos = line.find_first_of ("=");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (equalsPos != std::string::npos)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									std::string key = line.substr (0, equalsPos);
 | 
				
			||||||
 | 
									std::string val = line.substr (equalsPos + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									addProperty (currSectionName, key , val);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::getline (is, line);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (is.bad())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					std::string INIConfiguration::getStringProperty(const std::string& sname, const std::string& name, const std::string& def) const
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						auto sectionIt = m_SectionMap.find(toLowerCase(sname));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (sectionIt != m_SectionMap.end())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							std::string prop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if(sectionIt->second.getStringProperty(name, prop))
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return prop;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						return def;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void INIConfiguration::addProperty (const std::string& sname, const std::string& name, const std::string& val)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (m_SectionMap.find (toLowerCase(sname)) == m_SectionMap.end())
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							m_SectionMap.emplace (toLowerCase(sname), Section (sname));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Section::Property p;
 | 
				
			||||||
 | 
						p.m_Name = trim(name);
 | 
				
			||||||
 | 
						p.m_Value = trim(val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						m_SectionMap.at (toLowerCase(sname)).m_PropertyMap[toLowerCase(p.m_Name)] = p;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										46
									
								
								src/iniconfig.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/iniconfig.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,46 @@
 | 
				
			||||||
 | 
					#ifndef INICONFIG_H
 | 
				
			||||||
 | 
					#define INICONFIG_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <iostream>
 | 
				
			||||||
 | 
					#include <map>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class INIConfiguration
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						class Section
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							friend class INIConfiguration;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							struct Property
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								std::string m_Name;
 | 
				
			||||||
 | 
								std::string m_Value;
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							typedef std::map<std::string, Property> property_map;
 | 
				
			||||||
 | 
						public:
 | 
				
			||||||
 | 
							Section (const Section& s) = default;
 | 
				
			||||||
 | 
							Section (Section&& s) = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool getStringProperty (const std::string& name, std::string& outPropStr) const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						private:
 | 
				
			||||||
 | 
							explicit Section (const std::string& name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							std::string m_Name;
 | 
				
			||||||
 | 
							property_map m_PropertyMap;
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						typedef std::map<std::string, Section> section_map;
 | 
				
			||||||
 | 
					public:
 | 
				
			||||||
 | 
						bool load (std::istream& inStream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						std::string getStringProperty(const std::string& sname, const std::string& name, const std::string& def = "") const;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					protected:
 | 
				
			||||||
 | 
						void addProperty (const std::string& sname, const std::string& name, const std::string& val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private:
 | 
				
			||||||
 | 
						section_map m_SectionMap;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // INICONFIG_H
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue