2  * lemon/bits/item_reader.h - Part of LEMON, a generic C++ optimization library
 
     4  * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
 
     5  * (Egervary Research Group on Combinatorial Optimization, EGRES).
 
     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.
 
    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
 
    17 /// @defgroup item_io Item Readers and Writers
 
    19 /// \brief Item Readers and Writers
 
    21 /// The Input-Output classes can handle more data type by example
 
    22 /// as map or attribute value. Each of these should be written and
 
    23 /// read some way. The module make possible to do this.  
 
    27 /// \brief Item reader bits for lemon input.
 
    29 #ifndef LEMON_BITS_ITEM_READER_H
 
    30 #define LEMON_BITS_ITEM_READER_H
 
    42   template <typename Value>
 
    47   /// \brief Reader class for quoted strings.
 
    49   /// Reader class for quoted strings. It can process the escape
 
    50   /// sequences in the string.
 
    52   /// \author Balazs Dezso
 
    53   class QuotedStringReader {
 
    55     /// \brief The value type of reader.
 
    57     /// The value type of reader.
 
    58     typedef std::string Value;
 
    60     /// \brief Constructor for the reader.
 
    62     /// Constructor for the reader. If the given parameter is true
 
    63     /// the reader processes the escape sequences.
 
    64     QuotedStringReader(bool _escaped = true) 
 
    65       : escaped(_escaped) {}
 
    67     /// \brief Reads a quoted string from the given stream.
 
    69     /// Reads a quoted string from the given stream.
 
    70     void read(std::istream& is, std::string& value) const {
 
    74       if (!is.get(c) || c != '\"') 
 
    75 	throw DataFormatError("Quoted string format error");
 
    76       while (is.get(c) && c != '\"') {
 
    77 	if (escaped && c == '\\') {
 
    78 	  value += readEscape(is);
 
    83       if (!is) throw DataFormatError("Quoted string format error");
 
    88     static char readEscape(std::istream& is) {
 
    90       switch (is.get(c), c) {
 
   116 	  if (!is.get(c) || !isHex(c)) 
 
   117 	    throw DataFormatError("Escape format error");
 
   118 	  else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
 
   119 	  else code = code * 16 + valueHex(c);
 
   126 	    throw DataFormatError("Escape format error");
 
   127 	  else if (code = valueOct(c), !is.get(c) || !isOct(c)) 
 
   129 	  else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) 
 
   131 	  else code = code * 8 + valueOct(c);
 
   137     static bool isOct(char c) {
 
   138       return '0' <= c && c <='7'; 
 
   141     static int valueOct(char c) {
 
   145    static bool isHex(char c) {
 
   146       return ('0' <= c && c <= '9') || 
 
   147 	('a' <= c && c <= 'z') || 
 
   148 	('A' <= c && c <= 'Z'); 
 
   151     static int valueHex(char c) {
 
   152       if ('0' <= c && c <= '9') return c - '0';
 
   153       if ('a' <= c && c <= 'z') return c - 'a' + 10;
 
   161   /// \brief Reader for standard containers.
 
   163   /// Reader for back insertable standard containers. The representation
 
   164   /// of the container is the values enumerated between an open and a
 
   167   /// \author Balazs Dezso
 
   170     typename _ItemReader = DefaultReader<typename _Container::value_type> 
 
   172   class PushBackReader {
 
   174     typedef _Container Value;
 
   175     typedef _ItemReader ItemReader;
 
   179     ItemReader item_reader;
 
   183     /// \brief Reads the values into the container from the given stream.
 
   185     /// Reads the values into the container from the given stream.
 
   186     void read(std::istream& is, Value& value) const {
 
   188       if (!(is >> c) || c != '(') 
 
   189 	throw DataFormatError("PushBackReader format error");
 
   190       while (is >> c && c != ')') {
 
   192 	typename ItemReader::Value item;
 
   193 	item_reader.read(is, item);
 
   194 	value.push_back(item);
 
   196       if (!is) throw DataFormatError("PushBackReader format error");
 
   204   /// \brief Reader for standard containers.
 
   206   /// Reader for insertable standard containers. The representation
 
   207   /// of the container is the values enumerated between an open and a
 
   210   /// \author Balazs Dezso
 
   213     typename _ItemReader = DefaultReader<typename _Container::value_type> 
 
   217     typedef _Container Value;
 
   218     typedef _ItemReader ItemReader;
 
   222     ItemReader item_reader;
 
   226     /// \brief Reads the values into the container from the given stream.
 
   228     /// Reads the values into the container from the given stream.
 
   229     void read(std::istream& is, Value& value) const {
 
   231       if (!(is >> c) || c != '(') 
 
   232 	throw DataFormatError("InsertReader format error");
 
   233       while (is >> c && c != ')') {
 
   235 	typename ItemReader::Value item;
 
   236 	item_reader.read(is, item);
 
   239       if (!is) throw DataFormatError("PushBackReader format error");
 
   246   /// \brief Reader for parsed string.
 
   248   /// Reader for parsed strings. You can give the open and close
 
   249   /// parse characters.
 
   251   /// \author Balazs Dezso
 
   252   class ParsedStringReader {
 
   254     typedef std::string Value;
 
   256     /// \brief Constructor.
 
   258     /// Constructor for ParsedStringReader. You can give as parameter
 
   259     /// the open and close parse characters.
 
   260     ParsedStringReader(char _open = '(', char _close = ')')
 
   261       : open(_open), close(_close) {}
 
   264     /// \brief Reads the parsed string from the given stream.
 
   266     /// Reads the parsed string from the given stream.
 
   267     void read(std::istream& is, Value& value) const {
 
   269       if (!(is >> c) || c != open) {
 
   270 	throw DataFormatError("ParsedStringReader format error");
 
   274       while (counter > 0 && is >> c) {
 
   277 	} else if (c == open) {
 
   283 	throw DataFormatError("ParsedStrinReader format error");
 
   293   /// \brief Reader for read the whole line.
 
   295   /// Reader for read the whole line.
 
   297   /// \author Balazs Dezso
 
   300     typedef std::string Value;
 
   302     /// \brief Constructor.
 
   304     /// Constructor for the LineReader. If the given parameter is
 
   305     /// true then the spaces before the first not space character are
 
   307     LineReader(bool _skipSpaces = true) : skipSpaces(_skipSpaces) {}
 
   309     /// \brief Reads the line from the given stream.
 
   311     /// Reads the line from the given stream.
 
   312     void read(std::istream& is, Value& value) {
 
   313       if (skipSpaces) is >> std::ws;
 
   314       if (!getline(is, value)) {
 
   315 	throw DataFormatError("LineReader forma error");
 
   324   /// \brief The default item reader template class.
 
   326   /// The default item reader template class. If some section reader
 
   327   /// needs to read a value from a stream it will give the default way for it.
 
   329   /// \author Balazs Dezso
 
   330   template <typename _Value>
 
   331   class DefaultReader {
 
   334     typedef _Value Value;
 
   335     /// \brief Reads a value from the given stream.
 
   337     /// Reads a value from the given stream.
 
   338     void read(std::istream& is, Value& value) const {
 
   340 	throw DataFormatError("DefaultReader format error");
 
   345   class DefaultReader<std::string> {
 
   347     typedef std::string Value;
 
   349     void read(std::istream& is, Value& value) const {
 
   351       if (!(is >> std::ws >> c)) return;
 
   355 	QuotedStringReader().read(is, value);
 
   358 	ParsedStringReader().read(is, value);
 
   368   template <typename Item>
 
   369   class DefaultReader<std::vector<Item> > 
 
   370     : public PushBackReader<std::vector<Item> > {};
 
   372   template <typename Item>
 
   373   class DefaultReader<std::deque<Item> > 
 
   374     : public PushBackReader<std::deque<Item> > {};
 
   376   template <typename Item>
 
   377   class DefaultReader<std::list<Item> > 
 
   378     : public PushBackReader<std::list<Item> > {};
 
   380   template <typename Item>
 
   381   class DefaultReader<std::set<Item> > 
 
   382     : public InsertReader<std::set<Item> > {};
 
   384   template <typename Item>
 
   385   class DefaultReader<std::multiset<Item> > 
 
   386     : public InsertReader<std::multiset<Item> > {};
 
   390   /// \brief The default item reader for skipping a value in the stream.
 
   392   /// The default item reader for skipping a value in the stream.
 
   394   /// \author Balazs Dezso
 
   395   class DefaultSkipper : public DefaultReader<std::string> {};
 
   398   /// \brief Standard ReaderTraits for the GraphReader class.
 
   400   /// Standard ReaderTraits for the GraphReader class.
 
   401   /// It defines standard reading method for all type of value. 
 
   402   /// \author Balazs Dezso
 
   403   struct DefaultReaderTraits {
 
   405     template <typename _Value>
 
   406     struct Reader : DefaultReader<_Value> {};
 
   408     typedef DefaultSkipper Skipper;