itoatest.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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 "unittest.h"
  15. #include "rapidjson/internal/itoa.h"
  16. #ifdef __GNUC__
  17. RAPIDJSON_DIAG_PUSH
  18. RAPIDJSON_DIAG_OFF(type-limits)
  19. #endif
  20. using namespace rapidjson::internal;
  21. template <typename T>
  22. struct Traits {
  23. };
  24. template <>
  25. struct Traits<uint32_t> {
  26. enum { kBufferSize = 11 };
  27. enum { kMaxDigit = 10 };
  28. static uint32_t Negate(uint32_t x) { return x; }
  29. };
  30. template <>
  31. struct Traits<int32_t> {
  32. enum { kBufferSize = 12 };
  33. enum { kMaxDigit = 10 };
  34. static int32_t Negate(int32_t x) { return -x; }
  35. };
  36. template <>
  37. struct Traits<uint64_t> {
  38. enum { kBufferSize = 21 };
  39. enum { kMaxDigit = 20 };
  40. static uint64_t Negate(uint64_t x) { return x; }
  41. };
  42. template <>
  43. struct Traits<int64_t> {
  44. enum { kBufferSize = 22 };
  45. enum { kMaxDigit = 20 };
  46. static int64_t Negate(int64_t x) { return -x; }
  47. };
  48. template <typename T>
  49. static void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) {
  50. char buffer1[Traits<T>::kBufferSize];
  51. char buffer2[Traits<T>::kBufferSize];
  52. f(value, buffer1);
  53. *g(value, buffer2) = '\0';
  54. EXPECT_STREQ(buffer1, buffer2);
  55. }
  56. template <typename T>
  57. static void Verify(void(*f)(T, char*), char* (*g)(T, char*)) {
  58. // Boundary cases
  59. VerifyValue<T>(0, f, g);
  60. VerifyValue<T>(std::numeric_limits<T>::min(), f, g);
  61. VerifyValue<T>(std::numeric_limits<T>::max(), f, g);
  62. // 2^n - 1, 2^n, 10^n - 1, 10^n until overflow
  63. for (uint32_t power = 2; power <= 10; power += 8) {
  64. T i = 1, last;
  65. do {
  66. VerifyValue<T>(i - 1, f, g);
  67. VerifyValue<T>(i, f, g);
  68. if (std::numeric_limits<T>::min() < 0) {
  69. VerifyValue<T>(Traits<T>::Negate(i), f, g);
  70. VerifyValue<T>(Traits<T>::Negate(i + 1), f, g);
  71. }
  72. last = i;
  73. i *= power;
  74. } while (last < i);
  75. }
  76. }
  77. static void u32toa_naive(uint32_t value, char* buffer) {
  78. char temp[10];
  79. char *p = temp;
  80. do {
  81. *p++ = char(value % 10) + '0';
  82. value /= 10;
  83. } while (value > 0);
  84. do {
  85. *buffer++ = *--p;
  86. } while (p != temp);
  87. *buffer = '\0';
  88. }
  89. static void i32toa_naive(int32_t value, char* buffer) {
  90. uint32_t u = static_cast<uint32_t>(value);
  91. if (value < 0) {
  92. *buffer++ = '-';
  93. u = ~u + 1;
  94. }
  95. u32toa_naive(u, buffer);
  96. }
  97. static void u64toa_naive(uint64_t value, char* buffer) {
  98. char temp[20];
  99. char *p = temp;
  100. do {
  101. *p++ = char(value % 10) + '0';
  102. value /= 10;
  103. } while (value > 0);
  104. do {
  105. *buffer++ = *--p;
  106. } while (p != temp);
  107. *buffer = '\0';
  108. }
  109. static void i64toa_naive(int64_t value, char* buffer) {
  110. uint64_t u = static_cast<uint64_t>(value);
  111. if (value < 0) {
  112. *buffer++ = '-';
  113. u = ~u + 1;
  114. }
  115. u64toa_naive(u, buffer);
  116. }
  117. TEST(itoa, u32toa) {
  118. Verify(u32toa_naive, u32toa);
  119. }
  120. TEST(itoa, i32toa) {
  121. Verify(i32toa_naive, i32toa);
  122. }
  123. TEST(itoa, u64toa) {
  124. Verify(u64toa_naive, u64toa);
  125. }
  126. TEST(itoa, i64toa) {
  127. Verify(i64toa_naive, i64toa);
  128. }
  129. #ifdef __GNUC__
  130. RAPIDJSON_DIAG_POP
  131. #endif