src/lemon/bits/item_reader.h
author deba
Mon, 09 May 2005 11:24:26 +0000
changeset 1408 892c29484414
child 1415 2a5810c2f806
permissions -rw-r--r--
New graph reader interface.
     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