1/*
2 * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * All rights reserved. Distributed under the terms of the MIT license.
4 */
5
6#include "Directory.h"
7#include "Entry.h"
8#include "EntryIterator.h"
9#include "Volume.h"
10
11// constructor
12EntryIterator::EntryIterator(Directory *directory)
13	: fDirectory(directory),
14	  fEntry(NULL),
15	  fSuspended(false),
16	  fIsNext(false),
17	  fDone(false)
18{
19}
20
21// destructor
22EntryIterator::~EntryIterator()
23{
24	Unset();
25}
26
27// SetTo
28status_t
29EntryIterator::SetTo(Directory *directory)
30{
31	Unset();
32	status_t error = (directory ? B_OK : B_BAD_VALUE);
33	if (error == B_OK) {
34		fDirectory = directory;
35		fEntry = NULL;
36		fSuspended = false;
37		fIsNext = false;
38		fDone = false;
39	}
40	return error;
41}
42
43// Unset
44void
45EntryIterator::Unset()
46{
47	if (fDirectory && fSuspended)
48		Resume();
49	fDirectory = NULL;
50	fEntry = NULL;
51	fSuspended = false;
52	fIsNext = false;
53	fDone = false;
54}
55
56// Suspend
57status_t
58EntryIterator::Suspend()
59{
60	status_t error = (fDirectory ? B_OK : B_ERROR);
61	if (error == B_OK) {
62		if (fDirectory->GetVolume()->IteratorLock()) {
63			if (!fSuspended) {
64				if (fEntry)
65					fEntry->AttachEntryIterator(this);
66				fDirectory->GetVolume()->IteratorUnlock();
67				fSuspended = true;
68			} else
69				error = B_ERROR;
70		} else
71			error = B_ERROR;
72	}
73	return error;
74}
75
76// Resume
77status_t
78EntryIterator::Resume()
79{
80	status_t error = (fDirectory ? B_OK : B_ERROR);
81	if (error == B_OK) {
82		if (fDirectory->GetVolume()->IteratorLock()) {
83			if (fSuspended) {
84				if (fEntry)
85					fEntry->DetachEntryIterator(this);
86				fSuspended = false;
87			}
88			fDirectory->GetVolume()->IteratorUnlock();
89		} else
90			error = B_ERROR;
91	}
92	return error;
93}
94
95// GetNext
96status_t
97EntryIterator::GetNext(Entry **entry)
98{
99	status_t error = B_ENTRY_NOT_FOUND;
100	if (!fDone && fDirectory && entry) {
101		if (fIsNext) {
102			fIsNext = false;
103			if (fEntry)
104				error = B_OK;
105		} else
106			error = fDirectory->GetNextEntry(&fEntry);
107		*entry = fEntry;
108	}
109	fDone = (error != B_OK);
110	return error;
111}
112
113// Rewind
114status_t
115EntryIterator::Rewind()
116{
117	status_t error = (fDirectory ? B_OK : B_ERROR);
118	if (error == B_OK) {
119		if (fDirectory->GetVolume()->IteratorLock()) {
120			if (fSuspended && fEntry)
121				fEntry->DetachEntryIterator(this);
122			fEntry = NULL;
123			fIsNext = false;
124			fDone = false;
125			fDirectory->GetVolume()->IteratorUnlock();
126		} else
127			error = B_ERROR;
128	}
129	return error;
130}
131
132// SetCurrent
133void
134EntryIterator::SetCurrent(Entry *entry, bool isNext)
135{
136	fIsNext = isNext;
137	fEntry = entry;
138	fDone = !fEntry;
139}
140
141