add operator<< for messages (#2461)

This commit is contained in:
Josh Faust 2010-02-23 19:16:50 +00:00
parent ebca5bedca
commit b7d2f5af73
4 changed files with 129 additions and 3 deletions

View File

@ -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

View File

@ -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):
@ -599,6 +634,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):
"""
Generate a message
@ -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)

View File

@ -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

View File

@ -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);