deba@1408: /* -*- C++ -*-
deba@1408:  *
alpar@1956:  * This file is a part of LEMON, a generic C++ optimization library
alpar@1956:  *
alpar@1956:  * Copyright (C) 2003-2006
alpar@1956:  * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1956:  * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@1408:  *
deba@1408:  * Permission to use, modify and distribute this software is granted
deba@1408:  * provided that this copyright notice appears in all copies. For
deba@1408:  * precise terms see the accompanying LICENSE file.
deba@1408:  *
deba@1408:  * This software is provided "AS IS" with no warranty of any kind,
deba@1408:  * express or implied, and with no claim as to its suitability for any
deba@1408:  * purpose.
deba@1408:  *
deba@1408:  */
deba@1408: 
alpar@1946: /// \ingroup item_io
deba@1408: /// \file
deba@1408: /// \brief Item reader bits for lemon input.
deba@1408: 
deba@1408: #ifndef LEMON_BITS_ITEM_READER_H
deba@1408: #define LEMON_BITS_ITEM_READER_H
deba@1408: 
deba@1408: #include <iostream>
deba@1408: #include <string>
deba@1408: 
deba@1408: #include <vector>
deba@1408: #include <deque>
deba@1408: #include <list>
deba@1408: #include <set>
deba@1408: 
deba@1408: namespace lemon {
deba@1408:   
deba@1408:   template <typename Value>
deba@1408:   class DefaultReader;
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1408:   ///
deba@1408:   /// \brief Reader class for quoted strings.
deba@1408:   ///
deba@1408:   /// Reader class for quoted strings. It can process the escape
deba@1408:   /// sequences in the string.
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   class QuotedStringReader {
deba@1408:   public:
deba@1408:     /// \brief The value type of reader.
deba@1408:     ///
deba@1408:     /// The value type of reader.
deba@1408:     typedef std::string Value;
deba@1408:     
deba@1408:     /// \brief Constructor for the reader.
deba@1408:     ///
deba@1408:     /// Constructor for the reader. If the given parameter is true
deba@1408:     /// the reader processes the escape sequences.
deba@1408:     QuotedStringReader(bool _escaped = true) 
deba@1408:       : escaped(_escaped) {}
deba@1408:     
deba@1408:     /// \brief Reads a quoted string from the given stream.
deba@1408:     ///
deba@1408:     /// Reads a quoted string from the given stream.
deba@1408:     void read(std::istream& is, std::string& value) const {
deba@1408:       char c;
deba@1408:       value.clear();
deba@1408:       is >> std::ws;
deba@1408:       if (!is.get(c) || c != '\"') 
deba@1408: 	throw DataFormatError("Quoted string format error");
deba@1408:       while (is.get(c) && c != '\"') {
deba@1408: 	if (escaped && c == '\\') {
deba@1408: 	  value += readEscape(is);
deba@1408: 	} else {
deba@1408: 	  value += c;
deba@1408: 	}
deba@1408:       }
deba@1408:       if (!is) throw DataFormatError("Quoted string format error");
deba@1408:     }
deba@1408: 
deba@1408:   private:
deba@1408:     
deba@1408:     static char readEscape(std::istream& is) {
deba@1408:       char c;
deba@1408:       switch (is.get(c), c) {
deba@1408:       case '\\':
deba@1408: 	return '\\';
deba@1408:       case '\"':
deba@1408: 	return '\"';
deba@1408:       case '\'':
deba@1408: 	return '\'';
deba@1408:       case '\?':
deba@1408: 	return '\?';
deba@1408:       case 'a':
deba@1408: 	return '\a';
deba@1408:       case 'b':
deba@1408: 	return '\b';
deba@1408:       case 'f':
deba@1408: 	return '\f';
deba@1408:       case 'n':
deba@1408: 	return '\n';
deba@1408:       case 'r':
deba@1408: 	return '\r';
deba@1408:       case 't':
deba@1408: 	return '\t';
deba@1408:       case 'v':
deba@1408: 	return '\v';
deba@1408:       case 'x':
deba@1408: 	{
deba@1408: 	  int code;
deba@1408: 	  if (!is.get(c) || !isHex(c)) 
deba@1408: 	    throw DataFormatError("Escape format error");
deba@1408: 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
deba@1408: 	  else code = code * 16 + valueHex(c);
deba@1408: 	  return code;
deba@1408: 	}
deba@1408:       default:
deba@1408: 	{
deba@1408: 	  int code;
deba@1408: 	  if (!isOct(c)) 
deba@1408: 	    throw DataFormatError("Escape format error");
deba@1408: 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408: 	    is.putback(c);
deba@1408: 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
deba@1408: 	    is.putback(c);
deba@1408: 	  else code = code * 8 + valueOct(c);
deba@1408: 	  return code;
deba@1408: 	}	      
deba@1408:       } 
deba@1408:     }
deba@1408: 
deba@1408:     static bool isOct(char c) {
deba@1408:       return '0' <= c && c <='7'; 
deba@1408:     }
deba@1408:     
deba@1408:     static int valueOct(char c) {
deba@1408:       return c - '0';
deba@1408:     }
deba@1408: 
deba@1408:    static bool isHex(char c) {
deba@1408:       return ('0' <= c && c <= '9') || 
deba@1408: 	('a' <= c && c <= 'z') || 
deba@1408: 	('A' <= c && c <= 'Z'); 
deba@1408:     }
deba@1408:     
deba@1408:     static int valueHex(char c) {
deba@1408:       if ('0' <= c && c <= '9') return c - '0';
deba@1408:       if ('a' <= c && c <= 'z') return c - 'a' + 10;
deba@1408:       return c - 'A' + 10;
deba@1408:     }
deba@1408: 
deba@1408:     bool escaped;
deba@1408:   };
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1408:   /// \brief Reader for standard containers.
deba@1408:   ///
deba@1408:   /// Reader for back insertable standard containers. The representation
deba@1408:   /// of the container is the values enumerated between an open and a
deba@1408:   /// close parse. 
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   template <
deba@1408:     typename _Container, 
deba@1408:     typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408:   >
deba@1408:   class PushBackReader {
deba@1408:   public:
deba@1408:     typedef _Container Value;
deba@1408:     typedef _ItemReader ItemReader;
deba@1408: 
deba@1408:   private:
deba@1408: 
deba@1408:     ItemReader item_reader;
deba@1408: 
deba@1408:   public:
deba@1408: 
deba@1852:     /// \brief Constructor for InsertReader
deba@1852:     ///
deba@1852:     /// Constructor for InsertReader
deba@1852:     PushBackReader(const ItemReader& _item_reader = ItemReader())
deba@1852:       : item_reader(_item_reader) {}
deba@1852: 
deba@1408:     /// \brief Reads the values into the container from the given stream.
deba@1408:     ///
deba@1408:     /// Reads the values into the container from the given stream.
deba@1408:     void read(std::istream& is, Value& value) const {
deba@1408:       char c;
deba@1408:       if (!(is >> c) || c != '(') 
deba@1408: 	throw DataFormatError("PushBackReader format error");
deba@1408:       while (is >> c && c != ')') {
deba@1408: 	is.putback(c);
deba@1408: 	typename ItemReader::Value item;
deba@1408: 	item_reader.read(is, item);
deba@1408: 	value.push_back(item);
deba@1408:       }
deba@1408:       if (!is) throw DataFormatError("PushBackReader format error");
deba@1408:     }
deba@1408: 
deba@1408:   };
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1408:   ///
deba@1408:   /// \brief Reader for standard containers.
deba@1408:   ///
deba@1408:   /// Reader for insertable standard containers. The representation
deba@1408:   /// of the container is the values enumerated between an open and a
deba@1408:   /// close parse. 
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   template <
deba@1408:     typename _Container, 
deba@1408:     typename _ItemReader = DefaultReader<typename _Container::value_type> 
deba@1408:   >
deba@1408:   class InsertReader {
deba@1408:   public:
deba@1408:     typedef _Container Value;
deba@1408:     typedef _ItemReader ItemReader;
deba@1408: 
deba@1408:   private:
deba@1408: 
deba@1408:     ItemReader item_reader;
deba@1408: 
deba@1408:   public:
deba@1408: 
deba@1852:     /// \brief Constructor for InsertReader
deba@1852:     ///
deba@1852:     /// Constructor for InsertReader
deba@1852:     InsertReader(const ItemReader& _item_reader = ItemReader())
deba@1852:       : item_reader(_item_reader) {}
deba@1852: 
deba@1408:     /// \brief Reads the values into the container from the given stream.
deba@1408:     ///
deba@1408:     /// Reads the values into the container from the given stream.
deba@1408:     void read(std::istream& is, Value& value) const {
deba@1408:       char c;
deba@1408:       if (!(is >> c) || c != '(') 
deba@1408: 	throw DataFormatError("InsertReader format error");
deba@1408:       while (is >> c && c != ')') {
deba@1408: 	is.putback(c);
deba@1408: 	typename ItemReader::Value item;
deba@1408: 	item_reader.read(is, item);
deba@1408: 	value.insert(item);
deba@1408:       }
deba@1408:       if (!is) throw DataFormatError("PushBackReader format error");
deba@1408:     }
deba@1408: 
deba@1408:   };
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1408:   /// \brief Reader for parsed string.
deba@1408:   ///
deba@1744:   /// Reader for parsed strings. You can define the open and close
deba@1744:   /// parse characters. It reads from the input a character sequence
deba@1744:   /// which is right parsed.
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   class ParsedStringReader {
deba@1408:   public:
deba@1408:     typedef std::string Value;
deba@1408: 
deba@1408:     /// \brief Constructor.
deba@1408:     ///
deba@1408:     /// Constructor for ParsedStringReader. You can give as parameter
deba@1408:     /// the open and close parse characters.
deba@1408:     ParsedStringReader(char _open = '(', char _close = ')')
deba@1408:       : open(_open), close(_close) {}
deba@1408:     
deba@1408:     
deba@1408:     /// \brief Reads the parsed string from the given stream.
deba@1408:     ///
deba@1408:     /// Reads the parsed string from the given stream.
deba@1408:     void read(std::istream& is, Value& value) const {
deba@1408:       char c;
deba@1408:       if (!(is >> c) || c != open) {
deba@1408: 	throw DataFormatError("ParsedStringReader format error");
deba@1408:       }
deba@1408:       value += c;
deba@1408:       int counter = 1;
deba@1408:       while (counter > 0 && is >> c) {
deba@1408: 	if (c == close) {
deba@1408: 	  --counter;
deba@1408: 	} else if (c == open) {
deba@1408: 	  ++counter;
deba@1408: 	}
deba@1408: 	value += c;
deba@1408:       }
deba@1408:       if (!is) {
deba@1408: 	throw DataFormatError("ParsedStrinReader format error");
deba@1408:       }
deba@1408:     }
deba@1408: 
deba@1408:   private:
deba@1408:     char open, close;
deba@1408: 
deba@1408:   };
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1408:   /// \brief Reader for read the whole line.
deba@1408:   ///
deba@1408:   /// Reader for read the whole line.
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   class LineReader {
deba@1408:   public:
deba@1408:     typedef std::string Value;
deba@1408: 
deba@1408:     /// \brief Constructor.
deba@1408:     ///
deba@1408:     /// Constructor for the LineReader. If the given parameter is
deba@1408:     /// true then the spaces before the first not space character are
deba@1408:     /// skipped.
deba@1408:     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
deba@1408:     
deba@1408:     /// \brief Reads the line from the given stream.
deba@1408:     ///
deba@1408:     /// Reads the line from the given stream.
deba@1852:     void read(std::istream& is, Value& value) const {
deba@1408:       if (skipSpaces) is >> std::ws;
deba@1408:       if (!getline(is, value)) {
deba@1852: 	throw DataFormatError("LineReader format error");
deba@1408:       }
deba@1408:     }
deba@1408:   private:
deba@1408:     bool skipSpaces;
deba@1408:   };
deba@1408: 
alpar@1946:   /// \ingroup item_io
deba@1852:   /// \brief Reader for std::pair.
deba@1852:   ///
deba@1852:   /// Reader for std::pair.
deba@1852:   ///
deba@1852:   /// \author Balazs Dezso
deba@1852:   template <typename _Pair, 
deba@1852: 	    typename _FirstReader = 
deba@1852: 	    DefaultReader<typename _Pair::first_type>,
deba@1852: 	    typename _SecondReader = 
deba@1852: 	    DefaultReader<typename _Pair::second_type> >
deba@1852:   class PairReader {
deba@1852:   public:
deba@1852:     typedef _Pair Value;
deba@1852: 
deba@1852:     typedef _FirstReader FirstReader;
deba@1852:     typedef _SecondReader SecondReader;
deba@1852: 
deba@1852:   private:
deba@1852: 
deba@1852:     FirstReader first_reader;
deba@1852:     SecondReader second_reader;
deba@1852: 
deba@1852:   public:
deba@1852:     
deba@1852:     /// \brief Constructor.
deba@1852:     ///
deba@1852:     /// Constructor for the PairReader.
deba@1852:     PairReader(const FirstReader& _first_reader = FirstReader(), 
deba@1852: 	       const SecondReader& _second_reader = SecondReader()) 
deba@1852:       : first_reader(_first_reader), second_reader(_second_reader) {}
deba@1852:     
deba@1852:     /// \brief Reads the pair from the given stream.
deba@1852:     ///
deba@1852:     /// Reads the pair from the given stream.
deba@1852:     void read(std::istream& is, Value& value) const {
deba@1852:       char c;
deba@1852:       if (!(is >> c) || c != '(') {
deba@1852: 	throw DataFormatError("PairReader format error");
deba@1852:       }
deba@1852:       first_reader.read(is, value.first);
deba@1852:       if (!(is >> c) || c != '=') {
deba@1852: 	throw DataFormatError("PairReader format error");
deba@1852:       }
deba@1852:       if (!(is >> c) || c != '>') {
deba@1852: 	throw DataFormatError("PairReader format error");
deba@1852:       }
deba@1852:       second_reader.read(is, value.second);
deba@1852:       if (!(is >> c) || c != ')') {
deba@1852: 	throw DataFormatError("PairReader format error");
deba@1852:       }
deba@1852:     }
deba@1852:   };
deba@1852: 
alpar@1946:   /// \ingroup item_io
deba@1408:   /// 
deba@1408:   /// \brief The default item reader template class.
deba@1408:   ///
deba@1408:   /// The default item reader template class. If some section reader
deba@1408:   /// needs to read a value from a stream it will give the default way for it.
deba@1408:   ///
deba@1408:   /// \author Balazs Dezso
deba@1408:   template <typename _Value>
deba@1408:   class DefaultReader {
deba@1408:   public:
deba@1408:     /// The value type.
deba@1408:     typedef _Value Value;
deba@1408:     /// \brief Reads a value from the given stream.
deba@1408:     ///
deba@1408:     /// Reads a value from the given stream.
deba@1408:     void read(std::istream& is, Value& value) const {
deba@1408:       if (!(is >> value)) 
deba@1408: 	throw DataFormatError("DefaultReader format error");
deba@1408:     }
deba@1408:   };
deba@1408: 
deba@1427:   template <>
deba@1427:   class DefaultReader<std::string> {
deba@1427:   public:
deba@1427:     typedef std::string Value;
deba@1427:     
deba@1427:     void read(std::istream& is, Value& value) const {
deba@1427:       char c;
deba@1429:       if (!(is >> std::ws >> c)) return;
deba@1427:       is.putback(c);
deba@1427:       switch (c) {
deba@1427:       case '\"':
deba@1427: 	QuotedStringReader().read(is, value);
deba@1427: 	break;
deba@1427:       case '(':
deba@1427: 	ParsedStringReader().read(is, value);
deba@1427: 	break;
deba@1744:       case '[':
deba@1744: 	ParsedStringReader('[', ']').read(is, value);
deba@1744: 	break;
deba@1744:       case '/':
deba@1744: 	ParsedStringReader('/', '/').read(is, value);
deba@1744: 	break;
deba@1427:       default:
deba@1744: 	if (!(is >> value)) 
deba@1744: 	  throw DataFormatError("DefaultReader format error");
deba@1427: 	break;
deba@1427:       }
deba@1427:     }
deba@1427:     
deba@1427:   };
deba@1427: 
deba@1408:   template <typename Item>
deba@1408:   class DefaultReader<std::vector<Item> > 
deba@1408:     : public PushBackReader<std::vector<Item> > {};
deba@1408: 
deba@1408:   template <typename Item>
deba@1408:   class DefaultReader<std::deque<Item> > 
deba@1408:     : public PushBackReader<std::deque<Item> > {};
deba@1408: 
deba@1408:   template <typename Item>
deba@1408:   class DefaultReader<std::list<Item> > 
deba@1408:     : public PushBackReader<std::list<Item> > {};
deba@1408: 
deba@1408:   template <typename Item>
deba@1408:   class DefaultReader<std::set<Item> > 
deba@1408:     : public InsertReader<std::set<Item> > {};
deba@1408: 
deba@1852:   template <typename Key, typename Value>
deba@1852:   class DefaultReader<std::map<Key, Value> > 
deba@1852:     : public InsertReader<std::map<Key, Value>,
deba@1852: 			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852: 
deba@1408:   template <typename Item>
deba@1408:   class DefaultReader<std::multiset<Item> > 
deba@1408:     : public InsertReader<std::multiset<Item> > {};
deba@1408: 
deba@1852:   template <typename Key, typename Value>
deba@1852:   class DefaultReader<std::multimap<Key, Value> > 
deba@1852:     : public InsertReader<std::multimap<Key, Value>,
deba@1852: 			  DefaultReader<std::pair<Key, Value> > > {};
deba@1852: 
deba@1852:   template <typename First, typename Second>
deba@1852:   class DefaultReader<std::pair<First, Second> > 
deba@1852:     : public PairReader<std::pair<First, Second> > {};
deba@1852: 
alpar@1946:   /// \ingroup item_io
deba@1415:   /// 
deba@1415:   /// \brief The default item reader for skipping a value in the stream.
deba@1415:   ///
deba@1415:   /// The default item reader for skipping a value in the stream.
deba@1415:   ///
deba@1415:   /// \author Balazs Dezso
deba@1427:   class DefaultSkipper : public DefaultReader<std::string> {};
deba@1415: 
alpar@1946:   /// \ingroup item_io  
deba@1408:   /// \brief Standard ReaderTraits for the GraphReader class.
deba@1408:   ///
deba@1408:   /// Standard ReaderTraits for the GraphReader class.
deba@1408:   /// It defines standard reading method for all type of value. 
deba@1408:   /// \author Balazs Dezso
deba@1408:   struct DefaultReaderTraits {
deba@1408: 
deba@1408:     template <typename _Value>
deba@1408:     struct Reader : DefaultReader<_Value> {};
deba@1408: 
deba@1408:     typedef DefaultSkipper Skipper;
deba@1408: 
deba@1408:   };
deba@1408: 
deba@1408: }
deba@1408: 
deba@1408: #endif