33 #include "dynamic_graph.h"
45 inline std::string reduce_whitespace(
const std::string& str) {
48 for (
auto& ch : str) {
49 bool white = std::isspace(ch);
50 if (!ignore || !white) {
51 result += white ?
' ' : ch;
55 if (!result.empty() && result.front() ==
' ') {
56 result.erase(result.begin());
58 if (!result.empty() && result.back() ==
' ') {
64 inline std::vector<std::string> split(
const std::string& str,
char dlm =
' ') {
65 std::vector<std::string> result;
67 for (
unsigned i = 0; i < str.length(); ++i) {
71 if (str[i] == dlm || i == str.length() - 1) {
72 result.push_back(chunk);
79 inline bool skip_until(std::istream& in,
char ch) {
84 }
while (in.get() != ch);
88 inline std::string read_until(std::istream& in,
char ch) {
89 using namespace std::string_literals;
94 throw std::runtime_error(
"stream ended, expected '"s + ch +
"'"s);
100 }
while (last != ch);
104 inline void validate(
char ch) {
105 using namespace std::string_literals;
106 if (ch == std::char_traits<char>::eof()) {
107 throw std::runtime_error(
"unexpected end of input");
109 if (!std::isspace(ch)) {
110 throw std::runtime_error(
"unexpected character '"s + ch +
"'"s);
117 inline std::ostream& operator<<(std::ostream& out,
const node& n) {
118 out <<
"n " << n.id()
125 inline std::ostream& operator<<(std::ostream& out,
const edge& e) {
126 out <<
"e " << e.id()
133 template<
typename N,
typename E>
134 inline std::ostream& operator<<(std::ostream& out,
const graph<N, E>& g) {
136 for (
const node& n : g.nodes()) {
139 for (
const edge& e : g.edges()) {
146 inline std::ostream& operator<<(std::ostream& out,
const dynamic_graph& dgraph) {
148 for (
const auto& s : dgraph.states()) {
155 inline std::istream& operator>>(std::istream& in, node& n) {
156 if (!detail::skip_until(in,
'n')) {
159 std::string str = detail::read_until(in,
';');
160 str = detail::reduce_whitespace(str);
161 auto bits = detail::split(str);
162 if (bits.size() != 3) {
163 throw std::runtime_error(
"invalid number of node parameters");
166 n = node(std::stoi(bits[0]));
167 n.pos().x = std::stof(bits[1]);
168 n.pos().y = std::stof(bits[2]);
169 }
catch (
const std::exception&) {
170 throw std::runtime_error(
"invalid node parameters");
175 inline std::istream& operator>>(std::istream& in, edge& e) {
176 if (!detail::skip_until(in,
'e')) {
179 std::string str = detail::read_until(in,
';');
180 str = detail::reduce_whitespace(str);
181 auto bits = detail::split(str);
182 if (bits.size() != 3) {
183 throw std::runtime_error(
"invalid number of edge parameters");
186 e = edge(std::stoi(bits.at(0)), std::stoi(bits.at(1)), std::stoi(bits.at(2)));
187 }
catch (
const std::exception&) {
188 throw std::runtime_error(
"invalid edge parameters");
193 template<
typename N,
typename E>
194 inline std::istream& operator>>(std::istream& in, graph<N, E>& g) {
195 if (!detail::skip_until(in,
'[')) {
209 edge e(1337, 666, 420);
214 detail::validate(in.get());
221 inline std::istream& operator>>(std::istream& in, dynamic_graph& dgraph) {
222 if (!detail::skip_until(in,
'{')) {
225 std::vector<graph_state> states;
229 dgraph.build(std::move(states));
235 states.push_back(std::move(state));
238 detail::validate(in.get());
242 throw std::out_of_range(
"stream ended, expected '}'");