gravatar
deba@inf.elte.hu
deba@inf.elte.hu
Bug fixes and improvements in LGF IO
0 2 0
default
2 files changed with 33 insertions and 23 deletions:
↑ Collapse diff ↑
Show white space 96 line context
... ...
@@ -422,97 +422,97 @@
422 422

	
423 423
    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> 
424 424
      Attributes;
425 425
    Attributes _attributes;
426 426

	
427 427
    typedef std::map<std::string, _reader_bits::Section*> Sections;
428 428
    Sections _sections;
429 429

	
430 430
    bool _use_nodes;
431 431
    bool _use_arcs;
432 432

	
433 433
    int line_num;
434 434
    std::istringstream line;
435 435

	
436 436
  public:
437 437

	
438 438
    /// \brief Constructor
439 439
    ///
440 440
    /// Construct a directed graph reader, which reads from the given
441 441
    /// input stream.
442 442
    DigraphReader(std::istream& is, Digraph& digraph) 
443 443
      : _is(&is), local_is(false), _digraph(digraph),
444 444
	_use_nodes(false), _use_arcs(false) {}
445 445

	
446 446
    /// \brief Constructor
447 447
    ///
448 448
    /// Construct a directed graph reader, which reads from the given
449 449
    /// file.
450 450
    DigraphReader(const std::string& fn, Digraph& digraph) 
451 451
      : _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph),
452 452
    	_use_nodes(false), _use_arcs(false) {}
453 453
    
454 454
    /// \brief Constructor
455 455
    ///
456 456
    /// Construct a directed graph reader, which reads from the given
457 457
    /// file.
458 458
    DigraphReader(const char* fn, Digraph& digraph) 
459 459
      : _is(new std::ifstream(fn)), local_is(true), _digraph(digraph),
460 460
    	_use_nodes(false), _use_arcs(false) {}
461 461

	
462 462
    /// \brief Copy constructor
463 463
    ///
464 464
    /// The copy constructor transfers all data from the other reader,
465 465
    /// therefore the copied reader will not be usable more. 
466 466
    DigraphReader(DigraphReader& other) 
467 467
      : _is(other._is), local_is(other.local_is), _digraph(other._digraph),
468 468
	_use_nodes(other._use_nodes), _use_arcs(other._use_arcs) {
469 469

	
470
      other.is = 0;
470
      other._is = 0;
471 471
      other.local_is = false;
472 472
      
473 473
      _node_index.swap(other._node_index);
474 474
      _arc_index.swap(other._arc_index);
475 475

	
476 476
      _node_maps.swap(other._node_maps);
477 477
      _arc_maps.swap(other._arc_maps);
478 478
      _attributes.swap(other._attributes);
479 479

	
480 480
      _nodes_caption = other._nodes_caption;
481 481
      _arcs_caption = other._arcs_caption;
482 482
      _attributes_caption = other._attributes_caption;
483 483

	
484 484
      _sections.swap(other._sections);
485 485
    }
486 486

	
487 487
    /// \brief Destructor
488 488
    ~DigraphReader() {
489 489
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
490 490
	   it != _node_maps.end(); ++it) {
491 491
	delete it->second;
492 492
      }
493 493

	
494 494
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
495 495
	   it != _arc_maps.end(); ++it) {
496 496
	delete it->second;
497 497
      }
498 498

	
499 499
      for (typename Attributes::iterator it = _attributes.begin(); 
500 500
	   it != _attributes.end(); ++it) {
501 501
	delete it->second;
502 502
      }
503 503

	
504 504
      for (typename Sections::iterator it = _sections.begin(); 
505 505
	   it != _sections.end(); ++it) {
506 506
	delete it->second;
507 507
      }
508 508

	
509 509
      if (local_is) {
510 510
	delete _is;
511 511
      }
512 512

	
513 513
    }
514 514

	
515 515
  private:
516 516
    
517 517
    DigraphReader& operator=(const DigraphReader&);
518 518

	
... ...
@@ -1033,148 +1033,153 @@
1033 1033
	if (!_reader_bits::readToken(line, attr))
1034 1034
	  throw DataFormatError("Attribute name not found");
1035 1035
	if (!_reader_bits::readToken(line, token))
1036 1036
	  throw DataFormatError("Attribute value not found");
1037 1037
	if (line >> c)
1038 1038
	  throw DataFormatError("Extra character on the end of line");	  
1039 1039

	
1040 1040
	{
1041 1041
	  std::set<std::string>::iterator it = read_attr.find(attr);
1042 1042
	  if (it != read_attr.end()) {
1043 1043
	    std::ostringstream msg;
1044 1044
	    msg << "Multiple occurence of attribute " << attr;
1045 1045
	    throw DataFormatError(msg.str().c_str());
1046 1046
	  }
1047 1047
	  read_attr.insert(attr);
1048 1048
	}
1049 1049
	
1050 1050
	{
1051 1051
	  typename Attributes::iterator it = _attributes.lower_bound(attr);
1052 1052
	  while (it != _attributes.end() && it->first == attr) {
1053 1053
	    it->second->set(token);
1054 1054
	    ++it;
1055 1055
	  }
1056 1056
	}
1057 1057

	
1058 1058
      }
1059 1059
      if (readSuccess()) {
1060 1060
	line.putback(c);
1061 1061
      }
1062 1062
      for (typename Attributes::iterator it = _attributes.begin();
1063 1063
	   it != _attributes.end(); ++it) {
1064 1064
	if (read_attr.find(it->first) == read_attr.end()) {
1065 1065
	  std::ostringstream msg;
1066 1066
	  msg << "Attribute not found in file: " << it->first;
1067 1067
	  throw DataFormatError(msg.str().c_str());
1068 1068
	}	
1069 1069
      }
1070 1070
    }
1071 1071

	
1072 1072
  public:
1073 1073

	
1074 1074
    /// \name Execution of the reader    
1075 1075
    /// @{
1076 1076

	
1077 1077
    /// \brief Start the batch processing
1078 1078
    ///
1079 1079
    /// This function starts the batch processing
1080 1080
    void run() {
1081
      
1082 1081
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1082
      if (!*_is) {
1083
	throw DataFormatError("Cannot find file");
1084
      }
1083 1085
      
1084 1086
      bool nodes_done = false;
1085 1087
      bool arcs_done = false;
1086 1088
      bool attributes_done = false;
1087 1089
      std::set<std::string> extra_sections;
1088 1090

	
1089 1091
      line_num = 0;      
1090 1092
      readLine();
1091 1093

	
1092 1094
      while (readSuccess()) {
1093 1095
	skipSection();
1094 1096
	try {
1095 1097
	  char c;
1096 1098
	  std::string section, caption;
1097 1099
	  line >> c;
1098 1100
	  _reader_bits::readToken(line, section);
1099 1101
	  _reader_bits::readToken(line, caption);
1100 1102

	
1101 1103
	  if (line >> c) 
1102 1104
	    throw DataFormatError("Extra character on the end of line");
1103 1105

	
1104 1106
	  if (section == "nodes" && !nodes_done) {
1105 1107
	    if (_nodes_caption.empty() || _nodes_caption == caption) {
1106 1108
	      readNodes();
1107 1109
	      nodes_done = true;
1108 1110
	    }
1109 1111
	  } else if ((section == "arcs" || section == "edges") && 
1110 1112
		     !arcs_done) {
1111 1113
	    if (_arcs_caption.empty() || _arcs_caption == caption) {
1112 1114
	      readArcs();
1113 1115
	      arcs_done = true;
1114 1116
	    }
1115 1117
	  } else if (section == "attributes" && !attributes_done) {
1116 1118
	    if (_attributes_caption.empty() || _attributes_caption == caption) {
1117 1119
	      readAttributes();
1118 1120
	      attributes_done = true;
1119 1121
	    }
1120 1122
	  } else {
1121 1123
	    if (extra_sections.find(section) != extra_sections.end()) {
1122 1124
	      std::ostringstream msg;
1123 1125
	      msg << "Multiple occurence of section " << section;
1124 1126
	      throw DataFormatError(msg.str().c_str());
1125 1127
	    }
1126 1128
	    Sections::iterator it = _sections.find(section);
1127 1129
	    if (it != _sections.end()) {
1128 1130
	      extra_sections.insert(section);
1129 1131
	      it->second->process(*_is, line_num);
1130 1132
	      readLine();
1131 1133
	    } else {
1132 1134
	      readLine();
1133 1135
	      skipSection();
1134 1136
	    }
1135 1137
	  }
1136 1138
	} catch (DataFormatError& error) {
1137 1139
	  error.line(line_num);
1138 1140
	  throw;
1139 1141
	}	
1140 1142
      }
1141 1143

	
1142 1144
      if (!nodes_done) {
1143 1145
	throw DataFormatError("Section @nodes not found");
1144 1146
      }
1145 1147

	
1146 1148
      if (!arcs_done) {
1147 1149
	throw DataFormatError("Section @arcs not found");
1148 1150
      }
1149 1151

	
1150 1152
      if (!attributes_done && !_attributes.empty()) {
1151 1153
	throw DataFormatError("Section @attributes not found");
1152 1154
      }
1153 1155

	
1154 1156
    }
1155 1157

	
1156 1158
    /// @}
1157 1159
    
1158 1160
  };
1159 1161

	
1160 1162
  /// \relates DigraphReader
1161 1163
  template <typename Digraph>
1162 1164
  DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
1163
    return DigraphReader<Digraph>(is, digraph);
1165
    DigraphReader<Digraph> tmp(is, digraph);
1166
    return tmp;
1164 1167
  }
1165 1168

	
1166 1169
  /// \relates DigraphReader
1167 1170
  template <typename Digraph>
1168 1171
  DigraphReader<Digraph> digraphReader(const std::string& fn, 
1169 1172
				       Digraph& digraph) {
1170
    return DigraphReader<Digraph>(fn, digraph);
1173
    DigraphReader<Digraph> tmp(fn, digraph);
1174
    return tmp;
1171 1175
  }
1172 1176

	
1173 1177
  /// \relates DigraphReader
1174 1178
  template <typename Digraph>
1175 1179
  DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
1176
    return DigraphReader<Digraph>(fn, digraph);
1180
    DigraphReader<Digraph> tmp(fn, digraph);
1181
    return tmp;
1177 1182
  }
1178 1183
}
1179 1184

	
1180 1185
#endif
Show white space 96 line context
... ...
@@ -150,251 +150,253 @@
150 150
	if (it == _map.end()) {
151 151
	  throw DataFormatError("Item not found");
152 152
	}
153 153
	return it->second;
154 154
      }
155 155
    };
156 156

	
157 157
    bool isWhiteSpace(char c) {
158 158
      return c == ' ' || c == '\t' || c == '\v' || 
159 159
        c == '\n' || c == '\r' || c == '\f'; 
160 160
    }
161 161

	
162 162
    bool isEscaped(char c) {
163 163
      return c == '\\' || c == '\"' || c == '\'' || 
164 164
	c == '\a' || c == '\b';
165 165
    }
166 166

	
167 167
    static void writeEscape(std::ostream& os, char c) {
168 168
      switch (c) {
169 169
      case '\\':
170 170
	os << "\\\\";
171 171
	return;
172 172
      case '\"':
173 173
	os << "\\\"";
174 174
	return;
175 175
      case '\a':
176 176
	os << "\\a";
177 177
	return;
178 178
      case '\b':
179 179
	os << "\\b";
180 180
	return;
181 181
      case '\f':
182 182
	os << "\\f";
183 183
	return;
184 184
      case '\r':
185 185
	os << "\\r";
186 186
	return;
187 187
      case '\n':
188 188
	os << "\\n";
189 189
	return;
190 190
      case '\t':
191 191
	os << "\\t";
192 192
	return;
193 193
      case '\v':
194 194
	os << "\\v";
195 195
	return;
196 196
      default:
197 197
	if (c < 0x20) {
198
	  std::ios::fmtflags flags = os.flags();
198 199
	  os << '\\' << std::oct << static_cast<int>(c);
200
	  os.flags(flags);
199 201
	} else {
200 202
	  os << c;
201 203
	}
202 204
	return;
203 205
      }     
204 206
    }
205 207

	
206 208
    bool requireEscape(const std::string& str) {
207 209
      if (str.empty() || str[0] == '@') return true;
208 210
      std::istringstream is(str);
209 211
      char c;
210 212
      while (is.get(c)) {
211 213
	if (isWhiteSpace(c) || isEscaped(c)) {
212 214
	  return true;
213 215
	}
214 216
      }
215 217
      return false;
216 218
    }
217 219
    
218 220
    std::ostream& writeToken(std::ostream& os, const std::string& str) {
219 221

	
220 222
      if (requireEscape(str)) {
221 223
	os << '\"';
222 224
	for (std::string::const_iterator it = str.begin(); 
223 225
	     it != str.end(); ++it) {
224 226
	  writeEscape(os, *it);
225 227
	}	
226 228
	os << '\"';
227 229
      } else {
228 230
	os << str;
229 231
      }
230 232
      return os;
231 233
    }
232 234

	
233 235
  }
234 236
  
235 237
  /// \ingroup lemon_io
236 238
  ///  
237 239
  /// \brief LGF writer for directed graphs
238 240
  ///
239 241
  /// This utility writes an \ref lgf-format "LGF" file.
240 242
  ///
241 243
  /// The writing method does a batch processing. The user creates a
242 244
  /// writer object, then various writing rules can be added to the
243 245
  /// writer, and eventually the writing is executed with the \c run()
244 246
  /// member function. A map writing rule can be added to the writer
245 247
  /// with the \c nodeMap() or \c arcMap() members. An optional
246
  /// converter parameter can also be added as a standard functor converting from
247
  /// the value type of the map to std::string. If it is set, it will
248
  /// determine how the map's value type is written to the output
249
  /// stream. If the functor is not set, then a default conversion
250
  /// will be used. The \c attribute(), \c node() and \c arc() functions
251
  /// are used to add attribute writing rules.
248
  /// converter parameter can also be added as a standard functor
249
  /// converting from the value type of the map to std::string. If it
250
  /// is set, it will determine how the map's value type is written to
251
  /// the output stream. If the functor is not set, then a default
252
  /// conversion will be used. The \c attribute(), \c node() and \c
253
  /// arc() functions are used to add attribute writing rules.
252 254
  ///
253 255
  ///\code
254 256
  ///     DigraphWriter<Digraph>(std::cout, digraph).
255 257
  ///       nodeMap("coordinates", coord_map).
256 258
  ///       nodeMap("size", size).
257 259
  ///       nodeMap("title", title).
258 260
  ///       arcMap("capacity", cap_map).
259 261
  ///       node("source", src).
260 262
  ///       node("target", trg).
261 263
  ///       attribute("caption", caption).
262 264
  ///       run();
263 265
  ///\endcode
264 266
  ///
265 267
  ///
266 268
  /// By default, the writer does not write additional captions to the
267 269
  /// sections, but they can be give as an optional parameter of
268 270
  /// the \c nodes(), \c arcs() or \c
269 271
  /// attributes() functions.
270 272
  ///
271 273
  /// The \c skipNodes() and \c skipArcs() functions forbid the
272
  /// writing of the sections. If two arc sections should be written to the
273
  /// output, it can be done in two passes, the first pass writes the
274
  /// node section and the first arc section, then the second pass
275
  /// skips the node section and writes just the arc section to the
276
  /// stream. The output stream can be retrieved with the \c ostream()
277
  /// function, hence the second pass can append its output to the output of the
278
  /// first pass.
274
  /// writing of the sections. If two arc sections should be written
275
  /// to the output, it can be done in two passes, the first pass
276
  /// writes the node section and the first arc section, then the
277
  /// second pass skips the node section and writes just the arc
278
  /// section to the stream. The output stream can be retrieved with
279
  /// the \c ostream() function, hence the second pass can append its
280
  /// output to the output of the first pass.
279 281
  template <typename _Digraph>
280 282
  class DigraphWriter {
281 283
  public:
282 284

	
283 285
    typedef _Digraph Digraph;
284 286
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
285 287
    
286 288
  private:
287 289

	
288 290

	
289 291
    std::ostream* _os;
290 292
    bool local_os;
291 293

	
292 294
    Digraph& _digraph;
293 295

	
294 296
    std::string _nodes_caption;
295 297
    std::string _arcs_caption;
296 298
    std::string _attributes_caption;
297 299
    
298 300
    typedef std::map<Node, std::string> NodeIndex;
299 301
    NodeIndex _node_index;
300 302
    typedef std::map<Arc, std::string> ArcIndex;
301 303
    ArcIndex _arc_index;
302 304

	
303 305
    typedef std::vector<std::pair<std::string, 
304 306
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;    
305 307
    NodeMaps _node_maps; 
306 308

	
307 309
    typedef std::vector<std::pair<std::string, 
308 310
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
309 311
    ArcMaps _arc_maps;
310 312

	
311 313
    typedef std::vector<std::pair<std::string, 
312 314
      _writer_bits::ValueStorageBase*> > Attributes;
313 315
    Attributes _attributes;
314 316

	
315 317
    bool _skip_nodes;
316 318
    bool _skip_arcs;
317 319

	
318 320
  public:
319 321

	
320 322
    /// \brief Constructor
321 323
    ///
322 324
    /// Construct a directed graph writer, which writes to the given
323 325
    /// output stream.
324 326
    DigraphWriter(std::ostream& is, Digraph& digraph) 
325 327
      : _os(&is), local_os(false), _digraph(digraph),
326 328
	_skip_nodes(false), _skip_arcs(false) {}
327 329

	
328 330
    /// \brief Constructor
329 331
    ///
330 332
    /// Construct a directed graph writer, which writes to the given
331 333
    /// output file.
332 334
    DigraphWriter(const std::string& fn, Digraph& digraph) 
333 335
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
334 336
	_skip_nodes(false), _skip_arcs(false) {}
335 337

	
336 338
    /// \brief Constructor
337 339
    ///
338 340
    /// Construct a directed graph writer, which writes to the given
339 341
    /// output file.
340 342
    DigraphWriter(const char* fn, Digraph& digraph) 
341 343
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
342 344
	_skip_nodes(false), _skip_arcs(false) {}
343 345

	
344 346
    /// \brief Copy constructor
345 347
    ///
346 348
    /// The copy constructor transfers all data from the other writer,
347 349
    /// therefore the copied writer will not be usable more. 
348 350
    DigraphWriter(DigraphWriter& other) 
349 351
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
350 352
	_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
351 353

	
352
      other.is = 0;
354
      other._os = 0;
353 355
      other.local_os = false;
354 356

	
355 357
      _node_index.swap(other._node_index);
356 358
      _arc_index.swap(other._arc_index);
357 359

	
358 360
      _node_maps.swap(other._node_maps);
359 361
      _arc_maps.swap(other._arc_maps);
360 362
      _attributes.swap(other._attributes);
361 363

	
362 364
      _nodes_caption = other._nodes_caption;
363 365
      _arcs_caption = other._arcs_caption;
364 366
      _attributes_caption = other._attributes_caption;
365 367
    }
366 368

	
367 369
    /// \brief Destructor
368 370
    ~DigraphWriter() {
369 371
      for (typename NodeMaps::iterator it = _node_maps.begin(); 
370 372
	   it != _node_maps.end(); ++it) {
371 373
	delete it->second;
372 374
      }
373 375

	
374 376
      for (typename ArcMaps::iterator it = _arc_maps.begin(); 
375 377
	   it != _arc_maps.end(); ++it) {
376 378
	delete it->second;
377 379
      }
378 380

	
379 381
      for (typename Attributes::iterator it = _attributes.begin(); 
380 382
	   it != _attributes.end(); ++it) {
381 383
	delete it->second;
382 384
      }
383 385

	
384 386
      if (local_os) {
385 387
	delete _os;
386 388
      }
387 389
    }
388 390

	
389 391
  private:
390 392
    
391 393
    DigraphWriter& operator=(const DigraphWriter&);
392 394

	
393 395
  public:
394 396

	
395 397
    /// \name Writing rules
396 398
    /// @{
397 399
    
398 400
    /// \brief Node map reading rule
399 401
    ///
400 402
    /// Add a node map reading rule to the writer.
... ...
@@ -672,67 +674,70 @@
672 674
      }
673 675
    }
674 676

	
675 677
    void writeAttributes() {
676 678
      if (_attributes.empty()) return;
677 679
      *_os << "@attributes";
678 680
      if (!_attributes_caption.empty()) {
679 681
	_writer_bits::writeToken(*_os << ' ', _attributes_caption);
680 682
      }
681 683
      *_os << std::endl;
682 684
      for (typename Attributes::iterator it = _attributes.begin();
683 685
	   it != _attributes.end(); ++it) {
684 686
	_writer_bits::writeToken(*_os, it->first) << ' ';
685 687
	_writer_bits::writeToken(*_os, it->second->get());
686 688
	*_os << std::endl;
687 689
      }
688 690
    }
689 691
    
690 692
  public:
691 693
    
692 694
    /// \name Execution of the writer    
693 695
    /// @{
694 696

	
695 697
    /// \brief Start the batch processing
696 698
    ///
697 699
    /// This function starts the batch processing
698 700
    void run() {
699 701
      if (!_skip_nodes) {
700 702
	writeNodes();
701 703
      }
702 704
      if (!_skip_arcs) {      
703 705
	writeArcs();
704 706
      }
705 707
      writeAttributes();
706 708
    }
707 709

	
708 710
    /// \brief Gives back the stream of the writer
709 711
    ///
710 712
    /// Gives back the stream of the writer
711 713
    std::ostream& ostream() {
712 714
      return *_os;
713 715
    }
714 716

	
715 717
    /// @}
716 718
  };
717 719

	
718 720
  /// \relates DigraphWriter
719 721
  template <typename Digraph>
720
  DigraphWriter<Digraph> digraphWriter(std::istream& is, Digraph& digraph) {
721
    return DigraphWriter<Digraph>(is, digraph);
722
  DigraphWriter<Digraph> digraphWriter(std::ostream& os, Digraph& digraph) {
723
    DigraphWriter<Digraph> tmp(os, digraph);
724
    return tmp;
722 725
  }
723 726

	
724 727
  /// \relates DigraphWriter
725 728
  template <typename Digraph>
726 729
  DigraphWriter<Digraph> digraphWriter(const std::string& fn, 
727 730
				       Digraph& digraph) {
728
    return DigraphWriter<Digraph>(fn, digraph);
731
    DigraphWriter<Digraph> tmp(fn, digraph);
732
    return tmp;
729 733
  }
730 734

	
731 735
  /// \relates DigraphWriter
732 736
  template <typename Digraph>
733 737
  DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) {
734
    return DigraphWriter<Digraph>(fn, digraph);
738
    DigraphWriter<Digraph> tmp(fn, digraph);
739
    return tmp;
735 740
  }
736 741
}
737 742

	
738 743
#endif
0 comments (0 inline)