quickfix_ruby 1.14.3.1 → 1.15.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|