quickfix_ruby 1.14.3.1 → 1.15.1

Sign up to get free protection for your applications and to get access to all the features.
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