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

Generated on Mon Apr 5 20:59:50 2010 for QuickFIX by doxygen 1.6.1 written by Dimitri van Heesch, © 1997-2001