class fileblock
{
	long		_filepos;
	fileobject*	_pfile;
	bool		_modified;

	void		load();
	void		store();
protected:
	char		_block[BLOCKSIZE];
	enum { invalidpos= -1 };
	
	//setmodified is called when user changes the this object.
	///if he tries to change an invalid object, inform him with an asserion
	void	setmodified()	{	assert( _filepos!=invalidpos ); _modified = true; };
	bool	modified() const {	return _filepos!=invalidpos && _modified; };
	virtual void initdata()	= 0;
	virtual void markdata()	= 0;

public:
	enum { newpos = -2 };

	fileblock(fileobject *,long);
	virtual ~fileblock();

	void	del();
	void	createnew();
	long	pos() const;
	void	loadpos(long);
	void	flush();
	void	assign(fileblock *);
};

fileblock::fileblock(fileobject *pfile,long pos):_pfile(pfile)
{
	assert( pfile );
	memset(_block,0,BLOCKSIZE);

	if ( pos == newpos )
	{
		_filepos = pfile->newblock();
		_modified = true;
	}
	else if ( pos!=invalidpos )
	{
		_filepos = pos;
		load();
		_modified = false;
	}
	else
		_filepos = invalidpos;
}

fileblock::~fileblock()
{
	store();
}

long fileblock::pos() const
{
	assert( _filepos!=invalidpos );
	return _filepos;
}

void fileblock::createnew()
{
	//if the user tries to create a new block on a previous existing, although
	//it may be usefull(to create the new in the memory of the existing
	//without the need for a new object) it is not used in bptree
	//so if the object is valid, assert as that we must have done something wrong
	assert( _filepos==invalidpos );

	_filepos = _pfile->newblock();
	_modified = true;
}

void fileblock::del()
{
	//must be valid to del !
	assert( _filepos!=invalidpos );

	_pfile->delblock( _filepos );
	_filepos = invalidpos;
}

void fileblock::loadpos(long pos)
{
	assert( _filepos==invalidpos );//must not load on a valid object
	_filepos = pos;
	load();
	initdata();
	_modified = false;
}

void fileblock::load()
{
	assert( _filepos!=invalidpos );
	_pfile->readblock(_block,_filepos);
	_modified = false;
}

void fileblock::store()
{
	if ( _filepos!=invalidpos && _modified )
	{
		_pfile->writeblock(_block,_filepos);
		_modified = false;
		_filepos = invalidpos;//dont allow to store the same object twice
	}
}

void fileblock::flush()
{
	assert( _filepos!=invalidpos );
	markdata();
	store();
}

void fileblock::assign(fileblock *p)
{
	//if this object should be flushed to disk, then
	//assert because if assignment happens
	//the object contained previously will never be fluashed!
	assert( !modified() );

	//must not be the same object 
	assert( p != this );

	//must be valid to copy 
	assert( p->_filepos!=invalidpos );
	
	//must be of same file
	assert( _pfile == p->_pfile );

	_modified = p->_modified;
	_filepos = p->_filepos;
	memcpy(_block,p->_block,BLOCKSIZE);

	//mark as invalid so that the copy item will not be valid any more
	//as it should not be right to have 2 objects operating on the same block
	p->_filepos = invalidpos;
}