lemon/bits/item_reader.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 1956 a055123339d5
child 2254 50cb2b90daa9
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
     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