Ticket #35: lgf_io-single.patch
File lgf_io-single.patch, 40.0 KB (added by , 17 years ago) |
---|
-
demo/Makefile.am
# HG changeset patch # User Balazs Dezso <deba@inf.elte.hu> # Date 1208030668 -3600 # Node ID 7f0124fc9658c70d00d7f9e1c7ec310e7335c058 # Parent ae7785fe84315de6be35a182420b6369e851f00d Redesigned .lgf reader/writer diff --git a/demo/Makefile.am b/demo/Makefile.am
a b 4 4 if WANT_DEMO 5 5 6 6 noinst_PROGRAMS += \ 7 demo/arg_parser_demo 7 demo/arg_parser_demo \ 8 demo/lgf_demo 8 9 9 10 endif WANT_DEMO 10 11 11 12 demo_arg_parser_demo_SOURCES = demo/arg_parser_demo.cc 13 demo_lgf_demo_SOURCES = demo/lgf_demo.cc 12 14 -
new file demo/lgf_demo.cc
diff --git a/demo/lgf_demo.cc b/demo/lgf_demo.cc new file mode 100644
- + 1 /* -*- C++ -*- 2 * 3 * This file is a part of LEMON, a generic C++ optimization library 4 * 5 * Copyright (C) 2003-2008 6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 7 * (Egervary Research Group on Combinatorial Optimization, EGRES). 8 * 9 * Permission to use, modify and distribute this software is granted 10 * provided that this copyright notice appears in all copies. For 11 * precise terms see the accompanying LICENSE file. 12 * 13 * This software is provided "AS IS" with no warranty of any kind, 14 * express or implied, and with no claim as to its suitability for any 15 * purpose. 16 * 17 */ 18 19 ///\ingroup demos 20 ///\file 21 ///\brief Demonstrating graph input and output 22 /// 23 /// This simple demo program gives an example of how to read and write 24 /// a graph and additional maps (on the nodes or the edges) from/to a 25 /// stream. 26 /// 27 /// \include reader_writer_demo.cc 28 29 #include <iostream> 30 #include <lemon/smart_graph.h> 31 #include <lemon/lgf_reader.h> 32 #include <lemon/lgf_writer.h> 33 #include <lemon/random.h> 34 35 36 using namespace lemon; 37 38 int main(int argc, const char *argv[]) { 39 SmartDigraph digraph; 40 41 std::stringstream ss; 42 43 try { 44 45 typedef SmartDigraph Digraph; 46 typedef Digraph::Node Node; 47 typedef Digraph::Arc Arc; 48 typedef Digraph::ArcIt ArcIt; 49 50 typedef Digraph::NodeMap<int> PotentialMap; 51 typedef Digraph::ArcMap<int> CapacityMap; 52 typedef Digraph::ArcMap<std::string> NameMap; 53 54 const int n = argc > 1 ? std::atoi(argv[1]) : 20; 55 const int e = argc > 2 ? std::atoi(argv[2]) : static_cast<int>(n * log(n)); 56 const int m = argc > 3 ? std::atoi(argv[3]) : 100; 57 58 Digraph digraph; 59 PotentialMap potential(digraph); 60 CapacityMap capacity(digraph); 61 NameMap name(digraph); 62 63 std::vector<Node> nodes; 64 for (int i = 0; i < n; ++i) { 65 Node node = digraph.addNode(); 66 potential[node] = rnd[m]; 67 nodes.push_back(node); 68 } 69 70 std::vector<Arc> arcs; 71 for (int i = 0; i < e; ++i) { 72 int s = rnd[n]; 73 int t = rnd[n]; 74 int c = rnd[m]; 75 Arc arc = digraph.addArc(nodes[s], nodes[t]); 76 capacity[arc] = c; 77 std::ostringstream os; 78 os << "arc \t" << i << std::endl; 79 name[arc] = os.str(); 80 arcs.push_back(arc); 81 } 82 83 84 DigraphWriter<Digraph>(ss, digraph). 85 nodeMap("potential", potential). 86 arcMap("capacity", capacity). 87 arcMap("name", name). 88 node("source", nodes[0]). 89 node("target", nodes[1]). 90 arc("bottleneck", arcs[e / 2]). 91 attribute("creator", "lemon library"). 92 run(); 93 94 } catch (DataFormatError& error) { 95 std::cerr << error.what() << std::endl; 96 } 97 98 try { 99 100 typedef SmartDigraph Digraph; 101 typedef Digraph::Node Node; 102 typedef Digraph::Arc Arc; 103 typedef Digraph::ArcIt ArcIt; 104 105 typedef Digraph::NodeMap<int> PotentialMap; 106 typedef Digraph::ArcMap<int> CapacityMap; 107 typedef Digraph::ArcMap<std::string> NameMap; 108 109 Digraph digraph; 110 PotentialMap potential(digraph); 111 CapacityMap capacity(digraph); 112 NameMap name(digraph); 113 114 Node s, t; 115 Arc a; 116 117 std::string creator; 118 119 DigraphReader<Digraph>(ss, digraph). 120 nodeMap("potential", potential). 121 arcMap("capacity", capacity). 122 arcMap("name", name). 123 node("source", s). 124 node("target", t). 125 arc("bottleneck", a). 126 attribute("creator", creator). 127 run(); 128 129 DigraphWriter<Digraph>(std::cout, digraph). 130 nodeMap("potential", potential). 131 arcMap("capacity", capacity). 132 arcMap("name", name). 133 node("source", s). 134 node("target", t). 135 arc("bottleneck", a). 136 attribute("creator", creator). 137 run(); 138 139 } catch (DataFormatError& error) { 140 std::cerr << error.what() << std::endl; 141 } 142 143 144 return 0; 145 } -
lemon/Makefile.am
diff --git a/lemon/Makefile.am b/lemon/Makefile.am
a b 27 27 lemon/error.h \ 28 28 lemon/graph_utils.h \ 29 29 lemon/kruskal.h \ 30 lemon/lgf_reader.h \ 30 31 lemon/list_graph.h \ 31 32 lemon/maps.h \ 32 33 lemon/math.h \ -
new file lemon/lgf_reader.h
diff --git a/lemon/lgf_reader.h b/lemon/lgf_reader.h new file mode 100644
- + 1 /* -*- C++ -*- 2 * 3 * This file is a part of LEMON, a generic C++ optimization library 4 * 5 * Copyright (C) 2003-2008 6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 7 * (Egervary Research Group on Combinatorial Optimization, EGRES). 8 * 9 * Permission to use, modify and distribute this software is granted 10 * provided that this copyright notice appears in all copies. For 11 * precise terms see the accompanying LICENSE file. 12 * 13 * This software is provided "AS IS" with no warranty of any kind, 14 * express or implied, and with no claim as to its suitability for any 15 * purpose. 16 * 17 */ 18 19 ///\ingroup lemon_io 20 ///\file 21 ///\brief Lemon Graph Format reader. 22 23 24 #ifndef LEMON_LGF_READER_H 25 #define LEMON_LGF_READER_H 26 27 #include <iostream> 28 #include <fstream> 29 #include <sstream> 30 31 #include <map> 32 #include <typeinfo> 33 34 #include <lemon/assert.h> 35 #include <lemon/graph_utils.h> 36 37 #include <lemon/concept_check.h> 38 #include <lemon/concepts/maps.h> 39 40 namespace lemon { 41 42 namespace _reader_bits { 43 44 template <typename Value> 45 struct DefaultConverter { 46 Value operator()(const std::string& str) { 47 std::istringstream is(str); 48 Value value; 49 is >> value; 50 51 char c; 52 if (is >> std::ws >> c) { 53 throw DataFormatError("Remaining characters in token"); 54 } 55 return value; 56 } 57 }; 58 59 template <> 60 struct DefaultConverter<std::string> { 61 std::string operator()(const std::string& str) { 62 return str; 63 } 64 }; 65 66 template <typename _Item> 67 class MapStorageBase { 68 public: 69 typedef _Item Item; 70 71 private: 72 bool _touched; 73 74 public: 75 MapStorageBase() : _touched(false) {} 76 virtual ~MapStorageBase() {} 77 78 void touch(bool value = true) { _touched = value; } 79 bool touched() const { return _touched; } 80 81 virtual void set(const Item& item, const std::string& value) = 0; 82 83 }; 84 85 template <typename _Item, typename _Map, 86 typename _Converter = DefaultConverter<typename _Map::Value> > 87 class MapStorage : public MapStorageBase<_Item> { 88 public: 89 typedef _Map Map; 90 typedef _Converter Converter; 91 typedef _Item Item; 92 93 private: 94 Map& _map; 95 Converter _converter; 96 97 public: 98 MapStorage(Map& map, const Converter& converter = Converter()) 99 : _map(map), _converter(converter) {} 100 virtual ~MapStorage() {} 101 102 virtual void set(const Item& item ,const std::string& value) { 103 _map.set(item, _converter(value)); 104 } 105 }; 106 107 class ValueStorageBase { 108 private: 109 bool _touched; 110 111 public: 112 ValueStorageBase() : _touched(false) {} 113 virtual ~ValueStorageBase() {} 114 115 void touch() { _touched = true; } 116 bool touched() const { return _touched; } 117 118 virtual void set(const std::string&) = 0; 119 }; 120 121 template <typename _Value, typename _Converter = DefaultConverter<_Value> > 122 class ValueStorage : public ValueStorageBase { 123 public: 124 typedef _Value Value; 125 typedef _Converter Converter; 126 127 private: 128 Value& _value; 129 Converter _converter; 130 131 public: 132 ValueStorage(Value& value, const Converter& converter = Converter()) 133 : _value(value), _converter(converter) {} 134 135 virtual void set(const std::string& value) { 136 _value = _converter(value); 137 } 138 }; 139 140 template <typename Value> 141 struct MapLookUpConverter { 142 const std::map<std::string, Value>& _map; 143 144 MapLookUpConverter(const std::map<std::string, Value>& map) 145 : _map(map) {} 146 147 Value operator()(const std::string& str) { 148 typename std::map<std::string, Value>::const_iterator it = 149 _map.find(str); 150 if (it == _map.end()) { 151 std::ostringstream msg; 152 msg << "Item not found: " << str; 153 throw DataFormatError(msg.str().c_str()); 154 } 155 return it->second; 156 } 157 }; 158 159 bool isWhiteSpace(char c) { 160 return c == ' ' || c == '\t' || c == '\v' || 161 c == '\n' || c == '\r' || c == '\f'; 162 } 163 164 bool isOct(char c) { 165 return '0' <= c && c <='7'; 166 } 167 168 int valueOct(char c) { 169 LEMON_ASSERT(isOct(c), "The character is not octal."); 170 return c - '0'; 171 } 172 173 bool isHex(char c) { 174 return ('0' <= c && c <= '9') || 175 ('a' <= c && c <= 'z') || 176 ('A' <= c && c <= 'Z'); 177 } 178 179 int valueHex(char c) { 180 LEMON_ASSERT(isHex(c), "The character is not hexadecimal."); 181 if ('0' <= c && c <= '9') return c - '0'; 182 if ('a' <= c && c <= 'z') return c - 'a' + 10; 183 return c - 'A' + 10; 184 } 185 186 char readEscape(std::istream& is) { 187 char c; 188 if (!is.get(c)) 189 throw DataFormatError("Escape format error"); 190 191 switch (c) { 192 case '\\': 193 return '\\'; 194 case '\"': 195 return '\"'; 196 case '\'': 197 return '\''; 198 case '\?': 199 return '\?'; 200 case 'a': 201 return '\a'; 202 case 'b': 203 return '\b'; 204 case 'f': 205 return '\f'; 206 case 'n': 207 return '\n'; 208 case 'r': 209 return '\r'; 210 case 't': 211 return '\t'; 212 case 'v': 213 return '\v'; 214 case 'x': 215 { 216 int code; 217 if (!is.get(c) || !isHex(c)) 218 throw DataFormatError("Escape format error"); 219 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); 220 else code = code * 16 + valueHex(c); 221 return code; 222 } 223 default: 224 { 225 int code; 226 if (!isOct(c)) 227 throw DataFormatError("Escape format error"); 228 else if (code = valueOct(c), !is.get(c) || !isOct(c)) 229 is.putback(c); 230 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 231 is.putback(c); 232 else code = code * 8 + valueOct(c); 233 return code; 234 } 235 } 236 } 237 238 std::istream& readToken(std::istream& is, std::string& str) { 239 std::ostringstream os; 240 241 char c; 242 is >> std::ws; 243 244 if (!is.get(c)) 245 throw DataFormatError("Token not found"); 246 247 if (c == '\"') { 248 while (is.get(c) && c != '\"') { 249 if (c == '\\') 250 c = readEscape(is); 251 os << c; 252 } 253 if (!is) 254 throw DataFormatError("Quoted format error"); 255 } else { 256 is.putback(c); 257 while (is.get(c) && !isWhiteSpace(c)) { 258 if (c == '\\') 259 c = readEscape(is); 260 os << c; 261 } 262 if (!is) { 263 is.clear(); 264 } else { 265 is.putback(c); 266 } 267 } 268 str = os.str(); 269 return is; 270 } 271 272 } 273 274 /// \e 275 template <typename _Digraph> 276 class DigraphReader { 277 public: 278 279 typedef _Digraph Digraph; 280 GRAPH_TYPEDEFS(typename Digraph); 281 282 private: 283 284 285 std::istream* _is; 286 bool local_is; 287 288 Digraph& _digraph; 289 290 std::string _nodes_caption; 291 std::string _arcs_caption; 292 std::string _attributes_caption; 293 294 typedef std::map<std::string, Node> NodeIndex; 295 NodeIndex _node_index; 296 typedef std::map<std::string, Arc> ArcIndex; 297 ArcIndex _arc_index; 298 299 typedef std::multimap<std::string, _reader_bits::MapStorageBase<Node>* > 300 NodeMaps; 301 NodeMaps _node_maps; 302 303 typedef std::multimap<std::string, _reader_bits::MapStorageBase<Arc>* > 304 ArcMaps; 305 ArcMaps _arc_maps; 306 307 typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 308 Attributes; 309 Attributes _attributes; 310 311 int line_num; 312 std::istringstream line; 313 314 public: 315 316 /// \e 317 DigraphReader(std::istream& is, Digraph& digraph) 318 : _is(&is), local_is(false), _digraph(digraph) {} 319 320 /// \e 321 DigraphReader(const std::string& fn, Digraph& digraph) 322 : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph) {} 323 324 /// \e 325 DigraphReader(const char* fn, Digraph& digraph) 326 : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph) {} 327 328 DigraphReader(DigraphReader& other) 329 : _is(other._is), local_is(other.local_is), _digraph(other._digraph) { 330 331 other.is = 0; 332 other.local_is = false; 333 334 _node_index.swap(other._node_index); 335 _arc_index.swap(other._arc_index); 336 337 _node_maps.swap(other._node_maps); 338 _arc_maps.swap(other._arc_maps); 339 _attributes.swap(other._attributes); 340 341 _nodes_caption = other._nodes_caption; 342 _arcs_caption = other._arcs_caption; 343 _attributes_caption = other._attributes_caption; 344 } 345 346 /// \e 347 ~DigraphReader() { 348 for (typename NodeMaps::iterator it = _node_maps.begin(); 349 it != _node_maps.end(); ++it) { 350 delete it->second; 351 } 352 353 for (typename ArcMaps::iterator it = _arc_maps.begin(); 354 it != _arc_maps.end(); ++it) { 355 delete it->second; 356 } 357 358 for (typename Attributes::iterator it = _attributes.begin(); 359 it != _attributes.end(); ++it) { 360 delete it->second; 361 } 362 363 if (local_is) { 364 delete _is; 365 } 366 } 367 368 private: 369 370 DigraphReader& operator=(const DigraphReader&); 371 372 public: 373 374 /// \e 375 template <typename Map> 376 DigraphReader& nodeMap(const std::string& caption, Map& map) { 377 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); 378 _reader_bits::MapStorageBase<Node>* storage = 379 new _reader_bits::MapStorage<Node, Map>(map); 380 _node_maps.insert(std::make_pair(caption, storage)); 381 return *this; 382 } 383 384 /// \e 385 template <typename Map, typename Converter> 386 DigraphReader& nodeMap(const std::string& caption, Map& map, 387 const Converter& converter = Converter()) { 388 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); 389 _reader_bits::MapStorageBase<Node>* storage = 390 new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); 391 _node_maps.insert(std::make_pair(caption, storage)); 392 return *this; 393 } 394 395 /// \e 396 template <typename Map> 397 DigraphReader& arcMap(const std::string& caption, Map& map) { 398 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); 399 _reader_bits::MapStorageBase<Arc>* storage = 400 new _reader_bits::MapStorage<Arc, Map>(map); 401 _arc_maps.insert(std::make_pair(caption, storage)); 402 return *this; 403 } 404 405 /// \e 406 template <typename Map, typename Converter> 407 DigraphReader& arcMap(const std::string& caption, Map& map, 408 const Converter& converter = Converter()) { 409 checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); 410 _reader_bits::MapStorageBase<Arc>* storage = 411 new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter); 412 _arc_maps.insert(std::make_pair(caption, storage)); 413 return *this; 414 } 415 416 /// \e 417 template <typename Value> 418 DigraphReader& attribute(const std::string& caption, Value& value) { 419 _reader_bits::ValueStorageBase* storage = 420 new _reader_bits::ValueStorage<Value>(value); 421 _attributes.insert(std::make_pair(caption, storage)); 422 return *this; 423 } 424 425 /// \e 426 template <typename Value, typename Converter> 427 DigraphReader& attribute(const std::string& caption, Value& value, 428 const Converter& converter = Converter()) { 429 _reader_bits::ValueStorageBase* storage = 430 new _reader_bits::ValueStorage<Value, Converter>(value, converter); 431 _attributes.insert(std::make_pair(caption, storage)); 432 return *this; 433 } 434 435 /// \e 436 DigraphReader& node(const std::string& caption, Node& node) { 437 typedef _reader_bits::MapLookUpConverter<Node> Converter; 438 Converter converter(_node_index); 439 _reader_bits::ValueStorageBase* storage = 440 new _reader_bits::ValueStorage<Node, Converter>(node, converter); 441 _attributes.insert(std::make_pair(caption, storage)); 442 return *this; 443 } 444 445 /// \e 446 DigraphReader& arc(const std::string& caption, Arc& arc) { 447 typedef _reader_bits::MapLookUpConverter<Arc> Converter; 448 Converter converter(_arc_index); 449 _reader_bits::ValueStorageBase* storage = 450 new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); 451 _attributes.insert(std::make_pair(caption, storage)); 452 return *this; 453 } 454 455 /// \e 456 DigraphReader& nodes(const std::string& caption) { 457 _nodes_caption = caption; 458 return *this; 459 } 460 461 /// \e 462 DigraphReader& arcs(const std::string& caption) { 463 _arcs_caption = caption; 464 return *this; 465 } 466 467 /// \e 468 DigraphReader& attributes(const std::string& caption) { 469 _attributes_caption = caption; 470 return *this; 471 } 472 473 private: 474 475 bool readLine() { 476 std::string str; 477 while(++line_num, std::getline(*_is, str)) { 478 line.clear(); line.str(str); 479 char c; 480 if (line >> std::ws >> c && c != '#') { 481 line.putback(c); 482 return true; 483 } 484 } 485 return false; 486 } 487 488 bool readSuccess() { 489 return static_cast<bool>(*_is); 490 } 491 492 void skipSection() { 493 char c; 494 while (readSuccess() && line >> c && c != '@') { 495 readLine(); 496 } 497 line.putback(c); 498 } 499 500 void readNodes() { 501 502 std::vector<std::vector<_reader_bits::MapStorageBase<Node>*> > maps; 503 int label = -1; 504 505 if (readLine()) { 506 std::string map; 507 while (line >> map) { 508 509 if (map == "label") { 510 label = maps.size(); 511 } 512 513 maps.push_back(std::vector<_reader_bits::MapStorageBase<Node>*>()); 514 515 typename NodeMaps::iterator it = _node_maps.lower_bound(map); 516 while (it != _node_maps.end() && it->first == map) { 517 if (it->second->touched()) { 518 std::ostringstream msg; 519 msg << "Multiple occurence of node map " << map; 520 throw DataFormatError(msg.str().c_str()); 521 } 522 maps.back().push_back(it->second); 523 it->second->touch(); 524 ++it; 525 } 526 527 } 528 529 for (typename NodeMaps::iterator it = _node_maps.begin(); 530 it != _node_maps.end(); ++it) { 531 if (!it->second->touched()) { 532 std::ostringstream msg; 533 msg << "Map not found in file: " << it->first; 534 throw IoParameterError(msg.str().c_str()); 535 } 536 } 537 } 538 539 char c; 540 while (readLine() && line >> c && c != '@') { 541 line.putback(c); 542 Node n = _digraph.addNode(); 543 544 for (int i = 0; i < static_cast<int>(maps.size()); ++i) { 545 std::string token; 546 _reader_bits::readToken(line, token); 547 548 for (int j = 0; j < static_cast<int>(maps[i].size()); ++j) { 549 maps[i][j]->set(n, token); 550 } 551 552 if (label == i) { 553 _node_index.insert(std::make_pair(token, n)); 554 } 555 556 } 557 558 if (line >> std::ws >> c) { 559 throw DataFormatError("Extra character on the end of line"); 560 } 561 } 562 if (readSuccess()) { 563 line.putback(c); 564 } 565 } 566 567 void readArcs() { 568 569 std::vector<std::vector<_reader_bits::MapStorageBase<Arc>*> > maps; 570 int label = -1; 571 572 if (readLine()) { 573 std::string map; 574 while (line >> map) { 575 576 if (map == "label") { 577 label = maps.size(); 578 } 579 580 maps.push_back(std::vector<_reader_bits::MapStorageBase<Arc>*>()); 581 582 typename ArcMaps::iterator it = _arc_maps.lower_bound(map); 583 while (it != _arc_maps.end() && it->first == map) { 584 if (it->second->touched()) { 585 std::ostringstream msg; 586 msg << "Multiple occurence of arc map " << map; 587 throw DataFormatError(msg.str().c_str()); 588 } 589 maps.back().push_back(it->second); 590 it->second->touch(); 591 ++it; 592 } 593 } 594 595 for (typename ArcMaps::iterator it = _arc_maps.begin(); 596 it != _arc_maps.end(); ++it) { 597 if (!it->second->touched()) { 598 std::ostringstream msg; 599 msg << "Map not found in file: " << it->first; 600 throw IoParameterError(msg.str().c_str()); 601 } 602 } 603 } 604 605 char c; 606 while (readLine() && line >> c && c != '@') { 607 line.putback(c); 608 609 Node s, t; 610 { 611 std::string token; 612 typename NodeIndex::iterator it; 613 614 _reader_bits::readToken(line, token); 615 it = _node_index.find(token); 616 if (it == _node_index.end()) { 617 std::ostringstream msg; 618 msg << "Item not found: " << token; 619 throw DataFormatError(msg.str().c_str()); 620 } 621 s = it->second; 622 623 _reader_bits::readToken(line, token); 624 it = _node_index.find(token); 625 if (it == _node_index.end()) { 626 std::ostringstream msg; 627 msg << "Item not found: " << token; 628 throw DataFormatError(msg.str().c_str()); 629 } 630 t = it->second; 631 } 632 633 Arc a = _digraph.addArc(s, t); 634 635 for (int i = 0; i < static_cast<int>(maps.size()); ++i) { 636 std::string token; 637 _reader_bits::readToken(line, token); 638 639 for (int j = 0; j < static_cast<int>(maps[i].size()); ++j) { 640 maps[i][j]->set(a, token); 641 } 642 643 if (label == i) { 644 _arc_index.insert(std::make_pair(token, a)); 645 } 646 647 } 648 649 if (line >> std::ws >> c) { 650 throw DataFormatError("Extra character on the end of line"); 651 } 652 } 653 if (readSuccess()) { 654 line.putback(c); 655 } 656 } 657 658 void readAttributes() { 659 660 std::vector<std::string> maps; 661 662 char c; 663 while (readLine() && line >> c && c != '@') { 664 line.putback(c); 665 666 std::string attr, token; 667 line >> attr; 668 _reader_bits::readToken(line, token); 669 if (line >> c) { 670 throw DataFormatError("Extra character on the end of line"); 671 } 672 673 typename Attributes::iterator it = _attributes.lower_bound(attr); 674 while (it != _attributes.end() && it->first == attr) { 675 if (it->second->touched()) { 676 std::ostringstream msg; 677 msg << "Multiple occurence of attribute " << attr; 678 throw DataFormatError(msg.str().c_str()); 679 } 680 it->second->set(token); 681 it->second->touch(); 682 ++it; 683 } 684 } 685 if (readSuccess()) { 686 line.putback(c); 687 } 688 for (typename Attributes::iterator it = _attributes.begin(); 689 it != _attributes.end(); ++it) { 690 if (!it->second->touched()) { 691 std::ostringstream msg; 692 msg << "Attribute not found in file: " << it->first; 693 throw IoParameterError(msg.str().c_str()); 694 } 695 } 696 } 697 698 public: 699 700 /// \e 701 void run() { 702 LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); 703 704 bool nodes_done = false; 705 bool arcs_done = false; 706 bool attributes_done = false; 707 708 readLine(); 709 710 while (readSuccess()) { 711 skipSection(); 712 try { 713 std::string section, caption; 714 line >> section >> caption; 715 716 if (section == "@nodes" && !nodes_done) { 717 if (_nodes_caption.empty() || _nodes_caption == caption) { 718 readNodes(); 719 nodes_done = true; 720 } 721 } else if ((section == "@arcs" || section == "@edges") && 722 !arcs_done) { 723 if (_arcs_caption.empty() || _arcs_caption == caption) { 724 readArcs(); 725 arcs_done = true; 726 } 727 } else if (section == "@attributes" && !attributes_done) { 728 if (_attributes_caption.empty() || _attributes_caption == caption) { 729 readAttributes(); 730 attributes_done = true; 731 } 732 } 733 734 skipSection(); 735 } catch (DataFormatError& error) { 736 error.line(line_num); 737 throw; 738 } 739 } 740 741 if (!nodes_done) { 742 throw DataFormatError("Section @nodes not found"); 743 } 744 745 if (!arcs_done) { 746 throw DataFormatError("Section @arcs not found"); 747 } 748 749 if (!attributes_done && !_attributes.empty()) { 750 throw DataFormatError("Section @attributes not found"); 751 } 752 753 } 754 755 }; 756 757 template <typename Digraph> 758 DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) { 759 return DigraphReader<Digraph>(is, digraph); 760 } 761 762 template <typename Digraph> 763 DigraphReader<Digraph> digraphReader(const std::string& fn, 764 Digraph& digraph) { 765 return DigraphReader<Digraph>(fn, digraph); 766 } 767 768 template <typename Digraph> 769 DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { 770 return DigraphReader<Digraph>(fn, digraph); 771 } 772 } 773 774 #endif -
new file lemon/lgf_writer.h
diff --git a/lemon/lgf_writer.h b/lemon/lgf_writer.h new file mode 100644
- + 1 /* -*- C++ -*- 2 * 3 * This file is a part of LEMON, a generic C++ optimization library 4 * 5 * Copyright (C) 2003-2008 6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport 7 * (Egervary Research Group on Combinatorial Optimization, EGRES). 8 * 9 * Permission to use, modify and distribute this software is granted 10 * provided that this copyright notice appears in all copies. For 11 * precise terms see the accompanying LICENSE file. 12 * 13 * This software is provided "AS IS" with no warranty of any kind, 14 * express or implied, and with no claim as to its suitability for any 15 * purpose. 16 * 17 */ 18 19 ///\ingroup lemon_io 20 ///\file 21 ///\brief Lemon Graph Format writer. 22 23 24 #ifndef LEMON_LGF_WRITER_H 25 #define LEMON_LGF_WRITER_H 26 27 #include <iostream> 28 #include <fstream> 29 #include <sstream> 30 31 #include <algorithm> 32 33 #include <vector> 34 #include <functional> 35 36 #include <lemon/assert.h> 37 #include <lemon/graph_utils.h> 38 39 namespace lemon { 40 41 namespace _writer_bits { 42 43 template <typename Value> 44 struct DefaultConverter { 45 std::string operator()(const Value& value) { 46 std::ostringstream os; 47 os << value; 48 return os.str(); 49 } 50 }; 51 52 template <typename T> 53 bool operator<(const T&, const T&) { 54 throw DataFormatError("Label map is not comparable"); 55 } 56 57 template <typename _Map> 58 class MapLess { 59 public: 60 typedef _Map Map; 61 typedef typename Map::Key Item; 62 63 private: 64 const Map& _map; 65 66 public: 67 MapLess(const Map& map) : _map(map) {} 68 69 bool operator()(const Item& left, const Item& right) { 70 return _map[left] < _map[right]; 71 } 72 }; 73 74 template <typename _Item> 75 class MapStorageBase { 76 public: 77 typedef _Item Item; 78 79 public: 80 MapStorageBase() {} 81 virtual ~MapStorageBase() {} 82 83 virtual std::string get(const Item& item) = 0; 84 virtual void sort(std::vector<Item>&) = 0; 85 }; 86 87 template <typename _Item, typename _Map, 88 typename _Converter = DefaultConverter<typename _Map::Value> > 89 class MapStorage : public MapStorageBase<_Item> { 90 public: 91 typedef _Map Map; 92 typedef _Converter Converter; 93 typedef _Item Item; 94 95 private: 96 const Map& _map; 97 Converter _converter; 98 99 public: 100 MapStorage(const Map& map, const Converter& converter = Converter()) 101 : _map(map), _converter(converter) {} 102 virtual ~MapStorage() {} 103 104 virtual std::string get(const Item& item) { 105 return _converter(_map[item]); 106 } 107 virtual void sort(std::vector<Item>& items) { 108 MapLess<Map> less(_map); 109 std::sort(items.begin(), items.end(), less); 110 } 111 }; 112 113 class ValueStorageBase { 114 public: 115 ValueStorageBase() {} 116 virtual ~ValueStorageBase() {} 117 118 virtual std::string get() = 0; 119 }; 120 121 template <typename _Value, typename _Converter = DefaultConverter<_Value> > 122 class ValueStorage : public ValueStorageBase { 123 public: 124 typedef _Value Value; 125 typedef _Converter Converter; 126 127 private: 128 const Value& _value; 129 Converter _converter; 130 131 public: 132 ValueStorage(const Value& value, const Converter& converter = Converter()) 133 : _value(value), _converter(converter) {} 134 135 virtual std::string get() { 136 return _converter(_value); 137 } 138 }; 139 140 template <typename Value> 141 struct MapLookUpConverter { 142 const std::map<Value, std::string>& _map; 143 144 MapLookUpConverter(const std::map<Value, std::string>& map) 145 : _map(map) {} 146 147 std::string operator()(const Value& str) { 148 typename std::map<Value, std::string>::const_iterator it = 149 _map.find(str); 150 if (it == _map.end()) { 151 throw DataFormatError("Item not found"); 152 } 153 return it->second; 154 } 155 }; 156 157 bool isWhiteSpace(char c) { 158 return c == ' ' || c == '\t' || c == '\v' || 159 c == '\n' || c == '\r' || c == '\f'; 160 } 161 162 bool isEscaped(char c) { 163 return c == '\\' || c == '\"' || c == '\'' || 164 c == '\a' || c == '\b'; 165 } 166 167 static void writeEscape(std::ostream& os, char c) { 168 switch (c) { 169 case '\\': 170 os << "\\\\"; 171 return; 172 case '\"': 173 os << "\\\""; 174 return; 175 case '\a': 176 os << "\\a"; 177 return; 178 case '\b': 179 os << "\\b"; 180 return; 181 case '\f': 182 os << "\\f"; 183 return; 184 case '\r': 185 os << "\\r"; 186 return; 187 case '\n': 188 os << "\\n"; 189 return; 190 case '\t': 191 os << "\\t"; 192 return; 193 case '\v': 194 os << "\\v"; 195 return; 196 default: 197 if (c < 0x20) { 198 os << '\\' << std::oct << static_cast<int>(c); 199 } else { 200 os << c; 201 } 202 return; 203 } 204 } 205 206 bool requireEscape(const std::string& str) { 207 std::istringstream is(str); 208 char c; 209 while (is.get(c)) { 210 if (isWhiteSpace(c) || isEscaped(c)) { 211 return true; 212 } 213 } 214 return false; 215 } 216 217 std::ostream& writeToken(std::ostream& os, const std::string& str) { 218 219 if (requireEscape(str)) { 220 os << '\"'; 221 for (std::string::const_iterator it = str.begin(); 222 it != str.end(); ++it) { 223 writeEscape(os, *it); 224 } 225 os << '\"'; 226 } else { 227 os << str; 228 } 229 return os; 230 } 231 232 } 233 234 /// \e 235 template <typename _Digraph> 236 class DigraphWriter { 237 public: 238 239 typedef _Digraph Digraph; 240 GRAPH_TYPEDEFS(typename Digraph); 241 242 private: 243 244 245 std::ostream* _os; 246 bool local_os; 247 248 Digraph& _digraph; 249 250 std::string _nodes_caption; 251 std::string _arcs_caption; 252 std::string _attributes_caption; 253 254 typedef std::map<Node, std::string> NodeIndex; 255 NodeIndex _node_index; 256 typedef std::map<Arc, std::string> ArcIndex; 257 ArcIndex _arc_index; 258 259 typedef std::vector<std::pair<std::string, 260 _writer_bits::MapStorageBase<Node>* > > NodeMaps; 261 NodeMaps _node_maps; 262 263 typedef std::vector<std::pair<std::string, 264 _writer_bits::MapStorageBase<Arc>* > >ArcMaps; 265 ArcMaps _arc_maps; 266 267 typedef std::vector<std::pair<std::string, 268 _writer_bits::ValueStorageBase*> > Attributes; 269 Attributes _attributes; 270 271 public: 272 273 /// \e 274 DigraphWriter(std::ostream& is, Digraph& digraph) 275 : _os(&is), local_os(false), _digraph(digraph) {} 276 277 /// \e 278 DigraphWriter(const std::string& fn, Digraph& digraph) 279 : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph) {} 280 281 /// \e 282 DigraphWriter(const char* fn, Digraph& digraph) 283 : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph) {} 284 285 DigraphWriter(DigraphWriter& other) 286 : _os(other._os), local_os(other.local_os), _digraph(other._digraph) { 287 288 other.is = 0; 289 other.local_os = false; 290 291 _node_index.swap(other._node_index); 292 _arc_index.swap(other._arc_index); 293 294 _node_maps.swap(other._node_maps); 295 _arc_maps.swap(other._arc_maps); 296 _attributes.swap(other._attributes); 297 298 _nodes_caption = other._nodes_caption; 299 _arcs_caption = other._arcs_caption; 300 _attributes_caption = other._attributes_caption; 301 } 302 303 /// \e 304 ~DigraphWriter() { 305 for (typename NodeMaps::iterator it = _node_maps.begin(); 306 it != _node_maps.end(); ++it) { 307 delete it->second; 308 } 309 310 for (typename ArcMaps::iterator it = _arc_maps.begin(); 311 it != _arc_maps.end(); ++it) { 312 delete it->second; 313 } 314 315 for (typename Attributes::iterator it = _attributes.begin(); 316 it != _attributes.end(); ++it) { 317 delete it->second; 318 } 319 320 if (local_os) { 321 delete _os; 322 } 323 } 324 325 private: 326 327 DigraphWriter& operator=(const DigraphWriter&); 328 329 public: 330 331 /// \e 332 template <typename Map> 333 DigraphWriter& nodeMap(const std::string& caption, const Map& map) { 334 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); 335 _writer_bits::MapStorageBase<Node>* storage = 336 new _writer_bits::MapStorage<Node, Map>(map); 337 _node_maps.push_back(std::make_pair(caption, storage)); 338 return *this; 339 } 340 341 /// \e 342 template <typename Map, typename Converter> 343 DigraphWriter& nodeMap(const std::string& caption, const Map& map, 344 const Converter& converter = Converter()) { 345 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); 346 _writer_bits::MapStorageBase<Node>* storage = 347 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); 348 _node_maps.push_back(std::make_pair(caption, storage)); 349 return *this; 350 } 351 352 /// \e 353 template <typename Map> 354 DigraphWriter& arcMap(const std::string& caption, const Map& map) { 355 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); 356 _writer_bits::MapStorageBase<Arc>* storage = 357 new _writer_bits::MapStorage<Arc, Map>(map); 358 _arc_maps.push_back(std::make_pair(caption, storage)); 359 return *this; 360 } 361 362 /// \e 363 template <typename Map, typename Converter> 364 DigraphWriter& arcMap(const std::string& caption, const Map& map, 365 const Converter& converter = Converter()) { 366 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); 367 _writer_bits::MapStorageBase<Arc>* storage = 368 new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter); 369 _arc_maps.push_back(std::make_pair(caption, storage)); 370 return *this; 371 } 372 373 /// \e 374 template <typename Value> 375 DigraphWriter& attribute(const std::string& caption, const Value& value) { 376 _writer_bits::ValueStorageBase* storage = 377 new _writer_bits::ValueStorage<Value>(value); 378 _attributes.push_back(std::make_pair(caption, storage)); 379 return *this; 380 } 381 382 /// \e 383 template <typename Value, typename Converter> 384 DigraphWriter& attribute(const std::string& caption, const Value& value, 385 const Converter& converter = Converter()) { 386 _writer_bits::ValueStorageBase* storage = 387 new _writer_bits::ValueStorage<Value, Converter>(value, converter); 388 _attributes.push_back(std::make_pair(caption, storage)); 389 return *this; 390 } 391 392 /// \e 393 DigraphWriter& node(const std::string& caption, const Node& node) { 394 typedef _writer_bits::MapLookUpConverter<Node> Converter; 395 Converter converter(_node_index); 396 _writer_bits::ValueStorageBase* storage = 397 new _writer_bits::ValueStorage<Node, Converter>(node, converter); 398 _attributes.push_back(std::make_pair(caption, storage)); 399 return *this; 400 } 401 402 /// \e 403 DigraphWriter& arc(const std::string& caption, const Arc& arc) { 404 typedef _writer_bits::MapLookUpConverter<Arc> Converter; 405 Converter converter(_arc_index); 406 _writer_bits::ValueStorageBase* storage = 407 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); 408 _attributes.push_back(std::make_pair(caption, storage)); 409 return *this; 410 } 411 412 /// \e 413 DigraphWriter& nodes(const std::string& caption) { 414 _nodes_caption = caption; 415 return *this; 416 } 417 418 /// \e 419 DigraphWriter& arcs(const std::string& caption) { 420 _arcs_caption = caption; 421 return *this; 422 } 423 424 /// \e 425 DigraphWriter& attributes(const std::string& caption) { 426 _attributes_caption = caption; 427 return *this; 428 } 429 430 private: 431 432 void writeNodes() { 433 _writer_bits::MapStorageBase<Node>* label = 0; 434 for (typename NodeMaps::iterator it = _node_maps.begin(); 435 it != _node_maps.end(); ++it) { 436 if (it->first == "label") { 437 label = it->second; 438 break; 439 } 440 } 441 442 *_os << "@nodes"; 443 if (!_nodes_caption.empty()) { 444 *_os << ' ' << _nodes_caption; 445 } 446 *_os << std::endl; 447 448 if (label == 0) { 449 *_os << "label" << '\t'; 450 } 451 for (typename NodeMaps::iterator it = _node_maps.begin(); 452 it != _node_maps.end(); ++it) { 453 *_os << it->first << '\t'; 454 } 455 *_os << std::endl; 456 457 std::vector<Node> nodes; 458 for (NodeIt n(_digraph); n != INVALID; ++n) { 459 nodes.push_back(n); 460 } 461 462 if (label == 0) { 463 IdMap<Digraph, Node> id_map(_digraph); 464 _writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map); 465 std::sort(nodes.begin(), nodes.end(), id_less); 466 } else { 467 label->sort(nodes); 468 } 469 470 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) { 471 Node n = nodes[i]; 472 if (label == 0) { 473 std::ostringstream os; 474 os << _digraph.id(n); 475 _writer_bits::writeToken(*_os, os.str()); 476 *_os << '\t'; 477 _node_index.insert(std::make_pair(n, os.str())); 478 } 479 for (typename NodeMaps::iterator it = _node_maps.begin(); 480 it != _node_maps.end(); ++it) { 481 std::string value = it->second->get(n); 482 _writer_bits::writeToken(*_os, value); 483 if (it->first == "label") { 484 _node_index.insert(std::make_pair(n, value)); 485 } 486 *_os << '\t'; 487 } 488 *_os << std::endl; 489 } 490 } 491 492 void writeArcs() { 493 _writer_bits::MapStorageBase<Arc>* label = 0; 494 for (typename ArcMaps::iterator it = _arc_maps.begin(); 495 it != _arc_maps.end(); ++it) { 496 if (it->first == "label") { 497 label = it->second; 498 break; 499 } 500 } 501 502 *_os << "@arcs"; 503 if (!_arcs_caption.empty()) { 504 *_os << ' ' << _arcs_caption; 505 } 506 *_os << std::endl; 507 508 *_os << '\t' << '\t'; 509 if (label == 0) { 510 *_os << "label" << '\t'; 511 } 512 for (typename ArcMaps::iterator it = _arc_maps.begin(); 513 it != _arc_maps.end(); ++it) { 514 *_os << it->first << '\t'; 515 } 516 *_os << std::endl; 517 518 std::vector<Arc> arcs; 519 for (ArcIt n(_digraph); n != INVALID; ++n) { 520 arcs.push_back(n); 521 } 522 523 if (label == 0) { 524 IdMap<Digraph, Arc> id_map(_digraph); 525 _writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map); 526 std::sort(arcs.begin(), arcs.end(), id_less); 527 } else { 528 label->sort(arcs); 529 } 530 531 for (int i = 0; i < static_cast<int>(arcs.size()); ++i) { 532 Arc a = arcs[i]; 533 _writer_bits::writeToken(*_os, _node_index. 534 find(_digraph.source(a))->second); 535 *_os << '\t'; 536 _writer_bits::writeToken(*_os, _node_index. 537 find(_digraph.target(a))->second); 538 *_os << '\t'; 539 if (label == 0) { 540 std::ostringstream os; 541 os << _digraph.id(a); 542 _writer_bits::writeToken(*_os, os.str()); 543 *_os << '\t'; 544 _arc_index.insert(std::make_pair(a, os.str())); 545 } 546 for (typename ArcMaps::iterator it = _arc_maps.begin(); 547 it != _arc_maps.end(); ++it) { 548 std::string value = it->second->get(a); 549 _writer_bits::writeToken(*_os, value); 550 if (it->first == "label") { 551 _arc_index.insert(std::make_pair(a, value)); 552 } 553 *_os << '\t'; 554 } 555 *_os << std::endl; 556 } 557 } 558 559 void writeAttributes() { 560 if (_attributes.empty()) return; 561 *_os << "@attributes"; 562 if (!_attributes_caption.empty()) { 563 *_os << ' ' << _attributes_caption; 564 } 565 *_os << std::endl; 566 for (typename Attributes::iterator it = _attributes.begin(); 567 it != _attributes.end(); ++it) { 568 *_os << it->first << ' '; 569 _writer_bits::writeToken(*_os, it->second->get()); 570 *_os << std::endl; 571 } 572 } 573 574 public: 575 576 /// \e 577 void run() { 578 writeNodes(); 579 writeArcs(); 580 writeAttributes(); 581 } 582 583 }; 584 585 template <typename Digraph> 586 DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) { 587 return DigraphWriter<Digraph>(is, digraph); 588 } 589 590 template <typename Digraph> 591 DigraphWriter<Digraph> digraphWriter(const std::string& fn, 592 Digraph& digraph) { 593 return DigraphWriter<Digraph>(fn, digraph); 594 } 595 596 template <typename Digraph> 597 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { 598 return DigraphWriter<Digraph>(fn, digraph); 599 } 600 } 601 602 #endif