1178 template <typename Digraph> |
1227 template <typename Digraph> |
1179 DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { |
1228 DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) { |
1180 DigraphReader<Digraph> tmp(fn, digraph); |
1229 DigraphReader<Digraph> tmp(fn, digraph); |
1181 return tmp; |
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 #endif |
2076 #endif |