The Battle for Wesnoth  1.17.0-dev
playturn_network_adapter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 - 2021
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
16 #include "log.hpp"
17 
18 #include <functional>
19 #include <iostream>
20 #include <cassert>
21 
22 
23 static lg::log_domain log_network("network");
24 #define LOG_NW LOG_STREAM(info, log_network)
25 #define ERR_NW LOG_STREAM(err, log_network)
26 
28 {
29  assert(!data_.empty());
30 
31  this->data_.emplace_back();
32  config& back = data_.back();
33  bool has_data = false;
34  try
35  {
36  has_data = this->network_reader_(back);
37  }
38  catch(...)
39  {
40  //Readin from network can throw, we want to ignore the possibly corrupt packet in this case.
41  this->data_.pop_back();
42  throw;
43  }
44  //ping is handeled by network.cpp and we can ignore it.
45  back.remove_attribute("ping");
46  if((!has_data) || back.empty())
47  {
48  this->data_.pop_back();
49  return;
50  }
51  assert(!data_.back().empty());
52 
53  if(!back.attribute_range().empty() )
54  {
55  ERR_NW << "found unexpected attribute:" <<back.debug() << std::endl;
56  this->data_.pop_back();
57  //ignore those here
58  }
59  assert(!data_.back().empty());
60  //there should be no attributes left.
61 }
62 
64 {
65  assert(!data_.empty());
66  if (data_.size() > 1) return false;
67  return this->next_ == data_.back().ordered_end();
68 }
69 
71 {
72  data_front_.emplace_front(std::move(cfg));
73 }
74 
76 {
77  assert(dst.empty());
78  if(!data_front_.empty())
79  {
80  dst = std::move(data_front_.back());
81  data_front_.pop_back();
82  return true;
83  }
84  if(is_at_end())
85  {
87  }
88  if(is_at_end())
89  {
90  //that means we couldn't read anything from the network.
91  return false;
92  }
93  //skip empty data.
94  while(next_ == data_.begin()->ordered_end())
95  {
96  data_.pop_front();
97  next_ = data_.front().ordered_begin();
98  assert(!is_at_end());
99  }
100  config& child = dst.add_child(next_->key);
101  config& child_old = next_->cfg;
102  if(next_->key == "turn")
103  {
104  //split [turn] indo different [turn] for each child.
105  assert(next_->cfg.all_children_count() > next_command_num_);
106  config::all_children_iterator itor = child_old.ordered_begin();
107  std::advance(itor, next_command_num_);
108  config& childchild_old = itor->cfg;
109  config& childchild = child.add_child(itor->key);
110  childchild.swap(childchild_old);
111 
113  if(next_->cfg.all_children_count() == next_command_num_)
114  {
115  next_command_num_ = 0;
116  ++next_;
117  }
118  return true;
119  }
120  else
121  {
122  child.swap(child_old);
123  ++next_;
124  return true;
125  }
126 }
127 
129  : network_reader_(source)
130  , data_({config()})
131  , data_front_()
132  , next_(data_.front().ordered_end())
133  , next_command_num_(0)
134 
135 {
136 
137 }
138 
139 
141 {
142  try {
143  if(!is_at_end())
144  {
145  LOG_NW << "Destroying playturn_network_adapter with an non empty buffer, this means loss of network data" << std::endl;
146  }
147  } catch (...) {}
148 }
149 
151 {
152  network_reader_ = source;
153 }
154 
155 
156 static bool read_config(config& src, config& dst)
157 {
158  assert(dst.empty());
159  if(!src.empty())
160  {
161  src.swap(dst);
162  return true;
163  }
164  else
165  {
166  return false;
167  }
168 }
169 
171 {
172  return std::bind(read_config, std::ref(cfg), std::placeholders::_1);
173 }
#define ERR_NW
void remove_attribute(config_key_type key)
Definition: config.cpp:217
void set_source(source_type source)
const_attr_itors attribute_range() const
Definition: config.cpp:858
#define LOG_NW
void swap(config &cfg)
Definition: config.cpp:1447
static lg::log_domain log_network("network")
config::all_children_iterator next_
std::function< bool(config &)> source_type
static source_type get_source_from_config(config &src)
config & add_child(config_key_type key)
Definition: config.cpp:514
const_all_children_iterator ordered_begin() const
Definition: config.cpp:958
Standard logging facilities (interface).
static bool read_config(config &src, config &dst)
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:61
bool empty() const
Definition: config.cpp:941
std::string debug() const
Definition: config.cpp:1347
playturn_network_adapter(source_type source)