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
moos/libmoos_util/moos_protobuf_helpers.h
Go to the documentation of this file.
00001 // copyright 2011 t. schneider tes@mit.edu
00002 // 
00003 // this file is part of goby-acomms, a collection of libraries for acoustic underwater networking
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This software is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this software.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #ifndef MOOSPROTOBUFHELPERS20110216H
00019 #define MOOSPROTOBUFHELPERS20110216H
00020 
00021 #include "google/protobuf/io/printer.h"
00022 #include <google/protobuf/io/tokenizer.h>
00023 #include "goby/util/liblogger/flex_ostream.h"
00024 #include "goby/util/string.h"
00025 
00027 
00032 inline void serialize_for_moos(std::string* out, const google::protobuf::Message& msg)
00033 {
00034     google::protobuf::TextFormat::Printer printer;
00035     printer.SetSingleLineMode(true);
00036     printer.PrintToString(msg, out);
00037 }
00038 
00039 
00044 inline void parse_for_moos(const std::string& in, google::protobuf::Message* msg)
00045 {
00046     google::protobuf::TextFormat::Parser parser;
00047     FlexOStreamErrorCollector error_collector(in);
00048     parser.RecordErrorsTo(&error_collector);
00049     parser.ParseFromString(in, msg);
00050 }
00051 
00052 inline void from_moos_comma_equals_string_field(google::protobuf::Message* proto_msg, const google::protobuf::FieldDescriptor* field_desc, const std::vector<std::string>& values, int value_key = 0)
00053 {
00054     if(values.size() == 0)
00055         return;
00056     
00057     
00058     const google::protobuf::Reflection* refl = proto_msg->GetReflection();
00059     if(field_desc->is_repeated())
00060     {
00061         for(int j = 0, m = values.size(); j < m; ++j)
00062         {
00063             const std::string& v = values[j];
00064 
00065             switch(field_desc->cpp_type())
00066             {
00067                 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00068                     break;    
00069                         
00070                 case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
00071                     refl->AddInt32(proto_msg, field_desc, goby::util::as<google::protobuf::int32>(v));
00072                     break;
00073                             
00074                 case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
00075                     refl->AddInt64(proto_msg, field_desc, goby::util::as<google::protobuf::int64>(v));
00076                     break;
00077                             
00078                 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
00079                     refl->AddUInt32(proto_msg, field_desc, goby::util::as<google::protobuf::uint32>(v));
00080                     break;
00081                             
00082                 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
00083                     refl->AddUInt64(proto_msg, field_desc, goby::util::as<google::protobuf::uint64>(v));
00084                     break;
00085                             
00086                 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
00087                     refl->AddBool(proto_msg, field_desc, goby::util::as<bool>(v));
00088                     break;
00089                             
00090                 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
00091                     refl->AddString(proto_msg, field_desc, v);
00092                     break;                    
00093                             
00094                 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
00095                     refl->AddFloat(proto_msg, field_desc, goby::util::as<float>(v));
00096                     break;
00097                             
00098                 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
00099                     refl->AddDouble(proto_msg, field_desc, goby::util::as<double>(v));
00100                     break;
00101                             
00102                 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
00103                 {
00104                     const google::protobuf::EnumValueDescriptor* enum_desc =
00105                         refl->GetEnum(*proto_msg, field_desc)->type()->FindValueByName(v);
00106                     if(enum_desc)
00107                         refl->AddEnum(proto_msg, field_desc, enum_desc);
00108                 }
00109                 break;
00110                 
00111             }                
00112         }
00113     }
00114     else
00115     {
00116         const std::string& v = values[value_key];
00117         switch(field_desc->cpp_type())
00118         {
00119             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00120                 break;
00121                         
00122             case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
00123                 refl->SetInt32(proto_msg, field_desc, goby::util::as<google::protobuf::int32>(v));
00124                 break;
00125                         
00126             case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
00127                 refl->SetInt64(proto_msg, field_desc, goby::util::as<google::protobuf::int64>(v));                        
00128                 break;
00129 
00130             case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
00131                 refl->SetUInt32(proto_msg, field_desc, goby::util::as<google::protobuf::uint32>(v));
00132                 break;
00133 
00134             case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
00135                 refl->SetUInt64(proto_msg, field_desc, goby::util::as<google::protobuf::uint64>(v));
00136                 break;
00137                         
00138             case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
00139                 refl->SetBool(proto_msg, field_desc, goby::util::as<bool>(v));
00140                 break;
00141                     
00142             case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
00143                 refl->SetString(proto_msg, field_desc, v);
00144                 break;                    
00145                 
00146             case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
00147                 refl->SetFloat(proto_msg, field_desc, goby::util::as<float>(v));
00148                 break;
00149                 
00150             case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
00151                 refl->SetDouble(proto_msg, field_desc, goby::util::as<double>(v));
00152                 break;
00153                 
00154             case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
00155             {
00156                 const google::protobuf::EnumValueDescriptor* enum_desc =
00157                     refl->GetEnum(*proto_msg, field_desc)->type()->FindValueByName(v);
00158                 if(enum_desc)
00159                     refl->SetEnum(proto_msg, field_desc, enum_desc);
00160             }
00161             break;
00162         }
00163     }
00164 }
00165 
00166 inline void from_moos_comma_equals_string(google::protobuf::Message* proto_msg, const std::string& in)
00167 {
00168     const google::protobuf::Descriptor* desc = proto_msg->GetDescriptor();
00169     const google::protobuf::Reflection* refl = proto_msg->GetReflection();
00170 
00171     
00172     for(int i = 0, n = desc->field_count(); i < n; ++i)
00173     {
00174         const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
00175 
00176         switch(field_desc->cpp_type())
00177         {
00178             default:
00179             {
00180                 std::string val;
00181                 if(goby::util::val_from_string(val, in, field_desc->name()))
00182                 {
00183                     std::vector<std::string> vals;
00184                     boost::split(vals, val, boost::is_any_of(","));
00185                     from_moos_comma_equals_string_field(proto_msg, field_desc, vals);
00186                 }
00187             }
00188             break;
00189 
00190             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00191                 if(field_desc->is_repeated())
00192                 {
00193                     for(int k = 0, o = field_desc->message_type()->field_count(); k < o; ++k)
00194                     {
00195                         std::string val;
00196                         if(goby::util::val_from_string(val, in, field_desc->name() + "_" + field_desc->message_type()->field(k)->name()))
00197                         {
00198                             std::vector<std::string> vals;
00199                             boost::split(vals, val, boost::is_any_of(","));
00200                             
00201                             for(int j = 0, m = vals.size(); j < m; ++j)
00202                             {
00203 
00204                                 google::protobuf::Message* embedded_msg =
00205                                     (refl->FieldSize(*proto_msg, field_desc) < j+1) ?
00206                                     refl->AddMessage(proto_msg, field_desc) :
00207                                     refl->MutableRepeatedMessage(proto_msg, field_desc, j);     
00208                                 from_moos_comma_equals_string_field(embedded_msg, embedded_msg->GetDescriptor()->field(k), vals, j);
00209                             }
00210                         }
00211                     }   
00212                 }
00213                 else
00214                 {
00215                     for(int k = 0, o = field_desc->message_type()->field_count(); k < o; ++ k)
00216                     {
00217                         std::string val;
00218                         if(goby::util::val_from_string(val, in, field_desc->name() + "_" + field_desc->message_type()->field(k)->name()))
00219                         {
00220                             std::vector<std::string> vals;
00221                             boost::split(vals, val, boost::is_any_of(","));
00222 
00223                             google::protobuf::Message* embedded_msg = refl->MutableMessage(proto_msg, field_desc);     
00224                             from_moos_comma_equals_string_field(embedded_msg, embedded_msg->GetDescriptor()->field(k), vals);
00225                         }
00226                     }
00227                 }
00228                 break;
00229         }
00230     }    
00231 }
00232 
00233 inline std::string to_moos_comma_equals_string_field(const google::protobuf::Message& proto_msg, const google::protobuf::FieldDescriptor* field_desc, bool write_key = true)
00234 {
00235     const google::protobuf::Reflection* refl = proto_msg.GetReflection();
00236 
00237     std::stringstream out;
00238     const std::string& field_name = field_desc->name();
00239         
00240     if(field_desc->is_repeated())
00241     {
00242         if(write_key)
00243             out << field_name << "={";
00244 
00245         for(int j = 0, m = refl->FieldSize(proto_msg, field_desc); j < m; ++j)
00246         {
00247             if(j) out << ",";
00248             
00249             switch(field_desc->cpp_type())
00250             {
00251                 case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00252                     break;    
00253                         
00254                 case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
00255                     out << refl->GetRepeatedInt32(proto_msg, field_desc, j);
00256                     break;
00257                             
00258                 case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
00259                     out << refl->GetRepeatedInt64(proto_msg, field_desc, j);
00260                     break;
00261                             
00262                 case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
00263                     out << refl->GetRepeatedUInt32(proto_msg, field_desc, j);
00264                     break;
00265                             
00266                 case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
00267                     out << refl->GetRepeatedUInt64(proto_msg, field_desc, j);
00268                     break;
00269                             
00270                 case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
00271                     out << std::boolalpha << refl->GetRepeatedBool(proto_msg, field_desc, j);
00272                     break;
00273                             
00274                 case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
00275                     out << refl->GetRepeatedString(proto_msg, field_desc, j);
00276                     break;                    
00277                             
00278                 case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
00279                     out << refl->GetRepeatedFloat(proto_msg, field_desc, j);
00280                     break;
00281                             
00282                 case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
00283                     out << std::setprecision(15) << refl->GetRepeatedDouble(proto_msg, field_desc, j);
00284                     break;
00285                             
00286                 case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
00287                     out << refl->GetRepeatedEnum(proto_msg, field_desc, j)->name();
00288                     break;
00289                             
00290             }
00291                 
00292         }
00293         if(write_key)
00294             out << "}";
00295     }
00296     else
00297     {
00298         if(write_key)
00299             out << field_name << "=";
00300         switch(field_desc->cpp_type())
00301         {
00302             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00303                 break;
00304                         
00305             case google::protobuf::FieldDescriptor::CPPTYPE_INT32:
00306                 out << refl->GetInt32(proto_msg, field_desc);
00307                 break;
00308                         
00309             case google::protobuf::FieldDescriptor::CPPTYPE_INT64:
00310                 out << refl->GetInt64(proto_msg, field_desc);                        
00311                 break;
00312 
00313             case google::protobuf::FieldDescriptor::CPPTYPE_UINT32:
00314                 out << refl->GetUInt32(proto_msg, field_desc);
00315                 break;
00316 
00317             case google::protobuf::FieldDescriptor::CPPTYPE_UINT64:
00318                 out << refl->GetUInt64(proto_msg, field_desc);
00319                 break;
00320                         
00321             case google::protobuf::FieldDescriptor::CPPTYPE_BOOL:
00322                 out << std::boolalpha << refl->GetBool(proto_msg, field_desc);
00323                 break;
00324                     
00325             case google::protobuf::FieldDescriptor::CPPTYPE_STRING:
00326                 out << refl->GetString(proto_msg, field_desc);
00327                 break;                    
00328                 
00329             case google::protobuf::FieldDescriptor::CPPTYPE_FLOAT:
00330                 out << refl->GetFloat(proto_msg, field_desc);
00331                 break;
00332                 
00333             case google::protobuf::FieldDescriptor::CPPTYPE_DOUBLE:
00334                 out << std::setprecision(15) << refl->GetDouble(proto_msg, field_desc);
00335                 break;
00336                 
00337             case google::protobuf::FieldDescriptor::CPPTYPE_ENUM:
00338                 out << refl->GetEnum(proto_msg, field_desc)->name();
00339                 break;
00340         }
00341     }
00342     return out.str();
00343 }
00344 
00345 inline void to_moos_comma_equals_string(const google::protobuf::Message& proto_msg, std::string* out)
00346 {
00347     std::stringstream out_ss;
00348     const google::protobuf::Descriptor* desc = proto_msg.GetDescriptor();
00349     const google::protobuf::Reflection* refl = proto_msg.GetReflection();
00350     
00351     for(int i = 0, n = desc->field_count(); i < n; ++i)
00352     {
00353         const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
00354         if(i) out_ss << ",";
00355 
00356         const std::string& field_name = field_desc->name();
00357 
00358         switch(field_desc->cpp_type())
00359         {
00360             default:
00361                 out_ss << to_moos_comma_equals_string_field(proto_msg, field_desc);
00362                 break;
00363 
00364             case google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE:
00365                 if(field_desc->is_repeated())
00366                 {
00367                     for(int k = 0, o = field_desc->message_type()->field_count(); k < o; ++ k)
00368                     {
00369                         if(k) out_ss << ",";
00370                         out_ss << field_name << "_" << field_desc->message_type()->field(k)->name() << "={";
00371                         for(int j = 0, m = refl->FieldSize(proto_msg, field_desc); j < m; ++j)
00372                         {
00373                             if(j) out_ss << ",";
00374                             const google::protobuf::Message& embedded_msg = refl->GetRepeatedMessage(proto_msg, field_desc, j);
00375                             out_ss << to_moos_comma_equals_string_field(embedded_msg, embedded_msg.GetDescriptor()->field(k), false);
00376                         }
00377                         out_ss << "}";
00378                     }
00379                 }
00380                 
00381                 else
00382                 {
00383                     for(int k = 0, o = field_desc->message_type()->field_count(); k < o; ++ k)
00384                     {
00385                         if(k) out_ss << ",";
00386                         out_ss << field_name << "_" << field_desc->message_type()->field(k)->name() << "=";
00387                         const google::protobuf::Message& embedded_msg = refl->GetMessage(proto_msg, field_desc);
00388                         out_ss << to_moos_comma_equals_string_field(embedded_msg, embedded_msg.GetDescriptor()->field(k), false);
00389                     }
00390                 }
00391                 
00392                 break;
00393         }
00394     }    
00395     *out = out_ss.str();
00396 }
00397 
00398 
00399 
00400 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends