mirror of https://github.com/PCSX2/pcsx2.git
220 lines
6.3 KiB
C++
220 lines
6.3 KiB
C++
/* PCSX2 - PS2 Emulator for PCs
|
|
* Copyright (C) 2002-2010 PCSX2 Dev Team
|
|
*
|
|
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
|
|
* of the GNU Lesser General Public License as published by the Free Software Found-
|
|
* ation, either version 3 of the License, or (at your option) any later version.
|
|
*
|
|
* PCSX2 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 PCSX2.
|
|
* If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
//#include "Common.h"
|
|
#include "AppConfig.h"
|
|
#include "Utilities/HashMap.h"
|
|
|
|
#include <unordered_map>
|
|
#include <wx/wfstream.h>
|
|
|
|
struct key_pair;
|
|
struct Game_Data;
|
|
|
|
class StringHashNoCase
|
|
{
|
|
public:
|
|
StringHashNoCase() {}
|
|
|
|
HashTools::hash_key_t operator()( const wxString& src ) const
|
|
{
|
|
return HashTools::Hash( (const char *)src.Lower().wc_str(), src.length() * sizeof( wxChar ) );
|
|
}
|
|
};
|
|
|
|
|
|
typedef std::vector<key_pair> KeyPairArray;
|
|
|
|
struct key_pair {
|
|
wxString key;
|
|
wxString value;
|
|
|
|
key_pair() {}
|
|
key_pair(const wxString& _key, const wxString& _value)
|
|
: key(_key) , value(_value) {}
|
|
|
|
void Clear() {
|
|
key.clear();
|
|
value.clear();
|
|
}
|
|
|
|
// Performs case-insensitive compare against the key value.
|
|
bool CompareKey( const wxString& cmpto ) const {
|
|
return key.CmpNoCase(cmpto) == 0;
|
|
}
|
|
|
|
bool IsOk() const {
|
|
return !key.IsEmpty();
|
|
}
|
|
|
|
wxString toString() const {
|
|
if (key[0] == '[') {
|
|
pxAssertDev( key.EndsWith(L"]"), "Malformed multiline key detected: missing end bracket!" );
|
|
|
|
// 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 {
|
|
// Note: 6 char padding on the l-value makes things look nicer.
|
|
return wxsFormat(L"%-6s = %s\n", key.c_str(), value.c_str() );
|
|
}
|
|
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// Game_Data
|
|
// --------------------------------------------------------------------------------------
|
|
// This container is more or less required to be a simple struct (POD classification) --
|
|
// no virtuals and no inheritance. This is because it is used in a std::vector, so POD
|
|
// makes things... smoother.
|
|
struct Game_Data
|
|
{
|
|
wxString id; // Serial Identification Code
|
|
KeyPairArray kList; // List of all (key, value) pairs for game data
|
|
|
|
Game_Data(const wxString& _id = wxEmptyString)
|
|
: id(_id) {}
|
|
|
|
// Performs a case-insensitive compare of two IDs, returns TRUE if the IDs match
|
|
// or FALSE if the ids differ in a case-insensitive way.
|
|
bool CompareId( const wxString& _id ) const {
|
|
return id.CmpNoCase(_id) == 0;
|
|
}
|
|
|
|
void clear() {
|
|
id.clear();
|
|
kList.clear();
|
|
}
|
|
|
|
bool keyExists(const wxChar* key) const;
|
|
void deleteKey(const wxChar* key);
|
|
wxString getString(const wxChar* key) const;
|
|
void writeString(const wxString& key, const wxString& value);
|
|
void writeBool(const wxString& key, bool value);
|
|
|
|
bool IsOk() const {
|
|
return !id.IsEmpty();
|
|
}
|
|
|
|
bool sectionExists(const wxChar* key, const wxString& value) const {
|
|
return keyExists(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", WX_STR(value)));
|
|
}
|
|
|
|
wxString getSection(const wxChar* key, const wxString& value) const {
|
|
return getString(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", WX_STR(value)).wx_str());
|
|
}
|
|
|
|
// Gets an integer representation of the 'value' for the given key
|
|
int getInt(const wxChar* key) const {
|
|
unsigned long val;
|
|
getString(key).ToULong(&val);
|
|
return val;
|
|
}
|
|
|
|
// Gets a u8 representation of the 'value' for the given key
|
|
u8 getU8(const wxChar* key) const {
|
|
return (u8)wxAtoi(getString(key));
|
|
}
|
|
|
|
// Gets a bool representation of the 'value' for the given key
|
|
bool getBool(const wxChar* key) const {
|
|
return !!wxAtoi(getString(key));
|
|
}
|
|
|
|
bool keyExists(const char* key) const {
|
|
return keyExists(fromUTF8(key).wx_str());
|
|
}
|
|
|
|
bool keyExists(const wxString& key) const {
|
|
return keyExists(key.wx_str());
|
|
}
|
|
|
|
wxString getString(const char* key) const {
|
|
return getString(fromUTF8(key).wx_str());
|
|
}
|
|
|
|
int getInt(const char* key) const {
|
|
return getInt(fromUTF8(key).wx_str());
|
|
}
|
|
|
|
u8 getU8(const char* key) const {
|
|
return getU8(fromUTF8(key).wx_str());
|
|
}
|
|
|
|
bool getBool(const char* key) const {
|
|
return getBool(fromUTF8(key).wx_str());
|
|
}
|
|
|
|
bool getBool(const wxString& key) const {
|
|
return getBool(key.wx_str());
|
|
}
|
|
};
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// IGameDatabase
|
|
// --------------------------------------------------------------------------------------
|
|
class IGameDatabase
|
|
{
|
|
public:
|
|
virtual ~IGameDatabase() throw() {}
|
|
|
|
virtual wxString getBaseKey() const=0;
|
|
virtual bool findGame(Game_Data& dest, const wxString& id)=0;
|
|
virtual Game_Data* createNewGame( const wxString& id )=0;
|
|
virtual void updateGame(const Game_Data& game)=0;
|
|
};
|
|
|
|
typedef std::unordered_map<wxString, Game_Data*, StringHashNoCase> GameDataHash;
|
|
|
|
// --------------------------------------------------------------------------------------
|
|
// BaseGameDatabaseImpl
|
|
// --------------------------------------------------------------------------------------
|
|
// [TODO] Create a version of this that uses google hashsets; should be several magnitudes
|
|
// faster that way.
|
|
class BaseGameDatabaseImpl : public IGameDatabase
|
|
{
|
|
protected:
|
|
GameDataHash gHash; // hash table of game serials matched to their gList indexes!
|
|
wxString m_baseKey;
|
|
|
|
std::vector<Game_Data*> m_BlockTable;
|
|
uint m_BlockTableWritePos;
|
|
int m_CurBlockWritePos;
|
|
int m_GamesPerBlock;
|
|
|
|
public:
|
|
BaseGameDatabaseImpl();
|
|
virtual ~BaseGameDatabaseImpl() throw();
|
|
|
|
wxString getBaseKey() const { return m_baseKey; }
|
|
void setBaseKey( const wxString& key ) { m_baseKey = key; }
|
|
|
|
bool findGame(Game_Data& dest, const wxString& id);
|
|
Game_Data* createNewGame( const wxString& id );
|
|
void updateGame(const Game_Data& game);
|
|
};
|
|
|
|
extern IGameDatabase* AppHost_GetGameDatabase();
|