microRTPS_client.cpp.em: fix double conversions

@###############################################
@#
@# EmPy template for generating microRTPS_client.cpp file
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - msgs (List) list of all msg files
@#  - multi_topics (List) list of all multi-topic names
@#  - ids (List) list of all RTPS msg ids
@###############################################
@{
import os

import genmsg.msgs
import gencpp
from px_generate_uorb_topic_helper import * # this is in Tools/
from px_generate_uorb_topic_files import MsgScope # this is in Tools/

topic_names = [s.short_name for s in spec]
send_topics = [(alias[idx] if alias[idx] else s.short_name) for idx, s in enumerate(spec) if scope[idx] == MsgScope.SEND]
send_base_types = [s.short_name for idx, s in enumerate(spec) if scope[idx] == MsgScope.SEND]
recv_topics = [(alias[idx] if alias[idx] else s.short_name) for idx, s in enumerate(spec) if scope[idx] == MsgScope.RECEIVE]
receive_base_types = [s.short_name for idx, s in enumerate(spec) if scope[idx] == MsgScope.RECEIVE]
}@
/****************************************************************************
 *
 * Copyright (c) 2017 Proyectos y Sistemas de Mantenimiento SL (eProsima).
 * Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 *
 ****************************************************************************/

#include "microRTPS_transport.h"
#include "microRTPS_client.h"

#include <inttypes.h>
#include <cstdio>
#include <ctime>
#include <pthread.h>

#include <ucdr/microcdr.h>
#include <px4_time.h>
#include <uORB/uORB.h>

#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
@[for topic in list(set(topic_names))]@
#include <uORB/topics/@(topic).h>
#include <uORB_microcdr/topics/@(topic).h>
@[end for]@

void* send(void *data);

@[if send_topics]@
void* send(void* /*unused*/)
{
    char data_buffer[BUFFER_SIZE] = {};
    uint64_t sent = 0, total_sent = 0;
    int loop = 0, read = 0;
    uint32_t length = 0;
    size_t header_length = 0;

    /* subscribe to topics */
@[for idx, topic in enumerate(send_topics)]@
    uORB::Subscription @(topic)_sub{ORB_ID(@(topic))};
@[end for]@

    // ucdrBuffer to serialize using the user defined buffer
    ucdrBuffer writer;
    header_length = transport_node->get_header_length();
    ucdr_init_buffer(&writer, reinterpret_cast<uint8_t*>(&data_buffer[header_length]), BUFFER_SIZE - header_length);

    struct timespec begin;
    px4_clock_gettime(CLOCK_REALTIME, &begin);

    while (!_should_exit_task)
    {
@[for idx, topic in enumerate(send_topics)]@
        @(send_base_types[idx])_s @(topic)_data;
        if (@(topic)_sub.update(&@(topic)_data)) {
                // copy raw data into local buffer. Payload is shifted by header length to make room for header
                serialize_@(send_base_types[idx])(&writer, &@(topic)_data, &data_buffer[header_length], &length);
                if (0 < (read = transport_node->write(static_cast<char>(@(rtps_message_id(ids, topic))), data_buffer, length)))
                {
                    total_sent += read;
                    ++sent;
                }
        }
@[end for]@
        px4_usleep(_options.sleep_ms * 1000);
        ++loop;
    }

    struct timespec end;
    px4_clock_gettime(CLOCK_REALTIME, &end);
    double elapsed_secs = end.tv_sec - begin.tv_sec + (end.tv_nsec - begin.tv_nsec) / 1e9;
    PX4_INFO("SENT: %" PRIu64 " messages in %d LOOPS, %" PRIu64 " bytes in %.03f seconds - %.02fKB/s",
                sent, loop, total_sent, elapsed_secs, total_sent / (1e3 * elapsed_secs));

    return nullptr;
}

static int launch_send_thread(pthread_t &sender_thread)
{
    pthread_attr_t sender_thread_attr;
    pthread_attr_init(&sender_thread_attr);
    pthread_attr_setstacksize(&sender_thread_attr, PX4_STACK_ADJUSTED(4000));
    struct sched_param param;
    (void)pthread_attr_getschedparam(&sender_thread_attr, &param);
    param.sched_priority = SCHED_PRIORITY_DEFAULT;
    (void)pthread_attr_setschedparam(&sender_thread_attr, &param);
    pthread_create(&sender_thread, &sender_thread_attr, send, nullptr);
    pthread_attr_destroy(&sender_thread_attr);

    return 0;
}
@[end if]@

void micrortps_start_topics(struct timespec &begin, uint64_t &total_read, uint64_t &received, int &loop)
{
@[if recv_topics]@

    char data_buffer[BUFFER_SIZE] = {};
    int read = 0;
    uint8_t topic_ID = 255;

    // Declare received topics
@[for idx, topic in enumerate(recv_topics)]@
    @(receive_base_types[idx])_s @(topic)_data;
    uORB::Publication<@(receive_base_types[idx])_s> @(topic)_pub{ORB_ID(@(topic))};
@[end for]@

    // ucdrBuffer to deserialize using the user defined buffer
    ucdrBuffer reader;
    ucdr_init_buffer(&reader, reinterpret_cast<uint8_t*>(data_buffer), BUFFER_SIZE);
@[end if]@

    px4_clock_gettime(CLOCK_REALTIME, &begin);
    _should_exit_task = false;
@[if send_topics]@

    // create a thread for sending data to the simulator
    pthread_t sender_thread;
    launch_send_thread(sender_thread);
@[end if]@

    while (!_should_exit_task)
    {
@[if recv_topics]@
        while (0 < (read = transport_node->read(&topic_ID, data_buffer, BUFFER_SIZE)))
        {
            total_read += read;
            switch (topic_ID)
            {
@[for idx, topic in enumerate(recv_topics)]@
                case @(rtps_message_id(ids, topic)):
                {
                    deserialize_@(receive_base_types[idx])(&reader, &@(topic)_data, data_buffer);
                    @(topic)_pub.publish(@(topic)_data);
                    ++received;
                }
                break;
@[end for]@
                default:
                    PX4_WARN("Unexpected topic ID\n");
                break;
            }
        }
@[end if]@

        // loop forever if informed loop number is negative
        if (_options.loops >= 0 && loop >= _options.loops) break;

        px4_usleep(_options.sleep_ms * 1000);
        ++loop;
    }
@[if send_topics]@
    _should_exit_task = true;
    pthread_join(sender_thread, nullptr);
@[end if]@
}

@###############################################
@#
@# EmPy template for generating microRTPS_client.cpp file
@#
@###############################################
@# Start of Template
@#
@# Context:
@#  - msgs (List) list of all msg files
@#  - multi_topics (List) list of all multi-topic names
@#  - ids (List) list of all RTPS msg ids
@###############################################
@{
import os

import genmsg.msgs
import gencpp
from px_generate_uorb_topic_helper import * # this is in Tools/
from px_generate_uorb_topic_files import MsgScope # this is in Tools/

topic_names = [s.short_name for s in spec]
send_topics = [(alias[idx] if alias[idx] else s.short_name) for idx, s in enumerate(spec) if scope[idx] == MsgScope.SEND]
send_base_types = [s.short_name for idx, s in enumerate(spec) if scope[idx] == MsgScope.SEND]
recv_topics = [(alias[idx] if alias[idx] else s.short_name) for idx, s in enumerate(spec) if scope[idx] == MsgScope.RECEIVE]
receive_base_types = [s.short_name for idx, s in enumerate(spec) if scope[idx] == MsgScope.RECEIVE]
}@
/****************************************************************************
 *
 * Copyright (c) 2017 Proyectos y Sistemas de Mantenimiento SL (eProsima).
 * Copyright (c) 2018 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 * list of conditions and the following disclaimer.
 *
 * 2. 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.
 *
 * 3. Neither the name of the copyright holder 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 HOLDER 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.
 *
 ****************************************************************************/

#include "microRTPS_transport.h"
#include "microRTPS_client.h"

#include <inttypes.h>
#include <cstdio>
#include <ctime>
#include <pthread.h>

#include <ucdr/microcdr.h>
#include <px4_time.h>
#include <uORB/uORB.h>

#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
@[for topic in list(set(topic_names))]@
#include <uORB/topics/@(topic).h>
#include <uORB_microcdr/topics/@(topic).h>
@[end for]@

void* send(void *data);

@[if send_topics]@
void* send(void* /*unused*/)
{
    char data_buffer[BUFFER_SIZE] = {};
    uint64_t sent = 0, total_sent = 0;
    int loop = 0, read = 0;
    uint32_t length = 0;
    size_t header_length = 0;

    /* subscribe to topics */
@[for idx, topic in enumerate(send_topics)]@
    uORB::Subscription @(topic)_sub{ORB_ID(@(topic))};
@[end for]@

    // ucdrBuffer to serialize using the user defined buffer
    ucdrBuffer writer;
    header_length = transport_node->get_header_length();
    ucdr_init_buffer(&writer, reinterpret_cast<uint8_t*>(&data_buffer[header_length]), BUFFER_SIZE - header_length);

    struct timespec begin;
    px4_clock_gettime(CLOCK_REALTIME, &begin);

    while (!_should_exit_task)
    {
@[for idx, topic in enumerate(send_topics)]@
        @(send_base_types[idx])_s @(topic)_data;
        if (@(topic)_sub.update(&@(topic)_data)) {
                // copy raw data into local buffer. Payload is shifted by header length to make room for header
                serialize_@(send_base_types[idx])(&writer, &@(topic)_data, &data_buffer[header_length], &length);
                if (0 < (read = transport_node->write(static_cast<char>(@(rtps_message_id(ids, topic))), data_buffer, length)))
                {
                    total_sent += read;
                    ++sent;
                }
        }
@[end for]@
        px4_usleep(_options.sleep_ms * 1e3);
        ++loop;
    }

    struct timespec end;
    px4_clock_gettime(CLOCK_REALTIME, &end);
    double elapsed_secs = static_cast<double>(end.tv_sec - begin.tv_sec + (end.tv_nsec - begin.tv_nsec) / 1e9);
    PX4_INFO("SENT: %" PRIu64 " messages in %d LOOPS, %" PRIu64 " bytes in %.03f seconds - %.02fKB/s",
                sent, loop, total_sent, elapsed_secs, static_cast<double>(total_sent / (1e3 * elapsed_secs)));

    return nullptr;
}

static int launch_send_thread(pthread_t &sender_thread)
{
    pthread_attr_t sender_thread_attr;
    pthread_attr_init(&sender_thread_attr);
    pthread_attr_setstacksize(&sender_thread_attr, PX4_STACK_ADJUSTED(4000));
    struct sched_param param;
    (void)pthread_attr_getschedparam(&sender_thread_attr, &param);
    param.sched_priority = SCHED_PRIORITY_DEFAULT;
    (void)pthread_attr_setschedparam(&sender_thread_attr, &param);
    pthread_create(&sender_thread, &sender_thread_attr, send, nullptr);
    pthread_attr_destroy(&sender_thread_attr);

    return 0;
}
@[end if]@

void micrortps_start_topics(struct timespec &begin, uint64_t &total_read, uint64_t &received, int &loop)
{
@[if recv_topics]@

    char data_buffer[BUFFER_SIZE] = {};
    int read = 0;
    uint8_t topic_ID = 255;

    // Declare received topics
@[for idx, topic in enumerate(recv_topics)]@
    @(receive_base_types[idx])_s @(topic)_data;
    uORB::Publication<@(receive_base_types[idx])_s> @(topic)_pub{ORB_ID(@(topic))};
@[end for]@

    // ucdrBuffer to deserialize using the user defined buffer
    ucdrBuffer reader;
    ucdr_init_buffer(&reader, reinterpret_cast<uint8_t*>(data_buffer), BUFFER_SIZE);
@[end if]@

    px4_clock_gettime(CLOCK_REALTIME, &begin);
    _should_exit_task = false;
@[if send_topics]@

    // create a thread for sending data to the simulator
    pthread_t sender_thread;
    launch_send_thread(sender_thread);
@[end if]@

    while (!_should_exit_task)
    {
@[if recv_topics]@
        while (0 < (read = transport_node->read(&topic_ID, data_buffer, BUFFER_SIZE)))
        {
            total_read += read;
            switch (topic_ID)
            {
@[for idx, topic in enumerate(recv_topics)]@
                case @(rtps_message_id(ids, topic)):
                {
                    deserialize_@(receive_base_types[idx])(&reader, &@(topic)_data, data_buffer);
                    @(topic)_pub.publish(@(topic)_data);
                    ++received;
                }
                break;
@[end for]@
                default:
                    PX4_WARN("Unexpected topic ID\n");
                break;
            }
        }
@[end if]@

        // loop forever if informed loop number is negative
        if (_options.loops >= 0 && loop >= _options.loops) break;

        px4_usleep(_options.sleep_ms * 1e3);
        ++loop;
    }
@[if send_topics]@
    _should_exit_task = true;
    pthread_join(sender_thread, nullptr);
@[end if]@
}


Updated rosdep_init.Dockerfile.em snippet to always run rosdep init

RUN rosdep init
@[for url in custom_rosdep_urls]@
RUN (cd /etc/ros/rosdep/sources.list.d/ && wget --progress=dot -O $(basename @url ) @url )
@[end for]@

RUN mkdir -p /etc/ros/rosdep/sources.list.d

@[for url in custom_rosdep_urls]@
RUN (cd /etc/ros/rosdep/sources.list.d/ && wget --progress=dot @url )
@[end for]@
@[if not custom_rosdep_urls]@
RUN rosdep init
@[end if]@


Name service needs to use strict equality or it generates one object for a given value and multiple other objects may point to it, even though that is not how the original object graph looked.

if (typeof(std.persist) === 'undefined')
    throw new Error('Error.  Do not import this file directly.  Only import it from persistService.em');

/*Create a separate namespace for name service;*/
std.persist.NameService = function()
{
    /**
     Keys are object references; values are unique integers
     ("names").
     */
    // var objectsToNames  =  {  };

    /**
     Keys are integers ("names") each unique to a single object.
     Values are object references
     */
    var namesToObjects  = {  };

    /**
     Keys are object references.  Values are single objects that
     contain the references and names for every object that is
     reachable from that object.  Not all objects that are stored in
     objectsToNames and namesToObjects will have entries in
     hierarchyMap.  Just those that were the roots for a request to
     persist.
     */
    var hierarchyMap    = {  };

     var whichNameOn = 0;

     /**
      Does Not Exist.
      Returned when maps calling lookup on do not have a record for
      the index searching for.
      */
     this.DNE = -99;

     /**
      Prints all objects that we're responsible for and their names
      */
     this.__debugPrint = function ()
     {
         system.print('\nPrinting in name service\'s debug print\n');
         for (var s in namesToObjects)
         {
             system.print('\n');
             system.print(s);
             system.print(namesToObjects[s]);
         }
         system.print('\nDone\n');
     };

     /**
      @param name to lookup.  (name will be an integer starting at
      zero).
      @returns if object exists, returns the object.  If it does not,
      returns DNE
      */
     this.lookupObject = function(name)
     {
         if (name in namesToObjects)
             return namesToObjects[name];

         return this.DNE;
     };

     /**
      @param obj to lookup name of.  (name will be an integer starting
      at zero).
      @returns if object exists, returns the object.  If it does not,
      returns DNE
      */
     this.lookupName = function (obj)
     {
         for (var s in namesToObjects)
         {
             // NOTE: This *must* be strict equality.
             if (obj === namesToObjects[s])
                 return s;
         }

         return this.DNE;
     };

      /**
       @param objToInsert into name service.
       @return Returns the name for the object.
       */
      this.insertObject = function (objToInsert)
      {
          var ind = this.lookupName(objToInsert);
          if (ind != this.DNE)
          {
              system.print('\nAlready had inserted object\n');
              return ind;
          }

          namesToObjects[whichNameOn] = objToInsert;
          return whichNameOn++;
      };

    /**
     @param objToInsert into name service
     @param nameToUse How to index into the new name in the service.

     Note.  If nameToUse is greater than or equal to which name to
     insert into next, we increase the value for which name to insert
     into next to avoid possible collisions.
     */
     this.insertObjectWithName = function (objToInsert,nameToUse)
     {
         namesToObjects[nameToUse]    = objToInsert;

         if (nameToUse >= whichNameOn)
             whichNameOn = nameToUse + 1;
     };

 };

if (typeof(std.persist) === 'undefined')
    throw new Error('Error.  Do not import this file directly.  Only import it from persistService.em');

/*Create a separate namespace for name service;*/
std.persist.NameService = function()
{
    /**
     Keys are object references; values are unique integers
     ("names").
     */
    // var objectsToNames  =  {  };

    /**
     Keys are integers ("names") each unique to a single object.
     Values are object references
     */
    var namesToObjects  = {  };

    /**
     Keys are object references.  Values are single objects that
     contain the references and names for every object that is
     reachable from that object.  Not all objects that are stored in
     objectsToNames and namesToObjects will have entries in
     hierarchyMap.  Just those that were the roots for a request to
     persist.
     */
    var hierarchyMap    = {  };

     var whichNameOn = 0;

     /**
      Does Not Exist.
      Returned when maps calling lookup on do not have a record for
      the index searching for.
      */
     this.DNE = -99;

     /**
      Prints all objects that we're responsible for and their names
      */
     this.__debugPrint = function ()
     {
         system.print('\nPrinting in name service\'s debug print\n');
         for (var s in namesToObjects)
         {
             system.print('\n');
             system.print(s);
             system.print(namesToObjects[s]);
         }
         system.print('\nDone\n');
     };

     /**
      @param name to lookup.  (name will be an integer starting at
      zero).
      @returns if object exists, returns the object.  If it does not,
      returns DNE
      */
     this.lookupObject = function(name)
     {
         if (name in namesToObjects)
             return namesToObjects[name];

         return this.DNE;
     };

     /**
      @param obj to lookup name of.  (name will be an integer starting
      at zero).
      @returns if object exists, returns the object.  If it does not,
      returns DNE
      */
     this.lookupName = function (obj)
     {
         for (var s in namesToObjects)
         {
             if (obj == namesToObjects[s])
                 return s;
         }

         return this.DNE;
     };

      /**
       @param objToInsert into name service.
       @return Returns the name for the object.
       */
      this.insertObject = function (objToInsert)
      {
          var ind = this.lookupName(objToInsert);
          if (ind != this.DNE)
          {
              system.print('\nAlready had inserted object\n');
              return ind;
          }

          namesToObjects[whichNameOn] = objToInsert;
          return whichNameOn++;
      };

    /**
     @param objToInsert into name service
     @param nameToUse How to index into the new name in the service.

     Note.  If nameToUse is greater than or equal to which name to
     insert into next, we increase the value for which name to insert
     into next to avoid possible collisions.
     */
     this.insertObjectWithName = function (objToInsert,nameToUse)
     {
         namesToObjects[nameToUse]    = objToInsert;

         if (nameToUse >= whichNameOn)
             whichNameOn = nameToUse + 1;
     };

 };


fix number of tabs in rules file template

#!/usr/bin/make -f
# -*- makefile -*-
# Sample debian/rules that uses debhelper.
# This file was originally written by Joey Hess and Craig Small.
# As a special exception, when this file is copied by dh-make into a
# dh-make output file, you may use that output file without restriction.
# This special exception was added by Craig Small in version 0.37 of dh-make.

# Uncomment this to turn on verbose mode.
export DH_VERBOSE=1
export DH_OPTIONS=-v --buildsystem=cmake
# TODO: remove the LDFLAGS override.  It's here to avoid esoteric problems
# of this sort:
#  https://code.ros.org/trac/ros/ticket/2977
#  https://code.ros.org/trac/ros/ticket/3842
export LDFLAGS=
export PKG_CONFIG_PATH=@(InstallationPrefix)/lib/pkgconfig

%:
	dh  $@@

override_dh_auto_configure:
	# In case we're installing to a non-standard location, look for a setup.sh
	# in the install tree that was dropped by catkin, and source it.  It will
	# set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
	if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
	dh_auto_configure -- \
		-DCATKIN_BUILD_BINARY_PACKAGE="1" \
		-DCMAKE_INSTALL_PREFIX="@(InstallationPrefix)" \
		-DCMAKE_PREFIX_PATH="@(InstallationPrefix)"

override_dh_auto_build:
	# In case we're installing to a non-standard location, look for a setup.sh
	# in the install tree that was dropped by catkin, and source it.  It will
	# set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
	if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
	dh_auto_build

override_dh_auto_test:
	# In case we're installing to a non-standard location, look for a setup.sh
	# in the install tree that was dropped by catkin, and source it.  It will
	# set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
	echo -- Running tests. Even if one of them fails the build is not canceled.
	if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
	dh_auto_test || true

override_dh_shlibdeps:
	# In case we're installing to a non-standard location, look for a setup.sh
	# in the install tree that was dropped by catkin, and source it.  It will
	# set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
	if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
	dh_shlibdeps -l$(CURDIR)/debian/@(Package)/@(InstallationPrefix)/lib/

override_dh_auto_install:
	# In case we're installing to a non-standard location, look for a setup.sh
	# in the install tree that was dropped by catkin, and source it.  It will
	# set things like CMAKE_PREFIX_PATH, PKG_CONFIG_PATH, and PYTHONPATH.
	if [ -f "@(InstallationPrefix)/setup.sh" ]; then . "@(InstallationPrefix)/setup.sh"; fi && \
	dh_auto_install


order mattres

order mattres

#= require ./store
#= require_tree ./mixins
#= require_tree ./initializers
#= require_tree ./models
#= require_self
#= require_tree ./controllers
#= require_tree ./singletons
#= require_tree ./views
#= require_tree ./components
#= require_tree ./templates
#= require_tree ./routes
#= require ./router

#= require_tree ./mixins
#= require_tree ./initializers
#= require ./store
#= require_tree ./models
#= require_self
#= require_tree ./controllers
#= require_tree ./singletons
#= require_tree ./views
#= require_tree ./components
#= require_tree ./templates
#= require_tree ./routes
#= require ./router


fix bounded arrays

fix bounded arrays

// generated from rosidl_typesupport_connext_c/resource/msg__type_support_c.cpp.em
// generated code does not contain a copyright notice

@##########################################################################
@# EmPy template for generating <msg>__type_support.c files for Connext
@#
@# Context:
@#  - spec (rosidl_parser.MessageSpecification)
@#    Parsed specification of the .msg file
@#  - pkg (string)
@#    name of the containing package; equivalent to spec.base_type.pkg_name
@#  - msg (string)
@#    name of the message; equivalent to spec.msg_name
@#  - type (string)
@#    full type of the message; equivalent to spec.base_type.type
@#  - subfolder (string)
@#    The subfolder / subnamespace of the message
@#    Either 'msg' or 'srv'
@#  - get_header_filename_from_msg_name (function)
@##########################################################################
@
#include <cassert>
#include <limits>

// Provides the definition of the rosidl_message_type_support_t struct as well
// as the Connext specific macros, e.g. ROSIDL_GET_TYPE_SUPPORT_FUNCTION.
#include "rosidl_generator_c/message_type_support.h"
// Ensure the correct version of the above header was included.
static_assert(USING_ROSIDL_TYPESUPPORT_CONNEXT_C, "expected Connext C message type support");
// Provides the rosidl_typesupport_connext_c__identifier symbol declaration.
#include "rosidl_typesupport_connext_c/identifier.h"
// Provides the definition of the message_type_support_callbacks_t struct.
#include "rosidl_typesupport_connext_cpp/message_type_support.h"

@{header_file_name = get_header_filename_from_msg_name(type)}@
#include "@(pkg)/@(subfolder)/@(header_file_name)__struct.h"
#include "@(pkg)/@(subfolder)/@(header_file_name)__functions.h"

#ifndef _WIN32
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wunused-variable"
# ifdef __clang__
#  pragma clang diagnostic ignored "-Wdeprecated-register"
#  pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
# endif
#endif
#include "@(spec.base_type.pkg_name)/@(subfolder)/dds_connext/@(spec.base_type.type)_Support.h"
#ifndef _WIN32
# pragma GCC diagnostic pop
#endif

// includes and forward declarations of message dependencies and their conversion functions

@# // Include the message header for each non-primitive field.
#if defined(__cplusplus)
extern "C"
{
#endif

// Forward declare the get type support function for this type.
ROSIDL_GENERATOR_C_EXPORT_@(pkg)
const rosidl_message_type_support_t *
  ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(pkg), @(subfolder), @(msg))(void);

// include message dependencies
@{
includes = {}
for field in spec.fields:
    keys = set([])
    if field.type.is_primitive_type():
        if field.type.is_array:
            keys.add('rosidl_generator_c/primitives_array.h')
            keys.add('rosidl_generator_c/primitives_array_functions.h')
        if field.type.type == 'string':
            keys.add('rosidl_generator_c/string.h')
            keys.add('rosidl_generator_c/string_functions.h')
    else:
        header_file_name = get_header_filename_from_msg_name(field.type.type)
        keys.add('%s/msg/%s__functions.h' % (field.type.pkg_name, header_file_name))
    for key in keys:
        if key not in includes:
            includes[key] = set([])
        includes[key].add(field.name)
}@
@[for key in sorted(includes.keys())]@
#include "@(key)"  // @(', '.join(includes[key]))
@[end for]@

// forward declare type support functions
@{
forward_declares = {}
for field in spec.fields:
    if not field.type.is_primitive_type():
        key = (field.type.pkg_name, field.type.type)
        if key not in includes:
            forward_declares[key] = set([])
        forward_declares[key].add(field.name)
}@
@[for key in sorted(forward_declares.keys())]@
@[  if key[0] != pkg]@
ROSIDL_GENERATOR_C_IMPORT_@(pkg)
@[  end if]@
const rosidl_message_type_support_t *
  ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(key[0]), msg, @(key[1]))();  // @(', '.join(forward_declares[key]))
@[end for]@

@# // Make callback functions specific to this message type.

@{
__dds_msg_type_prefix = "{0}::{1}::dds_::{2}_".format(
  spec.base_type.pkg_name, subfolder, spec.base_type.type)
}@
using __dds_msg_type = @(__dds_msg_type_prefix);
using __ros_msg_type = @(pkg)__@(subfolder)__@(type);

static bool
register_type(void * untyped_participant, const char * type_name)
{
  if (!untyped_participant) {
    fprintf(stderr, "untyped participant handle is null\n");
    return false;
  }
  if (!type_name) {
    fprintf(stderr, "type name handle is null\n");
    return false;
  }
  DDSDomainParticipant * participant = static_cast<DDSDomainParticipant *>(untyped_participant);

  DDS_ReturnCode_t status =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type(participant, type_name);
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_BAD_PARAMETER:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "bad domain participant or type name parameter\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "already registered with a different TypeSupport class\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: unknown return code\n");
  }
  return false;
}

static bool
convert_ros_to_dds(const void * untyped_ros_message, void * untyped_dds_message)
{
  if (!untyped_ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }
  if (!untyped_dds_message) {
    fprintf(stderr, "dds message handle is null\n");
    return false;
  }
  const __ros_msg_type * ros_message = static_cast<const __ros_msg_type *>(untyped_ros_message);
  __dds_msg_type * dds_message = static_cast<__dds_msg_type *>(untyped_dds_message);
@[if not spec.fields]@
  // No fields is a no-op.
  (void)dds_message;
  (void)ros_message;
@[end if]@
@[for field in spec.fields]@
  // Field name: @(field.name)
  {
@[  if not field.type.is_primitive_type()]@
    const message_type_support_callbacks_t * @(field.type.pkg_name)__msg__@(field.type.type)__callbacks =
      static_cast<const message_type_support_callbacks_t *>(ROSIDL_GET_TYPE_SUPPORT_FUNCTION(
        @(field.type.pkg_name), msg, @(field.type.type)
      )()->data);
@[  end if]@
@[  if field.type.is_array]@
@[    if field.type.array_size]@
    size_t size = @(field.type.array_size);
@[    else]@
    size_t size = ros_message->@(field.name).size;
    if (size > (std::numeric_limits<DDS_Long>::max)()) {
      fprintf(stderr, "array size exceeds maximum DDS sequence size\n");
      return false;
    }
    DDS_Long length = static_cast<DDS_Long>(size);
    dds_message->@(field.name)_.ensure_length(length, length);
@[    end if]@
    for (DDS_Long i = 0; i < static_cast<DDS_Long>(size); ++i) {
@[    if field.type.array_size and not field.type.is_upper_bound]@
      auto & ros_i = ros_message->@(field.name)[i];
@[    else]@
      auto & ros_i = ros_message->@(field.name).data[i];
@[    end if]@
@[    if field.type.type == 'string']@
      const rosidl_generator_c__String * str = &ros_i;
      if (str->capacity == 0 || str->capacity <= str->size) {
        fprintf(stderr, "string capacity not greater than size\n");
        return false;
      }
      if (str->data[str->size] != '\0') {
        fprintf(stderr, "string not null-terminated\n");
        return false;
      }
      dds_message->@(field.name)_[i] = str->data;
@[    elif field.type.type == 'bool']@
      dds_message->@(field.name)_[i] = 1 ? ros_i : 0;
@[    elif field.type.is_primitive_type()]@
      dds_message->@(field.name)_[i] = ros_i;
@[    else]@
      if (!@(field.type.pkg_name)__msg__@(field.type.type)__callbacks->convert_ros_to_dds(
          &ros_i, &dds_message->@(field.name)_[i]))
      {
        return false;
      }
@[    end if]@
    }
@[  elif field.type.type == 'string']@
    const rosidl_generator_c__String * str = &ros_message->@(field.name);
    if (str->capacity == 0 || str->capacity <= str->size) {
      fprintf(stderr, "string capacity not greater than size\n");
      return false;
    }
    if (str->data[str->size] != '\0') {
      fprintf(stderr, "string not null-terminated\n");
      return false;
    }
    dds_message->@(field.name)_ = str->data;
@[  elif field.type.is_primitive_type()]@
    dds_message->@(field.name)_ = ros_message->@(field.name);
@[  else]@
    if (!@(field.type.pkg_name)__msg__@(field.type.type)__callbacks->convert_ros_to_dds(
        &ros_message->@(field.name), &dds_message->@(field.name)_))
    {
      return false;
    }
@[  end if]@
  }

@[end for]@
  return true;
}

static bool
publish(void * dds_data_writer, const void * untyped_ros_message)
{
  if (!dds_data_writer) {
    fprintf(stderr, "data writer handle is null\n");
    return false;
  }
  const __ros_msg_type * ros_message = static_cast<const __ros_msg_type *>(untyped_ros_message);
  if (!ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }

  DDSDataWriter * topic_writer = static_cast<DDSDataWriter *>(dds_data_writer);

  __dds_msg_type dds_message;
  if (!convert_ros_to_dds(ros_message, &dds_message)) {
    return false;
  }
  @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter * data_writer =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter::narrow(topic_writer);
  DDS_ReturnCode_t status = data_writer->write(dds_message, DDS_HANDLE_NIL);
@[for field in spec.fields]@
@[  if field.type.type == 'string']@
@[    if field.type.is_array]@
  {
@[      if field.type.array_size and not field.type.is_upper_bound]@
    DDS_Long size = static_cast<DDS_Long>(@(field.type.array_size));
    for (DDS_Long i = 0; i < size; ++i) {
      DDS_String_free(dds_message.@(field.name)_[i]);
      dds_message.@(field.name)_[i] =
        DDS_String_dup(ros_message->@(field.name)[i].data);
    }
@[      else]@
    DDS_Long size = dds_message.@(field.name)_.length();
    for (DDS_Long i = 0; i < size; ++i) {
      DDS_String_free(dds_message.@(field.name)_[i]);
      dds_message.@(field.name)_[i] =
        DDS_String_dup(ros_message->@(field.name).data[i].data);
    }
@[      end if]@
  }
@[    else]@
  DDS_String_free(static_cast<char *>(dds_message.@(field.name)_));
  dds_message.@(field.name)_ =
    DDS_String_dup(ros_message->@(field.name).data);
@[    end if]@
@[  end if]@
@[end for]@
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_BAD_PARAMETER:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "bad handle or instance_data parameter\n");
      return false;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "this @(__dds_msg_type_prefix)DataWriter has already been deleted\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "this @(__dds_msg_type_prefix)DataWriter is not enabled\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "the handle has not been registered with this @(__dds_msg_type_prefix)DataWriter\n");
      return false;
    case DDS_RETCODE_TIMEOUT:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "writing resulted in blocking and then exceeded the timeout set by the "
        "max_blocking_time of the ReliabilityQosPolicy\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "unknown return code\n");
  }
  return false;
}

static bool
convert_dds_to_ros(const void * untyped_dds_message, void * untyped_ros_message)
{
  if (!untyped_ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }
  if (!untyped_dds_message) {
    fprintf(stderr, "dds message handle is null\n");
    return false;
  }
  const __dds_msg_type * dds_message = static_cast<const __dds_msg_type *>(untyped_dds_message);
  __ros_msg_type * ros_message = static_cast<__ros_msg_type *>(untyped_ros_message);
@[if not spec.fields]@
  // No fields is a no-op.
  (void)dds_message;
  (void)ros_message;
@[end if]@
@[for field in spec.fields]@
  // Field name: @(field.name)
  {
@[  if field.type.is_array]@
@[    if field.type.array_size]@
    DDS_Long size = @(field.type.array_size);
@[    else]@
@{
if field.type.type == 'string':
    array_init = 'rosidl_generator_c__String__Array__init'
    array_fini = 'rosidl_generator_c__String__Array__fini'
elif field.type.is_primitive_type():
    array_init = 'rosidl_generator_c__{field.type.type}__Array__init'.format(**locals())
    array_fini = 'rosidl_generator_c__{field.type.type}__Array__fini'.format(**locals())
else:
    array_init = '{field.type.pkg_name}__msg__{field.type.type}__Array__init'.format(**locals())
    array_fini = '{field.type.pkg_name}__msg__{field.type.type}__Array__fini'.format(**locals())
}@
    DDS_Long size = dds_message->@(field.name)_.length();
    if (ros_message->@(field.name).data) {
      @(array_fini)(&ros_message->@(field.name));
    }
    if (!@(array_init)(&ros_message->@(field.name), size)) {
      return "failed to create array for field '@(field.name)'";
    }
@[    end if]@
    for (DDS_Long i = 0; i < size; i++) {
@[    if field.type.array_size and not field.type.is_upper_bound]@
      auto & ros_i = ros_message->@(field.name)[i];
@[    else]@
      auto & ros_i = ros_message->@(field.name).data[i];
@[    end if]@
@[    if field.type.type == 'bool']@
      ros_i = (dds_message->@(field.name)_[i] != 0);
@[    elif field.type.type == 'string']@
      if (!ros_i.data) {
        rosidl_generator_c__String__init(&ros_i);
      }
      bool succeeded = rosidl_generator_c__String__assign(
        &ros_i,
        dds_message->@(field.name)_[i]);
      if (!succeeded) {
        fprintf(stderr, "failed to assign string into field '@(field.name)'\n");
        return false;
      }
@[    elif field.type.is_primitive_type()]@
      ros_i = dds_message->@(field.name)_[i];
@[    else]@
      const rosidl_message_type_support_t * ts =
        ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(field.type.pkg_name), msg, @(field.type.type))();
      const message_type_support_callbacks_t * callbacks =
        static_cast<const message_type_support_callbacks_t *>(ts->data);
      callbacks->convert_dds_to_ros(&dds_message->@(field.name)_[i], &ros_i);
@[    end if]@
    }
@[  elif field.type.type == 'string']@
    if (!ros_message->@(field.name).data) {
      rosidl_generator_c__String__init(&ros_message->@(field.name));
    }
    bool succeeded = rosidl_generator_c__String__assign(
      &ros_message->@(field.name),
      dds_message->@(field.name)_);
    if (!succeeded) {
      fprintf(stderr, "failed to assign string into field '@(field.name)'\n");
      return false;
    }
@[  elif field.type.is_primitive_type()]@
    ros_message->@(field.name) = dds_message->@(field.name)_@(' == static_cast<DDS_Boolean>(true)' if field.type.type == 'bool' else '');
@[  else]@
    const rosidl_message_type_support_t * ts =
      ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(field.type.pkg_name), msg, @(field.type.type))();
    const message_type_support_callbacks_t * callbacks =
      static_cast<const message_type_support_callbacks_t *>(ts->data);
    callbacks->convert_dds_to_ros(&dds_message->@(field.name)_, &ros_message->@(field.name));
@[  end if]@
  }

@[end for]@
  return true;
}

static bool
take(
  void * dds_data_reader,
  bool ignore_local_publications,
  void * untyped_ros_message,
  bool * taken,
  void * sending_publication_handle)
{
  if (untyped_ros_message == 0) {
    fprintf(stderr, "invalid ros message pointer\n");
    return false;
  }

  DDSDataReader * topic_reader = static_cast<DDSDataReader *>(dds_data_reader);

  @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader * data_reader =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader::narrow(topic_reader);

  @(__dds_msg_type_prefix)Seq dds_messages;
  DDS_SampleInfoSeq sample_infos;
  DDS_ReturnCode_t status = data_reader->take(
    dds_messages,
    sample_infos,
    1,
    DDS_ANY_SAMPLE_STATE,
    DDS_ANY_VIEW_STATE,
    DDS_ANY_INSTANCE_STATE);

  bool ignore_sample = false;

  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "an internal error has occurred\n");
      goto finally;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "this @(__dds_msg_type_prefix)DataReader has already been deleted\n");
      goto finally;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "out of resources\n");
      goto finally;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "this @(__dds_msg_type_prefix)DataReader is not enabled\n");
      goto finally;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "a precondition is not met, one of: "
        "max_samples > maximum and max_samples != LENGTH_UNLIMITED, or "
        "the two sequences do not have matching parameters (length, maximum, release), or "
        "maximum > 0 and release is false.\n");
      goto finally;
    case DDS_RETCODE_NO_DATA:
      *taken = false;
      goto finally;
    case DDS_RETCODE_OK:
      break;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "unknown return code\n");
      goto finally;
  }

  {
    DDS_SampleInfo & sample_info = sample_infos[0];
    if (!sample_info.valid_data) {
      // skip sample without data
      ignore_sample = true;
    } else if (ignore_local_publications) {
      // compare the lower 12 octets of the guids from the sender and this receiver
      // if they are equal the sample has been sent from this process and should be ignored
      DDS_GUID_t sender_guid = sample_info.original_publication_virtual_guid;
      DDS_InstanceHandle_t receiver_instance_handle = topic_reader->get_instance_handle();
      ignore_sample = true;
      for (size_t i = 0; i < 12; ++i) {
        DDS_Octet * sender_element = &(sender_guid.value[i]);
        DDS_Octet * receiver_element = &(reinterpret_cast<DDS_Octet *>(&receiver_instance_handle)[i]);
        if (*sender_element != *receiver_element) {
          ignore_sample = false;
          break;
        }
      }
      // This is nullptr when being used with plain rmw_take, so check first.
      if (sending_publication_handle) {
        *static_cast<DDS_InstanceHandle_t *>(sending_publication_handle) =
          sample_info.publication_handle;
      }
    }
  }

  if (!ignore_sample) {
    if (!convert_dds_to_ros(&dds_messages[0], untyped_ros_message)) {
      goto finally;
    }
    *taken = true;
  } else {
    *taken = false;
  }

finally:
  // Ensure the loan is returned.
  status = data_reader->return_loan(dds_messages, sample_infos);
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "this @(__dds_msg_type_prefix)DataReader has already been deleted\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "this @(__dds_msg_type_prefix)DataReader is not enabled\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "a precondition is not met, one of: "
        "the data_values and info_seq do not belong to a single related pair, or "
        "the data_values and info_seq were not obtained from this "
        "@(__dds_msg_type_prefix)DataReader\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "unknown return code\n");
  }

  return false;
}
@
@# // Collect the callback functions and provide a function to get the type support struct.

static message_type_support_callbacks_t __callbacks = {
  "@(pkg)",  // package_name
  "@(msg)",  // message_name
  register_type,  // register_type
  publish,  // publish
  take,  // take
  convert_ros_to_dds,  // convert_ros_to_dds
  convert_dds_to_ros,  // convert_dds_to_ros
};

static rosidl_message_type_support_t __type_support = {
  // Cannot be set since it is not a constexpr, it is set in the get type support function below.
  0,
  &__callbacks
};

ROSIDL_GENERATOR_C_EXPORT_@(spec.base_type.pkg_name)
const rosidl_message_type_support_t *
ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(pkg), @(subfolder), @(msg))() {
  if (!__type_support.typesupport_identifier) {
    __type_support.typesupport_identifier = rosidl_typesupport_connext_c__identifier;
  }
  return &__type_support;
}

#if defined(__cplusplus)
}
#endif

// generated from rosidl_typesupport_connext_c/resource/msg__type_support_c.cpp.em
// generated code does not contain a copyright notice

@##########################################################################
@# EmPy template for generating <msg>__type_support.c files for Connext
@#
@# Context:
@#  - spec (rosidl_parser.MessageSpecification)
@#    Parsed specification of the .msg file
@#  - pkg (string)
@#    name of the containing package; equivalent to spec.base_type.pkg_name
@#  - msg (string)
@#    name of the message; equivalent to spec.msg_name
@#  - type (string)
@#    full type of the message; equivalent to spec.base_type.type
@#  - subfolder (string)
@#    The subfolder / subnamespace of the message
@#    Either 'msg' or 'srv'
@#  - get_header_filename_from_msg_name (function)
@##########################################################################
@
#include <cassert>
#include <limits>

// Provides the definition of the rosidl_message_type_support_t struct as well
// as the Connext specific macros, e.g. ROSIDL_GET_TYPE_SUPPORT_FUNCTION.
#include "rosidl_generator_c/message_type_support.h"
// Ensure the correct version of the above header was included.
static_assert(USING_ROSIDL_TYPESUPPORT_CONNEXT_C, "expected Connext C message type support");
// Provides the rosidl_typesupport_connext_c__identifier symbol declaration.
#include "rosidl_typesupport_connext_c/identifier.h"
// Provides the definition of the message_type_support_callbacks_t struct.
#include "rosidl_typesupport_connext_cpp/message_type_support.h"

@{header_file_name = get_header_filename_from_msg_name(type)}@
#include "@(pkg)/@(subfolder)/@(header_file_name)__struct.h"
#include "@(pkg)/@(subfolder)/@(header_file_name)__functions.h"

#ifndef _WIN32
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wunused-parameter"
# pragma GCC diagnostic ignored "-Wunused-variable"
# ifdef __clang__
#  pragma clang diagnostic ignored "-Wdeprecated-register"
#  pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
# endif
#endif
#include "@(spec.base_type.pkg_name)/@(subfolder)/dds_connext/@(spec.base_type.type)_Support.h"
#ifndef _WIN32
# pragma GCC diagnostic pop
#endif

// includes and forward declarations of message dependencies and their conversion functions

@# // Include the message header for each non-primitive field.
#if defined(__cplusplus)
extern "C"
{
#endif

// Forward declare the get type support function for this type.
ROSIDL_GENERATOR_C_EXPORT_@(pkg)
const rosidl_message_type_support_t *
  ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(pkg), @(subfolder), @(msg))(void);

// include message dependencies
@{
includes = {}
for field in spec.fields:
    keys = set([])
    if field.type.is_primitive_type():
        if field.type.is_array:
            keys.add('rosidl_generator_c/primitives_array.h')
            keys.add('rosidl_generator_c/primitives_array_functions.h')
        if field.type.type == 'string':
            keys.add('rosidl_generator_c/string.h')
            keys.add('rosidl_generator_c/string_functions.h')
    else:
        header_file_name = get_header_filename_from_msg_name(field.type.type)
        keys.add('%s/msg/%s__functions.h' % (field.type.pkg_name, header_file_name))
    for key in keys:
        if key not in includes:
            includes[key] = set([])
        includes[key].add(field.name)
}@
@[for key in sorted(includes.keys())]@
#include "@(key)"  // @(', '.join(includes[key]))
@[end for]@

// forward declare type support functions
@{
forward_declares = {}
for field in spec.fields:
    if not field.type.is_primitive_type():
        key = (field.type.pkg_name, field.type.type)
        if key not in includes:
            forward_declares[key] = set([])
        forward_declares[key].add(field.name)
}@
@[for key in sorted(forward_declares.keys())]@
@[  if key[0] != pkg]@
ROSIDL_GENERATOR_C_IMPORT_@(pkg)
@[  end if]@
const rosidl_message_type_support_t *
  ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(key[0]), msg, @(key[1]))();  // @(', '.join(forward_declares[key]))
@[end for]@

@# // Make callback functions specific to this message type.

@{
__dds_msg_type_prefix = "{0}::{1}::dds_::{2}_".format(
  spec.base_type.pkg_name, subfolder, spec.base_type.type)
}@
using __dds_msg_type = @(__dds_msg_type_prefix);
using __ros_msg_type = @(pkg)__@(subfolder)__@(type);

static bool
register_type(void * untyped_participant, const char * type_name)
{
  if (!untyped_participant) {
    fprintf(stderr, "untyped participant handle is null\n");
    return false;
  }
  if (!type_name) {
    fprintf(stderr, "type name handle is null\n");
    return false;
  }
  DDSDomainParticipant * participant = static_cast<DDSDomainParticipant *>(untyped_participant);

  DDS_ReturnCode_t status =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type(participant, type_name);
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_BAD_PARAMETER:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "bad domain participant or type name parameter\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: "
        "already registered with a different TypeSupport class\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_TypeSupport::register_type: unknown return code\n");
  }
  return false;
}

static bool
convert_ros_to_dds(const void * untyped_ros_message, void * untyped_dds_message)
{
  if (!untyped_ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }
  if (!untyped_dds_message) {
    fprintf(stderr, "dds message handle is null\n");
    return false;
  }
  const __ros_msg_type * ros_message = static_cast<const __ros_msg_type *>(untyped_ros_message);
  __dds_msg_type * dds_message = static_cast<__dds_msg_type *>(untyped_dds_message);
@[if not spec.fields]@
  // No fields is a no-op.
  (void)dds_message;
  (void)ros_message;
@[end if]@
@[for field in spec.fields]@
  // Field name: @(field.name)
  {
@[  if not field.type.is_primitive_type()]@
    const message_type_support_callbacks_t * @(field.type.pkg_name)__msg__@(field.type.type)__callbacks =
      static_cast<const message_type_support_callbacks_t *>(ROSIDL_GET_TYPE_SUPPORT_FUNCTION(
        @(field.type.pkg_name), msg, @(field.type.type)
      )()->data);
@[  end if]@
@[  if field.type.is_array]@
@[    if field.type.array_size]@
    size_t size = @(field.type.array_size);
@[    else]@
    size_t size = ros_message->@(field.name).size;
    if (size > (std::numeric_limits<DDS_Long>::max)()) {
      fprintf(stderr, "array size exceeds maximum DDS sequence size\n");
      return false;
    }
    DDS_Long length = static_cast<DDS_Long>(size);
    dds_message->@(field.name)_.ensure_length(length, length);
@[    end if]@
    for (DDS_Long i = 0; i < static_cast<DDS_Long>(size); ++i) {
@[    if field.type.array_size]@
      auto & ros_i = ros_message->@(field.name)[i];
@[    else]@
      auto & ros_i = ros_message->@(field.name).data[i];
@[    end if]@
@[    if field.type.type == 'string']@
      const rosidl_generator_c__String * str = &ros_i;
      if (str->capacity == 0 || str->capacity <= str->size) {
        fprintf(stderr, "string capacity not greater than size\n");
        return false;
      }
      if (str->data[str->size] != '\0') {
        fprintf(stderr, "string not null-terminated\n");
        return false;
      }
      dds_message->@(field.name)_[i] = str->data;
@[    elif field.type.type == 'bool']@
      dds_message->@(field.name)_[i] = 1 ? ros_i : 0;
@[    elif field.type.is_primitive_type()]@
      dds_message->@(field.name)_[i] = ros_i;
@[    else]@
      if (!@(field.type.pkg_name)__msg__@(field.type.type)__callbacks->convert_ros_to_dds(
          &ros_i, &dds_message->@(field.name)_[i]))
      {
        return false;
      }
@[    end if]@
    }
@[  elif field.type.type == 'string']@
    const rosidl_generator_c__String * str = &ros_message->@(field.name);
    if (str->capacity == 0 || str->capacity <= str->size) {
      fprintf(stderr, "string capacity not greater than size\n");
      return false;
    }
    if (str->data[str->size] != '\0') {
      fprintf(stderr, "string not null-terminated\n");
      return false;
    }
    dds_message->@(field.name)_ = str->data;
@[  elif field.type.is_primitive_type()]@
    dds_message->@(field.name)_ = ros_message->@(field.name);
@[  else]@
    if (!@(field.type.pkg_name)__msg__@(field.type.type)__callbacks->convert_ros_to_dds(
        &ros_message->@(field.name), &dds_message->@(field.name)_))
    {
      return false;
    }
@[  end if]@
  }

@[end for]@
  return true;
}

static bool
publish(void * dds_data_writer, const void * untyped_ros_message)
{
  if (!dds_data_writer) {
    fprintf(stderr, "data writer handle is null\n");
    return false;
  }
  const __ros_msg_type * ros_message = static_cast<const __ros_msg_type *>(untyped_ros_message);
  if (!ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }

  DDSDataWriter * topic_writer = static_cast<DDSDataWriter *>(dds_data_writer);

  __dds_msg_type dds_message;
  if (!convert_ros_to_dds(ros_message, &dds_message)) {
    return false;
  }
  @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter * data_writer =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter::narrow(topic_writer);
  DDS_ReturnCode_t status = data_writer->write(dds_message, DDS_HANDLE_NIL);
@[for field in spec.fields]@
@[  if field.type.type == 'string']@
@[    if field.type.is_array]@
  {
@[      if field.type.array_size]@
    DDS_Long size = static_cast<DDS_Long>(@(field.type.array_size));
    for (DDS_Long i = 0; i < size; ++i) {
      DDS_String_free(dds_message.@(field.name)_[i]);
      dds_message.@(field.name)_[i] =
        DDS_String_dup(ros_message->@(field.name)[i].data);
    }
@[      else]@
    DDS_Long size = dds_message.@(field.name)_.length();
    for (DDS_Long i = 0; i < size; ++i) {
      DDS_String_free(dds_message.@(field.name)_[i]);
      dds_message.@(field.name)_[i] =
        DDS_String_dup(ros_message->@(field.name).data[i].data);
    }
@[      end if]@
  }
@[    else]@
  DDS_String_free(static_cast<char *>(dds_message.@(field.name)_));
  dds_message.@(field.name)_ =
    DDS_String_dup(ros_message->@(field.name).data);
@[    end if]@
@[  end if]@
@[end for]@
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_BAD_PARAMETER:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "bad handle or instance_data parameter\n");
      return false;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "this @(__dds_msg_type_prefix)DataWriter has already been deleted\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "this @(__dds_msg_type_prefix)DataWriter is not enabled\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "the handle has not been registered with this @(__dds_msg_type_prefix)DataWriter\n");
      return false;
    case DDS_RETCODE_TIMEOUT:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "writing resulted in blocking and then exceeded the timeout set by the "
        "max_blocking_time of the ReliabilityQosPolicy\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataWriter.write: "
        "unknown return code\n");
  }
  return false;
}

static bool
convert_dds_to_ros(const void * untyped_dds_message, void * untyped_ros_message)
{
  if (!untyped_ros_message) {
    fprintf(stderr, "ros message handle is null\n");
    return false;
  }
  if (!untyped_dds_message) {
    fprintf(stderr, "dds message handle is null\n");
    return false;
  }
  const __dds_msg_type * dds_message = static_cast<const __dds_msg_type *>(untyped_dds_message);
  __ros_msg_type * ros_message = static_cast<__ros_msg_type *>(untyped_ros_message);
@[if not spec.fields]@
  // No fields is a no-op.
  (void)dds_message;
  (void)ros_message;
@[end if]@
@[for field in spec.fields]@
  // Field name: @(field.name)
  {
@[  if field.type.is_array]@
@[    if field.type.array_size]@
    DDS_Long size = @(field.type.array_size);
@[    else]@
@{
if field.type.type == 'string':
    array_init = 'rosidl_generator_c__String__Array__init'
    array_fini = 'rosidl_generator_c__String__Array__fini'
elif field.type.is_primitive_type():
    array_init = 'rosidl_generator_c__{field.type.type}__Array__init'.format(**locals())
    array_fini = 'rosidl_generator_c__{field.type.type}__Array__fini'.format(**locals())
else:
    array_init = '{field.type.pkg_name}__msg__{field.type.type}__Array__init'.format(**locals())
    array_fini = '{field.type.pkg_name}__msg__{field.type.type}__Array__fini'.format(**locals())
}@
    DDS_Long size = dds_message->@(field.name)_.length();
    if (ros_message->@(field.name).data) {
      @(array_fini)(&ros_message->@(field.name));
    }
    if (!@(array_init)(&ros_message->@(field.name), size)) {
      return "failed to create array for field '@(field.name)'";
    }
@[    end if]@
    for (DDS_Long i = 0; i < size; i++) {
@[    if field.type.array_size]@
      auto & ros_i = ros_message->@(field.name)[i];
@[    else]@
      auto & ros_i = ros_message->@(field.name).data[i];
@[    end if]@
@[    if field.type.type == 'bool']@
      ros_i = (dds_message->@(field.name)_[i] != 0);
@[    elif field.type.type == 'string']@
      if (!ros_i.data) {
        rosidl_generator_c__String__init(&ros_i);
      }
      bool succeeded = rosidl_generator_c__String__assign(
        &ros_i,
        dds_message->@(field.name)_[i]);
      if (!succeeded) {
        fprintf(stderr, "failed to assign string into field '@(field.name)'\n");
        return false;
      }
@[    elif field.type.is_primitive_type()]@
      ros_i = dds_message->@(field.name)_[i];
@[    else]@
      const rosidl_message_type_support_t * ts =
        ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(field.type.pkg_name), msg, @(field.type.type))();
      const message_type_support_callbacks_t * callbacks =
        static_cast<const message_type_support_callbacks_t *>(ts->data);
      callbacks->convert_dds_to_ros(&dds_message->@(field.name)_[i], &ros_i);
@[    end if]@
    }
@[  elif field.type.type == 'string']@
    if (!ros_message->@(field.name).data) {
      rosidl_generator_c__String__init(&ros_message->@(field.name));
    }
    bool succeeded = rosidl_generator_c__String__assign(
      &ros_message->@(field.name),
      dds_message->@(field.name)_);
    if (!succeeded) {
      fprintf(stderr, "failed to assign string into field '@(field.name)'\n");
      return false;
    }
@[  elif field.type.is_primitive_type()]@
    ros_message->@(field.name) = dds_message->@(field.name)_@(' == static_cast<DDS_Boolean>(true)' if field.type.type == 'bool' else '');
@[  else]@
    const rosidl_message_type_support_t * ts =
      ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(field.type.pkg_name), msg, @(field.type.type))();
    const message_type_support_callbacks_t * callbacks =
      static_cast<const message_type_support_callbacks_t *>(ts->data);
    callbacks->convert_dds_to_ros(&dds_message->@(field.name)_, &ros_message->@(field.name));
@[  end if]@
  }

@[end for]@
  return true;
}

static bool
take(
  void * dds_data_reader,
  bool ignore_local_publications,
  void * untyped_ros_message,
  bool * taken,
  void * sending_publication_handle)
{
  if (untyped_ros_message == 0) {
    fprintf(stderr, "invalid ros message pointer\n");
    return false;
  }

  DDSDataReader * topic_reader = static_cast<DDSDataReader *>(dds_data_reader);

  @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader * data_reader =
    @(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader::narrow(topic_reader);

  @(__dds_msg_type_prefix)Seq dds_messages;
  DDS_SampleInfoSeq sample_infos;
  DDS_ReturnCode_t status = data_reader->take(
    dds_messages,
    sample_infos,
    1,
    DDS_ANY_SAMPLE_STATE,
    DDS_ANY_VIEW_STATE,
    DDS_ANY_INSTANCE_STATE);

  bool ignore_sample = false;

  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "an internal error has occurred\n");
      goto finally;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "this @(__dds_msg_type_prefix)DataReader has already been deleted\n");
      goto finally;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "out of resources\n");
      goto finally;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "this @(__dds_msg_type_prefix)DataReader is not enabled\n");
      goto finally;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "a precondition is not met, one of: "
        "max_samples > maximum and max_samples != LENGTH_UNLIMITED, or "
        "the two sequences do not have matching parameters (length, maximum, release), or "
        "maximum > 0 and release is false.\n");
      goto finally;
    case DDS_RETCODE_NO_DATA:
      *taken = false;
      goto finally;
    case DDS_RETCODE_OK:
      break;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.take: "
        "unknown return code\n");
      goto finally;
  }

  {
    DDS_SampleInfo & sample_info = sample_infos[0];
    if (!sample_info.valid_data) {
      // skip sample without data
      ignore_sample = true;
    } else if (ignore_local_publications) {
      // compare the lower 12 octets of the guids from the sender and this receiver
      // if they are equal the sample has been sent from this process and should be ignored
      DDS_GUID_t sender_guid = sample_info.original_publication_virtual_guid;
      DDS_InstanceHandle_t receiver_instance_handle = topic_reader->get_instance_handle();
      ignore_sample = true;
      for (size_t i = 0; i < 12; ++i) {
        DDS_Octet * sender_element = &(sender_guid.value[i]);
        DDS_Octet * receiver_element = &(reinterpret_cast<DDS_Octet *>(&receiver_instance_handle)[i]);
        if (*sender_element != *receiver_element) {
          ignore_sample = false;
          break;
        }
      }
      // This is nullptr when being used with plain rmw_take, so check first.
      if (sending_publication_handle) {
        *static_cast<DDS_InstanceHandle_t *>(sending_publication_handle) =
          sample_info.publication_handle;
      }
    }
  }

  if (!ignore_sample) {
    if (!convert_dds_to_ros(&dds_messages[0], untyped_ros_message)) {
      goto finally;
    }
    *taken = true;
  } else {
    *taken = false;
  }

finally:
  // Ensure the loan is returned.
  status = data_reader->return_loan(dds_messages, sample_infos);
  switch (status) {
    case DDS_RETCODE_ERROR:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "an internal error has occurred\n");
      return false;
    case DDS_RETCODE_ALREADY_DELETED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "this @(__dds_msg_type_prefix)DataReader has already been deleted\n");
      return false;
    case DDS_RETCODE_OUT_OF_RESOURCES:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "out of resources\n");
      return false;
    case DDS_RETCODE_NOT_ENABLED:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "this @(__dds_msg_type_prefix)DataReader is not enabled\n");
      return false;
    case DDS_RETCODE_PRECONDITION_NOT_MET:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "a precondition is not met, one of: "
        "the data_values and info_seq do not belong to a single related pair, or "
        "the data_values and info_seq were not obtained from this "
        "@(__dds_msg_type_prefix)DataReader\n");
      return false;
    case DDS_RETCODE_OK:
      return true;
    default:
      fprintf(stderr, "@(spec.base_type.pkg_name)::@(subfolder)::dds_::@(spec.base_type.type)_DataReader.return_loan: "
        "unknown return code\n");
  }

  return false;
}
@
@# // Collect the callback functions and provide a function to get the type support struct.

static message_type_support_callbacks_t __callbacks = {
  "@(pkg)",  // package_name
  "@(msg)",  // message_name
  register_type,  // register_type
  publish,  // publish
  take,  // take
  convert_ros_to_dds,  // convert_ros_to_dds
  convert_dds_to_ros,  // convert_dds_to_ros
};

static rosidl_message_type_support_t __type_support = {
  // Cannot be set since it is not a constexpr, it is set in the get type support function below.
  0,
  &__callbacks
};

ROSIDL_GENERATOR_C_EXPORT_@(spec.base_type.pkg_name)
const rosidl_message_type_support_t *
ROSIDL_GET_TYPE_SUPPORT_FUNCTION(@(pkg), @(subfolder), @(msg))() {
  if (!__type_support.typesupport_identifier) {
    __type_support.typesupport_identifier = rosidl_typesupport_connext_c__identifier;
  }
  return &__type_support;
}

#if defined(__cplusplus)
}
#endif


add namespace manifest!

add namespace manifest!

#= require jquery
#= require jquery.ui.sortable
#= require handlebars
#= require ember
#= require ember-data
#= require ember-uploader
#= require js-yaml

#= require_self

#= require_tree ./models
#= require_tree ./mixins
#= require_tree ./views
#= require_tree ./components
#= require_tree ./templates

window.Herd = Ember.Namespace.create
  VERSION: '1.0.0'

#= require jquery
#= require jquery.ui.sortable
#= require handlebars
#= require ember
#= require ember-data
#= require ember-uploader
#= require js-yaml

#= require_self

#= require_tree ./models
#= require_tree ./views
#= require_tree ./components
#= require_tree ./templates

window.Herd = Ember.Namespace.create
  VERSION: '1.0.0'