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,580 @@
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 "Message.h"
27
+ #include "Utility.h"
28
+ #include "Values.h"
29
+ #include <iomanip>
30
+
31
+ namespace FIX
32
+ {
33
+ std::auto_ptr<DataDictionary> Message::s_dataDictionary;
34
+
35
+ Message::Message()
36
+ : m_validStructure( true ) {}
37
+
38
+ Message::Message( const std::string& string, bool validate )
39
+ throw( InvalidMessage )
40
+ : m_validStructure( true )
41
+ {
42
+ setString( string, validate );
43
+ }
44
+
45
+ Message::Message( const std::string& string,
46
+ const DataDictionary& dataDictionary,
47
+ bool validate )
48
+ throw( InvalidMessage )
49
+ : m_validStructure( true )
50
+ {
51
+ setString( string, validate, &dataDictionary, &dataDictionary );
52
+ }
53
+
54
+ Message::Message( const std::string& string,
55
+ const DataDictionary& sessionDataDictionary,
56
+ const DataDictionary& applicationDataDictionary,
57
+ bool validate )
58
+ throw( InvalidMessage )
59
+ : m_validStructure( true )
60
+ {
61
+ setStringHeader( string );
62
+ if( isAdmin() )
63
+ setString( string, validate, &sessionDataDictionary, &sessionDataDictionary );
64
+ else
65
+ setString( string, validate, &sessionDataDictionary, &applicationDataDictionary );
66
+ }
67
+
68
+ bool Message::InitializeXML( const std::string& url )
69
+ {
70
+ try
71
+ {
72
+ std::auto_ptr<DataDictionary> p =
73
+ std::auto_ptr<DataDictionary>(new DataDictionary(url));
74
+ s_dataDictionary = p;
75
+ return true;
76
+ }
77
+ catch( ConfigError& )
78
+ { return false; }
79
+ }
80
+
81
+ void Message::reverseRoute( const Header& header )
82
+ {
83
+ // required routing tags
84
+ BeginString beginString;
85
+ SenderCompID senderCompID;
86
+ TargetCompID targetCompID;
87
+
88
+ m_header.removeField( beginString.getField() );
89
+ m_header.removeField( senderCompID.getField() );
90
+ m_header.removeField( targetCompID.getField() );
91
+
92
+ if( header.getFieldIfSet( beginString ) )
93
+ {
94
+ if( beginString.getValue().size() )
95
+ m_header.setField( beginString );
96
+
97
+ OnBehalfOfLocationID onBehalfOfLocationID;
98
+ DeliverToLocationID deliverToLocationID;
99
+
100
+ m_header.removeField( onBehalfOfLocationID.getField() );
101
+ m_header.removeField( deliverToLocationID.getField() );
102
+
103
+ if( beginString >= BeginString_FIX41 )
104
+ {
105
+ if( header.getFieldIfSet( onBehalfOfLocationID ) )
106
+ {
107
+ if( onBehalfOfLocationID.getValue().size() )
108
+ m_header.setField( DeliverToLocationID( onBehalfOfLocationID ) );
109
+ }
110
+
111
+ if( header.getFieldIfSet( deliverToLocationID ) )
112
+ {
113
+ if( deliverToLocationID.getValue().size() )
114
+ m_header.setField( OnBehalfOfLocationID( deliverToLocationID ) );
115
+ }
116
+ }
117
+ }
118
+
119
+ if( header.getFieldIfSet( senderCompID ) )
120
+ {
121
+ if( senderCompID.getValue().size() )
122
+ m_header.setField( TargetCompID( senderCompID ) );
123
+ }
124
+
125
+ if( header.getFieldIfSet( targetCompID ) )
126
+ {
127
+ if( targetCompID.getValue().size() )
128
+ m_header.setField( SenderCompID( targetCompID ) );
129
+ }
130
+
131
+ // optional routing tags
132
+ OnBehalfOfCompID onBehalfOfCompID;
133
+ OnBehalfOfSubID onBehalfOfSubID;
134
+ DeliverToCompID deliverToCompID;
135
+ DeliverToSubID deliverToSubID;
136
+
137
+ m_header.removeField( onBehalfOfCompID.getField() );
138
+ m_header.removeField( onBehalfOfSubID.getField() );
139
+ m_header.removeField( deliverToCompID.getField() );
140
+ m_header.removeField( deliverToSubID.getField() );
141
+
142
+ if( header.getFieldIfSet( onBehalfOfCompID ) )
143
+ {
144
+ if( onBehalfOfCompID.getValue().size() )
145
+ m_header.setField( DeliverToCompID( onBehalfOfCompID ) );
146
+ }
147
+
148
+ if( header.getFieldIfSet( onBehalfOfSubID ) )
149
+ {
150
+ if( onBehalfOfSubID.getValue().size() )
151
+ m_header.setField( DeliverToSubID( onBehalfOfSubID ) );
152
+ }
153
+
154
+ if( header.getFieldIfSet( deliverToCompID ) )
155
+ {
156
+ if( deliverToCompID.getValue().size() )
157
+ m_header.setField( OnBehalfOfCompID( deliverToCompID ) );
158
+ }
159
+
160
+ if( header.getFieldIfSet( deliverToSubID ) )
161
+ {
162
+ if( deliverToSubID.getValue().size() )
163
+ m_header.setField( OnBehalfOfSubID( deliverToSubID ) );
164
+ }
165
+ }
166
+
167
+ std::string Message::toString( int beginStringField,
168
+ int bodyLengthField,
169
+ int checkSumField ) const
170
+ {
171
+ std::string str;
172
+ return toString( str, beginStringField, bodyLengthField, checkSumField );
173
+ }
174
+
175
+ std::string& Message::toString( std::string& str,
176
+ int beginStringField,
177
+ int bodyLengthField,
178
+ int checkSumField ) const
179
+ {
180
+ int length = bodyLength( beginStringField, bodyLengthField, checkSumField );
181
+ m_header.setField( IntField(bodyLengthField, length) );
182
+ m_trailer.setField( CheckSumField(checkSumField, checkSum(checkSumField)) );
183
+
184
+ #if defined(_MSC_VER) && _MSC_VER < 1300
185
+ str = "";
186
+ #else
187
+ str.clear();
188
+ #endif
189
+
190
+ /*small speculation about the space needed for FIX string*/
191
+ str.reserve( length + 64 );
192
+
193
+ m_header.calculateString( str );
194
+ FieldMap::calculateString( str );
195
+ m_trailer.calculateString( str );
196
+
197
+ return str;
198
+ }
199
+
200
+ std::string Message::toXML() const
201
+ {
202
+ std::string str;
203
+ return toXML( str );
204
+ }
205
+
206
+ std::string& Message::toXML( std::string& str ) const
207
+ {
208
+ std::stringstream stream;
209
+ stream << "<message>" << std::endl
210
+ << std::setw(2) << " " << "<header>" << std::endl
211
+ << toXMLFields(getHeader(), 4)
212
+ << std::setw(2) << " " << "</header>" << std::endl
213
+ << std::setw(2) << " " << "<body>" << std::endl
214
+ << toXMLFields(*this, 4)
215
+ << std::setw(2) << " " << "</body>" << std::endl
216
+ << std::setw(2) << " " << "<trailer>" << std::endl
217
+ << toXMLFields(getTrailer(), 4)
218
+ << std::setw(2) << " " << "</trailer>" << std::endl
219
+ << "</message>";
220
+
221
+ return str = stream.str();
222
+ }
223
+
224
+ std::string Message::toXMLFields(const FieldMap& fields, int space) const
225
+ {
226
+ std::stringstream stream;
227
+ FieldMap::iterator i;
228
+ std::string name;
229
+ for(i = fields.begin(); i != fields.end(); ++i)
230
+ {
231
+ int field = i->first;
232
+ std::string value = i->second.getString();
233
+
234
+ stream << std::setw(space) << " " << "<field ";
235
+ if(s_dataDictionary.get() && s_dataDictionary->getFieldName(field, name))
236
+ {
237
+ stream << "name=\"" << name << "\" ";
238
+ }
239
+ stream << "number=\"" << field << "\"";
240
+ if(s_dataDictionary.get()
241
+ && s_dataDictionary->getValueName(field, value, name))
242
+ {
243
+ stream << " enum=\"" << name << "\"";
244
+ }
245
+ stream << ">";
246
+ stream << "<![CDATA[" << value << "]]>";
247
+ stream << "</field>" << std::endl;
248
+ }
249
+
250
+ FieldMap::g_iterator j;
251
+ for(j = fields.g_begin(); j != fields.g_end(); ++j)
252
+ {
253
+ std::vector<FieldMap*>::const_iterator k;
254
+ for(k = j->second.begin(); k != j->second.end(); ++k)
255
+ {
256
+ stream << std::setw(space) << " " << "<group>" << std::endl
257
+ << toXMLFields(*(*k), space+2)
258
+ << std::setw(space) << " " << "</group>" << std::endl;
259
+ }
260
+ }
261
+
262
+ return stream.str();
263
+ }
264
+
265
+ void Message::setString( const std::string& string,
266
+ bool doValidation,
267
+ const DataDictionary* pSessionDataDictionary,
268
+ const DataDictionary* pApplicationDataDictionary )
269
+ throw( InvalidMessage )
270
+ {
271
+ clear();
272
+
273
+ std::string::size_type pos = 0;
274
+ int count = 0;
275
+ std::string msg;
276
+
277
+ static int const headerOrder[] =
278
+ {
279
+ FIELD::BeginString,
280
+ FIELD::BodyLength,
281
+ FIELD::MsgType
282
+ };
283
+
284
+ field_type type = header;
285
+
286
+ while ( pos < string.size() )
287
+ {
288
+ FieldBase field = extractField( string, pos, pSessionDataDictionary, pApplicationDataDictionary );
289
+ if ( count < 3 && headerOrder[ count++ ] != field.getField() )
290
+ if ( doValidation ) throw InvalidMessage("Header fields out of order");
291
+
292
+ if ( isHeaderField( field, pSessionDataDictionary ) )
293
+ {
294
+ if ( type != header )
295
+ {
296
+ if(m_field == 0) m_field = field.getField();
297
+ m_validStructure = false;
298
+ }
299
+
300
+ if ( field.getField() == FIELD::MsgType )
301
+ msg = field.getString();
302
+
303
+ m_header.setField( field, false );
304
+
305
+ if ( pSessionDataDictionary )
306
+ setGroup( "_header_", field, string, pos, getHeader(), *pSessionDataDictionary );
307
+ }
308
+ else if ( isTrailerField( field, pSessionDataDictionary ) )
309
+ {
310
+ type = trailer;
311
+ m_trailer.setField( field, false );
312
+
313
+ if ( pSessionDataDictionary )
314
+ setGroup( "_trailer_", field, string, pos, getTrailer(), *pSessionDataDictionary );
315
+ }
316
+ else
317
+ {
318
+ if ( type == trailer )
319
+ {
320
+ if(m_field == 0) m_field = field.getField();
321
+ m_validStructure = false;
322
+ }
323
+
324
+ type = body;
325
+ setField( field, false );
326
+
327
+ if ( pApplicationDataDictionary )
328
+ setGroup( msg, field, string, pos, *this, *pApplicationDataDictionary );
329
+ }
330
+ }
331
+
332
+ if ( doValidation )
333
+ validate();
334
+ }
335
+
336
+ void Message::setGroup( const std::string& msg, const FieldBase& field,
337
+ const std::string& string,
338
+ std::string::size_type& pos, FieldMap& map,
339
+ const DataDictionary& dataDictionary )
340
+ {
341
+ int group = field.getField();
342
+ int delim;
343
+ const DataDictionary* pDD = 0;
344
+ if ( !dataDictionary.getGroup( msg, group, delim, pDD ) ) return ;
345
+ std::auto_ptr<Group> pGroup;
346
+
347
+ while ( pos < string.size() )
348
+ {
349
+ std::string::size_type oldPos = pos;
350
+ FieldBase field = extractField( string, pos, &dataDictionary, &dataDictionary, pGroup.get() );
351
+
352
+ // Start a new group because...
353
+ if (// found delimiter
354
+ (field.getField() == delim) ||
355
+ // no delimiter, but field belongs to group OR field already processed
356
+ (pDD->isField( field.getField() ) && (pGroup.get() == 0 || pGroup->isSetField( field.getField() )) ))
357
+ {
358
+ if ( pGroup.get() )
359
+ {
360
+ map.addGroupPtr( group, pGroup.release(), false );
361
+ }
362
+ pGroup.reset( new Group( field.getField(), delim, pDD->getOrderedFields() ) );
363
+ }
364
+ else if ( !pDD->isField( field.getField() ) )
365
+ {
366
+ if ( pGroup.get() )
367
+ {
368
+ map.addGroupPtr( group, pGroup.release(), false );
369
+ }
370
+ pos = oldPos;
371
+ return ;
372
+ }
373
+
374
+ if ( !pGroup.get() ) return ;
375
+ pGroup->setField( field, false );
376
+ setGroup( msg, field, string, pos, *pGroup, *pDD );
377
+ }
378
+ }
379
+
380
+ bool Message::setStringHeader( const std::string& string )
381
+ {
382
+ clear();
383
+
384
+ std::string::size_type pos = 0;
385
+ int count = 0;
386
+
387
+ while ( pos < string.size() )
388
+ {
389
+ FieldBase field = extractField( string, pos );
390
+ if ( count < 3 && headerOrder[ count++ ] != field.getField() )
391
+ return false;
392
+
393
+ if ( isHeaderField( field ) )
394
+ m_header.setField( field, false );
395
+ else break;
396
+ }
397
+ return true;
398
+ }
399
+
400
+ bool Message::isHeaderField( int field )
401
+ {
402
+ switch ( field )
403
+ {
404
+ case FIELD::BeginString:
405
+ case FIELD::BodyLength:
406
+ case FIELD::MsgType:
407
+ case FIELD::SenderCompID:
408
+ case FIELD::TargetCompID:
409
+ case FIELD::OnBehalfOfCompID:
410
+ case FIELD::DeliverToCompID:
411
+ case FIELD::SecureDataLen:
412
+ case FIELD::MsgSeqNum:
413
+ case FIELD::SenderSubID:
414
+ case FIELD::SenderLocationID:
415
+ case FIELD::TargetSubID:
416
+ case FIELD::TargetLocationID:
417
+ case FIELD::OnBehalfOfSubID:
418
+ case FIELD::OnBehalfOfLocationID:
419
+ case FIELD::DeliverToSubID:
420
+ case FIELD::DeliverToLocationID:
421
+ case FIELD::PossDupFlag:
422
+ case FIELD::PossResend:
423
+ case FIELD::SendingTime:
424
+ case FIELD::OrigSendingTime:
425
+ case FIELD::XmlDataLen:
426
+ case FIELD::XmlData:
427
+ case FIELD::MessageEncoding:
428
+ case FIELD::LastMsgSeqNumProcessed:
429
+ case FIELD::OnBehalfOfSendingTime:
430
+ case FIELD::ApplVerID:
431
+ case FIELD::CstmApplVerID:
432
+ case FIELD::NoHops:
433
+ return true;
434
+ default:
435
+ return false;
436
+ };
437
+ }
438
+
439
+ bool Message::isHeaderField( const FieldBase& field,
440
+ const DataDictionary* pD )
441
+ {
442
+ if ( isHeaderField( field.getField() ) ) return true;
443
+ if ( pD ) return pD->isHeaderField( field.getField() );
444
+ return false;
445
+ }
446
+
447
+ bool Message::isTrailerField( int field )
448
+ {
449
+ switch ( field )
450
+ {
451
+ case FIELD::SignatureLength:
452
+ case FIELD::Signature:
453
+ case FIELD::CheckSum:
454
+ return true;
455
+ default:
456
+ return false;
457
+ };
458
+ }
459
+
460
+ bool Message::isTrailerField( const FieldBase& field,
461
+ const DataDictionary* pD )
462
+ {
463
+ if ( isTrailerField( field.getField() ) ) return true;
464
+ if ( pD ) return pD->isTrailerField( field.getField() );
465
+ return false;
466
+ }
467
+
468
+ SessionID Message::getSessionID( const std::string& qualifier ) const
469
+ throw( FieldNotFound )
470
+ {
471
+ BeginString beginString;
472
+ SenderCompID senderCompID;
473
+ TargetCompID targetCompID;
474
+
475
+ getHeader().getField( beginString );
476
+ getHeader().getField( senderCompID );
477
+ getHeader().getField( targetCompID );
478
+
479
+ return SessionID( beginString, senderCompID, targetCompID, qualifier );
480
+ }
481
+
482
+ void Message::setSessionID( const SessionID& sessionID )
483
+ {
484
+ getHeader().setField( sessionID.getBeginString() );
485
+ getHeader().setField( sessionID.getSenderCompID() );
486
+ getHeader().setField( sessionID.getTargetCompID() );
487
+ }
488
+
489
+ void Message::validate()
490
+ {
491
+ try
492
+ {
493
+ const BodyLength& aBodyLength = FIELD_GET_REF( m_header, BodyLength );
494
+
495
+ const int expectedLength = (int)aBodyLength;
496
+ const int actualLength = bodyLength();
497
+
498
+ if ( expectedLength != actualLength )
499
+ {
500
+ std::stringstream text;
501
+ text << "Expected BodyLength=" << actualLength
502
+ << ", Received BodyLength=" << expectedLength;
503
+ throw InvalidMessage(text.str());
504
+ }
505
+
506
+ const CheckSum& aCheckSum = FIELD_GET_REF( m_trailer, CheckSum );
507
+
508
+ const int expectedChecksum = (int)aCheckSum;
509
+ const int actualChecksum = checkSum();
510
+
511
+ if ( expectedChecksum != actualChecksum )
512
+ {
513
+ std::stringstream text;
514
+ text << "Expected CheckSum=" << actualChecksum
515
+ << ", Received CheckSum=" << expectedChecksum;
516
+ throw InvalidMessage(text.str());
517
+ }
518
+ }
519
+ catch ( FieldNotFound& e )
520
+ {
521
+ const std::string fieldName = ( e.field == FIX::FIELD::BodyLength ) ? "BodyLength" : "CheckSum";
522
+ throw InvalidMessage( fieldName + std::string(" is missing") );
523
+ }
524
+ catch ( IncorrectDataFormat& e )
525
+ {
526
+ const std::string fieldName = ( e.field == FIX::FIELD::BodyLength ) ? "BodyLength" : "CheckSum";
527
+ throw InvalidMessage( fieldName + std::string(" has wrong format: ") + e.detail );
528
+ }
529
+ }
530
+
531
+ FIX::FieldBase Message::extractField( const std::string& string, std::string::size_type& pos,
532
+ const DataDictionary* pSessionDD /*= 0*/, const DataDictionary* pAppDD /*= 0*/,
533
+ const Group* pGroup /*= 0*/ )
534
+ {
535
+ std::string::const_iterator const tagStart = string.begin() + pos;
536
+ std::string::const_iterator const strEnd = string.end();
537
+
538
+ std::string::const_iterator const equalSign = std::find( tagStart, strEnd, '=' );
539
+ if( equalSign == strEnd )
540
+ throw InvalidMessage("Equal sign not found in field");
541
+
542
+ int field = 0;
543
+ IntConvertor::convert( tagStart, equalSign, field );
544
+
545
+ std::string::const_iterator const valueStart = equalSign + 1;
546
+
547
+ std::string::const_iterator soh = std::find( valueStart, strEnd, '\001' );
548
+ if ( soh == strEnd )
549
+ throw InvalidMessage("SOH not found at end of field");
550
+
551
+ if ( IsDataField( field, pSessionDD, pAppDD ) )
552
+ {
553
+ // Assume length field is 1 less.
554
+ int lenField = field - 1;
555
+ // Special case for Signature which violates above assumption.
556
+ if ( field == FIELD::Signature ) lenField = FIELD::SignatureLength;
557
+
558
+ if ( pGroup && pGroup->isSetField( lenField ) )
559
+ {
560
+ const std::string& fieldLength = pGroup->getField( lenField );
561
+ soh = valueStart + atol( fieldLength.c_str() );
562
+ }
563
+ else if ( isSetField( lenField ) )
564
+ {
565
+ const std::string& fieldLength = getField( lenField );
566
+ soh = valueStart + atol( fieldLength.c_str() );
567
+ }
568
+ }
569
+
570
+ std::string::const_iterator const tagEnd = soh + 1;
571
+ pos = std::distance( string.begin(), tagEnd );
572
+
573
+ return FieldBase (
574
+ field,
575
+ valueStart,
576
+ soh,
577
+ tagStart,
578
+ tagEnd );
579
+ }
580
+ }