Goby Underwater Autonomy Project
Series: 1.1, revision: 163, released on 2013-02-06 14:23:27 -0500
|
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