src/lemon/bits/item_reader.h
changeset 1435 8e85e6bbefdf
parent 1427 14c75970840e
equal deleted inserted replaced
3:af6571a083e8 -1:000000000000
     1 /* -*- C++ -*-
       
     2  * src/lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
       
     3  *
       
     4  * Copyright (C) 2005 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 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       is.putback(c);
       
   198     }
       
   199 
       
   200   };
       
   201 
       
   202   /// \ingroup item_io
       
   203   ///
       
   204   /// \brief Reader for standard containers.
       
   205   ///
       
   206   /// Reader for insertable standard containers. The representation
       
   207   /// of the container is the values enumerated between an open and a
       
   208   /// close parse. 
       
   209   ///
       
   210   /// \author Balazs Dezso
       
   211   template <
       
   212     typename _Container, 
       
   213     typename _ItemReader = DefaultReader<typename _Container::value_type> 
       
   214   >
       
   215   class InsertReader {
       
   216   public:
       
   217     typedef _Container Value;
       
   218     typedef _ItemReader ItemReader;
       
   219 
       
   220   private:
       
   221 
       
   222     ItemReader item_reader;
       
   223 
       
   224   public:
       
   225 
       
   226     /// \brief Reads the values into the container from the given stream.
       
   227     ///
       
   228     /// Reads the values into the container from the given stream.
       
   229     void read(std::istream& is, Value& value) const {
       
   230       char c;
       
   231       if (!(is >> c) || c != '(') 
       
   232 	throw DataFormatError("InsertReader format error");
       
   233       while (is >> c && c != ')') {
       
   234 	is.putback(c);
       
   235 	typename ItemReader::Value item;
       
   236 	item_reader.read(is, item);
       
   237 	value.insert(item);
       
   238       }
       
   239       if (!is) throw DataFormatError("PushBackReader format error");
       
   240       is.putback(c);
       
   241     }
       
   242 
       
   243   };
       
   244 
       
   245   /// \ingroup item_io
       
   246   /// \brief Reader for parsed string.
       
   247   ///
       
   248   /// Reader for parsed strings. You can give the open and close
       
   249   /// parse characters.
       
   250   ///
       
   251   /// \author Balazs Dezso
       
   252   class ParsedStringReader {
       
   253   public:
       
   254     typedef std::string Value;
       
   255 
       
   256     /// \brief Constructor.
       
   257     ///
       
   258     /// Constructor for ParsedStringReader. You can give as parameter
       
   259     /// the open and close parse characters.
       
   260     ParsedStringReader(char _open = '(', char _close = ')')
       
   261       : open(_open), close(_close) {}
       
   262     
       
   263     
       
   264     /// \brief Reads the parsed string from the given stream.
       
   265     ///
       
   266     /// Reads the parsed string from the given stream.
       
   267     void read(std::istream& is, Value& value) const {
       
   268       char c;
       
   269       if (!(is >> c) || c != open) {
       
   270 	throw DataFormatError("ParsedStringReader format error");
       
   271       }
       
   272       value += c;
       
   273       int counter = 1;
       
   274       while (counter > 0 && is >> c) {
       
   275 	if (c == close) {
       
   276 	  --counter;
       
   277 	} else if (c == open) {
       
   278 	  ++counter;
       
   279 	}
       
   280 	value += c;
       
   281       }
       
   282       if (!is) {
       
   283 	throw DataFormatError("ParsedStrinReader format error");
       
   284       }
       
   285     }
       
   286 
       
   287   private:
       
   288     char open, close;
       
   289 
       
   290   };
       
   291 
       
   292   /// \ingroup item_io
       
   293   /// \brief Reader for read the whole line.
       
   294   ///
       
   295   /// Reader for read the whole line.
       
   296   ///
       
   297   /// \author Balazs Dezso
       
   298   class LineReader {
       
   299   public:
       
   300     typedef std::string Value;
       
   301 
       
   302     /// \brief Constructor.
       
   303     ///
       
   304     /// Constructor for the LineReader. If the given parameter is
       
   305     /// true then the spaces before the first not space character are
       
   306     /// skipped.
       
   307     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
       
   308     
       
   309     /// \brief Reads the line from the given stream.
       
   310     ///
       
   311     /// Reads the line from the given stream.
       
   312     void read(std::istream& is, Value& value) {
       
   313       if (skipSpaces) is >> std::ws;
       
   314       if (!getline(is, value)) {
       
   315 	throw DataFormatError("LineReader forma error");
       
   316       }
       
   317     }
       
   318   private:
       
   319     bool skipSpaces;
       
   320   };
       
   321 
       
   322   /// \ingroup item_io
       
   323   /// 
       
   324   /// \brief The default item reader template class.
       
   325   ///
       
   326   /// The default item reader template class. If some section reader
       
   327   /// needs to read a value from a stream it will give the default way for it.
       
   328   ///
       
   329   /// \author Balazs Dezso
       
   330   template <typename _Value>
       
   331   class DefaultReader {
       
   332   public:
       
   333     /// The value type.
       
   334     typedef _Value Value;
       
   335     /// \brief Reads a value from the given stream.
       
   336     ///
       
   337     /// Reads a value from the given stream.
       
   338     void read(std::istream& is, Value& value) const {
       
   339       if (!(is >> value)) 
       
   340 	throw DataFormatError("DefaultReader format error");
       
   341     }
       
   342   };
       
   343 
       
   344   template <>
       
   345   class DefaultReader<std::string> {
       
   346   public:
       
   347     typedef std::string Value;
       
   348     
       
   349     void read(std::istream& is, Value& value) const {
       
   350       char c;
       
   351       if (!(is >> std::ws >> c)) return;
       
   352       is.putback(c);
       
   353       switch (c) {
       
   354       case '\"':
       
   355 	QuotedStringReader().read(is, value);
       
   356 	break;
       
   357       case '(':
       
   358 	ParsedStringReader().read(is, value);
       
   359 	break;
       
   360       default:
       
   361 	is >> value; 
       
   362 	break;
       
   363       }
       
   364     }
       
   365     
       
   366   };
       
   367 
       
   368   template <typename Item>
       
   369   class DefaultReader<std::vector<Item> > 
       
   370     : public PushBackReader<std::vector<Item> > {};
       
   371 
       
   372   template <typename Item>
       
   373   class DefaultReader<std::deque<Item> > 
       
   374     : public PushBackReader<std::deque<Item> > {};
       
   375 
       
   376   template <typename Item>
       
   377   class DefaultReader<std::list<Item> > 
       
   378     : public PushBackReader<std::list<Item> > {};
       
   379 
       
   380   template <typename Item>
       
   381   class DefaultReader<std::set<Item> > 
       
   382     : public InsertReader<std::set<Item> > {};
       
   383 
       
   384   template <typename Item>
       
   385   class DefaultReader<std::multiset<Item> > 
       
   386     : public InsertReader<std::multiset<Item> > {};
       
   387 
       
   388   /// \ingroup item_io
       
   389   /// 
       
   390   /// \brief The default item reader for skipping a value in the stream.
       
   391   ///
       
   392   /// The default item reader for skipping a value in the stream.
       
   393   ///
       
   394   /// \author Balazs Dezso
       
   395   class DefaultSkipper : public DefaultReader<std::string> {};
       
   396 
       
   397   /// \ingroup item_io  
       
   398   /// \brief Standard ReaderTraits for the GraphReader class.
       
   399   ///
       
   400   /// Standard ReaderTraits for the GraphReader class.
       
   401   /// It defines standard reading method for all type of value. 
       
   402   /// \author Balazs Dezso
       
   403   struct DefaultReaderTraits {
       
   404 
       
   405     template <typename _Value>
       
   406     struct Reader : DefaultReader<_Value> {};
       
   407 
       
   408     typedef DefaultSkipper Skipper;
       
   409 
       
   410   };
       
   411 
       
   412 }
       
   413 
       
   414 #endif