packagefs: Refactor UnpackingAttributeDirectoryCookie

Pull out a reusable base class AutoPackageAttributeDirectoryCookie.
This commit is contained in:
Ingo Weinhold
2013-11-21 13:29:19 +01:00
parent 79b1f63e81
commit 4c61288e73
5 changed files with 178 additions and 77 deletions
@@ -22,6 +22,7 @@ HAIKU_PACKAGE_FS_SOURCES =
AttributeCookie.cpp
AttributeDirectoryCookie.cpp
AttributeIndex.cpp
AutoPackageAttributeDirectoryCookie.cpp
AutoPackageAttributes.cpp
BlockBufferPoolKernel.cpp
CachedDataReader.cpp
@@ -0,0 +1,110 @@
/*
* Copyright 2011-2013, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#include "AutoPackageAttributeDirectoryCookie.h"
#include "DebugSupport.h"
#include "Utils.h"
AutoPackageAttributeDirectoryCookie::AutoPackageAttributeDirectoryCookie()
:
fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST)
{
}
AutoPackageAttributeDirectoryCookie::~AutoPackageAttributeDirectoryCookie()
{
}
status_t
AutoPackageAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize, uint32* _count)
{
uint32 maxCount = *_count;
uint32 count = 0;
dirent* previousEntry = NULL;
String customAttributeName = CurrentCustomAttributeName();
while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
|| !customAttributeName.IsEmpty()) {
// don't read more entries than requested
if (count >= maxCount)
break;
// align the buffer for subsequent entries
if (count > 0) {
addr_t offset = (addr_t)buffer % 8;
if (offset > 0) {
offset = 8 - offset;
if (bufferSize <= offset)
break;
previousEntry->d_reclen += offset;
buffer = (dirent*)((addr_t)buffer + offset);
bufferSize -= offset;
}
}
// get the attribute name
const String& name = fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
? AutoPackageAttributes::NameForAttribute(
(AutoPackageAttribute)fState)
: customAttributeName;
// fill in the entry name -- checks whether the entry fits into the
// buffer
if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
if (count == 0)
RETURN_ERROR(B_BUFFER_OVERFLOW);
break;
}
// fill in the other data
buffer->d_dev = volumeID;
buffer->d_ino = nodeID;
count++;
previousEntry = buffer;
bufferSize -= buffer->d_reclen;
buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
fState++;
else
customAttributeName = NextCustomAttributeName();
}
*_count = count;
return B_OK;
}
status_t
AutoPackageAttributeDirectoryCookie::Rewind()
{
fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
return B_OK;
}
String
AutoPackageAttributeDirectoryCookie::CurrentCustomAttributeName()
{
return String();
}
String
AutoPackageAttributeDirectoryCookie::NextCustomAttributeName()
{
return String();
}
@@ -0,0 +1,41 @@
/*
* Copyright 2011-2013, Ingo Weinhold, [email protected].
* Distributed under the terms of the MIT License.
*/
#ifndef AUTO_PACKAGE_ATTRIBUTE_DIRECTORY_COOKIE_H
#define AUTO_PACKAGE_ATTRIBUTE_DIRECTORY_COOKIE_H
#include "AttributeDirectoryCookie.h"
#include "AutoPackageAttributes.h"
/*!
When used for nodes that only have the automatic package attributes, the
class can be used as is. Otherwise subclassing is required.
Derived classes need to override Rewind() to rewind to their first
attribute, but also call the base class version. Furthermore they must
implement CurrentCustomAttributeName() to return the current attribute's
name and NextCustomAttributeName() to iterate to the next attribute and
return its name.
*/
class AutoPackageAttributeDirectoryCookie : public AttributeDirectoryCookie {
public:
AutoPackageAttributeDirectoryCookie();
virtual ~AutoPackageAttributeDirectoryCookie();
virtual status_t Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize,
uint32* _count);
virtual status_t Rewind();
protected:
virtual String CurrentCustomAttributeName();
virtual String NextCustomAttributeName();
private:
uint32 fState;
};
#endif // AUTO_PACKAGE_ATTRIBUTE_DIRECTORY_COOKIE_H
@@ -8,15 +8,14 @@
#include "DebugSupport.h"
#include "PackageNode.h"
#include "Utils.h"
UnpackingAttributeDirectoryCookie::UnpackingAttributeDirectoryCookie(
PackageNode* packageNode)
:
AutoPackageAttributeDirectoryCookie(),
fPackageNode(packageNode),
fAttribute(NULL),
fState(AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST)
fAttribute(NULL)
{
if (fPackageNode != NULL) {
fPackageNode->AcquireReference();
@@ -46,75 +45,27 @@ UnpackingAttributeDirectoryCookie::Open(PackageNode* packageNode,
}
status_t
UnpackingAttributeDirectoryCookie::Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize, uint32* _count)
{
uint32 maxCount = *_count;
uint32 count = 0;
dirent* previousEntry = NULL;
while (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT || fAttribute != NULL) {
// don't read more entries than requested
if (count >= maxCount)
break;
// align the buffer for subsequent entries
if (count > 0) {
addr_t offset = (addr_t)buffer % 8;
if (offset > 0) {
offset = 8 - offset;
if (bufferSize <= offset)
break;
previousEntry->d_reclen += offset;
buffer = (dirent*)((addr_t)buffer + offset);
bufferSize -= offset;
}
}
// get the attribute name
const String& name = fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT
? AutoPackageAttributes::NameForAttribute(
(AutoPackageAttribute)fState)
: fAttribute->Name();
// fill in the entry name -- checks whether the entry fits into the
// buffer
if (!set_dirent_name(buffer, bufferSize, name, strlen(name))) {
if (count == 0)
RETURN_ERROR(B_BUFFER_OVERFLOW);
break;
}
// fill in the other data
buffer->d_dev = volumeID;
buffer->d_ino = nodeID;
count++;
previousEntry = buffer;
bufferSize -= buffer->d_reclen;
buffer = (dirent*)((addr_t)buffer + buffer->d_reclen);
if (fState < AUTO_PACKAGE_ATTRIBUTE_ENUM_COUNT)
fState++;
else
fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
}
*_count = count;
return B_OK;
}
status_t
UnpackingAttributeDirectoryCookie::Rewind()
{
if (fPackageNode != NULL)
fAttribute = fPackageNode->Attributes().Head();
fState = AUTO_PACKAGE_ATTRIBUTE_ENUM_FIRST;
return B_OK;
return AutoPackageAttributeDirectoryCookie::Rewind();
}
String
UnpackingAttributeDirectoryCookie::CurrentCustomAttributeName()
{
return fAttribute != NULL ? fAttribute->Name() : String();
}
String
UnpackingAttributeDirectoryCookie::NextCustomAttributeName()
{
if (fAttribute != NULL)
fAttribute = fPackageNode->Attributes().GetNext(fAttribute);
return fAttribute != NULL ? fAttribute->Name() : String();
}
@@ -6,17 +6,15 @@
#define UNPACKING_ATTRIBUTE_DIRECTORY_COOKIE_H
#include "AttributeDirectoryCookie.h"
#include "AutoPackageAttributes.h"
#include "AutoPackageAttributeDirectoryCookie.h"
struct dirent;
class PackageNode;
class PackageNodeAttribute;
class UnpackingAttributeDirectoryCookie : public AttributeDirectoryCookie {
class UnpackingAttributeDirectoryCookie
: public AutoPackageAttributeDirectoryCookie {
public:
UnpackingAttributeDirectoryCookie(
PackageNode* packageNode);
@@ -25,15 +23,15 @@ public:
static status_t Open(PackageNode* packageNode,
AttributeDirectoryCookie*& _cookie);
virtual status_t Read(dev_t volumeID, ino_t nodeID,
struct dirent* buffer, size_t bufferSize,
uint32* _count);
virtual status_t Rewind();
protected:
virtual String CurrentCustomAttributeName();
virtual String NextCustomAttributeName();
private:
PackageNode* fPackageNode;
PackageNodeAttribute* fAttribute;
uint32 fState;
};