wx: ini file and control config saving
This commit is contained in:
parent
2aa985baec
commit
16a06984bf
|
@ -0,0 +1,525 @@
|
||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program 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, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
// see IniFile.h
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
//#include "StringUtil.h"
|
||||||
|
#include "IniFile.h"
|
||||||
|
|
||||||
|
IniFile::IniFile()
|
||||||
|
{}
|
||||||
|
|
||||||
|
IniFile::~IniFile()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Section::Section()
|
||||||
|
: lines(), name(""), comment("") {}
|
||||||
|
|
||||||
|
|
||||||
|
Section::Section(const std::string& _name)
|
||||||
|
: lines(), name(_name), comment("") {}
|
||||||
|
|
||||||
|
|
||||||
|
Section::Section(const Section& other)
|
||||||
|
{
|
||||||
|
name = other.name;
|
||||||
|
comment = other.comment;
|
||||||
|
lines = other.lines;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Section* IniFile::GetSection(const char* sectionName) const
|
||||||
|
{
|
||||||
|
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||||
|
if (!strcasecmp(iter->name.c_str(), sectionName))
|
||||||
|
return (&(*iter));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Section* IniFile::GetSection(const char* sectionName)
|
||||||
|
{
|
||||||
|
for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||||
|
if (!strcasecmp(iter->name.c_str(), sectionName))
|
||||||
|
return (&(*iter));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Section* IniFile::GetOrCreateSection(const char* sectionName)
|
||||||
|
{
|
||||||
|
Section* section = GetSection(sectionName);
|
||||||
|
|
||||||
|
if (!section)
|
||||||
|
{
|
||||||
|
sections.push_back(Section(sectionName));
|
||||||
|
section = §ions[sections.size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
return(section);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IniFile::DeleteSection(const char* sectionName)
|
||||||
|
{
|
||||||
|
Section* s = GetSection(sectionName);
|
||||||
|
|
||||||
|
if (!s)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||||
|
{
|
||||||
|
if (&(*iter) == s)
|
||||||
|
{
|
||||||
|
sections.erase(iter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) const
|
||||||
|
{
|
||||||
|
//
|
||||||
|
int FirstEquals = (int)line.find("=", 0);
|
||||||
|
int FirstCommentChar = -1;
|
||||||
|
// Comments
|
||||||
|
//if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find(";", FirstEquals > 0 ? FirstEquals : 0);}
|
||||||
|
if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("#", FirstEquals > 0 ? FirstEquals : 0);}
|
||||||
|
if (FirstCommentChar < 0) {FirstCommentChar = (int)line.find("//", FirstEquals > 0 ? FirstEquals : 0);}
|
||||||
|
|
||||||
|
// Allow preservation of spacing before comment
|
||||||
|
if (FirstCommentChar > 0)
|
||||||
|
{
|
||||||
|
while (line[FirstCommentChar - 1] == ' ' || line[FirstCommentChar - 1] == 9) // 9 == tab
|
||||||
|
{
|
||||||
|
FirstCommentChar--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((FirstEquals >= 0) && ((FirstCommentChar < 0) || (FirstEquals < FirstCommentChar)))
|
||||||
|
{
|
||||||
|
// Yes, a valid line!
|
||||||
|
*keyOut = StripSpaces(line.substr(0, FirstEquals));
|
||||||
|
if (commentOut) *commentOut = FirstCommentChar > 0 ? line.substr(FirstCommentChar) : std::string("");
|
||||||
|
if (valueOut) *valueOut = StripQuotes(StripSpaces(line.substr(FirstEquals + 1, FirstCommentChar - FirstEquals - 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* IniFile::GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut)
|
||||||
|
{
|
||||||
|
for (std::vector<std::string>::iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string& line = *iter;
|
||||||
|
std::string lineKey;
|
||||||
|
ParseLine(line, &lineKey, valueOut, commentOut);
|
||||||
|
|
||||||
|
if (!strcasecmp(lineKey.c_str(), key))
|
||||||
|
{
|
||||||
|
return &line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IniFile::Exists(const char* const sectionName, const char* key) const
|
||||||
|
{
|
||||||
|
|
||||||
|
const Section* const section = GetSection(sectionName);
|
||||||
|
if (!section)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string lineKey;
|
||||||
|
ParseLine(*iter, &lineKey, NULL, NULL);
|
||||||
|
|
||||||
|
if (!strcasecmp(lineKey.c_str(), key))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniFile::SetLines(const char* sectionName, const std::vector<std::string> &lines)
|
||||||
|
{
|
||||||
|
Section* section = GetOrCreateSection(sectionName);
|
||||||
|
section->lines.clear();
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator iter = lines.begin(); iter != lines.end(); ++iter)
|
||||||
|
{
|
||||||
|
section->lines.push_back(*iter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IniFile::DeleteKey(const char* sectionName, const char* key)
|
||||||
|
{
|
||||||
|
Section* section = GetSection(sectionName);
|
||||||
|
|
||||||
|
if (!section)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* line = GetLine(section, key, 0, 0);
|
||||||
|
|
||||||
|
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
|
||||||
|
{
|
||||||
|
if (line == &(*liter))
|
||||||
|
{
|
||||||
|
section->lines.erase(liter);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; //shouldn't happen
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of all keys in a section
|
||||||
|
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys) const
|
||||||
|
{
|
||||||
|
const Section* section = GetSection(sectionName);
|
||||||
|
|
||||||
|
if (!section)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
keys.clear();
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
ParseLine(*liter, &key, 0, 0);
|
||||||
|
keys.push_back(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a list of all lines in a section
|
||||||
|
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines) const
|
||||||
|
{
|
||||||
|
const Section* section = GetSection(sectionName);
|
||||||
|
if (!section)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
lines.clear();
|
||||||
|
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||||
|
{
|
||||||
|
std::string line = StripSpaces(*iter);
|
||||||
|
int commentPos = (int)line.find('#');
|
||||||
|
if (commentPos == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commentPos != (int)std::string::npos)
|
||||||
|
{
|
||||||
|
line = StripSpaces(line.substr(0, commentPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IniFile::SortSections()
|
||||||
|
{
|
||||||
|
std::sort(sections.begin(), sections.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IniFile::Load(const char* filename)
|
||||||
|
{
|
||||||
|
// Maximum number of letters in a line
|
||||||
|
static const int MAX_BYTES = 1024*32;
|
||||||
|
|
||||||
|
sections.clear();
|
||||||
|
sections.push_back(Section(""));
|
||||||
|
// first section consists of the comments before the first real section
|
||||||
|
|
||||||
|
// Open file
|
||||||
|
std::ifstream in;
|
||||||
|
in.open(filename, std::ios::in);
|
||||||
|
|
||||||
|
if (in.fail()) return false;
|
||||||
|
|
||||||
|
while (!in.eof())
|
||||||
|
{
|
||||||
|
char templine[MAX_BYTES];
|
||||||
|
in.getline(templine, MAX_BYTES);
|
||||||
|
std::string line = templine;
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
// Check for CRLF eol and convert it to LF
|
||||||
|
if (!line.empty() && line.at(line.size()-1) == '\r')
|
||||||
|
{
|
||||||
|
line.erase(line.size()-1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (in.eof()) break;
|
||||||
|
|
||||||
|
if (line.size() > 0)
|
||||||
|
{
|
||||||
|
if (line[0] == '[')
|
||||||
|
{
|
||||||
|
size_t endpos = line.find("]");
|
||||||
|
|
||||||
|
if (endpos != std::string::npos)
|
||||||
|
{
|
||||||
|
// New section!
|
||||||
|
std::string sub = line.substr(1, endpos - 1);
|
||||||
|
sections.push_back(Section(sub));
|
||||||
|
|
||||||
|
if (endpos + 1 < line.size())
|
||||||
|
{
|
||||||
|
sections[sections.size() - 1].comment = line.substr(endpos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sections[sections.size() - 1].lines.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
in.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IniFile::Save(const char* filename)
|
||||||
|
{
|
||||||
|
std::ofstream out;
|
||||||
|
out.open(filename, std::ios::out);
|
||||||
|
|
||||||
|
if (out.fail())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||||
|
{
|
||||||
|
const Section& section = *iter;
|
||||||
|
|
||||||
|
if (section.name != "")
|
||||||
|
{
|
||||||
|
out << "[" << section.name << "]" << section.comment << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
|
||||||
|
{
|
||||||
|
std::string s = *liter;
|
||||||
|
out << s << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniFile::Set(const char* sectionName, const char* key, const char* newValue)
|
||||||
|
{
|
||||||
|
Section* section = GetOrCreateSection(sectionName);
|
||||||
|
std::string value, comment;
|
||||||
|
std::string* line = GetLine(section, key, &value, &comment);
|
||||||
|
|
||||||
|
if (line)
|
||||||
|
{
|
||||||
|
// Change the value - keep the key and comment
|
||||||
|
*line = StripSpaces(key) + " = " + newValue + comment;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The key did not already exist in this section - let's add it.
|
||||||
|
section->lines.push_back(std::string(key) + " = " + newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniFile::Set(const char* sectionName, const char* key, const std::vector<std::string>& newValues)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
|
||||||
|
// Join the strings with ,
|
||||||
|
std::vector<std::string>::const_iterator it;
|
||||||
|
for (it = newValues.begin(); it != newValues.end(); ++it) {
|
||||||
|
|
||||||
|
temp = (*it) + ",";
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove last ,
|
||||||
|
temp.resize(temp.length() - 1);
|
||||||
|
|
||||||
|
Set(sectionName, key, temp.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void IniFile::Set(const char* sectionName, const char* key, u32 newValue)
|
||||||
|
{
|
||||||
|
Set(sectionName, key, StringFromFormat("0x%08x", newValue).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IniFile::Set(const char* sectionName, const char* key, int newValue)
|
||||||
|
{
|
||||||
|
Set(sectionName, key, StringFromInt(newValue).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void IniFile::Set(const char* sectionName, const char* key, bool newValue)
|
||||||
|
{
|
||||||
|
Set(sectionName, key, StringFromBool(newValue).c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue)
|
||||||
|
{
|
||||||
|
Section* section = GetSection(sectionName);
|
||||||
|
|
||||||
|
if (!section)
|
||||||
|
{
|
||||||
|
if (defaultValue)
|
||||||
|
{
|
||||||
|
*value = defaultValue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string* line = GetLine(section, key, value, 0);
|
||||||
|
|
||||||
|
if (!line)
|
||||||
|
{
|
||||||
|
if (defaultValue)
|
||||||
|
{
|
||||||
|
*value = defaultValue;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IniFile::Get(const char* sectionName, const char* key, std::vector<std::string>& values)
|
||||||
|
{
|
||||||
|
|
||||||
|
std::string temp;
|
||||||
|
bool retval = Get(sectionName, key, &temp, 0);
|
||||||
|
|
||||||
|
if (! retval || temp.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ignore starting , if any
|
||||||
|
size_t subStart = temp.find_first_not_of(",");
|
||||||
|
size_t subEnd;
|
||||||
|
|
||||||
|
// split by ,
|
||||||
|
while (subStart != std::string::npos) {
|
||||||
|
|
||||||
|
// Find next ,
|
||||||
|
subEnd = temp.find_first_of(",", subStart);
|
||||||
|
if (subStart != subEnd)
|
||||||
|
// take from first char until next ,
|
||||||
|
values.push_back(StripSpaces(temp.substr(subStart, subEnd - subStart)));
|
||||||
|
|
||||||
|
// Find the next non , char
|
||||||
|
subStart = temp.find_first_not_of(",", subEnd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IniFile::Get(const char* sectionName, const char* key, int* value, int defaultValue)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
bool retval = Get(sectionName, key, &temp, 0);
|
||||||
|
|
||||||
|
if (retval && TryParseInt(temp.c_str(), value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = defaultValue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IniFile::Get(const char* sectionName, const char* key, u32* value, u32 defaultValue)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
bool retval = Get(sectionName, key, &temp, 0);
|
||||||
|
|
||||||
|
if (retval && TryParseUInt(temp.c_str(), value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = defaultValue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool defaultValue)
|
||||||
|
{
|
||||||
|
std::string temp;
|
||||||
|
bool retval = Get(sectionName, key, &temp, 0);
|
||||||
|
|
||||||
|
if (retval && TryParseBool(temp.c_str(), value))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*value = defaultValue;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Keep this code below?
|
||||||
|
/*
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
IniFile ini;
|
||||||
|
ini.Load("my.ini");
|
||||||
|
ini.Set("Hej", "A", "amaskdfl");
|
||||||
|
ini.Set("Mossa", "A", "amaskdfl");
|
||||||
|
ini.Set("Aissa", "A", "amaskdfl");
|
||||||
|
//ini.Read("my.ini");
|
||||||
|
std::string x;
|
||||||
|
ini.Get("Hej", "B", &x, "boo");
|
||||||
|
ini.DeleteKey("Mossa", "A");
|
||||||
|
ini.DeleteSection("Mossa");
|
||||||
|
ini.SortSections();
|
||||||
|
ini.Save("my.ini");
|
||||||
|
//UpdateVars(ini);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,93 @@
|
||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program 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, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#ifndef _INIFILE_H_
|
||||||
|
#define _INIFILE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
class Section
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Section();
|
||||||
|
Section(const std::string& _name);
|
||||||
|
Section(const Section& other);
|
||||||
|
std::vector<std::string>lines;
|
||||||
|
std::string name;
|
||||||
|
std::string comment;
|
||||||
|
|
||||||
|
bool operator<(const Section& other) const
|
||||||
|
{
|
||||||
|
return(name < other.name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class IniFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
IniFile();
|
||||||
|
~IniFile();
|
||||||
|
|
||||||
|
bool Load(const char* filename);
|
||||||
|
bool Save(const char* filename);
|
||||||
|
|
||||||
|
void Set(const char* sectionName, const char* key, const char* newValue);
|
||||||
|
void Set(const char* sectionName, const char* key, int newValue);
|
||||||
|
void Set(const char* sectionName, const char* key, u32 newValue);
|
||||||
|
void Set(const char* sectionName, const char* key, bool newValue);
|
||||||
|
void Set(const char* sectionName, const char* key, const std::string& newValue) {Set(sectionName, key, newValue.c_str());}
|
||||||
|
void Set(const char* sectionName, const char* key, const std::vector<std::string>& newValues);
|
||||||
|
|
||||||
|
void SetLines(const char* sectionName, const std::vector<std::string> &lines);
|
||||||
|
|
||||||
|
// Returns true if exists key in section
|
||||||
|
bool Exists(const char* sectionName, const char* key) const;
|
||||||
|
|
||||||
|
// getter should be const
|
||||||
|
bool Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue = "");
|
||||||
|
bool Get(const char* sectionName, const char* key, int* value, int defaultValue = 0);
|
||||||
|
bool Get(const char* sectionName, const char* key, u32* value, u32 defaultValue = 0);
|
||||||
|
bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false);
|
||||||
|
bool Get(const char* sectionName, const char* key, std::vector<std::string>& values);
|
||||||
|
|
||||||
|
bool GetKeys(const char* sectionName, std::vector<std::string>& keys) const;
|
||||||
|
bool GetLines(const char* sectionName, std::vector<std::string>& lines) const;
|
||||||
|
|
||||||
|
bool DeleteKey(const char* sectionName, const char* key);
|
||||||
|
bool DeleteSection(const char* sectionName);
|
||||||
|
|
||||||
|
void SortSections();
|
||||||
|
|
||||||
|
void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut) const;
|
||||||
|
std::string* GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<Section>sections;
|
||||||
|
|
||||||
|
const Section* GetSection(const char* section) const;
|
||||||
|
Section* GetSection(const char* section);
|
||||||
|
Section* GetOrCreateSection(const char* section);
|
||||||
|
std::string* GetLine(const char* section, const char* key);
|
||||||
|
void CreateSection(const char* section);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // _INIFILE_H_
|
|
@ -401,6 +401,7 @@ void PADConfigDialogSimple::OnClose(wxCloseEvent& event)
|
||||||
|
|
||||||
void PADConfigDialogSimple::OnCloseClick(wxCommandEvent& event)
|
void PADConfigDialogSimple::OnCloseClick(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
|
SaveConfig();
|
||||||
Close();
|
Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
//#include "LogManager.h"
|
//#include "LogManager.h"
|
||||||
#include "pluginspecs_pad.h"
|
#include "pluginspecs_pad.h"
|
||||||
#include "PadSimple.h"
|
#include "PadSimple.h"
|
||||||
//#include "IniFile.h"
|
#include "../IniFile.h"
|
||||||
//#include "StringUtil.h"
|
//#include "StringUtil.h"
|
||||||
//#include "FileUtil.h"
|
//#include "FileUtil.h"
|
||||||
//#include "ChunkFile.h"
|
//#include "ChunkFile.h"
|
||||||
|
@ -822,7 +822,7 @@ void PAD_Rumble(u8 _numPAD, unsigned int _uType, unsigned int _uStrength)
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
// Load and save the configuration
|
// Load and save the configuration
|
||||||
//******************************************************************************
|
//******************************************************************************
|
||||||
|
extern std::string executableDirectory;
|
||||||
void LoadConfig()
|
void LoadConfig()
|
||||||
{
|
{
|
||||||
// Initialize first pad to standard controls
|
// Initialize first pad to standard controls
|
||||||
|
@ -916,10 +916,9 @@ void LoadConfig()
|
||||||
46, // Mic (m)
|
46, // Mic (m)
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
//TODO
|
|
||||||
#if 0
|
|
||||||
IniFile file;
|
IniFile file;
|
||||||
file.Load(FULL_CONFIG_DIR "pad.ini");
|
|
||||||
|
file.Load((executableDirectory + std::string("pad.ini")).c_str());
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
|
@ -953,16 +952,13 @@ void LoadConfig()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void SaveConfig()
|
void SaveConfig()
|
||||||
{
|
{
|
||||||
//TODO
|
|
||||||
#if 0
|
|
||||||
IniFile file;
|
IniFile file;
|
||||||
file.Load(FULL_CONFIG_DIR "pad.ini");
|
file.Load((executableDirectory + std::string("pad.ini")).c_str());
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
|
@ -989,6 +985,5 @@ void SaveConfig()
|
||||||
file.Set(SectionName, controlNames[x], pad[i].keyForControl[x]);
|
file.Set(SectionName, controlNames[x], pad[i].keyForControl[x]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file.Save(FULL_CONFIG_DIR "pad.ini");
|
file.Save((executableDirectory + std::string("pad.ini")).c_str());
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,506 @@
|
||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program 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, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "StringUtil.h"
|
||||||
|
|
||||||
|
// faster than sscanf
|
||||||
|
bool AsciiToHex(const char* _szValue, u32& result)
|
||||||
|
{
|
||||||
|
u32 value = 0;
|
||||||
|
size_t finish = strlen(_szValue);
|
||||||
|
|
||||||
|
if (finish > 8)
|
||||||
|
finish = 8; // Max 32-bit values are supported.
|
||||||
|
|
||||||
|
for (size_t count = 0; count < finish; count++)
|
||||||
|
{
|
||||||
|
value <<= 4;
|
||||||
|
switch (_szValue[count])
|
||||||
|
{
|
||||||
|
case '0': break;
|
||||||
|
case '1': value += 1; break;
|
||||||
|
case '2': value += 2; break;
|
||||||
|
case '3': value += 3; break;
|
||||||
|
case '4': value += 4; break;
|
||||||
|
case '5': value += 5; break;
|
||||||
|
case '6': value += 6; break;
|
||||||
|
case '7': value += 7; break;
|
||||||
|
case '8': value += 8; break;
|
||||||
|
case '9': value += 9; break;
|
||||||
|
case 'A':
|
||||||
|
case 'a': value += 10; break;
|
||||||
|
case 'B':
|
||||||
|
case 'b': value += 11; break;
|
||||||
|
case 'C':
|
||||||
|
case 'c': value += 12; break;
|
||||||
|
case 'D':
|
||||||
|
case 'd': value += 13; break;
|
||||||
|
case 'E':
|
||||||
|
case 'e': value += 14; break;
|
||||||
|
case 'F':
|
||||||
|
case 'f': value += 15; break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result = value;
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert AB to it's ascii table entry numbers 0x4142
|
||||||
|
u32 Ascii2Hex(std::string _Text)
|
||||||
|
{
|
||||||
|
// Reset the return value zero
|
||||||
|
u32 Result = 0;
|
||||||
|
|
||||||
|
// Max 32-bit values are supported
|
||||||
|
size_t Length = _Text.length();
|
||||||
|
if (Length > 4)
|
||||||
|
Length = 4;
|
||||||
|
|
||||||
|
for (int i = 0; i < (int)Length; i++)
|
||||||
|
{
|
||||||
|
// Add up the values, for example RSPE becomes, 0x52000000, then 0x52530000 and so on
|
||||||
|
Result += _Text.c_str()[i] << ((Length - 1 - i) * 8);
|
||||||
|
}
|
||||||
|
// Return the value
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert it back again
|
||||||
|
std::string Hex2Ascii(u32 _Text)
|
||||||
|
{
|
||||||
|
// Create temporary storate
|
||||||
|
char Result[5]; // need space for the final \0
|
||||||
|
// Go through the four characters
|
||||||
|
sprintf(Result, "%c%c%c%c", _Text >> 24, _Text >> 16, _Text >> 8, _Text);
|
||||||
|
// Return the string
|
||||||
|
std::string StrResult = Result;
|
||||||
|
return StrResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
|
||||||
|
{
|
||||||
|
int writtenCount = vsnprintf(out, outsize, format, args);
|
||||||
|
|
||||||
|
if (writtenCount > 0 && writtenCount < outsize)
|
||||||
|
{
|
||||||
|
out[writtenCount] = '\0';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out[outsize - 1] = '\0';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expensive!
|
||||||
|
void ToStringFromFormat(std::string* out, const char* format, ...)
|
||||||
|
{
|
||||||
|
int writtenCount = -1;
|
||||||
|
int newSize = (int)strlen(format) + 4;
|
||||||
|
char *buf = 0;
|
||||||
|
va_list args;
|
||||||
|
while (writtenCount < 0)
|
||||||
|
{
|
||||||
|
delete [] buf;
|
||||||
|
buf = new char[newSize + 1];
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
writtenCount = vsnprintf(buf, newSize, format, args);
|
||||||
|
va_end(args);
|
||||||
|
if (writtenCount >= (int)newSize) {
|
||||||
|
writtenCount = -1;
|
||||||
|
}
|
||||||
|
// ARGH! vsnprintf does no longer return -1 on truncation in newer libc!
|
||||||
|
// WORKAROUND! let's fake the old behaviour (even though it's less efficient).
|
||||||
|
// TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :(
|
||||||
|
// if (writtenCount >= (int)newSize)
|
||||||
|
// writtenCount = -1;
|
||||||
|
newSize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[writtenCount] = '\0';
|
||||||
|
*out = buf;
|
||||||
|
delete[] buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string StringFromFormat(const char* format, ...)
|
||||||
|
{
|
||||||
|
int writtenCount = -1;
|
||||||
|
int newSize = (int)strlen(format) + 4;
|
||||||
|
char *buf = 0;
|
||||||
|
va_list args;
|
||||||
|
while (writtenCount < 0)
|
||||||
|
{
|
||||||
|
delete [] buf;
|
||||||
|
buf = new char[newSize + 1];
|
||||||
|
|
||||||
|
va_start(args, format);
|
||||||
|
writtenCount = vsnprintf(buf, newSize, format, args);
|
||||||
|
va_end(args);
|
||||||
|
if (writtenCount >= (int)newSize) {
|
||||||
|
writtenCount = -1;
|
||||||
|
}
|
||||||
|
// ARGH! vsnprintf does no longer return -1 on truncation in newer libc!
|
||||||
|
// WORKAROUND! let's fake the old behaviour (even though it's less efficient).
|
||||||
|
// TODO: figure out why the fix causes an invalid read in strlen called from vsnprintf :(
|
||||||
|
// if (writtenCount >= (int)newSize)
|
||||||
|
// writtenCount = -1;
|
||||||
|
newSize *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[writtenCount] = '\0';
|
||||||
|
std::string temp = buf;
|
||||||
|
delete[] buf;
|
||||||
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// For Debugging. Read out an u8 array.
|
||||||
|
std::string ArrayToString(const u8 *data, u32 size, u32 offset, int line_len, bool Spaces)
|
||||||
|
{
|
||||||
|
std::string Tmp, Spc;
|
||||||
|
if (Spaces) Spc = " "; else Spc = "";
|
||||||
|
for (u32 i = 0; i < size; i++)
|
||||||
|
{
|
||||||
|
Tmp += StringFromFormat("%02x%s", data[i + offset], Spc.c_str());
|
||||||
|
if(i > 1 && (i + 1) % line_len == 0) Tmp.append("\n"); // break long lines
|
||||||
|
}
|
||||||
|
return Tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Turns " hej " into "hej". Also handles tabs.
|
||||||
|
std::string StripSpaces(const std::string &str)
|
||||||
|
{
|
||||||
|
std::string s = str;
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < (int)s.size(); i++)
|
||||||
|
{
|
||||||
|
if ((s[i] != ' ') && (s[i] != 9))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s = s.substr(i);
|
||||||
|
|
||||||
|
for (i = (int)s.size() - 1; i > 0; i--)
|
||||||
|
{
|
||||||
|
if ((s[i] != ' ') && (s[i] != 9))
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s.substr(0, i + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// "\"hello\"" is turned to "hello"
|
||||||
|
// This one assumes that the string has already been space stripped in both
|
||||||
|
// ends, as done by StripSpaces above, for example.
|
||||||
|
std::string StripQuotes(const std::string& s)
|
||||||
|
{
|
||||||
|
if ((s[0] == '\"') && (s[s.size() - 1] == '\"'))
|
||||||
|
return s.substr(1, s.size() - 2);
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "\"hello\"" is turned to "hello"
|
||||||
|
// This one assumes that the string has already been space stripped in both
|
||||||
|
// ends, as done by StripSpaces above, for example.
|
||||||
|
std::string StripNewline(const std::string& s)
|
||||||
|
{
|
||||||
|
if (!s.size())
|
||||||
|
return s;
|
||||||
|
else if (s[s.size() - 1] == '\n')
|
||||||
|
return s.substr(0, s.size() - 1);
|
||||||
|
else
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TryParseInt(const char* str, int* outVal)
|
||||||
|
{
|
||||||
|
const char* s = str;
|
||||||
|
int value = 0;
|
||||||
|
bool negativ = false;
|
||||||
|
|
||||||
|
if (*s == '-')
|
||||||
|
{
|
||||||
|
negativ = true;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*s)
|
||||||
|
{
|
||||||
|
char c = *s++;
|
||||||
|
|
||||||
|
if ((c < '0') || (c > '9'))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = value * 10 + (c - '0');
|
||||||
|
}
|
||||||
|
if (negativ)
|
||||||
|
value = -value;
|
||||||
|
|
||||||
|
*outVal = value;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TryParseBool(const char* str, bool* output)
|
||||||
|
{
|
||||||
|
if ((str[0] == '1') || !strcmp(str, "true") || !strcmp(str, "True") || !strcmp(str, "TRUE"))
|
||||||
|
{
|
||||||
|
*output = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (str[0] == '0' || !strcmp(str, "false") || !strcmp(str, "False") || !strcmp(str, "FALSE"))
|
||||||
|
{
|
||||||
|
*output = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StringFromInt(int value)
|
||||||
|
{
|
||||||
|
char temp[16];
|
||||||
|
sprintf(temp, "%i", value);
|
||||||
|
return std::string(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string StringFromBool(bool value)
|
||||||
|
{
|
||||||
|
return value ? "True" : "False";
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||||
|
{
|
||||||
|
char drive[_MAX_DRIVE];
|
||||||
|
char dir[_MAX_DIR];
|
||||||
|
char fname[_MAX_FNAME];
|
||||||
|
char ext[_MAX_EXT];
|
||||||
|
|
||||||
|
if (_splitpath_s(full_path.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT) == 0)
|
||||||
|
{
|
||||||
|
if (_pPath)
|
||||||
|
{
|
||||||
|
*_pPath = std::string(drive) + std::string(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pFilename != 0)
|
||||||
|
{
|
||||||
|
*_pFilename = fname;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pExtension != 0)
|
||||||
|
{
|
||||||
|
*_pExtension = ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||||
|
{
|
||||||
|
size_t last_slash = full_path.rfind('/');
|
||||||
|
|
||||||
|
if (last_slash == std::string::npos)
|
||||||
|
{
|
||||||
|
return false; // FIXME return the filename
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t last_dot = full_path.rfind('.');
|
||||||
|
|
||||||
|
if ((last_dot == std::string::npos) || (last_dot < last_slash))
|
||||||
|
{
|
||||||
|
return false; // FIXME why missing . is critical?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pPath)
|
||||||
|
{
|
||||||
|
*_pPath = full_path.substr(0, last_slash + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pFilename)
|
||||||
|
{
|
||||||
|
*_pFilename = full_path.substr(last_slash + 1, last_dot - (last_slash + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_pExtension)
|
||||||
|
{
|
||||||
|
*_pExtension = full_path.substr(last_dot + 1);
|
||||||
|
_pExtension->insert(0, ".");
|
||||||
|
}
|
||||||
|
else if (_pFilename)
|
||||||
|
{
|
||||||
|
*_pFilename += full_path.substr(last_dot);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#define DIR_SEP "/"
|
||||||
|
#define DIR_SEP_CHR '/'
|
||||||
|
|
||||||
|
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
|
||||||
|
{
|
||||||
|
_CompleteFilename = _Path;
|
||||||
|
|
||||||
|
// check for seperator
|
||||||
|
if (_CompleteFilename[_CompleteFilename.size() - 1] != DIR_SEP_CHR)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (_CompleteFilename[_CompleteFilename.size() - 1] != '\\')
|
||||||
|
#endif
|
||||||
|
_CompleteFilename += DIR_SEP_CHR;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the filename
|
||||||
|
_CompleteFilename += _Filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SplitString(const std::string& str, const std::string& delim, std::vector<std::string>& output)
|
||||||
|
{
|
||||||
|
output.clear();
|
||||||
|
|
||||||
|
size_t offset = 0;
|
||||||
|
size_t delimIndex = 0;
|
||||||
|
|
||||||
|
delimIndex = str.find(delim, offset);
|
||||||
|
|
||||||
|
while (delimIndex != std::string::npos)
|
||||||
|
{
|
||||||
|
output.push_back(str.substr(offset, delimIndex - offset));
|
||||||
|
offset += delimIndex - offset + delim.length();
|
||||||
|
delimIndex = str.find(delim, offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push_back(str.substr(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool TryParseUInt(const std::string& str, u32* output)
|
||||||
|
{
|
||||||
|
if (!strcmp(str.substr(0, 2).c_str(), "0x") || !strcmp(str.substr(0, 2).c_str(), "0X"))
|
||||||
|
return sscanf(str.c_str() + 2, "%x", output) > 0;
|
||||||
|
else
|
||||||
|
return sscanf(str.c_str(), "%d", output) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ChooseStringFrom(const char* str, const char* * items)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
while (items[i] != 0)
|
||||||
|
{
|
||||||
|
if (!strcmp(str, items[i]))
|
||||||
|
return i;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Thousand separator. Turns 12345678 into 12,345,678
|
||||||
|
std::string ThS(int Integer, bool Unsigned, int Spaces)
|
||||||
|
{
|
||||||
|
// Create storage space
|
||||||
|
char cbuf[20];
|
||||||
|
// Determine treatment of signed or unsigned
|
||||||
|
if(Unsigned) sprintf(cbuf, "%u", Integer); else sprintf(cbuf, "%i", Integer);
|
||||||
|
|
||||||
|
std::string Sbuf = cbuf;
|
||||||
|
for (u32 i = 0; i < Sbuf.length(); ++i)
|
||||||
|
{
|
||||||
|
if((i & 3) == 3)
|
||||||
|
{
|
||||||
|
Sbuf.insert(Sbuf.length() - i, ",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spaces
|
||||||
|
std::string Spc = "";
|
||||||
|
for (int i = 0; i < (int)(Spaces - Sbuf.length()); i++) Spc += " ";
|
||||||
|
return Spc + Sbuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NormalizeDirSep(std::string* str)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
int i;
|
||||||
|
while ((i = (int)str->find_first_of('\\')) >= 0)
|
||||||
|
{
|
||||||
|
str->replace(i, 1, DIR_SEP);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string TabsToSpaces(int tab_size, const std::string &in)
|
||||||
|
{
|
||||||
|
std::string out;
|
||||||
|
int len = 0;
|
||||||
|
// First, compute the size of the new string.
|
||||||
|
for (unsigned i = 0; i < in.size(); i++)
|
||||||
|
{
|
||||||
|
if (in[i] == '\t')
|
||||||
|
len += tab_size;
|
||||||
|
else
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
out.resize(len);
|
||||||
|
int out_ctr = 0;
|
||||||
|
for (unsigned i = 0; i < in.size(); i++)
|
||||||
|
{
|
||||||
|
if (in[i] == '\t')
|
||||||
|
{
|
||||||
|
for (int j = 0; j < tab_size; j++)
|
||||||
|
out[out_ctr++] = ' ';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out[out_ctr++] = in[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string PathToFilename(std::string Path)
|
||||||
|
{
|
||||||
|
std::string Name, Ending;
|
||||||
|
SplitPath(Path, 0, &Name, &Ending);
|
||||||
|
return Name + Ending;
|
||||||
|
}
|
|
@ -0,0 +1,83 @@
|
||||||
|
// Copyright (C) 2003 Dolphin Project.
|
||||||
|
|
||||||
|
// This program 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, version 2.0.
|
||||||
|
|
||||||
|
// This program 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 2.0 for more details.
|
||||||
|
|
||||||
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
|
// If not, see http://www.gnu.org/licenses/
|
||||||
|
|
||||||
|
// Official SVN repository and contact information can be found at
|
||||||
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
|
#ifndef _STRINGUTIL_H_
|
||||||
|
#define _STRINGUTIL_H_
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "Common.h"
|
||||||
|
|
||||||
|
std::string StringFromFormat(const char* format, ...);
|
||||||
|
void ToStringFromFormat(std::string* out, const char* format, ...);
|
||||||
|
|
||||||
|
// WARNING - only call once with a set of args!
|
||||||
|
void StringFromFormatV(std::string* out, const char* format, va_list args);
|
||||||
|
// Cheap!
|
||||||
|
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
|
||||||
|
|
||||||
|
// Good
|
||||||
|
std::string ArrayToString(const u8 *data, u32 size, u32 offset = 0, int line_len = 20, bool Spaces = true);
|
||||||
|
|
||||||
|
|
||||||
|
template<size_t Count>
|
||||||
|
inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
CharArrayFromFormatV(out, Count, format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::string StripSpaces(const std::string &s);
|
||||||
|
std::string StripQuotes(const std::string &s);
|
||||||
|
std::string StripNewline(const std::string &s);
|
||||||
|
// Thousand separator. Turns 12345678 into 12,345,678
|
||||||
|
std::string ThS(int a, bool b = true, int Spaces = 0);
|
||||||
|
|
||||||
|
std::string StringFromInt(int value);
|
||||||
|
std::string StringFromBool(bool value);
|
||||||
|
|
||||||
|
bool TryParseInt(const char* str, int* outVal);
|
||||||
|
bool TryParseBool(const char* str, bool* output);
|
||||||
|
bool TryParseUInt(const std::string& str, u32* output);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: kill this
|
||||||
|
bool AsciiToHex(const char* _szValue, u32& result);
|
||||||
|
u32 Ascii2Hex(std::string _Text);
|
||||||
|
std::string Hex2Ascii(u32 _Text);
|
||||||
|
|
||||||
|
std::string TabsToSpaces(int tab_size, const std::string &in);
|
||||||
|
|
||||||
|
void SplitString(const std::string& str, const std::string& delim, std::vector<std::string>& output);
|
||||||
|
int ChooseStringFrom(const char* str, const char* * items);
|
||||||
|
|
||||||
|
|
||||||
|
// "C:\Windows\winhelp.exe" to "C:\Windows\", "winhelp", "exe"
|
||||||
|
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension);
|
||||||
|
// "C:\Windows\winhelp.exe" to "winhelp.exe"
|
||||||
|
std::string PathToFilename(std::string Path);
|
||||||
|
|
||||||
|
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename);
|
||||||
|
void NormalizeDirSep(std::string* str);
|
||||||
|
|
||||||
|
#endif // _STRINGUTIL_H_
|
|
@ -23,6 +23,8 @@
|
||||||
#include "wx/wx.h"
|
#include "wx/wx.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
std::string executableDirectory;
|
||||||
|
|
||||||
class Desmume: public wxApp
|
class Desmume: public wxApp
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -409,6 +411,14 @@ bool Desmume::OnInit()
|
||||||
DesmumeFrame *frame = new DesmumeFrame((char*)EMU_DESMUME_NAME_AND_VERSION());
|
DesmumeFrame *frame = new DesmumeFrame((char*)EMU_DESMUME_NAME_AND_VERSION());
|
||||||
frame->Show(true);
|
frame->Show(true);
|
||||||
|
|
||||||
|
char *p, *a;
|
||||||
|
std::string b = wxStandardPaths::Get().GetExecutablePath();
|
||||||
|
a = const_cast<char*>(b.c_str());
|
||||||
|
p = a + lstrlen(a);
|
||||||
|
while (p >= a && *p != '\\') p--;
|
||||||
|
if (++p >= a) *p = 0;
|
||||||
|
|
||||||
|
executableDirectory = std::string(a);
|
||||||
SPADInitialize PADInitialize;
|
SPADInitialize PADInitialize;
|
||||||
PADInitialize.padNumber = 1;
|
PADInitialize.padNumber = 1;
|
||||||
extern void Initialize(void *init);
|
extern void Initialize(void *init);
|
||||||
|
@ -425,7 +435,7 @@ DesmumeFrame::DesmumeFrame(const wxString& title)
|
||||||
: wxFrame(NULL, wxID_ANY, title)
|
: wxFrame(NULL, wxID_ANY, title)
|
||||||
{
|
{
|
||||||
|
|
||||||
this->SetSize(256,384+46);//why 46?
|
this->SetClientSize(256,384);
|
||||||
|
|
||||||
wxMenu *fileMenu = new wxMenu;
|
wxMenu *fileMenu = new wxMenu;
|
||||||
wxMenu *emulationMenu = new wxMenu;
|
wxMenu *emulationMenu = new wxMenu;
|
||||||
|
|
Loading…
Reference in New Issue