quickfix_ruby 1.14.3.1 → 1.15.1

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 (105) hide show
  1. checksums.yaml +4 -4
  2. data/ext/quickfix/Acceptor.h +2 -0
  3. data/ext/quickfix/AtomicCount.h +82 -12
  4. data/ext/quickfix/DOMDocument.h +9 -7
  5. data/ext/quickfix/DataDictionary.cpp +77 -14
  6. data/ext/quickfix/DataDictionary.h +90 -16
  7. data/ext/quickfix/Dictionary.cpp +1 -2
  8. data/ext/quickfix/Exceptions.h +3 -5
  9. data/ext/quickfix/Field.h +83 -32
  10. data/ext/quickfix/FieldConvertors.cpp +93 -0
  11. data/ext/quickfix/FieldConvertors.h +129 -275
  12. data/ext/quickfix/FieldMap.cpp +53 -13
  13. data/ext/quickfix/FieldMap.h +200 -62
  14. data/ext/quickfix/FieldTypes.cpp +10 -10
  15. data/ext/quickfix/FieldTypes.h +293 -44
  16. data/ext/quickfix/FileLog.cpp +6 -10
  17. data/ext/quickfix/FileLog.h +4 -10
  18. data/ext/quickfix/FileStore.cpp +19 -6
  19. data/ext/quickfix/FileStore.h +4 -0
  20. data/ext/quickfix/FixFieldNumbers.h +1462 -1461
  21. data/ext/quickfix/FixFields.h +1462 -1461
  22. data/ext/quickfix/FixValues.h +3230 -3227
  23. data/ext/quickfix/HttpConnection.cpp +1 -1
  24. data/ext/quickfix/Initiator.cpp +7 -1
  25. data/ext/quickfix/Initiator.h +2 -0
  26. data/ext/quickfix/Log.h +6 -12
  27. data/ext/quickfix/Message.cpp +186 -57
  28. data/ext/quickfix/Message.h +109 -47
  29. data/ext/quickfix/MySQLConnection.h +1 -1
  30. data/ext/quickfix/PostgreSQLConnection.h +1 -1
  31. data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
  32. data/ext/quickfix/QuickfixRuby.h +1 -1
  33. data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
  34. data/ext/quickfix/SSLSocketAcceptor.h +185 -0
  35. data/ext/quickfix/SSLSocketConnection.cpp +427 -0
  36. data/ext/quickfix/SSLSocketConnection.h +206 -0
  37. data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
  38. data/ext/quickfix/SSLSocketInitiator.h +196 -0
  39. data/ext/quickfix/Session.cpp +113 -20
  40. data/ext/quickfix/Session.h +18 -4
  41. data/ext/quickfix/SessionFactory.cpp +10 -3
  42. data/ext/quickfix/SessionSettings.cpp +5 -3
  43. data/ext/quickfix/SessionSettings.h +97 -5
  44. data/ext/quickfix/Settings.cpp +72 -2
  45. data/ext/quickfix/Settings.h +3 -0
  46. data/ext/quickfix/SharedArray.h +140 -6
  47. data/ext/quickfix/SocketConnection.cpp +2 -2
  48. data/ext/quickfix/SocketConnector.cpp +5 -2
  49. data/ext/quickfix/SocketConnector.h +3 -2
  50. data/ext/quickfix/SocketInitiator.cpp +28 -4
  51. data/ext/quickfix/SocketInitiator.h +1 -1
  52. data/ext/quickfix/SocketMonitor.cpp +5 -5
  53. data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
  54. data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
  55. data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
  56. data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
  57. data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
  58. data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
  59. data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
  60. data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
  61. data/ext/quickfix/ThreadedSocketConnection.h +4 -1
  62. data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
  63. data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
  64. data/ext/quickfix/Utility.cpp +23 -1
  65. data/ext/quickfix/Utility.h +28 -2
  66. data/ext/quickfix/UtilitySSL.cpp +1733 -0
  67. data/ext/quickfix/UtilitySSL.h +277 -0
  68. data/ext/quickfix/config-all.h +10 -0
  69. data/ext/quickfix/dirent_windows.h +838 -0
  70. data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
  71. data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
  72. data/ext/quickfix/double-conversion/bignum.cc +766 -0
  73. data/ext/quickfix/double-conversion/bignum.h +144 -0
  74. data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
  75. data/ext/quickfix/double-conversion/cached-powers.h +64 -0
  76. data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
  77. data/ext/quickfix/double-conversion/diy-fp.h +118 -0
  78. data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
  79. data/ext/quickfix/double-conversion/double-conversion.h +543 -0
  80. data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
  81. data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
  82. data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
  83. data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
  84. data/ext/quickfix/double-conversion/ieee.h +402 -0
  85. data/ext/quickfix/double-conversion/strtod.cc +557 -0
  86. data/ext/quickfix/double-conversion/strtod.h +45 -0
  87. data/ext/quickfix/double-conversion/utils.h +372 -0
  88. data/ext/quickfix/stdint_msvc.h +254 -0
  89. data/lib/quickfix44.rb +3329 -10
  90. data/lib/quickfix50.rb +6649 -81
  91. data/lib/quickfix50sp1.rb +8054 -142
  92. data/lib/quickfix50sp2.rb +10900 -234
  93. data/lib/quickfix_fields.rb +7662 -7649
  94. data/spec/FIX40.xml +28 -28
  95. data/spec/FIX41.xml +29 -29
  96. data/spec/FIX42.xml +47 -47
  97. data/spec/FIX43.xml +148 -148
  98. data/spec/FIX44.xml +1078 -1081
  99. data/spec/FIX50.xml +1292 -1289
  100. data/spec/FIX50SP1.xml +1811 -1802
  101. data/spec/FIX50SP2.xml +1948 -1939
  102. data/spec/FIXT11.xml +5 -8
  103. data/test/test_FieldBaseTestCase.rb +1 -1
  104. data/test/test_MessageTestCase.rb +2 -2
  105. metadata +42 -6
@@ -180,9 +180,22 @@ public:
180
180
  { m_refreshOnLogon = value; }
181
181
 
182
182
  bool getMillisecondsInTimeStamp()
183
- { return m_millisecondsInTimeStamp; }
183
+ { return (m_timestampPrecision == 3); }
184
184
  void setMillisecondsInTimeStamp ( bool value )
185
- { m_millisecondsInTimeStamp = value; }
185
+ { if (value)
186
+ m_timestampPrecision = 3;
187
+ else
188
+ m_timestampPrecision = 0;
189
+ }
190
+ int getTimestampPrecision()
191
+ { return m_timestampPrecision; }
192
+ void setTimestampPrecision(int precision)
193
+ {
194
+ if (precision < 0 || precision > 9)
195
+ return;
196
+
197
+ m_timestampPrecision = precision;
198
+ }
186
199
 
187
200
  bool getPersistMessages()
188
201
  { return m_persistMessages; }
@@ -298,6 +311,8 @@ private:
298
311
  bool set( int s, const Message& m );
299
312
  bool get( int s, Message& m ) const;
300
313
 
314
+ Message * newMessage(const std::string & msgType) const;
315
+
301
316
  Application& m_application;
302
317
  SessionID m_sessionID;
303
318
  TimeRange m_sessionTime;
@@ -313,7 +328,7 @@ private:
313
328
  bool m_resetOnLogout;
314
329
  bool m_resetOnDisconnect;
315
330
  bool m_refreshOnLogon;
316
- bool m_millisecondsInTimeStamp;
331
+ int m_timestampPrecision;
317
332
  bool m_persistMessages;
318
333
  bool m_validateLengthAndChecksum;
319
334
 
@@ -328,7 +343,6 @@ private:
328
343
  static SessionIDs s_sessionIDs;
329
344
  static Sessions s_registered;
330
345
  static Mutex s_mutex;
331
-
332
346
  };
333
347
  }
334
348
 
@@ -120,7 +120,7 @@ Session* SessionFactory::create( const SessionID& sessionID,
120
120
  if ( heartBtInt <= 0 ) throw ConfigError( "Heartbeat must be greater than zero" );
121
121
  }
122
122
 
123
- std::auto_ptr<Session> pSession;
123
+ SmartPtr<Session> pSession;
124
124
  pSession.reset( new Session( m_application, m_messageStoreFactory,
125
125
  sessionID, dataDictionaryProvider, sessionTimeRange,
126
126
  heartBtInt, m_pLogFactory ) );
@@ -189,7 +189,9 @@ Session* SessionFactory::create( const SessionID& sessionID,
189
189
  if ( settings.has( REFRESH_ON_LOGON ) )
190
190
  pSession->setRefreshOnLogon( settings.getBool( REFRESH_ON_LOGON ) );
191
191
  if ( settings.has( MILLISECONDS_IN_TIMESTAMP ) )
192
- pSession->setMillisecondsInTimeStamp( settings.getBool( MILLISECONDS_IN_TIMESTAMP ) );
192
+ pSession->setTimestampPrecision(3);
193
+ if ( settings.has( TIMESTAMP_PRECISION ) )
194
+ pSession->setTimestampPrecision(settings.getInt( TIMESTAMP_PRECISION ) );
193
195
  if ( settings.has( PERSIST_MESSAGES ) )
194
196
  pSession->setPersistMessages( settings.getBool( PERSIST_MESSAGES ) );
195
197
  if ( settings.has( VALIDATE_LENGTH_AND_CHECKSUM ) )
@@ -216,7 +218,10 @@ ptr::shared_ptr<DataDictionary> SessionFactory::createDataDictionary(const Sessi
216
218
  }
217
219
  else
218
220
  {
219
- pDD = ptr::shared_ptr<DataDictionary>(new DataDictionary( path ));
221
+ bool preserveMsgFldsOrder = false;
222
+ if( settings.has( PRESERVE_MESSAGE_FIELDS_ORDER ) )
223
+ preserveMsgFldsOrder = settings.getBool( PRESERVE_MESSAGE_FIELDS_ORDER );
224
+ pDD = ptr::shared_ptr<DataDictionary>(new DataDictionary( path, preserveMsgFldsOrder ));
220
225
  m_dictionaries[ path ] = pDD;
221
226
  }
222
227
 
@@ -228,6 +233,8 @@ ptr::shared_ptr<DataDictionary> SessionFactory::createDataDictionary(const Sessi
228
233
  pCopyOfDD->checkFieldsHaveValues( settings.getBool( VALIDATE_FIELDS_HAVE_VALUES ) );
229
234
  if( settings.has( VALIDATE_USER_DEFINED_FIELDS ) )
230
235
  pCopyOfDD->checkUserDefinedFields( settings.getBool( VALIDATE_USER_DEFINED_FIELDS ) );
236
+ if( settings.has( ALLOW_UNKNOWN_MSG_FIELDS ) )
237
+ pCopyOfDD->allowUnknownMsgFields( settings.getBool( ALLOW_UNKNOWN_MSG_FIELDS ) );
231
238
 
232
239
  return pCopyOfDD;
233
240
  }
@@ -30,14 +30,16 @@
30
30
 
31
31
  namespace FIX
32
32
  {
33
- SessionSettings::SessionSettings( std::istream& stream )
33
+ SessionSettings::SessionSettings( std::istream& stream, bool resolveEnvVars )
34
34
  throw( ConfigError )
35
+ : m_resolveEnvVars( resolveEnvVars )
35
36
  {
36
37
  stream >> *this;
37
38
  }
38
39
 
39
- SessionSettings::SessionSettings( const std::string& file )
40
+ SessionSettings::SessionSettings( const std::string& file, bool resolveEnvVars )
40
41
  throw( ConfigError )
42
+ : m_resolveEnvVars( resolveEnvVars )
41
43
  {
42
44
  std::ifstream fstream( file.c_str() );
43
45
  if ( !fstream.is_open() )
@@ -48,7 +50,7 @@ throw( ConfigError )
48
50
  std::istream& operator>>( std::istream& stream, SessionSettings& s )
49
51
  throw( ConfigError )
50
52
  {
51
- Settings settings;
53
+ Settings settings(s.m_resolveEnvVars);
52
54
  stream >> settings;
53
55
 
54
56
  Settings::Sections section;
@@ -63,14 +63,18 @@ const char SOCKET_ACCEPT_PORT[] = "SocketAcceptPort";
63
63
  const char SOCKET_REUSE_ADDRESS[] = "SocketReuseAddress";
64
64
  const char SOCKET_CONNECT_HOST[] = "SocketConnectHost";
65
65
  const char SOCKET_CONNECT_PORT[] = "SocketConnectPort";
66
+ const char SOCKET_CONNECT_SOURCE_HOST[] = "SocketConnectSourceHost";
67
+ const char SOCKET_CONNECT_SOURCE_PORT[] = "SocketConnectSourcePort";
66
68
  const char SOCKET_NODELAY[] = "SocketNodelay";
67
- const char SOCKET_SEND_BUFFER_SIZE[] = "SendBufferSize";
68
- const char SOCKET_RECEIVE_BUFFER_SIZE[] = "ReceiveBufferSize";
69
+ const char SOCKET_SEND_BUFFER_SIZE[] = "SocketSendBufferSize";
70
+ const char SOCKET_RECEIVE_BUFFER_SIZE[] = "SocketReceiveBufferSize";
69
71
  const char RECONNECT_INTERVAL[] = "ReconnectInterval";
70
72
  const char VALIDATE_LENGTH_AND_CHECKSUM[] = "ValidateLengthAndChecksum";
71
73
  const char VALIDATE_FIELDS_OUT_OF_ORDER[] = "ValidateFieldsOutOfOrder";
72
74
  const char VALIDATE_FIELDS_HAVE_VALUES[] = "ValidateFieldsHaveValues";
73
75
  const char VALIDATE_USER_DEFINED_FIELDS[] = "ValidateUserDefinedFields";
76
+ const char ALLOW_UNKNOWN_MSG_FIELDS[] = "AllowUnknownMsgFields";
77
+ const char PRESERVE_MESSAGE_FIELDS_ORDER[] = "PreserveMessageFieldsOrder";
74
78
  const char LOGON_TIMEOUT[] = "LogonTimeout";
75
79
  const char LOGOUT_TIMEOUT[] = "LogoutTimeout";
76
80
  const char FILE_STORE_PATH[] = "FileStorePath";
@@ -123,16 +127,102 @@ const char RESET_ON_LOGOUT[] = "ResetOnLogout";
123
127
  const char RESET_ON_DISCONNECT[] = "ResetOnDisconnect";
124
128
  const char REFRESH_ON_LOGON[] = "RefreshOnLogon";
125
129
  const char MILLISECONDS_IN_TIMESTAMP[] = "MillisecondsInTimeStamp";
130
+ const char TIMESTAMP_PRECISION[] = "TimestampPrecision";
126
131
  const char HTTP_ACCEPT_PORT[] = "HttpAcceptPort";
127
132
  const char PERSIST_MESSAGES[] = "PersistMessages";
133
+ const char SERVER_CERT_FILE[] = "ServerCertificateFile";
134
+ const char SERVER_CERT_KEY_FILE[] = "ServerCertificateKeyFile";
135
+ const char CLIENT_CERT_FILE[] = "ClientCertificateFile";
136
+ const char CLIENT_CERT_KEY_FILE[] = "ClientCertificateKeyFile";
137
+ const char CERT_AUTH_FILE[] = "CertificationAuthoritiesFile";
138
+ const char CERT_AUTH_DIR[] = "CertificationAuthoritiesDirectory";
139
+ const char CRL_FILE[] = "CertificateRevocationListFile";
140
+ const char CRL_DIR[] = "CertificateRevocationListDirectory";
141
+ const char VERIFY_LEVEL[] = "CertificateVerifyLevel";
142
+ /*
143
+ # This directive can be used to control the SSL protocol flavors the application
144
+ # should use when establishing its environment.
145
+ #
146
+ # The available (case-insensitive) protocols are:
147
+ #
148
+ # SSLv2
149
+ #
150
+ # This is the Secure Sockets Layer (SSL) protocol, version 2.0. It is the
151
+ # original SSL protocol as designed by Netscape Corporation.
152
+ #
153
+ # SSLv3
154
+ #
155
+ # This is the Secure Sockets Layer (SSL) protocol, version 3.0. It is the
156
+ # successor to SSLv2 and the currently (as of February 1999) de-facto
157
+ # standardized SSL protocol from Netscape Corporation. It's supported by
158
+ # almost all popular browsers.
159
+ #
160
+ # TLSv1
161
+ #
162
+ # This is the Transport Layer Security (TLS) protocol, version 1.0.
163
+ #
164
+ # TLSv1_1
165
+ #
166
+ # This is the Transport Layer Security (TLS) protocol, version 1.1.
167
+ #
168
+ # TLSv1_2
169
+ #
170
+ # This is the Transport Layer Security (TLS) protocol, version 1.2.
171
+ #
172
+ # all
173
+ #
174
+ # This is a shortcut for `+SSLv2 +SSLv3 +TLSv1 +TLSv1_1 +TLSv1_2' and a convenient way for
175
+ # enabling all protocols except one when used in combination with the minus
176
+ # sign on a protocol as the example above shows.
177
+ #
178
+ # Example:
179
+ #
180
+ # enable all but not SSLv2
181
+ # SSL_PROTOCOL = all -SSLv2
182
+ #
183
+ # `all -SSLv2` is the default value when the parameter is not specified.
184
+
185
+ */
186
+ const char SSL_PROTOCOL[] = "SSLProtocol";
187
+ /*
188
+ # This complex directive uses a colon-separated cipher-spec string consisting
189
+ # of OpenSSL cipher specifications to configure the Cipher Suite the client is
190
+ # permitted to negotiate in the SSL handshake phase. Notice that this directive
191
+ # can be used both in per-server and per-directory context. In per-server
192
+ # context it applies to the standard SSL handshake when a connection is
193
+ # established. In per-directory context it forces a SSL renegotation with the
194
+ # reconfigured Cipher Suite after the HTTP request was read but before the HTTP
195
+ # response is sent.
196
+ #
197
+ # An SSL cipher specification in cipher-spec is composed of 4 major attributes
198
+ # plus a few extra minor ones:
199
+ #
200
+ # Key Exchange Algorithm:
201
+ # RSA or Diffie-Hellman variants.
202
+ #
203
+ # Authentication Algorithm:
204
+ # RSA, Diffie-Hellman, DSS or none.
205
+ #
206
+ # Cipher/Encryption Algorithm:
207
+ # DES, Triple-DES, RC4, RC2, IDEA or none.
208
+ #
209
+ # MAC Digest Algorithm:
210
+ # MD5, SHA or SHA1.
211
+ #
212
+ # For more details refer to mod_ssl documentation.
213
+ #
214
+ # Example: RC4+RSA:+HIGH:
215
+ */
216
+ const char SSL_CIPHER_SUITE[] = "SSLCipherSuite";
217
+
128
218
 
129
219
  /// Container for setting dictionaries mapped to sessions.
130
220
  class SessionSettings
131
221
  {
132
222
  public:
133
- SessionSettings() {}
134
- SessionSettings( std::istream& stream ) throw( ConfigError );
135
- SessionSettings( const std::string& file ) throw( ConfigError );
223
+ SessionSettings() { m_resolveEnvVars = false; }
224
+ SessionSettings( std::istream& stream, bool resolveEnvVars = false ) throw( ConfigError );
225
+ SessionSettings( const std::string& file, bool resolveEnvVars = false ) throw( ConfigError );
136
226
 
137
227
  /// Check if session setings are present
138
228
  const bool has( const SessionID& ) const;
@@ -158,7 +248,9 @@ private:
158
248
 
159
249
  Dictionaries m_settings;
160
250
  Dictionary m_defaults;
251
+ bool m_resolveEnvVars; // while reading, replace $var, $(var) and ${var} by environment variable var
161
252
 
253
+ friend std::istream& operator>>( std::istream&, SessionSettings& ) throw( ConfigError );
162
254
  friend std::ostream& operator<<( std::ostream&, const SessionSettings& );
163
255
  };
164
256
  /*! @} */
@@ -23,6 +23,7 @@
23
23
  #include "config.h"
24
24
  #endif
25
25
 
26
+ #include <cstring>
26
27
  #include "Settings.h"
27
28
 
28
29
  namespace FIX
@@ -61,13 +62,82 @@ std::pair<std::string, std::string> splitKeyValue( const std::string& line )
61
62
  return std::pair<std::string, std::string>( key, value );
62
63
  }
63
64
 
65
+ std::string resolveEnvVars(const std::string& str)
66
+ {
67
+ std::string resultStr;
68
+ size_t actPos = 0;
69
+ size_t sourceLen = str.length();
70
+
71
+ while (actPos < sourceLen)
72
+ {
73
+ char c = str[actPos++];
74
+ if (actPos < sourceLen)
75
+ {
76
+ // escape character
77
+ if (c == '\\')
78
+ {
79
+ c = str[actPos++];
80
+ switch (c)
81
+ {
82
+ case 't' : resultStr.append(1, '\t'); break;
83
+ case 'r' : resultStr.append(1, '\r'); break;
84
+ case 'n' : resultStr.append(1, '\n'); break;
85
+ default :
86
+ resultStr.append(1, c);
87
+ break;
88
+ }
89
+ continue;
90
+ }
91
+
92
+ // variable substitution
93
+ if (c == '$')
94
+ {
95
+ bool inBraces = false;
96
+ c = str[actPos++];
97
+ if ((c == '(') || (c == '{'))
98
+ {
99
+ c = str[actPos++];
100
+ inBraces = true;
101
+ }
102
+
103
+ // actPos now points at start of var name
104
+ if (actPos >= sourceLen)
105
+ break;
106
+ std::string varName;
107
+ while ( (actPos <= sourceLen) )
108
+ {
109
+ varName.append(1, c); // this must be done before overwriting c
110
+ c = str[actPos++];
111
+ if (std::strchr(" /:;,.=\"'?#+*()[]{}$&%\t\n", c))
112
+ break;
113
+ }
114
+ if (inBraces && (actPos <= sourceLen) && ((c == ')') || (c == '}')))
115
+ ;
116
+ else
117
+ --actPos;
118
+ // varName contains the name of the variable,
119
+ // actPos points to first char _after_ variable
120
+ const char *varValue = 0;
121
+ if (!varName.empty() && (0 != (varValue = getenv(varName.c_str()))))
122
+ resultStr.append(varValue);
123
+ continue;
124
+ }
125
+ }
126
+
127
+ // nothing special, just copy
128
+ resultStr.append(1, c);
129
+ }
130
+
131
+ return resultStr;
132
+ }
133
+
64
134
  std::istream& operator>>( std::istream& stream, Settings& s )
65
135
  {
66
136
  char buffer[1024];
67
137
  std::string line;
68
138
  Settings::Sections::iterator section = s.m_sections.end();;
69
139
 
70
- while( stream.getline(buffer, 1024) )
140
+ while( stream.getline(buffer, sizeof(buffer)) )
71
141
  {
72
142
  line = string_strip( buffer );
73
143
  if( isComment(line) )
@@ -83,7 +153,7 @@ std::istream& operator>>( std::istream& stream, Settings& s )
83
153
  std::pair<std::string, std::string> keyValue = splitKeyValue( line );
84
154
  if( section == s.m_sections.end() )
85
155
  continue;
86
- (*section).setString( keyValue.first, keyValue.second );
156
+ (*section).setString( keyValue.first, s.m_resolveEnvVars ? resolveEnvVars(keyValue.second) : keyValue.second );
87
157
  }
88
158
  }
89
159
  return stream;
@@ -38,6 +38,8 @@ namespace FIX
38
38
  class Settings
39
39
  {
40
40
  public:
41
+ Settings( bool resolveEnvVars = false ) : m_resolveEnvVars(resolveEnvVars) {}
42
+
41
43
  typedef std::vector < Dictionary > Sections;
42
44
 
43
45
  Sections get( const std::string& name ) const;
@@ -45,6 +47,7 @@ public:
45
47
  friend std::istream& operator>>( std::istream&, Settings& );
46
48
  private:
47
49
  Sections m_sections;
50
+ bool m_resolveEnvVars;
48
51
  };
49
52
 
50
53
  std::istream& operator>>( std::istream&, Settings& );
@@ -22,14 +22,21 @@
22
22
  #ifndef SHARED_ARRAY
23
23
  #define SHARED_ARRAY
24
24
 
25
+ #include "config-all.h"
25
26
  #include "AtomicCount.h"
26
27
 
27
28
  namespace FIX
28
29
  {
29
30
  /// Shared array with atomic reference count
31
+ #ifndef NO_UNALIGNED_ACCESS
30
32
  template<typename T>
31
33
  class shared_array
32
34
  {
35
+ enum
36
+ {
37
+ data_offset = ( sizeof(atomic_count) / sizeof(T) + 1 )
38
+ };
39
+
33
40
  public:
34
41
  shared_array()
35
42
  : m_size(0)
@@ -67,16 +74,16 @@ namespace FIX
67
74
  { return m_buffer == 0; }
68
75
 
69
76
  operator T* () const
70
- { return m_buffer; }
77
+ { return &m_buffer[data_offset]; }
71
78
 
72
79
  //optimized function to allocate storage for buffer and counter object at once
73
80
  static shared_array create(const std::size_t nSize)
74
81
  {
75
- if(nSize <= 0)
82
+ if(nSize == 0)
76
83
  return shared_array();
77
84
 
78
85
  //verify the needed buffer size to allocate counter object and nSize elements
79
- const std::size_t sizeToAllocate = nSize + ( sizeof(atomic_count) / sizeof(T) + 1 );
86
+ const std::size_t sizeToAllocate = data_offset + nSize;
80
87
 
81
88
  //allocate and zero-fill the buffer
82
89
  T* storage = new T[ sizeToAllocate ];
@@ -84,7 +91,7 @@ namespace FIX
84
91
 
85
92
  // create the counter object at the end of the storage
86
93
  // with initial reference count set to 1
87
- new (&storage[nSize]) atomic_count( 1 );
94
+ new (storage) atomic_count( 1 );
88
95
 
89
96
  return shared_array(storage, nSize);
90
97
  }
@@ -100,7 +107,7 @@ namespace FIX
100
107
 
101
108
  atomic_count* get_counter() const
102
109
  {
103
- return reinterpret_cast<atomic_count*>( &m_buffer[ size() ] );
110
+ return reinterpret_cast<atomic_count*>( m_buffer );
104
111
  }
105
112
 
106
113
  void increment_reference_count() const
@@ -109,7 +116,7 @@ namespace FIX
109
116
  ++(*counter);
110
117
  }
111
118
 
112
- long decrement_reference_count()
119
+ long decrement_reference_count() const
113
120
  {
114
121
  atomic_count* counter = get_counter();
115
122
  return --(*counter);
@@ -145,6 +152,133 @@ namespace FIX
145
152
  std::size_t m_size;
146
153
  T * m_buffer;
147
154
  };
155
+ #else
156
+ template<typename T>
157
+ class shared_array
158
+ {
159
+ public:
160
+ shared_array()
161
+ : m_size(0)
162
+ , m_buffer(0)
163
+ , m_pCtr(0)
164
+ {}
165
+
166
+ shared_array(const shared_array& rhs)
167
+ : m_size(rhs.m_size)
168
+ , m_buffer(rhs.m_buffer)
169
+ {
170
+ rhs.attach();
171
+ }
172
+
173
+ ~shared_array()
174
+ { release(); }
175
+
176
+ shared_array& operator=(const shared_array& rhs)
177
+ {
178
+ if( &rhs == this )
179
+ return *this;
180
+
181
+ rhs.attach();
182
+ release();
183
+
184
+ m_size = rhs.m_size;
185
+ m_buffer = rhs.m_buffer;
186
+ m_pCtr = rhs.m_pCtr;
187
+
188
+ return *this;
189
+ }
190
+
191
+ std::size_t size() const
192
+ { return m_size; }
193
+
194
+ bool empty() const
195
+ { return m_buffer == 0; }
196
+
197
+ operator T* () const
198
+ { return m_buffer; }
199
+
200
+ //optimized function to allocate storage for buffer and counter object at once
201
+ static shared_array create(const std::size_t nSize)
202
+ {
203
+ if(nSize <= 0)
204
+ return shared_array();
205
+
206
+ //verify the needed buffer size to allocate counter object and nSize elements
207
+ const std::size_t sizeToAllocate = (nSize * sizeof(T)) + sizeof(atomic_count) + 15;
208
+
209
+ //allocate and zero-fill the buffer
210
+ void * buf = std::malloc(sizeToAllocate);
211
+ memset(buf, 0, sizeToAllocate);
212
+
213
+ // create the counter object at the end of the storage
214
+ // with initial reference count set to 1
215
+ /* round up to multiple of alignment : add (alignment - 1) and then round down by masking */
216
+ void *ptr = (void *) (((uintptr_t)(buf) + nSize * sizeof(T) + 15) & ~ (uintptr_t)0x0F);
217
+ new (ptr) atomic_count( 1 );
218
+
219
+ T* storage = reinterpret_cast<T*>(buf);
220
+ return shared_array(storage, nSize, ptr);
221
+ }
222
+
223
+ private:
224
+
225
+ shared_array( T * buff, std::size_t nSize, void * pCtr )
226
+ : m_size(nSize)
227
+ , m_buffer(buff)
228
+ , m_pCtr(pCtr)
229
+ {
230
+
231
+ }
232
+
233
+ atomic_count* get_counter() const
234
+ {
235
+ return reinterpret_cast<atomic_count*>( m_pCtr );
236
+ }
237
+
238
+ void increment_reference_count() const
239
+ {
240
+ atomic_count* counter = get_counter();
241
+ ++(*counter);
242
+ }
243
+
244
+ long decrement_reference_count() const
245
+ {
246
+ atomic_count* counter = get_counter();
247
+ return --(*counter);
248
+ }
249
+
250
+ void attach() const
251
+ {
252
+ if( !empty() )
253
+ increment_reference_count();
254
+ }
255
+
256
+ void release()
257
+ {
258
+ if( empty() )
259
+ return;
260
+
261
+ //free object if reference count has decreased to zero
262
+ if( decrement_reference_count() == 0)
263
+ {
264
+ T * tmpBuff = m_buffer;
265
+ atomic_count* tmpCounter = get_counter();
266
+
267
+ m_buffer = 0;
268
+ m_size = 0;
269
+
270
+ //explicitly call destructor for the counter object
271
+ tmpCounter->~atomic_count();
272
+
273
+ std::free(tmpBuff);
274
+ }
275
+ }
276
+
277
+ std::size_t m_size;
278
+ T * m_buffer;
279
+ void * m_pCtr;
280
+ };
281
+ #endif
148
282
  }
149
283
 
150
284
  #endif