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.
Files changed (105) hide show
  1. checksums.yaml +4 -4
  2. data/ext/quickfix/Acceptor.h +2 -0
  3. data/ext/quickfix/AtomicCount.h +82 -12
  4. data/ext/quickfix/DOMDocument.h +9 -7
  5. data/ext/quickfix/DataDictionary.cpp +77 -14
  6. data/ext/quickfix/DataDictionary.h +90 -16
  7. data/ext/quickfix/Dictionary.cpp +1 -2
  8. data/ext/quickfix/Exceptions.h +3 -5
  9. data/ext/quickfix/Field.h +83 -32
  10. data/ext/quickfix/FieldConvertors.cpp +93 -0
  11. data/ext/quickfix/FieldConvertors.h +129 -275
  12. data/ext/quickfix/FieldMap.cpp +53 -13
  13. data/ext/quickfix/FieldMap.h +200 -62
  14. data/ext/quickfix/FieldTypes.cpp +10 -10
  15. data/ext/quickfix/FieldTypes.h +293 -44
  16. data/ext/quickfix/FileLog.cpp +6 -10
  17. data/ext/quickfix/FileLog.h +4 -10
  18. data/ext/quickfix/FileStore.cpp +19 -6
  19. data/ext/quickfix/FileStore.h +4 -0
  20. data/ext/quickfix/FixFieldNumbers.h +1462 -1461
  21. data/ext/quickfix/FixFields.h +1462 -1461
  22. data/ext/quickfix/FixValues.h +3230 -3227
  23. data/ext/quickfix/HttpConnection.cpp +1 -1
  24. data/ext/quickfix/Initiator.cpp +7 -1
  25. data/ext/quickfix/Initiator.h +2 -0
  26. data/ext/quickfix/Log.h +6 -12
  27. data/ext/quickfix/Message.cpp +186 -57
  28. data/ext/quickfix/Message.h +109 -47
  29. data/ext/quickfix/MySQLConnection.h +1 -1
  30. data/ext/quickfix/PostgreSQLConnection.h +1 -1
  31. data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
  32. data/ext/quickfix/QuickfixRuby.h +1 -1
  33. data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
  34. data/ext/quickfix/SSLSocketAcceptor.h +185 -0
  35. data/ext/quickfix/SSLSocketConnection.cpp +427 -0
  36. data/ext/quickfix/SSLSocketConnection.h +206 -0
  37. data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
  38. data/ext/quickfix/SSLSocketInitiator.h +196 -0
  39. data/ext/quickfix/Session.cpp +113 -20
  40. data/ext/quickfix/Session.h +18 -4
  41. data/ext/quickfix/SessionFactory.cpp +10 -3
  42. data/ext/quickfix/SessionSettings.cpp +5 -3
  43. data/ext/quickfix/SessionSettings.h +97 -5
  44. data/ext/quickfix/Settings.cpp +72 -2
  45. data/ext/quickfix/Settings.h +3 -0
  46. data/ext/quickfix/SharedArray.h +140 -6
  47. data/ext/quickfix/SocketConnection.cpp +2 -2
  48. data/ext/quickfix/SocketConnector.cpp +5 -2
  49. data/ext/quickfix/SocketConnector.h +3 -2
  50. data/ext/quickfix/SocketInitiator.cpp +28 -4
  51. data/ext/quickfix/SocketInitiator.h +1 -1
  52. data/ext/quickfix/SocketMonitor.cpp +5 -5
  53. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
  54. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
  55. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
  56. data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
  57. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
  58. data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
  59. data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
  60. data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
  61. data/ext/quickfix/ThreadedSocketConnection.h +4 -1
  62. data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
  63. data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
  64. data/ext/quickfix/Utility.cpp +23 -1
  65. data/ext/quickfix/Utility.h +28 -2
  66. data/ext/quickfix/UtilitySSL.cpp +1733 -0
  67. data/ext/quickfix/UtilitySSL.h +277 -0
  68. data/ext/quickfix/config-all.h +10 -0
  69. data/ext/quickfix/dirent_windows.h +838 -0
  70. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  71. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  72. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  73. data/ext/quickfix/double-conversion/bignum.h +144 -0
  74. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  75. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  76. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  77. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  78. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  79. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  80. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  81. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  82. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  83. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  84. data/ext/quickfix/double-conversion/ieee.h +402 -0
  85. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  86. data/ext/quickfix/double-conversion/strtod.h +45 -0
  87. data/ext/quickfix/double-conversion/utils.h +372 -0
  88. data/ext/quickfix/stdint_msvc.h +254 -0
  89. data/lib/quickfix44.rb +3329 -10
  90. data/lib/quickfix50.rb +6649 -81
  91. data/lib/quickfix50sp1.rb +8054 -142
  92. data/lib/quickfix50sp2.rb +10900 -234
  93. data/lib/quickfix_fields.rb +7662 -7649
  94. data/spec/FIX40.xml +28 -28
  95. data/spec/FIX41.xml +29 -29
  96. data/spec/FIX42.xml +47 -47
  97. data/spec/FIX43.xml +148 -148
  98. data/spec/FIX44.xml +1078 -1081
  99. data/spec/FIX50.xml +1292 -1289
  100. data/spec/FIX50SP1.xml +1811 -1802
  101. data/spec/FIX50SP2.xml +1948 -1939
  102. data/spec/FIXT11.xml +5 -8
  103. data/test/test_FieldBaseTestCase.rb +1 -1
  104. data/test/test_MessageTestCase.rb +2 -2
  105. 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 = recv( m_socket, m_buffer, sizeof(m_buffer), 0 );
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
  }
@@ -231,7 +231,13 @@ void Initiator::stop( bool force )
231
231
 
232
232
  std::vector<Session*> enabledSessions;
233
233
 
234
- SessionIDs connected = m_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
  {
@@ -135,7 +135,9 @@ private:
135
135
  thread_id m_threadid;
136
136
  Application& m_application;
137
137
  MessageStoreFactory& m_messageStoreFactory;
138
+ protected:
138
139
  SessionSettings m_settings;
140
+ private:
139
141
  LogFactory* m_pLogFactory;
140
142
  Log* m_pLog;
141
143
  NullLog m_nullLog;
@@ -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 ), m_millisecondsInTimeStamp( true ) {}
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 ), m_millisecondsInTimeStamp( true ) {}
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, m_millisecondsInTimeStamp)
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, m_millisecondsInTimeStamp)
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, m_millisecondsInTimeStamp)
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
 
@@ -30,14 +30,31 @@
30
30
 
31
31
  namespace FIX
32
32
  {
33
- std::auto_ptr<DataDictionary> Message::s_dataDictionary;
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
- std::auto_ptr<DataDictionary> p =
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.getField() );
89
- m_header.removeField( senderCompID.getField() );
90
- m_header.removeField( targetCompID.getField() );
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.getField() );
101
- m_header.removeField( deliverToLocationID.getField() );
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.getField() );
138
- m_header.removeField( onBehalfOfSubID.getField() );
139
- m_header.removeField( deliverToCompID.getField() );
140
- m_header.removeField( deliverToSubID.getField() );
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
- return toString( str, beginStringField, bodyLengthField, checkSumField );
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
- return toXML( str );
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::iterator i;
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->first;
232
- std::string value = i->second.getString();
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::g_iterator j;
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
- static int const headerOrder[] =
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.getField() )
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(m_field == 0) m_field = field.getField();
361
+ if(m_tag == 0) m_tag = field.getTag();
297
362
  m_validStructure = false;
298
363
  }
299
364
 
300
- if ( field.getField() == FIELD::MsgType )
301
- msg = field.getString();
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.setField( field, false );
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.setField( field, false );
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(m_field == 0) m_field = field.getField();
406
+ if(m_tag == 0) m_tag = field.getTag();
321
407
  m_validStructure = false;
322
408
  }
323
409
 
324
410
  type = body;
325
- setField( field, false );
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.getField();
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
- std::auto_ptr<Group> pGroup;
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.getField() == delim) ||
449
+ (field.getTag() == delim) ||
355
450
  // no delimiter, but field belongs to group OR field already processed
356
- (pDD->isField( field.getField() ) && (pGroup.get() == 0 || pGroup->isSetField( field.getField() )) ))
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.getField(), delim, pDD->getOrderedFields() ) );
457
+ pGroup.reset( new Group( field.getTag(), delim, pDD->getOrderedFields() ) );
363
458
  }
364
- else if ( !pDD->isField( field.getField() ) )
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->setField( field, false );
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.getField() )
485
+ if ( count < 3 && headerOrder[ count++ ] != field.getTag() )
391
486
  return false;
392
487
 
393
488
  if ( isHeaderField( field ) )
394
- m_header.setField( field, false );
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
- if ( isHeaderField( field.getField() ) ) return true;
443
- if ( pD ) return pD->isHeaderField( field.getField() );
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
- if ( isTrailerField( field.getField() ) ) return true;
464
- if ( pD ) return pD->isTrailerField( field.getField() );
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
- if ( pGroup && pGroup->isSetField( lenField ) )
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
- const std::string& fieldLength = pGroup->getField( lenField );
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
- else if ( isSetField( lenField ) )
688
+ catch( FieldConvertError& e )
564
689
  {
565
- const std::string& fieldLength = getField( lenField );
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
  }