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