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