gravatar
ladanyi@tmit.bme.hu
ladanyi@tmit.bme.hu
Fix compilation with Visual Studio 2005.
0 2 0
default
2 files changed with 94 insertions and 136 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -298,201 +298,223 @@
298 298
      if (c == '\"') {
299 299
        while (is.get(c) && c != '\"') {
300 300
          if (c == '\\')
301 301
            c = readEscape(is);
302 302
          os << c;
303 303
        }
304 304
        if (!is)
305 305
          throw FormatError("Quoted format error");
306 306
      } else {
307 307
        is.putback(c);
308 308
        while (is.get(c) && !isWhiteSpace(c)) {
309 309
          if (c == '\\')
310 310
            c = readEscape(is);
311 311
          os << c;
312 312
        }
313 313
        if (!is) {
314 314
          is.clear();
315 315
        } else {
316 316
          is.putback(c);
317 317
        }
318 318
      }
319 319
      str = os.str();
320 320
      return is;
321 321
    }
322 322

	
323 323
    class Section {
324 324
    public:
325 325
      virtual ~Section() {}
326 326
      virtual void process(std::istream& is, int& line_num) = 0;
327 327
    };
328 328

	
329 329
    template <typename Functor>
330 330
    class LineSection : public Section {
331 331
    private:
332 332

	
333 333
      Functor _functor;
334 334

	
335 335
    public:
336 336

	
337 337
      LineSection(const Functor& functor) : _functor(functor) {}
338 338
      virtual ~LineSection() {}
339 339

	
340 340
      virtual void process(std::istream& is, int& line_num) {
341 341
        char c;
342 342
        std::string line;
343 343
        while (is.get(c) && c != '@') {
344 344
          if (c == '\n') {
345 345
            ++line_num;
346 346
          } else if (c == '#') {
347 347
            getline(is, line);
348 348
            ++line_num;
349 349
          } else if (!isWhiteSpace(c)) {
350 350
            is.putback(c);
351 351
            getline(is, line);
352 352
            _functor(line);
353 353
            ++line_num;
354 354
          }
355 355
        }
356 356
        if (is) is.putback(c);
357 357
        else if (is.eof()) is.clear();
358 358
      }
359 359
    };
360 360

	
361 361
    template <typename Functor>
362 362
    class StreamSection : public Section {
363 363
    private:
364 364

	
365 365
      Functor _functor;
366 366

	
367 367
    public:
368 368

	
369 369
      StreamSection(const Functor& functor) : _functor(functor) {}
370 370
      virtual ~StreamSection() {}
371 371

	
372 372
      virtual void process(std::istream& is, int& line_num) {
373 373
        _functor(is, line_num);
374 374
        char c;
375 375
        std::string line;
376 376
        while (is.get(c) && c != '@') {
377 377
          if (c == '\n') {
378 378
            ++line_num;
379 379
          } else if (!isWhiteSpace(c)) {
380 380
            getline(is, line);
381 381
            ++line_num;
382 382
          }
383 383
        }
384 384
        if (is) is.putback(c);
385 385
        else if (is.eof()) is.clear();
386 386
      }
387 387
    };
388 388

	
389 389
  }
390 390

	
391 391
  template <typename Digraph>
392 392
  class DigraphReader;
393 393

	
394
  /// \brief Return a \ref DigraphReader class
395
  ///
396
  /// This function just returns a \ref DigraphReader class.
397
  /// \relates DigraphReader
394 398
  template <typename Digraph>
395 399
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
396
                                       std::istream& is = std::cin);
397

	
400
                                       std::istream& is = std::cin) {
401
    DigraphReader<Digraph> tmp(digraph, is);
402
    return tmp;
403
  }
404

	
405
  /// \brief Return a \ref DigraphReader class
406
  ///
407
  /// This function just returns a \ref DigraphReader class.
408
  /// \relates DigraphReader
398 409
  template <typename Digraph>
399
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const std::string& fn);
400

	
410
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
411
                                       const std::string& fn) {
412
    DigraphReader<Digraph> tmp(digraph, fn);
413
    return tmp;
414
  }
415

	
416
  /// \brief Return a \ref DigraphReader class
417
  ///
418
  /// This function just returns a \ref DigraphReader class.
419
  /// \relates DigraphReader
401 420
  template <typename Digraph>
402
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char *fn);
421
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
422
    DigraphReader<Digraph> tmp(digraph, fn);
423
    return tmp;
424
  }
403 425

	
404 426
  /// \ingroup lemon_io
405 427
  ///
406 428
  /// \brief \ref lgf-format "LGF" reader for directed graphs
407 429
  ///
408 430
  /// This utility reads an \ref lgf-format "LGF" file.
409 431
  ///
410 432
  /// The reading method does a batch processing. The user creates a
411 433
  /// reader object, then various reading rules can be added to the
412 434
  /// reader, and eventually the reading is executed with the \c run()
413 435
  /// member function. A map reading rule can be added to the reader
414 436
  /// with the \c nodeMap() or \c arcMap() members. An optional
415 437
  /// converter parameter can also be added as a standard functor
416 438
  /// converting from \c std::string to the value type of the map. If it
417 439
  /// is set, it will determine how the tokens in the file should be
418 440
  /// converted to the value type of the map. If the functor is not set,
419 441
  /// then a default conversion will be used. One map can be read into
420 442
  /// multiple map objects at the same time. The \c attribute(), \c
421 443
  /// node() and \c arc() functions are used to add attribute reading
422 444
  /// rules.
423 445
  ///
424 446
  ///\code
425 447
  /// DigraphReader<Digraph>(digraph, std::cin).
426 448
  ///   nodeMap("coordinates", coord_map).
427 449
  ///   arcMap("capacity", cap_map).
428 450
  ///   node("source", src).
429 451
  ///   node("target", trg).
430 452
  ///   attribute("caption", caption).
431 453
  ///   run();
432 454
  ///\endcode
433 455
  ///
434 456
  /// By default the reader uses the first section in the file of the
435 457
  /// proper type. If a section has an optional name, then it can be
436 458
  /// selected for reading by giving an optional name parameter to the
437 459
  /// \c nodes(), \c arcs() or \c attributes() functions.
438 460
  ///
439 461
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
440 462
  /// that the nodes or arcs should not be constructed (added to the
441 463
  /// graph) during the reading, but instead the label map of the items
442 464
  /// are given as a parameter of these functions. An
443 465
  /// application of these functions is multipass reading, which is
444 466
  /// important if two \c \@arcs sections must be read from the
445 467
  /// file. In this case the first phase would read the node set and one
446 468
  /// of the arc sets, while the second phase would read the second arc
447 469
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
448 470
  /// The previously read label node map should be passed to the \c
449 471
  /// useNodes() functions. Another application of multipass reading when
450 472
  /// paths are given as a node map or an arc map.
451 473
  /// It is impossible to read this in
452 474
  /// a single pass, because the arcs are not constructed when the node
453 475
  /// maps are read.
454 476
  template <typename _Digraph>
455 477
  class DigraphReader {
456 478
  public:
457 479

	
458 480
    typedef _Digraph Digraph;
459 481
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
460 482

	
461 483
  private:
462 484

	
463 485

	
464 486
    std::istream* _is;
465 487
    bool local_is;
466 488
    std::string _filename;
467 489

	
468 490
    Digraph& _digraph;
469 491

	
470 492
    std::string _nodes_caption;
471 493
    std::string _arcs_caption;
472 494
    std::string _attributes_caption;
473 495

	
474 496
    typedef std::map<std::string, Node> NodeIndex;
475 497
    NodeIndex _node_index;
476 498
    typedef std::map<std::string, Arc> ArcIndex;
477 499
    ArcIndex _arc_index;
478 500

	
479 501
    typedef std::vector<std::pair<std::string,
480 502
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
481 503
    NodeMaps _node_maps;
482 504

	
483 505
    typedef std::vector<std::pair<std::string,
484 506
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
485 507
    ArcMaps _arc_maps;
486 508

	
487 509
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
488 510
      Attributes;
489 511
    Attributes _attributes;
490 512

	
491 513
    bool _use_nodes;
492 514
    bool _use_arcs;
493 515

	
494 516
    bool _skip_nodes;
495 517
    bool _skip_arcs;
496 518

	
497 519
    int line_num;
498 520
    std::istringstream line;
... ...
@@ -1096,237 +1118,225 @@
1096 1118
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1097 1119
          while (it != _attributes.end() && it->first == attr) {
1098 1120
            it->second->set(token);
1099 1121
            ++it;
1100 1122
          }
1101 1123
        }
1102 1124

	
1103 1125
      }
1104 1126
      if (readSuccess()) {
1105 1127
        line.putback(c);
1106 1128
      }
1107 1129
      for (typename Attributes::iterator it = _attributes.begin();
1108 1130
           it != _attributes.end(); ++it) {
1109 1131
        if (read_attr.find(it->first) == read_attr.end()) {
1110 1132
          std::ostringstream msg;
1111 1133
          msg << "Attribute not found: " << it->first;
1112 1134
          throw FormatError(msg.str());
1113 1135
        }
1114 1136
      }
1115 1137
    }
1116 1138

	
1117 1139
  public:
1118 1140

	
1119 1141
    /// \name Execution of the reader
1120 1142
    /// @{
1121 1143

	
1122 1144
    /// \brief Start the batch processing
1123 1145
    ///
1124 1146
    /// This function starts the batch processing
1125 1147
    void run() {
1126 1148
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1127 1149

	
1128 1150
      bool nodes_done = _skip_nodes;
1129 1151
      bool arcs_done = _skip_arcs;
1130 1152
      bool attributes_done = false;
1131 1153

	
1132 1154
      line_num = 0;
1133 1155
      readLine();
1134 1156
      skipSection();
1135 1157

	
1136 1158
      while (readSuccess()) {
1137 1159
        try {
1138 1160
          char c;
1139 1161
          std::string section, caption;
1140 1162
          line >> c;
1141 1163
          _reader_bits::readToken(line, section);
1142 1164
          _reader_bits::readToken(line, caption);
1143 1165

	
1144 1166
          if (line >> c)
1145 1167
            throw FormatError("Extra character at the end of line");
1146 1168

	
1147 1169
          if (section == "nodes" && !nodes_done) {
1148 1170
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1149 1171
              readNodes();
1150 1172
              nodes_done = true;
1151 1173
            }
1152 1174
          } else if ((section == "arcs" || section == "edges") &&
1153 1175
                     !arcs_done) {
1154 1176
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1155 1177
              readArcs();
1156 1178
              arcs_done = true;
1157 1179
            }
1158 1180
          } else if (section == "attributes" && !attributes_done) {
1159 1181
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1160 1182
              readAttributes();
1161 1183
              attributes_done = true;
1162 1184
            }
1163 1185
          } else {
1164 1186
            readLine();
1165 1187
            skipSection();
1166 1188
          }
1167 1189
        } catch (FormatError& error) {
1168 1190
          error.line(line_num);
1169 1191
          error.file(_filename);
1170 1192
          throw;
1171 1193
        }
1172 1194
      }
1173 1195

	
1174 1196
      if (!nodes_done) {
1175 1197
        throw FormatError("Section @nodes not found");
1176 1198
      }
1177 1199

	
1178 1200
      if (!arcs_done) {
1179 1201
        throw FormatError("Section @arcs not found");
1180 1202
      }
1181 1203

	
1182 1204
      if (!attributes_done && !_attributes.empty()) {
1183 1205
        throw FormatError("Section @attributes not found");
1184 1206
      }
1185 1207

	
1186 1208
    }
1187 1209

	
1188 1210
    /// @}
1189 1211

	
1190 1212
  };
1191 1213

	
1192
  /// \brief Return a \ref DigraphReader class
1214
  template <typename Graph>
1215
  class GraphReader;
1216

	
1217
  /// \brief Return a \ref GraphReader class
1193 1218
  ///
1194
  /// This function just returns a \ref DigraphReader class.
1195
  /// \relates DigraphReader
1196
  template <typename Digraph>
1197
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1198
                                       std::istream& is = std::cin) {
1199
    DigraphReader<Digraph> tmp(digraph, is);
1219
  /// This function just returns a \ref GraphReader class.
1220
  /// \relates GraphReader
1221
  template <typename Graph>
1222
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
1223
    GraphReader<Graph> tmp(graph, is);
1200 1224
    return tmp;
1201 1225
  }
1202 1226

	
1203
  /// \brief Return a \ref DigraphReader class
1227
  /// \brief Return a \ref GraphReader class
1204 1228
  ///
1205
  /// This function just returns a \ref DigraphReader class.
1206
  /// \relates DigraphReader
1207
  template <typename Digraph>
1208
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1209
                                       const std::string& fn) {
1210
    DigraphReader<Digraph> tmp(digraph, fn);
1229
  /// This function just returns a \ref GraphReader class.
1230
  /// \relates GraphReader
1231
  template <typename Graph>
1232
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
1233
    GraphReader<Graph> tmp(graph, fn);
1211 1234
    return tmp;
1212 1235
  }
1213 1236

	
1214
  /// \brief Return a \ref DigraphReader class
1237
  /// \brief Return a \ref GraphReader class
1215 1238
  ///
1216
  /// This function just returns a \ref DigraphReader class.
1217
  /// \relates DigraphReader
1218
  template <typename Digraph>
1219
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
1220
    DigraphReader<Digraph> tmp(digraph, fn);
1239
  /// This function just returns a \ref GraphReader class.
1240
  /// \relates GraphReader
1241
  template <typename Graph>
1242
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
1243
    GraphReader<Graph> tmp(graph, fn);
1221 1244
    return tmp;
1222 1245
  }
1223 1246

	
1224
  template <typename Graph>
1225
  class GraphReader;
1226

	
1227
  template <typename Graph>
1228
  GraphReader<Graph> graphReader(Graph& graph,
1229
                                 std::istream& is = std::cin);
1230

	
1231
  template <typename Graph>
1232
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn);
1233

	
1234
  template <typename Graph>
1235
  GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1236

	
1237 1247
  /// \ingroup lemon_io
1238 1248
  ///
1239 1249
  /// \brief \ref lgf-format "LGF" reader for undirected graphs
1240 1250
  ///
1241 1251
  /// This utility reads an \ref lgf-format "LGF" file.
1242 1252
  ///
1243 1253
  /// It can be used almost the same way as \c DigraphReader.
1244 1254
  /// The only difference is that this class can handle edges and
1245 1255
  /// edge maps as well as arcs and arc maps.
1246 1256
  ///
1247 1257
  /// The columns in the \c \@edges (or \c \@arcs) section are the
1248 1258
  /// edge maps. However, if there are two maps with the same name
1249 1259
  /// prefixed with \c '+' and \c '-', then these can be read into an
1250 1260
  /// arc map.  Similarly, an attribute can be read into an arc, if
1251 1261
  /// it's value is an edge label prefixed with \c '+' or \c '-'.
1252 1262
  template <typename _Graph>
1253 1263
  class GraphReader {
1254 1264
  public:
1255 1265

	
1256 1266
    typedef _Graph Graph;
1257 1267
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1258 1268

	
1259 1269
  private:
1260 1270

	
1261 1271
    std::istream* _is;
1262 1272
    bool local_is;
1263 1273
    std::string _filename;
1264 1274

	
1265 1275
    Graph& _graph;
1266 1276

	
1267 1277
    std::string _nodes_caption;
1268 1278
    std::string _edges_caption;
1269 1279
    std::string _attributes_caption;
1270 1280

	
1271 1281
    typedef std::map<std::string, Node> NodeIndex;
1272 1282
    NodeIndex _node_index;
1273 1283
    typedef std::map<std::string, Edge> EdgeIndex;
1274 1284
    EdgeIndex _edge_index;
1275 1285

	
1276 1286
    typedef std::vector<std::pair<std::string,
1277 1287
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1278 1288
    NodeMaps _node_maps;
1279 1289

	
1280 1290
    typedef std::vector<std::pair<std::string,
1281 1291
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1282 1292
    EdgeMaps _edge_maps;
1283 1293

	
1284 1294
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1285 1295
      Attributes;
1286 1296
    Attributes _attributes;
1287 1297

	
1288 1298
    bool _use_nodes;
1289 1299
    bool _use_edges;
1290 1300

	
1291 1301
    bool _skip_nodes;
1292 1302
    bool _skip_edges;
1293 1303

	
1294 1304
    int line_num;
1295 1305
    std::istringstream line;
1296 1306

	
1297 1307
  public:
1298 1308

	
1299 1309
    /// \brief Constructor
1300 1310
    ///
1301 1311
    /// Construct an undirected graph reader, which reads from the given
1302 1312
    /// input stream.
1303 1313
    GraphReader(Graph& graph, std::istream& is = std::cin)
1304 1314
      : _is(&is), local_is(false), _graph(graph),
1305 1315
        _use_nodes(false), _use_edges(false),
1306 1316
        _skip_nodes(false), _skip_edges(false) {}
1307 1317

	
1308 1318
    /// \brief Constructor
1309 1319
    ///
1310 1320
    /// Construct an undirected graph reader, which reads from the given
1311 1321
    /// file.
1312 1322
    GraphReader(Graph& graph, const std::string& fn)
1313 1323
      : _is(new std::ifstream(fn.c_str())), local_is(true),
1314 1324
        _filename(fn), _graph(graph),
1315 1325
        _use_nodes(false), _use_edges(false),
1316 1326
        _skip_nodes(false), _skip_edges(false) {
1317 1327
      if (!(*_is)) {
1318 1328
        delete _is;
1319 1329
        throw IoError("Cannot open file", fn);
1320 1330
      }
1321 1331
    }
1322 1332

	
1323 1333
    /// \brief Constructor
1324 1334
    ///
1325 1335
    /// Construct an undirected graph reader, which reads from the given
1326 1336
    /// file.
1327 1337
    GraphReader(Graph& graph, const char* fn)
1328 1338
      : _is(new std::ifstream(fn)), local_is(true),
1329 1339
        _filename(fn), _graph(graph),
1330 1340
        _use_nodes(false), _use_edges(false),
1331 1341
        _skip_nodes(false), _skip_edges(false) {
1332 1342
      if (!(*_is)) {
... ...
@@ -1938,222 +1948,192 @@
1938 1948
          while (it != _attributes.end() && it->first == attr) {
1939 1949
            it->second->set(token);
1940 1950
            ++it;
1941 1951
          }
1942 1952
        }
1943 1953

	
1944 1954
      }
1945 1955
      if (readSuccess()) {
1946 1956
        line.putback(c);
1947 1957
      }
1948 1958
      for (typename Attributes::iterator it = _attributes.begin();
1949 1959
           it != _attributes.end(); ++it) {
1950 1960
        if (read_attr.find(it->first) == read_attr.end()) {
1951 1961
          std::ostringstream msg;
1952 1962
          msg << "Attribute not found: " << it->first;
1953 1963
          throw FormatError(msg.str());
1954 1964
        }
1955 1965
      }
1956 1966
    }
1957 1967

	
1958 1968
  public:
1959 1969

	
1960 1970
    /// \name Execution of the reader
1961 1971
    /// @{
1962 1972

	
1963 1973
    /// \brief Start the batch processing
1964 1974
    ///
1965 1975
    /// This function starts the batch processing
1966 1976
    void run() {
1967 1977

	
1968 1978
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1969 1979

	
1970 1980
      bool nodes_done = _skip_nodes;
1971 1981
      bool edges_done = _skip_edges;
1972 1982
      bool attributes_done = false;
1973 1983

	
1974 1984
      line_num = 0;
1975 1985
      readLine();
1976 1986
      skipSection();
1977 1987

	
1978 1988
      while (readSuccess()) {
1979 1989
        try {
1980 1990
          char c;
1981 1991
          std::string section, caption;
1982 1992
          line >> c;
1983 1993
          _reader_bits::readToken(line, section);
1984 1994
          _reader_bits::readToken(line, caption);
1985 1995

	
1986 1996
          if (line >> c)
1987 1997
            throw FormatError("Extra character at the end of line");
1988 1998

	
1989 1999
          if (section == "nodes" && !nodes_done) {
1990 2000
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1991 2001
              readNodes();
1992 2002
              nodes_done = true;
1993 2003
            }
1994 2004
          } else if ((section == "edges" || section == "arcs") &&
1995 2005
                     !edges_done) {
1996 2006
            if (_edges_caption.empty() || _edges_caption == caption) {
1997 2007
              readEdges();
1998 2008
              edges_done = true;
1999 2009
            }
2000 2010
          } else if (section == "attributes" && !attributes_done) {
2001 2011
            if (_attributes_caption.empty() || _attributes_caption == caption) {
2002 2012
              readAttributes();
2003 2013
              attributes_done = true;
2004 2014
            }
2005 2015
          } else {
2006 2016
            readLine();
2007 2017
            skipSection();
2008 2018
          }
2009 2019
        } catch (FormatError& error) {
2010 2020
          error.line(line_num);
2011 2021
          error.file(_filename);
2012 2022
          throw;
2013 2023
        }
2014 2024
      }
2015 2025

	
2016 2026
      if (!nodes_done) {
2017 2027
        throw FormatError("Section @nodes not found");
2018 2028
      }
2019 2029

	
2020 2030
      if (!edges_done) {
2021 2031
        throw FormatError("Section @edges not found");
2022 2032
      }
2023 2033

	
2024 2034
      if (!attributes_done && !_attributes.empty()) {
2025 2035
        throw FormatError("Section @attributes not found");
2026 2036
      }
2027 2037

	
2028 2038
    }
2029 2039

	
2030 2040
    /// @}
2031 2041

	
2032 2042
  };
2033 2043

	
2034
  /// \brief Return a \ref GraphReader class
2035
  ///
2036
  /// This function just returns a \ref GraphReader class.
2037
  /// \relates GraphReader
2038
  template <typename Graph>
2039
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is = std::cin) {
2040
    GraphReader<Graph> tmp(graph, is);
2041
    return tmp;
2042
  }
2043

	
2044
  /// \brief Return a \ref GraphReader class
2045
  ///
2046
  /// This function just returns a \ref GraphReader class.
2047
  /// \relates GraphReader
2048
  template <typename Graph>
2049
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
2050
    GraphReader<Graph> tmp(graph, fn);
2051
    return tmp;
2052
  }
2053

	
2054
  /// \brief Return a \ref GraphReader class
2055
  ///
2056
  /// This function just returns a \ref GraphReader class.
2057
  /// \relates GraphReader
2058
  template <typename Graph>
2059
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
2060
    GraphReader<Graph> tmp(graph, fn);
2061
    return tmp;
2062
  }
2063

	
2064 2044
  class SectionReader;
2065 2045

	
2066 2046
  SectionReader sectionReader(std::istream& is);
2067 2047
  SectionReader sectionReader(const std::string& fn);
2068 2048
  SectionReader sectionReader(const char* fn);
2069 2049

	
2070 2050
  /// \ingroup lemon_io
2071 2051
  ///
2072 2052
  /// \brief Section reader class
2073 2053
  ///
2074 2054
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2075 2055
  /// which contain any data in arbitrary format. Such sections can be
2076 2056
  /// read with this class. A reading rule can be added to the class
2077 2057
  /// with two different functions. With the \c sectionLines() function a
2078 2058
  /// functor can process the section line-by-line, while with the \c
2079 2059
  /// sectionStream() member the section can be read from an input
2080 2060
  /// stream.
2081 2061
  class SectionReader {
2082 2062
  private:
2083 2063

	
2084 2064
    std::istream* _is;
2085 2065
    bool local_is;
2086 2066
    std::string _filename;
2087 2067

	
2088 2068
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2089 2069
    Sections _sections;
2090 2070

	
2091 2071
    int line_num;
2092 2072
    std::istringstream line;
2093 2073

	
2094 2074
  public:
2095 2075

	
2096 2076
    /// \brief Constructor
2097 2077
    ///
2098 2078
    /// Construct a section reader, which reads from the given input
2099 2079
    /// stream.
2100 2080
    SectionReader(std::istream& is)
2101 2081
      : _is(&is), local_is(false) {}
2102 2082

	
2103 2083
    /// \brief Constructor
2104 2084
    ///
2105 2085
    /// Construct a section reader, which reads from the given file.
2106 2086
    SectionReader(const std::string& fn)
2107 2087
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2108 2088
        _filename(fn) {
2109 2089
      if (!(*_is)) {
2110 2090
        delete _is;
2111 2091
        throw IoError("Cannot open file", fn);
2112 2092
      }
2113 2093
    }
2114 2094

	
2115 2095
    /// \brief Constructor
2116 2096
    ///
2117 2097
    /// Construct a section reader, which reads from the given file.
2118 2098
    SectionReader(const char* fn)
2119 2099
      : _is(new std::ifstream(fn)), local_is(true),
2120 2100
        _filename(fn) {
2121 2101
      if (!(*_is)) {
2122 2102
        delete _is;
2123 2103
        throw IoError("Cannot open file", fn);
2124 2104
      }
2125 2105
    }
2126 2106

	
2127 2107
    /// \brief Destructor
2128 2108
    ~SectionReader() {
2129 2109
      for (Sections::iterator it = _sections.begin();
2130 2110
           it != _sections.end(); ++it) {
2131 2111
        delete it->second;
2132 2112
      }
2133 2113

	
2134 2114
      if (local_is) {
2135 2115
        delete _is;
2136 2116
      }
2137 2117

	
2138 2118
    }
2139 2119

	
2140 2120
  private:
2141 2121

	
2142 2122
    friend SectionReader sectionReader(std::istream& is);
2143 2123
    friend SectionReader sectionReader(const std::string& fn);
2144 2124
    friend SectionReader sectionReader(const char* fn);
2145 2125

	
2146 2126
    SectionReader(SectionReader& other)
2147 2127
      : _is(other._is), local_is(other.local_is) {
2148 2128

	
2149 2129
      other._is = 0;
2150 2130
      other.local_is = false;
2151 2131

	
2152 2132
      _sections.swap(other._sections);
2153 2133
    }
2154 2134

	
2155 2135
    SectionReader& operator=(const SectionReader&);
2156 2136

	
2157 2137
  public:
2158 2138

	
2159 2139
    /// \name Section readers
Ignore white space 192 line context
... ...
@@ -258,203 +258,224 @@
258 258
        return;
259 259
      case '\r':
260 260
        os << "\\r";
261 261
        return;
262 262
      case '\n':
263 263
        os << "\\n";
264 264
        return;
265 265
      case '\t':
266 266
        os << "\\t";
267 267
        return;
268 268
      case '\v':
269 269
        os << "\\v";
270 270
        return;
271 271
      default:
272 272
        if (c < 0x20) {
273 273
          std::ios::fmtflags flags = os.flags();
274 274
          os << '\\' << std::oct << static_cast<int>(c);
275 275
          os.flags(flags);
276 276
        } else {
277 277
          os << c;
278 278
        }
279 279
        return;
280 280
      }
281 281
    }
282 282

	
283 283
    inline bool requireEscape(const std::string& str) {
284 284
      if (str.empty() || str[0] == '@') return true;
285 285
      std::istringstream is(str);
286 286
      char c;
287 287
      while (is.get(c)) {
288 288
        if (isWhiteSpace(c) || isEscaped(c)) {
289 289
          return true;
290 290
        }
291 291
      }
292 292
      return false;
293 293
    }
294 294

	
295 295
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
296 296

	
297 297
      if (requireEscape(str)) {
298 298
        os << '\"';
299 299
        for (std::string::const_iterator it = str.begin();
300 300
             it != str.end(); ++it) {
301 301
          writeEscape(os, *it);
302 302
        }
303 303
        os << '\"';
304 304
      } else {
305 305
        os << str;
306 306
      }
307 307
      return os;
308 308
    }
309 309

	
310 310
    class Section {
311 311
    public:
312 312
      virtual ~Section() {}
313 313
      virtual void process(std::ostream& os) = 0;
314 314
    };
315 315

	
316 316
    template <typename Functor>
317 317
    class LineSection : public Section {
318 318
    private:
319 319

	
320 320
      Functor _functor;
321 321

	
322 322
    public:
323 323

	
324 324
      LineSection(const Functor& functor) : _functor(functor) {}
325 325
      virtual ~LineSection() {}
326 326

	
327 327
      virtual void process(std::ostream& os) {
328 328
        std::string line;
329 329
        while (!(line = _functor()).empty()) os << line << std::endl;
330 330
      }
331 331
    };
332 332

	
333 333
    template <typename Functor>
334 334
    class StreamSection : public Section {
335 335
    private:
336 336

	
337 337
      Functor _functor;
338 338

	
339 339
    public:
340 340

	
341 341
      StreamSection(const Functor& functor) : _functor(functor) {}
342 342
      virtual ~StreamSection() {}
343 343

	
344 344
      virtual void process(std::ostream& os) {
345 345
        _functor(os);
346 346
      }
347 347
    };
348 348

	
349 349
  }
350 350

	
351 351
  template <typename Digraph>
352 352
  class DigraphWriter;
353 353

	
354
  /// \brief Return a \ref DigraphWriter class
355
  ///
356
  /// This function just returns a \ref DigraphWriter class.
357
  /// \relates DigraphWriter
354 358
  template <typename Digraph>
355 359
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
356
                                       std::ostream& os = std::cout);
360
                                       std::ostream& os = std::cout) {
361
    DigraphWriter<Digraph> tmp(digraph, os);
362
    return tmp;
363
  }
357 364

	
365
  /// \brief Return a \ref DigraphWriter class
366
  ///
367
  /// This function just returns a \ref DigraphWriter class.
368
  /// \relates DigraphWriter
358 369
  template <typename Digraph>
359 370
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
360
                                       const std::string& fn);
371
                                       const std::string& fn) {
372
    DigraphWriter<Digraph> tmp(digraph, fn);
373
    return tmp;
374
  }
361 375

	
376
  /// \brief Return a \ref DigraphWriter class
377
  ///
378
  /// This function just returns a \ref DigraphWriter class.
379
  /// \relates DigraphWriter
362 380
  template <typename Digraph>
363 381
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
364
                                       const char *fn);
382
                                       const char* fn) {
383
    DigraphWriter<Digraph> tmp(digraph, fn);
384
    return tmp;
385
  }
365 386

	
366 387
  /// \ingroup lemon_io
367 388
  ///
368 389
  /// \brief \ref lgf-format "LGF" writer for directed graphs
369 390
  ///
370 391
  /// This utility writes an \ref lgf-format "LGF" file.
371 392
  ///
372 393
  /// The writing method does a batch processing. The user creates a
373 394
  /// writer object, then various writing rules can be added to the
374 395
  /// writer, and eventually the writing is executed with the \c run()
375 396
  /// member function. A map writing rule can be added to the writer
376 397
  /// with the \c nodeMap() or \c arcMap() members. An optional
377 398
  /// converter parameter can also be added as a standard functor
378 399
  /// converting from the value type of the map to \c std::string. If it
379 400
  /// is set, it will determine how the value type of the map is written to
380 401
  /// the output stream. If the functor is not set, then a default
381 402
  /// conversion will be used. The \c attribute(), \c node() and \c
382 403
  /// arc() functions are used to add attribute writing rules.
383 404
  ///
384 405
  ///\code
385 406
  /// DigraphWriter<Digraph>(digraph, std::cout).
386 407
  ///   nodeMap("coordinates", coord_map).
387 408
  ///   nodeMap("size", size).
388 409
  ///   nodeMap("title", title).
389 410
  ///   arcMap("capacity", cap_map).
390 411
  ///   node("source", src).
391 412
  ///   node("target", trg).
392 413
  ///   attribute("caption", caption).
393 414
  ///   run();
394 415
  ///\endcode
395 416
  ///
396 417
  ///
397 418
  /// By default, the writer does not write additional captions to the
398 419
  /// sections, but they can be give as an optional parameter of
399 420
  /// the \c nodes(), \c arcs() or \c
400 421
  /// attributes() functions.
401 422
  ///
402 423
  /// The \c skipNodes() and \c skipArcs() functions forbid the
403 424
  /// writing of the sections. If two arc sections should be written
404 425
  /// to the output, it can be done in two passes, the first pass
405 426
  /// writes the node section and the first arc section, then the
406 427
  /// second pass skips the node section and writes just the arc
407 428
  /// section to the stream. The output stream can be retrieved with
408 429
  /// the \c ostream() function, hence the second pass can append its
409 430
  /// output to the output of the first pass.
410 431
  template <typename _Digraph>
411 432
  class DigraphWriter {
412 433
  public:
413 434

	
414 435
    typedef _Digraph Digraph;
415 436
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
416 437

	
417 438
  private:
418 439

	
419 440

	
420 441
    std::ostream* _os;
421 442
    bool local_os;
422 443

	
423 444
    const Digraph& _digraph;
424 445

	
425 446
    std::string _nodes_caption;
426 447
    std::string _arcs_caption;
427 448
    std::string _attributes_caption;
428 449

	
429 450
    typedef std::map<Node, std::string> NodeIndex;
430 451
    NodeIndex _node_index;
431 452
    typedef std::map<Arc, std::string> ArcIndex;
432 453
    ArcIndex _arc_index;
433 454

	
434 455
    typedef std::vector<std::pair<std::string,
435 456
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
436 457
    NodeMaps _node_maps;
437 458

	
438 459
    typedef std::vector<std::pair<std::string,
439 460
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
440 461
    ArcMaps _arc_maps;
441 462

	
442 463
    typedef std::vector<std::pair<std::string,
443 464
      _writer_bits::ValueStorageBase*> > Attributes;
444 465
    Attributes _attributes;
445 466

	
446 467
    bool _skip_nodes;
447 468
    bool _skip_arcs;
448 469

	
449 470
  public:
450 471

	
451 472
    /// \brief Constructor
452 473
    ///
453 474
    /// Construct a directed graph writer, which writes to the given
454 475
    /// output stream.
455 476
    DigraphWriter(const Digraph& digraph, std::ostream& os = std::cout)
456 477
      : _os(&os), local_os(false), _digraph(digraph),
457 478
        _skip_nodes(false), _skip_arcs(false) {}
458 479

	
459 480
    /// \brief Constructor
460 481
    ///
... ...
@@ -820,238 +841,226 @@
820 841
                                 find(_digraph.source(a))->second);
821 842
        *_os << '\t';
822 843
        _writer_bits::writeToken(*_os, _node_index.
823 844
                                 find(_digraph.target(a))->second);
824 845
        *_os << '\t';
825 846
        if (label == 0) {
826 847
          std::ostringstream os;
827 848
          os << _digraph.id(a);
828 849
          _writer_bits::writeToken(*_os, os.str());
829 850
          *_os << '\t';
830 851
          _arc_index.insert(std::make_pair(a, os.str()));
831 852
        }
832 853
        for (typename ArcMaps::iterator it = _arc_maps.begin();
833 854
             it != _arc_maps.end(); ++it) {
834 855
          std::string value = it->second->get(a);
835 856
          _writer_bits::writeToken(*_os, value);
836 857
          if (it->first == "label") {
837 858
            _arc_index.insert(std::make_pair(a, value));
838 859
          }
839 860
          *_os << '\t';
840 861
        }
841 862
        *_os << std::endl;
842 863
      }
843 864
    }
844 865

	
845 866
    void createArcIndex() {
846 867
      _writer_bits::MapStorageBase<Arc>* label = 0;
847 868
      for (typename ArcMaps::iterator it = _arc_maps.begin();
848 869
           it != _arc_maps.end(); ++it) {
849 870
        if (it->first == "label") {
850 871
          label = it->second;
851 872
          break;
852 873
        }
853 874
      }
854 875

	
855 876
      if (label == 0) {
856 877
        for (ArcIt a(_digraph); a != INVALID; ++a) {
857 878
          std::ostringstream os;
858 879
          os << _digraph.id(a);
859 880
          _arc_index.insert(std::make_pair(a, os.str()));
860 881
        }
861 882
      } else {
862 883
        for (ArcIt a(_digraph); a != INVALID; ++a) {
863 884
          std::string value = label->get(a);
864 885
          _arc_index.insert(std::make_pair(a, value));
865 886
        }
866 887
      }
867 888
    }
868 889

	
869 890
    void writeAttributes() {
870 891
      if (_attributes.empty()) return;
871 892
      *_os << "@attributes";
872 893
      if (!_attributes_caption.empty()) {
873 894
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
874 895
      }
875 896
      *_os << std::endl;
876 897
      for (typename Attributes::iterator it = _attributes.begin();
877 898
           it != _attributes.end(); ++it) {
878 899
        _writer_bits::writeToken(*_os, it->first) << ' ';
879 900
        _writer_bits::writeToken(*_os, it->second->get());
880 901
        *_os << std::endl;
881 902
      }
882 903
    }
883 904

	
884 905
  public:
885 906

	
886 907
    /// \name Execution of the writer
887 908
    /// @{
888 909

	
889 910
    /// \brief Start the batch processing
890 911
    ///
891 912
    /// This function starts the batch processing.
892 913
    void run() {
893 914
      if (!_skip_nodes) {
894 915
        writeNodes();
895 916
      } else {
896 917
        createNodeIndex();
897 918
      }
898 919
      if (!_skip_arcs) {
899 920
        writeArcs();
900 921
      } else {
901 922
        createArcIndex();
902 923
      }
903 924
      writeAttributes();
904 925
    }
905 926

	
906 927
    /// \brief Give back the stream of the writer
907 928
    ///
908 929
    /// Give back the stream of the writer.
909 930
    std::ostream& ostream() {
910 931
      return *_os;
911 932
    }
912 933

	
913 934
    /// @}
914 935
  };
915 936

	
916
  /// \brief Return a \ref DigraphWriter class
937
  template <typename Graph>
938
  class GraphWriter;
939

	
940
  /// \brief Return a \ref GraphWriter class
917 941
  ///
918
  /// This function just returns a \ref DigraphWriter class.
919
  /// \relates DigraphWriter
920
  template <typename Digraph>
921
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
922
                                       std::ostream& os = std::cout) {
923
    DigraphWriter<Digraph> tmp(digraph, os);
942
  /// This function just returns a \ref GraphWriter class.
943
  /// \relates GraphWriter
944
  template <typename Graph>
945
  GraphWriter<Graph> graphWriter(const Graph& graph,
946
                                 std::ostream& os = std::cout) {
947
    GraphWriter<Graph> tmp(graph, os);
924 948
    return tmp;
925 949
  }
926 950

	
927
  /// \brief Return a \ref DigraphWriter class
951
  /// \brief Return a \ref GraphWriter class
928 952
  ///
929
  /// This function just returns a \ref DigraphWriter class.
930
  /// \relates DigraphWriter
931
  template <typename Digraph>
932
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
933
                                       const std::string& fn) {
934
    DigraphWriter<Digraph> tmp(digraph, fn);
953
  /// This function just returns a \ref GraphWriter class.
954
  /// \relates GraphWriter
955
  template <typename Graph>
956
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
957
    GraphWriter<Graph> tmp(graph, fn);
935 958
    return tmp;
936 959
  }
937 960

	
938
  /// \brief Return a \ref DigraphWriter class
961
  /// \brief Return a \ref GraphWriter class
939 962
  ///
940
  /// This function just returns a \ref DigraphWriter class.
941
  /// \relates DigraphWriter
942
  template <typename Digraph>
943
  DigraphWriter<Digraph> digraphWriter(const Digraph& digraph,
944
                                       const char* fn) {
945
    DigraphWriter<Digraph> tmp(digraph, fn);
963
  /// This function just returns a \ref GraphWriter class.
964
  /// \relates GraphWriter
965
  template <typename Graph>
966
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
967
    GraphWriter<Graph> tmp(graph, fn);
946 968
    return tmp;
947 969
  }
948 970

	
949
  template <typename Graph>
950
  class GraphWriter;
951

	
952
  template <typename Graph>
953
  GraphWriter<Graph> graphWriter(const Graph& graph,
954
                                 std::ostream& os = std::cout);
955

	
956
  template <typename Graph>
957
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn);
958

	
959
  template <typename Graph>
960
  GraphWriter<Graph> graphWriter(const Graph& graph, const char *fn);
961

	
962 971
  /// \ingroup lemon_io
963 972
  ///
964 973
  /// \brief \ref lgf-format "LGF" writer for directed graphs
965 974
  ///
966 975
  /// This utility writes an \ref lgf-format "LGF" file.
967 976
  ///
968 977
  /// It can be used almost the same way as \c DigraphWriter.
969 978
  /// The only difference is that this class can handle edges and
970 979
  /// edge maps as well as arcs and arc maps.
971 980
  ///
972 981
  /// The arc maps are written into the file as two columns, the
973 982
  /// caption of the columns are the name of the map prefixed with \c
974 983
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
975 984
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
976 985
  /// of the arc) and the label of corresponding edge.
977 986
  template <typename _Graph>
978 987
  class GraphWriter {
979 988
  public:
980 989

	
981 990
    typedef _Graph Graph;
982 991
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
983 992

	
984 993
  private:
985 994

	
986 995

	
987 996
    std::ostream* _os;
988 997
    bool local_os;
989 998

	
990 999
    const Graph& _graph;
991 1000

	
992 1001
    std::string _nodes_caption;
993 1002
    std::string _edges_caption;
994 1003
    std::string _attributes_caption;
995 1004

	
996 1005
    typedef std::map<Node, std::string> NodeIndex;
997 1006
    NodeIndex _node_index;
998 1007
    typedef std::map<Edge, std::string> EdgeIndex;
999 1008
    EdgeIndex _edge_index;
1000 1009

	
1001 1010
    typedef std::vector<std::pair<std::string,
1002 1011
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
1003 1012
    NodeMaps _node_maps;
1004 1013

	
1005 1014
    typedef std::vector<std::pair<std::string,
1006 1015
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
1007 1016
    EdgeMaps _edge_maps;
1008 1017

	
1009 1018
    typedef std::vector<std::pair<std::string,
1010 1019
      _writer_bits::ValueStorageBase*> > Attributes;
1011 1020
    Attributes _attributes;
1012 1021

	
1013 1022
    bool _skip_nodes;
1014 1023
    bool _skip_edges;
1015 1024

	
1016 1025
  public:
1017 1026

	
1018 1027
    /// \brief Constructor
1019 1028
    ///
1020 1029
    /// Construct a directed graph writer, which writes to the given
1021 1030
    /// output stream.
1022 1031
    GraphWriter(const Graph& graph, std::ostream& os = std::cout)
1023 1032
      : _os(&os), local_os(false), _graph(graph),
1024 1033
        _skip_nodes(false), _skip_edges(false) {}
1025 1034

	
1026 1035
    /// \brief Constructor
1027 1036
    ///
1028 1037
    /// Construct a directed graph writer, which writes to the given
1029 1038
    /// output file.
1030 1039
    GraphWriter(const Graph& graph, const std::string& fn)
1031 1040
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
1032 1041
        _skip_nodes(false), _skip_edges(false) {
1033 1042
      if (!(*_os)) {
1034 1043
        delete _os;
1035 1044
        throw IoError("Cannot write file", fn);
1036 1045
      }
1037 1046
    }
1038 1047

	
1039 1048
    /// \brief Constructor
1040 1049
    ///
1041 1050
    /// Construct a directed graph writer, which writes to the given
1042 1051
    /// output file.
1043 1052
    GraphWriter(const Graph& graph, const char* fn)
1044 1053
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
1045 1054
        _skip_nodes(false), _skip_edges(false) {
1046 1055
      if (!(*_os)) {
1047 1056
        delete _os;
1048 1057
        throw IoError("Cannot write file", fn);
1049 1058
      }
1050 1059
    }
1051 1060

	
1052 1061
    /// \brief Destructor
1053 1062
    ~GraphWriter() {
1054 1063
      for (typename NodeMaps::iterator it = _node_maps.begin();
1055 1064
           it != _node_maps.end(); ++it) {
1056 1065
        delete it->second;
1057 1066
      }
... ...
@@ -1433,223 +1442,192 @@
1433 1442
                                 find(_graph.u(e))->second);
1434 1443
        *_os << '\t';
1435 1444
        _writer_bits::writeToken(*_os, _node_index.
1436 1445
                                 find(_graph.v(e))->second);
1437 1446
        *_os << '\t';
1438 1447
        if (label == 0) {
1439 1448
          std::ostringstream os;
1440 1449
          os << _graph.id(e);
1441 1450
          _writer_bits::writeToken(*_os, os.str());
1442 1451
          *_os << '\t';
1443 1452
          _edge_index.insert(std::make_pair(e, os.str()));
1444 1453
        }
1445 1454
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
1446 1455
             it != _edge_maps.end(); ++it) {
1447 1456
          std::string value = it->second->get(e);
1448 1457
          _writer_bits::writeToken(*_os, value);
1449 1458
          if (it->first == "label") {
1450 1459
            _edge_index.insert(std::make_pair(e, value));
1451 1460
          }
1452 1461
          *_os << '\t';
1453 1462
        }
1454 1463
        *_os << std::endl;
1455 1464
      }
1456 1465
    }
1457 1466

	
1458 1467
    void createEdgeIndex() {
1459 1468
      _writer_bits::MapStorageBase<Edge>* label = 0;
1460 1469
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1461 1470
           it != _edge_maps.end(); ++it) {
1462 1471
        if (it->first == "label") {
1463 1472
          label = it->second;
1464 1473
          break;
1465 1474
        }
1466 1475
      }
1467 1476

	
1468 1477
      if (label == 0) {
1469 1478
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1470 1479
          std::ostringstream os;
1471 1480
          os << _graph.id(e);
1472 1481
          _edge_index.insert(std::make_pair(e, os.str()));
1473 1482
        }
1474 1483
      } else {
1475 1484
        for (EdgeIt e(_graph); e != INVALID; ++e) {
1476 1485
          std::string value = label->get(e);
1477 1486
          _edge_index.insert(std::make_pair(e, value));
1478 1487
        }
1479 1488
      }
1480 1489
    }
1481 1490

	
1482 1491
    void writeAttributes() {
1483 1492
      if (_attributes.empty()) return;
1484 1493
      *_os << "@attributes";
1485 1494
      if (!_attributes_caption.empty()) {
1486 1495
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
1487 1496
      }
1488 1497
      *_os << std::endl;
1489 1498
      for (typename Attributes::iterator it = _attributes.begin();
1490 1499
           it != _attributes.end(); ++it) {
1491 1500
        _writer_bits::writeToken(*_os, it->first) << ' ';
1492 1501
        _writer_bits::writeToken(*_os, it->second->get());
1493 1502
        *_os << std::endl;
1494 1503
      }
1495 1504
    }
1496 1505

	
1497 1506
  public:
1498 1507

	
1499 1508
    /// \name Execution of the writer
1500 1509
    /// @{
1501 1510

	
1502 1511
    /// \brief Start the batch processing
1503 1512
    ///
1504 1513
    /// This function starts the batch processing.
1505 1514
    void run() {
1506 1515
      if (!_skip_nodes) {
1507 1516
        writeNodes();
1508 1517
      } else {
1509 1518
        createNodeIndex();
1510 1519
      }
1511 1520
      if (!_skip_edges) {
1512 1521
        writeEdges();
1513 1522
      } else {
1514 1523
        createEdgeIndex();
1515 1524
      }
1516 1525
      writeAttributes();
1517 1526
    }
1518 1527

	
1519 1528
    /// \brief Give back the stream of the writer
1520 1529
    ///
1521 1530
    /// Give back the stream of the writer
1522 1531
    std::ostream& ostream() {
1523 1532
      return *_os;
1524 1533
    }
1525 1534

	
1526 1535
    /// @}
1527 1536
  };
1528 1537

	
1529
  /// \brief Return a \ref GraphWriter class
1530
  ///
1531
  /// This function just returns a \ref GraphWriter class.
1532
  /// \relates GraphWriter
1533
  template <typename Graph>
1534
  GraphWriter<Graph> graphWriter(const Graph& graph,
1535
                                 std::ostream& os = std::cout) {
1536
    GraphWriter<Graph> tmp(graph, os);
1537
    return tmp;
1538
  }
1539

	
1540
  /// \brief Return a \ref GraphWriter class
1541
  ///
1542
  /// This function just returns a \ref GraphWriter class.
1543
  /// \relates GraphWriter
1544
  template <typename Graph>
1545
  GraphWriter<Graph> graphWriter(const Graph& graph, const std::string& fn) {
1546
    GraphWriter<Graph> tmp(graph, fn);
1547
    return tmp;
1548
  }
1549

	
1550
  /// \brief Return a \ref GraphWriter class
1551
  ///
1552
  /// This function just returns a \ref GraphWriter class.
1553
  /// \relates GraphWriter
1554
  template <typename Graph>
1555
  GraphWriter<Graph> graphWriter(const Graph& graph, const char* fn) {
1556
    GraphWriter<Graph> tmp(graph, fn);
1557
    return tmp;
1558
  }
1559

	
1560 1538
  class SectionWriter;
1561 1539

	
1562 1540
  SectionWriter sectionWriter(std::istream& is);
1563 1541
  SectionWriter sectionWriter(const std::string& fn);
1564 1542
  SectionWriter sectionWriter(const char* fn);
1565 1543

	
1566 1544
  /// \ingroup lemon_io
1567 1545
  ///
1568 1546
  /// \brief Section writer class
1569 1547
  ///
1570 1548
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
1571 1549
  /// which contain any data in arbitrary format. Such sections can be
1572 1550
  /// written with this class. A writing rule can be added to the
1573 1551
  /// class with two different functions. With the \c sectionLines()
1574 1552
  /// function a generator can write the section line-by-line, while
1575 1553
  /// with the \c sectionStream() member the section can be written to
1576 1554
  /// an output stream.
1577 1555
  class SectionWriter {
1578 1556
  private:
1579 1557

	
1580 1558
    std::ostream* _os;
1581 1559
    bool local_os;
1582 1560

	
1583 1561
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
1584 1562
    Sections;
1585 1563

	
1586 1564
    Sections _sections;
1587 1565

	
1588 1566
  public:
1589 1567

	
1590 1568
    /// \brief Constructor
1591 1569
    ///
1592 1570
    /// Construct a section writer, which writes to the given output
1593 1571
    /// stream.
1594 1572
    SectionWriter(std::ostream& os)
1595 1573
      : _os(&os), local_os(false) {}
1596 1574

	
1597 1575
    /// \brief Constructor
1598 1576
    ///
1599 1577
    /// Construct a section writer, which writes into the given file.
1600 1578
    SectionWriter(const std::string& fn)
1601 1579
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
1602 1580
      if (!(*_os)) {
1603 1581
        delete _os;
1604 1582
        throw IoError("Cannot write file", fn);
1605 1583
      }
1606 1584
    }
1607 1585

	
1608 1586
    /// \brief Constructor
1609 1587
    ///
1610 1588
    /// Construct a section writer, which writes into the given file.
1611 1589
    SectionWriter(const char* fn)
1612 1590
      : _os(new std::ofstream(fn)), local_os(true) {
1613 1591
      if (!(*_os)) {
1614 1592
        delete _os;
1615 1593
        throw IoError("Cannot write file", fn);
1616 1594
      }
1617 1595
    }
1618 1596

	
1619 1597
    /// \brief Destructor
1620 1598
    ~SectionWriter() {
1621 1599
      for (Sections::iterator it = _sections.begin();
1622 1600
           it != _sections.end(); ++it) {
1623 1601
        delete it->second;
1624 1602
      }
1625 1603

	
1626 1604
      if (local_os) {
1627 1605
        delete _os;
1628 1606
      }
1629 1607

	
1630 1608
    }
1631 1609

	
1632 1610
  private:
1633 1611

	
1634 1612
    friend SectionWriter sectionWriter(std::ostream& os);
1635 1613
    friend SectionWriter sectionWriter(const std::string& fn);
1636 1614
    friend SectionWriter sectionWriter(const char* fn);
1637 1615

	
1638 1616
    SectionWriter(SectionWriter& other)
1639 1617
      : _os(other._os), local_os(other.local_os) {
1640 1618

	
1641 1619
      other._os = 0;
1642 1620
      other.local_os = false;
1643 1621

	
1644 1622
      _sections.swap(other._sections);
1645 1623
    }
1646 1624

	
1647 1625
    SectionWriter& operator=(const SectionWriter&);
1648 1626

	
1649 1627
  public:
1650 1628

	
1651 1629
    /// \name Section writers
1652 1630
    /// @{
1653 1631

	
1654 1632
    /// \brief Add a section writer with line oriented writing
1655 1633
    ///
0 comments (0 inline)