Author: suokko
Date: Sat Aug 23 18:08:44 2008
New Revision: 28884
URL: http://svn.gna.org/viewcvs/wesnoth?rev=28884&view=rev
Log:
Made config_cache 'just work' like old cofig loading code used to. It still
needs interface refactoring
Modified:
trunk/src/config_cache.cpp
trunk/src/config_cache.hpp
trunk/src/tests/main.cpp
trunk/src/tests/test_config_cache.cpp
Modified: trunk/src/config_cache.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/config_cache.cpp?rev=28884&r1=28883&r2=28884&view=diff
==============================================================================
--- trunk/src/config_cache.cpp (original)
+++ trunk/src/config_cache.cpp Sat Aug 23 18:08:44 2008
@@ -12,11 +12,34 @@
See the COPYING file for more details.
*/
+#include "config_cache.hpp"
#include "filesystem.hpp"
-#include "config_cache.hpp"
+#include "foreach.hpp"
+#include "gettext.hpp"
#include "game_config.hpp"
+#include "game_display.hpp"
+#include "loadscreen.hpp"
+#include "log.hpp"
+#include "marked-up_text.hpp"
+#include "show_dialog.hpp"
+#include "sha1.hpp"
+#include "serialization/binary_wml.hpp"
+#include "serialization/parser.hpp"
+
+#define ERR_CONFIG LOG_STREAM(err, config)
+#define LOG_CONFIG LOG_STREAM(info, config)
+#define DBG_CONFIG LOG_STREAM(debug, config)
+
+#define ERR_FS LOG_STREAM(err, filesystem)
namespace game_config {
+ config_cache config_cache::cache_;
+
+ config_cache& config_cache::instance()
+ {
+ return cache_;
+ }
+
config_cache::config_cache() :
game_config_(),
force_valid_cache_(false),
@@ -37,12 +60,23 @@
void config_cache::set_config_root(const std::string& path)
{
+ if (path == config_root_)
+ return;
+ dirty_ = true;
config_root_ = path;
}
std::string config_cache::get_user_config_root() const
{
return user_config_root_;
+ }
+
+ void config_cache::set_user_config_root(const std::string& path)
+ {
+ if (path == user_config_root_)
+ return;
+ dirty_ = true;
+ user_config_root_ = path;
}
const preproc_map& config_cache::get_preproc_map() const
@@ -76,36 +110,223 @@
{
if (dirty_)
{
- reload_configs();
+ load_configs(game_config_, false);
} else {
game_config_.reset_translation();
game_config::load_config(game_config_.child("game_config"));
}
}
- config& config_cache::get_config()
+ config& config_cache::get_config(bool recheck_cache)
{
if (!dirty_)
return game_config_;
- reload_configs();
+ load_configs(game_config_, recheck_cache);
+ dirty_ = false;
+
+ return game_config_;
+ }
+
+ void config_cache::read_configs(config& cfg, std::string& error_log)
+ {
+ preproc_map defines_map(defines_map_);
+
+ std::string user_error_log;
+ //read the file and then write to the cache
+ scoped_istream stream = preprocess_file(config_root_,
&defines_map, &error_log);
+
+ //reset the parse counter before reading the game files
+ if (loadscreen::global_loadscreen) {
+ loadscreen::global_loadscreen->parser_counter = 0;
+ }
+
+ read(cfg, *stream, &error_log);
+ // clone and put the gfx rules aside so that we can prepend the
add-on
+ // rules to them.
+ config core_terrain_rules;
+ // FIXME: there should be a canned algorithm for cloning
child_list objects,
+ // along with the memory their elements point to... little
implementation detail.
+ foreach(config const* p_cfg,
game_config_.get_children("terrain_graphics")) {
+ core_terrain_rules.add_child("terrain_graphics",
*p_cfg);
+ }
+ game_config_.clear_children("terrain_graphics");
+
+ // load usermade add-ons
+// const std::string user_campaign_dir = get_addon_campaigns_dir();
+ std::vector< std::string > error_addons;
+ // Scan addon directories
+ std::vector<std::string> user_addons;
+
+
get_files_in_dir(user_config_root_,NULL,&user_addons,ENTIRE_FILE_PATH);
+
+ // Load the addons
+ for(std::vector<std::string>::const_iterator uc =
user_addons.begin(); uc != user_addons.end(); ++uc) {
+ std::string oldstyle_cfg = *uc + ".cfg";
+ std::string main_cfg = *uc + "/_main.cfg";
+ std::string toplevel;
+ if (file_exists(oldstyle_cfg))
+ toplevel = oldstyle_cfg;
+ else if (file_exists(main_cfg))
+ toplevel = main_cfg;
+ else
+ continue;
+
+ try {
+ preproc_map addon_defines_map(defines_map);
+ scoped_istream stream =
preprocess_file(toplevel, &addon_defines_map);
+
+ std::string addon_error_log;
+
+ config umc_cfg;
+ read(umc_cfg, *stream, &addon_error_log);
+
+ if (addon_error_log.empty()) {
+ game_config_.append(umc_cfg);
+ } else {
+ user_error_log += addon_error_log;
+ error_addons.push_back(*uc);
+ }
+ } catch(config::error& err) {
+ ERR_CONFIG << "error reading usermade add-on '"
<< *uc << "'\n";
+ error_addons.push_back(*uc);
+ user_error_log += err.message + "\n";
+ } catch(preproc_config::error&) {
+ ERR_CONFIG << "error reading usermade add-on '"
<< *uc << "'\n";
+ error_addons.push_back(*uc);
+ //no need to modify the error log here, already
done by the preprocessor
+ } catch(io_exception&) {
+ ERR_CONFIG << "error reading usermade add-on '"
<< *uc << "'\n";
+ error_addons.push_back(*uc);
+ }
+ if(error_addons.empty() == false) {
+ std::stringstream msg;
+ msg << _n("The following add-on had errors and
could not be loaded:",
+ "The following add-ons had
errors and could not be loaded:",
+ error_addons.size());
+ for(std::vector<std::string>::const_iterator i
= error_addons.begin(); i != error_addons.end(); ++i) {
+ msg << "\n" << *i;
+ }
+
+ msg << "\n" << _("ERROR DETAILS:") << "\n" <<
font::nullify_markup(user_error_log);
+
+
gui::show_error_message(*game_display::get_singleton(),msg.str());
+ }
+ }
+
+ cfg.merge_children("units");
+ cfg.append(core_terrain_rules);
+
+ }
+
+ void config_cache::load_configs(config& cfg, bool recheck_cache)
+ {
+ bool is_valid = true;
+ std::stringstream defines_string;
+ for(preproc_map::const_iterator i = defines_map_.begin(); i !=
defines_map_.end(); ++i) {
+ if(i->second.value != "" || i->second.arguments.empty()
== false) {
+ is_valid = false;
+ ERR_CONFIG << "Preproc define not valid\n";
+ break;
+ }
+
+ defines_string << " " << i->first;
+ }
+ //std::string localename = get_locale().localename;
+ //str << "-lang_" << (localename.empty() ? "default" :
localename);
+
+ if(is_valid && use_cache_) {
+ const std::string& cache = get_cache_dir();
+ if(cache != "") {
+ sha1_hash sha(defines_string.str()); // use a
hash for a shorter display of the defines
+ const std::string fname = cache + "/cache-v" +
game_config::version + "-" + sha.display();
+ const std::string fname_checksum = fname +
".checksum";
+
+ file_tree_checksum dir_checksum;
+
+ if(!force_valid_cache_) {
+ try {
+ if(file_exists(fname_checksum))
{
+ config checksum_cfg;
+ scoped_istream stream =
istream_file(fname_checksum);
+ read(checksum_cfg,
*stream);
+ dir_checksum =
file_tree_checksum(checksum_cfg);
+ }
+ } catch(config::error&) {
+ ERR_CONFIG << "cache checksum
is corrupt\n";
+ } catch(io_exception&) {
+ ERR_CONFIG << "error reading
cache checksum\n";
+ }
+ }
+
+ if(force_valid_cache_) {
+ LOG_CONFIG << "skipping cache
validation (forced)\n";
+ }
+
+ if(file_exists(fname) && (force_valid_cache_ ||
(dir_checksum == data_tree_checksum(recheck_cache)))) {
+ LOG_CONFIG << "found valid cache at '"
<< fname << "' using it\n";
+ log_scope("read cache");
+ try {
+ scoped_istream stream =
istream_file(fname);
+ read_compressed(cfg, *stream);
+ return;
+ } catch(config::error&) {
+ ERR_CONFIG << "cache is
corrupt. Loading from files\n";
+ } catch(io_exception&) {
+ ERR_CONFIG << "error reading
cache. Loading from files\n";
+ }
+ }
+
+ LOG_CONFIG << "no valid cache found. Writing
cache to '" << fname << " with defines_map "<< defines_string.str() << "'\n";
+ DBG_CONFIG << ((use_cache_ &&
file_exists(fname)) ? "yes":"no ") << " " << dir_checksum.modified << "==" <<
data_tree_checksum().modified << " " << dir_checksum.nfiles << "==" <<
data_tree_checksum().nfiles << " " << dir_checksum.sum_size << "==" <<
data_tree_checksum().sum_size << "\n";
+
+ std::string error_log;
+
+ read_configs(cfg, error_log);
+
+ if(!error_log.empty()) {
+
gui::show_error_message(*game_display::get_singleton(),
+ _("Warning: Errors
occurred while loading game configuration files: '") +
+
font::nullify_markup(error_log));
+
+ } else {
+ try {
+ scoped_ostream cache =
ostream_file(fname);
+ write_compressed(*cache, cfg);
+ config checksum_cfg;
+
data_tree_checksum().write(checksum_cfg);
+ scoped_ostream checksum =
ostream_file(fname_checksum);
+ write(*checksum, checksum_cfg);
+ } catch(io_exception&) {
+ ERR_FS << "could not write to
cache '" << fname << "'\n";
+ }
+ }
+
+ return;
+ }
+ }
+
+ ERR_CONFIG << "caching cannot be done. Reading file\n";
+
+ std::string error_log;
+
+ read_configs(cfg, error_log);
+ if(!error_log.empty()) {
+ gui::show_error_message(*game_display::get_singleton(),
+ _("Warning: Errors occurred while
loading game configuration files: '") +
+ font::nullify_markup(error_log));
+
+ }
+ }
+
+ void config_cache::set_use_cache(bool use)
+ {
+ use_cache_ = use;
+ }
+
+ void config_cache::add_define(const std::string& define)
+ {
dirty_ = true;
-
- return game_config_;
- }
-
- void config_cache::reload_configs(bool recheck_cache)
- {
- file_tree_checksum checksum =
data_tree_checksum(recheck_cache);
- }
-
- void config_cache::set_use_cache(bool use)
- {
- use_cache_ = use;
- }
-
- void config_cache::add_define(const std::string& define)
- {
defines_map_[define] = preproc_define();
}
}
Modified: trunk/src/config_cache.hpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/config_cache.hpp?rev=28884&r1=28883&r2=28884&view=diff
==============================================================================
--- trunk/src/config_cache.hpp (original)
+++ trunk/src/config_cache.hpp Sat Aug 23 18:08:44 2008
@@ -34,6 +34,8 @@
std::string config_root_, user_config_root_;
preproc_map defines_map_;
+ void read_configs(config&, std::string&);
+
protected:
config_cache();
@@ -41,6 +43,7 @@
std::string get_config_root() const;
std::string get_user_config_root() const;
const preproc_map& get_preproc_map() const;
+ void load_configs(config& cfg, bool recheck_cache);
public:
static config_cache& instance();
@@ -48,13 +51,12 @@
void set_config_root(const std::string&);
void set_user_config_root(const std::string&);
- config& get_config();
+ config& get_config(bool recheck_cache = false);
void clear_defines();
void add_define(const std::string& define);
void reload_translations();
- void reload_configs(bool recheck_cache = false);
void set_use_cache(bool use);
};
Modified: trunk/src/tests/main.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/main.cpp?rev=28884&r1=28883&r2=28884&view=diff
==============================================================================
--- trunk/src/tests/main.cpp (original)
+++ trunk/src/tests/main.cpp Sat Aug 23 18:08:44 2008
@@ -19,6 +19,7 @@
#include "SDL.h"
+#include "config_cache.hpp"
#include "filesystem.hpp"
#include "game_config.hpp"
#include "game_errors.hpp"
@@ -53,6 +54,9 @@
game_config::use_dummylocales = true;
game_config::path = get_cwd();
+ load_language_list();
+
::init_textdomains(game_config::config_cache::instance().get_config());
+
// Initialize unit tests
SDL_Init(SDL_INIT_TIMER);
test_utils::get_fake_display();
@@ -68,7 +72,6 @@
boost::unit_test::unit_test_monitor.register_exception_translator<game::error>(&exception_translator_game);
boost::unit_test::unit_test_monitor.register_exception_translator<network::error>(&exception_translator_network);
boost::unit_test::unit_test_monitor.register_exception_translator<config::error>(&exception_translator_config);
- load_language_list();
}
~wesnoth_global_fixture()
{
Modified: trunk/src/tests/test_config_cache.cpp
URL:
http://svn.gna.org/viewcvs/wesnoth/trunk/src/tests/test_config_cache.cpp?rev=28884&r1=28883&r2=28884&view=diff
==============================================================================
--- trunk/src/tests/test_config_cache.cpp (original)
+++ trunk/src/tests/test_config_cache.cpp Sat Aug 23 18:08:44 2008
@@ -11,6 +11,9 @@
See the COPYING file for more details.
*/
+
+#define GETTEXT_DOMAIN "wesnoth"
+
#include <boost/test/auto_unit_test.hpp>
#include "config_cache.hpp"
@@ -102,6 +105,9 @@
std::string test_data_path("data/test/test/");
cache.set_config_root(test_data_path);
BOOST_CHECK_EQUAL(test_data_path, cache.get_config_root());
+ test_data_path = "invalid";
+ cache.set_user_config_root(test_data_path);
+ BOOST_CHECK_EQUAL(test_data_path, cache.get_user_config_root());
config test_config;
config* child = &test_config.add_child("textdomain");
@@ -116,7 +122,7 @@
cache.add_define("TEST_DEFINE");
child = &test_config.add_child("test_key");
- (*child)["define"] = _("testing translation reset");
+ (*child)["define"] = _("testing translation reset.");
BOOST_CHECK_EQUAL(test_config, cache.get_config());
@@ -138,7 +144,7 @@
(*child)["define"] = "test";
child = &test_config.add_child("test_key");
- (*child)["define"] = _("testing translation reset");
+ (*child)["define"] = _("testing translation reset.");
// Change language
const std::vector<language_def>& languages = get_languages();
@@ -152,7 +158,7 @@
BOOST_CHECK_MESSAGE( test_config != cache.get_config(), "Translation
update failed update translations!" );
- (*child)["define"] = _("test translation reset");
+ (*child)["define"] = _("testing translation reset.");
BOOST_CHECK_EQUAL(test_config, cache.get_config());
}
_______________________________________________
Wesnoth-commits mailing list
[email protected]
https://mail.gna.org/listinfo/wesnoth-commits