0
2
0
23
18
... | ... |
@@ -446,49 +446,49 @@ |
446 | 446 |
/// \brief Constructor |
447 | 447 |
/// |
448 | 448 |
/// Construct a directed graph reader, which reads from the given |
449 | 449 |
/// file. |
450 | 450 |
DigraphReader(const std::string& fn, Digraph& digraph) |
451 | 451 |
: _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph), |
452 | 452 |
_use_nodes(false), _use_arcs(false) {} |
453 | 453 |
|
454 | 454 |
/// \brief Constructor |
455 | 455 |
/// |
456 | 456 |
/// Construct a directed graph reader, which reads from the given |
457 | 457 |
/// file. |
458 | 458 |
DigraphReader(const char* fn, Digraph& digraph) |
459 | 459 |
: _is(new std::ifstream(fn)), local_is(true), _digraph(digraph), |
460 | 460 |
_use_nodes(false), _use_arcs(false) {} |
461 | 461 |
|
462 | 462 |
/// \brief Copy constructor |
463 | 463 |
/// |
464 | 464 |
/// The copy constructor transfers all data from the other reader, |
465 | 465 |
/// therefore the copied reader will not be usable more. |
466 | 466 |
DigraphReader(DigraphReader& other) |
467 | 467 |
: _is(other._is), local_is(other.local_is), _digraph(other._digraph), |
468 | 468 |
_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) { |
469 | 469 |
|
470 |
other. |
|
470 |
other._is = 0; |
|
471 | 471 |
other.local_is = false; |
472 | 472 |
|
473 | 473 |
_node_index.swap(other._node_index); |
474 | 474 |
_arc_index.swap(other._arc_index); |
475 | 475 |
|
476 | 476 |
_node_maps.swap(other._node_maps); |
477 | 477 |
_arc_maps.swap(other._arc_maps); |
478 | 478 |
_attributes.swap(other._attributes); |
479 | 479 |
|
480 | 480 |
_nodes_caption = other._nodes_caption; |
481 | 481 |
_arcs_caption = other._arcs_caption; |
482 | 482 |
_attributes_caption = other._attributes_caption; |
483 | 483 |
|
484 | 484 |
_sections.swap(other._sections); |
485 | 485 |
} |
486 | 486 |
|
487 | 487 |
/// \brief Destructor |
488 | 488 |
~DigraphReader() { |
489 | 489 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
490 | 490 |
it != _node_maps.end(); ++it) { |
491 | 491 |
delete it->second; |
492 | 492 |
} |
493 | 493 |
|
494 | 494 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
... | ... |
@@ -1057,50 +1057,52 @@ |
1057 | 1057 |
|
1058 | 1058 |
} |
1059 | 1059 |
if (readSuccess()) { |
1060 | 1060 |
line.putback(c); |
1061 | 1061 |
} |
1062 | 1062 |
for (typename Attributes::iterator it = _attributes.begin(); |
1063 | 1063 |
it != _attributes.end(); ++it) { |
1064 | 1064 |
if (read_attr.find(it->first) == read_attr.end()) { |
1065 | 1065 |
std::ostringstream msg; |
1066 | 1066 |
msg << "Attribute not found in file: " << it->first; |
1067 | 1067 |
throw DataFormatError(msg.str().c_str()); |
1068 | 1068 |
} |
1069 | 1069 |
} |
1070 | 1070 |
} |
1071 | 1071 |
|
1072 | 1072 |
public: |
1073 | 1073 |
|
1074 | 1074 |
/// \name Execution of the reader |
1075 | 1075 |
/// @{ |
1076 | 1076 |
|
1077 | 1077 |
/// \brief Start the batch processing |
1078 | 1078 |
/// |
1079 | 1079 |
/// This function starts the batch processing |
1080 | 1080 |
void run() { |
1081 |
|
|
1082 | 1081 |
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
1082 |
if (!*_is) { |
|
1083 |
throw DataFormatError("Cannot find file"); |
|
1084 |
} |
|
1083 | 1085 |
|
1084 | 1086 |
bool nodes_done = false; |
1085 | 1087 |
bool arcs_done = false; |
1086 | 1088 |
bool attributes_done = false; |
1087 | 1089 |
std::set<std::string> extra_sections; |
1088 | 1090 |
|
1089 | 1091 |
line_num = 0; |
1090 | 1092 |
readLine(); |
1091 | 1093 |
|
1092 | 1094 |
while (readSuccess()) { |
1093 | 1095 |
skipSection(); |
1094 | 1096 |
try { |
1095 | 1097 |
char c; |
1096 | 1098 |
std::string section, caption; |
1097 | 1099 |
line >> c; |
1098 | 1100 |
_reader_bits::readToken(line, section); |
1099 | 1101 |
_reader_bits::readToken(line, caption); |
1100 | 1102 |
|
1101 | 1103 |
if (line >> c) |
1102 | 1104 |
throw DataFormatError("Extra character on the end of line"); |
1103 | 1105 |
|
1104 | 1106 |
if (section == "nodes" && !nodes_done) { |
1105 | 1107 |
if (_nodes_caption.empty() || _nodes_caption == caption) { |
1106 | 1108 |
readNodes(); |
... | ... |
@@ -1139,42 +1141,45 @@ |
1139 | 1141 |
} |
1140 | 1142 |
} |
1141 | 1143 |
|
1142 | 1144 |
if (!nodes_done) { |
1143 | 1145 |
throw DataFormatError("Section @nodes not found"); |
1144 | 1146 |
} |
1145 | 1147 |
|
1146 | 1148 |
if (!arcs_done) { |
1147 | 1149 |
throw DataFormatError("Section @arcs not found"); |
1148 | 1150 |
} |
1149 | 1151 |
|
1150 | 1152 |
if (!attributes_done && !_attributes.empty()) { |
1151 | 1153 |
throw DataFormatError("Section @attributes not found"); |
1152 | 1154 |
} |
1153 | 1155 |
|
1154 | 1156 |
} |
1155 | 1157 |
|
1156 | 1158 |
/// @} |
1157 | 1159 |
|
1158 | 1160 |
}; |
1159 | 1161 |
|
1160 | 1162 |
/// \relates DigraphReader |
1161 | 1163 |
template <typename Digraph> |
1162 | 1164 |
DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) { |
1163 |
|
|
1165 |
DigraphReader<Digraph> tmp(is, digraph); |
|
1166 |
return tmp; |
|
1164 | 1167 |
} |
1165 | 1168 |
|
1166 | 1169 |
/// \relates DigraphReader |
1167 | 1170 |
template <typename Digraph> |
1168 | 1171 |
DigraphReader<Digraph> digraphReader(const std::string& fn, |
1169 | 1172 |
Digraph& digraph) { |
1170 |
|
|
1173 |
DigraphReader<Digraph> tmp(fn, digraph); |
|
1174 |
return tmp; |
|
1171 | 1175 |
} |
1172 | 1176 |
|
1173 | 1177 |
/// \relates DigraphReader |
1174 | 1178 |
template <typename Digraph> |
1175 | 1179 |
DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { |
1176 |
|
|
1180 |
DigraphReader<Digraph> tmp(fn, digraph); |
|
1181 |
return tmp; |
|
1177 | 1182 |
} |
1178 | 1183 |
} |
1179 | 1184 |
|
1180 | 1185 |
#endif |
... | ... |
@@ -174,129 +174,131 @@ |
174 | 174 |
return; |
175 | 175 |
case '\a': |
176 | 176 |
os << "\\a"; |
177 | 177 |
return; |
178 | 178 |
case '\b': |
179 | 179 |
os << "\\b"; |
180 | 180 |
return; |
181 | 181 |
case '\f': |
182 | 182 |
os << "\\f"; |
183 | 183 |
return; |
184 | 184 |
case '\r': |
185 | 185 |
os << "\\r"; |
186 | 186 |
return; |
187 | 187 |
case '\n': |
188 | 188 |
os << "\\n"; |
189 | 189 |
return; |
190 | 190 |
case '\t': |
191 | 191 |
os << "\\t"; |
192 | 192 |
return; |
193 | 193 |
case '\v': |
194 | 194 |
os << "\\v"; |
195 | 195 |
return; |
196 | 196 |
default: |
197 | 197 |
if (c < 0x20) { |
198 |
std::ios::fmtflags flags = os.flags(); |
|
198 | 199 |
os << '\\' << std::oct << static_cast<int>(c); |
200 |
os.flags(flags); |
|
199 | 201 |
} else { |
200 | 202 |
os << c; |
201 | 203 |
} |
202 | 204 |
return; |
203 | 205 |
} |
204 | 206 |
} |
205 | 207 |
|
206 | 208 |
bool requireEscape(const std::string& str) { |
207 | 209 |
if (str.empty() || str[0] == '@') return true; |
208 | 210 |
std::istringstream is(str); |
209 | 211 |
char c; |
210 | 212 |
while (is.get(c)) { |
211 | 213 |
if (isWhiteSpace(c) || isEscaped(c)) { |
212 | 214 |
return true; |
213 | 215 |
} |
214 | 216 |
} |
215 | 217 |
return false; |
216 | 218 |
} |
217 | 219 |
|
218 | 220 |
std::ostream& writeToken(std::ostream& os, const std::string& str) { |
219 | 221 |
|
220 | 222 |
if (requireEscape(str)) { |
221 | 223 |
os << '\"'; |
222 | 224 |
for (std::string::const_iterator it = str.begin(); |
223 | 225 |
it != str.end(); ++it) { |
224 | 226 |
writeEscape(os, *it); |
225 | 227 |
} |
226 | 228 |
os << '\"'; |
227 | 229 |
} else { |
228 | 230 |
os << str; |
229 | 231 |
} |
230 | 232 |
return os; |
231 | 233 |
} |
232 | 234 |
|
233 | 235 |
} |
234 | 236 |
|
235 | 237 |
/// \ingroup lemon_io |
236 | 238 |
/// |
237 | 239 |
/// \brief LGF writer for directed graphs |
238 | 240 |
/// |
239 | 241 |
/// This utility writes an \ref lgf-format "LGF" file. |
240 | 242 |
/// |
241 | 243 |
/// The writing method does a batch processing. The user creates a |
242 | 244 |
/// writer object, then various writing rules can be added to the |
243 | 245 |
/// writer, and eventually the writing is executed with the \c run() |
244 | 246 |
/// member function. A map writing rule can be added to the writer |
245 | 247 |
/// with the \c nodeMap() or \c arcMap() members. An optional |
246 |
/// converter parameter can also be added as a standard functor converting from |
|
247 |
/// the value type of the map to std::string. If it is set, it will |
|
248 |
/// determine how the map's value type is written to the output |
|
249 |
/// stream. If the functor is not set, then a default conversion |
|
250 |
/// will be used. The \c attribute(), \c node() and \c arc() functions |
|
251 |
/// are used to add attribute writing rules. |
|
248 |
/// converter parameter can also be added as a standard functor |
|
249 |
/// converting from the value type of the map to std::string. If it |
|
250 |
/// is set, it will determine how the map's value type is written to |
|
251 |
/// the output stream. If the functor is not set, then a default |
|
252 |
/// conversion will be used. The \c attribute(), \c node() and \c |
|
253 |
/// arc() functions are used to add attribute writing rules. |
|
252 | 254 |
/// |
253 | 255 |
///\code |
254 | 256 |
/// DigraphWriter<Digraph>(std::cout, digraph). |
255 | 257 |
/// nodeMap("coordinates", coord_map). |
256 | 258 |
/// nodeMap("size", size). |
257 | 259 |
/// nodeMap("title", title). |
258 | 260 |
/// arcMap("capacity", cap_map). |
259 | 261 |
/// node("source", src). |
260 | 262 |
/// node("target", trg). |
261 | 263 |
/// attribute("caption", caption). |
262 | 264 |
/// run(); |
263 | 265 |
///\endcode |
264 | 266 |
/// |
265 | 267 |
/// |
266 | 268 |
/// By default, the writer does not write additional captions to the |
267 | 269 |
/// sections, but they can be give as an optional parameter of |
268 | 270 |
/// the \c nodes(), \c arcs() or \c |
269 | 271 |
/// attributes() functions. |
270 | 272 |
/// |
271 | 273 |
/// The \c skipNodes() and \c skipArcs() functions forbid the |
272 |
/// writing of the sections. If two arc sections should be written to the |
|
273 |
/// output, it can be done in two passes, the first pass writes the |
|
274 |
/// node section and the first arc section, then the second pass |
|
275 |
/// skips the node section and writes just the arc section to the |
|
276 |
/// stream. The output stream can be retrieved with the \c ostream() |
|
277 |
/// function, hence the second pass can append its output to the output of the |
|
278 |
/// |
|
274 |
/// writing of the sections. If two arc sections should be written |
|
275 |
/// to the output, it can be done in two passes, the first pass |
|
276 |
/// writes the node section and the first arc section, then the |
|
277 |
/// second pass skips the node section and writes just the arc |
|
278 |
/// section to the stream. The output stream can be retrieved with |
|
279 |
/// the \c ostream() function, hence the second pass can append its |
|
280 |
/// output to the output of the first pass. |
|
279 | 281 |
template <typename _Digraph> |
280 | 282 |
class DigraphWriter { |
281 | 283 |
public: |
282 | 284 |
|
283 | 285 |
typedef _Digraph Digraph; |
284 | 286 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
285 | 287 |
|
286 | 288 |
private: |
287 | 289 |
|
288 | 290 |
|
289 | 291 |
std::ostream* _os; |
290 | 292 |
bool local_os; |
291 | 293 |
|
292 | 294 |
Digraph& _digraph; |
293 | 295 |
|
294 | 296 |
std::string _nodes_caption; |
295 | 297 |
std::string _arcs_caption; |
296 | 298 |
std::string _attributes_caption; |
297 | 299 |
|
298 | 300 |
typedef std::map<Node, std::string> NodeIndex; |
299 | 301 |
NodeIndex _node_index; |
300 | 302 |
typedef std::map<Arc, std::string> ArcIndex; |
301 | 303 |
ArcIndex _arc_index; |
302 | 304 |
|
... | ... |
@@ -328,49 +330,49 @@ |
328 | 330 |
/// \brief Constructor |
329 | 331 |
/// |
330 | 332 |
/// Construct a directed graph writer, which writes to the given |
331 | 333 |
/// output file. |
332 | 334 |
DigraphWriter(const std::string& fn, Digraph& digraph) |
333 | 335 |
: _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph), |
334 | 336 |
_skip_nodes(false), _skip_arcs(false) {} |
335 | 337 |
|
336 | 338 |
/// \brief Constructor |
337 | 339 |
/// |
338 | 340 |
/// Construct a directed graph writer, which writes to the given |
339 | 341 |
/// output file. |
340 | 342 |
DigraphWriter(const char* fn, Digraph& digraph) |
341 | 343 |
: _os(new std::ofstream(fn)), local_os(true), _digraph(digraph), |
342 | 344 |
_skip_nodes(false), _skip_arcs(false) {} |
343 | 345 |
|
344 | 346 |
/// \brief Copy constructor |
345 | 347 |
/// |
346 | 348 |
/// The copy constructor transfers all data from the other writer, |
347 | 349 |
/// therefore the copied writer will not be usable more. |
348 | 350 |
DigraphWriter(DigraphWriter& other) |
349 | 351 |
: _os(other._os), local_os(other.local_os), _digraph(other._digraph), |
350 | 352 |
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) { |
351 | 353 |
|
352 |
other. |
|
354 |
other._os = 0; |
|
353 | 355 |
other.local_os = false; |
354 | 356 |
|
355 | 357 |
_node_index.swap(other._node_index); |
356 | 358 |
_arc_index.swap(other._arc_index); |
357 | 359 |
|
358 | 360 |
_node_maps.swap(other._node_maps); |
359 | 361 |
_arc_maps.swap(other._arc_maps); |
360 | 362 |
_attributes.swap(other._attributes); |
361 | 363 |
|
362 | 364 |
_nodes_caption = other._nodes_caption; |
363 | 365 |
_arcs_caption = other._arcs_caption; |
364 | 366 |
_attributes_caption = other._attributes_caption; |
365 | 367 |
} |
366 | 368 |
|
367 | 369 |
/// \brief Destructor |
368 | 370 |
~DigraphWriter() { |
369 | 371 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
370 | 372 |
it != _node_maps.end(); ++it) { |
371 | 373 |
delete it->second; |
372 | 374 |
} |
373 | 375 |
|
374 | 376 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
375 | 377 |
it != _arc_maps.end(); ++it) { |
376 | 378 |
delete it->second; |
... | ... |
@@ -696,43 +698,46 @@ |
696 | 698 |
/// |
697 | 699 |
/// This function starts the batch processing |
698 | 700 |
void run() { |
699 | 701 |
if (!_skip_nodes) { |
700 | 702 |
writeNodes(); |
701 | 703 |
} |
702 | 704 |
if (!_skip_arcs) { |
703 | 705 |
writeArcs(); |
704 | 706 |
} |
705 | 707 |
writeAttributes(); |
706 | 708 |
} |
707 | 709 |
|
708 | 710 |
/// \brief Gives back the stream of the writer |
709 | 711 |
/// |
710 | 712 |
/// Gives back the stream of the writer |
711 | 713 |
std::ostream& ostream() { |
712 | 714 |
return *_os; |
713 | 715 |
} |
714 | 716 |
|
715 | 717 |
/// @} |
716 | 718 |
}; |
717 | 719 |
|
718 | 720 |
/// \relates DigraphWriter |
719 | 721 |
template <typename Digraph> |
720 |
DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) { |
|
721 |
return DigraphWriter<Digraph>(is, digraph); |
|
722 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) { |
|
723 |
DigraphWriter<Digraph> tmp(os, digraph); |
|
724 |
return tmp; |
|
722 | 725 |
} |
723 | 726 |
|
724 | 727 |
/// \relates DigraphWriter |
725 | 728 |
template <typename Digraph> |
726 | 729 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
727 | 730 |
Digraph& digraph) { |
728 |
|
|
731 |
DigraphWriter<Digraph> tmp(fn, digraph); |
|
732 |
return tmp; |
|
729 | 733 |
} |
730 | 734 |
|
731 | 735 |
/// \relates DigraphWriter |
732 | 736 |
template <typename Digraph> |
733 | 737 |
DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { |
734 |
|
|
738 |
DigraphWriter<Digraph> tmp(fn, digraph); |
|
739 |
return tmp; |
|
735 | 740 |
} |
736 | 741 |
} |
737 | 742 |
|
738 | 743 |
#endif |
0 comments (0 inline)