471 lines
18 KiB
C++
471 lines
18 KiB
C++
/*
|
|
* Copyright Onix Solutions Limited [OnixS]. All rights reserved.
|
|
*
|
|
* This software owned by Onix Solutions Limited [OnixS] and is protected by copyright law
|
|
* and international copyright treaties.
|
|
*
|
|
* Access to and use of the software is governed by the terms of the applicable OnixS Software
|
|
* Services Agreement (the Agreement) and Customer end user license agreements granting
|
|
* a non-assignable, non-transferable and non-exclusive license to use the software
|
|
* for it's own data processing purposes under the terms defined in the Agreement.
|
|
*
|
|
* Except as otherwise granted within the terms of the Agreement, copying or reproduction of any part
|
|
* of this source code or associated reference material to any other location for further reproduction
|
|
* or redistribution, and any amendments to this copyright notice, are expressly prohibited.
|
|
*
|
|
* Any reproduction or redistribution for sale or hiring of the Software not in accordance with
|
|
* the terms of the Agreement is a violation of copyright law.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <iterator>
|
|
|
|
#include <OnixS/FIXEngine/FIX/Tag.h>
|
|
#include <OnixS/FIXEngine/FIX/Numeric.h>
|
|
#include <OnixS/FIXEngine/FIX/StringRef.h>
|
|
#include <OnixS/FIXEngine/FIX/Timestamp.h>
|
|
|
|
#include <OnixS/FIXEngine/FIX/FlatFieldRefAndKey.h>
|
|
#include <OnixS/FIXEngine/FIX/FieldValueRef.h>
|
|
|
|
#include <OnixS/FIXEngine/FIX/ProtocolVersion.h>
|
|
|
|
namespace OnixS {
|
|
namespace FIX {
|
|
ONIXS_FIXENGINE_API_DECL(class, Message);
|
|
ONIXS_FIXENGINE_API_DECL(class, FlatGroup);
|
|
|
|
/// The insert mode of FlatMessage::insert() methods.
|
|
struct InsertMode
|
|
{
|
|
enum Enum
|
|
{
|
|
/// The new field will be inserted before the position tag.
|
|
Before,
|
|
|
|
/// The new field will be inserted after the position tag.
|
|
After
|
|
};
|
|
};
|
|
|
|
/// Field primary attributes (a tag and a reference to a value).
|
|
struct ONIXS_FIXENGINE_API FlatField
|
|
{
|
|
/// The field tag.
|
|
Tag tag;
|
|
|
|
/// The field value reference.
|
|
StringRef value;
|
|
|
|
/// Initializes the field which refers to nothing.
|
|
FlatField()
|
|
: tag(0) {}
|
|
|
|
/// Initializes all members.
|
|
FlatField(
|
|
Tag fieldTag,
|
|
const StringRef & fieldValue)
|
|
: tag(fieldTag), value(fieldValue) {}
|
|
};
|
|
|
|
/// Provides an access to FIX fields from a flat (tag=value) message.
|
|
///
|
|
/// Fields can be accessed using temporary field references and using
|
|
/// special keys which remain constant during the lifetime of the single instance.
|
|
///
|
|
/// To access a field, a reference must be obtained using the 'find' member.
|
|
/// The 'find' member searches for a field using a regular Tag identifier.
|
|
/// If the 'find' succeeds, a temporary reference is returned. That reference can
|
|
/// be either used to modify the field or to allocate a key for that field using
|
|
/// the 'allocateKey' member. Once the key is allocated it can be used like a tag
|
|
/// to quick access the field.
|
|
///
|
|
/// There are pre-allocated keys to access service fields like MsgType, MsgSeqNum, SendingTime, etc.
|
|
///
|
|
/// @note BodyLength and CheckSum fields are not synchronized each time other fields are updated.
|
|
/// Therefore, to bring the flat message (tag=value) into the valid state, it's necessary to invoke the 'adjust' member.
|
|
class ONIXS_FIXENGINE_API FlatMessage
|
|
{
|
|
public:
|
|
/// Constructs the blank instance.
|
|
///
|
|
/// @note This constructor does not support the zero-copy feature.
|
|
FlatMessage();
|
|
|
|
/// Constructs an instance with empty required message header fields.
|
|
///
|
|
/// @note This constructor does not support the zero-copy feature.
|
|
FlatMessage(OnixS::FIX::ProtocolVersion::Enum protocolVersion, const char * msgType);
|
|
|
|
/// Constructs an instance from the tag=value form.
|
|
FlatMessage(const char * rawMessage, size_t rawMessageSize, bool useZeroCopyBuffer = true);
|
|
|
|
/// Constructs an instance from the tag=value form without session-level fields.
|
|
/// Required fields will be added during the construction.
|
|
FlatMessage(
|
|
OnixS::FIX::ProtocolVersion::Enum protocolVersion,
|
|
const char * msgType,
|
|
const char * senderCompId,
|
|
const char * targetCompId,
|
|
const char * rawMessageWithoutHeaderTrailer,
|
|
size_t rawMessageWithoutHeaderTrailerSize,
|
|
bool useZeroCopyBuffer = true);
|
|
|
|
/// Constructs an instance from the given Message object.
|
|
FlatMessage(const OnixS::FIX::Message & message, bool useZeroCopyBuffer = true);
|
|
|
|
/// Initializes as a copy of the given instance.
|
|
FlatMessage(const FlatMessage & other);
|
|
|
|
/// Utilizes internal resources.
|
|
~FlatMessage();
|
|
|
|
/// Returns the content of the flat message.
|
|
const char * chars() const;
|
|
|
|
/// The size of the flat content.
|
|
size_t size() const;
|
|
|
|
/// Returns a string that represents the flat message.
|
|
std::string toString() const;
|
|
|
|
/// Looks for a field using the given tag number.
|
|
/// @return A valid reference in case of success, otherwise - an invalid one.
|
|
FlatFieldRef find(Tag) const;
|
|
|
|
/// Looks for a field with assumption the field is located
|
|
/// after the given field using its tag number.
|
|
///
|
|
/// The member is suitable to access same fields but from
|
|
/// different repeating group instances.
|
|
///
|
|
/// @return A valid reference in case of success, otherwise - an invalid one.
|
|
FlatFieldRef find(Tag, const FlatFieldRef &) const;
|
|
|
|
/// Allocates a key to the requested field for the further access.
|
|
FlatFieldKey allocateKey(const FlatFieldRef &);
|
|
|
|
/// Finds and allocates a key to the requested field for the further access.
|
|
FlatFieldKey allocateKey(Tag);
|
|
|
|
/// Provides an access to a field value by the given temporary reference.
|
|
StringRef operator[](const FlatFieldRef &) const;
|
|
|
|
/// Provides an access to a field value by the given field key.
|
|
StringRef operator[](FlatFieldKey) const;
|
|
|
|
/// Returns the reference to a repeating group - if exists.
|
|
///
|
|
/// @param numberOfInstancesRef The reference of
|
|
/// the field that defines the number of instances
|
|
/// in this repeating group (the NoXXX field).
|
|
///
|
|
/// @throw std::exception if the given field does not contain the number of instances.
|
|
FlatGroup getGroup(const FlatFieldRef & numberOfInstancesRef) const;
|
|
|
|
/// Converts the StringRef value of the given FlatMessage to the FlatFieldRef object.
|
|
FlatFieldRef getFlatFieldRef(const StringRef & value) const;
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to
|
|
/// access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, const StringRef &);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, const StringRef &);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, Char);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, Char);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, Int32);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, Int32);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, UInt32);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, UInt32);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, Int64);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, Int64);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, UInt64);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, UInt64);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, const Decimal &);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, const Decimal &);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, const Timestamp &, TimestampFormat::Enum);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, const Timestamp &, TimestampFormat::Enum);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, const TimeSpan &, TimeSpanFormat::Enum);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, const TimeSpan &, TimeSpanFormat::Enum);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldRef &, const FieldValueRef &);
|
|
|
|
/// Updates the field value.
|
|
///
|
|
/// @note Once the value is updated, only the reference used to access the field remains valid, other references become invalid.
|
|
FlatMessage & set(FlatFieldKey, const FieldValueRef &);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, const StringRef &);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, Char);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, Int32);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, UInt32);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, Int64);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, UInt64);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, const Decimal &);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, const Timestamp &, TimestampFormat::Enum);
|
|
|
|
/// Adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & add(Tag, const TimeSpan &, TimeSpanFormat::Enum);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, const StringRef &, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, Char, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, Int32, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, UInt32, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, Int64, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, UInt64, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, const Decimal &, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, const Timestamp &, TimestampFormat::Enum, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Inserts the tag/value pair to the message before or after the position field.
|
|
/// If the position tag is not found, it adds the tag/value pair to the end of the message.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & insert(Tag, const TimeSpan &, TimeSpanFormat::Enum, Tag, InsertMode::Enum = InsertMode::Before);
|
|
|
|
/// Removes the field value.
|
|
///
|
|
/// Once value is removed, all references
|
|
/// to other fields become invalid.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
FlatMessage & remove(Tag);
|
|
|
|
/// Updates BodyLength and CheckSum fields.
|
|
void adjust();
|
|
|
|
/// Resets the instance to the new tag=value form.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
void reset(const char * rawMessage, size_t rawMessageSize);
|
|
|
|
/// Resets the instance to the blank state.
|
|
///
|
|
/// @note This method does not support the zero-copy feature.
|
|
void reset();
|
|
|
|
// Returns the `ProtocolVersion`, which corresponds to `BeginString` and 'ApplVerID' tag values.
|
|
ProtocolVersion::Enum version() const;
|
|
|
|
/// A user data associated with the message.
|
|
///
|
|
/// @return A pointer to data was previously
|
|
/// attached to the instance or NULL.
|
|
void * userData() const;
|
|
|
|
/// Attaches a user data to the message.
|
|
void userData(void * data);
|
|
|
|
/// Re-initializes as a copy of the given instance.
|
|
FlatMessage & operator = (const FlatMessage &);
|
|
|
|
/// The constant iterator to iterate over all fields in the given FlatMessage instance.
|
|
class ONIXS_FIXENGINE_API ConstIterator
|
|
{
|
|
public:
|
|
|
|
typedef std::forward_iterator_tag iterator_category;
|
|
typedef FlatField value_type;
|
|
typedef FlatField difference_type;
|
|
typedef FlatField * pointer;
|
|
typedef FlatField & reference;
|
|
|
|
/// Initializes an iterator by a first field from which you need to iterate.
|
|
ConstIterator(const FlatMessage *, Tag);
|
|
|
|
const FlatField & operator*() const {
|
|
return currentField_;
|
|
}
|
|
|
|
const FlatField * operator->() const {
|
|
return ¤tField_;
|
|
}
|
|
|
|
bool operator == (const ConstIterator &) const;
|
|
bool operator != (const ConstIterator &) const;
|
|
|
|
ConstIterator & operator ++();
|
|
|
|
private:
|
|
/// The FlatMessage instance to iterate.
|
|
const FlatMessage * container_;
|
|
|
|
/// The current field.
|
|
FlatField currentField_;
|
|
};
|
|
|
|
/// Returns the constant iterator to the first field in the FlatMessage instance.
|
|
ConstIterator begin() const;
|
|
|
|
/// Returns the constant iterator to the field after the last one in the FlatMessage instance.
|
|
ConstIterator end() const;
|
|
|
|
private:
|
|
friend class MessageOperator;
|
|
friend class FlatMessageWrapper;
|
|
|
|
FlatMessage(const OnixS::FIX::Core::Messaging::Extras::FlatMessage & other);
|
|
|
|
OnixS::FIX::Core::Messaging::Extras::FlatMessage * impl_;
|
|
const bool isOwned_;
|
|
};
|
|
|
|
typedef FlatMessage SerializedMessage;
|
|
|
|
inline
|
|
FlatFieldRef
|
|
FlatMessage::find(Tag tag) const
|
|
{
|
|
return find(tag, FlatFieldRef());
|
|
}
|
|
|
|
/// The stream output.
|
|
ONIXS_FIXENGINE_API
|
|
std::ostream & operator << (std::ostream & os, const FlatMessage & message);
|
|
}
|
|
}
|