⛏️ index : haiku.git

/*
 * 	Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com
 * 	Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net
 * 	Copyright 2002-2020, Axel DΓΆrfler, axeld@pinc-software.de
 * 	Distributed under the terms of the MIT License.
 */
#ifndef _UDF_CACHED_BLOCK_H
#define _UDF_CACHED_BLOCK_H

/*! \file CachedBlock.h

	Based on the CachedBlock class from BFS, written by
	Axel DΓΆrfler, axeld@pinc-software.de
*/

#include <fs_cache.h>
#include <util/kernel_cpp.h>

#include "UdfDebug.h"
#include "UdfStructures.h"
#include "Volume.h"


class CachedBlock {
public:
								CachedBlock(Volume *volume);
								CachedBlock(CachedBlock *cached);
								~CachedBlock();

	uint8						*Block() const { return fBlock; }
	off_t						BlockNumber() const { return fBlockNumber; }
	uint32						BlockSize() const { return fVolume->BlockSize(); }
	uint32						BlockShift() const { return fVolume->BlockShift(); }

	inline void					Keep();
	inline void					Unset();

	inline status_t				SetTo(off_t block);
	inline status_t				SetTo(long_address address);
	template <class Accessor, class Descriptor>
	inline status_t				SetTo(Accessor &accessor,
									Descriptor &descriptor);

protected:
	uint8						*fBlock;
	off_t						fBlockNumber;
	Volume						*fVolume;
};


inline
CachedBlock::CachedBlock(Volume *volume)
	:
	fBlock(NULL),
	fBlockNumber(0),
	fVolume(volume)
{
}


inline
CachedBlock::CachedBlock(CachedBlock *cached)
	:
	fBlock(cached->fBlock),
	fBlockNumber(cached->BlockNumber()),
	fVolume(cached->fVolume)
{
	cached->Keep();
}


inline
CachedBlock::~CachedBlock()
{
	Unset();
}


inline void
CachedBlock::Keep()
{
	fBlock = NULL;
}


inline void
CachedBlock::Unset()
{
	if (fBlock != NULL) {
		block_cache_put(fVolume->BlockCache(), fBlockNumber);
		fBlock = NULL;
	}
}


inline status_t
CachedBlock::SetTo(off_t block)
{
	Unset();
	fBlockNumber = block;
	return block_cache_get_etc(fVolume->BlockCache(), block,
		(const void**)&fBlock);
}


inline status_t
CachedBlock::SetTo(long_address address)
{
	off_t block;
	if (fVolume->MapBlock(address, &block) == B_OK)
		return SetTo(block);

	return B_BAD_VALUE;
}


template <class Accessor, class Descriptor>
inline status_t
CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor)
{
	// Make a long_address out of the descriptor and call it a day
	long_address address;
	address.set_to(accessor.GetBlock(descriptor),
		accessor.GetPartition(descriptor));
    return SetTo(address);
}


#endif	// _UDF_CACHED_BLOCK_H