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

	
19
#include <lemon/list_graph.h>
20
#include <lemon/lgf_reader.h>
21
#include "test_tools.h"
22

	
23
using namespace lemon;
24

	
25
char test_lgf[] =
26
  "@nodes\n"
27
  "label\n"
28
  "0\n"
29
  "1\n"
30
  "@arcs\n"
31
  "     label\n"
32
  "0 1  0\n"
33
  "1 0  1\n"
34
  "@attributes\n"
35
  "source 0\n"
36
  "target 1\n";
37

	
38
char test_lgf_nomap[] =
39
  "@nodes\n"
40
  "label\n"
41
  "0\n"
42
  "1\n"
43
  "@arcs\n"
44
  "     -\n"
45
  "0 1\n";
46

	
47
char test_lgf_bad1[] =
48
  "@nodes\n"
49
  "label\n"
50
  "0\n"
51
  "1\n"
52
  "@arcs\n"
53
  "     - another\n"
54
  "0 1\n";
55

	
56
char test_lgf_bad2[] =
57
  "@nodes\n"
58
  "label\n"
59
  "0\n"
60
  "1\n"
61
  "@arcs\n"
62
  "     label -\n"
63
  "0 1\n";
64

	
65

	
66
int main() 
67
{
68
  {
69
    ListDigraph d; 
70
    ListDigraph::Node s,t;
71
    ListDigraph::ArcMap<int> label(d);
72
    std::istringstream input(test_lgf);
73
    digraphReader(d, input).
74
      node("source", s).
75
      node("target", t).
76
      arcMap("label", label).
77
      run();
78
    check(countNodes(d) == 2,"There should be 2 nodes");
79
    check(countArcs(d) == 2,"There should be 2 arcs");
80
  }
81
  {
82
    ListGraph g;
83
    ListGraph::Node s,t;
84
    ListGraph::EdgeMap<int> label(g);
85
    std::istringstream input(test_lgf);
86
    graphReader(g, input).
87
      node("source", s).
88
      node("target", t).
89
      edgeMap("label", label).
90
      run();
91
    check(countNodes(g) == 2,"There should be 2 nodes");
92
    check(countEdges(g) == 2,"There should be 2 arcs");
93
  }
94

	
95
  {
96
    ListDigraph d; 
97
    std::istringstream input(test_lgf_nomap);
98
    digraphReader(d, input).
99
      run();
100
    check(countNodes(d) == 2,"There should be 2 nodes");
101
    check(countArcs(d) == 1,"There should be 1 arc");
102
  }
103
  {
104
    ListGraph g;
105
    std::istringstream input(test_lgf_nomap);
106
    graphReader(g, input).
107
      run();
108
    check(countNodes(g) == 2,"There should be 2 nodes");
109
    check(countEdges(g) == 1,"There should be 1 edge");
110
  }
111

	
112
  {
113
    ListDigraph d; 
114
    std::istringstream input(test_lgf_bad1);
115
    bool ok=false;
116
    try {
117
      digraphReader(d, input).
118
        run();
119
    }
120
    catch (FormatError& error) 
121
      {
122
        ok = true;
123
      }
124
    check(ok,"FormatError exception should have occured");
125
  }
126
  {
127
    ListGraph g;
128
    std::istringstream input(test_lgf_bad1);
129
    bool ok=false;
130
    try {
131
      graphReader(g, input).
132
        run();
133
    }
134
    catch (FormatError& error)
135
      {
136
        ok = true;
137
      }
138
    check(ok,"FormatError exception should have occured");
139
  }
140

	
141
  {
142
    ListDigraph d; 
143
    std::istringstream input(test_lgf_bad2);
144
    bool ok=false;
145
    try {
146
      digraphReader(d, input).
147
        run();
148
    }
149
    catch (FormatError& error)
150
      {
151
        ok = true;
152
      }
153
    check(ok,"FormatError exception should have occured");
154
  }
155
  {
156
    ListGraph g;
157
    std::istringstream input(test_lgf_bad2);
158
    bool ok=false;
159
    try {
160
      graphReader(g, input).
161
        run();
162
    }
163
    catch (FormatError& error)
164
      {
165
        ok = true;
166
      }
167
    check(ok,"FormatError exception should have occured");
168
  }
169
}
Ignore white space 768 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
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
namespace lemon {
20 20
/*!
21 21

	
22 22

	
23 23

	
24 24
\page lgf-format LEMON Graph Format (LGF)
25 25

	
26 26
The \e LGF is a <em>column oriented</em>
27 27
file format for storing graphs and associated data like
28 28
node and edge maps.
29 29

	
30 30
Each line with \c '#' first non-whitespace
31 31
character is considered as a comment line.
32 32

	
33 33
Otherwise the file consists of sections starting with
34 34
a header line. The header lines starts with an \c '@' character followed by the
35 35
type of section. The standard section types are \c \@nodes, \c
36 36
\@arcs and \c \@edges
37 37
and \@attributes. Each header line may also have an optional
38 38
\e name, which can be use to distinguish the sections of the same
39 39
type.
40 40

	
41 41
The standard sections are column oriented, each line consists of
42 42
<em>token</em>s separated by whitespaces. A token can be \e plain or
43 43
\e quoted. A plain token is just a sequence of non-whitespace characters,
44 44
while a quoted token is a
45 45
character sequence surrounded by double quotes, and it can also
46 46
contain whitespaces and escape sequences.
47 47

	
48 48
The \c \@nodes section describes a set of nodes and associated
49 49
maps. The first is a header line, its columns are the names of the
50 50
maps appearing in the following lines.
51 51
One of the maps must be called \c
52 52
"label", which plays special role in the file.
53 53
The following
54 54
non-empty lines until the next section describes nodes of the
55 55
graph. Each line contains the values of the node maps
56 56
associated to the current node.
57 57

	
58 58
\code
59 59
 @nodes
60 60
 label  coordinates  size    title
61 61
 1      (10,20)      10      "First node"
62 62
 2      (80,80)      8       "Second node"
63 63
 3      (40,10)      10      "Third node"
64 64
\endcode
65 65

	
66
The \c \@arcs section is very similar to the \c \@nodes section,
67
it again starts with a header line describing the names of the maps,
68
but the \c "label" map is not obligatory here. The following lines
69
describe the arcs. The first two tokens of each line are
70
the source and the target node of the arc, respectively, then come the map
66
The \c \@arcs section is very similar to the \c \@nodes section, it
67
again starts with a header line describing the names of the maps, but
68
the \c "label" map is not obligatory here. The following lines
69
describe the arcs. The first two tokens of each line are the source
70
and the target node of the arc, respectively, then come the map
71 71
values. The source and target tokens must be node labels.
72 72

	
73 73
\code
74 74
 @arcs
75 75
         capacity
76 76
 1   2   16
77 77
 1   3   12
78 78
 2   3   18
79 79
\endcode
80 80

	
81
If there is no map in the \c \@arcs section at all, then it must be
82
indicated by a sole '-' sign in the first line.
83

	
84
\code
85
 @arcs
86
         -
87
 1   2
88
 1   3
89
 2   3
90
\endcode
91

	
81 92
The \c \@edges is just a synonym of \c \@arcs. The \@arcs section can
82 93
also store the edge set of an undirected graph. In such case there is
83 94
a conventional method for store arc maps in the file, if two columns
84
has the same caption with \c '+' and \c '-' prefix, then these columns
95
have the same caption with \c '+' and \c '-' prefix, then these columns
85 96
can be regarded as the values of an arc map.
86 97

	
87 98
The \c \@attributes section contains key-value pairs, each line
88 99
consists of two tokens, an attribute name, and then an attribute
89 100
value. The value of the attribute could be also a label value of a
90 101
node or an edge, or even an edge label prefixed with \c '+' or \c '-',
91 102
which regards to the forward or backward directed arc of the
92 103
corresponding edge.
93 104

	
94 105
\code
95 106
 @attributes
96 107
 source 1
97 108
 target 3
98 109
 caption "LEMON test digraph"
99 110
\endcode
100 111

	
101 112
The \e LGF can contain extra sections, but there is no restriction on
102 113
the format of such sections.
103 114

	
104 115
*/
105 116
}
106 117

	
107 118
//  LocalWords:  whitespace whitespaces
Ignore white space 768 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2008
5
 * Copyright (C) 2003-2011
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 \ref lgf-format "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/core.h>
35 35

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

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

	
41 41
namespace lemon {
42 42

	
43 43
  namespace _reader_bits {
44 44

	
45 45
    template <typename Value>
46 46
    struct DefaultConverter {
47 47
      Value operator()(const std::string& str) {
48 48
        std::istringstream is(str);
49 49
        Value value;
50 50
        if (!(is >> value)) {
51 51
          throw FormatError("Cannot read token");
52 52
        }
53 53

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

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

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

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

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

	
80 80
    };
81 81

	
82 82
    template <typename _Item, typename _Map,
83 83
              typename _Converter = DefaultConverter<typename _Map::Value> >
84 84
    class MapStorage : public MapStorageBase<_Item> {
85 85
    public:
86 86
      typedef _Map Map;
87 87
      typedef _Converter Converter;
88 88
      typedef _Item Item;
89 89

	
90 90
    private:
91 91
      Map& _map;
92 92
      Converter _converter;
93 93

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

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

	
104 104
    template <typename _Graph, bool _dir, typename _Map,
105 105
              typename _Converter = DefaultConverter<typename _Map::Value> >
106 106
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
107 107
    public:
108 108
      typedef _Map Map;
109 109
      typedef _Converter Converter;
110 110
      typedef _Graph Graph;
111 111
      typedef typename Graph::Edge Item;
112 112
      static const bool dir = _dir;
113 113

	
114 114
    private:
115 115
      const Graph& _graph;
116 116
      Map& _map;
117 117
      Converter _converter;
118 118

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

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

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

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

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

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

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

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

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

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

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

	
176 176
    template <typename Graph>
177 177
    struct GraphArcLookUpConverter {
178 178
      const Graph& _graph;
179 179
      const std::map<std::string, typename Graph::Edge>& _map;
180 180

	
181 181
      GraphArcLookUpConverter(const Graph& graph,
182 182
                              const std::map<std::string,
183 183
                                             typename Graph::Edge>& map)
184 184
        : _graph(graph), _map(map) {}
185 185

	
186 186
      typename Graph::Arc operator()(const std::string& str) {
187 187
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
188 188
          throw FormatError("Item must start with '+' or '-'");
189 189
        }
190 190
        typename std::map<std::string, typename Graph::Edge>
191 191
          ::const_iterator it = _map.find(str.substr(1));
192 192
        if (it == _map.end()) {
193 193
          throw FormatError("Item not found");
194 194
        }
195 195
        return _graph.direct(it->second, str[0] == '+');
196 196
      }
197 197
    };
198 198

	
199 199
    inline bool isWhiteSpace(char c) {
200 200
      return c == ' ' || c == '\t' || c == '\v' ||
201 201
        c == '\n' || c == '\r' || c == '\f';
202 202
    }
203 203

	
204 204
    inline bool isOct(char c) {
205 205
      return '0' <= c && c <='7';
206 206
    }
207 207

	
208 208
    inline int valueOct(char c) {
209 209
      LEMON_ASSERT(isOct(c), "The character is not octal.");
210 210
      return c - '0';
211 211
    }
212 212

	
213 213
    inline bool isHex(char c) {
214 214
      return ('0' <= c && c <= '9') ||
215 215
        ('a' <= c && c <= 'z') ||
216 216
        ('A' <= c && c <= 'Z');
217 217
    }
218 218

	
219 219
    inline int valueHex(char c) {
220 220
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
221 221
      if ('0' <= c && c <= '9') return c - '0';
222 222
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
223 223
      return c - 'A' + 10;
224 224
    }
225 225

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

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

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

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

	
288 288
    inline std::istream& readToken(std::istream& is, std::string& str) {
289 289
      std::ostringstream os;
290 290

	
291 291
      char c;
292 292
      is >> std::ws;
293 293

	
294 294
      if (!is.get(c))
295 295
        return is;
296 296

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

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

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

	
332 332
      Functor _functor;
333 333

	
334 334
    public:
335 335

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

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

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

	
364 364
      Functor _functor;
365 365

	
366 366
    public:
367 367

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

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

	
388 388
  }
389 389

	
... ...
@@ -584,768 +584,775 @@
584 584
      _attributes.swap(other._attributes);
585 585

	
586 586
      _nodes_caption = other._nodes_caption;
587 587
      _arcs_caption = other._arcs_caption;
588 588
      _attributes_caption = other._attributes_caption;
589 589

	
590 590
    }
591 591

	
592 592
    DigraphReader& operator=(const DigraphReader&);
593 593

	
594 594
  public:
595 595

	
596 596
    /// \name Reading rules
597 597
    /// @{
598 598

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

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

	
625 625
    /// \brief Arc map reading rule
626 626
    ///
627 627
    /// Add an arc map reading rule to the reader.
628 628
    template <typename Map>
629 629
    DigraphReader& arcMap(const std::string& caption, Map& map) {
630 630
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
631 631
      _reader_bits::MapStorageBase<Arc>* storage =
632 632
        new _reader_bits::MapStorage<Arc, Map>(map);
633 633
      _arc_maps.push_back(std::make_pair(caption, storage));
634 634
      return *this;
635 635
    }
636 636

	
637 637
    /// \brief Arc map reading rule
638 638
    ///
639 639
    /// Add an arc map reading rule with specialized converter to the
640 640
    /// reader.
641 641
    template <typename Map, typename Converter>
642 642
    DigraphReader& arcMap(const std::string& caption, Map& map,
643 643
                          const Converter& converter = Converter()) {
644 644
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
645 645
      _reader_bits::MapStorageBase<Arc>* storage =
646 646
        new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
647 647
      _arc_maps.push_back(std::make_pair(caption, storage));
648 648
      return *this;
649 649
    }
650 650

	
651 651
    /// \brief Attribute reading rule
652 652
    ///
653 653
    /// Add an attribute reading rule to the reader.
654 654
    template <typename Value>
655 655
    DigraphReader& attribute(const std::string& caption, Value& value) {
656 656
      _reader_bits::ValueStorageBase* storage =
657 657
        new _reader_bits::ValueStorage<Value>(value);
658 658
      _attributes.insert(std::make_pair(caption, storage));
659 659
      return *this;
660 660
    }
661 661

	
662 662
    /// \brief Attribute reading rule
663 663
    ///
664 664
    /// Add an attribute reading rule with specialized converter to the
665 665
    /// reader.
666 666
    template <typename Value, typename Converter>
667 667
    DigraphReader& attribute(const std::string& caption, Value& value,
668 668
                             const Converter& converter = Converter()) {
669 669
      _reader_bits::ValueStorageBase* storage =
670 670
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
671 671
      _attributes.insert(std::make_pair(caption, storage));
672 672
      return *this;
673 673
    }
674 674

	
675 675
    /// \brief Node reading rule
676 676
    ///
677 677
    /// Add a node reading rule to reader.
678 678
    DigraphReader& node(const std::string& caption, Node& node) {
679 679
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
680 680
      Converter converter(_node_index);
681 681
      _reader_bits::ValueStorageBase* storage =
682 682
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
683 683
      _attributes.insert(std::make_pair(caption, storage));
684 684
      return *this;
685 685
    }
686 686

	
687 687
    /// \brief Arc reading rule
688 688
    ///
689 689
    /// Add an arc reading rule to reader.
690 690
    DigraphReader& arc(const std::string& caption, Arc& arc) {
691 691
      typedef _reader_bits::MapLookUpConverter<Arc> Converter;
692 692
      Converter converter(_arc_index);
693 693
      _reader_bits::ValueStorageBase* storage =
694 694
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
695 695
      _attributes.insert(std::make_pair(caption, storage));
696 696
      return *this;
697 697
    }
698 698

	
699 699
    /// @}
700 700

	
701 701
    /// \name Select section by name
702 702
    /// @{
703 703

	
704 704
    /// \brief Set \c \@nodes section to be read
705 705
    ///
706 706
    /// Set \c \@nodes section to be read
707 707
    DigraphReader& nodes(const std::string& caption) {
708 708
      _nodes_caption = caption;
709 709
      return *this;
710 710
    }
711 711

	
712 712
    /// \brief Set \c \@arcs section to be read
713 713
    ///
714 714
    /// Set \c \@arcs section to be read
715 715
    DigraphReader& arcs(const std::string& caption) {
716 716
      _arcs_caption = caption;
717 717
      return *this;
718 718
    }
719 719

	
720 720
    /// \brief Set \c \@attributes section to be read
721 721
    ///
722 722
    /// Set \c \@attributes section to be read
723 723
    DigraphReader& attributes(const std::string& caption) {
724 724
      _attributes_caption = caption;
725 725
      return *this;
726 726
    }
727 727

	
728 728
    /// @}
729 729

	
730 730
    /// \name Using previously constructed node or arc set
731 731
    /// @{
732 732

	
733 733
    /// \brief Use previously constructed node set
734 734
    ///
735 735
    /// Use previously constructed node set, and specify the node
736 736
    /// label map.
737 737
    template <typename Map>
738 738
    DigraphReader& useNodes(const Map& map) {
739 739
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
740 740
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
741 741
      _use_nodes = true;
742 742
      _writer_bits::DefaultConverter<typename Map::Value> converter;
743 743
      for (NodeIt n(_digraph); n != INVALID; ++n) {
744 744
        _node_index.insert(std::make_pair(converter(map[n]), n));
745 745
      }
746 746
      return *this;
747 747
    }
748 748

	
749 749
    /// \brief Use previously constructed node set
750 750
    ///
751 751
    /// Use previously constructed node set, and specify the node
752 752
    /// label map and a functor which converts the label map values to
753 753
    /// \c std::string.
754 754
    template <typename Map, typename Converter>
755 755
    DigraphReader& useNodes(const Map& map,
756 756
                            const Converter& converter = Converter()) {
757 757
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
758 758
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
759 759
      _use_nodes = true;
760 760
      for (NodeIt n(_digraph); n != INVALID; ++n) {
761 761
        _node_index.insert(std::make_pair(converter(map[n]), n));
762 762
      }
763 763
      return *this;
764 764
    }
765 765

	
766 766
    /// \brief Use previously constructed arc set
767 767
    ///
768 768
    /// Use previously constructed arc set, and specify the arc
769 769
    /// label map.
770 770
    template <typename Map>
771 771
    DigraphReader& useArcs(const Map& map) {
772 772
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
773 773
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
774 774
      _use_arcs = true;
775 775
      _writer_bits::DefaultConverter<typename Map::Value> converter;
776 776
      for (ArcIt a(_digraph); a != INVALID; ++a) {
777 777
        _arc_index.insert(std::make_pair(converter(map[a]), a));
778 778
      }
779 779
      return *this;
780 780
    }
781 781

	
782 782
    /// \brief Use previously constructed arc set
783 783
    ///
784 784
    /// Use previously constructed arc set, and specify the arc
785 785
    /// label map and a functor which converts the label map values to
786 786
    /// \c std::string.
787 787
    template <typename Map, typename Converter>
788 788
    DigraphReader& useArcs(const Map& map,
789 789
                           const Converter& converter = Converter()) {
790 790
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
791 791
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
792 792
      _use_arcs = true;
793 793
      for (ArcIt a(_digraph); a != INVALID; ++a) {
794 794
        _arc_index.insert(std::make_pair(converter(map[a]), a));
795 795
      }
796 796
      return *this;
797 797
    }
798 798

	
799 799
    /// \brief Skips the reading of node section
800 800
    ///
801 801
    /// Omit the reading of the node section. This implies that each node
802 802
    /// map reading rule will be abandoned, and the nodes of the graph
803 803
    /// will not be constructed, which usually cause that the arc set
804 804
    /// could not be read due to lack of node name resolving.
805 805
    /// Therefore \c skipArcs() function should also be used, or
806 806
    /// \c useNodes() should be used to specify the label of the nodes.
807 807
    DigraphReader& skipNodes() {
808 808
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
809 809
      _skip_nodes = true;
810 810
      return *this;
811 811
    }
812 812

	
813 813
    /// \brief Skips the reading of arc section
814 814
    ///
815 815
    /// Omit the reading of the arc section. This implies that each arc
816 816
    /// map reading rule will be abandoned, and the arcs of the graph
817 817
    /// will not be constructed.
818 818
    DigraphReader& skipArcs() {
819 819
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
820 820
      _skip_arcs = true;
821 821
      return *this;
822 822
    }
823 823

	
824 824
    /// @}
825 825

	
826 826
  private:
827 827

	
828 828
    bool readLine() {
829 829
      std::string str;
830 830
      while(++line_num, std::getline(*_is, str)) {
831 831
        line.clear(); line.str(str);
832 832
        char c;
833 833
        if (line >> std::ws >> c && c != '#') {
834 834
          line.putback(c);
835 835
          return true;
836 836
        }
837 837
      }
838 838
      return false;
839 839
    }
840 840

	
841 841
    bool readSuccess() {
842 842
      return static_cast<bool>(*_is);
843 843
    }
844 844

	
845 845
    void skipSection() {
846 846
      char c;
847 847
      while (readSuccess() && line >> c && c != '@') {
848 848
        readLine();
849 849
      }
850 850
      if (readSuccess()) {
851 851
        line.putback(c);
852 852
      }
853 853
    }
854 854

	
855 855
    void readNodes() {
856 856

	
857 857
      std::vector<int> map_index(_node_maps.size());
858 858
      int map_num, label_index;
859 859

	
860 860
      char c;
861 861
      if (!readLine() || !(line >> c) || c == '@') {
862 862
        if (readSuccess() && line) line.putback(c);
863 863
        if (!_node_maps.empty())
864 864
          throw FormatError("Cannot find map names");
865 865
        return;
866 866
      }
867 867
      line.putback(c);
868 868

	
869 869
      {
870 870
        std::map<std::string, int> maps;
871 871

	
872 872
        std::string map;
873 873
        int index = 0;
874 874
        while (_reader_bits::readToken(line, map)) {
875 875
          if (maps.find(map) != maps.end()) {
876 876
            std::ostringstream msg;
877 877
            msg << "Multiple occurence of node map: " << map;
878 878
            throw FormatError(msg.str());
879 879
          }
880 880
          maps.insert(std::make_pair(map, index));
881 881
          ++index;
882 882
        }
883 883

	
884 884
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
885 885
          std::map<std::string, int>::iterator jt =
886 886
            maps.find(_node_maps[i].first);
887 887
          if (jt == maps.end()) {
888 888
            std::ostringstream msg;
889 889
            msg << "Map not found: " << _node_maps[i].first;
890 890
            throw FormatError(msg.str());
891 891
          }
892 892
          map_index[i] = jt->second;
893 893
        }
894 894

	
895 895
        {
896 896
          std::map<std::string, int>::iterator jt = maps.find("label");
897 897
          if (jt != maps.end()) {
898 898
            label_index = jt->second;
899 899
          } else {
900 900
            label_index = -1;
901 901
          }
902 902
        }
903 903
        map_num = maps.size();
904 904
      }
905 905

	
906 906
      while (readLine() && line >> c && c != '@') {
907 907
        line.putback(c);
908 908

	
909 909
        std::vector<std::string> tokens(map_num);
910 910
        for (int i = 0; i < map_num; ++i) {
911 911
          if (!_reader_bits::readToken(line, tokens[i])) {
912 912
            std::ostringstream msg;
913 913
            msg << "Column not found (" << i + 1 << ")";
914 914
            throw FormatError(msg.str());
915 915
          }
916 916
        }
917 917
        if (line >> std::ws >> c)
918 918
          throw FormatError("Extra character at the end of line");
919 919

	
920 920
        Node n;
921 921
        if (!_use_nodes) {
922 922
          n = _digraph.addNode();
923 923
          if (label_index != -1)
924 924
            _node_index.insert(std::make_pair(tokens[label_index], n));
925 925
        } else {
926 926
          if (label_index == -1)
927 927
            throw FormatError("Label map not found");
928 928
          typename std::map<std::string, Node>::iterator it =
929 929
            _node_index.find(tokens[label_index]);
930 930
          if (it == _node_index.end()) {
931 931
            std::ostringstream msg;
932 932
            msg << "Node with label not found: " << tokens[label_index];
933 933
            throw FormatError(msg.str());
934 934
          }
935 935
          n = it->second;
936 936
        }
937 937

	
938 938
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
939 939
          _node_maps[i].second->set(n, tokens[map_index[i]]);
940 940
        }
941 941

	
942 942
      }
943 943
      if (readSuccess()) {
944 944
        line.putback(c);
945 945
      }
946 946
    }
947 947

	
948 948
    void readArcs() {
949 949

	
950 950
      std::vector<int> map_index(_arc_maps.size());
951 951
      int map_num, label_index;
952 952

	
953 953
      char c;
954 954
      if (!readLine() || !(line >> c) || c == '@') {
955 955
        if (readSuccess() && line) line.putback(c);
956 956
        if (!_arc_maps.empty())
957 957
          throw FormatError("Cannot find map names");
958 958
        return;
959 959
      }
960 960
      line.putback(c);
961 961

	
962 962
      {
963 963
        std::map<std::string, int> maps;
964 964

	
965 965
        std::string map;
966 966
        int index = 0;
967 967
        while (_reader_bits::readToken(line, map)) {
968
          if(map == "-") {
969
              if(index!=0)
970
                throw FormatError("'-' is not allowed as a map name");
971
              else if (line >> std::ws >> c)
972
                throw FormatError("Extra character at the end of line");
973
              else break;
974
            }
968 975
          if (maps.find(map) != maps.end()) {
969 976
            std::ostringstream msg;
970 977
            msg << "Multiple occurence of arc map: " << map;
971 978
            throw FormatError(msg.str());
972 979
          }
973 980
          maps.insert(std::make_pair(map, index));
974 981
          ++index;
975 982
        }
976 983

	
977 984
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
978 985
          std::map<std::string, int>::iterator jt =
979 986
            maps.find(_arc_maps[i].first);
980 987
          if (jt == maps.end()) {
981 988
            std::ostringstream msg;
982 989
            msg << "Map not found: " << _arc_maps[i].first;
983 990
            throw FormatError(msg.str());
984 991
          }
985 992
          map_index[i] = jt->second;
986 993
        }
987 994

	
988 995
        {
989 996
          std::map<std::string, int>::iterator jt = maps.find("label");
990 997
          if (jt != maps.end()) {
991 998
            label_index = jt->second;
992 999
          } else {
993 1000
            label_index = -1;
994 1001
          }
995 1002
        }
996 1003
        map_num = maps.size();
997 1004
      }
998 1005

	
999 1006
      while (readLine() && line >> c && c != '@') {
1000 1007
        line.putback(c);
1001 1008

	
1002 1009
        std::string source_token;
1003 1010
        std::string target_token;
1004 1011

	
1005 1012
        if (!_reader_bits::readToken(line, source_token))
1006 1013
          throw FormatError("Source not found");
1007 1014

	
1008 1015
        if (!_reader_bits::readToken(line, target_token))
1009 1016
          throw FormatError("Target not found");
1010 1017

	
1011 1018
        std::vector<std::string> tokens(map_num);
1012 1019
        for (int i = 0; i < map_num; ++i) {
1013 1020
          if (!_reader_bits::readToken(line, tokens[i])) {
1014 1021
            std::ostringstream msg;
1015 1022
            msg << "Column not found (" << i + 1 << ")";
1016 1023
            throw FormatError(msg.str());
1017 1024
          }
1018 1025
        }
1019 1026
        if (line >> std::ws >> c)
1020 1027
          throw FormatError("Extra character at the end of line");
1021 1028

	
1022 1029
        Arc a;
1023 1030
        if (!_use_arcs) {
1024 1031

	
1025 1032
          typename NodeIndex::iterator it;
1026 1033

	
1027 1034
          it = _node_index.find(source_token);
1028 1035
          if (it == _node_index.end()) {
1029 1036
            std::ostringstream msg;
1030 1037
            msg << "Item not found: " << source_token;
1031 1038
            throw FormatError(msg.str());
1032 1039
          }
1033 1040
          Node source = it->second;
1034 1041

	
1035 1042
          it = _node_index.find(target_token);
1036 1043
          if (it == _node_index.end()) {
1037 1044
            std::ostringstream msg;
1038 1045
            msg << "Item not found: " << target_token;
1039 1046
            throw FormatError(msg.str());
1040 1047
          }
1041 1048
          Node target = it->second;
1042 1049

	
1043 1050
          a = _digraph.addArc(source, target);
1044 1051
          if (label_index != -1)
1045 1052
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1046 1053
        } else {
1047 1054
          if (label_index == -1)
1048 1055
            throw FormatError("Label map not found");
1049 1056
          typename std::map<std::string, Arc>::iterator it =
1050 1057
            _arc_index.find(tokens[label_index]);
1051 1058
          if (it == _arc_index.end()) {
1052 1059
            std::ostringstream msg;
1053 1060
            msg << "Arc with label not found: " << tokens[label_index];
1054 1061
            throw FormatError(msg.str());
1055 1062
          }
1056 1063
          a = it->second;
1057 1064
        }
1058 1065

	
1059 1066
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1060 1067
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
1061 1068
        }
1062 1069

	
1063 1070
      }
1064 1071
      if (readSuccess()) {
1065 1072
        line.putback(c);
1066 1073
      }
1067 1074
    }
1068 1075

	
1069 1076
    void readAttributes() {
1070 1077

	
1071 1078
      std::set<std::string> read_attr;
1072 1079

	
1073 1080
      char c;
1074 1081
      while (readLine() && line >> c && c != '@') {
1075 1082
        line.putback(c);
1076 1083

	
1077 1084
        std::string attr, token;
1078 1085
        if (!_reader_bits::readToken(line, attr))
1079 1086
          throw FormatError("Attribute name not found");
1080 1087
        if (!_reader_bits::readToken(line, token))
1081 1088
          throw FormatError("Attribute value not found");
1082 1089
        if (line >> c)
1083 1090
          throw FormatError("Extra character at the end of line");
1084 1091

	
1085 1092
        {
1086 1093
          std::set<std::string>::iterator it = read_attr.find(attr);
1087 1094
          if (it != read_attr.end()) {
1088 1095
            std::ostringstream msg;
1089 1096
            msg << "Multiple occurence of attribute: " << attr;
1090 1097
            throw FormatError(msg.str());
1091 1098
          }
1092 1099
          read_attr.insert(attr);
1093 1100
        }
1094 1101

	
1095 1102
        {
1096 1103
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1097 1104
          while (it != _attributes.end() && it->first == attr) {
1098 1105
            it->second->set(token);
1099 1106
            ++it;
1100 1107
          }
1101 1108
        }
1102 1109

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

	
1117 1124
  public:
1118 1125

	
1119 1126
    /// \name Execution of the reader
1120 1127
    /// @{
1121 1128

	
1122 1129
    /// \brief Start the batch processing
1123 1130
    ///
1124 1131
    /// This function starts the batch processing
1125 1132
    void run() {
1126 1133
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1127 1134

	
1128 1135
      bool nodes_done = _skip_nodes;
1129 1136
      bool arcs_done = _skip_arcs;
1130 1137
      bool attributes_done = false;
1131 1138

	
1132 1139
      line_num = 0;
1133 1140
      readLine();
1134 1141
      skipSection();
1135 1142

	
1136 1143
      while (readSuccess()) {
1137 1144
        try {
1138 1145
          char c;
1139 1146
          std::string section, caption;
1140 1147
          line >> c;
1141 1148
          _reader_bits::readToken(line, section);
1142 1149
          _reader_bits::readToken(line, caption);
1143 1150

	
1144 1151
          if (line >> c)
1145 1152
            throw FormatError("Extra character at the end of line");
1146 1153

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

	
1174 1181
      if (!nodes_done) {
1175 1182
        throw FormatError("Section @nodes not found");
1176 1183
      }
1177 1184

	
1178 1185
      if (!arcs_done) {
1179 1186
        throw FormatError("Section @arcs not found");
1180 1187
      }
1181 1188

	
1182 1189
      if (!attributes_done && !_attributes.empty()) {
1183 1190
        throw FormatError("Section @attributes not found");
1184 1191
      }
1185 1192

	
1186 1193
    }
1187 1194

	
1188 1195
    /// @}
1189 1196

	
1190 1197
  };
1191 1198

	
1192 1199
  /// \brief Return a \ref DigraphReader class
1193 1200
  ///
1194 1201
  /// This function just returns a \ref DigraphReader class.
1195 1202
  /// \relates DigraphReader
1196 1203
  template <typename Digraph>
1197 1204
  DigraphReader<Digraph> digraphReader(Digraph& digraph, std::istream& is) {
1198 1205
    DigraphReader<Digraph> tmp(digraph, is);
1199 1206
    return tmp;
1200 1207
  }
1201 1208

	
1202 1209
  /// \brief Return a \ref DigraphReader class
1203 1210
  ///
1204 1211
  /// This function just returns a \ref DigraphReader class.
1205 1212
  /// \relates DigraphReader
1206 1213
  template <typename Digraph>
1207 1214
  DigraphReader<Digraph> digraphReader(Digraph& digraph,
1208 1215
                                       const std::string& fn) {
1209 1216
    DigraphReader<Digraph> tmp(digraph, fn);
1210 1217
    return tmp;
1211 1218
  }
1212 1219

	
1213 1220
  /// \brief Return a \ref DigraphReader class
1214 1221
  ///
1215 1222
  /// This function just returns a \ref DigraphReader class.
1216 1223
  /// \relates DigraphReader
1217 1224
  template <typename Digraph>
1218 1225
  DigraphReader<Digraph> digraphReader(Digraph& digraph, const char* fn) {
1219 1226
    DigraphReader<Digraph> tmp(digraph, fn);
1220 1227
    return tmp;
1221 1228
  }
1222 1229

	
1223 1230
  template <typename Graph>
1224 1231
  class GraphReader;
1225 1232
 
1226 1233
  template <typename Graph>
1227 1234
  GraphReader<Graph> graphReader(Graph& graph, 
1228 1235
                                 std::istream& is = std::cin);
1229 1236
  template <typename Graph>
1230 1237
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn);
1231 1238
  template <typename Graph>
1232 1239
  GraphReader<Graph> graphReader(Graph& graph, const char *fn);
1233 1240

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

	
1253 1260
    typedef _Graph Graph;
1254 1261
    TEMPLATE_GRAPH_TYPEDEFS(Graph);
1255 1262

	
1256 1263
  private:
1257 1264

	
1258 1265
    std::istream* _is;
1259 1266
    bool local_is;
1260 1267
    std::string _filename;
1261 1268

	
1262 1269
    Graph& _graph;
1263 1270

	
1264 1271
    std::string _nodes_caption;
1265 1272
    std::string _edges_caption;
1266 1273
    std::string _attributes_caption;
1267 1274

	
1268 1275
    typedef std::map<std::string, Node> NodeIndex;
1269 1276
    NodeIndex _node_index;
1270 1277
    typedef std::map<std::string, Edge> EdgeIndex;
1271 1278
    EdgeIndex _edge_index;
1272 1279

	
1273 1280
    typedef std::vector<std::pair<std::string,
1274 1281
      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
1275 1282
    NodeMaps _node_maps;
1276 1283

	
1277 1284
    typedef std::vector<std::pair<std::string,
1278 1285
      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
1279 1286
    EdgeMaps _edge_maps;
1280 1287

	
1281 1288
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
1282 1289
      Attributes;
1283 1290
    Attributes _attributes;
1284 1291

	
1285 1292
    bool _use_nodes;
1286 1293
    bool _use_edges;
1287 1294

	
1288 1295
    bool _skip_nodes;
1289 1296
    bool _skip_edges;
1290 1297

	
1291 1298
    int line_num;
1292 1299
    std::istringstream line;
1293 1300

	
1294 1301
  public:
1295 1302

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

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

	
1320 1327
    /// \brief Constructor
1321 1328
    ///
1322 1329
    /// Construct an undirected graph reader, which reads from the given
1323 1330
    /// file.
1324 1331
    GraphReader(Graph& graph, const char* fn)
1325 1332
      : _is(new std::ifstream(fn)), local_is(true),
1326 1333
        _filename(fn), _graph(graph),
1327 1334
        _use_nodes(false), _use_edges(false),
1328 1335
        _skip_nodes(false), _skip_edges(false) {
1329 1336
      if (!(*_is)) {
1330 1337
        delete _is;
1331 1338
        throw IoError("Cannot open file", fn);
1332 1339
      }
1333 1340
    }
1334 1341

	
1335 1342
    /// \brief Destructor
1336 1343
    ~GraphReader() {
1337 1344
      for (typename NodeMaps::iterator it = _node_maps.begin();
1338 1345
           it != _node_maps.end(); ++it) {
1339 1346
        delete it->second;
1340 1347
      }
1341 1348

	
1342 1349
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
1343 1350
           it != _edge_maps.end(); ++it) {
1344 1351
        delete it->second;
1345 1352
      }
1346 1353

	
1347 1354
      for (typename Attributes::iterator it = _attributes.begin();
1348 1355
           it != _attributes.end(); ++it) {
1349 1356
        delete it->second;
1350 1357
      }
1351 1358

	
... ...
@@ -1426,768 +1433,775 @@
1426 1433
      _reader_bits::MapStorageBase<Edge>* storage =
1427 1434
        new _reader_bits::MapStorage<Edge, Map>(map);
1428 1435
      _edge_maps.push_back(std::make_pair(caption, storage));
1429 1436
      return *this;
1430 1437
    }
1431 1438

	
1432 1439
    /// \brief Edge map reading rule
1433 1440
    ///
1434 1441
    /// Add an edge map reading rule with specialized converter to the
1435 1442
    /// reader.
1436 1443
    template <typename Map, typename Converter>
1437 1444
    GraphReader& edgeMap(const std::string& caption, Map& map,
1438 1445
                          const Converter& converter = Converter()) {
1439 1446
      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
1440 1447
      _reader_bits::MapStorageBase<Edge>* storage =
1441 1448
        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
1442 1449
      _edge_maps.push_back(std::make_pair(caption, storage));
1443 1450
      return *this;
1444 1451
    }
1445 1452

	
1446 1453
    /// \brief Arc map reading rule
1447 1454
    ///
1448 1455
    /// Add an arc map reading rule to the reader.
1449 1456
    template <typename Map>
1450 1457
    GraphReader& arcMap(const std::string& caption, Map& map) {
1451 1458
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1452 1459
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1453 1460
        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
1454 1461
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1455 1462
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1456 1463
        new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map);
1457 1464
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1458 1465
      return *this;
1459 1466
    }
1460 1467

	
1461 1468
    /// \brief Arc map reading rule
1462 1469
    ///
1463 1470
    /// Add an arc map reading rule with specialized converter to the
1464 1471
    /// reader.
1465 1472
    template <typename Map, typename Converter>
1466 1473
    GraphReader& arcMap(const std::string& caption, Map& map,
1467 1474
                          const Converter& converter = Converter()) {
1468 1475
      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
1469 1476
      _reader_bits::MapStorageBase<Edge>* forward_storage =
1470 1477
        new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter>
1471 1478
        (_graph, map, converter);
1472 1479
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
1473 1480
      _reader_bits::MapStorageBase<Edge>* backward_storage =
1474 1481
        new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter>
1475 1482
        (_graph, map, converter);
1476 1483
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
1477 1484
      return *this;
1478 1485
    }
1479 1486

	
1480 1487
    /// \brief Attribute reading rule
1481 1488
    ///
1482 1489
    /// Add an attribute reading rule to the reader.
1483 1490
    template <typename Value>
1484 1491
    GraphReader& attribute(const std::string& caption, Value& value) {
1485 1492
      _reader_bits::ValueStorageBase* storage =
1486 1493
        new _reader_bits::ValueStorage<Value>(value);
1487 1494
      _attributes.insert(std::make_pair(caption, storage));
1488 1495
      return *this;
1489 1496
    }
1490 1497

	
1491 1498
    /// \brief Attribute reading rule
1492 1499
    ///
1493 1500
    /// Add an attribute reading rule with specialized converter to the
1494 1501
    /// reader.
1495 1502
    template <typename Value, typename Converter>
1496 1503
    GraphReader& attribute(const std::string& caption, Value& value,
1497 1504
                             const Converter& converter = Converter()) {
1498 1505
      _reader_bits::ValueStorageBase* storage =
1499 1506
        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
1500 1507
      _attributes.insert(std::make_pair(caption, storage));
1501 1508
      return *this;
1502 1509
    }
1503 1510

	
1504 1511
    /// \brief Node reading rule
1505 1512
    ///
1506 1513
    /// Add a node reading rule to reader.
1507 1514
    GraphReader& node(const std::string& caption, Node& node) {
1508 1515
      typedef _reader_bits::MapLookUpConverter<Node> Converter;
1509 1516
      Converter converter(_node_index);
1510 1517
      _reader_bits::ValueStorageBase* storage =
1511 1518
        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
1512 1519
      _attributes.insert(std::make_pair(caption, storage));
1513 1520
      return *this;
1514 1521
    }
1515 1522

	
1516 1523
    /// \brief Edge reading rule
1517 1524
    ///
1518 1525
    /// Add an edge reading rule to reader.
1519 1526
    GraphReader& edge(const std::string& caption, Edge& edge) {
1520 1527
      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
1521 1528
      Converter converter(_edge_index);
1522 1529
      _reader_bits::ValueStorageBase* storage =
1523 1530
        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
1524 1531
      _attributes.insert(std::make_pair(caption, storage));
1525 1532
      return *this;
1526 1533
    }
1527 1534

	
1528 1535
    /// \brief Arc reading rule
1529 1536
    ///
1530 1537
    /// Add an arc reading rule to reader.
1531 1538
    GraphReader& arc(const std::string& caption, Arc& arc) {
1532 1539
      typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter;
1533 1540
      Converter converter(_graph, _edge_index);
1534 1541
      _reader_bits::ValueStorageBase* storage =
1535 1542
        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
1536 1543
      _attributes.insert(std::make_pair(caption, storage));
1537 1544
      return *this;
1538 1545
    }
1539 1546

	
1540 1547
    /// @}
1541 1548

	
1542 1549
    /// \name Select section by name
1543 1550
    /// @{
1544 1551

	
1545 1552
    /// \brief Set \c \@nodes section to be read
1546 1553
    ///
1547 1554
    /// Set \c \@nodes section to be read.
1548 1555
    GraphReader& nodes(const std::string& caption) {
1549 1556
      _nodes_caption = caption;
1550 1557
      return *this;
1551 1558
    }
1552 1559

	
1553 1560
    /// \brief Set \c \@edges section to be read
1554 1561
    ///
1555 1562
    /// Set \c \@edges section to be read.
1556 1563
    GraphReader& edges(const std::string& caption) {
1557 1564
      _edges_caption = caption;
1558 1565
      return *this;
1559 1566
    }
1560 1567

	
1561 1568
    /// \brief Set \c \@attributes section to be read
1562 1569
    ///
1563 1570
    /// Set \c \@attributes section to be read.
1564 1571
    GraphReader& attributes(const std::string& caption) {
1565 1572
      _attributes_caption = caption;
1566 1573
      return *this;
1567 1574
    }
1568 1575

	
1569 1576
    /// @}
1570 1577

	
1571 1578
    /// \name Using previously constructed node or edge set
1572 1579
    /// @{
1573 1580

	
1574 1581
    /// \brief Use previously constructed node set
1575 1582
    ///
1576 1583
    /// Use previously constructed node set, and specify the node
1577 1584
    /// label map.
1578 1585
    template <typename Map>
1579 1586
    GraphReader& useNodes(const Map& map) {
1580 1587
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1581 1588
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1582 1589
      _use_nodes = true;
1583 1590
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1584 1591
      for (NodeIt n(_graph); n != INVALID; ++n) {
1585 1592
        _node_index.insert(std::make_pair(converter(map[n]), n));
1586 1593
      }
1587 1594
      return *this;
1588 1595
    }
1589 1596

	
1590 1597
    /// \brief Use previously constructed node set
1591 1598
    ///
1592 1599
    /// Use previously constructed node set, and specify the node
1593 1600
    /// label map and a functor which converts the label map values to
1594 1601
    /// \c std::string.
1595 1602
    template <typename Map, typename Converter>
1596 1603
    GraphReader& useNodes(const Map& map,
1597 1604
                            const Converter& converter = Converter()) {
1598 1605
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1599 1606
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1600 1607
      _use_nodes = true;
1601 1608
      for (NodeIt n(_graph); n != INVALID; ++n) {
1602 1609
        _node_index.insert(std::make_pair(converter(map[n]), n));
1603 1610
      }
1604 1611
      return *this;
1605 1612
    }
1606 1613

	
1607 1614
    /// \brief Use previously constructed edge set
1608 1615
    ///
1609 1616
    /// Use previously constructed edge set, and specify the edge
1610 1617
    /// label map.
1611 1618
    template <typename Map>
1612 1619
    GraphReader& useEdges(const Map& map) {
1613 1620
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1614 1621
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1615 1622
      _use_edges = true;
1616 1623
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1617 1624
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1618 1625
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1619 1626
      }
1620 1627
      return *this;
1621 1628
    }
1622 1629

	
1623 1630
    /// \brief Use previously constructed edge set
1624 1631
    ///
1625 1632
    /// Use previously constructed edge set, and specify the edge
1626 1633
    /// label map and a functor which converts the label map values to
1627 1634
    /// \c std::string.
1628 1635
    template <typename Map, typename Converter>
1629 1636
    GraphReader& useEdges(const Map& map,
1630 1637
                            const Converter& converter = Converter()) {
1631 1638
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1632 1639
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1633 1640
      _use_edges = true;
1634 1641
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1635 1642
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1636 1643
      }
1637 1644
      return *this;
1638 1645
    }
1639 1646

	
1640 1647
    /// \brief Skip the reading of node section
1641 1648
    ///
1642 1649
    /// Omit the reading of the node section. This implies that each node
1643 1650
    /// map reading rule will be abandoned, and the nodes of the graph
1644 1651
    /// will not be constructed, which usually cause that the edge set
1645 1652
    /// could not be read due to lack of node name
1646 1653
    /// could not be read due to lack of node name resolving.
1647 1654
    /// Therefore \c skipEdges() function should also be used, or
1648 1655
    /// \c useNodes() should be used to specify the label of the nodes.
1649 1656
    GraphReader& skipNodes() {
1650 1657
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1651 1658
      _skip_nodes = true;
1652 1659
      return *this;
1653 1660
    }
1654 1661

	
1655 1662
    /// \brief Skip the reading of edge section
1656 1663
    ///
1657 1664
    /// Omit the reading of the edge section. This implies that each edge
1658 1665
    /// map reading rule will be abandoned, and the edges of the graph
1659 1666
    /// will not be constructed.
1660 1667
    GraphReader& skipEdges() {
1661 1668
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1662 1669
      _skip_edges = true;
1663 1670
      return *this;
1664 1671
    }
1665 1672

	
1666 1673
    /// @}
1667 1674

	
1668 1675
  private:
1669 1676

	
1670 1677
    bool readLine() {
1671 1678
      std::string str;
1672 1679
      while(++line_num, std::getline(*_is, str)) {
1673 1680
        line.clear(); line.str(str);
1674 1681
        char c;
1675 1682
        if (line >> std::ws >> c && c != '#') {
1676 1683
          line.putback(c);
1677 1684
          return true;
1678 1685
        }
1679 1686
      }
1680 1687
      return false;
1681 1688
    }
1682 1689

	
1683 1690
    bool readSuccess() {
1684 1691
      return static_cast<bool>(*_is);
1685 1692
    }
1686 1693

	
1687 1694
    void skipSection() {
1688 1695
      char c;
1689 1696
      while (readSuccess() && line >> c && c != '@') {
1690 1697
        readLine();
1691 1698
      }
1692 1699
      if (readSuccess()) {
1693 1700
        line.putback(c);
1694 1701
      }
1695 1702
    }
1696 1703

	
1697 1704
    void readNodes() {
1698 1705

	
1699 1706
      std::vector<int> map_index(_node_maps.size());
1700 1707
      int map_num, label_index;
1701 1708

	
1702 1709
      char c;
1703 1710
      if (!readLine() || !(line >> c) || c == '@') {
1704 1711
        if (readSuccess() && line) line.putback(c);
1705 1712
        if (!_node_maps.empty())
1706 1713
          throw FormatError("Cannot find map names");
1707 1714
        return;
1708 1715
      }
1709 1716
      line.putback(c);
1710 1717

	
1711 1718
      {
1712 1719
        std::map<std::string, int> maps;
1713 1720

	
1714 1721
        std::string map;
1715 1722
        int index = 0;
1716 1723
        while (_reader_bits::readToken(line, map)) {
1717 1724
          if (maps.find(map) != maps.end()) {
1718 1725
            std::ostringstream msg;
1719 1726
            msg << "Multiple occurence of node map: " << map;
1720 1727
            throw FormatError(msg.str());
1721 1728
          }
1722 1729
          maps.insert(std::make_pair(map, index));
1723 1730
          ++index;
1724 1731
        }
1725 1732

	
1726 1733
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1727 1734
          std::map<std::string, int>::iterator jt =
1728 1735
            maps.find(_node_maps[i].first);
1729 1736
          if (jt == maps.end()) {
1730 1737
            std::ostringstream msg;
1731 1738
            msg << "Map not found: " << _node_maps[i].first;
1732 1739
            throw FormatError(msg.str());
1733 1740
          }
1734 1741
          map_index[i] = jt->second;
1735 1742
        }
1736 1743

	
1737 1744
        {
1738 1745
          std::map<std::string, int>::iterator jt = maps.find("label");
1739 1746
          if (jt != maps.end()) {
1740 1747
            label_index = jt->second;
1741 1748
          } else {
1742 1749
            label_index = -1;
1743 1750
          }
1744 1751
        }
1745 1752
        map_num = maps.size();
1746 1753
      }
1747 1754

	
1748 1755
      while (readLine() && line >> c && c != '@') {
1749 1756
        line.putback(c);
1750 1757

	
1751 1758
        std::vector<std::string> tokens(map_num);
1752 1759
        for (int i = 0; i < map_num; ++i) {
1753 1760
          if (!_reader_bits::readToken(line, tokens[i])) {
1754 1761
            std::ostringstream msg;
1755 1762
            msg << "Column not found (" << i + 1 << ")";
1756 1763
            throw FormatError(msg.str());
1757 1764
          }
1758 1765
        }
1759 1766
        if (line >> std::ws >> c)
1760 1767
          throw FormatError("Extra character at the end of line");
1761 1768

	
1762 1769
        Node n;
1763 1770
        if (!_use_nodes) {
1764 1771
          n = _graph.addNode();
1765 1772
          if (label_index != -1)
1766 1773
            _node_index.insert(std::make_pair(tokens[label_index], n));
1767 1774
        } else {
1768 1775
          if (label_index == -1)
1769 1776
            throw FormatError("Label map not found");
1770 1777
          typename std::map<std::string, Node>::iterator it =
1771 1778
            _node_index.find(tokens[label_index]);
1772 1779
          if (it == _node_index.end()) {
1773 1780
            std::ostringstream msg;
1774 1781
            msg << "Node with label not found: " << tokens[label_index];
1775 1782
            throw FormatError(msg.str());
1776 1783
          }
1777 1784
          n = it->second;
1778 1785
        }
1779 1786

	
1780 1787
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1781 1788
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1782 1789
        }
1783 1790

	
1784 1791
      }
1785 1792
      if (readSuccess()) {
1786 1793
        line.putback(c);
1787 1794
      }
1788 1795
    }
1789 1796

	
1790 1797
    void readEdges() {
1791 1798

	
1792 1799
      std::vector<int> map_index(_edge_maps.size());
1793 1800
      int map_num, label_index;
1794 1801

	
1795 1802
      char c;
1796 1803
      if (!readLine() || !(line >> c) || c == '@') {
1797 1804
        if (readSuccess() && line) line.putback(c);
1798 1805
        if (!_edge_maps.empty())
1799 1806
          throw FormatError("Cannot find map names");
1800 1807
        return;
1801 1808
      }
1802 1809
      line.putback(c);
1803 1810

	
1804 1811
      {
1805 1812
        std::map<std::string, int> maps;
1806 1813

	
1807 1814
        std::string map;
1808 1815
        int index = 0;
1809 1816
        while (_reader_bits::readToken(line, map)) {
1817
          if(map == "-") {
1818
              if(index!=0)
1819
                throw FormatError("'-' is not allowed as a map name");
1820
              else if (line >> std::ws >> c)
1821
                throw FormatError("Extra character at the end of line");
1822
              else break;
1823
            }
1810 1824
          if (maps.find(map) != maps.end()) {
1811 1825
            std::ostringstream msg;
1812 1826
            msg << "Multiple occurence of edge map: " << map;
1813 1827
            throw FormatError(msg.str());
1814 1828
          }
1815 1829
          maps.insert(std::make_pair(map, index));
1816 1830
          ++index;
1817 1831
        }
1818 1832

	
1819 1833
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1820 1834
          std::map<std::string, int>::iterator jt =
1821 1835
            maps.find(_edge_maps[i].first);
1822 1836
          if (jt == maps.end()) {
1823 1837
            std::ostringstream msg;
1824 1838
            msg << "Map not found: " << _edge_maps[i].first;
1825 1839
            throw FormatError(msg.str());
1826 1840
          }
1827 1841
          map_index[i] = jt->second;
1828 1842
        }
1829 1843

	
1830 1844
        {
1831 1845
          std::map<std::string, int>::iterator jt = maps.find("label");
1832 1846
          if (jt != maps.end()) {
1833 1847
            label_index = jt->second;
1834 1848
          } else {
1835 1849
            label_index = -1;
1836 1850
          }
1837 1851
        }
1838 1852
        map_num = maps.size();
1839 1853
      }
1840 1854

	
1841 1855
      while (readLine() && line >> c && c != '@') {
1842 1856
        line.putback(c);
1843 1857

	
1844 1858
        std::string source_token;
1845 1859
        std::string target_token;
1846 1860

	
1847 1861
        if (!_reader_bits::readToken(line, source_token))
1848 1862
          throw FormatError("Node u not found");
1849 1863

	
1850 1864
        if (!_reader_bits::readToken(line, target_token))
1851 1865
          throw FormatError("Node v not found");
1852 1866

	
1853 1867
        std::vector<std::string> tokens(map_num);
1854 1868
        for (int i = 0; i < map_num; ++i) {
1855 1869
          if (!_reader_bits::readToken(line, tokens[i])) {
1856 1870
            std::ostringstream msg;
1857 1871
            msg << "Column not found (" << i + 1 << ")";
1858 1872
            throw FormatError(msg.str());
1859 1873
          }
1860 1874
        }
1861 1875
        if (line >> std::ws >> c)
1862 1876
          throw FormatError("Extra character at the end of line");
1863 1877

	
1864 1878
        Edge e;
1865 1879
        if (!_use_edges) {
1866 1880

	
1867 1881
          typename NodeIndex::iterator it;
1868 1882

	
1869 1883
          it = _node_index.find(source_token);
1870 1884
          if (it == _node_index.end()) {
1871 1885
            std::ostringstream msg;
1872 1886
            msg << "Item not found: " << source_token;
1873 1887
            throw FormatError(msg.str());
1874 1888
          }
1875 1889
          Node source = it->second;
1876 1890

	
1877 1891
          it = _node_index.find(target_token);
1878 1892
          if (it == _node_index.end()) {
1879 1893
            std::ostringstream msg;
1880 1894
            msg << "Item not found: " << target_token;
1881 1895
            throw FormatError(msg.str());
1882 1896
          }
1883 1897
          Node target = it->second;
1884 1898

	
1885 1899
          e = _graph.addEdge(source, target);
1886 1900
          if (label_index != -1)
1887 1901
            _edge_index.insert(std::make_pair(tokens[label_index], e));
1888 1902
        } else {
1889 1903
          if (label_index == -1)
1890 1904
            throw FormatError("Label map not found");
1891 1905
          typename std::map<std::string, Edge>::iterator it =
1892 1906
            _edge_index.find(tokens[label_index]);
1893 1907
          if (it == _edge_index.end()) {
1894 1908
            std::ostringstream msg;
1895 1909
            msg << "Edge with label not found: " << tokens[label_index];
1896 1910
            throw FormatError(msg.str());
1897 1911
          }
1898 1912
          e = it->second;
1899 1913
        }
1900 1914

	
1901 1915
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1902 1916
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1903 1917
        }
1904 1918

	
1905 1919
      }
1906 1920
      if (readSuccess()) {
1907 1921
        line.putback(c);
1908 1922
      }
1909 1923
    }
1910 1924

	
1911 1925
    void readAttributes() {
1912 1926

	
1913 1927
      std::set<std::string> read_attr;
1914 1928

	
1915 1929
      char c;
1916 1930
      while (readLine() && line >> c && c != '@') {
1917 1931
        line.putback(c);
1918 1932

	
1919 1933
        std::string attr, token;
1920 1934
        if (!_reader_bits::readToken(line, attr))
1921 1935
          throw FormatError("Attribute name not found");
1922 1936
        if (!_reader_bits::readToken(line, token))
1923 1937
          throw FormatError("Attribute value not found");
1924 1938
        if (line >> c)
1925 1939
          throw FormatError("Extra character at the end of line");
1926 1940

	
1927 1941
        {
1928 1942
          std::set<std::string>::iterator it = read_attr.find(attr);
1929 1943
          if (it != read_attr.end()) {
1930 1944
            std::ostringstream msg;
1931 1945
            msg << "Multiple occurence of attribute: " << attr;
1932 1946
            throw FormatError(msg.str());
1933 1947
          }
1934 1948
          read_attr.insert(attr);
1935 1949
        }
1936 1950

	
1937 1951
        {
1938 1952
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1939 1953
          while (it != _attributes.end() && it->first == attr) {
1940 1954
            it->second->set(token);
1941 1955
            ++it;
1942 1956
          }
1943 1957
        }
1944 1958

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

	
1959 1973
  public:
1960 1974

	
1961 1975
    /// \name Execution of the reader
1962 1976
    /// @{
1963 1977

	
1964 1978
    /// \brief Start the batch processing
1965 1979
    ///
1966 1980
    /// This function starts the batch processing
1967 1981
    void run() {
1968 1982

	
1969 1983
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1970 1984

	
1971 1985
      bool nodes_done = _skip_nodes;
1972 1986
      bool edges_done = _skip_edges;
1973 1987
      bool attributes_done = false;
1974 1988

	
1975 1989
      line_num = 0;
1976 1990
      readLine();
1977 1991
      skipSection();
1978 1992

	
1979 1993
      while (readSuccess()) {
1980 1994
        try {
1981 1995
          char c;
1982 1996
          std::string section, caption;
1983 1997
          line >> c;
1984 1998
          _reader_bits::readToken(line, section);
1985 1999
          _reader_bits::readToken(line, caption);
1986 2000

	
1987 2001
          if (line >> c)
1988 2002
            throw FormatError("Extra character at the end of line");
1989 2003

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

	
2017 2031
      if (!nodes_done) {
2018 2032
        throw FormatError("Section @nodes not found");
2019 2033
      }
2020 2034

	
2021 2035
      if (!edges_done) {
2022 2036
        throw FormatError("Section @edges not found");
2023 2037
      }
2024 2038

	
2025 2039
      if (!attributes_done && !_attributes.empty()) {
2026 2040
        throw FormatError("Section @attributes not found");
2027 2041
      }
2028 2042

	
2029 2043
    }
2030 2044

	
2031 2045
    /// @}
2032 2046

	
2033 2047
  };
2034 2048

	
2035 2049
  /// \brief Return a \ref GraphReader class
2036 2050
  ///
2037 2051
  /// This function just returns a \ref GraphReader class.
2038 2052
  /// \relates GraphReader
2039 2053
  template <typename Graph>
2040 2054
  GraphReader<Graph> graphReader(Graph& graph, std::istream& is) {
2041 2055
    GraphReader<Graph> tmp(graph, is);
2042 2056
    return tmp;
2043 2057
  }
2044 2058

	
2045 2059
  /// \brief Return a \ref GraphReader class
2046 2060
  ///
2047 2061
  /// This function just returns a \ref GraphReader class.
2048 2062
  /// \relates GraphReader
2049 2063
  template <typename Graph>
2050 2064
  GraphReader<Graph> graphReader(Graph& graph, const std::string& fn) {
2051 2065
    GraphReader<Graph> tmp(graph, fn);
2052 2066
    return tmp;
2053 2067
  }
2054 2068

	
2055 2069
  /// \brief Return a \ref GraphReader class
2056 2070
  ///
2057 2071
  /// This function just returns a \ref GraphReader class.
2058 2072
  /// \relates GraphReader
2059 2073
  template <typename Graph>
2060 2074
  GraphReader<Graph> graphReader(Graph& graph, const char* fn) {
2061 2075
    GraphReader<Graph> tmp(graph, fn);
2062 2076
    return tmp;
2063 2077
  }
2064 2078

	
2065 2079
  class SectionReader;
2066 2080

	
2067 2081
  SectionReader sectionReader(std::istream& is);
2068 2082
  SectionReader sectionReader(const std::string& fn);
2069 2083
  SectionReader sectionReader(const char* fn);
2070 2084

	
2071 2085
  /// \ingroup lemon_io
2072 2086
  ///
2073 2087
  /// \brief Section reader class
2074 2088
  ///
2075 2089
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
2076 2090
  /// which contain any data in arbitrary format. Such sections can be
2077 2091
  /// read with this class. A reading rule can be added to the class
2078 2092
  /// with two different functions. With the \c sectionLines() function a
2079 2093
  /// functor can process the section line-by-line, while with the \c
2080 2094
  /// sectionStream() member the section can be read from an input
2081 2095
  /// stream.
2082 2096
  class SectionReader {
2083 2097
  private:
2084 2098

	
2085 2099
    std::istream* _is;
2086 2100
    bool local_is;
2087 2101
    std::string _filename;
2088 2102

	
2089 2103
    typedef std::map<std::string, _reader_bits::Section*> Sections;
2090 2104
    Sections _sections;
2091 2105

	
2092 2106
    int line_num;
2093 2107
    std::istringstream line;
2094 2108

	
2095 2109
  public:
2096 2110

	
2097 2111
    /// \brief Constructor
2098 2112
    ///
2099 2113
    /// Construct a section reader, which reads from the given input
2100 2114
    /// stream.
2101 2115
    SectionReader(std::istream& is)
2102 2116
      : _is(&is), local_is(false) {}
2103 2117

	
2104 2118
    /// \brief Constructor
2105 2119
    ///
2106 2120
    /// Construct a section reader, which reads from the given file.
2107 2121
    SectionReader(const std::string& fn)
2108 2122
      : _is(new std::ifstream(fn.c_str())), local_is(true),
2109 2123
        _filename(fn) {
2110 2124
      if (!(*_is)) {
2111 2125
        delete _is;
2112 2126
        throw IoError("Cannot open file", fn);
2113 2127
      }
2114 2128
    }
2115 2129

	
2116 2130
    /// \brief Constructor
2117 2131
    ///
2118 2132
    /// Construct a section reader, which reads from the given file.
2119 2133
    SectionReader(const char* fn)
2120 2134
      : _is(new std::ifstream(fn)), local_is(true),
2121 2135
        _filename(fn) {
2122 2136
      if (!(*_is)) {
2123 2137
        delete _is;
2124 2138
        throw IoError("Cannot open file", fn);
2125 2139
      }
2126 2140
    }
2127 2141

	
2128 2142
    /// \brief Destructor
2129 2143
    ~SectionReader() {
2130 2144
      for (Sections::iterator it = _sections.begin();
2131 2145
           it != _sections.end(); ++it) {
2132 2146
        delete it->second;
2133 2147
      }
2134 2148

	
2135 2149
      if (local_is) {
2136 2150
        delete _is;
2137 2151
      }
2138 2152

	
2139 2153
    }
2140 2154

	
2141 2155
  private:
2142 2156

	
2143 2157
    friend SectionReader sectionReader(std::istream& is);
2144 2158
    friend SectionReader sectionReader(const std::string& fn);
2145 2159
    friend SectionReader sectionReader(const char* fn);
2146 2160

	
2147 2161
    SectionReader(SectionReader& other)
2148 2162
      : _is(other._is), local_is(other.local_is) {
2149 2163

	
2150 2164
      other._is = 0;
2151 2165
      other.local_is = false;
2152 2166

	
2153 2167
      _sections.swap(other._sections);
2154 2168
    }
2155 2169

	
2156 2170
    SectionReader& operator=(const SectionReader&);
2157 2171

	
2158 2172
  public:
2159 2173

	
2160 2174
    /// \name Section readers
2161 2175
    /// @{
2162 2176

	
2163 2177
    /// \brief Add a section processor with line oriented reading
2164 2178
    ///
2165 2179
    /// The first parameter is the type descriptor of the section, the
2166 2180
    /// second is a functor, which takes just one \c std::string
2167 2181
    /// parameter. At the reading process, each line of the section
2168 2182
    /// will be given to the functor object. However, the empty lines
2169 2183
    /// and the comment lines are filtered out, and the leading
2170 2184
    /// whitespaces are trimmed from each processed string.
2171 2185
    ///
2172 2186
    /// For example let's see a section, which contain several
2173 2187
    /// integers, which should be inserted into a vector.
2174 2188
    ///\code
2175 2189
    ///  @numbers
2176 2190
    ///  12 45 23
2177 2191
    ///  4
2178 2192
    ///  23 6
2179 2193
    ///\endcode
2180 2194
    ///
2181 2195
    /// The functor is implemented as a struct:
2182 2196
    ///\code
2183 2197
    ///  struct NumberSection {
2184 2198
    ///    std::vector<int>& _data;
2185 2199
    ///    NumberSection(std::vector<int>& data) : _data(data) {}
2186 2200
    ///    void operator()(const std::string& line) {
2187 2201
    ///      std::istringstream ls(line);
2188 2202
    ///      int value;
2189 2203
    ///      while (ls >> value) _data.push_back(value);
2190 2204
    ///    }
2191 2205
    ///  };
2192 2206
    ///
2193 2207
    ///  // ...
Ignore white space 768 line context
1 1
INCLUDE_DIRECTORIES(
2 2
  ${CMAKE_SOURCE_DIR}
3 3
  ${PROJECT_BINARY_DIR}
4 4
)
5 5

	
6 6
LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/lemon)
7 7

	
8 8
SET(TESTS
9 9
  bfs_test
10 10
  counter_test
11 11
  dfs_test
12 12
  digraph_test
13 13
  dijkstra_test
14 14
  dim_test
15 15
  error_test
16 16
  graph_copy_test
17 17
  graph_test
18 18
  graph_utils_test
19 19
  heap_test
20 20
  kruskal_test
21
  lgf_test
21 22
  maps_test
22 23
  random_test
23 24
  path_test
24 25
  time_measure_test
25 26
  unionfind_test)
26 27

	
27 28
FOREACH(TEST_NAME ${TESTS})
28 29
  ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.cc)
29 30
  TARGET_LINK_LIBRARIES(${TEST_NAME} lemon)
30 31
  ADD_TEST(${TEST_NAME} ${TEST_NAME})
31 32
ENDFOREACH(TEST_NAME)
Ignore white space 768 line context
1 1
EXTRA_DIST += \
2 2
	test/CMakeLists.txt
3 3

	
4 4
noinst_HEADERS += \
5 5
	test/graph_test.h \
6 6
        test/test_tools.h
7 7

	
8 8
check_PROGRAMS += \
9 9
	test/bfs_test \
10 10
        test/counter_test \
11 11
	test/dfs_test \
12 12
	test/digraph_test \
13 13
	test/dijkstra_test \
14 14
        test/dim_test \
15 15
	test/error_test \
16 16
	test/graph_copy_test \
17 17
	test/graph_test \
18 18
	test/graph_utils_test \
19 19
	test/heap_test \
20 20
	test/kruskal_test \
21
	test/lgf_test \
21 22
        test/maps_test \
22 23
        test/random_test \
23 24
        test/path_test \
24 25
        test/test_tools_fail \
25 26
        test/test_tools_pass \
26 27
        test/time_measure_test \
27 28
	test/unionfind_test
28 29

	
29 30
TESTS += $(check_PROGRAMS)
30 31
XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
31 32

	
32 33
test_bfs_test_SOURCES = test/bfs_test.cc
33 34
test_counter_test_SOURCES = test/counter_test.cc
34 35
test_dfs_test_SOURCES = test/dfs_test.cc
35 36
test_digraph_test_SOURCES = test/digraph_test.cc
36 37
test_dijkstra_test_SOURCES = test/dijkstra_test.cc
37 38
test_dim_test_SOURCES = test/dim_test.cc
38 39
test_error_test_SOURCES = test/error_test.cc
39 40
test_graph_copy_test_SOURCES = test/graph_copy_test.cc
40 41
test_graph_test_SOURCES = test/graph_test.cc
41 42
test_graph_utils_test_SOURCES = test/graph_utils_test.cc
42 43
test_heap_test_SOURCES = test/heap_test.cc
43 44
test_kruskal_test_SOURCES = test/kruskal_test.cc
45
test_lgf_test_SOURCES = test/lgf_test.cc
44 46
test_maps_test_SOURCES = test/maps_test.cc
45 47
test_path_test_SOURCES = test/path_test.cc
46 48
test_random_test_SOURCES = test/random_test.cc
47 49
test_test_tools_fail_SOURCES = test/test_tools_fail.cc
48 50
test_test_tools_pass_SOURCES = test/test_tools_pass.cc
49 51
test_time_measure_test_SOURCES = test/time_measure_test.cc
50 52
test_unionfind_test_SOURCES = test/unionfind_test.cc
0 comments (0 inline)