Skip to content

Commit

Permalink
Ease-of-use improvements for JSON creation
Browse files Browse the repository at this point in the history
  • Loading branch information
gbittoun committed Nov 14, 2017
1 parent 1ebfc7b commit a3cf2a3
Show file tree
Hide file tree
Showing 2 changed files with 219 additions and 0 deletions.
172 changes: 172 additions & 0 deletions picojson.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#include <iterator>
#include <limits>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>
Expand Down Expand Up @@ -183,6 +184,8 @@ class value {
template <typename Iter> void serialize(Iter os, bool prettify = false) const;
std::string serialize(bool prettify = false) const;

int get_type() const;

private:
template <typename T> value(const T *); // intentionally defined to block implicit conversion of pointer to bool
template <typename Iter> static void _indent(Iter os, int indent);
Expand Down Expand Up @@ -634,6 +637,10 @@ inline std::string value::_serialize(int indent) const {
return s;
}

inline int value::get_type() const {
return type_;
}

template <typename Iter> class input {
protected:
Iter cur_, end_;
Expand Down Expand Up @@ -1129,6 +1136,171 @@ inline bool operator==(const value &x, const value &y) {
inline bool operator!=(const value &x, const value &y) {
return !(x == y);
}

class value_holder
{
private:
static value static_null_value;

public:
value_holder() :
value_ref(static_null_value),
value_ptr(std::make_unique<value>())
{
}

value_holder(bool b) :
value_ref(static_null_value),
value_ptr(std::make_unique<value>(b))
{
}

value_holder(const std::string & s) :
value_ref(static_null_value),
value_ptr(std::make_unique<value>(s))
{
}

value_holder(double d) :
value_ref(static_null_value),
value_ptr(std::make_unique<value>(d))
{
}

value_holder(value & value) :
value_ref(value),
value_ptr()
{
}

value & get()
{
if (value_ptr)
return *value_ptr;
else
return value_ref;
}

value & operator*()
{
return get();
}

value * operator->()
{
return &get();
}

private:
picojson::value & value_ref;
std::unique_ptr<picojson::value> value_ptr;
};

value value_holder::static_null_value;

class easyjson
{
public:

//Constructors

easyjson() :
holder() {
}

easyjson(picojson::value & v) :
holder(v) {
}

easyjson(bool b):
holder(b) {
}

easyjson(const char * c):
holder(std::string(c)) {
}

easyjson(const std::string & s):
holder(s) {
}

easyjson(int value):
holder(double(value)) {
}

easyjson(double d):
holder(d) {
}

// Equality operators

easyjson & operator=(bool value) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == boolean_type);
*holder = picojson::value(value);
return *this;
}

easyjson & operator=(const char * value) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == string_type);
*holder = picojson::value(std::string(value));
return *this;
}

easyjson & operator=(const std::string & value) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == string_type);
*holder = picojson::value(value);
return *this;
}

easyjson & operator=(int value) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == number_type);
*holder = picojson::value(double(value));
return *this;
}

easyjson & operator=(double value) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == number_type);
*holder = picojson::value(value);
return *this;
}

picojson::value & get_value() {
return *holder;
}

// Assignment operators

easyjson operator[](const std::string & s) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == object_type);

if (holder->get_type() == null_type)
holder->set<picojson::value::object>(picojson::value::object());

return holder->get<picojson::value::object>()[std::string(s)];
}

easyjson operator[](const char * c) {
return operator[](std::string(c));
}

easyjson operator[](picojson::value::array::size_type index) {
PICOJSON_ASSERT(holder->get_type() == null_type || holder->get_type() == array_type);

if (holder->get_type() == null_type) {
holder->set<picojson::value::array>(picojson::value::array(index + 1));
}

if (holder->get<picojson::value::array>().size() <= index) {
holder->get<picojson::value::array>().resize(index + 1);
}

return holder->get<picojson::value::array>().at(index);
}

private:
value_holder holder;
};

}

#if !PICOJSON_USE_RVALUE_REFERENCE
Expand Down
47 changes: 47 additions & 0 deletions test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -344,5 +344,52 @@ int main(void)
is(*reststr, 'a', "should point at the next char");
}

{
picojson::easyjson v("foo");
_ok(v.get_value().get<std::string>() == "foo", "equals value");
v = "bar";
_ok(v.get_value().get<std::string>() == "bar", "equals value");
}

{
picojson::easyjson v(std::string("foo"));
_ok(v.get_value().get<std::string>() == "foo", "equals value");
v = std::string("bar");
_ok(v.get_value().get<std::string>() == "bar", "equals value");
}

{
picojson::easyjson v(1);
_ok(v.get_value().get<double>() == 1, "equals value");
v = 2;
_ok(v.get_value().get<double>() == 2, "equals value");
}

{
picojson::easyjson v(1.0f);
_ok(v.get_value().get<double>() == 1.0f, "equals value");
v = 2.0f;
_ok(v.get_value().get<double>() == 2.0f, "equals value");
}

{
picojson::easyjson v(1.0);
_ok(v.get_value().get<double>() == 1.0, "equals value");
v = 2.0;
_ok(v.get_value().get<double>() == 2.0, "equals value");
}

{
picojson::easyjson v;
v["foo"] = 12;
_ok(v["foo"].get_value().get<double>() == 12, "equals value");
}

{
picojson::easyjson v;
v[12] = "foo";
_ok(v[12].get_value().get<std::string>() == "foo", "equals value");
}

return done_testing();
}

0 comments on commit a3cf2a3

Please sign in to comment.