Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
00001 // copyright 2009 t. schneider tes@mit.edu 00002 // 00003 // this file is part of the Dynamic Compact Control Language (DCCL), 00004 // the goby-acomms codec. goby-acomms is a collection of libraries 00005 // for acoustic underwater networking 00006 // 00007 // This program is free software: you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation, either version 3 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // This software is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with this software. If not, see <http://www.gnu.org/licenses/>. 00019 00020 #include <stdexcept> 00021 #include <iomanip> 00022 00023 #include <boost/foreach.hpp> 00024 00025 #include <boost/lexical_cast.hpp> 00026 #include <boost/numeric/conversion/cast.hpp> 00027 00028 #include "goby/util/string.h" 00029 #include "goby/util/sci.h" 00030 00031 #include "message_val.h" 00032 #include "dccl_exception.h" 00033 00034 using goby::util::as; 00035 00036 00037 void goby::acomms::DCCLMessageVal::init() 00038 { 00039 sval_ = ""; 00040 dval_ = 0; 00041 lval_ = 0; 00042 bval_ = false; 00043 precision_ = MAX_DBL_PRECISION; 00044 type_ = cpp_notype; 00045 } 00046 00047 00048 goby::acomms::DCCLMessageVal::DCCLMessageVal() 00049 { init(); } 00050 00051 00052 goby::acomms::DCCLMessageVal::DCCLMessageVal(const std::string& s) 00053 { 00054 init(); 00055 sval_ = s; 00056 type_ = cpp_string; 00057 } 00058 00059 00060 goby::acomms::DCCLMessageVal::DCCLMessageVal(const char* s) 00061 { 00062 init(); 00063 sval_ = s; 00064 type_ = cpp_string; 00065 } 00066 00067 00068 goby::acomms::DCCLMessageVal::DCCLMessageVal(double d, int p /* = MAX_DBL_PRECISION*/ ) 00069 { 00070 init(); 00071 dval_ = d; 00072 precision_ = p; 00073 type_ = cpp_double; 00074 } 00075 00076 goby::acomms::DCCLMessageVal::DCCLMessageVal(float f) 00077 { 00078 init(); 00079 dval_ = f; 00080 type_ = cpp_double; 00081 } 00082 00083 goby::acomms::DCCLMessageVal::DCCLMessageVal(long l) 00084 { 00085 init(); 00086 lval_ = l; 00087 type_ = cpp_long; 00088 } 00089 00090 goby::acomms::DCCLMessageVal::DCCLMessageVal(int i) 00091 { 00092 init(); 00093 lval_ = i; 00094 type_ = cpp_long; 00095 } 00096 00097 goby::acomms::DCCLMessageVal::DCCLMessageVal(bool b) 00098 { 00099 init(); 00100 bval_ = b; 00101 type_ = cpp_bool; 00102 } 00103 00104 00105 goby::acomms::DCCLMessageVal::DCCLMessageVal(const std::vector<DCCLMessageVal>& vm) 00106 { 00107 if(vm.size() != 1) 00108 throw(DCCLException("vector cast to DCCLMessageVal failed: vector is not size 1")); 00109 else 00110 *this = vm[0]; 00111 } 00112 00113 00114 void goby::acomms::DCCLMessageVal::set(std::string sval) 00115 { sval_ = sval; type_ = cpp_string; } 00116 void goby::acomms::DCCLMessageVal::set(double dval, int precision /* = MAX_DBL_PRECISION */) 00117 { dval_ = dval; type_ = cpp_double; precision_ = precision; } 00118 void goby::acomms::DCCLMessageVal::set(long lval) 00119 { lval_ = lval; type_ = cpp_long; } 00120 void goby::acomms::DCCLMessageVal::set(bool bval) 00121 { bval_ = bval; type_ = cpp_bool; } 00122 00123 00124 bool goby::acomms::DCCLMessageVal::get(std::string& s) const 00125 { 00126 std::stringstream ss; 00127 switch(type_) 00128 { 00129 case cpp_string: 00130 s = sval_; 00131 return true; 00132 00133 case cpp_double: 00134 if((log10(abs(dval_)) + precision_) <= MAX_DBL_PRECISION) 00135 ss << std::fixed << std::setprecision(precision_) << dval_; 00136 else 00137 ss << std::setprecision(precision_) << dval_; 00138 00139 s = ss.str(); 00140 return true; 00141 00142 case cpp_long: 00143 s = as<std::string>(lval_); 00144 return true; 00145 00146 case cpp_bool: 00147 s = (bval_) ? "true" : "false"; 00148 return true; 00149 00150 default: 00151 return false; 00152 } 00153 } 00154 00155 bool goby::acomms::DCCLMessageVal::get(bool& b) const 00156 { 00157 switch(type_) 00158 { 00159 case cpp_string: 00160 if(boost::iequals(sval_, "true") || boost::iequals(sval_, "1")) 00161 b = true; 00162 else if(boost::iequals(sval_, "false") || boost::iequals(sval_, "0")) 00163 b = false; 00164 else 00165 return false; 00166 return true; 00167 00168 case cpp_double: 00169 try { b = boost::numeric_cast<bool>(dval_); } 00170 catch(...) { return false; } 00171 return true; 00172 00173 case cpp_long: 00174 try { b = boost::numeric_cast<bool>(lval_); } 00175 catch(...) { return false; } 00176 return true; 00177 00178 case cpp_bool: 00179 b = bval_; 00180 return true; 00181 00182 default: 00183 return false; 00184 } 00185 } 00186 00187 bool goby::acomms::DCCLMessageVal::get(long& t) const 00188 { 00189 switch(type_) 00190 { 00191 case cpp_string: 00192 try 00193 { 00194 double d = boost::lexical_cast<double>(sval_); 00195 t = boost::numeric_cast<long>(util::unbiased_round(d, 0)); 00196 } 00197 catch (...) 00198 { 00199 if(boost::iequals(sval_, "true")) 00200 t = 1; 00201 else if(boost::iequals(sval_, "false")) 00202 t = 0; 00203 else 00204 return false; 00205 } 00206 return true; 00207 00208 case cpp_double: 00209 try { t = boost::numeric_cast<long>(util::unbiased_round(dval_, 0)); } 00210 catch(...) { return false; } 00211 return true; 00212 00213 case cpp_long: 00214 t = lval_; 00215 return true; 00216 00217 case cpp_bool: 00218 t = (bval_) ? 1 : 0; 00219 return true; 00220 00221 default: 00222 return false; 00223 } 00224 } 00225 00226 bool goby::acomms::DCCLMessageVal::get(double& d) const 00227 { 00228 switch(type_) 00229 { 00230 case cpp_string: 00231 try { d = boost::lexical_cast<double>(sval_); } 00232 catch (boost::bad_lexical_cast &) 00233 { 00234 if(boost::iequals(sval_, "true")) 00235 d = 1; 00236 else if(boost::iequals(sval_, "false")) 00237 d = 0; 00238 else 00239 return false; 00240 } 00241 return true; 00242 00243 case cpp_double: 00244 d = dval_; 00245 return true; 00246 00247 case cpp_long: 00248 try { d = boost::numeric_cast<double>(lval_); } 00249 catch (...) { return false; } 00250 return true; 00251 00252 case cpp_bool: 00253 d = (bval_) ? 1 : 0; 00254 return true; 00255 00256 default: 00257 return false; 00258 00259 } 00260 } 00261 00262 00263 00264 00265 goby::acomms::DCCLMessageVal::operator double() const 00266 { 00267 double d; 00268 if(get(d)) return d; 00269 else return acomms::NaN; 00270 } 00271 00272 00273 goby::acomms::DCCLMessageVal::operator bool() const 00274 { 00275 bool b; 00276 if(get(b)) return b; 00277 else return false; 00278 } 00279 00280 goby::acomms::DCCLMessageVal::operator std::string() const 00281 { 00282 std::string s; 00283 if(get(s)) return s; 00284 else return ""; 00285 } 00286 00287 goby::acomms::DCCLMessageVal::operator long() const 00288 { 00289 long l; 00290 if(get(l)) return l; 00291 else return 0; 00292 } 00293 00294 goby::acomms::DCCLMessageVal::operator int() const 00295 { 00296 return long(*this); 00297 } 00298 00299 goby::acomms::DCCLMessageVal::operator unsigned() const 00300 { 00301 return long(*this); 00302 } 00303 00304 goby::acomms::DCCLMessageVal::operator float() const 00305 { 00306 return double(*this); 00307 } 00308 00309 goby::acomms::DCCLMessageVal::operator std::vector<goby::acomms::DCCLMessageVal>() const 00310 { 00311 return std::vector<DCCLMessageVal>(1, *this); 00312 } 00313 00314 bool goby::acomms::DCCLMessageVal::operator==(const DCCLMessageVal& mv) const 00315 { 00316 switch(mv.type_) 00317 { 00318 case cpp_string: return mv == sval_; 00319 case cpp_double: return mv == dval_; 00320 case cpp_long: return mv == lval_; 00321 case cpp_bool: return mv == bval_; 00322 default: return false; 00323 } 00324 } 00325 00326 bool goby::acomms::DCCLMessageVal::operator==(const std::string& s) const 00327 { 00328 std::string us; 00329 return get(us) && us == s; 00330 } 00331 00332 bool goby::acomms::DCCLMessageVal::operator==(double d) const 00333 { 00334 double us; 00335 return get(us) && us == d; 00336 } 00337 00338 bool goby::acomms::DCCLMessageVal::operator==(long l) const 00339 { 00340 long us; 00341 return get(us) && us == l; 00342 } 00343 00344 bool goby::acomms::DCCLMessageVal::operator==(bool b) const 00345 { 00346 bool us; 00347 return get(us) && us == b; 00348 } 00349 00350 00351 00352 std::ostream& goby::acomms::operator<<(std::ostream& os, const goby::acomms::DCCLMessageVal& mv) 00353 { 00354 switch(mv.type_) 00355 { 00356 case cpp_string: return os << "std::string: " << mv.sval_; 00357 case cpp_double: return os << "double: " << std::fixed << std::setprecision(mv.precision_) << mv.dval_; 00358 case cpp_long: return os << "long: " << mv.lval_; 00359 case cpp_bool: return os << "bool: " << std::boolalpha << mv.bval_; 00360 default: return os << "{empty}"; 00361 } 00362 } 00363 00364 00365 std::ostream& goby::acomms::operator<<(std::ostream& os, const std::vector<goby::acomms::DCCLMessageVal>& vm) 00366 { 00367 int j=0; 00368 BOOST_FOREACH(const DCCLMessageVal& m, vm) 00369 { 00370 if(j) os << ","; 00371 os << m; 00372 ++j; 00373 } 00374 return os; 00375 }