Some improvements on item readers and writers
authordeba
Wed, 18 Oct 2006 15:05:12 +0000
changeset 225450cb2b90daa9
parent 2253 1645f6cc9667
child 2255 4a9cc8c800ae
Some improvements on item readers and writers
lemon/bits/item_reader.h
lemon/bits/item_writer.h
     1.1 --- a/lemon/bits/item_reader.h	Tue Oct 17 11:05:23 2006 +0000
     1.2 +++ b/lemon/bits/item_reader.h	Wed Oct 18 15:05:12 2006 +0000
     1.3 @@ -38,6 +38,112 @@
     1.4  
     1.5    /// \ingroup item_io
     1.6    ///
     1.7 +  /// \brief Reader class for unformatted strings.
     1.8 +  ///
     1.9 +  /// Reader class for unformatted strings. This class want to be
    1.10 +  /// a general reader type which can read the most 
    1.11 +  ///
    1.12 +  /// \author Balazs Dezso
    1.13 +  class UnformattedReader {
    1.14 +  public:
    1.15 +    /// \brief The value type of reader.
    1.16 +    ///
    1.17 +    /// The value type of reader.
    1.18 +    typedef std::string Value;
    1.19 +    
    1.20 +    /// \brief Constructor for the reader.
    1.21 +    ///
    1.22 +    /// Constructor for the reader.
    1.23 +    UnformattedReader() {} 
    1.24 +    
    1.25 +    /// \brief Reads an unformatted string from the given stream.
    1.26 +    ///
    1.27 +    /// Reads an unformatted string from the given stream.
    1.28 +    void read(std::istream& is, std::string& value) const {
    1.29 +      char c;
    1.30 +      value.clear();
    1.31 +      is >> std::ws;
    1.32 +      while (is.get(c) && !whiteSpace(c)) {
    1.33 +        processChar(c, is, value);
    1.34 +      }
    1.35 +    }
    1.36 +
    1.37 +  private:
    1.38 +
    1.39 +    void processChar(char c, std::istream& is, Value& value) const {
    1.40 +      switch (c) {
    1.41 +      case '(':
    1.42 +        is.putback(c);
    1.43 +        readParsed('(', ')', is, value);
    1.44 +        break;
    1.45 +      case '[':
    1.46 +        is.putback(c);
    1.47 +        readParsed('[', ']', is, value);
    1.48 +        break;
    1.49 +      case '{':
    1.50 +        is.putback(c);
    1.51 +        readParsed('{', '}', is, value);
    1.52 +        break;
    1.53 +      case '/':
    1.54 +        is.putback(c);
    1.55 +        readParsed('/', '/', is, value);
    1.56 +        break;
    1.57 +      case '\"':
    1.58 +        is.putback(c);
    1.59 +        readQuoted('\"', is, value);
    1.60 +        break;
    1.61 +      case '\'':
    1.62 +        is.putback(c);
    1.63 +        readQuoted('\'', is, value);
    1.64 +        break;
    1.65 +      default:
    1.66 +        value += c;
    1.67 +        break;
    1.68 +      }
    1.69 +    }
    1.70 +
    1.71 +    void readParsed(char open, char close, 
    1.72 +                    std::istream& is, Value& value) const {
    1.73 +      char c;
    1.74 +      if (!is.get(c) || c != open)
    1.75 +	throw DataFormatError("Unformatted string format error");
    1.76 +      value += c;
    1.77 +      while (is.get(c) && c != close) {
    1.78 +        processChar(c, is, value);
    1.79 +      }
    1.80 +      if (!is) 
    1.81 +        throw DataFormatError("Unformatted string format error");
    1.82 +      value += c;      
    1.83 +    }
    1.84 +
    1.85 +    void readQuoted(char quote, std::istream& is, Value& value) const {
    1.86 +      char c;
    1.87 +      bool esc = false;
    1.88 +      if (!is.get(c) || c != quote)
    1.89 +	throw DataFormatError("Unformatted string format error");
    1.90 +      value += c;
    1.91 +      while (is.get(c) && (c != quote || esc)) {
    1.92 +        if (c == '\\') esc = !esc;
    1.93 +        else esc = false;
    1.94 +        value += c;
    1.95 +      }
    1.96 +      if (!is) 
    1.97 +        throw DataFormatError("Unformatted string format error");
    1.98 +      value += c;
    1.99 +    }
   1.100 +
   1.101 +
   1.102 +
   1.103 +    static bool whiteSpace(char c) {
   1.104 +      return c == ' ' || c == '\t' || c == '\v' || 
   1.105 +        c == '\n' || c == '\r' || c == '\f'; 
   1.106 +    }
   1.107 +
   1.108 +    
   1.109 +  };
   1.110 +
   1.111 +  /// \ingroup item_io
   1.112 +  ///
   1.113    /// \brief Reader class for quoted strings.
   1.114    ///
   1.115    /// Reader class for quoted strings. It can process the escape
   1.116 @@ -45,6 +151,7 @@
   1.117    ///
   1.118    /// \author Balazs Dezso
   1.119    class QuotedStringReader {
   1.120 +    friend class QuotedCharReader;
   1.121    public:
   1.122      /// \brief The value type of reader.
   1.123      ///
   1.124 @@ -66,7 +173,7 @@
   1.125        value.clear();
   1.126        is >> std::ws;
   1.127        if (!is.get(c) || c != '\"') 
   1.128 -	throw DataFormatError("Quoted string format error");
   1.129 +	throw DataFormatError("Quoted format error");
   1.130        while (is.get(c) && c != '\"') {
   1.131  	if (escaped && c == '\\') {
   1.132  	  value += readEscape(is);
   1.133 @@ -74,7 +181,7 @@
   1.134  	  value += c;
   1.135  	}
   1.136        }
   1.137 -      if (!is) throw DataFormatError("Quoted string format error");
   1.138 +      if (!is) throw DataFormatError("Quoted format error");
   1.139      }
   1.140  
   1.141    private:
   1.142 @@ -152,6 +259,51 @@
   1.143    };
   1.144  
   1.145    /// \ingroup item_io
   1.146 +  ///
   1.147 +  /// \brief Reader class for quoted strings.
   1.148 +  ///
   1.149 +  /// Reader class for quoted strings. It can process the escape
   1.150 +  /// sequences in the string.
   1.151 +  ///
   1.152 +  /// \author Balazs Dezso
   1.153 +  class QuotedCharReader {
   1.154 +  public:
   1.155 +    /// \brief The value type of reader.
   1.156 +    ///
   1.157 +    /// The value type of reader.
   1.158 +    typedef char Value;
   1.159 +    
   1.160 +    /// \brief Constructor for the reader.
   1.161 +    ///
   1.162 +    /// Constructor for the reader. If the given parameter is true
   1.163 +    /// the reader processes the escape sequences.
   1.164 +    QuotedCharReader(bool _escaped = true) 
   1.165 +      : escaped(_escaped) {}
   1.166 +    
   1.167 +    /// \brief Reads a quoted string from the given stream.
   1.168 +    ///
   1.169 +    /// Reads a quoted string from the given stream.
   1.170 +    void read(std::istream& is, char& value) const {
   1.171 +      char c;
   1.172 +      is >> std::ws;
   1.173 +      if (!is.get(c) || c != '\'') 
   1.174 +	throw DataFormatError("Quoted format error");
   1.175 +      if (!is.get(c)) 
   1.176 +        throw DataFormatError("Quoted format error");
   1.177 +      if (escaped && c == '\\') {
   1.178 +        value = QuotedStringReader::readEscape(is);
   1.179 +      } else {
   1.180 +        value = c;
   1.181 +      }
   1.182 +      if (!is.get(c) || c != '\'') 
   1.183 +	throw DataFormatError("Quoted format error");
   1.184 +    }
   1.185 +
   1.186 +  private:
   1.187 +    bool escaped;
   1.188 +  };
   1.189 +
   1.190 +  /// \ingroup item_io
   1.191    /// \brief Reader for standard containers.
   1.192    ///
   1.193    /// Reader for back insertable standard containers. The representation
   1.194 @@ -271,6 +423,7 @@
   1.195      /// Reads the parsed string from the given stream.
   1.196      void read(std::istream& is, Value& value) const {
   1.197        char c;
   1.198 +      value.clear();
   1.199        if (!(is >> c) || c != open) {
   1.200  	throw DataFormatError("ParsedStringReader format error");
   1.201        }
   1.202 @@ -407,30 +560,64 @@
   1.203      
   1.204      void read(std::istream& is, Value& value) const {
   1.205        char c;
   1.206 -      if (!(is >> std::ws >> c)) return;
   1.207 +      if (!(is >> std::ws >> c)) 
   1.208 +        throw DataFormatError("DefaultReader<string> format error");
   1.209        is.putback(c);
   1.210        switch (c) {
   1.211        case '\"':
   1.212  	QuotedStringReader().read(is, value);
   1.213  	break;
   1.214 -      case '(':
   1.215 -	ParsedStringReader().read(is, value);
   1.216 -	break;
   1.217 -      case '[':
   1.218 -	ParsedStringReader('[', ']').read(is, value);
   1.219 -	break;
   1.220 -      case '/':
   1.221 -	ParsedStringReader('/', '/').read(is, value);
   1.222 -	break;
   1.223        default:
   1.224 -	if (!(is >> value)) 
   1.225 -	  throw DataFormatError("DefaultReader format error");
   1.226 +        UnformattedReader().read(is, value);
   1.227  	break;
   1.228        }
   1.229      }
   1.230      
   1.231    };
   1.232  
   1.233 +  template <>
   1.234 +  class DefaultReader<char> {
   1.235 +  public:
   1.236 +    typedef char Value;
   1.237 +    
   1.238 +    void read(std::istream& is, Value& value) const {
   1.239 +      char c;
   1.240 +      if (!(is >> std::ws >> c))
   1.241 +        throw DataFormatError("DefaultReader<char> format error");
   1.242 +      is.putback(c);
   1.243 +      switch (c) {
   1.244 +      case '\'':
   1.245 +	QuotedCharReader().read(is, value);
   1.246 +	break;
   1.247 +      default:
   1.248 +        { 
   1.249 +          int temp;          
   1.250 +          if (!(is >> temp)) 
   1.251 +            throw DataFormatError("DefaultReader<char> format error");
   1.252 +          value = (char)temp;
   1.253 +          break;
   1.254 +        }
   1.255 +      }
   1.256 +    }    
   1.257 +  };
   1.258 +
   1.259 +  template <>
   1.260 +  class DefaultReader<bool> {
   1.261 +  public:
   1.262 +    typedef bool Value;
   1.263 +    
   1.264 +    void read(std::istream& is, Value& value) const {
   1.265 +      std::string rep;
   1.266 +      if (!(is >> rep))
   1.267 +        throw DataFormatError("DefaultReader<bool> format error");
   1.268 +      if (rep == "true" || rep == "t" || rep == "1") {
   1.269 +        value = true;
   1.270 +      } else if (rep == "false" || rep == "f" || rep == "0") {
   1.271 +        value = false;
   1.272 +      } else throw DataFormatError("DefaultReader<bool> format error");
   1.273 +    }    
   1.274 +  };
   1.275 +
   1.276    template <typename Item>
   1.277    class DefaultReader<std::vector<Item> > 
   1.278      : public PushBackReader<std::vector<Item> > {};
   1.279 @@ -472,7 +659,7 @@
   1.280    /// The default item reader for skipping a value in the stream.
   1.281    ///
   1.282    /// \author Balazs Dezso
   1.283 -  class DefaultSkipper : public DefaultReader<std::string> {};
   1.284 +  class DefaultSkipper : public UnformattedReader {};
   1.285  
   1.286    /// \ingroup item_io  
   1.287    /// \brief Standard ReaderTraits for the GraphReader class.
     2.1 --- a/lemon/bits/item_writer.h	Tue Oct 17 11:05:23 2006 +0000
     2.2 +++ b/lemon/bits/item_writer.h	Wed Oct 18 15:05:12 2006 +0000
     2.3 @@ -24,6 +24,7 @@
     2.4  #define LEMON_BITS_ITEM_WRITER_H
     2.5  
     2.6  #include <iostream>
     2.7 +#include <sstream>
     2.8  #include <string>
     2.9  
    2.10  #include <vector>
    2.11 @@ -39,10 +40,101 @@
    2.12    /// \ingroup item_io
    2.13    /// \brief Writer class for quoted strings.
    2.14    ///
    2.15 +  /// Writer class for unformatted strings.
    2.16 +  /// \author Balazs Dezso
    2.17 +  class UnformattedWriter {
    2.18 +  public:
    2.19 +    typedef std::string Value;
    2.20 +
    2.21 +    /// \brief Constructor for the writer.
    2.22 +    ///
    2.23 +    /// Constructor for the writer.
    2.24 +    UnformattedWriter() {}
    2.25 +
    2.26 +    /// \brief Writes an unformatted string to the given stream.
    2.27 +    ///
    2.28 +    /// Writes an unformatted string to the given stream.
    2.29 +    void write(std::ostream& os, const std::string& value) const {
    2.30 +      os << value;
    2.31 +    }
    2.32 +
    2.33 +    bool readable(const std::string& value) const {
    2.34 +      std::istringstream is(value);
    2.35 +      char c;
    2.36 +      while (is.get(c) && !whiteSpace(c)) {
    2.37 +        if (!processChar(c, is)) return false;
    2.38 +      }
    2.39 +      if (is) return false;
    2.40 +      return true;
    2.41 +    }
    2.42 +
    2.43 +  private:
    2.44 +
    2.45 +    bool processChar(char c, std::istream& is) const {
    2.46 +      switch (c) {
    2.47 +      case '(':
    2.48 +        is.putback(c);
    2.49 +        if (!readableParsed('(', ')', is)) return false;
    2.50 +        break;
    2.51 +      case '[':
    2.52 +        is.putback(c);
    2.53 +        if (!readableParsed('[', ']', is)) return false;
    2.54 +        break;
    2.55 +      case '{':
    2.56 +        is.putback(c);
    2.57 +        if (!readableParsed('{', '}', is)) return false;
    2.58 +        break;
    2.59 +      case '\"':
    2.60 +        is.putback(c);
    2.61 +        if (!readableQuoted('\"', is)) return false;
    2.62 +        break;
    2.63 +      case '\'':
    2.64 +        is.putback(c);
    2.65 +        if (!readableQuoted('\'', is)) return false;
    2.66 +        break;
    2.67 +      default:
    2.68 +        break;
    2.69 +      }
    2.70 +      return true;
    2.71 +    }
    2.72 +
    2.73 +    bool readableParsed(char open, char close, std::istream& is) const {
    2.74 +      char c;
    2.75 +      if (!is.get(c) || c != open) return false;
    2.76 +      while (is.get(c) && c != close) {
    2.77 +        if (!processChar(c, is)) return false;
    2.78 +      }
    2.79 +      if (!is) return false;
    2.80 +      return true;
    2.81 +    }
    2.82 +
    2.83 +    bool readableQuoted(char quote, std::istream& is) const {
    2.84 +      char c;
    2.85 +      bool esc = false;
    2.86 +      if (!is.get(c) || c != quote) return false;
    2.87 +      while (is.get(c) && c != quote && !esc) {
    2.88 +        if (c == '\\') esc = !esc;
    2.89 +        else esc = false;
    2.90 +      }
    2.91 +      if (!is) return false;
    2.92 +      return true;
    2.93 +    }
    2.94 +
    2.95 +    static bool whiteSpace(char c) {
    2.96 +      return c == ' ' || c == '\t' || c == '\v' || 
    2.97 +        c == '\n' || c == '\r' || c == '\f'; 
    2.98 +    }
    2.99 +
   2.100 +  };
   2.101 +
   2.102 +  /// \ingroup item_io
   2.103 +  /// \brief Writer class for quoted strings.
   2.104 +  ///
   2.105    /// Writer class for quoted strings. It can process the escape
   2.106    /// sequences in the string.
   2.107    /// \author Balazs Dezso
   2.108    class QuotedStringWriter {
   2.109 +    friend class QuotedCharWriter;
   2.110    public:
   2.111      typedef std::string Value;
   2.112  
   2.113 @@ -120,6 +212,41 @@
   2.114    };
   2.115  
   2.116    /// \ingroup item_io
   2.117 +  /// \brief Writer class for quoted chars.
   2.118 +  ///
   2.119 +  /// Writer class for quoted char. It can process the escape
   2.120 +  /// sequences in the string.
   2.121 +  /// \author Balazs Dezso
   2.122 +  class QuotedCharWriter {
   2.123 +  public:
   2.124 +    typedef char Value;
   2.125 +
   2.126 +    /// \brief Constructor for the writer.
   2.127 +    ///
   2.128 +    /// Constructor for the writer. If the given parameter is true
   2.129 +    /// the writer creates escape sequences from special characters.
   2.130 +    QuotedCharWriter(bool _escaped = true) : escaped(_escaped) {}
   2.131 +
   2.132 +    /// \brief Writes a quoted char to the given stream.
   2.133 +    ///
   2.134 +    /// Writes a quoted char to the given stream.
   2.135 +    void write(std::ostream& os, const char& value) const {
   2.136 +      os << "\'";
   2.137 +      if (escaped) {
   2.138 +	std::ostringstream ls;
   2.139 +        QuotedStringWriter::writeEscape(ls, value);
   2.140 +	os << ls.str();
   2.141 +      } else {
   2.142 +	os << value;
   2.143 +      }
   2.144 +      os << "\'";
   2.145 +    }
   2.146 +
   2.147 +  private:
   2.148 +    bool escaped;
   2.149 +  };
   2.150 +
   2.151 +  /// \ingroup item_io
   2.152    /// \brief Writer class for quoted char array.
   2.153    ///
   2.154    /// Writer class for quoted char array. It can process the escape
   2.155 @@ -258,8 +385,34 @@
   2.156    };
   2.157  
   2.158    template <>
   2.159 -  class DefaultWriter<std::string> 
   2.160 -    : public QuotedStringWriter {};
   2.161 +  class DefaultWriter<std::string> {
   2.162 +  public:
   2.163 +    typedef std::string Value;
   2.164 +    
   2.165 +    void write(std::ostream& os, const Value& value) const {
   2.166 +      if (UnformattedWriter().readable(value)) {
   2.167 +        UnformattedWriter().write(os, value);
   2.168 +      } else {
   2.169 +        QuotedStringWriter().write(os, value);
   2.170 +      }
   2.171 +    }
   2.172 +      
   2.173 +  };
   2.174 +
   2.175 +  template <>
   2.176 +  class DefaultWriter<char> 
   2.177 +    : public QuotedCharWriter {};
   2.178 +
   2.179 +  template <>
   2.180 +  class DefaultWriter<bool> {
   2.181 +  public:
   2.182 +    typedef bool Value;
   2.183 +    
   2.184 +    void write(std::ostream& os, const Value& value) const {
   2.185 +      os << (value ? "1" : "0");
   2.186 +    }
   2.187 +      
   2.188 +  };
   2.189  
   2.190    template <int length>
   2.191    class DefaultWriter<char[length]>