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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 58371578252b4082a68d2cd3f842349de57003f3
4
- data.tar.gz: aa6278870deec6cedffb3202d93a9f8f64cc1d2e
3
+ metadata.gz: df5047d3c81911491ebbf1d707c5ac0385d4a39d
4
+ data.tar.gz: 1558e66c08562f551af3d1d5a7589d09b6018ec3
5
5
  SHA512:
6
- metadata.gz: 8c370996d33ff6f659df2803b61581bcd1d1d22c080b6e41b8eec322ac01b29f67bb0d2d3d50433d37700e65085b7c7a203f19da0066ad9c167a3f97c5f26aee
7
- data.tar.gz: 643191c64ec5026fa6b0aca09ece4c46e3614cef586db704d811d873b0c01b0fb000896f8d0d7c1ebdf14ef4c40550e3d212eb147b8f08e64944c55b588f416d
6
+ metadata.gz: 7923a274db5a89bbd5e730d6bee308c4d9a7a853b52938f4f5a2a1b20cac2a9891ee0b0371be75895c5853a7a48ab3c613608d8fedac9bf3e80b3465dfb85de5
7
+ data.tar.gz: 8c0fd54ae7116b8b55d2ce21670ecab11dea76a204cbf5c4aa68901f72271e4ec1c5b1c393b17e39fe2b52c5d9b1adfee23e71c69e20655d2a8ed162dfcf43c0
@@ -114,7 +114,9 @@ private:
114
114
  SessionIDs m_sessionIDs;
115
115
  Application& m_application;
116
116
  MessageStoreFactory& m_messageStoreFactory;
117
+ protected:
117
118
  SessionSettings m_settings;
119
+ private:
118
120
  LogFactory* m_pLogFactory;
119
121
  Log* m_pLog;
120
122
  NullLog m_nullLog;
@@ -22,7 +22,11 @@
22
22
  #ifndef ATOMIC_COUNT
23
23
  #define ATOMIC_COUNT
24
24
 
25
+ #include "Utility.h"
26
+
27
+ #if defined(__SUNPRO_CC) || defined(__TOS_AIX__)
25
28
  #include "Mutex.h"
29
+ #endif
26
30
 
27
31
  namespace FIX
28
32
  {
@@ -55,7 +59,7 @@ typedef boost::detail::atomic_count atomic_count;
55
59
 
56
60
  operator long() const
57
61
  {
58
- return static_cast<long const volatile &>( m_counter );
62
+ return ::InterlockedExchangeAdd(const_cast<long volatile *>( &m_counter ), 0 );
59
63
  }
60
64
 
61
65
  private:
@@ -66,30 +70,75 @@ typedef boost::detail::atomic_count atomic_count;
66
70
  long volatile m_counter;
67
71
  };
68
72
 
73
+ #elif defined(__SUNPRO_CC) || defined(__TOS_AIX__)
74
+
75
+ // general purpose atomic counter using mutexes
76
+ class atomic_count
77
+ {
78
+ public:
79
+ explicit atomic_count( long v ): m_counter( v )
80
+ {
81
+ }
82
+
83
+ long operator++()
84
+ {
85
+ Locker _lock(m_mutex);
86
+ return ++m_counter;
87
+ }
88
+
89
+ long operator--()
90
+ {
91
+ Locker _lock(m_mutex);
92
+ return --m_counter;
93
+ }
94
+
95
+ operator long() const
96
+ {
97
+ return static_cast<long const volatile &>( m_counter );
98
+ }
99
+
100
+ private:
101
+
102
+ atomic_count( atomic_count const & );
103
+ atomic_count & operator=( atomic_count const & );
104
+
105
+ Mutex m_mutex;
106
+ long m_counter;
107
+ };
108
+
69
109
  #else
70
- // general purpose atomic counter using mutexes
110
+
111
+ //
112
+ // boost/detail/atomic_count_gcc_x86.hpp
113
+ //
114
+ // atomic_count for g++ on 486+/AMD64
115
+ //
116
+ // Copyright 2007 Peter Dimov
117
+ //
118
+ // Distributed under the Boost Software License, Version 1.0. (See
119
+ // accompanying file LICENSE_1_0.txt or copy at
120
+ // http://www.boost.org/LICENSE_1_0.txt)
121
+ //
122
+
71
123
  class atomic_count
72
124
  {
73
125
  public:
74
- explicit atomic_count( long v ): m_counter( v )
75
- {
76
- }
126
+
127
+ explicit atomic_count( long v ) : value_(static_cast<int>(v)) {}
77
128
 
78
129
  long operator++()
79
130
  {
80
- Locker _lock(m_mutex);
81
- return ++m_counter;
131
+ return atomic_exchange_and_add( &value_, 1 ) + 1;
82
132
  }
83
133
 
84
134
  long operator--()
85
135
  {
86
- Locker _lock(m_mutex);
87
- return --m_counter;
136
+ return atomic_exchange_and_add( &value_, -1 ) - 1;
88
137
  }
89
138
 
90
139
  operator long() const
91
140
  {
92
- return static_cast<long const volatile &>( m_counter );
141
+ return atomic_exchange_and_add( &value_, 0 );
93
142
  }
94
143
 
95
144
  private:
@@ -97,8 +146,29 @@ typedef boost::detail::atomic_count atomic_count;
97
146
  atomic_count( atomic_count const & );
98
147
  atomic_count & operator=( atomic_count const & );
99
148
 
100
- Mutex m_mutex;
101
- long m_counter;
149
+ mutable int value_;
150
+
151
+ private:
152
+
153
+ static int atomic_exchange_and_add(int * pw, int dv)
154
+ {
155
+ // int r = *pw;
156
+ // *pw += dv;
157
+ // return r;
158
+
159
+ int r;
160
+
161
+ __asm__ __volatile__
162
+ (
163
+ "lock\n\t"
164
+ "xadd %1, %0":
165
+ "+m"(*pw), "=r"(r) : // outputs (%0, %1)
166
+ "1"(dv) : // inputs (%2 == %1)
167
+ "memory", "cc" // clobbers
168
+ );
169
+
170
+ return r;
171
+ }
102
172
  };
103
173
 
104
174
  #endif
@@ -26,9 +26,11 @@
26
26
  #include <map>
27
27
  #include <iostream>
28
28
  #include <memory>
29
+ #include "Utility.h"
29
30
 
30
31
  namespace FIX
31
32
  {
33
+ #include "Utility.h"
32
34
  /// Interface that represents attribute from underlying XML parser.
33
35
  class DOMAttributes
34
36
  {
@@ -40,7 +42,7 @@ namespace FIX
40
42
  virtual bool get( const std::string&, std::string& ) = 0;
41
43
  virtual map toMap() = 0;
42
44
  };
43
- typedef std::auto_ptr<DOMAttributes> DOMAttributesPtr;
45
+ typedef SmartPtr<DOMAttributes> DOMAttributesPtr;
44
46
 
45
47
  /// Interface that represents node from underlying XML parser.
46
48
  class DOMNode
@@ -48,13 +50,13 @@ namespace FIX
48
50
  public:
49
51
  virtual ~DOMNode() {}
50
52
 
51
- virtual std::auto_ptr<DOMNode> getFirstChildNode() = 0;
52
- virtual std::auto_ptr<DOMNode> getNextSiblingNode() = 0;
53
- virtual std::auto_ptr<DOMAttributes> getAttributes() = 0;
53
+ virtual SmartPtr<DOMNode> getFirstChildNode() = 0;
54
+ virtual SmartPtr<DOMNode> getNextSiblingNode() = 0;
55
+ virtual SmartPtr<DOMAttributes> getAttributes() = 0;
54
56
  virtual std::string getName() = 0;
55
57
  virtual std::string getText() = 0;
56
58
  };
57
- typedef std::auto_ptr<DOMNode> DOMNodePtr;
59
+ typedef SmartPtr<DOMNode> DOMNodePtr;
58
60
 
59
61
  /// Interface that represents document of underlying XML parser.
60
62
  class DOMDocument
@@ -66,9 +68,9 @@ namespace FIX
66
68
  virtual bool load( const std::string& ) = 0;
67
69
  virtual bool xml( std::ostream& ) = 0;
68
70
 
69
- virtual std::auto_ptr<DOMNode> getNode( const std::string& ) = 0;
71
+ virtual SmartPtr<DOMNode> getNode( const std::string& ) = 0;
70
72
  };
71
- typedef std::auto_ptr<DOMDocument> DOMDocumentPtr;
73
+ typedef SmartPtr<DOMDocument> DOMDocumentPtr;
72
74
  }
73
75
 
74
76
  #endif
@@ -40,22 +40,21 @@ namespace FIX
40
40
  {
41
41
  DataDictionary::DataDictionary()
42
42
  : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
43
- m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
43
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ), m_allowUnknownMessageFields( false ), m_storeMsgFieldsOrder(false)
44
44
  {}
45
45
 
46
- DataDictionary::DataDictionary( std::istream& stream )
46
+ DataDictionary::DataDictionary( std::istream& stream, bool preserveMsgFldsOrder )
47
47
  throw( ConfigError )
48
48
  : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
49
- m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
49
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ), m_allowUnknownMessageFields( false ), m_storeMsgFieldsOrder(preserveMsgFldsOrder)
50
50
  {
51
51
  readFromStream( stream );
52
52
  }
53
53
 
54
- DataDictionary::DataDictionary( const std::string& url )
54
+ DataDictionary::DataDictionary( const std::string& url, bool preserveMsgFldsOrder )
55
55
  throw( ConfigError )
56
56
  : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
57
- m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
58
- m_orderedFieldsArray(0)
57
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ), m_allowUnknownMessageFields( false ), m_storeMsgFieldsOrder(preserveMsgFldsOrder), m_orderedFieldsArray(0)
59
58
  {
60
59
  readFromURL( url );
61
60
  }
@@ -83,7 +82,9 @@ DataDictionary& DataDictionary::operator=( const DataDictionary& rhs )
83
82
  m_hasVersion = rhs.m_hasVersion;
84
83
  m_checkFieldsOutOfOrder = rhs.m_checkFieldsOutOfOrder;
85
84
  m_checkFieldsHaveValues = rhs.m_checkFieldsHaveValues;
85
+ m_storeMsgFieldsOrder = rhs.m_storeMsgFieldsOrder;
86
86
  m_checkUserDefinedFields = rhs.m_checkUserDefinedFields;
87
+ m_allowUnknownMessageFields = rhs.m_allowUnknownMessageFields;
87
88
  m_beginString = rhs.m_beginString;
88
89
  m_messageFields = rhs.m_messageFields;
89
90
  m_requiredFields = rhs.m_requiredFields;
@@ -99,6 +100,11 @@ DataDictionary& DataDictionary::operator=( const DataDictionary& rhs )
99
100
  m_names = rhs.m_names;
100
101
  m_valueNames = rhs.m_valueNames;
101
102
  m_dataFields = rhs.m_dataFields;
103
+ m_headerOrderedFields = rhs.m_headerOrderedFields;
104
+ m_headerOrder = rhs.m_headerOrder;
105
+ m_trailerOrderedFields = rhs.m_trailerOrderedFields;
106
+ m_trailerOrder = rhs.m_trailerOrder;
107
+ m_messageOrderedFields = rhs.m_messageOrderedFields;
102
108
 
103
109
  FieldToGroup::const_iterator i = rhs.m_groups.begin();
104
110
  for ( ; i != rhs.m_groups.end(); ++i )
@@ -121,7 +127,15 @@ throw( FIX::Exception )
121
127
  {
122
128
  const Header& header = message.getHeader();
123
129
  const BeginString& beginString = FIELD_GET_REF( header, BeginString );
130
+ #ifdef HAVE_EMX
131
+ const std::string & msgType = message.getSubMessageType();
132
+ if (msgType.empty())
133
+ {
134
+ throw InvalidMessageType("empty subMsgType, check Tag 9426/MESSAGE_ID");
135
+ }
136
+ #else
124
137
  const MsgType& msgType = FIELD_GET_REF( header, MsgType );
138
+ #endif
125
139
  if ( pSessionDD != 0 && pSessionDD->m_hasVersion )
126
140
  {
127
141
  if( pSessionDD->getVersion() != beginString )
@@ -160,11 +174,11 @@ void DataDictionary::iterate( const FieldMap& map, const MsgType& msgType ) cons
160
174
  {
161
175
  int lastField = 0;
162
176
 
163
- FieldMap::iterator i;
177
+ FieldMap::const_iterator i;
164
178
  for ( i = map.begin(); i != map.end(); ++i )
165
179
  {
166
- const FieldBase& field = i->second;
167
- if( i != map.begin() && (field.getField() == lastField) )
180
+ const FieldBase& field = (*i);
181
+ if( i != map.begin() && (field.getTag() == lastField) )
168
182
  throw RepeatedTag( lastField );
169
183
  checkHasValue( field );
170
184
 
@@ -184,14 +198,14 @@ void DataDictionary::iterate( const FieldMap& map, const MsgType& msgType ) cons
184
198
  checkGroupCount( field, map, msgType );
185
199
  }
186
200
  }
187
- lastField = field.getField();
201
+ lastField = field.getTag();
188
202
  }
189
203
  }
190
204
 
191
205
  void DataDictionary::readFromURL( const std::string& url )
192
206
  throw( ConfigError )
193
207
  {
194
- DOMDocumentPtr pDoc = DOMDocumentPtr(new PUGIXML_DOMDocument());
208
+ DOMDocumentPtr pDoc(new PUGIXML_DOMDocument());
195
209
 
196
210
  if(!pDoc->load(url))
197
211
  throw ConfigError(url + ": Could not parse data dictionary file");
@@ -209,7 +223,7 @@ throw( ConfigError )
209
223
  void DataDictionary::readFromStream( std::istream& stream )
210
224
  throw( ConfigError )
211
225
  {
212
- DOMDocumentPtr pDoc = DOMDocumentPtr(new PUGIXML_DOMDocument());
226
+ DOMDocumentPtr pDoc(new PUGIXML_DOMDocument());
213
227
 
214
228
  if(!pDoc->load(stream))
215
229
  throw ConfigError("Could not parse data dictionary stream");
@@ -217,7 +231,7 @@ throw( ConfigError )
217
231
  readFromDocument( pDoc );
218
232
  }
219
233
 
220
- void DataDictionary::readFromDocument( DOMDocumentPtr pDoc )
234
+ void DataDictionary::readFromDocument( const DOMDocumentPtr &pDoc )
221
235
  throw( ConfigError )
222
236
  {
223
237
  // VERSION
@@ -441,6 +455,55 @@ message_order const& DataDictionary::getOrderedFields() const
441
455
  return m_orderedFieldsArray;
442
456
  }
443
457
 
458
+ message_order const& DataDictionary::getHeaderOrderedFields() const throw( ConfigError )
459
+ {
460
+ if( m_headerOrder ) return m_headerOrder;
461
+
462
+ if (m_headerOrderedFields.size() == 0)
463
+ throw ConfigError("<Header> does not have a stored message order");
464
+
465
+ int * tmp = new int[m_headerOrderedFields.size() + 1];
466
+ int * i = tmp;
467
+
468
+ OrderedFields::const_iterator iter;
469
+ for( iter = m_headerOrderedFields.begin(); iter != m_headerOrderedFields.end(); *(i++) = *(iter++) ) {}
470
+ *i = 0;
471
+
472
+ m_headerOrder = message_order(tmp);
473
+ delete [] tmp;
474
+
475
+ return m_headerOrder;
476
+ }
477
+
478
+ message_order const& DataDictionary::getTrailerOrderedFields() const throw( ConfigError )
479
+ {
480
+ if( m_trailerOrder ) return m_trailerOrder;
481
+
482
+ if (m_trailerOrderedFields.size() == 0)
483
+ throw ConfigError("<Trailer> does not have a stored message order");
484
+
485
+ int * tmp = new int[m_trailerOrderedFields.size() + 1];
486
+ int * i = tmp;
487
+
488
+ OrderedFields::const_iterator iter;
489
+ for( iter = m_trailerOrderedFields.begin(); iter != m_trailerOrderedFields.end(); *(i++) = *(iter++) ) {}
490
+ *i = 0;
491
+
492
+ m_trailerOrder = message_order(tmp);
493
+ delete [] tmp;
494
+
495
+ return m_trailerOrder;
496
+ }
497
+
498
+ const message_order &DataDictionary::getMessageOrderedFields(const std::string & msgType) const throw( ConfigError )
499
+ {
500
+ MsgTypeToOrderedFields::const_iterator iter = m_messageOrderedFields.find(msgType);
501
+ if (iter == m_messageOrderedFields.end())
502
+ throw ConfigError("<Message> " + msgType + " does not have a stored message order");
503
+
504
+ return iter->second.getMessageOrder();
505
+ }
506
+
444
507
  int DataDictionary::lookupXMLFieldNumber( DOMDocument* pDoc, DOMNode* pNode ) const
445
508
  {
446
509
  DOMAttributesPtr attrs = pNode->getAttributes();
@@ -474,7 +537,7 @@ int DataDictionary::addXMLComponentFields( DOMDocument* pDoc, DOMNode* pNode,
474
537
  DOMNodePtr pComponentNode =
475
538
  pDoc->getNode("/fix/components/component[@name='" + name + "']");
476
539
  if(pComponentNode.get() == 0)
477
- throw ConfigError("Component not found");
540
+ throw ConfigError("Component not found: " + name);
478
541
 
479
542
  DOMNodePtr pComponentFieldNode = pComponentNode->getFirstChildNode();
480
543
  while(pComponentFieldNode.get())
@@ -54,6 +54,46 @@ class DataDictionary
54
54
  typedef std::set < int > Fields;
55
55
  typedef std::map < int, bool > NonBodyFields;
56
56
  typedef std::vector< int > OrderedFields;
57
+
58
+ struct MessageFieldsOrderHolder
59
+ {
60
+ MessageFieldsOrderHolder()
61
+ {}
62
+
63
+ ~MessageFieldsOrderHolder()
64
+ {}
65
+
66
+ void push_back(int field)
67
+ {
68
+ m_orderedFlds.push_back(field);
69
+ }
70
+
71
+ const message_order & getMessageOrder() const
72
+ {
73
+ if (m_msgOrder)
74
+ return m_msgOrder;
75
+
76
+ int * tmp = new int[m_orderedFlds.size() + 1];
77
+ int * i = tmp;
78
+
79
+ OrderedFields::const_iterator iter;
80
+ for( iter = m_orderedFlds.begin(); iter != m_orderedFlds.end(); *(i++) = *(iter++) ) {}
81
+ *i = 0;
82
+
83
+ m_msgOrder = message_order(tmp);
84
+ delete [] tmp;
85
+
86
+ return m_msgOrder;
87
+ }
88
+
89
+ private:
90
+
91
+ mutable message_order m_msgOrder;
92
+ OrderedFields m_orderedFlds;
93
+ };
94
+
95
+ typedef std::map<std::string, MessageFieldsOrderHolder > MsgTypeToOrderedFields;
96
+
57
97
  typedef message_order OrderedFieldsArray;
58
98
  typedef std::map < int, TYPE::Type > FieldTypes;
59
99
  typedef std::set < std::string > Values;
@@ -72,15 +112,18 @@ class DataDictionary
72
112
  public:
73
113
  DataDictionary();
74
114
  DataDictionary( const DataDictionary& copy );
75
- DataDictionary( std::istream& stream ) throw( ConfigError );
76
- DataDictionary( const std::string& url ) throw( ConfigError );
115
+ DataDictionary(std::istream& stream , bool preserveMsgFldsOrder = false) throw( ConfigError );
116
+ DataDictionary(const std::string& url , bool preserveMsgFldsOrder = false) throw( ConfigError );
77
117
  virtual ~DataDictionary();
78
118
 
79
119
  void readFromURL( const std::string& url ) throw( ConfigError );
80
- void readFromDocument( DOMDocumentPtr pDoc ) throw( ConfigError );
120
+ void readFromDocument( const DOMDocumentPtr &pDoc ) throw( ConfigError );
81
121
  void readFromStream( std::istream& stream ) throw( ConfigError );
82
122
 
83
123
  message_order const& getOrderedFields() const;
124
+ message_order const& getHeaderOrderedFields() const throw( ConfigError );
125
+ message_order const& getTrailerOrderedFields() const throw( ConfigError );
126
+ message_order const& getMessageOrderedFields(const std::string & msgType) const throw( ConfigError );
84
127
 
85
128
  // storage functions
86
129
  void setVersion( const std::string& beginString )
@@ -152,6 +195,11 @@ public:
152
195
 
153
196
  void addMsgField( const std::string& msgType, int field )
154
197
  {
198
+ if (m_storeMsgFieldsOrder)
199
+ {
200
+ m_messageOrderedFields[ msgType ].push_back(field);
201
+ }
202
+
155
203
  m_messageFields[ msgType ].insert( field );
156
204
  }
157
205
 
@@ -164,6 +212,11 @@ public:
164
212
 
165
213
  void addHeaderField( int field, bool required )
166
214
  {
215
+ if (m_storeMsgFieldsOrder)
216
+ {
217
+ m_headerOrderedFields.push_back(field);
218
+ }
219
+
167
220
  m_headerFields[ field ] = required;
168
221
  }
169
222
 
@@ -174,6 +227,11 @@ public:
174
227
 
175
228
  void addTrailerField( int field, bool required )
176
229
  {
230
+ if (m_storeMsgFieldsOrder)
231
+ {
232
+ m_trailerOrderedFields.push_back(field);
233
+ }
234
+
177
235
  m_trailerFields[ field ] = required;
178
236
  }
179
237
 
@@ -303,6 +361,12 @@ public:
303
361
  { m_checkFieldsHaveValues = value; }
304
362
  void checkUserDefinedFields( bool value )
305
363
  { m_checkUserDefinedFields = value; }
364
+ void allowUnknownMsgFields( bool value )
365
+ { m_allowUnknownMessageFields = value; }
366
+ void preserveMessageFieldsOrder( bool value )
367
+ { m_storeMsgFieldsOrder = value; }
368
+ bool isMessageFieldsOrderPreserved() const
369
+ { return m_storeMsgFieldsOrder; }
306
370
 
307
371
  /// Validate a message.
308
372
  static void validate( const Message& message,
@@ -330,7 +394,9 @@ private:
330
394
  /// If we need to check for the tag in the dictionary
331
395
  bool shouldCheckTag( const FieldBase& field ) const
332
396
  {
333
- if( !m_checkUserDefinedFields && field.getField() >= FIELD::UserMin )
397
+ if( m_allowUnknownMessageFields && field.getTag() < FIELD::UserMin )
398
+ return false;
399
+ else if( !m_checkUserDefinedFields && field.getTag() >= FIELD::UserMin )
334
400
  return false;
335
401
  else
336
402
  return true;
@@ -340,8 +406,8 @@ private:
340
406
  void checkValidTagNumber( const FieldBase& field ) const
341
407
  throw( InvalidTagNumber )
342
408
  {
343
- if( m_fields.find( field.getField() ) == m_fields.end() )
344
- throw InvalidTagNumber( field.getField() );
409
+ if( m_fields.find( field.getTag() ) == m_fields.end() )
410
+ throw InvalidTagNumber( field.getTag() );
345
411
  }
346
412
 
347
413
  void checkValidFormat( const FieldBase& field ) const
@@ -350,7 +416,7 @@ private:
350
416
  try
351
417
  {
352
418
  TYPE::Type type = TYPE::Unknown;
353
- getFieldType( field.getField(), type );
419
+ getFieldType( field.getTag(), type );
354
420
  switch ( type )
355
421
  {
356
422
  case TYPE::String:
@@ -417,17 +483,17 @@ private:
417
483
  }
418
484
  }
419
485
  catch ( FieldConvertError& )
420
- { throw IncorrectDataFormat( field.getField(), field.getString() ); }
486
+ { throw IncorrectDataFormat( field.getTag(), field.getString() ); }
421
487
  }
422
488
 
423
489
  void checkValue( const FieldBase& field ) const
424
490
  throw( IncorrectTagValue )
425
491
  {
426
- if ( !hasFieldValue( field.getField() ) ) return ;
492
+ if ( !hasFieldValue( field.getTag() ) ) return ;
427
493
 
428
494
  const std::string& value = field.getString();
429
- if ( !isFieldValue( field.getField(), value ) )
430
- throw IncorrectTagValue( field.getField() );
495
+ if ( !isFieldValue( field.getTag(), value ) )
496
+ throw IncorrectTagValue( field.getTag() );
431
497
  }
432
498
 
433
499
  /// Check if a field has a value.
@@ -435,7 +501,7 @@ private:
435
501
  throw( NoTagValue )
436
502
  {
437
503
  if ( m_checkFieldsHaveValues && !field.getString().length() )
438
- throw NoTagValue( field.getField() );
504
+ throw NoTagValue( field.getTag() );
439
505
  }
440
506
 
441
507
  /// Check if a field is in this message type.
@@ -443,8 +509,8 @@ private:
443
509
  ( const FieldBase& field, const MsgType& msgType ) const
444
510
  throw( TagNotDefinedForMessage )
445
511
  {
446
- if ( !isMsgField( msgType, field.getField() ) )
447
- throw TagNotDefinedForMessage( field.getField() );
512
+ if ( !isMsgField( msgType, field.getTag() ) )
513
+ throw TagNotDefinedForMessage( field.getTag() );
448
514
  }
449
515
 
450
516
  /// Check if group count matches number of groups in
@@ -452,7 +518,7 @@ private:
452
518
  ( const FieldBase& field, const FieldMap& fieldMap, const MsgType& msgType ) const
453
519
  throw( RepeatingGroupCountMismatch )
454
520
  {
455
- int fieldNum = field.getField();
521
+ int fieldNum = field.getTag();
456
522
  if( isGroup(msgType, fieldNum) )
457
523
  {
458
524
  if( (int)fieldMap.groupCount(fieldNum)
@@ -492,7 +558,7 @@ private:
492
558
  throw RequiredTagMissing( *iF );
493
559
  }
494
560
 
495
- FieldMap::g_iterator groups;
561
+ FieldMap::g_const_iterator groups;
496
562
  for( groups = body.g_begin(); groups != body.g_end(); ++groups )
497
563
  {
498
564
  int delim;
@@ -517,6 +583,9 @@ private:
517
583
  bool m_checkFieldsOutOfOrder;
518
584
  bool m_checkFieldsHaveValues;
519
585
  bool m_checkUserDefinedFields;
586
+ bool m_allowUnknownMessageFields;
587
+ bool m_storeMsgFieldsOrder;
588
+
520
589
  BeginString m_beginString;
521
590
  MsgTypeToField m_messageFields;
522
591
  MsgTypeToField m_requiredFields;
@@ -533,6 +602,11 @@ private:
533
602
  ValueToName m_valueNames;
534
603
  FieldToGroup m_groups;
535
604
  MsgFields m_dataFields;
605
+ OrderedFields m_headerOrderedFields;
606
+ mutable OrderedFieldsArray m_headerOrder;
607
+ OrderedFields m_trailerOrderedFields;
608
+ mutable OrderedFieldsArray m_trailerOrder;
609
+ MsgTypeToOrderedFields m_messageOrderedFields;
536
610
  };
537
611
  }
538
612