
#ifndef DKUTIL_SHARED_BUFFER_HPP
#define DKUTIL_SHARED_BUFFER_HPP

#include <dkutil/boost/shared_array.hpp>
#include <dkutil/serialize.hpp>

namespace dkutil{



///shared_arrayをバッファ化したもの
template<typename TYPE_T=char>
class shared_buffer_base : public boost::shared_array<TYPE_T>
{
public:
	typedef size_t size_type;
	typedef TYPE_T value_type;
	typedef shared_buffer_base<TYPE_T> self_type;
	typedef boost::shared_array<value_type> base_type; 
	/*
	typedef ALLOCATE_POLICY__ allocator;

	struct allocate_select{
	};
	void *operator new[](size_t size,allocate_select x){
		return mA.Allocate(size);
	}
	void *operator delete[]
	*/
protected:
	size_type mSize;
public:
	shared_buffer_base(size_type size){
		mSize = 0;
		reset(size);
	}
	shared_buffer_base(){
		mSize = 0;
	}
	~shared_buffer_base(){
	}
	/*smart_buffer(const self_type &x){
		*this = x;
	}*/
	self_type &operator=(const self_type &x)
	{
		mSize = x.mSize;
		base_type::operator=((const base_type &)x);
		return *this;
	}
	void clear(){
		base_type::reset();
		mSize = 0;
	}
	bool reset(size_type size){
		clear();
		value_type *p = new value_type[size];
		if(NULL==p) return false;
		base_type::reset(p);
		mSize = size;
		return true;
	}
	/*value_type *get(){
		return mP.get();
	}
	const value_type *get()const{
		return mP.get();
	}*/
	size_t size()const{
		return mSize;
	}
	const value_type *get_const()const{
		return get();
	}

	///str分バッファを確保してコピーする
	bool copy_string(parm_string str){
		size_t len = str.size();
		//NULL文字分も
		if(false==reset(len + 1)) return false;	
		//memcpy(get(),str.c_str(),len);
		if(DKUTIL_FAILED(
			dkc_strcpy((char *)get(),size(),str.c_str(),len)
			)){
			return false;
		}
		get()[len] = '\0'; 
		return true;
	}
	bool copy(const value_type *x,size_t size){
		if(false==reset(size)) return false;
		memcpy(get(),x,size);
		return true;
	}
	void fill(value_type x){
		synchronized swimming;
		size_t len = size();
		if(0==len) return;
		dkcSecureFillMemory(get(),len,x);
	}
	void fillzero(){
		fill(0);
	}
	bool to_string(std::string &dest)const{
		std::string s;
		if(get()[size()-1] != '\0') return false;
		//if(strlen(get())!=size()-1) return false;
		for(size_t i=0;i<size();i++){
			const char *p = (const char *)get();
			if('\0'==p[i]) break;
			s += p[i];
		}
		dest = s;
		return true;
	}
	bool if_resize(size_type siz){
		bool r = true;
		if(size() < siz){
			r = reset(siz);
		}
		return r;
	}
	/*
	self_type *self(){
		return this;
	}
	const self_type *self()const{
		return this;
	}*/
	void serialize(ISerializeStream *p)
	{
		uint32 t;
		if(p->is_read_mode())
		{
			*p << t;
			if(false==reset(t))
				throw serialize_error("shared_buffer::serialize() read reset() error");
		}else{
			t = size();
			*p << t;
		}
		p->serialize(get(),size());		
	}
	///@return シリアライズする時のファイルに出力するサイズを返す。
	size_t serialize_size()const{
		return size() + sizeof(uint32);
	}
	friend bool operator==(const self_type &x,const self_type &y)
	{
		if(x.size() != y.size()) return false;
		bool r = 0==memcmp(x.get(),y.get(),x.size());
		return r;
	}
	friend bool operator!=(const self_type &x,const self_type &y)
	{
		return !operator==(x,y);
	}
};

typedef shared_buffer_base<char> shared_buffer_char;
typedef shared_buffer_base<unsigned char> shared_buffer_byte;
typedef shared_buffer_byte shared_buffer;
/*
template<class T> class shared_array
{
private:

    // Borland 5.5.1 specific workarounds
    typedef checked_array_deleter<T> deleter;
    typedef shared_array<T> this_type;

public:

    typedef T element_type;

    explicit shared_array(T * p = 0): px(p), pn(p, deleter())
    {
    }

    //
    // Requirements: D's copy constructor must not throw
    //
    // shared_array will release p by calling d(p)
    //

    template<class D> shared_array(T * p, D d): px(p), pn(p, d)
    {
    }

//  generated copy constructor, assignment, destructor are fine

    void reset(T * p = 0)
    {
        BOOST_ASSERT(p == 0 || p != px);
        this_type(p).swap(*this);
    }

    template <class D> void reset(T * p, D d)
    {
        this_type(p, d).swap(*this);
    }

    T & operator[] (std::ptrdiff_t i) const // never throws
    {
        BOOST_ASSERT(px != 0);
        BOOST_ASSERT(i >= 0);
        return px[i];
    }
    
    T * get() const // never throws
    {
        return px;
    }

    // implicit conversion to "bool"

#if defined(__SUNPRO_CC) && BOOST_WORKAROUND(__SUNPRO_CC, <= 0x530)

    operator bool () const
    {
        return px != 0;
    }

#else

    typedef T * (this_type::*unspecified_bool_type)() const;

    operator unspecified_bool_type() const // never throws
    {
        return px == 0? 0: &this_type::get;
    }

#endif

    bool operator! () const // never throws
    {
        return px == 0;
    }

    bool unique() const // never throws
    {
        return pn.unique();
    }

    long use_count() const // never throws
    {
        return pn.use_count();
    }

    void swap(shared_array<T> & other) // never throws
    {
        std::swap(px, other.px);
        pn.swap(other.pn);
    }

private:

    T * px;                     // contained pointer
    detail::shared_count pn;    // reference counter

};  // shared_array


template<class T> inline bool operator==(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
    return a.get() == b.get();
}

template<class T> inline bool operator!=(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
    return a.get() != b.get();
}

template<class T> inline bool operator<(shared_array<T> const & a, shared_array<T> const & b) // never throws
{
    return std::less<T*>()(a.get(), b.get());
}

template<class T> void swap(shared_array<T> & a, shared_array<T> & b) // never throws
{
    a.swap(b);
}
*/

}//end of dkutil namespace



#endif