From 15c0132fd080003f2bf47749e30e1f724b249341 Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Mon, 29 Mar 2010 07:30:52 +0200 Subject: dynamic registration of songloading_strategies with static template --- src/base/songloading/songloader.cpp | 27 ++++----- src/base/songloading/songloader.hpp | 6 +- src/base/songloading/songloading_strategy.hpp | 9 +++ .../songloading_strategy_base_factory.cpp | 41 ++++++++++++++ .../songloading_strategy_base_factory.hpp | 55 ++++++++++++++++++ .../songloading/songloading_strategy_factory.hpp | 66 ++++++++++++++++++++++ src/base/songloading/songloading_strategy_txt.cpp | 8 +-- src/base/songloading/songloading_strategy_txt.hpp | 10 +++- src/base/songloading/songloading_strategy_xml.hpp | 5 ++ 9 files changed, 202 insertions(+), 25 deletions(-) create mode 100644 src/base/songloading/songloading_strategy_base_factory.cpp create mode 100644 src/base/songloading/songloading_strategy_base_factory.hpp create mode 100644 src/base/songloading/songloading_strategy_factory.hpp (limited to 'src/base') diff --git a/src/base/songloading/songloader.cpp b/src/base/songloading/songloader.cpp index 2f3d3508..0524d18c 100644 --- a/src/base/songloading/songloader.cpp +++ b/src/base/songloading/songloader.cpp @@ -37,22 +37,10 @@ namespace usdx Songloader::Songloader(void) { - // add different strategies to map - strategies[L".txt"] = new SongloadingStrategyTxt(); - strategies[L".xml"] = new SongloadingStrategyXml(); - } - - void remove_element(std::pair e) - { - delete e.second; - e.second = NULL; } Songloader::~Songloader(void) { - // clear memory for all elements in the map - std::for_each(strategies.begin(), strategies.end(), - remove_element); strategies.clear(); // remove reference from singleton to make regeneration possible @@ -71,24 +59,31 @@ namespace usdx Song *Songloader::load_header(const boost::filesystem::wpath& filename) { std::wstring ext = extension(filename); - std::map::iterator it = strategies.find(ext); + std::map::iterator it = strategies.find(ext); if (it == strategies.end()) { LOG4CXX_WARN(log, L"No SongloadingStrategy found for file extension: '" << ext << L"'"); throw NoStrategyException("Unknown file format."); } - return it->second->load_header(filename); + return it->second->get_songloader()->load_header(filename); } Song* Songloader::load_song(Song* song) { std::wstring ext = extension(song->get_filename()); - std::map::iterator it = strategies.find(ext); + std::map::iterator it = strategies.find(ext); if (it == strategies.end()) { LOG4CXX_WARN(log, L"No SongloadingStrategy found for file extension: '" << ext << L"'"); throw NoStrategyException("Unknown file format."); } - return it->second->load_song(song); + return it->second->get_songloader()->load_song(song); + } + + void Songloader::add_strategy(SongloadingStrategyBaseFactory *factory) + { + if (factory) { + strategies[factory->get_fileextension()] = factory; + } } }; diff --git a/src/base/songloading/songloader.hpp b/src/base/songloading/songloader.hpp index 0e8a6bd1..ac18f41d 100644 --- a/src/base/songloading/songloader.hpp +++ b/src/base/songloading/songloader.hpp @@ -30,9 +30,9 @@ #include #include #include -#include "songloading_strategy.hpp" #include "song.hpp" #include "utils/base_exception.hpp" +#include "songloading_strategy_base_factory.hpp" namespace usdx { @@ -50,7 +50,7 @@ namespace usdx Songloader(void); - std::map strategies; + std::map strategies; /** * Singleton @@ -64,6 +64,8 @@ namespace usdx Song* load_header(const boost::filesystem::wpath& filename); Song* load_song(Song* song); + + void add_strategy(SongloadingStrategyBaseFactory* strategie); }; }; diff --git a/src/base/songloading/songloading_strategy.hpp b/src/base/songloading/songloading_strategy.hpp index 48e115b7..3178f6ed 100644 --- a/src/base/songloading/songloading_strategy.hpp +++ b/src/base/songloading/songloading_strategy.hpp @@ -31,6 +31,15 @@ #include #include "song.hpp" +#define _USDX_JOIN(strategy, line) _USDX_JOIN1(strategy, line) +#define _USDX_JOIN1(strategy, line) autoregistration__strategy__##line + +/* Macros to simplify registration of SongLoadingStrategy */ +#define REGISTER_SONGLOADING_STRATEGY(strategy) \ + static SongloadingStrategyFactory \ + _USDX_JOIN(strategy, __LINE__) + + namespace usdx { class SongloadingStrategy diff --git a/src/base/songloading/songloading_strategy_base_factory.cpp b/src/base/songloading/songloading_strategy_base_factory.cpp new file mode 100644 index 00000000..9f8333b4 --- /dev/null +++ b/src/base/songloading/songloading_strategy_base_factory.cpp @@ -0,0 +1,41 @@ +/* + * UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#include "songloading_strategy_base_factory.hpp" +#include "songloader.hpp" + +namespace usdx +{ + SongloadingStrategyBaseFactory::SongloadingStrategyBaseFactory(std::wstring fileextension) : fileextension(fileextension) + { + Songloader::get_instance()->add_strategy(this); + } + + std::wstring SongloadingStrategyBaseFactory::get_fileextension(void) + { + return fileextension; + } +}; diff --git a/src/base/songloading/songloading_strategy_base_factory.hpp b/src/base/songloading/songloading_strategy_base_factory.hpp new file mode 100644 index 00000000..ae20b1ce --- /dev/null +++ b/src/base/songloading/songloading_strategy_base_factory.hpp @@ -0,0 +1,55 @@ +/* + * UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef SONGLOADING_STRATEGY_BASE_FACTORY_HPP +#define SONGLOADING_STRATEGY_BASE_FACTORY_HPP + +#include +#include "songloading_strategy.hpp" + +namespace usdx +{ + class SongloadingStrategyBaseFactory + { + private: + /// no copy + SongloadingStrategyBaseFactory(SongloadingStrategyBaseFactory&) {}; + + /// no copy + void operator=(SongloadingStrategyBaseFactory&) {}; + + std::wstring fileextension; + + public: + SongloadingStrategyBaseFactory(std::wstring fileextension); + virtual ~SongloadingStrategyBaseFactory(void) {}; + + virtual SongloadingStrategy *get_songloader(void) = 0; + std::wstring get_fileextension(void); + }; +}; + +#endif diff --git a/src/base/songloading/songloading_strategy_factory.hpp b/src/base/songloading/songloading_strategy_factory.hpp new file mode 100644 index 00000000..e523560d --- /dev/null +++ b/src/base/songloading/songloading_strategy_factory.hpp @@ -0,0 +1,66 @@ +/* + * UltraStar Deluxe - Karaoke Game + * + * UltraStar Deluxe is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * 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; either version 2 + * of the License, or (at your option) any later version. + * + * 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 for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +#ifndef SONGLOADING_STRATEGY_FACTORY_HPP +#define SONGLOADING_STRATEGY_FACTORY_HPP + +#include "songloading_strategy_base_factory.hpp" + +namespace usdx +{ + template + class SongloadingStrategyFactory : public SongloadingStrategyBaseFactory + { + private: + T *songloader; + + public: + SongloadingStrategyFactory(void) : + SongloadingStrategyBaseFactory(T::get_fileextension()), + songloader(NULL) + { + } + + virtual ~SongloadingStrategyFactory(void) + { + if (songloader) { + delete songloader; + songloader = NULL; + } + } + + T *get_songloader(void) + { + if (!songloader) { + songloader = new T(); + } + + return songloader; + } + }; +}; + +#endif diff --git a/src/base/songloading/songloading_strategy_txt.cpp b/src/base/songloading/songloading_strategy_txt.cpp index 7560a9c2..b80289ee 100644 --- a/src/base/songloading/songloading_strategy_txt.cpp +++ b/src/base/songloading/songloading_strategy_txt.cpp @@ -32,7 +32,7 @@ #include #include "songloading_strategy_txt.hpp" -#include "utils/file.hpp" +#include "utils/unicode_file.hpp" #include "utils/locale_independent_float.hpp" namespace usdx @@ -83,7 +83,7 @@ namespace usdx { LOG4CXX_DEBUG(log, L"Starting loading song from file: " << song->get_filename()); - File file(song->get_filename()); + UnicodeFile file(song->get_filename()); int line_number = 0; while (file.stream().good() && parse_line(song, file, ++line_number)); @@ -93,7 +93,7 @@ namespace usdx return song; } - bool SongloadingStrategyTxt::parse_line(Song* song, File& file, const int line_number) + bool SongloadingStrategyTxt::parse_line(Song* song, UnicodeFile& file, const int line_number) { try { std::wstring line; @@ -191,7 +191,7 @@ namespace usdx Song* SongloadingStrategyTxt::load_header(const boost::filesystem::wpath& filename) { - File file(filename); + UnicodeFile file(filename); std::wstring line; std::map header_fields; diff --git a/src/base/songloading/songloading_strategy_txt.hpp b/src/base/songloading/songloading_strategy_txt.hpp index 13851e6e..6177a5d3 100644 --- a/src/base/songloading/songloading_strategy_txt.hpp +++ b/src/base/songloading/songloading_strategy_txt.hpp @@ -31,7 +31,8 @@ #include #include #include "songloading_strategy.hpp" -#include "utils/file.hpp" +#include "songloading_strategy_factory.hpp" +#include "utils/unicode_file.hpp" namespace usdx { @@ -45,19 +46,22 @@ namespace usdx */ std::pair split_header_field(std::wstring &line); - bool parse_line(Song* song, File& file, const int line_number); + bool parse_line(Song* song, UnicodeFile& file, const int line_number); void parse_newline(Song* song, std::wistringstream& linestream, const int line_number); void parse_bpm(Song* song, std::wistringstream& linestream, const int line_number); void parse_note(Song* song, wchar_t type, std::wistringstream& linestream, const int line_number); - public: SongloadingStrategyTxt(); virtual ~SongloadingStrategyTxt(); virtual Song* load_song(Song* song); virtual Song* load_header(const boost::filesystem::wpath& filename); + + static std::wstring get_fileextension(void) { return L".txt"; }; }; + + REGISTER_SONGLOADING_STRATEGY(SongloadingStrategyTxt); }; #endif diff --git a/src/base/songloading/songloading_strategy_xml.hpp b/src/base/songloading/songloading_strategy_xml.hpp index 76e3f76e..38637646 100644 --- a/src/base/songloading/songloading_strategy_xml.hpp +++ b/src/base/songloading/songloading_strategy_xml.hpp @@ -29,6 +29,7 @@ #include #include "songloading_strategy.hpp" +#include "songloading_strategy_factory.hpp" namespace usdx { @@ -40,7 +41,11 @@ namespace usdx virtual Song* load_song(Song* song); virtual Song* load_header(const boost::filesystem::wpath& filename); + + static std::wstring get_fileextension(void) { return L".xml"; }; }; + + REGISTER_SONGLOADING_STRATEGY(SongloadingStrategyXml); }; #endif -- cgit v1.2.3