Skip to content

Commit

Permalink
Added BAD_ENUM, improved MessageBuilders API
Browse files Browse the repository at this point in the history
Fixed TimestampKeeper in ReusableMessageBuilder::resizeIfNecessary()
  • Loading branch information
sashamakarenko committed Oct 19, 2024
1 parent c676dd7 commit c1050b0
Show file tree
Hide file tree
Showing 24 changed files with 2,843 additions and 1,289 deletions.
246 changes: 245 additions & 1 deletion examples/fix44/src/fix44/Fields.cpp

Large diffs are not rendered by default.

490 changes: 490 additions & 0 deletions examples/fix44/src/fix44/Fields.h

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions examples/fix44/src/fix44/FixApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ inline std::string toString( const FieldEnum< VT > & item )
return toString( item.value );
}

template<typename T>
struct BadEnum{ static constexpr T value = std::numeric_limits<T>::max(); };

template<>
struct BadEnum<sohstr>{ static constexpr sohstr value{nullptr}; };

using FieldEnumMap = std::map< raw_enum_t, const FieldEnumBase * >;

// Base structure for all field enums.
Expand Down
20 changes: 13 additions & 7 deletions examples/fix44/src/fix44/FixTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,12 +679,15 @@ inline std::string toString( const V & value )
template<>
inline std::string toString<sohstr>( const sohstr & value )
{
offset_t pos = 0;
gotoNextField( value.ptr, pos );
return std::string( value.ptr, (std::size_t)pos-1 );
if( value.ptr )
{
offset_t pos = 0;
gotoNextField( value.ptr, pos );
return std::string( value.ptr, (std::size_t)pos-1 );
}
return {};
}


template<>
inline std::string toString<char>( const char & value )
{
Expand Down Expand Up @@ -725,10 +728,13 @@ inline raw_enum_t toRawEnum( int i )
inline raw_enum_t toRawEnum( const char * str )
{
raw_enum_t value{0};
char * to = reinterpret_cast<char *>( &value );
for( unsigned len = 0; str[len] != FIXPP_SOH && len < sizeof( value ); ++len )
if( str )
{
to[ len ] = str[ len ];
char * to = reinterpret_cast<char *>( &value );
for( unsigned len = 0; str[len] != FIXPP_SOH && len < sizeof( value ); ++len )
{
to[ len ] = str[ len ];
}
}
return value;
}
Expand Down
2,842 changes: 1,670 additions & 1,172 deletions examples/fix44/src/fix44/MessageBuilders.h

Large diffs are not rendered by default.

60 changes: 50 additions & 10 deletions examples/fix44/src/fix44/SenderApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,15 +410,25 @@ struct TimestampKeeper
{
}

void reset()
{
startOfDay = 0;
endOfDay = 0;
begin = nullptr;
lastSecond = 0;
lastFraction = 0;
secFraction = Precision::SECONDS;
}

unsigned fill( char * buffer, Precision secPrecision, const TimePoint & tp = ClockType::now() )
{
if( begin != buffer or secFraction != secPrecision )
{
begin = buffer;
secFraction = secPrecision;
startOfDay = 0;
endOfDay = 0;
lastSecond = 0;
begin = buffer;
secFraction = secPrecision;
startOfDay = 0;
endOfDay = 0;
lastSecond = 0;
lastFraction = 0;
}
if( buffer )
Expand Down Expand Up @@ -579,7 +589,7 @@ struct ReusableMessageBuilder: FixBufferStream
ReusableMessageBuilder( const std::string & messageType, unsigned maxBodyLength, unsigned headerTemplateCapacity = 128 )
: FixBufferStream ( nullptr )
, msgType ( messageType )
, buffer ( maxBodyLength + 1, (char)0 )
, buffer ( headerTemplateCapacity + maxBodyLength + 1, (char)0 )
, start ( nullptr )
, lastSeqnumWidth ( 0 )
, minSeqnumWidth ( 1 )
Expand All @@ -589,6 +599,10 @@ struct ReusableMessageBuilder: FixBufferStream
, header ( headerTemplateCapacity, messageType )
{
begin = end = &buffer[0] + headerTemplateCapacity;
for( unsigned i = 0; i < NO_TIMES; ++i )
{
userTime[i].reset();
}
}

ReusableMessageBuilder( const ReusableMessageBuilder & ) = delete;
Expand Down Expand Up @@ -651,9 +665,24 @@ struct ReusableMessageBuilder: FixBufferStream
if( endOffset + (ssize_t)valueLength >= (ssize_t)buffer.size() )
{
auto beginOffset = begin - &buffer[0];
ssize_t userTimeOffset[NO_TIMES] = {};
for( unsigned i = 0; i < NO_TIMES; ++i )
{
if( userTime[i].begin )
{
userTimeOffset[i] = userTime[i].begin - &buffer[0];
}
}
buffer.resize( ( 1 + ( endOffset + valueLength ) / bufferGrowChunk ) * bufferGrowChunk );
begin = &buffer[0] + beginOffset;
end = &buffer[0] + endOffset;
for( unsigned i = 0; i < 5; ++i )
{
if( userTime[i].begin )
{
userTime[i].begin = &buffer[0] + userTimeOffset[i];
}
}
}
}

Expand Down Expand Up @@ -684,6 +713,14 @@ struct ReusableMessageBuilder: FixBufferStream
return pushValue( v, precision );
}

template< typename FIELD >
FixBufferStream & appendSafely( TimestampKeeper & v, const TimePoint & tp = ClockType::now() )
{
resizeIfNecessary( TimestampKeeper::DATE_TIME_NANOS_LENGTH );
end = insert<FIELD>(end);
return pushValue( v, tp );
}

template< typename FIELD >
FixBufferStream & appendSafely( const FieldEnum< typename FIELD::ValueType > & item )
{
Expand All @@ -700,11 +737,14 @@ struct ReusableMessageBuilder: FixBufferStream
unsigned minBodyLengthWidth;
unsigned bufferGrowChunk;
HeaderTemplate header;

static constexpr unsigned NO_TIMES = 5;
union
{
TimestampKeeper sendingTime;
TimestampKeeper userTime1; // user defined timestamps
TimestampKeeper userTime2;
TimestampKeeper userTime3;
TimestampKeeper userTime4;
TimestampKeeper userTime[NO_TIMES];
};

};

}
Expand Down
9 changes: 9 additions & 0 deletions examples/order/src/order/Fields.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -215,10 +215,12 @@ const char * const FixNoNestedPartySubIDs = "NoNestedPartySubIDs";
const char * const FixNestedPartySubIDType = "NestedPartySubIDType";


const QtyTypeEnums::ItemType QtyTypeEnums::BAD_ENUM( "BAD_ENUM", QtyTypeEnums::ITEM_BAD_ENUM );
const QtyTypeEnums::ItemType QtyTypeEnums::UNITS( "UNITS", 0 );
const QtyTypeEnums::ItemType QtyTypeEnums::CONTRACTS( "CONTRACTS", 1 );


const ProductEnums::ItemType ProductEnums::BAD_ENUM( "BAD_ENUM", ProductEnums::ITEM_BAD_ENUM );
const ProductEnums::ItemType ProductEnums::AGENCY( "AGENCY", 1 );
const ProductEnums::ItemType ProductEnums::COMMODITY( "COMMODITY", 2 );
const ProductEnums::ItemType ProductEnums::CORPORATE( "CORPORATE", 3 );
Expand All @@ -234,10 +236,12 @@ const ProductEnums::ItemType ProductEnums::OTHER( "OTHER", 12 );
const ProductEnums::ItemType ProductEnums::FINANCING( "FINANCING", 13 );


const MsgTypeEnums::ItemType MsgTypeEnums::BAD_ENUM( "BAD_ENUM", MsgTypeEnums::ITEM_BAD_ENUM );
const MsgTypeEnums::ItemType MsgTypeEnums::EXECUTION_REPORT( "EXECUTION_REPORT", SOHSTR(8) );
const MsgTypeEnums::ItemType MsgTypeEnums::NEW_ORDER_SINGLE( "NEW_ORDER_SINGLE", SOHSTR(D) );


const OrdStatusEnums::ItemType OrdStatusEnums::BAD_ENUM( "BAD_ENUM", OrdStatusEnums::ITEM_BAD_ENUM );
const OrdStatusEnums::ItemType OrdStatusEnums::NEW( "NEW", '0' );
const OrdStatusEnums::ItemType OrdStatusEnums::PARTIALLY_FILLED( "PARTIALLY_FILLED", '1' );
const OrdStatusEnums::ItemType OrdStatusEnums::FILLED( "FILLED", '2' );
Expand All @@ -254,6 +258,7 @@ const OrdStatusEnums::ItemType OrdStatusEnums::ACCEPTED_FOR_BIDDING( "ACCEPTED_F
const OrdStatusEnums::ItemType OrdStatusEnums::PENDING_REPLACE( "PENDING_REPLACE", 'E' );


const OrdTypeEnums::ItemType OrdTypeEnums::BAD_ENUM( "BAD_ENUM", OrdTypeEnums::ITEM_BAD_ENUM );
const OrdTypeEnums::ItemType OrdTypeEnums::MARKET( "MARKET", '1' );
const OrdTypeEnums::ItemType OrdTypeEnums::LIMIT( "LIMIT", '2' );
const OrdTypeEnums::ItemType OrdTypeEnums::STOP( "STOP", '3' );
Expand All @@ -273,10 +278,12 @@ const OrdTypeEnums::ItemType OrdTypeEnums::NEXT_FUND_VALUATION_POINT( "NEXT_FUND
const OrdTypeEnums::ItemType OrdTypeEnums::PEGGED( "PEGGED", 'P' );


const SideEnums::ItemType SideEnums::BAD_ENUM( "BAD_ENUM", SideEnums::ITEM_BAD_ENUM );
const SideEnums::ItemType SideEnums::BUY( "BUY", '1' );
const SideEnums::ItemType SideEnums::SELL( "SELL", '2' );


const TimeInForceEnums::ItemType TimeInForceEnums::BAD_ENUM( "BAD_ENUM", TimeInForceEnums::ITEM_BAD_ENUM );
const TimeInForceEnums::ItemType TimeInForceEnums::DAY( "DAY", '0' );
const TimeInForceEnums::ItemType TimeInForceEnums::GOOD_TILL_CANCEL( "GOOD_TILL_CANCEL", '1' );
const TimeInForceEnums::ItemType TimeInForceEnums::AT_THE_OPENING( "AT_THE_OPENING", '2' );
Expand All @@ -287,6 +294,7 @@ const TimeInForceEnums::ItemType TimeInForceEnums::GOOD_TILL_DATE( "GOOD_TILL_DA
const TimeInForceEnums::ItemType TimeInForceEnums::AT_THE_CLOSE( "AT_THE_CLOSE", '7' );


const PriceTypeEnums::ItemType PriceTypeEnums::BAD_ENUM( "BAD_ENUM", PriceTypeEnums::ITEM_BAD_ENUM );
const PriceTypeEnums::ItemType PriceTypeEnums::PERCENTAGE( "PERCENTAGE", 1 );
const PriceTypeEnums::ItemType PriceTypeEnums::PER_UNIT( "PER_UNIT", 2 );
const PriceTypeEnums::ItemType PriceTypeEnums::FIXED_AMOUNT( "FIXED_AMOUNT", 3 );
Expand All @@ -300,6 +308,7 @@ const PriceTypeEnums::ItemType PriceTypeEnums::FIXED_CABINET_TRADE_PRICE( "FIXED
const PriceTypeEnums::ItemType PriceTypeEnums::VARIABLE_CABINET_TRADE_PRICE( "VARIABLE_CABINET_TRADE_PRICE", 11 );


const SecurityTypeEnums::ItemType SecurityTypeEnums::BAD_ENUM( "BAD_ENUM", SecurityTypeEnums::ITEM_BAD_ENUM );
const SecurityTypeEnums::ItemType SecurityTypeEnums::FUTURE( "FUTURE", SOHSTR(FUT) );
const SecurityTypeEnums::ItemType SecurityTypeEnums::OPTION( "OPTION", SOHSTR(OPT) );
const SecurityTypeEnums::ItemType SecurityTypeEnums::EURO_SUPRANATIONAL_COUPONS( "EURO_SUPRANATIONAL_COUPONS", SOHSTR(EUSUPRA) );
Expand Down
18 changes: 18 additions & 0 deletions examples/order/src/order/Fields.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ struct QtyTypeEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_UNITS = 0;
static const ItemType CONTRACTS;
static constexpr ValueType ITEM_CONTRACTS = 1;
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct ProductEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -227,6 +229,8 @@ struct ProductEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_OTHER = 12;
static const ItemType FINANCING;
static constexpr ValueType ITEM_FINANCING = 13;
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct MsgTypeEnums final: FieldEnumsBase {
Expand All @@ -245,6 +249,8 @@ struct MsgTypeEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_EXECUTION_REPORT = SOHSTR(8);
static const ItemType NEW_ORDER_SINGLE;
static constexpr ValueType ITEM_NEW_ORDER_SINGLE = SOHSTR(D);
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct OrdStatusEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -287,6 +293,8 @@ struct OrdStatusEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_ACCEPTED_FOR_BIDDING = 'D';
static const ItemType PENDING_REPLACE;
static constexpr ValueType ITEM_PENDING_REPLACE = 'E';
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct OrdTypeEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -335,6 +343,8 @@ struct OrdTypeEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_NEXT_FUND_VALUATION_POINT = 'M';
static const ItemType PEGGED;
static constexpr ValueType ITEM_PEGGED = 'P';
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};


Expand All @@ -354,6 +364,8 @@ struct SideEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_BUY = '1';
static const ItemType SELL;
static constexpr ValueType ITEM_SELL = '2';
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct TimeInForceEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -384,6 +396,8 @@ struct TimeInForceEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_GOOD_TILL_DATE = '6';
static const ItemType AT_THE_CLOSE;
static constexpr ValueType ITEM_AT_THE_CLOSE = '7';
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct PriceTypeEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -420,6 +434,8 @@ struct PriceTypeEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_FIXED_CABINET_TRADE_PRICE = 10;
static const ItemType VARIABLE_CABINET_TRADE_PRICE;
static constexpr ValueType ITEM_VARIABLE_CABINET_TRADE_PRICE = 11;
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};

struct SecurityTypeEnums final: FieldEnumsBase {
Expand Down Expand Up @@ -624,6 +640,8 @@ struct SecurityTypeEnums final: FieldEnumsBase {
static constexpr ValueType ITEM_MULTI_LEG_INSTRUMENT = SOHSTR(MLEG);
static const ItemType NO_SECURITY_TYPE;
static constexpr ValueType ITEM_NO_SECURITY_TYPE = SOHSTR(NONE);
static const ItemType BAD_ENUM;
static constexpr ValueType ITEM_BAD_ENUM = BadEnum<ValueType>::value;
};


Expand Down
6 changes: 6 additions & 0 deletions examples/order/src/order/FixApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,12 @@ inline std::string toString( const FieldEnum< VT > & item )
return toString( item.value );
}

template<typename T>
struct BadEnum{ static constexpr T value = std::numeric_limits<T>::max(); };

template<>
struct BadEnum<sohstr>{ static constexpr sohstr value{nullptr}; };

using FieldEnumMap = std::map< raw_enum_t, const FieldEnumBase * >;

// Base structure for all field enums.
Expand Down
20 changes: 13 additions & 7 deletions examples/order/src/order/FixTypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -679,12 +679,15 @@ inline std::string toString( const V & value )
template<>
inline std::string toString<sohstr>( const sohstr & value )
{
offset_t pos = 0;
gotoNextField( value.ptr, pos );
return std::string( value.ptr, (std::size_t)pos-1 );
if( value.ptr )
{
offset_t pos = 0;
gotoNextField( value.ptr, pos );
return std::string( value.ptr, (std::size_t)pos-1 );
}
return {};
}


template<>
inline std::string toString<char>( const char & value )
{
Expand Down Expand Up @@ -725,10 +728,13 @@ inline raw_enum_t toRawEnum( int i )
inline raw_enum_t toRawEnum( const char * str )
{
raw_enum_t value{0};
char * to = reinterpret_cast<char *>( &value );
for( unsigned len = 0; str[len] != FIXPP_SOH && len < sizeof( value ); ++len )
if( str )
{
to[ len ] = str[ len ];
char * to = reinterpret_cast<char *>( &value );
for( unsigned len = 0; str[len] != FIXPP_SOH && len < sizeof( value ); ++len )
{
to[ len ] = str[ len ];
}
}
return value;
}
Expand Down
Loading

0 comments on commit c1050b0

Please sign in to comment.