gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Undirected LGF IO
0 2 0
default
2 files changed with 1473 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -100,6 +100,32 @@
100 100
      }
101 101
    };
102 102

	
103
    template <typename _Graph, bool _dir, typename _Map, 
104
	      typename _Converter = DefaultConverter<typename _Map::Value> >
105
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
106
    public:
107
      typedef _Map Map;
108
      typedef _Converter Converter;
109
      typedef _Graph Graph;
110
      typedef typename Graph::Edge Item;
111
      static const bool dir = _dir;
112
      
113
    private:
114
      const Graph& _graph;
115
      Map& _map;
116
      Converter _converter;
117

	
118
    public:
119
      GraphArcMapStorage(const Graph& graph, Map& map, 
120
			 const Converter& converter = Converter()) 
121
	: _graph(graph), _map(map), _converter(converter) {}
122
      virtual ~GraphArcMapStorage() {}
123

	
124
      virtual void set(const Item& item ,const std::string& value) {
125
	_map.set(_graph.direct(item, dir), _converter(value));
126
      }
127
    };
128

	
103 129
    class ValueStorageBase {
104 130
    public:
105 131
      ValueStorageBase() {}
... ...
@@ -146,6 +172,29 @@
146 172
      }
147 173
    };
148 174

	
175
    template <typename Graph>
176
    struct GraphArcLookUpConverter {
177
      const Graph& _graph;
178
      const std::map<std::string, typename Graph::Edge>& _map;
179
      
180
      GraphArcLookUpConverter(const Graph& graph, 
181
			      const std::map<std::string,
182
			                     typename Graph::Edge>& map) 
183
	: _graph(graph), _map(map) {}
184
      
185
      typename Graph::Arc operator()(const std::string& str) {
186
	if (str.empty() || (str[0] != '+' && str[0] != '-')) {
187
	  throw DataFormatError("Item must start with '+' or '-'");
188
	}
189
	typename std::map<std::string, typename Graph::Edge>
190
	  ::const_iterator it = _map.find(str.substr(1));
191
	if (it == _map.end()) {
192
	  throw DataFormatError("Item not found");
193
	}
194
	return _graph.direct(it->second, str[0] == '+');
195
      }
196
    };
197

	
149 198
    bool isWhiteSpace(char c) {
150 199
      return c == ' ' || c == '\t' || c == '\v' || 
151 200
        c == '\n' || c == '\r' || c == '\f'; 
... ...
@@ -1180,6 +1229,848 @@
1180 1229
    DigraphReader<Digraph> tmp(fn, digraph);
1181 1230
    return tmp;
1182 1231
  }
1232

	
1233
  /// \ingroup lemon_io
1234
  ///  
1235
  /// \brief LGF reader for undirected graphs
1236
  ///
1237
  /// This utility reads an \ref lgf-format "LGF" file.
1238
  template <typename _Graph>
1239
  class GraphReader {
1240
  public:
1241

	
1242
    typedef _Graph Graph;
1243
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1244
    
1245
  private:
1246

	
1247

	
1248
    std::istream* _is;
1249
    bool local_is;
1250

	
1251
    Graph& _graph;
1252

	
1253
    std::string _nodes_caption;
1254
    std::string _edges_caption;
1255
    std::string _attributes_caption;
1256

	
1257
    typedef std::map<std::string, Node> NodeIndex;
1258
    NodeIndex _node_index;
1259
    typedef std::map<std::string, Edge> EdgeIndex;
1260
    EdgeIndex _edge_index;
1261
    
1262
    typedef std::vector<std::pair<std::string, 
1263
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
1264
    NodeMaps _node_maps; 
1265

	
1266
    typedef std::vector<std::pair<std::string,
1267
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1268
    EdgeMaps _edge_maps;
1269

	
1270
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
1271
      Attributes;
1272
    Attributes _attributes;
1273

	
1274
    typedef std::map<std::string, _reader_bits::Section*> Sections;
1275
    Sections _sections;
1276

	
1277
    bool _use_nodes;
1278
    bool _use_edges;
1279

	
1280
    int line_num;
1281
    std::istringstream line;
1282

	
1283
  public:
1284

	
1285
    /// \brief Constructor
1286
    ///
1287
    /// Construct a undirected graph reader, which reads from the given
1288
    /// input stream.
1289
    GraphReader(std::istream& is, Graph& graph) 
1290
      : _is(&is), local_is(false), _graph(graph),
1291
	_use_nodes(false), _use_edges(false) {}
1292

	
1293
    /// \brief Constructor
1294
    ///
1295
    /// Construct a undirected graph reader, which reads from the given
1296
    /// file.
1297
    GraphReader(const std::string& fn, Graph& graph) 
1298
      : _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph),
1299
    	_use_nodes(false), _use_edges(false) {}
1300
    
1301
    /// \brief Constructor
1302
    ///
1303
    /// Construct a undirected graph reader, which reads from the given
1304
    /// file.
1305
    GraphReader(const char* fn, Graph& graph) 
1306
      : _is(new std::ifstream(fn)), local_is(true), _graph(graph),
1307
    	_use_nodes(false), _use_edges(false) {}
1308

	
1309
    /// \brief Copy constructor
1310
    ///
1311
    /// The copy constructor transfers all data from the other reader,
1312
    /// therefore the copied reader will not be usable more. 
1313
    GraphReader(GraphReader& other) 
1314
      : _is(other._is), local_is(other.local_is), _graph(other._graph),
1315
	_use_nodes(other._use_nodes), _use_edges(other._use_edges) {
1316

	
1317
      other._is = 0;
1318
      other.local_is = false;
1319
      
1320
      _node_index.swap(other._node_index);
1321
      _edge_index.swap(other._edge_index);
1322

	
1323
      _node_maps.swap(other._node_maps);
1324
      _edge_maps.swap(other._edge_maps);
1325
      _attributes.swap(other._attributes);
1326

	
1327
      _nodes_caption = other._nodes_caption;
1328
      _edges_caption = other._edges_caption;
1329
      _attributes_caption = other._attributes_caption;
1330

	
1331
      _sections.swap(other._sections);
1332
    }
1333

	
1334
    /// \brief Destructor
1335
    ~GraphReader() {
1336
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
1337
	   it != _node_maps.end(); ++it) {
1338
	delete it->second;
1339
      }
1340

	
1341
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
1342
	   it != _edge_maps.end(); ++it) {
1343
	delete it->second;
1344
      }
1345

	
1346
      for (typename Attributes::iterator it = _attributes.begin(); 
1347
	   it != _attributes.end(); ++it) {
1348
	delete it->second;
1349
      }
1350

	
1351
      for (typename Sections::iterator it = _sections.begin(); 
1352
	   it != _sections.end(); ++it) {
1353
	delete it->second;
1354
      }
1355

	
1356
      if (local_is) {
1357
	delete _is;
1358
      }
1359

	
1360
    }
1361

	
1362
  private:
1363
    
1364
    GraphReader& operator=(const GraphReader&);
1365

	
1366
  public:
1367

	
1368
    /// \name Reading rules
1369
    /// @{
1370
    
1371
    /// \brief Node map reading rule
1372
    ///
1373
    /// Add a node map reading rule to the reader.
1374
    template <typename Map>
1375
    GraphReader& nodeMap(const std::string& caption, Map& map) {
1376
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1377
      _reader_bits::MapStorageBase<Node>* storage = 
1378
	new _reader_bits::MapStorage<Node, Map>(map);
1379
      _node_maps.push_back(std::make_pair(caption, storage));
1380
      return *this;
1381
    }
1382

	
1383
    /// \brief Node map reading rule
1384
    ///
1385
    /// Add a node map reading rule with specialized converter to the
1386
    /// reader.
1387
    template <typename Map, typename Converter>
1388
    GraphReader& nodeMap(const std::string& caption, Map& map, 
1389
			   const Converter& converter = Converter()) {
1390
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
1391
      _reader_bits::MapStorageBase<Node>* storage = 
1392
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
1393
      _node_maps.push_back(std::make_pair(caption, storage));
1394
      return *this;
1395
    }
1396

	
1397
    /// \brief Edge map reading rule
1398
    ///
1399
    /// Add an edge map reading rule to the reader.
1400
    template <typename Map>
1401
    GraphReader& edgeMap(const std::string& caption, Map& map) {
1402
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1403
      _reader_bits::MapStorageBase<Edge>* storage = 
1404
	new _reader_bits::MapStorage<Edge, Map>(map);
1405
      _edge_maps.push_back(std::make_pair(caption, storage));
1406
      return *this;
1407
    }
1408

	
1409
    /// \brief Edge map reading rule
1410
    ///
1411
    /// Add an edge map reading rule with specialized converter to the
1412
    /// reader.
1413
    template <typename Map, typename Converter>
1414
    GraphReader& edgeMap(const std::string& caption, Map& map, 
1415
			  const Converter& converter = Converter()) {
1416
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1417
      _reader_bits::MapStorageBase<Edge>* storage = 
1418
	new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1419
      _edge_maps.push_back(std::make_pair(caption, storage));
1420
      return *this;
1421
    }
1422

	
1423
    /// \brief Arc map reading rule
1424
    ///
1425
    /// Add an arc map reading rule to the reader.
1426
    template <typename Map>
1427
    GraphReader& arcMap(const std::string& caption, Map& map) {
1428
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1429
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1430
	new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1431
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1432
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1433
	new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1434
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1435
      return *this;
1436
    }
1437

	
1438
    /// \brief Arc map reading rule
1439
    ///
1440
    /// Add an arc map reading rule with specialized converter to the
1441
    /// reader.
1442
    template <typename Map, typename Converter>
1443
    GraphReader& arcMap(const std::string& caption, Map& map, 
1444
			  const Converter& converter = Converter()) {
1445
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1446
      _reader_bits::MapStorageBase<Edge>* forward_storage = 
1447
	new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1448
	(_graph, map, converter);
1449
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1450
      _reader_bits::MapStorageBase<Edge>* backward_storage = 
1451
	new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1452
	(_graph, map, converter);
1453
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1454
      return *this;
1455
    }
1456

	
1457
    /// \brief Attribute reading rule
1458
    ///
1459
    /// Add an attribute reading rule to the reader.
1460
    template <typename Value>
1461
    GraphReader& attribute(const std::string& caption, Value& value) {
1462
      _reader_bits::ValueStorageBase* storage = 
1463
	new _reader_bits::ValueStorage<Value>(value);
1464
      _attributes.insert(std::make_pair(caption, storage));
1465
      return *this;
1466
    }
1467

	
1468
    /// \brief Attribute reading rule
1469
    ///
1470
    /// Add an attribute reading rule with specialized converter to the
1471
    /// reader.
1472
    template <typename Value, typename Converter>
1473
    GraphReader& attribute(const std::string& caption, Value& value, 
1474
			     const Converter& converter = Converter()) {
1475
      _reader_bits::ValueStorageBase* storage = 
1476
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1477
      _attributes.insert(std::make_pair(caption, storage));
1478
      return *this;
1479
    }
1480

	
1481
    /// \brief Node reading rule
1482
    ///
1483
    /// Add a node reading rule to reader.
1484
    GraphReader& node(const std::string& caption, Node& node) {
1485
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1486
      Converter converter(_node_index);
1487
      _reader_bits::ValueStorageBase* storage = 
1488
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1489
      _attributes.insert(std::make_pair(caption, storage));
1490
      return *this;
1491
    }
1492

	
1493
    /// \brief Edge reading rule
1494
    ///
1495
    /// Add an edge reading rule to reader.
1496
    GraphReader& edge(const std::string& caption, Edge& edge) {
1497
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1498
      Converter converter(_edge_index);
1499
      _reader_bits::ValueStorageBase* storage = 
1500
	new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1501
      _attributes.insert(std::make_pair(caption, storage));
1502
      return *this;
1503
    }
1504

	
1505
    /// \brief Arc reading rule
1506
    ///
1507
    /// Add an arc reading rule to reader.
1508
    GraphReader& arc(const std::string& caption, Arc& arc) {
1509
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1510
      Converter converter(_graph, _edge_index);
1511
      _reader_bits::ValueStorageBase* storage = 
1512
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1513
      _attributes.insert(std::make_pair(caption, storage));
1514
      return *this;
1515
    }
1516

	
1517
    /// @}
1518

	
1519
    /// \name Select section by name
1520
    /// @{
1521

	
1522
    /// \brief Set \c \@nodes section to be read
1523
    ///
1524
    /// Set \c \@nodes section to be read
1525
    GraphReader& nodes(const std::string& caption) {
1526
      _nodes_caption = caption;
1527
      return *this;
1528
    }
1529

	
1530
    /// \brief Set \c \@edges section to be read
1531
    ///
1532
    /// Set \c \@edges section to be read
1533
    GraphReader& edges(const std::string& caption) {
1534
      _edges_caption = caption;
1535
      return *this;
1536
    }
1537

	
1538
    /// \brief Set \c \@attributes section to be read
1539
    ///
1540
    /// Set \c \@attributes section to be read
1541
    GraphReader& attributes(const std::string& caption) {
1542
      _attributes_caption = caption;
1543
      return *this;
1544
    }
1545

	
1546
    /// @}
1547

	
1548
    /// \name Section readers
1549
    /// @{
1550

	
1551
    /// \brief Add a section processor with line oriented reading
1552
    ///
1553
    /// In the \e LGF file extra sections can be placed, which contain
1554
    /// any data in arbitrary format. These sections can be read with
1555
    /// this function line by line. The first parameter is the type
1556
    /// descriptor of the section, the second is a functor, which
1557
    /// takes just one \c std::string parameter. At the reading
1558
    /// process, each line of the section will be given to the functor
1559
    /// object. However, the empty lines and the comment lines are
1560
    /// filtered out, and the leading whitespaces are stipped from
1561
    /// each processed string.
1562
    ///
1563
    /// For example let's see a section, which contain several
1564
    /// integers, which should be inserted into a vector.
1565
    ///\code
1566
    ///  @numbers
1567
    ///  12 45 23
1568
    ///  4
1569
    ///  23 6
1570
    ///\endcode
1571
    ///
1572
    /// The functor is implemented as an struct:
1573
    ///\code
1574
    ///  struct NumberSection {
1575
    ///    std::vector<int>& _data;
1576
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
1577
    ///    void operator()(const std::string& line) {
1578
    ///      std::istringstream ls(line);
1579
    ///      int value;
1580
    ///      while (ls >> value) _data.push_back(value);
1581
    ///    }
1582
    ///  };
1583
    ///
1584
    ///  // ...
1585
    ///
1586
    ///  reader.sectionLines("numbers", NumberSection(vec));  
1587
    ///\endcode
1588
    template <typename Functor>
1589
    GraphReader& sectionLines(const std::string& type, Functor functor) {
1590
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1591
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1592
		   "Multiple reading of section.");
1593
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1594
		   type != "attributes", "Multiple reading of section.");
1595
      _sections.insert(std::make_pair(type, 
1596
        new _reader_bits::LineSection<Functor>(functor)));
1597
      return *this;
1598
    }
1599

	
1600

	
1601
    /// \brief Add a section processor with stream oriented reading
1602
    ///
1603
    /// In the \e LGF file extra sections can be placed, which contain
1604
    /// any data in arbitrary format. These sections can be read
1605
    /// directly with this function. The first parameter is the type
1606
    /// of the section, the second is a functor, which takes an \c
1607
    /// std::istream& and an int& parameter, the latter regard to the
1608
    /// line number of stream. The functor can read the input while
1609
    /// the section go on, and the line number should be modified
1610
    /// accordingly.
1611
    template <typename Functor>
1612
    GraphReader& sectionStream(const std::string& type, Functor functor) {
1613
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
1614
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
1615
		   "Multiple reading of section.");
1616
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
1617
		   type != "attributes", "Multiple reading of section.");
1618
      _sections.insert(std::make_pair(type, 
1619
	 new _reader_bits::StreamSection<Functor>(functor)));
1620
      return *this;
1621
    }    
1622
    
1623
    /// @}
1624

	
1625
    /// \name Using previously constructed node or edge set
1626
    /// @{
1627

	
1628
    /// \brief Use previously constructed node set
1629
    ///
1630
    /// Use previously constructed node set, and specify the node
1631
    /// label map.
1632
    template <typename Map>
1633
    GraphReader& useNodes(const Map& map) {
1634
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1635
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1636
      _use_nodes = true;
1637
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1638
      for (NodeIt n(_graph); n != INVALID; ++n) {
1639
	_node_index.insert(std::make_pair(converter(map[n]), n));
1640
      }
1641
      return *this;
1642
    }
1643

	
1644
    /// \brief Use previously constructed node set
1645
    ///
1646
    /// Use previously constructed node set, and specify the node
1647
    /// label map and a functor which converts the label map values to
1648
    /// std::string.
1649
    template <typename Map, typename Converter>
1650
    GraphReader& useNodes(const Map& map, 
1651
			    const Converter& converter = Converter()) {
1652
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1653
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
1654
      _use_nodes = true;
1655
      for (NodeIt n(_graph); n != INVALID; ++n) {
1656
	_node_index.insert(std::make_pair(converter(map[n]), n));
1657
      }
1658
      return *this;
1659
    }
1660

	
1661
    /// \brief Use previously constructed edge set
1662
    ///
1663
    /// Use previously constructed edge set, and specify the edge
1664
    /// label map.
1665
    template <typename Map>
1666
    GraphReader& useEdges(const Map& map) {
1667
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1668
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1669
      _use_edges = true;
1670
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1671
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1672
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1673
      }
1674
      return *this;
1675
    }
1676

	
1677
    /// \brief Use previously constructed edge set
1678
    ///
1679
    /// Use previously constructed edge set, and specify the edge
1680
    /// label map and a functor which converts the label map values to
1681
    /// std::string.
1682
    template <typename Map, typename Converter>
1683
    GraphReader& useEdges(const Map& map, 
1684
			    const Converter& converter = Converter()) {
1685
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1686
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); 
1687
      _use_edges = true;
1688
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1689
	_edge_index.insert(std::make_pair(converter(map[a]), a));
1690
      }
1691
      return *this;
1692
    }
1693

	
1694
    /// @}
1695

	
1696
  private:
1697

	
1698
    bool readLine() {
1699
      std::string str;
1700
      while(++line_num, std::getline(*_is, str)) {
1701
	line.clear(); line.str(str);
1702
	char c;
1703
	if (line >> std::ws >> c && c != '#') {
1704
	  line.putback(c);
1705
	  return true;
1706
	}
1707
      }
1708
      return false;
1709
    }
1710

	
1711
    bool readSuccess() {
1712
      return static_cast<bool>(*_is);
1713
    }
1714
    
1715
    void skipSection() {
1716
      char c;
1717
      while (readSuccess() && line >> c && c != '@') {
1718
	readLine();
1719
      }
1720
      line.putback(c);
1721
    }
1722

	
1723
    void readNodes() {
1724

	
1725
      std::vector<int> map_index(_node_maps.size());
1726
      int map_num, label_index;
1727

	
1728
      if (!readLine()) 
1729
	throw DataFormatError("Cannot find map captions");
1730
      
1731
      {
1732
	std::map<std::string, int> maps;
1733
	
1734
	std::string map;
1735
	int index = 0;
1736
	while (_reader_bits::readToken(line, map)) {
1737
	  if (maps.find(map) != maps.end()) {
1738
	    std::ostringstream msg;
1739
	    msg << "Multiple occurence of node map: " << map;
1740
	    throw DataFormatError(msg.str().c_str());
1741
	  }
1742
	  maps.insert(std::make_pair(map, index));
1743
	  ++index;
1744
	}
1745
	
1746
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1747
	  std::map<std::string, int>::iterator jt = 
1748
	    maps.find(_node_maps[i].first);
1749
	  if (jt == maps.end()) {
1750
	    std::ostringstream msg;
1751
	    msg << "Map not found in file: " << _node_maps[i].first;
1752
	    throw DataFormatError(msg.str().c_str());
1753
	  }
1754
	  map_index[i] = jt->second;
1755
	}
1756

	
1757
	{
1758
	  std::map<std::string, int>::iterator jt = maps.find("label");
1759
	  if (jt == maps.end())
1760
	    throw DataFormatError("Label map not found in file");
1761
	  label_index = jt->second;
1762
	}
1763
	map_num = maps.size();
1764
      }
1765

	
1766
      char c;
1767
      while (readLine() && line >> c && c != '@') {
1768
	line.putback(c);
1769

	
1770
	std::vector<std::string> tokens(map_num);
1771
	for (int i = 0; i < map_num; ++i) {
1772
	  if (!_reader_bits::readToken(line, tokens[i])) {
1773
	    std::ostringstream msg;
1774
	    msg << "Column not found (" << i + 1 << ")";
1775
	    throw DataFormatError(msg.str().c_str());
1776
	  }
1777
	}
1778
	if (line >> std::ws >> c)
1779
	  throw DataFormatError("Extra character on the end of line");
1780
	
1781
	Node n;
1782
	if (!_use_nodes) {
1783
	  n = _graph.addNode();
1784
	  _node_index.insert(std::make_pair(tokens[label_index], n));
1785
	} else {
1786
	  typename std::map<std::string, Node>::iterator it =
1787
	    _node_index.find(tokens[label_index]);
1788
	  if (it == _node_index.end()) {
1789
	    std::ostringstream msg;
1790
	    msg << "Node with label not found: " << tokens[label_index];
1791
	    throw DataFormatError(msg.str().c_str());	    
1792
	  }
1793
	  n = it->second;
1794
	}
1795

	
1796
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1797
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
1798
	}
1799

	
1800
      }
1801
      if (readSuccess()) {
1802
	line.putback(c);
1803
      }
1804
    }
1805

	
1806
    void readEdges() {
1807

	
1808
      std::vector<int> map_index(_edge_maps.size());
1809
      int map_num, label_index;
1810

	
1811
      if (!readLine()) 
1812
	throw DataFormatError("Cannot find map captions");
1813
      
1814
      {
1815
	std::map<std::string, int> maps;
1816
	
1817
	std::string map;
1818
	int index = 0;
1819
	while (_reader_bits::readToken(line, map)) {
1820
	  if (maps.find(map) != maps.end()) {
1821
	    std::ostringstream msg;
1822
	    msg << "Multiple occurence of edge map: " << map;
1823
	    throw DataFormatError(msg.str().c_str());
1824
	  }
1825
	  maps.insert(std::make_pair(map, index));
1826
	  ++index;
1827
	}
1828
	
1829
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1830
	  std::map<std::string, int>::iterator jt = 
1831
	    maps.find(_edge_maps[i].first);
1832
	  if (jt == maps.end()) {
1833
	    std::ostringstream msg;
1834
	    msg << "Map not found in file: " << _edge_maps[i].first;
1835
	    throw DataFormatError(msg.str().c_str());
1836
	  }
1837
	  map_index[i] = jt->second;
1838
	}
1839

	
1840
	{
1841
	  std::map<std::string, int>::iterator jt = maps.find("label");
1842
	  if (jt == maps.end())
1843
	    throw DataFormatError("Label map not found in file");
1844
	  label_index = jt->second;
1845
	}
1846
	map_num = maps.size();
1847
      }
1848

	
1849
      char c;
1850
      while (readLine() && line >> c && c != '@') {
1851
	line.putback(c);
1852

	
1853
	std::string source_token;
1854
	std::string target_token;
1855

	
1856
	if (!_reader_bits::readToken(line, source_token))
1857
	  throw DataFormatError("Source not found");
1858

	
1859
	if (!_reader_bits::readToken(line, target_token))
1860
	  throw DataFormatError("Source not found");
1861
	
1862
	std::vector<std::string> tokens(map_num);
1863
	for (int i = 0; i < map_num; ++i) {
1864
	  if (!_reader_bits::readToken(line, tokens[i])) {
1865
	    std::ostringstream msg;
1866
	    msg << "Column not found (" << i + 1 << ")";
1867
	    throw DataFormatError(msg.str().c_str());
1868
	  }
1869
	}
1870
	if (line >> std::ws >> c)
1871
	  throw DataFormatError("Extra character on the end of line");
1872
	
1873
	Edge e;
1874
	if (!_use_edges) {
1875

	
1876
          typename NodeIndex::iterator it;
1877
 
1878
          it = _node_index.find(source_token);
1879
          if (it == _node_index.end()) {
1880
            std::ostringstream msg;
1881
            msg << "Item not found: " << source_token;
1882
            throw DataFormatError(msg.str().c_str());
1883
          }
1884
          Node source = it->second;
1885

	
1886
          it = _node_index.find(target_token);
1887
          if (it == _node_index.end()) {       
1888
            std::ostringstream msg;            
1889
            msg << "Item not found: " << target_token;
1890
            throw DataFormatError(msg.str().c_str());
1891
          }                                          
1892
          Node target = it->second;                            
1893

	
1894
	  e = _graph.addEdge(source, target);
1895
	  _edge_index.insert(std::make_pair(tokens[label_index], e));
1896
	} else {
1897
	  typename std::map<std::string, Edge>::iterator it =
1898
	    _edge_index.find(tokens[label_index]);
1899
	  if (it == _edge_index.end()) {
1900
	    std::ostringstream msg;
1901
	    msg << "Edge with label not found: " << tokens[label_index];
1902
	    throw DataFormatError(msg.str().c_str());	    
1903
	  }
1904
	  e = it->second;
1905
	}
1906

	
1907
	for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1908
	  _edge_maps[i].second->set(e, tokens[map_index[i]]);
1909
	}
1910

	
1911
      }
1912
      if (readSuccess()) {
1913
	line.putback(c);
1914
      }
1915
    }
1916

	
1917
    void readAttributes() {
1918

	
1919
      std::set<std::string> read_attr;
1920

	
1921
      char c;
1922
      while (readLine() && line >> c && c != '@') {
1923
	line.putback(c);
1924
	
1925
	std::string attr, token;
1926
	if (!_reader_bits::readToken(line, attr))
1927
	  throw DataFormatError("Attribute name not found");
1928
	if (!_reader_bits::readToken(line, token))
1929
	  throw DataFormatError("Attribute value not found");
1930
	if (line >> c)
1931
	  throw DataFormatError("Extra character on the end of line");	  
1932

	
1933
	{
1934
	  std::set<std::string>::iterator it = read_attr.find(attr);
1935
	  if (it != read_attr.end()) {
1936
	    std::ostringstream msg;
1937
	    msg << "Multiple occurence of attribute " << attr;
1938
	    throw DataFormatError(msg.str().c_str());
1939
	  }
1940
	  read_attr.insert(attr);
1941
	}
1942
	
1943
	{
1944
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1945
	  while (it != _attributes.end() && it->first == attr) {
1946
	    it->second->set(token);
1947
	    ++it;
1948
	  }
1949
	}
1950

	
1951
      }
1952
      if (readSuccess()) {
1953
	line.putback(c);
1954
      }
1955
      for (typename Attributes::iterator it = _attributes.begin();
1956
	   it != _attributes.end(); ++it) {
1957
	if (read_attr.find(it->first) == read_attr.end()) {
1958
	  std::ostringstream msg;
1959
	  msg << "Attribute not found in file: " << it->first;
1960
	  throw DataFormatError(msg.str().c_str());
1961
	}	
1962
      }
1963
    }
1964

	
1965
  public:
1966

	
1967
    /// \name Execution of the reader    
1968
    /// @{
1969

	
1970
    /// \brief Start the batch processing
1971
    ///
1972
    /// This function starts the batch processing
1973
    void run() {
1974
      
1975
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1976
      
1977
      bool nodes_done = false;
1978
      bool edges_done = false;
1979
      bool attributes_done = false;
1980
      std::set<std::string> extra_sections;
1981

	
1982
      line_num = 0;      
1983
      readLine();
1984

	
1985
      while (readSuccess()) {
1986
	skipSection();
1987
	try {
1988
	  char c;
1989
	  std::string section, caption;
1990
	  line >> c;
1991
	  _reader_bits::readToken(line, section);
1992
	  _reader_bits::readToken(line, caption);
1993

	
1994
	  if (line >> c) 
1995
	    throw DataFormatError("Extra character on the end of line");
1996

	
1997
	  if (section == "nodes" && !nodes_done) {
1998
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1999
	      readNodes();
2000
	      nodes_done = true;
2001
	    }
2002
	  } else if ((section == "edges" || section == "arcs") && 
2003
		     !edges_done) {
2004
	    if (_edges_caption.empty() || _edges_caption == caption) {
2005
	      readEdges();
2006
	      edges_done = true;
2007
	    }
2008
	  } else if (section == "attributes" && !attributes_done) {
2009
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
2010
	      readAttributes();
2011
	      attributes_done = true;
2012
	    }
2013
	  } else {
2014
	    if (extra_sections.find(section) != extra_sections.end()) {
2015
	      std::ostringstream msg;
2016
	      msg << "Multiple occurence of section " << section;
2017
	      throw DataFormatError(msg.str().c_str());
2018
	    }
2019
	    Sections::iterator it = _sections.find(section);
2020
	    if (it != _sections.end()) {
2021
	      extra_sections.insert(section);
2022
	      it->second->process(*_is, line_num);
2023
	      readLine();
2024
	    } else {
2025
	      readLine();
2026
	      skipSection();
2027
	    }
2028
	  }
2029
	} catch (DataFormatError& error) {
2030
	  error.line(line_num);
2031
	  throw;
2032
	}	
2033
      }
2034

	
2035
      if (!nodes_done) {
2036
	throw DataFormatError("Section @nodes not found");
2037
      }
2038

	
2039
      if (!edges_done) {
2040
	throw DataFormatError("Section @edges not found");
2041
      }
2042

	
2043
      if (!attributes_done && !_attributes.empty()) {
2044
	throw DataFormatError("Section @attributes not found");
2045
      }
2046

	
2047
    }
2048

	
2049
    /// @}
2050
    
2051
  };
2052

	
2053
  /// \relates GraphReader
2054
  template <typename Graph>
2055
  GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
2056
    GraphReader<Graph> tmp(is, graph);
2057
    return tmp;
2058
  }
2059

	
2060
  /// \relates GraphReader
2061
  template <typename Graph>
2062
  GraphReader<Graph> graphReader(const std::string& fn, 
2063
				       Graph& graph) {
2064
    GraphReader<Graph> tmp(fn, graph);
2065
    return tmp;
2066
  }
2067

	
2068
  /// \relates GraphReader
2069
  template <typename Graph>
2070
  GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
2071
    GraphReader<Graph> tmp(fn, graph);
2072
    return tmp;
2073
  }
1183 2074
}
1184 2075

	
1185 2076
#endif
Ignore white space 6 line context
... ...
@@ -71,6 +71,27 @@
71 71
      }
72 72
    };
73 73

	
74
    template <typename _Graph, bool _dir, typename _Map>
75
    class GraphArcMapLess {
76
    public:
77
      typedef _Map Map;
78
      typedef _Graph Graph;
79
      typedef typename Graph::Edge Item;
80

	
81
    private:
82
      const Graph& _graph;
83
      const Map& _map;
84
      
85
    public:
86
      GraphArcMapLess(const Graph& graph, const Map& map) 
87
	: _graph(graph), _map(map) {}
88

	
89
      bool operator()(const Item& left, const Item& right) {
90
	return _map[_graph.direct(left, _dir)] < 
91
	  _map[_graph.direct(right, _dir)];
92
      }
93
    };
94

	
74 95
    template <typename _Item>    
75 96
    class MapStorageBase {
76 97
    public:
... ...
@@ -110,6 +131,36 @@
110 131
      }
111 132
    };
112 133

	
134
    template <typename _Graph, bool _dir, typename _Map, 
135
	      typename _Converter = DefaultConverter<typename _Map::Value> >
136
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
137
    public:
138
      typedef _Map Map;
139
      typedef _Converter Converter;
140
      typedef _Graph Graph;
141
      typedef typename Graph::Edge Item;
142
      static const bool dir = _dir;
143
      
144
    private:
145
      const Graph& _graph;
146
      const Map& _map;
147
      Converter _converter;
148

	
149
    public:
150
      GraphArcMapStorage(const Graph& graph, const Map& map,  
151
			 const Converter& converter = Converter()) 
152
	: _graph(graph), _map(map), _converter(converter) {}
153
      virtual ~GraphArcMapStorage() {}
154

	
155
      virtual std::string get(const Item& item) {
156
	return _converter(_map[_graph.direct(item, dir)]);
157
      }
158
      virtual void sort(std::vector<Item>& items) {
159
	GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
160
	std::sort(items.begin(), items.end(), less);
161
      }
162
    };
163

	
113 164
    class ValueStorageBase {
114 165
    public:
115 166
      ValueStorageBase() {}
... ...
@@ -154,6 +205,26 @@
154 205
      }
155 206
    };
156 207

	
208
    template <typename Graph>
209
    struct GraphArcLookUpConverter {
210
      const Graph& _graph;
211
      const std::map<typename Graph::Edge, std::string>& _map;
212
      
213
      GraphArcLookUpConverter(const Graph& graph, 
214
			      const std::map<typename Graph::Edge, 
215
			                     std::string>& map) 
216
	: _graph(graph), _map(map) {}
217
      
218
      std::string operator()(const typename Graph::Arc& val) {
219
	typename std::map<typename Graph::Edge, std::string>
220
	  ::const_iterator it = _map.find(val);
221
	if (it == _map.end()) {
222
	  throw DataFormatError("Item not found");
223
	}
224
	return (_graph.direction(val) ? '+' : '-') + it->second;
225
      }
226
    };
227

	
157 228
    bool isWhiteSpace(char c) {
158 229
      return c == ' ' || c == '\t' || c == '\v' || 
159 230
        c == '\n' || c == '\r' || c == '\f'; 
... ...
@@ -738,6 +809,517 @@
738 809
    DigraphWriter<Digraph> tmp(fn, digraph);
739 810
    return tmp;
740 811
  }
812

	
813
  /// \ingroup lemon_io
814
  ///  
815
  /// \brief LGF writer for directed graphs
816
  ///
817
  /// This utility writes an \ref lgf-format "LGF" file.
818
  template <typename _Graph>
819
  class GraphWriter {
820
  public:
821

	
822
    typedef _Graph Graph;
823
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
824
    
825
  private:
826

	
827

	
828
    std::ostream* _os;
829
    bool local_os;
830

	
831
    Graph& _graph;
832

	
833
    std::string _nodes_caption;
834
    std::string _edges_caption;
835
    std::string _attributes_caption;
836
    
837
    typedef std::map<Node, std::string> NodeIndex;
838
    NodeIndex _node_index;
839
    typedef std::map<Edge, std::string> EdgeIndex;
840
    EdgeIndex _edge_index;
841

	
842
    typedef std::vector<std::pair<std::string, 
843
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
844
    NodeMaps _node_maps; 
845

	
846
    typedef std::vector<std::pair<std::string, 
847
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
848
    EdgeMaps _edge_maps;
849

	
850
    typedef std::vector<std::pair<std::string, 
851
      _writer_bits::ValueStorageBase*> > Attributes;
852
    Attributes _attributes;
853

	
854
    bool _skip_nodes;
855
    bool _skip_edges;
856

	
857
  public:
858

	
859
    /// \brief Constructor
860
    ///
861
    /// Construct a directed graph writer, which writes to the given
862
    /// output stream.
863
    GraphWriter(std::ostream& is, Graph& graph) 
864
      : _os(&is), local_os(false), _graph(graph),
865
	_skip_nodes(false), _skip_edges(false) {}
866

	
867
    /// \brief Constructor
868
    ///
869
    /// Construct a directed graph writer, which writes to the given
870
    /// output file.
871
    GraphWriter(const std::string& fn, Graph& graph) 
872
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
873
	_skip_nodes(false), _skip_edges(false) {}
874

	
875
    /// \brief Constructor
876
    ///
877
    /// Construct a directed graph writer, which writes to the given
878
    /// output file.
879
    GraphWriter(const char* fn, Graph& graph) 
880
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
881
	_skip_nodes(false), _skip_edges(false) {}
882

	
883
    /// \brief Copy constructor
884
    ///
885
    /// The copy constructor transfers all data from the other writer,
886
    /// therefore the copied writer will not be usable more. 
887
    GraphWriter(GraphWriter& other) 
888
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
889
	_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
890

	
891
      other._os = 0;
892
      other.local_os = false;
893

	
894
      _node_index.swap(other._node_index);
895
      _edge_index.swap(other._edge_index);
896

	
897
      _node_maps.swap(other._node_maps);
898
      _edge_maps.swap(other._edge_maps);
899
      _attributes.swap(other._attributes);
900

	
901
      _nodes_caption = other._nodes_caption;
902
      _edges_caption = other._edges_caption;
903
      _attributes_caption = other._attributes_caption;
904
    }
905

	
906
    /// \brief Destructor
907
    ~GraphWriter() {
908
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
909
	   it != _node_maps.end(); ++it) {
910
	delete it->second;
911
      }
912

	
913
      for (typename EdgeMaps::iterator it = _edge_maps.begin(); 
914
	   it != _edge_maps.end(); ++it) {
915
	delete it->second;
916
      }
917

	
918
      for (typename Attributes::iterator it = _attributes.begin(); 
919
	   it != _attributes.end(); ++it) {
920
	delete it->second;
921
      }
922

	
923
      if (local_os) {
924
	delete _os;
925
      }
926
    }
927

	
928
  private:
929
    
930
    GraphWriter& operator=(const GraphWriter&);
931

	
932
  public:
933

	
934
    /// \name Writing rules
935
    /// @{
936
    
937
    /// \brief Node map reading rule
938
    ///
939
    /// Add a node map reading rule to the writer.
940
    template <typename Map>
941
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
942
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
943
      _writer_bits::MapStorageBase<Node>* storage = 
944
	new _writer_bits::MapStorage<Node, Map>(map);
945
      _node_maps.push_back(std::make_pair(caption, storage));
946
      return *this;
947
    }
948

	
949
    /// \brief Node map writing rule
950
    ///
951
    /// Add a node map writing rule with specialized converter to the
952
    /// writer.
953
    template <typename Map, typename Converter>
954
    GraphWriter& nodeMap(const std::string& caption, const Map& map, 
955
			   const Converter& converter = Converter()) {
956
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
957
      _writer_bits::MapStorageBase<Node>* storage = 
958
	new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
959
      _node_maps.push_back(std::make_pair(caption, storage));
960
      return *this;
961
    }
962

	
963
    /// \brief Edge map writing rule
964
    ///
965
    /// Add an edge map writing rule to the writer.
966
    template <typename Map>
967
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
968
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
969
      _writer_bits::MapStorageBase<Edge>* storage = 
970
	new _writer_bits::MapStorage<Edge, Map>(map);
971
      _edge_maps.push_back(std::make_pair(caption, storage));
972
      return *this;
973
    }
974

	
975
    /// \brief Edge map writing rule
976
    ///
977
    /// Add an edge map writing rule with specialized converter to the
978
    /// writer.
979
    template <typename Map, typename Converter>
980
    GraphWriter& edgeMap(const std::string& caption, const Map& map, 
981
			  const Converter& converter = Converter()) {
982
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
983
      _writer_bits::MapStorageBase<Edge>* storage = 
984
	new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
985
      _edge_maps.push_back(std::make_pair(caption, storage));
986
      return *this;
987
    }
988

	
989
    /// \brief Arc map writing rule
990
    ///
991
    /// Add an arc map writing rule to the writer.
992
    template <typename Map>
993
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
994
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
995
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
996
	new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
997
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
998
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
999
	new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1000
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1001
      return *this;
1002
    }
1003

	
1004
    /// \brief Arc map writing rule
1005
    ///
1006
    /// Add an arc map writing rule with specialized converter to the
1007
    /// writer.
1008
    template <typename Map, typename Converter>
1009
    GraphWriter& arcMap(const std::string& caption, const Map& map, 
1010
			  const Converter& converter = Converter()) {
1011
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
1012
      _writer_bits::MapStorageBase<Edge>* forward_storage = 
1013
	new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1014
	(_graph, map, converter);
1015
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1016
      _writer_bits::MapStorageBase<Edge>* backward_storage = 
1017
	new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1018
	(_graph, map, converter);
1019
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1020
      return *this;
1021
    }
1022

	
1023
    /// \brief Attribute writing rule
1024
    ///
1025
    /// Add an attribute writing rule to the writer.
1026
    template <typename Value>
1027
    GraphWriter& attribute(const std::string& caption, const Value& value) {
1028
      _writer_bits::ValueStorageBase* storage = 
1029
	new _writer_bits::ValueStorage<Value>(value);
1030
      _attributes.push_back(std::make_pair(caption, storage));
1031
      return *this;
1032
    }
1033

	
1034
    /// \brief Attribute writing rule
1035
    ///
1036
    /// Add an attribute writing rule with specialized converter to the
1037
    /// writer.
1038
    template <typename Value, typename Converter>
1039
    GraphWriter& attribute(const std::string& caption, const Value& value, 
1040
			     const Converter& converter = Converter()) {
1041
      _writer_bits::ValueStorageBase* storage = 
1042
	new _writer_bits::ValueStorage<Value, Converter>(value, converter);
1043
      _attributes.push_back(std::make_pair(caption, storage));
1044
      return *this;
1045
    }
1046

	
1047
    /// \brief Node writing rule
1048
    ///
1049
    /// Add a node writing rule to the writer.
1050
    GraphWriter& node(const std::string& caption, const Node& node) {
1051
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
1052
      Converter converter(_node_index);
1053
      _writer_bits::ValueStorageBase* storage = 
1054
	new _writer_bits::ValueStorage<Node, Converter>(node, converter);
1055
      _attributes.push_back(std::make_pair(caption, storage));
1056
      return *this;
1057
    }
1058

	
1059
    /// \brief Edge writing rule
1060
    ///
1061
    /// Add an edge writing rule to writer.
1062
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
1063
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
1064
      Converter converter(_edge_index);
1065
      _writer_bits::ValueStorageBase* storage = 
1066
	new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
1067
      _attributes.push_back(std::make_pair(caption, storage));
1068
      return *this;
1069
    }
1070

	
1071
    /// \brief Arc writing rule
1072
    ///
1073
    /// Add an arc writing rule to writer.
1074
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
1075
      typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter;
1076
      Converter converter(_graph, _edge_index);
1077
      _writer_bits::ValueStorageBase* storage = 
1078
	new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
1079
      _attributes.push_back(std::make_pair(caption, storage));
1080
      return *this;
1081
    }
1082

	
1083
    /// \name Select section by name
1084
    /// @{
1085

	
1086
    /// \brief Set \c \@nodes section to be read
1087
    ///
1088
    /// Set \c \@nodes section to be read
1089
    GraphWriter& nodes(const std::string& caption) {
1090
      _nodes_caption = caption;
1091
      return *this;
1092
    }
1093

	
1094
    /// \brief Set \c \@edges section to be read
1095
    ///
1096
    /// Set \c \@edges section to be read
1097
    GraphWriter& edges(const std::string& caption) {
1098
      _edges_caption = caption;
1099
      return *this;
1100
    }
1101

	
1102
    /// \brief Set \c \@attributes section to be read
1103
    ///
1104
    /// Set \c \@attributes section to be read
1105
    GraphWriter& attributes(const std::string& caption) {
1106
      _attributes_caption = caption;
1107
      return *this;
1108
    }
1109

	
1110
    /// \name Skipping section
1111
    /// @{
1112

	
1113
    /// \brief Skip writing the node set
1114
    ///
1115
    /// The \c \@nodes section will be not written to the stream.
1116
    GraphWriter& skipNodes() {
1117
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
1118
      return *this;
1119
    }
1120

	
1121
    /// \brief Skip writing edge set
1122
    ///
1123
    /// The \c \@edges section will be not written to the stream.
1124
    GraphWriter& skipEdges() {
1125
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
1126
      return *this;
1127
    }
1128

	
1129
    /// @}
1130

	
1131
  private:
1132

	
1133
    void writeNodes() {
1134
      _writer_bits::MapStorageBase<Node>* label = 0;
1135
      for (typename NodeMaps::iterator it = _node_maps.begin();
1136
	   it != _node_maps.end(); ++it) {
1137
        if (it->first == "label") {
1138
	  label = it->second;
1139
	  break;
1140
	}
1141
      }
1142

	
1143
      *_os << "@nodes";
1144
      if (!_nodes_caption.empty()) {
1145
	_writer_bits::writeToken(*_os << ' ', _nodes_caption);
1146
      }
1147
      *_os << std::endl;
1148

	
1149
      if (label == 0) {
1150
	*_os << "label" << '\t';
1151
      }
1152
      for (typename NodeMaps::iterator it = _node_maps.begin();
1153
	   it != _node_maps.end(); ++it) {
1154
	_writer_bits::writeToken(*_os, it->first) << '\t';
1155
      }
1156
      *_os << std::endl;
1157

	
1158
      std::vector<Node> nodes;
1159
      for (NodeIt n(_graph); n != INVALID; ++n) {
1160
	nodes.push_back(n);
1161
      }
1162
      
1163
      if (label == 0) {
1164
	IdMap<Graph, Node> id_map(_graph);
1165
	_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map);
1166
	std::sort(nodes.begin(), nodes.end(), id_less);
1167
      } else {
1168
	label->sort(nodes);
1169
      }
1170

	
1171
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
1172
	Node n = nodes[i];
1173
	if (label == 0) {
1174
	  std::ostringstream os;
1175
	  os << _graph.id(n);
1176
	  _writer_bits::writeToken(*_os, os.str());
1177
	  *_os << '\t';
1178
	  _node_index.insert(std::make_pair(n, os.str()));
1179
	}
1180
	for (typename NodeMaps::iterator it = _node_maps.begin();
1181
	     it != _node_maps.end(); ++it) {
1182
	  std::string value = it->second->get(n);
1183
	  _writer_bits::writeToken(*_os, value);
1184
	  if (it->first == "label") {
1185
	    _node_index.insert(std::make_pair(n, value));
1186
	  }
1187
	  *_os << '\t';
1188
	}
1189
	*_os << std::endl;
1190
      }
1191
    }
1192

	
1193
    void writeEdges() {
1194
      _writer_bits::MapStorageBase<Edge>* label = 0;
1195
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1196
	   it != _edge_maps.end(); ++it) {
1197
        if (it->first == "label") {
1198
	  label = it->second;
1199
	  break;
1200
	}
1201
      }
1202

	
1203
      *_os << "@edges";
1204
      if (!_edges_caption.empty()) {
1205
	_writer_bits::writeToken(*_os << ' ', _edges_caption);
1206
      }
1207
      *_os << std::endl;
1208

	
1209
      *_os << '\t' << '\t';
1210
      if (label == 0) {
1211
	*_os << "label" << '\t';
1212
      }
1213
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1214
	   it != _edge_maps.end(); ++it) {
1215
	_writer_bits::writeToken(*_os, it->first) << '\t';
1216
      }
1217
      *_os << std::endl;
1218

	
1219
      std::vector<Edge> edges;
1220
      for (EdgeIt n(_graph); n != INVALID; ++n) {
1221
	edges.push_back(n);
1222
      }
1223
      
1224
      if (label == 0) {
1225
	IdMap<Graph, Edge> id_map(_graph);
1226
	_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map);
1227
	std::sort(edges.begin(), edges.end(), id_less);
1228
      } else {
1229
	label->sort(edges);
1230
      }
1231

	
1232
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
1233
	Edge e = edges[i];
1234
	_writer_bits::writeToken(*_os, _node_index.
1235
				 find(_graph.u(e))->second);
1236
	*_os << '\t';
1237
	_writer_bits::writeToken(*_os, _node_index.
1238
				 find(_graph.v(e))->second);
1239
	*_os << '\t';
1240
	if (label == 0) {
1241
	  std::ostringstream os;
1242
	  os << _graph.id(e);
1243
	  _writer_bits::writeToken(*_os, os.str());
1244
	  *_os << '\t';
1245
	  _edge_index.insert(std::make_pair(e, os.str()));
1246
	}
1247
	for (typename EdgeMaps::iterator it = _edge_maps.begin();
1248
	     it != _edge_maps.end(); ++it) {
1249
	  std::string value = it->second->get(e);
1250
	  _writer_bits::writeToken(*_os, value);
1251
	  if (it->first == "label") {
1252
	    _edge_index.insert(std::make_pair(e, value));
1253
	  }
1254
	  *_os << '\t';
1255
	}
1256
	*_os << std::endl;
1257
      }
1258
    }
1259

	
1260
    void writeAttributes() {
1261
      if (_attributes.empty()) return;
1262
      *_os << "@attributes";
1263
      if (!_attributes_caption.empty()) {
1264
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
1265
      }
1266
      *_os << std::endl;
1267
      for (typename Attributes::iterator it = _attributes.begin();
1268
	   it != _attributes.end(); ++it) {
1269
	_writer_bits::writeToken(*_os, it->first) << ' ';
1270
	_writer_bits::writeToken(*_os, it->second->get());
1271
	*_os << std::endl;
1272
      }
1273
    }
1274
    
1275
  public:
1276
    
1277
    /// \name Execution of the writer    
1278
    /// @{
1279

	
1280
    /// \brief Start the batch processing
1281
    ///
1282
    /// This function starts the batch processing
1283
    void run() {
1284
      if (!_skip_nodes) {
1285
	writeNodes();
1286
      }
1287
      if (!_skip_edges) {      
1288
	writeEdges();
1289
      }
1290
      writeAttributes();
1291
    }
1292

	
1293
    /// \brief Gives back the stream of the writer
1294
    ///
1295
    /// Gives back the stream of the writer
1296
    std::ostream& ostream() {
1297
      return *_os;
1298
    }
1299

	
1300
    /// @}
1301
  };
1302

	
1303
  /// \relates GraphWriter
1304
  template <typename Graph>
1305
  GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) {
1306
    GraphWriter<Graph> tmp(os, graph);
1307
    return tmp;
1308
  }
1309

	
1310
  /// \relates GraphWriter
1311
  template <typename Graph>
1312
  GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) {
1313
    GraphWriter<Graph> tmp(fn, graph);
1314
    return tmp;
1315
  }
1316

	
1317
  /// \relates GraphWriter
1318
  template <typename Graph>
1319
  GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) {
1320
    GraphWriter<Graph> tmp(fn, graph);
1321
    return tmp;
1322
  }
741 1323
}
742 1324

	
743 1325
#endif
0 comments (0 inline)