Apama 10.3 | Apama Documentation | Connecting Apama Applications to External Components | Working with Connectivity Plug-ins | Developing Connectivity Plug-ins | C++ data types
C++ data types
C++ plug-ins handle messages, which have a payload which can be any of the following:
*string (null terminated UTF-8) (const char*)
*integer (64 bit) (int64_t)
*float (64 bit) (double)
*decimal (64 bit) (decimal_t)
*boolean (bool)
*map of any of these types to any of these types (map_t)
*list of any of these types (list_t)
*byte buffer (buffer_t)
*a custom object - a pointer to a user-defined class (custom_t)
*an empty or "null" value
To facilitate this, the payload member of a message is of the com::softwareag::connectivity::data_t class type. The data_t type is a "smart union" that holds one of the above types, and knows which type it holds. It has a similar API to a boost variant. The data_t class has constructors from each of the above types, and a no-argument constructor which creates an empty value. Accessing the data contained in a data_t instance can be performed as described below.
*Use the get free template function. For example:
data_t data("some text");
const char *text = get<const char*>(data);
map_t map;
data_t mapdata(map);
map &mapref = get<map_t>(mapdata);
For compound types map_t, list_t, custom_t and buffer_t, this returns a reference to the object.
*You can attempt to convert integer, boolean, string or float values inside a data_t to each other, regardless of the underlying type. The following is an example for turning a string into its numerical representation:
data_t data("10");
int64_t i = convert_to<int64_t>(data);
double f = convert_to<double>(data);
*Use a visitor and the apply_visitor free template function. A visitor is a class with operator() methods for each of the types (and no arguments for empty data_t). If you wish to use a visitor that only handles a few types and throws an error on all other types, then sub-class the provided visitor or const_visitor template and override one or more of the following methods:
The result of apply_visitor is of type visitor::result_type (typically a typedef), or the second template argument of visitor/const_visitor. For example:
struct print_data: public const_visitor<print_config, void>
void visitString(const char *s) const { std::cout << s; }
void visitList(const list_t &l) const
std::cout << "[";
for (list_t::const_iterator it = l.begin(); it != l.end(); ++it) {
apply_visitor(print_data(), *it);
if (it+1 != l.end()) std::cout << ", ";
std::cout << "]";
void visitMap(const map_t &m) const
std::cout << "{";
std::vector<std::string> keys;
for (map_t::const_iterator it = m.begin(); it != m.end(); ++it) {
keys.push_back(get<const char*>(it.key()));
std::sort(keys.begin(), keys.end());
for (std::vector<std::string>::iterator it = keys.begin();
it != keys.end(); ++it) {
std::cout << *it << "=";
if (it+1 != keys.end()) std::cout << ", ";
std::cout << "}";

data_t data;
apply_visitor(print_data(), data);
Containers and custom values
The list_t and map_t classes are containers that hold a list or unordered (hash) map of data_t elements (and for map_t, keys). These are similar in behavior to the C++ standard library classes std::vector and std::unordered_map - with a subset of the methods available. list_t maintains order of the elements in them, and allows access with the operator[] overload or iterators returned from begin and end (or rbegin and rend, or cbegin and cend). map_t does not maintain ordering, and should give average O(1) cost for insertions and lookups. map_t does not permit a data_t holding a custom_t value to be used as a key.
The buffer_t is similar to list_t, but its element type is byte (uint8_t). buffer_t can be translated to and from a Java byte[], but not to host plug-ins as there is no correlator type that maps to or from them.
The custom_t type behaves like a std::unique_ptr to a user-specified class, with an explicit copy method. The class must have a copy constructor and destructor that do not throw exceptions. It is up to you to ensure that the correct type is used; but if all classes wrapped in custom_t are virtual, then it is possible to use dynamic_cast or typeinfo to distinguish the types of the objects held by custom_t. Note that visitors are called with a sag_underlying_custom_t reference; this needs to be cast with static_cast to the expected custom_t<Type> reference. custom_t values can only be passed between C++ plug-ins; they cannot be passed to host plug-ins or Java plug-ins (and you need to ensure that the plug-ins share the same definition of the class).
The Apama decimal type is converted to/from a decimal_t struct. This has a single int64_t which is the bit pattern of the IEE754 64-bit floating point decimal. This can be serialized, copied or moved, but no facilities are provided for arithmetic or conversion to string or normal floating point types; a third-party decimal library is required if such functionality is required.
Copying, moving and swapping
The data_t and compound types list_t, map_t, buffer_t and custom_t deliberately hide access to the copy constructor and assignment operator to avoid accidental copies. Explicit copies are possible with the copy() method, which performs a deep copy (that is, for a map or list value, it copies each element, and each element of those if they are compound types). Rather than copying values, consider if the move constructor or move assignment operator can be used (these leave the object moved from as empty). To call these, the argument needs to be enclosed in the std::move( ).

Copyright © 2013-2018 | Software AG, Darmstadt, Germany and/or Software AG USA, Inc., Reston, VA, USA, and/or its subsidiaries and/or its affiliates and/or their licensors.