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