Fix gruesome errors in database loading/saving.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3191 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-06-10 11:27:30 +00:00
parent d2b6171ce8
commit e285ff4b50
8 changed files with 99 additions and 36 deletions

View File

@ -20,6 +20,47 @@
#include <wx/tokenzr.h>
#include <wx/gdicmn.h> // for wxPoint/wxRect stuff
// --------------------------------------------------------------------------------------
// pxToUTF8
// --------------------------------------------------------------------------------------
// Converts a string to UTF8 and provides an interface for getting its length.
class pxToUTF8
{
DeclareNoncopyableObject( pxToUTF8 );
protected:
wxCharBuffer m_result;
int m_length;
public:
explicit pxToUTF8(const wxString& src)
: m_result( src.ToUTF8() )
{
m_length = -1;
}
size_t Length()
{
if( -1 == m_length )
m_length = strlen( m_result );
return m_length;
}
void Convert( const wxString& src )
{
m_result = src.ToUTF8();
m_length = -1;
}
const char* data() const { return m_result; }
operator const char*() const
{
return m_result.data();
}
};
extern void px_fputs( FILE* fp, const char* src );
extern wxString fromUTF8( const char* src );

View File

@ -82,7 +82,10 @@ void pxWriteLine( wxOutputStream& output )
void pxWriteLine( wxOutputStream& output, const wxString& text )
{
if( !text.IsEmpty() )
output.Write(text.ToUTF8(), text.Length());
{
pxToUTF8 utf8(text);
output.Write(utf8, utf8.Length());
}
pxWriteLine( output );
}
@ -92,7 +95,8 @@ void pxWriteMultiline( wxOutputStream& output, const wxString& src )
wxString result( src );
result.Replace( L"\r\n", L"\n" );
result.Replace( L"\r", wxEmptyString );
result.Replace( L"\r", L"\n" );
output.Write(result.ToUTF8(), result.Length());
pxToUTF8 utf8(result);
output.Write(utf8, utf8.Length());
}

View File

@ -19,37 +19,40 @@ void DataBase_Loader::doError(const wxString& line, key_pair& keyPair, bool doMs
// [/section]
//
// ... where the =value part is OPTIONAL.
void DataBase_Loader::extractMultiLine(key_pair& keyPair, wxInputStream& ffile) {
bool DataBase_Loader::extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& ffile) {
if (!keyPair.key.EndsWith(L"]")) {
doError(keyPair.key, keyPair, true);
return;
if (line[0] != L'[') return false; // All multiline sections begin with a '['!
if (!line.EndsWith(L"]")) {
doError(line, keyPair, true);
return false;
}
keyPair.key = line;
// Use Mid() to strip off the left and right side brackets.
ParsedAssignmentString set( keyPair.key.Mid(1, keyPair.key.Length()-2) );
wxString midLine(line.Mid(1, line.Length()-2));
wxString lvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false));
//wxString rvalue(midLine.AfterFirst(L'=').Trim(true).Trim(false));
wxString endString;
endString.Printf( L"[/%s]", set.lvalue.c_str() );
endString.Printf( L"[/%s]", lvalue.c_str() );
for(;;) {
while(!ffile.Eof()) {
pxReadLine( ffile, m_dest, m_intermediate );
if (m_dest == endString) break;
keyPair.value += m_dest + L"\n";
}
return true;
}
void DataBase_Loader::extract(const wxString& line, key_pair& keyPair, wxInputStream& reader) {
keyPair.key = line;
keyPair.key.clear();
keyPair.value.clear();
if( line.IsEmpty() ) return;
if (keyPair.key[0] == L'[') {
extractMultiLine(keyPair, reader);
return;
}
if( extractMultiLine(line, keyPair, reader) ) return;
if( !pxParseAssignmentString( line, keyPair.key, keyPair.value ) ) return;
if( keyPair.value.IsEmpty() )
doError(line, keyPair, true);

View File

@ -31,8 +31,15 @@ struct key_pair {
wxString toString() const {
if (key[0] == '[') {
pxAssumeDev( key.EndsWith(L"]"), "Malformed multiline key detected: missing end bracket!" );
return wxsFormat( L"%s\n%s\n[/%s\n",
key.c_str(), value.c_str(), key.Mid(1, key.length()-1).c_str()
// Terminating tag must be written without the "rvalue" -- in the form of:
// [/patches]
// Use Mid() to strip off the left and right side brackets.
wxString midLine(key.Mid(1, key.Length()-2));
wxString keyLvalue(midLine.BeforeFirst(L'=').Trim(true).Trim(false));
return wxsFormat( L"%s\n%s[/%s]\n",
key.c_str(), value.c_str(), keyLvalue.c_str()
);
}
else {
@ -70,7 +77,7 @@ class DataBase_Loader {
protected:
bool isComment(const wxString& s);
void doError(const wxString& line, key_pair& keyPair, bool doMsg = false);
void extractMultiLine(key_pair& keyPair, wxInputStream& reader);
bool extractMultiLine(const wxString& line, key_pair& keyPair, wxInputStream& reader);
void extract(const wxString& line, key_pair& keyPair, wxInputStream& reader);
const wxString m_emptyString; // empty string for returning stuff .. never modify!

View File

@ -1385,7 +1385,7 @@ void PluginManager::SendSettingsFolder()
ScopedLock lock( m_mtx_PluginStatus );
if( m_SettingsFolder.IsEmpty() ) return;
wxCharBuffer utf8buffer( m_SettingsFolder.ToUTF8() );
pxToUTF8 utf8buffer( m_SettingsFolder );
const PluginInfo* pi = tbl_PluginInfo; do {
if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetSettingsDir( utf8buffer );
@ -1412,7 +1412,7 @@ void PluginManager::SendLogFolder()
ScopedLock lock( m_mtx_PluginStatus );
if( m_LogFolder.IsEmpty() ) return;
wxCharBuffer utf8buffer( m_LogFolder.ToUTF8() );
pxToUTF8 utf8buffer( m_LogFolder );
const PluginInfo* pi = tbl_PluginInfo; do {
if( m_info[pi->id] ) m_info[pi->id]->CommonBindings.SetLogFolder( utf8buffer );

View File

@ -111,8 +111,9 @@ void SaveStateBase::FreezeBios()
memzero( descin );
memzero( desccmp );
memcpy_fast( descin, descout.ToUTF8().data(), descout.Length() );
memcpy_fast( desccmp, descout.ToUTF8().data(), descout.Length() );
pxToUTF8 utf8(descout);
memcpy_fast( descin, utf8, utf8.Length() );
memcpy_fast( desccmp, utf8, utf8.Length() );
// ... and only freeze bios info once per state, since the user msg could
// become really annoying on a corrupted state or something. (have to always
@ -130,7 +131,7 @@ void SaveStateBase::FreezeBios()
Console.Indent(2).Error(
"Current Version: %s\n"
"Savestate Version: %s\n",
descout.ToUTF8().data(), descin
utf8.data(), descin
);
}
}

View File

@ -359,14 +359,17 @@ namespace Panels
wxTextCtrl* commentBox;
wxTextCtrl* patchesBox;
pxCheckBox* gameFixes[NUM_OF_GAME_FIXES];
public:
GameDatabasePanel( wxWindow* parent );
virtual ~GameDatabasePanel() throw() { }
void PopulateFields();
void WriteFieldsToDB();
void Search_Click( wxCommandEvent& evt );
void Apply();
void AppStatusEvent_OnSettingsApplied();
protected:
void PopulateFields();
bool WriteFieldsToDB();
void Search_Click( wxCommandEvent& evt );
};
class SettingsDirPickerPanel : public DirPickerPanel

View File

@ -141,11 +141,12 @@ void Panels::GameDatabasePanel::PopulateFields() {
else GameDB->writeBool(wxT(_key), _value); \
}
void Panels::GameDatabasePanel::WriteFieldsToDB() {
// returns True if the database is modified, or FALSE if no changes to save.
bool Panels::GameDatabasePanel::WriteFieldsToDB() {
wxString wxStr( serialBox->GetValue() );
if (wxStr.IsEmpty()) return;
if (wxStr == GameDB->getString("Serial")) {
if (wxStr.IsEmpty()) return false;
if (wxStr != GameDB->getString("Serial")) {
GameDB->addGame(wxStr);
}
@ -163,6 +164,7 @@ void Panels::GameDatabasePanel::WriteFieldsToDB() {
writeGameFixToDB("IPUWaitHack", gameFixes[6]->GetValue());
writeGameFixToDB("EETimingHack", gameFixes[7]->GetValue());
writeGameFixToDB("SkipMPEGHack", gameFixes[8]->GetValue());
return true;
}
void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
@ -178,10 +180,12 @@ void Panels::GameDatabasePanel::Search_Click(wxCommandEvent& evt) {
}
void Panels::GameDatabasePanel::Apply() {
if( WriteFieldsToDB() )
{
Console.WriteLn("Saving changes to Game Database...");
WriteFieldsToDB();
GameDB->saveToFile();
}
}
void Panels::GameDatabasePanel::AppStatusEvent_OnSettingsApplied()
{