Note: Goby version 1 (shown here) is now considered obsolete. Please use version 2 for new projects, and consider upgrading old projects.

Goby Underwater Autonomy Project  Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
acomms/libdccl/message_val.cpp
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends