allow to write multiple configs in a network package.

It is now possible to write multiple config objects in a single package,
the server reads them then as one big config. Prevoulsy if people wanted
to do that they had to copy both configs into a new config which is
slow, specially if those configs are very big becasue they contain a
whole scenario or an era.
This commit is contained in:
gfgtdf 2016-06-01 18:35:44 +02:00
parent dca57bd5b0
commit 033f3c97b3
5 changed files with 79 additions and 11 deletions

47
src/configr_assign.hpp Normal file
View File

@ -0,0 +1,47 @@
/*
Copyright (C) 2014 - 2016 by David White <dave@whitevine.net>
Part of the Battle for Wesnoth Project http://www.wesnoth.org/
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.
See the COPYING file for more details.
*/
#pragma once
#include <string>
#include "config.hpp"
#include <boost/variant.hpp>
//Similar to config_of but it stores references to configs (instead of cyoping them).
struct configr_of
{
template <typename AT>
configr_of(const std::string& attrname, AT value)
{
this->operator()(attrname, value);
}
configr_of(const config& cfg)
{
this->operator()(cfg);
}
configr_of& operator()(const config& cfg)
{
data_ = &cfg;
return *this;
}
configr_of& operator()(const std::string& tagname, const configr_of& child)
{
subtags_.push_back(std::make_pair(&tagname, &child));
return *this;
}
std::vector<std::pair<const std::string*, const configr_of*>> subtags_;
const config* data_;
};

View File

@ -597,14 +597,35 @@ static void write_internal(config const &cfg, std::ostream &out, std::string& te
}
}
void write(std::ostream &out, config const &cfg, unsigned int level)
static void write_internal(configr_of const &cfg, std::ostream &out, std::string& textdomain, size_t tab = 0)
{
if (tab > max_recursion_levels)
throw config::error("Too many recursion levels in config write");
if (cfg.data_) {
write_internal(*cfg.data_, out, textdomain, tab);
}
for (const auto &pair: cfg.subtags_)
{
assert(pair.first && pair.second);
if (!config::valid_id(*pair.first)) {
ERR_CF << "Config contains invalid tag name '" << *pair.first << "', skipping...\n";
continue;
}
write_open_child(out, *pair.first, tab);
write_internal(*pair.second, out, textdomain, tab + 1);
write_close_child(out, *pair.first, tab);
}
}
void write(std::ostream &out, configr_of const &cfg, unsigned int level)
{
std::string textdomain = PACKAGE;
write_internal(cfg, out, textdomain, level);
}
template <typename compressor>
void write_compressed(std::ostream &out, config const &cfg)
void write_compressed(std::ostream &out, configr_of const &cfg)
{
boost::iostreams::filtering_stream<boost::iostreams::output> filter;
filter.push(compressor());
@ -615,12 +636,12 @@ void write_compressed(std::ostream &out, config const &cfg)
filter << "\n";
}
void write_gz(std::ostream &out, config const &cfg)
void write_gz(std::ostream &out, configr_of const &cfg)
{
write_compressed<boost::iostreams::gzip_compressor>(out, cfg);
}
void write_bz2(std::ostream &out, config const &cfg)
void write_bz2(std::ostream &out, configr_of const &cfg)
{
write_compressed<boost::iostreams::bzip2_compressor>(out, cfg);
}

View File

@ -20,7 +20,7 @@
#include "global.hpp"
#include "config.hpp"
#include "configr_assign.hpp"
class abstract_validator;
// Read data in, clobbering existing data.
@ -33,9 +33,9 @@ void read_gz(config &cfg, std::istream &in,
void read_bz2(config &cfg, std::istream &in,
abstract_validator * validator = nullptr);
void write(std::ostream &out, config const &cfg, unsigned int level=0);
void write_gz(std::ostream &out, config const &cfg);
void write_bz2(std::ostream &out, config const &cfg);
void write(std::ostream &out, configr_of const &cfg, unsigned int level=0);
void write_gz(std::ostream &out, configr_of const &cfg);
void write_bz2(std::ostream &out, configr_of const &cfg);
void write_key_val(std::ostream &out, const std::string &key, const config::attribute_value &value, unsigned level, std::string &textdomain);
void write_open_child(std::ostream &out, const std::string &child, unsigned int level);
void write_close_child(std::ostream &out, const std::string &child, unsigned int level);

View File

@ -111,7 +111,7 @@ void twesnothd_connection::handle_handshake(const error_code& ec)
recv();
}
void twesnothd_connection::send_data(const config& request)
void twesnothd_connection::send_data(const configr_of& request)
{
poll();
send_queue_.emplace_back();

View File

@ -33,7 +33,7 @@
#include <list>
#include "exceptions.hpp"
#include "wesnothd_connection_error.hpp"
#include "configr_assign.hpp"
class config;
/** A class that represents a TCP/IP connection to the wesnothd server. */
@ -50,7 +50,7 @@ public:
*/
twesnothd_connection(const std::string& host, const std::string& service);
void send_data(const config& request);
void send_data(const configr_of& request);
bool receive_data(config& result);