Index Source Files Annotated Class List Alphabetical Class List Class Hierarchy Graphical Class Hierarchy

# FieldConvertors.h

Go to the documentation of this file.

    00001 /* -*- C++ -*- */
    00002
    00003 /****************************************************************************
    00004 ** Copyright (c) quickfixengine.org  All rights reserved.
    00005 **
    00006 ** This file is part of the QuickFIX FIX Engine
    00007 **
    00008 ** This file may be distributed under the terms of the quickfixengine.org
    00009 ** license as defined by quickfixengine.org and appearing in the file
    00010 ** LICENSE included in the packaging of this file.
    00011 **
    00012 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
    00013 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
    00014 **
    00015 ** See http://www.quickfixengine.org/LICENSE for licensing information.
    00016 **
    00017 ** Contact ask@quickfixengine.org if any conditions of this licensing are
    00018 ** not clear to you.
    00019 **
    00020 ****************************************************************************/
    00021
    00022 #ifndef FIX_FIELDCONVERTORS_H
    00023 #define FIX_FIELDCONVERTORS_H
    00024
    00025 #include "FieldTypes.h"
    00026 #include "Exceptions.h"
    00027 #include "Utility.h"
    00028 #include <string>
    00029 #include <sstream>
    00030 #include <iomanip>
    00031 #include <cstdio>
    00032 #include <limits>
    00033
    00034 namespace FIX
    00035 {
    00036 template<class T>
    00037 inline char* integer_to_string( char* buf, const size_t len, T t )
    00038 {
    00039   const bool isNegative = t < 0;
    00040   char* p = buf + len;
    00041
    00042   *--p = '\0';
    00043
    00044   if( isNegative )
    00045   {
    00046     if( t == (std::numeric_limits<T>::min)() )
    00047     {
    00048       *--p = '0' + (char)((10-t%10)%10);
    00049       t/=10;
    00050     }
    00051     t = -t;
    00052     do
    00053     {
    00054       *--p = '0' + (char)(t % 10);
    00055       t /= 10;
    00056     } while (t > 0);
    00057     *--p = '-';
    00058   }
    00059   else
    00060   {
    00061     do
    00062     {
    00063       *--p = '0' + (char)(t % 10);
    00064       t /= 10;
    00065     } while( t > 0 );
    00066   }
    00067   return p;
    00068 }
    00069
    00070 template<class T>
    00071 inline char* integer_to_string_padded
    00072 ( char* buf, const size_t len, T t,
    00073   const size_t width = 0,
    00074   const char paddingChar = '0')
    00075 {
    00076   if( !width ) return integer_to_string( buf, len, t );
    00077
    00078   const bool isNegative = t < 0;
    00079   char* p = buf + len;
    00080
    00081   *--p = '\0';
    00082
    00083   if( isNegative )
    00084   {
    00085     if( t == (std::numeric_limits<T>::min)() )
    00086     {
    00087       *--p = '0' + (char)(( 10 -t % 10 ) % 10);
    00088       t/=10;
    00089     }
    00090     t=-t;
    00091     do
    00092     {
    00093       *--p = '0' + (char)(t % 10);
    00094       t /= 10;
    00095     } while (t > 0);
    00096     if( p > buf )
    00097       *--p = '-';
    00098   }
    00099   else
    00100   {
    00101     do
    00102     {
    00103       *--p = '0' + (char)(t % 10);
    00104       t /= 10;
    00105     } while( t > 0 );
    00106   }
    00107   const char* stop_p = buf + len - width - 1;
    00108   if( stop_p < buf ) stop_p = buf;
    00109   while( p > stop_p )
    00110     *--p = paddingChar;
    00111   return p;
    00112 }
    00113
    00115 struct EmptyConvertor
    00116 {
    00117   static const std::string& convert( const std::string& value )
    00118   { return value; }
    00119 };
    00120
    00121 typedef EmptyConvertor StringConvertor;
    00122
    00124 struct IntConvertor
    00125 {
    00126   static std::string convert( long value )
    00127   {
    00128     // buffer is big enough for significant digits and extra digit,
    00129     // minus and null
    00130     char buffer[std::numeric_limits<long>::digits10 + 3];
    00131     const char* const start
    00132       = integer_to_string( buffer, sizeof (buffer), value );
    00133     return std::string( start, buffer + sizeof (buffer) - start - 1 );
    00134   }
    00135
    00136   static bool convert( const std::string& value, long& result )
    00137   {
    00138     const char* str = value.c_str();
    00139     bool isNegative = false;
    00140     long x = 0;
    00141
    00142     if( *str == '-' )
    00143     {
    00144       isNegative = true;
    00145       ++str;
    00146     }
    00147
    00148     do
    00149     {
    00150       const int c = *str - '0';
    00151       if( c < 0 || 9 < c ) return false;
    00152       x = 10 * x + c;
    00153     } while (*++str);
    00154
    00155     if( isNegative )
    00156       x = -x;
    00157
    00158     result = x;
    00159     return true;
    00160   }
    00161
    00162   static long convert( const std::string& value )
    00163   throw( FieldConvertError )
    00164   {
    00165     long result = 0;
    00166     if( !convert( value, result ) )
    00167       throw FieldConvertError();
    00168     else
    00169       return result;
    00170   }
    00171 };
    00172
    00174 struct CheckSumConvertor
    00175 {
    00176   static std::string convert( long value )
    00177   throw( FieldConvertError )
    00178   {
    00179     if ( value > 255 || value < 0 ) throw FieldConvertError();
    00180     char result[4];
    00181     if( integer_to_string_padded(result, sizeof(result), value, 3, '0') != result )
    00182     {
    00183       throw FieldConvertError();
    00184     }
    00185     return std::string( result, 3 );
    00186   }
    00187
    00188   static bool convert( const std::string& value, long& result )
    00189   {
    00190     return IntConvertor::convert( value, result );
    00191   }
    00192
    00193   static long convert( const std::string& value )
    00194   throw( FieldConvertError )
    00195   {
    00196     return IntConvertor::convert( value );
    00197   }
    00198 };
    00199
    00201 struct DoubleConvertor
    00202 {
    00203   static std::string convert( double value, int padding = 0 )
    00204   {
    00205     char result[32];
    00206     char *end = 0;
    00207
    00208     int size;
    00209     if( value == 0 || value > 0.0001 || value <= -0.0001 )
    00210     {
    00211       size = STRING_SPRINTF( result, "%.15g", value );
    00212
    00213       if( padding > 0 )
    00214       {
    00215         char* point = result;
    00216         end = result + size - 1;
    00217         while( *point != '.' && *point != 0 )
    00218           point++;
    00219
    00220         if( *point == 0 )
    00221         {
    00222           end = point;
    00223           *point = '.';
    00224           size++;
    00225         }
    00226         int needed = padding - (int)(end - point);
    00227
    00228         while( needed-- > 0 )
    00229         {
    00230           *(++end) = '0';
    00231           size++;
    00232         }
    00233         *(end+1) = 0;
    00234       }
    00235     }
    00236     else
    00237     {
    00238       size = STRING_SPRINTF( result, "%.15f", value );
    00239       // strip trailing 0's
    00240       end = result + size - 1;
    00241
    00242       if( padding > 0 )
    00243       {
    00244         int discard = 15 - padding;
    00245
    00246         while( (*end == '0') && (discard-- > 0) )
    00247         {
    00248           *(end--) = 0;
    00249           size--;
    00250         }
    00251      }
    00252      else
    00253      {
    00254        while( *end == '0' )
    00255        {
    00256          *(end--) = 0;
    00257          size--;
    00258        }
    00259      }
    00260    }
    00261
    00262    return std::string( result, size );
    00263 }
    00264
    00265 static bool convert( const std::string& value, double& result )
    00266 {
    00267   const char * i = value.c_str();
    00268
    00269   // Catch null strings
    00270   if( !*i ) return false;
    00271   // Eat leading '-' and recheck for null string
    00272   if( *i == '-' && !*++i ) return false;
    00273
    00274   bool haveDigit = false;
    00275
    00276   if( isdigit(*i) )
    00277   {
    00278     haveDigit = true;
    00279     while( isdigit (*++i) );
    00280   }
    00281
    00282   if( *i == '.' && isdigit(*++i) )
    00283   {
    00284     haveDigit = true;
    00285     while( isdigit (*++i) );
    00286   }
    00287
    00288   if( *i || !haveDigit ) return false;
    00289     result = strtod( value.c_str(), 0 );
    00290     return true;
    00291   }
    00292
    00293   static double convert( const std::string& value )
    00294   throw( FieldConvertError )
    00295   {
    00296     double result = 0.0;
    00297     if( !convert( value, result ) )
    00298       throw FieldConvertError();
    00299     else
    00300       return result;
    00301   }
    00302 };
    00303
    00305 struct CharConvertor
    00306 {
    00307   static std::string convert( char value )
    00308   {
    00309     if( value == '\0' ) return "";
    00310     return std::string( 1, value );
    00311   }
    00312
    00313   static bool convert( const std::string& value, char& result )
    00314   {
    00315     if( value.size() != 1 ) return false;
    00316     result = value[0];
    00317     return true;
    00318   }
    00319
    00320   static char convert( const std::string& value )
    00321   throw( FieldConvertError )
    00322   {
    00323     char result = '\0';
    00324     if( !convert( value, result ) )
    00325       throw FieldConvertError();
    00326     else
    00327       return result;
    00328   }
    00329 };
    00330
    00332 struct BoolConvertor
    00333 {
    00334   static std::string convert( bool value )
    00335   {
    00336     const char ch = value ? 'Y' : 'N';
    00337     return std::string( 1, ch );
    00338   }
    00339
    00340   static bool convert( const std::string& value, bool& result )
    00341   {
    00342     if( value.size() != 1 ) return false;
    00343     switch( value[0] )
    00344     {
    00345       case 'Y': result = true; break;
    00346       case 'N': result = false; break;
    00347       default: return false;
    00348     }
    00349
    00350     return true;
    00351   }
    00352
    00353   static bool convert( const std::string& value )
    00354   throw( FieldConvertError )
    00355   {
    00356     bool result = false;
    00357     if( !convert( value, result ) )
    00358       throw FieldConvertError();
    00359     else
    00360       return result;
    00361   }
    00362 };
    00363
    00365 struct UtcTimeStampConvertor
    00366 {
    00367   static std::string convert( const UtcTimeStamp& value,
    00368                               bool showMilliseconds = false )
    00369   throw( FieldConvertError )
    00370   {
    00371     char result[ 18+4 ];
    00372     int year, month, day, hour, minute, second, millis;
    00373
    00374     value.getYMD( year, month, day );
    00375     value.getHMS( hour, minute, second, millis );
    00376
    00377     integer_to_string_padded( result, 5, year, 4, '0' );
    00378     integer_to_string_padded( result + 4, 3, month, 2, '0' );
    00379     integer_to_string_padded( result + 6, 3, day, 2, '0' );
    00380     result[8]  = '-';
    00381     integer_to_string_padded( result + 9, 3, hour, 2, '0' );
    00382     result[11] = ':';
    00383     integer_to_string_padded( result + 12, 3, minute, 2, '0' );
    00384     result[14] = ':';
    00385     integer_to_string_padded( result + 15, 3, second, 2, '0' );
    00386
    00387     if( showMilliseconds )
    00388     {
    00389       result[17] = '.';
    00390       if( integer_to_string_padded ( result + 18, 4, millis, 3, '0' )
    00391           != result + 18 )
    00392       {
    00393         throw FieldConvertError();
    00394       }
    00395     }
    00396
    00397     return result;
    00398   }
    00399
    00400   static UtcTimeStamp convert( const std::string& value,
    00401                                bool calculateDays = false )
    00402   throw( FieldConvertError )
    00403   {
    00404     bool haveMilliseconds = false;
    00405
    00406     switch( value.size() )
    00407     {
    00408       case 21: haveMilliseconds = true;
    00409       case 17: break;
    00410       default: throw FieldConvertError();
    00411     }
    00412
    00413     int i = 0;
    00414     int c = 0;
    00415     for( c = 0; c < 8; ++c )
    00416       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00417     if (value[i++] != '-') throw FieldConvertError();
    00418     for( c = 0; c < 2; ++c )
    00419       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00420     if( value[i++] != ':' ) throw FieldConvertError();
    00421     for( c = 0; c < 2; ++c )
    00422       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00423     if( value[i++] != ':' ) throw FieldConvertError();
    00424     for( c = 0; c < 2; ++c )
    00425       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00426
    00427     if( haveMilliseconds )
    00428     {
    00429       if( value[i++] != '.' ) throw FieldConvertError();
    00430       for( c = 0; c < 3; ++c )
    00431               if( !isdigit(value[i++]) ) throw FieldConvertError();
    00432     }
    00433
    00434     int year, mon, mday, hour, min, sec, millis;
    00435
    00436     i = 0;
    00437
    00438     year = value[i++] - '0';
    00439     year = 10 * year + value[i++] - '0';
    00440     year = 10 * year + value[i++] - '0';
    00441     year = 10 * year + value[i++] - '0';
    00442
    00443     mon = value[i++] - '0';
    00444     mon = 10 * mon + value[i++] - '0';
    00445     if( mon < 1 || 12 < mon ) throw FieldConvertError();
    00446
    00447     mday = value[i++] - '0';
    00448     mday = 10 * mday + value[i++] - '0';
    00449     if( mday < 1 || 31 < mday ) throw FieldConvertError();
    00450
    00451     ++i; // skip '-'
    00452
    00453     hour = value[i++] - '0';
    00454     hour = 10 * hour + value[i++] - '0';
    00455     // No check for >= 0 as no '-' are converted here
    00456     if( 23 < hour ) throw FieldConvertError();
    00457
    00458     ++i; // skip ':'
    00459
    00460     min = value[i++] - '0';
    00461     min = 10 * min + value[i++] - '0';
    00462     // No check for >= 0 as no '-' are converted here
    00463     if( 59 < min ) throw FieldConvertError();
    00464
    00465     ++i; // skip ':'
    00466
    00467     sec = value[i++] - '0';
    00468     sec = 10 * sec + value[i++] - '0';
    00469
    00470     // No check for >= 0 as no '-' are converted here
    00471     if( 60 < sec ) throw FieldConvertError();
    00472
    00473     if( haveMilliseconds )
    00474     {
    00475       millis = (100 * (value[i+1] - '0')
    00476                 + 10 * (value[i+2] - '0')
    00477                 + (value[i+3] - '0'));
    00478     }
    00479     else
    00480       millis = 0;
    00481
    00482     return UtcTimeStamp (hour, min, sec, millis,
    00483                          mday, mon, year);
    00484   }
    00485 };
    00486
    00488 struct UtcTimeOnlyConvertor
    00489 {
    00490   static std::string convert( const UtcTimeOnly& value,
    00491                               bool showMilliseconds = false)
    00492   throw( FieldConvertError )
    00493   {
    00494     char result[ 9+4 ];
    00495     int hour, minute, second, millis;
    00496
    00497     value.getHMS( hour, minute, second, millis );
    00498
    00499     integer_to_string_padded ( result, 3, hour, 2, '0' );
    00500     result[2] = ':';
    00501     integer_to_string_padded ( result + 3, 3, minute,  2, '0' );
    00502     result[5] = ':';
    00503     integer_to_string_padded ( result + 6, 3, second,  2, '0' );
    00504
    00505     if( showMilliseconds )
    00506     {
    00507       result[8] = '.';
    00508       if( integer_to_string_padded ( result + 9, 4, millis, 3, '0' )
    00509           != result + 9 )
    00510           throw FieldConvertError();
    00511     }
    00512
    00513     return result;
    00514   }
    00515
    00516   static UtcTimeOnly convert( const std::string& value )
    00517   throw( FieldConvertError )
    00518   {
    00519     bool haveMilliseconds = false;
    00520
    00521     switch( value.size() )
    00522     {
    00523       case 12: haveMilliseconds = true;
    00524       case 8: break;
    00525       default: throw FieldConvertError();
    00526     }
    00527
    00528     int i = 0;
    00529     int c = 0;
    00530     for( c = 0; c < 2; ++c )
    00531       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00532     if( value[i++] != ':' ) throw FieldConvertError();
    00533     for( c = 0; c < 2; ++c )
    00534       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00535     if( value[i++] != ':' ) throw FieldConvertError();
    00536     for( c = 0; c < 2; ++c )
    00537       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00538
    00539     if( haveMilliseconds )
    00540     {
    00541       // ++i instead of i++ skips the '.' separator
    00542       for( c = 0; c < 3; ++c )
    00543               if( !isdigit(value[++i]) ) throw FieldConvertError();
    00544     }
    00545
    00546     int hour, min, sec, millis;
    00547
    00548     i = 0;
    00549
    00550     hour = value[i++] - '0';
    00551     hour = 10 * hour + value[i++] - '0';
    00552     // No check for >= 0 as no '-' are converted here
    00553     if( 23 < hour ) throw FieldConvertError();
    00554     ++i; // skip ':'
    00555
    00556     min = value[i++] - '0';
    00557     min = 10 * min + value[i++] - '0';
    00558     // No check for >= 0 as no '-' are converted here
    00559     if( 59 < min ) throw FieldConvertError();
    00560     ++i; // skip ':'
    00561
    00562     sec = value[i++] - '0';
    00563     sec = 10 * sec + value[i++] - '0';
    00564     // No check for >= 0 as no '-' are converted here
    00565     if( 60 < sec ) throw FieldConvertError();
    00566
    00567     if( haveMilliseconds )
    00568     {
    00569       millis = (100 * (value[i+1] - '0')
    00570                 + 10 * (value[i+2] - '0')
    00571                 + (value[i+3] - '0'));
    00572     }
    00573     else
    00574       millis = 0;
    00575
    00576     return UtcTimeOnly( hour, min, sec, millis );
    00577   }
    00578 };
    00579
    00581 struct UtcDateConvertor
    00582 {
    00583   static std::string convert( const UtcDate& value )
    00584   throw( FieldConvertError )
    00585   {
    00586     char result[ 9 ];
    00587     int year, month, day;
    00588
    00589     value.getYMD( year, month, day );
    00590
    00591     integer_to_string_padded( result, 5, year, 4, '0' );
    00592     integer_to_string_padded( result + 4, 3, month, 2, '0' );
    00593     integer_to_string_padded( result + 6, 3, day, 2, '0' );
    00594     return result;
    00595   }
    00596
    00597   static UtcDate convert( const std::string& value )
    00598   throw( FieldConvertError )
    00599   {
    00600     if( value.size() != 8 ) throw FieldConvertError();
    00601
    00602     int i = 0;
    00603     for( int c=0; c<8; ++c )
    00604       if( !isdigit(value[i++]) ) throw FieldConvertError();
    00605
    00606     int year, mon, mday;
    00607
    00608     i = 0;
    00609
    00610     year = value[i++] - '0';
    00611     year = 10 * year + value[i++] - '0';
    00612     year = 10 * year + value[i++] - '0';
    00613     year = 10 * year + value[i++] - '0';
    00614
    00615     mon = value[i++] - '0';
    00616     mon = 10 * mon + value[i++] - '0';
    00617     if( mon < 1 || 12 < mon )
    00618       throw FieldConvertError();
    00619
    00620     mday = value[i++] - '0';
    00621     mday = 10 * mday + value[i++] - '0';
    00622     if( mday < 1 || 31 < mday )
    00623       throw FieldConvertError();
    00624
    00625     return UtcDateOnly( mday, mon, year );
    00626   }
    00627 };
    00628
    00629 typedef UtcDateConvertor UtcDateOnlyConvertor;
    00630
    00631 typedef StringConvertor STRING_CONVERTOR;
    00632 typedef CharConvertor CHAR_CONVERTOR;
    00633 typedef DoubleConvertor PRICE_CONVERTOR;
    00634 typedef IntConvertor INT_CONVERTOR;
    00635 typedef DoubleConvertor AMT_CONVERTOR;
    00636 typedef DoubleConvertor QTY_CONVERTOR;
    00637 typedef StringConvertor CURRENCY_CONVERTOR;
    00638 typedef StringConvertor MULTIPLEVALUESTRING_CONVERTOR;
    00639 typedef StringConvertor MULTIPLESTRINGVALUE_CONVERTOR;
    00640 typedef StringConvertor MULTIPLECHARVALUE_CONVERTOR;
    00641 typedef StringConvertor EXCHANGE_CONVERTOR;
    00642 typedef UtcTimeStampConvertor UTCTIMESTAMP_CONVERTOR;
    00643 typedef BoolConvertor BOOLEAN_CONVERTOR;
    00644 typedef StringConvertor LOCALMKTDATE_CONVERTOR;
    00645 typedef StringConvertor DATA_CONVERTOR;
    00646 typedef DoubleConvertor FLOAT_CONVERTOR;
    00647 typedef DoubleConvertor PRICEOFFSET_CONVERTOR;
    00648 typedef StringConvertor MONTHYEAR_CONVERTOR;
    00649 typedef StringConvertor DAYOFMONTH_CONVERTOR;
    00650 typedef UtcDateConvertor UTCDATE_CONVERTOR;
    00651 typedef UtcTimeOnlyConvertor UTCTIMEONLY_CONVERTOR;
    00652 typedef IntConvertor NUMINGROUP_CONVERTOR;
    00653 typedef DoubleConvertor PERCENTAGE_CONVERTOR;
    00654 typedef IntConvertor SEQNUM_CONVERTOR;
    00655 typedef IntConvertor LENGTH_CONVERTOR;
    00656 typedef StringConvertor COUNTRY_CONVERTOR;
    00657 typedef StringConvertor TZTIMEONLY_CONVERTOR;
    00658 typedef StringConvertor TZTIMESTAMP_CONVERTOR;
    00659 typedef StringConvertor XMLDATA_CONVERTOR;
    00660 typedef StringConvertor LANGUAGE_CONVERTOR;
    00661 typedef CheckSumConvertor CHECKSUM_CONVERTOR;
    00662 }
    00663
    00664 #endif //FIX_FIELDCONVERTORS_H