Skip to content

Commit 2f2c64f

Browse files
committed
Use nullptr to represent JSON Null.
This change removes the need for a separate memory allocation for null and default-contructed json::values.
1 parent 7c4389e commit 2f2c64f

File tree

3 files changed

+42
-26
lines changed

3 files changed

+42
-26
lines changed

Release/include/cpprest/json.h

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ namespace json
4646
{
4747
class _Value;
4848
class _Number;
49-
class _Null;
5049
class _Boolean;
5150
class _String;
5251
class _Object;
@@ -738,6 +737,8 @@ namespace json
738737
friend class web::json::details::_Array;
739738
friend class web::json::details::JSON_Parser;
740739

740+
inline size_t serialize_size() const;
741+
741742
/// <summary>
742743
/// INTERNAL USE ONLY
743744
/// Used by the JSON_Parser to create json::values.
@@ -1490,20 +1491,6 @@ namespace json
14901491
friend class web::json::value;
14911492
};
14921493

1493-
class _Null final : public _Value
1494-
{
1495-
public:
1496-
virtual std::unique_ptr<_Value> _copy_value() override
1497-
{
1498-
return utility::details::make_unique<_Null>();
1499-
}
1500-
virtual json::value::value_type type() const override { return json::value::Null; }
1501-
virtual void serialize_impl(utf8string& str) const override {
1502-
str.append("null");
1503-
}
1504-
virtual size_t serialize_size() const override { return 4; }
1505-
};
1506-
15071494
class _Number final : public _Value
15081495
{
15091496
public:
@@ -1670,7 +1657,7 @@ namespace json
16701657
size_t valueSize = elem.second.size() * 20; // Multipler by each object/array element
16711658
if (valueSize == 0)
16721659
{
1673-
valueSize = elem.second.m_value->serialize_size();
1660+
valueSize = elem.second.serialize_size();
16741661
}
16751662
reserveSize += valueSize;
16761663
}
@@ -1769,7 +1756,10 @@ namespace json
17691756

17701757
inline void value::serialize(std::string& outstr) const
17711758
{
1772-
m_value->serialize_impl(outstr);
1759+
if (m_value)
1760+
m_value->serialize_impl(outstr);
1761+
else
1762+
outstr.append("null");
17731763
}
17741764

17751765
/// <summary>
@@ -1778,7 +1768,7 @@ namespace json
17781768
/// <returns>The number of children. 0 for all non-composites.</returns>
17791769
inline size_t value::size() const
17801770
{
1781-
return m_value->size();
1771+
return m_value ? m_value->size() : 0;
17821772
}
17831773

17841774
/// <summary>
@@ -1788,13 +1778,18 @@ namespace json
17881778
/// <returns>True if the field exists, false otherwise.</returns>
17891779
inline bool value::has_field(const std::string& key) const
17901780
{
1791-
return m_value->has_field(key);
1781+
return m_value ? m_value->has_field(key) : false;
1782+
}
1783+
1784+
inline size_t value::serialize_size() const
1785+
{
1786+
return m_value ? m_value->serialize_size() : 4;
17921787
}
17931788

17941789
inline value::value(std::unique_ptr<details::_Value> v)
17951790
: m_value(std::move(v))
17961791
#ifdef ENABLE_JSON_VALUE_VISUALIZER
1797-
, m_kind(m_value->type())
1792+
, m_kind(m_value ? m_value->type() : json::value::Null)
17981793
#endif
17991794
{}
18001795

Release/src/json/json.cpp

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void json::keep_object_element_order(bool keep_order)
3535
}
3636

3737
web::json::value::value() :
38-
value(utility::details::make_unique<web::json::details::_Null>())
38+
value(std::unique_ptr<web::json::details::_Value>())
3939
{ }
4040

4141
web::json::value::value(int32_t v) :
@@ -71,14 +71,17 @@ web::json::value::value(std::string v, bool has_escape_chars) :
7171
{ }
7272

7373
web::json::value::value(const value &other) :
74-
value(other.m_value->_copy_value())
74+
value(other.m_value ? other.m_value->_copy_value() : std::unique_ptr<json::details::_Value>(nullptr))
7575
{ }
7676

7777
web::json::value &web::json::value::operator=(const value &other)
7878
{
7979
if(this != &other)
8080
{
81-
m_value = std::unique_ptr<details::_Value>(other.m_value->_copy_value());
81+
if (other.m_value)
82+
m_value = other.m_value->_copy_value();
83+
else
84+
m_value.reset();
8285
#ifdef ENABLE_JSON_VALUE_VISUALIZER
8386
m_kind = other.m_kind;
8487
#endif
@@ -114,41 +117,57 @@ web::json::value web::json::value::array(std::vector<value> elements)
114117

115118
const web::json::number& web::json::value::as_number() const
116119
{
120+
if (!m_value)
121+
throw json_exception("not a number");
117122
return m_value->as_number();
118123
}
119124

120125
double web::json::value::as_double() const
121126
{
127+
if (!m_value)
128+
throw json_exception("not a number");
122129
return m_value->as_double();
123130
}
124131

125132
int web::json::value::as_integer() const
126133
{
134+
if (!m_value)
135+
throw json_exception("not a number");
127136
return m_value->as_integer();
128137
}
129138

130139
bool web::json::value::as_bool() const
131140
{
141+
if (!m_value)
142+
throw json_exception("not a boolean");
132143
return m_value->as_bool();
133144
}
134145

135146
json::array& web::json::value::as_array()
136147
{
148+
if (!m_value)
149+
throw json_exception("not an array");
137150
return m_value->as_array();
138151
}
139152

140153
const json::array& web::json::value::as_array() const
141154
{
155+
if (!m_value)
156+
throw json_exception("not an array");
142157
return m_value->as_array();
143158
}
144159

145160
json::object& web::json::value::as_object()
146161
{
162+
if (!m_value)
163+
throw json_exception("not an object");
147164
return m_value->as_object();
148165
}
149166

150167
const json::object& web::json::value::as_object() const
151168
{
169+
if (!m_value)
170+
throw json_exception("not an object");
152171
return m_value->as_object();
153172
}
154173

@@ -199,7 +218,7 @@ bool web::json::details::_String::has_escape_chars(const _String &str)
199218
});
200219
}
201220

202-
web::json::value::value_type json::value::type() const { return m_value->type(); }
221+
web::json::value::value_type json::value::type() const { return m_value ? m_value->type() : json::value::Null; }
203222

204223
bool json::value::is_integer() const
205224
{

Release/src/json/json_serialization.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ void web::json::details::_Number::serialize_impl(std::string& stream) const
165165

166166
const std::string& web::json::value::as_string() const
167167
{
168+
if (!m_value)
169+
throw json_exception("not a string");
168170
return m_value->as_string();
169171
}
170172

@@ -175,7 +177,7 @@ std::string json::value::serialize() const
175177
#endif
176178

177179
std::string ret;
178-
ret.reserve(m_value->serialize_size());
179-
m_value->serialize_impl(ret);
180+
ret.reserve(serialize_size());
181+
serialize(ret);
180182
return ret;
181183
}

0 commit comments

Comments
 (0)