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.
- checksums.yaml +7 -0
- data/ext/quickfix/Acceptor.cpp +257 -0
- data/ext/quickfix/Acceptor.h +127 -0
- data/ext/quickfix/Allocator.h +9 -0
- data/ext/quickfix/Application.h +137 -0
- data/ext/quickfix/DOMDocument.h +70 -0
- data/ext/quickfix/DataDictionary.cpp +679 -0
- data/ext/quickfix/DataDictionary.h +607 -0
- data/ext/quickfix/DataDictionaryProvider.cpp +66 -0
- data/ext/quickfix/DataDictionaryProvider.h +67 -0
- data/ext/quickfix/DatabaseConnectionID.h +98 -0
- data/ext/quickfix/DatabaseConnectionPool.h +84 -0
- data/ext/quickfix/Dictionary.cpp +157 -0
- data/ext/quickfix/Dictionary.h +89 -0
- data/ext/quickfix/Event.h +89 -0
- data/ext/quickfix/Except.h +39 -0
- data/ext/quickfix/Exceptions.h +257 -0
- data/ext/quickfix/Field.h +654 -0
- data/ext/quickfix/FieldConvertors.cpp +86 -0
- data/ext/quickfix/FieldConvertors.h +800 -0
- data/ext/quickfix/FieldMap.cpp +254 -0
- data/ext/quickfix/FieldMap.h +327 -0
- data/ext/quickfix/FieldNumbers.h +44 -0
- data/ext/quickfix/FieldTypes.cpp +62 -0
- data/ext/quickfix/FieldTypes.h +817 -0
- data/ext/quickfix/Fields.h +30 -0
- data/ext/quickfix/FileLog.cpp +176 -0
- data/ext/quickfix/FileLog.h +110 -0
- data/ext/quickfix/FileStore.cpp +369 -0
- data/ext/quickfix/FileStore.h +131 -0
- data/ext/quickfix/FixCommonFields.h +13 -0
- data/ext/quickfix/FixFieldNumbers.h +6132 -0
- data/ext/quickfix/FixFields.h +6133 -0
- data/ext/quickfix/FixValues.h +5790 -0
- data/ext/quickfix/Group.cpp +44 -0
- data/ext/quickfix/Group.h +78 -0
- data/ext/quickfix/HostDetailsProvider.cpp +79 -0
- data/ext/quickfix/HostDetailsProvider.h +44 -0
- data/ext/quickfix/HtmlBuilder.h +178 -0
- data/ext/quickfix/HttpConnection.cpp +914 -0
- data/ext/quickfix/HttpConnection.h +74 -0
- data/ext/quickfix/HttpMessage.cpp +229 -0
- data/ext/quickfix/HttpMessage.h +112 -0
- data/ext/quickfix/HttpParser.cpp +49 -0
- data/ext/quickfix/HttpParser.h +49 -0
- data/ext/quickfix/HttpServer.cpp +152 -0
- data/ext/quickfix/HttpServer.h +76 -0
- data/ext/quickfix/Initiator.cpp +310 -0
- data/ext/quickfix/Initiator.h +151 -0
- data/ext/quickfix/Log.cpp +71 -0
- data/ext/quickfix/Log.h +254 -0
- data/ext/quickfix/Message.cpp +617 -0
- data/ext/quickfix/Message.h +419 -0
- data/ext/quickfix/MessageCracker.h +171 -0
- data/ext/quickfix/MessageSorters.cpp +101 -0
- data/ext/quickfix/MessageSorters.h +185 -0
- data/ext/quickfix/MessageStore.cpp +182 -0
- data/ext/quickfix/MessageStore.h +164 -0
- data/ext/quickfix/Mutex.h +120 -0
- data/ext/quickfix/MySQLConnection.h +187 -0
- data/ext/quickfix/MySQLLog.cpp +262 -0
- data/ext/quickfix/MySQLLog.h +158 -0
- data/ext/quickfix/MySQLStore.cpp +323 -0
- data/ext/quickfix/MySQLStore.h +161 -0
- data/ext/quickfix/MySQLStubs.h +203 -0
- data/ext/quickfix/NullStore.cpp +40 -0
- data/ext/quickfix/NullStore.h +89 -0
- data/ext/quickfix/OdbcConnection.h +241 -0
- data/ext/quickfix/OdbcLog.cpp +230 -0
- data/ext/quickfix/OdbcLog.h +109 -0
- data/ext/quickfix/OdbcStore.cpp +313 -0
- data/ext/quickfix/OdbcStore.h +124 -0
- data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
- data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
- data/ext/quickfix/Parser.cpp +111 -0
- data/ext/quickfix/Parser.h +50 -0
- data/ext/quickfix/PostgreSQLConnection.h +163 -0
- data/ext/quickfix/PostgreSQLLog.cpp +263 -0
- data/ext/quickfix/PostgreSQLLog.h +157 -0
- data/ext/quickfix/PostgreSQLStore.cpp +327 -0
- data/ext/quickfix/PostgreSQLStore.h +160 -0
- data/ext/quickfix/PostgreSQLStubs.h +203 -0
- data/ext/quickfix/Queue.h +66 -0
- data/ext/quickfix/QuickfixRuby.cpp +131900 -0
- data/ext/quickfix/QuickfixRuby.h +56 -0
- data/ext/quickfix/Responder.h +41 -0
- data/ext/quickfix/SSLSocketAcceptor.cpp +409 -0
- data/ext/quickfix/SSLSocketAcceptor.h +186 -0
- data/ext/quickfix/SSLSocketConnection.cpp +434 -0
- data/ext/quickfix/SSLSocketConnection.h +221 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +558 -0
- data/ext/quickfix/SSLSocketInitiator.h +203 -0
- data/ext/quickfix/SSLStubs.h +129 -0
- data/ext/quickfix/Session.cpp +1437 -0
- data/ext/quickfix/Session.h +343 -0
- data/ext/quickfix/SessionFactory.cpp +314 -0
- data/ext/quickfix/SessionFactory.h +84 -0
- data/ext/quickfix/SessionID.h +136 -0
- data/ext/quickfix/SessionSettings.cpp +165 -0
- data/ext/quickfix/SessionSettings.h +283 -0
- data/ext/quickfix/SessionState.h +260 -0
- data/ext/quickfix/Settings.cpp +160 -0
- data/ext/quickfix/Settings.h +56 -0
- data/ext/quickfix/SharedArray.h +274 -0
- data/ext/quickfix/SocketAcceptor.cpp +216 -0
- data/ext/quickfix/SocketAcceptor.h +77 -0
- data/ext/quickfix/SocketConnection.cpp +256 -0
- data/ext/quickfix/SocketConnection.h +102 -0
- data/ext/quickfix/SocketConnector.cpp +112 -0
- data/ext/quickfix/SocketConnector.h +76 -0
- data/ext/quickfix/SocketInitiator.cpp +241 -0
- data/ext/quickfix/SocketInitiator.h +76 -0
- data/ext/quickfix/SocketMonitor.h +26 -0
- data/ext/quickfix/SocketMonitor_UNIX.cpp +238 -0
- data/ext/quickfix/SocketMonitor_UNIX.h +101 -0
- data/ext/quickfix/SocketMonitor_WIN32.cpp +248 -0
- data/ext/quickfix/SocketMonitor_WIN32.h +99 -0
- data/ext/quickfix/SocketServer.cpp +163 -0
- data/ext/quickfix/SocketServer.h +100 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +436 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +209 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +364 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +191 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +434 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +193 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +242 -0
- data/ext/quickfix/ThreadedSocketAcceptor.h +95 -0
- data/ext/quickfix/ThreadedSocketConnection.cpp +227 -0
- data/ext/quickfix/ThreadedSocketConnection.h +89 -0
- data/ext/quickfix/ThreadedSocketInitiator.cpp +238 -0
- data/ext/quickfix/ThreadedSocketInitiator.h +78 -0
- data/ext/quickfix/TimeRange.cpp +227 -0
- data/ext/quickfix/TimeRange.h +215 -0
- data/ext/quickfix/Utility.cpp +639 -0
- data/ext/quickfix/Utility.h +255 -0
- data/ext/quickfix/UtilitySSL.cpp +1612 -0
- data/ext/quickfix/UtilitySSL.h +274 -0
- data/ext/quickfix/Values.h +63 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/config.h +10 -0
- data/ext/quickfix/config_unix.h +178 -0
- data/ext/quickfix/config_windows.h +0 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +374 -0
- data/ext/quickfix/extconf.rb +76 -0
- data/ext/quickfix/index.h +37 -0
- data/ext/quickfix/pugiconfig.hpp +77 -0
- data/ext/quickfix/pugixml.cpp +13237 -0
- data/ext/quickfix/pugixml.hpp +1516 -0
- data/ext/quickfix/scope_guard.hpp +215 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/ext/quickfix/strptime.h +7 -0
- data/lib/quickfix40.rb +274 -0
- data/lib/quickfix41.rb +351 -0
- data/lib/quickfix42.rb +1184 -0
- data/lib/quickfix43.rb +3504 -0
- data/lib/quickfix44.rb +14040 -0
- data/lib/quickfix50.rb +20051 -0
- data/lib/quickfix50sp1.rb +23596 -0
- data/lib/quickfix50sp2.rb +412444 -0
- data/lib/quickfix_fields.rb +79393 -0
- data/lib/quickfix_ruby.rb +82 -0
- data/lib/quickfixt11.rb +65 -0
- data/spec/FIX40.xml +862 -0
- data/spec/FIX41.xml +1282 -0
- data/spec/FIX42.xml +2743 -0
- data/spec/FIX43.xml +4230 -0
- data/spec/FIX44.xml +6600 -0
- data/spec/FIX50.xml +8142 -0
- data/spec/FIX50SP1.xml +9506 -0
- data/spec/FIX50SP2.xml +26069 -0
- data/spec/FIXT11.xml +252 -0
- data/test/DataDictionaryTestCase.rb +268 -0
- data/test/DictionaryTestCase.rb +112 -0
- data/test/FieldBaseTestCase.rb +24 -0
- data/test/MessageStoreTestCase.rb +19 -0
- data/test/MessageTestCase.rb +368 -0
- data/test/SessionSettingsTestCase.rb +41 -0
- metadata +236 -0
@@ -0,0 +1,607 @@
|
|
1
|
+
/* -*- C++ -*- */
|
2
|
+
|
3
|
+
/****************************************************************************
|
4
|
+
** Copyright (c) 2001-2014
|
5
|
+
**
|
6
|
+
** This file is part of the QuickFIX FIX Engine
|
7
|
+
**
|
8
|
+
** This file may be distributed under the terms of the quickfixengine.org
|
9
|
+
** license as defined by quickfixengine.org and appearing in the file
|
10
|
+
** LICENSE included in the packaging of this file.
|
11
|
+
**
|
12
|
+
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
|
13
|
+
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
14
|
+
**
|
15
|
+
** See http://www.quickfixengine.org/LICENSE for licensing information.
|
16
|
+
**
|
17
|
+
** Contact ask@quickfixengine.org if any conditions of this licensing are
|
18
|
+
** not clear to you.
|
19
|
+
**
|
20
|
+
****************************************************************************/
|
21
|
+
|
22
|
+
#ifndef FIX_DATADICTIONARY_H
|
23
|
+
#define FIX_DATADICTIONARY_H
|
24
|
+
|
25
|
+
#ifdef _MSC_VER
|
26
|
+
#pragma warning(disable : 4503 4355 4786 4290)
|
27
|
+
#endif
|
28
|
+
|
29
|
+
#include "DOMDocument.h"
|
30
|
+
#include "Exceptions.h"
|
31
|
+
#include "FieldMap.h"
|
32
|
+
#include "Fields.h"
|
33
|
+
#include <map>
|
34
|
+
#include <set>
|
35
|
+
#include <string.h>
|
36
|
+
|
37
|
+
namespace FIX {
|
38
|
+
class FieldMap;
|
39
|
+
class Message;
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Represents a data dictionary for a version of %FIX.
|
43
|
+
*
|
44
|
+
* Generally loaded from an XML document. The DataDictionary is also
|
45
|
+
* responsible for validation beyond the basic structure of a message.
|
46
|
+
*/
|
47
|
+
|
48
|
+
class DataDictionary {
|
49
|
+
typedef std::set<int> MsgFields;
|
50
|
+
typedef std::map<std::string, MsgFields> MsgTypeToField;
|
51
|
+
typedef std::set<std::string> MsgTypes;
|
52
|
+
typedef std::set<int> Fields;
|
53
|
+
typedef std::map<int, bool> NonBodyFields;
|
54
|
+
typedef std::vector<int> OrderedFields;
|
55
|
+
|
56
|
+
struct MessageFieldsOrderHolder {
|
57
|
+
MessageFieldsOrderHolder() {}
|
58
|
+
|
59
|
+
~MessageFieldsOrderHolder() {}
|
60
|
+
|
61
|
+
void push_back(int field) { m_orderedFlds.push_back(field); }
|
62
|
+
|
63
|
+
const message_order &getMessageOrder() const {
|
64
|
+
if (m_msgOrder) {
|
65
|
+
return m_msgOrder;
|
66
|
+
}
|
67
|
+
|
68
|
+
int *tmp = new int[m_orderedFlds.size() + 1];
|
69
|
+
int *i = tmp;
|
70
|
+
|
71
|
+
for (OrderedFields::const_iterator iter = m_orderedFlds.begin(); iter != m_orderedFlds.end();
|
72
|
+
*(i++) = *(iter++)) {}
|
73
|
+
*i = 0;
|
74
|
+
|
75
|
+
m_msgOrder = message_order(tmp);
|
76
|
+
delete[] tmp;
|
77
|
+
|
78
|
+
return m_msgOrder;
|
79
|
+
}
|
80
|
+
|
81
|
+
private:
|
82
|
+
mutable message_order m_msgOrder;
|
83
|
+
OrderedFields m_orderedFlds;
|
84
|
+
};
|
85
|
+
|
86
|
+
typedef std::map<std::string, MessageFieldsOrderHolder> MsgTypeToOrderedFields;
|
87
|
+
|
88
|
+
typedef message_order OrderedFieldsArray;
|
89
|
+
typedef std::map<int, TYPE::Type> FieldTypes;
|
90
|
+
typedef std::set<std::string> Values;
|
91
|
+
typedef std::map<int, Values> FieldToValue;
|
92
|
+
typedef std::map<int, std::string> FieldToName;
|
93
|
+
typedef std::map<std::string, int> NameToField;
|
94
|
+
typedef std::map<std::pair<int, std::string>, std::string> ValueToName;
|
95
|
+
// while FieldToGroup structure seems to be overcomplicated
|
96
|
+
// in reality it yields a lot of performance because:
|
97
|
+
// 1) avoids memory copying;
|
98
|
+
// 2) first lookup is done by comparing integers and not string objects
|
99
|
+
// TODO: use hash_map with good hashing algorithm
|
100
|
+
typedef std::map<std::string, std::pair<int, DataDictionary *>> FieldPresenceMap;
|
101
|
+
typedef std::map<int, FieldPresenceMap> FieldToGroup;
|
102
|
+
|
103
|
+
public:
|
104
|
+
DataDictionary();
|
105
|
+
DataDictionary(const DataDictionary ©);
|
106
|
+
DataDictionary(std::istream &stream, bool preserveMsgFldsOrder = false) EXCEPT(ConfigError);
|
107
|
+
DataDictionary(const std::string &url, bool preserveMsgFldsOrder = false) EXCEPT(ConfigError);
|
108
|
+
virtual ~DataDictionary();
|
109
|
+
|
110
|
+
void readFromURL(const std::string &url) EXCEPT(ConfigError);
|
111
|
+
void readFromDocument(const DOMDocumentPtr &pDoc) EXCEPT(ConfigError);
|
112
|
+
void readFromStream(std::istream &stream) EXCEPT(ConfigError);
|
113
|
+
|
114
|
+
message_order const &getOrderedFields() const;
|
115
|
+
message_order const &getHeaderOrderedFields() const EXCEPT(ConfigError);
|
116
|
+
message_order const &getTrailerOrderedFields() const EXCEPT(ConfigError);
|
117
|
+
message_order const &getMessageOrderedFields(const std::string &msgType) const EXCEPT(ConfigError);
|
118
|
+
|
119
|
+
// storage functions
|
120
|
+
void setVersion(const std::string &beginString) {
|
121
|
+
m_beginString = beginString;
|
122
|
+
m_hasVersion = true;
|
123
|
+
}
|
124
|
+
std::string getVersion() const { return m_beginString.getString(); }
|
125
|
+
|
126
|
+
void addField(int field) {
|
127
|
+
m_fields.insert(field);
|
128
|
+
m_orderedFields.push_back(field);
|
129
|
+
}
|
130
|
+
|
131
|
+
void addFieldName(int field, const std::string &name) {
|
132
|
+
if (m_names.insert(std::make_pair(name, field)).second == false) {
|
133
|
+
throw ConfigError("Field named " + name + " defined multiple times");
|
134
|
+
}
|
135
|
+
m_fieldNames[field] = name;
|
136
|
+
}
|
137
|
+
|
138
|
+
bool getFieldName(int field, std::string &name) const {
|
139
|
+
FieldToName::const_iterator i = m_fieldNames.find(field);
|
140
|
+
if (i == m_fieldNames.end()) {
|
141
|
+
return false;
|
142
|
+
}
|
143
|
+
name = i->second;
|
144
|
+
return true;
|
145
|
+
}
|
146
|
+
|
147
|
+
bool getFieldTag(const std::string &name, int &field) const {
|
148
|
+
NameToField::const_iterator i = m_names.find(name);
|
149
|
+
if (i == m_names.end()) {
|
150
|
+
return false;
|
151
|
+
}
|
152
|
+
field = i->second;
|
153
|
+
return true;
|
154
|
+
}
|
155
|
+
|
156
|
+
void addValueName(int field, const std::string &value, const std::string &name) {
|
157
|
+
m_valueNames[std::make_pair(field, value)] = name;
|
158
|
+
m_nameValues[std::make_pair(field, name)] = value;
|
159
|
+
}
|
160
|
+
|
161
|
+
bool getValueName(int field, const std::string &value, std::string &name) const {
|
162
|
+
ValueToName::const_iterator i = m_valueNames.find(std::make_pair(field, value));
|
163
|
+
if (i == m_valueNames.end()) {
|
164
|
+
return false;
|
165
|
+
}
|
166
|
+
name = i->second;
|
167
|
+
return true;
|
168
|
+
}
|
169
|
+
|
170
|
+
bool getNameValue(int field, const std::string &name, std::string &value) const {
|
171
|
+
ValueToName::const_iterator i = m_nameValues.find(std::make_pair(field, name));
|
172
|
+
if (m_nameValues.end() == i) {
|
173
|
+
return false;
|
174
|
+
}
|
175
|
+
value = i->second;
|
176
|
+
return true;
|
177
|
+
}
|
178
|
+
|
179
|
+
bool isField(int field) const { return m_fields.find(field) != m_fields.end(); }
|
180
|
+
|
181
|
+
void addMsgType(const std::string &msgType) { m_messages.insert(msgType); }
|
182
|
+
|
183
|
+
bool isMsgType(const std::string &msgType) const { return m_messages.find(msgType) != m_messages.end(); }
|
184
|
+
|
185
|
+
void addMsgField(const std::string &msgType, int field) {
|
186
|
+
if (m_storeMsgFieldsOrder) {
|
187
|
+
m_messageOrderedFields[msgType].push_back(field);
|
188
|
+
}
|
189
|
+
|
190
|
+
m_messageFields[msgType].insert(field);
|
191
|
+
}
|
192
|
+
|
193
|
+
bool isMsgField(const std::string &msgType, int field) const {
|
194
|
+
MsgTypeToField::const_iterator i = m_messageFields.find(msgType);
|
195
|
+
if (i == m_messageFields.end()) {
|
196
|
+
return false;
|
197
|
+
}
|
198
|
+
return i->second.find(field) != i->second.end();
|
199
|
+
}
|
200
|
+
|
201
|
+
void addHeaderField(int field, bool required) {
|
202
|
+
if (m_storeMsgFieldsOrder) {
|
203
|
+
m_headerOrderedFields.push_back(field);
|
204
|
+
}
|
205
|
+
|
206
|
+
m_headerFields[field] = required;
|
207
|
+
}
|
208
|
+
|
209
|
+
bool isHeaderField(int field) const { return m_headerFields.find(field) != m_headerFields.end(); }
|
210
|
+
|
211
|
+
void addTrailerField(int field, bool required) {
|
212
|
+
if (m_storeMsgFieldsOrder) {
|
213
|
+
m_trailerOrderedFields.push_back(field);
|
214
|
+
}
|
215
|
+
|
216
|
+
m_trailerFields[field] = required;
|
217
|
+
}
|
218
|
+
|
219
|
+
bool isTrailerField(int field) const { return m_trailerFields.find(field) != m_trailerFields.end(); }
|
220
|
+
|
221
|
+
void addFieldType(int field, FIX::TYPE::Type type) {
|
222
|
+
m_fieldTypes[field] = type;
|
223
|
+
|
224
|
+
if (type == FIX::TYPE::Data) {
|
225
|
+
m_dataFields.insert(field);
|
226
|
+
}
|
227
|
+
}
|
228
|
+
|
229
|
+
bool getFieldType(int field, FIX::TYPE::Type &type) const {
|
230
|
+
FieldTypes::const_iterator i = m_fieldTypes.find(field);
|
231
|
+
if (i == m_fieldTypes.end()) {
|
232
|
+
return false;
|
233
|
+
}
|
234
|
+
type = i->second;
|
235
|
+
return true;
|
236
|
+
}
|
237
|
+
|
238
|
+
void addRequiredField(const std::string &msgType, int field) { m_requiredFields[msgType].insert(field); }
|
239
|
+
|
240
|
+
bool isRequiredField(const std::string &msgType, int field) const {
|
241
|
+
MsgTypeToField::const_iterator i = m_requiredFields.find(msgType);
|
242
|
+
if (i == m_requiredFields.end()) {
|
243
|
+
return false;
|
244
|
+
}
|
245
|
+
return i->second.find(field) != i->second.end();
|
246
|
+
}
|
247
|
+
|
248
|
+
void addFieldValue(int field, const std::string &value) { m_fieldValues[field].insert(value); }
|
249
|
+
|
250
|
+
bool hasFieldValue(int field) const {
|
251
|
+
FieldToValue::const_iterator i = m_fieldValues.find(field);
|
252
|
+
return i != m_fieldValues.end();
|
253
|
+
}
|
254
|
+
|
255
|
+
bool isFieldValue(int field, const std::string &value) const {
|
256
|
+
FieldToValue::const_iterator i = m_fieldValues.find(field);
|
257
|
+
if (i == m_fieldValues.end()) {
|
258
|
+
return false;
|
259
|
+
}
|
260
|
+
if (!isMultipleValueField(field)) {
|
261
|
+
return i->second.find(value) != i->second.end();
|
262
|
+
}
|
263
|
+
|
264
|
+
// MultipleValue
|
265
|
+
std::string::size_type startPos = 0;
|
266
|
+
std::string::size_type endPos = 0;
|
267
|
+
do {
|
268
|
+
endPos = value.find_first_of(' ', startPos);
|
269
|
+
std::string singleValue = value.substr(startPos, endPos - startPos);
|
270
|
+
if (i->second.find(singleValue) == i->second.end()) {
|
271
|
+
return false;
|
272
|
+
}
|
273
|
+
startPos = endPos + 1;
|
274
|
+
} while (endPos != std::string::npos);
|
275
|
+
return true;
|
276
|
+
}
|
277
|
+
|
278
|
+
void addGroup(const std::string &msg, int field, int delim, const DataDictionary &dataDictionary) {
|
279
|
+
DataDictionary *pDD = new DataDictionary(dataDictionary);
|
280
|
+
pDD->setVersion(getVersion());
|
281
|
+
|
282
|
+
FieldPresenceMap &presenceMap = m_groups[field];
|
283
|
+
presenceMap[msg] = std::make_pair(delim, pDD);
|
284
|
+
}
|
285
|
+
|
286
|
+
bool isGroup(const std::string &msg, int field) const {
|
287
|
+
FieldToGroup::const_iterator i = m_groups.find(field);
|
288
|
+
if (i == m_groups.end()) {
|
289
|
+
return false;
|
290
|
+
}
|
291
|
+
|
292
|
+
const FieldPresenceMap &presenceMap = i->second;
|
293
|
+
|
294
|
+
FieldPresenceMap::const_iterator iter = presenceMap.find(msg);
|
295
|
+
return (iter != presenceMap.end());
|
296
|
+
}
|
297
|
+
|
298
|
+
bool getGroup(const std::string &msg, int field, int &delim, const DataDictionary *&pDataDictionary) const {
|
299
|
+
FieldToGroup::const_iterator i = m_groups.find(field);
|
300
|
+
if (i == m_groups.end()) {
|
301
|
+
return false;
|
302
|
+
}
|
303
|
+
|
304
|
+
const FieldPresenceMap &presenceMap = i->second;
|
305
|
+
|
306
|
+
FieldPresenceMap::const_iterator iter = presenceMap.find(msg);
|
307
|
+
if (iter == presenceMap.end()) {
|
308
|
+
return false;
|
309
|
+
}
|
310
|
+
|
311
|
+
std::pair<int, DataDictionary *> pair = iter->second;
|
312
|
+
delim = pair.first;
|
313
|
+
pDataDictionary = pair.second;
|
314
|
+
return true;
|
315
|
+
}
|
316
|
+
|
317
|
+
bool isDataField(int field) const {
|
318
|
+
MsgFields::const_iterator iter = m_dataFields.find(field);
|
319
|
+
return iter != m_dataFields.end();
|
320
|
+
}
|
321
|
+
|
322
|
+
bool isMultipleValueField(int field) const {
|
323
|
+
FieldTypes::const_iterator i = m_fieldTypes.find(field);
|
324
|
+
return i != m_fieldTypes.end()
|
325
|
+
&& (i->second == TYPE::MultipleValueString || i->second == TYPE::MultipleCharValue
|
326
|
+
|| i->second == TYPE::MultipleStringValue);
|
327
|
+
}
|
328
|
+
|
329
|
+
void checkFieldsOutOfOrder(bool value) { m_checkFieldsOutOfOrder = value; }
|
330
|
+
void checkFieldsHaveValues(bool value) { m_checkFieldsHaveValues = value; }
|
331
|
+
void checkUserDefinedFields(bool value) { m_checkUserDefinedFields = value; }
|
332
|
+
void allowUnknownMsgFields(bool value) { m_allowUnknownMessageFields = value; }
|
333
|
+
void preserveMessageFieldsOrder(bool value) { m_storeMsgFieldsOrder = value; }
|
334
|
+
bool isMessageFieldsOrderPreserved() const { return m_storeMsgFieldsOrder; }
|
335
|
+
|
336
|
+
/// Validate a message.
|
337
|
+
static void validate(
|
338
|
+
const Message &message,
|
339
|
+
const DataDictionary *const pSessionDD,
|
340
|
+
const DataDictionary *const pAppID) EXCEPT(FIX::Exception);
|
341
|
+
|
342
|
+
void validate(const Message &message) const EXCEPT(FIX::Exception) { validate(message, false); }
|
343
|
+
void validate(const Message &message, bool bodyOnly) const EXCEPT(FIX::Exception) {
|
344
|
+
validate(message, bodyOnly ? (DataDictionary *)0 : this, this);
|
345
|
+
}
|
346
|
+
|
347
|
+
DataDictionary &operator=(const DataDictionary &rhs);
|
348
|
+
|
349
|
+
private:
|
350
|
+
/// Iterate through fields while applying checks.
|
351
|
+
void iterate(const FieldMap &map, const MsgType &msgType) const;
|
352
|
+
|
353
|
+
/// Check if message type is defined in spec.
|
354
|
+
void checkMsgType(const MsgType &msgType) const {
|
355
|
+
if (!isMsgType(msgType.getValue())) {
|
356
|
+
throw InvalidMessageType();
|
357
|
+
}
|
358
|
+
}
|
359
|
+
|
360
|
+
/// If we need to check for the tag in the dictionary
|
361
|
+
bool shouldCheckTag(const FieldBase &field) const {
|
362
|
+
if (m_allowUnknownMessageFields && field.getTag() < FIELD::UserMin) {
|
363
|
+
return false;
|
364
|
+
} else if (!m_checkUserDefinedFields && field.getTag() >= FIELD::UserMin) {
|
365
|
+
return false;
|
366
|
+
} else {
|
367
|
+
return true;
|
368
|
+
}
|
369
|
+
}
|
370
|
+
|
371
|
+
/// Check if field tag number is defined in spec.
|
372
|
+
void checkValidTagNumber(const FieldBase &field) const EXCEPT(InvalidTagNumber) {
|
373
|
+
if (m_fields.find(field.getTag()) == m_fields.end()) {
|
374
|
+
throw InvalidTagNumber(field.getTag());
|
375
|
+
}
|
376
|
+
}
|
377
|
+
|
378
|
+
void checkValidFormat(const FieldBase &field) const EXCEPT(IncorrectDataFormat) {
|
379
|
+
try {
|
380
|
+
TYPE::Type type = TYPE::Unknown;
|
381
|
+
getFieldType(field.getTag(), type);
|
382
|
+
switch (type) {
|
383
|
+
case TYPE::String:
|
384
|
+
STRING_CONVERTOR::convert(field.getString());
|
385
|
+
break;
|
386
|
+
case TYPE::Char:
|
387
|
+
CHAR_CONVERTOR::convert(field.getString());
|
388
|
+
break;
|
389
|
+
case TYPE::Price:
|
390
|
+
PRICE_CONVERTOR::convert(field.getString());
|
391
|
+
break;
|
392
|
+
case TYPE::Int:
|
393
|
+
INT_CONVERTOR::convert(field.getString());
|
394
|
+
break;
|
395
|
+
case TYPE::Amt:
|
396
|
+
AMT_CONVERTOR::convert(field.getString());
|
397
|
+
break;
|
398
|
+
case TYPE::Qty:
|
399
|
+
QTY_CONVERTOR::convert(field.getString());
|
400
|
+
break;
|
401
|
+
case TYPE::Currency:
|
402
|
+
CURRENCY_CONVERTOR::convert(field.getString());
|
403
|
+
break;
|
404
|
+
case TYPE::MultipleValueString:
|
405
|
+
MULTIPLEVALUESTRING_CONVERTOR::convert(field.getString());
|
406
|
+
break;
|
407
|
+
case TYPE::MultipleStringValue:
|
408
|
+
MULTIPLESTRINGVALUE_CONVERTOR::convert(field.getString());
|
409
|
+
break;
|
410
|
+
case TYPE::MultipleCharValue:
|
411
|
+
MULTIPLECHARVALUE_CONVERTOR::convert(field.getString());
|
412
|
+
break;
|
413
|
+
case TYPE::Exchange:
|
414
|
+
EXCHANGE_CONVERTOR::convert(field.getString());
|
415
|
+
break;
|
416
|
+
case TYPE::UtcTimeStamp:
|
417
|
+
UTCTIMESTAMP_CONVERTOR::convert(field.getString());
|
418
|
+
break;
|
419
|
+
case TYPE::Boolean:
|
420
|
+
BOOLEAN_CONVERTOR::convert(field.getString());
|
421
|
+
break;
|
422
|
+
case TYPE::LocalMktTime:
|
423
|
+
LOCALMKTTIME_CONVERTOR::convert(field.getString());
|
424
|
+
break;
|
425
|
+
case TYPE::LocalMktDate:
|
426
|
+
LOCALMKTDATE_CONVERTOR::convert(field.getString());
|
427
|
+
break;
|
428
|
+
case TYPE::Data:
|
429
|
+
DATA_CONVERTOR::convert(field.getString());
|
430
|
+
break;
|
431
|
+
case TYPE::Float:
|
432
|
+
FLOAT_CONVERTOR::convert(field.getString());
|
433
|
+
break;
|
434
|
+
case TYPE::PriceOffset:
|
435
|
+
PRICEOFFSET_CONVERTOR::convert(field.getString());
|
436
|
+
break;
|
437
|
+
case TYPE::MonthYear:
|
438
|
+
MONTHYEAR_CONVERTOR::convert(field.getString());
|
439
|
+
break;
|
440
|
+
case TYPE::DayOfMonth:
|
441
|
+
DAYOFMONTH_CONVERTOR::convert(field.getString());
|
442
|
+
break;
|
443
|
+
case TYPE::UtcDate:
|
444
|
+
UTCDATE_CONVERTOR::convert(field.getString());
|
445
|
+
break;
|
446
|
+
case TYPE::UtcTimeOnly:
|
447
|
+
UTCTIMEONLY_CONVERTOR::convert(field.getString());
|
448
|
+
break;
|
449
|
+
case TYPE::NumInGroup:
|
450
|
+
NUMINGROUP_CONVERTOR::convert(field.getString());
|
451
|
+
break;
|
452
|
+
case TYPE::Percentage:
|
453
|
+
PERCENTAGE_CONVERTOR::convert(field.getString());
|
454
|
+
break;
|
455
|
+
case TYPE::SeqNum:
|
456
|
+
SEQNUM_CONVERTOR::convert(field.getString());
|
457
|
+
break;
|
458
|
+
case TYPE::TagNum:
|
459
|
+
TAGNUM_CONVERTOR::convert(field.getString());
|
460
|
+
break;
|
461
|
+
case TYPE::Length:
|
462
|
+
LENGTH_CONVERTOR::convert(field.getString());
|
463
|
+
break;
|
464
|
+
case TYPE::Country:
|
465
|
+
COUNTRY_CONVERTOR::convert(field.getString());
|
466
|
+
break;
|
467
|
+
case TYPE::TzTimeOnly:
|
468
|
+
TZTIMEONLY_CONVERTOR::convert(field.getString());
|
469
|
+
break;
|
470
|
+
case TYPE::TzTimeStamp:
|
471
|
+
TZTIMESTAMP_CONVERTOR::convert(field.getString());
|
472
|
+
break;
|
473
|
+
case TYPE::XmlData:
|
474
|
+
XMLDATA_CONVERTOR::convert(field.getString());
|
475
|
+
break;
|
476
|
+
case TYPE::Language:
|
477
|
+
LANGUAGE_CONVERTOR::convert(field.getString());
|
478
|
+
break;
|
479
|
+
case TYPE::Xid:
|
480
|
+
XID_CONVERTOR::convert(field.getString());
|
481
|
+
break;
|
482
|
+
case TYPE::XidRef:
|
483
|
+
XIDREF_CONVERTOR::convert(field.getString());
|
484
|
+
break;
|
485
|
+
case TYPE::Unknown:
|
486
|
+
break;
|
487
|
+
}
|
488
|
+
} catch (FieldConvertError &) {
|
489
|
+
throw IncorrectDataFormat(field.getTag(), field.getString());
|
490
|
+
}
|
491
|
+
}
|
492
|
+
|
493
|
+
void checkValue(const FieldBase &field) const EXCEPT(IncorrectTagValue) {
|
494
|
+
if (!hasFieldValue(field.getTag())) {
|
495
|
+
return;
|
496
|
+
}
|
497
|
+
|
498
|
+
const std::string &value = field.getString();
|
499
|
+
if (!isFieldValue(field.getTag(), value)) {
|
500
|
+
throw IncorrectTagValue(field.getTag());
|
501
|
+
}
|
502
|
+
}
|
503
|
+
|
504
|
+
/// Check if a field has a value.
|
505
|
+
void checkHasValue(const FieldBase &field) const EXCEPT(NoTagValue) {
|
506
|
+
if (m_checkFieldsHaveValues && !field.getString().length()) {
|
507
|
+
throw NoTagValue(field.getTag());
|
508
|
+
}
|
509
|
+
}
|
510
|
+
|
511
|
+
/// Check if a field is in this message type.
|
512
|
+
void checkIsInMessage(const FieldBase &field, const MsgType &msgType) const EXCEPT(TagNotDefinedForMessage) {
|
513
|
+
if (!isMsgField(msgType, field.getTag())) {
|
514
|
+
throw TagNotDefinedForMessage(field.getTag());
|
515
|
+
}
|
516
|
+
}
|
517
|
+
|
518
|
+
/// Check if group count matches number of groups in
|
519
|
+
void checkGroupCount(const FieldBase &field, const FieldMap &fieldMap, const MsgType &msgType) const
|
520
|
+
EXCEPT(RepeatingGroupCountMismatch) {
|
521
|
+
int fieldNum = field.getTag();
|
522
|
+
if (isGroup(msgType, fieldNum)) {
|
523
|
+
if ((int)fieldMap.groupCount(fieldNum) != IntConvertor::convert(field.getString())) {
|
524
|
+
throw RepeatingGroupCountMismatch(fieldNum);
|
525
|
+
}
|
526
|
+
}
|
527
|
+
}
|
528
|
+
|
529
|
+
/// Check if a message has all required fields.
|
530
|
+
void checkHasRequired(const FieldMap &header, const FieldMap &body, const FieldMap &trailer, const MsgType &msgType)
|
531
|
+
const EXCEPT(RequiredTagMissing) {
|
532
|
+
for (const NonBodyFields::value_type &NBF : m_headerFields) {
|
533
|
+
if (NBF.second == true && !header.isSetField(NBF.first)) {
|
534
|
+
throw RequiredTagMissing(NBF.first);
|
535
|
+
}
|
536
|
+
}
|
537
|
+
|
538
|
+
for (const NonBodyFields::value_type &NBF : m_trailerFields) {
|
539
|
+
if (NBF.second == true && !trailer.isSetField(NBF.first)) {
|
540
|
+
throw RequiredTagMissing(NBF.first);
|
541
|
+
}
|
542
|
+
}
|
543
|
+
|
544
|
+
MsgTypeToField::const_iterator iM = m_requiredFields.find(msgType.getString());
|
545
|
+
if (iM == m_requiredFields.end()) {
|
546
|
+
return;
|
547
|
+
}
|
548
|
+
|
549
|
+
const MsgFields &fields = iM->second;
|
550
|
+
MsgFields::const_iterator iF;
|
551
|
+
for (const MsgFields::value_type &F : fields) {
|
552
|
+
if (!body.isSetField(F)) {
|
553
|
+
throw RequiredTagMissing(F);
|
554
|
+
}
|
555
|
+
}
|
556
|
+
|
557
|
+
for (FieldMap::g_const_iterator groups = body.g_begin(); groups != body.g_end(); ++groups) {
|
558
|
+
int delim;
|
559
|
+
const DataDictionary *DD = 0;
|
560
|
+
int field = groups->first;
|
561
|
+
if (getGroup(msgType.getValue(), field, delim, DD)) {
|
562
|
+
for (const FieldMap *group : groups->second) {
|
563
|
+
DD->checkHasRequired(*group, *group, *group, msgType);
|
564
|
+
}
|
565
|
+
}
|
566
|
+
}
|
567
|
+
}
|
568
|
+
|
569
|
+
int lookupXMLFieldNumber(DOMDocument *, DOMNode *) const;
|
570
|
+
int lookupXMLFieldNumber(DOMDocument *, const std::string &name) const;
|
571
|
+
int addXMLComponentFields(DOMDocument *, DOMNode *, const std::string &msgtype, DataDictionary &, bool);
|
572
|
+
void addXMLGroup(DOMDocument *, DOMNode *, const std::string &msgtype, DataDictionary &, bool);
|
573
|
+
TYPE::Type XMLTypeToType(const std::string &xmlType) const;
|
574
|
+
|
575
|
+
bool m_hasVersion;
|
576
|
+
bool m_checkFieldsOutOfOrder;
|
577
|
+
bool m_checkFieldsHaveValues;
|
578
|
+
bool m_checkUserDefinedFields;
|
579
|
+
bool m_allowUnknownMessageFields;
|
580
|
+
bool m_storeMsgFieldsOrder;
|
581
|
+
|
582
|
+
BeginString m_beginString;
|
583
|
+
MsgTypeToField m_messageFields;
|
584
|
+
MsgTypeToField m_requiredFields;
|
585
|
+
MsgTypes m_messages;
|
586
|
+
Fields m_fields;
|
587
|
+
OrderedFields m_orderedFields;
|
588
|
+
mutable OrderedFieldsArray m_orderedFieldsArray;
|
589
|
+
NonBodyFields m_headerFields;
|
590
|
+
NonBodyFields m_trailerFields;
|
591
|
+
FieldTypes m_fieldTypes;
|
592
|
+
FieldToValue m_fieldValues;
|
593
|
+
FieldToName m_fieldNames;
|
594
|
+
NameToField m_names;
|
595
|
+
ValueToName m_valueNames;
|
596
|
+
ValueToName m_nameValues;
|
597
|
+
FieldToGroup m_groups;
|
598
|
+
MsgFields m_dataFields;
|
599
|
+
OrderedFields m_headerOrderedFields;
|
600
|
+
mutable OrderedFieldsArray m_headerOrder;
|
601
|
+
OrderedFields m_trailerOrderedFields;
|
602
|
+
mutable OrderedFieldsArray m_trailerOrder;
|
603
|
+
MsgTypeToOrderedFields m_messageOrderedFields;
|
604
|
+
};
|
605
|
+
} // namespace FIX
|
606
|
+
|
607
|
+
#endif // FIX_DATADICTIONARY_H
|
@@ -0,0 +1,66 @@
|
|
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 "DataDictionaryProvider.h"
|
28
|
+
#include "Fields.h"
|
29
|
+
|
30
|
+
namespace FIX {
|
31
|
+
DataDictionaryProvider::DataDictionaryProvider(const DataDictionaryProvider ©) { *this = copy; }
|
32
|
+
|
33
|
+
const DataDictionary &DataDictionaryProvider::getSessionDataDictionary(const BeginString &beginString) const
|
34
|
+
EXCEPT(DataDictionaryNotFound) {
|
35
|
+
std::map<std::string, std::shared_ptr<DataDictionary>>::const_iterator find
|
36
|
+
= m_transportDictionaries.find(beginString);
|
37
|
+
if (find != m_transportDictionaries.end()) {
|
38
|
+
return *find->second;
|
39
|
+
}
|
40
|
+
|
41
|
+
return emptyDataDictionary;
|
42
|
+
}
|
43
|
+
|
44
|
+
const DataDictionary &DataDictionaryProvider::getApplicationDataDictionary(const ApplVerID &applVerID) const
|
45
|
+
EXCEPT(DataDictionaryNotFound) {
|
46
|
+
std::map<std::string, std::shared_ptr<DataDictionary>>::const_iterator find
|
47
|
+
= m_applicationDictionaries.find(applVerID);
|
48
|
+
if (find != m_applicationDictionaries.end()) {
|
49
|
+
return *find->second;
|
50
|
+
}
|
51
|
+
|
52
|
+
return emptyDataDictionary;
|
53
|
+
}
|
54
|
+
|
55
|
+
void DataDictionaryProvider::addTransportDataDictionary(
|
56
|
+
const BeginString &beginString,
|
57
|
+
std::shared_ptr<DataDictionary> pDD) {
|
58
|
+
m_transportDictionaries[beginString.getValue()] = pDD;
|
59
|
+
}
|
60
|
+
|
61
|
+
void DataDictionaryProvider::addApplicationDataDictionary(
|
62
|
+
const ApplVerID &applVerID,
|
63
|
+
std::shared_ptr<DataDictionary> pDD) {
|
64
|
+
m_applicationDictionaries[applVerID.getValue()] = pDD;
|
65
|
+
}
|
66
|
+
} // namespace FIX
|