00001 #include <iostream>
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
00042
00043
00044
00045
00046
00047 #include "util/integer_to_string.hh"
00048 #include <cassert>
00049 #include <stdint.h>
00050
00051 namespace util {
00052
00053 namespace {
00054 const char gDigitsLut[200] = {
00055 '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
00056 '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
00057 '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
00058 '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
00059 '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
00060 '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
00061 '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
00062 '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
00063 '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
00064 '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
00065 };
00066 }
00067
00068
00069
00070
00071 #if defined(__amd64) || defined(_M_X64) || (defined(__SSE2__) && (defined(_M_IX86) || defined(i386)))
00072
00073 #include <emmintrin.h>
00074
00075 #ifdef _MSC_VER
00076 #include "intrin.h"
00077 #endif
00078
00079 #ifdef _MSC_VER
00080 #define ALIGN_PRE __declspec(align(16))
00081 #define ALIGN_SUF
00082 #else
00083 #define ALIGN_PRE
00084 #define ALIGN_SUF __attribute__ ((aligned(16)))
00085 #endif
00086
00087 namespace {
00088
00089 static const uint32_t kDiv10000 = 0xd1b71759;
00090 ALIGN_PRE static const uint32_t kDiv10000Vector[4] ALIGN_SUF = { kDiv10000, kDiv10000, kDiv10000, kDiv10000 };
00091 ALIGN_PRE static const uint32_t k10000Vector[4] ALIGN_SUF = { 10000, 10000, 10000, 10000 };
00092 ALIGN_PRE static const uint16_t kDivPowersVector[8] ALIGN_SUF = { 8389, 5243, 13108, 32768, 8389, 5243, 13108, 32768 };
00093 ALIGN_PRE static const uint16_t kShiftPowersVector[8] ALIGN_SUF = {
00094 1 << (16 - (23 + 2 - 16)),
00095 1 << (16 - (19 + 2 - 16)),
00096 1 << (16 - 1 - 2),
00097 1 << (15),
00098 1 << (16 - (23 + 2 - 16)),
00099 1 << (16 - (19 + 2 - 16)),
00100 1 << (16 - 1 - 2),
00101 1 << (15)
00102 };
00103 ALIGN_PRE static const uint16_t k10Vector[8] ALIGN_SUF = { 10, 10, 10, 10, 10, 10, 10, 10 };
00104 ALIGN_PRE static const char kAsciiZero[16] ALIGN_SUF = { '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0' };
00105
00106 inline __m128i Convert8DigitsSSE2(uint32_t value) {
00107 assert(value <= 99999999);
00108
00109
00110 const __m128i abcdefgh = _mm_cvtsi32_si128(value);
00111 const __m128i abcd = _mm_srli_epi64(_mm_mul_epu32(abcdefgh, reinterpret_cast<const __m128i*>(kDiv10000Vector)[0]), 45);
00112 const __m128i efgh = _mm_sub_epi32(abcdefgh, _mm_mul_epu32(abcd, reinterpret_cast<const __m128i*>(k10000Vector)[0]));
00113
00114
00115 const __m128i v1 = _mm_unpacklo_epi16(abcd, efgh);
00116
00117
00118 const __m128i v1a = _mm_slli_epi64(v1, 2);
00119
00120
00121 const __m128i v2a = _mm_unpacklo_epi16(v1a, v1a);
00122 const __m128i v2 = _mm_unpacklo_epi32(v2a, v2a);
00123
00124
00125 const __m128i v3 = _mm_mulhi_epu16(v2, reinterpret_cast<const __m128i*>(kDivPowersVector)[0]);
00126 const __m128i v4 = _mm_mulhi_epu16(v3, reinterpret_cast<const __m128i*>(kShiftPowersVector)[0]);
00127
00128
00129 const __m128i v5 = _mm_mullo_epi16(v4, reinterpret_cast<const __m128i*>(k10Vector)[0]);
00130
00131
00132 const __m128i v6 = _mm_slli_epi64(v5, 16);
00133
00134
00135 const __m128i v7 = _mm_sub_epi16(v4, v6);
00136
00137 return v7;
00138 }
00139
00140 inline __m128i ShiftDigits_SSE2(__m128i a, unsigned digit) {
00141 assert(digit <= 8);
00142 switch (digit) {
00143 case 0: return a;
00144 case 1: return _mm_srli_si128(a, 1);
00145 case 2: return _mm_srli_si128(a, 2);
00146 case 3: return _mm_srli_si128(a, 3);
00147 case 4: return _mm_srli_si128(a, 4);
00148 case 5: return _mm_srli_si128(a, 5);
00149 case 6: return _mm_srli_si128(a, 6);
00150 case 7: return _mm_srli_si128(a, 7);
00151 case 8: return _mm_srli_si128(a, 8);
00152 }
00153 return a;
00154 }
00155
00156 }
00157
00158
00159 char *ToString(uint32_t value, char* buffer) {
00160 if (value < 10000) {
00161 const uint32_t d1 = (value / 100) << 1;
00162 const uint32_t d2 = (value % 100) << 1;
00163
00164 if (value >= 1000)
00165 *buffer++ = gDigitsLut[d1];
00166 if (value >= 100)
00167 *buffer++ = gDigitsLut[d1 + 1];
00168 if (value >= 10)
00169 *buffer++ = gDigitsLut[d2];
00170 *buffer++ = gDigitsLut[d2 + 1];
00171
00172 return buffer;
00173 }
00174 else if (value < 100000000) {
00175
00176 #if 0
00177 const __m128i a = Convert8DigitsSSE2(value);
00178
00179
00180 const __m128i va = _mm_add_epi8(_mm_packus_epi16(a, _mm_setzero_si128()), reinterpret_cast<const __m128i*>(kAsciiZero)[0]);
00181
00182
00183 const unsigned mask = _mm_movemask_epi8(_mm_cmpeq_epi8(va, reinterpret_cast<const __m128i*>(kAsciiZero)[0]));
00184 unsigned long digit;
00185 #ifdef _MSC_VER
00186 _BitScanForward(&digit, ~mask | 0x8000);
00187 #else
00188 digit = __builtin_ctz(~mask | 0x8000);
00189 #endif
00190
00191
00192 __m128i result = ShiftDigits_SSE2(va, digit);
00193
00194 _mm_storel_epi64(reinterpret_cast<__m128i*>(buffer), result);
00195 buffer[8 - digit] = '\0';
00196 #else
00197
00198 const uint32_t b = value / 10000;
00199 const uint32_t c = value % 10000;
00200
00201 const uint32_t d1 = (b / 100) << 1;
00202 const uint32_t d2 = (b % 100) << 1;
00203
00204 const uint32_t d3 = (c / 100) << 1;
00205 const uint32_t d4 = (c % 100) << 1;
00206
00207 if (value >= 10000000)
00208 *buffer++ = gDigitsLut[d1];
00209 if (value >= 1000000)
00210 *buffer++ = gDigitsLut[d1 + 1];
00211 if (value >= 100000)
00212 *buffer++ = gDigitsLut[d2];
00213 *buffer++ = gDigitsLut[d2 + 1];
00214
00215 *buffer++ = gDigitsLut[d3];
00216 *buffer++ = gDigitsLut[d3 + 1];
00217 *buffer++ = gDigitsLut[d4];
00218 *buffer++ = gDigitsLut[d4 + 1];
00219
00220 return buffer;
00221 #endif
00222 }
00223 else {
00224
00225
00226 const uint32_t a = value / 100000000;
00227 value %= 100000000;
00228
00229 if (a >= 10) {
00230 const unsigned i = a << 1;
00231 *buffer++ = gDigitsLut[i];
00232 *buffer++ = gDigitsLut[i + 1];
00233 }
00234 else
00235 *buffer++ = '0' + static_cast<char>(a);
00236
00237 const __m128i b = Convert8DigitsSSE2(value);
00238 const __m128i ba = _mm_add_epi8(_mm_packus_epi16(_mm_setzero_si128(), b), reinterpret_cast<const __m128i*>(kAsciiZero)[0]);
00239 const __m128i result = _mm_srli_si128(ba, 8);
00240 _mm_storel_epi64(reinterpret_cast<__m128i*>(buffer), result);
00241
00242 return buffer + 8;
00243 }
00244 }
00245
00246
00247 char *ToString(uint64_t value, char* buffer) {
00248 if (value < 100000000) {
00249 uint32_t v = static_cast<uint32_t>(value);
00250 if (v < 10000) {
00251 const uint32_t d1 = (v / 100) << 1;
00252 const uint32_t d2 = (v % 100) << 1;
00253
00254 if (v >= 1000)
00255 *buffer++ = gDigitsLut[d1];
00256 if (v >= 100)
00257 *buffer++ = gDigitsLut[d1 + 1];
00258 if (v >= 10)
00259 *buffer++ = gDigitsLut[d2];
00260 *buffer++ = gDigitsLut[d2 + 1];
00261
00262 return buffer;
00263 }
00264 else {
00265
00266 #if 0
00267 const __m128i a = Convert8DigitsSSE2(v);
00268
00269
00270 const __m128i va = _mm_add_epi8(_mm_packus_epi16(a, _mm_setzero_si128()), reinterpret_cast<const __m128i*>(kAsciiZero)[0]);
00271
00272
00273 const unsigned mask = _mm_movemask_epi8(_mm_cmpeq_epi8(va, reinterpret_cast<const __m128i*>(kAsciiZero)[0]));
00274 unsigned long digit;
00275 #ifdef _MSC_VER
00276 _BitScanForward(&digit, ~mask | 0x8000);
00277 #else
00278 digit = __builtin_ctz(~mask | 0x8000);
00279 #endif
00280
00281
00282 __m128i result = ShiftDigits_SSE2(va, digit);
00283 _mm_storel_epi64(reinterpret_cast<__m128i*>(buffer), result);
00284 buffer[8 - digit] = '\0';
00285 #else
00286
00287 const uint32_t b = v / 10000;
00288 const uint32_t c = v % 10000;
00289
00290 const uint32_t d1 = (b / 100) << 1;
00291 const uint32_t d2 = (b % 100) << 1;
00292
00293 const uint32_t d3 = (c / 100) << 1;
00294 const uint32_t d4 = (c % 100) << 1;
00295
00296 if (value >= 10000000)
00297 *buffer++ = gDigitsLut[d1];
00298 if (value >= 1000000)
00299 *buffer++ = gDigitsLut[d1 + 1];
00300 if (value >= 100000)
00301 *buffer++ = gDigitsLut[d2];
00302 *buffer++ = gDigitsLut[d2 + 1];
00303
00304 *buffer++ = gDigitsLut[d3];
00305 *buffer++ = gDigitsLut[d3 + 1];
00306 *buffer++ = gDigitsLut[d4];
00307 *buffer++ = gDigitsLut[d4 + 1];
00308
00309 return buffer;
00310 #endif
00311 }
00312 }
00313 else if (value < 10000000000000000) {
00314 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
00315 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
00316
00317 const __m128i a0 = Convert8DigitsSSE2(v0);
00318 const __m128i a1 = Convert8DigitsSSE2(v1);
00319
00320
00321 const __m128i va = _mm_add_epi8(_mm_packus_epi16(a0, a1), reinterpret_cast<const __m128i*>(kAsciiZero)[0]);
00322
00323
00324 const unsigned mask = _mm_movemask_epi8(_mm_cmpeq_epi8(va, reinterpret_cast<const __m128i*>(kAsciiZero)[0]));
00325 #ifdef _MSC_VER
00326 unsigned long digit;
00327 _BitScanForward(&digit, ~mask | 0x8000);
00328 #else
00329 unsigned digit = __builtin_ctz(~mask | 0x8000);
00330 #endif
00331
00332
00333 __m128i result = ShiftDigits_SSE2(va, digit);
00334 _mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), result);
00335
00336 return &buffer[16 - digit];
00337 }
00338 else {
00339 const uint32_t a = static_cast<uint32_t>(value / 10000000000000000);
00340 value %= 10000000000000000;
00341
00342 if (a < 10)
00343 *buffer++ = '0' + static_cast<char>(a);
00344 else if (a < 100) {
00345 const uint32_t i = a << 1;
00346 *buffer++ = gDigitsLut[i];
00347 *buffer++ = gDigitsLut[i + 1];
00348 }
00349 else if (a < 1000) {
00350 *buffer++ = '0' + static_cast<char>(a / 100);
00351
00352 const uint32_t i = (a % 100) << 1;
00353 *buffer++ = gDigitsLut[i];
00354 *buffer++ = gDigitsLut[i + 1];
00355 }
00356 else {
00357 const uint32_t i = (a / 100) << 1;
00358 const uint32_t j = (a % 100) << 1;
00359 *buffer++ = gDigitsLut[i];
00360 *buffer++ = gDigitsLut[i + 1];
00361 *buffer++ = gDigitsLut[j];
00362 *buffer++ = gDigitsLut[j + 1];
00363 }
00364
00365 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
00366 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
00367
00368 const __m128i a0 = Convert8DigitsSSE2(v0);
00369 const __m128i a1 = Convert8DigitsSSE2(v1);
00370
00371
00372 const __m128i va = _mm_add_epi8(_mm_packus_epi16(a0, a1), reinterpret_cast<const __m128i*>(kAsciiZero)[0]);
00373 _mm_storeu_si128(reinterpret_cast<__m128i*>(buffer), va);
00374
00375 return &buffer[16];
00376 }
00377 }
00378
00379 #else // Generic Non-x86 case
00380
00381
00382 char *ToString(uint32_t value, char* buffer) {
00383 if (value < 10000) {
00384 const uint32_t d1 = (value / 100) << 1;
00385 const uint32_t d2 = (value % 100) << 1;
00386
00387 if (value >= 1000)
00388 *buffer++ = gDigitsLut[d1];
00389 if (value >= 100)
00390 *buffer++ = gDigitsLut[d1 + 1];
00391 if (value >= 10)
00392 *buffer++ = gDigitsLut[d2];
00393 *buffer++ = gDigitsLut[d2 + 1];
00394 }
00395 else if (value < 100000000) {
00396
00397 const uint32_t b = value / 10000;
00398 const uint32_t c = value % 10000;
00399
00400 const uint32_t d1 = (b / 100) << 1;
00401 const uint32_t d2 = (b % 100) << 1;
00402
00403 const uint32_t d3 = (c / 100) << 1;
00404 const uint32_t d4 = (c % 100) << 1;
00405
00406 if (value >= 10000000)
00407 *buffer++ = gDigitsLut[d1];
00408 if (value >= 1000000)
00409 *buffer++ = gDigitsLut[d1 + 1];
00410 if (value >= 100000)
00411 *buffer++ = gDigitsLut[d2];
00412 *buffer++ = gDigitsLut[d2 + 1];
00413
00414 *buffer++ = gDigitsLut[d3];
00415 *buffer++ = gDigitsLut[d3 + 1];
00416 *buffer++ = gDigitsLut[d4];
00417 *buffer++ = gDigitsLut[d4 + 1];
00418 }
00419 else {
00420
00421
00422 const uint32_t a = value / 100000000;
00423 value %= 100000000;
00424
00425 if (a >= 10) {
00426 const unsigned i = a << 1;
00427 *buffer++ = gDigitsLut[i];
00428 *buffer++ = gDigitsLut[i + 1];
00429 }
00430 else
00431 *buffer++ = '0' + static_cast<char>(a);
00432
00433 const uint32_t b = value / 10000;
00434 const uint32_t c = value % 10000;
00435
00436 const uint32_t d1 = (b / 100) << 1;
00437 const uint32_t d2 = (b % 100) << 1;
00438
00439 const uint32_t d3 = (c / 100) << 1;
00440 const uint32_t d4 = (c % 100) << 1;
00441
00442 *buffer++ = gDigitsLut[d1];
00443 *buffer++ = gDigitsLut[d1 + 1];
00444 *buffer++ = gDigitsLut[d2];
00445 *buffer++ = gDigitsLut[d2 + 1];
00446 *buffer++ = gDigitsLut[d3];
00447 *buffer++ = gDigitsLut[d3 + 1];
00448 *buffer++ = gDigitsLut[d4];
00449 *buffer++ = gDigitsLut[d4 + 1];
00450 }
00451 return buffer;
00452 }
00453
00454
00455 char *ToString(uint64_t value, char* buffer) {
00456 if (value < 100000000) {
00457 uint32_t v = static_cast<uint32_t>(value);
00458 if (v < 10000) {
00459 const uint32_t d1 = (v / 100) << 1;
00460 const uint32_t d2 = (v % 100) << 1;
00461
00462 if (v >= 1000)
00463 *buffer++ = gDigitsLut[d1];
00464 if (v >= 100)
00465 *buffer++ = gDigitsLut[d1 + 1];
00466 if (v >= 10)
00467 *buffer++ = gDigitsLut[d2];
00468 *buffer++ = gDigitsLut[d2 + 1];
00469 }
00470 else {
00471
00472 const uint32_t b = v / 10000;
00473 const uint32_t c = v % 10000;
00474
00475 const uint32_t d1 = (b / 100) << 1;
00476 const uint32_t d2 = (b % 100) << 1;
00477
00478 const uint32_t d3 = (c / 100) << 1;
00479 const uint32_t d4 = (c % 100) << 1;
00480
00481 if (value >= 10000000)
00482 *buffer++ = gDigitsLut[d1];
00483 if (value >= 1000000)
00484 *buffer++ = gDigitsLut[d1 + 1];
00485 if (value >= 100000)
00486 *buffer++ = gDigitsLut[d2];
00487 *buffer++ = gDigitsLut[d2 + 1];
00488
00489 *buffer++ = gDigitsLut[d3];
00490 *buffer++ = gDigitsLut[d3 + 1];
00491 *buffer++ = gDigitsLut[d4];
00492 *buffer++ = gDigitsLut[d4 + 1];
00493 }
00494 }
00495 else if (value < 10000000000000000) {
00496 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
00497 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
00498
00499 const uint32_t b0 = v0 / 10000;
00500 const uint32_t c0 = v0 % 10000;
00501
00502 const uint32_t d1 = (b0 / 100) << 1;
00503 const uint32_t d2 = (b0 % 100) << 1;
00504
00505 const uint32_t d3 = (c0 / 100) << 1;
00506 const uint32_t d4 = (c0 % 100) << 1;
00507
00508 const uint32_t b1 = v1 / 10000;
00509 const uint32_t c1 = v1 % 10000;
00510
00511 const uint32_t d5 = (b1 / 100) << 1;
00512 const uint32_t d6 = (b1 % 100) << 1;
00513
00514 const uint32_t d7 = (c1 / 100) << 1;
00515 const uint32_t d8 = (c1 % 100) << 1;
00516
00517 if (value >= 1000000000000000)
00518 *buffer++ = gDigitsLut[d1];
00519 if (value >= 100000000000000)
00520 *buffer++ = gDigitsLut[d1 + 1];
00521 if (value >= 10000000000000)
00522 *buffer++ = gDigitsLut[d2];
00523 if (value >= 1000000000000)
00524 *buffer++ = gDigitsLut[d2 + 1];
00525 if (value >= 100000000000)
00526 *buffer++ = gDigitsLut[d3];
00527 if (value >= 10000000000)
00528 *buffer++ = gDigitsLut[d3 + 1];
00529 if (value >= 1000000000)
00530 *buffer++ = gDigitsLut[d4];
00531 if (value >= 100000000)
00532 *buffer++ = gDigitsLut[d4 + 1];
00533
00534 *buffer++ = gDigitsLut[d5];
00535 *buffer++ = gDigitsLut[d5 + 1];
00536 *buffer++ = gDigitsLut[d6];
00537 *buffer++ = gDigitsLut[d6 + 1];
00538 *buffer++ = gDigitsLut[d7];
00539 *buffer++ = gDigitsLut[d7 + 1];
00540 *buffer++ = gDigitsLut[d8];
00541 *buffer++ = gDigitsLut[d8 + 1];
00542 }
00543 else {
00544 const uint32_t a = static_cast<uint32_t>(value / 10000000000000000);
00545 value %= 10000000000000000;
00546
00547 if (a < 10)
00548 *buffer++ = '0' + static_cast<char>(a);
00549 else if (a < 100) {
00550 const uint32_t i = a << 1;
00551 *buffer++ = gDigitsLut[i];
00552 *buffer++ = gDigitsLut[i + 1];
00553 }
00554 else if (a < 1000) {
00555 *buffer++ = '0' + static_cast<char>(a / 100);
00556
00557 const uint32_t i = (a % 100) << 1;
00558 *buffer++ = gDigitsLut[i];
00559 *buffer++ = gDigitsLut[i + 1];
00560 }
00561 else {
00562 const uint32_t i = (a / 100) << 1;
00563 const uint32_t j = (a % 100) << 1;
00564 *buffer++ = gDigitsLut[i];
00565 *buffer++ = gDigitsLut[i + 1];
00566 *buffer++ = gDigitsLut[j];
00567 *buffer++ = gDigitsLut[j + 1];
00568 }
00569
00570 const uint32_t v0 = static_cast<uint32_t>(value / 100000000);
00571 const uint32_t v1 = static_cast<uint32_t>(value % 100000000);
00572
00573 const uint32_t b0 = v0 / 10000;
00574 const uint32_t c0 = v0 % 10000;
00575
00576 const uint32_t d1 = (b0 / 100) << 1;
00577 const uint32_t d2 = (b0 % 100) << 1;
00578
00579 const uint32_t d3 = (c0 / 100) << 1;
00580 const uint32_t d4 = (c0 % 100) << 1;
00581
00582 const uint32_t b1 = v1 / 10000;
00583 const uint32_t c1 = v1 % 10000;
00584
00585 const uint32_t d5 = (b1 / 100) << 1;
00586 const uint32_t d6 = (b1 % 100) << 1;
00587
00588 const uint32_t d7 = (c1 / 100) << 1;
00589 const uint32_t d8 = (c1 % 100) << 1;
00590
00591 *buffer++ = gDigitsLut[d1];
00592 *buffer++ = gDigitsLut[d1 + 1];
00593 *buffer++ = gDigitsLut[d2];
00594 *buffer++ = gDigitsLut[d2 + 1];
00595 *buffer++ = gDigitsLut[d3];
00596 *buffer++ = gDigitsLut[d3 + 1];
00597 *buffer++ = gDigitsLut[d4];
00598 *buffer++ = gDigitsLut[d4 + 1];
00599 *buffer++ = gDigitsLut[d5];
00600 *buffer++ = gDigitsLut[d5 + 1];
00601 *buffer++ = gDigitsLut[d6];
00602 *buffer++ = gDigitsLut[d6 + 1];
00603 *buffer++ = gDigitsLut[d7];
00604 *buffer++ = gDigitsLut[d7 + 1];
00605 *buffer++ = gDigitsLut[d8];
00606 *buffer++ = gDigitsLut[d8 + 1];
00607 }
00608 return buffer;
00609 }
00610
00611 #endif // End of architecture if statement.
00612
00613
00614
00615 char *ToString(int32_t value, char *to) {
00616 uint32_t un = static_cast<uint32_t>(value);
00617 if (value < 0) {
00618 *to++ = '-';
00619 un = -un;
00620 }
00621 return ToString(un, to);
00622 }
00623
00624 char *ToString(int64_t value, char *to) {
00625 uint64_t un = static_cast<uint64_t>(value);
00626 if (value < 0) {
00627 *to++ = '-';
00628 un = -un;
00629 }
00630 return ToString(un, to);
00631 }
00632
00633
00634 char *ToString(int16_t value, char *to) {
00635 return ToString((int32_t)value, to);
00636 }
00637 char *ToString(uint16_t value, char *to) {
00638 return ToString((uint32_t)value, to);
00639 }
00640
00641
00642 namespace {
00643 const char kHexDigits[] = "0123456789abcdef";
00644 }
00645
00646 char *ToString(const void *v, char *to) {
00647 *to++ = '0';
00648 *to++ = 'x';
00649
00650
00651
00652 if (!v) {
00653 *to++ = '0';
00654 return to;
00655 }
00656
00657 uintptr_t value = reinterpret_cast<uintptr_t>(v);
00658 uint8_t shift = sizeof(void*) * 8 - 4;
00659 for (; !(value >> shift); shift -= 4) {}
00660 for (; ; shift -= 4) {
00661 *to++ = kHexDigits[(value >> shift) & 0xf];
00662 if (!shift) break;
00663 }
00664 return to;
00665 }
00666
00667 }