gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge
0 1 0
merge default
1 file changed with 6 insertions and 10 deletions:
↑ Collapse diff ↑
Ignore white space 6144 line context
1 1
/* -*- C++ -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library
4 4
 *
5 5
 * Copyright (C) 2003-2008
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup lemon_io
20 20
///\file
21 21
///\brief Lemon Graph Format reader.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_READER_H
25 25
#define LEMON_LGF_READER_H
26 26

	
27 27
#include <iostream>
28 28
#include <fstream>
29 29
#include <sstream>
30 30

	
31 31
#include <set>
32 32
#include <map>
33 33

	
34 34
#include <lemon/assert.h>
35 35
#include <lemon/graph_utils.h>
36 36

	
37 37
#include <lemon/lgf_writer.h>
38 38

	
39 39
#include <lemon/concept_check.h>
40 40
#include <lemon/concepts/maps.h>
41 41

	
42 42
namespace lemon {
43 43

	
44 44
  namespace _reader_bits {
45 45

	
46 46
    template <typename Value>
47 47
    struct DefaultConverter {
48 48
      Value operator()(const std::string& str) {
49 49
	std::istringstream is(str);
50 50
	Value value;
51 51
	is >> value;
52 52

	
53 53
	char c;
54 54
	if (is >> std::ws >> c) {
55 55
	  throw DataFormatError("Remaining characters in token");
56 56
	}
57 57
	return value;
58 58
      }
59 59
    };
60 60

	
61 61
    template <>
62 62
    struct DefaultConverter<std::string> {
63 63
      std::string operator()(const std::string& str) {
64 64
	return str;
65 65
      }
66 66
    };
67 67

	
68 68
    template <typename _Item>    
69 69
    class MapStorageBase {
70 70
    public:
71 71
      typedef _Item Item;
72 72

	
73 73
    public:
74 74
      MapStorageBase() {}
75 75
      virtual ~MapStorageBase() {}
76 76

	
77 77
      virtual void set(const Item& item, const std::string& value) = 0;
78 78

	
79 79
    };
80 80

	
81 81
    template <typename _Item, typename _Map, 
82 82
	      typename _Converter = DefaultConverter<typename _Map::Value> >
83 83
    class MapStorage : public MapStorageBase<_Item> {
84 84
    public:
85 85
      typedef _Map Map;
86 86
      typedef _Converter Converter;
87 87
      typedef _Item Item;
88 88
      
89 89
    private:
90 90
      Map& _map;
91 91
      Converter _converter;
92 92

	
93 93
    public:
94 94
      MapStorage(Map& map, const Converter& converter = Converter()) 
95 95
	: _map(map), _converter(converter) {}
96 96
      virtual ~MapStorage() {}
97 97

	
98 98
      virtual void set(const Item& item ,const std::string& value) {
99 99
	_map.set(item, _converter(value));
100 100
      }
101 101
    };
102 102

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

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

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

	
129 129
    class ValueStorageBase {
130 130
    public:
131 131
      ValueStorageBase() {}
132 132
      virtual ~ValueStorageBase() {}
133 133

	
134 134
      virtual void set(const std::string&) = 0;
135 135
    };
136 136

	
137 137
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
138 138
    class ValueStorage : public ValueStorageBase {
139 139
    public:
140 140
      typedef _Value Value;
141 141
      typedef _Converter Converter;
142 142

	
143 143
    private:
144 144
      Value& _value;
145 145
      Converter _converter;
146 146

	
147 147
    public:
148 148
      ValueStorage(Value& value, const Converter& converter = Converter())
149 149
 	: _value(value), _converter(converter) {}
150 150

	
151 151
      virtual void set(const std::string& value) {
152 152
	_value = _converter(value);
153 153
      }
154 154
    };
155 155

	
156 156
    template <typename Value>
157 157
    struct MapLookUpConverter {
158 158
      const std::map<std::string, Value>& _map;
159 159

	
160 160
      MapLookUpConverter(const std::map<std::string, Value>& map)
161 161
        : _map(map) {}
162 162

	
163 163
      Value operator()(const std::string& str) {
164 164
        typename std::map<std::string, Value>::const_iterator it =
165 165
          _map.find(str);
166 166
        if (it == _map.end()) {
167 167
          std::ostringstream msg;
168 168
          msg << "Item not found: " << str;
169 169
          throw DataFormatError(msg.str().c_str());
170 170
        }
171 171
        return it->second;
172 172
      }
173 173
    };
174 174

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

	
198 198
    bool isWhiteSpace(char c) {
199 199
      return c == ' ' || c == '\t' || c == '\v' || 
200 200
        c == '\n' || c == '\r' || c == '\f'; 
201 201
    }
202 202
    
203 203
    bool isOct(char c) {
204 204
      return '0' <= c && c <='7'; 
205 205
    }
206 206
    
207 207
    int valueOct(char c) {
208 208
      LEMON_ASSERT(isOct(c), "The character is not octal.");
209 209
      return c - '0';
210 210
    }
211 211

	
212 212
    bool isHex(char c) {
213 213
      return ('0' <= c && c <= '9') || 
214 214
	('a' <= c && c <= 'z') || 
215 215
	('A' <= c && c <= 'Z'); 
216 216
    }
217 217
    
218 218
    int valueHex(char c) {
219 219
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
220 220
      if ('0' <= c && c <= '9') return c - '0';
221 221
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
222 222
      return c - 'A' + 10;
223 223
    }
224 224

	
225 225
    bool isIdentifierFirstChar(char c) {
226 226
      return ('a' <= c && c <= 'z') ||
227 227
	('A' <= c && c <= 'Z') || c == '_';
228 228
    }
229 229

	
230 230
    bool isIdentifierChar(char c) {
231 231
      return isIdentifierFirstChar(c) ||
232 232
	('0' <= c && c <= '9');
233 233
    }
234 234

	
235 235
    char readEscape(std::istream& is) {
236 236
      char c;
237 237
      if (!is.get(c))
238 238
	throw DataFormatError("Escape format error");
239 239

	
240 240
      switch (c) {
241 241
      case '\\':
242 242
	return '\\';
243 243
      case '\"':
244 244
	return '\"';
245 245
      case '\'':
246 246
	return '\'';
247 247
      case '\?':
248 248
	return '\?';
249 249
      case 'a':
250 250
	return '\a';
251 251
      case 'b':
252 252
	return '\b';
253 253
      case 'f':
254 254
	return '\f';
255 255
      case 'n':
256 256
	return '\n';
257 257
      case 'r':
258 258
	return '\r';
259 259
      case 't':
260 260
	return '\t';
261 261
      case 'v':
262 262
	return '\v';
263 263
      case 'x':
264 264
	{
265 265
	  int code;
266 266
	  if (!is.get(c) || !isHex(c)) 
267 267
	    throw DataFormatError("Escape format error");
268 268
	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
269 269
	  else code = code * 16 + valueHex(c);
270 270
	  return code;
271 271
	}
272 272
      default:
273 273
	{
274 274
	  int code;
275 275
	  if (!isOct(c)) 
276 276
	    throw DataFormatError("Escape format error");
277 277
	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
278 278
	    is.putback(c);
279 279
	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
280 280
	    is.putback(c);
281 281
	  else code = code * 8 + valueOct(c);
282 282
	  return code;
283 283
	}	      
284 284
      } 
285 285
    }
286 286
    
287 287
    std::istream& readToken(std::istream& is, std::string& str) {
288 288
      std::ostringstream os;
289 289

	
290 290
      char c;
291 291
      is >> std::ws;
292 292
      
293 293
      if (!is.get(c)) 
294 294
	return is;
295 295

	
296 296
      if (c == '\"') {
297 297
	while (is.get(c) && c != '\"') {
298 298
	  if (c == '\\') 
299 299
	    c = readEscape(is);
300 300
	  os << c;
301 301
	}
302 302
	if (!is) 
303 303
	  throw DataFormatError("Quoted format error");
304 304
      } else {
305 305
	is.putback(c);
306 306
	while (is.get(c) && !isWhiteSpace(c)) {
307 307
	  if (c == '\\') 
308 308
	    c = readEscape(is);
309 309
	  os << c;
310 310
	}
311 311
	if (!is) {
312 312
	  is.clear();
313 313
	} else {
314 314
	  is.putback(c);
315 315
	}
316 316
      }
317 317
      str = os.str();
318 318
      return is;
319 319
    }
320 320

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

	
327 327
    template <typename Functor>
328 328
    class LineSection : public Section {
329 329
    private:
330 330

	
331 331
      Functor _functor;
332 332

	
333 333
    public:
334 334
      
335 335
      LineSection(const Functor& functor) : _functor(functor) {}
336 336
      virtual ~LineSection() {}
337 337

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

	
359 359
    template <typename Functor>
360 360
    class StreamSection : public Section {
361 361
    private:
362 362

	
363 363
      Functor _functor;
364 364

	
365 365
    public:
366 366
      
367 367
      StreamSection(const Functor& functor) : _functor(functor) {}
368 368
      virtual ~StreamSection() {} 
369 369

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

	
389 389
  /// \ingroup lemon_io
390 390
  ///  
391 391
  /// \brief LGF reader for directed graphs
392 392
  ///
393 393
  /// This utility reads an \ref lgf-format "LGF" file.
394 394
  ///
395 395
  /// The reading method does a batch processing. The user creates a
396 396
  /// reader object, then various reading rules can be added to the
397 397
  /// reader, and eventually the reading is executed with the \c run()
398 398
  /// member function. A map reading rule can be added to the reader
399 399
  /// with the \c nodeMap() or \c arcMap() members. An optional
400 400
  /// converter parameter can also be added as a standard functor
401 401
  /// converting from std::string to the value type of the map. If it
402 402
  /// is set, it will determine how the tokens in the file should be
403 403
  /// is converted to the map's value type. If the functor is not set,
404 404
  /// then a default conversion will be used. One map can be read into
405 405
  /// multiple map objects at the same time. The \c attribute(), \c
406 406
  /// node() and \c arc() functions are used to add attribute reading
407 407
  /// rules.
408 408
  ///
409 409
  ///\code
410 410
  ///     DigraphReader<Digraph>(std::cin, digraph).
411 411
  ///       nodeMap("coordinates", coord_map).
412 412
  ///       arcMap("capacity", cap_map).
413 413
  ///       node("source", src).
414 414
  ///       node("target", trg).
415 415
  ///       attribute("caption", caption).
416 416
  ///       run();
417 417
  ///\endcode
418 418
  ///
419 419
  /// By default the reader uses the first section in the file of the
420 420
  /// proper type. If a section has an optional name, then it can be
421 421
  /// selected for reading by giving an optional name parameter to the
422 422
  /// \c nodes(), \c arcs() or \c attributes() functions. The readers
423 423
  /// also can load extra sections with the \c sectionLines() and
424 424
  /// sectionStream() functions.
425 425
  ///
426 426
  /// The \c useNodes() and \c useArcs() functions are used to tell the reader
427 427
  /// that the nodes or arcs should not be constructed (added to the
428 428
  /// graph) during the reading, but instead the label map of the items
429 429
  /// are given as a parameter of these functions. An
430 430
  /// application of these function is multipass reading, which is
431 431
  /// important if two \e \@arcs sections must be read from the
432 432
  /// file. In this example the first phase would read the node set and one
433 433
  /// of the arc sets, while the second phase would read the second arc
434 434
  /// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
435 435
  /// The previously read label node map should be passed to the \c
436 436
  /// useNodes() functions. Another application of multipass reading when
437 437
  /// paths are given as a node map or an arc map. It is impossible read this in
438 438
  /// a single pass, because the arcs are not constructed when the node
439 439
  /// maps are read.
440 440
  template <typename _Digraph>
441 441
  class DigraphReader {
442 442
  public:
443 443

	
444 444
    typedef _Digraph Digraph;
445 445
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
446 446
    
447 447
  private:
448 448

	
449 449

	
450 450
    std::istream* _is;
451 451
    bool local_is;
452 452

	
453 453
    Digraph& _digraph;
454 454

	
455 455
    std::string _nodes_caption;
456 456
    std::string _arcs_caption;
457 457
    std::string _attributes_caption;
458 458

	
459 459
    typedef std::map<std::string, Node> NodeIndex;
460 460
    NodeIndex _node_index;
461 461
    typedef std::map<std::string, Arc> ArcIndex;
462 462
    ArcIndex _arc_index;
463 463
    
464 464
    typedef std::vector<std::pair<std::string, 
465 465
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;    
466 466
    NodeMaps _node_maps; 
467 467

	
468 468
    typedef std::vector<std::pair<std::string,
469 469
      _reader_bits::MapStorageBase<Arc>*> >ArcMaps;
470 470
    ArcMaps _arc_maps;
471 471

	
472 472
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
473 473
      Attributes;
474 474
    Attributes _attributes;
475 475

	
476 476
    typedef std::map<std::string, _reader_bits::Section*> Sections;
477 477
    Sections _sections;
478 478

	
479 479
    bool _use_nodes;
480 480
    bool _use_arcs;
481 481

	
482 482
    int line_num;
483 483
    std::istringstream line;
484 484

	
485 485
  public:
486 486

	
487 487
    /// \brief Constructor
488 488
    ///
489 489
    /// Construct a directed graph reader, which reads from the given
490 490
    /// input stream.
491 491
    DigraphReader(std::istream& is, Digraph& digraph) 
492 492
      : _is(&is), local_is(false), _digraph(digraph),
493 493
	_use_nodes(false), _use_arcs(false) {}
494 494

	
495 495
    /// \brief Constructor
496 496
    ///
497 497
    /// Construct a directed graph reader, which reads from the given
498 498
    /// file.
499 499
    DigraphReader(const std::string& fn, Digraph& digraph) 
500 500
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
501 501
    	_use_nodes(false), _use_arcs(false) {}
502 502
    
503 503
    /// \brief Constructor
504 504
    ///
505 505
    /// Construct a directed graph reader, which reads from the given
506 506
    /// file.
507 507
    DigraphReader(const char* fn, Digraph& digraph) 
508 508
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
509 509
    	_use_nodes(false), _use_arcs(false) {}
510 510

	
511 511
    /// \brief Copy constructor
512 512
    ///
513 513
    /// The copy constructor transfers all data from the other reader,
514 514
    /// therefore the copied reader will not be usable more. 
515 515
    DigraphReader(DigraphReader& other) 
516 516
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
517 517
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
518 518

	
519 519
      other._is = 0;
520 520
      other.local_is = false;
521 521
      
522 522
      _node_index.swap(other._node_index);
523 523
      _arc_index.swap(other._arc_index);
524 524

	
525 525
      _node_maps.swap(other._node_maps);
526 526
      _arc_maps.swap(other._arc_maps);
527 527
      _attributes.swap(other._attributes);
528 528

	
529 529
      _nodes_caption = other._nodes_caption;
530 530
      _arcs_caption = other._arcs_caption;
531 531
      _attributes_caption = other._attributes_caption;
532 532

	
533 533
      _sections.swap(other._sections);
534 534
    }
535 535

	
536 536
    /// \brief Destructor
537 537
    ~DigraphReader() {
538 538
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
539 539
	   it != _node_maps.end(); ++it) {
540 540
	delete it->second;
541 541
      }
542 542

	
543 543
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
544 544
	   it != _arc_maps.end(); ++it) {
545 545
	delete it->second;
546 546
      }
547 547

	
548 548
      for (typename Attributes::iterator it = _attributes.begin(); 
549 549
	   it != _attributes.end(); ++it) {
550 550
	delete it->second;
551 551
      }
552 552

	
553 553
      for (typename Sections::iterator it = _sections.begin(); 
554 554
	   it != _sections.end(); ++it) {
555 555
	delete it->second;
556 556
      }
557 557

	
558 558
      if (local_is) {
559 559
	delete _is;
560 560
      }
561 561

	
562 562
    }
563 563

	
564 564
  private:
565 565
    
566 566
    DigraphReader& operator=(const DigraphReader&);
567 567

	
568 568
  public:
569 569

	
570 570
    /// \name Reading rules
571 571
    /// @{
572 572
    
573 573
    /// \brief Node map reading rule
574 574
    ///
575 575
    /// Add a node map reading rule to the reader.
576 576
    template <typename Map>
577 577
    DigraphReader& nodeMap(const std::string& caption, Map& map) {
578 578
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
579 579
      _reader_bits::MapStorageBase<Node>* storage = 
580 580
	new _reader_bits::MapStorage<Node, Map>(map);
581 581
      _node_maps.push_back(std::make_pair(caption, storage));
582 582
      return *this;
583 583
    }
584 584

	
585 585
    /// \brief Node map reading rule
586 586
    ///
587 587
    /// Add a node map reading rule with specialized converter to the
588 588
    /// reader.
589 589
    template <typename Map, typename Converter>
590 590
    DigraphReader& nodeMap(const std::string& caption, Map& map, 
591 591
			   const Converter& converter = Converter()) {
592 592
      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
593 593
      _reader_bits::MapStorageBase<Node>* storage = 
594 594
	new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
595 595
      _node_maps.push_back(std::make_pair(caption, storage));
596 596
      return *this;
597 597
    }
598 598

	
599 599
    /// \brief Arc map reading rule
600 600
    ///
601 601
    /// Add an arc map reading rule to the reader.
602 602
    template <typename Map>
603 603
    DigraphReader& arcMap(const std::string& caption, Map& map) {
604 604
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
605 605
      _reader_bits::MapStorageBase<Arc>* storage = 
606 606
	new _reader_bits::MapStorage<Arc, Map>(map);
607 607
      _arc_maps.push_back(std::make_pair(caption, storage));
608 608
      return *this;
609 609
    }
610 610

	
611 611
    /// \brief Arc map reading rule
612 612
    ///
613 613
    /// Add an arc map reading rule with specialized converter to the
614 614
    /// reader.
615 615
    template <typename Map, typename Converter>
616 616
    DigraphReader& arcMap(const std::string& caption, Map& map, 
617 617
			  const Converter& converter = Converter()) {
618 618
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
619 619
      _reader_bits::MapStorageBase<Arc>* storage = 
620 620
	new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
621 621
      _arc_maps.push_back(std::make_pair(caption, storage));
622 622
      return *this;
623 623
    }
624 624

	
625 625
    /// \brief Attribute reading rule
626 626
    ///
627 627
    /// Add an attribute reading rule to the reader.
628 628
    template <typename Value>
629 629
    DigraphReader& attribute(const std::string& caption, Value& value) {
630 630
      _reader_bits::ValueStorageBase* storage = 
631 631
	new _reader_bits::ValueStorage<Value>(value);
632 632
      _attributes.insert(std::make_pair(caption, storage));
633 633
      return *this;
634 634
    }
635 635

	
636 636
    /// \brief Attribute reading rule
637 637
    ///
638 638
    /// Add an attribute reading rule with specialized converter to the
639 639
    /// reader.
640 640
    template <typename Value, typename Converter>
641 641
    DigraphReader& attribute(const std::string& caption, Value& value, 
642 642
			     const Converter& converter = Converter()) {
643 643
      _reader_bits::ValueStorageBase* storage = 
644 644
	new _reader_bits::ValueStorage<Value, Converter>(value, converter);
645 645
      _attributes.insert(std::make_pair(caption, storage));
646 646
      return *this;
647 647
    }
648 648

	
649 649
    /// \brief Node reading rule
650 650
    ///
651 651
    /// Add a node reading rule to reader.
652 652
    DigraphReader& node(const std::string& caption, Node& node) {
653 653
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
654 654
      Converter converter(_node_index);
655 655
      _reader_bits::ValueStorageBase* storage = 
656 656
	new _reader_bits::ValueStorage<Node, Converter>(node, converter);
657 657
      _attributes.insert(std::make_pair(caption, storage));
658 658
      return *this;
659 659
    }
660 660

	
661 661
    /// \brief Arc reading rule
662 662
    ///
663 663
    /// Add an arc reading rule to reader.
664 664
    DigraphReader& arc(const std::string& caption, Arc& arc) {
665 665
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
666 666
      Converter converter(_arc_index);
667 667
      _reader_bits::ValueStorageBase* storage = 
668 668
	new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
669 669
      _attributes.insert(std::make_pair(caption, storage));
670 670
      return *this;
671 671
    }
672 672

	
673 673
    /// @}
674 674

	
675 675
    /// \name Select section by name
676 676
    /// @{
677 677

	
678 678
    /// \brief Set \c \@nodes section to be read
679 679
    ///
680 680
    /// Set \c \@nodes section to be read
681 681
    DigraphReader& nodes(const std::string& caption) {
682 682
      _nodes_caption = caption;
683 683
      return *this;
684 684
    }
685 685

	
686 686
    /// \brief Set \c \@arcs section to be read
687 687
    ///
688 688
    /// Set \c \@arcs section to be read
689 689
    DigraphReader& arcs(const std::string& caption) {
690 690
      _arcs_caption = caption;
691 691
      return *this;
692 692
    }
693 693

	
694 694
    /// \brief Set \c \@attributes section to be read
695 695
    ///
696 696
    /// Set \c \@attributes section to be read
697 697
    DigraphReader& attributes(const std::string& caption) {
698 698
      _attributes_caption = caption;
699 699
      return *this;
700 700
    }
701 701

	
702 702
    /// @}
703 703

	
704 704
    /// \name Section readers
705 705
    /// @{
706 706

	
707 707
    /// \brief Add a section processor with line oriented reading
708 708
    ///
709 709
    /// In the \e LGF file extra sections can be placed, which contain
710 710
    /// any data in arbitrary format. These sections can be read with
711 711
    /// this function line by line. The first parameter is the type
712 712
    /// descriptor of the section, the second is a functor, which
713 713
    /// takes just one \c std::string parameter. At the reading
714 714
    /// process, each line of the section will be given to the functor
715 715
    /// object. However, the empty lines and the comment lines are
716 716
    /// filtered out, and the leading whitespaces are stipped from
717 717
    /// each processed string.
718 718
    ///
719 719
    /// For example let's see a section, which contain several
720 720
    /// integers, which should be inserted into a vector.
721 721
    ///\code
722 722
    ///  @numbers
723 723
    ///  12 45 23
724 724
    ///  4
725 725
    ///  23 6
726 726
    ///\endcode
727 727
    ///
728 728
    /// The functor is implemented as an struct:
729 729
    ///\code
730 730
    ///  struct NumberSection {
731 731
    ///    std::vector<int>& _data;
732 732
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
733 733
    ///    void operator()(const std::string& line) {
734 734
    ///      std::istringstream ls(line);
735 735
    ///      int value;
736 736
    ///      while (ls >> value) _data.push_back(value);
737 737
    ///    }
738 738
    ///  };
739 739
    ///
740 740
    ///  // ...
741 741
    ///
742 742
    ///  reader.sectionLines("numbers", NumberSection(vec));  
743 743
    ///\endcode
744 744
    template <typename Functor>
745 745
    DigraphReader& sectionLines(const std::string& type, Functor functor) {
746 746
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
747 747
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
748 748
		   "Multiple reading of section.");
749 749
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
750 750
		   type != "attributes", "Multiple reading of section.");
751 751
      _sections.insert(std::make_pair(type, 
752 752
        new _reader_bits::LineSection<Functor>(functor)));
753 753
      return *this;
754 754
    }
755 755

	
756 756

	
757 757
    /// \brief Add a section processor with stream oriented reading
758 758
    ///
759 759
    /// In the \e LGF file extra sections can be placed, which contain
760 760
    /// any data in arbitrary format. These sections can be read
761 761
    /// directly with this function. The first parameter is the type
762 762
    /// of the section, the second is a functor, which takes an \c
763 763
    /// std::istream& and an int& parameter, the latter regard to the
764 764
    /// line number of stream. The functor can read the input while
765 765
    /// the section go on, and the line number should be modified
766 766
    /// accordingly.
767 767
    template <typename Functor>
768 768
    DigraphReader& sectionStream(const std::string& type, Functor functor) {
769 769
      LEMON_ASSERT(!type.empty(), "Type is not empty.");
770 770
      LEMON_ASSERT(_sections.find(type) == _sections.end(), 
771 771
		   "Multiple reading of section.");
772 772
      LEMON_ASSERT(type != "nodes" && type != "arcs" && type != "edges" &&
773 773
		   type != "attributes", "Multiple reading of section.");
774 774
      _sections.insert(std::make_pair(type, 
775 775
	 new _reader_bits::StreamSection<Functor>(functor)));
776 776
      return *this;
777 777
    }    
778 778
    
779 779
    /// @}
780 780

	
781 781
    /// \name Using previously constructed node or arc set
782 782
    /// @{
783 783

	
784 784
    /// \brief Use previously constructed node set
785 785
    ///
786 786
    /// Use previously constructed node set, and specify the node
787 787
    /// label map.
788 788
    template <typename Map>
789 789
    DigraphReader& useNodes(const Map& map) {
790 790
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
791 791
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
792 792
      _use_nodes = true;
793 793
      _writer_bits::DefaultConverter<typename Map::Value> converter;
794 794
      for (NodeIt n(_digraph); n != INVALID; ++n) {
795 795
	_node_index.insert(std::make_pair(converter(map[n]), n));
796 796
      }
797 797
      return *this;
798 798
    }
799 799

	
800 800
    /// \brief Use previously constructed node set
801 801
    ///
802 802
    /// Use previously constructed node set, and specify the node
803 803
    /// label map and a functor which converts the label map values to
804 804
    /// std::string.
805 805
    template <typename Map, typename Converter>
806 806
    DigraphReader& useNodes(const Map& map, 
807 807
			    const Converter& converter = Converter()) {
808 808
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
809 809
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); 
810 810
      _use_nodes = true;
811 811
      for (NodeIt n(_digraph); n != INVALID; ++n) {
812 812
	_node_index.insert(std::make_pair(converter(map[n]), n));
813 813
      }
814 814
      return *this;
815 815
    }
816 816

	
817 817
    /// \brief Use previously constructed arc set
818 818
    ///
819 819
    /// Use previously constructed arc set, and specify the arc
820 820
    /// label map.
821 821
    template <typename Map>
822 822
    DigraphReader& useArcs(const Map& map) {
823 823
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
824 824
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
825 825
      _use_arcs = true;
826 826
      _writer_bits::DefaultConverter<typename Map::Value> converter;
827 827
      for (ArcIt a(_digraph); a != INVALID; ++a) {
828 828
	_arc_index.insert(std::make_pair(converter(map[a]), a));
829 829
      }
830 830
      return *this;
831 831
    }
832 832

	
833 833
    /// \brief Use previously constructed arc set
834 834
    ///
835 835
    /// Use previously constructed arc set, and specify the arc
836 836
    /// label map and a functor which converts the label map values to
837 837
    /// std::string.
838 838
    template <typename Map, typename Converter>
839 839
    DigraphReader& useArcs(const Map& map, 
840 840
			    const Converter& converter = Converter()) {
841 841
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
842 842
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); 
843 843
      _use_arcs = true;
844 844
      for (ArcIt a(_digraph); a != INVALID; ++a) {
845 845
	_arc_index.insert(std::make_pair(converter(map[a]), a));
846 846
      }
847 847
      return *this;
848 848
    }
849 849

	
850 850
    /// @}
851 851

	
852 852
  private:
853 853

	
854 854
    bool readLine() {
855 855
      std::string str;
856 856
      while(++line_num, std::getline(*_is, str)) {
857 857
	line.clear(); line.str(str);
858 858
	char c;
859 859
	if (line >> std::ws >> c && c != '#') {
860 860
	  line.putback(c);
861 861
	  return true;
862 862
	}
863 863
      }
864 864
      return false;
865 865
    }
866 866

	
867 867
    bool readSuccess() {
868 868
      return static_cast<bool>(*_is);
869 869
    }
870 870
    
871 871
    void skipSection() {
872 872
      char c;
873 873
      while (readSuccess() && line >> c && c != '@') {
874 874
	readLine();
875 875
      }
876 876
      line.putback(c);
877 877
    }
878 878

	
879 879
    void readNodes() {
880 880

	
881 881
      std::vector<int> map_index(_node_maps.size());
882 882
      int map_num, label_index;
883 883

	
884 884
      if (!readLine()) 
885 885
	throw DataFormatError("Cannot find map captions");
886 886
      
887 887
      {
888 888
	std::map<std::string, int> maps;
889 889
	
890 890
	std::string map;
891 891
	int index = 0;
892 892
	while (_reader_bits::readToken(line, map)) {
893 893
	  if (maps.find(map) != maps.end()) {
894 894
	    std::ostringstream msg;
895 895
	    msg << "Multiple occurence of node map: " << map;
896 896
	    throw DataFormatError(msg.str().c_str());
897 897
	  }
898 898
	  maps.insert(std::make_pair(map, index));
899 899
	  ++index;
900 900
	}
901 901
	
902 902
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
903 903
	  std::map<std::string, int>::iterator jt = 
904 904
	    maps.find(_node_maps[i].first);
905 905
	  if (jt == maps.end()) {
906 906
	    std::ostringstream msg;
907 907
	    msg << "Map not found in file: " << _node_maps[i].first;
908 908
	    throw DataFormatError(msg.str().c_str());
909 909
	  }
910 910
	  map_index[i] = jt->second;
911 911
	}
912 912

	
913 913
	{
914 914
	  std::map<std::string, int>::iterator jt = maps.find("label");
915 915
	  if (jt == maps.end())
916 916
	    throw DataFormatError("Label map not found in file");
917 917
	  label_index = jt->second;
918 918
	}
919 919
	map_num = maps.size();
920 920
      }
921 921

	
922 922
      char c;
923 923
      while (readLine() && line >> c && c != '@') {
924 924
	line.putback(c);
925 925

	
926 926
	std::vector<std::string> tokens(map_num);
927 927
	for (int i = 0; i < map_num; ++i) {
928 928
	  if (!_reader_bits::readToken(line, tokens[i])) {
929 929
	    std::ostringstream msg;
930 930
	    msg << "Column not found (" << i + 1 << ")";
931 931
	    throw DataFormatError(msg.str().c_str());
932 932
	  }
933 933
	}
934 934
	if (line >> std::ws >> c)
935 935
	  throw DataFormatError("Extra character on the end of line");
936 936
	
937 937
	Node n;
938 938
	if (!_use_nodes) {
939 939
	  n = _digraph.addNode();
940 940
	  _node_index.insert(std::make_pair(tokens[label_index], n));
941 941
	} else {
942 942
	  typename std::map<std::string, Node>::iterator it =
943 943
	    _node_index.find(tokens[label_index]);
944 944
	  if (it == _node_index.end()) {
945 945
	    std::ostringstream msg;
946 946
	    msg << "Node with label not found: " << tokens[label_index];
947 947
	    throw DataFormatError(msg.str().c_str());	    
948 948
	  }
949 949
	  n = it->second;
950 950
	}
951 951

	
952 952
	for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
953 953
	  _node_maps[i].second->set(n, tokens[map_index[i]]);
954 954
	}
955 955

	
956 956
      }
957 957
      if (readSuccess()) {
958 958
	line.putback(c);
959 959
      }
960 960
    }
961 961

	
962 962
    void readArcs() {
963 963

	
964 964
      std::vector<int> map_index(_arc_maps.size());
965 965
      int map_num, label_index;
966 966

	
967 967
      if (!readLine()) 
968 968
	throw DataFormatError("Cannot find map captions");
969 969
      
970 970
      {
971 971
	std::map<std::string, int> maps;
972 972
	
973 973
	std::string map;
974 974
	int index = 0;
975 975
	while (_reader_bits::readToken(line, map)) {
976 976
	  if (maps.find(map) != maps.end()) {
977 977
	    std::ostringstream msg;
978 978
	    msg << "Multiple occurence of arc map: " << map;
979 979
	    throw DataFormatError(msg.str().c_str());
980 980
	  }
981 981
	  maps.insert(std::make_pair(map, index));
982 982
	  ++index;
983 983
	}
984 984
	
985 985
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
986 986
	  std::map<std::string, int>::iterator jt = 
987 987
	    maps.find(_arc_maps[i].first);
988 988
	  if (jt == maps.end()) {
989 989
	    std::ostringstream msg;
990 990
	    msg << "Map not found in file: " << _arc_maps[i].first;
991 991
	    throw DataFormatError(msg.str().c_str());
992 992
	  }
993 993
	  map_index[i] = jt->second;
994 994
	}
995 995

	
996 996
	{
997 997
	  std::map<std::string, int>::iterator jt = maps.find("label");
998 998
	  if (jt == maps.end())
999 999
	    throw DataFormatError("Label map not found in file");
1000 1000
	  label_index = jt->second;
1001 1001
	}
1002 1002
	map_num = maps.size();
1003 1003
      }
1004 1004

	
1005 1005
      char c;
1006 1006
      while (readLine() && line >> c && c != '@') {
1007 1007
	line.putback(c);
1008 1008

	
1009 1009
	std::string source_token;
1010 1010
	std::string target_token;
1011 1011

	
1012 1012
	if (!_reader_bits::readToken(line, source_token))
1013 1013
	  throw DataFormatError("Source not found");
1014 1014

	
1015 1015
	if (!_reader_bits::readToken(line, target_token))
1016 1016
	  throw DataFormatError("Source not found");
1017 1017
	
1018 1018
	std::vector<std::string> tokens(map_num);
1019 1019
	for (int i = 0; i < map_num; ++i) {
1020 1020
	  if (!_reader_bits::readToken(line, tokens[i])) {
1021 1021
	    std::ostringstream msg;
1022 1022
	    msg << "Column not found (" << i + 1 << ")";
1023 1023
	    throw DataFormatError(msg.str().c_str());
1024 1024
	  }
1025 1025
	}
1026 1026
	if (line >> std::ws >> c)
1027 1027
	  throw DataFormatError("Extra character on the end of line");
1028 1028
	
1029 1029
	Arc a;
1030 1030
	if (!_use_arcs) {
1031 1031

	
1032 1032
          typename NodeIndex::iterator it;
1033 1033
 
1034 1034
          it = _node_index.find(source_token);
1035 1035
          if (it == _node_index.end()) {
1036 1036
            std::ostringstream msg;
1037 1037
            msg << "Item not found: " << source_token;
1038 1038
            throw DataFormatError(msg.str().c_str());
1039 1039
          }
1040 1040
          Node source = it->second;
1041 1041

	
1042 1042
          it = _node_index.find(target_token);
1043 1043
          if (it == _node_index.end()) {       
1044 1044
            std::ostringstream msg;            
1045 1045
            msg << "Item not found: " << target_token;
1046 1046
            throw DataFormatError(msg.str().c_str());
1047 1047
          }                                          
1048 1048
          Node target = it->second;                            
1049 1049

	
1050 1050
	  a = _digraph.addArc(source, target);
1051 1051
	  _arc_index.insert(std::make_pair(tokens[label_index], a));
1052 1052
	} else {
1053 1053
	  typename std::map<std::string, Arc>::iterator it =
1054 1054
	    _arc_index.find(tokens[label_index]);
1055 1055
	  if (it == _arc_index.end()) {
1056 1056
	    std::ostringstream msg;
1057 1057
	    msg << "Arc with label not found: " << tokens[label_index];
1058 1058
	    throw DataFormatError(msg.str().c_str());	    
1059 1059
	  }
1060 1060
	  a = it->second;
1061 1061
	}
1062 1062

	
1063 1063
	for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1064 1064
	  _arc_maps[i].second->set(a, tokens[map_index[i]]);
1065 1065
	}
1066 1066

	
1067 1067
      }
1068 1068
      if (readSuccess()) {
1069 1069
	line.putback(c);
1070 1070
      }
1071 1071
    }
1072 1072

	
1073 1073
    void readAttributes() {
1074 1074

	
1075 1075
      std::set<std::string> read_attr;
1076 1076

	
1077 1077
      char c;
1078 1078
      while (readLine() && line >> c && c != '@') {
1079 1079
	line.putback(c);
1080 1080
	
1081 1081
	std::string attr, token;
1082 1082
	if (!_reader_bits::readToken(line, attr))
1083 1083
	  throw DataFormatError("Attribute name not found");
1084 1084
	if (!_reader_bits::readToken(line, token))
1085 1085
	  throw DataFormatError("Attribute value not found");
1086 1086
	if (line >> c)
1087 1087
	  throw DataFormatError("Extra character on the end of line");	  
1088 1088

	
1089 1089
	{
1090 1090
	  std::set<std::string>::iterator it = read_attr.find(attr);
1091 1091
	  if (it != read_attr.end()) {
1092 1092
	    std::ostringstream msg;
1093 1093
	    msg << "Multiple occurence of attribute " << attr;
1094 1094
	    throw DataFormatError(msg.str().c_str());
1095 1095
	  }
1096 1096
	  read_attr.insert(attr);
1097 1097
	}
1098 1098
	
1099 1099
	{
1100 1100
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1101 1101
	  while (it != _attributes.end() && it->first == attr) {
1102 1102
	    it->second->set(token);
1103 1103
	    ++it;
1104 1104
	  }
1105 1105
	}
1106 1106

	
1107 1107
      }
1108 1108
      if (readSuccess()) {
1109 1109
	line.putback(c);
1110 1110
      }
1111 1111
      for (typename Attributes::iterator it = _attributes.begin();
1112 1112
	   it != _attributes.end(); ++it) {
1113 1113
	if (read_attr.find(it->first) == read_attr.end()) {
1114 1114
	  std::ostringstream msg;
1115 1115
	  msg << "Attribute not found in file: " << it->first;
1116 1116
	  throw DataFormatError(msg.str().c_str());
1117 1117
	}	
1118 1118
      }
1119 1119
    }
1120 1120

	
1121 1121
  public:
1122 1122

	
1123 1123
    /// \name Execution of the reader    
1124 1124
    /// @{
1125 1125

	
1126 1126
    /// \brief Start the batch processing
1127 1127
    ///
1128 1128
    /// This function starts the batch processing
1129 1129
    void run() {
1130 1130
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1131 1131
      if (!*_is) {
1132 1132
	throw DataFormatError("Cannot find file");
1133 1133
      }
1134 1134
      
1135 1135
      bool nodes_done = false;
1136 1136
      bool arcs_done = false;
1137 1137
      bool attributes_done = false;
1138 1138
      std::set<std::string> extra_sections;
1139 1139

	
1140 1140
      line_num = 0;      
1141 1141
      readLine();
1142
      skipSection();
1142 1143

	
1143 1144
      while (readSuccess()) {
1144
	skipSection();
1145 1145
	try {
1146 1146
	  char c;
1147 1147
	  std::string section, caption;
1148 1148
	  line >> c;
1149 1149
	  _reader_bits::readToken(line, section);
1150 1150
	  _reader_bits::readToken(line, caption);
1151 1151

	
1152 1152
	  if (line >> c) 
1153 1153
	    throw DataFormatError("Extra character on the end of line");
1154 1154

	
1155 1155
	  if (section == "nodes" && !nodes_done) {
1156 1156
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1157 1157
	      readNodes();
1158 1158
	      nodes_done = true;
1159 1159
	    }
1160 1160
	  } else if ((section == "arcs" || section == "edges") && 
1161 1161
		     !arcs_done) {
1162 1162
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1163 1163
	      readArcs();
1164 1164
	      arcs_done = true;
1165 1165
	    }
1166 1166
	  } else if (section == "attributes" && !attributes_done) {
1167 1167
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1168 1168
	      readAttributes();
1169 1169
	      attributes_done = true;
1170 1170
	    }
1171 1171
	  } else {
1172 1172
	    if (extra_sections.find(section) != extra_sections.end()) {
1173 1173
	      std::ostringstream msg;
1174 1174
	      msg << "Multiple occurence of section " << section;
1175 1175
	      throw DataFormatError(msg.str().c_str());
1176 1176
	    }
1177 1177
	    Sections::iterator it = _sections.find(section);
1178 1178
	    if (it != _sections.end()) {
1179 1179
	      extra_sections.insert(section);
1180 1180
	      it->second->process(*_is, line_num);
1181
	      readLine();
1182
	    } else {
1183
	      readLine();
1184
	      skipSection();
1185 1181
	    }
1182
	    readLine();
1183
	    skipSection();
1186 1184
	  }
1187 1185
	} catch (DataFormatError& error) {
1188 1186
	  error.line(line_num);
1189 1187
	  throw;
1190 1188
	}	
1191 1189
      }
1192 1190

	
1193 1191
      if (!nodes_done) {
1194 1192
	throw DataFormatError("Section @nodes not found");
1195 1193
      }
1196 1194

	
1197 1195
      if (!arcs_done) {
1198 1196
	throw DataFormatError("Section @arcs not found");
1199 1197
      }
1200 1198

	
1201 1199
      if (!attributes_done && !_attributes.empty()) {
1202 1200
	throw DataFormatError("Section @attributes not found");
1203 1201
      }
1204 1202

	
1205 1203
    }
1206 1204

	
1207 1205
    /// @}
1208 1206
    
1209 1207
  };
1210 1208

	
1211 1209
  /// \relates DigraphReader
1212 1210
  template <typename Digraph>
1213 1211
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1214 1212
    DigraphReader<Digraph> tmp(is, digraph);
1215 1213
    return tmp;
1216 1214
  }
1217 1215

	
1218 1216
  /// \relates DigraphReader
1219 1217
  template <typename Digraph>
1220 1218
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1221 1219
				       Digraph& digraph) {
1222 1220
    DigraphReader<Digraph> tmp(fn, digraph);
1223 1221
    return tmp;
1224 1222
  }
1225 1223

	
1226 1224
  /// \relates DigraphReader
1227 1225
  template <typename Digraph>
1228 1226
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1229 1227
    DigraphReader<Digraph> tmp(fn, digraph);
1230 1228
    return tmp;
1231 1229
  }
1232 1230

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

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

	
1247 1245

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

	
1251 1249
    Graph& _graph;
1252 1250

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

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

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

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

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

	
1277 1275
    bool _use_nodes;
1278 1276
    bool _use_edges;
1279 1277

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

	
1283 1281
  public:
1284 1282

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

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

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

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

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

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

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

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

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

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

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

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

	
1360 1358
    }
1361 1359

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

	
1366 1364
  public:
1367 1365

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

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

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

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

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

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

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

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

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

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

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

	
1517 1515
    /// @}
1518 1516

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

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

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

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

	
1546 1544
    /// @}
1547 1545

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

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

	
1600 1598

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

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

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

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

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

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

	
1694 1692
    /// @}
1695 1693

	
1696 1694
  private:
1697 1695

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

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

	
1723 1721
    void readNodes() {
1724 1722

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

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

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

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

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

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

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

	
1806 1804
    void readEdges() {
1807 1805

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

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

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

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

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

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

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

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

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

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

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

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

	
1917 1915
    void readAttributes() {
1918 1916

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

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

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

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

	
1965 1963
  public:
1966 1964

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

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

	
1982 1980
      line_num = 0;      
1983 1981
      readLine();
1982
      skipSection();
1984 1983

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

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

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

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

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

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

	
2047 2043
    }
2048 2044

	
2049 2045
    /// @}
2050 2046
    
2051 2047
  };
2052 2048

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

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

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

	
2075 2071
  /// \ingroup lemon_io
2076 2072
  ///
2077 2073
  /// \brief Reader for the content of the \ref lgf-format "LGF" file 
2078 2074
  ///
2079 2075
  /// This class can be used to read the sections, the map names and
2080 2076
  /// the attributes from a file. Usually, the Lemon programs know
2081 2077
  /// that, which type of graph, which maps and which attributes
2082 2078
  /// should be read from a file, but in general tools (like glemon)
2083 2079
  /// the content of an LGF file should be guessed somehow. This class
2084 2080
  /// reads the graph and stores the appropriate information for
2085 2081
  /// reading the graph.
2086 2082
  ///
2087 2083
  ///\code LgfContent content("graph.lgf"); 
2088 2084
  /// content.run();
2089 2085
  ///
2090 2086
  /// // does it contain any node section and arc section
2091 2087
  /// if (content.nodeSectionNum() == 0 || content.arcSectionNum()) {
2092 2088
  ///   std::cerr << "Failure, cannot find graph" << std::endl;
2093 2089
  ///   return -1;
2094 2090
  /// }
2095 2091
  /// std::cout << "The name of the default node section : " 
2096 2092
  ///           << content.nodeSection(0) << std::endl;
2097 2093
  /// std::cout << "The number of the arc maps : " 
2098 2094
  ///           << content.arcMaps(0).size() << std::endl;
2099 2095
  /// std::cout << "The name of second arc map : " 
2100 2096
  ///           << content.arcMaps(0)[1] << std::endl;
2101 2097
  ///\endcode
2102 2098
  class LgfContent {    
2103 2099
  private:
2104 2100

	
2105 2101
    std::istream* _is;
2106 2102
    bool local_is;
2107 2103

	
2108 2104
    std::vector<std::string> _node_sections;
2109 2105
    std::vector<std::string> _edge_sections;
2110 2106
    std::vector<std::string> _attribute_sections;
2111 2107
    std::vector<std::string> _extra_sections;
2112 2108

	
2113 2109
    std::vector<bool> _arc_sections;
2114 2110

	
2115 2111
    std::vector<std::vector<std::string> > _node_maps;
2116 2112
    std::vector<std::vector<std::string> > _edge_maps;
2117 2113

	
2118 2114
    std::vector<std::vector<std::string> > _attributes;
2119 2115

	
2120 2116

	
2121 2117
    int line_num;
2122 2118
    std::istringstream line;
2123 2119
    
2124 2120
  public:
2125 2121

	
2126 2122
    /// \brief Constructor
2127 2123
    ///
2128 2124
    /// Construct an \e LGF content reader, which reads from the given
2129 2125
    /// input stream.
2130 2126
    LgfContent(std::istream& is) 
2131 2127
      : _is(&is), local_is(false) {}
2132 2128

	
2133 2129
    /// \brief Constructor
2134 2130
    ///
2135 2131
    /// Construct an \e LGF content reader, which reads from the given
2136 2132
    /// file.
2137 2133
    LgfContent(const std::string& fn) 
2138 2134
      : _is(new std::ifstream(fn.c_str())), local_is(true) {}
2139 2135

	
2140 2136
    /// \brief Constructor
2141 2137
    ///
2142 2138
    /// Construct an \e LGF content reader, which reads from the given
2143 2139
    /// file.
2144 2140
    LgfContent(const char* fn)
2145 2141
      : _is(new std::ifstream(fn)), local_is(true) {}
2146 2142

	
2147 2143
    /// \brief Copy constructor
2148 2144
    ///
2149 2145
    /// The copy constructor transfers all data from the other reader,
2150 2146
    /// therefore the copied reader will not be usable more. 
2151 2147
    LgfContent(LgfContent& other)
2152 2148
      : _is(other._is), local_is(other.local_is) {
2153 2149
      
2154 2150
      other._is = 0;
2155 2151
      other.local_is = false;
2156 2152
      
2157 2153
      _node_sections.swap(other._node_sections);
2158 2154
      _edge_sections.swap(other._edge_sections);
2159 2155
      _attribute_sections.swap(other._attribute_sections);
2160 2156
      _extra_sections.swap(other._extra_sections);
2161 2157

	
2162 2158
      _arc_sections.swap(other._arc_sections);
2163 2159

	
2164 2160
      _node_maps.swap(other._node_maps);
2165 2161
      _edge_maps.swap(other._edge_maps);
2166 2162
      _attributes.swap(other._attributes);
2167 2163
    }
2168 2164
    
2169 2165
    /// \brief Destructor
2170 2166
    ~LgfContent() {
2171 2167
      if (local_is) delete _is;
2172 2168
    }
2173 2169

	
2174 2170

	
2175 2171
    /// \name Node sections
2176 2172
    /// @{
2177 2173

	
2178 2174
    /// \brief Gives back the number of node sections in the file.
2179 2175
    ///
2180 2176
    /// Gives back the number of node sections in the file.
2181 2177
    int nodeSectionNum() const {
2182 2178
      return _node_sections.size();
2183 2179
    }
2184 2180

	
2185 2181
    /// \brief Returns the section name at the given position. 
2186 2182
    ///
2187 2183
    /// Returns the section name at the given position. 
2188 2184
    const std::string& nodeSection(int i) const {
2189 2185
      return _node_sections[i];
2190 2186
    }
2191 2187

	
2192 2188
    /// \brief Gives back the node maps for the given section.
2193 2189
    ///
2194 2190
    /// Gives back the node maps for the given section.
2195 2191
    const std::vector<std::string>& nodeMaps(int i) const {
2196 2192
      return _node_maps[i];
2197 2193
    }
2198 2194

	
2199 2195
    /// @}
2200 2196

	
2201 2197
    /// \name Arc sections 
2202 2198
    /// @{
2203 2199

	
2204 2200
    /// \brief Gives back the number of arc sections in the file.
2205 2201
    ///
2206 2202
    /// Gives back the number of arc sections in the file.
2207 2203
    /// \note It is synonim of \c edgeSectionNum().
2208 2204
    int arcSectionNum() const {
2209 2205
      return _edge_sections.size();
2210 2206
    }
2211 2207

	
2212 2208
    /// \brief Returns the section name at the given position. 
2213 2209
    ///
2214 2210
    /// Returns the section name at the given position. 
2215 2211
    /// \note It is synonim of \c edgeSection().
2216 2212
    const std::string& arcSection(int i) const {
2217 2213
      return _edge_sections[i];
2218 2214
    }
2219 2215

	
2220 2216
    /// \brief Gives back the arc maps for the given section.
2221 2217
    ///
2222 2218
    /// Gives back the arc maps for the given section.
2223 2219
    /// \note It is synonim of \c edgeMaps().
2224 2220
    const std::vector<std::string>& arcMaps(int i) const {
2225 2221
      return _edge_maps[i];
2226 2222
    }
2227 2223

	
2228 2224
    /// \brief Returns true when the section type is \c "@arcs".
2229 2225
    ///
2230 2226
    /// Returns true when the section type is \c "@arcs", and not "@edges".
2231 2227
    bool isArcSection(int i) const {
2232 2228
      return _arc_sections[i];
2233 2229
    }
2234 2230

	
2235 2231
    /// @}
2236 2232

	
2237 2233
    /// \name Edge sections   
2238 2234
    /// @{
2239 2235

	
2240 2236
    /// \brief Gives back the number of edge sections in the file.
2241 2237
    ///
2242 2238
    /// Gives back the number of edge sections in the file.
2243 2239
    int edgeSectionNum() const {
2244 2240
      return _edge_sections.size();
2245 2241
    }
2246 2242

	
2247 2243
    /// \brief Returns the section name at the given position. 
2248 2244
    ///
2249 2245
    /// Returns the section name at the given position. 
2250 2246
    const std::string& edgeSection(int i) const {
2251 2247
      return _edge_sections[i];
2252 2248
    }
2253 2249

	
2254 2250
    /// \brief Gives back the edge maps for the given section.
2255 2251
    ///
2256 2252
    /// Gives back the edge maps for the given section.
2257 2253
    const std::vector<std::string>& edgeMaps(int i) const {
2258 2254
      return _edge_maps[i];
2259 2255
    }
2260 2256

	
2261 2257
    /// \brief Returns true when the section type is \c "@edges".
2262 2258
    ///
2263 2259
    /// Returns true when the section type is \c "@edges", and not "@arcs".
2264 2260
    bool isEdgeSection(int i) const {
2265 2261
      return !_arc_sections[i];
2266 2262
    }
2267 2263

	
2268 2264
    /// @}
2269 2265

	
2270 2266
    /// \name Attribute sections   
2271 2267
    /// @{
2272 2268

	
2273 2269
    /// \brief Gives back the number of attribute sections in the file.
2274 2270
    ///
2275 2271
    /// Gives back the number of attribute sections in the file.
2276 2272
    int attributeSectionNum() const {
2277 2273
      return _attribute_sections.size();
2278 2274
    }
2279 2275

	
2280 2276
    /// \brief Returns the section name at the given position. 
2281 2277
    ///
2282 2278
    /// Returns the section name at the given position. 
2283 2279
    const std::string& attributeSection(int i) const {
2284 2280
      return _attribute_sections[i];
2285 2281
    }
2286 2282

	
2287 2283
    /// \brief Gives back the attributes for the given section.
2288 2284
    ///
2289 2285
    /// Gives back the attributes for the given section.
2290 2286
    const std::vector<std::string>& attributes(int i) const {
2291 2287
      return _attributes[i];
2292 2288
    }
2293 2289

	
2294 2290
    /// @}
2295 2291

	
2296 2292
    /// \name Extra sections   
2297 2293
    /// @{
2298 2294

	
2299 2295
    /// \brief Gives back the number of extra sections in the file.
2300 2296
    ///
2301 2297
    /// Gives back the number of extra sections in the file.
2302 2298
    int extraSectionNum() const {
2303 2299
      return _extra_sections.size();
2304 2300
    }
2305 2301

	
2306 2302
    /// \brief Returns the extra section type at the given position. 
2307 2303
    ///
2308 2304
    /// Returns the section type at the given position. 
2309 2305
    const std::string& extraSection(int i) const {
2310 2306
      return _extra_sections[i];
2311 2307
    }
2312 2308

	
2313 2309
    /// @}
2314 2310

	
2315 2311
  private:
2316 2312

	
2317 2313
    bool readLine() {
2318 2314
      std::string str;
2319 2315
      while(++line_num, std::getline(*_is, str)) {
2320 2316
	line.clear(); line.str(str);
2321 2317
	char c;
2322 2318
	if (line >> std::ws >> c && c != '#') {
2323 2319
	  line.putback(c);
2324 2320
	  return true;
2325 2321
	}
2326 2322
      }
2327 2323
      return false;
2328 2324
    }
2329 2325

	
2330 2326
    bool readSuccess() {
2331 2327
      return static_cast<bool>(*_is);
2332 2328
    }
2333 2329

	
2334 2330
    void skipSection() {
2335 2331
      char c;
2336 2332
      while (readSuccess() && line >> c && c != '@') {
2337 2333
	readLine();
2338 2334
      }
2339 2335
      line.putback(c);
2340 2336
    }
2341 2337

	
2342 2338
    void readMaps(std::vector<std::string>& maps) {
2343 2339
      if (!readLine()) 
2344 2340
	throw DataFormatError("Cannot find map captions");
2345 2341
      std::string map;
2346 2342
      while (_reader_bits::readToken(line, map)) {
2347 2343
	maps.push_back(map);
2348 2344
      }
2349 2345
    }
2350 2346

	
2351 2347
    void readAttributes(std::vector<std::string>& attrs) {
2352 2348
      readLine();
2353 2349
      char c;
2354 2350
      while (readSuccess() && line >> c && c != '@') {
2355 2351
	line.putback(c);
2356 2352
	std::string attr;
2357 2353
	_reader_bits::readToken(line, attr);
2358 2354
	attrs.push_back(attr);
2359 2355
	readLine();
2360 2356
      }
2361 2357
      line.putback(c);
2362 2358
    }
2363 2359

	
2364 2360
  public:
2365 2361

	
2366 2362
    /// \name Execution of the content reader    
2367 2363
    /// @{
2368 2364

	
2369 2365
    /// \brief Start the reading
2370 2366
    ///
2371 2367
    /// This function starts the reading
2372 2368
    void run() {
2373 2369

	
2374 2370
      readLine();
2375 2371
      skipSection();
2376 2372

	
2377 2373
      while (readSuccess()) {
2378 2374

	
2379 2375
	char c;
2380 2376
	line >> c;
2381 2377

	
2382 2378
	std::string section, caption;
2383 2379
	_reader_bits::readToken(line, section);
2384 2380
	_reader_bits::readToken(line, caption);
2385 2381

	
2386 2382
	if (section == "nodes") {
2387 2383
	  _node_sections.push_back(caption);
2388 2384
	  _node_maps.push_back(std::vector<std::string>());
2389 2385
	  readMaps(_node_maps.back());
2390 2386
	  readLine(); skipSection();
2391 2387
	} else if (section == "arcs" || section == "edges") {
2392 2388
	  _edge_sections.push_back(caption);
2393 2389
	  _arc_sections.push_back(section == "arcs");
2394 2390
	  _edge_maps.push_back(std::vector<std::string>());
2395 2391
	  readMaps(_edge_maps.back());
2396 2392
	  readLine(); skipSection();
2397 2393
	} else if (section == "attributes") {
2398 2394
	  _attribute_sections.push_back(caption);
2399 2395
	  _attributes.push_back(std::vector<std::string>());
2400 2396
	  readAttributes(_attributes.back());
2401 2397
	} else {
2402 2398
	  _extra_sections.push_back(section);
2403 2399
	  readLine(); skipSection();
2404 2400
	}
2405 2401
      }
2406 2402
    }
2407 2403

	
2408 2404
    /// @}
2409 2405
    
2410 2406
  };
2411 2407
}
2412 2408

	
2413 2409
#endif
0 comments (0 inline)