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.
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
  }