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
@@ -87,7 +87,7 @@ throw( ConfigError, FieldConvertError )
87
87
  try
88
88
  {
89
89
  std::string value = getString(key);
90
- if( value.size() < 2 ) throw FieldConvertError(0);
90
+ if( value.size() < 2 ) throw FieldConvertError();
91
91
  std::string abbr = value.substr(0, 2);
92
92
  std::transform( abbr.begin(), abbr.end(), abbr.begin(), tolower );
93
93
  if( abbr == "su" ) return 1;
@@ -97,7 +97,6 @@ throw( ConfigError, FieldConvertError )
97
97
  if( abbr == "th" ) return 5;
98
98
  if( abbr == "fr" ) return 6;
99
99
  if( abbr == "sa" ) return 7;
100
- if( value.size() < 2 ) throw FieldConvertError(0);
101
100
  }
102
101
  catch ( FieldConvertError& )
103
102
  {
@@ -250,22 +250,20 @@ struct SocketException : public Exception
250
250
  SocketException( const std::string& what )
251
251
  : Exception( "Socket Error", what ) {}
252
252
 
253
- std::string errorToWhat()
253
+ static std::string errorToWhat()
254
254
  {
255
255
  #ifdef _MSC_VER
256
- error = WSAGetLastError();
256
+ int error = WSAGetLastError();
257
257
  char buffer[2048];
258
258
  FormatMessageA( FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
259
259
  MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
260
260
  buffer, 2048, NULL );
261
261
  return buffer;
262
262
  #else
263
- error = errno;
263
+ int error = errno;
264
264
  return strerror( error );
265
265
  #endif
266
266
  }
267
-
268
- int error;
269
267
  };
270
268
 
271
269
  /// Socket send operation failed
@@ -33,6 +33,10 @@
33
33
  #include "FieldTypes.h"
34
34
  #include "Utility.h"
35
35
 
36
+ #if defined(__SUNPRO_CC)
37
+ #include <algorithm>
38
+ #endif
39
+
36
40
  namespace FIX
37
41
  {
38
42
  /**
@@ -73,30 +77,62 @@ class FieldBase
73
77
  friend class Message;
74
78
 
75
79
  /// Constructor which also calculates field metrics
76
- FieldBase( int field,
80
+ FieldBase( int tag,
77
81
  std::string::const_iterator valueStart,
78
82
  std::string::const_iterator valueEnd,
79
83
  std::string::const_iterator tagStart,
80
84
  std::string::const_iterator tagEnd )
81
- : m_field( field )
85
+ : m_tag( tag )
82
86
  , m_string( valueStart, valueEnd )
83
87
  , m_metrics( calculateMetrics( tagStart, tagEnd ) )
84
88
  {}
85
89
 
86
90
  public:
87
- FieldBase( int field, const std::string& string )
88
- : m_field( field ), m_string(string), m_metrics( no_metrics() )
91
+ FieldBase( int tag, const std::string& string )
92
+ : m_tag( tag ), m_string(string), m_metrics( no_metrics() )
89
93
  {}
90
94
 
91
95
  virtual ~FieldBase() {}
92
96
 
93
- void setField( int field )
97
+ FieldBase( const FieldBase& rhs )
98
+ : m_tag( rhs.getTag() )
99
+ , m_string( rhs.m_string )
100
+ , m_metrics( rhs.m_metrics )
101
+ {
102
+
103
+ }
104
+
105
+ FieldBase& operator=( const FieldBase& rhs)
106
+ {
107
+ m_tag = rhs.getTag();
108
+ m_string = rhs.m_string;
109
+ m_metrics = rhs.m_metrics;
110
+ m_data.clear();
111
+
112
+ return *this;
113
+ }
114
+
115
+ void swap( FieldBase& rhs )
94
116
  {
95
- m_field = field;
117
+ std::swap( m_tag, rhs.m_tag );
118
+ std::swap( m_metrics, rhs.m_metrics );
119
+ m_string.swap( rhs.m_string );
120
+ m_data.swap( rhs.m_data );
121
+ }
122
+
123
+ void setTag( int tag )
124
+ {
125
+ m_tag = tag;
96
126
  m_metrics = no_metrics();
97
127
  m_data.clear();
98
128
  }
99
129
 
130
+ /// @deprecated Use setTag
131
+ void setField( int field )
132
+ {
133
+ setTag( field );
134
+ }
135
+
100
136
  void setString( const std::string& string )
101
137
  {
102
138
  m_string = string;
@@ -105,8 +141,12 @@ public:
105
141
  }
106
142
 
107
143
  /// Get the fields integer tag.
144
+ int getTag() const
145
+ { return m_tag; }
146
+
147
+ /// @deprecated Use getTag
108
148
  int getField() const
109
- { return m_field; }
149
+ { return getTag(); }
110
150
 
111
151
  /// Get the string representation of the fields value.
112
152
  const std::string& getString() const
@@ -137,7 +177,7 @@ public:
137
177
 
138
178
  /// Compares fields based on their tag numbers
139
179
  bool operator < ( const FieldBase& field ) const
140
- { return m_field < field.m_field; }
180
+ { return m_tag < field.m_tag; }
141
181
 
142
182
  private:
143
183
 
@@ -151,16 +191,16 @@ private:
151
191
  /// Serializes string representation of the Field to input string
152
192
  void encodeTo( std::string& result ) const
153
193
  {
154
- size_t tagLength = FIX::number_of_symbols_in( m_field ) + 1;
155
- size_t totalLength = tagLength + m_string.length() + 1;
194
+ size_t tagLength = FIX::number_of_symbols_in( m_tag );
195
+ size_t totalLength = tagLength + m_string.length() + 2;
156
196
 
157
197
  result.resize( totalLength );
158
198
 
159
199
  char * buf = (char*)result.c_str();
160
- FIX::integer_to_string( buf, tagLength, m_field );
200
+ FIX::integer_to_string( buf, tagLength, m_tag );
161
201
 
162
- buf[tagLength - 1] = '=';
163
- memcpy( buf + tagLength, m_string.data(), m_string.length() );
202
+ buf[tagLength] = '=';
203
+ memcpy( buf + tagLength + 1, m_string.data(), m_string.length() );
164
204
  buf[totalLength - 1] = '\001';
165
205
  }
166
206
 
@@ -178,7 +218,13 @@ private:
178
218
  for ( std::string::const_iterator str = start; str != end; ++str )
179
219
  checksum += (unsigned char)( *str );
180
220
 
221
+ #if defined(__SUNPRO_CC)
222
+ std::ptrdiff_t d;
223
+ std::distance(start, end, d);
224
+ return field_metrics( d, checksum );
225
+ #else
181
226
  return field_metrics( std::distance( start, end ), checksum );
227
+ #endif
182
228
  }
183
229
 
184
230
  static field_metrics calculateMetrics( const std::string& field )
@@ -186,7 +232,7 @@ private:
186
232
  return calculateMetrics( field.begin(), field.end() );
187
233
  }
188
234
 
189
- int m_field;
235
+ int m_tag;
190
236
  std::string m_string;
191
237
  mutable std::string m_data;
192
238
  mutable field_metrics m_metrics;
@@ -200,6 +246,11 @@ inline std::ostream& operator <<
200
246
  return stream;
201
247
  }
202
248
 
249
+ inline void swap( FieldBase& lhs, FieldBase& rhs )
250
+ {
251
+ lhs.swap( rhs );
252
+ }
253
+
203
254
  /**
204
255
  * MSC doesn't support partial template specialization so we have this.
205
256
  * this is here to provide equality checking against native char arrays.
@@ -323,7 +374,7 @@ public:
323
374
  { try
324
375
  { return CharConvertor::convert( getString() ); }
325
376
  catch( FieldConvertError& )
326
- { throw IncorrectDataFormat( getField(), getString() ); } }
377
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
327
378
  operator char() const
328
379
  { return getValue(); }
329
380
  };
@@ -343,7 +394,7 @@ public:
343
394
  { try
344
395
  { return DoubleConvertor::convert( getString() ); }
345
396
  catch( FieldConvertError& )
346
- { throw IncorrectDataFormat( getField(), getString() ); } }
397
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
347
398
  operator double() const
348
399
  { return getValue(); }
349
400
  };
@@ -363,7 +414,7 @@ public:
363
414
  { try
364
415
  { return IntConvertor::convert( getString() ); }
365
416
  catch( FieldConvertError& )
366
- { throw IncorrectDataFormat( getField(), getString() ); } }
417
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
367
418
  operator const int() const
368
419
  { return getValue(); }
369
420
  };
@@ -383,7 +434,7 @@ public:
383
434
  { try
384
435
  { return BoolConvertor::convert( getString() ); }
385
436
  catch( FieldConvertError& )
386
- { throw IncorrectDataFormat( getField(), getString() ); } }
437
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
387
438
  operator bool() const
388
439
  { return getValue(); }
389
440
  };
@@ -392,10 +443,10 @@ public:
392
443
  class UtcTimeStampField : public FieldBase
393
444
  {
394
445
  public:
395
- explicit UtcTimeStampField( int field, const UtcTimeStamp& data, bool showMilliseconds = false )
396
- : FieldBase( field, UtcTimeStampConvertor::convert( data, showMilliseconds ) ) {}
397
- UtcTimeStampField( int field, bool showMilliseconds = false )
398
- : FieldBase( field, UtcTimeStampConvertor::convert( UtcTimeStamp(), showMilliseconds ) ) {}
446
+ explicit UtcTimeStampField( int field, const UtcTimeStamp& data, int precision = 0 )
447
+ : FieldBase( field, UtcTimeStampConvertor::convert( data, precision ) ) {}
448
+ UtcTimeStampField( int field, int precision = 0 )
449
+ : FieldBase( field, UtcTimeStampConvertor::convert( UtcTimeStamp(), precision ) ) {}
399
450
 
400
451
  void setValue( const UtcTimeStamp& value )
401
452
  { setString( UtcTimeStampConvertor::convert( value ) ); }
@@ -403,7 +454,7 @@ public:
403
454
  { try
404
455
  { return UtcTimeStampConvertor::convert( getString() ); }
405
456
  catch( FieldConvertError& )
406
- { throw IncorrectDataFormat( getField(), getString() ); } }
457
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
407
458
  operator UtcTimeStamp() const
408
459
  { return getValue(); }
409
460
 
@@ -430,7 +481,7 @@ public:
430
481
  { try
431
482
  { return UtcDateConvertor::convert( getString() ); }
432
483
  catch( FieldConvertError& )
433
- { throw IncorrectDataFormat( getField(), getString() ); } }
484
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
434
485
  operator UtcDate() const
435
486
  { return getValue(); }
436
487
 
@@ -446,10 +497,10 @@ public:
446
497
  class UtcTimeOnlyField : public FieldBase
447
498
  {
448
499
  public:
449
- explicit UtcTimeOnlyField( int field, const UtcTimeOnly& data, bool showMilliseconds = false )
450
- : FieldBase( field, UtcTimeOnlyConvertor::convert( data, showMilliseconds ) ) {}
451
- UtcTimeOnlyField( int field, bool showMilliseconds = false )
452
- : FieldBase( field, UtcTimeOnlyConvertor::convert( UtcTimeOnly(), showMilliseconds ) ) {}
500
+ explicit UtcTimeOnlyField( int field, const UtcTimeOnly& data, int precision = 0 )
501
+ : FieldBase( field, UtcTimeOnlyConvertor::convert( data, precision ) ) {}
502
+ UtcTimeOnlyField( int field, int precision = 0 )
503
+ : FieldBase( field, UtcTimeOnlyConvertor::convert( UtcTimeOnly(), precision ) ) {}
453
504
 
454
505
  void setValue( const UtcTimeOnly& value )
455
506
  { setString( UtcTimeOnlyConvertor::convert( value ) ); }
@@ -457,7 +508,7 @@ public:
457
508
  { try
458
509
  { return UtcTimeOnlyConvertor::convert( getString() ); }
459
510
  catch( FieldConvertError& )
460
- { throw IncorrectDataFormat( getField(), getString() ); } }
511
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
461
512
  operator UtcTimeOnly() const
462
513
  { return getValue(); }
463
514
 
@@ -484,7 +535,7 @@ public:
484
535
  { try
485
536
  { return CheckSumConvertor::convert( getString() ); }
486
537
  catch( FieldConvertError& )
487
- { throw IncorrectDataFormat( getField(), getString() ); } }
538
+ { throw IncorrectDataFormat( getTag(), getString() ); } }
488
539
  operator const int() const
489
540
  { return getValue(); }
490
541
  };
@@ -529,9 +580,9 @@ DEFINE_FIELD_CLASS_NUM(NAME, TOK, TYPE, DEPRECATED_FIELD::NAME)
529
580
  #define DEFINE_FIELD_TIMECLASS_NUM( NAME, TOK, TYPE, NUM ) \
530
581
  class NAME : public TOK##Field { public: \
531
582
  NAME() : TOK##Field(NUM, false) {} \
532
- NAME(bool showMilliseconds) : TOK##Field(NUM, showMilliseconds) {} \
583
+ NAME(int precision) : TOK##Field(NUM, precision) {} \
533
584
  NAME(const TYPE& value) : TOK##Field(NUM, value) {} \
534
- NAME(const TYPE& value, bool showMilliseconds) : TOK##Field(NUM, value, showMilliseconds) {} \
585
+ NAME(const TYPE& value, int precision) : TOK##Field(NUM, value, precision) {} \
535
586
  }
536
587
 
537
588
  #define DEFINE_FIELD_TIMECLASS( NAME, TOK, TYPE ) \
@@ -0,0 +1,93 @@
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 <math.h>
27
+ #include "FieldConvertors.h"
28
+ #include <math.h>
29
+
30
+ namespace FIX
31
+ {
32
+
33
+ // we include "double-conversion" project in FIX namespace
34
+ // to avoid linking errors if quickfix is linked statically
35
+ // and "double-conversion" is already used by target project
36
+
37
+ #include "double-conversion/diy-fp.cc"
38
+ #include "double-conversion/fixed-dtoa.cc"
39
+ #include "double-conversion/bignum.cc"
40
+ #include "double-conversion/bignum-dtoa.cc"
41
+ #include "double-conversion/cached-powers.cc"
42
+ #include "double-conversion/fast-dtoa.cc"
43
+ #include "double-conversion/strtod.cc"
44
+ #include "double-conversion/double-conversion.cc"
45
+
46
+ static double_conversion::DoubleToStringConverter g_dtoa_converter(
47
+ double_conversion::DoubleToStringConverter::NO_FLAGS,
48
+ "INF",
49
+ "NAN",
50
+ 'e',
51
+ -DoubleConvertor::SIGNIFICANT_DIGITS,
52
+ DoubleConvertor::SIGNIFICANT_DIGITS,
53
+ DoubleConvertor::SIGNIFICANT_DIGITS - 1,
54
+ 0);
55
+
56
+ static double_conversion::StringToDoubleConverter g_atod_converter(
57
+ double_conversion::StringToDoubleConverter::NO_FLAGS,
58
+ std::numeric_limits<double>::quiet_NaN(),
59
+ std::numeric_limits<double>::quiet_NaN(),
60
+ "INF",
61
+ "NAN");
62
+
63
+ double DoubleConvertor::fast_strtod( const char * buffer, int size, int * processed_chars )
64
+ {
65
+ return g_atod_converter.StringToDouble( buffer, size, processed_chars );
66
+ }
67
+
68
+ int DoubleConvertor::fast_dtoa( char * buffer, int size, double value )
69
+ {
70
+ double_conversion::StringBuilder builder( buffer, size );
71
+ if( !g_dtoa_converter.ToPrecision( value, DoubleConvertor::SIGNIFICANT_DIGITS, &builder ) )
72
+ {
73
+ builder.Reset();
74
+ return 0;
75
+ }
76
+
77
+ builder.TrimTrailingZeros();
78
+ return builder.position();
79
+ }
80
+
81
+ int DoubleConvertor::fast_fixed_dtoa( char * buffer, int size, double value )
82
+ {
83
+ double_conversion::StringBuilder builder( buffer, size );
84
+ if( !g_dtoa_converter.ToFixed( value, DoubleConvertor::SIGNIFICANT_DIGITS, &builder ) )
85
+ {
86
+ builder.Reset();
87
+ return 0;
88
+ }
89
+
90
+ return builder.position();
91
+ }
92
+
93
+ }
@@ -22,14 +22,20 @@
22
22
  #ifndef FIX_FIELDCONVERTORS_H
23
23
  #define FIX_FIELDCONVERTORS_H
24
24
 
25
+ #ifdef _MSC_VER
26
+ #pragma warning( disable: 4146 )
27
+ #endif
28
+
25
29
  #include "FieldTypes.h"
26
30
  #include "Exceptions.h"
27
31
  #include "Utility.h"
32
+ #include "config-all.h"
28
33
  #include <string>
29
34
  #include <sstream>
30
35
  #include <iomanip>
31
36
  #include <cstdio>
32
37
  #include <limits>
38
+ #include <iterator>
33
39
 
34
40
  namespace FIX
35
41
  {
@@ -37,7 +43,7 @@ namespace FIX
37
43
  typedef int signed_int;
38
44
  typedef unsigned int unsigned_int;
39
45
 
40
- #define UNSIGNED_VALUE_OF( x ) unsigned_int( x < 0 ? -x : x )
46
+ #define UNSIGNED_VALUE_OF( x ) ( ( x < 0 ) ? -unsigned_int(x) : unsigned_int(x) )
41
47
 
42
48
  #define IS_SPACE( x ) ( x == ' ' )
43
49
  #define IS_DIGIT( x ) ( unsigned_int( x - '0' ) < 10 )
@@ -95,22 +101,21 @@ inline char* integer_to_string( char* buf, const size_t len, signed_int t )
95
101
  const bool isNegative = t < 0;
96
102
  char* p = buf + len;
97
103
 
98
- *--p = '\0';
99
-
100
104
  unsigned_int number = UNSIGNED_VALUE_OF( t );
101
105
 
102
106
  while( number > 99 )
103
107
  {
104
108
  unsigned_int pos = number % 100;
105
109
  number /= 100;
106
- p -= 2;
107
- *(short*)(p) = *(short*)(digit_pairs + 2 * pos);
110
+
111
+ *--p = digit_pairs[2 * pos + 1];
112
+ *--p = digit_pairs[2 * pos];
108
113
  }
109
114
 
110
115
  if( number > 9 )
111
116
  {
112
- p -= 2;
113
- *(short*)(p) = *(short*)(digit_pairs + 2 * number);
117
+ *--p = digit_pairs[2 * number + 1];
118
+ *--p = digit_pairs[2 * number];
114
119
  }
115
120
  else
116
121
  {
@@ -125,16 +130,10 @@ inline char* integer_to_string( char* buf, const size_t len, signed_int t )
125
130
 
126
131
  inline char* integer_to_string_padded
127
132
  ( char* buf, const size_t len, signed_int t,
128
- const size_t width = 0,
129
133
  const char paddingChar = '0')
130
134
  {
131
135
  char* p = integer_to_string( buf, len, t );
132
- if( !width )
133
- return p;
134
-
135
- const char* stop_p = buf + len - width - 1;
136
- if( stop_p < buf ) stop_p = buf;
137
- while( p > stop_p )
136
+ while( p > buf )
138
137
  *--p = paddingChar;
139
138
  return p;
140
139
  }
@@ -155,10 +154,10 @@ struct IntConvertor
155
154
  {
156
155
  // buffer is big enough for significant digits and extra digit,
157
156
  // minus and null
158
- char buffer[std::numeric_limits<signed_int>::digits10 + 3];
157
+ char buffer[std::numeric_limits<signed_int>::digits10 + 2];
159
158
  const char* const start
160
159
  = integer_to_string( buffer, sizeof (buffer), value );
161
- return std::string( start, buffer + sizeof (buffer) - start - 1 );
160
+ return std::string( start, buffer + sizeof (buffer) - start );
162
161
  }
163
162
 
164
163
  static bool convert(
@@ -187,7 +186,7 @@ struct IntConvertor
187
186
  } while ( ++str != end );
188
187
 
189
188
  if( isNegative )
190
- x = -x;
189
+ x = -unsigned_int(x);
191
190
 
192
191
  result = x;
193
192
  return true;
@@ -207,70 +206,6 @@ struct IntConvertor
207
206
  else
208
207
  return result;
209
208
  }
210
-
211
- /// Converts only positive number e.g. FIX field ID: [1 ... 2147483647]
212
- /// No leading whitespace/zero/plus/sign symbols allowed
213
- /// Value is fixed to not make difference between 32bit and 64bit code
214
- static bool convertPositive(
215
- std::string::const_iterator str,
216
- std::string::const_iterator end,
217
- signed_int& result )
218
- {
219
- const int MAX_VALUE = 2147483647; // max value for 32-bit signed integer
220
- const int HIGH_MARK = MAX_VALUE / 10;
221
- const unsigned_int STOP_SYMBOL = MAX_VALUE % 10;
222
- const std::size_t MAX_DIGITS = 10; // integer can hold up to 10 digits
223
-
224
- const std::size_t length = std::distance( str, end );
225
- if( length < 1 || length > MAX_DIGITS)
226
- return false;
227
-
228
- if( length == MAX_DIGITS )
229
- {
230
- end = str;
231
- std::advance( end, length - 1 );
232
- }
233
-
234
- const unsigned_int ch = *str - '1';
235
- if( ch > 8 )
236
- return false;
237
-
238
- unsigned_int x = 0;
239
-
240
- do
241
- {
242
- const unsigned_int c = *str - '0';
243
- if( c > 9 ) return false;
244
- x = 10 * x + c;
245
- } while( ++str < end );
246
-
247
- // complete overflow condition check and value calculation
248
- // this saves about 25% of speed when executed out of the main loop
249
- if( length == MAX_DIGITS )
250
- {
251
- if( x > (unsigned int)HIGH_MARK )
252
- return false;
253
-
254
- const unsigned_int c = *str - '0';
255
- if( x == (unsigned int)HIGH_MARK && c > STOP_SYMBOL )
256
- return false;
257
-
258
- x = 10 * x + c;
259
- }
260
-
261
- result = x;
262
- return true;
263
- }
264
-
265
- static signed_int convertPositive( const std::string& value )
266
- throw( FieldConvertError )
267
- {
268
- signed_int result = 0;
269
- if( !convertPositive( value.begin(), value.end(), result ) )
270
- throw FieldConvertError(value);
271
- else
272
- return result;
273
- }
274
209
  };
275
210
 
276
211
  /// Converts checksum to/from a string
@@ -280,12 +215,12 @@ struct CheckSumConvertor
280
215
  throw( FieldConvertError )
281
216
  {
282
217
  if ( value > 255 || value < 0 ) throw FieldConvertError();
283
- char result[4];
284
- if( integer_to_string_padded(result, sizeof(result), value, 3) != result )
218
+ char result[3];
219
+ if( integer_to_string_padded(result, sizeof(result), value) != result )
285
220
  {
286
221
  throw FieldConvertError();
287
222
  }
288
- return std::string( result, 3 );
223
+ return std::string( result, sizeof( result ) );
289
224
  }
290
225
 
291
226
  static bool convert( const std::string& value, int& result )
@@ -306,107 +241,28 @@ struct DoubleConvertor
306
241
 
307
242
  private:
308
243
 
309
- /*Simple and fast atof (ascii to float) function.
310
- Executes about 5x faster than standard MSCRT library atof().
311
- An attractive alternative if the number of calls is in the millions.
312
- Assumes input is a proper integer, fraction, or scientific format.
313
- Matches library atof() to 15 digits (except at extreme exponents).
314
- Follows atof() precedent of essentially no error checking.
315
- 09-May-2009 Tom Van Baak (tvb) www.LeapSecond.com */
316
- static double fast_atof (const char *p)
317
- {
318
- bool frac(false);
319
- double sign(1.), value(0.), scale(1.);
320
-
321
- while (IS_SPACE(*p))
322
- ++p;
323
-
324
- // Get sign, if any.
325
- if (*p == '-')
326
- {
327
- sign = -1.;
328
- ++p;
329
- }
330
- else if (*p == '+')
331
- ++p;
332
-
333
- // Get digits before decimal point or exponent, if any.
334
- while (IS_DIGIT(*p))
335
- {
336
- value = value * 10. + (*p - '0');
337
- ++p;
338
- }
339
-
340
- // Get digits after decimal point, if any.
341
- if (*p == '.')
342
- {
343
- ++p;
344
- double pow10(10.);
345
- while (IS_DIGIT(*p))
346
- {
347
- value += (*p - '0') / pow10;
348
- pow10 *= 10.;
349
- ++p;
350
- }
351
- }
352
-
353
- // Handle exponent, if any.
354
- if (toupper(*p) == 'E')
355
- {
356
- unsigned int expon(0);
357
- ++p;
358
-
359
- // Get sign of exponent, if any.
360
- if (*p == '-')
361
- {
362
- frac = true;
363
- ++p;
364
- }
365
- else if (*p == '+')
366
- ++p;
367
-
368
- // Get digits of exponent, if any.
369
- while (IS_DIGIT(*p))
370
- {
371
- expon = expon * 10 + (*p - '0');
372
- ++p;
373
- }
374
- if (expon > 308)
375
- expon = 308;
244
+ static double fast_strtod( const char * buffer, int size, int * processed_chars );
376
245
 
377
- // Calculate scaling factor.
378
- while (expon >= 50)
379
- {
380
- scale *= 1E50;
381
- expon -= 50;
382
- }
383
- while (expon >= 8)
384
- {
385
- scale *= 1E8;
386
- expon -= 8;
387
- }
388
- while (expon > 0)
389
- {
390
- scale *= 10.0;
391
- expon -= 1;
392
- }
393
- }
246
+ static int fast_dtoa( char * buffer, int size, double value );
394
247
 
395
- // Return signed and scaled floating point result.
396
- return sign * (frac ? (value / scale) : (value * scale));
397
- }
248
+ static int fast_fixed_dtoa( char * buffer, int size, double value );
398
249
 
399
250
  public:
400
251
 
252
+ static const int SIGNIFICANT_DIGITS = 15;
253
+ static const int BUFFFER_SIZE = 32;
254
+
401
255
  static std::string convert( double value, int padding = 0 )
402
256
  {
403
- char result[32];
257
+ char result[BUFFFER_SIZE];
404
258
  char *end = 0;
405
259
 
406
260
  int size;
407
- if( value == 0 || value > 0.0001 || value <= -0.0001 )
261
+ if( value == 0 || value > 0.0001 || value < -0.0001 )
408
262
  {
409
- size = STRING_SPRINTF( result, "%.15g", value );
263
+ size = fast_dtoa( result, BUFFFER_SIZE, value );
264
+ if( size == 0 )
265
+ return std::string();
410
266
 
411
267
  if( padding > 0 )
412
268
  {
@@ -419,42 +275,44 @@ public:
419
275
  {
420
276
  end = point;
421
277
  *point = '.';
422
- size++;
278
+ ++size;
423
279
  }
424
280
  int needed = padding - (int)(end - point);
425
281
 
426
- while( needed-- > 0 )
282
+ if( needed > 0 )
427
283
  {
428
- *(++end) = '0';
429
- size++;
284
+ memset( ++end, '0', needed );
285
+ size += needed;
430
286
  }
431
- *(end+1) = 0;
432
287
  }
433
288
  }
434
289
  else
435
290
  {
436
- size = STRING_SPRINTF( result, "%.15f", value );
291
+ size = fast_fixed_dtoa( result, BUFFFER_SIZE, value );
292
+ if( size == 0 )
293
+ return std::string();
294
+
437
295
  // strip trailing 0's
438
296
  end = result + size - 1;
439
297
 
440
298
  if( padding > 0 )
441
299
  {
442
- int discard = 15 - padding;
300
+ int discard = SIGNIFICANT_DIGITS - padding;
443
301
 
444
302
  while( (*end == '0') && (discard-- > 0) )
445
303
  {
446
- *(end--) = 0;
447
- size--;
304
+ --end;
305
+ --size;
306
+ }
307
+ }
308
+ else
309
+ {
310
+ while( *end == '0' )
311
+ {
312
+ --end;
313
+ --size;
448
314
  }
449
- }
450
- else
451
- {
452
- while( *end == '0' )
453
- {
454
- *(end--) = 0;
455
- size--;
456
- }
457
- }
315
+ }
458
316
  }
459
317
 
460
318
  return std::string( result, size );
@@ -485,10 +343,20 @@ static bool convert( const std::string& value, double& result )
485
343
 
486
344
  if( *i || !haveDigit ) return false;
487
345
 
488
- result = fast_atof( value.c_str() );
489
- return true;
346
+ int processed_chars;
347
+ const int total_length = value.length();
348
+ const double val = fast_strtod( value.c_str(), total_length, &processed_chars);
349
+
350
+ if ( processed_chars != total_length ||
351
+ val != val /*test for quite NaN*/ )
352
+ {
353
+ return false;
490
354
  }
491
355
 
356
+ result = val;
357
+ return true;
358
+ }
359
+
492
360
  static double convert( const std::string& value )
493
361
  throw( FieldConvertError )
494
362
  {
@@ -564,52 +432,45 @@ struct BoolConvertor
564
432
  struct UtcTimeStampConvertor
565
433
  {
566
434
  static std::string convert( const UtcTimeStamp& value,
567
- bool showMilliseconds = false )
435
+ int precision = 0 )
568
436
  throw( FieldConvertError )
569
437
  {
570
- char result[ 18+4 ];
571
- int year, month, day, hour, minute, second, millis;
438
+ char result[ 17+10 ]; // Maximum
439
+ int year, month, day, hour, minute, second, fraction;
572
440
 
573
441
  value.getYMD( year, month, day );
574
- value.getHMS( hour, minute, second, millis );
442
+ value.getHMS( hour, minute, second, fraction, precision );
575
443
 
576
- integer_to_string_padded( result, 5, year, 4 );
577
- integer_to_string_padded( result + 4, 3, month, 2 );
578
- integer_to_string_padded( result + 6, 3, day, 2 );
444
+ integer_to_string_padded( result, 4, year);
445
+ integer_to_string_padded( result + 4, 2, month );
446
+ integer_to_string_padded( result + 6, 2, day );
579
447
  result[8] = '-';
580
- integer_to_string_padded( result + 9, 3, hour, 2 );
448
+ integer_to_string_padded( result + 9, 2, hour);
581
449
  result[11] = ':';
582
- integer_to_string_padded( result + 12, 3, minute, 2 );
450
+ integer_to_string_padded( result + 12, 2, minute);
583
451
  result[14] = ':';
584
- integer_to_string_padded( result + 15, 3, second, 2 );
452
+ integer_to_string_padded( result + 15, 2, second);
585
453
 
586
- if( showMilliseconds )
454
+ if( precision )
587
455
  {
588
456
  result[17] = '.';
589
- if( integer_to_string_padded ( result + 18, 4, millis, 3 )
457
+ if( integer_to_string_padded ( result + 18, precision, fraction )
590
458
  != result + 18 )
591
459
  {
592
460
  throw FieldConvertError();
593
461
  }
594
462
  }
595
463
 
596
- return result;
464
+ return std::string(result, precision ? (17 + 1 + precision) : 17);
597
465
  }
598
466
 
599
- static UtcTimeStamp convert( const std::string& value,
600
- bool calculateDays = false )
467
+ static UtcTimeStamp convert( const std::string& value )
601
468
  throw( FieldConvertError )
602
469
  {
603
- bool haveMilliseconds = false;
470
+ size_t len = value.size();
471
+ if (len < 17 || len > 27) throw FieldConvertError(value);
604
472
 
605
- switch( value.size() )
606
- {
607
- case 21: haveMilliseconds = true;
608
- case 17: break;
609
- default: throw FieldConvertError(value);
610
- }
611
-
612
- int i = 0;
473
+ size_t i = 0;
613
474
  int c = 0;
614
475
  for( c = 0; c < 8; ++c )
615
476
  if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
@@ -623,14 +484,7 @@ struct UtcTimeStampConvertor
623
484
  for( c = 0; c < 2; ++c )
624
485
  if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
625
486
 
626
- if( haveMilliseconds )
627
- {
628
- if( value[i++] != '.' ) throw FieldConvertError(value);
629
- for( c = 0; c < 3; ++c )
630
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
631
- }
632
-
633
- int year, mon, mday, hour, min, sec, millis;
487
+ int year, mon, mday, hour, min, sec;
634
488
 
635
489
  i = 0;
636
490
 
@@ -669,17 +523,22 @@ struct UtcTimeStampConvertor
669
523
  // No check for >= 0 as no '-' are converted here
670
524
  if( 60 < sec ) throw FieldConvertError(value);
671
525
 
672
- if( haveMilliseconds )
526
+ if (len == 17)
527
+ return UtcTimeStamp (hour, min, sec, 0,
528
+ mday, mon, year);
529
+
530
+ if( value[i++] != '.' ) throw FieldConvertError(value);
531
+
532
+ int fraction = 0;
533
+ for (; i < len; ++i)
673
534
  {
674
- millis = (100 * (value[i+1] - '0')
675
- + 10 * (value[i+2] - '0')
676
- + (value[i+3] - '0'));
535
+ char ch = value[i];
536
+ if( !IS_DIGIT(ch)) throw FieldConvertError(value);
537
+ fraction = (fraction * 10) + ch - '0';
677
538
  }
678
- else
679
- millis = 0;
680
539
 
681
- return UtcTimeStamp (hour, min, sec, millis,
682
- mday, mon, year);
540
+ return UtcTimeStamp (hour, min, sec, fraction,
541
+ mday, mon, year, len - 17 - 1);
683
542
  }
684
543
  };
685
544
 
@@ -687,44 +546,38 @@ struct UtcTimeStampConvertor
687
546
  struct UtcTimeOnlyConvertor
688
547
  {
689
548
  static std::string convert( const UtcTimeOnly& value,
690
- bool showMilliseconds = false)
549
+ int precision = 0 )
691
550
  throw( FieldConvertError )
692
551
  {
693
- char result[ 9+4 ];
694
- int hour, minute, second, millis;
552
+ char result[ 8+10 ]; // Maximum
553
+ int hour, minute, second, fraction;
695
554
 
696
- value.getHMS( hour, minute, second, millis );
555
+ value.getHMS( hour, minute, second, fraction, precision );
697
556
 
698
- integer_to_string_padded ( result, 3, hour, 2 );
557
+ integer_to_string_padded ( result, 2, hour );
699
558
  result[2] = ':';
700
- integer_to_string_padded ( result + 3, 3, minute, 2 );
559
+ integer_to_string_padded ( result + 3, 2, minute );
701
560
  result[5] = ':';
702
- integer_to_string_padded ( result + 6, 3, second, 2 );
561
+ integer_to_string_padded ( result + 6, 2, second );
703
562
 
704
- if( showMilliseconds )
563
+ if( precision )
705
564
  {
706
565
  result[8] = '.';
707
- if( integer_to_string_padded ( result + 9, 4, millis, 3 )
566
+ if( integer_to_string_padded ( result + 9, precision, fraction )
708
567
  != result + 9 )
709
568
  throw FieldConvertError();
710
569
  }
711
570
 
712
- return result;
571
+ return std::string(result, precision ? (8 + 1 + precision) : 8);
713
572
  }
714
573
 
715
- static UtcTimeOnly convert( const std::string& value )
574
+ static UtcTimeOnly convert( const std::string& value)
716
575
  throw( FieldConvertError )
717
576
  {
718
- bool haveMilliseconds = false;
577
+ size_t len = value.size();
578
+ if (len < 8 || len > 18) throw FieldConvertError(value);
719
579
 
720
- switch( value.size() )
721
- {
722
- case 12: haveMilliseconds = true;
723
- case 8: break;
724
- default: throw FieldConvertError(value);
725
- }
726
-
727
- int i = 0;
580
+ size_t i = 0;
728
581
  int c = 0;
729
582
  for( c = 0; c < 2; ++c )
730
583
  if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
@@ -735,44 +588,44 @@ struct UtcTimeOnlyConvertor
735
588
  for( c = 0; c < 2; ++c )
736
589
  if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
737
590
 
738
- if( haveMilliseconds )
739
- {
740
- // ++i instead of i++ skips the '.' separator
741
- for( c = 0; c < 3; ++c )
742
- if( !IS_DIGIT(value[++i]) ) throw FieldConvertError(value);
743
- }
591
+ int hour, min, sec;
744
592
 
745
- int hour, min, sec, millis;
746
-
747
593
  i = 0;
748
594
 
749
595
  hour = value[i++] - '0';
750
596
  hour = 10 * hour + value[i++] - '0';
751
597
  // No check for >= 0 as no '-' are converted here
752
598
  if( 23 < hour ) throw FieldConvertError(value);
599
+
753
600
  ++i; // skip ':'
754
601
 
755
602
  min = value[i++] - '0';
756
603
  min = 10 * min + value[i++] - '0';
757
604
  // No check for >= 0 as no '-' are converted here
758
605
  if( 59 < min ) throw FieldConvertError(value);
606
+
759
607
  ++i; // skip ':'
760
608
 
761
609
  sec = value[i++] - '0';
762
610
  sec = 10 * sec + value[i++] - '0';
611
+
763
612
  // No check for >= 0 as no '-' are converted here
764
613
  if( 60 < sec ) throw FieldConvertError(value);
765
614
 
766
- if( haveMilliseconds )
615
+ if (len == 8)
616
+ return UtcTimeOnly (hour, min, sec, 0);
617
+
618
+ if( value[i++] != '.' ) throw FieldConvertError(value);
619
+
620
+ int fraction = 0;
621
+ for (; i < len; ++i)
767
622
  {
768
- millis = (100 * (value[i+1] - '0')
769
- + 10 * (value[i+2] - '0')
770
- + (value[i+3] - '0'));
623
+ char ch = value[i];
624
+ if( !IS_DIGIT(ch)) throw FieldConvertError(value);
625
+ fraction = (fraction * 10) + ch - '0';
771
626
  }
772
- else
773
- millis = 0;
774
627
 
775
- return UtcTimeOnly( hour, min, sec, millis );
628
+ return UtcTimeOnly (hour, min, sec, fraction, len - 8 - 1);
776
629
  }
777
630
  };
778
631
 
@@ -782,15 +635,16 @@ struct UtcDateConvertor
782
635
  static std::string convert( const UtcDate& value )
783
636
  throw( FieldConvertError )
784
637
  {
785
- char result[ 9 ];
786
638
  int year, month, day;
787
-
788
639
  value.getYMD( year, month, day );
789
640
 
790
- integer_to_string_padded( result, 5, year, 4 );
791
- integer_to_string_padded( result + 4, 3, month, 2 );
792
- integer_to_string_padded( result + 6, 3, day, 2 );
793
- return result;
641
+ char result[ 8 ];
642
+
643
+ integer_to_string_padded( result, 4, year );
644
+ integer_to_string_padded( result + 4, 2, month );
645
+ integer_to_string_padded( result + 6, 2, day );
646
+
647
+ return std::string( result, sizeof( result ) );
794
648
  }
795
649
 
796
650
  static UtcDate convert( const std::string& value )