| deba@1408 |      1 | /* -*- C++ -*-
 | 
| deba@1408 |      2 |  *
 | 
| alpar@1956 |      3 |  * This file is a part of LEMON, a generic C++ optimization library
 | 
| alpar@1956 |      4 |  *
 | 
| alpar@1956 |      5 |  * Copyright (C) 2003-2006
 | 
| alpar@1956 |      6 |  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 | 
| alpar@1956 |      7 |  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 | 
| deba@1408 |      8 |  *
 | 
| deba@1408 |      9 |  * Permission to use, modify and distribute this software is granted
 | 
| deba@1408 |     10 |  * provided that this copyright notice appears in all copies. For
 | 
| deba@1408 |     11 |  * precise terms see the accompanying LICENSE file.
 | 
| deba@1408 |     12 |  *
 | 
| deba@1408 |     13 |  * This software is provided "AS IS" with no warranty of any kind,
 | 
| deba@1408 |     14 |  * express or implied, and with no claim as to its suitability for any
 | 
| deba@1408 |     15 |  * purpose.
 | 
| deba@1408 |     16 |  *
 | 
| deba@1408 |     17 |  */
 | 
| deba@1408 |     18 | 
 | 
| deba@1910 |     19 | /// @defgroin item_io Item Readers and Writers
 | 
| alpar@1946 |     20 | /// @ingroup io_groin
 | 
| deba@1415 |     21 | /// \brief Item Readers and Writers
 | 
| deba@1415 |     22 | /// 
 | 
| deba@1415 |     23 | /// The Input-Output classes can handle more data type by example
 | 
| deba@1415 |     24 | /// as map or attribute value. Each of these should be written and
 | 
| deba@1415 |     25 | /// read some way. The module make possible to do this.  
 | 
| deba@1415 |     26 | 
 | 
| alpar@1946 |     27 | /// \ingroup item_io
 | 
| deba@1408 |     28 | /// \file
 | 
| deba@1408 |     29 | /// \brief Item reader bits for lemon input.
 | 
| deba@1408 |     30 | 
 | 
| deba@1408 |     31 | #ifndef LEMON_BITS_ITEM_READER_H
 | 
| deba@1408 |     32 | #define LEMON_BITS_ITEM_READER_H
 | 
| deba@1408 |     33 | 
 | 
| deba@1408 |     34 | #include <iostream>
 | 
| deba@1408 |     35 | #include <string>
 | 
| deba@1408 |     36 | 
 | 
| deba@1408 |     37 | #include <vector>
 | 
| deba@1408 |     38 | #include <deque>
 | 
| deba@1408 |     39 | #include <list>
 | 
| deba@1408 |     40 | #include <set>
 | 
| deba@1408 |     41 | 
 | 
| deba@1408 |     42 | namespace lemon {
 | 
| deba@1408 |     43 |   
 | 
| deba@1408 |     44 |   template <typename Value>
 | 
| deba@1408 |     45 |   class DefaultReader;
 | 
| deba@1408 |     46 | 
 | 
| alpar@1946 |     47 |   /// \ingroup item_io
 | 
| deba@1408 |     48 |   ///
 | 
| deba@1408 |     49 |   /// \brief Reader class for quoted strings.
 | 
| deba@1408 |     50 |   ///
 | 
| deba@1408 |     51 |   /// Reader class for quoted strings. It can process the escape
 | 
| deba@1408 |     52 |   /// sequences in the string.
 | 
| deba@1408 |     53 |   ///
 | 
| deba@1408 |     54 |   /// \author Balazs Dezso
 | 
| deba@1408 |     55 |   class QuotedStringReader {
 | 
| deba@1408 |     56 |   public:
 | 
| deba@1408 |     57 |     /// \brief The value type of reader.
 | 
| deba@1408 |     58 |     ///
 | 
| deba@1408 |     59 |     /// The value type of reader.
 | 
| deba@1408 |     60 |     typedef std::string Value;
 | 
| deba@1408 |     61 |     
 | 
| deba@1408 |     62 |     /// \brief Constructor for the reader.
 | 
| deba@1408 |     63 |     ///
 | 
| deba@1408 |     64 |     /// Constructor for the reader. If the given parameter is true
 | 
| deba@1408 |     65 |     /// the reader processes the escape sequences.
 | 
| deba@1408 |     66 |     QuotedStringReader(bool _escaped = true) 
 | 
| deba@1408 |     67 |       : escaped(_escaped) {}
 | 
| deba@1408 |     68 |     
 | 
| deba@1408 |     69 |     /// \brief Reads a quoted string from the given stream.
 | 
| deba@1408 |     70 |     ///
 | 
| deba@1408 |     71 |     /// Reads a quoted string from the given stream.
 | 
| deba@1408 |     72 |     void read(std::istream& is, std::string& value) const {
 | 
| deba@1408 |     73 |       char c;
 | 
| deba@1408 |     74 |       value.clear();
 | 
| deba@1408 |     75 |       is >> std::ws;
 | 
| deba@1408 |     76 |       if (!is.get(c) || c != '\"') 
 | 
| deba@1408 |     77 | 	throw DataFormatError("Quoted string format error");
 | 
| deba@1408 |     78 |       while (is.get(c) && c != '\"') {
 | 
| deba@1408 |     79 | 	if (escaped && c == '\\') {
 | 
| deba@1408 |     80 | 	  value += readEscape(is);
 | 
| deba@1408 |     81 | 	} else {
 | 
| deba@1408 |     82 | 	  value += c;
 | 
| deba@1408 |     83 | 	}
 | 
| deba@1408 |     84 |       }
 | 
| deba@1408 |     85 |       if (!is) throw DataFormatError("Quoted string format error");
 | 
| deba@1408 |     86 |     }
 | 
| deba@1408 |     87 | 
 | 
| deba@1408 |     88 |   private:
 | 
| deba@1408 |     89 |     
 | 
| deba@1408 |     90 |     static char readEscape(std::istream& is) {
 | 
| deba@1408 |     91 |       char c;
 | 
| deba@1408 |     92 |       switch (is.get(c), c) {
 | 
| deba@1408 |     93 |       case '\\':
 | 
| deba@1408 |     94 | 	return '\\';
 | 
| deba@1408 |     95 |       case '\"':
 | 
| deba@1408 |     96 | 	return '\"';
 | 
| deba@1408 |     97 |       case '\'':
 | 
| deba@1408 |     98 | 	return '\'';
 | 
| deba@1408 |     99 |       case '\?':
 | 
| deba@1408 |    100 | 	return '\?';
 | 
| deba@1408 |    101 |       case 'a':
 | 
| deba@1408 |    102 | 	return '\a';
 | 
| deba@1408 |    103 |       case 'b':
 | 
| deba@1408 |    104 | 	return '\b';
 | 
| deba@1408 |    105 |       case 'f':
 | 
| deba@1408 |    106 | 	return '\f';
 | 
| deba@1408 |    107 |       case 'n':
 | 
| deba@1408 |    108 | 	return '\n';
 | 
| deba@1408 |    109 |       case 'r':
 | 
| deba@1408 |    110 | 	return '\r';
 | 
| deba@1408 |    111 |       case 't':
 | 
| deba@1408 |    112 | 	return '\t';
 | 
| deba@1408 |    113 |       case 'v':
 | 
| deba@1408 |    114 | 	return '\v';
 | 
| deba@1408 |    115 |       case 'x':
 | 
| deba@1408 |    116 | 	{
 | 
| deba@1408 |    117 | 	  int code;
 | 
| deba@1408 |    118 | 	  if (!is.get(c) || !isHex(c)) 
 | 
| deba@1408 |    119 | 	    throw DataFormatError("Escape format error");
 | 
| deba@1408 |    120 | 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
 | 
| deba@1408 |    121 | 	  else code = code * 16 + valueHex(c);
 | 
| deba@1408 |    122 | 	  return code;
 | 
| deba@1408 |    123 | 	}
 | 
| deba@1408 |    124 |       default:
 | 
| deba@1408 |    125 | 	{
 | 
| deba@1408 |    126 | 	  int code;
 | 
| deba@1408 |    127 | 	  if (!isOct(c)) 
 | 
| deba@1408 |    128 | 	    throw DataFormatError("Escape format error");
 | 
| deba@1408 |    129 | 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
 | 
| deba@1408 |    130 | 	    is.putback(c);
 | 
| deba@1408 |    131 | 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
 | 
| deba@1408 |    132 | 	    is.putback(c);
 | 
| deba@1408 |    133 | 	  else code = code * 8 + valueOct(c);
 | 
| deba@1408 |    134 | 	  return code;
 | 
| deba@1408 |    135 | 	}	      
 | 
| deba@1408 |    136 |       } 
 | 
| deba@1408 |    137 |     }
 | 
| deba@1408 |    138 | 
 | 
| deba@1408 |    139 |     static bool isOct(char c) {
 | 
| deba@1408 |    140 |       return '0' <= c && c <='7'; 
 | 
| deba@1408 |    141 |     }
 | 
| deba@1408 |    142 |     
 | 
| deba@1408 |    143 |     static int valueOct(char c) {
 | 
| deba@1408 |    144 |       return c - '0';
 | 
| deba@1408 |    145 |     }
 | 
| deba@1408 |    146 | 
 | 
| deba@1408 |    147 |    static bool isHex(char c) {
 | 
| deba@1408 |    148 |       return ('0' <= c && c <= '9') || 
 | 
| deba@1408 |    149 | 	('a' <= c && c <= 'z') || 
 | 
| deba@1408 |    150 | 	('A' <= c && c <= 'Z'); 
 | 
| deba@1408 |    151 |     }
 | 
| deba@1408 |    152 |     
 | 
| deba@1408 |    153 |     static int valueHex(char c) {
 | 
| deba@1408 |    154 |       if ('0' <= c && c <= '9') return c - '0';
 | 
| deba@1408 |    155 |       if ('a' <= c && c <= 'z') return c - 'a' + 10;
 | 
| deba@1408 |    156 |       return c - 'A' + 10;
 | 
| deba@1408 |    157 |     }
 | 
| deba@1408 |    158 | 
 | 
| deba@1408 |    159 |     bool escaped;
 | 
| deba@1408 |    160 |   };
 | 
| deba@1408 |    161 | 
 | 
| alpar@1946 |    162 |   /// \ingroup item_io
 | 
| deba@1408 |    163 |   /// \brief Reader for standard containers.
 | 
| deba@1408 |    164 |   ///
 | 
| deba@1408 |    165 |   /// Reader for back insertable standard containers. The representation
 | 
| deba@1408 |    166 |   /// of the container is the values enumerated between an open and a
 | 
| deba@1408 |    167 |   /// close parse. 
 | 
| deba@1408 |    168 |   ///
 | 
| deba@1408 |    169 |   /// \author Balazs Dezso
 | 
| deba@1408 |    170 |   template <
 | 
| deba@1408 |    171 |     typename _Container, 
 | 
| deba@1408 |    172 |     typename _ItemReader = DefaultReader<typename _Container::value_type> 
 | 
| deba@1408 |    173 |   >
 | 
| deba@1408 |    174 |   class PushBackReader {
 | 
| deba@1408 |    175 |   public:
 | 
| deba@1408 |    176 |     typedef _Container Value;
 | 
| deba@1408 |    177 |     typedef _ItemReader ItemReader;
 | 
| deba@1408 |    178 | 
 | 
| deba@1408 |    179 |   private:
 | 
| deba@1408 |    180 | 
 | 
| deba@1408 |    181 |     ItemReader item_reader;
 | 
| deba@1408 |    182 | 
 | 
| deba@1408 |    183 |   public:
 | 
| deba@1408 |    184 | 
 | 
| deba@1852 |    185 |     /// \brief Constructor for InsertReader
 | 
| deba@1852 |    186 |     ///
 | 
| deba@1852 |    187 |     /// Constructor for InsertReader
 | 
| deba@1852 |    188 |     PushBackReader(const ItemReader& _item_reader = ItemReader())
 | 
| deba@1852 |    189 |       : item_reader(_item_reader) {}
 | 
| deba@1852 |    190 | 
 | 
| deba@1408 |    191 |     /// \brief Reads the values into the container from the given stream.
 | 
| deba@1408 |    192 |     ///
 | 
| deba@1408 |    193 |     /// Reads the values into the container from the given stream.
 | 
| deba@1408 |    194 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1408 |    195 |       char c;
 | 
| deba@1408 |    196 |       if (!(is >> c) || c != '(') 
 | 
| deba@1408 |    197 | 	throw DataFormatError("PushBackReader format error");
 | 
| deba@1408 |    198 |       while (is >> c && c != ')') {
 | 
| deba@1408 |    199 | 	is.putback(c);
 | 
| deba@1408 |    200 | 	typename ItemReader::Value item;
 | 
| deba@1408 |    201 | 	item_reader.read(is, item);
 | 
| deba@1408 |    202 | 	value.push_back(item);
 | 
| deba@1408 |    203 |       }
 | 
| deba@1408 |    204 |       if (!is) throw DataFormatError("PushBackReader format error");
 | 
| deba@1408 |    205 |     }
 | 
| deba@1408 |    206 | 
 | 
| deba@1408 |    207 |   };
 | 
| deba@1408 |    208 | 
 | 
| alpar@1946 |    209 |   /// \ingroup item_io
 | 
| deba@1408 |    210 |   ///
 | 
| deba@1408 |    211 |   /// \brief Reader for standard containers.
 | 
| deba@1408 |    212 |   ///
 | 
| deba@1408 |    213 |   /// Reader for insertable standard containers. The representation
 | 
| deba@1408 |    214 |   /// of the container is the values enumerated between an open and a
 | 
| deba@1408 |    215 |   /// close parse. 
 | 
| deba@1408 |    216 |   ///
 | 
| deba@1408 |    217 |   /// \author Balazs Dezso
 | 
| deba@1408 |    218 |   template <
 | 
| deba@1408 |    219 |     typename _Container, 
 | 
| deba@1408 |    220 |     typename _ItemReader = DefaultReader<typename _Container::value_type> 
 | 
| deba@1408 |    221 |   >
 | 
| deba@1408 |    222 |   class InsertReader {
 | 
| deba@1408 |    223 |   public:
 | 
| deba@1408 |    224 |     typedef _Container Value;
 | 
| deba@1408 |    225 |     typedef _ItemReader ItemReader;
 | 
| deba@1408 |    226 | 
 | 
| deba@1408 |    227 |   private:
 | 
| deba@1408 |    228 | 
 | 
| deba@1408 |    229 |     ItemReader item_reader;
 | 
| deba@1408 |    230 | 
 | 
| deba@1408 |    231 |   public:
 | 
| deba@1408 |    232 | 
 | 
| deba@1852 |    233 |     /// \brief Constructor for InsertReader
 | 
| deba@1852 |    234 |     ///
 | 
| deba@1852 |    235 |     /// Constructor for InsertReader
 | 
| deba@1852 |    236 |     InsertReader(const ItemReader& _item_reader = ItemReader())
 | 
| deba@1852 |    237 |       : item_reader(_item_reader) {}
 | 
| deba@1852 |    238 | 
 | 
| deba@1408 |    239 |     /// \brief Reads the values into the container from the given stream.
 | 
| deba@1408 |    240 |     ///
 | 
| deba@1408 |    241 |     /// Reads the values into the container from the given stream.
 | 
| deba@1408 |    242 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1408 |    243 |       char c;
 | 
| deba@1408 |    244 |       if (!(is >> c) || c != '(') 
 | 
| deba@1408 |    245 | 	throw DataFormatError("InsertReader format error");
 | 
| deba@1408 |    246 |       while (is >> c && c != ')') {
 | 
| deba@1408 |    247 | 	is.putback(c);
 | 
| deba@1408 |    248 | 	typename ItemReader::Value item;
 | 
| deba@1408 |    249 | 	item_reader.read(is, item);
 | 
| deba@1408 |    250 | 	value.insert(item);
 | 
| deba@1408 |    251 |       }
 | 
| deba@1408 |    252 |       if (!is) throw DataFormatError("PushBackReader format error");
 | 
| deba@1408 |    253 |     }
 | 
| deba@1408 |    254 | 
 | 
| deba@1408 |    255 |   };
 | 
| deba@1408 |    256 | 
 | 
| alpar@1946 |    257 |   /// \ingroup item_io
 | 
| deba@1408 |    258 |   /// \brief Reader for parsed string.
 | 
| deba@1408 |    259 |   ///
 | 
| deba@1744 |    260 |   /// Reader for parsed strings. You can define the open and close
 | 
| deba@1744 |    261 |   /// parse characters. It reads from the input a character sequence
 | 
| deba@1744 |    262 |   /// which is right parsed.
 | 
| deba@1408 |    263 |   ///
 | 
| deba@1408 |    264 |   /// \author Balazs Dezso
 | 
| deba@1408 |    265 |   class ParsedStringReader {
 | 
| deba@1408 |    266 |   public:
 | 
| deba@1408 |    267 |     typedef std::string Value;
 | 
| deba@1408 |    268 | 
 | 
| deba@1408 |    269 |     /// \brief Constructor.
 | 
| deba@1408 |    270 |     ///
 | 
| deba@1408 |    271 |     /// Constructor for ParsedStringReader. You can give as parameter
 | 
| deba@1408 |    272 |     /// the open and close parse characters.
 | 
| deba@1408 |    273 |     ParsedStringReader(char _open = '(', char _close = ')')
 | 
| deba@1408 |    274 |       : open(_open), close(_close) {}
 | 
| deba@1408 |    275 |     
 | 
| deba@1408 |    276 |     
 | 
| deba@1408 |    277 |     /// \brief Reads the parsed string from the given stream.
 | 
| deba@1408 |    278 |     ///
 | 
| deba@1408 |    279 |     /// Reads the parsed string from the given stream.
 | 
| deba@1408 |    280 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1408 |    281 |       char c;
 | 
| deba@1408 |    282 |       if (!(is >> c) || c != open) {
 | 
| deba@1408 |    283 | 	throw DataFormatError("ParsedStringReader format error");
 | 
| deba@1408 |    284 |       }
 | 
| deba@1408 |    285 |       value += c;
 | 
| deba@1408 |    286 |       int counter = 1;
 | 
| deba@1408 |    287 |       while (counter > 0 && is >> c) {
 | 
| deba@1408 |    288 | 	if (c == close) {
 | 
| deba@1408 |    289 | 	  --counter;
 | 
| deba@1408 |    290 | 	} else if (c == open) {
 | 
| deba@1408 |    291 | 	  ++counter;
 | 
| deba@1408 |    292 | 	}
 | 
| deba@1408 |    293 | 	value += c;
 | 
| deba@1408 |    294 |       }
 | 
| deba@1408 |    295 |       if (!is) {
 | 
| deba@1408 |    296 | 	throw DataFormatError("ParsedStrinReader format error");
 | 
| deba@1408 |    297 |       }
 | 
| deba@1408 |    298 |     }
 | 
| deba@1408 |    299 | 
 | 
| deba@1408 |    300 |   private:
 | 
| deba@1408 |    301 |     char open, close;
 | 
| deba@1408 |    302 | 
 | 
| deba@1408 |    303 |   };
 | 
| deba@1408 |    304 | 
 | 
| alpar@1946 |    305 |   /// \ingroup item_io
 | 
| deba@1408 |    306 |   /// \brief Reader for read the whole line.
 | 
| deba@1408 |    307 |   ///
 | 
| deba@1408 |    308 |   /// Reader for read the whole line.
 | 
| deba@1408 |    309 |   ///
 | 
| deba@1408 |    310 |   /// \author Balazs Dezso
 | 
| deba@1408 |    311 |   class LineReader {
 | 
| deba@1408 |    312 |   public:
 | 
| deba@1408 |    313 |     typedef std::string Value;
 | 
| deba@1408 |    314 | 
 | 
| deba@1408 |    315 |     /// \brief Constructor.
 | 
| deba@1408 |    316 |     ///
 | 
| deba@1408 |    317 |     /// Constructor for the LineReader. If the given parameter is
 | 
| deba@1408 |    318 |     /// true then the spaces before the first not space character are
 | 
| deba@1408 |    319 |     /// skipped.
 | 
| deba@1408 |    320 |     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
 | 
| deba@1408 |    321 |     
 | 
| deba@1408 |    322 |     /// \brief Reads the line from the given stream.
 | 
| deba@1408 |    323 |     ///
 | 
| deba@1408 |    324 |     /// Reads the line from the given stream.
 | 
| deba@1852 |    325 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1408 |    326 |       if (skipSpaces) is >> std::ws;
 | 
| deba@1408 |    327 |       if (!getline(is, value)) {
 | 
| deba@1852 |    328 | 	throw DataFormatError("LineReader format error");
 | 
| deba@1408 |    329 |       }
 | 
| deba@1408 |    330 |     }
 | 
| deba@1408 |    331 |   private:
 | 
| deba@1408 |    332 |     bool skipSpaces;
 | 
| deba@1408 |    333 |   };
 | 
| deba@1408 |    334 | 
 | 
| alpar@1946 |    335 |   /// \ingroup item_io
 | 
| deba@1852 |    336 |   /// \brief Reader for std::pair.
 | 
| deba@1852 |    337 |   ///
 | 
| deba@1852 |    338 |   /// Reader for std::pair.
 | 
| deba@1852 |    339 |   ///
 | 
| deba@1852 |    340 |   /// \author Balazs Dezso
 | 
| deba@1852 |    341 |   template <typename _Pair, 
 | 
| deba@1852 |    342 | 	    typename _FirstReader = 
 | 
| deba@1852 |    343 | 	    DefaultReader<typename _Pair::first_type>,
 | 
| deba@1852 |    344 | 	    typename _SecondReader = 
 | 
| deba@1852 |    345 | 	    DefaultReader<typename _Pair::second_type> >
 | 
| deba@1852 |    346 |   class PairReader {
 | 
| deba@1852 |    347 |   public:
 | 
| deba@1852 |    348 |     typedef _Pair Value;
 | 
| deba@1852 |    349 | 
 | 
| deba@1852 |    350 |     typedef _FirstReader FirstReader;
 | 
| deba@1852 |    351 |     typedef _SecondReader SecondReader;
 | 
| deba@1852 |    352 | 
 | 
| deba@1852 |    353 |   private:
 | 
| deba@1852 |    354 | 
 | 
| deba@1852 |    355 |     FirstReader first_reader;
 | 
| deba@1852 |    356 |     SecondReader second_reader;
 | 
| deba@1852 |    357 | 
 | 
| deba@1852 |    358 |   public:
 | 
| deba@1852 |    359 |     
 | 
| deba@1852 |    360 |     /// \brief Constructor.
 | 
| deba@1852 |    361 |     ///
 | 
| deba@1852 |    362 |     /// Constructor for the PairReader.
 | 
| deba@1852 |    363 |     PairReader(const FirstReader& _first_reader = FirstReader(), 
 | 
| deba@1852 |    364 | 	       const SecondReader& _second_reader = SecondReader()) 
 | 
| deba@1852 |    365 |       : first_reader(_first_reader), second_reader(_second_reader) {}
 | 
| deba@1852 |    366 |     
 | 
| deba@1852 |    367 |     /// \brief Reads the pair from the given stream.
 | 
| deba@1852 |    368 |     ///
 | 
| deba@1852 |    369 |     /// Reads the pair from the given stream.
 | 
| deba@1852 |    370 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1852 |    371 |       char c;
 | 
| deba@1852 |    372 |       if (!(is >> c) || c != '(') {
 | 
| deba@1852 |    373 | 	throw DataFormatError("PairReader format error");
 | 
| deba@1852 |    374 |       }
 | 
| deba@1852 |    375 |       first_reader.read(is, value.first);
 | 
| deba@1852 |    376 |       if (!(is >> c) || c != '=') {
 | 
| deba@1852 |    377 | 	throw DataFormatError("PairReader format error");
 | 
| deba@1852 |    378 |       }
 | 
| deba@1852 |    379 |       if (!(is >> c) || c != '>') {
 | 
| deba@1852 |    380 | 	throw DataFormatError("PairReader format error");
 | 
| deba@1852 |    381 |       }
 | 
| deba@1852 |    382 |       second_reader.read(is, value.second);
 | 
| deba@1852 |    383 |       if (!(is >> c) || c != ')') {
 | 
| deba@1852 |    384 | 	throw DataFormatError("PairReader format error");
 | 
| deba@1852 |    385 |       }
 | 
| deba@1852 |    386 |     }
 | 
| deba@1852 |    387 |   };
 | 
| deba@1852 |    388 | 
 | 
| alpar@1946 |    389 |   /// \ingroup item_io
 | 
| deba@1408 |    390 |   /// 
 | 
| deba@1408 |    391 |   /// \brief The default item reader template class.
 | 
| deba@1408 |    392 |   ///
 | 
| deba@1408 |    393 |   /// The default item reader template class. If some section reader
 | 
| deba@1408 |    394 |   /// needs to read a value from a stream it will give the default way for it.
 | 
| deba@1408 |    395 |   ///
 | 
| deba@1408 |    396 |   /// \author Balazs Dezso
 | 
| deba@1408 |    397 |   template <typename _Value>
 | 
| deba@1408 |    398 |   class DefaultReader {
 | 
| deba@1408 |    399 |   public:
 | 
| deba@1408 |    400 |     /// The value type.
 | 
| deba@1408 |    401 |     typedef _Value Value;
 | 
| deba@1408 |    402 |     /// \brief Reads a value from the given stream.
 | 
| deba@1408 |    403 |     ///
 | 
| deba@1408 |    404 |     /// Reads a value from the given stream.
 | 
| deba@1408 |    405 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1408 |    406 |       if (!(is >> value)) 
 | 
| deba@1408 |    407 | 	throw DataFormatError("DefaultReader format error");
 | 
| deba@1408 |    408 |     }
 | 
| deba@1408 |    409 |   };
 | 
| deba@1408 |    410 | 
 | 
| deba@1427 |    411 |   template <>
 | 
| deba@1427 |    412 |   class DefaultReader<std::string> {
 | 
| deba@1427 |    413 |   public:
 | 
| deba@1427 |    414 |     typedef std::string Value;
 | 
| deba@1427 |    415 |     
 | 
| deba@1427 |    416 |     void read(std::istream& is, Value& value) const {
 | 
| deba@1427 |    417 |       char c;
 | 
| deba@1429 |    418 |       if (!(is >> std::ws >> c)) return;
 | 
| deba@1427 |    419 |       is.putback(c);
 | 
| deba@1427 |    420 |       switch (c) {
 | 
| deba@1427 |    421 |       case '\"':
 | 
| deba@1427 |    422 | 	QuotedStringReader().read(is, value);
 | 
| deba@1427 |    423 | 	break;
 | 
| deba@1427 |    424 |       case '(':
 | 
| deba@1427 |    425 | 	ParsedStringReader().read(is, value);
 | 
| deba@1427 |    426 | 	break;
 | 
| deba@1744 |    427 |       case '[':
 | 
| deba@1744 |    428 | 	ParsedStringReader('[', ']').read(is, value);
 | 
| deba@1744 |    429 | 	break;
 | 
| deba@1744 |    430 |       case '/':
 | 
| deba@1744 |    431 | 	ParsedStringReader('/', '/').read(is, value);
 | 
| deba@1744 |    432 | 	break;
 | 
| deba@1427 |    433 |       default:
 | 
| deba@1744 |    434 | 	if (!(is >> value)) 
 | 
| deba@1744 |    435 | 	  throw DataFormatError("DefaultReader format error");
 | 
| deba@1427 |    436 | 	break;
 | 
| deba@1427 |    437 |       }
 | 
| deba@1427 |    438 |     }
 | 
| deba@1427 |    439 |     
 | 
| deba@1427 |    440 |   };
 | 
| deba@1427 |    441 | 
 | 
| deba@1408 |    442 |   template <typename Item>
 | 
| deba@1408 |    443 |   class DefaultReader<std::vector<Item> > 
 | 
| deba@1408 |    444 |     : public PushBackReader<std::vector<Item> > {};
 | 
| deba@1408 |    445 | 
 | 
| deba@1408 |    446 |   template <typename Item>
 | 
| deba@1408 |    447 |   class DefaultReader<std::deque<Item> > 
 | 
| deba@1408 |    448 |     : public PushBackReader<std::deque<Item> > {};
 | 
| deba@1408 |    449 | 
 | 
| deba@1408 |    450 |   template <typename Item>
 | 
| deba@1408 |    451 |   class DefaultReader<std::list<Item> > 
 | 
| deba@1408 |    452 |     : public PushBackReader<std::list<Item> > {};
 | 
| deba@1408 |    453 | 
 | 
| deba@1408 |    454 |   template <typename Item>
 | 
| deba@1408 |    455 |   class DefaultReader<std::set<Item> > 
 | 
| deba@1408 |    456 |     : public InsertReader<std::set<Item> > {};
 | 
| deba@1408 |    457 | 
 | 
| deba@1852 |    458 |   template <typename Key, typename Value>
 | 
| deba@1852 |    459 |   class DefaultReader<std::map<Key, Value> > 
 | 
| deba@1852 |    460 |     : public InsertReader<std::map<Key, Value>,
 | 
| deba@1852 |    461 | 			  DefaultReader<std::pair<Key, Value> > > {};
 | 
| deba@1852 |    462 | 
 | 
| deba@1408 |    463 |   template <typename Item>
 | 
| deba@1408 |    464 |   class DefaultReader<std::multiset<Item> > 
 | 
| deba@1408 |    465 |     : public InsertReader<std::multiset<Item> > {};
 | 
| deba@1408 |    466 | 
 | 
| deba@1852 |    467 |   template <typename Key, typename Value>
 | 
| deba@1852 |    468 |   class DefaultReader<std::multimap<Key, Value> > 
 | 
| deba@1852 |    469 |     : public InsertReader<std::multimap<Key, Value>,
 | 
| deba@1852 |    470 | 			  DefaultReader<std::pair<Key, Value> > > {};
 | 
| deba@1852 |    471 | 
 | 
| deba@1852 |    472 |   template <typename First, typename Second>
 | 
| deba@1852 |    473 |   class DefaultReader<std::pair<First, Second> > 
 | 
| deba@1852 |    474 |     : public PairReader<std::pair<First, Second> > {};
 | 
| deba@1852 |    475 | 
 | 
| alpar@1946 |    476 |   /// \ingroup item_io
 | 
| deba@1415 |    477 |   /// 
 | 
| deba@1415 |    478 |   /// \brief The default item reader for skipping a value in the stream.
 | 
| deba@1415 |    479 |   ///
 | 
| deba@1415 |    480 |   /// The default item reader for skipping a value in the stream.
 | 
| deba@1415 |    481 |   ///
 | 
| deba@1415 |    482 |   /// \author Balazs Dezso
 | 
| deba@1427 |    483 |   class DefaultSkipper : public DefaultReader<std::string> {};
 | 
| deba@1415 |    484 | 
 | 
| alpar@1946 |    485 |   /// \ingroup item_io  
 | 
| deba@1408 |    486 |   /// \brief Standard ReaderTraits for the GraphReader class.
 | 
| deba@1408 |    487 |   ///
 | 
| deba@1408 |    488 |   /// Standard ReaderTraits for the GraphReader class.
 | 
| deba@1408 |    489 |   /// It defines standard reading method for all type of value. 
 | 
| deba@1408 |    490 |   /// \author Balazs Dezso
 | 
| deba@1408 |    491 |   struct DefaultReaderTraits {
 | 
| deba@1408 |    492 | 
 | 
| deba@1408 |    493 |     template <typename _Value>
 | 
| deba@1408 |    494 |     struct Reader : DefaultReader<_Value> {};
 | 
| deba@1408 |    495 | 
 | 
| deba@1408 |    496 |     typedef DefaultSkipper Skipper;
 | 
| deba@1408 |    497 | 
 | 
| deba@1408 |    498 |   };
 | 
| deba@1408 |    499 | 
 | 
| deba@1408 |    500 | }
 | 
| deba@1408 |    501 | 
 | 
| deba@1408 |    502 | #endif
 |