1e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Tencent is pleased to support the open source community by making RapidJSON available.
2e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
3e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
4e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
5e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Licensed under the MIT License (the "License"); you may not use this file except
6e462795ff5d4c7359f9e8637c10544bb2de70107tturney// in compliance with the License. You may obtain a copy of the License at
7e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
8e462795ff5d4c7359f9e8637c10544bb2de70107tturney// http://opensource.org/licenses/MIT
9e462795ff5d4c7359f9e8637c10544bb2de70107tturney//
10e462795ff5d4c7359f9e8637c10544bb2de70107tturney// Unless required by applicable law or agreed to in writing, software distributed
11e462795ff5d4c7359f9e8637c10544bb2de70107tturney// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12e462795ff5d4c7359f9e8637c10544bb2de70107tturney// CONDITIONS OF ANY KIND, either express or implied. See the License for the
13e462795ff5d4c7359f9e8637c10544bb2de70107tturney// specific language governing permissions and limitations under the License.
14e462795ff5d4c7359f9e8637c10544bb2de70107tturney
15e462795ff5d4c7359f9e8637c10544bb2de70107tturney#include "unittest.h"
16e462795ff5d4c7359f9e8637c10544bb2de70107tturney#include "rapidjson/internal/itoa.h"
17e462795ff5d4c7359f9e8637c10544bb2de70107tturney
18e462795ff5d4c7359f9e8637c10544bb2de70107tturney#ifdef __GNUC__
19e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_PUSH
20e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_OFF(type-limits)
21e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
22e462795ff5d4c7359f9e8637c10544bb2de70107tturney
23e462795ff5d4c7359f9e8637c10544bb2de70107tturneyusing namespace rapidjson::internal;
24e462795ff5d4c7359f9e8637c10544bb2de70107tturney
25e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T>
26e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct Traits {
27e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
28e462795ff5d4c7359f9e8637c10544bb2de70107tturney
29e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <>
30e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct Traits<uint32_t> {
31e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kBufferSize = 11 };
32e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kMaxDigit = 10 };
33e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static uint32_t Negate(uint32_t x) { return x; };
34e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
35e462795ff5d4c7359f9e8637c10544bb2de70107tturney
36e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <>
37e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct Traits<int32_t> {
38e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kBufferSize = 12 };
39e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kMaxDigit = 10 };
40e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static int32_t Negate(int32_t x) { return -x; };
41e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
42e462795ff5d4c7359f9e8637c10544bb2de70107tturney
43e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <>
44e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct Traits<uint64_t> {
45e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kBufferSize = 21 };
46e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kMaxDigit = 20 };
47e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static uint64_t Negate(uint64_t x) { return x; };
48e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
49e462795ff5d4c7359f9e8637c10544bb2de70107tturney
50e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <>
51e462795ff5d4c7359f9e8637c10544bb2de70107tturneystruct Traits<int64_t> {
52e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kBufferSize = 22 };
53e462795ff5d4c7359f9e8637c10544bb2de70107tturney    enum { kMaxDigit = 20 };
54e462795ff5d4c7359f9e8637c10544bb2de70107tturney    static int64_t Negate(int64_t x) { return -x; };
55e462795ff5d4c7359f9e8637c10544bb2de70107tturney};
56e462795ff5d4c7359f9e8637c10544bb2de70107tturney
57e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T>
58e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void VerifyValue(T value, void(*f)(T, char*), char* (*g)(T, char*)) {
59e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char buffer1[Traits<T>::kBufferSize];
60e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char buffer2[Traits<T>::kBufferSize];
61e462795ff5d4c7359f9e8637c10544bb2de70107tturney
62e462795ff5d4c7359f9e8637c10544bb2de70107tturney    f(value, buffer1);
63e462795ff5d4c7359f9e8637c10544bb2de70107tturney    *g(value, buffer2) = '\0';
64e462795ff5d4c7359f9e8637c10544bb2de70107tturney
65e462795ff5d4c7359f9e8637c10544bb2de70107tturney
66e462795ff5d4c7359f9e8637c10544bb2de70107tturney    EXPECT_STREQ(buffer1, buffer2);
67e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
68e462795ff5d4c7359f9e8637c10544bb2de70107tturney
69e462795ff5d4c7359f9e8637c10544bb2de70107tturneytemplate <typename T>
70e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void Verify(void(*f)(T, char*), char* (*g)(T, char*)) {
71e462795ff5d4c7359f9e8637c10544bb2de70107tturney    // Boundary cases
72e462795ff5d4c7359f9e8637c10544bb2de70107tturney    VerifyValue<T>(0, f, g);
73e462795ff5d4c7359f9e8637c10544bb2de70107tturney    VerifyValue<T>(std::numeric_limits<T>::min(), f, g);
74e462795ff5d4c7359f9e8637c10544bb2de70107tturney    VerifyValue<T>(std::numeric_limits<T>::max(), f, g);
75e462795ff5d4c7359f9e8637c10544bb2de70107tturney
76e462795ff5d4c7359f9e8637c10544bb2de70107tturney    // 2^n - 1, 2^n, 10^n - 1, 10^n until overflow
77e462795ff5d4c7359f9e8637c10544bb2de70107tturney    for (uint32_t power = 2; power <= 10; power += 8) {
78e462795ff5d4c7359f9e8637c10544bb2de70107tturney        T i = 1, last;
79e462795ff5d4c7359f9e8637c10544bb2de70107tturney        do {
80e462795ff5d4c7359f9e8637c10544bb2de70107tturney            VerifyValue<T>(i - 1, f, g);
81e462795ff5d4c7359f9e8637c10544bb2de70107tturney            VerifyValue<T>(i, f, g);
82e462795ff5d4c7359f9e8637c10544bb2de70107tturney            if (std::numeric_limits<T>::min() < 0) {
83e462795ff5d4c7359f9e8637c10544bb2de70107tturney                VerifyValue<T>(Traits<T>::Negate(i), f, g);
84e462795ff5d4c7359f9e8637c10544bb2de70107tturney                VerifyValue<T>(Traits<T>::Negate(i + 1), f, g);
85e462795ff5d4c7359f9e8637c10544bb2de70107tturney            }
86e462795ff5d4c7359f9e8637c10544bb2de70107tturney            last = i;
87e462795ff5d4c7359f9e8637c10544bb2de70107tturney            i *= power;
88e462795ff5d4c7359f9e8637c10544bb2de70107tturney        } while (last < i);
89e462795ff5d4c7359f9e8637c10544bb2de70107tturney    }
90e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
91e462795ff5d4c7359f9e8637c10544bb2de70107tturney
92e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void u32toa_naive(uint32_t value, char* buffer) {
93e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char temp[10];
94e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char *p = temp;
95e462795ff5d4c7359f9e8637c10544bb2de70107tturney    do {
96e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *p++ = char(value % 10) + '0';
97e462795ff5d4c7359f9e8637c10544bb2de70107tturney        value /= 10;
98e462795ff5d4c7359f9e8637c10544bb2de70107tturney    } while (value > 0);
99e462795ff5d4c7359f9e8637c10544bb2de70107tturney
100e462795ff5d4c7359f9e8637c10544bb2de70107tturney    do {
101e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *buffer++ = *--p;
102e462795ff5d4c7359f9e8637c10544bb2de70107tturney    } while (p != temp);
103e462795ff5d4c7359f9e8637c10544bb2de70107tturney
104e462795ff5d4c7359f9e8637c10544bb2de70107tturney    *buffer = '\0';
105e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
106e462795ff5d4c7359f9e8637c10544bb2de70107tturney
107e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void i32toa_naive(int32_t value, char* buffer) {
108e462795ff5d4c7359f9e8637c10544bb2de70107tturney    uint32_t u = static_cast<uint32_t>(value);
109e462795ff5d4c7359f9e8637c10544bb2de70107tturney    if (value < 0) {
110e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *buffer++ = '-';
111e462795ff5d4c7359f9e8637c10544bb2de70107tturney        u = ~u + 1;
112e462795ff5d4c7359f9e8637c10544bb2de70107tturney    }
113e462795ff5d4c7359f9e8637c10544bb2de70107tturney    u32toa_naive(u, buffer);
114e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
115e462795ff5d4c7359f9e8637c10544bb2de70107tturney
116e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void u64toa_naive(uint64_t value, char* buffer) {
117e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char temp[20];
118e462795ff5d4c7359f9e8637c10544bb2de70107tturney    char *p = temp;
119e462795ff5d4c7359f9e8637c10544bb2de70107tturney    do {
120e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *p++ = char(value % 10) + '0';
121e462795ff5d4c7359f9e8637c10544bb2de70107tturney        value /= 10;
122e462795ff5d4c7359f9e8637c10544bb2de70107tturney    } while (value > 0);
123e462795ff5d4c7359f9e8637c10544bb2de70107tturney
124e462795ff5d4c7359f9e8637c10544bb2de70107tturney    do {
125e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *buffer++ = *--p;
126e462795ff5d4c7359f9e8637c10544bb2de70107tturney    } while (p != temp);
127e462795ff5d4c7359f9e8637c10544bb2de70107tturney
128e462795ff5d4c7359f9e8637c10544bb2de70107tturney    *buffer = '\0';
129e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
130e462795ff5d4c7359f9e8637c10544bb2de70107tturney
131e462795ff5d4c7359f9e8637c10544bb2de70107tturneystatic void i64toa_naive(int64_t value, char* buffer) {
132e462795ff5d4c7359f9e8637c10544bb2de70107tturney    uint64_t u = static_cast<uint64_t>(value);
133e462795ff5d4c7359f9e8637c10544bb2de70107tturney    if (value < 0) {
134e462795ff5d4c7359f9e8637c10544bb2de70107tturney        *buffer++ = '-';
135e462795ff5d4c7359f9e8637c10544bb2de70107tturney        u = ~u + 1;
136e462795ff5d4c7359f9e8637c10544bb2de70107tturney    }
137e462795ff5d4c7359f9e8637c10544bb2de70107tturney    u64toa_naive(u, buffer);
138e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
139e462795ff5d4c7359f9e8637c10544bb2de70107tturney
140e462795ff5d4c7359f9e8637c10544bb2de70107tturneyTEST(itoa, u32toa) {
141e462795ff5d4c7359f9e8637c10544bb2de70107tturney    Verify(u32toa_naive, u32toa);
142e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
143e462795ff5d4c7359f9e8637c10544bb2de70107tturney
144e462795ff5d4c7359f9e8637c10544bb2de70107tturneyTEST(itoa, i32toa) {
145e462795ff5d4c7359f9e8637c10544bb2de70107tturney    Verify(i32toa_naive, i32toa);
146e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
147e462795ff5d4c7359f9e8637c10544bb2de70107tturney
148e462795ff5d4c7359f9e8637c10544bb2de70107tturneyTEST(itoa, u64toa) {
149e462795ff5d4c7359f9e8637c10544bb2de70107tturney    Verify(u64toa_naive, u64toa);
150e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
151e462795ff5d4c7359f9e8637c10544bb2de70107tturney
152e462795ff5d4c7359f9e8637c10544bb2de70107tturneyTEST(itoa, i64toa) {
153e462795ff5d4c7359f9e8637c10544bb2de70107tturney    Verify(i64toa_naive, i64toa);
154e462795ff5d4c7359f9e8637c10544bb2de70107tturney}
155e462795ff5d4c7359f9e8637c10544bb2de70107tturney
156e462795ff5d4c7359f9e8637c10544bb2de70107tturney#ifdef __GNUC__
157e462795ff5d4c7359f9e8637c10544bb2de70107tturneyRAPIDJSON_DIAG_POP
158e462795ff5d4c7359f9e8637c10544bb2de70107tturney#endif
159