yat  0.8.3pre
utility.h
Go to the documentation of this file.
00001 #ifndef _theplu_yat_utility_utility_
00002 #define _theplu_yat_utility_utility_ 
00003 
00004 // $Id: utility.h 2667 2011-12-01 16:32:32Z peter $
00005 
00006 /*
00007   Copyright (C) 2005 Jari Häkkinen, Peter Johansson, Markus Ringnér
00008   Copyright (C) 2006 Jari Häkkinen
00009   Copyright (C) 2007, 2008 Jari Häkkinen, Peter Johansson
00010   Copyright (C) 2009, 2010, 2011 Peter Johansson
00011 
00012   This file is part of the yat library, http://dev.thep.lu.se/yat
00013 
00014   The yat library is free software; you can redistribute it and/or
00015   modify it under the terms of the GNU General Public License as
00016   published by the Free Software Foundation; either version 3 of the
00017   License, or (at your option) any later version.
00018 
00019   The yat library is distributed in the hope that it will be useful,
00020   but WITHOUT ANY WARRANTY; without even the implied warranty of
00021   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00022   General Public License for more details.
00023 
00024   You should have received a copy of the GNU General Public License
00025   along with yat. If not, see <http://www.gnu.org/licenses/>.
00026 */
00027 
00033 
00034 #include "deprecate.h"
00035 #include "Exception.h"
00036 
00037 #include <algorithm>
00038 #include <cctype>
00039 #include <cmath>
00040 #include <functional>
00041 #include <limits>
00042 #include <locale>
00043 #include <istream>
00044 #include <string>
00045 #include <stdexcept>
00046 #include <sstream>
00047 #include <utility>
00048 #include <vector>
00049 
00050 namespace theplu {
00051 namespace yat {
00052 namespace utility {
00053 
00064   template<typename InputIterator, typename OutputIterator>
00065   bool binary_weight(InputIterator first, InputIterator last, 
00066                      OutputIterator result);
00067 
00075   template<typename T>
00076   std::string convert(T input);
00077 
00083   template<typename T>
00084   T convert(const std::string& s);
00085 
00091   template<typename T>
00092   bool is(const std::string& s);
00093 
00100   bool is_double(const std::string&) YAT_DEPRECATE;
00101 
00110   bool is_equal(std::string s, std::string other);
00111 
00118   bool is_float(const std::string&) YAT_DEPRECATE;
00119 
00126   bool is_int(const std::string&) YAT_DEPRECATE;
00127 
00131   bool is_nan(const std::string& s);
00132 
00168   template<typename T>
00169   void load(std::istream& is, std::vector<std::vector<T> >& vec, char sep='\0', 
00170             char line_sep='\n', bool ignore_empty=false, bool rectangle=true);
00171 
00193   template<typename T>
00194   void load(std::istream& is, std::vector<T>& vec, char sep='\0');
00195   
00196 // private namespace
00197 namespace detail {
00198 
00208   template<typename T>
00209   bool convert(const std::string& s, T& t);
00210 
00214   template<typename T>
00215   struct VectorPusher
00216   {
00222     void operator()(const std::string& element, std::vector<T>& vec)
00223     { 
00224       if (!element.size())
00225         vec.push_back(std::numeric_limits<T>::quiet_NaN());
00226       else {
00227         vec.push_back(theplu::yat::utility::convert<T>(element));
00228       }
00229     }
00230   };
00231 
00237   template<>
00238   struct VectorPusher<std::string>
00239   {
00243     void operator()(const std::string& element, std::vector<std::string>& vec)
00244     { 
00245       vec.push_back(element);
00246     }
00247   };
00248 
00249 } // end of namespace detail
00250 
00251 
00252   // template implementations
00253 
00254   template<typename InputIterator, typename OutputIterator>
00255   bool binary_weight(InputIterator first, InputIterator last, 
00256                      OutputIterator result)
00257   {
00258     bool nan=false;
00259     while (first!=last) {
00260       if (std::isnan(*first)) {
00261         *result=0;
00262         nan=true;
00263       }
00264       else
00265         *result = 1.0;
00266       ++first;
00267       ++result;
00268     }
00269     return nan;
00270   }
00271 
00272 
00273   // template implementations
00274   template<typename T>
00275   std::string convert(T input)
00276   {
00277     std::ostringstream ss;
00278     ss << input;
00279     return ss.str();
00280   }
00281 
00282 
00283   template<typename T>
00284   T convert(const std::string& s)
00285   {
00286     T result;
00287     if (!detail::convert(s, result))
00288       throw runtime_error(std::string("yat::utility::convert(\"")+s+
00289                           std::string("\")"));
00290     return result;
00291   }
00292 
00293 
00294   template<typename T>
00295   bool is(const std::string& s)
00296   {
00297     T tmp;
00298     return detail::convert(s, tmp);
00299   }
00300 
00301 
00302   template<typename T>
00303   void load(std::istream& is, std::vector<std::vector<T> >& matrix, 
00304             char sep, char line_sep, bool ignore_empty, 
00305             bool rectangle)
00306   {
00307     size_t nof_columns=0;
00308     std::string line;
00309     while(getline(is, line, line_sep)){
00310       if (line.empty() && ignore_empty)
00311         continue;
00312       matrix.push_back(std::vector<T>());
00313       std::vector<T>& v=matrix.back();
00314       v.reserve(nof_columns);
00315       std::stringstream ss(line);
00316       load(ss, v, sep);
00317       // add NaN for final separator (or empty string if T=std::string)
00318       detail::VectorPusher<T> pusher;
00319       if(sep!='\0' && !line.empty() && line[line.size()-1]==sep) 
00320         pusher("", v);
00321       
00322       if (rectangle && nof_columns && v.size()!=nof_columns) {
00323         std::ostringstream s;
00324         s << "load stream error: "
00325           << "line " << matrix.size() << " has " << v.size()
00326           << " columns; expected " << nof_columns << " columns.";
00327         throw utility::IO_error(s.str());
00328       }       
00329       nof_columns = std::max(nof_columns, v.size());
00330     }
00331 
00332     // manipulate the state of the stream to be good
00333     is.clear(std::ios::goodbit);
00334   }
00335 
00336   template<typename T>
00337   void load(std::istream& is, std::vector<T>& vec, char sep)
00338   {
00339     detail::VectorPusher<T> pusher;
00340     std::string element;
00341     bool ok=true;
00342     while(true) {
00343       if(sep=='\0')
00344         ok=(is>>element);
00345       else
00346         ok=getline(is, element, sep);
00347       if(!ok)
00348         break;
00349       pusher(element, vec);
00350     }
00351   }           
00352 
00353 
00354 namespace detail {
00355   template<typename T>
00356   bool convert(const std::string& s, T& result)
00357   {
00358     if (!std::numeric_limits<T>::is_signed) {
00359       // first non-whitespace character
00360       std::string::const_iterator iter = s.begin();
00361       while (iter!=s.end() && std::isspace(*iter))
00362         ++iter;
00363       // unsigned int cannot start with a '-' and with some compilers
00364       // operation ss >> result won't fail so catch it like this instead.
00365       if (iter==s.end() || *iter=='-')
00366         return false;
00367     }
00368     std::istringstream ss(s);
00369     ss >> result;
00370     if (ss.fail()) {
00371       if (is_nan(s)) {
00372         result = std::numeric_limits<T>::quiet_NaN();
00373         return true;
00374       }
00375       if (is_equal(s, "inf")) {
00376         result = std::numeric_limits<T>::infinity();
00377         return true;
00378       }
00379       if (std::numeric_limits<T>::is_signed && is_equal(s, "-inf")) {
00380         result = -std::numeric_limits<T>::infinity();
00381         return true;
00382       }
00383       return false;
00384     }
00385     // Check that nothing is left on stream
00386     std::string b;
00387     ss >> b;
00388     return b.empty();
00389   }
00390 } // of namespace detail
00391 
00392 }}} // of namespace utility, yat, and theplu
00393 
00394 #endif

Generated on Thu Dec 20 2012 03:12:57 for yat by  doxygen 1.8.0-20120409