/* Copyright 2012. Bloomberg Finance L.P.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: The above
* copyright notice and this permission notice shall be included in all copies
* or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
// blpapi_subscriptionlist.h -*-C++-*-
#ifndef INCLUDED_BLPAPI_SUBSCRIPTIONLIST
#define INCLUDED_BLPAPI_SUBSCRIPTIONLIST
//@PURPOSE: Provide a list of subscriptions.
//
//@CLASSES:
// blpapi::SubscriptionList: Represents a list of subscriptions.
//
//@DESCRIPTION: This component provides a structure to hold the data used (and
// returned) by the 'Session::subscribe', 'Session::resubscribe', and
// 'Session::unsubscribe' methods. This structure comprises a list in which
// each list entry contains two primary fields: a 'CorrelationId' associated
// with the subscription, and a string, called a *subscription* *string*,
// describing the data to be delivered as a part of the subscription.
//
// STRUCTURE OF SUBSCRIPTION STRING
// ---------------------------------
// The simplest form of a subscription string is a *fully* *qualified*
// subscription string, which has the following structure:
//
// "//blp/mktdata/ticker/IBM US Equity?fields=BID,ASK&interval=2"
// \-----------/\------/\-----------/\------------------------/
// | | | |
// Service Prefix Instrument Suffix
//
// Such a fully-qualified string is composed of:
//: Service Identifier: a string matching the expression
//: '^//[-_.a-zA-Z0-9]+/[-_.a-zA-Z0-9]+$', e.g. //blp/mktdata. See
//: 'blpapi_abstractsession' for further details.
//:
//: Prefix: a string matching the expression '/([-_.a-zA-Z0-9]+/)?', often used
//: as a symbology identifier. Common examples include '/ticker/' and
//: '/cusip/'. Not all services make use of prefices. Note than an "empty"
//: topic prefix consists of the string "/", so the topic prefix always
//: separates the service string from the instrument string.
//:
//: Instrument: a non-empty string that does not contain the character '?'
//: (i.e. a string matching '[^?]+') e.g. "IBM US Equity", or "SPX Index".
//: The service, prefix, and instrument together uniquely identify a source
//: for subscription data.
//:
//: Suffix: a suffix contains a question mark followed by a list of options
//: which can affect the content delivery. The format of these options is
//: service specific, but they generally follow URI query string conventions:
//: a sequence of "key=value" pairs separated by "&" characters. Further,
//: many common services follow the convention that the value given for the
//: 'fields' key is formatted as a comma-separated list of field names.
//: BLPAPI provides several convenience functions to assist in formatting
//: subscription strings for services that make use of these conventions;
//: see the 'SubscriptionList::add' methods for details.
//
// Subscription strings need not be fully qualified: BLPAPI allows the service
// and prefix to be omitted from subscription strings, and automatically
// qualifies these strings using information stored in a 'Session' object.
//
// QUALIFYING SUBSCRIPTION STRINGS
// -------------------------------
// The subscription strings passed to 'Session::subscribe' and
// 'Session::resubscribe' are automatically qualified if the service identifier
// is missing (i.e. if the subscription string does not start with "//"). The
// subscription parameters (i.e. the optional part after instrument identifier)
// are never modified.
// The rules for qualifying the subscription string are:
//
//: o If the subscription string begins with "//" then it is assumed to be a
//: a fully qualified subscription string including service identifier,
//: prefix, and instrument. In this case the string will not be modified and
//: session options defaults have no affect on the subscription.
//:
//: o If the subscription string begins with a '/' and the second character is
//: not '/', then the string is assumed to begin with the topic prefix, but
//: no service identifier. In this case the string is qualified by prepending
//: the 'SessionOptions::defaultSubscriptionService()' to the specified
//: string.
//:
//: o If the subscription string does not begin with a '/' it is assumed to
//: begin with an instrument identifier. In this case the string is
//: qualified by prepending the
//: 'SessionOptions::defaultSubscriptionService()' followed by
//: 'SessionOptions::defaultTopicPrefix()' to the specified string.
//: If the 'defaultTopicPrefix' is empty or null, then the prefix used is
//: '/'. Otherwise (in the case of a nontrivial prefix) if the separator '/'
//: is not specified at the beginning or the end of the 'defaultTopicPrefix',
//: then it will be added.
#ifndef INCLUDED_BLPAPI_CALL
#include <blpapi_call.h>
#endif
#ifndef INCLUDED_BLPAPI_CORRELATIONID
#include <blpapi_correlationid.h>
#endif
#ifndef INCLUDED_BLPAPI_DEFS
#include <blpapi_defs.h>
#endif
#ifndef INCLUDED_BLPAPI_EXCEPTION
#include <blpapi_exception.h>
#endif
#ifndef INCLUDED_BLPAPI_TYPES
#include <blpapi_types.h>
#endif
#include <stddef.h>
struct blpapi_SubscriptionList;
typedef struct blpapi_SubscriptionList blpapi_SubscriptionList_t;
#ifdef __cplusplus
extern "C" {
#endif
BLPAPI_EXPORT
blpapi_SubscriptionList_t *blpapi_SubscriptionList_create(void);
BLPAPI_EXPORT
void blpapi_SubscriptionList_destroy(blpapi_SubscriptionList_t *list);
BLPAPI_EXPORT
int blpapi_SubscriptionList_add(
blpapi_SubscriptionList_t *list,
const char *subscriptionString,
const blpapi_CorrelationId_t *correlationId,
const char **fields,
const char **options,
size_t numfields,
size_t numOptions);
BLPAPI_EXPORT
int blpapi_SubscriptionList_addResolved(
blpapi_SubscriptionList_t *list,
const char *subscriptionString,
const blpapi_CorrelationId_t *correlationId);
BLPAPI_EXPORT
int blpapi_SubscriptionList_clear(blpapi_SubscriptionList_t *list);
BLPAPI_EXPORT
int blpapi_SubscriptionList_append(blpapi_SubscriptionList_t *dest,
const blpapi_SubscriptionList_t *src);
BLPAPI_EXPORT
int blpapi_SubscriptionList_size(const blpapi_SubscriptionList_t *list);
BLPAPI_EXPORT
int blpapi_SubscriptionList_correlationIdAt(
const blpapi_SubscriptionList_t *list,
blpapi_CorrelationId_t *result,
size_t index);
BLPAPI_EXPORT
int blpapi_SubscriptionList_topicStringAt(blpapi_SubscriptionList_t *list,
const char **result,
size_t index);
BLPAPI_EXPORT
int blpapi_SubscriptionList_isResolvedAt(blpapi_SubscriptionList_t *list,
int *result,
size_t index);
#ifdef __cplusplus
}
#ifndef INCLUDED_CSTRING
#include <cstring>
#define INCLUDED_CSTRING
#endif
#ifndef INCLUDED_STRING
#include <string>
#define INCLUDED_STRING
#endif
#ifndef INCLUDED_VECTOR
#include <vector>
#define INCLUDED_VECTOR
#endif
namespace BloombergLP {
namespace blpapi {
// ======================
// class SubscriptionList
// ======================
class SubscriptionList {
// Contains a list of subscriptions used when subscribing and
// unsubscribing.
//
// A 'SubscriptionList' is used when calling 'Session::subscribe()',
// 'Session::resubscribe()' and 'Session::unsubscribe()'. The entries can
// be constructed in a variety of ways.
// The two important elements when creating a subscription are
//: Subscription String: A subscription string represents a topic whose
//: updates user is interested in. A subscription string follows a
//: structure as specified below.
//: CorrelationId: the unique identifier to tag all data associated with
//: this subscription.
//
// The following table describes how various operations use the above
// elements:
// --------------|--------------------------------------------------------|
// OPERATION | SUBSCRIPTION STRING | CORRELATION ID |
// --------------|-----------------------+--------------------------------|
// 'subscribe' |Used to specify the |Identifier for the subscription.|
// |topic to subscribe to. |If uninitialized correlationid |
// | |was specified an internally |
// | |generated correlationId will be |
// | |set for the subscription. |
// --------------+-----------------------+--------------------------------|
// 'resubscribe' |Used to specify the new|Identifier of the subscription |
// |topic to which the |which needs to be modified. |
// |subscription should be | |
// |modified to. | |
// --------------+-----------------------+--------------------------------|
// 'unsubscribe' | NOT USED |Identifier of the subscription |
// | |which needs to be canceled. |
// -----------------------------------------------------------------------|
blpapi_SubscriptionList_t *d_handle_p;
public:
SubscriptionList();
// Create an empty 'SubscriptionList'.
SubscriptionList(const SubscriptionList& original);
// Create a 'SubscriptionList' object initialized to the list of
// subscriptions from the specified 'original'.
~SubscriptionList();
// Destroy this object.
// MANIPULATORS
int add(const char *subscriptionString);
// Append the specified 'subscriptionString' to this 'SubscriptionList'
// object, associating an internally generated 'CorrelationId' with it.
// The subscription string may include options. Note that the
// subscription string provided to this function may be resolved by
// functions operating on this 'SubscriptionList' object; use
// 'SubscriptionList::addResolved', below, to request that such
// functions bypass resolution.
int add(const char *subscriptionString,
const CorrelationId& correlationId);
// Append the specified 'subscriptionString' to this 'SubscriptionList'
// object, associating the specified 'correlationId' with it. The
// subscription string may include options. Note that the subscription
// string provided to this function may be resolved by functions
// operating on this 'SubscriptionList' object; use
// 'SubscriptionList::addResolved', below, to request that such
// functions bypass resolution.
int add(const char *subscriptionWithoutOptions,
const std::vector<std::string>& fields,
const std::vector<std::string>& options,
const CorrelationId& correlationId);
// Append the specified 'subscriptionString', with the specified
// 'fields' and the specified 'options', to this 'SubscriptionList'
// object, associating the specified 'correlationId' with it.
int add(const char *subscriptionWithoutOptions,
const char *fields,
const char *options,
const CorrelationId& correlationId);
// Append the specified 'subscriptionString' with the specified
// 'fields', which must be formatted as a comma-separated list, and the
// specified 'options', which must be formatted as an
// ampersand-separated list, to this 'SubscriptionList' object, and
// associate the specified 'correlationId' with it.
int add(const CorrelationId& correlationId);
// Append the specified 'correlationId' to this 'SubscriptionList'
// object. A 'SubscriptionList' entry containing only a
// 'CorrelationId' can be used only in a 'Session::unsubscribe' call.
int addResolved(const char *subscriptionString);
// Add the specified 'subscriptionString' to this 'SubscriptionList',
// associating an internally generated 'CorrelationId' with it. The
// subscription string may include options. The behavior of this
// function, and of functions operating on this 'SubscriptionList'
// object, is undefined unless 'subscriptionString' is a
// fully-resolved subscription string; clients that cannot provide
// fully-resolved subscription strings should use
// 'SubscriptionList::add' instead. Note that it is at the discretion
// of each function operating on a 'SubscriptionList' whether to
// perform resolution on this subscription.
int addResolved(const char *subscriptionString,
const CorrelationId& correlationId);
// Add the specified 'subscriptionString' to this 'SubscriptionList'
// object, associating the specified 'correlationId' with it. The
// subscription string may include options. The behavior of this
// function, and of functions operating on this 'SubscriptionList'
// object, is undefined unless 'subscriptionString' is a
// fully-resolved subscription string; clients that cannot provide
// fully-resolved subscription strings should use
// 'SubscriptionList::add' instead. Note that it is at the discretion
// of each function operating on a 'SubscriptionList' whether to
// perform resolution on this subscription.
int append(const SubscriptionList& other);
// Extend this object by appending a copy of each entry in the
// specified 'other'. Note that this function adds 'other.size()' new
// entries to this object. Note also that this function is alias-safe;
// i.e. 'x.append(x)' has well-defined behavior.
void clear();
// Remove all entries from this object.
SubscriptionList& operator=(const SubscriptionList& rhs);
// Replace the contents of this 'SubscriptionList' object with the
// contents of the specified 'rhs' and return a modifiable reference to
// this 'SubscriptionList' object.
// ACCESSORS
size_t size() const;
// Return the number of entries in this object.
CorrelationId correlationIdAt(size_t index) const;
// Return the 'CorrelationId' of the specified 'index'th entry in this
// 'SubscriptionList' object. An exception is thrown if
// 'index >= size()'.
const char *topicStringAt(size_t index) const;
// Return a pointer to a null-terminated string which contains the full
// topic string (including any field and option portions) of the
// 'index'th entry in this 'SubscriptionList' object. The pointer
// remains valid until this 'SubscriptionList' object is destroyed or
// 'clear()' is called. An exception is thrown if 'index >= size()'.
bool isResolvedTopicAt(size_t index) const;
// Return 'true' if the 'index'th entry in this 'SubscriptionList'
// object was created using 'SubscriptionList::addResolved' and 'false'
// if it was created using 'SubscriptionList::add'. An exception is
// thrown if 'index >= size()'.
const blpapi_SubscriptionList_t *impl() const;
};
// ============================================================================
// INLINE FUNCTION DEFINITIONS
// ============================================================================
// ----------------------
// class SubscriptionList
// ----------------------
inline
SubscriptionList::SubscriptionList()
: d_handle_p(blpapi_SubscriptionList_create())
{
}
inline
SubscriptionList::SubscriptionList(const SubscriptionList& original)
: d_handle_p(blpapi_SubscriptionList_create())
{
blpapi_SubscriptionList_append(d_handle_p, original.d_handle_p);
}
inline
SubscriptionList::~SubscriptionList()
{
blpapi_SubscriptionList_destroy(d_handle_p);
}
inline
int SubscriptionList::add(const char *subscriptionString)
{
blpapi_CorrelationId_t correlationId;
std::memset(&correlationId, 0, sizeof(correlationId));
return blpapi_SubscriptionList_add(d_handle_p,
subscriptionString,
&correlationId,
0,
0,
0,
0);
}
inline
int SubscriptionList::add(const char *subscriptionString,
const CorrelationId& correlationId)
{
return blpapi_SubscriptionList_add(d_handle_p,
subscriptionString,
&correlationId.impl(),
0,
0,
0,
0);
}
inline
int SubscriptionList::add(const char *subscriptionString,
const std::vector<std::string>& fields,
const std::vector<std::string>& options,
const CorrelationId& correlationId)
{
std::vector<const char *> tmpVector;
const char *arena[256];
const char **tmpArray = arena;
size_t sizeNeeded = fields.size() + options.size();
if (sizeNeeded > sizeof(arena)/sizeof(arena[0])) {
tmpVector.resize(sizeNeeded);
tmpArray = &tmpVector[0];
}
const char **p = tmpArray;
for (std::vector<std::string>::const_iterator itr = fields.begin(),
end = fields.end(); itr != end; ++itr, ++p) {
*p = itr->c_str();
}
for (std::vector<std::string>::const_iterator itr = options.begin(),
end = options.end(); itr != end; ++itr, ++p) {
*p = itr->c_str();
}
return blpapi_SubscriptionList_add(d_handle_p,
subscriptionString,
&correlationId.impl(),
tmpArray,
tmpArray + fields.size(),
fields.size(),
options.size());
}
inline
int SubscriptionList::add(const char *subscriptionString,
const char *fields,
const char *options,
const CorrelationId& correlationId)
{
return blpapi_SubscriptionList_add(d_handle_p,
subscriptionString,
&correlationId.impl(),
&fields,
&options,
fields ? 1 : 0,
options ? 1 : 0 );
}
inline
int SubscriptionList::add(const CorrelationId& correlationId)
{
return blpapi_SubscriptionList_add(d_handle_p,
"",
&correlationId.impl(),
0,
0,
0,
0);
}
inline
int SubscriptionList::addResolved(const char *subscriptionString)
{
blpapi_CorrelationId_t correlationId;
std::memset(&correlationId, 0, sizeof(correlationId));
return BLPAPI_CALL_SUBSCRIPTIONLIST_ADDRESOLVED(d_handle_p,
subscriptionString,
&correlationId);
}
inline
int SubscriptionList::addResolved(const char *subscriptionString,
const CorrelationId& correlationId)
{
return BLPAPI_CALL_SUBSCRIPTIONLIST_ADDRESOLVED(d_handle_p,
subscriptionString,
&correlationId.impl());
}
inline
int SubscriptionList::append(const SubscriptionList& other)
{
return blpapi_SubscriptionList_append(d_handle_p, other.d_handle_p);
}
inline
void SubscriptionList::clear()
{
blpapi_SubscriptionList_clear(d_handle_p);
}
inline
SubscriptionList& SubscriptionList::operator=(const SubscriptionList& rhs)
{
blpapi_SubscriptionList_clear(d_handle_p);
blpapi_SubscriptionList_append(d_handle_p, rhs.d_handle_p);
return *this;
}
inline
size_t SubscriptionList::size() const
{
return blpapi_SubscriptionList_size(d_handle_p);
}
inline
CorrelationId SubscriptionList::correlationIdAt(size_t index) const
{
blpapi_CorrelationId_t correlationId;
ExceptionUtil::throwOnError(
blpapi_SubscriptionList_correlationIdAt(d_handle_p,
&correlationId,
index));
return CorrelationId(correlationId);
}
inline
const char *SubscriptionList::topicStringAt(size_t index) const
{
const char *result;
ExceptionUtil::throwOnError(
blpapi_SubscriptionList_topicStringAt(d_handle_p,
&result,
index));
return result;
}
inline
bool SubscriptionList::isResolvedTopicAt(size_t index) const
{
int result;
ExceptionUtil::throwOnError(
BLPAPI_CALL_SUBSCRIPTIONLIST_ISRESOLVEDAT(d_handle_p,
&result,
index));
return result ? true : false;
}
inline
const blpapi_SubscriptionList_t *SubscriptionList::impl() const
{
return d_handle_p;
}
} // close package namespace
} // close enterprise namespace
#endif // ifdef __cplusplus
#endif // #ifndef INCLUDED_BLPAPI_SUBSCRIPTIONLIST