* Copyright (c) 2008 Stephan Aßmus <superstippi@gmx.de>
* Copyright (c) 1998-2007 Matthijs Hollemans
* All rights reserved. Distributed under the terms of the MIT License.
*/
#include "InitialIterator.h"
#include <new>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <Directory.h>
#include "Model.h"
using std::nothrow;
InitialIterator::InitialIterator(const Model* model)
: FileIterator(),
fDirectories(32),
fCurrentDir(new (nothrow) BDirectory(&model->fDirectory)),
fCurrentRef(0),
fSelectedFiles(model->fSelectedFiles),
fRecurseDirs(model->fRecurseDirs),
fRecurseLinks(model->fRecurseLinks),
fSkipDotDirs(model->fSkipDotDirs),
fTextOnly(model->fTextOnly)
{
if (!fCurrentDir || !fDirectories.AddItem(fCurrentDir)) {
delete fCurrentDir;
fCurrentDir = NULL;
}
}
InitialIterator::~InitialIterator()
{
for (int32 i = fDirectories.CountItems() - 1; i >= 0; i--)
delete (BDirectory*)fDirectories.ItemAt(i);
}
bool
InitialIterator::IsValid() const
{
return fCurrentDir != NULL;
}
bool
InitialIterator::GetNextName(char* buffer)
{
BEntry entry;
struct stat fileStat;
while (true) {
if (!_GetNextEntry(entry))
return false;
if (entry.GetStat(&fileStat) == B_OK) {
if (S_ISDIR(fileStat.st_mode)) {
_ExamineSubdir(entry);
} else {
if (_ExamineFile(entry, buffer, fTextOnly))
return true;
}
}
}
}
bool
InitialIterator::NotifyNegatives() const
{
return false;
}
bool
InitialIterator::GetTopEntry(BEntry& entry)
{
entry_ref fileRef;
if (fSelectedFiles.FindRef("refs", fCurrentRef, &fileRef) == B_OK) {
entry.SetTo(&fileRef, fRecurseLinks);
++fCurrentRef;
return true;
} else if (fCurrentRef > 0) {
return false;
} else if (fCurrentDir != NULL) {
return fCurrentDir->GetNextEntry(&entry, fRecurseLinks) == B_OK;
}
return false;
}
bool
InitialIterator::FollowSubdir(BEntry& entry) const
{
if (!fRecurseDirs)
return false;
if (fSkipDotDirs) {
char nameBuf[B_FILE_NAME_LENGTH];
if (entry.GetName(nameBuf) == B_OK) {
if (*nameBuf == '.')
return false;
}
}
return true;
}
bool
InitialIterator::_GetNextEntry(BEntry& entry)
{
if (fDirectories.CountItems() == 1)
return GetTopEntry(entry);
else
return _GetSubEntry(entry);
}
bool
InitialIterator::_GetSubEntry(BEntry& entry)
{
if (!fCurrentDir)
return false;
if (fCurrentDir->GetNextEntry(&entry, fRecurseLinks) == B_OK)
return true;
fDirectories.RemoveItem(fCurrentDir);
delete fCurrentDir;
fCurrentDir = (BDirectory*)fDirectories.LastItem();
return _GetNextEntry(entry);
}
void
InitialIterator::_ExamineSubdir(BEntry& entry)
{
if (!FollowSubdir(entry))
return;
BDirectory* dir = new (nothrow) BDirectory(&entry);
if (dir == NULL || dir->InitCheck() != B_OK || !fDirectories.AddItem(dir)) {
delete dir;
return;
}
fCurrentDir = dir;
}