123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863 |
- /* -*- C++ -*- */
- /****************************************************************************
- ** Copyright (c) 2001-2014
- **
- ** This file is part of the QuickFIX FIX Engine
- **
- ** This file may be distributed under the terms of the quickfixengine.org
- ** license as defined by quickfixengine.org and appearing in the file
- ** LICENSE included in the packaging of this file.
- **
- ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- **
- ** See http://www.quickfixengine.org/LICENSE for licensing information.
- **
- ** Contact ask@quickfixengine.org if any conditions of this licensing are
- ** not clear to you.
- **
- ****************************************************************************/
- #ifndef FIX_FIELDCONVERTORS_H
- #define FIX_FIELDCONVERTORS_H
- #include "FieldTypes.h"
- #include "Exceptions.h"
- #include "Utility.h"
- #include <string>
- #include <sstream>
- #include <iomanip>
- #include <cstdio>
- #include <limits>
- namespace FIX
- {
- typedef int signed_int;
- typedef unsigned int unsigned_int;
- #define UNSIGNED_VALUE_OF( x ) unsigned_int( x < 0 ? -x : x )
- #define IS_SPACE( x ) ( x == ' ' )
- #define IS_DIGIT( x ) ( unsigned_int( x - '0' ) < 10 )
- inline int number_of_symbols_in( const signed_int value )
- {
- unsigned_int number = UNSIGNED_VALUE_OF( value );
- int symbols = 0;
- while( number > 9999 )
- {
- symbols += 4;
- number /= 10000;
- }
- // small tweak to make comparison times consistent
- // always 2 comparisons instead of [1 - 4]
- if( number > 99 )
- {
- if( number > 999 )
- symbols += 4;
- else
- symbols += 3;
- }
- else
- {
- if( number > 9 )
- symbols += 2;
- else
- symbols += 1;
- }
- if( value < 0 )
- symbols += 1;
- return symbols;
- }
- static const char digit_pairs[201] = {
- "00010203040506070809"
- "10111213141516171819"
- "20212223242526272829"
- "30313233343536373839"
- "40414243444546474849"
- "50515253545556575859"
- "60616263646566676869"
- "70717273747576777879"
- "80818283848586878889"
- "90919293949596979899"
- };
- inline char* integer_to_string( char* buf, const size_t len, signed_int t )
- {
- const bool isNegative = t < 0;
- char* p = buf + len;
- *--p = '\0';
-
- unsigned_int number = UNSIGNED_VALUE_OF( t );
- while( number > 99 )
- {
- unsigned_int pos = number % 100;
- number /= 100;
- p -= 2;
- *(short*)(p) = *(short*)(digit_pairs + 2 * pos);
- }
- if( number > 9 )
- {
- p -= 2;
- *(short*)(p) = *(short*)(digit_pairs + 2 * number);
- }
- else
- {
- *--p = '0' + char(number);
- }
- if( isNegative )
- *--p = '-';
- return p;
- }
- inline char* integer_to_string_padded
- ( char* buf, const size_t len, signed_int t,
- const size_t width = 0,
- const char paddingChar = '0')
- {
- char* p = integer_to_string( buf, len, t );
- if( !width )
- return p;
- const char* stop_p = buf + len - width - 1;
- if( stop_p < buf ) stop_p = buf;
- while( p > stop_p )
- *--p = paddingChar;
- return p;
- }
- /// Empty converter is a no-op.
- struct EmptyConvertor
- {
- static const std::string& convert( const std::string& value )
- { return value; }
- };
- typedef EmptyConvertor StringConvertor;
- /// Converts integer to/from a string
- struct IntConvertor
- {
- static std::string convert( signed_int value )
- {
- // buffer is big enough for significant digits and extra digit,
- // minus and null
- char buffer[std::numeric_limits<signed_int>::digits10 + 3];
- const char* const start
- = integer_to_string( buffer, sizeof (buffer), value );
- return std::string( start, buffer + sizeof (buffer) - start - 1 );
- }
- static bool convert(
- std::string::const_iterator str,
- std::string::const_iterator end,
- signed_int& result )
- {
- bool isNegative = false;
- signed_int x = 0;
- if( str == end )
- return false;
- if( *str == '-' )
- {
- isNegative = true;
- if( ++str == end )
- return false;
- }
- do
- {
- const unsigned_int c = *str - '0';
- if( c > 9 ) return false;
- x = 10 * x + c;
- } while ( ++str != end );
- if( isNegative )
- x = -x;
- result = x;
- return true;
- }
- static bool convert( const std::string& value, signed_int& result )
- {
- return convert( value.begin(), value.end(), result );
- }
- static signed_int convert( const std::string& value )
- throw( FieldConvertError )
- {
- signed_int result = 0;
- if( !convert( value.begin(), value.end(), result ) )
- throw FieldConvertError(value);
- else
- return result;
- }
- /// Converts only positive number e.g. FIX field ID: [1 ... 2147483647]
- /// No leading whitespace/zero/plus/sign symbols allowed
- /// Value is fixed to not make difference between 32bit and 64bit code
- static bool convertPositive(
- std::string::const_iterator str,
- std::string::const_iterator end,
- signed_int& result )
- {
- const int MAX_VALUE = 2147483647; // max value for 32-bit signed integer
- const int HIGH_MARK = MAX_VALUE / 10;
- const unsigned_int STOP_SYMBOL = MAX_VALUE % 10;
- const std::size_t MAX_DIGITS = 10; // integer can hold up to 10 digits
- const std::size_t length = std::distance( str, end );
- if( length < 1 || length > MAX_DIGITS)
- return false;
- if( length == MAX_DIGITS )
- {
- end = str;
- std::advance( end, length - 1 );
- }
- const unsigned_int ch = *str - '1';
- if( ch > 8 )
- return false;
- unsigned_int x = 0;
- do
- {
- const unsigned_int c = *str - '0';
- if( c > 9 ) return false;
- x = 10 * x + c;
- } while( ++str < end );
- // complete overflow condition check and value calculation
- // this saves about 25% of speed when executed out of the main loop
- if( length == MAX_DIGITS )
- {
- if( x > (unsigned int)HIGH_MARK )
- return false;
- const unsigned_int c = *str - '0';
- if( x == (unsigned int)HIGH_MARK && c > STOP_SYMBOL )
- return false;
- x = 10 * x + c;
- }
- result = x;
- return true;
- }
- static signed_int convertPositive( const std::string& value )
- throw( FieldConvertError )
- {
- signed_int result = 0;
- if( !convertPositive( value.begin(), value.end(), result ) )
- throw FieldConvertError(value);
- else
- return result;
- }
- };
- /// Converts checksum to/from a string
- struct CheckSumConvertor
- {
- static std::string convert( int value )
- throw( FieldConvertError )
- {
- if ( value > 255 || value < 0 ) throw FieldConvertError();
- char result[4];
- if( integer_to_string_padded(result, sizeof(result), value, 3) != result )
- {
- throw FieldConvertError();
- }
- return std::string( result, 3 );
- }
- static bool convert( const std::string& value, int& result )
- {
- return IntConvertor::convert( value, result );
- }
- static int convert( const std::string& value )
- throw( FieldConvertError )
- {
- return IntConvertor::convert( value );
- }
- };
- /// Converts double to/from a string
- struct DoubleConvertor
- {
- private:
- /*Simple and fast atof (ascii to float) function.
- Executes about 5x faster than standard MSCRT library atof().
- An attractive alternative if the number of calls is in the millions.
- Assumes input is a proper integer, fraction, or scientific format.
- Matches library atof() to 15 digits (except at extreme exponents).
- Follows atof() precedent of essentially no error checking.
- 09-May-2009 Tom Van Baak (tvb) www.LeapSecond.com */
- static double fast_atof (const char *p)
- {
- bool frac(false);
- double sign(1.), value(0.), scale(1.);
- while (IS_SPACE(*p))
- ++p;
- // Get sign, if any.
- if (*p == '-')
- {
- sign = -1.;
- ++p;
- }
- else if (*p == '+')
- ++p;
- // Get digits before decimal point or exponent, if any.
- while (IS_DIGIT(*p))
- {
- value = value * 10. + (*p - '0');
- ++p;
- }
- // Get digits after decimal point, if any.
- if (*p == '.')
- {
- ++p;
- double pow10(10.);
- while (IS_DIGIT(*p))
- {
- value += (*p - '0') / pow10;
- pow10 *= 10.;
- ++p;
- }
- }
- // Handle exponent, if any.
- if (toupper(*p) == 'E')
- {
- unsigned int expon(0);
- ++p;
- // Get sign of exponent, if any.
- if (*p == '-')
- {
- frac = true;
- ++p;
- }
- else if (*p == '+')
- ++p;
- // Get digits of exponent, if any.
- while (IS_DIGIT(*p))
- {
- expon = expon * 10 + (*p - '0');
- ++p;
- }
- if (expon > 308)
- expon = 308;
- // Calculate scaling factor.
- while (expon >= 50)
- {
- scale *= 1E50;
- expon -= 50;
- }
- while (expon >= 8)
- {
- scale *= 1E8;
- expon -= 8;
- }
- while (expon > 0)
- {
- scale *= 10.0;
- expon -= 1;
- }
- }
- // Return signed and scaled floating point result.
- return sign * (frac ? (value / scale) : (value * scale));
- }
- public:
- static std::string convert( double value, int padding = 0 )
- {
- char result[32];
- char *end = 0;
- int size;
- if( value == 0 || value > 0.0001 || value <= -0.0001 )
- {
- size = STRING_SPRINTF( result, "%.15g", value );
- if( padding > 0 )
- {
- char* point = result;
- end = result + size - 1;
- while( *point != '.' && *point != 0 )
- point++;
- if( *point == 0 )
- {
- end = point;
- *point = '.';
- size++;
- }
- int needed = padding - (int)(end - point);
- while( needed-- > 0 )
- {
- *(++end) = '0';
- size++;
- }
- *(end+1) = 0;
- }
- }
- else
- {
- size = STRING_SPRINTF( result, "%.15f", value );
- // strip trailing 0's
- end = result + size - 1;
- if( padding > 0 )
- {
- int discard = 15 - padding;
- while( (*end == '0') && (discard-- > 0) )
- {
- *(end--) = 0;
- size--;
- }
- }
- else
- {
- while( *end == '0' )
- {
- *(end--) = 0;
- size--;
- }
- }
- }
- return std::string( result, size );
- }
- static bool convert( const std::string& value, double& result )
- {
- const char * i = value.c_str();
- // Catch null strings
- if( !*i ) return false;
- // Eat leading '-' and recheck for null string
- if( *i == '-' && !*++i ) return false;
- bool haveDigit = false;
- if( IS_DIGIT(*i) )
- {
- haveDigit = true;
- while( IS_DIGIT (*++i) );
- }
- if( *i == '.' && IS_DIGIT(*++i) )
- {
- haveDigit = true;
- while( IS_DIGIT (*++i) );
- }
- if( *i || !haveDigit ) return false;
-
- result = fast_atof( value.c_str() );
- return true;
- }
- static double convert( const std::string& value )
- throw( FieldConvertError )
- {
- double result = 0.0;
- if( !convert( value, result ) )
- throw FieldConvertError(value);
- else
- return result;
- }
- };
- /// Converts character to/from a string
- struct CharConvertor
- {
- static std::string convert( char value )
- {
- if( value == '\0' ) return "";
- return std::string( 1, value );
- }
- static bool convert( const std::string& value, char& result )
- {
- if( value.size() != 1 ) return false;
- result = value[0];
- return true;
- }
- static char convert( const std::string& value )
- throw( FieldConvertError )
- {
- char result = '\0';
- if( !convert( value, result ) )
- throw FieldConvertError(value);
- else
- return result;
- }
- };
- /// Converts boolean to/from a string
- struct BoolConvertor
- {
- static std::string convert( bool value )
- {
- const char ch = value ? 'Y' : 'N';
- return std::string( 1, ch );
- }
- static bool convert( const std::string& value, bool& result )
- {
- if( value.size() != 1 ) return false;
- switch( value[0] )
- {
- case 'Y': result = true; break;
- case 'N': result = false; break;
- default: return false;
- }
- return true;
- }
- static bool convert( const std::string& value )
- throw( FieldConvertError )
- {
- bool result = false;
- if( !convert( value, result ) )
- throw FieldConvertError(value);
- else
- return result;
- }
- };
- /// Converts a UtcTimeStamp to/from a string
- struct UtcTimeStampConvertor
- {
- static std::string convert( const UtcTimeStamp& value,
- bool showMilliseconds = false )
- throw( FieldConvertError )
- {
- char result[ 18+4 ];
- int year, month, day, hour, minute, second, millis;
- value.getYMD( year, month, day );
- value.getHMS( hour, minute, second, millis );
- integer_to_string_padded( result, 5, year, 4 );
- integer_to_string_padded( result + 4, 3, month, 2 );
- integer_to_string_padded( result + 6, 3, day, 2 );
- result[8] = '-';
- integer_to_string_padded( result + 9, 3, hour, 2 );
- result[11] = ':';
- integer_to_string_padded( result + 12, 3, minute, 2 );
- result[14] = ':';
- integer_to_string_padded( result + 15, 3, second, 2 );
- if( showMilliseconds )
- {
- result[17] = '.';
- if( integer_to_string_padded ( result + 18, 4, millis, 3 )
- != result + 18 )
- {
- throw FieldConvertError();
- }
- }
- return result;
- }
- static UtcTimeStamp convert( const std::string& value,
- bool calculateDays = false )
- throw( FieldConvertError )
- {
- bool haveMilliseconds = false;
- switch( value.size() )
- {
- case 21: haveMilliseconds = true;
- case 17: break;
- default: throw FieldConvertError(value);
- }
- int i = 0;
- int c = 0;
- for( c = 0; c < 8; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if (value[i++] != '-') throw FieldConvertError(value);
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( value[i++] != ':' ) throw FieldConvertError(value);
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( value[i++] != ':' ) throw FieldConvertError(value);
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( haveMilliseconds )
- {
- if( value[i++] != '.' ) throw FieldConvertError(value);
- for( c = 0; c < 3; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- }
- int year, mon, mday, hour, min, sec, millis;
- i = 0;
- year = value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- mon = value[i++] - '0';
- mon = 10 * mon + value[i++] - '0';
- if( mon < 1 || 12 < mon ) throw FieldConvertError(value);
- mday = value[i++] - '0';
- mday = 10 * mday + value[i++] - '0';
- if( mday < 1 || 31 < mday ) throw FieldConvertError(value);
- ++i; // skip '-'
- hour = value[i++] - '0';
- hour = 10 * hour + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 23 < hour ) throw FieldConvertError(value);
- ++i; // skip ':'
- min = value[i++] - '0';
- min = 10 * min + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 59 < min ) throw FieldConvertError(value);
- ++i; // skip ':'
- sec = value[i++] - '0';
- sec = 10 * sec + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 60 < sec ) throw FieldConvertError(value);
- if( haveMilliseconds )
- {
- millis = (100 * (value[i+1] - '0')
- + 10 * (value[i+2] - '0')
- + (value[i+3] - '0'));
- }
- else
- millis = 0;
- return UtcTimeStamp (hour, min, sec, millis,
- mday, mon, year);
- }
- };
- /// Converts a UtcTimeOnly to/from a string
- struct UtcTimeOnlyConvertor
- {
- static std::string convert( const UtcTimeOnly& value,
- bool showMilliseconds = false)
- throw( FieldConvertError )
- {
- char result[ 9+4 ];
- int hour, minute, second, millis;
- value.getHMS( hour, minute, second, millis );
- integer_to_string_padded ( result, 3, hour, 2 );
- result[2] = ':';
- integer_to_string_padded ( result + 3, 3, minute, 2 );
- result[5] = ':';
- integer_to_string_padded ( result + 6, 3, second, 2 );
- if( showMilliseconds )
- {
- result[8] = '.';
- if( integer_to_string_padded ( result + 9, 4, millis, 3 )
- != result + 9 )
- throw FieldConvertError();
- }
- return result;
- }
- static UtcTimeOnly convert( const std::string& value )
- throw( FieldConvertError )
- {
- bool haveMilliseconds = false;
- switch( value.size() )
- {
- case 12: haveMilliseconds = true;
- case 8: break;
- default: throw FieldConvertError(value);
- }
- int i = 0;
- int c = 0;
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( value[i++] != ':' ) throw FieldConvertError(value);
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( value[i++] != ':' ) throw FieldConvertError(value);
- for( c = 0; c < 2; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- if( haveMilliseconds )
- {
- // ++i instead of i++ skips the '.' separator
- for( c = 0; c < 3; ++c )
- if( !IS_DIGIT(value[++i]) ) throw FieldConvertError(value);
- }
- int hour, min, sec, millis;
-
- i = 0;
- hour = value[i++] - '0';
- hour = 10 * hour + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 23 < hour ) throw FieldConvertError(value);
- ++i; // skip ':'
- min = value[i++] - '0';
- min = 10 * min + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 59 < min ) throw FieldConvertError(value);
- ++i; // skip ':'
- sec = value[i++] - '0';
- sec = 10 * sec + value[i++] - '0';
- // No check for >= 0 as no '-' are converted here
- if( 60 < sec ) throw FieldConvertError(value);
- if( haveMilliseconds )
- {
- millis = (100 * (value[i+1] - '0')
- + 10 * (value[i+2] - '0')
- + (value[i+3] - '0'));
- }
- else
- millis = 0;
- return UtcTimeOnly( hour, min, sec, millis );
- }
- };
- /// Converts a UtcDate to/from a string
- struct UtcDateConvertor
- {
- static std::string convert( const UtcDate& value )
- throw( FieldConvertError )
- {
- char result[ 9 ];
- int year, month, day;
- value.getYMD( year, month, day );
- integer_to_string_padded( result, 5, year, 4 );
- integer_to_string_padded( result + 4, 3, month, 2 );
- integer_to_string_padded( result + 6, 3, day, 2 );
- return result;
- }
- static UtcDate convert( const std::string& value )
- throw( FieldConvertError )
- {
- if( value.size() != 8 ) throw FieldConvertError(value);
- int i = 0;
- for( int c=0; c<8; ++c )
- if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
- int year, mon, mday;
- i = 0;
- year = value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- year = 10 * year + value[i++] - '0';
- mon = value[i++] - '0';
- mon = 10 * mon + value[i++] - '0';
- if( mon < 1 || 12 < mon )
- throw FieldConvertError(value);
- mday = value[i++] - '0';
- mday = 10 * mday + value[i++] - '0';
- if( mday < 1 || 31 < mday )
- throw FieldConvertError(value);
- return UtcDateOnly( mday, mon, year );
- }
- };
- typedef UtcDateConvertor UtcDateOnlyConvertor;
- typedef StringConvertor STRING_CONVERTOR;
- typedef CharConvertor CHAR_CONVERTOR;
- typedef DoubleConvertor PRICE_CONVERTOR;
- typedef IntConvertor INT_CONVERTOR;
- typedef DoubleConvertor AMT_CONVERTOR;
- typedef DoubleConvertor QTY_CONVERTOR;
- typedef StringConvertor CURRENCY_CONVERTOR;
- typedef StringConvertor MULTIPLEVALUESTRING_CONVERTOR;
- typedef StringConvertor MULTIPLESTRINGVALUE_CONVERTOR;
- typedef StringConvertor MULTIPLECHARVALUE_CONVERTOR;
- typedef StringConvertor EXCHANGE_CONVERTOR;
- typedef UtcTimeStampConvertor UTCTIMESTAMP_CONVERTOR;
- typedef BoolConvertor BOOLEAN_CONVERTOR;
- typedef StringConvertor LOCALMKTDATE_CONVERTOR;
- typedef StringConvertor DATA_CONVERTOR;
- typedef DoubleConvertor FLOAT_CONVERTOR;
- typedef DoubleConvertor PRICEOFFSET_CONVERTOR;
- typedef StringConvertor MONTHYEAR_CONVERTOR;
- typedef StringConvertor DAYOFMONTH_CONVERTOR;
- typedef UtcDateConvertor UTCDATE_CONVERTOR;
- typedef UtcTimeOnlyConvertor UTCTIMEONLY_CONVERTOR;
- typedef IntConvertor NUMINGROUP_CONVERTOR;
- typedef DoubleConvertor PERCENTAGE_CONVERTOR;
- typedef IntConvertor SEQNUM_CONVERTOR;
- typedef IntConvertor LENGTH_CONVERTOR;
- typedef StringConvertor COUNTRY_CONVERTOR;
- typedef StringConvertor TZTIMEONLY_CONVERTOR;
- typedef StringConvertor TZTIMESTAMP_CONVERTOR;
- typedef StringConvertor XMLDATA_CONVERTOR;
- typedef StringConvertor LANGUAGE_CONVERTOR;
- typedef CheckSumConvertor CHECKSUM_CONVERTOR;
- }
- #endif //FIX_FIELDCONVERTORS_H
|