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
@@ -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 )