src/lemon/bits/item_reader.h
changeset 1408 892c29484414
child 1415 2a5810c2f806
equal deleted inserted replaced
-1:000000000000 0:5b8b5ec8a1da
       
     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 /// \ingroup io_group
       
    18 /// \file
       
    19 /// \brief Item reader bits for lemon input.
       
    20 
       
    21 #ifndef LEMON_BITS_ITEM_READER_H
       
    22 #define LEMON_BITS_ITEM_READER_H
       
    23 
       
    24 #include <iostream>
       
    25 #include <string>
       
    26 
       
    27 #include <vector>
       
    28 #include <deque>
       
    29 #include <list>
       
    30 #include <set>
       
    31 
       
    32 namespace lemon {
       
    33   
       
    34   template <typename Value>
       
    35   class DefaultReader;
       
    36 
       
    37   /// \ingroup io_group
       
    38   ///
       
    39   /// \brief Reader class for quoted strings.
       
    40   ///
       
    41   /// Reader class for quoted strings. It can process the escape
       
    42   /// sequences in the string.
       
    43   ///
       
    44   /// \author Balazs Dezso
       
    45   class QuotedStringReader {
       
    46   public:
       
    47     /// \brief The value type of reader.
       
    48     ///
       
    49     /// The value type of reader.
       
    50     typedef std::string Value;
       
    51     
       
    52     /// \brief Constructor for the reader.
       
    53     ///
       
    54     /// Constructor for the reader. If the given parameter is true
       
    55     /// the reader processes the escape sequences.
       
    56     QuotedStringReader(bool _escaped = true) 
       
    57       : escaped(_escaped) {}
       
    58     
       
    59     /// \brief Reads a quoted string from the given stream.
       
    60     ///
       
    61     /// Reads a quoted string from the given stream.
       
    62     void read(std::istream& is, std::string& value) const {
       
    63       char c;
       
    64       value.clear();
       
    65       is >> std::ws;
       
    66       if (!is.get(c) || c != '\"') 
       
    67 	throw DataFormatError("Quoted string format error");
       
    68       while (is.get(c) && c != '\"') {
       
    69 	if (escaped && c == '\\') {
       
    70 	  value += readEscape(is);
       
    71 	} else {
       
    72 	  value += c;
       
    73 	}
       
    74       }
       
    75       if (!is) throw DataFormatError("Quoted string format error");
       
    76     }
       
    77 
       
    78   private:
       
    79     
       
    80     static char readEscape(std::istream& is) {
       
    81       char c;
       
    82       switch (is.get(c), c) {
       
    83       case '\\':
       
    84 	return '\\';
       
    85       case '\"':
       
    86 	return '\"';
       
    87       case '\'':
       
    88 	return '\'';
       
    89       case '\?':
       
    90 	return '\?';
       
    91       case 'a':
       
    92 	return '\a';
       
    93       case 'b':
       
    94 	return '\b';
       
    95       case 'f':
       
    96 	return '\f';
       
    97       case 'n':
       
    98 	return '\n';
       
    99       case 'r':
       
   100 	return '\r';
       
   101       case 't':
       
   102 	return '\t';
       
   103       case 'v':
       
   104 	return '\v';
       
   105       case 'x':
       
   106 	{
       
   107 	  int code;
       
   108 	  if (!is.get(c) || !isHex(c)) 
       
   109 	    throw DataFormatError("Escape format error");
       
   110 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
       
   111 	  else code = code * 16 + valueHex(c);
       
   112 	  return code;
       
   113 	}
       
   114       default:
       
   115 	{
       
   116 	  int code;
       
   117 	  if (!isOct(c)) 
       
   118 	    throw DataFormatError("Escape format error");
       
   119 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
       
   120 	    is.putback(c);
       
   121 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
       
   122 	    is.putback(c);
       
   123 	  else code = code * 8 + valueOct(c);
       
   124 	  return code;
       
   125 	}	      
       
   126       } 
       
   127     }
       
   128 
       
   129     static bool isOct(char c) {
       
   130       return '0' <= c && c <='7'; 
       
   131     }
       
   132     
       
   133     static int valueOct(char c) {
       
   134       return c - '0';
       
   135     }
       
   136 
       
   137    static bool isHex(char c) {
       
   138       return ('0' <= c && c <= '9') || 
       
   139 	('a' <= c && c <= 'z') || 
       
   140 	('A' <= c && c <= 'Z'); 
       
   141     }
       
   142     
       
   143     static int valueHex(char c) {
       
   144       if ('0' <= c && c <= '9') return c - '0';
       
   145       if ('a' <= c && c <= 'z') return c - 'a' + 10;
       
   146       return c - 'A' + 10;
       
   147     }
       
   148 
       
   149     bool escaped;
       
   150   };
       
   151 
       
   152   /// \ingroup io_group
       
   153   /// \brief Reader for standard containers.
       
   154   ///
       
   155   /// Reader for back insertable standard containers. The representation
       
   156   /// of the container is the values enumerated between an open and a
       
   157   /// close parse. 
       
   158   ///
       
   159   /// \author Balazs Dezso
       
   160   template <
       
   161     typename _Container, 
       
   162     typename _ItemReader = DefaultReader<typename _Container::value_type> 
       
   163   >
       
   164   class PushBackReader {
       
   165   public:
       
   166     typedef _Container Value;
       
   167     typedef _ItemReader ItemReader;
       
   168 
       
   169   private:
       
   170 
       
   171     ItemReader item_reader;
       
   172 
       
   173   public:
       
   174 
       
   175     /// \brief Reads the values into the container from the given stream.
       
   176     ///
       
   177     /// Reads the values into the container from the given stream.
       
   178     void read(std::istream& is, Value& value) const {
       
   179       char c;
       
   180       if (!(is >> c) || c != '(') 
       
   181 	throw DataFormatError("PushBackReader format error");
       
   182       while (is >> c && c != ')') {
       
   183 	is.putback(c);
       
   184 	typename ItemReader::Value item;
       
   185 	item_reader.read(is, item);
       
   186 	value.push_back(item);
       
   187       }
       
   188       if (!is) throw DataFormatError("PushBackReader format error");
       
   189       is.putback(c);
       
   190     }
       
   191 
       
   192   };
       
   193 
       
   194   /// \ingroup io_group
       
   195   ///
       
   196   /// \brief Reader for standard containers.
       
   197   ///
       
   198   /// Reader for insertable standard containers. The representation
       
   199   /// of the container is the values enumerated between an open and a
       
   200   /// close parse. 
       
   201   ///
       
   202   /// \author Balazs Dezso
       
   203   template <
       
   204     typename _Container, 
       
   205     typename _ItemReader = DefaultReader<typename _Container::value_type> 
       
   206   >
       
   207   class InsertReader {
       
   208   public:
       
   209     typedef _Container Value;
       
   210     typedef _ItemReader ItemReader;
       
   211 
       
   212   private:
       
   213 
       
   214     ItemReader item_reader;
       
   215 
       
   216   public:
       
   217 
       
   218     /// \brief Reads the values into the container from the given stream.
       
   219     ///
       
   220     /// Reads the values into the container from the given stream.
       
   221     void read(std::istream& is, Value& value) const {
       
   222       char c;
       
   223       if (!(is >> c) || c != '(') 
       
   224 	throw DataFormatError("InsertReader format error");
       
   225       while (is >> c && c != ')') {
       
   226 	is.putback(c);
       
   227 	typename ItemReader::Value item;
       
   228 	item_reader.read(is, item);
       
   229 	value.insert(item);
       
   230       }
       
   231       if (!is) throw DataFormatError("PushBackReader format error");
       
   232       is.putback(c);
       
   233     }
       
   234 
       
   235   };
       
   236 
       
   237   /// \ingroup io_group
       
   238   /// \brief Reader for parsed string.
       
   239   ///
       
   240   /// Reader for parsed strings. You can give the open and close
       
   241   /// parse characters.
       
   242   ///
       
   243   /// \author Balazs Dezso
       
   244   class ParsedStringReader {
       
   245   public:
       
   246     typedef std::string Value;
       
   247 
       
   248     /// \brief Constructor.
       
   249     ///
       
   250     /// Constructor for ParsedStringReader. You can give as parameter
       
   251     /// the open and close parse characters.
       
   252     ParsedStringReader(char _open = '(', char _close = ')')
       
   253       : open(_open), close(_close) {}
       
   254     
       
   255     
       
   256     /// \brief Reads the parsed string from the given stream.
       
   257     ///
       
   258     /// Reads the parsed string from the given stream.
       
   259     void read(std::istream& is, Value& value) const {
       
   260       char c;
       
   261       if (!(is >> c) || c != open) {
       
   262 	throw DataFormatError("ParsedStringReader format error");
       
   263       }
       
   264       value += c;
       
   265       int counter = 1;
       
   266       while (counter > 0 && is >> c) {
       
   267 	if (c == close) {
       
   268 	  --counter;
       
   269 	} else if (c == open) {
       
   270 	  ++counter;
       
   271 	}
       
   272 	value += c;
       
   273       }
       
   274       if (!is) {
       
   275 	throw DataFormatError("ParsedStrinReader format error");
       
   276       }
       
   277     }
       
   278 
       
   279   private:
       
   280     char open, close;
       
   281 
       
   282   };
       
   283 
       
   284   /// \ingroup io_group
       
   285   /// \brief Reader for read the whole line.
       
   286   ///
       
   287   /// Reader for read the whole line.
       
   288   ///
       
   289   /// \author Balazs Dezso
       
   290   class LineReader {
       
   291   public:
       
   292     typedef std::string Value;
       
   293 
       
   294     /// \brief Constructor.
       
   295     ///
       
   296     /// Constructor for the LineReader. If the given parameter is
       
   297     /// true then the spaces before the first not space character are
       
   298     /// skipped.
       
   299     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
       
   300     
       
   301     /// \brief Reads the line from the given stream.
       
   302     ///
       
   303     /// Reads the line from the given stream.
       
   304     void read(std::istream& is, Value& value) {
       
   305       if (skipSpaces) is >> std::ws;
       
   306       if (!getline(is, value)) {
       
   307 	throw DataFormatError("LineReader forma error");
       
   308       }
       
   309     }
       
   310   private:
       
   311     bool skipSpaces;
       
   312   };
       
   313 
       
   314   /// \ingroup io_group
       
   315   /// 
       
   316   /// \brief The default item reader template class.
       
   317   ///
       
   318   /// The default item reader template class. If some section reader
       
   319   /// needs to read a value from a stream it will give the default way for it.
       
   320   ///
       
   321   /// \author Balazs Dezso
       
   322   template <typename _Value>
       
   323   class DefaultReader {
       
   324   public:
       
   325     /// The value type.
       
   326     typedef _Value Value;
       
   327     /// \brief Reads a value from the given stream.
       
   328     ///
       
   329     /// Reads a value from the given stream.
       
   330     void read(std::istream& is, Value& value) const {
       
   331       if (!(is >> value)) 
       
   332 	throw DataFormatError("DefaultReader format error");
       
   333     }
       
   334   };
       
   335 
       
   336   template <typename Item>
       
   337   class DefaultReader<std::vector<Item> > 
       
   338     : public PushBackReader<std::vector<Item> > {};
       
   339 
       
   340   template <typename Item>
       
   341   class DefaultReader<std::deque<Item> > 
       
   342     : public PushBackReader<std::deque<Item> > {};
       
   343 
       
   344   template <typename Item>
       
   345   class DefaultReader<std::list<Item> > 
       
   346     : public PushBackReader<std::list<Item> > {};
       
   347 
       
   348   template <typename Item>
       
   349   class DefaultReader<std::set<Item> > 
       
   350     : public InsertReader<std::set<Item> > {};
       
   351 
       
   352   template <typename Item>
       
   353   class DefaultReader<std::multiset<Item> > 
       
   354     : public InsertReader<std::multiset<Item> > {};
       
   355 
       
   356   /// \ingroup io_group
       
   357   class DefaultSkipper {
       
   358   public:
       
   359     typedef std::string Value;
       
   360     
       
   361     void read(std::istream& is, Value& value) const {
       
   362       char c;
       
   363       if (!(is >> c)) return;
       
   364       is.putback(c);
       
   365       switch (c) {
       
   366       case '\"':
       
   367 	QuotedStringReader().read(is, value);
       
   368 	break;
       
   369       case '(':
       
   370 	ParsedStringReader().read(is, value);
       
   371 	break;
       
   372       default:
       
   373 	DefaultReader<std::string>().read(is, value); 
       
   374 	break;
       
   375       }
       
   376     }
       
   377   };
       
   378   
       
   379   /// \brief Standard ReaderTraits for the GraphReader class.
       
   380   ///
       
   381   /// Standard ReaderTraits for the GraphReader class.
       
   382   /// It defines standard reading method for all type of value. 
       
   383   /// \author Balazs Dezso
       
   384   struct DefaultReaderTraits {
       
   385 
       
   386     template <typename _Value>
       
   387     struct Reader : DefaultReader<_Value> {};
       
   388 
       
   389     typedef DefaultSkipper Skipper;
       
   390 
       
   391   };
       
   392 
       
   393 }
       
   394 
       
   395 #endif