

#ifndef _dkutil_EasySeries__
#define _dkutil_EasySeries__


#include "dkutilDefined.h"
#include "dKingyoMacro.h"
#include "dkutilGetParam.h"
#include "dkutilBuffer.h"
#include "filesystem/dkutilFileSystem.h"

namespace dkutil{

class IEasySeries{
public:
	typedef std::size_t size_type;
	IEasySeries(){}
	virtual ~IEasySeries(){};
	//virtual void Release() = 0;
	virtual bool isValid() = 0;
	//virtual void Reserve(size_type) = 0;
	//何かを貰う
	//virtual void *Get(int id=NULL) = 0;
	//virtual void Set(int id=NULL,void *ptr=NULL) = 0;
	//定義していない場合はedk_Not_Defined_Functionを返す
	//virtual int Task(int mes=NULL,void *adr=NULL) = 0;
	/*!
	@param filename[in] 出力するファイルの名前
	@throw std::exceptionとか投げる
	元のクラスをファイルにダンプ(またはXML等に保存)する
	*/
	virtual bool Serialize(const char *filename)const = 0;
	/*!
	元のクラスを復元する
	@param filename[in] 保存してあるファイルの名前
	@thorw std::exceptionとか投げる
	*/
	virtual bool DeSerialize(const char *filename) = 0;

};

#define IEasySeriesTypedefDefine \
	typedef IEasySeries::size_type size_type









namespace private_{

/*!
シリアライズ用オフセットぷっしゃ〜
（ただリトルエンディアンとビッグエンディアンを保存する領域分のみ
*/
class serialize_offset_pusher : public offset_pusher<char>{
public:
	typedef offset_pusher<char> BASE_TYPE;
	typedef offset_pusher<char>::size_type size_type;
	serialize_offset_pusher(const char *buf,size_type size) : 
		BASE_TYPE(buf,size){
		reset(buf,size);	
	}

	static size_type get_top_size(){return 1;}
	char *get()const{//	return &(BASE_TYPE::get())[get_top_size()];}
		return BASE_TYPE::get();
	}
	char *now()const{	return get() + BASE_TYPE::size();}
	void reset(const char *buf,size_type size){
		BASE_TYPE::reset(buf,size);
		bool f=isLittleEndian();
		push_back((const char *)&f,get_top_size());
	}
	bool EndianCheck(){
		return ((char)isLittleEndian() == (char)(BASE_TYPE::get()[0]));
	}
};

/*
class file_stream{
	enum{
		binary,
		text
*/

}//end of private_ namespace


class serializer : public private_::serialize_offset_pusher{
private:
	scoped_buffer mbuf;
public:
	typedef private_::serialize_offset_pusher BASE_TYPE;
	typedef BASE_TYPE::size_type size_type;
	serializer(size_type size=0) : BASE_TYPE(NULL,size){
		reset(size);	
	}
	virtual ~serializer(){}
	void clear(){
		mbuf.clear();
	}
	void reset(size_type size){
		//size + エンディアン格納 + NULL文字（がある場合)
		size_type asize = size + BASE_TYPE::get_top_size() + 1;
		if(size == 0) return;
		mbuf.reset(asize);
		BASE_TYPE::reset(mbuf.get(),asize);
	}
	///後ろに追加する
	void push_back(const char *data,size_type size){
		if(mbuf.isValid()==false){
			//くらいあがれ〜〜！！！！
			throw std::logic_error("メモリが確保されてません。resetを呼び出してください。");
		}
		BASE_TYPE::push_back(data,size);
	}
	///参照してsize分下がる
	const char *reference_back(size_type size){
		const char *ptr=BASE_TYPE::now();
		BASE_TYPE::OffsetPlus(size);
		return ptr;
	}
	///push_backしたものを保存する
	int serialize(const char *filename)const{
		return SaveWin32APIFile(filename,mbuf.data(),mbuf.capacity());
	}
	///前、ファイルにダンプしたものを復元する
	int deserialize(const char *filename){
		clear();
		size_type size = filesystem::GetFileSizeMini(filename);
		reset(size);
		DWORD loaded_size;
		if(DKUTIL_FAILED(LoadWin32APIFile_Proto(filename,mbuf.data(),size,&loaded_size))){
			return edk_FAILED;
		}
		//NULL文字ぶち込む　NULL文字も考慮してmbufは確保している！(はず･･･
		//mbuf.get()[loaded_size] = '\0';
		
		if(false==BASE_TYPE::EndianCheck()){
			return edk_FAILED;//変なもん読み込むなぁ！！
		}
		return edk_SUCCEEDED;
	}

};
/*
template<class T>
class IEasySerializ{
private:
	std::size_t mfsize;
protected:
	void SetSize(std::size_t size){	mfsize = size;}
public:
	IEasySerialize(std::size_t size) : mfsize(size){}
	std::size_t GetSize(){return mfsize;}
	virtual T GetData() = 0;
};		
*/

}//end of dkutil namespace



#endif//end of include once