00001 /* 00002 ------------------------------------------------------------------- 00003 00004 Copyright (C) 2008, 2009, Andrew W. Steiner 00005 00006 This file is part of O2scl. 00007 00008 O2scl is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 O2scl is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with O2scl. If not, see <http://www.gnu.org/licenses/>. 00020 00021 ------------------------------------------------------------------- 00022 */ 00023 #ifndef O2SCL_CONVERT_UNITS_GNU_H 00024 #define O2SCL_CONVERT_UNITS_GNU_H 00025 00026 #include <cstdio> 00027 #include <cstdlib> 00028 #include <iostream> 00029 #include <o2scl/err_hnd.h> 00030 #include <o2scl/file_format.h> 00031 #include <o2scl/misc.h> 00032 #include <o2scl/constants.h> 00033 #include <o2scl/convert_units.h> 00034 00035 #ifndef DOXYGENP 00036 namespace o2scl { 00037 #endif 00038 00039 /** 00040 \brief Convert units using a system call to GNU units 00041 00042 Experimental. 00043 */ 00044 class convert_units_gnu : public convert_units { 00045 00046 public: 00047 00048 /** \brief Return the value \c val after converting using units \c 00049 from and \c to 00050 */ 00051 virtual double convert(std::string from, std::string to, double val) { 00052 00053 // Look in cache for conversion 00054 std::string both=from+","+to; 00055 miter m3=mcache.find(both); 00056 if (m3!=mcache.end()) { 00057 return val*m3->second.c; 00058 } 00059 00060 // Look in cache for reverse conversion 00061 std::string both2=to+","+from; 00062 m3=mcache.find(both2); 00063 if (m3!=mcache.end()) { 00064 return val/m3->second.c; 00065 } 00066 00067 // Look for combined conversions 00068 for(miter m=mcache.begin();m!=mcache.end();m++) { 00069 if (m->second.f==from) { 00070 std::string b=m->second.t+","+to; 00071 miter m2=mcache.find(b); 00072 if (m2!=mcache.end()) { 00073 if (verbose>0) { 00074 std::cout << "Using conversions: " << m->second.f << " , " 00075 << m->second.t << std::endl; 00076 std::cout << " (1) and: " << m2->second.f << " , " 00077 << m2->second.t << std::endl; 00078 } 00079 return m->second.c*m2->second.c; 00080 } 00081 std::string b2=to+","+m->second.t; 00082 miter m4=mcache.find(b2); 00083 if (m4!=mcache.end()) { 00084 if (verbose>0) { 00085 std::cout << "Using conversions: " << m->second.f << " , " 00086 << m->second.t << std::endl; 00087 std::cout << " (2) and: " << m4->second.f << " , " 00088 << m4->second.t << std::endl; 00089 } 00090 return m->second.c/m4->second.c; 00091 } 00092 } else if (m->second.t==from) { 00093 std::string b=m->second.f+","+to; 00094 miter m2=mcache.find(b); 00095 if (m2!=mcache.end()) { 00096 if (verbose>0) { 00097 std::cout << "Using conversions: " << m->second.f << " , " 00098 << m->second.t << std::endl; 00099 std::cout << " (3) and: " << m2->second.f << " , " 00100 << m2->second.t << std::endl; 00101 } 00102 return 1.0/m->second.c*m2->second.c; 00103 } 00104 } else if (m->second.f==to) { 00105 std::string b=m->second.t+","+from; 00106 miter m2=mcache.find(b); 00107 if (m2!=mcache.end()) { 00108 if (verbose>0) { 00109 std::cout << "Using conversions: " << m->second.f << " , " 00110 << m->second.t << std::endl; 00111 std::cout << " (4) and: " << m2->second.f << " , " 00112 << m2->second.t << std::endl; 00113 } 00114 return 1.0/m->second.c/m2->second.c; 00115 } 00116 std::string b2=from+","+m->second.t; 00117 miter m4=mcache.find(b2); 00118 if (m4!=mcache.end()) { 00119 if (verbose>0) { 00120 std::cout << "Using conversions: " << m->second.f << " , " 00121 << m->second.t << std::endl; 00122 std::cout << " (5) and: " << m4->second.f << " , " 00123 << m4->second.t << std::endl; 00124 } 00125 return 1.0/m->second.c*m4->second.c; 00126 } 00127 } else if (m->second.t==to) { 00128 std::string b=m->second.f+","+from; 00129 miter m2=mcache.find(b); 00130 if (m2!=mcache.end()) { 00131 if (verbose>0) { 00132 std::cout << "Using conversions: " << m->second.f << " , " 00133 << m->second.t << std::endl; 00134 std::cout << " (6) and: " << m2->second.f << " , " 00135 << m2->second.t << std::endl; 00136 } 00137 return m->second.c/m2->second.c; 00138 } 00139 } 00140 } 00141 00142 // Neither found, run the 'units' command 00143 std::string cmd="units '"+from+"' '"+to+"'"; 00144 if (verbose>0) std::cout << "cmd: " << cmd << std::endl; 00145 FILE *ps_pipe=popen(cmd.c_str(),"r"); 00146 00147 if (!ps_pipe) { 00148 O2SCL_ERR("Pipe could not be opened in convert_units::convert().", 00149 gsl_efailed); 00150 return 0.0; 00151 } 00152 00153 char line1[80]; 00154 int size=80; 00155 00156 fgets(line1,80,ps_pipe); 00157 if (verbose>0) std::cout << "output: " << line1 << std::endl; 00158 00159 // Read the output from the 'units' command and compute the 00160 // conversion factor 00161 std::string s=line1, t1, t2; 00162 std::istringstream *ins=new std::istringstream(s); 00163 (*ins) >> t1 >> t2; 00164 delete ins; 00165 double conv=stod(t2); 00166 00167 // Cleanup 00168 if (pclose(ps_pipe)!=0) { 00169 O2SCL_ERR("Pipe could not be closed in convert_units::convert().", 00170 gsl_efailed); 00171 return 0.0; 00172 } 00173 00174 // Add the newly computed conversion to the table 00175 unit_t ut; 00176 ut.f=from; 00177 ut.t=to; 00178 ut.c=conv; 00179 mcache.insert(make_pair(both,ut)); 00180 00181 return conv*val; 00182 } 00183 00184 }; 00185 00186 #ifndef DOXYGENP 00187 } 00188 #endif 00189 00190 #endif
Documentation generated with Doxygen and provided under the GNU Free Documentation License. See License Information for details.
Project hosting provided by
,
O2scl Sourceforge Project Page