quickfix_ruby_ud 2.0.7

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 (196) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +257 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +137 -0
  6. data/ext/quickfix/DOMDocument.h +70 -0
  7. data/ext/quickfix/DataDictionary.cpp +679 -0
  8. data/ext/quickfix/DataDictionary.h +607 -0
  9. data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
  10. data/ext/quickfix/DataDictionaryProvider.h +67 -0
  11. data/ext/quickfix/DatabaseConnectionID.h +98 -0
  12. data/ext/quickfix/DatabaseConnectionPool.h +84 -0
  13. data/ext/quickfix/Dictionary.cpp +157 -0
  14. data/ext/quickfix/Dictionary.h +89 -0
  15. data/ext/quickfix/Event.h +89 -0
  16. data/ext/quickfix/Except.h +39 -0
  17. data/ext/quickfix/Exceptions.h +257 -0
  18. data/ext/quickfix/Field.h +654 -0
  19. data/ext/quickfix/FieldConvertors.cpp +86 -0
  20. data/ext/quickfix/FieldConvertors.h +800 -0
  21. data/ext/quickfix/FieldMap.cpp +254 -0
  22. data/ext/quickfix/FieldMap.h +327 -0
  23. data/ext/quickfix/FieldNumbers.h +44 -0
  24. data/ext/quickfix/FieldTypes.cpp +62 -0
  25. data/ext/quickfix/FieldTypes.h +817 -0
  26. data/ext/quickfix/Fields.h +30 -0
  27. data/ext/quickfix/FileLog.cpp +176 -0
  28. data/ext/quickfix/FileLog.h +110 -0
  29. data/ext/quickfix/FileStore.cpp +369 -0
  30. data/ext/quickfix/FileStore.h +131 -0
  31. data/ext/quickfix/FixCommonFields.h +13 -0
  32. data/ext/quickfix/FixFieldNumbers.h +6132 -0
  33. data/ext/quickfix/FixFields.h +6133 -0
  34. data/ext/quickfix/FixValues.h +5790 -0
  35. data/ext/quickfix/Group.cpp +44 -0
  36. data/ext/quickfix/Group.h +78 -0
  37. data/ext/quickfix/HostDetailsProvider.cpp +79 -0
  38. data/ext/quickfix/HostDetailsProvider.h +44 -0
  39. data/ext/quickfix/HtmlBuilder.h +178 -0
  40. data/ext/quickfix/HttpConnection.cpp +914 -0
  41. data/ext/quickfix/HttpConnection.h +74 -0
  42. data/ext/quickfix/HttpMessage.cpp +229 -0
  43. data/ext/quickfix/HttpMessage.h +112 -0
  44. data/ext/quickfix/HttpParser.cpp +49 -0
  45. data/ext/quickfix/HttpParser.h +49 -0
  46. data/ext/quickfix/HttpServer.cpp +152 -0
  47. data/ext/quickfix/HttpServer.h +76 -0
  48. data/ext/quickfix/Initiator.cpp +310 -0
  49. data/ext/quickfix/Initiator.h +151 -0
  50. data/ext/quickfix/Log.cpp +71 -0
  51. data/ext/quickfix/Log.h +254 -0
  52. data/ext/quickfix/Message.cpp +617 -0
  53. data/ext/quickfix/Message.h +419 -0
  54. data/ext/quickfix/MessageCracker.h +171 -0
  55. data/ext/quickfix/MessageSorters.cpp +101 -0
  56. data/ext/quickfix/MessageSorters.h +185 -0
  57. data/ext/quickfix/MessageStore.cpp +182 -0
  58. data/ext/quickfix/MessageStore.h +164 -0
  59. data/ext/quickfix/Mutex.h +120 -0
  60. data/ext/quickfix/MySQLConnection.h +187 -0
  61. data/ext/quickfix/MySQLLog.cpp +262 -0
  62. data/ext/quickfix/MySQLLog.h +158 -0
  63. data/ext/quickfix/MySQLStore.cpp +323 -0
  64. data/ext/quickfix/MySQLStore.h +161 -0
  65. data/ext/quickfix/MySQLStubs.h +203 -0
  66. data/ext/quickfix/NullStore.cpp +40 -0
  67. data/ext/quickfix/NullStore.h +89 -0
  68. data/ext/quickfix/OdbcConnection.h +241 -0
  69. data/ext/quickfix/OdbcLog.cpp +230 -0
  70. data/ext/quickfix/OdbcLog.h +109 -0
  71. data/ext/quickfix/OdbcStore.cpp +313 -0
  72. data/ext/quickfix/OdbcStore.h +124 -0
  73. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  74. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  75. data/ext/quickfix/Parser.cpp +111 -0
  76. data/ext/quickfix/Parser.h +50 -0
  77. data/ext/quickfix/PostgreSQLConnection.h +163 -0
  78. data/ext/quickfix/PostgreSQLLog.cpp +263 -0
  79. data/ext/quickfix/PostgreSQLLog.h +157 -0
  80. data/ext/quickfix/PostgreSQLStore.cpp +327 -0
  81. data/ext/quickfix/PostgreSQLStore.h +160 -0
  82. data/ext/quickfix/PostgreSQLStubs.h +203 -0
  83. data/ext/quickfix/Queue.h +66 -0
  84. data/ext/quickfix/QuickfixRuby.cpp +131900 -0
  85. data/ext/quickfix/QuickfixRuby.h +56 -0
  86. data/ext/quickfix/Responder.h +41 -0
  87. data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
  88. data/ext/quickfix/SSLSocketAcceptor.h +186 -0
  89. data/ext/quickfix/SSLSocketConnection.cpp +434 -0
  90. data/ext/quickfix/SSLSocketConnection.h +221 -0
  91. data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
  92. data/ext/quickfix/SSLSocketInitiator.h +203 -0
  93. data/ext/quickfix/SSLStubs.h +129 -0
  94. data/ext/quickfix/Session.cpp +1437 -0
  95. data/ext/quickfix/Session.h +343 -0
  96. data/ext/quickfix/SessionFactory.cpp +314 -0
  97. data/ext/quickfix/SessionFactory.h +84 -0
  98. data/ext/quickfix/SessionID.h +136 -0
  99. data/ext/quickfix/SessionSettings.cpp +165 -0
  100. data/ext/quickfix/SessionSettings.h +283 -0
  101. data/ext/quickfix/SessionState.h +260 -0
  102. data/ext/quickfix/Settings.cpp +160 -0
  103. data/ext/quickfix/Settings.h +56 -0
  104. data/ext/quickfix/SharedArray.h +274 -0
  105. data/ext/quickfix/SocketAcceptor.cpp +216 -0
  106. data/ext/quickfix/SocketAcceptor.h +77 -0
  107. data/ext/quickfix/SocketConnection.cpp +256 -0
  108. data/ext/quickfix/SocketConnection.h +102 -0
  109. data/ext/quickfix/SocketConnector.cpp +112 -0
  110. data/ext/quickfix/SocketConnector.h +76 -0
  111. data/ext/quickfix/SocketInitiator.cpp +241 -0
  112. data/ext/quickfix/SocketInitiator.h +76 -0
  113. data/ext/quickfix/SocketMonitor.h +26 -0
  114. data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
  115. data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
  116. data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
  117. data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
  118. data/ext/quickfix/SocketServer.cpp +163 -0
  119. data/ext/quickfix/SocketServer.h +100 -0
  120. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
  121. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
  122. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
  123. data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
  124. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
  125. data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
  126. data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
  127. data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
  128. data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
  129. data/ext/quickfix/ThreadedSocketConnection.h +89 -0
  130. data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
  131. data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
  132. data/ext/quickfix/TimeRange.cpp +227 -0
  133. data/ext/quickfix/TimeRange.h +215 -0
  134. data/ext/quickfix/Utility.cpp +639 -0
  135. data/ext/quickfix/Utility.h +255 -0
  136. data/ext/quickfix/UtilitySSL.cpp +1612 -0
  137. data/ext/quickfix/UtilitySSL.h +274 -0
  138. data/ext/quickfix/Values.h +63 -0
  139. data/ext/quickfix/config-all.h +10 -0
  140. data/ext/quickfix/config.h +10 -0
  141. data/ext/quickfix/config_unix.h +178 -0
  142. data/ext/quickfix/config_windows.h +0 -0
  143. data/ext/quickfix/dirent_windows.h +838 -0
  144. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  145. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  146. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  147. data/ext/quickfix/double-conversion/bignum.h +144 -0
  148. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  149. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  150. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  151. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  152. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  153. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  154. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  155. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  156. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  157. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  158. data/ext/quickfix/double-conversion/ieee.h +402 -0
  159. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  160. data/ext/quickfix/double-conversion/strtod.h +45 -0
  161. data/ext/quickfix/double-conversion/utils.h +374 -0
  162. data/ext/quickfix/extconf.rb +76 -0
  163. data/ext/quickfix/index.h +37 -0
  164. data/ext/quickfix/pugiconfig.hpp +77 -0
  165. data/ext/quickfix/pugixml.cpp +13237 -0
  166. data/ext/quickfix/pugixml.hpp +1516 -0
  167. data/ext/quickfix/scope_guard.hpp +215 -0
  168. data/ext/quickfix/stdint_msvc.h +254 -0
  169. data/ext/quickfix/strptime.h +7 -0
  170. data/lib/quickfix40.rb +274 -0
  171. data/lib/quickfix41.rb +351 -0
  172. data/lib/quickfix42.rb +1184 -0
  173. data/lib/quickfix43.rb +3504 -0
  174. data/lib/quickfix44.rb +14040 -0
  175. data/lib/quickfix50.rb +20051 -0
  176. data/lib/quickfix50sp1.rb +23596 -0
  177. data/lib/quickfix50sp2.rb +412444 -0
  178. data/lib/quickfix_fields.rb +79393 -0
  179. data/lib/quickfix_ruby.rb +82 -0
  180. data/lib/quickfixt11.rb +65 -0
  181. data/spec/FIX40.xml +862 -0
  182. data/spec/FIX41.xml +1282 -0
  183. data/spec/FIX42.xml +2743 -0
  184. data/spec/FIX43.xml +4230 -0
  185. data/spec/FIX44.xml +6600 -0
  186. data/spec/FIX50.xml +8142 -0
  187. data/spec/FIX50SP1.xml +9506 -0
  188. data/spec/FIX50SP2.xml +26069 -0
  189. data/spec/FIXT11.xml +252 -0
  190. data/test/DataDictionaryTestCase.rb +268 -0
  191. data/test/DictionaryTestCase.rb +112 -0
  192. data/test/FieldBaseTestCase.rb +24 -0
  193. data/test/MessageStoreTestCase.rb +19 -0
  194. data/test/MessageTestCase.rb +368 -0
  195. data/test/SessionSettingsTestCase.rb +41 -0
  196. metadata +236 -0
@@ -0,0 +1,617 @@
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
+ int const headerOrder[] = {FIELD::BeginString, FIELD::BodyLength, FIELD::MsgType};
34
+
35
+ std::unique_ptr<DataDictionary> Message::s_dataDictionary;
36
+
37
+ Message::Message()
38
+ : m_validStructure(true),
39
+ m_tag(0) {}
40
+
41
+ Message::Message(const message_order &headerOrder, const message_order &trailerOrder, const message_order &order)
42
+ : FieldMap(order),
43
+ m_header(headerOrder),
44
+ m_trailer(trailerOrder),
45
+ m_validStructure(true) {}
46
+
47
+ Message::Message(const std::string &string, bool validate) EXCEPT(InvalidMessage)
48
+ : m_validStructure(true),
49
+ m_tag(0) {
50
+ setString(string, validate);
51
+ }
52
+
53
+ Message::Message(const std::string &string, const DataDictionary &dataDictionary, bool validate) EXCEPT(InvalidMessage)
54
+ : m_validStructure(true),
55
+ m_tag(0) {
56
+ setString(string, validate, &dataDictionary, &dataDictionary);
57
+ }
58
+
59
+ Message::Message(
60
+ const std::string &string,
61
+ const DataDictionary &sessionDataDictionary,
62
+ const DataDictionary &applicationDataDictionary,
63
+ bool validate) EXCEPT(InvalidMessage)
64
+ : m_validStructure(true),
65
+ m_tag(0) {
66
+ setString(string, validate, &sessionDataDictionary, &applicationDataDictionary);
67
+ }
68
+
69
+ Message::Message(
70
+ const message_order &headerOrder,
71
+ const message_order &trailerOrder,
72
+ const message_order &order,
73
+ const std::string &string,
74
+ const DataDictionary &dataDictionary,
75
+ bool validate) EXCEPT(InvalidMessage)
76
+ : FieldMap(order),
77
+ m_header(headerOrder),
78
+ m_trailer(trailerOrder),
79
+ m_validStructure(true) {
80
+ setString(string, validate, &dataDictionary, &dataDictionary);
81
+ }
82
+
83
+ Message::Message(
84
+ const message_order &headerOrder,
85
+ const message_order &trailerOrder,
86
+ const message_order &order,
87
+ const std::string &string,
88
+ const DataDictionary &sessionDataDictionary,
89
+ const DataDictionary &applicationDataDictionary,
90
+ bool validate) EXCEPT(InvalidMessage)
91
+ : FieldMap(order),
92
+ m_header(headerOrder),
93
+ m_trailer(trailerOrder),
94
+ m_validStructure(true) {
95
+ setStringHeader(string);
96
+ if (isAdmin()) {
97
+ setString(string, validate, &sessionDataDictionary, &sessionDataDictionary);
98
+ } else {
99
+ setString(string, validate, &sessionDataDictionary, &applicationDataDictionary);
100
+ }
101
+ }
102
+
103
+ Message::Message(const BeginString &beginString, const MsgType &msgType)
104
+ : m_validStructure(true),
105
+ m_tag(0) {
106
+ m_header.setField(beginString);
107
+ m_header.setField(msgType);
108
+ }
109
+
110
+ Message::~Message() {}
111
+
112
+ bool Message::InitializeXML(const std::string &url) {
113
+ try {
114
+ s_dataDictionary.reset(new DataDictionary(url));
115
+ return true;
116
+ } catch (ConfigError &) {
117
+ return false;
118
+ }
119
+ }
120
+
121
+ void Message::reverseRoute(const Header &header) {
122
+ // required routing tags
123
+ BeginString beginString;
124
+ SenderCompID senderCompID;
125
+ TargetCompID targetCompID;
126
+
127
+ m_header.removeField(beginString.getTag());
128
+ m_header.removeField(senderCompID.getTag());
129
+ m_header.removeField(targetCompID.getTag());
130
+
131
+ if (header.getFieldIfSet(beginString)) {
132
+ if (beginString.getValue().size()) {
133
+ m_header.setField(beginString);
134
+ }
135
+
136
+ OnBehalfOfLocationID onBehalfOfLocationID;
137
+ DeliverToLocationID deliverToLocationID;
138
+
139
+ m_header.removeField(onBehalfOfLocationID.getTag());
140
+ m_header.removeField(deliverToLocationID.getTag());
141
+
142
+ if (beginString >= BeginString_FIX41) {
143
+ if (header.getFieldIfSet(onBehalfOfLocationID)) {
144
+ if (onBehalfOfLocationID.getValue().size()) {
145
+ m_header.setField(DeliverToLocationID(onBehalfOfLocationID));
146
+ }
147
+ }
148
+
149
+ if (header.getFieldIfSet(deliverToLocationID)) {
150
+ if (deliverToLocationID.getValue().size()) {
151
+ m_header.setField(OnBehalfOfLocationID(deliverToLocationID));
152
+ }
153
+ }
154
+ }
155
+ }
156
+
157
+ if (header.getFieldIfSet(senderCompID)) {
158
+ if (senderCompID.getValue().size()) {
159
+ m_header.setField(TargetCompID(senderCompID));
160
+ }
161
+ }
162
+
163
+ if (header.getFieldIfSet(targetCompID)) {
164
+ if (targetCompID.getValue().size()) {
165
+ m_header.setField(SenderCompID(targetCompID));
166
+ }
167
+ }
168
+
169
+ // optional routing tags
170
+ OnBehalfOfCompID onBehalfOfCompID;
171
+ OnBehalfOfSubID onBehalfOfSubID;
172
+ DeliverToCompID deliverToCompID;
173
+ DeliverToSubID deliverToSubID;
174
+
175
+ m_header.removeField(onBehalfOfCompID.getTag());
176
+ m_header.removeField(onBehalfOfSubID.getTag());
177
+ m_header.removeField(deliverToCompID.getTag());
178
+ m_header.removeField(deliverToSubID.getTag());
179
+
180
+ if (header.getFieldIfSet(onBehalfOfCompID)) {
181
+ if (onBehalfOfCompID.getValue().size()) {
182
+ m_header.setField(DeliverToCompID(onBehalfOfCompID));
183
+ }
184
+ }
185
+
186
+ if (header.getFieldIfSet(onBehalfOfSubID)) {
187
+ if (onBehalfOfSubID.getValue().size()) {
188
+ m_header.setField(DeliverToSubID(onBehalfOfSubID));
189
+ }
190
+ }
191
+
192
+ if (header.getFieldIfSet(deliverToCompID)) {
193
+ if (deliverToCompID.getValue().size()) {
194
+ m_header.setField(OnBehalfOfCompID(deliverToCompID));
195
+ }
196
+ }
197
+
198
+ if (header.getFieldIfSet(deliverToSubID)) {
199
+ if (deliverToSubID.getValue().size()) {
200
+ m_header.setField(OnBehalfOfSubID(deliverToSubID));
201
+ }
202
+ }
203
+ }
204
+
205
+ std::string Message::toString(int beginStringField, int bodyLengthField, int checkSumField) const {
206
+ std::string str;
207
+ toString(str, beginStringField, bodyLengthField, checkSumField);
208
+ return str;
209
+ }
210
+
211
+ std::string &Message::toString(std::string &str, int beginStringField, int bodyLengthField, int checkSumField) const {
212
+ size_t length = bodyLength(beginStringField, bodyLengthField, checkSumField);
213
+ m_header.setField(IntField(bodyLengthField, static_cast<int>(length)));
214
+ m_trailer.setField(CheckSumField(checkSumField, checkSum(checkSumField)));
215
+
216
+ #if defined(_MSC_VER) && _MSC_VER < 1300
217
+ str = "";
218
+ #else
219
+ str.clear();
220
+ #endif
221
+
222
+ /*small speculation about the space needed for FIX string*/
223
+ str.reserve(length + 64);
224
+
225
+ m_header.calculateString(str);
226
+ FieldMap::calculateString(str);
227
+ m_trailer.calculateString(str);
228
+
229
+ return str;
230
+ }
231
+
232
+ std::string Message::toXML() const {
233
+ std::string str;
234
+ toXML(str);
235
+ return str;
236
+ }
237
+
238
+ std::string &Message::toXML(std::string &str) const {
239
+ std::stringstream stream;
240
+ stream << "<message>" << std::endl
241
+ << std::setw(2) << " " << "<header>" << std::endl
242
+ << toXMLFields(getHeader(), 4) << std::setw(2) << " " << "</header>" << std::endl
243
+ << std::setw(2) << " " << "<body>" << std::endl
244
+ << toXMLFields(*this, 4) << std::setw(2) << " " << "</body>" << std::endl
245
+ << std::setw(2) << " " << "<trailer>" << std::endl
246
+ << toXMLFields(getTrailer(), 4) << std::setw(2) << " " << "</trailer>" << std::endl
247
+ << "</message>";
248
+
249
+ return str = stream.str();
250
+ }
251
+
252
+ std::string Message::toXMLFields(const FieldMap &fields, int space) const {
253
+ std::stringstream stream;
254
+ std::string name;
255
+ for (const FieldMap::value_type &field : fields) {
256
+ int tag = field.getTag();
257
+ std::string value = field.getString();
258
+
259
+ stream << std::setw(space) << " " << "<field ";
260
+ if (s_dataDictionary.get() && s_dataDictionary->getFieldName(tag, name)) {
261
+ stream << "name=\"" << name << "\" ";
262
+ }
263
+ stream << "number=\"" << tag << "\"";
264
+ if (s_dataDictionary.get() && s_dataDictionary->getValueName(tag, value, name)) {
265
+ stream << " enum=\"" << name << "\"";
266
+ }
267
+ stream << ">";
268
+ stream << "<![CDATA[" << value << "]]>";
269
+ stream << "</field>" << std::endl;
270
+ }
271
+
272
+ for (const FieldMap::g_value_type &group : fields.groups()) {
273
+ for (const FieldMap *groupFields : group.second) {
274
+ stream << std::setw(space) << " " << "<group>" << std::endl
275
+ << toXMLFields(*groupFields, space + 2) << std::setw(space) << " " << "</group>" << std::endl;
276
+ }
277
+ }
278
+
279
+ return stream.str();
280
+ }
281
+
282
+ void Message::setString(
283
+ const std::string &string,
284
+ bool doValidation,
285
+ const DataDictionary *pSessionDataDictionary,
286
+ const DataDictionary *pApplicationDataDictionary) EXCEPT(InvalidMessage) {
287
+ clear();
288
+
289
+ std::string::size_type pos = 0;
290
+ int count = 0;
291
+
292
+ FIX::MsgType msg;
293
+
294
+ field_type type = header;
295
+
296
+ while (pos < string.size()) {
297
+ FieldBase field = extractField(string, pos, pSessionDataDictionary, pApplicationDataDictionary);
298
+ if (count < 3 && headerOrder[count++] != field.getTag()) {
299
+ if (doValidation) {
300
+ throw InvalidMessage("Header fields out of order");
301
+ }
302
+ }
303
+
304
+ if (isHeaderField(field, pSessionDataDictionary)) {
305
+ if (type != header) {
306
+ if (m_tag == 0) {
307
+ m_tag = field.getTag();
308
+ }
309
+ m_validStructure = false;
310
+ }
311
+
312
+ if (field.getTag() == FIELD::MsgType) {
313
+ msg.setString(field.getString());
314
+ if (isAdminMsgType(msg)) {
315
+ pApplicationDataDictionary = pSessionDataDictionary;
316
+ }
317
+ }
318
+
319
+ m_header.appendField(field);
320
+
321
+ if (pSessionDataDictionary) {
322
+ setGroup("_header_", field, string, pos, getHeader(), *pSessionDataDictionary);
323
+ }
324
+ } else if (isTrailerField(field, pSessionDataDictionary)) {
325
+ type = trailer;
326
+ m_trailer.appendField(field);
327
+
328
+ if (pSessionDataDictionary) {
329
+ setGroup("_trailer_", field, string, pos, getTrailer(), *pSessionDataDictionary);
330
+ }
331
+ } else {
332
+ if (type == trailer) {
333
+ if (m_tag == 0) {
334
+ m_tag = field.getTag();
335
+ }
336
+ m_validStructure = false;
337
+ }
338
+
339
+ type = body;
340
+ appendField(field);
341
+
342
+ if (pApplicationDataDictionary) {
343
+ setGroup(msg, field, string, pos, *this, *pApplicationDataDictionary);
344
+ }
345
+ }
346
+ }
347
+
348
+ // sort fields
349
+ m_header.sortFields();
350
+ sortFields();
351
+ m_trailer.sortFields();
352
+
353
+ if (doValidation) {
354
+ validate();
355
+ }
356
+ }
357
+
358
+ void Message::setGroup(
359
+ const std::string &msg,
360
+ const FieldBase &field,
361
+ const std::string &string,
362
+ std::string::size_type &pos,
363
+ FieldMap &map,
364
+ const DataDictionary &dataDictionary) {
365
+ int group = field.getTag();
366
+ int delim;
367
+ const DataDictionary *pDD = 0;
368
+ if (!dataDictionary.getGroup(msg, group, delim, pDD)) {
369
+ return;
370
+ }
371
+ std::unique_ptr<Group> pGroup;
372
+
373
+ while (pos < string.size()) {
374
+ std::string::size_type oldPos = pos;
375
+ FieldBase field = extractField(string, pos, &dataDictionary, &dataDictionary, pGroup.get());
376
+
377
+ // Start a new group because...
378
+ if ( // found delimiter
379
+ (field.getTag() == delim) ||
380
+ // no delimiter, but field belongs to group OR field already processed
381
+ (pDD->isField(field.getTag()) && (pGroup.get() == 0 || pGroup->isSetField(field.getTag())))) {
382
+ if (pGroup.get()) {
383
+ map.addGroupPtr(group, pGroup.release(), false);
384
+ }
385
+ pGroup.reset(new Group(field.getTag(), delim, pDD->getOrderedFields()));
386
+ } else if (!pDD->isField(field.getTag())) {
387
+ if (pGroup.get()) {
388
+ map.addGroupPtr(group, pGroup.release(), false);
389
+ }
390
+ pos = oldPos;
391
+ return;
392
+ }
393
+
394
+ if (!pGroup.get()) {
395
+ return;
396
+ }
397
+ pGroup->addField(field);
398
+ setGroup(msg, field, string, pos, *pGroup, *pDD);
399
+ }
400
+ }
401
+
402
+ bool Message::setStringHeader(const std::string &string) {
403
+ clear();
404
+
405
+ std::string::size_type pos = 0;
406
+ int count = 0;
407
+
408
+ while (pos < string.size()) {
409
+ FieldBase field = extractField(string, pos);
410
+ if (count < 3 && headerOrder[count++] != field.getTag()) {
411
+ return false;
412
+ }
413
+
414
+ if (isHeaderField(field)) {
415
+ m_header.appendField(field);
416
+ } else {
417
+ break;
418
+ }
419
+ }
420
+
421
+ m_header.sortFields();
422
+ return true;
423
+ }
424
+
425
+ bool Message::isHeaderField(int field) {
426
+ switch (field) {
427
+ case FIELD::BeginString:
428
+ case FIELD::BodyLength:
429
+ case FIELD::MsgType:
430
+ case FIELD::SenderCompID:
431
+ case FIELD::TargetCompID:
432
+ case FIELD::OnBehalfOfCompID:
433
+ case FIELD::DeliverToCompID:
434
+ case FIELD::SecureDataLen:
435
+ case FIELD::MsgSeqNum:
436
+ case FIELD::SenderSubID:
437
+ case FIELD::SenderLocationID:
438
+ case FIELD::TargetSubID:
439
+ case FIELD::TargetLocationID:
440
+ case FIELD::OnBehalfOfSubID:
441
+ case FIELD::OnBehalfOfLocationID:
442
+ case FIELD::DeliverToSubID:
443
+ case FIELD::DeliverToLocationID:
444
+ case FIELD::PossDupFlag:
445
+ case FIELD::PossResend:
446
+ case FIELD::SendingTime:
447
+ case FIELD::OrigSendingTime:
448
+ case FIELD::XmlDataLen:
449
+ case FIELD::XmlData:
450
+ case FIELD::MessageEncoding:
451
+ case FIELD::LastMsgSeqNumProcessed:
452
+ case FIELD::OnBehalfOfSendingTime:
453
+ case FIELD::ApplVerID:
454
+ case FIELD::CstmApplVerID:
455
+ case FIELD::NoHops:
456
+ return true;
457
+ default:
458
+ return false;
459
+ };
460
+ }
461
+
462
+ bool Message::isHeaderField(const FieldBase &field, const DataDictionary *pD) {
463
+ return isHeaderField(field.getTag(), pD);
464
+ }
465
+
466
+ bool Message::isHeaderField(int field, const DataDictionary *pD) {
467
+ if (isHeaderField(field)) {
468
+ return true;
469
+ }
470
+ if (pD) {
471
+ return pD->isHeaderField(field);
472
+ }
473
+ return false;
474
+ }
475
+
476
+ bool Message::isTrailerField(int field) {
477
+ switch (field) {
478
+ case FIELD::SignatureLength:
479
+ case FIELD::Signature:
480
+ case FIELD::CheckSum:
481
+ return true;
482
+ default:
483
+ return false;
484
+ };
485
+ }
486
+
487
+ bool Message::isTrailerField(const FieldBase &field, const DataDictionary *pD) {
488
+ return isTrailerField(field.getTag(), pD);
489
+ }
490
+
491
+ bool Message::isTrailerField(int field, const DataDictionary *pD) {
492
+ if (isTrailerField(field)) {
493
+ return true;
494
+ }
495
+ if (pD) {
496
+ return pD->isTrailerField(field);
497
+ }
498
+ return false;
499
+ }
500
+
501
+ SessionID Message::getSessionID(const std::string &qualifier) const EXCEPT(FieldNotFound) {
502
+ return SessionID(
503
+ getHeader().getField<BeginString>(),
504
+ getHeader().getField<SenderCompID>(),
505
+ getHeader().getField<TargetCompID>(),
506
+ qualifier);
507
+ }
508
+
509
+ void Message::setSessionID(const SessionID &sessionID) {
510
+ getHeader().setField(sessionID.getBeginString());
511
+ getHeader().setField(sessionID.getSenderCompID());
512
+ getHeader().setField(sessionID.getTargetCompID());
513
+ }
514
+
515
+ void Message::validate() const {
516
+ try {
517
+ const BodyLength &aBodyLength = FIELD_GET_REF(m_header, BodyLength);
518
+
519
+ const size_t expectedLength = static_cast<size_t>(aBodyLength);
520
+ const size_t receivedLength = bodyLength();
521
+
522
+ if (expectedLength != receivedLength) {
523
+ std::stringstream text;
524
+ text << "Expected BodyLength=" << expectedLength << ", Received BodyLength=" << receivedLength;
525
+ throw InvalidMessage(text.str());
526
+ }
527
+
528
+ const CheckSum &aCheckSum = FIELD_GET_REF(m_trailer, CheckSum);
529
+
530
+ const int expectedChecksum = (int)aCheckSum;
531
+ const int receivedChecksum = checkSum();
532
+
533
+ if (expectedChecksum != receivedChecksum) {
534
+ std::stringstream text;
535
+ text << "Expected CheckSum=" << expectedChecksum << ", Received CheckSum=" << receivedChecksum;
536
+ throw InvalidMessage(text.str());
537
+ }
538
+ } catch (FieldNotFound &e) {
539
+ const std::string fieldName = (e.field == FIX::FIELD::BodyLength) ? "BodyLength" : "CheckSum";
540
+ throw InvalidMessage(fieldName + std::string(" is missing"));
541
+ } catch (IncorrectDataFormat &e) {
542
+ const std::string fieldName = (e.field == FIX::FIELD::BodyLength) ? "BodyLength" : "CheckSum";
543
+ throw InvalidMessage(fieldName + std::string(" has wrong format: ") + e.detail);
544
+ }
545
+ }
546
+
547
+ FIX::FieldBase Message::extractField(
548
+ const std::string &string,
549
+ std::string::size_type &pos,
550
+ const DataDictionary *pSessionDD /*= 0*/,
551
+ const DataDictionary *pAppDD /*= 0*/,
552
+ const Group *pGroup /*= 0*/) const {
553
+ std::string::const_iterator const tagStart = string.begin() + pos;
554
+ std::string::const_iterator const strEnd = string.end();
555
+
556
+ std::string::const_iterator const equalSign = std::find(tagStart, strEnd, '=');
557
+ if (equalSign == strEnd) {
558
+ throw InvalidMessage("Equal sign not found in field");
559
+ }
560
+
561
+ int field = 0;
562
+ if (!IntConvertor::convert(tagStart, equalSign, field)) {
563
+ throw InvalidMessage(std::string("Field tag is invalid: ") + std::string(tagStart, equalSign));
564
+ }
565
+
566
+ std::string::const_iterator const valueStart = equalSign + 1;
567
+
568
+ std::string::const_iterator soh = std::find(valueStart, strEnd, '\001');
569
+ if (soh == strEnd) {
570
+ throw InvalidMessage("SOH not found at end of field");
571
+ }
572
+
573
+ if (IsDataField(field, pSessionDD, pAppDD)) {
574
+ // Assume length field is 1 less.
575
+ int lenField = field - 1;
576
+ // Special case for Signature which violates above assumption.
577
+ if (field == FIELD::Signature) {
578
+ lenField = FIELD::SignatureLength;
579
+ }
580
+
581
+ // identify part of the message that should contain length field
582
+ const FieldMap *location = pGroup;
583
+ if (!location) {
584
+ if (isHeaderField(lenField, pSessionDD)) {
585
+ location = &m_header;
586
+ } else if (isTrailerField(lenField, pSessionDD)) {
587
+ location = &m_trailer;
588
+ } else {
589
+ location = this;
590
+ }
591
+ }
592
+
593
+ try {
594
+ const FieldBase &fieldLength = location->reverse_find(lenField);
595
+ soh = valueStart + IntConvertor::convert(fieldLength.getString());
596
+ } catch (FieldNotFound &) {
597
+ throw InvalidMessage(
598
+ std::string("Data length field ") + IntConvertor::convert(lenField)
599
+ + std::string(" was not found for data field ") + IntConvertor::convert(field));
600
+ } catch (FieldConvertError &e) {
601
+ throw InvalidMessage(
602
+ std::string("Unable to determine SOH for data field ") + IntConvertor::convert(field) + std::string(": ")
603
+ + e.what());
604
+ }
605
+ }
606
+
607
+ std::string::const_iterator const tagEnd = soh + 1;
608
+ #if defined(__SUNPRO_CC)
609
+ std::distance(string.begin(), tagEnd, pos);
610
+ #else
611
+ pos = std::distance(string.begin(), tagEnd);
612
+ #endif
613
+
614
+ return FieldBase(field, valueStart, soh, tagStart, tagEnd);
615
+ }
616
+
617
+ } // namespace FIX