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