Skip to content

Instantly share code, notes, and snippets.

@carasuca
Created April 18, 2013 13:51
Show Gist options
  • Save carasuca/5412845 to your computer and use it in GitHub Desktop.
Save carasuca/5412845 to your computer and use it in GitHub Desktop.
Here's some alternative look at JSON-like metadata.
#include "stdafx.h"
#include <string>
#include <vector>
#include <map>
#include <sstream>
#include <iostream>
#include <memory>
using namespace std;
class ISerializable
{
public:
string str() const {return *this;}
virtual operator string() const = 0;
virtual ISerializable& operator=(const string&) = 0;
virtual ~ISerializable() {} /*= default;*/ // OMG MS wake up
};
template<typename T>
class Serializable: public ISerializable
{
public:
Serializable(const T& t): _t(t) {}
Serializable& operator=(const T& t)
{
_t = t;
}
/*ISerializable::*/
operator string() const
{
ostringstream oss;
oss << _t;
return oss.str();
}
ISerializable& ISerializable::operator =( const string& s)
{
istringstream iss(s);
iss >> _t;
return *this;
}
private:
T _t;
};
class Node
{
typedef shared_ptr<ISerializable> ptr_type;
Node(ISerializable* s): _value(s) {}
Node& set(ISerializable* p)
{
_value.reset(p);
return *this;
}
Node& add(ISerializable* p)
{
_value.reset();
_dict.clear();
_array.push_back(p);
return *this;
}
public:
Node() {}
template<typename T>
Node& operator =(const T& t)
{
return set(new Serializable<T>(t));
}
Node& operator =(const string::value_type t[])
{
return set(new Serializable<string>(string(t)));
}
template<typename T>
Node& operator ,(const T& t)
{
return add(new Serializable<T>(t));
}
Node& operator ,(const string::value_type t[])
{
return add(new Serializable<string>(string(t)));
}
Node& operator ()(const string& s)
{
return _dict[s];
}
Node& operator ,(const Node& n)
{
return *this;
}
const Node& operator ()(const string& s) const
{
const auto it = _dict.find(s);
return it == _dict.end() ? _dummy : it->second;
}
const Node& operator[](size_t i) const
{
return (i > array_size()) ? _dummy : _array[i];
}
Node& operator[](size_t i)
{
_value.reset();
_dict.clear();
if (i + 1 > _array.size()) _array.resize(i + 1/*, Node()*/);
return _array.back();
}
ISerializable& value()
{
return _value ? *_value.get() : _bad;
}
const ISerializable& value() const
{
return _value ? *_value.get() : _bad;
}
bool good() const
{
return this != &_dummy;//_value || !_dict.empty() || !_array.empty() /*this != _dummy*/;
}
bool is_value() const
{
return _value && _dict.empty();
}
bool is_dict()
{
return !_value && !_dict.empty();
}
void clear()
{
_dict.clear();
_array.clear();
_value.reset();
}
size_t array_size() const
{
return _array.size();
}
size_t dict_size() const
{
return _dict.size();
}
Node& operator <<(const Node& n)
{
_dict.insert(n._dict.begin(), n._dict.end());
_array.reserve(_array.size()+n._array.size());
_array.insert(_array.end(), n._array.begin(), n._array.end());
return *this;
}
private:
map<string, Node> _dict;
vector<Node> _array;
ptr_type _value;
static class Bad: public ISerializable
{
virtual ISerializable& operator =( const string& )
{
return *this;
}
virtual operator string() const
{
return string();
}
} _bad;
static const Node _dummy;
};
Node::Bad Node::_bad;
const Node Node::_dummy;
typedef Node Metadata;
int _tmain(int argc, _TCHAR* argv[])
{
Metadata n, n2;
n("test") = 5;
n("test") = "string";
string s = n("test")("subtest1").value();
n("test").array_size();
n("test"), "foo", "baz", "bar", 1;
n("test")[1] = "john";
n("test");
n2 = n;
return 0;
}
@malleor
Copy link

malleor commented Apr 21, 2013

From the user's perspective, my implementation will be as sweet as you sketched in _tmain :D

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment