1/* 2 * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com 3 * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net 4 * Copyright 2002-2020, Axel D��rfler, axeld@pinc-software.de 5 * Distributed under the terms of the MIT License. 6 */ 7#ifndef _UDF_CACHED_BLOCK_H 8#define _UDF_CACHED_BLOCK_H 9 10/*! \file CachedBlock.h 11 12 Based on the CachedBlock class from BFS, written by 13 Axel D��rfler, axeld@pinc-software.de 14*/ 15 16#include <fs_cache.h> 17#include <util/kernel_cpp.h> 18 19#include "UdfDebug.h" 20#include "UdfStructures.h" 21#include "Volume.h" 22 23 24class CachedBlock { 25public: 26 CachedBlock(Volume *volume); 27 CachedBlock(CachedBlock *cached); 28 ~CachedBlock(); 29 30 uint8 *Block() const { return fBlock; } 31 off_t BlockNumber() const { return fBlockNumber; } 32 uint32 BlockSize() const { return fVolume->BlockSize(); } 33 uint32 BlockShift() const { return fVolume->BlockShift(); } 34 35 inline void Keep(); 36 inline void Unset(); 37 38 inline status_t SetTo(off_t block); 39 inline status_t SetTo(off_t block, off_t base, size_t length); 40 inline status_t SetTo(long_address address); 41 template <class Accessor, class Descriptor> 42 inline status_t SetTo(Accessor &accessor, 43 Descriptor &descriptor); 44 45protected: 46 uint8 *fBlock; 47 off_t fBlockNumber; 48 Volume *fVolume; 49}; 50 51 52inline 53CachedBlock::CachedBlock(Volume *volume) 54 : 55 fBlock(NULL), 56 fBlockNumber(0), 57 fVolume(volume) 58{ 59} 60 61 62inline 63CachedBlock::CachedBlock(CachedBlock *cached) 64 : 65 fBlock(cached->fBlock), 66 fBlockNumber(cached->BlockNumber()), 67 fVolume(cached->fVolume) 68{ 69 cached->Keep(); 70} 71 72 73inline 74CachedBlock::~CachedBlock() 75{ 76 Unset(); 77} 78 79 80inline void 81CachedBlock::Keep() 82{ 83 fBlock = NULL; 84} 85 86 87inline void 88CachedBlock::Unset() 89{ 90 if (fBlock != NULL) { 91 block_cache_put(fVolume->BlockCache(), fBlockNumber); 92 fBlock = NULL; 93 } 94} 95 96 97inline status_t 98CachedBlock::SetTo(off_t block) 99{ 100 return SetTo(block, block, 1); 101} 102 103 104inline status_t 105CachedBlock::SetTo(off_t block, off_t base, size_t length) 106{ 107 Unset(); 108 fBlockNumber = block; 109 return block_cache_get_etc(fVolume->BlockCache(), block, base, length, 110 (const void**)&fBlock); 111} 112 113 114inline status_t 115CachedBlock::SetTo(long_address address) 116{ 117 off_t block; 118 if (fVolume->MapBlock(address, &block) == B_OK) 119 return SetTo(block, block, 1); 120 121 return B_BAD_VALUE; 122} 123 124 125template <class Accessor, class Descriptor> 126inline status_t 127CachedBlock::SetTo(Accessor &accessor, Descriptor &descriptor) 128{ 129 // Make a long_address out of the descriptor and call it a day 130 long_address address; 131 address.set_to(accessor.GetBlock(descriptor), 132 accessor.GetPartition(descriptor)); 133 return SetTo(address); 134} 135 136 137#endif // _UDF_CACHED_BLOCK_H 138