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