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.
- checksums.yaml +4 -4
- data/ext/quickfix/Acceptor.h +2 -0
- data/ext/quickfix/AtomicCount.h +82 -12
- data/ext/quickfix/DOMDocument.h +9 -7
- data/ext/quickfix/DataDictionary.cpp +77 -14
- data/ext/quickfix/DataDictionary.h +90 -16
- data/ext/quickfix/Dictionary.cpp +1 -2
- data/ext/quickfix/Exceptions.h +3 -5
- data/ext/quickfix/Field.h +83 -32
- data/ext/quickfix/FieldConvertors.cpp +93 -0
- data/ext/quickfix/FieldConvertors.h +129 -275
- data/ext/quickfix/FieldMap.cpp +53 -13
- data/ext/quickfix/FieldMap.h +200 -62
- data/ext/quickfix/FieldTypes.cpp +10 -10
- data/ext/quickfix/FieldTypes.h +293 -44
- data/ext/quickfix/FileLog.cpp +6 -10
- data/ext/quickfix/FileLog.h +4 -10
- data/ext/quickfix/FileStore.cpp +19 -6
- data/ext/quickfix/FileStore.h +4 -0
- data/ext/quickfix/FixFieldNumbers.h +1462 -1461
- data/ext/quickfix/FixFields.h +1462 -1461
- data/ext/quickfix/FixValues.h +3230 -3227
- data/ext/quickfix/HttpConnection.cpp +1 -1
- data/ext/quickfix/Initiator.cpp +7 -1
- data/ext/quickfix/Initiator.h +2 -0
- data/ext/quickfix/Log.h +6 -12
- data/ext/quickfix/Message.cpp +186 -57
- data/ext/quickfix/Message.h +109 -47
- data/ext/quickfix/MySQLConnection.h +1 -1
- data/ext/quickfix/PostgreSQLConnection.h +1 -1
- data/ext/quickfix/QuickfixRuby.cpp +79141 -77959
- data/ext/quickfix/QuickfixRuby.h +1 -1
- data/ext/quickfix/SSLSocketAcceptor.cpp +410 -0
- data/ext/quickfix/SSLSocketAcceptor.h +185 -0
- data/ext/quickfix/SSLSocketConnection.cpp +427 -0
- data/ext/quickfix/SSLSocketConnection.h +206 -0
- data/ext/quickfix/SSLSocketInitiator.cpp +485 -0
- data/ext/quickfix/SSLSocketInitiator.h +196 -0
- data/ext/quickfix/Session.cpp +113 -20
- data/ext/quickfix/Session.h +18 -4
- data/ext/quickfix/SessionFactory.cpp +10 -3
- data/ext/quickfix/SessionSettings.cpp +5 -3
- data/ext/quickfix/SessionSettings.h +97 -5
- data/ext/quickfix/Settings.cpp +72 -2
- data/ext/quickfix/Settings.h +3 -0
- data/ext/quickfix/SharedArray.h +140 -6
- data/ext/quickfix/SocketConnection.cpp +2 -2
- data/ext/quickfix/SocketConnector.cpp +5 -2
- data/ext/quickfix/SocketConnector.h +3 -2
- data/ext/quickfix/SocketInitiator.cpp +28 -4
- data/ext/quickfix/SocketInitiator.h +1 -1
- data/ext/quickfix/SocketMonitor.cpp +5 -5
- data/ext/quickfix/ThreadedSSLSocketAcceptor.cpp +455 -0
- data/ext/quickfix/ThreadedSSLSocketAcceptor.h +217 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.cpp +404 -0
- data/ext/quickfix/ThreadedSSLSocketConnection.h +189 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.cpp +469 -0
- data/ext/quickfix/ThreadedSSLSocketInitiator.h +201 -0
- data/ext/quickfix/ThreadedSocketAcceptor.cpp +5 -1
- data/ext/quickfix/ThreadedSocketConnection.cpp +8 -2
- data/ext/quickfix/ThreadedSocketConnection.h +4 -1
- data/ext/quickfix/ThreadedSocketInitiator.cpp +24 -4
- data/ext/quickfix/ThreadedSocketInitiator.h +1 -1
- data/ext/quickfix/Utility.cpp +23 -1
- data/ext/quickfix/Utility.h +28 -2
- data/ext/quickfix/UtilitySSL.cpp +1733 -0
- data/ext/quickfix/UtilitySSL.h +277 -0
- data/ext/quickfix/config-all.h +10 -0
- data/ext/quickfix/dirent_windows.h +838 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.cc +641 -0
- data/ext/quickfix/double-conversion/bignum-dtoa.h +84 -0
- data/ext/quickfix/double-conversion/bignum.cc +766 -0
- data/ext/quickfix/double-conversion/bignum.h +144 -0
- data/ext/quickfix/double-conversion/cached-powers.cc +176 -0
- data/ext/quickfix/double-conversion/cached-powers.h +64 -0
- data/ext/quickfix/double-conversion/diy-fp.cc +57 -0
- data/ext/quickfix/double-conversion/diy-fp.h +118 -0
- data/ext/quickfix/double-conversion/double-conversion.cc +994 -0
- data/ext/quickfix/double-conversion/double-conversion.h +543 -0
- data/ext/quickfix/double-conversion/fast-dtoa.cc +665 -0
- data/ext/quickfix/double-conversion/fast-dtoa.h +88 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.cc +404 -0
- data/ext/quickfix/double-conversion/fixed-dtoa.h +56 -0
- data/ext/quickfix/double-conversion/ieee.h +402 -0
- data/ext/quickfix/double-conversion/strtod.cc +557 -0
- data/ext/quickfix/double-conversion/strtod.h +45 -0
- data/ext/quickfix/double-conversion/utils.h +372 -0
- data/ext/quickfix/stdint_msvc.h +254 -0
- data/lib/quickfix44.rb +3329 -10
- data/lib/quickfix50.rb +6649 -81
- data/lib/quickfix50sp1.rb +8054 -142
- data/lib/quickfix50sp2.rb +10900 -234
- data/lib/quickfix_fields.rb +7662 -7649
- data/spec/FIX40.xml +28 -28
- data/spec/FIX41.xml +29 -29
- data/spec/FIX42.xml +47 -47
- data/spec/FIX43.xml +148 -148
- data/spec/FIX44.xml +1078 -1081
- data/spec/FIX50.xml +1292 -1289
- data/spec/FIX50SP1.xml +1811 -1802
- data/spec/FIX50SP2.xml +1948 -1939
- data/spec/FIXT11.xml +5 -8
- data/test/test_FieldBaseTestCase.rb +1 -1
- data/test/test_MessageTestCase.rb +2 -2
- metadata +42 -6
data/ext/quickfix/Dictionary.cpp
CHANGED
@@ -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(
|
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
|
{
|
data/ext/quickfix/Exceptions.h
CHANGED
@@ -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
|
data/ext/quickfix/Field.h
CHANGED
@@ -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
|
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
|
-
:
|
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
|
88
|
-
:
|
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
|
-
|
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
|
-
|
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
|
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
|
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(
|
155
|
-
size_t totalLength = tagLength + m_string.length() +
|
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,
|
200
|
+
FIX::integer_to_string( buf, tagLength, m_tag );
|
161
201
|
|
162
|
-
buf[tagLength
|
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
|
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(
|
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(
|
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(
|
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(
|
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,
|
396
|
-
: FieldBase( field, UtcTimeStampConvertor::convert( data,
|
397
|
-
UtcTimeStampField( int field,
|
398
|
-
: FieldBase( field, UtcTimeStampConvertor::convert( UtcTimeStamp(),
|
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(
|
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(
|
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,
|
450
|
-
: FieldBase( field, UtcTimeOnlyConvertor::convert( data,
|
451
|
-
UtcTimeOnlyField( int field,
|
452
|
-
: FieldBase( field, UtcTimeOnlyConvertor::convert( UtcTimeOnly(),
|
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(
|
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(
|
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(
|
583
|
+
NAME(int precision) : TOK##Field(NUM, precision) {} \
|
533
584
|
NAME(const TYPE& value) : TOK##Field(NUM, value) {} \
|
534
|
-
NAME(const TYPE& value,
|
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 )
|
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
|
-
|
107
|
-
|
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
|
113
|
-
|
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
|
-
|
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 +
|
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
|
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[
|
284
|
-
if( integer_to_string_padded(result, sizeof(result), value
|
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,
|
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
|
-
|
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
|
-
|
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
|
-
|
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[
|
257
|
+
char result[BUFFFER_SIZE];
|
404
258
|
char *end = 0;
|
405
259
|
|
406
260
|
int size;
|
407
|
-
if( value == 0 || value > 0.0001 || value
|
261
|
+
if( value == 0 || value > 0.0001 || value < -0.0001 )
|
408
262
|
{
|
409
|
-
size =
|
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
|
-
|
282
|
+
if( needed > 0 )
|
427
283
|
{
|
428
|
-
|
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 =
|
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 =
|
300
|
+
int discard = SIGNIFICANT_DIGITS - padding;
|
443
301
|
|
444
302
|
while( (*end == '0') && (discard-- > 0) )
|
445
303
|
{
|
446
|
-
|
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
|
-
|
489
|
-
|
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
|
-
|
435
|
+
int precision = 0 )
|
568
436
|
throw( FieldConvertError )
|
569
437
|
{
|
570
|
-
char result[
|
571
|
-
int year, month, day, hour, minute, second,
|
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,
|
442
|
+
value.getHMS( hour, minute, second, fraction, precision );
|
575
443
|
|
576
|
-
integer_to_string_padded( result,
|
577
|
-
integer_to_string_padded( result + 4,
|
578
|
-
integer_to_string_padded( result + 6,
|
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,
|
448
|
+
integer_to_string_padded( result + 9, 2, hour);
|
581
449
|
result[11] = ':';
|
582
|
-
integer_to_string_padded( result + 12,
|
450
|
+
integer_to_string_padded( result + 12, 2, minute);
|
583
451
|
result[14] = ':';
|
584
|
-
integer_to_string_padded( result + 15,
|
452
|
+
integer_to_string_padded( result + 15, 2, second);
|
585
453
|
|
586
|
-
if(
|
454
|
+
if( precision )
|
587
455
|
{
|
588
456
|
result[17] = '.';
|
589
|
-
if( integer_to_string_padded ( result + 18,
|
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
|
-
|
470
|
+
size_t len = value.size();
|
471
|
+
if (len < 17 || len > 27) throw FieldConvertError(value);
|
604
472
|
|
605
|
-
|
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
|
-
|
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(
|
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
|
-
|
675
|
-
|
676
|
-
|
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,
|
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
|
-
|
549
|
+
int precision = 0 )
|
691
550
|
throw( FieldConvertError )
|
692
551
|
{
|
693
|
-
char result[
|
694
|
-
int hour, minute, second,
|
552
|
+
char result[ 8+10 ]; // Maximum
|
553
|
+
int hour, minute, second, fraction;
|
695
554
|
|
696
|
-
value.getHMS( hour, minute, second,
|
555
|
+
value.getHMS( hour, minute, second, fraction, precision );
|
697
556
|
|
698
|
-
integer_to_string_padded ( result,
|
557
|
+
integer_to_string_padded ( result, 2, hour );
|
699
558
|
result[2] = ':';
|
700
|
-
integer_to_string_padded ( result + 3,
|
559
|
+
integer_to_string_padded ( result + 3, 2, minute );
|
701
560
|
result[5] = ':';
|
702
|
-
integer_to_string_padded ( result + 6,
|
561
|
+
integer_to_string_padded ( result + 6, 2, second );
|
703
562
|
|
704
|
-
if(
|
563
|
+
if( precision )
|
705
564
|
{
|
706
565
|
result[8] = '.';
|
707
|
-
if( integer_to_string_padded ( result + 9,
|
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
|
-
|
577
|
+
size_t len = value.size();
|
578
|
+
if (len < 8 || len > 18) throw FieldConvertError(value);
|
719
579
|
|
720
|
-
|
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
|
-
|
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(
|
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
|
-
|
769
|
-
|
770
|
-
|
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(
|
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
|
-
|
791
|
-
|
792
|
-
integer_to_string_padded( result
|
793
|
-
|
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 )
|