1
// Copyright 2014 BitPay Inc.
2
// Copyright 2015 Bitcoin Core Developers
3
// Distributed under the MIT software license, see the accompanying
4
// file COPYING or https://opensource.org/licenses/mit-license.php.
5

            
6
#include <stdint.h>
7
#include <errno.h>
8
#include <string.h>
9
#include <stdlib.h>
10
#include <stdexcept>
11
#include <vector>
12
#include <limits>
13
#include <string>
14
#include <sstream>
15

            
16
#include "univalue.h"
17

            
18
namespace
19
{
20
static bool ParsePrechecks(const std::string& str)
21
{
22
    if (str.empty()) // No empty string allowed
23
        return false;
24
    if (str.size() >= 1 && (json_isspace(str[0]) || json_isspace(str[str.size()-1]))) // No padding allowed
25
        return false;
26
    if (str.size() != strlen(str.c_str())) // No embedded NUL characters allowed
27
        return false;
28
    return true;
29
}
30

            
31
bool ParseInt32(const std::string& str, int32_t *out)
32
{
33
    if (!ParsePrechecks(str))
34
        return false;
35
    char *endp = nullptr;
36
    errno = 0; // strtol will not set errno if valid
37
    long int n = strtol(str.c_str(), &endp, 10);
38
    if(out) *out = (int32_t)n;
39
    // Note that strtol returns a *long int*, so even if strtol doesn't report an over/underflow
40
    // we still have to check that the returned value is within the range of an *int32_t*. On 64-bit
41
    // platforms the size of these types may be different.
42
    return endp && *endp == 0 && !errno &&
43
        n >= std::numeric_limits<int32_t>::min() &&
44
        n <= std::numeric_limits<int32_t>::max();
45
}
46

            
47
bool ParseInt64(const std::string& str, int64_t *out)
48
{
49
    if (!ParsePrechecks(str))
50
        return false;
51
    char *endp = nullptr;
52
    errno = 0; // strtoll will not set errno if valid
53
    long long int n = strtoll(str.c_str(), &endp, 10);
54
    if(out) *out = (int64_t)n;
55
    // Note that strtoll returns a *long long int*, so even if strtol doesn't report a over/underflow
56
    // we still have to check that the returned value is within the range of an *int64_t*.
57
    return endp && *endp == 0 && !errno &&
58
        n >= std::numeric_limits<int64_t>::min() &&
59
        n <= std::numeric_limits<int64_t>::max();
60
}
61

            
62
bool ParseDouble(const std::string& str, double *out)
63
{
64
    if (!ParsePrechecks(str))
65
        return false;
66
    if (str.size() >= 2 && str[0] == '0' && str[1] == 'x') // No hexadecimal floats allowed
67
        return false;
68
    std::istringstream text(str);
69
    text.imbue(std::locale::classic());
70
    double result;
71
    text >> result;
72
    if(out) *out = result;
73
    return text.eof() && !text.fail();
74
}
75
}
76

            
77
const std::vector<std::string>& UniValue::getKeys() const
78
{
79
    if (typ != VOBJ)
80
        throw std::runtime_error("JSON value is not an object as expected");
81
    return keys;
82
}
83

            
84
const std::vector<UniValue>& UniValue::getValues() const
85
{
86
    if (typ != VOBJ && typ != VARR)
87
        throw std::runtime_error("JSON value is not an object or array as expected");
88
    return values;
89
}
90

            
91
bool UniValue::get_bool() const
92
{
93
    if (typ != VBOOL)
94
        throw std::runtime_error("JSON value is not a boolean as expected");
95
    return getBool();
96
}
97

            
98
const std::string& UniValue::get_str() const
99
{
100
    if (typ != VSTR)
101
        throw std::runtime_error("JSON value is not a string as expected");
102
    return getValStr();
103
}
104

            
105
int UniValue::get_int() const
106
{
107
    if (typ != VNUM)
108
        throw std::runtime_error("JSON value is not an integer as expected");
109
    int32_t retval;
110
    if (!ParseInt32(getValStr(), &retval))
111
        throw std::runtime_error("JSON integer out of range");
112
    return retval;
113
}
114

            
115
int64_t UniValue::get_int64() const
116
{
117
    if (typ != VNUM)
118
        throw std::runtime_error("JSON value is not an integer as expected");
119
    int64_t retval;
120
    if (!ParseInt64(getValStr(), &retval))
121
        throw std::runtime_error("JSON integer out of range");
122
    return retval;
123
}
124

            
125
double UniValue::get_real() const
126
{
127
    if (typ != VNUM)
128
        throw std::runtime_error("JSON value is not a number as expected");
129
    double retval;
130
    if (!ParseDouble(getValStr(), &retval))
131
        throw std::runtime_error("JSON double out of range");
132
    return retval;
133
}
134

            
135
const UniValue& UniValue::get_obj() const
136
{
137
    if (typ != VOBJ)
138
        throw std::runtime_error("JSON value is not an object as expected");
139
    return *this;
140
}
141

            
142
const UniValue& UniValue::get_array() const
143
{
144
    if (typ != VARR)
145
        throw std::runtime_error("JSON value is not an array as expected");
146
    return *this;
147
}
148