mail[Wesnoth-commits] r28884 - in /trunk/src: config_cache.cpp config_cache.hpp tests/main.cpp tests/test_config_cache.cpp


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by paniemin on August 23, 2008 - 18:08:
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());
 }




Related Messages


Powered by MHonArc, Updated Sat Aug 23 19:01:41 2008