Home | History | Annotate | Download | only in internal
      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 #ifndef RAPIDJSON_ITOA_
     16 #define RAPIDJSON_ITOA_
     17 
     18 #include "../rapidjson.h"
     19 
     20 RAPIDJSON_NAMESPACE_BEGIN
     21 namespace internal {
     22 
     23 inline const char* GetDigitsLut() {
     24     static const char cDigitsLut[200] = {
     25         '0','0','0','1','0','2','0','3','0','4','0','5','0','6','0','7','0','8','0','9',
     26         '1','0','1','1','1','2','1','3','1','4','1','5','1','6','1','7','1','8','1','9',
     27         '2','0','2','1','2','2','2','3','2','4','2','5','2','6','2','7','2','8','2','9',
     28         '3','0','3','1','3','2','3','3','3','4','3','5','3','6','3','7','3','8','3','9',
     29         '4','0','4','1','4','2','4','3','4','4','4','5','4','6','4','7','4','8','4','9',
     30         '5','0','5','1','5','2','5','3','5','4','5','5','5','6','5','7','5','8','5','9',
     31         '6','0','6','1','6','2','6','3','6','4','6','5','6','6','6','7','6','8','6','9',
     32         '7','0','7','1','7','2','7','3','7','4','7','5','7','6','7','7','7','8','7','9',
     33         '8','0','8','1','8','2','8','3','8','4','8','5','8','6','8','7','8','8','8','9',
     34         '9','0','9','1','9','2','9','3','9','4','9','5','9','6','9','7','9','8','9','9'
     35     };
     36     return cDigitsLut;
     37 }
     38 
     39 inline char* u32toa(uint32_t value, char* buffer) {
     40     const char* cDigitsLut = GetDigitsLut();
     41 
     42     if (value < 10000) {
     43         const uint32_t d1 = (value / 100) << 1;
     44         const uint32_t d2 = (value % 100) << 1;
     45 
     46         if (value >= 1000)
     47             *buffer++ = cDigitsLut[d1];
     48         if (value >= 100)
     49             *buffer++ = cDigitsLut[d1 + 1];
     50         if (value >= 10)
     51             *buffer++ = cDigitsLut[d2];
     52         *buffer++ = cDigitsLut[d2 + 1];
     53     }
     54     else if (value < 100000000) {
     55         // value = bbbbcccc
     56         const uint32_t b = value / 10000;
     57         const uint32_t c = value % 10000;
     58 
     59         const uint32_t d1 = (b / 100) << 1;
     60         const uint32_t d2 = (b % 100) << 1;
     61 
     62         const uint32_t d3 = (c / 100) << 1;
     63         const uint32_t d4 = (c % 100) << 1;
     64 
     65         if (value >= 10000000)
     66             *buffer++ = cDigitsLut[d1];
     67         if (value >= 1000000)
     68             *buffer++ = cDigitsLut[d1 + 1];
     69         if (value >= 100000)
     70             *buffer++ = cDigitsLut[d2];
     71         *buffer++ = cDigitsLut[d2 + 1];
     72 
     73         *buffer++ = cDigitsLut[d3];
     74         *buffer++ = cDigitsLut[d3 + 1];
     75         *buffer++ = cDigitsLut[d4];
     76         *buffer++ = cDigitsLut[d4 + 1];
     77     }
     78     else {
     79         // value = aabbbbcccc in decimal
     80 
     81         const uint32_t a = value / 100000000; // 1 to 42
     82         value %= 100000000;
     83 
     84         if (a >= 10) {
     85             const unsigned i = a << 1;
     86             *buffer++ = cDigitsLut[i];
     87             *buffer++ = cDigitsLut[i + 1];
     88         }
     89         else
     90             *buffer++ = static_cast<char>('0' + static_cast<char>(a));
     91 
     92         const uint32_t b = value / 10000; // 0 to 9999
     93         const uint32_t c = value % 10000; // 0 to 9999
     94 
     95         const uint32_t d1 = (b / 100) << 1;
     96         const uint32_t d2 = (b % 100) << 1;
     97 
     98         const uint32_t d3 = (c / 100) << 1;
     99         const uint32_t d4 = (c % 100) << 1;
    100 
    101         *buffer++ = cDigitsLut[d1];
    102         *buffer++ = cDigitsLut[d1 + 1];
    103         *buffer++ = cDigitsLut[d2];
    104         *buffer++ = cDigitsLut[d2 + 1];
    105         *buffer++ = cDigitsLut[d3];
    106         *buffer++ = cDigitsLut[d3 + 1];
    107         *buffer++ = cDigitsLut[d4];
    108         *buffer++ = cDigitsLut[d4 + 1];
    109     }
    110     return buffer;
    111 }
    112 
    113 inline char* i32toa(int32_t value, char* buffer) {
    114     uint32_t u = static_cast<uint32_t>(value);
    115     if (value < 0) {
    116         *buffer++ = '-';
    117         u = ~u + 1;
    118     }
    119 
    120     return u32toa(u, buffer);
    121 }
    122 
    123 inline char* u64toa(uint64_t value, char* buffer) {
    124     const char* cDigitsLut = GetDigitsLut();
    125     const uint64_t  kTen8 = 100000000;
    126     const uint64_t  kTen9 = kTen8 * 10;
    127     const uint64_t kTen10 = kTen8 * 100;
    128     const uint64_t kTen11 = kTen8 * 1000;
    129     const uint64_t kTen12 = kTen8 * 10000;
    130     const uint64_t kTen13 = kTen8 * 100000;
    131     const uint64_t kTen14 = kTen8 * 1000000;
    132     const uint64_t kTen15 = kTen8 * 10000000;
    133     const uint64_t kTen16 = kTen8 * kTen8;
    134 
    135     if (value < kTen8) {
    136         uint32_t v = static_cast<uint32_t>(value);
    137         if (v < 10000) {
    138             const uint32_t d1 = (v / 100) << 1;
    139             const uint32_t d2 = (v % 100) << 1;
    140 
    141             if (v >= 1000)
    142                 *buffer++ = cDigitsLut[d1];
    143             if (v >= 100)
    144                 *buffer++ = cDigitsLut[d1 + 1];
    145             if (v >= 10)
    146                 *buffer++ = cDigitsLut[d2];
    147             *buffer++ = cDigitsLut[d2 + 1];
    148         }
    149         else {
    150             // value = bbbbcccc
    151             const uint32_t b = v / 10000;
    152             const uint32_t c = v % 10000;
    153 
    154             const uint32_t d1 = (b / 100) << 1;
    155             const uint32_t d2 = (b % 100) << 1;
    156 
    157             const uint32_t d3 = (c / 100) << 1;
    158             const uint32_t d4 = (c % 100) << 1;
    159 
    160             if (value >= 10000000)
    161                 *buffer++ = cDigitsLut[d1];
    162             if (value >= 1000000)
    163                 *buffer++ = cDigitsLut[d1 + 1];
    164             if (value >= 100000)
    165                 *buffer++ = cDigitsLut[d2];
    166             *buffer++ = cDigitsLut[d2 + 1];
    167 
    168             *buffer++ = cDigitsLut[d3];
    169             *buffer++ = cDigitsLut[d3 + 1];
    170             *buffer++ = cDigitsLut[d4];
    171             *buffer++ = cDigitsLut[d4 + 1];
    172         }
    173     }
    174     else if (value < kTen16) {
    175         const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
    176         const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
    177 
    178         const uint32_t b0 = v0 / 10000;
    179         const uint32_t c0 = v0 % 10000;
    180 
    181         const uint32_t d1 = (b0 / 100) << 1;
    182         const uint32_t d2 = (b0 % 100) << 1;
    183 
    184         const uint32_t d3 = (c0 / 100) << 1;
    185         const uint32_t d4 = (c0 % 100) << 1;
    186 
    187         const uint32_t b1 = v1 / 10000;
    188         const uint32_t c1 = v1 % 10000;
    189 
    190         const uint32_t d5 = (b1 / 100) << 1;
    191         const uint32_t d6 = (b1 % 100) << 1;
    192 
    193         const uint32_t d7 = (c1 / 100) << 1;
    194         const uint32_t d8 = (c1 % 100) << 1;
    195 
    196         if (value >= kTen15)
    197             *buffer++ = cDigitsLut[d1];
    198         if (value >= kTen14)
    199             *buffer++ = cDigitsLut[d1 + 1];
    200         if (value >= kTen13)
    201             *buffer++ = cDigitsLut[d2];
    202         if (value >= kTen12)
    203             *buffer++ = cDigitsLut[d2 + 1];
    204         if (value >= kTen11)
    205             *buffer++ = cDigitsLut[d3];
    206         if (value >= kTen10)
    207             *buffer++ = cDigitsLut[d3 + 1];
    208         if (value >= kTen9)
    209             *buffer++ = cDigitsLut[d4];
    210         if (value >= kTen8)
    211             *buffer++ = cDigitsLut[d4 + 1];
    212 
    213         *buffer++ = cDigitsLut[d5];
    214         *buffer++ = cDigitsLut[d5 + 1];
    215         *buffer++ = cDigitsLut[d6];
    216         *buffer++ = cDigitsLut[d6 + 1];
    217         *buffer++ = cDigitsLut[d7];
    218         *buffer++ = cDigitsLut[d7 + 1];
    219         *buffer++ = cDigitsLut[d8];
    220         *buffer++ = cDigitsLut[d8 + 1];
    221     }
    222     else {
    223         const uint32_t a = static_cast<uint32_t>(value / kTen16); // 1 to 1844
    224         value %= kTen16;
    225 
    226         if (a < 10)
    227             *buffer++ = static_cast<char>('0' + static_cast<char>(a));
    228         else if (a < 100) {
    229             const uint32_t i = a << 1;
    230             *buffer++ = cDigitsLut[i];
    231             *buffer++ = cDigitsLut[i + 1];
    232         }
    233         else if (a < 1000) {
    234             *buffer++ = static_cast<char>('0' + static_cast<char>(a / 100));
    235 
    236             const uint32_t i = (a % 100) << 1;
    237             *buffer++ = cDigitsLut[i];
    238             *buffer++ = cDigitsLut[i + 1];
    239         }
    240         else {
    241             const uint32_t i = (a / 100) << 1;
    242             const uint32_t j = (a % 100) << 1;
    243             *buffer++ = cDigitsLut[i];
    244             *buffer++ = cDigitsLut[i + 1];
    245             *buffer++ = cDigitsLut[j];
    246             *buffer++ = cDigitsLut[j + 1];
    247         }
    248 
    249         const uint32_t v0 = static_cast<uint32_t>(value / kTen8);
    250         const uint32_t v1 = static_cast<uint32_t>(value % kTen8);
    251 
    252         const uint32_t b0 = v0 / 10000;
    253         const uint32_t c0 = v0 % 10000;
    254 
    255         const uint32_t d1 = (b0 / 100) << 1;
    256         const uint32_t d2 = (b0 % 100) << 1;
    257 
    258         const uint32_t d3 = (c0 / 100) << 1;
    259         const uint32_t d4 = (c0 % 100) << 1;
    260 
    261         const uint32_t b1 = v1 / 10000;
    262         const uint32_t c1 = v1 % 10000;
    263 
    264         const uint32_t d5 = (b1 / 100) << 1;
    265         const uint32_t d6 = (b1 % 100) << 1;
    266 
    267         const uint32_t d7 = (c1 / 100) << 1;
    268         const uint32_t d8 = (c1 % 100) << 1;
    269 
    270         *buffer++ = cDigitsLut[d1];
    271         *buffer++ = cDigitsLut[d1 + 1];
    272         *buffer++ = cDigitsLut[d2];
    273         *buffer++ = cDigitsLut[d2 + 1];
    274         *buffer++ = cDigitsLut[d3];
    275         *buffer++ = cDigitsLut[d3 + 1];
    276         *buffer++ = cDigitsLut[d4];
    277         *buffer++ = cDigitsLut[d4 + 1];
    278         *buffer++ = cDigitsLut[d5];
    279         *buffer++ = cDigitsLut[d5 + 1];
    280         *buffer++ = cDigitsLut[d6];
    281         *buffer++ = cDigitsLut[d6 + 1];
    282         *buffer++ = cDigitsLut[d7];
    283         *buffer++ = cDigitsLut[d7 + 1];
    284         *buffer++ = cDigitsLut[d8];
    285         *buffer++ = cDigitsLut[d8 + 1];
    286     }
    287 
    288     return buffer;
    289 }
    290 
    291 inline char* i64toa(int64_t value, char* buffer) {
    292     uint64_t u = static_cast<uint64_t>(value);
    293     if (value < 0) {
    294         *buffer++ = '-';
    295         u = ~u + 1;
    296     }
    297 
    298     return u64toa(u, buffer);
    299 }
    300 
    301 } // namespace internal
    302 RAPIDJSON_NAMESPACE_END
    303 
    304 #endif // RAPIDJSON_ITOA_
    305