Assorted whitespace cleanup and typo fixes.
[haiku.git] / src / kits / tracker / EntryIterator.cpp
blob0f22b396402109f0d29a53c0f2a4b8ee496882c1
1 /*
2 Open Tracker License
4 Terms and Conditions
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
36 #include <Debug.h>
37 #include <Entry.h>
38 #include <ObjectList.h>
39 #include <Path.h>
41 #include <new>
42 #include <string.h>
44 #include "EntryIterator.h"
47 // #pragma mark - TWalkerWrapper
50 TWalkerWrapper::TWalkerWrapper(BTrackerPrivate::TWalker* walker)
52 fWalker(walker),
53 fStatus(B_OK)
58 TWalkerWrapper::~TWalkerWrapper()
60 delete fWalker;
64 status_t
65 TWalkerWrapper::InitCheck() const
67 return fStatus;
71 status_t
72 TWalkerWrapper::GetNextEntry(BEntry* entry, bool traverse)
74 fStatus = fWalker->GetNextEntry(entry, traverse);
76 return fStatus;
80 status_t
81 TWalkerWrapper::GetNextRef(entry_ref* ref)
83 fStatus = fWalker->GetNextRef(ref);
85 return fStatus;
89 int32
90 TWalkerWrapper::GetNextDirents(struct dirent* buffer, size_t length,
91 int32 count)
93 int32 result = fWalker->GetNextDirents(buffer, length, count);
94 fStatus = result < B_OK ? result : (result ? B_OK : B_ENTRY_NOT_FOUND);
96 return result;
100 status_t
101 TWalkerWrapper::Rewind()
103 return fWalker->Rewind();
107 int32
108 TWalkerWrapper::CountEntries()
110 return fWalker->CountEntries();
114 // #pragma mark - EntryListBase
117 EntryListBase::EntryListBase()
119 fStatus(B_OK)
124 status_t
125 EntryListBase::InitCheck() const
127 return fStatus;
131 dirent*
132 EntryListBase::Next(dirent* ent)
134 return (dirent*)((char*)ent + ent->d_reclen);
138 // #pragma mark - CachedEntryIterator
141 CachedEntryIterator::CachedEntryIterator(BEntryList* iterator,
142 int32 numEntries, bool sortInodes)
144 fIterator(iterator),
145 fEntryRefBuffer(NULL),
146 fCacheSize(numEntries),
147 fNumEntries(0),
148 fIndex(0),
149 fDirentBuffer(NULL),
150 fCurrentDirent(NULL),
151 fSortInodes(sortInodes),
152 fSortedList(NULL),
153 fEntryBuffer(NULL)
158 CachedEntryIterator::~CachedEntryIterator()
160 delete[] fEntryRefBuffer;
161 free(fDirentBuffer);
162 delete fSortedList;
163 delete[] fEntryBuffer;
167 status_t
168 CachedEntryIterator::GetNextEntry(BEntry* result, bool traverse)
170 ASSERT(fDirentBuffer != NULL);
171 ASSERT(fEntryRefBuffer != NULL);
173 if (fEntryBuffer == NULL) {
174 fEntryBuffer = new BEntry [fCacheSize];
175 ASSERT(fIndex == 0 && fNumEntries == 0);
178 if (fIndex >= fNumEntries) {
179 // fill up the buffer or stop if error; keep error around
180 // and return it when appropriate
181 fStatus = B_OK;
182 for (fNumEntries = 0; fNumEntries < fCacheSize; fNumEntries++) {
183 fStatus = fIterator->GetNextEntry(&fEntryBuffer[fNumEntries],
184 traverse);
185 if (fStatus != B_OK)
186 break;
188 fIndex = 0;
191 *result = fEntryBuffer[fIndex++];
192 if (fIndex > fNumEntries) {
193 // we are at the end of the cache we loaded up, time to return
194 // an error, if we had one
195 return fStatus;
198 return B_OK;
202 status_t
203 CachedEntryIterator::GetNextRef(entry_ref* ref)
205 ASSERT(fDirentBuffer == NULL);
206 ASSERT(fEntryBuffer == NULL);
208 if (fEntryRefBuffer == NULL) {
209 fEntryRefBuffer = new entry_ref[fCacheSize];
210 ASSERT(fIndex == 0 && fNumEntries == 0);
213 if (fIndex >= fNumEntries) {
214 // fill up the buffer or stop if error; keep error around
215 // and return it when appropriate
216 fStatus = B_OK;
217 for (fNumEntries = 0; fNumEntries < fCacheSize; fNumEntries++) {
218 fStatus = fIterator->GetNextRef(&fEntryRefBuffer[fNumEntries]);
219 if (fStatus != B_OK)
220 break;
222 fIndex = 0;
225 *ref = fEntryRefBuffer[fIndex++];
226 if (fIndex > fNumEntries) {
227 // we are at the end of the cache we loaded up, time to return
228 // an error, if we had one
229 return fStatus;
232 return B_OK;
236 /*static*/ int
237 CachedEntryIterator::_CompareInodes(const dirent* ent1, const dirent* ent2)
239 if (ent1->d_ino < ent2->d_ino)
240 return -1;
242 if (ent1->d_ino == ent2->d_ino)
243 return 0;
245 return 1;
249 int32
250 CachedEntryIterator::GetNextDirents(struct dirent* ent, size_t size,
251 int32 count)
253 ASSERT(fEntryRefBuffer == NULL);
254 if (fDirentBuffer == NULL) {
255 fDirentBuffer = (dirent*)malloc(kDirentBufferSize);
256 ASSERT(fIndex == 0 && fNumEntries == 0);
257 ASSERT(size > sizeof(dirent) + B_FILE_NAME_LENGTH);
260 if (count == 0)
261 return 0;
263 if (fIndex >= fNumEntries) {
264 // we are out of stock, cache em up
265 fCurrentDirent = fDirentBuffer;
266 int32 bufferRemain = kDirentBufferSize;
267 for (fNumEntries = 0; fNumEntries < fCacheSize; ) {
268 int32 count = fIterator->GetNextDirents(fCurrentDirent,
269 bufferRemain, 1);
271 if (count <= 0)
272 break;
274 fNumEntries += count;
276 int32 currentDirentSize = fCurrentDirent->d_reclen;
277 bufferRemain -= currentDirentSize;
278 ASSERT(bufferRemain >= 0);
280 if ((size_t)bufferRemain
281 < (sizeof(dirent) + B_FILE_NAME_LENGTH)) {
282 // cant fit a big entryRef in the buffer, just bail
283 // and start from scratch
284 break;
287 fCurrentDirent
288 = (dirent*)((char*)fCurrentDirent + currentDirentSize);
290 fCurrentDirent = fDirentBuffer;
291 if (fSortInodes) {
292 if (!fSortedList)
293 fSortedList = new BObjectList<dirent>(fCacheSize);
294 else
295 fSortedList->MakeEmpty();
297 for (int32 count = 0; count < fNumEntries; count++) {
298 fSortedList->AddItem(fCurrentDirent, 0);
299 fCurrentDirent = Next(fCurrentDirent);
301 fSortedList->SortItems(&_CompareInodes);
302 fCurrentDirent = fDirentBuffer;
304 fIndex = 0;
306 if (fIndex >= fNumEntries) {
307 // we are done, no more dirents left
308 return 0;
311 if (fSortInodes)
312 fCurrentDirent = fSortedList->ItemAt(fIndex);
314 fIndex++;
315 uint32 currentDirentSize = fCurrentDirent->d_reclen;
316 ASSERT(currentDirentSize <= size);
317 if (currentDirentSize > size)
318 return 0;
320 memcpy(ent, fCurrentDirent, currentDirentSize);
322 if (!fSortInodes)
323 fCurrentDirent = (dirent*)((char*)fCurrentDirent + currentDirentSize);
325 return 1;
329 status_t
330 CachedEntryIterator::Rewind()
332 fIndex = 0;
333 fNumEntries = 0;
334 fCurrentDirent = NULL;
335 fStatus = B_OK;
337 delete fSortedList;
338 fSortedList = NULL;
340 return fIterator->Rewind();
344 int32
345 CachedEntryIterator::CountEntries()
347 return fIterator->CountEntries();
351 void
352 CachedEntryIterator::SetTo(BEntryList* iterator)
354 fIndex = 0;
355 fNumEntries = 0;
356 fStatus = B_OK;
357 fIterator = iterator;
361 // #pragma mark - CachedDirectoryEntryList
364 CachedDirectoryEntryList::CachedDirectoryEntryList(const BDirectory& directory)
366 CachedEntryIterator(0, 40, true),
367 fDirectory(directory)
369 fStatus = fDirectory.InitCheck();
370 SetTo(&fDirectory);
374 CachedDirectoryEntryList::~CachedDirectoryEntryList()
379 // #pragma mark - DirectoryEntryList
382 DirectoryEntryList::DirectoryEntryList(const BDirectory& directory)
384 fDirectory(directory)
386 fStatus = fDirectory.InitCheck();
390 status_t
391 DirectoryEntryList::GetNextEntry(BEntry* entry, bool traverse)
393 fStatus = fDirectory.GetNextEntry(entry, traverse);
394 return fStatus;
398 status_t
399 DirectoryEntryList::GetNextRef(entry_ref* ref)
401 fStatus = fDirectory.GetNextRef(ref);
402 return fStatus;
406 int32
407 DirectoryEntryList::GetNextDirents(struct dirent* buffer, size_t length,
408 int32 count)
410 fStatus = fDirectory.GetNextDirents(buffer, length, count);
411 return fStatus;
415 status_t
416 DirectoryEntryList::Rewind()
418 fStatus = fDirectory.Rewind();
419 return fStatus;
423 int32
424 DirectoryEntryList::CountEntries()
426 return fDirectory.CountEntries();
430 // #pragma mark - EntryIteratorList
433 EntryIteratorList::EntryIteratorList()
435 fList(5, true),
436 fCurrentIndex(0)
441 EntryIteratorList::~EntryIteratorList()
443 int32 count = fList.CountItems();
444 for (;count; count--) {
445 // workaround for BEntryList not having a proper destructor
446 BEntryList* entry = fList.RemoveItemAt(count - 1);
447 EntryListBase* fixedEntry = dynamic_cast<EntryListBase*>(entry);
448 if (fixedEntry != NULL)
449 delete fixedEntry;
450 else
451 delete entry;
456 void
457 EntryIteratorList::AddItem(BEntryList* walker)
459 fList.AddItem(walker);
463 status_t
464 EntryIteratorList::GetNextEntry(BEntry* entry, bool traverse)
466 while (true) {
467 if (fCurrentIndex >= fList.CountItems()) {
468 fStatus = B_ENTRY_NOT_FOUND;
469 break;
472 fStatus = fList.ItemAt(fCurrentIndex)->GetNextEntry(entry, traverse);
473 if (fStatus != B_ENTRY_NOT_FOUND)
474 break;
476 fCurrentIndex++;
478 return fStatus;
482 status_t
483 EntryIteratorList::GetNextRef(entry_ref* ref)
485 while (true) {
486 if (fCurrentIndex >= fList.CountItems()) {
487 fStatus = B_ENTRY_NOT_FOUND;
488 break;
491 fStatus = fList.ItemAt(fCurrentIndex)->GetNextRef(ref);
492 if (fStatus != B_ENTRY_NOT_FOUND)
493 break;
495 fCurrentIndex++;
497 return fStatus;
501 int32
502 EntryIteratorList::GetNextDirents(struct dirent* buffer, size_t length,
503 int32 count)
505 int32 result = 0;
506 while (true) {
507 if (fCurrentIndex >= fList.CountItems()) {
508 fStatus = B_ENTRY_NOT_FOUND;
509 break;
512 result = fList.ItemAt(fCurrentIndex)->GetNextDirents(buffer, length,
513 count);
514 if (result > 0) {
515 fStatus = B_OK;
516 break;
519 fCurrentIndex++;
521 return result;
525 status_t
526 EntryIteratorList::Rewind()
528 fCurrentIndex = 0;
529 int32 count = fList.CountItems();
530 for (int32 index = 0; index < count; index++)
531 fStatus = fList.ItemAt(index)->Rewind();
533 return fStatus;
537 int32
538 EntryIteratorList::CountEntries()
540 int32 result = 0;
542 int32 count = fList.CountItems();
543 for (int32 index = 0; index < count; index++)
544 result += fList.ItemAt(fCurrentIndex)->CountEntries();
546 return result;
550 // #pragma mark - CachedEntryIteratorList
553 CachedEntryIteratorList::CachedEntryIteratorList(bool sortInodes)
555 CachedEntryIterator(NULL, 10, sortInodes)
557 fStatus = B_OK;
558 SetTo(&fIteratorList);
562 void
563 CachedEntryIteratorList::AddItem(BEntryList* walker)
565 fIteratorList.AddItem(walker);