Now the preprocessor output is also a stream, and so is the parser input, ...

...hence they can be plugged, yay. Also introduce a scoped_istream to
prevent leaking descriptors in case of exceptions. Once again, the
stream changes are purely on the interface level for the time being,
so there can be a slight performance hit when no cache is present. But
once the cache is built, everything should be fine, even faster than
it was before the changes. And isn't that the point of a cache?
This commit is contained in:
Guillaume Melquiond 2005-03-25 18:19:20 +00:00
parent 507183d9b2
commit d21e4149d6
19 changed files with 84 additions and 47 deletions

View File

@ -44,7 +44,8 @@ private:
int campaign_server::load_config()
{
read(cfg_, read_file(file_));
scoped_istream stream = stream_file(file_);
read(cfg_, *stream);
return lexical_cast_default<int>(cfg_["port"], 15002);
}
@ -90,9 +91,8 @@ void campaign_server::run()
network::send_data(construct_error("Campaign not found."),sock);
} else {
config cfg;
std::istream *stream = stream_file((*campaign)["filename"]);
scoped_istream stream = stream_file((*campaign)["filename"]);
read_compressed(cfg, *stream);
delete stream;
network::queue_data(cfg,sock);
const int downloads = lexical_cast_default<int>((*campaign)["downloads"],0)+1;

View File

@ -99,7 +99,8 @@ map_editor::map_editor(display &gui, gamemap &map, config &theme, config &game_c
// Perform some initializations that should only be performed
// the first time the editor object is created.
try {
read(prefs_, read_file(prefs_filename));
scoped_istream stream = stream_file(prefs_filename);
read(prefs_, *stream);
}
catch (config::error e) {
std::cerr << "Error when reading " << prefs_filename << ": "

View File

@ -227,7 +227,8 @@ int main(int argc, char** argv)
//Read the configuration af
config cfg;
try {
read(cfg, preprocess_file("data/game.cfg", &defines_map));
scoped_istream stream = preprocess_file("data/game.cfg", &defines_map);
read(cfg, *stream);
}
catch (config::error e) {
std::cerr << "Error when reading game config: '" << e.message << "'" << std::endl;

View File

@ -825,3 +825,13 @@ std::string get_binary_file_location(const std::string& type, const std::string&
return "";
}
void scoped_istream::operator=(std::istream *s)
{
delete stream;
stream = s;
}
scoped_istream::~scoped_istream()
{
delete stream;
}

View File

@ -15,6 +15,7 @@
#include <time.h>
#include <iosfwd>
#include <string>
#include <vector>
@ -139,4 +140,14 @@ const std::vector<std::string>& get_binary_paths(const std::string& type);
//the file isn't present
std::string get_binary_file_location(const std::string& type, const std::string& filename);
class scoped_istream {
std::istream *stream;
public:
scoped_istream(std::istream *s): stream(s) {}
void operator=(std::istream *);
std::istream &operator*() { return *stream; }
std::istream *operator->() { return stream; }
~scoped_istream();
};
#endif

View File

@ -1322,7 +1322,8 @@ bool load_font_config()
//config when changing languages
config cfg;
try {
read(cfg, preprocess_file("data/fonts.cfg"));
scoped_istream stream = preprocess_file("data/fonts.cfg");
read(cfg, *stream);
} catch(config::error&) {
std::cerr << "Could not read fonts.cfg\n";
return false;

View File

@ -256,7 +256,8 @@ void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, con
try {
if(file_exists(fname_checksum)) {
config checksum_cfg;
read(checksum_cfg, read_file(fname_checksum));
scoped_istream stream = stream_file(fname_checksum);
read(checksum_cfg, *stream);
dir_checksum = file_tree_checksum(checksum_cfg);
}
} catch(config::error&) {
@ -269,12 +270,9 @@ void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, con
if(use_cache && file_exists(fname) && file_create_time(fname) > data_tree_checksum().modified && dir_checksum == data_tree_checksum()) {
std::cerr << "found valid cache at '" << fname << "' using it\n";
log_scope("read cache");
compression_schema schema;
try {
std::istream *stream = stream_file(fname);
read_compressed(cfg, *stream, schema);
delete stream;
scoped_istream stream = stream_file(fname);
read_compressed(cfg, *stream);
return;
} catch(config::error&) {
std::cerr << "cache is corrupt. Loading from files\n";
@ -286,10 +284,10 @@ void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, con
std::cerr << "no valid cache found. Writing cache to '" << fname << "'\n";
//read the file and then write to the cache
read(cfg, preprocess_file("data/game.cfg", &defines, &line_src), &line_src);
scoped_istream stream = preprocess_file("data/game.cfg", &defines, &line_src);
read(cfg, *stream, &line_src);
try {
compression_schema schema;
write_file(fname, write_compressed(cfg, schema));
write_file(fname, write_compressed(cfg));
config checksum_cfg;
data_tree_checksum().write(checksum_cfg);
@ -305,7 +303,8 @@ void read_game_cfg(preproc_map& defines, std::vector<line_source>& line_src, con
}
std::cerr << "caching cannot be done. Reading file\n";
read(cfg, preprocess_file("data/game.cfg", &defines, &line_src), &line_src);
scoped_istream stream = preprocess_file("data/game.cfg", &defines, &line_src);
read(cfg, *stream, &line_src);
}
bool less_campaigns_rank(const config* a, const config* b) {
@ -1525,8 +1524,8 @@ int play_game(int argc, char** argv)
const std::string input(argv[arg+1]);
const std::string output(argv[arg+2]);
const std::string in(read_file(input));
if(in == "") {
scoped_istream stream = stream_file(input);
if (stream->fail()) {
std::cerr << "could not read file '" << input << "'\n";
return 0;
}
@ -1535,7 +1534,7 @@ int play_game(int argc, char** argv)
const bool compress = val == "--compress";
try {
const bool is_compressed = detect_format_and_read(cfg, in);
const bool is_compressed = detect_format_and_read(cfg, *stream);
if(is_compressed && compress) {
std::cerr << input << " is already compressed\n";
return 0;

View File

@ -418,13 +418,12 @@ void read_save_file(const std::string& name, config& cfg)
std::replace(modified_name.begin(),modified_name.end(),' ','_');
//try reading the file both with and without underscores
std::string file_data = read_file(get_saves_dir() + "/" + modified_name);
if(file_data.empty()) {
file_data = read_file(get_saves_dir() + "/" + name);
}
scoped_istream file_stream = stream_file(get_saves_dir() + "/" + modified_name);
if (file_stream->fail())
file_stream = stream_file(get_saves_dir() + "/" + name);
cfg.clear();
detect_format_and_read(cfg, file_data);
detect_format_and_read(cfg, *file_stream);
if(cfg.empty()) {
std::cerr << "Could not parse file data into config\n";
@ -479,7 +478,8 @@ config& save_index()
{
if(save_index_loaded == false) {
try {
detect_format_and_read(save_index_cfg, read_file(get_save_index_file()));
scoped_istream stream = stream_file(get_save_index_file());
detect_format_and_read(save_index_cfg, *stream);
} catch(io_exception& e) {
std::cerr << "error reading save index: '" << e.what() << "'\n";
} catch(config::error&) {

View File

@ -1677,7 +1677,8 @@ void help_text_area::set_items() {
// Should be parsed as WML.
try {
config cfg;
read(cfg, *it);
std::istringstream stream(*it);
read(cfg, stream);
config *child = cfg.child("ref");
if (child != NULL) {
handle_ref_cfg(*child);

View File

@ -15,6 +15,7 @@
#include "global.hpp"
#include "config.hpp"
#include "filesystem.hpp"
#include "gettext.hpp"
#include "language.hpp"
#include "preferences.hpp"
@ -158,7 +159,8 @@ bool set_language(const language_def& locale)
// fill string_table (should be moved somwhere else some day)
try {
read(cfg, preprocess_file("data/translations/english.cfg"));
scoped_istream stream = preprocess_file("data/translations/english.cfg");
read(cfg, *stream);
} catch(config::error& e) {
std::cerr << "Could not read english.cfg\n";
throw e;

View File

@ -68,7 +68,8 @@ namespace preferences {
manager::manager()
{
read(prefs, read_file(get_prefs_file()));
scoped_istream stream = stream_file(get_prefs_file());
read(prefs, *stream);
set_music_volume(music_volume());
set_sound_volume(sound_volume());

View File

@ -26,7 +26,8 @@ void setup_dirs()
void get_campaign_info(const std::string& campaign_name, config& cfg)
{
read(cfg, read_file(campaign_dir() + "/" + campaign_name + ".pbl"));
scoped_istream stream = stream_file(campaign_dir() + "/" + campaign_name + ".pbl");
read(cfg, *stream);
}
void set_campaign_info(const std::string& campaign_name, const config& cfg)

View File

@ -16,17 +16,14 @@
#include "serialization/binary_wml.hpp"
#include "serialization/parser.hpp"
#include <sstream>
bool detect_format_and_read(config &cfg, std::string const &data)
bool detect_format_and_read(config &cfg, std::istream &in)
{
try {
std::istringstream stream(data);
read_compressed(cfg, stream);
read_compressed(cfg, in);
return true;
} catch (config::error &) {
}
read(cfg, data);
read(cfg, in);
return false;
}

View File

@ -50,8 +50,17 @@ line_source get_line_source(std::vector< line_source > const &line_src, int line
return res;
}
void read(config &cfg, std::string const &data, std::vector< line_source > const *line_sources)
void read(config &cfg, std::istream &data_in, std::vector< line_source > const *line_sources)
{
std::string data_str;
{
//temporary, only here to accomodate the old parser
std::stringstream tmp_in;
tmp_in << data_in.rdbuf();
data_str = tmp_in.str();
}
std::string const &data = data_str;
cfg.clear();
std::stack< std::string > element_names;

View File

@ -14,7 +14,7 @@
#ifndef SERIALIZATION_PARSER_HPP_INCLUDED
#define SERIALIZATION_PARSER_HPP_INCLUDED
#include <string>
#include <iosfwd>
#include <vector>
class config;
@ -23,13 +23,13 @@ struct line_source;
line_source get_line_source(std::vector< line_source > const &line_src, int line);
//read data in, clobbering existing data.
void read(config &cfg, std::string const &data, std::vector< line_source > const *lines = 0); //throws config::error
void read(config &cfg, std::istream &in, std::vector< line_source > const *lines = 0); //throws config::error
std::string write(config const &cfg);
//function which reads a file, and automatically detects whether it's compressed or not before
//reading it. If it's not a valid file at all, it will throw an error as if it was trying to
//read it as text WML. Returns true iff the format is compressed
bool detect_format_and_read(config &cfg, std::string const &data); //throws config::error
bool detect_format_and_read(config &cfg, std::istream &in); //throws config::error
#endif

View File

@ -389,7 +389,7 @@ void internal_preprocess_file(const std::string& fname,
} //end anonymous namespace
std::string preprocess_file(std::string const &fname,
std::istream *preprocess_file(std::string const &fname,
const preproc_map* defines,
std::vector<line_source>* line_sources)
{
@ -401,5 +401,5 @@ std::string preprocess_file(std::string const &fname,
std::vector<char> res;
int linenum = 0;
internal_preprocess_file(fname,defines_copy,0,res,line_sources,linenum);
return std::string(res.begin(),res.end());
return new std::istringstream(std::string(res.begin(), res.end()));
}

View File

@ -14,6 +14,7 @@
#ifndef SERIALIZATION_PREPROCESSOR_HPP_INCLUDED
#define SERIALIZATION_PREPROCESSOR_HPP_INCLUDED
#include <iosfwd>
#include <map>
#include <string>
#include <vector>
@ -48,8 +49,8 @@ typedef std::map< std::string, preproc_define > preproc_map;
//function to use the WML preprocessor on a file, and returns the resulting
//preprocessed file data. defines is a map of symbols defined. src is used
//internally and should be set to NULL
std::string preprocess_file(std::string const &fname,
preproc_map const *defines = NULL,
std::vector< line_source > *src = NULL);
std::istream *preprocess_file(std::string const &fname,
preproc_map const *defines = NULL,
std::vector< line_source > *src = NULL);
#endif

View File

@ -4,6 +4,7 @@
#include "cursor.hpp"
#include "display.hpp"
#include "events.hpp"
#include "filesystem.hpp"
#include "font.hpp"
#include "game_config.hpp"
#include "hotkeys.hpp"
@ -126,7 +127,8 @@ const config get_tips_of_day()
std::cerr << "Loading tips of day\n";
try {
read(cfg, preprocess_file("data/tips.cfg"));
scoped_istream stream = preprocess_file("data/tips.cfg");
read(cfg, *stream);
} catch(config::error&) {
std::cerr << "Could not read tips.cfg\n";
}

View File

@ -27,12 +27,12 @@ cutter::cutter() : verbose_(false)
const config cutter::load_config(const std::string &filename)
{
const std::string conf_string = find_configuration(filename);
const std::string pre_conf_string = preprocess_file(conf_string);
config res;
try {
read(res, pre_conf_string);
scoped_istream stream = preprocess_file(conf_string);
read(res, *stream);
} catch(config::error err) {
throw exploder_failure("Unable to load the configuration for the file " + filename + ": "+ err.message);
}