#include "VirtualDir.h"
#include <string.h>
#include <AutoDeleter.h>
VirtualDirEntry::VirtualDirEntry()
: fName(),
fNode(NULL)
{
}
VirtualDirEntry::~VirtualDirEntry()
{
}
status_t
VirtualDirEntry::SetTo(const char* name, Node* node)
{
if (!name || strlen(name) == 0 || !node)
return B_BAD_VALUE;
if (!fName.SetTo(name))
return B_NO_MEMORY;
fNode = node;
return B_OK;
}
const char*
VirtualDirEntry::GetName() const
{
return fName.GetString();
}
Node*
VirtualDirEntry::GetNode() const
{
return fNode;
}
VirtualDirIterator::VirtualDirIterator()
: fDirectory(NULL),
fCurrentEntry(NULL),
fState(STATE_DOT)
{
}
VirtualDirIterator::~VirtualDirIterator()
{
SetDirectory(NULL);
}
void
VirtualDirIterator::SetDirectory(VirtualDir* directory, bool onlyChildren)
{
if (fDirectory)
fDirectory->RemoveDirIterator(this);
fDirectory = directory;
if (fDirectory) {
fDirectory->AddDirIterator(this);
if (onlyChildren) {
fCurrentEntry = fDirectory->GetFirstEntry();
fState = STATE_OTHERS;
} else {
fCurrentEntry = NULL;
fState = STATE_DOT;
}
}
}
bool
VirtualDirIterator::GetCurrentEntry(const char** name, Node** node)
{
if (!fDirectory)
return false;
switch (fState) {
case STATE_DOT:
*name = ".";
*node = fDirectory;
return true;
case STATE_DOT_DOT:
*name = "..";
*node = fDirectory->GetParent();
if (!*node)
*node = fDirectory;
return true;
default:
if (!fCurrentEntry)
return false;
*name = fCurrentEntry->GetName();
*node = fCurrentEntry->GetNode();
return true;
}
}
VirtualDirEntry*
VirtualDirIterator::GetCurrentEntry() const
{
return fCurrentEntry;
}
void
VirtualDirIterator::NextEntry()
{
if (!fDirectory)
return;
switch (fState) {
case STATE_DOT:
fState = STATE_DOT_DOT;
break;
case STATE_DOT_DOT:
fState = STATE_OTHERS;
fCurrentEntry = fDirectory->GetFirstEntry();
break;
default:
if (fCurrentEntry)
fCurrentEntry = fDirectory->GetNextEntry(fCurrentEntry);
break;
}
}
void
VirtualDirIterator::Rewind()
{
fState = STATE_DOT;
fCurrentEntry = NULL;
}
VirtualDir::VirtualDir(Volume* volume, vnode_id nodeID)
: Node(volume, nodeID),
fParent(NULL),
fCreationTime(0),
fEntries(),
fEntryList(),
fIterators()
{
}
VirtualDir::~VirtualDir()
{
while (VirtualDirEntry* entry = GetFirstEntry())
RemoveEntry(entry->GetName());
}
status_t
VirtualDir::InitCheck() const
{
return fEntries.InitCheck();
}
void
VirtualDir::SetParent(VirtualDir* parent)
{
fParent = parent;
}
VirtualDir*
VirtualDir::GetParent() const
{
return fParent;
}
time_t
VirtualDir::GetCreationTime() const
{
return fCreationTime;
}
status_t
VirtualDir::AddEntry(const char* name, Node* child)
{
if (!name || !child || fEntries.ContainsKey(name))
return B_BAD_VALUE;
VirtualDirEntry* entry = new(std::nothrow) VirtualDirEntry;
if (!entry)
return B_NO_MEMORY;
ObjectDeleter<VirtualDirEntry> entryDeleter(entry);
status_t error = entry->SetTo(name, child);
if (error != B_OK)
return error;
error = fEntries.Put(name, entry);
if (error != B_OK)
return error;
fEntryList.Insert(entry);
entryDeleter.Detach();
if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
childDir->SetParent(this);
return error;
}
Node*
VirtualDir::RemoveEntry(const char* name)
{
if (!name)
return NULL;
Node* child = NULL;
VirtualDirEntry* entry = fEntries.Remove(name);
if (entry) {
child = entry->GetNode();
for (VirtualDirIterator* iterator = fIterators.First();
iterator;
iterator = fIterators.GetNext(iterator)) {
if (iterator->GetCurrentEntry() == entry)
iterator->NextEntry();
}
fEntryList.Remove(entry);
delete entry;
if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
childDir->SetParent(NULL);
}
return child;
}
VirtualDirEntry*
VirtualDir::GetEntry(const char* name) const
{
if (!name)
return NULL;
return fEntries.Get(name);
}
Node*
VirtualDir::GetChildNode(const char* name) const
{
if (VirtualDirEntry* entry = GetEntry(name))
return entry->GetNode();
return NULL;
}
VirtualDirEntry*
VirtualDir::GetFirstEntry() const
{
return fEntryList.First();
}
VirtualDirEntry*
VirtualDir::GetNextEntry(VirtualDirEntry* entry) const
{
if (!entry)
return NULL;
return fEntryList.GetNext(entry);
}
void
VirtualDir::AddDirIterator(VirtualDirIterator* iterator)
{
if (!iterator)
return;
fIterators.Insert(iterator);
}
void
VirtualDir::RemoveDirIterator(VirtualDirIterator* iterator)
{
if (!iterator)
return;
fIterators.Remove(iterator);
}