lemon/bits/item_reader.h
author deba
Tue, 30 Oct 2007 10:51:07 +0000
changeset 2504 46a82ce84cc6
parent 2391 14a343be7a5a
child 2553 bfced05fa852
permissions -rw-r--r--
Bug fix
     1 /* -*- C++ -*-
     2  *
     3  * This file is a part of LEMON, a generic C++ optimization library
     4  *
     5  * Copyright (C) 2003-2007
     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 #include <map>
    34 
    35 #include <lemon/error.h>
    36 
    37 namespace lemon {
    38   
    39   template <typename Value>
    40   class DefaultReader;
    41 
    42   /// \ingroup item_io
    43   ///
    44   /// \brief Reader class for unformatted strings.
    45   ///
    46   /// Reader class for unformatted strings. This class want to be
    47   /// a general reader type which can read the most 
    48   ///
    49   /// \author Balazs Dezso
    50   class UnformattedReader {
    51   public:
    52     /// \brief The value type of reader.
    53     ///
    54     /// The value type of reader.
    55     typedef std::string Value;
    56     
    57     /// \brief Constructor for the reader.
    58     ///
    59     /// Constructor for the reader.
    60     UnformattedReader() {} 
    61     
    62     /// \brief Reads an unformatted string from the given stream.
    63     ///
    64     /// Reads an unformatted string from the given stream.
    65     void read(std::istream& is, std::string& value) const {
    66       char c;
    67       value.clear();
    68       is >> std::ws;
    69       while (is.get(c) && !whiteSpace(c)) {
    70         processChar(c, is, value);
    71       }
    72     }
    73 
    74   private:
    75 
    76     void processChar(char c, std::istream& is, Value& value) const {
    77       switch (c) {
    78       case '(':
    79         is.putback(c);
    80         readParsed('(', ')', is, value);
    81         break;
    82       case '[':
    83         is.putback(c);
    84         readParsed('[', ']', is, value);
    85         break;
    86       case '{':
    87         is.putback(c);
    88         readParsed('{', '}', is, value);
    89         break;
    90       case '/':
    91         is.putback(c);
    92         readParsed('/', '/', is, value);
    93         break;
    94       case '\"':
    95         is.putback(c);
    96         readQuoted('\"', is, value);
    97         break;
    98       case '\'':
    99         is.putback(c);
   100         readQuoted('\'', is, value);
   101         break;
   102       default:
   103         value += c;
   104         break;
   105       }
   106     }
   107 
   108     void readParsed(char open, char close, 
   109                     std::istream& is, Value& value) const {
   110       char c;
   111       if (!is.get(c) || c != open)
   112 	throw DataFormatError("Unformatted string format error");
   113       value += c;
   114       while (is.get(c) && c != close) {
   115         processChar(c, is, value);
   116       }
   117       if (!is) 
   118         throw DataFormatError("Unformatted string format error");
   119       value += c;      
   120     }
   121 
   122     void readQuoted(char quote, std::istream& is, Value& value) const {
   123       char c;
   124       bool esc = false;
   125       if (!is.get(c) || c != quote)
   126 	throw DataFormatError("Unformatted string format error");
   127       value += c;
   128       while (is.get(c) && (c != quote || esc)) {
   129         if (c == '\\') esc = !esc;
   130         else esc = false;
   131         value += c;
   132       }
   133       if (!is) 
   134         throw DataFormatError("Unformatted string format error");
   135       value += c;
   136     }
   137 
   138 
   139 
   140     static bool whiteSpace(char c) {
   141       return c == ' ' || c == '\t' || c == '\v' || 
   142         c == '\n' || c == '\r' || c == '\f'; 
   143     }
   144 
   145     
   146   };
   147 
   148   /// \ingroup item_io
   149   ///
   150   /// \brief Reader class for quoted strings.
   151   ///
   152   /// Reader class for quoted strings. It can process the escape
   153   /// sequences in the string.
   154   ///
   155   /// \author Balazs Dezso
   156   class QuotedStringReader {
   157     friend class QuotedCharReader;
   158   public:
   159     /// \brief The value type of reader.
   160     ///
   161     /// The value type of reader.
   162     typedef std::string Value;
   163     
   164     /// \brief Constructor for the reader.
   165     ///
   166     /// Constructor for the reader. If the given parameter is true
   167     /// the reader processes the escape sequences.
   168     QuotedStringReader(bool _escaped = true) 
   169       : escaped(_escaped) {}
   170     
   171     /// \brief Reads a quoted string from the given stream.
   172     ///
   173     /// Reads a quoted string from the given stream.
   174     void read(std::istream& is, std::string& value) const {
   175       char c;
   176       value.clear();
   177       is >> std::ws;
   178       if (!is.get(c) || (c != '\"' && c != '\'')) 
   179 	throw DataFormatError("Quoted format error");
   180       char quote = c;
   181       while (is.get(c) && c != quote) {
   182 	if (escaped && c == '\\') {
   183 	  value += readEscape(is);
   184 	} else {
   185 	  value += c;
   186 	}
   187       }
   188       if (!is) throw DataFormatError("Quoted format error");
   189     }
   190 
   191   private:
   192     
   193     static char readEscape(std::istream& is) {
   194       char c;
   195       switch (is.get(c), c) {
   196       case '\\':
   197 	return '\\';
   198       case '\"':
   199 	return '\"';
   200       case '\'':
   201 	return '\'';
   202       case '\?':
   203 	return '\?';
   204       case 'a':
   205 	return '\a';
   206       case 'b':
   207 	return '\b';
   208       case 'f':
   209 	return '\f';
   210       case 'n':
   211 	return '\n';
   212       case 'r':
   213 	return '\r';
   214       case 't':
   215 	return '\t';
   216       case 'v':
   217 	return '\v';
   218       case 'x':
   219 	{
   220 	  int code;
   221 	  if (!is.get(c) || !isHex(c)) 
   222 	    throw DataFormatError("Escape format error");
   223 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
   224 	  else code = code * 16 + valueHex(c);
   225 	  return code;
   226 	}
   227       default:
   228 	{
   229 	  int code;
   230 	  if (!isOct(c)) 
   231 	    throw DataFormatError("Escape format error");
   232 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
   233 	    is.putback(c);
   234 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
   235 	    is.putback(c);
   236 	  else code = code * 8 + valueOct(c);
   237 	  return code;
   238 	}	      
   239       } 
   240     }
   241 
   242     static bool isOct(char c) {
   243       return '0' <= c && c <='7'; 
   244     }
   245     
   246     static int valueOct(char c) {
   247       return c - '0';
   248     }
   249 
   250    static bool isHex(char c) {
   251       return ('0' <= c && c <= '9') || 
   252 	('a' <= c && c <= 'z') || 
   253 	('A' <= c && c <= 'Z'); 
   254     }
   255     
   256     static int valueHex(char c) {
   257       if ('0' <= c && c <= '9') return c - '0';
   258       if ('a' <= c && c <= 'z') return c - 'a' + 10;
   259       return c - 'A' + 10;
   260     }
   261 
   262     bool escaped;
   263   };
   264 
   265   /// \ingroup item_io
   266   ///
   267   /// \brief Reader class for quoted strings.
   268   ///
   269   /// Reader class for quoted strings. It can process the escape
   270   /// sequences in the string.
   271   ///
   272   /// \author Balazs Dezso
   273   class QuotedCharReader {
   274   public:
   275     /// \brief The value type of reader.
   276     ///
   277     /// The value type of reader.
   278     typedef char Value;
   279     
   280     /// \brief Constructor for the reader.
   281     ///
   282     /// Constructor for the reader. If the given parameter is true
   283     /// the reader processes the escape sequences.
   284     QuotedCharReader(bool _escaped = true) 
   285       : escaped(_escaped) {}
   286     
   287     /// \brief Reads a quoted string from the given stream.
   288     ///
   289     /// Reads a quoted string from the given stream.
   290     void read(std::istream& is, char& value) const {
   291       char c;
   292       is >> std::ws;
   293       if (!is.get(c) || c != '\'') 
   294 	throw DataFormatError("Quoted format error");
   295       if (!is.get(c)) 
   296         throw DataFormatError("Quoted format error");
   297       if (escaped && c == '\\') {
   298         value = QuotedStringReader::readEscape(is);
   299       } else {
   300         value = c;
   301       }
   302       if (!is.get(c) || c != '\'') 
   303 	throw DataFormatError("Quoted format error");
   304     }
   305 
   306   private:
   307     bool escaped;
   308   };
   309 
   310   /// \ingroup item_io
   311   /// \brief Reader for standard containers.
   312   ///
   313   /// Reader for back insertable standard containers. The representation
   314   /// of the container is the values enumerated between an open and a
   315   /// close parse. 
   316   ///
   317   /// \author Balazs Dezso
   318   template <
   319     typename _Container, 
   320     typename _ItemReader = DefaultReader<typename _Container::value_type> 
   321   >
   322   class PushBackReader {
   323   public:
   324     typedef _Container Value;
   325     typedef _ItemReader ItemReader;
   326 
   327   private:
   328 
   329     ItemReader item_reader;
   330 
   331   public:
   332 
   333     /// \brief Constructor for InsertReader
   334     ///
   335     /// Constructor for InsertReader
   336     PushBackReader(const ItemReader& _item_reader = ItemReader())
   337       : item_reader(_item_reader) {}
   338 
   339     /// \brief Reads the values into the container from the given stream.
   340     ///
   341     /// Reads the values into the container from the given stream.
   342     void read(std::istream& is, Value& value) const {
   343       char c;
   344       if (!(is >> c) || c != '(') 
   345 	throw DataFormatError("PushBackReader format error");
   346       while (is >> c && c != ')') {
   347 	is.putback(c);
   348 	typename ItemReader::Value item;
   349 	item_reader.read(is, item);
   350 	value.push_back(item);
   351       }
   352       if (!is) throw DataFormatError("PushBackReader format error");
   353     }
   354 
   355   };
   356 
   357   /// \ingroup item_io
   358   ///
   359   /// \brief Reader for standard containers.
   360   ///
   361   /// Reader for insertable standard containers. The representation
   362   /// of the container is the values enumerated between an open and a
   363   /// close parse. 
   364   ///
   365   /// \author Balazs Dezso
   366   template <
   367     typename _Container, 
   368     typename _ItemReader = DefaultReader<typename _Container::value_type> 
   369   >
   370   class InsertReader {
   371   public:
   372     typedef _Container Value;
   373     typedef _ItemReader ItemReader;
   374 
   375   private:
   376 
   377     ItemReader item_reader;
   378 
   379   public:
   380 
   381     /// \brief Constructor for InsertReader
   382     ///
   383     /// Constructor for InsertReader
   384     InsertReader(const ItemReader& _item_reader = ItemReader())
   385       : item_reader(_item_reader) {}
   386 
   387     /// \brief Reads the values into the container from the given stream.
   388     ///
   389     /// Reads the values into the container from the given stream.
   390     void read(std::istream& is, Value& value) const {
   391       char c;
   392       if (!(is >> c) || c != '(') 
   393 	throw DataFormatError("InsertReader format error");
   394       while (is >> c && c != ')') {
   395 	is.putback(c);
   396 	typename ItemReader::Value item;
   397 	item_reader.read(is, item);
   398 	value.insert(item);
   399       }
   400       if (!is) throw DataFormatError("PushBackReader format error");
   401     }
   402 
   403   };
   404 
   405   /// \ingroup item_io
   406   /// \brief Reader for parsed string.
   407   ///
   408   /// Reader for parsed strings. You can define the open and close
   409   /// parse characters. It reads from the input a character sequence
   410   /// which is right parsed.
   411   ///
   412   /// \author Balazs Dezso
   413   class ParsedStringReader {
   414   public:
   415     typedef std::string Value;
   416 
   417     /// \brief Constructor.
   418     ///
   419     /// Constructor for ParsedStringReader. You can give as parameter
   420     /// the open and close parse characters.
   421     ParsedStringReader(char _open = '(', char _close = ')')
   422       : open(_open), close(_close) {}
   423     
   424     
   425     /// \brief Reads the parsed string from the given stream.
   426     ///
   427     /// Reads the parsed string from the given stream.
   428     void read(std::istream& is, Value& value) const {
   429       char c;
   430       value.clear();
   431       if (!(is >> c) || c != open) {
   432 	throw DataFormatError("ParsedStringReader format error");
   433       }
   434       value += c;
   435       int counter = 1;
   436       while (counter > 0 && is >> c) {
   437 	if (c == close) {
   438 	  --counter;
   439 	} else if (c == open) {
   440 	  ++counter;
   441 	}
   442 	value += c;
   443       }
   444       if (!is) {
   445 	throw DataFormatError("ParsedStrinReader format error");
   446       }
   447     }
   448 
   449   private:
   450     char open, close;
   451 
   452   };
   453 
   454   /// \ingroup item_io
   455   /// \brief Reader for read the whole line.
   456   ///
   457   /// Reader for read the whole line.
   458   ///
   459   /// \author Balazs Dezso
   460   class LineReader {
   461   public:
   462     typedef std::string Value;
   463 
   464     /// \brief Constructor.
   465     ///
   466     /// Constructor for the LineReader. If the given parameter is
   467     /// true then the spaces before the first not space character are
   468     /// skipped.
   469     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
   470     
   471     /// \brief Reads the line from the given stream.
   472     ///
   473     /// Reads the line from the given stream.
   474     void read(std::istream& is, Value& value) const {
   475       if (skipSpaces) is >> std::ws;
   476       if (!getline(is, value)) {
   477 	throw DataFormatError("LineReader format error");
   478       }
   479     }
   480   private:
   481     bool skipSpaces;
   482   };
   483 
   484   /// \ingroup item_io
   485   /// \brief Reader for std::pair.
   486   ///
   487   /// Reader for std::pair.
   488   ///
   489   /// \author Balazs Dezso
   490   template <typename _Pair, 
   491 	    typename _FirstReader = 
   492 	    DefaultReader<typename _Pair::first_type>,
   493 	    typename _SecondReader = 
   494 	    DefaultReader<typename _Pair::second_type> >
   495   class PairReader {
   496   public:
   497     typedef _Pair Value;
   498 
   499     typedef _FirstReader FirstReader;
   500     typedef _SecondReader SecondReader;
   501 
   502   private:
   503 
   504     FirstReader first_reader;
   505     SecondReader second_reader;
   506 
   507   public:
   508     
   509     /// \brief Constructor.
   510     ///
   511     /// Constructor for the PairReader.
   512     PairReader(const FirstReader& _first_reader = FirstReader(), 
   513 	       const SecondReader& _second_reader = SecondReader()) 
   514       : first_reader(_first_reader), second_reader(_second_reader) {}
   515     
   516     /// \brief Reads the pair from the given stream.
   517     ///
   518     /// Reads the pair from the given stream.
   519     void read(std::istream& is, Value& value) const {
   520       char c;
   521       if (!(is >> c) || c != '(') {
   522 	throw DataFormatError("PairReader format error");
   523       }
   524       first_reader.read(is, value.first);
   525       if (!(is >> c) || c != '=') {
   526 	throw DataFormatError("PairReader format error");
   527       }
   528       if (!(is >> c) || c != '>') {
   529 	throw DataFormatError("PairReader format error");
   530       }
   531       second_reader.read(is, value.second);
   532       if (!(is >> c) || c != ')') {
   533 	throw DataFormatError("PairReader format error");
   534       }
   535     }
   536   };
   537 
   538   /// \ingroup item_io
   539   /// 
   540   /// \brief The default item reader template class.
   541   ///
   542   /// The default item reader template class. If some section reader
   543   /// needs to read a value from a stream it will give the default way for it.
   544   ///
   545   /// \author Balazs Dezso
   546   template <typename _Value>
   547   class DefaultReader {
   548   public:
   549     /// The value type.
   550     typedef _Value Value;
   551     /// \brief Reads a value from the given stream.
   552     ///
   553     /// Reads a value from the given stream.
   554     void read(std::istream& is, Value& value) const {
   555       if (!(is >> value)) 
   556 	throw DataFormatError("DefaultReader format error");
   557     }
   558   };
   559 
   560   template <>
   561   class DefaultReader<std::string> {
   562   public:
   563     typedef std::string Value;
   564     
   565     void read(std::istream& is, Value& value) const {
   566       char c;
   567       if (!(is >> std::ws >> c)) 
   568         throw DataFormatError("DefaultReader<string> format error");
   569       is.putback(c);
   570       switch (c) {
   571       case '\"':
   572 	QuotedStringReader().read(is, value);
   573 	break;
   574       default:
   575         UnformattedReader().read(is, value);
   576 	break;
   577       }
   578     }
   579     
   580   };
   581 
   582   template <>
   583   class DefaultReader<char> {
   584   public:
   585     typedef char Value;
   586     
   587     void read(std::istream& is, Value& value) const {
   588       char c;
   589       if (!(is >> std::ws >> c))
   590         throw DataFormatError("DefaultReader<char> format error");
   591       is.putback(c);
   592       switch (c) {
   593       case '\'':
   594 	QuotedCharReader().read(is, value);
   595 	break;
   596       default:
   597         { 
   598           int temp;          
   599           if (!(is >> temp)) 
   600             throw DataFormatError("DefaultReader<char> format error");
   601           value = static_cast<char>(temp);
   602           break;
   603         }
   604       }
   605     }    
   606   };
   607 
   608   template <>
   609   class DefaultReader<bool> {
   610   public:
   611     typedef bool Value;
   612     
   613     void read(std::istream& is, Value& value) const {
   614       std::string rep;
   615       if (!(is >> rep))
   616         throw DataFormatError("DefaultReader<bool> format error");
   617       if (rep == "true" || rep == "t" || rep == "1") {
   618         value = true;
   619       } else if (rep == "false" || rep == "f" || rep == "0") {
   620         value = false;
   621       } else throw DataFormatError("DefaultReader<bool> format error");
   622     }    
   623   };
   624 
   625   template <typename Item>
   626   class DefaultReader<std::vector<Item> > 
   627     : public PushBackReader<std::vector<Item> > {};
   628 
   629   template <typename Item>
   630   class DefaultReader<std::deque<Item> > 
   631     : public PushBackReader<std::deque<Item> > {};
   632 
   633   template <typename Item>
   634   class DefaultReader<std::list<Item> > 
   635     : public PushBackReader<std::list<Item> > {};
   636 
   637   template <typename Item>
   638   class DefaultReader<std::set<Item> > 
   639     : public InsertReader<std::set<Item> > {};
   640 
   641   template <typename Key, typename Value>
   642   class DefaultReader<std::map<Key, Value> > 
   643     : public InsertReader<std::map<Key, Value>,
   644 			  DefaultReader<std::pair<Key, Value> > > {};
   645 
   646   template <typename Item>
   647   class DefaultReader<std::multiset<Item> > 
   648     : public InsertReader<std::multiset<Item> > {};
   649 
   650   template <typename Key, typename Value>
   651   class DefaultReader<std::multimap<Key, Value> > 
   652     : public InsertReader<std::multimap<Key, Value>,
   653 			  DefaultReader<std::pair<Key, Value> > > {};
   654 
   655   template <typename First, typename Second>
   656   class DefaultReader<std::pair<First, Second> > 
   657     : public PairReader<std::pair<First, Second> > {};
   658 
   659   /// \ingroup item_io
   660   /// 
   661   /// \brief The default item reader for skipping a value in the stream.
   662   ///
   663   /// The default item reader for skipping a value in the stream.
   664   ///
   665   /// \author Balazs Dezso
   666   class DefaultSkipper : public UnformattedReader {};
   667 
   668   /// \ingroup item_io  
   669   /// \brief Standard ReaderTraits for the GraphReader class.
   670   ///
   671   /// Standard ReaderTraits for the GraphReader class.
   672   /// It defines standard reading method for all type of value. 
   673   /// \author Balazs Dezso
   674   struct DefaultReaderTraits {
   675 
   676     template <typename _Value>
   677     struct Reader : DefaultReader<_Value> {};
   678 
   679     typedef DefaultSkipper Skipper;
   680 
   681   };
   682 
   683 }
   684 
   685 #endif