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

#ifndef __CURSOR_HPP
#define	__CURSOR_HPP

#include "Database.hpp"
#include "ScopedDbt.hpp"

namespace DbXml
{

/// Provides exception safety for a Berkeley Db Cursor.
class Cursor
{
public:
	Cursor(DbEnv *environment, Db &db, DbTxn *txn);
	~Cursor()
	{
		if (error_ == 0)
			dbc_->close();
	}
	int error() const
	{
		return error_;
	}
	int get(Dbt *key, Dbt *data, u_int32_t flags)
	{
		return dbc_->get(key, data, flags);
	}
	int put(Dbt *key, Dbt *data, u_int32_t flags)
	{
		return dbc_->put(key, data, flags);
	}
	int del(u_int32_t flags)
	{
		return dbc_->del(flags);
	}
private:
	// no need for copy and assignment
	Cursor(const Cursor&);
	Cursor &operator = (const Cursor &);

	Dbc *dbc_;
	int error_;
};

/// Wraps a Dbc, for a Primary Database.
class PrimaryCursor
{
public:
	PrimaryCursor(PrimaryDatabase &db, DbTxn *txn, Database::Operation operation, Key *k1);
	~PrimaryCursor();
	int error() const
	{
		return cursor_.error();
	}

	/// Done when id==0
	int first(ID &id);
	/// Done when id==0
	int next(ID &id);

private:
	// no need for copy and assignment
	PrimaryCursor(const PrimaryCursor&);
	PrimaryCursor & operator = (const PrimaryCursor &);

	int doNext(ID &id, int flags);

	Database::Operation operation_;
	Cursor cursor_;
	DbtOut key_; // The key for passing data into get()
	DbtIn data_; // The data we get back from get().
	bool done_;
	bool swap_;
};

/// Wraps a Dbc, for a Secondary Database.
class SecondaryCursor
{
public:
	SecondaryCursor(SecondaryDatabase &db, DbTxn *txn, Database::Operation operation, Key *k1, const Syntax *syntax);
	SecondaryCursor(SecondaryDatabase &db, DbTxn *txn, Database::Operation gto, Key *k1, Database::Operation lto, Key *k2, const Syntax *syntax);
	~SecondaryCursor();
	int error() const
	{
		return cursor_.error();
	}

	/// Done when id==0
	int first(ID &id);
	/// Done when id==0
	int next(ID &id);

private:
	// no need for copy and assignment
	SecondaryCursor(const SecondaryCursor&);
	SecondaryCursor & operator = (const SecondaryCursor &);

	int doNext(ID &id, int flags);

	DbEnv *environment_;
	const Syntax *syntax_; // Provides functions for comparing keys.
	Database::Operation operation_; // The operation passed through the constructor.
	Database::Operation greaterThanOperation_; // Ranges: The upper bound operation. GTX|GTE
	Database::Operation lessThanOperation_; // Ranges: The lower bound operation. LTX|LTE
	Cursor cursor_;
	DbtOut originalKey_; // The original key we are looking for. (Only for prefix, and inequality searches)
	DbtOut key_;  // The key we pass into get(). Range: The start of the range.
	DbtOut key2_; // The key we pass into get(). Range: The end of the range.
	DbtOut data_; // The data we get back from get().
	bool done_;
	bool swap_;
};

}

#endif

