24 static const std::regex
NamePattern(
"^(?:([a-zA-Z][\\w|/]*)\\/)?([a-zA-Z]\\w*)$");
27 static const std::regex
LinePattern(
"^\\s*(?:([^\\s#]+)\\s+([a-zA-Z][a-zA-Z0-9_]*)\\s*(?:=\\s*(.*\\S)\\s*)?)?(?:#.*)?\\r?$");
30 static const std::regex
TypePattern(
"^([^\\[]+)(\\[(\\d+)?\\])?$");
38 return *found->second;
43 if (std::regex_match(messageType, match,
NamePattern))
46 auto package = match[1].str();
47 auto type = match[2].str();
52 if (parentPackage.size() > 0)
54 package = parentPackage;
63 auto key =
package + "/" + type;
67 return *found->second;
76 path +=
"/msg/" + type +
".msg";
99 std::ifstream stream(path);
102 while (std::getline(stream, line))
109 std::smatch lineMatch;
110 if (std::regex_match(line, lineMatch,
LinePattern))
112 if (lineMatch[1].matched)
115 auto type = lineMatch[1].str();
116 auto name = lineMatch[2].str();
119 if (lineMatch[3].matched)
122 auto value = lineMatch[3].str();
128 _constants.emplace_back(name, serializer, value);
133 std::smatch typeMatch;
134 if (std::regex_match(type, typeMatch,
TypePattern))
137 const char* parentPackage = package.c_str();
138 if (typeMatch[1].str() ==
"Header" &&
_fields.empty())
140 parentPackage =
"std_msgs";
147 if (typeMatch[2].matched)
150 if (typeMatch[3].matched)
153 auto length = std::stoul(typeMatch[3].str());
156 _fields.push_back(std::make_unique<FixedArrayField>(name, serializer, length));
166 _fields.push_back(std::make_unique<ArrayField>(name, serializer));
172 _fields.push_back(std::make_unique<Field>(name, serializer));
211 const auto& name =
_fields.front()->GetName();
212 if ((package ==
"swarmros" && name ==
"value") || (package ==
"std_msgs" && name ==
"data"))
219 if (!
_fields.empty() &&
_fields.front()->GetName() ==
"header" &&
_fields.front()->GetSerializer().GetFullName() ==
"std_msgs/Header")
228 std::stringstream stream;
229 for (
const auto& field :
_fields)
231 field->WriteDefinition(stream,
false);
242 bool firstLine =
true;
243 std::stringstream stream;
254 constant.WriteDefinition(stream,
true);
258 for (
const auto& field :
_fields)
268 field->WriteDefinition(stream,
true);
272 unsigned char rawHash[16];
273 std::string base = stream.str();
276 MD5_Update(&context, base.c_str(), base.size());
280 std::stringstream hashStream;
281 hashStream << std::hex << std::setfill(
'0');
282 for (
int i = 0; i <
sizeof(rawHash); ++i)
284 hashStream << std::setw(2) << (int)rawHash[i];
286 return hashStream.str();
300 else if (value.value_case() == swarmio::data::Variant::ValueCase::kMapValue)
307 "Unexpected source type for MessageSerializer",
309 swarmio::data::Variant::ValueCase::kMapValue,
317 for (
const auto& field :
_fields)
319 length += field->GetDefaultLength(fieldStack);
330 while (skipCount > 0)
340 auto entry = value.pairs().find(field->GetName());
341 if (entry != value.pairs().end())
343 length += field->CalculateSerializedLength(entry->second, fieldStack);
347 length += field->GetDefaultLength(fieldStack);
359 if (value.value_case() == swarmio::data::Variant::ValueCase::kMapArray)
362 for (
const auto& element : value.map_array().elements())
383 else if (value.value_case() == swarmio::data::Variant::ValueCase::kMapValue)
386 Serialize(stream, value.map_value(), skipCount, fieldStack);
391 "Unexpected source type for MessageSerializer",
393 swarmio::data::Variant::ValueCase::kMapValue,
400 const auto& pairs = value.pairs();
404 while (skipCount > 0)
414 auto value = pairs.find(field->GetName());
415 if (value != pairs.end())
417 field->Serialize(stream, value->second, fieldStack);
421 field->EmitDefault(stream, fieldStack);
430 for (
const auto& field :
_fields)
432 field->EmitDefault(stream, fieldStack);
447 swarmio::data::Variant value;
448 for (uint32_t i = 0; i < count; ++i)
450 Deserialize(stream, *value.mutable_map_array()->add_elements(), 0, current);
471 swarmio::data::Variant value;
472 Deserialize(stream, *value.mutable_map_value(), skipCount, fieldStack);
479 auto& map = *value.mutable_pairs();
483 while (skipCount > 0)
493 map[field->GetName()] = field->Deserialize(stream, fieldStack);
507 swarmio::data::discovery::Field field;
515 swarmio::data::discovery::Schema schema;
516 auto& map = *schema.mutable_fields();
520 while (skipCount > 0)
530 map[field->GetName()] = field->GetFieldDescriptor();
543 if (!enumerator(n++, *field))
void MD5_Init(MD5_CTX *ctx)
Init MD5 context.
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
Update MD5 context.
MessageSerializer(const std::string &package, const std::string &name, const std::string &path)
Construct a new MessageSerializer object.
static const std::regex TypePattern("^([^\\[]+)(\\[(\\d+)?\\])?$")
virtual swarmio::data::Variant DeserializeArray(ros::serialization::IStream &stream, uint32_t count, const FieldStack &fieldStack) const override
Deserialize a stream into a variant array.
virtual void Serialize(ros::serialization::OStream &stream, const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Serialize a variant onto a stream.
std::string _hash
MD5 hash of the message.
virtual swarmio::data::discovery::Field GetFieldDescriptor() const override
Build a field descriptor for the underlying type.
void EnumerateFields(std::function< bool(unsigned, const Field &)> enumerator) const
Enumerate the fields of the message with a function.
static const MessageSerializer & MessageSerializerForType(const std::string &type, const std::string &parentPackage)
Look up or build a reader for a message type.
const Field * _shortcut
For certain messages, the normal field processing is skipped and a single field is used to deserializ...
static std::map< std::string, std::unique_ptr< MessageSerializer > > _messageSerializers
Map of message serializers.
virtual std::string GetLocation() const =0
Construct the current location.
Serializer for full-fledged message types.
A Field represents an entry in a message reader that can read one of its fields.
bool _hasHeader
Whether the message begins with the standard header.
Exception thrown while parsing a message definition file.
static const std::regex NamePattern("^(?:([a-zA-Z][\\w|/]*)\\/)?([a-zA-Z]\\w*)$")
std::list< ConstantField > _constants
Constant fields.
virtual swarmio::data::Variant Deserialize(ros::serialization::IStream &stream, const FieldStack &fieldStack) const override
Deserialize a stream into a variant.
std::list< std::unique_ptr< Field > > _fields
Variable fields.
virtual void Serialize(ros::serialization::OStream &stream, const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Serialize a variant onto a stream.
ROSLIB_DECL std::string getPath(const std::string &package_name)
virtual uint32_t GetDefaultLength(const FieldStack &fieldStack) const override
Get the length of the default value.
std::string _package
Package name.
virtual void EmitDefault(ros::serialization::OStream &stream, const FieldStack &fieldStack) const override
Write the default value to the stream.
Exception thrown when the expected type of the Variant does not match the actual type.
virtual uint32_t CalculateSerializedLength(const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Calculate the length of a serialized message in bytes.
Serializer is the base class for all binary message interpreters.
static const Serializer & SerializerForType(const std::string &type, const std::string &parentPackage)
Look up or build a reader for a message type.
static const std::regex LinePattern("^\\s*(?:([^\\s#]+)\\s+([a-zA-Z][a-zA-Z0-9_]*)\\s*(?:=\\s*(.*\\S)\\s*)?)?(?:#.*)?\\r?$")
std::string CalculateHash()
Calculate the MD5 hash used to identify the message type.
std::string BuildCanonicalDefinition()
Build a canonical definition for the message.
virtual swarmio::data::discovery::Field GetFieldDescriptor() const override
Build a field descriptor for the underlying type.
const char * what() const noexceptoverride
Get the error message.
virtual swarmio::data::Variant Deserialize(ros::serialization::IStream &stream, const FieldStack &fieldStack) const override
Deserialize a stream into a variant.
virtual swarmio::data::Variant DeserializeArray(ros::serialization::IStream &stream, uint32_t count, const FieldStack &fieldStack) const override
Deserialize a stream into a variant array - not supported on Fields.
An exception that is expected to be caught and translated into another exception. ...
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
Finalize MD5 context.
virtual uint32_t CalculateSerializedLength(const swarmio::data::Variant &value, const FieldStack &fieldStack) const override
Calculate the length of a serialized message in bytes.
std::string _canonicalDefinition
Canonical definition of the message.
swarmio::data::discovery::Schema GetSchemaDescriptor(unsigned skipCount) const
Build a field descriptor for the underlying type, with or without its header.
std::string _fullName
Full name.