RTI Connext DDS Micro  Version 2.4.9
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Working with Sequences

Introduction

RTI Connext DDS Micro, and DDS, uses IDL as the language to define data-types. One of the constructs in IDL is the sequence; a variable length vector where each element is of the same type. This document describes how to work with sequences and in particular the string sequence since it has special properties.

Working with Sequences

Overview

Logically a sequence can be viewed as a variable length vector with N elements as illustrated below. Note that sequences indices are 0 based.

         +---+
      0  | T |
         +---+
      1  | T |
         +---+
      2  | T |
         +---+
           |
           |
         +---+
    N-1  | T |
         +---+

There are three types of sequences in RTI Connext DDS Micro:

The following built-in sequences exist (please refer to Reference Manuals for the complete API).

IDL Type RTI Connext DDS Micro Type RTI Connext DDS Micro Sequence
octet DDS_Octet DDS_OctetSeq
char DDS_Char DDS_CharSeq
boolean DDS_Boolean DDS_BooleanSeq
short DDS_Short DDS_ShortSeq
unsigned short DDS_UnsignedShort DDS_UnsignedShortSeq
long DDS_Long DDS_LongSeq
unsigned long DDS_UnsignedLong DDS_UnsignedLongSeq
enum DDS_Enum DDS_EnumSeq
wchar DDS_Wchar DDS_WcharSeq
long long DDS_LongLong DDS_LongLongSeq
unsigned long long DDS_UnsignedLongLong DDS_UnsignedLongLongSeq
float DDS_Float DDS_FloatSeq
double DDS_Double DDS_DoubleSeq
long double DDS_LongDouble DDS_LongDoubleSeq
string DDS_String DDS_StringSeq
wstring DDS_Wstring

DDS_WstringSeq

The following are important properties of sequences to remember:

Working with IDL Sequences

Sequences which originate from IDL are created when the IDL type they belong to is created. IDL sequences are always initialized with the maximum size specified in the IDL file. The maximum size of a type, and hence the sequence size, is used to calculate memory needs for serialization and deserialization buffers. Thus, changing the size of an IDL sequence can lead to hard to find memory corruption.

The string and wstring sequences are special in that not only is the maximum sequence size allocated, but because strings are also always of a finite maximum length, the maximum space needed for each string element is also allocated. This ensure that RTI Connext DDS Micro can prevent memory overruns and validate input.

Some typical scenarios with a long sequence and a string sequence defined in IDL is shown below:

/* In IDL */
struct SomeIdlType
{
// A sequence of 20 longs
sequence<long,20> long_seq;
// A sequence of 10 strings, each string has a maximum length of 255 bytes
// (excluding NUL)
sequence<string<255>,10> string_seq;
}
/* In C source */
SomeIdlType *my_sample = SomeIdlTypeTypeSupport_create_data()
DDS_LongSet_set_length(&my_sample->long_seq,5);
DDS_StringSeq_set_length(&my_sample->string_seq,5);
/* Assign the first 5 longs in long_seq */
for (i = 0; i < 5; ++i)
{
*DDS_LongSeq_get_reference(&my_sample->long_seq,i) = i;
snprintf(*DDS_StringSeq_get_reference(&my_sample->string_seq,0),255,"SomeString %d",i);
}
SomeIdlTypeTypeSupport_delete_data(my_sample);
/* In C++ source */
SomeIdlType *my_sample = SomeIdlTypeTypeSupport::create_data()
/* Assign the first 5 longs in long_seq */
my_sample->long_seq.length(5);
my_sample->string_seq.length(5);
for (i = 0; i < 5; ++i)
{
/* use method */
*DDSLongSeq_get_reference(&my_sample->long_seq,i) = i;
snprintf(*DDSStringSeq_get_reference(&my_sample->string_seq,i),255,"SomeString %d",i);
/* or assignment */
my_sample->long_seq[i] = i;
snprintf(my_sample->string_seq[i],255,"SomeString %d",i);
}
SomeIdlTypeTypeSupport::delete_data(my_sample);

Note that in this examples above the sequence length is set. The maximum size for each sequence is set when my_sample is allocated.

A special case is to copy a string sequence from a sample to a string sequence defined outside of the sample. This is possible, but care must be taken to ensure that the memory is allocated properly:

Conside the IDL type from the previous example. A string sequence of equal size can be allocated as follows:

struct DDS_StringSeq app_seq = DDS_SEQUUENCE_INITIALIZER;
/* This ensures that memory for the strings are allocated upfront */
DDS_StringSeq_set_maximum_w_max(&app_seq,10,255);
DDS_StringSeq_copy(&app_seq,&my_sample->string_seq);

If instead the following code was used, memory for the string in app_seq would be allocated as needed.

struct DDS_StringSeq app_seq = DDS_SEQUUENCE_INITIALIZER;
/* This ensures that memory for the strings are allocated upfront */
DDS_StringSeq_set_maximum(&app_seq,10);
DDS_StringSeq_copy(&app_seq,&my_sample->string_seq);

Working with Application Defined Sequences

Application defined sequences work in the same way as sequences defined in IDL with two exceptions:

struct DDS_StringSeq my_seq = DDS_SEQUENCE_INITIALIZER;
DDS_StringSeq_ensure_length(&my_seq,10,20);
for (i = 0; i < 10; i++)
{
*DDS_StringSeq_get_reference(&my_seq,i) = DDS_String_dup("test");
}
DDS_StringSeq_finalize(&my_seq);

DDS_StringSeq_finalize automatically free memory pointed to by each element using DDS_String_free. All memory allocated to a string element should be allocated using a DDS_String function.

It is possible to assign any memory to a string sequence element if all elements are released manually first:

struct DDS_StringSeq my_seq = DDS_SEQUENCE_INITIALIZER;
DDS_StringSeq_ensure_length(&my_seq,10,20);
for (i = 0; i < 10; i++)
{
*DDS_StringSeq_get_reference(&my_seq,i) = static_string[i];
}
/* Work with the sequence */
for (i = 0; i < 10; i++)
{
*DDS_StringSeq_get_reference(&my_seq,i) = NULL;
}
DDS_StringSeq_finalize(&my_seq);

RTI Connext DDS Micro Version 2.4.9 Copyright © Thu Dec 15 2016 Real-Time Innovations, Inc