quickfix_ruby 1.14.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/ext/quickfix/Acceptor.cpp +248 -0
  3. data/ext/quickfix/Acceptor.h +127 -0
  4. data/ext/quickfix/Allocator.h +9 -0
  5. data/ext/quickfix/Application.h +127 -0
  6. data/ext/quickfix/AtomicCount.h +109 -0
  7. data/ext/quickfix/DOMDocument.h +74 -0
  8. data/ext/quickfix/DataDictionary.cpp +618 -0
  9. data/ext/quickfix/DataDictionary.h +539 -0
  10. data/ext/quickfix/DataDictionaryProvider.cpp +71 -0
  11. data/ext/quickfix/DataDictionaryProvider.h +70 -0
  12. data/ext/quickfix/DatabaseConnectionID.h +105 -0
  13. data/ext/quickfix/DatabaseConnectionPool.h +91 -0
  14. data/ext/quickfix/Dictionary.cpp +162 -0
  15. data/ext/quickfix/Dictionary.h +94 -0
  16. data/ext/quickfix/Event.h +95 -0
  17. data/ext/quickfix/Exceptions.h +299 -0
  18. data/ext/quickfix/Field.h +672 -0
  19. data/ext/quickfix/FieldConvertors.h +863 -0
  20. data/ext/quickfix/FieldMap.cpp +238 -0
  21. data/ext/quickfix/FieldMap.h +244 -0
  22. data/ext/quickfix/FieldNumbers.h +46 -0
  23. data/ext/quickfix/FieldTypes.cpp +64 -0
  24. data/ext/quickfix/FieldTypes.h +698 -0
  25. data/ext/quickfix/Fields.h +31 -0
  26. data/ext/quickfix/FileLog.cpp +200 -0
  27. data/ext/quickfix/FileLog.h +112 -0
  28. data/ext/quickfix/FileStore.cpp +332 -0
  29. data/ext/quickfix/FileStore.h +129 -0
  30. data/ext/quickfix/FixFieldNumbers.h +1537 -0
  31. data/ext/quickfix/FixFields.h +1538 -0
  32. data/ext/quickfix/FixValues.h +3281 -0
  33. data/ext/quickfix/FlexLexer.h +188 -0
  34. data/ext/quickfix/Group.cpp +64 -0
  35. data/ext/quickfix/Group.h +73 -0
  36. data/ext/quickfix/HtmlBuilder.h +186 -0
  37. data/ext/quickfix/HttpConnection.cpp +739 -0
  38. data/ext/quickfix/HttpConnection.h +78 -0
  39. data/ext/quickfix/HttpMessage.cpp +149 -0
  40. data/ext/quickfix/HttpMessage.h +133 -0
  41. data/ext/quickfix/HttpParser.cpp +49 -0
  42. data/ext/quickfix/HttpParser.h +54 -0
  43. data/ext/quickfix/HttpServer.cpp +169 -0
  44. data/ext/quickfix/HttpServer.h +78 -0
  45. data/ext/quickfix/Initiator.cpp +289 -0
  46. data/ext/quickfix/Initiator.h +149 -0
  47. data/ext/quickfix/Log.cpp +77 -0
  48. data/ext/quickfix/Log.h +179 -0
  49. data/ext/quickfix/Message.cpp +580 -0
  50. data/ext/quickfix/Message.h +370 -0
  51. data/ext/quickfix/MessageCracker.h +188 -0
  52. data/ext/quickfix/MessageSorters.cpp +105 -0
  53. data/ext/quickfix/MessageSorters.h +156 -0
  54. data/ext/quickfix/MessageStore.cpp +146 -0
  55. data/ext/quickfix/MessageStore.h +174 -0
  56. data/ext/quickfix/Mutex.h +131 -0
  57. data/ext/quickfix/MySQLConnection.h +194 -0
  58. data/ext/quickfix/MySQLLog.cpp +275 -0
  59. data/ext/quickfix/MySQLLog.h +145 -0
  60. data/ext/quickfix/MySQLStore.cpp +331 -0
  61. data/ext/quickfix/MySQLStore.h +142 -0
  62. data/ext/quickfix/NullStore.cpp +54 -0
  63. data/ext/quickfix/NullStore.h +99 -0
  64. data/ext/quickfix/OdbcConnection.h +266 -0
  65. data/ext/quickfix/OdbcLog.cpp +252 -0
  66. data/ext/quickfix/OdbcLog.h +117 -0
  67. data/ext/quickfix/OdbcStore.cpp +338 -0
  68. data/ext/quickfix/OdbcStore.h +113 -0
  69. data/ext/quickfix/PUGIXML_DOMDocument.cpp +112 -0
  70. data/ext/quickfix/PUGIXML_DOMDocument.h +81 -0
  71. data/ext/quickfix/Parser.cpp +103 -0
  72. data/ext/quickfix/Parser.h +57 -0
  73. data/ext/quickfix/PostgreSQLConnection.h +176 -0
  74. data/ext/quickfix/PostgreSQLLog.cpp +276 -0
  75. data/ext/quickfix/PostgreSQLLog.h +144 -0
  76. data/ext/quickfix/PostgreSQLStore.cpp +334 -0
  77. data/ext/quickfix/PostgreSQLStore.h +141 -0
  78. data/ext/quickfix/Queue.h +75 -0
  79. data/ext/quickfix/QuickfixRuby.cpp +252066 -0
  80. data/ext/quickfix/QuickfixRuby.h +34 -0
  81. data/ext/quickfix/Responder.h +43 -0
  82. data/ext/quickfix/Session.cpp +1487 -0
  83. data/ext/quickfix/Session.h +335 -0
  84. data/ext/quickfix/SessionFactory.cpp +274 -0
  85. data/ext/quickfix/SessionFactory.h +86 -0
  86. data/ext/quickfix/SessionID.h +170 -0
  87. data/ext/quickfix/SessionSettings.cpp +189 -0
  88. data/ext/quickfix/SessionSettings.h +171 -0
  89. data/ext/quickfix/SessionState.h +231 -0
  90. data/ext/quickfix/Settings.cpp +100 -0
  91. data/ext/quickfix/Settings.h +53 -0
  92. data/ext/quickfix/SharedArray.h +150 -0
  93. data/ext/quickfix/SocketAcceptor.cpp +222 -0
  94. data/ext/quickfix/SocketAcceptor.h +75 -0
  95. data/ext/quickfix/SocketConnection.cpp +238 -0
  96. data/ext/quickfix/SocketConnection.h +103 -0
  97. data/ext/quickfix/SocketConnector.cpp +116 -0
  98. data/ext/quickfix/SocketConnector.h +67 -0
  99. data/ext/quickfix/SocketInitiator.cpp +260 -0
  100. data/ext/quickfix/SocketInitiator.h +81 -0
  101. data/ext/quickfix/SocketMonitor.cpp +335 -0
  102. data/ext/quickfix/SocketMonitor.h +111 -0
  103. data/ext/quickfix/SocketServer.cpp +177 -0
  104. data/ext/quickfix/SocketServer.h +100 -0
  105. data/ext/quickfix/ThreadedSocketAcceptor.cpp +258 -0
  106. data/ext/quickfix/ThreadedSocketAcceptor.h +98 -0
  107. data/ext/quickfix/ThreadedSocketConnection.cpp +209 -0
  108. data/ext/quickfix/ThreadedSocketConnection.h +82 -0
  109. data/ext/quickfix/ThreadedSocketInitiator.cpp +268 -0
  110. data/ext/quickfix/ThreadedSocketInitiator.h +84 -0
  111. data/ext/quickfix/TimeRange.cpp +173 -0
  112. data/ext/quickfix/TimeRange.h +258 -0
  113. data/ext/quickfix/Utility.cpp +537 -0
  114. data/ext/quickfix/Utility.h +219 -0
  115. data/ext/quickfix/Values.h +62 -0
  116. data/ext/quickfix/config.h +0 -0
  117. data/ext/quickfix/config_windows.h +0 -0
  118. data/ext/quickfix/extconf.rb +12 -0
  119. data/ext/quickfix/index.h +37 -0
  120. data/ext/quickfix/pugiconfig.hpp +72 -0
  121. data/ext/quickfix/pugixml.cpp +10765 -0
  122. data/ext/quickfix/pugixml.hpp +1341 -0
  123. data/ext/quickfix/strptime.h +7 -0
  124. data/lib/quickfix40.rb +274 -0
  125. data/lib/quickfix41.rb +351 -0
  126. data/lib/quickfix42.rb +1184 -0
  127. data/lib/quickfix43.rb +3504 -0
  128. data/lib/quickfix44.rb +10721 -0
  129. data/lib/quickfix50.rb +13426 -0
  130. data/lib/quickfix50sp1.rb +15629 -0
  131. data/lib/quickfix50sp2.rb +17068 -0
  132. data/lib/quickfix_fields.rb +19853 -0
  133. data/lib/quickfix_ruby.rb +82 -0
  134. data/lib/quickfixt11.rb +70 -0
  135. data/spec/FIX40.xml +862 -0
  136. data/spec/FIX41.xml +1285 -0
  137. data/spec/FIX42.xml +2746 -0
  138. data/spec/FIX43.xml +4229 -0
  139. data/spec/FIX44.xml +6596 -0
  140. data/spec/FIX50.xml +8137 -0
  141. data/spec/FIX50SP1.xml +9496 -0
  142. data/spec/FIX50SP2.xml +10011 -0
  143. data/spec/FIXT11.xml +313 -0
  144. data/test/test_DataDictionaryTestCase.rb +268 -0
  145. data/test/test_DictionaryTestCase.rb +112 -0
  146. data/test/test_FieldBaseTestCase.rb +24 -0
  147. data/test/test_MessageTestCase.rb +368 -0
  148. data/test/test_SessionSettingsTestCase.rb +41 -0
  149. metadata +193 -0
@@ -0,0 +1,863 @@
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
+ #include "FieldTypes.h"
26
+ #include "Exceptions.h"
27
+ #include "Utility.h"
28
+ #include <string>
29
+ #include <sstream>
30
+ #include <iomanip>
31
+ #include <cstdio>
32
+ #include <limits>
33
+
34
+ namespace FIX
35
+ {
36
+
37
+ typedef int signed_int;
38
+ typedef unsigned int unsigned_int;
39
+
40
+ #define UNSIGNED_VALUE_OF( x ) unsigned_int( x < 0 ? -x : x )
41
+
42
+ #define IS_SPACE( x ) ( x == ' ' )
43
+ #define IS_DIGIT( x ) ( unsigned_int( x - '0' ) < 10 )
44
+
45
+ inline int number_of_symbols_in( const signed_int value )
46
+ {
47
+ unsigned_int number = UNSIGNED_VALUE_OF( value );
48
+
49
+ int symbols = 0;
50
+
51
+ while( number > 9999 )
52
+ {
53
+ symbols += 4;
54
+ number /= 10000;
55
+ }
56
+
57
+ // small tweak to make comparison times consistent
58
+ // always 2 comparisons instead of [1 - 4]
59
+ if( number > 99 )
60
+ {
61
+ if( number > 999 )
62
+ symbols += 4;
63
+ else
64
+ symbols += 3;
65
+ }
66
+ else
67
+ {
68
+ if( number > 9 )
69
+ symbols += 2;
70
+ else
71
+ symbols += 1;
72
+ }
73
+
74
+ if( value < 0 )
75
+ symbols += 1;
76
+
77
+ return symbols;
78
+ }
79
+
80
+ static const char digit_pairs[201] = {
81
+ "00010203040506070809"
82
+ "10111213141516171819"
83
+ "20212223242526272829"
84
+ "30313233343536373839"
85
+ "40414243444546474849"
86
+ "50515253545556575859"
87
+ "60616263646566676869"
88
+ "70717273747576777879"
89
+ "80818283848586878889"
90
+ "90919293949596979899"
91
+ };
92
+
93
+ inline char* integer_to_string( char* buf, const size_t len, signed_int t )
94
+ {
95
+ const bool isNegative = t < 0;
96
+ char* p = buf + len;
97
+
98
+ *--p = '\0';
99
+
100
+ unsigned_int number = UNSIGNED_VALUE_OF( t );
101
+
102
+ while( number > 99 )
103
+ {
104
+ unsigned_int pos = number % 100;
105
+ number /= 100;
106
+ p -= 2;
107
+ *(short*)(p) = *(short*)(digit_pairs + 2 * pos);
108
+ }
109
+
110
+ if( number > 9 )
111
+ {
112
+ p -= 2;
113
+ *(short*)(p) = *(short*)(digit_pairs + 2 * number);
114
+ }
115
+ else
116
+ {
117
+ *--p = '0' + char(number);
118
+ }
119
+
120
+ if( isNegative )
121
+ *--p = '-';
122
+
123
+ return p;
124
+ }
125
+
126
+ inline char* integer_to_string_padded
127
+ ( char* buf, const size_t len, signed_int t,
128
+ const size_t width = 0,
129
+ const char paddingChar = '0')
130
+ {
131
+ char* p = integer_to_string( buf, len, t );
132
+ if( !width )
133
+ return p;
134
+
135
+ const char* stop_p = buf + len - width - 1;
136
+ if( stop_p < buf ) stop_p = buf;
137
+ while( p > stop_p )
138
+ *--p = paddingChar;
139
+ return p;
140
+ }
141
+
142
+ /// Empty converter is a no-op.
143
+ struct EmptyConvertor
144
+ {
145
+ static const std::string& convert( const std::string& value )
146
+ { return value; }
147
+ };
148
+
149
+ typedef EmptyConvertor StringConvertor;
150
+
151
+ /// Converts integer to/from a string
152
+ struct IntConvertor
153
+ {
154
+ static std::string convert( signed_int value )
155
+ {
156
+ // buffer is big enough for significant digits and extra digit,
157
+ // minus and null
158
+ char buffer[std::numeric_limits<signed_int>::digits10 + 3];
159
+ const char* const start
160
+ = integer_to_string( buffer, sizeof (buffer), value );
161
+ return std::string( start, buffer + sizeof (buffer) - start - 1 );
162
+ }
163
+
164
+ static bool convert(
165
+ std::string::const_iterator str,
166
+ std::string::const_iterator end,
167
+ signed_int& result )
168
+ {
169
+ bool isNegative = false;
170
+ signed_int x = 0;
171
+
172
+ if( str == end )
173
+ return false;
174
+
175
+ if( *str == '-' )
176
+ {
177
+ isNegative = true;
178
+ if( ++str == end )
179
+ return false;
180
+ }
181
+
182
+ do
183
+ {
184
+ const unsigned_int c = *str - '0';
185
+ if( c > 9 ) return false;
186
+ x = 10 * x + c;
187
+ } while ( ++str != end );
188
+
189
+ if( isNegative )
190
+ x = -x;
191
+
192
+ result = x;
193
+ return true;
194
+ }
195
+
196
+ static bool convert( const std::string& value, signed_int& result )
197
+ {
198
+ return convert( value.begin(), value.end(), result );
199
+ }
200
+
201
+ static signed_int convert( const std::string& value )
202
+ throw( FieldConvertError )
203
+ {
204
+ signed_int result = 0;
205
+ if( !convert( value.begin(), value.end(), result ) )
206
+ throw FieldConvertError(value);
207
+ else
208
+ return result;
209
+ }
210
+
211
+ /// Converts only positive number e.g. FIX field ID: [1 ... 2147483647]
212
+ /// No leading whitespace/zero/plus/sign symbols allowed
213
+ /// Value is fixed to not make difference between 32bit and 64bit code
214
+ static bool convertPositive(
215
+ std::string::const_iterator str,
216
+ std::string::const_iterator end,
217
+ signed_int& result )
218
+ {
219
+ const int MAX_VALUE = 2147483647; // max value for 32-bit signed integer
220
+ const int HIGH_MARK = MAX_VALUE / 10;
221
+ const unsigned_int STOP_SYMBOL = MAX_VALUE % 10;
222
+ const std::size_t MAX_DIGITS = 10; // integer can hold up to 10 digits
223
+
224
+ const std::size_t length = std::distance( str, end );
225
+ if( length < 1 || length > MAX_DIGITS)
226
+ return false;
227
+
228
+ if( length == MAX_DIGITS )
229
+ {
230
+ end = str;
231
+ std::advance( end, length - 1 );
232
+ }
233
+
234
+ const unsigned_int ch = *str - '1';
235
+ if( ch > 8 )
236
+ return false;
237
+
238
+ unsigned_int x = 0;
239
+
240
+ do
241
+ {
242
+ const unsigned_int c = *str - '0';
243
+ if( c > 9 ) return false;
244
+ x = 10 * x + c;
245
+ } while( ++str < end );
246
+
247
+ // complete overflow condition check and value calculation
248
+ // this saves about 25% of speed when executed out of the main loop
249
+ if( length == MAX_DIGITS )
250
+ {
251
+ if( x > (unsigned int)HIGH_MARK )
252
+ return false;
253
+
254
+ const unsigned_int c = *str - '0';
255
+ if( x == (unsigned int)HIGH_MARK && c > STOP_SYMBOL )
256
+ return false;
257
+
258
+ x = 10 * x + c;
259
+ }
260
+
261
+ result = x;
262
+ return true;
263
+ }
264
+
265
+ static signed_int convertPositive( const std::string& value )
266
+ throw( FieldConvertError )
267
+ {
268
+ signed_int result = 0;
269
+ if( !convertPositive( value.begin(), value.end(), result ) )
270
+ throw FieldConvertError(value);
271
+ else
272
+ return result;
273
+ }
274
+ };
275
+
276
+ /// Converts checksum to/from a string
277
+ struct CheckSumConvertor
278
+ {
279
+ static std::string convert( int value )
280
+ throw( FieldConvertError )
281
+ {
282
+ if ( value > 255 || value < 0 ) throw FieldConvertError();
283
+ char result[4];
284
+ if( integer_to_string_padded(result, sizeof(result), value, 3) != result )
285
+ {
286
+ throw FieldConvertError();
287
+ }
288
+ return std::string( result, 3 );
289
+ }
290
+
291
+ static bool convert( const std::string& value, int& result )
292
+ {
293
+ return IntConvertor::convert( value, result );
294
+ }
295
+
296
+ static int convert( const std::string& value )
297
+ throw( FieldConvertError )
298
+ {
299
+ return IntConvertor::convert( value );
300
+ }
301
+ };
302
+
303
+ /// Converts double to/from a string
304
+ struct DoubleConvertor
305
+ {
306
+
307
+ private:
308
+
309
+ /*Simple and fast atof (ascii to float) function.
310
+ Executes about 5x faster than standard MSCRT library atof().
311
+ An attractive alternative if the number of calls is in the millions.
312
+ Assumes input is a proper integer, fraction, or scientific format.
313
+ Matches library atof() to 15 digits (except at extreme exponents).
314
+ Follows atof() precedent of essentially no error checking.
315
+ 09-May-2009 Tom Van Baak (tvb) www.LeapSecond.com */
316
+ static double fast_atof (const char *p)
317
+ {
318
+ bool frac(false);
319
+ double sign(1.), value(0.), scale(1.);
320
+
321
+ while (IS_SPACE(*p))
322
+ ++p;
323
+
324
+ // Get sign, if any.
325
+ if (*p == '-')
326
+ {
327
+ sign = -1.;
328
+ ++p;
329
+ }
330
+ else if (*p == '+')
331
+ ++p;
332
+
333
+ // Get digits before decimal point or exponent, if any.
334
+ while (IS_DIGIT(*p))
335
+ {
336
+ value = value * 10. + (*p - '0');
337
+ ++p;
338
+ }
339
+
340
+ // Get digits after decimal point, if any.
341
+ if (*p == '.')
342
+ {
343
+ ++p;
344
+ double pow10(10.);
345
+ while (IS_DIGIT(*p))
346
+ {
347
+ value += (*p - '0') / pow10;
348
+ pow10 *= 10.;
349
+ ++p;
350
+ }
351
+ }
352
+
353
+ // Handle exponent, if any.
354
+ if (toupper(*p) == 'E')
355
+ {
356
+ unsigned int expon(0);
357
+ ++p;
358
+
359
+ // Get sign of exponent, if any.
360
+ if (*p == '-')
361
+ {
362
+ frac = true;
363
+ ++p;
364
+ }
365
+ else if (*p == '+')
366
+ ++p;
367
+
368
+ // Get digits of exponent, if any.
369
+ while (IS_DIGIT(*p))
370
+ {
371
+ expon = expon * 10 + (*p - '0');
372
+ ++p;
373
+ }
374
+ if (expon > 308)
375
+ expon = 308;
376
+
377
+ // Calculate scaling factor.
378
+ while (expon >= 50)
379
+ {
380
+ scale *= 1E50;
381
+ expon -= 50;
382
+ }
383
+ while (expon >= 8)
384
+ {
385
+ scale *= 1E8;
386
+ expon -= 8;
387
+ }
388
+ while (expon > 0)
389
+ {
390
+ scale *= 10.0;
391
+ expon -= 1;
392
+ }
393
+ }
394
+
395
+ // Return signed and scaled floating point result.
396
+ return sign * (frac ? (value / scale) : (value * scale));
397
+ }
398
+
399
+ public:
400
+
401
+ static std::string convert( double value, int padding = 0 )
402
+ {
403
+ char result[32];
404
+ char *end = 0;
405
+
406
+ int size;
407
+ if( value == 0 || value > 0.0001 || value <= -0.0001 )
408
+ {
409
+ size = STRING_SPRINTF( result, "%.15g", value );
410
+
411
+ if( padding > 0 )
412
+ {
413
+ char* point = result;
414
+ end = result + size - 1;
415
+ while( *point != '.' && *point != 0 )
416
+ point++;
417
+
418
+ if( *point == 0 )
419
+ {
420
+ end = point;
421
+ *point = '.';
422
+ size++;
423
+ }
424
+ int needed = padding - (int)(end - point);
425
+
426
+ while( needed-- > 0 )
427
+ {
428
+ *(++end) = '0';
429
+ size++;
430
+ }
431
+ *(end+1) = 0;
432
+ }
433
+ }
434
+ else
435
+ {
436
+ size = STRING_SPRINTF( result, "%.15f", value );
437
+ // strip trailing 0's
438
+ end = result + size - 1;
439
+
440
+ if( padding > 0 )
441
+ {
442
+ int discard = 15 - padding;
443
+
444
+ while( (*end == '0') && (discard-- > 0) )
445
+ {
446
+ *(end--) = 0;
447
+ size--;
448
+ }
449
+ }
450
+ else
451
+ {
452
+ while( *end == '0' )
453
+ {
454
+ *(end--) = 0;
455
+ size--;
456
+ }
457
+ }
458
+ }
459
+
460
+ return std::string( result, size );
461
+ }
462
+
463
+ static bool convert( const std::string& value, double& result )
464
+ {
465
+ const char * i = value.c_str();
466
+
467
+ // Catch null strings
468
+ if( !*i ) return false;
469
+ // Eat leading '-' and recheck for null string
470
+ if( *i == '-' && !*++i ) return false;
471
+
472
+ bool haveDigit = false;
473
+
474
+ if( IS_DIGIT(*i) )
475
+ {
476
+ haveDigit = true;
477
+ while( IS_DIGIT (*++i) );
478
+ }
479
+
480
+ if( *i == '.' && IS_DIGIT(*++i) )
481
+ {
482
+ haveDigit = true;
483
+ while( IS_DIGIT (*++i) );
484
+ }
485
+
486
+ if( *i || !haveDigit ) return false;
487
+
488
+ result = fast_atof( value.c_str() );
489
+ return true;
490
+ }
491
+
492
+ static double convert( const std::string& value )
493
+ throw( FieldConvertError )
494
+ {
495
+ double result = 0.0;
496
+ if( !convert( value, result ) )
497
+ throw FieldConvertError(value);
498
+ else
499
+ return result;
500
+ }
501
+ };
502
+
503
+ /// Converts character to/from a string
504
+ struct CharConvertor
505
+ {
506
+ static std::string convert( char value )
507
+ {
508
+ if( value == '\0' ) return "";
509
+ return std::string( 1, value );
510
+ }
511
+
512
+ static bool convert( const std::string& value, char& result )
513
+ {
514
+ if( value.size() != 1 ) return false;
515
+ result = value[0];
516
+ return true;
517
+ }
518
+
519
+ static char convert( const std::string& value )
520
+ throw( FieldConvertError )
521
+ {
522
+ char result = '\0';
523
+ if( !convert( value, result ) )
524
+ throw FieldConvertError(value);
525
+ else
526
+ return result;
527
+ }
528
+ };
529
+
530
+ /// Converts boolean to/from a string
531
+ struct BoolConvertor
532
+ {
533
+ static std::string convert( bool value )
534
+ {
535
+ const char ch = value ? 'Y' : 'N';
536
+ return std::string( 1, ch );
537
+ }
538
+
539
+ static bool convert( const std::string& value, bool& result )
540
+ {
541
+ if( value.size() != 1 ) return false;
542
+ switch( value[0] )
543
+ {
544
+ case 'Y': result = true; break;
545
+ case 'N': result = false; break;
546
+ default: return false;
547
+ }
548
+
549
+ return true;
550
+ }
551
+
552
+ static bool convert( const std::string& value )
553
+ throw( FieldConvertError )
554
+ {
555
+ bool result = false;
556
+ if( !convert( value, result ) )
557
+ throw FieldConvertError(value);
558
+ else
559
+ return result;
560
+ }
561
+ };
562
+
563
+ /// Converts a UtcTimeStamp to/from a string
564
+ struct UtcTimeStampConvertor
565
+ {
566
+ static std::string convert( const UtcTimeStamp& value,
567
+ bool showMilliseconds = false )
568
+ throw( FieldConvertError )
569
+ {
570
+ char result[ 18+4 ];
571
+ int year, month, day, hour, minute, second, millis;
572
+
573
+ value.getYMD( year, month, day );
574
+ value.getHMS( hour, minute, second, millis );
575
+
576
+ integer_to_string_padded( result, 5, year, 4 );
577
+ integer_to_string_padded( result + 4, 3, month, 2 );
578
+ integer_to_string_padded( result + 6, 3, day, 2 );
579
+ result[8] = '-';
580
+ integer_to_string_padded( result + 9, 3, hour, 2 );
581
+ result[11] = ':';
582
+ integer_to_string_padded( result + 12, 3, minute, 2 );
583
+ result[14] = ':';
584
+ integer_to_string_padded( result + 15, 3, second, 2 );
585
+
586
+ if( showMilliseconds )
587
+ {
588
+ result[17] = '.';
589
+ if( integer_to_string_padded ( result + 18, 4, millis, 3 )
590
+ != result + 18 )
591
+ {
592
+ throw FieldConvertError();
593
+ }
594
+ }
595
+
596
+ return result;
597
+ }
598
+
599
+ static UtcTimeStamp convert( const std::string& value,
600
+ bool calculateDays = false )
601
+ throw( FieldConvertError )
602
+ {
603
+ bool haveMilliseconds = false;
604
+
605
+ switch( value.size() )
606
+ {
607
+ case 21: haveMilliseconds = true;
608
+ case 17: break;
609
+ default: throw FieldConvertError(value);
610
+ }
611
+
612
+ int i = 0;
613
+ int c = 0;
614
+ for( c = 0; c < 8; ++c )
615
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
616
+ if (value[i++] != '-') throw FieldConvertError(value);
617
+ for( c = 0; c < 2; ++c )
618
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
619
+ if( value[i++] != ':' ) throw FieldConvertError(value);
620
+ for( c = 0; c < 2; ++c )
621
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
622
+ if( value[i++] != ':' ) throw FieldConvertError(value);
623
+ for( c = 0; c < 2; ++c )
624
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
625
+
626
+ if( haveMilliseconds )
627
+ {
628
+ if( value[i++] != '.' ) throw FieldConvertError(value);
629
+ for( c = 0; c < 3; ++c )
630
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
631
+ }
632
+
633
+ int year, mon, mday, hour, min, sec, millis;
634
+
635
+ i = 0;
636
+
637
+ year = value[i++] - '0';
638
+ year = 10 * year + value[i++] - '0';
639
+ year = 10 * year + value[i++] - '0';
640
+ year = 10 * year + value[i++] - '0';
641
+
642
+ mon = value[i++] - '0';
643
+ mon = 10 * mon + value[i++] - '0';
644
+ if( mon < 1 || 12 < mon ) throw FieldConvertError(value);
645
+
646
+ mday = value[i++] - '0';
647
+ mday = 10 * mday + value[i++] - '0';
648
+ if( mday < 1 || 31 < mday ) throw FieldConvertError(value);
649
+
650
+ ++i; // skip '-'
651
+
652
+ hour = value[i++] - '0';
653
+ hour = 10 * hour + value[i++] - '0';
654
+ // No check for >= 0 as no '-' are converted here
655
+ if( 23 < hour ) throw FieldConvertError(value);
656
+
657
+ ++i; // skip ':'
658
+
659
+ min = value[i++] - '0';
660
+ min = 10 * min + value[i++] - '0';
661
+ // No check for >= 0 as no '-' are converted here
662
+ if( 59 < min ) throw FieldConvertError(value);
663
+
664
+ ++i; // skip ':'
665
+
666
+ sec = value[i++] - '0';
667
+ sec = 10 * sec + value[i++] - '0';
668
+
669
+ // No check for >= 0 as no '-' are converted here
670
+ if( 60 < sec ) throw FieldConvertError(value);
671
+
672
+ if( haveMilliseconds )
673
+ {
674
+ millis = (100 * (value[i+1] - '0')
675
+ + 10 * (value[i+2] - '0')
676
+ + (value[i+3] - '0'));
677
+ }
678
+ else
679
+ millis = 0;
680
+
681
+ return UtcTimeStamp (hour, min, sec, millis,
682
+ mday, mon, year);
683
+ }
684
+ };
685
+
686
+ /// Converts a UtcTimeOnly to/from a string
687
+ struct UtcTimeOnlyConvertor
688
+ {
689
+ static std::string convert( const UtcTimeOnly& value,
690
+ bool showMilliseconds = false)
691
+ throw( FieldConvertError )
692
+ {
693
+ char result[ 9+4 ];
694
+ int hour, minute, second, millis;
695
+
696
+ value.getHMS( hour, minute, second, millis );
697
+
698
+ integer_to_string_padded ( result, 3, hour, 2 );
699
+ result[2] = ':';
700
+ integer_to_string_padded ( result + 3, 3, minute, 2 );
701
+ result[5] = ':';
702
+ integer_to_string_padded ( result + 6, 3, second, 2 );
703
+
704
+ if( showMilliseconds )
705
+ {
706
+ result[8] = '.';
707
+ if( integer_to_string_padded ( result + 9, 4, millis, 3 )
708
+ != result + 9 )
709
+ throw FieldConvertError();
710
+ }
711
+
712
+ return result;
713
+ }
714
+
715
+ static UtcTimeOnly convert( const std::string& value )
716
+ throw( FieldConvertError )
717
+ {
718
+ bool haveMilliseconds = false;
719
+
720
+ switch( value.size() )
721
+ {
722
+ case 12: haveMilliseconds = true;
723
+ case 8: break;
724
+ default: throw FieldConvertError(value);
725
+ }
726
+
727
+ int i = 0;
728
+ int c = 0;
729
+ for( c = 0; c < 2; ++c )
730
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
731
+ if( value[i++] != ':' ) throw FieldConvertError(value);
732
+ for( c = 0; c < 2; ++c )
733
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
734
+ if( value[i++] != ':' ) throw FieldConvertError(value);
735
+ for( c = 0; c < 2; ++c )
736
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
737
+
738
+ if( haveMilliseconds )
739
+ {
740
+ // ++i instead of i++ skips the '.' separator
741
+ for( c = 0; c < 3; ++c )
742
+ if( !IS_DIGIT(value[++i]) ) throw FieldConvertError(value);
743
+ }
744
+
745
+ int hour, min, sec, millis;
746
+
747
+ i = 0;
748
+
749
+ hour = value[i++] - '0';
750
+ hour = 10 * hour + value[i++] - '0';
751
+ // No check for >= 0 as no '-' are converted here
752
+ if( 23 < hour ) throw FieldConvertError(value);
753
+ ++i; // skip ':'
754
+
755
+ min = value[i++] - '0';
756
+ min = 10 * min + value[i++] - '0';
757
+ // No check for >= 0 as no '-' are converted here
758
+ if( 59 < min ) throw FieldConvertError(value);
759
+ ++i; // skip ':'
760
+
761
+ sec = value[i++] - '0';
762
+ sec = 10 * sec + value[i++] - '0';
763
+ // No check for >= 0 as no '-' are converted here
764
+ if( 60 < sec ) throw FieldConvertError(value);
765
+
766
+ if( haveMilliseconds )
767
+ {
768
+ millis = (100 * (value[i+1] - '0')
769
+ + 10 * (value[i+2] - '0')
770
+ + (value[i+3] - '0'));
771
+ }
772
+ else
773
+ millis = 0;
774
+
775
+ return UtcTimeOnly( hour, min, sec, millis );
776
+ }
777
+ };
778
+
779
+ /// Converts a UtcDate to/from a string
780
+ struct UtcDateConvertor
781
+ {
782
+ static std::string convert( const UtcDate& value )
783
+ throw( FieldConvertError )
784
+ {
785
+ char result[ 9 ];
786
+ int year, month, day;
787
+
788
+ value.getYMD( year, month, day );
789
+
790
+ integer_to_string_padded( result, 5, year, 4 );
791
+ integer_to_string_padded( result + 4, 3, month, 2 );
792
+ integer_to_string_padded( result + 6, 3, day, 2 );
793
+ return result;
794
+ }
795
+
796
+ static UtcDate convert( const std::string& value )
797
+ throw( FieldConvertError )
798
+ {
799
+ if( value.size() != 8 ) throw FieldConvertError(value);
800
+
801
+ int i = 0;
802
+ for( int c=0; c<8; ++c )
803
+ if( !IS_DIGIT(value[i++]) ) throw FieldConvertError(value);
804
+
805
+ int year, mon, mday;
806
+
807
+ i = 0;
808
+
809
+ year = value[i++] - '0';
810
+ year = 10 * year + value[i++] - '0';
811
+ year = 10 * year + value[i++] - '0';
812
+ year = 10 * year + value[i++] - '0';
813
+
814
+ mon = value[i++] - '0';
815
+ mon = 10 * mon + value[i++] - '0';
816
+ if( mon < 1 || 12 < mon )
817
+ throw FieldConvertError(value);
818
+
819
+ mday = value[i++] - '0';
820
+ mday = 10 * mday + value[i++] - '0';
821
+ if( mday < 1 || 31 < mday )
822
+ throw FieldConvertError(value);
823
+
824
+ return UtcDateOnly( mday, mon, year );
825
+ }
826
+ };
827
+
828
+ typedef UtcDateConvertor UtcDateOnlyConvertor;
829
+
830
+ typedef StringConvertor STRING_CONVERTOR;
831
+ typedef CharConvertor CHAR_CONVERTOR;
832
+ typedef DoubleConvertor PRICE_CONVERTOR;
833
+ typedef IntConvertor INT_CONVERTOR;
834
+ typedef DoubleConvertor AMT_CONVERTOR;
835
+ typedef DoubleConvertor QTY_CONVERTOR;
836
+ typedef StringConvertor CURRENCY_CONVERTOR;
837
+ typedef StringConvertor MULTIPLEVALUESTRING_CONVERTOR;
838
+ typedef StringConvertor MULTIPLESTRINGVALUE_CONVERTOR;
839
+ typedef StringConvertor MULTIPLECHARVALUE_CONVERTOR;
840
+ typedef StringConvertor EXCHANGE_CONVERTOR;
841
+ typedef UtcTimeStampConvertor UTCTIMESTAMP_CONVERTOR;
842
+ typedef BoolConvertor BOOLEAN_CONVERTOR;
843
+ typedef StringConvertor LOCALMKTDATE_CONVERTOR;
844
+ typedef StringConvertor DATA_CONVERTOR;
845
+ typedef DoubleConvertor FLOAT_CONVERTOR;
846
+ typedef DoubleConvertor PRICEOFFSET_CONVERTOR;
847
+ typedef StringConvertor MONTHYEAR_CONVERTOR;
848
+ typedef StringConvertor DAYOFMONTH_CONVERTOR;
849
+ typedef UtcDateConvertor UTCDATE_CONVERTOR;
850
+ typedef UtcTimeOnlyConvertor UTCTIMEONLY_CONVERTOR;
851
+ typedef IntConvertor NUMINGROUP_CONVERTOR;
852
+ typedef DoubleConvertor PERCENTAGE_CONVERTOR;
853
+ typedef IntConvertor SEQNUM_CONVERTOR;
854
+ typedef IntConvertor LENGTH_CONVERTOR;
855
+ typedef StringConvertor COUNTRY_CONVERTOR;
856
+ typedef StringConvertor TZTIMEONLY_CONVERTOR;
857
+ typedef StringConvertor TZTIMESTAMP_CONVERTOR;
858
+ typedef StringConvertor XMLDATA_CONVERTOR;
859
+ typedef StringConvertor LANGUAGE_CONVERTOR;
860
+ typedef CheckSumConvertor CHECKSUM_CONVERTOR;
861
+ }
862
+
863
+ #endif //FIX_FIELDCONVERTORS_H