One more step towards Undir -> U conversion...
3 * This file is a part of LEMON, a generic C++ optimization library
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
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.
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
19 /// @defgroin item_io Item Readers and Writers
21 /// \brief Item Readers and Writers
23 /// The Input-Output classes can handle more data type by example
24 /// as map or attribute value. Each of these should be written and
25 /// read some way. The module make possible to do this.
29 /// \brief Item reader bits for lemon input.
31 #ifndef LEMON_BITS_ITEM_READER_H
32 #define LEMON_BITS_ITEM_READER_H
44 template <typename Value>
49 /// \brief Reader class for quoted strings.
51 /// Reader class for quoted strings. It can process the escape
52 /// sequences in the string.
54 /// \author Balazs Dezso
55 class QuotedStringReader {
57 /// \brief The value type of reader.
59 /// The value type of reader.
60 typedef std::string Value;
62 /// \brief Constructor for the reader.
64 /// Constructor for the reader. If the given parameter is true
65 /// the reader processes the escape sequences.
66 QuotedStringReader(bool _escaped = true)
67 : escaped(_escaped) {}
69 /// \brief Reads a quoted string from the given stream.
71 /// Reads a quoted string from the given stream.
72 void read(std::istream& is, std::string& value) const {
76 if (!is.get(c) || c != '\"')
77 throw DataFormatError("Quoted string format error");
78 while (is.get(c) && c != '\"') {
79 if (escaped && c == '\\') {
80 value += readEscape(is);
85 if (!is) throw DataFormatError("Quoted string format error");
90 static char readEscape(std::istream& is) {
92 switch (is.get(c), c) {
118 if (!is.get(c) || !isHex(c))
119 throw DataFormatError("Escape format error");
120 else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
121 else code = code * 16 + valueHex(c);
128 throw DataFormatError("Escape format error");
129 else if (code = valueOct(c), !is.get(c) || !isOct(c))
131 else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
133 else code = code * 8 + valueOct(c);
139 static bool isOct(char c) {
140 return '0' <= c && c <='7';
143 static int valueOct(char c) {
147 static bool isHex(char c) {
148 return ('0' <= c && c <= '9') ||
149 ('a' <= c && c <= 'z') ||
150 ('A' <= c && c <= 'Z');
153 static int valueHex(char c) {
154 if ('0' <= c && c <= '9') return c - '0';
155 if ('a' <= c && c <= 'z') return c - 'a' + 10;
163 /// \brief Reader for standard containers.
165 /// Reader for back insertable standard containers. The representation
166 /// of the container is the values enumerated between an open and a
169 /// \author Balazs Dezso
172 typename _ItemReader = DefaultReader<typename _Container::value_type>
174 class PushBackReader {
176 typedef _Container Value;
177 typedef _ItemReader ItemReader;
181 ItemReader item_reader;
185 /// \brief Constructor for InsertReader
187 /// Constructor for InsertReader
188 PushBackReader(const ItemReader& _item_reader = ItemReader())
189 : item_reader(_item_reader) {}
191 /// \brief Reads the values into the container from the given stream.
193 /// Reads the values into the container from the given stream.
194 void read(std::istream& is, Value& value) const {
196 if (!(is >> c) || c != '(')
197 throw DataFormatError("PushBackReader format error");
198 while (is >> c && c != ')') {
200 typename ItemReader::Value item;
201 item_reader.read(is, item);
202 value.push_back(item);
204 if (!is) throw DataFormatError("PushBackReader format error");
211 /// \brief Reader for standard containers.
213 /// Reader for insertable standard containers. The representation
214 /// of the container is the values enumerated between an open and a
217 /// \author Balazs Dezso
220 typename _ItemReader = DefaultReader<typename _Container::value_type>
224 typedef _Container Value;
225 typedef _ItemReader ItemReader;
229 ItemReader item_reader;
233 /// \brief Constructor for InsertReader
235 /// Constructor for InsertReader
236 InsertReader(const ItemReader& _item_reader = ItemReader())
237 : item_reader(_item_reader) {}
239 /// \brief Reads the values into the container from the given stream.
241 /// Reads the values into the container from the given stream.
242 void read(std::istream& is, Value& value) const {
244 if (!(is >> c) || c != '(')
245 throw DataFormatError("InsertReader format error");
246 while (is >> c && c != ')') {
248 typename ItemReader::Value item;
249 item_reader.read(is, item);
252 if (!is) throw DataFormatError("PushBackReader format error");
258 /// \brief Reader for parsed string.
260 /// Reader for parsed strings. You can define the open and close
261 /// parse characters. It reads from the input a character sequence
262 /// which is right parsed.
264 /// \author Balazs Dezso
265 class ParsedStringReader {
267 typedef std::string Value;
269 /// \brief Constructor.
271 /// Constructor for ParsedStringReader. You can give as parameter
272 /// the open and close parse characters.
273 ParsedStringReader(char _open = '(', char _close = ')')
274 : open(_open), close(_close) {}
277 /// \brief Reads the parsed string from the given stream.
279 /// Reads the parsed string from the given stream.
280 void read(std::istream& is, Value& value) const {
282 if (!(is >> c) || c != open) {
283 throw DataFormatError("ParsedStringReader format error");
287 while (counter > 0 && is >> c) {
290 } else if (c == open) {
296 throw DataFormatError("ParsedStrinReader format error");
306 /// \brief Reader for read the whole line.
308 /// Reader for read the whole line.
310 /// \author Balazs Dezso
313 typedef std::string Value;
315 /// \brief Constructor.
317 /// Constructor for the LineReader. If the given parameter is
318 /// true then the spaces before the first not space character are
320 LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
322 /// \brief Reads the line from the given stream.
324 /// Reads the line from the given stream.
325 void read(std::istream& is, Value& value) const {
326 if (skipSpaces) is >> std::ws;
327 if (!getline(is, value)) {
328 throw DataFormatError("LineReader format error");
336 /// \brief Reader for std::pair.
338 /// Reader for std::pair.
340 /// \author Balazs Dezso
341 template <typename _Pair,
342 typename _FirstReader =
343 DefaultReader<typename _Pair::first_type>,
344 typename _SecondReader =
345 DefaultReader<typename _Pair::second_type> >
350 typedef _FirstReader FirstReader;
351 typedef _SecondReader SecondReader;
355 FirstReader first_reader;
356 SecondReader second_reader;
360 /// \brief Constructor.
362 /// Constructor for the PairReader.
363 PairReader(const FirstReader& _first_reader = FirstReader(),
364 const SecondReader& _second_reader = SecondReader())
365 : first_reader(_first_reader), second_reader(_second_reader) {}
367 /// \brief Reads the pair from the given stream.
369 /// Reads the pair from the given stream.
370 void read(std::istream& is, Value& value) const {
372 if (!(is >> c) || c != '(') {
373 throw DataFormatError("PairReader format error");
375 first_reader.read(is, value.first);
376 if (!(is >> c) || c != '=') {
377 throw DataFormatError("PairReader format error");
379 if (!(is >> c) || c != '>') {
380 throw DataFormatError("PairReader format error");
382 second_reader.read(is, value.second);
383 if (!(is >> c) || c != ')') {
384 throw DataFormatError("PairReader format error");
391 /// \brief The default item reader template class.
393 /// The default item reader template class. If some section reader
394 /// needs to read a value from a stream it will give the default way for it.
396 /// \author Balazs Dezso
397 template <typename _Value>
398 class DefaultReader {
401 typedef _Value Value;
402 /// \brief Reads a value from the given stream.
404 /// Reads a value from the given stream.
405 void read(std::istream& is, Value& value) const {
407 throw DataFormatError("DefaultReader format error");
412 class DefaultReader<std::string> {
414 typedef std::string Value;
416 void read(std::istream& is, Value& value) const {
418 if (!(is >> std::ws >> c)) return;
422 QuotedStringReader().read(is, value);
425 ParsedStringReader().read(is, value);
428 ParsedStringReader('[', ']').read(is, value);
431 ParsedStringReader('/', '/').read(is, value);
435 throw DataFormatError("DefaultReader format error");
442 template <typename Item>
443 class DefaultReader<std::vector<Item> >
444 : public PushBackReader<std::vector<Item> > {};
446 template <typename Item>
447 class DefaultReader<std::deque<Item> >
448 : public PushBackReader<std::deque<Item> > {};
450 template <typename Item>
451 class DefaultReader<std::list<Item> >
452 : public PushBackReader<std::list<Item> > {};
454 template <typename Item>
455 class DefaultReader<std::set<Item> >
456 : public InsertReader<std::set<Item> > {};
458 template <typename Key, typename Value>
459 class DefaultReader<std::map<Key, Value> >
460 : public InsertReader<std::map<Key, Value>,
461 DefaultReader<std::pair<Key, Value> > > {};
463 template <typename Item>
464 class DefaultReader<std::multiset<Item> >
465 : public InsertReader<std::multiset<Item> > {};
467 template <typename Key, typename Value>
468 class DefaultReader<std::multimap<Key, Value> >
469 : public InsertReader<std::multimap<Key, Value>,
470 DefaultReader<std::pair<Key, Value> > > {};
472 template <typename First, typename Second>
473 class DefaultReader<std::pair<First, Second> >
474 : public PairReader<std::pair<First, Second> > {};
478 /// \brief The default item reader for skipping a value in the stream.
480 /// The default item reader for skipping a value in the stream.
482 /// \author Balazs Dezso
483 class DefaultSkipper : public DefaultReader<std::string> {};
486 /// \brief Standard ReaderTraits for the GraphReader class.
488 /// Standard ReaderTraits for the GraphReader class.
489 /// It defines standard reading method for all type of value.
490 /// \author Balazs Dezso
491 struct DefaultReaderTraits {
493 template <typename _Value>
494 struct Reader : DefaultReader<_Value> {};
496 typedef DefaultSkipper Skipper;