//
// See the file LICENSE for redistribution information.
//
// Copyright (c) 2002-2003
//	Sleepycat Software.  All rights reserved.
//
// $Id: Key.hpp,v 1.38 2003/09/17 16:47:36 merrells Exp $
//

#ifndef __KEY_H
#define	__KEY_H

#include <memory>
#include <string>
#include "db_cxx.h"
#include "scoped_ptr.hpp"
#include "ID.hpp"
#include "Buffer.hpp"
#include "Syntax.hpp"
#include "IndexSpecification.hpp"

namespace DbXml
{

class XmlValue;
class QueryContext;
class XmlContainer;
class KeyStash;
class Container;

class Key
{
public:
	Key();
	~Key();

	void set(const Index &i, const ID &id1, const ID &id2);
	void set(const Index &index, const ID &id1, const ID &id2, const char *value);
	void set(const Index &index, const ID &id1, const ID &id2, XmlValue &v, QueryContext *context);
	void set(const Key &key, const char *p, size_t l);
	void reset();

	// Add the key to a stash of keys.
	void addKeyToStash(KeyStash &stash, bool swap) const;

	// Methods used by the QueryPlan
	void setDbtFromThis(DbtOut &dbt, bool swap) const;
	void setThisFromDbt(const DbtOut &dbt, bool swap);

	void setValue(const char *p, size_t l);
	void addValue(const char *value, size_t len);
	const char *getValue() const;
	size_t getValueSize() const;
	void setIndex(const Index &index)
	{
		index_ = index;
	}
	const Index &getIndex() const
	{
		return index_;
	}
	Syntax::Type getSyntaxType() const
	{
		return (Syntax::Type)index_.getSyntax();
	} // jcm - cast
	const Syntax *getSyntax() const;
	ID &getID1()
	{
		return id1_;
	}
	ID &getID2()
	{
		return id2_;
	}
	void setID1(const ID &id)
	{
		id1_ = id;
	}
	void setID2(const ID &id)
	{
		id2_ = id;
	}
	std::string asString() const;
	std::string asString_XML(DbTxn *txn, const Container &container) const;

private:
	Key(const Key&);
	void operator=(const Key &);

	void setValue(XmlValue &v, QueryContext *context);
	size_t keyBufferSize(size_t length) const;
	void writeKeyBufferToBuffer(Buffer &buffer, const char *value, size_t length, bool swap) const;
	void readKeyFromBuffer(Buffer &buffer, bool swap);
	void doAddKeyToStash(KeyStash &stash, const char *value, size_t length, bool swap) const;

	Index index_;
	ID id1_;
	ID id2_;
	Buffer *value_;
};

class KeyStash
{
public:
	typedef unsigned char *iterator;
	KeyStash();
	void reset();
	void write(const void *p, size_t l);
	void *first(iterator &i, size_t &n, Index &index);
	void *next(iterator &i, size_t &n, Index &index);
	Buffer &getBuffer()
	{
		return buffer_;
	}
private:
	void *dereferenceIterator(iterator &i, size_t &n, Index &index);

	Buffer buffer_;
};
}

#endif

