Files
2024-09-23 12:00:04 -04:00

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 &currentField_;
}
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);
}
}