The Battle for Wesnoth  1.19.7+dev
playturn_network_adapter.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2017 - 2024
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 #include "utils/general.hpp"
18 
19 #include <cassert>
20 #include <functional>
21 #include <utility>
22 
23 
24 static lg::log_domain log_network("network");
25 #define DBG_NW LOG_STREAM(debug, log_network)
26 #define LOG_NW LOG_STREAM(info, log_network)
27 #define ERR_NW LOG_STREAM(err, log_network)
28 
30 {
31  assert(!data_.empty());
32 
33  this->data_.emplace_back();
34  config& back = data_.back();
35  bool has_data = false;
36  try
37  {
38  has_data = this->network_reader_(back);
39  }
40  catch(...)
41  {
42  //Reading from network can throw, we want to ignore the possibly corrupt packet in this case.
43  DBG_NW << "Caught exception reading from the network: " << utils::get_unknown_exception_type();
44  this->data_.pop_back();
45  throw;
46  }
47  //ping is handeled by network.cpp and we can ignore it.
48  back.remove_attribute("ping");
49  if((!has_data) || back.empty())
50  {
51  this->data_.pop_back();
52  return;
53  }
54  assert(!data_.back().empty());
55 
56  if(!back.attribute_range().empty() )
57  {
58  ERR_NW << "found unexpected attribute:" <<back.debug();
59  this->data_.pop_back();
60  //ignore those here
61  }
62  assert(!data_.back().empty());
63  //there should be no attributes left.
64 }
65 
67 {
68  assert(!data_.empty());
69  if (data_.size() > 1) return false;
70  return this->next_ == data_.back().ordered_end();
71 }
72 
74 {
75  data_front_.emplace_front(std::move(cfg));
76 }
77 
79 {
80  assert(dst.empty());
81  if(!data_front_.empty())
82  {
83  dst = std::move(data_front_.back());
84  data_front_.pop_back();
85  return true;
86  }
87  if(is_at_end())
88  {
90  }
91  if(is_at_end())
92  {
93  //that means we couldn't read anything from the network.
94  return false;
95  }
96  //skip empty data.
97  while(next_ == data_.begin()->ordered_end())
98  {
99  data_.pop_front();
100  next_ = data_.front().ordered_begin();
101  assert(!is_at_end());
102  }
103  config& child = dst.add_child(next_->key);
104  config& child_old = next_->cfg;
105  if(next_->key == "turn")
106  {
107  //split [turn] indo different [turn] for each child.
108  assert(next_->cfg.all_children_count() > next_command_num_);
109  config::all_children_iterator itor = child_old.ordered_begin();
110  std::advance(itor, next_command_num_);
111  config& childchild_old = itor->cfg;
112  config& childchild = child.add_child(itor->key);
113  childchild.swap(childchild_old);
114 
116  if(next_->cfg.all_children_count() == next_command_num_)
117  {
118  next_command_num_ = 0;
119  ++next_;
120  }
121  return true;
122  }
123  else
124  {
125  child.swap(child_old);
126  ++next_;
127  return true;
128  }
129 }
130 
132  : network_reader_(std::move(source))
133  , data_({config()})
134  , data_front_()
135  , next_(data_.front().ordered_end())
136  , next_command_num_(0)
137 
138 {
139 
140 }
141 
142 
144 {
145  try {
146  if(!is_at_end())
147  {
148  LOG_NW << "Destroying playturn_network_adapter with an non empty buffer, this means loss of network data";
149  }
150  } catch (...) {}
151 }
152 
154 {
155  network_reader_ = std::move(source);
156 }
157 
158 
159 static bool read_config(config& src, config& dst)
160 {
161  assert(dst.empty());
162  if(!src.empty())
163  {
164  src.swap(dst);
165  return true;
166  }
167  else
168  {
169  return false;
170  }
171 }
172 
174 {
175  return std::bind(read_config, std::ref(cfg), std::placeholders::_1);
176 }
A config object defines a single node in a WML file, with access to child nodes.
Definition: config.hpp:172
const_all_children_iterator ordered_begin() const
Definition: config.cpp:864
const_attr_itors attribute_range() const
Definition: config.cpp:760
void remove_attribute(config_key_type key)
Definition: config.cpp:162
std::string debug() const
Definition: config.cpp:1240
void swap(config &cfg)
Definition: config.cpp:1336
bool empty() const
Definition: config.cpp:849
config & add_child(config_key_type key)
Definition: config.cpp:440
std::function< bool(config &)> source_type
config::all_children_iterator next_
playturn_network_adapter(source_type source)
void set_source(source_type source)
static source_type get_source_from_config(config &src)
Standard logging facilities (interface).
std::string get_unknown_exception_type()
Utility function for finding the type of thing caught with catch(...).
Definition: general.cpp:23
#define ERR_NW
#define LOG_NW
static bool read_config(config &src, config &dst)
static lg::log_domain log_network("network")
#define DBG_NW
rect dst
Location on the final composed sheet.
rect src
Non-transparent portion of the surface to compose.
bool empty() const
False if both w and h are > 0, true otherwise.
Definition: rect.cpp:48