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