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
util/string.h
00001 // copyright 2010 t. schneider tes@mit.edu
00002 // ocean engineering graudate student - mit / whoi joint program
00003 // massachusetts institute of technology (mit)
00004 // laboratory for autonomous marine sensing systems (lamss)    
00005 // 
00006 // this file is part of goby-util, a collection of utility libraries
00007 //
00008 //
00009 // This program is free software: you can redistribute it and/or modify
00010 // it under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 3 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // This software is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with this software.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022 #ifndef STRING20100713H
00023 #define STRING20100713H
00024 
00025 #include <string>
00026 #include <vector>
00027 #include <boost/lexical_cast.hpp>
00028 #include <iostream>
00029 #include <limits>
00030 #include <boost/utility.hpp>
00031 #include <boost/type_traits.hpp>
00032 #include <boost/algorithm/string.hpp>
00033 
00034 namespace goby
00035 {
00036 
00037     namespace util
00038     {   
00040 
00041         
00046         template<typename To, typename From>
00047             To as(From from, typename boost::enable_if<boost::is_fundamental<To> >::type* dummy = 0)
00048         {
00049             try { return boost::lexical_cast<To>(from); }
00050             catch(boost::bad_lexical_cast&)
00051             {
00052                 // return NaN or minimum value supported by the type
00053                 return std::numeric_limits<To>::has_quiet_NaN
00054                     ? std::numeric_limits<To>::quiet_NaN()
00055                     : std::numeric_limits<To>::min();
00056             }
00057         }
00058 
00063         template<typename To, typename From>
00064             To as(From from, typename boost::disable_if<boost::is_fundamental<To> >::type* dummy = 0)
00065         {
00066             try { return boost::lexical_cast<To>(from); }
00067             catch(boost::bad_lexical_cast&)
00068             {
00069                 return To();
00070             }
00071         }
00072         
00074         template <>
00075             inline bool as<bool, std::string>(std::string from, void* dummy)
00076         {
00077             return (boost::iequals(from, "true") || boost::iequals(from, "1"));
00078         }
00079         
00081         template <>
00082             inline std::string as<std::string, bool>(bool from, void* dummy)
00083         {
00084             std::stringstream ss;
00085             ss << std::boolalpha << from;
00086             return ss.str();
00087         }
00088 
00089 
00090         
00092         inline void stripblanks(std::string& s)
00093         {
00094             for(std::string::iterator it=s.end()-1; it!=s.begin()-1; --it)
00095             {    
00096                 if(isspace(*it))
00097                     s.erase(it);
00098             }
00099         }
00100 
00101         
00102         
00112         inline bool val_from_string(std::string& out, const std::string& str, const std::string & key)
00113         {
00114             // str:  foo=1,bar={2,3,4,5},pig=3,cow=yes
00115             // two cases:
00116             // key:  bar
00117             // key:  pig
00118             
00119             out.erase();
00120 
00121             // str:  foo=1,bar={2,3,4,5},pig=3,cow=yes
00122             //  start_pos  ^             ^
00123             std::string::size_type start_pos = str.find(std::string(key+"="));
00124         
00125             // deal with foo=bar,o=bar problem when looking for "o=" since
00126             // o is contained in foo
00127 
00128             // ok: beginning of string, end of string, comma right before start_pos
00129             while(!(start_pos == 0 || start_pos == std::string::npos || str[start_pos-1] == ','))
00130                 start_pos = str.find(std::string(key+"="), start_pos+1);
00131         
00132             if(start_pos != std::string::npos)
00133             {
00134                 // chopped:   bar={2,3,4,5},pig=3,cow=yes
00135                 // chopped:   pig=3,cow=yes
00136                 std::string chopped = str.substr(start_pos);
00137 
00138                 // chopped:  bar={2,3,4,5},pig=3,cow=yes
00139                 // equal_pos    ^         
00140                 // chopped:  pig=3,cow=yes
00141                 // equal_pos    ^         
00142                 std::string::size_type equal_pos = chopped.find("=");
00143 
00144                 // check for array
00145                 bool is_array = (equal_pos+1 < chopped.length() && chopped[equal_pos+1] == '{');
00146             
00147                 if(equal_pos != std::string::npos)
00148                 {
00149                     // chopped_twice:  ={2,3,4,5},pig=3,cow=yes
00150                     // chopped_twice:  =pig=3,cow=yes              
00151                     std::string chopped_twice = chopped.substr(equal_pos);
00152 
00153                     // chopped_twice:  ={2,3,4,5},pig=3,cow=yes  
00154                     // end_pos                  ^     
00155                     // chopped_twice:  =pig=3,cow=yes
00156                     // end_pos               ^         
00157                     std::string::size_type end_pos =
00158                         (is_array) ? chopped_twice.find("}") : chopped_twice.find(",");
00159 
00160                     // out:  2,3,4,5
00161                     // out:  3
00162                     out = (is_array) ? chopped_twice.substr(2, end_pos-2) : chopped_twice.substr(1, end_pos-1);
00163 
00164                     return true;
00165                 }
00166             }
00167 
00168             return false;        
00169         }        
00170 
00173         template<typename T>
00174             inline bool val_from_string(T& out, const std::string& str, const std::string & key)        
00175         {
00176             std::string s;
00177             if(!val_from_string(s, str, key)) return false;
00178             
00179             try { out = boost::lexical_cast<T>(s); }
00180             catch (boost::bad_lexical_cast&)
00181             { return false; }
00182 
00183             return true;            
00184         }
00185         
00186 
00188         inline bool val_from_string(bool& out, const std::string& str, const std::string & key)
00189         {
00190             std::string s;
00191             if(!val_from_string(s, str, key)) return false;
00192 
00193             out = as<bool>(s);
00194             return true;            
00195         }        
00197     }
00198 }
00199 #endif
00200 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends