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.
38 #include <ObjectList.h>
44 #include "EntryIterator.h"
47 // #pragma mark - TWalkerWrapper
50 TWalkerWrapper::TWalkerWrapper(BTrackerPrivate::TWalker
* walker
)
58 TWalkerWrapper::~TWalkerWrapper()
65 TWalkerWrapper::InitCheck() const
72 TWalkerWrapper::GetNextEntry(BEntry
* entry
, bool traverse
)
74 fStatus
= fWalker
->GetNextEntry(entry
, traverse
);
81 TWalkerWrapper::GetNextRef(entry_ref
* ref
)
83 fStatus
= fWalker
->GetNextRef(ref
);
90 TWalkerWrapper::GetNextDirents(struct dirent
* buffer
, size_t length
,
93 int32 result
= fWalker
->GetNextDirents(buffer
, length
, count
);
94 fStatus
= result
< B_OK
? result
: (result
? B_OK
: B_ENTRY_NOT_FOUND
);
101 TWalkerWrapper::Rewind()
103 return fWalker
->Rewind();
108 TWalkerWrapper::CountEntries()
110 return fWalker
->CountEntries();
114 // #pragma mark - EntryListBase
117 EntryListBase::EntryListBase()
125 EntryListBase::InitCheck() const
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
)
145 fEntryRefBuffer(NULL
),
146 fCacheSize(numEntries
),
150 fCurrentDirent(NULL
),
151 fSortInodes(sortInodes
),
158 CachedEntryIterator::~CachedEntryIterator()
160 delete[] fEntryRefBuffer
;
163 delete[] fEntryBuffer
;
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
182 for (fNumEntries
= 0; fNumEntries
< fCacheSize
; fNumEntries
++) {
183 fStatus
= fIterator
->GetNextEntry(&fEntryBuffer
[fNumEntries
],
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
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
217 for (fNumEntries
= 0; fNumEntries
< fCacheSize
; fNumEntries
++) {
218 fStatus
= fIterator
->GetNextRef(&fEntryRefBuffer
[fNumEntries
]);
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
237 CachedEntryIterator::_CompareInodes(const dirent
* ent1
, const dirent
* ent2
)
239 if (ent1
->d_ino
< ent2
->d_ino
)
242 if (ent1
->d_ino
== ent2
->d_ino
)
250 CachedEntryIterator::GetNextDirents(struct dirent
* ent
, size_t size
,
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
);
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
,
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
288 = (dirent
*)((char*)fCurrentDirent
+ currentDirentSize
);
290 fCurrentDirent
= fDirentBuffer
;
293 fSortedList
= new BObjectList
<dirent
>(fCacheSize
);
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
;
306 if (fIndex
>= fNumEntries
) {
307 // we are done, no more dirents left
312 fCurrentDirent
= fSortedList
->ItemAt(fIndex
);
315 uint32 currentDirentSize
= fCurrentDirent
->d_reclen
;
316 ASSERT(currentDirentSize
<= size
);
317 if (currentDirentSize
> size
)
320 memcpy(ent
, fCurrentDirent
, currentDirentSize
);
323 fCurrentDirent
= (dirent
*)((char*)fCurrentDirent
+ currentDirentSize
);
330 CachedEntryIterator::Rewind()
334 fCurrentDirent
= NULL
;
340 return fIterator
->Rewind();
345 CachedEntryIterator::CountEntries()
347 return fIterator
->CountEntries();
352 CachedEntryIterator::SetTo(BEntryList
* iterator
)
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();
374 CachedDirectoryEntryList::~CachedDirectoryEntryList()
379 // #pragma mark - DirectoryEntryList
382 DirectoryEntryList::DirectoryEntryList(const BDirectory
& directory
)
384 fDirectory(directory
)
386 fStatus
= fDirectory
.InitCheck();
391 DirectoryEntryList::GetNextEntry(BEntry
* entry
, bool traverse
)
393 fStatus
= fDirectory
.GetNextEntry(entry
, traverse
);
399 DirectoryEntryList::GetNextRef(entry_ref
* ref
)
401 fStatus
= fDirectory
.GetNextRef(ref
);
407 DirectoryEntryList::GetNextDirents(struct dirent
* buffer
, size_t length
,
410 fStatus
= fDirectory
.GetNextDirents(buffer
, length
, count
);
416 DirectoryEntryList::Rewind()
418 fStatus
= fDirectory
.Rewind();
424 DirectoryEntryList::CountEntries()
426 return fDirectory
.CountEntries();
430 // #pragma mark - EntryIteratorList
433 EntryIteratorList::EntryIteratorList()
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
)
457 EntryIteratorList::AddItem(BEntryList
* walker
)
459 fList
.AddItem(walker
);
464 EntryIteratorList::GetNextEntry(BEntry
* entry
, bool traverse
)
467 if (fCurrentIndex
>= fList
.CountItems()) {
468 fStatus
= B_ENTRY_NOT_FOUND
;
472 fStatus
= fList
.ItemAt(fCurrentIndex
)->GetNextEntry(entry
, traverse
);
473 if (fStatus
!= B_ENTRY_NOT_FOUND
)
483 EntryIteratorList::GetNextRef(entry_ref
* ref
)
486 if (fCurrentIndex
>= fList
.CountItems()) {
487 fStatus
= B_ENTRY_NOT_FOUND
;
491 fStatus
= fList
.ItemAt(fCurrentIndex
)->GetNextRef(ref
);
492 if (fStatus
!= B_ENTRY_NOT_FOUND
)
502 EntryIteratorList::GetNextDirents(struct dirent
* buffer
, size_t length
,
507 if (fCurrentIndex
>= fList
.CountItems()) {
508 fStatus
= B_ENTRY_NOT_FOUND
;
512 result
= fList
.ItemAt(fCurrentIndex
)->GetNextDirents(buffer
, length
,
526 EntryIteratorList::Rewind()
529 int32 count
= fList
.CountItems();
530 for (int32 index
= 0; index
< count
; index
++)
531 fStatus
= fList
.ItemAt(index
)->Rewind();
538 EntryIteratorList::CountEntries()
542 int32 count
= fList
.CountItems();
543 for (int32 index
= 0; index
< count
; index
++)
544 result
+= fList
.ItemAt(fCurrentIndex
)->CountEntries();
550 // #pragma mark - CachedEntryIteratorList
553 CachedEntryIteratorList::CachedEntryIteratorList(bool sortInodes
)
555 CachedEntryIterator(NULL
, 10, sortInodes
)
558 SetTo(&fIteratorList
);
563 CachedEntryIteratorList::AddItem(BEntryList
* walker
)
565 fIteratorList
.AddItem(walker
);