1 // VirtualDir.cpp 2 3 #include "VirtualDir.h" 4 5 #include <string.h> 6 7 #include <AutoDeleter.h> 8 9 // constructor 10 VirtualDirEntry::VirtualDirEntry() 11 : fName(), 12 fNode(NULL) 13 { 14 } 15 16 // destructor 17 VirtualDirEntry::~VirtualDirEntry() 18 { 19 } 20 21 // SetTo 22 status_t 23 VirtualDirEntry::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 36 const char* 37 VirtualDirEntry::GetName() const 38 { 39 return fName.GetString(); 40 } 41 42 // GetNode 43 Node* 44 VirtualDirEntry::GetNode() const 45 { 46 return fNode; 47 } 48 49 50 // #pragma mark - 51 52 // constructor 53 VirtualDirIterator::VirtualDirIterator() 54 : fDirectory(NULL), 55 fCurrentEntry(NULL), 56 fState(STATE_DOT) 57 { 58 } 59 60 // destructor 61 VirtualDirIterator::~VirtualDirIterator() 62 { 63 SetDirectory(NULL); 64 } 65 66 // SetDirectory 67 void 68 VirtualDirIterator::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 90 bool 91 VirtualDirIterator::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 116 VirtualDirEntry* 117 VirtualDirIterator::GetCurrentEntry() const 118 { 119 return fCurrentEntry; 120 } 121 122 // NextEntry 123 void 124 VirtualDirIterator::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 144 void 145 VirtualDirIterator::Rewind() 146 { 147 fState = STATE_DOT; 148 fCurrentEntry = NULL; 149 } 150 151 152 // #pragma mark - 153 154 // constructor 155 VirtualDir::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 166 VirtualDir::~VirtualDir() 167 { 168 while (VirtualDirEntry* entry = GetFirstEntry()) 169 RemoveEntry(entry->GetName()); 170 } 171 172 // InitCheck 173 status_t 174 VirtualDir::InitCheck() const 175 { 176 return fEntries.InitCheck(); 177 } 178 179 // SetParent 180 void 181 VirtualDir::SetParent(VirtualDir* parent) 182 { 183 fParent = parent; 184 } 185 186 // GetParent 187 VirtualDir* 188 VirtualDir::GetParent() const 189 { 190 return fParent; 191 } 192 193 // GetCreationTime 194 time_t 195 VirtualDir::GetCreationTime() const 196 { 197 return fCreationTime; 198 } 199 200 // AddEntry 201 status_t 202 VirtualDir::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 232 Node* 233 VirtualDir::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 262 VirtualDirEntry* 263 VirtualDir::GetEntry(const char* name) const 264 { 265 if (!name) 266 return NULL; 267 268 return fEntries.Get(name); 269 } 270 271 // GetChildNode 272 Node* 273 VirtualDir::GetChildNode(const char* name) const 274 { 275 if (VirtualDirEntry* entry = GetEntry(name)) 276 return entry->GetNode(); 277 return NULL; 278 } 279 280 // GetFirstEntry 281 VirtualDirEntry* 282 VirtualDir::GetFirstEntry() const 283 { 284 return fEntryList.First(); 285 } 286 287 // GetNextEntry 288 VirtualDirEntry* 289 VirtualDir::GetNextEntry(VirtualDirEntry* entry) const 290 { 291 if (!entry) 292 return NULL; 293 return fEntryList.GetNext(entry); 294 } 295 296 // AddDirIterator 297 void 298 VirtualDir::AddDirIterator(VirtualDirIterator* iterator) 299 { 300 if (!iterator) 301 return; 302 303 fIterators.Insert(iterator); 304 } 305 306 // RemoveDirIterator 307 void 308 VirtualDir::RemoveDirIterator(VirtualDirIterator* iterator) 309 { 310 if (!iterator) 311 return; 312 313 fIterators.Remove(iterator); 314 } 315