quickfix_ruby 1.14.3.1 → 1.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/quickfix/Acceptor.h +2 -0
- data/ext/quickfix/AtomicCount.h +82 -12
- data/ext/quickfix/DOMDocument.h +9 -7
- data/ext/quickfix/DataDictionary.cpp +77 -14
- data/ext/quickfix/DataDictionary.h +90 -16
- data/ext/quickfix/Dictionary.cpp +1 -2
- data/ext/quickfix/Exceptions.h +3 -5
- data/ext/quickfix/Field.h +83 -32
- data/ext/quickfix/FieldConvertors.cpp +93 -0
- data/ext/quickfix/FieldConvertors.h +129 -275
- data/ext/quickfix/FieldMap.cpp +53 -13
- data/ext/quickfix/FieldMap.h +200 -62
- data/ext/quickfix/FieldTypes.cpp +10 -10
- data/ext/quickfix/FieldTypes.h +293 -44
- data/ext/quickfix/FileLog.cpp +6 -10
- data/ext/quickfix/FileLog.h +4 -10
- data/ext/quickfix/FileStore.cpp +19 -6
- data/ext/quickfix/FileStore.h +4 -0
- data/ext/quickfix/FixFieldNumbers.h +1462 -1461
- data/ext/quickfix/FixFields.h +1462 -1461
- data/ext/quickfix/FixValues.h +3230 -3227
- data/ext/quickfix/HttpConnection.cpp +1 -1
- data/ext/quickfix/Initiator.cpp +7 -1
- data/ext/quickfix/Initiator.h +2 -0
- data/ext/quickfix/Log.h +6 -12
- data/ext/quickfix/Message.cpp +186 -57
- data/ext/quickfix/Message.h +109 -47
- data/ext/quickfix/MySQLConnection.h +1 -1
- data/ext/quickfix/PostgreSQLConnection.h +1 -1
- data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
- data/ext/quickfix/QuickfixRuby.h +1 -1
- data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
- data/ext/quickfix/SSLSocketAcceptor.h +185 -0
- data/ext/quickfix/SSLSocketConnection.cpp +427 -0
- data/ext/quickfix/SSLSocketConnection.h +206 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
- data/ext/quickfix/SSLSocketInitiator.h +196 -0
- data/ext/quickfix/Session.cpp +113 -20
- data/ext/quickfix/Session.h +18 -4
- data/ext/quickfix/SessionFactory.cpp +10 -3
- data/ext/quickfix/SessionSettings.cpp +5 -3
- data/ext/quickfix/SessionSettings.h +97 -5
- data/ext/quickfix/Settings.cpp +72 -2
- data/ext/quickfix/Settings.h +3 -0
- data/ext/quickfix/SharedArray.h +140 -6
- data/ext/quickfix/SocketConnection.cpp +2 -2
- data/ext/quickfix/SocketConnector.cpp +5 -2
- data/ext/quickfix/SocketConnector.h +3 -2
- data/ext/quickfix/SocketInitiator.cpp +28 -4
- data/ext/quickfix/SocketInitiator.h +1 -1
- data/ext/quickfix/SocketMonitor.cpp +5 -5
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
- data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
- data/ext/quickfix/ThreadedSocketConnection.h +4 -1
- data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
- data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
- data/ext/quickfix/Utility.cpp +23 -1
- data/ext/quickfix/Utility.h +28 -2
- data/ext/quickfix/UtilitySSL.cpp +1733 -0
- data/ext/quickfix/UtilitySSL.h +277 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +372 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/lib/quickfix44.rb +3329 -10
- data/lib/quickfix50.rb +6649 -81
- data/lib/quickfix50sp1.rb +8054 -142
- data/lib/quickfix50sp2.rb +10900 -234
- data/lib/quickfix_fields.rb +7662 -7649
- data/spec/FIX40.xml +28 -28
- data/spec/FIX41.xml +29 -29
- data/spec/FIX42.xml +47 -47
- data/spec/FIX43.xml +148 -148
- data/spec/FIX44.xml +1078 -1081
- data/spec/FIX50.xml +1292 -1289
- data/spec/FIX50SP1.xml +1811 -1802
- data/spec/FIX50SP2.xml +1948 -1939
- data/spec/FIXT11.xml +5 -8
- data/test/test_FieldBaseTestCase.rb +1 -1
- data/test/test_MessageTestCase.rb +2 -2
- metadata +42 -6
|
@@ -66,7 +66,7 @@ bool HttpConnection::read()
|
|
|
66
66
|
if( result > 0 ) // Something to read
|
|
67
67
|
{
|
|
68
68
|
// We can read without blocking
|
|
69
|
-
ssize_t size =
|
|
69
|
+
ssize_t size = socket_recv( m_socket, m_buffer, sizeof(m_buffer) );
|
|
70
70
|
if ( size <= 0 ) { throw SocketRecvFailed( size ); }
|
|
71
71
|
m_parser.addToStream( m_buffer, size );
|
|
72
72
|
}
|
data/ext/quickfix/Initiator.cpp
CHANGED
|
@@ -231,7 +231,13 @@ void Initiator::stop( bool force )
|
|
|
231
231
|
|
|
232
232
|
std::vector<Session*> enabledSessions;
|
|
233
233
|
|
|
234
|
-
SessionIDs connected
|
|
234
|
+
SessionIDs connected;
|
|
235
|
+
|
|
236
|
+
{
|
|
237
|
+
Locker l(m_mutex);
|
|
238
|
+
connected = m_connected;
|
|
239
|
+
}
|
|
240
|
+
|
|
235
241
|
SessionIDs::iterator i = connected.begin();
|
|
236
242
|
for ( ; i != connected.end(); ++i )
|
|
237
243
|
{
|
data/ext/quickfix/Initiator.h
CHANGED
data/ext/quickfix/Log.h
CHANGED
|
@@ -115,14 +115,14 @@ public:
|
|
|
115
115
|
class ScreenLog : public Log
|
|
116
116
|
{
|
|
117
117
|
public:
|
|
118
|
-
ScreenLog( bool incoming, bool outgoing, bool event )
|
|
118
|
+
ScreenLog( bool incoming, bool outgoing, bool event )
|
|
119
119
|
: m_prefix( "GLOBAL" ),
|
|
120
|
-
m_incoming( incoming ), m_outgoing( outgoing ), m_event( event )
|
|
120
|
+
m_incoming( incoming ), m_outgoing( outgoing ), m_event( event ) {}
|
|
121
121
|
|
|
122
122
|
ScreenLog( const SessionID& sessionID,
|
|
123
123
|
bool incoming, bool outgoing, bool event )
|
|
124
124
|
: m_prefix( sessionID.toString() ),
|
|
125
|
-
m_incoming( incoming ), m_outgoing( outgoing ), m_event( event )
|
|
125
|
+
m_incoming( incoming ), m_outgoing( outgoing ), m_event( event ) {}
|
|
126
126
|
|
|
127
127
|
void clear() {}
|
|
128
128
|
void backup() {}
|
|
@@ -132,7 +132,7 @@ public:
|
|
|
132
132
|
if ( !m_incoming ) return ;
|
|
133
133
|
Locker l( s_mutex );
|
|
134
134
|
m_time.setCurrent();
|
|
135
|
-
std::cout << "<" << UtcTimeStampConvertor::convert(m_time,
|
|
135
|
+
std::cout << "<" << UtcTimeStampConvertor::convert(m_time, 9)
|
|
136
136
|
<< ", " << m_prefix
|
|
137
137
|
<< ", " << "incoming>" << std::endl
|
|
138
138
|
<< " (" << value << ")" << std::endl;
|
|
@@ -143,7 +143,7 @@ public:
|
|
|
143
143
|
if ( !m_outgoing ) return ;
|
|
144
144
|
Locker l( s_mutex );
|
|
145
145
|
m_time.setCurrent();
|
|
146
|
-
std::cout << "<" << UtcTimeStampConvertor::convert(m_time,
|
|
146
|
+
std::cout << "<" << UtcTimeStampConvertor::convert(m_time, 9)
|
|
147
147
|
<< ", " << m_prefix
|
|
148
148
|
<< ", " << "outgoing>" << std::endl
|
|
149
149
|
<< " (" << value << ")" << std::endl;
|
|
@@ -154,17 +154,12 @@ public:
|
|
|
154
154
|
if ( !m_event ) return ;
|
|
155
155
|
Locker l( s_mutex );
|
|
156
156
|
m_time.setCurrent();
|
|
157
|
-
std::cout << "<" << UtcTimeStampConvertor::convert(m_time,
|
|
157
|
+
std::cout << "<" << UtcTimeStampConvertor::convert(m_time, 9)
|
|
158
158
|
<< ", " << m_prefix
|
|
159
159
|
<< ", " << "event>" << std::endl
|
|
160
160
|
<< " (" << value << ")" << std::endl;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
-
bool getMillisecondsInTimeStamp() const
|
|
164
|
-
{ return m_millisecondsInTimeStamp; }
|
|
165
|
-
void setMillisecondsInTimeStamp ( bool value )
|
|
166
|
-
{ m_millisecondsInTimeStamp = value; }
|
|
167
|
-
|
|
168
163
|
private:
|
|
169
164
|
std::string m_prefix;
|
|
170
165
|
UtcTimeStamp m_time;
|
|
@@ -172,7 +167,6 @@ private:
|
|
|
172
167
|
bool m_outgoing;
|
|
173
168
|
bool m_event;
|
|
174
169
|
static Mutex s_mutex;
|
|
175
|
-
bool m_millisecondsInTimeStamp;
|
|
176
170
|
};
|
|
177
171
|
}
|
|
178
172
|
|
data/ext/quickfix/Message.cpp
CHANGED
|
@@ -30,14 +30,31 @@
|
|
|
30
30
|
|
|
31
31
|
namespace FIX
|
|
32
32
|
{
|
|
33
|
-
|
|
33
|
+
|
|
34
|
+
int const headerOrder[] =
|
|
35
|
+
{
|
|
36
|
+
FIELD::BeginString,
|
|
37
|
+
FIELD::BodyLength,
|
|
38
|
+
FIELD::MsgType
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
SmartPtr<DataDictionary> Message::s_dataDictionary;
|
|
34
42
|
|
|
35
43
|
Message::Message()
|
|
36
|
-
: m_validStructure( true )
|
|
44
|
+
: m_validStructure( true )
|
|
45
|
+
, m_tag( 0 )
|
|
46
|
+
{
|
|
47
|
+
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
Message::Message(const message_order &hdrOrder, const message_order &trlOrder, const message_order& order)
|
|
51
|
+
: FieldMap(order), m_header(hdrOrder),
|
|
52
|
+
m_trailer(trlOrder), m_validStructure( true ) {}
|
|
37
53
|
|
|
38
54
|
Message::Message( const std::string& string, bool validate )
|
|
39
55
|
throw( InvalidMessage )
|
|
40
56
|
: m_validStructure( true )
|
|
57
|
+
, m_tag( 0 )
|
|
41
58
|
{
|
|
42
59
|
setString( string, validate );
|
|
43
60
|
}
|
|
@@ -47,6 +64,7 @@ Message::Message( const std::string& string,
|
|
|
47
64
|
bool validate )
|
|
48
65
|
throw( InvalidMessage )
|
|
49
66
|
: m_validStructure( true )
|
|
67
|
+
, m_tag( 0 )
|
|
50
68
|
{
|
|
51
69
|
setString( string, validate, &dataDictionary, &dataDictionary );
|
|
52
70
|
}
|
|
@@ -57,6 +75,34 @@ Message::Message( const std::string& string,
|
|
|
57
75
|
bool validate )
|
|
58
76
|
throw( InvalidMessage )
|
|
59
77
|
: m_validStructure( true )
|
|
78
|
+
, m_tag( 0 )
|
|
79
|
+
{
|
|
80
|
+
setString( string, validate, &sessionDataDictionary, &applicationDataDictionary );
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
Message::Message( const message_order &hdrOrder,
|
|
84
|
+
const message_order &trlOrder,
|
|
85
|
+
const message_order& order,
|
|
86
|
+
const std::string& string,
|
|
87
|
+
const DataDictionary& dataDictionary,
|
|
88
|
+
bool validate )
|
|
89
|
+
throw( InvalidMessage )
|
|
90
|
+
: FieldMap(order), m_header(hdrOrder),
|
|
91
|
+
m_trailer(trlOrder), m_validStructure( true )
|
|
92
|
+
{
|
|
93
|
+
setString( string, validate, &dataDictionary, &dataDictionary );
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
Message::Message( const message_order &hdrOrder,
|
|
97
|
+
const message_order &trlOrder,
|
|
98
|
+
const message_order& order,
|
|
99
|
+
const std::string& string,
|
|
100
|
+
const DataDictionary& sessionDataDictionary,
|
|
101
|
+
const DataDictionary& applicationDataDictionary,
|
|
102
|
+
bool validate )
|
|
103
|
+
throw( InvalidMessage )
|
|
104
|
+
: FieldMap(order), m_header(hdrOrder),
|
|
105
|
+
m_trailer(trlOrder), m_validStructure( true )
|
|
60
106
|
{
|
|
61
107
|
setStringHeader( string );
|
|
62
108
|
if( isAdmin() )
|
|
@@ -65,13 +111,36 @@ throw( InvalidMessage )
|
|
|
65
111
|
setString( string, validate, &sessionDataDictionary, &applicationDataDictionary );
|
|
66
112
|
}
|
|
67
113
|
|
|
114
|
+
Message::Message( const BeginString& beginString, const MsgType& msgType )
|
|
115
|
+
: m_validStructure(true)
|
|
116
|
+
, m_tag( 0 )
|
|
117
|
+
{
|
|
118
|
+
m_header.setField(beginString);
|
|
119
|
+
m_header.setField(msgType);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
Message::Message(const Message& copy)
|
|
123
|
+
: FieldMap(copy)
|
|
124
|
+
, m_header(copy.m_header)
|
|
125
|
+
, m_trailer(copy.m_trailer)
|
|
126
|
+
, m_validStructure(copy.m_validStructure)
|
|
127
|
+
, m_tag(copy.m_tag)
|
|
128
|
+
#ifdef HAVE_EMX
|
|
129
|
+
, m_subMsgType(copy.m_subMsgType)
|
|
130
|
+
#endif
|
|
131
|
+
{
|
|
132
|
+
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Message::~Message()
|
|
136
|
+
{
|
|
137
|
+
}
|
|
138
|
+
|
|
68
139
|
bool Message::InitializeXML( const std::string& url )
|
|
69
140
|
{
|
|
70
141
|
try
|
|
71
142
|
{
|
|
72
|
-
|
|
73
|
-
std::auto_ptr<DataDictionary>(new DataDictionary(url));
|
|
74
|
-
s_dataDictionary = p;
|
|
143
|
+
s_dataDictionary.reset(new DataDictionary(url));
|
|
75
144
|
return true;
|
|
76
145
|
}
|
|
77
146
|
catch( ConfigError& )
|
|
@@ -85,9 +154,9 @@ void Message::reverseRoute( const Header& header )
|
|
|
85
154
|
SenderCompID senderCompID;
|
|
86
155
|
TargetCompID targetCompID;
|
|
87
156
|
|
|
88
|
-
m_header.removeField( beginString.
|
|
89
|
-
m_header.removeField( senderCompID.
|
|
90
|
-
m_header.removeField( targetCompID.
|
|
157
|
+
m_header.removeField( beginString.getTag() );
|
|
158
|
+
m_header.removeField( senderCompID.getTag() );
|
|
159
|
+
m_header.removeField( targetCompID.getTag() );
|
|
91
160
|
|
|
92
161
|
if( header.getFieldIfSet( beginString ) )
|
|
93
162
|
{
|
|
@@ -97,8 +166,8 @@ void Message::reverseRoute( const Header& header )
|
|
|
97
166
|
OnBehalfOfLocationID onBehalfOfLocationID;
|
|
98
167
|
DeliverToLocationID deliverToLocationID;
|
|
99
168
|
|
|
100
|
-
m_header.removeField( onBehalfOfLocationID.
|
|
101
|
-
m_header.removeField( deliverToLocationID.
|
|
169
|
+
m_header.removeField( onBehalfOfLocationID.getTag() );
|
|
170
|
+
m_header.removeField( deliverToLocationID.getTag() );
|
|
102
171
|
|
|
103
172
|
if( beginString >= BeginString_FIX41 )
|
|
104
173
|
{
|
|
@@ -134,10 +203,10 @@ void Message::reverseRoute( const Header& header )
|
|
|
134
203
|
DeliverToCompID deliverToCompID;
|
|
135
204
|
DeliverToSubID deliverToSubID;
|
|
136
205
|
|
|
137
|
-
m_header.removeField( onBehalfOfCompID.
|
|
138
|
-
m_header.removeField( onBehalfOfSubID.
|
|
139
|
-
m_header.removeField( deliverToCompID.
|
|
140
|
-
m_header.removeField( deliverToSubID.
|
|
206
|
+
m_header.removeField( onBehalfOfCompID.getTag() );
|
|
207
|
+
m_header.removeField( onBehalfOfSubID.getTag() );
|
|
208
|
+
m_header.removeField( deliverToCompID.getTag() );
|
|
209
|
+
m_header.removeField( deliverToSubID.getTag() );
|
|
141
210
|
|
|
142
211
|
if( header.getFieldIfSet( onBehalfOfCompID ) )
|
|
143
212
|
{
|
|
@@ -169,7 +238,8 @@ std::string Message::toString( int beginStringField,
|
|
|
169
238
|
int checkSumField ) const
|
|
170
239
|
{
|
|
171
240
|
std::string str;
|
|
172
|
-
|
|
241
|
+
toString( str, beginStringField, bodyLengthField, checkSumField );
|
|
242
|
+
return str;
|
|
173
243
|
}
|
|
174
244
|
|
|
175
245
|
std::string& Message::toString( std::string& str,
|
|
@@ -200,7 +270,8 @@ std::string& Message::toString( std::string& str,
|
|
|
200
270
|
std::string Message::toXML() const
|
|
201
271
|
{
|
|
202
272
|
std::string str;
|
|
203
|
-
|
|
273
|
+
toXML( str );
|
|
274
|
+
return str;
|
|
204
275
|
}
|
|
205
276
|
|
|
206
277
|
std::string& Message::toXML( std::string& str ) const
|
|
@@ -224,12 +295,12 @@ std::string& Message::toXML( std::string& str ) const
|
|
|
224
295
|
std::string Message::toXMLFields(const FieldMap& fields, int space) const
|
|
225
296
|
{
|
|
226
297
|
std::stringstream stream;
|
|
227
|
-
FieldMap::
|
|
298
|
+
FieldMap::const_iterator i;
|
|
228
299
|
std::string name;
|
|
229
300
|
for(i = fields.begin(); i != fields.end(); ++i)
|
|
230
301
|
{
|
|
231
|
-
int field = i->
|
|
232
|
-
std::string value = i->
|
|
302
|
+
int field = i->getTag();
|
|
303
|
+
std::string value = i->getString();
|
|
233
304
|
|
|
234
305
|
stream << std::setw(space) << " " << "<field ";
|
|
235
306
|
if(s_dataDictionary.get() && s_dataDictionary->getFieldName(field, name))
|
|
@@ -247,7 +318,7 @@ std::string Message::toXMLFields(const FieldMap& fields, int space) const
|
|
|
247
318
|
stream << "</field>" << std::endl;
|
|
248
319
|
}
|
|
249
320
|
|
|
250
|
-
FieldMap::
|
|
321
|
+
FieldMap::g_const_iterator j;
|
|
251
322
|
for(j = fields.g_begin(); j != fields.g_end(); ++j)
|
|
252
323
|
{
|
|
253
324
|
std::vector<FieldMap*>::const_iterator k;
|
|
@@ -272,35 +343,50 @@ throw( InvalidMessage )
|
|
|
272
343
|
|
|
273
344
|
std::string::size_type pos = 0;
|
|
274
345
|
int count = 0;
|
|
275
|
-
std::string msg;
|
|
276
346
|
|
|
277
|
-
|
|
278
|
-
{
|
|
279
|
-
FIELD::BeginString,
|
|
280
|
-
FIELD::BodyLength,
|
|
281
|
-
FIELD::MsgType
|
|
282
|
-
};
|
|
347
|
+
FIX::MsgType msg;
|
|
283
348
|
|
|
284
349
|
field_type type = header;
|
|
285
350
|
|
|
286
351
|
while ( pos < string.size() )
|
|
287
352
|
{
|
|
288
353
|
FieldBase field = extractField( string, pos, pSessionDataDictionary, pApplicationDataDictionary );
|
|
289
|
-
if ( count < 3 && headerOrder[ count++ ] != field.
|
|
354
|
+
if ( count < 3 && headerOrder[ count++ ] != field.getTag() )
|
|
290
355
|
if ( doValidation ) throw InvalidMessage("Header fields out of order");
|
|
291
356
|
|
|
292
357
|
if ( isHeaderField( field, pSessionDataDictionary ) )
|
|
293
358
|
{
|
|
294
359
|
if ( type != header )
|
|
295
360
|
{
|
|
296
|
-
if(
|
|
361
|
+
if(m_tag == 0) m_tag = field.getTag();
|
|
297
362
|
m_validStructure = false;
|
|
298
363
|
}
|
|
299
364
|
|
|
300
|
-
if ( field.
|
|
301
|
-
|
|
365
|
+
if ( field.getTag() == FIELD::MsgType )
|
|
366
|
+
{
|
|
367
|
+
msg.setString( field.getString() );
|
|
368
|
+
if ( isAdminMsgType( msg ) )
|
|
369
|
+
{
|
|
370
|
+
pApplicationDataDictionary = pSessionDataDictionary;
|
|
371
|
+
#ifdef HAVE_EMX
|
|
372
|
+
m_subMsgType.assign(msg);
|
|
373
|
+
}
|
|
374
|
+
else
|
|
375
|
+
{
|
|
376
|
+
std::string::size_type equalSign = string.find("\0019426=", pos);
|
|
377
|
+
if (equalSign == std::string::npos)
|
|
378
|
+
throw InvalidMessage("EMX message type (9426) not found");
|
|
379
|
+
|
|
380
|
+
equalSign += 6;
|
|
381
|
+
std::string::size_type soh = string.find_first_of('\001', equalSign);
|
|
382
|
+
if (soh == std::string::npos)
|
|
383
|
+
throw InvalidMessage("EMX message type (9426) soh char not found");
|
|
384
|
+
m_subMsgType.assign(string.substr(equalSign, soh - equalSign ));
|
|
385
|
+
#endif
|
|
386
|
+
}
|
|
387
|
+
}
|
|
302
388
|
|
|
303
|
-
m_header.
|
|
389
|
+
m_header.appendField( field );
|
|
304
390
|
|
|
305
391
|
if ( pSessionDataDictionary )
|
|
306
392
|
setGroup( "_header_", field, string, pos, getHeader(), *pSessionDataDictionary );
|
|
@@ -308,7 +394,7 @@ throw( InvalidMessage )
|
|
|
308
394
|
else if ( isTrailerField( field, pSessionDataDictionary ) )
|
|
309
395
|
{
|
|
310
396
|
type = trailer;
|
|
311
|
-
m_trailer.
|
|
397
|
+
m_trailer.appendField( field );
|
|
312
398
|
|
|
313
399
|
if ( pSessionDataDictionary )
|
|
314
400
|
setGroup( "_trailer_", field, string, pos, getTrailer(), *pSessionDataDictionary );
|
|
@@ -317,18 +403,27 @@ throw( InvalidMessage )
|
|
|
317
403
|
{
|
|
318
404
|
if ( type == trailer )
|
|
319
405
|
{
|
|
320
|
-
if(
|
|
406
|
+
if(m_tag == 0) m_tag = field.getTag();
|
|
321
407
|
m_validStructure = false;
|
|
322
408
|
}
|
|
323
409
|
|
|
324
410
|
type = body;
|
|
325
|
-
|
|
411
|
+
appendField( field );
|
|
326
412
|
|
|
327
413
|
if ( pApplicationDataDictionary )
|
|
414
|
+
#ifdef HAVE_EMX
|
|
415
|
+
setGroup(m_subMsgType, field, string, pos, *this, *pApplicationDataDictionary);
|
|
416
|
+
#else
|
|
328
417
|
setGroup( msg, field, string, pos, *this, *pApplicationDataDictionary );
|
|
418
|
+
#endif
|
|
329
419
|
}
|
|
330
420
|
}
|
|
331
421
|
|
|
422
|
+
// sort fields
|
|
423
|
+
m_header.sortFields();
|
|
424
|
+
sortFields();
|
|
425
|
+
m_trailer.sortFields();
|
|
426
|
+
|
|
332
427
|
if ( doValidation )
|
|
333
428
|
validate();
|
|
334
429
|
}
|
|
@@ -338,11 +433,11 @@ void Message::setGroup( const std::string& msg, const FieldBase& field,
|
|
|
338
433
|
std::string::size_type& pos, FieldMap& map,
|
|
339
434
|
const DataDictionary& dataDictionary )
|
|
340
435
|
{
|
|
341
|
-
int group = field.
|
|
436
|
+
int group = field.getTag();
|
|
342
437
|
int delim;
|
|
343
438
|
const DataDictionary* pDD = 0;
|
|
344
439
|
if ( !dataDictionary.getGroup( msg, group, delim, pDD ) ) return ;
|
|
345
|
-
|
|
440
|
+
SmartPtr<Group> pGroup;
|
|
346
441
|
|
|
347
442
|
while ( pos < string.size() )
|
|
348
443
|
{
|
|
@@ -351,17 +446,17 @@ void Message::setGroup( const std::string& msg, const FieldBase& field,
|
|
|
351
446
|
|
|
352
447
|
// Start a new group because...
|
|
353
448
|
if (// found delimiter
|
|
354
|
-
(field.
|
|
449
|
+
(field.getTag() == delim) ||
|
|
355
450
|
// no delimiter, but field belongs to group OR field already processed
|
|
356
|
-
(pDD->isField( field.
|
|
451
|
+
(pDD->isField( field.getTag() ) && (pGroup.get() == 0 || pGroup->isSetField( field.getTag() )) ))
|
|
357
452
|
{
|
|
358
453
|
if ( pGroup.get() )
|
|
359
454
|
{
|
|
360
455
|
map.addGroupPtr( group, pGroup.release(), false );
|
|
361
456
|
}
|
|
362
|
-
pGroup.reset( new Group( field.
|
|
457
|
+
pGroup.reset( new Group( field.getTag(), delim, pDD->getOrderedFields() ) );
|
|
363
458
|
}
|
|
364
|
-
else if ( !pDD->isField( field.
|
|
459
|
+
else if ( !pDD->isField( field.getTag() ) )
|
|
365
460
|
{
|
|
366
461
|
if ( pGroup.get() )
|
|
367
462
|
{
|
|
@@ -372,7 +467,7 @@ void Message::setGroup( const std::string& msg, const FieldBase& field,
|
|
|
372
467
|
}
|
|
373
468
|
|
|
374
469
|
if ( !pGroup.get() ) return ;
|
|
375
|
-
pGroup->
|
|
470
|
+
pGroup->addField( field );
|
|
376
471
|
setGroup( msg, field, string, pos, *pGroup, *pDD );
|
|
377
472
|
}
|
|
378
473
|
}
|
|
@@ -387,13 +482,15 @@ bool Message::setStringHeader( const std::string& string )
|
|
|
387
482
|
while ( pos < string.size() )
|
|
388
483
|
{
|
|
389
484
|
FieldBase field = extractField( string, pos );
|
|
390
|
-
if ( count < 3 && headerOrder[ count++ ] != field.
|
|
485
|
+
if ( count < 3 && headerOrder[ count++ ] != field.getTag() )
|
|
391
486
|
return false;
|
|
392
487
|
|
|
393
488
|
if ( isHeaderField( field ) )
|
|
394
|
-
m_header.
|
|
489
|
+
m_header.appendField( field );
|
|
395
490
|
else break;
|
|
396
491
|
}
|
|
492
|
+
|
|
493
|
+
m_header.sortFields();
|
|
397
494
|
return true;
|
|
398
495
|
}
|
|
399
496
|
|
|
@@ -439,8 +536,14 @@ bool Message::isHeaderField( int field )
|
|
|
439
536
|
bool Message::isHeaderField( const FieldBase& field,
|
|
440
537
|
const DataDictionary* pD )
|
|
441
538
|
{
|
|
442
|
-
|
|
443
|
-
|
|
539
|
+
return isHeaderField( field.getTag(), pD );
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
bool Message::isHeaderField( int field,
|
|
543
|
+
const DataDictionary * pD )
|
|
544
|
+
{
|
|
545
|
+
if ( isHeaderField( field ) ) return true;
|
|
546
|
+
if ( pD ) return pD->isHeaderField( field );
|
|
444
547
|
return false;
|
|
445
548
|
}
|
|
446
549
|
|
|
@@ -460,8 +563,13 @@ bool Message::isTrailerField( int field )
|
|
|
460
563
|
bool Message::isTrailerField( const FieldBase& field,
|
|
461
564
|
const DataDictionary* pD )
|
|
462
565
|
{
|
|
463
|
-
|
|
464
|
-
|
|
566
|
+
return isTrailerField( field.getTag(), pD );
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
bool Message::isTrailerField( int field, const DataDictionary * pD )
|
|
570
|
+
{
|
|
571
|
+
if ( isTrailerField( field ) ) return true;
|
|
572
|
+
if ( pD ) return pD->isTrailerField( field );
|
|
465
573
|
return false;
|
|
466
574
|
}
|
|
467
575
|
|
|
@@ -486,7 +594,7 @@ void Message::setSessionID( const SessionID& sessionID )
|
|
|
486
594
|
getHeader().setField( sessionID.getTargetCompID() );
|
|
487
595
|
}
|
|
488
596
|
|
|
489
|
-
void Message::validate()
|
|
597
|
+
void Message::validate() const
|
|
490
598
|
{
|
|
491
599
|
try
|
|
492
600
|
{
|
|
@@ -530,7 +638,7 @@ void Message::validate()
|
|
|
530
638
|
|
|
531
639
|
FIX::FieldBase Message::extractField( const std::string& string, std::string::size_type& pos,
|
|
532
640
|
const DataDictionary* pSessionDD /*= 0*/, const DataDictionary* pAppDD /*= 0*/,
|
|
533
|
-
const Group* pGroup /*= 0*/ )
|
|
641
|
+
const Group* pGroup /*= 0*/ ) const
|
|
534
642
|
{
|
|
535
643
|
std::string::const_iterator const tagStart = string.begin() + pos;
|
|
536
644
|
std::string::const_iterator const strEnd = string.end();
|
|
@@ -540,7 +648,8 @@ FIX::FieldBase Message::extractField( const std::string& string, std::string::si
|
|
|
540
648
|
throw InvalidMessage("Equal sign not found in field");
|
|
541
649
|
|
|
542
650
|
int field = 0;
|
|
543
|
-
IntConvertor::convert( tagStart, equalSign, field )
|
|
651
|
+
if( !IntConvertor::convert( tagStart, equalSign, field ) )
|
|
652
|
+
throw InvalidMessage( std::string("Field tag is invalid: ") + std::string( tagStart, equalSign ));
|
|
544
653
|
|
|
545
654
|
std::string::const_iterator const valueStart = equalSign + 1;
|
|
546
655
|
|
|
@@ -555,20 +664,39 @@ FIX::FieldBase Message::extractField( const std::string& string, std::string::si
|
|
|
555
664
|
// Special case for Signature which violates above assumption.
|
|
556
665
|
if ( field == FIELD::Signature ) lenField = FIELD::SignatureLength;
|
|
557
666
|
|
|
558
|
-
|
|
667
|
+
// identify part of the message that should contain length field
|
|
668
|
+
const FieldMap * location = pGroup;
|
|
669
|
+
if ( !location )
|
|
670
|
+
{
|
|
671
|
+
if ( isHeaderField( lenField, pSessionDD ) )
|
|
672
|
+
location = &m_header;
|
|
673
|
+
else if ( isTrailerField( lenField, pSessionDD ) )
|
|
674
|
+
location = &m_trailer;
|
|
675
|
+
else
|
|
676
|
+
location = this;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
try
|
|
680
|
+
{
|
|
681
|
+
const FieldBase& fieldLength = location->reverse_find( lenField );
|
|
682
|
+
soh = valueStart + IntConvertor::convert( fieldLength.getString() );
|
|
683
|
+
}
|
|
684
|
+
catch( FieldNotFound& )
|
|
559
685
|
{
|
|
560
|
-
|
|
561
|
-
soh = valueStart + atol( fieldLength.c_str() );
|
|
686
|
+
throw InvalidMessage( std::string( "Data length field " ) + IntConvertor::convert( lenField ) + std::string( " was not found for data field " ) + IntConvertor::convert( field ) );
|
|
562
687
|
}
|
|
563
|
-
|
|
688
|
+
catch( FieldConvertError& e )
|
|
564
689
|
{
|
|
565
|
-
|
|
566
|
-
soh = valueStart + atol( fieldLength.c_str() );
|
|
690
|
+
throw InvalidMessage( std::string( "Unable to determine SOH for data field " ) + IntConvertor::convert( field ) + std::string( ": " ) + e.what() );
|
|
567
691
|
}
|
|
568
692
|
}
|
|
569
693
|
|
|
570
694
|
std::string::const_iterator const tagEnd = soh + 1;
|
|
695
|
+
#if defined(__SUNPRO_CC)
|
|
696
|
+
std::distance( string.begin(), tagEnd, pos );
|
|
697
|
+
#else
|
|
571
698
|
pos = std::distance( string.begin(), tagEnd );
|
|
699
|
+
#endif
|
|
572
700
|
|
|
573
701
|
return FieldBase (
|
|
574
702
|
field,
|
|
@@ -577,4 +705,5 @@ FIX::FieldBase Message::extractField( const std::string& string, std::string::si
|
|
|
577
705
|
tagStart,
|
|
578
706
|
tagEnd );
|
|
579
707
|
}
|
|
708
|
+
|
|
580
709
|
}
|