Permalink
Browse files

Merge pull request #20 from chipdude/topic/serial

better serialize again
  • Loading branch information...
2 parents 3da40f8 + 7489973 commit ff45492d2bc728babea284f5c8b313ef53306616 @toffaletti toffaletti committed Apr 30, 2012
View
@@ -5,166 +5,266 @@
#include "ten/error.hh"
#include <type_traits>
+// FIXME: in theory I shouldn't have to do this, but SafeInt<> defines
+// operator &. revisit on rename to archive().
+#include "ten/SafeInt3.hpp"
+
namespace ten {
-using std::move;
-// KV<> wraps a named field
-// ConstKV<> wraps a named field that is not dynamic
+// kvt<> wraps a named field
+// const_kvt<> wraps a named field that is not dynamic
-template <class V> struct KV {
+template <class V> struct kvt {
const char *key;
V &&value;
- KV(const char *k, V &&v) : key(k), value(v) {}
+ kvt(const char *k, V &&v) : key(k), value(v) {}
};
-template <class V> struct ConstKV : public KV<V> {
- ConstKV(const char *k, V &&v) : KV<V>(k, v) {}
+template <class V> struct const_kvt : public kvt<V> {
+ const_kvt(const char *k, V &&v) : kvt<V>(k, v) {}
};
-template <class V> KV<V> kv(const char *k, V &&v) { return KV<V>(k, v); }
-template <class V> ConstKV<V> const_kv(const char *k, V &&v) { return ConstKV<V>(k, v); }
+template <class V> inline kvt< V&> kv(const char *k, V &v) { return {k, v}; }
+template <class V> inline kvt< const V&> kv(const char *k, const V &v) { return {k, v}; }
+template <class V> inline const_kvt< V&> const_kv(const char *k, V &v) { return {k, v}; }
+template <class V> inline const_kvt<const V&> const_kv(const char *k, const V &v) { return {k, v}; }
-// JSave
+// json_archive, now with virtuality!
-enum save_mode {
- save_all,
- save_dynamic
+enum archive_mode {
+ archive_dynamic,
+ archive_all
};
-class JSave {
- private:
+class json_saver;
+class json_loader;
+
+class json_archive {
+ protected:
json _j;
unsigned _version;
- save_mode _mode;
+ archive_mode _mode;
+
+ json_archive(unsigned ver = 0, archive_mode mode = archive_all) : _version(ver), _mode(mode) {}
+
+ json_archive(const json_archive &) = delete;
+ void operator = (const json_archive &) = delete;
public:
using is_archive = std::true_type;
- using is_save = std::true_type;
- using is_load = std::false_type;
-
- explicit JSave(unsigned ver = 0, save_mode mode = save_all)
- : _version(ver), _mode(mode) {}
- save_mode mode() const { return _mode; }
- unsigned version() const { return _version; }
+ virtual bool is_save_v() const = 0;
+ bool is_load_v() const { return !is_save_v(); }
- // make one like the other but without memory
- JSave clone() const { return JSave(_version, _mode); }
+ unsigned version() const { return _version; }
+ archive_mode mode() const { return _mode; }
- // public value extraction
- friend json result(const JSave &ar) { return ar._j; }
- friend json result( JSave &&ar) { return move(ar._j); }
+ bool empty() const { return empty_v(); }
+ virtual bool empty_v() const = 0;
- // operator << works on save only,
- template <class T> JSave & operator << (T &t) { return *this & t; }
- template <class V> JSave & operator << ( KV<V &> f) { return *this & f; }
- template <class V> JSave & operator << (ConstKV<V &> f) { return *this & f; }
+ virtual void vserialize(json &j) = 0;
+ virtual void vserialize(json &j, const char *key, archive_mode min_mode) = 0;
- // save functions
+ template <class T> json_archive & operator & (T &t) {
+ bool is_save = is_save_v();
+ json j;
+ if (is_save) {
+ j = result(json_saver(_version, _mode) & t);
+ if (!j)
+ return *this;
+ }
+ vserialize(j);
+ if (!is_save)
+ json_loader(j, _version, _mode) & t;
+ return *this;
+ }
- JSave & operator & (const json &j) {
- req_empty_for(j);
- _j = j;
+ template <class T> json_archive & operator & (kvt<T&> f) {
+ bool is_save = is_save_v();
+ json j;
+ if (is_save) {
+ j = result(json_saver(_version, _mode) & f.value);
+ if (!j)
+ return *this;
+ }
+ vserialize(j, f.key, archive_all);
+ if (!is_save && j)
+ json_loader(j, _version, _mode) & f.value;
return *this;
}
- template <class T, class X = typename std::enable_if<json_traits<T>::can_make>::type>
- JSave & operator & (const T &t) {
- json j(to_json(t));
- req_empty_for(j);
- _j = move(j);
+ template <class T> json_archive & operator & (const_kvt<T&> f) {
+ if (_mode >= archive_dynamic)
+ *this & static_cast<kvt<T&> &>(f);
return *this;
}
+};
- // kv pair specialization
- template <class V>
- JSave & operator & (KV<V> f) {
- req_obj_for(f.key);
- auto js = clone();
- auto jv = result(js & f.value);
- if (jv)
- _j.set(f.key, move(jv));
- return *this;
+// json_saver
+
+class json_saver : public json_archive {
+ public:
+ explicit json_saver(unsigned ver = 0, archive_mode mode = archive_all)
+ : json_archive(ver, mode) {}
+
+ using is_save = std::true_type;
+ using is_load = std::false_type;
+
+ bool empty() const { return !_j; }
+
+ // public value extraction
+ friend json result(const json_saver &ar) { return ar._j; }
+ friend json result( json_saver &&ar) { return move(ar._j); }
+
+ // serialization, main interface
+ friend void serialize (json_saver &ar, const json &j) {
+ ar.req_empty_for(j);
+ ar._j = j;
+ }
+ template <class T, class Enable = typename std::enable_if<json_traits<T>::can_make>::type>
+ friend void serialize(json_saver &ar, const T &t) {
+ serialize(ar, json_traits<T>::make(t));
}
+ // kvt<> and const_kvt<> specialization
template <class V>
- JSave & operator & (ConstKV<V> kv) {
- if (_mode == save_all)
- *this & static_cast<KV<V>&>(kv);
- return *this;
+ friend void serialize(json_saver &ar, kvt<V&> f) {
+ ar.req_obj_for(f.key);
+ json_saver ar2(ar._version, ar._mode);
+ serialize(ar2, f.value);
+ if (!ar2.empty())
+ ar._j.set(f.key, result(ar2));
+ }
+ template <class V>
+ friend void serialize(json_saver &ar, const_kvt<V&> f) {
+ if (ar._mode > archive_dynamic)
+ serialize(ar, static_cast<kvt<V&> &>(f));
+ }
+
+ // SafeInt<> specialization - because SafeInt<> has operator &
+ template <class I>
+ friend void serialize(json_saver &ar, const SafeInt<I> &si) {
+ serialize(ar, *si.Ptr());
+ }
+
+ // runtime polymorphic interface - premade json only
+ bool is_save_v() const override {
+ return true;
+ }
+ bool empty_v() const override {
+ return empty();
+ }
+ void vserialize(json &j) override {
+ serialize(*this, j);
+ }
+ void vserialize(json &j, const char *key, archive_mode min_mode) override {
+ if (_mode >= min_mode)
+ serialize(*this, kv(key, j));
}
+ // eye candy
+ template <class T> json_saver & operator & (T &t) { serialize(*this, t); return *this; }
+ template <class V> json_saver & operator & ( kvt<V&> f) { serialize(*this, f); return *this; }
+ template <class V> json_saver & operator & (const_kvt<V&> f) { serialize(*this, f); return *this; }
+
+ template <class T> json_saver & operator << (T &t) { serialize(*this, t); return *this; }
+ template <class V> json_saver & operator << ( kvt<V&> f) { serialize(*this, f); return *this; }
+ template <class V> json_saver & operator << (const_kvt<V&> f) { serialize(*this, f); return *this; }
+
protected:
// convenience for save functions
void req_empty_for(const json &jn) {
- if (_j) throw errorx("JSave multiple: %s & %s", _j.dump().c_str(), jn.dump().c_str());
+ if (_j) throw errorx("json_saver multiple: %s & %s", _j.dump().c_str(), jn.dump().c_str());
}
void req_obj_for(const char *key) {
if (!_j) _j = json::object();
- else if (!_j.is_object()) throw errorx("JSave key '%s' to non-object: %s", key, _j.dump().c_str());
+ else if (!_j.is_object()) throw errorx("json_saver key '%s' to non-object: %s", key, _j.dump().c_str());
}
};
-// JLoad
-
-class JLoad {
- json _j;
- unsigned _version;
+// json_loader
+class json_loader : public json_archive {
public:
- using is_archive = std::true_type;
+ explicit json_loader(const json & j, unsigned ver = 0, archive_mode mode = archive_all)
+ : json_archive(ver, mode) { _j = j; }
+ explicit json_loader( json &&j, unsigned ver = 0, archive_mode mode = archive_all)
+ : json_archive(ver, mode) { _j = j; }
+
using is_save = std::false_type;
using is_load = std::true_type;
- JLoad(const json & j, unsigned ver = 0) : _j(j), _version(ver) {}
- JLoad( json &&j, unsigned ver = 0) : _j(j), _version(ver) {}
-
- json source() const { return _j; }
- unsigned version() const { return _version; }
+ bool empty() const { return !_j; }
- // make one like the other but without memory
- JLoad clone() const { return JLoad(_version); }
-
- // operator >> works on load only,
- template <class T> JLoad & operator >> (T &t) { return *this & t; }
- template <class V> JLoad & operator >> ( KV<V &> f) { return *this & f; } // not ref
- template <class V> JLoad & operator >> (ConstKV<V &> f) { return *this & f; } // not ref
-
- // load functions
-
- JLoad & operator & (json &j) {
- j = _j;
- return *this;
+ // serialization, main interface
+ friend void serialize (json_loader &ar, json &j) {
+ j = ar._j;
}
-
- template <class T, class X = typename std::enable_if<json_traits<T>::can_cast>::type>
- JLoad & operator & (T &t) {
- t = json_cast<T>(_j);
- return *this;
+ template <class T, class Enable = typename std::enable_if<json_traits<T>::can_cast>::type>
+ friend void serialize(json_loader &ar, T &t) {
+ t = json_traits<T>::cast(ar._j);
}
+ // kvt<> and const_kvt<> specialization
template <class V>
- JLoad & operator & (KV<V &> f) {
- req_obj_for(f.key);
- json jv(_j[f.key]);
+ friend void serialize(json_loader &ar, kvt<V&> f) {
+ ar.req_obj_for(f.key);
+ json jv(ar._j[f.key]);
if (jv) {
- JLoad js(move(jv), _version);
- js & f.value;
+ json_loader ar2(std::move(jv), ar._version, ar._mode);
+ serialize(ar2, f.value);
}
- return *this;
+ }
+ template <class V>
+ friend void serialize(json_loader &ar, const_kvt<V> f) {
+ if (ar._mode > archive_dynamic)
+ serialize(ar, static_cast<kvt<V> &>(f));
+ }
+
+ // SafeInt<> specialization - because SafeInt<> has operator &
+ template <class I>
+ friend void serialize(json_loader &ar, SafeInt<I> &si) {
+ serialize(ar, *si.Ptr());
+ }
+
+ // runtime polymorphic interface - premade json only
+ bool is_save_v() const override {
+ return false;
+ }
+ bool empty_v() const override {
+ return empty();
+ }
+ void vserialize(json &j) override {
+ serialize(*this, j);
+ }
+ void vserialize(json &j, const char *key, archive_mode min_mode) override {
+ if (_mode >= min_mode)
+ serialize(*this, kv(key, j));
}
+ // eye candy
+ template <class T> json_loader & operator & (T &t) { serialize(*this, t); return *this; }
+ template <class V> json_loader & operator & ( kvt<V&> f) { serialize(*this, f); return *this; }
+ template <class V> json_loader & operator & (const_kvt<V&> f) { serialize(*this, f); return *this; }
+
+ template <class T> json_loader & operator >> (T &t) { serialize(*this, t); return *this; }
+ template <class V> json_loader & operator >> ( kvt<V&> f) { serialize(*this, f); return *this; }
+ template <class V> json_loader & operator >> (const_kvt<V&> f) { serialize(*this, f); return *this; }
+
protected:
// convenience for load functions
void req_obj_for(const char *key) {
- if (!_j.is_object()) throw errorx("JLoad key '%s' from non-object %s", key, _j.dump().c_str());
+ if (!_j.is_object()) throw errorx("json_loader key '%s' from non-object %s", key, _j.dump().c_str());
}
};
-template <class T> inline json jsave_all(T &t) { JSave ar(save_all); ar << t; return result(move(ar)); }
-template <class T> inline json jsave_dyn(T &t) { JSave ar(save_dynamic); ar << t; return result(move(ar)); }
+
+// global functions
+
+template <class T> inline json jsave_all(const T &t) { json_saver ar(0, archive_all); ar << const_cast<T&>(t); return result(std::move(ar)); }
+template <class T> inline json jsave_dyn(const T &t) { json_saver ar(0, archive_dynamic); ar << const_cast<T&>(t); return result(std::move(ar)); }
} // ten
Oops, something went wrong.

0 comments on commit ff45492

Please sign in to comment.