From 4ef471dec035b93c621f2cf0ceb6c355bd95eb10 Mon Sep 17 00:00:00 2001 From: Salvatore Benedetto Date: Fri, 8 Aug 2008 22:53:36 +0000 Subject: [PATCH] Start porting udf - Cleaning up AllocationDescriptorList in order to follow our coding guidelines - Moving methods implentation outside the class I've already ported udf but I'm going to commit it one file at the time so it's easier to review, plus I still have to clean up the code. Please review. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26880 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- .../udf/AllocationDescriptorList.h | 447 ++++++++++-------- 1 file changed, 245 insertions(+), 202 deletions(-) diff --git a/src/add-ons/kernel/file_systems/udf/AllocationDescriptorList.h b/src/add-ons/kernel/file_systems/udf/AllocationDescriptorList.h index a5e114f4a0..6fd42e0454 100644 --- a/src/add-ons/kernel/file_systems/udf/AllocationDescriptorList.h +++ b/src/add-ons/kernel/file_systems/udf/AllocationDescriptorList.h @@ -1,27 +1,25 @@ -//---------------------------------------------------------------------- -// This software is part of the OpenBeOS distribution and is covered -// by the OpenBeOS license. -// -// Copyright (c) 2003 Tyler Dauwalder, tyler@dauwalder.net -//--------------------------------------------------------------------- +/* + * Copyright 2008, Salvatore Benedetto, salvatore.benedetto@gmail.com + * Copyright 2003, Tyler Dauwalder, tyler@dauwalder.net. + * Distributed under the terms of the MIT License. + */ + #ifndef _UDF_ALLOCATION_DESCRIPTOR_LIST_H #define _UDF_ALLOCATION_DESCRIPTOR_LIST_H -/*! \file AllocationDescriptorList.h -*/ +/*! \file AllocationDescriptorList.h */ -#include "kernel_cpp.h" #include "UdfDebug.h" -#include "UdfStructures.h" #include "Icb.h" +#include "UdfStructures.h" #include "Volume.h" -namespace Udf { +#include /*! \brief Common interface for dealing with the three standard forms of allocation descriptors used in UDF icbs. - + The \c Accessor class is an allocation descriptor accessor class for the allocation scheme of interest. Instances of it should be passable by value, and should define the following public members: @@ -35,227 +33,272 @@ template class AllocationDescriptorList { private: typedef typename Accessor::DescriptorType Descriptor; + public: - AllocationDescriptorList(Icb *icb, Accessor accessor = Accessor()) - : fIcb(icb) - , fVolume(icb->GetVolume()) - , fIcbDescriptors(reinterpret_cast(icb->AllocationDescriptors())) - , fIcbDescriptorsSize(icb->AllocationDescriptorsSize()) - , fAdditionalDescriptors(icb->GetVolume()) - , fReadFromIcb(true) - , fAccessor(accessor) - , fDescriptorIndex(0) - , fDescriptorNumber(0) - , fBlockIndex(0) - { - DEBUG_INIT("AllocationDescriptorList<>"); - _WalkContinuationChain(_CurrentDescriptor()); - } - - /*! \brief Finds the extent for the given address in the stream, - returning it in the address pointed to by \a blockRun. - - \param start The byte address of interest - \param extent The extent containing the stream address given - by \c start. - \param isEmpty If set to true, indicates that the given extent is unrecorded - and thus its contents should be interpreted as all zeros. - */ - status_t FindExtent(off_t start, long_address *extent, bool *isEmpty) { - DEBUG_INIT_ETC("AllocationDescriptorList<>", - ("start: %Ld, extent: %p, isEmpty: %p", start, extent, isEmpty)); - off_t startBlock = start >> fVolume->BlockShift(); - - // This should never have to happen, as FindExtent is only called by - // Icb::_Read() sequentially as a file read is performed, but you - // never know. :-) - if (startBlock < _BlockIndex()) - _Rewind(); - - status_t error = B_OK; - while (true) { - Descriptor *descriptor = _CurrentDescriptor(); - if (descriptor) { - if (_BlockIndex() <= startBlock - && startBlock < _BlockIndex()+fAccessor.GetLength(*descriptor)) - { - // The start block is somewhere in this extent, so return - // the applicable tail end portion. - off_t offset = startBlock - _BlockIndex(); - extent->set_block(fAccessor.GetBlock(*descriptor)+offset); - extent->set_partition(fAccessor.GetPartition(*descriptor)); - extent->set_length(fAccessor.GetLength(*descriptor)-(offset*fVolume->BlockSize())); - extent->set_type(fAccessor.GetType(*descriptor)); - break; - } else { - _MoveToNextDescriptor(); - } - } else { - PRINT(("Descriptor #%ld found NULL\n", _DescriptorNumber())); - error = B_ERROR; - break; - } - } - RETURN(error); - } + AllocationDescriptorList(Icb *icb, + Accessor accessor = Accessor()); + + status_t FindExtent(off_t start, long_address *extent, + bool *isEmpty); private: - - Descriptor* _CurrentDescriptor() const { - DEBUG_INIT("AllocationDescriptorList<>"); - PRINT(("(_DescriptorIndex()+1)*sizeof(Descriptor) = %ld\n", (_DescriptorIndex()+1)*sizeof(Descriptor))); - PRINT(("_DescriptorArraySize() = %ld\n", _DescriptorArraySize())); - PRINT(("_DescriptorArray() = %p\n", _DescriptorArray())); - return ((_DescriptorIndex()+1)*sizeof(Descriptor) <= _DescriptorArraySize()) - ? &(_DescriptorArray()[_DescriptorIndex()]) - : NULL; - } - status_t _MoveToNextDescriptor() { - DEBUG_INIT("AllocationDescriptorList<>"); - - Descriptor* descriptor = _CurrentDescriptor(); - if (!descriptor) { - RETURN(B_ENTRY_NOT_FOUND); - } else { - // Increment our indices and get the next descriptor - // from this extent. - fBlockIndex += fAccessor.GetLength(*descriptor); - fDescriptorIndex++; - fDescriptorNumber++; - descriptor = _CurrentDescriptor(); - - // If no such descriptor exists, we've run out of - // descriptors in this extent, and we're done. The - // next time _CurrentDescriptor() is called, it will - // return NULL, signifying this. Otherwise, we have to - // see if the new descriptor identifies the next extent - // of allocation descriptors, in which case we have to - // load up the appropriate extent (guaranteed to be at - // most one block in length by UDF-2.01 5.1 and UDF-2.01 - // 2.3.11). - _WalkContinuationChain(descriptor); - } - - - RETURN(B_ERROR); - } - - void _WalkContinuationChain(Descriptor *descriptor) { - DEBUG_INIT_ETC("AllocationDescriptorList<>", - ("descriptor: %p", descriptor)); - if (descriptor && fAccessor.GetType(*descriptor) == EXTENT_TYPE_CONTINUATION) { - // Load the new block, make sure we're not trying - // to read from the icb descriptors anymore, and - // reset the descriptor index. - fAdditionalDescriptors.SetTo(fAccessor, *descriptor); - fReadFromIcb = false; - fDescriptorIndex = 0; - - // Make sure that the first descriptor in this extent isn't - // another continuation. That would be stupid, but not - // technically illegal. - _WalkContinuationChain(_CurrentDescriptor()); - - } - - - } - - void _Rewind() { - fDescriptorIndex = 0; - fDescriptorNumber = 0; - fReadFromIcb = true; - } + off_t _BlockIndex() const { return fBlockIndex; } + Descriptor *_CurrentDescriptor() const; + Descriptor *_DescriptorArray() const; + size_t _DescriptorArraySize() const; + int32 _DescriptorIndex() const { return fDescriptorIndex; } + int32 _DescriptorNumber() const { return fDescriptorNumber; } + status_t _MoveToNextDescriptor(); + void _Rewind(); + void _WalkContinuationChain(Descriptor *descriptor); - Descriptor *_DescriptorArray() const { - return fReadFromIcb - ? fIcbDescriptors - : reinterpret_cast(fAdditionalDescriptors.Block()); - } - - size_t _DescriptorArraySize() const { - return fReadFromIcb ? fIcbDescriptorsSize : fAdditionalDescriptors.BlockSize(); - } - - int32 _DescriptorIndex() const { - return fDescriptorIndex; - } - - int32 _DescriptorNumber() const { - return fDescriptorNumber; - } - - off_t _BlockIndex() const { - return fBlockIndex; - } + CachedBlock fAdditionalDescriptors; + Icb *fIcb; + Descriptor *fIcbDescriptors; + int32 fIcbDescriptorsSize; + bool fReadFromIcb; + Volume *fVolume; - Icb *fIcb; - Volume *fVolume; - Descriptor *fIcbDescriptors; - int32 fIcbDescriptorsSize; - CachedBlock fAdditionalDescriptors; - bool fReadFromIcb; - - Accessor fAccessor; - int32 fDescriptorIndex; - int32 fDescriptorNumber; - off_t fBlockIndex; - + Accessor fAccessor; + int32 fDescriptorIndex; + int32 fDescriptorNumber; + off_t fBlockIndex; }; -// Accessors + +template +AllocationDescriptorList::AllocationDescriptorList(Icb *icb, + Accessor accessor) + : + fAccessor(accessor), + fAdditionalDescriptors(icb->GetVolume()), + fBlockIndex(0), + fIcb(icb), + fIcbDescriptors((Descriptor *)icb->AllocationDescriptors()), + fDescriptorIndex(0), + fDescriptorNumber(0), + fIcbDescriptorsSize(icb->AllocationDescriptorsSize()), + fReadFromIcb(true), + fVolume(icb->GetVolume()) +{ + DEBUG_INIT("AllocationDescriptorList<>"); + _WalkContinuationChain(_CurrentDescriptor()); +} + +/*! \brief Finds the extent for the given address in the stream, + returning it in the address pointed to by \a blockRun. + + \param start The byte address of interest + \param extent The extent containing the stream address given + by \c start. + \param isEmpty If set to true, indicates that the given extent is + unrecorded and thus its contents should be interpreted + as all zeros. +*/ +template +status_t +AllocationDescriptorList::FindExtent(off_t start, + long_address *extent, bool *isEmpty) +{ + TRACE(("UDF: AllocationDescriptorList<>::FindExtent: start: %Ld, " + "extent: %p, isEmpty: %p", start, extent, isEmpty)); + + off_t startBlock = start >> fVolume->BlockShift(); + + // This should never have to happen, as FindExtent is only called by + // Icb::_Read() sequentially, as a file read is performed, but you + // never know. :-) + if (startBlock < _BlockIndex()) + _Rewind(); + + status_t status = B_OK; + while (true) { + Descriptor *descriptor = _CurrentDescriptor(); + if (descriptor) { + if (_BlockIndex() <= startBlock && startBlock + < _BlockIndex() + fAccessor.GetLength(*descriptor)) { + // The start block is somewhere in this extent, so return + // the applicable tail end portion. + off_t offset = startBlock - _BlockIndex(); + extent->set_block(fAccessor.GetBlock(*descriptor) + offset); + extent->set_partition(fAccessor.GetPartition(*descriptor)); + extent->set_length(fAccessor.GetLength(*descriptor) + - (offset*fVolume->BlockSize())); + extent->set_type(fAccessor.GetType(*descriptor)); + break; + } else { + _MoveToNextDescriptor(); + } + } else { + TRACE_ERROR(("UDF: AllocationDescriptorList<>::FindExtent: " + "Descriptor #%ld found NULL\n", _DescriptorNumber())); + status = B_ERROR; + break; + } + } + + return status; +} + + +// #pragma - Private methods + +template +AllocationDescriptorList::Descriptor* +AllocationDescriptorList::_CurrentDescriptor() const +{ + DEBUG_INIT("AllocationDescriptorList<>"); + PRINT(("(_DescriptorIndex()+1)*sizeof(Descriptor) = %ld\n", (_DescriptorIndex()+1)*sizeof(Descriptor))); + PRINT(("_DescriptorArraySize() = %ld\n", _DescriptorArraySize())); + PRINT(("_DescriptorArray() = %p\n", _DescriptorArray())); + return ((_DescriptorIndex() + 1) * sizeof(Descriptor) + <= _DescriptorArraySize()) + ? &(_DescriptorArray()[_DescriptorIndex()]) + : NULL; +} + +template +status_t +AllocationDescriptorList::_MoveToNextDescriptor() +{ + Descriptor* descriptor = _CurrentDescriptor(); + if (!descriptor) + return B_ENTRY_NOT_FOUND; + + // Increment our indices and get the next descriptor + // from this extent. + fBlockIndex += fAccessor.GetLength(*descriptor); + fDescriptorIndex++; + fDescriptorNumber++; + descriptor = _CurrentDescriptor(); + + // If no such descriptor exists, we've run out of + // descriptors in this extent, and we're done. The + // next time _CurrentDescriptor() is called, it will + // return NULL, signifying this. Otherwise, we have to + // see if the new descriptor identifies the next extent + // of allocation descriptors, in which case we have to + // load up the appropriate extent (guaranteed to be at + // most one block in length by UDF-2.01 5.1 and UDF-2.01 + // 2.3.11). + _WalkContinuationChain(descriptor); + + return B_ERROR; +} + + +template +void +AllocationDescriptorList::_WalkContinuationChain(Descriptor *descriptor) +{ + if (descriptor + && fAccessor.GetType(*descriptor) == EXTENT_TYPE_CONTINUATION) { + // Load the new block, make sure we're not trying + // to read from the icb descriptors anymore, and + // reset the descriptor index. + fAdditionalDescriptors.SetTo(fAccessor, *descriptor); + fReadFromIcb = false; + fDescriptorIndex = 0; + + // Make sure that the first descriptor in this extent isn't + // another continuation. That would be stupid, but not + // technically illegal. + _WalkContinuationChain(_CurrentDescriptor()); + } +} + + +template +void +AllocationDescriptorList::_Rewind() +{ + fDescriptorIndex = 0; + fDescriptorNumber = 0; + fReadFromIcb = true; +} + + +template +AllocationDescriptorList::Descriptor* +AllocationDescriptorList::_DescriptorArray() const +{ + return fReadFromIcb ? fIcbDescriptors + : (AllocationDescriptorList::Descriptor *) + fAdditionalDescriptors.Block(); +} + + +template +size_t +AllocationDescriptorList::_DescriptorArraySize() const +{ + return fReadFromIcb ? fIcbDescriptorsSize + : fAdditionalDescriptors.BlockSize(); +} + + +// pragma - Accessors class ShortDescriptorAccessor { public: ShortDescriptorAccessor(uint16 partition) - : fPartition(partition) + : + fPartition(partition) { } - + typedef short_address DescriptorType; - inline uint8 GetType(DescriptorType &descriptor) const { + inline uint32 GetBlock(DescriptorType &descriptor) const + { + return descriptor.block(); + } + + inline uint32 GetLength(DescriptorType &descriptor) const + { + return descriptor.length(); + } + + inline uint16 GetPartition(DescriptorType &descriptor) const + { + return fPartition; + } + + inline uint8 GetType(DescriptorType &descriptor) const + { return descriptor.type(); } - inline uint32 GetBlock(DescriptorType &descriptor) const { - return descriptor.block(); - } - - inline uint16 GetPartition(DescriptorType &descriptor) const { - return fPartition; - } - - inline uint32 GetLength(DescriptorType &descriptor) const { - return descriptor.length(); - } private: - uint16 fPartition; + uint16 fPartition; }; + class LongDescriptorAccessor { public: typedef long_address DescriptorType; - inline uint8 GetType(DescriptorType &descriptor) const { - return descriptor.type(); - } - - inline uint32 GetBlock(DescriptorType &descriptor) const { + inline uint32 GetBlock(DescriptorType &descriptor) const + { return descriptor.block(); } - - inline uint16 GetPartition(DescriptorType &descriptor) const { + + inline uint32 GetLength(DescriptorType &descriptor) const + { + return descriptor.length(); + } + + inline uint16 GetPartition(DescriptorType &descriptor) const + { return descriptor.partition(); } - - inline uint32 GetLength(DescriptorType &descriptor) const { - return descriptor.length(); + + inline uint8 GetType(DescriptorType &descriptor) const + { + return descriptor.type(); } }; - -}; // namespace Udf - #endif // _UDF_ALLOCATION_DESCRIPTOR_LIST_H +