Add wstring support

Signed-off-by: Erik Boasson <eb@ilities.com>
This commit is contained in:
Erik Boasson 2019-08-19 11:09:01 +02:00 committed by eboasson
parent 021910e565
commit 10f18f0525
6 changed files with 244 additions and 0 deletions

View file

@ -54,6 +54,7 @@ add_library(rmw_cyclonedds_cpp
src/rmw_node.cpp src/rmw_node.cpp
src/serdata.cpp src/serdata.cpp
src/serdes.cpp src/serdes.cpp
src/u16string.cpp
) )
target_link_libraries(rmw_cyclonedds_cpp CycloneDDS::ddsc) target_link_libraries(rmw_cyclonedds_cpp CycloneDDS::ddsc)

View file

@ -18,6 +18,7 @@
#include <rosidl_generator_c/string.h> #include <rosidl_generator_c/string.h>
#include <rosidl_generator_c/string_functions.h> #include <rosidl_generator_c/string_functions.h>
#include <rosidl_generator_c/u16string_functions.h>
#include <cassert> #include <cassert>
#include <string> #include <string>

View file

@ -31,8 +31,10 @@
#include "rosidl_typesupport_introspection_c/service_introspection.h" #include "rosidl_typesupport_introspection_c/service_introspection.h"
#include "rosidl_generator_c/primitives_sequence_functions.h" #include "rosidl_generator_c/primitives_sequence_functions.h"
#include "rosidl_generator_c/u16string_functions.h"
#include "serdes.hpp" #include "serdes.hpp"
#include "u16string.hpp"
namespace rmw_cyclonedds_cpp namespace rmw_cyclonedds_cpp
{ {
@ -219,6 +221,35 @@ void serialize_field(
} }
} }
template<>
inline
void serialize_field<std::wstring>(
const rosidl_typesupport_introspection_cpp::MessageMember * member,
void * field,
cycser & ser)
{
std::wstring wstr;
if (!member->is_array_) {
auto u16str = static_cast<std::u16string *>(field);
u16string_to_wstring(*u16str, wstr);
ser << wstr;
} else {
size_t size;
if (member->array_size_ && !member->is_upper_bound_) {
size = member->array_size_;
} else {
size = member->size_function(field);
ser << static_cast<uint32_t>(size);
}
for (size_t i = 0; i < size; ++i) {
const void * element = member->get_const_function(field, i);
auto u16str = static_cast<const std::u16string *>(element);
u16string_to_wstring(*u16str, wstr);
ser << wstr;
}
}
}
// C specialization // C specialization
template<typename T> template<typename T>
void serialize_field( void serialize_field(
@ -275,6 +306,34 @@ void serialize_field<std::string>(
} }
} }
template<>
inline
void serialize_field<std::wstring>(
const rosidl_typesupport_introspection_c__MessageMember * member,
void * field,
cycser & ser)
{
std::wstring wstr;
if (!member->is_array_) {
auto u16str = static_cast<rosidl_generator_c__U16String *>(field);
u16string_to_wstring(*u16str, wstr);
ser << wstr;
} else if (member->array_size_ && !member->is_upper_bound_) {
auto array = static_cast<rosidl_generator_c__U16String *>(field);
for (size_t i = 0; i < member->array_size_; ++i) {
u16string_to_wstring(array[i], wstr);
ser << wstr;
}
} else {
auto sequence = static_cast<rosidl_generator_c__U16String__Sequence *>(field);
ser << static_cast<uint32_t>(sequence->size);
for (size_t i = 0; i < sequence->size; ++i) {
u16string_to_wstring(sequence->data[i], wstr);
ser << wstr;
}
}
}
inline inline
size_t get_array_size_and_assign_field( size_t get_array_size_and_assign_field(
const rosidl_typesupport_introspection_cpp::MessageMember * member, const rosidl_typesupport_introspection_cpp::MessageMember * member,
@ -363,6 +422,9 @@ bool TypeSupport<MembersType>::serializeROSmessage(
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING: case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING:
serialize_field<std::string>(member, field, ser); serialize_field<std::string>(member, field, ser);
break; break;
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_WSTRING:
serialize_field<std::wstring>(member, field, ser);
break;
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE: case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE:
{ {
auto sub_members = static_cast<const MembersType *>(member->members_->data); auto sub_members = static_cast<const MembersType *>(member->members_->data);
@ -453,6 +515,36 @@ inline void deserialize_field<std::string>(
} }
} }
template<>
inline void deserialize_field<std::wstring>(
const rosidl_typesupport_introspection_cpp::MessageMember * member,
void * field,
cycdeser & deser,
bool call_new)
{
(void)call_new;
std::wstring wstr;
if (!member->is_array_) {
deser >> wstr;
wstring_to_u16string(
wstr, *static_cast<std::u16string *>(field));
} else {
uint32_t size;
if (member->array_size_ && !member->is_upper_bound_) {
size = static_cast<uint32_t>(member->array_size_);
} else {
deser >> size;
member->resize_function(field, size);
}
for (size_t i = 0; i < size; ++i) {
void * element = member->get_function(field, i);
auto u16str = static_cast<std::u16string *>(element);
deser >> wstr;
wstring_to_u16string(wstr, *u16str);
}
}
}
template<typename T> template<typename T>
void deserialize_field( void deserialize_field(
const rosidl_typesupport_introspection_c__MessageMember * member, const rosidl_typesupport_introspection_c__MessageMember * member,
@ -519,6 +611,39 @@ inline void deserialize_field<std::string>(
} }
} }
template<>
inline void deserialize_field<std::wstring>(
const rosidl_typesupport_introspection_c__MessageMember * member,
void * field,
cycdeser & deser,
bool call_new)
{
(void)call_new;
std::wstring wstr;
if (!member->is_array_) {
deser >> wstr;
wstring_to_u16string(
wstr, *static_cast<rosidl_generator_c__U16String *>(field));
} else if (member->array_size_ && !member->is_upper_bound_) {
auto array = static_cast<rosidl_generator_c__U16String *>(field);
for (size_t i = 0; i < member->array_size_; ++i) {
deser >> wstr;
wstring_to_u16string(wstr, array[i]);
}
} else {
uint32_t size;
deser >> size;
auto sequence = static_cast<rosidl_generator_c__U16String__Sequence *>(field);
if (!rosidl_generator_c__U16String__Sequence__init(sequence, size)) {
throw std::runtime_error("unable to initialize rosidl_generator_c__U16String sequence");
}
for (size_t i = 0; i < sequence->size; ++i) {
deser >> wstr;
wstring_to_u16string(wstr, sequence->data[i]);
}
}
}
inline size_t get_submessage_array_deserialize( inline size_t get_submessage_array_deserialize(
const rosidl_typesupport_introspection_cpp::MessageMember * member, const rosidl_typesupport_introspection_cpp::MessageMember * member,
cycdeser & deser, cycdeser & deser,
@ -610,6 +735,9 @@ bool TypeSupport<MembersType>::deserializeROSmessage(
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING: case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_STRING:
deserialize_field<std::string>(member, field, deser, call_new); deserialize_field<std::string>(member, field, deser, call_new);
break; break;
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_WSTRING:
deserialize_field<std::wstring>(member, field, deser, call_new);
break;
case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE: case ::rosidl_typesupport_introspection_cpp::ROS_TYPE_MESSAGE:
{ {
auto sub_members = (const MembersType *)member->members_->data; auto sub_members = (const MembersType *)member->members_->data;

View file

@ -42,6 +42,7 @@ public:
inline cycser & operator<<(double x) {serialize(x); return *this;} inline cycser & operator<<(double x) {serialize(x); return *this;}
inline cycser & operator<<(const char * x) {serialize(x); return *this;} inline cycser & operator<<(const char * x) {serialize(x); return *this;}
inline cycser & operator<<(const std::string & x) {serialize(x); return *this;} inline cycser & operator<<(const std::string & x) {serialize(x); return *this;}
inline cycser & operator<<(const std::wstring & x) {serialize(x); return *this;}
template<class T> template<class T>
inline cycser & operator<<(const std::vector<T> & x) {serialize(x); return *this;} inline cycser & operator<<(const std::vector<T> & x) {serialize(x); return *this;}
template<class T, size_t S> template<class T, size_t S>
@ -88,6 +89,14 @@ public:
memcpy(data() + off, x.c_str(), sz); memcpy(data() + off, x.c_str(), sz);
off += sz; off += sz;
} }
inline void serialize(const std::wstring & x)
{
size_t sz = x.size() + 1;
serialize(static_cast<uint32_t>(sz));
resize(off + sz * sizeof(wchar_t));
memcpy(data() + off, reinterpret_cast<const char *>(x.c_str()), sz * sizeof(wchar_t));
off += sz * sizeof(wchar_t);
}
#define SIMPLEA(T) inline void serializeA(const T * x, size_t cnt) { \ #define SIMPLEA(T) inline void serializeA(const T * x, size_t cnt) { \
if (cnt > 0) { \ if (cnt > 0) { \
@ -165,6 +174,7 @@ public:
inline cycdeser & operator>>(double & x) {deserialize(x); return *this;} inline cycdeser & operator>>(double & x) {deserialize(x); return *this;}
inline cycdeser & operator>>(char * & x) {deserialize(x); return *this;} inline cycdeser & operator>>(char * & x) {deserialize(x); return *this;}
inline cycdeser & operator>>(std::string & x) {deserialize(x); return *this;} inline cycdeser & operator>>(std::string & x) {deserialize(x); return *this;}
inline cycdeser & operator>>(std::wstring & x) {deserialize(x); return *this;}
template<class T> template<class T>
inline cycdeser & operator>>(std::vector<T> & x) {deserialize(x); return *this;} inline cycdeser & operator>>(std::vector<T> & x) {deserialize(x); return *this;}
template<class T, size_t S> template<class T, size_t S>
@ -209,6 +219,12 @@ public:
x = std::string(data + pos, sz - 1); x = std::string(data + pos, sz - 1);
pos += sz; pos += sz;
} }
inline void deserialize(std::wstring & x)
{
const uint32_t sz = deserialize32();
x = std::wstring(reinterpret_cast<const wchar_t *>(data + pos), sz - 1);
pos += sz * sizeof(wchar_t);
}
#define SIMPLEA(T) inline void deserializeA(T * x, size_t cnt) { \ #define SIMPLEA(T) inline void deserializeA(T * x, size_t cnt) { \
if (cnt > 0) { \ if (cnt > 0) { \

View file

@ -0,0 +1,36 @@
// Copyright 2019 ADLINK Technology
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef RMW_CYCLONEDDS_CPP__U16STRING_HPP_
#define RMW_CYCLONEDDS_CPP__U16STRING_HPP_
#include <string>
#include "rosidl_generator_c/u16string_functions.h"
namespace rmw_cyclonedds_cpp
{
void u16string_to_wstring(
const rosidl_generator_c__U16String & u16str, std::wstring & wstr);
bool wstring_to_u16string(
const std::wstring & wstr, rosidl_generator_c__U16String & u16str);
void u16string_to_wstring(const std::u16string & u16str, std::wstring & wstr);
bool wstring_to_u16string(const std::wstring & wstr, std::u16string & u16str);
} // namespace rmw_cyclonedds_cpp
#endif // RMW_CYCLONEDDS_CPP__U16STRING_HPP_

View file

@ -0,0 +1,62 @@
// Copyright 2019 ADLINK Technology
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <string>
#include "rosidl_generator_c/u16string_functions.h"
namespace rmw_cyclonedds_cpp
{
void u16string_to_wstring(const std::u16string & u16str, std::wstring & wstr)
{
wstr.resize(u16str.size());
for (size_t i = 0; i < u16str.size(); ++i) {
wstr[i] = static_cast<wchar_t>(u16str[i]);
}
}
bool wstring_to_u16string(const std::wstring & wstr, std::u16string & u16str)
{
try {
u16str.resize(wstr.size());
} catch (...) {
return false;
}
for (size_t i = 0; i < wstr.size(); ++i) {
u16str[i] = static_cast<char16_t>(wstr[i]);
}
return true;
}
void u16string_to_wstring(const rosidl_generator_c__U16String & u16str, std::wstring & wstr)
{
wstr.resize(u16str.size);
for (size_t i = 0; i < u16str.size; ++i) {
wstr[i] = static_cast<wchar_t>(u16str.data[i]);
}
}
bool wstring_to_u16string(const std::wstring & wstr, rosidl_generator_c__U16String & u16str)
{
bool succeeded = rosidl_generator_c__U16String__resize(&u16str, wstr.size());
if (!succeeded) {
return false;
}
for (size_t i = 0; i < wstr.size(); ++i) {
u16str.data[i] = static_cast<char16_t>(wstr[i]);
}
return true;
}
} // namespace rmw_cyclonedds_cpp