itoatest.cpp 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  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 (int 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. if (i > static_cast<T>(std::numeric_limits<T>::max() / static_cast<T>(power)))
  74. break;
  75. i *= static_cast<T>(power);
  76. } while (last < i);
  77. }
  78. }
  79. static void u32toa_naive(uint32_t value, char* buffer) {
  80. char temp[10];
  81. char *p = temp;
  82. do {
  83. *p++ = static_cast<char>(char(value % 10) + '0');
  84. value /= 10;
  85. } while (value > 0);
  86. do {
  87. *buffer++ = *--p;
  88. } while (p != temp);
  89. *buffer = '\0';
  90. }
  91. static void i32toa_naive(int32_t value, char* buffer) {
  92. uint32_t u = static_cast<uint32_t>(value);
  93. if (value < 0) {
  94. *buffer++ = '-';
  95. u = ~u + 1;
  96. }
  97. u32toa_naive(u, buffer);
  98. }
  99. static void u64toa_naive(uint64_t value, char* buffer) {
  100. char temp[20];
  101. char *p = temp;
  102. do {
  103. *p++ = static_cast<char>(char(value % 10) + '0');
  104. value /= 10;
  105. } while (value > 0);
  106. do {
  107. *buffer++ = *--p;
  108. } while (p != temp);
  109. *buffer = '\0';
  110. }
  111. static void i64toa_naive(int64_t value, char* buffer) {
  112. uint64_t u = static_cast<uint64_t>(value);
  113. if (value < 0) {
  114. *buffer++ = '-';
  115. u = ~u + 1;
  116. }
  117. u64toa_naive(u, buffer);
  118. }
  119. TEST(itoa, u32toa) {
  120. Verify(u32toa_naive, u32toa);
  121. }
  122. TEST(itoa, i32toa) {
  123. Verify(i32toa_naive, i32toa);
  124. }
  125. TEST(itoa, u64toa) {
  126. Verify(u64toa_naive, u64toa);
  127. }
  128. TEST(itoa, i64toa) {
  129. Verify(i64toa_naive, i64toa);
  130. }
  131. #ifdef __GNUC__
  132. RAPIDJSON_DIAG_POP
  133. #endif