Coverage Report

Created: 2022-08-24 06:31

/src/solidity/libsolutil/JSON.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
  This file is part of solidity.
3
4
  solidity is free software: you can redistribute it and/or modify
5
  it under the terms of the GNU General Public License as published by
6
  the Free Software Foundation, either version 3 of the License, or
7
  (at your option) any later version.
8
9
  solidity is distributed in the hope that it will be useful,
10
  but WITHOUT ANY WARRANTY; without even the implied warranty of
11
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
  GNU General Public License for more details.
13
14
  You should have received a copy of the GNU General Public License
15
  along with solidity.  If not, see <http://www.gnu.org/licenses/>.
16
*/
17
// SPDX-License-Identifier: GPL-3.0
18
/** @file JSON.cpp
19
 * @author Alexander Arlt <alexander.arlt@arlt-labs.com>
20
 * @date 2018
21
 */
22
23
#include <libsolutil/JSON.h>
24
25
#include <libsolutil/CommonIO.h>
26
27
#include <boost/algorithm/string/replace.hpp>
28
29
#include <sstream>
30
#include <map>
31
#include <memory>
32
33
using namespace std;
34
35
static_assert(
36
  (JSONCPP_VERSION_MAJOR == 1) && (JSONCPP_VERSION_MINOR == 9) && (JSONCPP_VERSION_PATCH == 3),
37
  "Unexpected jsoncpp version: " JSONCPP_VERSION_STRING ". Expecting 1.9.3."
38
);
39
40
namespace solidity::util
41
{
42
43
namespace
44
{
45
46
/// StreamWriterBuilder that can be constructed with specific settings
47
class StreamWriterBuilder: public Json::StreamWriterBuilder
48
{
49
public:
50
  explicit StreamWriterBuilder(map<string, Json::Value> const& _settings)
51
0
  {
52
0
    for (auto const& iter: _settings)
53
0
      this->settings_[iter.first] = iter.second;
54
0
  }
55
};
56
57
/// CharReaderBuilder with strict-mode settings
58
class StrictModeCharReaderBuilder: public Json::CharReaderBuilder
59
{
60
public:
61
  StrictModeCharReaderBuilder()
62
0
  {
63
0
    Json::CharReaderBuilder::strictMode(&this->settings_);
64
0
  }
65
};
66
67
/// Serialise the JSON object (@a _input) with specific builder (@a _builder)
68
/// \param _input JSON input string
69
/// \param _builder StreamWriterBuilder that is used to create new Json::StreamWriter
70
/// \return serialized json object
71
string print(Json::Value const& _input, Json::StreamWriterBuilder const& _builder)
72
0
{
73
0
  stringstream stream;
74
0
  unique_ptr<Json::StreamWriter> writer(_builder.newStreamWriter());
75
0
  writer->write(_input, &stream);
76
0
  return stream.str();
77
0
}
78
79
/// Parse a JSON string (@a _input) with specified builder (@ _builder) and writes resulting JSON object to (@a _json)
80
/// \param _builder CharReaderBuilder that is used to create new Json::CharReaders
81
/// \param _input JSON input string
82
/// \param _json [out] resulting JSON object
83
/// \param _errs [out] Formatted error messages
84
/// \return \c true if the document was successfully parsed, \c false if an error occurred.
85
bool parse(Json::CharReaderBuilder& _builder, string const& _input, Json::Value& _json, string* _errs)
86
0
{
87
0
  unique_ptr<Json::CharReader> reader(_builder.newCharReader());
88
0
  return reader->parse(_input.c_str(), _input.c_str() + _input.length(), &_json, _errs);
89
0
}
90
91
/// Takes a JSON value (@ _json) and removes all its members with value 'null' recursively.
92
void removeNullMembersHelper(Json::Value& _json)
93
0
{
94
0
  if (_json.type() == Json::ValueType::arrayValue)
95
0
    for (auto& child: _json)
96
0
      removeNullMembersHelper(child);
97
0
  else if (_json.type() == Json::ValueType::objectValue)
98
0
    for (auto const& key: _json.getMemberNames())
99
0
    {
100
0
      Json::Value& value = _json[key];
101
0
      if (value.isNull())
102
0
        _json.removeMember(key);
103
0
      else
104
0
        removeNullMembersHelper(value);
105
0
    }
106
0
}
107
108
} // end anonymous namespace
109
110
Json::Value removeNullMembers(Json::Value _json)
111
0
{
112
0
  removeNullMembersHelper(_json);
113
0
  return _json;
114
0
}
115
116
string jsonPrettyPrint(Json::Value const& _input)
117
0
{
118
0
  return jsonPrint(_input, JsonFormat{ JsonFormat::Pretty });
119
0
}
120
121
string jsonCompactPrint(Json::Value const& _input)
122
0
{
123
0
  return jsonPrint(_input, JsonFormat{ JsonFormat::Compact });
124
0
}
125
126
string jsonPrint(Json::Value const& _input, JsonFormat const& _format)
127
0
{
128
0
  map<string, Json::Value> settings;
129
0
  if (_format.format == JsonFormat::Pretty)
130
0
  {
131
0
    settings["indentation"] = string(_format.indent, ' ');
132
0
    settings["enableYAMLCompatibility"] = true;
133
0
  }
134
0
  else
135
0
    settings["indentation"] = "";
136
0
  StreamWriterBuilder writerBuilder(settings);
137
0
  string result = print(_input, writerBuilder);
138
0
  if (_format.format == JsonFormat::Pretty)
139
0
    boost::replace_all(result, " \n", "\n");
140
0
  return result;
141
0
}
142
143
bool jsonParseStrict(string const& _input, Json::Value& _json, string* _errs /* = nullptr */)
144
0
{
145
0
  static StrictModeCharReaderBuilder readerBuilder;
146
0
  return parse(readerBuilder, _input, _json, _errs);
147
0
}
148
149
} // namespace solidity::util