Created
April 18, 2013 13:51
-
-
Save carasuca/5412845 to your computer and use it in GitHub Desktop.
Here's some alternative look at JSON-like metadata.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
From the user's perspective, my implementation will be as sweet as you sketched in
_tmain
:D