aboutsummaryrefslogtreecommitdiffstats
path: root/vendor/github.com/byzantine-lab/mcl/include/cybozu/atoi.hpp
blob: a22853a17a9ab46a6f66546dde722c246dfe7988 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#pragma once
/**
    @file
    @brief converter between integer and string

    @author MITSUNARI Shigeo(@herumi)
*/

#include <memory.h>
#include <limits.h>
#include <limits>
#include <cybozu/exception.hpp>

namespace cybozu {

namespace atoi_local {

template<typename T, size_t n>
T convertToInt(bool *b, const char *p, size_t size, const char (&max)[n], T min, T overflow1, char overflow2)
{
    if (size > 0 && *p) {
        bool isMinus = false;
        size_t i = 0;
        if (*p == '-') {
            isMinus = true;
            i++;
        }
        if (i < size && p[i]) {
            // skip leading zero
            while (i < size && p[i] == '0') i++;
            // check minimum
            if (isMinus && size - i >= n - 1 && memcmp(max, &p[i], n - 1) == 0) {
                if (b) *b = true;
                return min;
            }
            T x = 0;
            for (;;) {
                unsigned char c;
                if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
                    if (b) *b = true;
                    return isMinus ? -x : x;
                }
                unsigned int y = c - '0';
                if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) {
                    break;
                }
                x = x * 10 + T(y);
                i++;
            }
        }
    }
    if (b) {
        *b = false;
        return 0;
    } else {
        throw cybozu::Exception("atoi::convertToInt") << cybozu::exception::makeString(p, size);
    }
}

template<typename T>
T convertToUint(bool *b, const char *p, size_t size, T overflow1, char overflow2)
{
    if (size > 0 && *p) {
        size_t i = 0;
        // skip leading zero
        while (i < size && p[i] == '0') i++;
        T x = 0;
        for (;;) {
            unsigned char c;
            if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
                if (b) *b = true;
                return x;
            }
            unsigned int y = c - '0';
            if (y > 9 || x > overflow1 || (x == overflow1 && c >= overflow2)) {
                break;
            }
            x = x * 10 + T(y);
            i++;
        }
    }
    if (b) {
        *b = false;
        return 0;
    } else {
        throw cybozu::Exception("atoi::convertToUint") << cybozu::exception::makeString(p, size);
    }
}

template<typename T>
T convertHexToInt(bool *b, const char *p, size_t size)
{
    if (size > 0 && *p) {
        size_t i = 0;
        T x = 0;
        for (;;) {
            unsigned int c;
            if (i == size || (c = static_cast<unsigned char>(p[i])) == '\0') {
                if (b) *b = true;
                return x;
            }
            if (c - 'A' <= 'F' - 'A') {
                c = (c - 'A') + 10;
            } else if (c - 'a' <= 'f' - 'a') {
                c = (c - 'a') + 10;
            } else if (c - '0' <= '9' - '0') {
                c = c - '0';
            } else {
                break;
            }
            // avoid overflow
            if (x > (std::numeric_limits<T>::max)() / 16) break;
            x = x * 16 + T(c);
            i++;
        }
    }
    if (b) {
        *b = false;
        return 0;
    } else {
        throw cybozu::Exception("atoi::convertHexToInt") << cybozu::exception::makeString(p, size);
    }
}

} // atoi_local

/**
    auto detect return value class
    @note if you set bool pointer p then throw nothing and set *p = false if bad string
*/
class atoi {
    const char *p_;
    size_t size_;
    bool *b_;
    void set(bool *b, const char *p, size_t size)
    {
        b_ = b;
        p_ = p;
        size_ = size;
    }
public:
    atoi(const char *p, size_t size = -1)
    {
        set(0, p, size);
    }
    atoi(bool *b, const char *p, size_t size = -1)
    {
        set(b, p, size);
    }
    atoi(const std::string& str)
    {
        set(0, str.c_str(), str.size());
    }
    atoi(bool *b, const std::string& str)
    {
        set(b, str.c_str(), str.size());
    }
    inline operator signed char() const
    {
        return atoi_local::convertToInt<signed char>(b_, p_, size_, "128", -128, 12, '8');
    }
    inline operator unsigned char() const
    {
        return atoi_local::convertToUint<unsigned char>(b_, p_, size_, 25, '6');
    }
    inline operator short() const
    {
        return atoi_local::convertToInt<short>(b_, p_, size_, "32768", -32768, 3276, '8');
    }
    inline operator unsigned short() const
    {
        return atoi_local::convertToUint<unsigned short>(b_, p_, size_, 6553, '6');
    }
    inline operator int() const
    {
        return atoi_local::convertToInt<int>(b_, p_, size_, "2147483648", INT_MIN, 214748364, '8');
    }
    inline operator unsigned int() const
    {
        return atoi_local::convertToUint<unsigned int>(b_, p_, size_, 429496729, '6');
    }
    inline operator long long() const
    {
        return atoi_local::convertToInt<long long>(b_, p_, size_, "9223372036854775808", LLONG_MIN, 922337203685477580LL, '8');
    }
    inline operator unsigned long long() const
    {
        return atoi_local::convertToUint<unsigned long long>(b_, p_, size_, 1844674407370955161ULL, '6');
    }
#if defined(__SIZEOF_LONG__) && (__SIZEOF_LONG__ == 8)
    inline operator long() const { return static_cast<long>(static_cast<long long>(*this)); }
    inline operator unsigned long() const { return static_cast<unsigned long>(static_cast<unsigned long long>(*this)); }
#else
    inline operator long() const { return static_cast<long>(static_cast<int>(*this)); }
    inline operator unsigned long() const { return static_cast<unsigned long>(static_cast<unsigned int>(*this)); }
#endif
};

class hextoi {
    const char *p_;
    size_t size_;
    bool *b_;
    void set(bool *b, const char *p, size_t size)
    {
        b_ = b;
        p_ = p;
        size_ = size;
    }
public:
    hextoi(const char *p, size_t size = -1)
    {
        set(0, p, size);
    }
    hextoi(bool *b, const char *p, size_t size = -1)
    {
        set(b, p, size);
    }
    hextoi(const std::string& str)
    {
        set(0, str.c_str(), str.size());
    }
    hextoi(bool *b, const std::string& str)
    {
        set(b, str.c_str(), str.size());
    }
    operator unsigned char() const { return atoi_local::convertHexToInt<unsigned char>(b_, p_, size_); }
    operator unsigned short() const { return atoi_local::convertHexToInt<unsigned short>(b_, p_, size_); }
    operator unsigned int() const { return atoi_local::convertHexToInt<unsigned int>(b_, p_, size_); }
    operator unsigned long() const { return atoi_local::convertHexToInt<unsigned long>(b_, p_, size_); }
    operator unsigned long long() const { return atoi_local::convertHexToInt<unsigned long long>(b_, p_, size_); }
    operator char() const { return atoi_local::convertHexToInt<char>(b_, p_, size_); }
    operator signed char() const { return atoi_local::convertHexToInt<signed char>(b_, p_, size_); }
    operator short() const { return atoi_local::convertHexToInt<short>(b_, p_, size_); }
    operator int() const { return atoi_local::convertHexToInt<int>(b_, p_, size_); }
    operator long() const { return atoi_local::convertHexToInt<long>(b_, p_, size_); }
    operator long long() const { return atoi_local::convertHexToInt<long long>(b_, p_, size_); }
};

} // cybozu