/// Copyright (C) 2017, Mocchi
/// rapidjson helper
/// License: Boost ver.1

#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/prettywriter.h"

namespace rapidjson{
namespace helper{
template <typename Doc, typename StrBuf> void ToStringBuffer(const Doc &doc, StrBuf &strbuf){
	doc.Accept(PrettyWriter<StrBuf>(strbuf));
}
template <typename Val, typename Doc> void ClonePiece(const Val &src, Doc &dst){
	StringBuffer sb;
	ToStringBuffer(src, sb);
	dst.Parse<0>(sb.GetString());
}
template <typename Val1, typename Val2, typename Allocator> void DeepCopy(Val1 &lhs, Val2 &rhs, Allocator &alloc){
	if (lhs.IsNull())        rhs.SetNull();
	else if (lhs.IsBool())   rhs.SetBool(lhs.GetBool());
	else if (lhs.IsUint64()) rhs.SetUint64(lhs.GetUint64());
	else if (lhs.IsInt64())  rhs.SetUint64(lhs.GetInt64());
	else if (lhs.IsUint())   rhs.SetUint(lhs.GetUint());
	else if (lhs.IsInt())    rhs.SetUint(lhs.GetInt());
	else if (lhs.IsDouble()) rhs.SetDouble(lhs.GetDouble());
	else if (lhs.IsString()) rhs.SetString(lhs.GetString(), lhs.GetStringLength());
	else{
		GenericDocument<Val::EncodingType> doc(&alloc);
		ClonePiece(lhs, doc);
		dst = doc;
	}
}
template <typename Val> bool TryGetBoolean(Val val, bool default_value){
	return (val.IsBool()) ? val.GetBool() : default_value;
}
template <typename Val> int TryGetInteger(Val &val, int default_value){
	return (val.IsInt()) ? val.GetInt() : default_value;
}
template <typename Val> double TryGetDouble(Val &val, double default_value){
	return (val.IsNumber()) ? val.GetDouble() : default_value;
}
template <typename Val> const char *TryGetString(Val &val, const char *default_value){
	return (val.IsString()) ? val.GetString() : default_value;
}
template <typename Obj, typename MemIter, typename Allocator> void GetOrCreateMember(Obj &obj, const char *key, MemIter &member, Allocator &alloc){
	member = obj.FindMember(key);
	if (!member){
		GenericValue<Obj::EncodingType, Obj::AllocatorType> newobj;
		newobj.SetObject();
		obj.AddMember(Value(key, alloc), newobj, alloc);
		member = obj.MemberEnd();
		--member;
	}
}
}
}
