add operator<< for messages (#2461)
This commit is contained in:
parent
ebca5bedca
commit
b7d2f5af73
|
@ -18,7 +18,7 @@ PACKAGE_NAME=$(shell basename $(PWD))
|
|||
# and thus CMake no longer knows about it.
|
||||
clean:
|
||||
-cd build && make clean
|
||||
rm -rf gen_msg gen_srv msg/cpp msg/lisp msg/oct msg/java srv/cpp srv/lisp srv/oct srv/java src/$(PACKAGE_NAME)/msg src/$(PACKAGE_NAME)/srv
|
||||
rm -rf msg_gen srv_gen msg/cpp msg/lisp msg/oct msg/java srv/cpp srv/lisp srv/oct srv/java src/$(PACKAGE_NAME)/msg src/$(PACKAGE_NAME)/srv
|
||||
rm -rf build
|
||||
|
||||
# All other targets are just passed through
|
||||
|
|
|
@ -145,8 +145,10 @@ def write_generic_includes(s):
|
|||
"""
|
||||
s.write('#include <string>\n')
|
||||
s.write('#include <vector>\n')
|
||||
s.write('#include <ostream>\n')
|
||||
s.write('#include "ros/serialization.h"\n')
|
||||
s.write('#include "ros/builtin_message_traits.h"\n')
|
||||
s.write('#include "ros/message_operations.h"\n')
|
||||
s.write('#include "ros/message.h"\n')
|
||||
s.write('#include "ros/time.h"\n\n')
|
||||
|
||||
|
@ -564,9 +566,42 @@ def write_traits(s, spec, cpp_name_prefix, datatype = None):
|
|||
if (is_fixed_length(spec)):
|
||||
write_trait_true_class(s, 'IsFixedSize', cpp_msg_with_alloc)
|
||||
|
||||
s.write('} // namespace message_traits\n')
|
||||
s.write('} // namespace ros\n\n')
|
||||
|
||||
def write_operations(s, spec, cpp_name_prefix):
|
||||
(cpp_msg_unqualified, cpp_msg_with_alloc, _) = cpp_message_declarations(cpp_name_prefix, spec.short_name)
|
||||
s.write('namespace ros\n{\n')
|
||||
s.write('namespace message_operations\n{\n')
|
||||
|
||||
# Write the Printer operation
|
||||
s.write('\ntemplate<class ContainerAllocator>\nstruct Printer<%s>\n{\n'%(cpp_msg_with_alloc))
|
||||
s.write(' template<typename Stream> static void stream(Stream& s, const std::string& indent, const %s& v) \n {\n'%cpp_msg_with_alloc)
|
||||
for field in spec.parsed_fields():
|
||||
cpp_type = msg_type_to_cpp(field.base_type)
|
||||
if (field.is_array):
|
||||
s.write(' s << indent << "%s[]" << std::endl;\n'%(field.name))
|
||||
s.write(' for (size_t i = 0; i < v.%s.size(); ++i)\n {\n'%(field.name))
|
||||
s.write(' s << indent << " %s[" << i << "]: ";\n'%field.name)
|
||||
indent_increment = ' '
|
||||
if (not field.is_builtin):
|
||||
s.write(' s << std::endl;\n')
|
||||
s.write(' s << indent;\n')
|
||||
indent_increment = ' ';
|
||||
s.write(' Printer<%s>::stream(s, indent + "%s", v.%s[i]);\n'%(cpp_type, indent_increment, field.name))
|
||||
s.write(' }\n')
|
||||
else:
|
||||
s.write(' s << indent << "%s: ";\n'%field.name)
|
||||
indent_increment = ' '
|
||||
if (not field.is_builtin or field.is_array):
|
||||
s.write('s << std::endl;\n')
|
||||
s.write(' Printer<%s>::stream(s, indent + "%s", v.%s);\n'%(cpp_type, indent_increment, field.name))
|
||||
s.write(' }\n')
|
||||
s.write('};\n\n')
|
||||
|
||||
s.write('\n')
|
||||
|
||||
s.write('} // namespace message_traits\n')
|
||||
s.write('} // namespace message_operations\n')
|
||||
s.write('} // namespace ros\n\n')
|
||||
|
||||
def write_serialization(s, spec, cpp_name_prefix):
|
||||
|
@ -598,6 +633,11 @@ def write_serialization(s, spec, cpp_name_prefix):
|
|||
|
||||
s.write('} // namespace serialization\n')
|
||||
s.write('} // namespace ros\n\n')
|
||||
|
||||
def write_ostream_operator(s, spec, cpp_name_prefix):
|
||||
(cpp_msg_unqualified, cpp_msg_with_alloc, _) = cpp_message_declarations(cpp_name_prefix, spec.short_name)
|
||||
s.write('template<typename ContainerAllocator>\nstd::ostream& operator<<(std::ostream& s, const %s& v)\n{\n'%(cpp_msg_with_alloc))
|
||||
s.write(' ros::message_operations::Printer<%s>::stream(s, "", v);\n return s;}\n\n'%(cpp_msg_with_alloc))
|
||||
|
||||
def generate(msg_path):
|
||||
"""
|
||||
|
@ -618,10 +658,12 @@ def generate(msg_path):
|
|||
|
||||
s.write('namespace %s\n{\n'%(package))
|
||||
write_struct(s, spec, cpp_prefix)
|
||||
write_ostream_operator(s, spec, cpp_prefix)
|
||||
s.write('} // namespace %s\n\n'%(package))
|
||||
|
||||
write_traits(s, spec, cpp_prefix)
|
||||
write_serialization(s, spec, cpp_prefix)
|
||||
write_operations(s, spec, cpp_prefix)
|
||||
write_end(s, spec)
|
||||
|
||||
output_dir = '%s/msg_gen/cpp/include/%s'%(package_dir, package)
|
||||
|
@ -632,7 +674,7 @@ def generate(msg_path):
|
|||
os.makedirs(output_dir)
|
||||
except OSError, e:
|
||||
pass
|
||||
|
||||
|
||||
f = open('%s/%s.h'%(output_dir, spec.short_name), 'w')
|
||||
print >> f, s.getvalue()
|
||||
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2010, Willow Garage, Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the names of Willow Garage, Inc. nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ROSLIB_MESSAGE_OPERATIONS_H
|
||||
#define ROSLIB_MESSAGE_OPERATIONS_H
|
||||
|
||||
#include <ostream>
|
||||
|
||||
namespace ros
|
||||
{
|
||||
namespace message_operations
|
||||
{
|
||||
|
||||
template<typename M>
|
||||
struct Printer
|
||||
{
|
||||
template<typename Stream>
|
||||
static void stream(Stream& s, const std::string& indent, const M& value)
|
||||
{
|
||||
s << value << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
// Explicitly specialize for uint8_t/int8_t because otherwise it thinks it's a char, and treats
|
||||
// the value as a character code
|
||||
template<>
|
||||
struct Printer<int8_t>
|
||||
{
|
||||
template<typename Stream>
|
||||
static void stream(Stream& s, const std::string& indent, int8_t value)
|
||||
{
|
||||
s << (uint32_t)value << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Printer<uint8_t>
|
||||
{
|
||||
template<typename Stream>
|
||||
static void stream(Stream& s, const std::string& indent, uint8_t value)
|
||||
{
|
||||
s << (uint32_t)value << "\n";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace message_operations
|
||||
} // namespace ros
|
||||
|
||||
#endif // ROSLIB_MESSAGE_OPERATIONS_H
|
||||
|
|
@ -225,6 +225,16 @@ ALLOCATOR_CONSTRUCTOR_COMPILATION_TEST(MyWithMemberNamedHeaderThatIsNotAHeader,
|
|||
ALLOCATOR_CONSTRUCTOR_COMPILATION_TEST(MyFixedLengthArrayOfExternal, Allocator<void>);
|
||||
ALLOCATOR_CONSTRUCTOR_COMPILATION_TEST(MyVariableLengthArrayOfExternal, Allocator<void>);
|
||||
|
||||
TEST(Generated, serializationOStreamOperator)
|
||||
{
|
||||
using namespace ros::serialization;
|
||||
Array b(new uint8_t[8]);
|
||||
OStream ostream(b.get(), 8);
|
||||
FixedLength m;
|
||||
ostream << m;
|
||||
ASSERT_EQ(ostream.getLength(), 0UL);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
|
Loading…
Reference in New Issue