00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00129
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
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
00270 if( !*i ) return false;
00271
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;
00452
00453 hour = value[i++] - '0';
00454 hour = 10 * hour + value[i++] - '0';
00455
00456 if( 23 < hour ) throw FieldConvertError();
00457
00458 ++i;
00459
00460 min = value[i++] - '0';
00461 min = 10 * min + value[i++] - '0';
00462
00463 if( 59 < min ) throw FieldConvertError();
00464
00465 ++i;
00466
00467 sec = value[i++] - '0';
00468 sec = 10 * sec + value[i++] - '0';
00469
00470
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
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
00553 if( 23 < hour ) throw FieldConvertError();
00554 ++i;
00555
00556 min = value[i++] - '0';
00557 min = 10 * min + value[i++] - '0';
00558
00559 if( 59 < min ) throw FieldConvertError();
00560 ++i;
00561
00562 sec = value[i++] - '0';
00563 sec = 10 * sec + value[i++] - '0';
00564
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