1 // Tencent is pleased to support the open source community by making RapidJSON available. 2 // 3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved. 4 // 5 // Licensed under the MIT License (the "License"); you may not use this file except 6 // in compliance with the License. You may obtain a copy of the License at 7 // 8 // http://opensource.org/licenses/MIT 9 // 10 // Unless required by applicable law or agreed to in writing, software distributed 11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 12 // CONDITIONS OF ANY KIND, either express or implied. See the License for the 13 // specific language governing permissions and limitations under the License. 14 15 #include "perftest.h" 16 17 #if TEST_MISC 18 19 #define __STDC_FORMAT_MACROS 20 #include "rapidjson/stringbuffer.h" 21 22 #define protected public 23 #include "rapidjson/writer.h" 24 #undef private 25 26 class Misc : public PerfTest { 27 }; 28 29 // Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern (at) hoehrmann.de> 30 // See http://bjoern.hoehrmann.de/utf-8/decoder/dfa/ for details. 31 32 #define UTF8_ACCEPT 0 33 #define UTF8_REJECT 12 34 35 static const unsigned char utf8d[] = { 36 // The first part of the table maps bytes to character classes that 37 // to reduce the size of the transition table and create bitmasks. 38 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 39 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 40 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 41 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 42 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 43 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 44 8,8,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 45 10,3,3,3,3,3,3,3,3,3,3,3,3,4,3,3, 11,6,6,6,5,8,8,8,8,8,8,8,8,8,8,8, 46 47 // The second part is a transition table that maps a combination 48 // of a state of the automaton and a character class to a state. 49 0,12,24,36,60,96,84,12,12,12,48,72, 12,12,12,12,12,12,12,12,12,12,12,12, 50 12, 0,12,12,12,12,12, 0,12, 0,12,12, 12,24,12,12,12,12,12,24,12,24,12,12, 51 12,12,12,12,12,12,12,24,12,12,12,12, 12,24,12,12,12,12,12,12,12,24,12,12, 52 12,12,12,12,12,12,12,36,12,36,12,12, 12,36,12,12,12,12,12,36,12,36,12,12, 53 12,36,12,12,12,12,12,12,12,12,12,12, 54 }; 55 56 static unsigned inline decode(unsigned* state, unsigned* codep, unsigned byte) { 57 unsigned type = utf8d[byte]; 58 59 *codep = (*state != UTF8_ACCEPT) ? 60 (byte & 0x3fu) | (*codep << 6) : 61 (0xff >> type) & (byte); 62 63 *state = utf8d[256 + *state + type]; 64 return *state; 65 } 66 67 static bool IsUTF8(unsigned char* s) { 68 unsigned codepoint, state = 0; 69 70 while (*s) 71 decode(&state, &codepoint, *s++); 72 73 return state == UTF8_ACCEPT; 74 } 75 76 TEST_F(Misc, Hoehrmann_IsUTF8) { 77 for (size_t i = 0; i < kTrialCount; i++) { 78 EXPECT_TRUE(IsUTF8((unsigned char*)json_)); 79 } 80 } 81 82 //////////////////////////////////////////////////////////////////////////////// 83 // CountDecimalDigit: Count number of decimal places 84 85 inline unsigned CountDecimalDigit_naive(unsigned n) { 86 unsigned count = 1; 87 while (n >= 10) { 88 n /= 10; 89 count++; 90 } 91 return count; 92 } 93 94 inline unsigned CountDecimalDigit_enroll4(unsigned n) { 95 unsigned count = 1; 96 while (n >= 10000) { 97 n /= 10000u; 98 count += 4; 99 } 100 if (n < 10) return count; 101 if (n < 100) return count + 1; 102 if (n < 1000) return count + 2; 103 return count + 3; 104 } 105 106 inline unsigned CountDecimalDigit64_enroll4(uint64_t n) { 107 unsigned count = 1; 108 while (n >= 10000) { 109 n /= 10000u; 110 count += 4; 111 } 112 if (n < 10) return count; 113 if (n < 100) return count + 1; 114 if (n < 1000) return count + 2; 115 return count + 3; 116 } 117 118 inline unsigned CountDecimalDigit_fast(unsigned n) { 119 static const uint32_t powers_of_10[] = { 120 0, 121 10, 122 100, 123 1000, 124 10000, 125 100000, 126 1000000, 127 10000000, 128 100000000, 129 1000000000 130 }; 131 132 #if defined(_M_IX86) || defined(_M_X64) 133 unsigned long i = 0; 134 _BitScanReverse(&i, n | 1); 135 uint32_t t = (i + 1) * 1233 >> 12; 136 #elif defined(__GNUC__) 137 uint32_t t = (32 - __builtin_clz(n | 1)) * 1233 >> 12; 138 #else 139 #error 140 #endif 141 return t - (n < powers_of_10[t]) + 1; 142 } 143 144 inline unsigned CountDecimalDigit64_fast(uint64_t n) { 145 static const uint64_t powers_of_10[] = { 146 0, 147 10, 148 100, 149 1000, 150 10000, 151 100000, 152 1000000, 153 10000000, 154 100000000, 155 1000000000, 156 10000000000, 157 100000000000, 158 1000000000000, 159 10000000000000, 160 100000000000000, 161 1000000000000000, 162 10000000000000000, 163 100000000000000000, 164 1000000000000000000, 165 10000000000000000000U 166 }; 167 168 #if defined(_M_IX86) 169 uint64_t m = n | 1; 170 unsigned long i = 0; 171 if (_BitScanReverse(&i, m >> 32)) 172 i += 32; 173 else 174 _BitScanReverse(&i, m & 0xFFFFFFFF); 175 uint32_t t = (i + 1) * 1233 >> 12; 176 #elif defined(_M_X64) 177 unsigned long i = 0; 178 _BitScanReverse64(&i, n | 1); 179 uint32_t t = (i + 1) * 1233 >> 12; 180 #elif defined(__GNUC__) 181 uint32_t t = (64 - __builtin_clzll(n | 1)) * 1233 >> 12; 182 #else 183 #error 184 #endif 185 186 return t - (n < powers_of_10[t]) + 1; 187 } 188 189 #if 0 190 // Exhaustive, very slow 191 TEST_F(Misc, CountDecimalDigit_Verify) { 192 unsigned i = 0; 193 do { 194 if (i % (65536 * 256) == 0) 195 printf("%u\n", i); 196 ASSERT_EQ(CountDecimalDigit_enroll4(i), CountDecimalDigit_fast(i)); 197 i++; 198 } while (i != 0); 199 } 200 201 static const unsigned kDigits10Trial = 1000000000u; 202 TEST_F(Misc, CountDecimalDigit_naive) { 203 unsigned sum = 0; 204 for (unsigned i = 0; i < kDigits10Trial; i++) 205 sum += CountDecimalDigit_naive(i); 206 printf("%u\n", sum); 207 } 208 209 TEST_F(Misc, CountDecimalDigit_enroll4) { 210 unsigned sum = 0; 211 for (unsigned i = 0; i < kDigits10Trial; i++) 212 sum += CountDecimalDigit_enroll4(i); 213 printf("%u\n", sum); 214 } 215 216 TEST_F(Misc, CountDecimalDigit_fast) { 217 unsigned sum = 0; 218 for (unsigned i = 0; i < kDigits10Trial; i++) 219 sum += CountDecimalDigit_fast(i); 220 printf("%u\n", sum); 221 } 222 #endif 223 224 TEST_F(Misc, CountDecimalDigit64_VerifyFast) { 225 uint64_t i = 1, j; 226 do { 227 //printf("%" PRIu64 "\n", i); 228 ASSERT_EQ(CountDecimalDigit64_enroll4(i), CountDecimalDigit64_fast(i)); 229 j = i; 230 i *= 3; 231 } while (j < i); 232 } 233 234 //////////////////////////////////////////////////////////////////////////////// 235 // integer-to-string conversion 236 237 // https://gist.github.com/anonymous/7179097 238 static const int randval[] ={ 239 936116, 369532, 453755, -72860, 209713, 268347, 435278, -360266, -416287, -182064, 240 -644712, 944969, 640463, -366588, 471577, -69401, -744294, -505829, 923883, 831785, 241 -601136, -636767, -437054, 591718, 100758, 231907, -719038, 973540, -605220, 506659, 242 -871653, 462533, 764843, -919138, 404305, -630931, -288711, -751454, -173726, -718208, 243 432689, -281157, 360737, 659827, 19174, -376450, 769984, -858198, 439127, 734703, 244 -683426, 7, 386135, 186997, -643900, -744422, -604708, -629545, 42313, -933592, 245 -635566, 182308, 439024, -367219, -73924, -516649, 421935, -470515, 413507, -78952, 246 -427917, -561158, 737176, 94538, 572322, 405217, 709266, -357278, -908099, -425447, 247 601119, 750712, -862285, -177869, 900102, 384877, 157859, -641680, 503738, -702558, 248 278225, 463290, 268378, -212840, 580090, 347346, -473985, -950968, -114547, -839893, 249 -738032, -789424, 409540, 493495, 432099, 119755, 905004, -174834, 338266, 234298, 250 74641, -965136, -754593, 685273, 466924, 920560, 385062, 796402, -67229, 994864, 251 376974, 299869, -647540, -128724, 469890, -163167, -547803, -743363, 486463, -621028, 252 612288, 27459, -514224, 126342, -66612, 803409, -777155, -336453, -284002, 472451, 253 342390, -163630, 908356, -456147, -825607, 268092, -974715, 287227, 227890, -524101, 254 616370, -782456, 922098, -624001, -813690, 171605, -192962, 796151, 707183, -95696, 255 -23163, -721260, 508892, 430715, 791331, 482048, -996102, 863274, 275406, -8279, 256 -556239, -902076, 268647, -818565, 260069, -798232, -172924, -566311, -806503, -885992, 257 813969, -78468, 956632, 304288, 494867, -508784, 381751, 151264, 762953, 76352, 258 594902, 375424, 271700, -743062, 390176, 924237, 772574, 676610, 435752, -153847, 259 3959, -971937, -294181, -538049, -344620, -170136, 19120, -703157, 868152, -657961, 260 -818631, 219015, -872729, -940001, -956570, 880727, -345910, 942913, -942271, -788115, 261 225294, 701108, -517736, -416071, 281940, 488730, 942698, 711494, 838382, -892302, 262 -533028, 103052, 528823, 901515, 949577, 159364, 718227, -241814, -733661, -462928, 263 -495829, 165170, 513580, -629188, -509571, -459083, 198437, 77198, -644612, 811276, 264 -422298, -860842, -52584, 920369, 686424, -530667, -243476, 49763, 345866, -411960, 265 -114863, 470810, -302860, 683007, -509080, 2, -174981, -772163, -48697, 447770, 266 -268246, 213268, 269215, 78810, -236340, -639140, -864323, 505113, -986569, -325215, 267 541859, 163070, -819998, -645161, -583336, 573414, 696417, -132375, 3, -294501, 268 320435, 682591, 840008, 351740, 426951, 609354, 898154, -943254, 227321, -859793, 269 -727993, 44137, -497965, -782239, 14955, -746080, -243366, 9837, -233083, 606507, 270 -995864, -615287, -994307, 602715, 770771, -315040, 610860, 446102, -307120, 710728, 271 -590392, -230474, -762625, -637525, 134963, -202700, -766902, -985541, 218163, 682009, 272 926051, 525156, -61195, 403211, -810098, 245539, -431733, 179998, -806533, 745943, 273 447597, 131973, -187130, 826019, 286107, -937230, -577419, 20254, 681802, -340500, 274 323080, 266283, -667617, 309656, 416386, 611863, 759991, -534257, 523112, -634892, 275 -169913, -204905, -909867, -882185, -944908, 741811, -717675, 967007, -317396, 407230, 276 -412805, 792905, 994873, 744793, -456797, 713493, 355232, 116900, -945199, 880539, 277 342505, -580824, -262273, 982968, -349497, -735488, 311767, -455191, 570918, 389734, 278 -958386, 10262, -99267, 155481, 304210, 204724, 704367, -144893, -233664, -671441, 279 896849, 408613, 762236, 322697, 981321, 688476, 13663, -970704, -379507, 896412, 280 977084, 348869, 875948, 341348, 318710, 512081, 6163, 669044, 833295, 811883, 281 708756, -802534, -536057, 608413, -389625, -694603, 541106, -110037, 720322, -540581, 282 645420, 32980, 62442, 510157, -981870, -87093, -325960, -500494, -718291, -67889, 283 991501, 374804, 769026, -978869, 294747, 714623, 413327, -199164, 671368, 804789, 284 -362507, 798196, -170790, -568895, -869379, 62020, -316693, -837793, 644994, -39341, 285 -417504, -243068, -957756, 99072, 622234, -739992, 225668, 8863, -505910, 82483, 286 -559244, 241572, 1315, -36175, -54990, 376813, -11, 162647, -688204, -486163, 287 -54934, -197470, 744223, -762707, 732540, 996618, 351561, -445933, -898491, 486531, 288 456151, 15276, 290186, -817110, -52995, 313046, -452533, -96267, 94470, -500176, 289 -818026, -398071, -810548, -143325, -819741, 1338, -897676, -101577, -855445, 37309, 290 285742, 953804, -777927, -926962, -811217, -936744, -952245, -802300, -490188, -964953, 291 -552279, 329142, -570048, -505756, 682898, -381089, -14352, 175138, 152390, -582268, 292 -485137, 717035, 805329, 239572, -730409, 209643, -184403, -385864, 675086, 819648, 293 629058, -527109, -488666, -171981, 532788, 552441, 174666, 984921, 766514, 758787, 294 716309, 338801, -978004, -412163, 876079, -734212, 789557, -160491, -522719, 56644, 295 -991, -286038, -53983, 663740, 809812, 919889, -717502, -137704, 220511, 184396, 296 -825740, -588447, 430870, 124309, 135956, 558662, -307087, -788055, -451328, 812260, 297 931601, 324347, -482989, -117858, -278861, 189068, -172774, 929057, 293787, 198161, 298 -342386, -47173, 906555, -759955, -12779, 777604, -97869, 899320, 927486, -25284, 299 -848550, 259450, -485856, -17820, 88, 171400, 235492, -326783, -340793, 886886, 300 112428, -246280, 5979, 648444, -114982, 991013, -56489, -9497, 419706, 632820, 301 -341664, 393926, -848977, -22538, 257307, 773731, -905319, 491153, 734883, -868212, 302 -951053, 644458, -580758, 764735, 584316, 297077, 28852, -397710, -953669, 201772, 303 879050, -198237, -588468, 448102, -116837, 770007, -231812, 642906, -582166, -885828, 304 9, 305082, -996577, 303559, 75008, -772956, -447960, 599825, -295552, 870739, 305 -386278, -950300, 485359, -457081, 629461, -850276, 550496, -451755, -620841, -11766, 306 -950137, 832337, 28711, -273398, -507197, 91921, -271360, -705991, -753220, -388968, 307 967945, 340434, -320883, -662793, -554617, -574568, 477946, -6148, -129519, 689217, 308 920020, -656315, -974523, -212525, 80921, -612532, 645096, 545655, 655713, -591631, 309 -307385, -816688, -618823, -113713, 526430, 673063, 735916, -809095, -850417, 639004, 310 432281, -388185, 270708, 860146, -39902, -786157, -258180, -246169, -966720, -264957, 311 548072, -306010, -57367, -635665, 933824, 70553, -989936, -488741, 72411, -452509, 312 529831, 956277, 449019, -577850, -360986, -803418, 48833, 296073, 203430, 609591, 313 715483, 470964, 658106, -718254, -96424, 790163, 334739, 181070, -373578, 5, 314 -435088, 329841, 330939, -256602, 394355, 912412, 231910, 927278, -661933, 788539, 315 -769664, -893274, -96856, 298205, 901043, -608122, -527430, 183618, -553963, -35246, 316 -393924, 948832, -483198, 594501, 35460, -407007, 93494, -336881, -634072, 984205, 317 -812161, 944664, -31062, 753872, 823933, -69566, 50445, 290147, 85134, 34706, 318 551902, 405202, -991246, -84642, 154341, 316432, -695101, -651588, -5030, 137564, 319 -294665, 332541, 528307, -90572, -344923, 523766, -758498, -968047, 339028, 494578, 320 593129, -725773, 31834, -718406, -208638, 159665, -2043, 673344, -442767, 75816, 321 755442, 769257, -158730, -410272, 691688, 589550, -878398, -184121, 460679, 346312, 322 294163, -544602, 653308, 254167, -276979, 52073, -892684, 887653, -41222, 983065, 323 -68258, -408799, -99069, -674069, -863635, -32890, 622757, -743862, 40872, -4837, 324 -967228, 522370, -903951, -818669, 524459, 514702, 925801, 20007, -299229, 579348, 325 626021, 430089, 348139, -562692, -607728, -130606, -928451, -424793, -458647, -448892, 326 -312230, 143337, 109746, 880042, -339658, -785614, 938995, 540916, 118429, 661351, 327 -402967, 404729, -40918, -976535, 743230, 713110, 440182, -381314, -499252, 74613, 328 193652, 912717, 491323, 583633, 324691, 459397, 281253, 195540, -2764, -888651, 329 892449, 132663, -478373, -430002, -314551, 527826, 247165, 557966, 554778, 481531, 330 -946634, 431685, -769059, -348371, 174046, 184597, -354867, 584422, 227390, -850397, 331 -542924, -849093, -737769, 325359, 736314, 269101, 767940, 674809, 81413, -447458, 332 445076, 189072, 906218, 502688, -718476, -863827, -731381, 100660, 623249, 710008, 333 572060, 922203, 685740, 55096, 263394, -243695, -353910, -516788, 388471, 455165, 334 844103, -643772, 363976, 268875, -899450, 104470, 104029, -238874, -274659, 732969, 335 -676443, 953291, -916289, -861849, -242344, 958083, -479593, -970395, 799831, 277841, 336 -243236, -283462, -201510, 166263, -259105, -575706, 878926, 891064, 895297, 655262, 337 -34807, -809833, -89281, 342585, 554920, 1, 902141, -333425, 139703, 852318, 338 -618438, 329498, -932596, -692836, -513372, 733656, -523411, 85779, 500478, -682697, 339 -502836, 138776, 156341, -420037, -557964, -556378, 710993, -50383, -877159, 916334, 340 132996, 583516, -603392, -111615, -12288, -780214, 476780, 123327, 137607, 519956, 341 745837, 17358, -158581, -53490 342 }; 343 static const size_t randvalCount = sizeof(randval) / sizeof(randval[0]); 344 static const size_t kItoaTrialCount = 10000; 345 346 static const char digits[201] = 347 "0001020304050607080910111213141516171819" 348 "2021222324252627282930313233343536373839" 349 "4041424344454647484950515253545556575859" 350 "6061626364656667686970717273747576777879" 351 "8081828384858687888990919293949596979899"; 352 353 // Prevent code being optimized out 354 //#define OUTPUT_LENGTH(length) printf("", length) 355 #define OUTPUT_LENGTH(length) printf("%u\n", (unsigned)length) 356 357 template<typename OutputStream> 358 class Writer1 { 359 public: 360 Writer1() : os_() {} 361 Writer1(OutputStream& os) : os_(&os) {} 362 363 void Reset(OutputStream& os) { 364 os_ = &os; 365 } 366 367 bool WriteInt(int i) { 368 if (i < 0) { 369 os_->Put('-'); 370 i = -i; 371 } 372 return WriteUint((unsigned)i); 373 } 374 375 bool WriteUint(unsigned u) { 376 char buffer[10]; 377 char *p = buffer; 378 do { 379 *p++ = char(u % 10) + '0'; 380 u /= 10; 381 } while (u > 0); 382 383 do { 384 --p; 385 os_->Put(*p); 386 } while (p != buffer); 387 return true; 388 } 389 390 bool WriteInt64(int64_t i64) { 391 if (i64 < 0) { 392 os_->Put('-'); 393 i64 = -i64; 394 } 395 WriteUint64((uint64_t)i64); 396 return true; 397 } 398 399 bool WriteUint64(uint64_t u64) { 400 char buffer[20]; 401 char *p = buffer; 402 do { 403 *p++ = char(u64 % 10) + '0'; 404 u64 /= 10; 405 } while (u64 > 0); 406 407 do { 408 --p; 409 os_->Put(*p); 410 } while (p != buffer); 411 return true; 412 } 413 414 private: 415 OutputStream* os_; 416 }; 417 418 template<> 419 bool Writer1<rapidjson::StringBuffer>::WriteUint(unsigned u) { 420 char buffer[10]; 421 char* p = buffer; 422 do { 423 *p++ = char(u % 10) + '0'; 424 u /= 10; 425 } while (u > 0); 426 427 char* d = os_->Push(p - buffer); 428 do { 429 --p; 430 *d++ = *p; 431 } while (p != buffer); 432 return true; 433 } 434 435 // Using digits LUT to reduce divsion/modulo 436 template<typename OutputStream> 437 class Writer2 { 438 public: 439 Writer2() : os_() {} 440 Writer2(OutputStream& os) : os_(&os) {} 441 442 void Reset(OutputStream& os) { 443 os_ = &os; 444 } 445 446 bool WriteInt(int i) { 447 if (i < 0) { 448 os_->Put('-'); 449 i = -i; 450 } 451 return WriteUint((unsigned)i); 452 } 453 454 bool WriteUint(unsigned u) { 455 char buffer[10]; 456 char* p = buffer; 457 while (u >= 100) { 458 const unsigned i = (u % 100) << 1; 459 u /= 100; 460 *p++ = digits[i + 1]; 461 *p++ = digits[i]; 462 } 463 if (u < 10) 464 *p++ = char(u) + '0'; 465 else { 466 const unsigned i = u << 1; 467 *p++ = digits[i + 1]; 468 *p++ = digits[i]; 469 } 470 471 do { 472 --p; 473 os_->Put(*p); 474 } while (p != buffer); 475 return true; 476 } 477 478 bool WriteInt64(int64_t i64) { 479 if (i64 < 0) { 480 os_->Put('-'); 481 i64 = -i64; 482 } 483 WriteUint64((uint64_t)i64); 484 return true; 485 } 486 487 bool WriteUint64(uint64_t u64) { 488 char buffer[20]; 489 char* p = buffer; 490 while (u64 >= 100) { 491 const unsigned i = static_cast<unsigned>(u64 % 100) << 1; 492 u64 /= 100; 493 *p++ = digits[i + 1]; 494 *p++ = digits[i]; 495 } 496 if (u64 < 10) 497 *p++ = char(u64) + '0'; 498 else { 499 const unsigned i = static_cast<unsigned>(u64) << 1; 500 *p++ = digits[i + 1]; 501 *p++ = digits[i]; 502 } 503 504 do { 505 --p; 506 os_->Put(*p); 507 } while (p != buffer); 508 return true; 509 } 510 511 private: 512 OutputStream* os_; 513 }; 514 515 // First pass to count digits 516 template<typename OutputStream> 517 class Writer3 { 518 public: 519 Writer3() : os_() {} 520 Writer3(OutputStream& os) : os_(&os) {} 521 522 void Reset(OutputStream& os) { 523 os_ = &os; 524 } 525 526 bool WriteInt(int i) { 527 if (i < 0) { 528 os_->Put('-'); 529 i = -i; 530 } 531 return WriteUint((unsigned)i); 532 } 533 534 bool WriteUint(unsigned u) { 535 char buffer[10]; 536 char *p = buffer; 537 do { 538 *p++ = char(u % 10) + '0'; 539 u /= 10; 540 } while (u > 0); 541 542 do { 543 --p; 544 os_->Put(*p); 545 } while (p != buffer); 546 return true; 547 } 548 549 bool WriteInt64(int64_t i64) { 550 if (i64 < 0) { 551 os_->Put('-'); 552 i64 = -i64; 553 } 554 WriteUint64((uint64_t)i64); 555 return true; 556 } 557 558 bool WriteUint64(uint64_t u64) { 559 char buffer[20]; 560 char *p = buffer; 561 do { 562 *p++ = char(u64 % 10) + '0'; 563 u64 /= 10; 564 } while (u64 > 0); 565 566 do { 567 --p; 568 os_->Put(*p); 569 } while (p != buffer); 570 return true; 571 } 572 573 private: 574 void WriteUintReverse(char* d, unsigned u) { 575 do { 576 *--d = char(u % 10) + '0'; 577 u /= 10; 578 } while (u > 0); 579 } 580 581 void WriteUint64Reverse(char* d, uint64_t u) { 582 do { 583 *--d = char(u % 10) + '0'; 584 u /= 10; 585 } while (u > 0); 586 } 587 588 OutputStream* os_; 589 }; 590 591 template<> 592 inline bool Writer3<rapidjson::StringBuffer>::WriteUint(unsigned u) { 593 unsigned digit = CountDecimalDigit_fast(u); 594 WriteUintReverse(os_->Push(digit) + digit, u); 595 return true; 596 } 597 598 template<> 599 inline bool Writer3<rapidjson::InsituStringStream>::WriteUint(unsigned u) { 600 unsigned digit = CountDecimalDigit_fast(u); 601 WriteUintReverse(os_->Push(digit) + digit, u); 602 return true; 603 } 604 605 template<> 606 inline bool Writer3<rapidjson::StringBuffer>::WriteUint64(uint64_t u) { 607 unsigned digit = CountDecimalDigit64_fast(u); 608 WriteUint64Reverse(os_->Push(digit) + digit, u); 609 return true; 610 } 611 612 template<> 613 inline bool Writer3<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) { 614 unsigned digit = CountDecimalDigit64_fast(u); 615 WriteUint64Reverse(os_->Push(digit) + digit, u); 616 return true; 617 } 618 619 // Using digits LUT to reduce divsion/modulo, two passes 620 template<typename OutputStream> 621 class Writer4 { 622 public: 623 Writer4() : os_() {} 624 Writer4(OutputStream& os) : os_(&os) {} 625 626 void Reset(OutputStream& os) { 627 os_ = &os; 628 } 629 630 bool WriteInt(int i) { 631 if (i < 0) { 632 os_->Put('-'); 633 i = -i; 634 } 635 return WriteUint((unsigned)i); 636 } 637 638 bool WriteUint(unsigned u) { 639 char buffer[10]; 640 char* p = buffer; 641 while (u >= 100) { 642 const unsigned i = (u % 100) << 1; 643 u /= 100; 644 *p++ = digits[i + 1]; 645 *p++ = digits[i]; 646 } 647 if (u < 10) 648 *p++ = char(u) + '0'; 649 else { 650 const unsigned i = u << 1; 651 *p++ = digits[i + 1]; 652 *p++ = digits[i]; 653 } 654 655 do { 656 --p; 657 os_->Put(*p); 658 } while (p != buffer); 659 return true; 660 } 661 662 bool WriteInt64(int64_t i64) { 663 if (i64 < 0) { 664 os_->Put('-'); 665 i64 = -i64; 666 } 667 WriteUint64((uint64_t)i64); 668 return true; 669 } 670 671 bool WriteUint64(uint64_t u64) { 672 char buffer[20]; 673 char* p = buffer; 674 while (u64 >= 100) { 675 const unsigned i = static_cast<unsigned>(u64 % 100) << 1; 676 u64 /= 100; 677 *p++ = digits[i + 1]; 678 *p++ = digits[i]; 679 } 680 if (u64 < 10) 681 *p++ = char(u64) + '0'; 682 else { 683 const unsigned i = static_cast<unsigned>(u64) << 1; 684 *p++ = digits[i + 1]; 685 *p++ = digits[i]; 686 } 687 688 do { 689 --p; 690 os_->Put(*p); 691 } while (p != buffer); 692 return true; 693 } 694 695 private: 696 void WriteUintReverse(char* d, unsigned u) { 697 while (u >= 100) { 698 const unsigned i = (u % 100) << 1; 699 u /= 100; 700 *--d = digits[i + 1]; 701 *--d = digits[i]; 702 } 703 if (u < 10) { 704 *--d = char(u) + '0'; 705 } 706 else { 707 const unsigned i = u << 1; 708 *--d = digits[i + 1]; 709 *--d = digits[i]; 710 } 711 } 712 713 void WriteUint64Reverse(char* d, uint64_t u) { 714 while (u >= 100) { 715 const unsigned i = (u % 100) << 1; 716 u /= 100; 717 *--d = digits[i + 1]; 718 *--d = digits[i]; 719 } 720 if (u < 10) { 721 *--d = char(u) + '0'; 722 } 723 else { 724 const unsigned i = u << 1; 725 *--d = digits[i + 1]; 726 *--d = digits[i]; 727 } 728 } 729 730 OutputStream* os_; 731 }; 732 733 template<> 734 inline bool Writer4<rapidjson::StringBuffer>::WriteUint(unsigned u) { 735 unsigned digit = CountDecimalDigit_fast(u); 736 WriteUintReverse(os_->Push(digit) + digit, u); 737 return true; 738 } 739 740 template<> 741 inline bool Writer4<rapidjson::InsituStringStream>::WriteUint(unsigned u) { 742 unsigned digit = CountDecimalDigit_fast(u); 743 WriteUintReverse(os_->Push(digit) + digit, u); 744 return true; 745 } 746 747 template<> 748 inline bool Writer4<rapidjson::StringBuffer>::WriteUint64(uint64_t u) { 749 unsigned digit = CountDecimalDigit64_fast(u); 750 WriteUint64Reverse(os_->Push(digit) + digit, u); 751 return true; 752 } 753 754 template<> 755 inline bool Writer4<rapidjson::InsituStringStream>::WriteUint64(uint64_t u) { 756 unsigned digit = CountDecimalDigit64_fast(u); 757 WriteUint64Reverse(os_->Push(digit) + digit, u); 758 return true; 759 } 760 761 template <typename Writer> 762 void itoa_Writer_StringBufferVerify() { 763 rapidjson::StringBuffer sb; 764 Writer writer(sb); 765 for (size_t j = 0; j < randvalCount; j++) { 766 char buffer[32]; 767 sprintf(buffer, "%d", randval[j]); 768 writer.WriteInt(randval[j]); 769 ASSERT_STREQ(buffer, sb.GetString()); 770 sb.Clear(); 771 } 772 } 773 774 template <typename Writer> 775 void itoa_Writer_InsituStringStreamVerify() { 776 Writer writer; 777 for (size_t j = 0; j < randvalCount; j++) { 778 char buffer[32]; 779 sprintf(buffer, "%d", randval[j]); 780 char buffer2[32]; 781 rapidjson::InsituStringStream ss(buffer2); 782 writer.Reset(ss); 783 char* begin = ss.PutBegin(); 784 writer.WriteInt(randval[j]); 785 ss.Put('\0'); 786 ss.PutEnd(begin); 787 ASSERT_STREQ(buffer, buffer2); 788 } 789 } 790 791 template <typename Writer> 792 void itoa_Writer_StringBuffer() { 793 size_t length = 0; 794 795 rapidjson::StringBuffer sb; 796 Writer writer(sb); 797 798 for (size_t i = 0; i < kItoaTrialCount; i++) { 799 for (size_t j = 0; j < randvalCount; j++) { 800 writer.WriteInt(randval[j]); 801 length += sb.GetSize(); 802 sb.Clear(); 803 } 804 } 805 OUTPUT_LENGTH(length); 806 } 807 808 template <typename Writer> 809 void itoa_Writer_InsituStringStream() { 810 size_t length = 0; 811 812 char buffer[32]; 813 Writer writer; 814 for (size_t i = 0; i < kItoaTrialCount; i++) { 815 for (size_t j = 0; j < randvalCount; j++) { 816 rapidjson::InsituStringStream ss(buffer); 817 writer.Reset(ss); 818 char* begin = ss.PutBegin(); 819 writer.WriteInt(randval[j]); 820 length += ss.PutEnd(begin); 821 } 822 } 823 OUTPUT_LENGTH(length); 824 }; 825 826 template <typename Writer> 827 void itoa64_Writer_StringBufferVerify() { 828 rapidjson::StringBuffer sb; 829 Writer writer(sb); 830 for (size_t j = 0; j < randvalCount; j++) { 831 char buffer[32]; 832 int64_t x = randval[j] * randval[j]; 833 sprintf(buffer, "%" PRIi64, x); 834 writer.WriteInt64(x); 835 ASSERT_STREQ(buffer, sb.GetString()); 836 sb.Clear(); 837 } 838 } 839 840 template <typename Writer> 841 void itoa64_Writer_InsituStringStreamVerify() { 842 Writer writer; 843 for (size_t j = 0; j < randvalCount; j++) { 844 char buffer[32]; 845 int64_t x = randval[j] * randval[j]; 846 sprintf(buffer, "%" PRIi64, x); 847 char buffer2[32]; 848 rapidjson::InsituStringStream ss(buffer2); 849 writer.Reset(ss); 850 char* begin = ss.PutBegin(); 851 writer.WriteInt64(x); 852 ss.Put('\0'); 853 ss.PutEnd(begin); 854 ASSERT_STREQ(buffer, buffer2); 855 } 856 } 857 858 template <typename Writer> 859 void itoa64_Writer_StringBuffer() { 860 size_t length = 0; 861 862 rapidjson::StringBuffer sb; 863 Writer writer(sb); 864 865 for (size_t i = 0; i < kItoaTrialCount; i++) { 866 for (size_t j = 0; j < randvalCount; j++) { 867 writer.WriteInt64(randval[j] * randval[j]); 868 length += sb.GetSize(); 869 sb.Clear(); 870 } 871 } 872 OUTPUT_LENGTH(length); 873 } 874 875 template <typename Writer> 876 void itoa64_Writer_InsituStringStream() { 877 size_t length = 0; 878 879 char buffer[32]; 880 Writer writer; 881 for (size_t i = 0; i < kItoaTrialCount; i++) { 882 for (size_t j = 0; j < randvalCount; j++) { 883 rapidjson::InsituStringStream ss(buffer); 884 writer.Reset(ss); 885 char* begin = ss.PutBegin(); 886 writer.WriteInt64(randval[j] * randval[j]); 887 length += ss.PutEnd(begin); 888 } 889 } 890 OUTPUT_LENGTH(length); 891 }; 892 893 // Full specialization for InsituStringStream to prevent memory copying 894 // (normally we will not use InsituStringStream for writing, just for testing) 895 896 namespace rapidjson { 897 898 template<> 899 bool rapidjson::Writer<InsituStringStream>::WriteInt(int i) { 900 char *buffer = os_->Push(11); 901 const char* end = internal::i32toa(i, buffer); 902 os_->Pop(11 - (end - buffer)); 903 return true; 904 } 905 906 template<> 907 bool Writer<InsituStringStream>::WriteUint(unsigned u) { 908 char *buffer = os_->Push(10); 909 const char* end = internal::u32toa(u, buffer); 910 os_->Pop(10 - (end - buffer)); 911 return true; 912 } 913 914 template<> 915 bool Writer<InsituStringStream>::WriteInt64(int64_t i64) { 916 char *buffer = os_->Push(21); 917 const char* end = internal::i64toa(i64, buffer); 918 os_->Pop(21 - (end - buffer)); 919 return true; 920 } 921 922 template<> 923 bool Writer<InsituStringStream>::WriteUint64(uint64_t u) { 924 char *buffer = os_->Push(20); 925 const char* end = internal::u64toa(u, buffer); 926 os_->Pop(20 - (end - buffer)); 927 return true; 928 } 929 930 } // namespace rapidjson 931 932 TEST_F(Misc, itoa_Writer_StringBufferVerify) { itoa_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); } 933 TEST_F(Misc, itoa_Writer1_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); } 934 TEST_F(Misc, itoa_Writer2_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); } 935 TEST_F(Misc, itoa_Writer3_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); } 936 TEST_F(Misc, itoa_Writer4_StringBufferVerify) { itoa_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); } 937 TEST_F(Misc, itoa_Writer_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); } 938 TEST_F(Misc, itoa_Writer1_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); } 939 TEST_F(Misc, itoa_Writer2_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); } 940 TEST_F(Misc, itoa_Writer3_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); } 941 TEST_F(Misc, itoa_Writer4_InsituStringStreamVerify) { itoa_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); } 942 TEST_F(Misc, itoa_Writer_StringBuffer) { itoa_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); } 943 TEST_F(Misc, itoa_Writer1_StringBuffer) { itoa_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); } 944 TEST_F(Misc, itoa_Writer2_StringBuffer) { itoa_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); } 945 TEST_F(Misc, itoa_Writer3_StringBuffer) { itoa_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); } 946 TEST_F(Misc, itoa_Writer4_StringBuffer) { itoa_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); } 947 TEST_F(Misc, itoa_Writer_InsituStringStream) { itoa_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); } 948 TEST_F(Misc, itoa_Writer1_InsituStringStream) { itoa_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); } 949 TEST_F(Misc, itoa_Writer2_InsituStringStream) { itoa_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); } 950 TEST_F(Misc, itoa_Writer3_InsituStringStream) { itoa_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); } 951 TEST_F(Misc, itoa_Writer4_InsituStringStream) { itoa_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); } 952 953 TEST_F(Misc, itoa64_Writer_StringBufferVerify) { itoa64_Writer_StringBufferVerify<rapidjson::Writer<rapidjson::StringBuffer> >(); } 954 TEST_F(Misc, itoa64_Writer1_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer1<rapidjson::StringBuffer> >(); } 955 TEST_F(Misc, itoa64_Writer2_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer2<rapidjson::StringBuffer> >(); } 956 TEST_F(Misc, itoa64_Writer3_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer3<rapidjson::StringBuffer> >(); } 957 TEST_F(Misc, itoa64_Writer4_StringBufferVerify) { itoa64_Writer_StringBufferVerify<Writer4<rapidjson::StringBuffer> >(); } 958 TEST_F(Misc, itoa64_Writer_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<rapidjson::Writer<rapidjson::InsituStringStream> >(); } 959 TEST_F(Misc, itoa64_Writer1_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer1<rapidjson::InsituStringStream> >(); } 960 TEST_F(Misc, itoa64_Writer2_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer2<rapidjson::InsituStringStream> >(); } 961 TEST_F(Misc, itoa64_Writer3_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer3<rapidjson::InsituStringStream> >(); } 962 TEST_F(Misc, itoa64_Writer4_InsituStringStreamVerify) { itoa64_Writer_InsituStringStreamVerify<Writer4<rapidjson::InsituStringStream> >(); } 963 TEST_F(Misc, itoa64_Writer_StringBuffer) { itoa64_Writer_StringBuffer<rapidjson::Writer<rapidjson::StringBuffer> >(); } 964 TEST_F(Misc, itoa64_Writer1_StringBuffer) { itoa64_Writer_StringBuffer<Writer1<rapidjson::StringBuffer> >(); } 965 TEST_F(Misc, itoa64_Writer2_StringBuffer) { itoa64_Writer_StringBuffer<Writer2<rapidjson::StringBuffer> >(); } 966 TEST_F(Misc, itoa64_Writer3_StringBuffer) { itoa64_Writer_StringBuffer<Writer3<rapidjson::StringBuffer> >(); } 967 TEST_F(Misc, itoa64_Writer4_StringBuffer) { itoa64_Writer_StringBuffer<Writer4<rapidjson::StringBuffer> >(); } 968 TEST_F(Misc, itoa64_Writer_InsituStringStream) { itoa64_Writer_InsituStringStream<rapidjson::Writer<rapidjson::InsituStringStream> >(); } 969 TEST_F(Misc, itoa64_Writer1_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer1<rapidjson::InsituStringStream> >(); } 970 TEST_F(Misc, itoa64_Writer2_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer2<rapidjson::InsituStringStream> >(); } 971 TEST_F(Misc, itoa64_Writer3_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer3<rapidjson::InsituStringStream> >(); } 972 TEST_F(Misc, itoa64_Writer4_InsituStringStream) { itoa64_Writer_InsituStringStream<Writer4<rapidjson::InsituStringStream> >(); } 973 974 #endif // TEST_MISC 975