From 033f3c97b34c2aa36a9c5d6a6625287dc36dd4f7 Mon Sep 17 00:00:00 2001 From: gfgtdf Date: Wed, 1 Jun 2016 18:35:44 +0200 Subject: [PATCH] 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. --- src/configr_assign.hpp | 47 ++++++++++++++++++++++++++++++++++++ src/serialization/parser.cpp | 29 +++++++++++++++++++--- src/serialization/parser.hpp | 8 +++--- src/wesnothd_connection.cpp | 2 +- src/wesnothd_connection.hpp | 4 +-- 5 files changed, 79 insertions(+), 11 deletions(-) create mode 100644 src/configr_assign.hpp diff --git a/src/configr_assign.hpp b/src/configr_assign.hpp new file mode 100644 index 000000000000..117b26aa47aa --- /dev/null +++ b/src/configr_assign.hpp @@ -0,0 +1,47 @@ +/* + Copyright (C) 2014 - 2016 by David White + 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 +#include "config.hpp" +#include + +//Similar to config_of but it stores references to configs (instead of cyoping them). +struct configr_of +{ + template + 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> subtags_; + const config* data_; +}; \ No newline at end of file diff --git a/src/serialization/parser.cpp b/src/serialization/parser.cpp index 14571bdcd46c..2b5630af62cd 100644 --- a/src/serialization/parser.cpp +++ b/src/serialization/parser.cpp @@ -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 -void write_compressed(std::ostream &out, config const &cfg) +void write_compressed(std::ostream &out, configr_of const &cfg) { boost::iostreams::filtering_stream 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(out, cfg); } -void write_bz2(std::ostream &out, config const &cfg) +void write_bz2(std::ostream &out, configr_of const &cfg) { write_compressed(out, cfg); } diff --git a/src/serialization/parser.hpp b/src/serialization/parser.hpp index 2fce1432d93d..56be7fa39f27 100644 --- a/src/serialization/parser.hpp +++ b/src/serialization/parser.hpp @@ -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); diff --git a/src/wesnothd_connection.cpp b/src/wesnothd_connection.cpp index 47ce893cdd2e..31dd6e98bb83 100644 --- a/src/wesnothd_connection.cpp +++ b/src/wesnothd_connection.cpp @@ -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(); diff --git a/src/wesnothd_connection.hpp b/src/wesnothd_connection.hpp index f583db8213af..47fc8413c1f7 100644 --- a/src/wesnothd_connection.hpp +++ b/src/wesnothd_connection.hpp @@ -33,7 +33,7 @@ #include #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 @@ class twesnothd_connection : boost::noncopyable */ 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);