lemon/bits/item_reader.h
author alpar
Tue, 21 Feb 2006 12:37:00 +0000
changeset 1977 8ef02f0c4245
parent 1946 17eb3eaad9f8
child 2016 ecb067198349
permissions -rw-r--r--
RefPtr: a reference counted pointer class
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2006
     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 /// @defgroin item_io Item Readers and Writers
    20 /// @ingroup io_groin
    21 /// \brief Item Readers and Writers
    22 /// 
    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.  
    26 
    27 /// \ingroup item_io
    28 /// \file
    29 /// \brief Item reader bits for lemon input.
    30 
    31 #ifndef LEMON_BITS_ITEM_READER_H
    32 #define LEMON_BITS_ITEM_READER_H
    33 
    34 #include <iostream>
    35 #include <string>
    36 
    37 #include <vector>
    38 #include <deque>
    39 #include <list>
    40 #include <set>
    41 
    42 namespace lemon {
    43   
    44   template <typename Value>
    45   class DefaultReader;
    46 
    47   /// \ingroup item_io
    48   ///
    49   /// \brief Reader class for quoted strings.
    50   ///
    51   /// Reader class for quoted strings. It can process the escape
    52   /// sequences in the string.
    53   ///
    54   /// \author Balazs Dezso
    55   class QuotedStringReader {
    56   public:
    57     /// \brief The value type of reader.
    58     ///
    59     /// The value type of reader.
    60     typedef std::string Value;
    61     
    62     /// \brief Constructor for the reader.
    63     ///
    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) {}
    68     
    69     /// \brief Reads a quoted string from the given stream.
    70     ///
    71     /// Reads a quoted string from the given stream.
    72     void read(std::istream& is, std::string& value) const {
    73       char c;
    74       value.clear();
    75       is >> std::ws;
    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);
    81 	} else {
    82 	  value += c;
    83 	}
    84       }
    85       if (!is) throw DataFormatError("Quoted string format error");
    86     }
    87 
    88   private:
    89     
    90     static char readEscape(std::istream& is) {
    91       char c;
    92       switch (is.get(c), c) {
    93       case '\\':
    94 	return '\\';
    95       case '\"':
    96 	return '\"';
    97       case '\'':
    98 	return '\'';
    99       case '\?':
   100 	return '\?';
   101       case 'a':
   102 	return '\a';
   103       case 'b':
   104 	return '\b';
   105       case 'f':
   106 	return '\f';
   107       case 'n':
   108 	return '\n';
   109       case 'r':
   110 	return '\r';
   111       case 't':
   112 	return '\t';
   113       case 'v':
   114 	return '\v';
   115       case 'x':
   116 	{
   117 	  int code;
   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);
   122 	  return code;
   123 	}
   124       default:
   125 	{
   126 	  int code;
   127 	  if (!isOct(c)) 
   128 	    throw DataFormatError("Escape format error");
   129 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   130 	    is.putback(c);
   131 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   132 	    is.putback(c);
   133 	  else code = code * 8 + valueOct(c);
   134 	  return code;
   135 	}	      
   136       } 
   137     }
   138 
   139     static bool isOct(char c) {
   140       return '0' <= c && c <='7'; 
   141     }
   142     
   143     static int valueOct(char c) {
   144       return c - '0';
   145     }
   146 
   147    static bool isHex(char c) {
   148       return ('0' <= c && c <= '9') || 
   149 	('a' <= c && c <= 'z') || 
   150 	('A' <= c && c <= 'Z'); 
   151     }
   152     
   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;
   156       return c - 'A' + 10;
   157     }
   158 
   159     bool escaped;
   160   };
   161 
   162   /// \ingroup item_io
   163   /// \brief Reader for standard containers.
   164   ///
   165   /// Reader for back insertable standard containers. The representation
   166   /// of the container is the values enumerated between an open and a
   167   /// close parse. 
   168   ///
   169   /// \author Balazs Dezso
   170   template <
   171     typename _Container, 
   172     typename _ItemReader = DefaultReader<typename _Container::value_type> 
   173   >
   174   class PushBackReader {
   175   public:
   176     typedef _Container Value;
   177     typedef _ItemReader ItemReader;
   178 
   179   private:
   180 
   181     ItemReader item_reader;
   182 
   183   public:
   184 
   185     /// \brief Constructor for InsertReader
   186     ///
   187     /// Constructor for InsertReader
   188     PushBackReader(const ItemReader& _item_reader = ItemReader())
   189       : item_reader(_item_reader) {}
   190 
   191     /// \brief Reads the values into the container from the given stream.
   192     ///
   193     /// Reads the values into the container from the given stream.
   194     void read(std::istream& is, Value& value) const {
   195       char c;
   196       if (!(is >> c) || c != '(') 
   197 	throw DataFormatError("PushBackReader format error");
   198       while (is >> c && c != ')') {
   199 	is.putback(c);
   200 	typename ItemReader::Value item;
   201 	item_reader.read(is, item);
   202 	value.push_back(item);
   203       }
   204       if (!is) throw DataFormatError("PushBackReader format error");
   205     }
   206 
   207   };
   208 
   209   /// \ingroup item_io
   210   ///
   211   /// \brief Reader for standard containers.
   212   ///
   213   /// Reader for insertable standard containers. The representation
   214   /// of the container is the values enumerated between an open and a
   215   /// close parse. 
   216   ///
   217   /// \author Balazs Dezso
   218   template <
   219     typename _Container, 
   220     typename _ItemReader = DefaultReader<typename _Container::value_type> 
   221   >
   222   class InsertReader {
   223   public:
   224     typedef _Container Value;
   225     typedef _ItemReader ItemReader;
   226 
   227   private:
   228 
   229     ItemReader item_reader;
   230 
   231   public:
   232 
   233     /// \brief Constructor for InsertReader
   234     ///
   235     /// Constructor for InsertReader
   236     InsertReader(const ItemReader& _item_reader = ItemReader())
   237       : item_reader(_item_reader) {}
   238 
   239     /// \brief Reads the values into the container from the given stream.
   240     ///
   241     /// Reads the values into the container from the given stream.
   242     void read(std::istream& is, Value& value) const {
   243       char c;
   244       if (!(is >> c) || c != '(') 
   245 	throw DataFormatError("InsertReader format error");
   246       while (is >> c && c != ')') {
   247 	is.putback(c);
   248 	typename ItemReader::Value item;
   249 	item_reader.read(is, item);
   250 	value.insert(item);
   251       }
   252       if (!is) throw DataFormatError("PushBackReader format error");
   253     }
   254 
   255   };
   256 
   257   /// \ingroup item_io
   258   /// \brief Reader for parsed string.
   259   ///
   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.
   263   ///
   264   /// \author Balazs Dezso
   265   class ParsedStringReader {
   266   public:
   267     typedef std::string Value;
   268 
   269     /// \brief Constructor.
   270     ///
   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) {}
   275     
   276     
   277     /// \brief Reads the parsed string from the given stream.
   278     ///
   279     /// Reads the parsed string from the given stream.
   280     void read(std::istream& is, Value& value) const {
   281       char c;
   282       if (!(is >> c) || c != open) {
   283 	throw DataFormatError("ParsedStringReader format error");
   284       }
   285       value += c;
   286       int counter = 1;
   287       while (counter > 0 && is >> c) {
   288 	if (c == close) {
   289 	  --counter;
   290 	} else if (c == open) {
   291 	  ++counter;
   292 	}
   293 	value += c;
   294       }
   295       if (!is) {
   296 	throw DataFormatError("ParsedStrinReader format error");
   297       }
   298     }
   299 
   300   private:
   301     char open, close;
   302 
   303   };
   304 
   305   /// \ingroup item_io
   306   /// \brief Reader for read the whole line.
   307   ///
   308   /// Reader for read the whole line.
   309   ///
   310   /// \author Balazs Dezso
   311   class LineReader {
   312   public:
   313     typedef std::string Value;
   314 
   315     /// \brief Constructor.
   316     ///
   317     /// Constructor for the LineReader. If the given parameter is
   318     /// true then the spaces before the first not space character are
   319     /// skipped.
   320     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
   321     
   322     /// \brief Reads the line from the given stream.
   323     ///
   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");
   329       }
   330     }
   331   private:
   332     bool skipSpaces;
   333   };
   334 
   335   /// \ingroup item_io
   336   /// \brief Reader for std::pair.
   337   ///
   338   /// Reader for std::pair.
   339   ///
   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> >
   346   class PairReader {
   347   public:
   348     typedef _Pair Value;
   349 
   350     typedef _FirstReader FirstReader;
   351     typedef _SecondReader SecondReader;
   352 
   353   private:
   354 
   355     FirstReader first_reader;
   356     SecondReader second_reader;
   357 
   358   public:
   359     
   360     /// \brief Constructor.
   361     ///
   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) {}
   366     
   367     /// \brief Reads the pair from the given stream.
   368     ///
   369     /// Reads the pair from the given stream.
   370     void read(std::istream& is, Value& value) const {
   371       char c;
   372       if (!(is >> c) || c != '(') {
   373 	throw DataFormatError("PairReader format error");
   374       }
   375       first_reader.read(is, value.first);
   376       if (!(is >> c) || c != '=') {
   377 	throw DataFormatError("PairReader format error");
   378       }
   379       if (!(is >> c) || c != '>') {
   380 	throw DataFormatError("PairReader format error");
   381       }
   382       second_reader.read(is, value.second);
   383       if (!(is >> c) || c != ')') {
   384 	throw DataFormatError("PairReader format error");
   385       }
   386     }
   387   };
   388 
   389   /// \ingroup item_io
   390   /// 
   391   /// \brief The default item reader template class.
   392   ///
   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.
   395   ///
   396   /// \author Balazs Dezso
   397   template <typename _Value>
   398   class DefaultReader {
   399   public:
   400     /// The value type.
   401     typedef _Value Value;
   402     /// \brief Reads a value from the given stream.
   403     ///
   404     /// Reads a value from the given stream.
   405     void read(std::istream& is, Value& value) const {
   406       if (!(is >> value)) 
   407 	throw DataFormatError("DefaultReader format error");
   408     }
   409   };
   410 
   411   template <>
   412   class DefaultReader<std::string> {
   413   public:
   414     typedef std::string Value;
   415     
   416     void read(std::istream& is, Value& value) const {
   417       char c;
   418       if (!(is >> std::ws >> c)) return;
   419       is.putback(c);
   420       switch (c) {
   421       case '\"':
   422 	QuotedStringReader().read(is, value);
   423 	break;
   424       case '(':
   425 	ParsedStringReader().read(is, value);
   426 	break;
   427       case '[':
   428 	ParsedStringReader('[', ']').read(is, value);
   429 	break;
   430       case '/':
   431 	ParsedStringReader('/', '/').read(is, value);
   432 	break;
   433       default:
   434 	if (!(is >> value)) 
   435 	  throw DataFormatError("DefaultReader format error");
   436 	break;
   437       }
   438     }
   439     
   440   };
   441 
   442   template <typename Item>
   443   class DefaultReader<std::vector<Item> > 
   444     : public PushBackReader<std::vector<Item> > {};
   445 
   446   template <typename Item>
   447   class DefaultReader<std::deque<Item> > 
   448     : public PushBackReader<std::deque<Item> > {};
   449 
   450   template <typename Item>
   451   class DefaultReader<std::list<Item> > 
   452     : public PushBackReader<std::list<Item> > {};
   453 
   454   template <typename Item>
   455   class DefaultReader<std::set<Item> > 
   456     : public InsertReader<std::set<Item> > {};
   457 
   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> > > {};
   462 
   463   template <typename Item>
   464   class DefaultReader<std::multiset<Item> > 
   465     : public InsertReader<std::multiset<Item> > {};
   466 
   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> > > {};
   471 
   472   template <typename First, typename Second>
   473   class DefaultReader<std::pair<First, Second> > 
   474     : public PairReader<std::pair<First, Second> > {};
   475 
   476   /// \ingroup item_io
   477   /// 
   478   /// \brief The default item reader for skipping a value in the stream.
   479   ///
   480   /// The default item reader for skipping a value in the stream.
   481   ///
   482   /// \author Balazs Dezso
   483   class DefaultSkipper : public DefaultReader<std::string> {};
   484 
   485   /// \ingroup item_io  
   486   /// \brief Standard ReaderTraits for the GraphReader class.
   487   ///
   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 {
   492 
   493     template <typename _Value>
   494     struct Reader : DefaultReader<_Value> {};
   495 
   496     typedef DefaultSkipper Skipper;
   497 
   498   };
   499 
   500 }
   501 
   502 #endif