//
// See the file LICENSE for redistribution information.
//
// Copyright (c) 2002-2003
//	Sleepycat Software.  All rights reserved.
//
// $Id: ScopedDbt.hpp,v 1.22 2003/05/09 00:01:52 mjc Exp $
//

#ifndef __SCOPEDDBT_HPP
#define	__SCOPEDDBT_HPP

#include <cassert>
#include <cstdlib>
#include <cstring>
#include "db_cxx.h"
#include "shared_ptr.hpp"

namespace DbXml
{

// A Dbt for passing data into a DB method.
class DbtIn : public Dbt
{
public:
	DbtIn() : Dbt()
	{
		Dbt::set_flags(DB_DBT_USERMEM);
	}
	DbtIn(void *data, size_t size) : Dbt(data, size)
	{
		Dbt::set_flags(DB_DBT_USERMEM);
		set_ulen(size);
	}
	DbtIn(const DbtIn &dbt) : Dbt()
	{
		Dbt::set_flags(DB_DBT_USERMEM);
		set_data(dbt.get_data());
		set_size(dbt.get_size());
	}
	~DbtIn()
	{}
	void set_flags(u_int32_t flags)
	{
		assert(!(flags&(DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)));
		Dbt::set_flags(DB_DBT_USERMEM | flags);
	}
	void set(void *data, size_t size)
	{
		set_data(data);
		set_size(size);
		set_ulen(size);
	}
	bool operator<(const DbtIn &o) const
	{
		size_t s1 = get_size();
		size_t s2 = o.get_size();
		return (s1 == s2 ? memcmp(get_data(), o.get_data(), s1) < 0 : s1 < s2);
	}
private:
	DbtIn &operator= (const DbtIn &o);
};

// A Dbt for passing into and getting data back from a DB method.
class DbtOut : public Dbt
{
public:
	typedef DbXml::shared_ptr<DbXml::DbtOut> Ptr;
	DbtOut()
	{
		Dbt::set_flags(DB_DBT_REALLOC);
	}
	DbtOut(const void *data, size_t size)
	{
		Dbt::set_flags(DB_DBT_REALLOC);
		set(data, size);
	}
	DbtOut(const Dbt &dbt)
	{
		Dbt::set_flags(DB_DBT_REALLOC);
		set(dbt.get_data(), dbt.get_size());
	}
	~DbtOut()
	{
		if (get_data()) {
			::free(get_data());
		}
	}
	void set_flags(u_int32_t flags)
	{
		assert(!(flags&(DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERMEM)));
		Dbt::set_flags(DB_DBT_REALLOC | flags);
	}
	void set(const void *data, size_t size)
	{
		if (size > get_size()) {
			Dbt::set_data(::realloc(get_data(), size));
		}
		Dbt::set_size(size);
		if (data != 0) {
			::memcpy(get_data(), data, size);
		}
	}
	void set_data(void *)
	{
		assert(0);
	}
	void set_size(size_t size)
	{
		set(0, size);
	}
private:
	DbtOut &operator= (const DbtOut &o);
	DbtOut(DbtOut &dbt);
};

}

#endif
