FieldConvertors.h
Go to the documentation of this file.
1/* -*- C++ -*- */
2
3/****************************************************************************
4** Copyright (c) 2001-2014
5**
6** This file is part of the QuickFIX FIX Engine
7**
8** This file may be distributed under the terms of the quickfixengine.org
9** license as defined by quickfixengine.org and appearing in the file
10** LICENSE included in the packaging of this file.
11**
12** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
13** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14**
15** See http://www.quickfixengine.org/LICENSE for licensing information.
16**
17** Contact ask@quickfixengine.org if any conditions of this licensing are
18** not clear to you.
19**
20****************************************************************************/
21
22#ifndef FIX_FIELDCONVERTORS_H
23#define FIX_FIELDCONVERTORS_H
24
25#ifdef _MSC_VER
26#pragma warning( disable: 4146 )
27#endif
28
29#include "FieldTypes.h"
30#include "Exceptions.h"
31#include "Utility.h"
32#include "config-all.h"
33#include <string>
34#include <sstream>
35#include <iomanip>
36#include <cstdio>
37#include <limits>
38#include <iterator>
39
40namespace FIX
41{
42
43typedef int signed_int;
44typedef unsigned int unsigned_int;
45
46#define UNSIGNED_VALUE_OF( x ) ( ( x < 0 ) ? -unsigned_int(x) : unsigned_int(x) )
47
48#define IS_SPACE( x ) ( x == ' ' )
49#define IS_DIGIT( x ) ( unsigned_int( x - '0' ) < 10 )
50
51inline int number_of_symbols_in( const signed_int value )
52{
53 unsigned_int number = UNSIGNED_VALUE_OF( value );
54
55 int symbols = 0;
56
57 while( number > 9999 )
58 {
59 symbols += 4;
60 number /= 10000;
61 }
62
63 // small tweak to make comparison times consistent
64 // always 2 comparisons instead of [1 - 4]
65 if( number > 99 )
66 {
67 if( number > 999 )
68 symbols += 4;
69 else
70 symbols += 3;
71 }
72 else
73 {
74 if( number > 9 )
75 symbols += 2;
76 else
77 symbols += 1;
78 }
79
80 if( value < 0 )
81 symbols += 1;
82
83 return symbols;
84}
85
86static const char digit_pairs[201] = {
87 "00010203040506070809"
88 "10111213141516171819"
89 "20212223242526272829"
90 "30313233343536373839"
91 "40414243444546474849"
92 "50515253545556575859"
93 "60616263646566676869"
94 "70717273747576777879"
95 "80818283848586878889"
96 "90919293949596979899"
97};
98
99inline char* integer_to_string( char* buf, const size_t len, signed_int t )
100{
101 const bool isNegative = t < 0;
102 char* p = buf + len;
103
104 unsigned_int number = UNSIGNED_VALUE_OF( t );
105
106 while( number > 99 )
107 {
108 unsigned_int pos = number % 100;
109 number /= 100;
110
111 *--p = digit_pairs[2 * pos + 1];
112 *--p = digit_pairs[2 * pos];
113 }
114
115 if( number > 9 )
116 {
117 *--p = digit_pairs[2 * number + 1];
118 *--p = digit_pairs[2 * number];
119 }
120 else
121 {
122 *--p = '0' + char(number);
123 }
124
125 if( isNegative )
126 *--p = '-';
127
128 return p;
129}
130
132( char* buf, const size_t len, signed_int t,
133 const char paddingChar = '0')
134{
135 char* p = integer_to_string( buf, len, t );
136 while( p > buf )
137 *--p = paddingChar;
138 return p;
139}
140
143{
144 static const std::string& convert( const std::string& value )
145 { return value; }
146};
147
149
152{
153 static std::string convert( signed_int value )
154 {
155 // buffer is big enough for significant digits and extra digit,
156 // minus and null
157 char buffer[std::numeric_limits<signed_int>::digits10 + 2];
158 const char* const start
159 = integer_to_string( buffer, sizeof (buffer), value );
160 return std::string( start, buffer + sizeof (buffer) - start );
161 }
162
163 static bool convert(
164 std::string::const_iterator str,
165 std::string::const_iterator end,
166 signed_int& result )
167 {
168 bool isNegative = false;
169 signed_int x = 0;
170
171 if( str == end )
172 return false;
173
174 if( *str == '-' )
175 {
176 isNegative = true;
177 if( ++str == end )
178 return false;
179 }
180
181 do
182 {
183 const unsigned_int c = *str - '0';
184 if( c > 9 ) return false;
185 x = 10 * x + c;
186 } while ( ++str != end );
187
188 if( isNegative )
189 x = -unsigned_int(x);
190
191 result = x;
192 return true;
193 }
194
195 static bool convert( const std::string& value, signed_int& result )
196 {
197 return convert( value.begin(), value.end(), result );
198 }
199
200 static signed_int convert( const std::string& value )
201 throw( FieldConvertError )
202 {
203 signed_int result = 0;
204 if( !convert( value.begin(), value.end(), result ) )
205 throw FieldConvertError(value);
206 else
207 return result;
208 }
209};
210
213{
214 static std::string convert( int value )
215 throw( FieldConvertError )
216 {
217 if ( value > 255 || value < 0 ) throw FieldConvertError();
218 char result[3];
219 if( integer_to_string_padded(result, sizeof(result), value) != result )
220 {
221 throw FieldConvertError();
222 }
223 return std::string( result, sizeof( result ) );
224 }
225
226 static bool convert( const std::string& value, int& result )
227 {
228 return IntConvertor::convert( value, result );
229 }
230
231 static int convert( const std::string& value )
232 throw( FieldConvertError )
233 {
234 return IntConvertor::convert( value );
235 }
236};
237
240{
241
242private:
243
244 static double fast_strtod( const char * buffer, int size, int * processed_chars );
245
246 static int fast_dtoa( char * buffer, int size, double value );
247
248 static int fast_fixed_dtoa( char * buffer, int size, double value );
249
250public:
251
252 static const int SIGNIFICANT_DIGITS = 15;
253 static const int BUFFFER_SIZE = 32;
254
255 static std::string convert( double value, int padding = 0 )
256 {
257 char result[BUFFFER_SIZE];
258 char *end = 0;
259
260 int size;
261 if( value == 0 || value > 0.0001 || value < -0.0001 )
262 {
263 size = fast_dtoa( result, BUFFFER_SIZE, value );
264 if( size == 0 )
265 return std::string();
266
267 if( padding > 0 )
268 {
269 char* point = result;
270 end = result + size - 1;
271 while( *point != '.' && *point != 0 )
272 point++;
273
274 if( *point == 0 )
275 {
276 end = point;
277 *point = '.';
278 ++size;
279 }
280 int needed = padding - (int)(end - point);
281
282 if( needed > 0 )
283 {
284 memset( ++end, '0', needed );
285 size += needed;
286 }
287 }
288 }
289 else
290 {
291 size = fast_fixed_dtoa( result, BUFFFER_SIZE, value );
292 if( size == 0 )
293 return std::string();
294
295 // strip trailing 0's
296 end = result + size - 1;
297
298 if( padding > 0 )
299 {
300 int discard = SIGNIFICANT_DIGITS - padding;
301
302 while( (*end == '0') && (discard-- > 0) )
303 {
304 --end;
305 --size;
306 }
307 }
308 else
309 {
310 while( *end == '0' )
311 {
312 --end;
313 --size;
314 }
315 }
316 }
317
318 return std::string( result, size );
319}
320
321static bool convert( const std::string& value, double& result )
322{
323 const char * i = value.c_str();
324
325 // Catch null strings
326 if( !*i ) return false;
327 // Eat leading '-' and recheck for null string
328 if( *i == '-' && !*++i ) return false;
329
330 bool haveDigit = false;
331
332 if( IS_DIGIT(*i) )
333 {
334 haveDigit = true;
335 while( IS_DIGIT (*++i) );
336 }
337
338 if( *i == '.' && IS_DIGIT(*++i) )
339 {
340 haveDigit = true;
341 while( IS_DIGIT (*++i) );
342 }
343
344 if( *i || !haveDigit ) return false;
345
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;
354 }
355
356 result = val;
357 return true;
358}
359
360 static double convert( const std::string& value )
361 throw( FieldConvertError )
362 {
363 double result = 0.0;
364 if( !convert( value, result ) )
365 throw FieldConvertError(value);
366 else
367 return result;
368 }
369};
370
373{
374 static std::string convert( char value )
375 {
376 if( value == '\0' ) return "";
377 return std::string( 1, value );
378 }
379
380 static bool convert( const std::string& value, char& result )
381 {
382 if( value.size() != 1 ) return false;
383 result = value[0];
384 return true;
385 }
386
387 static char convert( const std::string& value )
388 throw( FieldConvertError )
389 {
390 char result = '\0';
391 if( !convert( value, result ) )
392 throw FieldConvertError(value);
393 else
394 return result;
395 }
396};
397
400{
401 static std::string convert( bool value )
402 {
403 const char ch = value ? 'Y' : 'N';
404 return std::string( 1, ch );
405 }
406
407 static bool convert( const std::string& value, bool& result )
408 {
409 if( value.size() != 1 ) return false;
410 switch( value[0] )
411 {
412 case 'Y': result = true; break;
413 case 'N': result = false; break;
414 default: return false;
415 }
416
417 return true;
418 }
419
420 static bool convert( const std::string& value )
421 throw( FieldConvertError )
422 {
423 bool result = false;
424 if( !convert( value, result ) )
425 throw FieldConvertError(value);
426 else
427 return result;
428 }
429};
430
433{
434 static std::string convert( const UtcTimeStamp& value,
435 int precision = 0 )
436 throw( FieldConvertError )
437 {
438 char result[ 17+10 ]; // Maximum
439 int year, month, day, hour, minute, second, fraction;
440
441 value.getYMD( year, month, day );
442 value.getHMS( hour, minute, second, fraction, precision );
443
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 );
447 result[8] = '-';
448 integer_to_string_padded( result + 9, 2, hour);
449 result[11] = ':';
450 integer_to_string_padded( result + 12, 2, minute);
451 result[14] = ':';
452 integer_to_string_padded( result + 15, 2, second);
453
454 if( precision )
455 {
456 result[17] = '.';
457 if( integer_to_string_padded ( result + 18, precision, fraction )
458 != result + 18 )
459 {
460 throw FieldConvertError();
461 }
462 }
463
464 return std::string(result, precision ? (17 + 1 + precision) : 17);
465 }
466
467 static UtcTimeStamp convert( const std::string& value )
468 throw( FieldConvertError )
469 {
470 size_t len = value.size();
471 if (len < 17 || len > 27) throw FieldConvertError(value);
472
473 size_t i = 0;
474 int c = 0;
475 for( c = 0; c < 8; ++c )
476 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
477 if (value[i++] != '-') throw FieldConvertError(value);
478 for( c = 0; c < 2; ++c )
479 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
480 if( value[i++] != ':' ) throw FieldConvertError(value);
481 for( c = 0; c < 2; ++c )
482 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
483 if( value[i++] != ':' ) throw FieldConvertError(value);
484 for( c = 0; c < 2; ++c )
485 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
486
487 int year, mon, mday, hour, min, sec;
488
489 i = 0;
490
491 year = value[i++] - '0';
492 year = 10 * year + value[i++] - '0';
493 year = 10 * year + value[i++] - '0';
494 year = 10 * year + value[i++] - '0';
495
496 mon = value[i++] - '0';
497 mon = 10 * mon + value[i++] - '0';
498 if( mon < 1 || 12 < mon ) throw FieldConvertError(value);
499
500 mday = value[i++] - '0';
501 mday = 10 * mday + value[i++] - '0';
502 if( mday < 1 || 31 < mday ) throw FieldConvertError(value);
503
504 ++i; // skip '-'
505
506 hour = value[i++] - '0';
507 hour = 10 * hour + value[i++] - '0';
508 // No check for >= 0 as no '-' are converted here
509 if( 23 < hour ) throw FieldConvertError(value);
510
511 ++i; // skip ':'
512
513 min = value[i++] - '0';
514 min = 10 * min + value[i++] - '0';
515 // No check for >= 0 as no '-' are converted here
516 if( 59 < min ) throw FieldConvertError(value);
517
518 ++i; // skip ':'
519
520 sec = value[i++] - '0';
521 sec = 10 * sec + value[i++] - '0';
522
523 // No check for >= 0 as no '-' are converted here
524 if( 60 < sec ) throw FieldConvertError(value);
525
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)
534 {
535 char ch = value[i];
536 if( !IS_DIGIT(ch)) throw FieldConvertError(value);
537 fraction = (fraction * 10) + ch - '0';
538 }
539
540 return UtcTimeStamp (hour, min, sec, fraction,
541 mday, mon, year, len - 17 - 1);
542 }
543};
544
547{
548 static std::string convert( const UtcTimeOnly& value,
549 int precision = 0 )
550 throw( FieldConvertError )
551 {
552 char result[ 8+10 ]; // Maximum
553 int hour, minute, second, fraction;
554
555 value.getHMS( hour, minute, second, fraction, precision );
556
557 integer_to_string_padded ( result, 2, hour );
558 result[2] = ':';
559 integer_to_string_padded ( result + 3, 2, minute );
560 result[5] = ':';
561 integer_to_string_padded ( result + 6, 2, second );
562
563 if( precision )
564 {
565 result[8] = '.';
566 if( integer_to_string_padded ( result + 9, precision, fraction )
567 != result + 9 )
568 throw FieldConvertError();
569 }
570
571 return std::string(result, precision ? (8 + 1 + precision) : 8);
572 }
573
574 static UtcTimeOnly convert( const std::string& value)
575 throw( FieldConvertError )
576 {
577 size_t len = value.size();
578 if (len < 8 || len > 18) throw FieldConvertError(value);
579
580 size_t i = 0;
581 int c = 0;
582 for( c = 0; c < 2; ++c )
583 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
584 if( value[i++] != ':' ) throw FieldConvertError(value);
585 for( c = 0; c < 2; ++c )
586 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
587 if( value[i++] != ':' ) throw FieldConvertError(value);
588 for( c = 0; c < 2; ++c )
589 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
590
591 int hour, min, sec;
592
593 i = 0;
594
595 hour = value[i++] - '0';
596 hour = 10 * hour + value[i++] - '0';
597 // No check for >= 0 as no '-' are converted here
598 if( 23 < hour ) throw FieldConvertError(value);
599
600 ++i; // skip ':'
601
602 min = value[i++] - '0';
603 min = 10 * min + value[i++] - '0';
604 // No check for >= 0 as no '-' are converted here
605 if( 59 < min ) throw FieldConvertError(value);
606
607 ++i; // skip ':'
608
609 sec = value[i++] - '0';
610 sec = 10 * sec + value[i++] - '0';
611
612 // No check for >= 0 as no '-' are converted here
613 if( 60 < sec ) throw FieldConvertError(value);
614
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)
622 {
623 char ch = value[i];
624 if( !IS_DIGIT(ch)) throw FieldConvertError(value);
625 fraction = (fraction * 10) + ch - '0';
626 }
627
628 return UtcTimeOnly (hour, min, sec, fraction, len - 8 - 1);
629 }
630};
631
634{
635 static std::string convert( const UtcDate& value )
636 throw( FieldConvertError )
637 {
638 int year, month, day;
639 value.getYMD( year, month, day );
640
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 ) );
648 }
649
650 static UtcDate convert( const std::string& value )
651 throw( FieldConvertError )
652 {
653 if( value.size() != 8 ) throw FieldConvertError(value);
654
655 int i = 0;
656 for( int c=0; c<8; ++c )
657 if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
658
659 int year, mon, mday;
660
661 i = 0;
662
663 year = value[i++] - '0';
664 year = 10 * year + value[i++] - '0';
665 year = 10 * year + value[i++] - '0';
666 year = 10 * year + value[i++] - '0';
667
668 mon = value[i++] - '0';
669 mon = 10 * mon + value[i++] - '0';
670 if( mon < 1 || 12 < mon )
671 throw FieldConvertError(value);
672
673 mday = value[i++] - '0';
674 mday = 10 * mday + value[i++] - '0';
675 if( mday < 1 || 31 < mday )
676 throw FieldConvertError(value);
677
678 return UtcDateOnly( mday, mon, year );
679 }
680};
681
683
715}
716
717#endif //FIX_FIELDCONVERTORS_H
#define IS_DIGIT(x)
#define UNSIGNED_VALUE_OF(x)
Date only represented in UTC.
Definition FieldTypes.h:801
Time only represented in UTC.
Definition FieldTypes.h:685
Date and Time represented in UTC.
Definition FieldTypes.h:583
unsigned int unsigned_int
StringConvertor LOCALMKTDATE_CONVERTOR
IntConvertor INT_CONVERTOR
static const char digit_pairs[201]
StringConvertor MULTIPLECHARVALUE_CONVERTOR
StringConvertor EXCHANGE_CONVERTOR
StringConvertor MULTIPLESTRINGVALUE_CONVERTOR
CheckSumConvertor CHECKSUM_CONVERTOR
DoubleConvertor FLOAT_CONVERTOR
DoubleConvertor QTY_CONVERTOR
StringConvertor MULTIPLEVALUESTRING_CONVERTOR
DoubleConvertor PRICE_CONVERTOR
int signed_int
EmptyConvertor StringConvertor
UtcDateConvertor UtcDateOnlyConvertor
StringConvertor XMLDATA_CONVERTOR
StringConvertor COUNTRY_CONVERTOR
StringConvertor TZTIMEONLY_CONVERTOR
StringConvertor STRING_CONVERTOR
CharConvertor CHAR_CONVERTOR
UtcTimeStampConvertor UTCTIMESTAMP_CONVERTOR
IntConvertor NUMINGROUP_CONVERTOR
StringConvertor CURRENCY_CONVERTOR
DoubleConvertor PRICEOFFSET_CONVERTOR
char * integer_to_string(char *buf, const size_t len, signed_int t)
StringConvertor TZTIMESTAMP_CONVERTOR
StringConvertor MONTHYEAR_CONVERTOR
StringConvertor DATA_CONVERTOR
BoolConvertor BOOLEAN_CONVERTOR
StringConvertor DAYOFMONTH_CONVERTOR
char * integer_to_string_padded(char *buf, const size_t len, signed_int t, const char paddingChar='0')
DoubleConvertor PERCENTAGE_CONVERTOR
IntConvertor LENGTH_CONVERTOR
DoubleConvertor AMT_CONVERTOR
int number_of_symbols_in(const signed_int value)
IntConvertor SEQNUM_CONVERTOR
UtcTimeOnlyConvertor UTCTIMEONLY_CONVERTOR
StringConvertor LANGUAGE_CONVERTOR
UtcDate UtcDateOnly
Definition FieldTypes.h:873
UtcDateConvertor UTCDATE_CONVERTOR
Converts boolean to/from a string.
static bool convert(const std::string &value, bool &result)
static bool convert(const std::string &value)
static std::string convert(bool value)
Converts character to/from a string.
static char convert(const std::string &value)
static bool convert(const std::string &value, char &result)
static std::string convert(char value)
Converts checksum to/from a string.
static int convert(const std::string &value)
static bool convert(const std::string &value, int &result)
static std::string convert(int value)
void getYMD(int &year, int &month, int &day) const
Load the referenced values with the year, month and day portions of the date in a single operation.
Definition FieldTypes.h:211
void getHMS(int &hour, int &minute, int &second, int &millis) const
Load the referenced values with the hour, minute, second and millisecond portions of the time in a si...
Definition FieldTypes.h:218
Converts double to/from a string.
static int fast_fixed_dtoa(char *buffer, int size, double value)
static const int BUFFFER_SIZE
static double fast_strtod(const char *buffer, int size, int *processed_chars)
static int fast_dtoa(char *buffer, int size, double value)
static bool convert(const std::string &value, double &result)
static double convert(const std::string &value)
static std::string convert(double value, int padding=0)
static const int SIGNIFICANT_DIGITS
Empty converter is a no-op.
static const std::string & convert(const std::string &value)
Unable to convert field into its native format.
Definition Exceptions.h:67
Converts integer to/from a string.
static bool convert(std::string::const_iterator str, std::string::const_iterator end, signed_int &result)
static bool convert(const std::string &value, signed_int &result)
static std::string convert(signed_int value)
static signed_int convert(const std::string &value)
Converts a UtcDate to/from a string.
static UtcDate convert(const std::string &value)
static std::string convert(const UtcDate &value)
Converts a UtcTimeOnly to/from a string.
static std::string convert(const UtcTimeOnly &value, int precision=0)
static UtcTimeOnly convert(const std::string &value)
Converts a UtcTimeStamp to/from a string.
static UtcTimeStamp convert(const std::string &value)
static std::string convert(const UtcTimeStamp &value, int precision=0)

Generated on Thu May 22 2025 08:23:50 for QuickFIX by doxygen 1.9.8 written by Dimitri van Heesch, © 1997-2001