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,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
+ }