pax_global_header00006660000000000000000000000064134437474360014531gustar00rootroot0000000000000052 comment=e12443e0b6ab29f51eb361149e87e82bebfa4d93 gencpp-0.6.2/000077500000000000000000000000001344374743600130125ustar00rootroot00000000000000gencpp-0.6.2/.gitignore000066400000000000000000000000151344374743600147760ustar00rootroot00000000000000*.pyc ._* *~ gencpp-0.6.2/CHANGELOG.rst000066400000000000000000000046011344374743600150340ustar00rootroot00000000000000^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Changelog for package gencpp ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0.6.2 (2019-03-18) ------------------ * add plugins the ability to also generate free functions (`#40 `_) 0.6.1 (2019-03-04) ------------------ * enable Windows build (`#38 `_) 0.6.0 (2018-01-29) ------------------ * add plugin support for generated C++ message headers (`#32 `_) * put all the message integer constants into a common enum (`#25 `_) 0.5.5 (2016-06-27) ------------------ * fix extra semicolon warning (`#26 `_) 0.5.4 (2016-03-14) ------------------ * fix unused parameter warning (`#24 `_) 0.5.3 (2014-12-22) ------------------ * remove copyright header from generated code (`#20 `_) 0.5.2 (2014-05-07) ------------------ * add architecture_independent flag in package.xml (`#19 `_) 0.5.1 (2014-02-24) ------------------ * use catkin_install_python() to install Python scripts (`#18 `_) * add 'u' suffix to unsigned enum values to avoid compiler warning (`#16 `_) 0.5.0 (2014-01-29) ------------------ * remove __connection_header from message template (`#3 `_) 0.4.16 (2014-01-27) ------------------- * fix warning about empty message definition (`ros/ros_comm#344 `_) 0.4.15 (2014-01-07) ------------------- * python 3 compatibility * fix generated code of message definition with windows line endings (`#6 `_) 0.4.14 (2013-08-21) ------------------- * make gencpp relocatable (`ros/catkin#490 `_) 0.4.13 (2013-06-18) ------------------- * update message targets to depend on template * update msg template to generate empty functions without warnings about unused variables (`#4 `_) 0.4.12 (2013-03-08) ------------------- * fix handling spaces in folder names (`ros/catkin#375 `_) 0.4.11 (2012-12-21) ------------------- * first public release for Groovy gencpp-0.6.2/CMakeLists.txt000066400000000000000000000006441344374743600155560ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.8.3) project(gencpp) find_package(catkin REQUIRED COMPONENTS genmsg) catkin_package( CATKIN_DEPENDS genmsg CFG_EXTRAS gencpp-extras.cmake ) add_subdirectory(scripts) file(WRITE ${CATKIN_DEVEL_PREFIX}/${GENMSG_LANGS_DESTINATION}/gencpp "C++") install(FILES ${CATKIN_DEVEL_PREFIX}/${GENMSG_LANGS_DESTINATION}/gencpp DESTINATION ${GENMSG_LANGS_DESTINATION}) catkin_python_setup() gencpp-0.6.2/cmake/000077500000000000000000000000001344374743600140725ustar00rootroot00000000000000gencpp-0.6.2/cmake/gencpp-extras.cmake.em000066400000000000000000000065411344374743600202620ustar00rootroot00000000000000@[if DEVELSPACE]@ # bin and template dir variables in develspace set(GENCPP_BIN "@(CMAKE_CURRENT_SOURCE_DIR)/scripts/gen_cpp.py") set(GENCPP_TEMPLATE_DIR "@(CMAKE_CURRENT_SOURCE_DIR)/scripts") @[else]@ # bin and template dir variables in installspace set(GENCPP_BIN "${gencpp_DIR}/../../../@(CATKIN_PACKAGE_BIN_DESTINATION)/gen_cpp.py") set(GENCPP_TEMPLATE_DIR "${gencpp_DIR}/..") @[end if]@ # Generate .msg->.h for cpp # The generated .h files should be added ALL_GEN_OUTPUT_FILES_cpp macro(_generate_msg_cpp ARG_PKG ARG_MSG ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR) file(MAKE_DIRECTORY ${ARG_GEN_OUTPUT_DIR}) #Create input and output filenames get_filename_component(MSG_NAME ${ARG_MSG} NAME) get_filename_component(MSG_SHORT_NAME ${ARG_MSG} NAME_WE) set(MSG_GENERATED_NAME ${MSG_SHORT_NAME}.h) set(GEN_OUTPUT_FILE ${ARG_GEN_OUTPUT_DIR}/${MSG_GENERATED_NAME}) # check if a user-provided header file exists if(EXISTS "${PROJECT_SOURCE_DIR}/include/${ARG_PKG}/${MSG_SHORT_NAME}.h") message(STATUS "${ARG_PKG}: Found user-provided header '${PROJECT_SOURCE_DIR}/include/${ARG_PKG}/${MSG_SHORT_NAME}.h' for message '${ARG_PKG}/${MSG_SHORT_NAME}'. Skipping generation...") # Do nothing. The header will be installed by the user. else() # check if a user-provided plugin header file exists if(EXISTS "${PROJECT_SOURCE_DIR}/include/${ARG_PKG}/plugin/${MSG_SHORT_NAME}.h") message(STATUS "${ARG_PKG}: Found user-provided plugin header '${PROJECT_SOURCE_DIR}/include/${ARG_PKG}/plugin/${MSG_SHORT_NAME}.h' for message '${ARG_PKG}/${MSG_SHORT_NAME}'.") # Add a file dependency to enforce regeneration if the plugin header was added after initial cmake invocation. # Even with --force-cmake the generator would otherwise not run if the .msg file did not change. set(MSG_PLUGIN "${PROJECT_SOURCE_DIR}/include/${ARG_PKG}/plugin/${MSG_SHORT_NAME}.h") else() set(MSG_PLUGIN) endif() assert(CATKIN_ENV) add_custom_command(OUTPUT ${GEN_OUTPUT_FILE} DEPENDS ${GENCPP_BIN} ${ARG_MSG} ${ARG_MSG_DEPS} ${MSG_PLUGIN} "${GENCPP_TEMPLATE_DIR}/msg.h.template" ${ARGN} COMMAND ${CATKIN_ENV} ${PYTHON_EXECUTABLE} ${GENCPP_BIN} ${ARG_MSG} ${ARG_IFLAGS} -p ${ARG_PKG} -o ${ARG_GEN_OUTPUT_DIR} -e ${GENCPP_TEMPLATE_DIR} COMMENT "Generating C++ code from ${ARG_PKG}/${MSG_NAME}" WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" ) list(APPEND ALL_GEN_OUTPUT_FILES_cpp ${GEN_OUTPUT_FILE}) endif() gencpp_append_include_dirs() endmacro() #gencpp uses the same program to generate srv and msg files, so call the same macro macro(_generate_srv_cpp ARG_PKG ARG_SRV ARG_IFLAGS ARG_MSG_DEPS ARG_GEN_OUTPUT_DIR) _generate_msg_cpp(${ARG_PKG} ${ARG_SRV} "${ARG_IFLAGS}" "${ARG_MSG_DEPS}" ${ARG_GEN_OUTPUT_DIR} "${GENCPP_TEMPLATE_DIR}/srv.h.template") endmacro() macro(_generate_module_cpp) # the macros, they do nothing endmacro() set(gencpp_INSTALL_DIR include) macro(gencpp_append_include_dirs) if(NOT gencpp_APPENDED_INCLUDE_DIRS) # make sure we can find generated messages and that they overlay all other includes include_directories(BEFORE ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}) # pass the include directory to catkin_package() list(APPEND ${PROJECT_NAME}_INCLUDE_DIRS ${CATKIN_DEVEL_PREFIX}/${gencpp_INSTALL_DIR}) set(gencpp_APPENDED_INCLUDE_DIRS TRUE) endif() endmacro() gencpp-0.6.2/package.xml000066400000000000000000000014041344374743600151260ustar00rootroot00000000000000 gencpp 0.6.2 C++ ROS message and service generators. Dirk Thomas BSD https://github.com/ros/gencpp/issues https://github.com/ros/gencpp Josh Faust Troy Straszheim Morgen Kjaergaard catkin genmsg genmsg cpp gencpp-0.6.2/scripts/000077500000000000000000000000001344374743600145015ustar00rootroot00000000000000gencpp-0.6.2/scripts/CMakeLists.txt000066400000000000000000000003011344374743600172330ustar00rootroot00000000000000install( FILES msg.h.template srv.h.template DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}) catkin_install_python( PROGRAMS gen_cpp.py DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}) gencpp-0.6.2/scripts/gen_cpp.py000077500000000000000000000041701344374743600164730ustar00rootroot00000000000000#!/usr/bin/env python # Software License Agreement (BSD License) # # Copyright (c) 2009, Willow Garage, Inc. # All rights reserved. # # 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 name 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. # ## ROS message source code generation for C++ ## ## Converts ROS .msg files in a package into C++ source code implementations. import sys import os import genmsg.template_tools msg_template_map = { 'msg.h.template':'@NAME@.h' } srv_template_map = { 'srv.h.template':'@NAME@.h' } if __name__ == "__main__": genmsg.template_tools.generate_from_command_line_options(sys.argv, msg_template_map, srv_template_map) gencpp-0.6.2/scripts/msg.h.template000066400000000000000000000240101344374743600172470ustar00rootroot00000000000000@############################################### @# @# ROS message source code generation for C++ @# @# EmPy template for generating .h files @# @############################################### @# Start of Template @# @# Context: @# - file_name_in (String) Source file @# - spec (msggen.MsgSpec) Parsed specification of the .msg file @# - md5sum (String) MD5Sum of the .msg specification @############################################### // Generated by gencpp from file @(spec.package)/@(spec.short_name).msg // DO NOT EDIT! @{ import genmsg.msgs import gencpp import os cpp_namespace = '::%s::'%(spec.package) # TODO handle nested namespace cpp_class = '%s_'%spec.short_name cpp_full_name = '%s%s'%(cpp_namespace,cpp_class) cpp_full_name_with_alloc = '%s'%(cpp_full_name) cpp_msg_definition = gencpp.escape_message_definition(msg_definition) has_plugin = os.path.exists('include/%s/plugin/%s.h' % (spec.package, spec.short_name)) has_plugin_after = os.path.exists('include/%s/plugin/%s.after.h' % (spec.package, spec.short_name)) }@ #ifndef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H #define @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H @############################## @# Generic Includes @############################## #include #include #include #include #include #include #include @############################## @# Includes for dependencies @############################## @{ for field in spec.parsed_fields(): if (not field.is_builtin): if (field.is_header): print('#include ') else: (package, name) = genmsg.names.package_resource_name(field.base_type) package = package or spec.package # convert '' to package print('#include <%s/%s.h>'%(package, name)) }@ @############################## @# Plugin @############################## @[if has_plugin]@ #include <@(spec.package)/plugin/@(spec.short_name).h> @[end if]@ namespace @(spec.package) { template struct @(spec.short_name)_ { typedef @(spec.short_name)_ Type; @# constructors (with and without allocator) @[if has_plugin]@ #ifdef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_CONSTRUCTOR @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_CONSTRUCTOR #else @[end if]@ @[for (alloc_type,alloc_name) in [['',''],['const ContainerAllocator& ','_alloc']]]@ @(spec.short_name)_(@(alloc_type+alloc_name)) @# Write initializer list @('\n '.join(gencpp.generate_initializer_list(spec, alloc_name != '' )))@ { @# Fixed length arrays @[if alloc_name != '' and not [f for f in spec.parsed_fields() if f.is_array and f.array_len is not None and f.base_type == 'string']]@ (void)_alloc; @[end if]@ @('\n '.join(gencpp.generate_fixed_length_assigns(spec, alloc_name != '', '%s::'%(spec.package))))@ } @[end for] @[if has_plugin]@ #endif @[end if]@ @[for field in spec.parsed_fields()] @{cpp_type = gencpp.msg_type_to_cpp(field.type)}@ typedef @(cpp_type) _@(field.name)_type; _@(field.name)_type @(field.name); @[end for] @# Constants @{ constants_integer = [] constants_non_integer = [] for constant in spec.constants: if constant.type in ['byte', 'int8', 'int16', 'int32', 'int64', 'char', 'uint8', 'uint16', 'uint32', 'uint64']: constants_integer.append(constant) else: constants_non_integer.append(constant) }@ @# Integer constants @[if len(constants_integer) > 0]@ enum { @[for constant in constants_integer]@ @[if (constant.type in ['byte', 'int8', 'int16', 'int32', 'int64', 'char'])]@ @(constant.name) = @(int(constant.val)), @[elif (constant.type in ['uint8', 'uint16', 'uint32', 'uint64'])]@ @(constant.name) = @(int(constant.val))u, @[end if]@ @[end for]@ }; @[end if]@ @# Non-integer constants @[for constant in constants_non_integer]@ static const @(gencpp.msg_type_to_cpp(constant.type)) @(constant.name); @[end for]@ @# Shared pointer typedefs typedef boost::shared_ptr< @(cpp_full_name) > Ptr; typedef boost::shared_ptr< @(cpp_full_name) const> ConstPtr; @# Class body extensions provided by plugin @[if has_plugin]@ #ifdef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_CLASS_BODY @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_CLASS_BODY #endif @[end if]@ }; // struct @(cpp_class) @# Typedef of template instance using std::allocator typedef @(cpp_full_name) > @(spec.short_name); @# Shared pointer typedefs typedef boost::shared_ptr< @(cpp_namespace+spec.short_name) > @(spec.short_name)Ptr; typedef boost::shared_ptr< @(cpp_namespace+spec.short_name) const> @(spec.short_name)ConstPtr; // constants requiring out of line definition @[for c in spec.constants] @[if c.type not in ['byte', 'int8', 'int16', 'int32', 'int64', 'char', 'uint8', 'uint16', 'uint32', 'uint64']] template const @(gencpp.msg_type_to_cpp(c.type)) @(spec.short_name)_::@(c.name) = @[if c.type == 'string'] "@(gencpp.escape_string(c.val))" @[elif c.type == 'bool'] @(int(c.val)) @[else] @c.val @[end if] ; @[end if] @[end for] @# Printer template std::ostream& operator<<(std::ostream& s, const @(cpp_full_name_with_alloc) & v) { ros::message_operations::Printer< @(cpp_full_name_with_alloc) >::stream(s, "", v); return s; } @# End of namespace } // namespace @(spec.package) @# Message Traits namespace ros { namespace message_traits { @{ bool_traits = dict(IsMessage=True, IsFixedSize=gencpp.is_fixed_length(spec, msg_context, search_path), HasHeader=spec.has_header(), ) def booltotype(b): return "TrueType" if b else "FalseType" } // BOOLTRAITS @bool_traits // @search_path @# TODO // !!!!!!!!!!! @(dir(spec)) @#if spec.is_fixed_length(): @# traits = traits.append('IsFixedSize') @#template @#struct IsFixedSize<@(cpp_full_name_with_alloc) >:: @(dir(spec)) ? "TrueType" ! "FalseType") { }; @#template @#struct IsFixedSize<@(cpp_full_name_with_alloc) const >:: @(dir(spec)) ? "TrueType" ! "FalseType") { }; @# Binary traits @[for k, v in bool_traits.items()]@ template struct @(k)< @(cpp_full_name_with_alloc) > : @(booltotype(v)) { }; template struct @(k)< @(cpp_full_name_with_alloc) const> : @(booltotype(v)) { }; @[end for]@ @# String traits @[for trait_class,trait_value in [['MD5Sum', md5sum], ['DataType', spec.full_name], ['Definition', cpp_msg_definition]]]@ template struct @(trait_class)< @(cpp_full_name_with_alloc) > { static const char* value() { @[if trait_class == 'Definition']@ return @(trait_value); @[else]@ return "@(trait_value)"; @[end if]@ } static const char* value(const @(cpp_full_name_with_alloc)&) { return value(); } @{ if trait_class == 'MD5Sum': iter_count = int(len(trait_value) / 16) for i in range(0, iter_count): start = i*16 print(' static const uint64_t static_value%s = 0x%sULL;'%((i+1), trait_value[start:start+16])) }@ }; @[end for]@ @# End of traits } // namespace message_traits } // namespace ros @# Serialization namespace ros { namespace serialization { @[if has_plugin]@ #ifdef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_SERIALIZER @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_SERIALIZER #else @[end if]@ template struct Serializer< @(cpp_full_name_with_alloc) > { @[if spec.parsed_fields()]@ template inline static void allInOne(Stream& stream, T m) { @[for field in spec.parsed_fields()]@ stream.next(m.@(field.name)); @[end for]@ } @[else]@ template inline static void allInOne(Stream&, T) {} @[end if]@ ROS_DECLARE_ALLINONE_SERIALIZER }; // struct @(cpp_class) @[if has_plugin]@ #endif @[end if]@ } // namespace serialization } // namespace ros @# Message Operations namespace ros { namespace message_operations { @# Printer operation @[if has_plugin]@ #ifdef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_PRINTER @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_PLUGIN_PRINTER #else @[end if]@ template struct Printer< @(cpp_full_name_with_alloc) > { @[if spec.parsed_fields()]@ template static void stream(Stream& s, const std::string& indent, const @(cpp_full_name_with_alloc)& v) { @# todo, change this stuff below into proper EmPy syntax @{ for field in spec.parsed_fields(): cpp_type = gencpp.msg_type_to_cpp(field.base_type) if (field.is_array): print(' s << indent << "%s[]" << std::endl;'%(field.name)) print(' for (size_t i = 0; i < v.%s.size(); ++i)'%(field.name)) print(' {') print(' s << indent << " %s[" << i << "]: ";'%(field.name)) indent_increment = ' ' if (not field.is_builtin): print(' s << std::endl;') print(' s << indent;') indent_increment = ' '; print(' Printer<%s>::stream(s, indent + "%s", v.%s[i]);'%(cpp_type, indent_increment, field.name)) print(' }') else: print(' s << indent << "%s: ";'%(field.name)) indent_increment = ' ' if (not field.is_builtin or field.is_array): print(' s << std::endl;') print(' Printer<%s>::stream(s, indent + "%s", v.%s);'%(cpp_type, indent_increment, field.name)) }@ } @[else]@ template static void stream(Stream&, const std::string&, const @(cpp_full_name_with_alloc)&) {} @[end if]@ }; @[if has_plugin]@ #endif @[end if]@ } // namespace message_operations } // namespace ros @# Free function extensions provided by plugin @[if has_plugin_after]@ #include <@(spec.package)/plugin/@(spec.short_name).after.h> @[end if]@ #endif // @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H gencpp-0.6.2/scripts/srv.h.template000066400000000000000000000066331344374743600173060ustar00rootroot00000000000000@############################################### @# @# ROS message source code generation for C++ @# @# EmPy template for generating .h files @# @############################################### @# Start of Template @# @# Context: @# - file_name_in (String) Source .srv file @# - spec (msggen.SrvSpec) Parsed specification of the .srv file @# - md5sum (String) MD5Sum of the .srv specification @############################################### // Generated by gencpp from file @(spec.package)/@(spec.short_name).msg // DO NOT EDIT! @{ cpp_namespace = '::'+spec.package+'::' # TODO handle nested namespace cpp_class = spec.short_name cpp_full_name = cpp_namespace+cpp_class }@ #ifndef @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H #define @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H #include @############################################### @# Generate Request and Response Messages @############################################### #include <@(spec.package)/@(spec.short_name)Request.h> #include <@(spec.package)/@(spec.short_name)Response.h> @############################################### @# Service Struct @############################################### namespace @(spec.package) { struct @(spec.short_name) { typedef @(spec.request.short_name) Request; typedef @(spec.response.short_name) Response; Request request; Response response; typedef Request RequestType; typedef Response ResponseType; }; // struct @(spec.short_name) } // namespace @(spec.package) @############################################### @# Service-Traits @############################################### namespace ros { namespace service_traits { @[for trait_class,trait_value in [['MD5Sum', md5sum], ['DataType', spec.full_name]] ] template<> struct @trait_class< @cpp_full_name > { static const char* value() { return "@(trait_value)"; } static const char* value(const @(cpp_full_name)&) { return value(); } }; @[end for] // service_traits::MD5Sum< @(cpp_full_name)Request> should match // service_traits::MD5Sum< @cpp_full_name > template<> struct MD5Sum< @(cpp_full_name)Request> { static const char* value() { return MD5Sum< @cpp_full_name >::value(); } static const char* value(const @(cpp_full_name)Request&) { return value(); } }; // service_traits::DataType< @(cpp_full_name)Request> should match // service_traits::DataType< @cpp_full_name > template<> struct DataType< @(cpp_full_name)Request> { static const char* value() { return DataType< @cpp_full_name >::value(); } static const char* value(const @(cpp_full_name)Request&) { return value(); } }; // service_traits::MD5Sum< @(cpp_full_name)Response> should match // service_traits::MD5Sum< @cpp_full_name > template<> struct MD5Sum< @(cpp_full_name)Response> { static const char* value() { return MD5Sum< @cpp_full_name >::value(); } static const char* value(const @(cpp_full_name)Response&) { return value(); } }; // service_traits::DataType< @(cpp_full_name)Response> should match // service_traits::DataType< @cpp_full_name > template<> struct DataType< @(cpp_full_name)Response> { static const char* value() { return DataType< @cpp_full_name >::value(); } static const char* value(const @(cpp_full_name)Response&) { return value(); } }; } // namespace service_traits } // namespace ros #endif // @(spec.package.upper())_MESSAGE_@(spec.short_name.upper())_H gencpp-0.6.2/setup.py000077500000000000000000000003601344374743600145260ustar00rootroot00000000000000#!/usr/bin/env python from distutils.core import setup from catkin_pkg.python_setup import generate_distutils_setup d = generate_distutils_setup( packages=['gencpp'], package_dir={'': 'src'}, requires=['genmsg'] ) setup(**d) gencpp-0.6.2/src/000077500000000000000000000000001344374743600136015ustar00rootroot00000000000000gencpp-0.6.2/src/gencpp/000077500000000000000000000000001344374743600150555ustar00rootroot00000000000000gencpp-0.6.2/src/gencpp/__init__.py000066400000000000000000000227151344374743600171750ustar00rootroot00000000000000# Software License Agreement (BSD License) # # Copyright (c) 2011, Willow Garage, Inc. # All rights reserved. # # 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 name 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. import genmsg.msgs try: from cStringIO import StringIO #Python 2.x except ImportError: from io import StringIO #Python 3.x MSG_TYPE_TO_CPP = {'byte': 'int8_t', 'char': 'uint8_t', 'bool': 'uint8_t', 'uint8': 'uint8_t', 'int8': 'int8_t', 'uint16': 'uint16_t', 'int16': 'int16_t', 'uint32': 'uint32_t', 'int32': 'int32_t', 'uint64': 'uint64_t', 'int64': 'int64_t', 'float32': 'float', 'float64': 'double', 'string': 'std::basic_string, typename ContainerAllocator::template rebind::other > ', 'time': 'ros::Time', 'duration': 'ros::Duration'} #used def msg_type_to_cpp(type): """ Converts a message type (e.g. uint32, std_msgs/String, etc.) into the C++ declaration for that type (e.g. uint32_t, std_msgs::String_) @param type: The message type @type type: str @return: The C++ declaration @rtype: str """ (base_type, is_array, array_len) = genmsg.msgs.parse_type(type) cpp_type = None if (genmsg.msgs.is_builtin(base_type)): cpp_type = MSG_TYPE_TO_CPP[base_type] elif (len(base_type.split('/')) == 1): if (genmsg.msgs.is_header_type(base_type)): cpp_type = ' ::std_msgs::Header_ ' else: cpp_type = '%s_ '%(base_type) else: pkg = base_type.split('/')[0] msg = base_type.split('/')[1] cpp_type = ' ::%s::%s_ '%(pkg, msg) if (is_array): if (array_len is None): return 'std::vector<%s, typename ContainerAllocator::template rebind<%s>::other > '%(cpp_type, cpp_type) else: return 'boost::array<%s, %s> '%(cpp_type, array_len) else: return cpp_type def _escape_string(s): s = s.replace('\\', '\\\\') s = s.replace('"', '\\"') return s def escape_message_definition(definition): lines = definition.splitlines() if not lines: lines.append('') s = StringIO() for line in lines: line = _escape_string(line) # individual string literals cannot be too long; need to utilize string concatenation for long strings # https://docs.microsoft.com/en-us/cpp/c-language/maximum-string-length?view=vs-2017 s.write('"%s\\n"\n'%(line)) val = s.getvalue() s.close() return val #used2 def cpp_message_declarations(name_prefix, msg): """ Returns the different possible C++ declarations for a message given the message itself. @param name_prefix: The C++ prefix to be prepended to the name, e.g. "std_msgs::" @type name_prefix: str @param msg: The message type @type msg: str @return: A tuple of 3 different names. cpp_message_decelarations("std_msgs::", "String") returns the tuple ("std_msgs::String_", "std_msgs::String_", "std_msgs::String") @rtype: str """ pkg, basetype = genmsg.names.package_resource_name(msg) cpp_name = ' ::%s%s'%(name_prefix, msg) if (pkg): cpp_name = ' ::%s::%s'%(pkg, basetype) return ('%s_'%(cpp_name), '%s_ '%(cpp_name), '%s'%(cpp_name)) #todo def is_fixed_length(spec, msg_context, includepath): """ Returns whether or not the message is fixed-length @param spec: The message spec @type spec: genmsg.msgs.MsgSpec @param package: The package of the @type package: str """ types = [] for field in spec.parsed_fields(): if (field.is_array and field.array_len is None): return False if (field.base_type == 'string'): return False if (not field.is_builtin): types.append(field.base_type) types = set(types) for t in types: t = genmsg.msgs.resolve_type(t, spec.package) assert isinstance(includepath, dict) new_spec = genmsg.msg_loader.load_msg_by_type(msg_context, t, includepath) if (not is_fixed_length(new_spec, msg_context, includepath)): return False return True #used2 def default_value(type): """ Returns the value to initialize a message member with. 0 for integer types, 0.0 for floating point, false for bool, empty string for everything else @param type: The type @type type: str """ if type in ['byte', 'int8', 'int16', 'int32', 'int64', 'char', 'uint8', 'uint16', 'uint32', 'uint64']: return '0' elif type in ['float32', 'float64']: return '0.0' elif type == 'bool': return 'false' return "" #used2 def takes_allocator(type): """ Returns whether or not a type can take an allocator in its constructor. False for all builtin types except string. True for all others. @param type: The type @type: str """ return not type in ['byte', 'int8', 'int16', 'int32', 'int64', 'char', 'uint8', 'uint16', 'uint32', 'uint64', 'float32', 'float64', 'bool', 'time', 'duration'] def escape_string(str): str = str.replace('\\', '\\\\') str = str.replace('"', '\\"') return str #used def generate_fixed_length_assigns(spec, container_gets_allocator, cpp_name_prefix): """ Initialize any fixed-length arrays @param s: The stream to write to @type s: stream @param spec: The message spec @type spec: genmsg.msgs.MsgSpec @param container_gets_allocator: Whether or not a container type (whether it's another message, a vector, array or string) should have the allocator passed to its constructor. Assumes the allocator is named _alloc. @type container_gets_allocator: bool @param cpp_name_prefix: The C++ prefix to use when referring to the message, e.g. "std_msgs::" @type cpp_name_prefix: str """ # Assign all fixed-length arrays their default values for field in spec.parsed_fields(): if (not field.is_array or field.array_len is None): continue val = default_value(field.base_type) if (container_gets_allocator and takes_allocator(field.base_type)): # String is a special case, as it is the only builtin type that takes an allocator if (field.base_type == "string"): string_cpp = msg_type_to_cpp("string") yield ' %s.assign(%s(_alloc));\n'%(field.name, string_cpp) else: (cpp_msg_unqualified, cpp_msg_with_alloc, _) = cpp_message_declarations(cpp_name_prefix, field.base_type) yield ' %s.assign(%s(_alloc));\n'%(field.name, cpp_msg_with_alloc) elif (len(val) > 0): yield ' %s.assign(%s);\n'%(field.name, val) #used def generate_initializer_list(spec, container_gets_allocator): """ Writes the initializer list for a constructor @param s: The stream to write to @type s: stream @param spec: The message spec @type spec: genmsg.msgs.MsgSpec @param container_gets_allocator: Whether or not a container type (whether it's another message, a vector, array or string) should have the allocator passed to its constructor. Assumes the allocator is named _alloc. @type container_gets_allocator: bool """ op = ':' for field in spec.parsed_fields(): val = default_value(field.base_type) use_alloc = takes_allocator(field.base_type) if (field.is_array): if (field.array_len is None and container_gets_allocator): yield ' %s %s(_alloc)'%(op, field.name) else: yield ' %s %s()'%(op, field.name) else: if (container_gets_allocator and use_alloc): yield ' %s %s(_alloc)'%(op, field.name) else: yield ' %s %s(%s)'%(op, field.name, val) op = ','