quickfix_ruby 1.14.3

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 (149) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +248 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +127 -0
  6. data/ext/quickfix/AtomicCount.h +109 -0
  7. data/ext/quickfix/DOMDocument.h +74 -0
  8. data/ext/quickfix/DataDictionary.cpp +618 -0
  9. data/ext/quickfix/DataDictionary.h +539 -0
  10. data/ext/quickfix/DataDictionaryProvider.cpp +71 -0
  11. data/ext/quickfix/DataDictionaryProvider.h +70 -0
  12. data/ext/quickfix/DatabaseConnectionID.h +105 -0
  13. data/ext/quickfix/DatabaseConnectionPool.h +91 -0
  14. data/ext/quickfix/Dictionary.cpp +162 -0
  15. data/ext/quickfix/Dictionary.h +94 -0
  16. data/ext/quickfix/Event.h +95 -0
  17. data/ext/quickfix/Exceptions.h +299 -0
  18. data/ext/quickfix/Field.h +672 -0
  19. data/ext/quickfix/FieldConvertors.h +863 -0
  20. data/ext/quickfix/FieldMap.cpp +238 -0
  21. data/ext/quickfix/FieldMap.h +244 -0
  22. data/ext/quickfix/FieldNumbers.h +46 -0
  23. data/ext/quickfix/FieldTypes.cpp +64 -0
  24. data/ext/quickfix/FieldTypes.h +698 -0
  25. data/ext/quickfix/Fields.h +31 -0
  26. data/ext/quickfix/FileLog.cpp +200 -0
  27. data/ext/quickfix/FileLog.h +112 -0
  28. data/ext/quickfix/FileStore.cpp +332 -0
  29. data/ext/quickfix/FileStore.h +129 -0
  30. data/ext/quickfix/FixFieldNumbers.h +1537 -0
  31. data/ext/quickfix/FixFields.h +1538 -0
  32. data/ext/quickfix/FixValues.h +3281 -0
  33. data/ext/quickfix/FlexLexer.h +188 -0
  34. data/ext/quickfix/Group.cpp +64 -0
  35. data/ext/quickfix/Group.h +73 -0
  36. data/ext/quickfix/HtmlBuilder.h +186 -0
  37. data/ext/quickfix/HttpConnection.cpp +739 -0
  38. data/ext/quickfix/HttpConnection.h +78 -0
  39. data/ext/quickfix/HttpMessage.cpp +149 -0
  40. data/ext/quickfix/HttpMessage.h +133 -0
  41. data/ext/quickfix/HttpParser.cpp +49 -0
  42. data/ext/quickfix/HttpParser.h +54 -0
  43. data/ext/quickfix/HttpServer.cpp +169 -0
  44. data/ext/quickfix/HttpServer.h +78 -0
  45. data/ext/quickfix/Initiator.cpp +289 -0
  46. data/ext/quickfix/Initiator.h +149 -0
  47. data/ext/quickfix/Log.cpp +77 -0
  48. data/ext/quickfix/Log.h +179 -0
  49. data/ext/quickfix/Message.cpp +580 -0
  50. data/ext/quickfix/Message.h +370 -0
  51. data/ext/quickfix/MessageCracker.h +188 -0
  52. data/ext/quickfix/MessageSorters.cpp +105 -0
  53. data/ext/quickfix/MessageSorters.h +156 -0
  54. data/ext/quickfix/MessageStore.cpp +146 -0
  55. data/ext/quickfix/MessageStore.h +174 -0
  56. data/ext/quickfix/Mutex.h +131 -0
  57. data/ext/quickfix/MySQLConnection.h +194 -0
  58. data/ext/quickfix/MySQLLog.cpp +275 -0
  59. data/ext/quickfix/MySQLLog.h +145 -0
  60. data/ext/quickfix/MySQLStore.cpp +331 -0
  61. data/ext/quickfix/MySQLStore.h +142 -0
  62. data/ext/quickfix/NullStore.cpp +54 -0
  63. data/ext/quickfix/NullStore.h +99 -0
  64. data/ext/quickfix/OdbcConnection.h +266 -0
  65. data/ext/quickfix/OdbcLog.cpp +252 -0
  66. data/ext/quickfix/OdbcLog.h +117 -0
  67. data/ext/quickfix/OdbcStore.cpp +338 -0
  68. data/ext/quickfix/OdbcStore.h +113 -0
  69. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  70. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  71. data/ext/quickfix/Parser.cpp +103 -0
  72. data/ext/quickfix/Parser.h +57 -0
  73. data/ext/quickfix/PostgreSQLConnection.h +176 -0
  74. data/ext/quickfix/PostgreSQLLog.cpp +276 -0
  75. data/ext/quickfix/PostgreSQLLog.h +144 -0
  76. data/ext/quickfix/PostgreSQLStore.cpp +334 -0
  77. data/ext/quickfix/PostgreSQLStore.h +141 -0
  78. data/ext/quickfix/Queue.h +75 -0
  79. data/ext/quickfix/QuickfixRuby.cpp +252066 -0
  80. data/ext/quickfix/QuickfixRuby.h +34 -0
  81. data/ext/quickfix/Responder.h +43 -0
  82. data/ext/quickfix/Session.cpp +1487 -0
  83. data/ext/quickfix/Session.h +335 -0
  84. data/ext/quickfix/SessionFactory.cpp +274 -0
  85. data/ext/quickfix/SessionFactory.h +86 -0
  86. data/ext/quickfix/SessionID.h +170 -0
  87. data/ext/quickfix/SessionSettings.cpp +189 -0
  88. data/ext/quickfix/SessionSettings.h +171 -0
  89. data/ext/quickfix/SessionState.h +231 -0
  90. data/ext/quickfix/Settings.cpp +100 -0
  91. data/ext/quickfix/Settings.h +53 -0
  92. data/ext/quickfix/SharedArray.h +150 -0
  93. data/ext/quickfix/SocketAcceptor.cpp +222 -0
  94. data/ext/quickfix/SocketAcceptor.h +75 -0
  95. data/ext/quickfix/SocketConnection.cpp +238 -0
  96. data/ext/quickfix/SocketConnection.h +103 -0
  97. data/ext/quickfix/SocketConnector.cpp +116 -0
  98. data/ext/quickfix/SocketConnector.h +67 -0
  99. data/ext/quickfix/SocketInitiator.cpp +260 -0
  100. data/ext/quickfix/SocketInitiator.h +81 -0
  101. data/ext/quickfix/SocketMonitor.cpp +335 -0
  102. data/ext/quickfix/SocketMonitor.h +111 -0
  103. data/ext/quickfix/SocketServer.cpp +177 -0
  104. data/ext/quickfix/SocketServer.h +100 -0
  105. data/ext/quickfix/ThreadedSocketAcceptor.cpp +258 -0
  106. data/ext/quickfix/ThreadedSocketAcceptor.h +98 -0
  107. data/ext/quickfix/ThreadedSocketConnection.cpp +209 -0
  108. data/ext/quickfix/ThreadedSocketConnection.h +82 -0
  109. data/ext/quickfix/ThreadedSocketInitiator.cpp +268 -0
  110. data/ext/quickfix/ThreadedSocketInitiator.h +84 -0
  111. data/ext/quickfix/TimeRange.cpp +173 -0
  112. data/ext/quickfix/TimeRange.h +258 -0
  113. data/ext/quickfix/Utility.cpp +537 -0
  114. data/ext/quickfix/Utility.h +219 -0
  115. data/ext/quickfix/Values.h +62 -0
  116. data/ext/quickfix/config.h +0 -0
  117. data/ext/quickfix/config_windows.h +0 -0
  118. data/ext/quickfix/extconf.rb +12 -0
  119. data/ext/quickfix/index.h +37 -0
  120. data/ext/quickfix/pugiconfig.hpp +72 -0
  121. data/ext/quickfix/pugixml.cpp +10765 -0
  122. data/ext/quickfix/pugixml.hpp +1341 -0
  123. data/ext/quickfix/strptime.h +7 -0
  124. data/lib/quickfix40.rb +274 -0
  125. data/lib/quickfix41.rb +351 -0
  126. data/lib/quickfix42.rb +1184 -0
  127. data/lib/quickfix43.rb +3504 -0
  128. data/lib/quickfix44.rb +10721 -0
  129. data/lib/quickfix50.rb +13426 -0
  130. data/lib/quickfix50sp1.rb +15629 -0
  131. data/lib/quickfix50sp2.rb +17068 -0
  132. data/lib/quickfix_fields.rb +19853 -0
  133. data/lib/quickfix_ruby.rb +82 -0
  134. data/lib/quickfixt11.rb +70 -0
  135. data/spec/FIX40.xml +862 -0
  136. data/spec/FIX41.xml +1285 -0
  137. data/spec/FIX42.xml +2746 -0
  138. data/spec/FIX43.xml +4229 -0
  139. data/spec/FIX44.xml +6596 -0
  140. data/spec/FIX50.xml +8137 -0
  141. data/spec/FIX50SP1.xml +9496 -0
  142. data/spec/FIX50SP2.xml +10011 -0
  143. data/spec/FIXT11.xml +313 -0
  144. data/test/test_DataDictionaryTestCase.rb +268 -0
  145. data/test/test_DictionaryTestCase.rb +112 -0
  146. data/test/test_FieldBaseTestCase.rb +24 -0
  147. data/test/test_MessageTestCase.rb +368 -0
  148. data/test/test_SessionSettingsTestCase.rb +41 -0
  149. metadata +193 -0
@@ -0,0 +1,618 @@
1
+ /****************************************************************************
2
+ ** Copyright (c) 2001-2014
3
+ **
4
+ ** This file is part of the QuickFIX FIX Engine
5
+ **
6
+ ** This file may be distributed under the terms of the quickfixengine.org
7
+ ** license as defined by quickfixengine.org and appearing in the file
8
+ ** LICENSE included in the packaging of this file.
9
+ **
10
+ ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
11
+ ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
+ **
13
+ ** See http://www.quickfixengine.org/LICENSE for licensing information.
14
+ **
15
+ ** Contact ask@quickfixengine.org if any conditions of this licensing are
16
+ ** not clear to you.
17
+ **
18
+ ****************************************************************************/
19
+
20
+ #ifdef _MSC_VER
21
+ #include "stdafx.h"
22
+ #else
23
+ #include "config.h"
24
+ #endif
25
+
26
+ #include "DataDictionary.h"
27
+ #include "Message.h"
28
+ #include <fstream>
29
+ #include <memory>
30
+
31
+ #include "PUGIXML_DOMDocument.h"
32
+
33
+ #ifdef _MSC_VER
34
+ #define RESET_AUTO_PTR(OLD, NEW) OLD = NEW;
35
+ #else
36
+ #define RESET_AUTO_PTR(OLD, NEW) OLD.reset( NEW.release() );
37
+ #endif
38
+
39
+ namespace FIX
40
+ {
41
+ DataDictionary::DataDictionary()
42
+ : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
43
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
44
+ {}
45
+
46
+ DataDictionary::DataDictionary( std::istream& stream )
47
+ throw( ConfigError )
48
+ : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
49
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true )
50
+ {
51
+ readFromStream( stream );
52
+ }
53
+
54
+ DataDictionary::DataDictionary( const std::string& url )
55
+ throw( ConfigError )
56
+ : m_hasVersion( false ), m_checkFieldsOutOfOrder( true ),
57
+ m_checkFieldsHaveValues( true ), m_checkUserDefinedFields( true ),
58
+ m_orderedFieldsArray(0)
59
+ {
60
+ readFromURL( url );
61
+ }
62
+
63
+ DataDictionary::DataDictionary( const DataDictionary& copy )
64
+ {
65
+ *this = copy;
66
+ }
67
+
68
+ DataDictionary::~DataDictionary()
69
+ {
70
+ FieldToGroup::iterator i;
71
+ for ( i = m_groups.begin(); i != m_groups.end(); ++i )
72
+ {
73
+ const FieldPresenceMap& presenceMap = i->second;
74
+
75
+ FieldPresenceMap::const_iterator iter = presenceMap.begin();
76
+ for ( ; iter != presenceMap.end(); ++iter )
77
+ delete iter->second.second;
78
+ }
79
+ }
80
+
81
+ DataDictionary& DataDictionary::operator=( const DataDictionary& rhs )
82
+ {
83
+ m_hasVersion = rhs.m_hasVersion;
84
+ m_checkFieldsOutOfOrder = rhs.m_checkFieldsOutOfOrder;
85
+ m_checkFieldsHaveValues = rhs.m_checkFieldsHaveValues;
86
+ m_checkUserDefinedFields = rhs.m_checkUserDefinedFields;
87
+ m_beginString = rhs.m_beginString;
88
+ m_messageFields = rhs.m_messageFields;
89
+ m_requiredFields = rhs.m_requiredFields;
90
+ m_messages = rhs.m_messages;
91
+ m_fields = rhs.m_fields;
92
+ m_orderedFields = rhs.m_orderedFields;
93
+ m_orderedFieldsArray = rhs.m_orderedFieldsArray;
94
+ m_headerFields = rhs.m_headerFields;
95
+ m_trailerFields = rhs.m_trailerFields;
96
+ m_fieldTypes = rhs.m_fieldTypes;
97
+ m_fieldValues = rhs.m_fieldValues;
98
+ m_fieldNames = rhs.m_fieldNames;
99
+ m_names = rhs.m_names;
100
+ m_valueNames = rhs.m_valueNames;
101
+ m_dataFields = rhs.m_dataFields;
102
+
103
+ FieldToGroup::const_iterator i = rhs.m_groups.begin();
104
+ for ( ; i != rhs.m_groups.end(); ++i )
105
+ {
106
+ const FieldPresenceMap& presenceMap = i->second;
107
+
108
+ FieldPresenceMap::const_iterator iter = presenceMap.begin();
109
+ for ( ; iter != presenceMap.end(); ++iter )
110
+ {
111
+ addGroup( iter->first, i->first, iter->second.first, *iter->second.second );
112
+ }
113
+ }
114
+ return *this;
115
+ }
116
+
117
+ void DataDictionary::validate( const Message& message,
118
+ const DataDictionary* const pSessionDD,
119
+ const DataDictionary* const pAppDD )
120
+ throw( FIX::Exception )
121
+ {
122
+ const Header& header = message.getHeader();
123
+ const BeginString& beginString = FIELD_GET_REF( header, BeginString );
124
+ const MsgType& msgType = FIELD_GET_REF( header, MsgType );
125
+ if ( pSessionDD != 0 && pSessionDD->m_hasVersion )
126
+ {
127
+ if( pSessionDD->getVersion() != beginString )
128
+ {
129
+ throw UnsupportedVersion();
130
+ }
131
+ }
132
+
133
+ int field = 0;
134
+ if( (pSessionDD !=0 && pSessionDD->m_checkFieldsOutOfOrder) ||
135
+ (pAppDD != 0 && pAppDD->m_checkFieldsOutOfOrder) )
136
+ {
137
+ if ( !message.hasValidStructure(field) )
138
+ throw TagOutOfOrder(field);
139
+ }
140
+
141
+ if ( pAppDD != 0 && pAppDD->m_hasVersion )
142
+ {
143
+ pAppDD->checkMsgType( msgType );
144
+ pAppDD->checkHasRequired( message.getHeader(), message, message.getTrailer(), msgType );
145
+ }
146
+
147
+ if( pSessionDD != 0 )
148
+ {
149
+ pSessionDD->iterate( message.getHeader(), msgType );
150
+ pSessionDD->iterate( message.getTrailer(), msgType );
151
+ }
152
+
153
+ if( pAppDD != 0 )
154
+ {
155
+ pAppDD->iterate( message, msgType );
156
+ }
157
+ }
158
+
159
+ void DataDictionary::iterate( const FieldMap& map, const MsgType& msgType ) const
160
+ {
161
+ int lastField = 0;
162
+
163
+ FieldMap::iterator i;
164
+ for ( i = map.begin(); i != map.end(); ++i )
165
+ {
166
+ const FieldBase& field = i->second;
167
+ if( i != map.begin() && (field.getField() == lastField) )
168
+ throw RepeatedTag( lastField );
169
+ checkHasValue( field );
170
+
171
+ if ( m_hasVersion )
172
+ {
173
+ checkValidFormat( field );
174
+ checkValue( field );
175
+ }
176
+
177
+ if ( m_beginString.getValue().length() && shouldCheckTag(field) )
178
+ {
179
+ checkValidTagNumber( field );
180
+ if ( !Message::isHeaderField( field, this )
181
+ && !Message::isTrailerField( field, this ) )
182
+ {
183
+ checkIsInMessage( field, msgType );
184
+ checkGroupCount( field, map, msgType );
185
+ }
186
+ }
187
+ lastField = field.getField();
188
+ }
189
+ }
190
+
191
+ void DataDictionary::readFromURL( const std::string& url )
192
+ throw( ConfigError )
193
+ {
194
+ DOMDocumentPtr pDoc = DOMDocumentPtr(new PUGIXML_DOMDocument());
195
+
196
+ if(!pDoc->load(url))
197
+ throw ConfigError(url + ": Could not parse data dictionary file");
198
+
199
+ try
200
+ {
201
+ readFromDocument( pDoc );
202
+ }
203
+ catch( ConfigError& e )
204
+ {
205
+ throw ConfigError( url + ": " + e.what() );
206
+ }
207
+ }
208
+
209
+ void DataDictionary::readFromStream( std::istream& stream )
210
+ throw( ConfigError )
211
+ {
212
+ DOMDocumentPtr pDoc = DOMDocumentPtr(new PUGIXML_DOMDocument());
213
+
214
+ if(!pDoc->load(stream))
215
+ throw ConfigError("Could not parse data dictionary stream");
216
+
217
+ readFromDocument( pDoc );
218
+ }
219
+
220
+ void DataDictionary::readFromDocument( DOMDocumentPtr pDoc )
221
+ throw( ConfigError )
222
+ {
223
+ // VERSION
224
+ DOMNodePtr pFixNode = pDoc->getNode("/fix");
225
+ if(!pFixNode.get())
226
+ throw ConfigError("Could not parse data dictionary file"
227
+ ", or no <fix> node found at root");
228
+ DOMAttributesPtr attrs = pFixNode->getAttributes();
229
+ std::string type = "FIX";
230
+ if(attrs->get("type", type))
231
+ {
232
+ if(type != "FIX" && type != "FIXT")
233
+ throw ConfigError("type attribute must be FIX or FIXT");
234
+ }
235
+ std::string major;
236
+ if(!attrs->get("major", major))
237
+ throw ConfigError("major attribute not found on <fix>");
238
+ std::string minor;
239
+ if(!attrs->get("minor", minor))
240
+ throw ConfigError("minor attribute not found on <fix>");
241
+ setVersion(type + "." + major + "." + minor);
242
+
243
+ // FIELDS
244
+ DOMNodePtr pFieldsNode = pDoc->getNode("/fix/fields");
245
+ if(!pFieldsNode.get())
246
+ throw ConfigError("<fields> section not found in data dictionary");
247
+
248
+ DOMNodePtr pFieldNode = pFieldsNode->getFirstChildNode();
249
+ if(!pFieldNode.get()) throw ConfigError("No fields defined");
250
+
251
+ while(pFieldNode.get())
252
+ {
253
+ if(pFieldNode->getName() == "field")
254
+ {
255
+ DOMAttributesPtr attrs = pFieldNode->getAttributes();
256
+ std::string name;
257
+ if(!attrs->get("name", name))
258
+ throw ConfigError("<field> does not have a name attribute");
259
+ std::string number;
260
+ if(!attrs->get("number", number))
261
+ throw ConfigError("<field> " + name + " does not have a number attribute");
262
+ int num = atoi(number.c_str());
263
+ std::string type;
264
+ if(!attrs->get("type", type))
265
+ throw ConfigError("<field> " + name + " does not have a type attribute");
266
+ addField(num);
267
+ addFieldType(num, XMLTypeToType(type));
268
+ addFieldName(num, name);
269
+
270
+ DOMNodePtr pFieldValueNode = pFieldNode->getFirstChildNode();
271
+ while(pFieldValueNode.get())
272
+ {
273
+ if(pFieldValueNode->getName() == "value")
274
+ {
275
+ DOMAttributesPtr attrs = pFieldValueNode->getAttributes();
276
+ std::string enumeration;
277
+ if(!attrs->get("enum", enumeration))
278
+ throw ConfigError("<value> does not have enum attribute in field " + name);
279
+ addFieldValue(num, enumeration);
280
+ std::string description;
281
+ if(attrs->get("description", description))
282
+ addValueName(num, enumeration, description);
283
+ }
284
+ RESET_AUTO_PTR(pFieldValueNode, pFieldValueNode->getNextSiblingNode());
285
+ }
286
+ }
287
+ RESET_AUTO_PTR(pFieldNode, pFieldNode->getNextSiblingNode());
288
+ }
289
+
290
+ // HEADER
291
+ if( type == "FIXT" || (type == "FIX" && major < "5") )
292
+ {
293
+ DOMNodePtr pHeaderNode = pDoc->getNode("/fix/header");
294
+ if(!pHeaderNode.get())
295
+ throw ConfigError("<header> section not found in data dictionary");
296
+
297
+ DOMNodePtr pHeaderFieldNode = pHeaderNode->getFirstChildNode();
298
+ if(!pHeaderFieldNode.get()) throw ConfigError("No header fields defined");
299
+
300
+ while(pHeaderFieldNode.get())
301
+ {
302
+ if(pHeaderFieldNode->getName() == "field" || pHeaderFieldNode->getName() == "group" )
303
+ {
304
+ DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
305
+ std::string name;
306
+ if(!attrs->get("name", name))
307
+ throw ConfigError("<field> does not have a name attribute");
308
+ std::string required = "false";
309
+ attrs->get("required", required);
310
+ addHeaderField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
311
+ }
312
+ if(pHeaderFieldNode->getName() == "group")
313
+ {
314
+ DOMAttributesPtr attrs = pHeaderFieldNode->getAttributes();
315
+ std::string required;
316
+ attrs->get("required", required);
317
+ bool isRequired = (required == "Y" || required == "y");
318
+ addXMLGroup(pDoc.get(), pHeaderFieldNode.get(), "_header_", *this, isRequired);
319
+ }
320
+
321
+ RESET_AUTO_PTR(pHeaderFieldNode, pHeaderFieldNode->getNextSiblingNode());
322
+ }
323
+ }
324
+
325
+ // TRAILER
326
+ if( type == "FIXT" || (type == "FIX" && major < "5") )
327
+ {
328
+ DOMNodePtr pTrailerNode = pDoc->getNode("/fix/trailer");
329
+ if(!pTrailerNode.get())
330
+ throw ConfigError("<trailer> section not found in data dictionary");
331
+
332
+ DOMNodePtr pTrailerFieldNode = pTrailerNode->getFirstChildNode();
333
+ if(!pTrailerFieldNode.get()) throw ConfigError("No trailer fields defined");
334
+
335
+ while(pTrailerFieldNode.get())
336
+ {
337
+ if(pTrailerFieldNode->getName() == "field" || pTrailerFieldNode->getName() == "group" )
338
+ {
339
+ DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
340
+ std::string name;
341
+ if(!attrs->get("name", name))
342
+ throw ConfigError("<field> does not have a name attribute");
343
+ std::string required = "false";
344
+ attrs->get("required", required);
345
+ addTrailerField(lookupXMLFieldNumber(pDoc.get(), name), required == "true");
346
+ }
347
+ if(pTrailerFieldNode->getName() == "group")
348
+ {
349
+ DOMAttributesPtr attrs = pTrailerFieldNode->getAttributes();
350
+ std::string required;
351
+ attrs->get("required", required);
352
+ bool isRequired = (required == "Y" || required == "y");
353
+ addXMLGroup(pDoc.get(), pTrailerFieldNode.get(), "_trailer_", *this, isRequired);
354
+ }
355
+
356
+ RESET_AUTO_PTR(pTrailerFieldNode, pTrailerFieldNode->getNextSiblingNode());
357
+ }
358
+ }
359
+
360
+ // MSGTYPE
361
+ DOMNodePtr pMessagesNode = pDoc->getNode("/fix/messages");
362
+ if(!pMessagesNode.get())
363
+ throw ConfigError("<messages> section not found in data dictionary");
364
+
365
+ DOMNodePtr pMessageNode = pMessagesNode->getFirstChildNode();
366
+ if(!pMessageNode.get()) throw ConfigError("No messages defined");
367
+
368
+ while(pMessageNode.get())
369
+ {
370
+ if(pMessageNode->getName() == "message")
371
+ {
372
+ DOMAttributesPtr attrs = pMessageNode->getAttributes();
373
+ std::string msgtype;
374
+ if(!attrs->get("msgtype", msgtype))
375
+ throw ConfigError("<field> does not have a name attribute");
376
+ addMsgType(msgtype);
377
+
378
+ std::string name;
379
+ if(attrs->get("name", name))
380
+ addValueName( 35, msgtype, name );
381
+
382
+ DOMNodePtr pMessageFieldNode = pMessageNode->getFirstChildNode();
383
+ while( pMessageFieldNode.get() )
384
+ {
385
+ if(pMessageFieldNode->getName() == "field"
386
+ || pMessageFieldNode->getName() == "group")
387
+ {
388
+ DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
389
+ std::string name;
390
+ if(!attrs->get("name", name))
391
+ throw ConfigError("<field> does not have a name attribute");
392
+ int num = lookupXMLFieldNumber(pDoc.get(), name);
393
+ addMsgField(msgtype, num);
394
+
395
+ std::string required;
396
+ if(attrs->get("required", required)
397
+ && (required == "Y" || required == "y"))
398
+ {
399
+ addRequiredField(msgtype, num);
400
+ }
401
+ }
402
+ else if(pMessageFieldNode->getName() == "component")
403
+ {
404
+ DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
405
+ std::string required;
406
+ attrs->get("required", required);
407
+ bool isRequired = (required == "Y" || required == "y");
408
+ addXMLComponentFields(pDoc.get(), pMessageFieldNode.get(),
409
+ msgtype, *this, isRequired);
410
+ }
411
+ if(pMessageFieldNode->getName() == "group")
412
+ {
413
+ DOMAttributesPtr attrs = pMessageFieldNode->getAttributes();
414
+ std::string required;
415
+ attrs->get("required", required);
416
+ bool isRequired = (required == "Y" || required == "y");
417
+ addXMLGroup(pDoc.get(), pMessageFieldNode.get(), msgtype, *this, isRequired);
418
+ }
419
+ RESET_AUTO_PTR(pMessageFieldNode,
420
+ pMessageFieldNode->getNextSiblingNode());
421
+ }
422
+ }
423
+ RESET_AUTO_PTR(pMessageNode, pMessageNode->getNextSiblingNode());
424
+ }
425
+ }
426
+
427
+ message_order const& DataDictionary::getOrderedFields() const
428
+ {
429
+ if( m_orderedFieldsArray ) return m_orderedFieldsArray;
430
+
431
+ int * tmp = new int[m_orderedFields.size() + 1];
432
+ int * i = tmp;
433
+
434
+ OrderedFields::const_iterator iter;
435
+ for( iter = m_orderedFields.begin(); iter != m_orderedFields.end(); *(i++) = *(iter++) ) {}
436
+ *i = 0;
437
+
438
+ m_orderedFieldsArray = message_order(tmp);
439
+ delete [] tmp;
440
+
441
+ return m_orderedFieldsArray;
442
+ }
443
+
444
+ int DataDictionary::lookupXMLFieldNumber( DOMDocument* pDoc, DOMNode* pNode ) const
445
+ {
446
+ DOMAttributesPtr attrs = pNode->getAttributes();
447
+ std::string name;
448
+ if(!attrs->get("name", name))
449
+ throw ConfigError("No name given to field");
450
+ return lookupXMLFieldNumber( pDoc, name );
451
+ }
452
+
453
+ int DataDictionary::lookupXMLFieldNumber
454
+ ( DOMDocument* pDoc, const std::string& name ) const
455
+ {
456
+ NameToField::const_iterator i = m_names.find(name);
457
+ if( i == m_names.end() )
458
+ throw ConfigError("Field " + name + " not defined in fields section");
459
+ return i->second;
460
+ }
461
+
462
+ int DataDictionary::addXMLComponentFields( DOMDocument* pDoc, DOMNode* pNode,
463
+ const std::string& msgtype,
464
+ DataDictionary& DD,
465
+ bool componentRequired )
466
+ {
467
+ int firstField = 0;
468
+
469
+ DOMAttributesPtr attrs = pNode->getAttributes();
470
+ std::string name;
471
+ if(!attrs->get("name", name))
472
+ throw ConfigError("No name given to component");
473
+
474
+ DOMNodePtr pComponentNode =
475
+ pDoc->getNode("/fix/components/component[@name='" + name + "']");
476
+ if(pComponentNode.get() == 0)
477
+ throw ConfigError("Component not found");
478
+
479
+ DOMNodePtr pComponentFieldNode = pComponentNode->getFirstChildNode();
480
+ while(pComponentFieldNode.get())
481
+ {
482
+ if(pComponentFieldNode->getName() == "field"
483
+ || pComponentFieldNode->getName() == "group")
484
+ {
485
+ DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
486
+ std::string name;
487
+ if(!attrs->get("name", name))
488
+ throw ConfigError("No name given to field");
489
+ int field = lookupXMLFieldNumber(pDoc, name);
490
+ if( firstField == 0 ) firstField = field;
491
+
492
+ std::string required;
493
+ if(attrs->get("required", required)
494
+ && (required == "Y" || required =="y")
495
+ && componentRequired)
496
+ {
497
+ addRequiredField(msgtype, field);
498
+ }
499
+
500
+ DD.addField(field);
501
+ DD.addMsgField(msgtype, field);
502
+ }
503
+ if(pComponentFieldNode->getName() == "component")
504
+ {
505
+ DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
506
+ std::string required;
507
+ attrs->get("required", required);
508
+ bool isRequired = (required == "Y" || required == "y");
509
+ addXMLComponentFields(pDoc, pComponentFieldNode.get(),
510
+ msgtype, DD, isRequired);
511
+ }
512
+ if(pComponentFieldNode->getName() == "group")
513
+ {
514
+ DOMAttributesPtr attrs = pComponentFieldNode->getAttributes();
515
+ std::string required;
516
+ attrs->get("required", required);
517
+ bool isRequired = (required == "Y" || required == "y");
518
+ addXMLGroup(pDoc, pComponentFieldNode.get(), msgtype, DD, isRequired);
519
+ }
520
+ RESET_AUTO_PTR(pComponentFieldNode,
521
+ pComponentFieldNode->getNextSiblingNode());
522
+ }
523
+ return firstField;
524
+ }
525
+
526
+ void DataDictionary::addXMLGroup( DOMDocument* pDoc, DOMNode* pNode,
527
+ const std::string& msgtype,
528
+ DataDictionary& DD, bool groupRequired )
529
+ {
530
+ DOMAttributesPtr attrs = pNode->getAttributes();
531
+ std::string name;
532
+ if(!attrs->get("name", name))
533
+ throw ConfigError("No name given to group");
534
+ int group = lookupXMLFieldNumber( pDoc, name );
535
+ int delim = 0;
536
+ int field = 0;
537
+ DataDictionary groupDD;
538
+ DOMNodePtr node = pNode->getFirstChildNode();
539
+ while(node.get())
540
+ {
541
+ if( node->getName() == "field" )
542
+ {
543
+ field = lookupXMLFieldNumber( pDoc, node.get() );
544
+ groupDD.addField( field );
545
+
546
+ DOMAttributesPtr attrs = node->getAttributes();
547
+ std::string required;
548
+ if( attrs->get("required", required)
549
+ && ( required == "Y" || required =="y" )
550
+ && groupRequired )
551
+ {
552
+ groupDD.addRequiredField(msgtype, field);
553
+ }
554
+ }
555
+ else if( node->getName() == "component" )
556
+ {
557
+ field = addXMLComponentFields( pDoc, node.get(), msgtype, groupDD, false );
558
+ }
559
+ else if( node->getName() == "group" )
560
+ {
561
+ field = lookupXMLFieldNumber( pDoc, node.get() );
562
+ groupDD.addField( field );
563
+ DOMAttributesPtr attrs = node->getAttributes();
564
+ std::string required;
565
+ if( attrs->get("required", required )
566
+ && ( required == "Y" || required =="y" )
567
+ && groupRequired)
568
+ {
569
+ groupDD.addRequiredField(msgtype, field);
570
+ }
571
+ bool isRequired = false;
572
+ if( attrs->get("required", required) )
573
+ isRequired = (required == "Y" || required == "y");
574
+ addXMLGroup( pDoc, node.get(), msgtype, groupDD, isRequired );
575
+ }
576
+ if( delim == 0 ) delim = field;
577
+ RESET_AUTO_PTR(node, node->getNextSiblingNode());
578
+ }
579
+
580
+ if( delim ) DD.addGroup( msgtype, group, delim, groupDD );
581
+ }
582
+
583
+ TYPE::Type DataDictionary::XMLTypeToType( const std::string& type ) const
584
+ {
585
+ if ( m_beginString < "FIX.4.2" && type == "CHAR" )
586
+ return TYPE::String;
587
+
588
+ if ( type == "STRING" ) return TYPE::String;
589
+ if ( type == "CHAR" ) return TYPE::Char;
590
+ if ( type == "PRICE" ) return TYPE::Price;
591
+ if ( type == "INT" ) return TYPE::Int;
592
+ if ( type == "AMT" ) return TYPE::Amt;
593
+ if ( type == "QTY" ) return TYPE::Qty;
594
+ if ( type == "CURRENCY" ) return TYPE::Currency;
595
+ if ( type == "MULTIPLEVALUESTRING" ) return TYPE::MultipleValueString;
596
+ if ( type == "MULTIPLESTRINGVALUE" ) return TYPE::MultipleStringValue;
597
+ if ( type == "MULTIPLECHARVALUE" ) return TYPE::MultipleCharValue;
598
+ if ( type == "EXCHANGE" ) return TYPE::Exchange;
599
+ if ( type == "UTCTIMESTAMP" ) return TYPE::UtcTimeStamp;
600
+ if ( type == "BOOLEAN" ) return TYPE::Boolean;
601
+ if ( type == "LOCALMKTDATE" ) return TYPE::LocalMktDate;
602
+ if ( type == "DATA" ) return TYPE::Data;
603
+ if ( type == "FLOAT" ) return TYPE::Float;
604
+ if ( type == "PRICEOFFSET" ) return TYPE::PriceOffset;
605
+ if ( type == "MONTHYEAR" ) return TYPE::MonthYear;
606
+ if ( type == "DAYOFMONTH" ) return TYPE::DayOfMonth;
607
+ if ( type == "UTCDATE" ) return TYPE::UtcDate;
608
+ if ( type == "UTCDATEONLY" ) return TYPE::UtcDateOnly;
609
+ if ( type == "UTCTIMEONLY" ) return TYPE::UtcTimeOnly;
610
+ if ( type == "NUMINGROUP" ) return TYPE::NumInGroup;
611
+ if ( type == "PERCENTAGE" ) return TYPE::Percentage;
612
+ if ( type == "SEQNUM" ) return TYPE::SeqNum;
613
+ if ( type == "LENGTH" ) return TYPE::Length;
614
+ if ( type == "COUNTRY" ) return TYPE::Country;
615
+ if ( type == "TIME" ) return TYPE::UtcTimeStamp;
616
+ return TYPE::Unknown;
617
+ }
618
+ }