1*5a1d355fSStephan Aßmus // VirtualDir.cpp
2*5a1d355fSStephan Aßmus
3*5a1d355fSStephan Aßmus #include "VirtualDir.h"
4*5a1d355fSStephan Aßmus
5*5a1d355fSStephan Aßmus #include <string.h>
6*5a1d355fSStephan Aßmus
7*5a1d355fSStephan Aßmus #include <AutoDeleter.h>
8*5a1d355fSStephan Aßmus
9*5a1d355fSStephan Aßmus // constructor
VirtualDirEntry()10*5a1d355fSStephan Aßmus VirtualDirEntry::VirtualDirEntry()
11*5a1d355fSStephan Aßmus : fName(),
12*5a1d355fSStephan Aßmus fNode(NULL)
13*5a1d355fSStephan Aßmus {
14*5a1d355fSStephan Aßmus }
15*5a1d355fSStephan Aßmus
16*5a1d355fSStephan Aßmus // destructor
~VirtualDirEntry()17*5a1d355fSStephan Aßmus VirtualDirEntry::~VirtualDirEntry()
18*5a1d355fSStephan Aßmus {
19*5a1d355fSStephan Aßmus }
20*5a1d355fSStephan Aßmus
21*5a1d355fSStephan Aßmus // SetTo
22*5a1d355fSStephan Aßmus status_t
SetTo(const char * name,Node * node)23*5a1d355fSStephan Aßmus VirtualDirEntry::SetTo(const char* name, Node* node)
24*5a1d355fSStephan Aßmus {
25*5a1d355fSStephan Aßmus if (!name || strlen(name) == 0 || !node)
26*5a1d355fSStephan Aßmus return B_BAD_VALUE;
27*5a1d355fSStephan Aßmus
28*5a1d355fSStephan Aßmus if (!fName.SetTo(name))
29*5a1d355fSStephan Aßmus return B_NO_MEMORY;
30*5a1d355fSStephan Aßmus fNode = node;
31*5a1d355fSStephan Aßmus
32*5a1d355fSStephan Aßmus return B_OK;
33*5a1d355fSStephan Aßmus }
34*5a1d355fSStephan Aßmus
35*5a1d355fSStephan Aßmus // GetName
36*5a1d355fSStephan Aßmus const char*
GetName() const37*5a1d355fSStephan Aßmus VirtualDirEntry::GetName() const
38*5a1d355fSStephan Aßmus {
39*5a1d355fSStephan Aßmus return fName.GetString();
40*5a1d355fSStephan Aßmus }
41*5a1d355fSStephan Aßmus
42*5a1d355fSStephan Aßmus // GetNode
43*5a1d355fSStephan Aßmus Node*
GetNode() const44*5a1d355fSStephan Aßmus VirtualDirEntry::GetNode() const
45*5a1d355fSStephan Aßmus {
46*5a1d355fSStephan Aßmus return fNode;
47*5a1d355fSStephan Aßmus }
48*5a1d355fSStephan Aßmus
49*5a1d355fSStephan Aßmus
50*5a1d355fSStephan Aßmus // #pragma mark -
51*5a1d355fSStephan Aßmus
52*5a1d355fSStephan Aßmus // constructor
VirtualDirIterator()53*5a1d355fSStephan Aßmus VirtualDirIterator::VirtualDirIterator()
54*5a1d355fSStephan Aßmus : fDirectory(NULL),
55*5a1d355fSStephan Aßmus fCurrentEntry(NULL),
56*5a1d355fSStephan Aßmus fState(STATE_DOT)
57*5a1d355fSStephan Aßmus {
58*5a1d355fSStephan Aßmus }
59*5a1d355fSStephan Aßmus
60*5a1d355fSStephan Aßmus // destructor
~VirtualDirIterator()61*5a1d355fSStephan Aßmus VirtualDirIterator::~VirtualDirIterator()
62*5a1d355fSStephan Aßmus {
63*5a1d355fSStephan Aßmus SetDirectory(NULL);
64*5a1d355fSStephan Aßmus }
65*5a1d355fSStephan Aßmus
66*5a1d355fSStephan Aßmus // SetDirectory
67*5a1d355fSStephan Aßmus void
SetDirectory(VirtualDir * directory,bool onlyChildren)68*5a1d355fSStephan Aßmus VirtualDirIterator::SetDirectory(VirtualDir* directory, bool onlyChildren)
69*5a1d355fSStephan Aßmus {
70*5a1d355fSStephan Aßmus // unset the old directory
71*5a1d355fSStephan Aßmus if (fDirectory)
72*5a1d355fSStephan Aßmus fDirectory->RemoveDirIterator(this);
73*5a1d355fSStephan Aßmus
74*5a1d355fSStephan Aßmus // set the new directory
75*5a1d355fSStephan Aßmus fDirectory = directory;
76*5a1d355fSStephan Aßmus if (fDirectory) {
77*5a1d355fSStephan Aßmus fDirectory->AddDirIterator(this);
78*5a1d355fSStephan Aßmus
79*5a1d355fSStephan Aßmus if (onlyChildren) {
80*5a1d355fSStephan Aßmus fCurrentEntry = fDirectory->GetFirstEntry();
81*5a1d355fSStephan Aßmus fState = STATE_OTHERS;
82*5a1d355fSStephan Aßmus } else {
83*5a1d355fSStephan Aßmus fCurrentEntry = NULL;
84*5a1d355fSStephan Aßmus fState = STATE_DOT;
85*5a1d355fSStephan Aßmus }
86*5a1d355fSStephan Aßmus }
87*5a1d355fSStephan Aßmus }
88*5a1d355fSStephan Aßmus
89*5a1d355fSStephan Aßmus // GetCurrentEntry
90*5a1d355fSStephan Aßmus bool
GetCurrentEntry(const char ** name,Node ** node)91*5a1d355fSStephan Aßmus VirtualDirIterator::GetCurrentEntry(const char** name, Node** node)
92*5a1d355fSStephan Aßmus {
93*5a1d355fSStephan Aßmus if (!fDirectory)
94*5a1d355fSStephan Aßmus return false;
95*5a1d355fSStephan Aßmus switch (fState) {
96*5a1d355fSStephan Aßmus case STATE_DOT:
97*5a1d355fSStephan Aßmus *name = ".";
98*5a1d355fSStephan Aßmus *node = fDirectory;
99*5a1d355fSStephan Aßmus return true;
100*5a1d355fSStephan Aßmus case STATE_DOT_DOT:
101*5a1d355fSStephan Aßmus *name = "..";
102*5a1d355fSStephan Aßmus *node = fDirectory->GetParent();
103*5a1d355fSStephan Aßmus if (!*node)
104*5a1d355fSStephan Aßmus *node = fDirectory;
105*5a1d355fSStephan Aßmus return true;
106*5a1d355fSStephan Aßmus default:
107*5a1d355fSStephan Aßmus if (!fCurrentEntry)
108*5a1d355fSStephan Aßmus return false;
109*5a1d355fSStephan Aßmus *name = fCurrentEntry->GetName();
110*5a1d355fSStephan Aßmus *node = fCurrentEntry->GetNode();
111*5a1d355fSStephan Aßmus return true;
112*5a1d355fSStephan Aßmus }
113*5a1d355fSStephan Aßmus }
114*5a1d355fSStephan Aßmus
115*5a1d355fSStephan Aßmus // GetCurrentEntry
116*5a1d355fSStephan Aßmus VirtualDirEntry*
GetCurrentEntry() const117*5a1d355fSStephan Aßmus VirtualDirIterator::GetCurrentEntry() const
118*5a1d355fSStephan Aßmus {
119*5a1d355fSStephan Aßmus return fCurrentEntry;
120*5a1d355fSStephan Aßmus }
121*5a1d355fSStephan Aßmus
122*5a1d355fSStephan Aßmus // NextEntry
123*5a1d355fSStephan Aßmus void
NextEntry()124*5a1d355fSStephan Aßmus VirtualDirIterator::NextEntry()
125*5a1d355fSStephan Aßmus {
126*5a1d355fSStephan Aßmus if (!fDirectory)
127*5a1d355fSStephan Aßmus return;
128*5a1d355fSStephan Aßmus switch (fState) {
129*5a1d355fSStephan Aßmus case STATE_DOT:
130*5a1d355fSStephan Aßmus fState = STATE_DOT_DOT;
131*5a1d355fSStephan Aßmus break;
132*5a1d355fSStephan Aßmus case STATE_DOT_DOT:
133*5a1d355fSStephan Aßmus fState = STATE_OTHERS;
134*5a1d355fSStephan Aßmus fCurrentEntry = fDirectory->GetFirstEntry();
135*5a1d355fSStephan Aßmus break;
136*5a1d355fSStephan Aßmus default:
137*5a1d355fSStephan Aßmus if (fCurrentEntry)
138*5a1d355fSStephan Aßmus fCurrentEntry = fDirectory->GetNextEntry(fCurrentEntry);
139*5a1d355fSStephan Aßmus break;
140*5a1d355fSStephan Aßmus }
141*5a1d355fSStephan Aßmus }
142*5a1d355fSStephan Aßmus
143*5a1d355fSStephan Aßmus // Rewind
144*5a1d355fSStephan Aßmus void
Rewind()145*5a1d355fSStephan Aßmus VirtualDirIterator::Rewind()
146*5a1d355fSStephan Aßmus {
147*5a1d355fSStephan Aßmus fState = STATE_DOT;
148*5a1d355fSStephan Aßmus fCurrentEntry = NULL;
149*5a1d355fSStephan Aßmus }
150*5a1d355fSStephan Aßmus
151*5a1d355fSStephan Aßmus
152*5a1d355fSStephan Aßmus // #pragma mark -
153*5a1d355fSStephan Aßmus
154*5a1d355fSStephan Aßmus // constructor
VirtualDir(Volume * volume,vnode_id nodeID)155*5a1d355fSStephan Aßmus VirtualDir::VirtualDir(Volume* volume, vnode_id nodeID)
156*5a1d355fSStephan Aßmus : Node(volume, nodeID),
157*5a1d355fSStephan Aßmus fParent(NULL),
158*5a1d355fSStephan Aßmus fCreationTime(0),
159*5a1d355fSStephan Aßmus fEntries(),
160*5a1d355fSStephan Aßmus fEntryList(),
161*5a1d355fSStephan Aßmus fIterators()
162*5a1d355fSStephan Aßmus {
163*5a1d355fSStephan Aßmus }
164*5a1d355fSStephan Aßmus
165*5a1d355fSStephan Aßmus // destructor
~VirtualDir()166*5a1d355fSStephan Aßmus VirtualDir::~VirtualDir()
167*5a1d355fSStephan Aßmus {
168*5a1d355fSStephan Aßmus while (VirtualDirEntry* entry = GetFirstEntry())
169*5a1d355fSStephan Aßmus RemoveEntry(entry->GetName());
170*5a1d355fSStephan Aßmus }
171*5a1d355fSStephan Aßmus
172*5a1d355fSStephan Aßmus // InitCheck
173*5a1d355fSStephan Aßmus status_t
InitCheck() const174*5a1d355fSStephan Aßmus VirtualDir::InitCheck() const
175*5a1d355fSStephan Aßmus {
176*5a1d355fSStephan Aßmus return fEntries.InitCheck();
177*5a1d355fSStephan Aßmus }
178*5a1d355fSStephan Aßmus
179*5a1d355fSStephan Aßmus // SetParent
180*5a1d355fSStephan Aßmus void
SetParent(VirtualDir * parent)181*5a1d355fSStephan Aßmus VirtualDir::SetParent(VirtualDir* parent)
182*5a1d355fSStephan Aßmus {
183*5a1d355fSStephan Aßmus fParent = parent;
184*5a1d355fSStephan Aßmus }
185*5a1d355fSStephan Aßmus
186*5a1d355fSStephan Aßmus // GetParent
187*5a1d355fSStephan Aßmus VirtualDir*
GetParent() const188*5a1d355fSStephan Aßmus VirtualDir::GetParent() const
189*5a1d355fSStephan Aßmus {
190*5a1d355fSStephan Aßmus return fParent;
191*5a1d355fSStephan Aßmus }
192*5a1d355fSStephan Aßmus
193*5a1d355fSStephan Aßmus // GetCreationTime
194*5a1d355fSStephan Aßmus time_t
GetCreationTime() const195*5a1d355fSStephan Aßmus VirtualDir::GetCreationTime() const
196*5a1d355fSStephan Aßmus {
197*5a1d355fSStephan Aßmus return fCreationTime;
198*5a1d355fSStephan Aßmus }
199*5a1d355fSStephan Aßmus
200*5a1d355fSStephan Aßmus // AddEntry
201*5a1d355fSStephan Aßmus status_t
AddEntry(const char * name,Node * child)202*5a1d355fSStephan Aßmus VirtualDir::AddEntry(const char* name, Node* child)
203*5a1d355fSStephan Aßmus {
204*5a1d355fSStephan Aßmus if (!name || !child || fEntries.ContainsKey(name))
205*5a1d355fSStephan Aßmus return B_BAD_VALUE;
206*5a1d355fSStephan Aßmus
207*5a1d355fSStephan Aßmus // create an entry
208*5a1d355fSStephan Aßmus VirtualDirEntry* entry = new(std::nothrow) VirtualDirEntry;
209*5a1d355fSStephan Aßmus if (!entry)
210*5a1d355fSStephan Aßmus return B_NO_MEMORY;
211*5a1d355fSStephan Aßmus ObjectDeleter<VirtualDirEntry> entryDeleter(entry);
212*5a1d355fSStephan Aßmus status_t error = entry->SetTo(name, child);
213*5a1d355fSStephan Aßmus if (error != B_OK)
214*5a1d355fSStephan Aßmus return error;
215*5a1d355fSStephan Aßmus
216*5a1d355fSStephan Aßmus // add the entry
217*5a1d355fSStephan Aßmus error = fEntries.Put(name, entry);
218*5a1d355fSStephan Aßmus if (error != B_OK)
219*5a1d355fSStephan Aßmus return error;
220*5a1d355fSStephan Aßmus fEntryList.Insert(entry);
221*5a1d355fSStephan Aßmus entryDeleter.Detach();
222*5a1d355fSStephan Aßmus
223*5a1d355fSStephan Aßmus // TODO: That's not so nice. Check whether better to move the fParent
224*5a1d355fSStephan Aßmus // property to Node.
225*5a1d355fSStephan Aßmus if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
226*5a1d355fSStephan Aßmus childDir->SetParent(this);
227*5a1d355fSStephan Aßmus
228*5a1d355fSStephan Aßmus return error;
229*5a1d355fSStephan Aßmus }
230*5a1d355fSStephan Aßmus
231*5a1d355fSStephan Aßmus // RemoveEntry
232*5a1d355fSStephan Aßmus Node*
RemoveEntry(const char * name)233*5a1d355fSStephan Aßmus VirtualDir::RemoveEntry(const char* name)
234*5a1d355fSStephan Aßmus {
235*5a1d355fSStephan Aßmus if (!name)
236*5a1d355fSStephan Aßmus return NULL;
237*5a1d355fSStephan Aßmus
238*5a1d355fSStephan Aßmus Node* child = NULL;
239*5a1d355fSStephan Aßmus VirtualDirEntry* entry = fEntries.Remove(name);
240*5a1d355fSStephan Aßmus if (entry) {
241*5a1d355fSStephan Aßmus child = entry->GetNode();
242*5a1d355fSStephan Aßmus // update the directory iterators pointing to the removed entry
243*5a1d355fSStephan Aßmus for (VirtualDirIterator* iterator = fIterators.First();
244*5a1d355fSStephan Aßmus iterator;
245*5a1d355fSStephan Aßmus iterator = fIterators.GetNext(iterator)) {
246*5a1d355fSStephan Aßmus if (iterator->GetCurrentEntry() == entry)
247*5a1d355fSStephan Aßmus iterator->NextEntry();
248*5a1d355fSStephan Aßmus }
249*5a1d355fSStephan Aßmus
250*5a1d355fSStephan Aßmus // remove the entry completely
251*5a1d355fSStephan Aßmus fEntryList.Remove(entry);
252*5a1d355fSStephan Aßmus delete entry;
253*5a1d355fSStephan Aßmus
254*5a1d355fSStephan Aßmus // TODO: See AddEntry().
255*5a1d355fSStephan Aßmus if (VirtualDir* childDir = dynamic_cast<VirtualDir*>(child))
256*5a1d355fSStephan Aßmus childDir->SetParent(NULL);
257*5a1d355fSStephan Aßmus }
258*5a1d355fSStephan Aßmus return child;
259*5a1d355fSStephan Aßmus }
260*5a1d355fSStephan Aßmus
261*5a1d355fSStephan Aßmus // GetEntry
262*5a1d355fSStephan Aßmus VirtualDirEntry*
GetEntry(const char * name) const263*5a1d355fSStephan Aßmus VirtualDir::GetEntry(const char* name) const
264*5a1d355fSStephan Aßmus {
265*5a1d355fSStephan Aßmus if (!name)
266*5a1d355fSStephan Aßmus return NULL;
267*5a1d355fSStephan Aßmus
268*5a1d355fSStephan Aßmus return fEntries.Get(name);
269*5a1d355fSStephan Aßmus }
270*5a1d355fSStephan Aßmus
271*5a1d355fSStephan Aßmus // GetChildNode
272*5a1d355fSStephan Aßmus Node*
GetChildNode(const char * name) const273*5a1d355fSStephan Aßmus VirtualDir::GetChildNode(const char* name) const
274*5a1d355fSStephan Aßmus {
275*5a1d355fSStephan Aßmus if (VirtualDirEntry* entry = GetEntry(name))
276*5a1d355fSStephan Aßmus return entry->GetNode();
277*5a1d355fSStephan Aßmus return NULL;
278*5a1d355fSStephan Aßmus }
279*5a1d355fSStephan Aßmus
280*5a1d355fSStephan Aßmus // GetFirstEntry
281*5a1d355fSStephan Aßmus VirtualDirEntry*
GetFirstEntry() const282*5a1d355fSStephan Aßmus VirtualDir::GetFirstEntry() const
283*5a1d355fSStephan Aßmus {
284*5a1d355fSStephan Aßmus return fEntryList.First();
285*5a1d355fSStephan Aßmus }
286*5a1d355fSStephan Aßmus
287*5a1d355fSStephan Aßmus // GetNextEntry
288*5a1d355fSStephan Aßmus VirtualDirEntry*
GetNextEntry(VirtualDirEntry * entry) const289*5a1d355fSStephan Aßmus VirtualDir::GetNextEntry(VirtualDirEntry* entry) const
290*5a1d355fSStephan Aßmus {
291*5a1d355fSStephan Aßmus if (!entry)
292*5a1d355fSStephan Aßmus return NULL;
293*5a1d355fSStephan Aßmus return fEntryList.GetNext(entry);
294*5a1d355fSStephan Aßmus }
295*5a1d355fSStephan Aßmus
296*5a1d355fSStephan Aßmus // AddDirIterator
297*5a1d355fSStephan Aßmus void
AddDirIterator(VirtualDirIterator * iterator)298*5a1d355fSStephan Aßmus VirtualDir::AddDirIterator(VirtualDirIterator* iterator)
299*5a1d355fSStephan Aßmus {
300*5a1d355fSStephan Aßmus if (!iterator)
301*5a1d355fSStephan Aßmus return;
302*5a1d355fSStephan Aßmus
303*5a1d355fSStephan Aßmus fIterators.Insert(iterator);
304*5a1d355fSStephan Aßmus }
305*5a1d355fSStephan Aßmus
306*5a1d355fSStephan Aßmus // RemoveDirIterator
307*5a1d355fSStephan Aßmus void
RemoveDirIterator(VirtualDirIterator * iterator)308*5a1d355fSStephan Aßmus VirtualDir::RemoveDirIterator(VirtualDirIterator* iterator)
309*5a1d355fSStephan Aßmus {
310*5a1d355fSStephan Aßmus if (!iterator)
311*5a1d355fSStephan Aßmus return;
312*5a1d355fSStephan Aßmus
313*5a1d355fSStephan Aßmus fIterators.Remove(iterator);
314*5a1d355fSStephan Aßmus }
315