/* 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 . */ #pragma once //#include "Common.h" #include "AppConfig.h" #include "Utilities/HashMap.h" #include "Utilities/SafeArray.h" #include 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().data(), src.length() * sizeof( wxChar ) ); } }; typedef std::vector 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" = ", value.c_str())); } wxString getSection(const wxChar* key, const wxString& value) const { return getString(wxsFormat(L"[%s%s%s]", key, value.IsEmpty() ? L"" : L" = ", value.c_str())); } // Gets an integer representation of the 'value' for the given key int getInt(const wxChar* key) const { return wxStrtoul(getString(key), NULL, 0); } // 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)); } wxString getString(const char* key) const { return getString(fromUTF8(key)); } int getInt(const char* key) const { return getInt(fromUTF8(key)); } u8 getU8(const char* key) const { return getU8(fromUTF8(key)); } bool getBool(const char* key) const { return getBool(fromUTF8(key)); } }; // -------------------------------------------------------------------------------------- // 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 pxDictionary 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 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();