yat
0.8.3pre
|
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