misctest.cpp 35 KB

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