00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00047 #ifndef FASTFORMAT_INCL_FASTFORMAT_INSERTERS_HPP_INTEGER
00048 #define FASTFORMAT_INCL_FASTFORMAT_INSERTERS_HPP_INTEGER
00049
00050
00051
00052
00053
00054 #ifndef FASTFORMAT_DOCUMENTATION_SKIP_SECTION
00055 # define FASTFORMAT_VER_FASTFORMAT_INSERTERS_HPP_INTEGER_MAJOR 1
00056 # define FASTFORMAT_VER_FASTFORMAT_INSERTERS_HPP_INTEGER_MINOR 1
00057 # define FASTFORMAT_VER_FASTFORMAT_INSERTERS_HPP_INTEGER_REVISION 2
00058 # define FASTFORMAT_VER_FASTFORMAT_INSERTERS_HPP_INTEGER_EDIT 7
00059 #endif
00060
00061
00062
00063
00064
00065 #include <fastformat/fastformat.h>
00066 #include <fastformat/quality/contract.h>
00067 #include <fastformat/util/string/snprintf.h>
00068
00069 #include <stlsoft/conversion/integer_to_string.hpp>
00070 #include <stlsoft/meta/is_integral_type.hpp>
00071 #include <stlsoft/string/case_functions.hpp>
00072 #include <stlsoft/string/ctype_traits.hpp>
00073 #include <stlsoft/string/shim_string.hpp>
00074 #include <stlsoft/shims/access/string/std/c_string.h>
00075 #include <stlsoft/util/limit_traits.h>
00076 #include <stlsoft/util/integral_printf_traits.hpp>
00077
00078 #include <ctype.h>
00079 #include <stdlib.h>
00080
00081
00082
00083
00084
00085 #if defined(STLSOFT_COMPILER_IS_MSVC) && \
00086 _MSC_VER < 1300
00087
00088
00089
00090
00091 # define FASTFORMAT_INSERTER_INTEGER_NO_USE_SHIM_STRING_
00092 # include <stlsoft/string/simple_string.hpp>
00093 #endif
00094
00095
00096
00097
00098
00099 #if !defined(FASTFORMAT_NO_NAMESPACE)
00100 namespace fastformat
00101 {
00102 namespace inserters
00103 {
00104 #endif
00105
00106
00107
00108
00109
00110 #ifndef FASTFORMAT_DOCUMENTATION_SKIP_SECTION
00111 namespace integer_impl
00112 {
00113
00114 # ifdef FASTFORMAT_INSERTER_INTEGER_NO_USE_SHIM_STRING_
00115 typedef stlsoft::basic_simple_string<ff_char_t> ff_to_i_r_t_;
00116 # else
00117 typedef stlsoft::basic_shim_string<ff_char_t, 20> ff_to_i_r_t_;
00118 # endif
00119
00120 inline int default_width_sentinel_()
00121 {
00122 return stlsoft::limit_traits<int>::minimum();
00123 }
00124
00125 inline int default_precision_sentinel_()
00126 {
00127 return -1;
00128 }
00129
00130 inline ff_char_t* make_x_upper_(ff_char_t* from, ff_char_t* to)
00131 {
00132 for(; to != from; ++from)
00133 {
00134 if('x' == *from)
00135 {
00136 *from = 'X';
00137 break;
00138 }
00139 }
00140
00141 return from;
00142 }
00143
00144 template <typename I>
00145 inline ff_to_i_r_t_ integer_helper_2(
00146 I const& value
00147 , ff_char_t const* fmt
00148 )
00149 {
00150 STLSOFT_STATIC_ASSERT(stlsoft::is_integral_type<I>::value);
00151
00152 FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(NULL != fmt, "fmt may not be null");
00153
00154 typedef ff_to_i_r_t_ result_t;
00155
00156 enum { maxRepeats = 3 };
00157
00158 #ifdef FASTFORMAT_INSERTER_INTEGER_NO_USE_SHIM_STRING_
00159
00160 result_t result(20u, '~');
00161
00162 { for(int i = 0;; )
00163 {
00164 int n = fastformat_util_snprintf(&result[0], result.size(), fmt, value);
00165
00166 if(n > int(result.size()))
00167 {
00168
00169
00170
00171
00172
00173
00174 result.resize(n);
00175 }
00176 else if(n < 0)
00177 {
00178 if(maxRepeats == ++i)
00179 {
00180 result.clear();
00181 break;
00182 }
00183 else
00184 {
00185
00186
00187
00188 result.resize(1u + result.size() * 3);
00189 }
00190 }
00191 else
00192 {
00193
00194
00195
00196
00197 result.resize(size_t(n));
00198
00199 break;
00200 }
00201 }}
00202
00203 return result;
00204
00205 #else
00206
00207
00208 # if _STLSOFT_VER < 0x010a0000 && \
00209 defined(_STLSOFT_1_10_VER) && \
00210 _STLSOFT_1_10_VER < 0x010a0109
00211
00212
00213
00214 # error This class cannot work with STLSoft 1.10 versions between 1.10.1 alpha 1 and 1.10.1 alpha 9. Please download the latest version of STLSoft 1.10 alpha
00215
00216 # elif _STLSOFT_VER >= 0x010a0000 || \
00217 defined(_STLSOFT_1_10_VER)
00218
00219
00220
00221
00222
00223 result_t result(64);
00224
00225 # ifndef STLSOFT_CF_THROW_BAD_ALLOC
00226 if(!result.empty())
00227 # endif
00228 {
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 { for(int i = 0;; )
00239 {
00240 int n = fastformat_util_snprintf(result.data(), result.size() - 1, fmt, value);
00241
00242 if(n > int(result.size()))
00243 {
00244
00245
00246
00247
00248
00249
00250 if(!result.resize(n))
00251 {
00252 result.truncate(0);
00253 break;
00254 }
00255 }
00256 else if(n < 0)
00257 {
00258 if(maxRepeats == ++i)
00259 {
00260 result.truncate(0);
00261 break;
00262 }
00263 else
00264 {
00265
00266
00267
00268 if(!result.resize(1u + result.size() * 3))
00269 {
00270 result.truncate(0);
00271 break;
00272 }
00273 }
00274 }
00275 else
00276 {
00277
00278
00279
00280
00281 result.truncate(size_t(n));
00282
00283 break;
00284 }
00285 }}
00286 }
00287
00288 return result;
00289
00290 # else
00291
00292
00293
00294
00295
00296
00297
00298 result_t result(64);
00299 result_t::buffer_type& buffer = result.get_buffer();
00300
00301 # ifndef STLSOFT_CF_THROW_BAD_ALLOC
00302 if(!buffer.empty())
00303 # endif
00304 {
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314 { for(int i = 0;; )
00315 {
00316 int n = fastformat_util_snprintf(&buffer[0], buffer.size() - 1, fmt, value);
00317
00318 if(n > int(buffer.size() - 1))
00319 {
00320
00321
00322
00323
00324
00325
00326 if(!buffer.resize(size_t(n) + 1u))
00327 {
00328 buffer.resize(1u);
00329 break;
00330 }
00331 }
00332 else if(n < 0)
00333 {
00334 if(maxRepeats == ++i)
00335 {
00336 break;
00337 }
00338 else
00339 {
00340
00341
00342
00343 if(!buffer.resize(1u + buffer.size() * 3))
00344 {
00345 buffer.resize(1u);
00346 break;
00347 }
00348 }
00349 }
00350 else
00351 {
00352
00353
00354
00355
00356 buffer[size_t(n)] = '\0';
00357
00358 buffer.resize(size_t(n) + 1u);
00359
00360 break;
00361 }
00362 }}
00363 }
00364
00365 return result;
00366 # endif
00367 #endif
00368 }
00369
00370 inline ff_to_i_r_t_ hex_integer_helper(
00371 stlsoft::uint64_t value
00372 , int uppercaseAlpha
00373 )
00374 {
00375 ff_char_t result[17];
00376 int n = fastformat_util_snprintf(
00377 &result[0]
00378 , STLSOFT_NUM_ELEMENTS(result)
00379 #ifdef FASTFORMAT_USE_WIDE_STRINGS
00380 , stlsoft::integral_printf_traits<stlsoft::uint64_t>::hex_format_w()
00381 #else
00382 , stlsoft::integral_printf_traits<stlsoft::uint64_t>::hex_format_a()
00383 #endif
00384 , value);
00385
00386 if(uppercaseAlpha)
00387 {
00388 typedef stlsoft::ctype_traits<ff_char_t> ctype_traits_t;
00389
00390 stlsoft::std_transform(result, result + n, result, ctype_traits_t::to_upper);
00391 }
00392
00393 return ff_to_i_r_t_(result, size_t(n));
00394 }
00395
00396 inline ff_to_i_r_t_ hex_integer_helper(
00397 stlsoft::sint64_t value
00398 , int uppercaseAlpha
00399 )
00400 {
00401 return hex_integer_helper(static_cast<stlsoft::uint64_t>(value), uppercaseAlpha);
00402 }
00403
00404 template <typename I>
00405 inline ff_to_i_r_t_ hex_integer_helper(
00406 I const& value
00407 , int uppercaseAlpha
00408 )
00409 {
00410 ff_char_t fmt[3] = { '%', uppercaseAlpha ? 'X' : 'x', '\0' };
00411 ff_char_t result[17];
00412 int n = fastformat_util_snprintf(&result[0], STLSOFT_NUM_ELEMENTS(result), fmt, value);
00413
00414 return ff_to_i_r_t_(result, size_t(n));
00415 }
00416
00417 template <typename I>
00418 inline ff_to_i_r_t_ integer_helper_5(
00419 I const& value
00420 , int minimumWidth
00421 , int precision
00422 , int base
00423 , int uppercaseAlpha
00424 )
00425 {
00426 STLSOFT_STATIC_ASSERT(stlsoft::is_integral_type<I>::value);
00427
00428 FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_INTERNAL(10 == base || 16 == base, "base must be 10 (decimal) or 16 (hex)");
00429
00430 if( default_width_sentinel_() == minimumWidth &&
00431 precision < 0)
00432 {
00433
00434
00435 if(10 == base)
00436 {
00437 ff_char_t sz[21];
00438 size_t n;
00439 ff_char_t const* s = stlsoft::integer_to_string(&sz[0], STLSOFT_NUM_ELEMENTS(sz), value, n);
00440
00441 return ff_to_i_r_t_(s, n);
00442 }
00443 else
00444 {
00445 FASTFORMAT_CONTRACT_ENFORCE_ASSUMPTION(16 == base);
00446
00447 return hex_integer_helper(value, uppercaseAlpha);
00448 }
00449 }
00450 else
00451 {
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 ff_char_t fmt_[101];
00468 ff_char_t* fmt = fmt_;
00469 ff_char_t const* type;
00470 size_t typeLen;
00471
00472 if(10 == base)
00473 {
00474 #ifdef FASTFORMAT_USE_WIDE_STRINGS
00475 type = stlsoft::integral_printf_traits<I>::format_w() + 1;
00476 #else
00477 type = stlsoft::integral_printf_traits<I>::format_a() + 1;
00478 #endif
00479 typeLen = stlsoft::c_str_len(type);
00480 }
00481 else
00482 {
00483 FASTFORMAT_CONTRACT_ENFORCE_ASSUMPTION(16 == base);
00484
00485 #ifdef FASTFORMAT_USE_WIDE_STRINGS
00486 type = stlsoft::integral_printf_traits<I>::hex_format_w() + 1;
00487 #else
00488 type = stlsoft::integral_printf_traits<I>::hex_format_a() + 1;
00489 #endif
00490 typeLen = stlsoft::c_str_len(type);
00491 }
00492
00493 if(default_width_sentinel_() == minimumWidth)
00494 {
00495 minimumWidth = 0;
00496 }
00497 if(precision < 0)
00498 {
00499 precision = (0 == value) ? 1 : 0;
00500 }
00501
00502 const size_t fmtDim = STLSOFT_NUM_ELEMENTS(fmt_) - 1;
00503 ff_char_t* end = &fmt[fmtDim];
00504 size_t n1;
00505 size_t n2;
00506
00507
00508
00509
00510
00511 stlsoft::integer_to_string(end - (21 + typeLen), 21, precision, n1);
00512
00513
00514 ::memcpy(end - (typeLen + 1), type, sizeof(ff_char_t) * typeLen);
00515 if(uppercaseAlpha)
00516 {
00517
00518 make_x_upper_(end - (typeLen + 1), end - (typeLen + 1) + typeLen);
00519 }
00520
00521
00522 *--end = '\0';
00523
00524 end -= typeLen;
00525 end -= n1;
00526
00527
00528 stlsoft::integer_to_string(end - 21, 21, minimumWidth, n2);
00529
00530
00531 *--end = '.';
00532
00533 end -= n2;
00534
00535
00536 *--end = '%';
00537 fmt = end;
00538
00539 return integer_helper_2(value, fmt);
00540 }
00541 }
00542
00543 template <typename I>
00544 inline ff_to_i_r_t_ integer_helper_3(
00545 I const& value
00546 , int minimumWidth
00547 , int precision
00548 )
00549 {
00550 return integer_helper_5(value, minimumWidth, precision, 10, false);
00551 }
00552
00553 template <typename I>
00554 inline ff_to_i_r_t_ integer_helper_hex_3(
00555 I const& value
00556 , int minimumWidth
00557 , int precision
00558 , int uppercaseX
00559 )
00560 {
00561 return integer_helper_5(value, minimumWidth, precision, 16, uppercaseX);
00562 }
00563
00564 }
00565 #endif
00566
00567
00568
00569
00570
00585 template <typename I>
00586 inline integer_impl::ff_to_i_r_t_ integer(
00587 I const& value
00588 , int minimumWidth
00589 , int precision
00590 )
00591 {
00592 STLSOFT_STATIC_ASSERT(stlsoft::is_integral_type<I>::value);
00593
00594 FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_APPL_LAYER(abs(minimumWidth) < 512, "maximum value for width exceeded");
00595 FASTFORMAT_CONTRACT_ENFORCE_PRECONDITION_PARAMS_APPL_LAYER(abs(minimumWidth) < 1 || precision <= abs(minimumWidth), "decimal places must not exceed width");
00596
00597 return integer_impl::integer_helper_3(value, minimumWidth, precision);
00598 }
00599
00600
00601
00602
00603
00604 #if !defined(FASTFORMAT_NO_NAMESPACE)
00605 }
00606 using ::fastformat::inserters::integer;
00607 }
00608 #endif
00609
00610
00611
00612
00613
00614 #ifdef STLSOFT_PPF_pragma_once_SUPPORT
00615 # pragma once
00616 #endif
00617
00618
00619
00620 #endif
00621
00622