quickfix_ruby 1.14.3

Sign up to get free protection for your applications and to get access to all the features.
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
+ }