2 * Copyright (c) 2008 Stephan Aßmus <superstippi@gmx.de>
3 * Copyright (c) 1998-2007 Matthijs Hollemans
4 * All rights reserved. Distributed under the terms of the MIT License.
7 #include "InitialIterator.h"
14 #include <Directory.h>
20 // TODO: stippi: Check if this is a the best place to maintain a global
21 // list of files and folders for node monitoring. It should probably monitor
22 // every file that was grepped, as well as every visited (sub) folder.
23 // For the moment I don't know the life cycle of the InitialIterator object.
26 InitialIterator::InitialIterator(const Model
* model
)
29 fCurrentDir(new (nothrow
) BDirectory(&model
->fDirectory
)),
32 fSelectedFiles(model
->fSelectedFiles
),
34 fRecurseDirs(model
->fRecurseDirs
),
35 fRecurseLinks(model
->fRecurseLinks
),
36 fSkipDotDirs(model
->fSkipDotDirs
),
37 fTextOnly(model
->fTextOnly
)
39 if (!fCurrentDir
|| !fDirectories
.AddItem(fCurrentDir
)) {
47 InitialIterator::~InitialIterator()
49 for (int32 i
= fDirectories
.CountItems() - 1; i
>= 0; i
--)
50 delete (BDirectory
*)fDirectories
.ItemAt(i
);
55 InitialIterator::IsValid() const
57 return fCurrentDir
!= NULL
;
62 InitialIterator::GetNextName(char* buffer
)
68 // Traverse the directory to get a new BEntry.
69 // _GetNextEntry returns false if there are no
70 // more entries, and we exit the loop.
72 if (!_GetNextEntry(entry
))
75 // If the entry is a subdir, then add it to the
76 // list of directories and continue the loop.
77 // If the entry is a file and we can grep it
78 // (i.e. it is a text file), then we're done
79 // here. Otherwise, continue with the next entry.
81 if (entry
.GetStat(&fileStat
) == B_OK
) {
82 if (S_ISDIR(fileStat
.st_mode
)) {
84 _ExamineSubdir(entry
);
86 // file or a (non-traversed) symbolic link
87 if (_ExamineFile(entry
, buffer
, fTextOnly
))
96 InitialIterator::NotifyNegatives() const
103 InitialIterator::GetTopEntry(BEntry
& entry
)
105 // If the user selected one or more files, we must look
106 // at the "refs" inside the message that was passed into
107 // our add-on's process_refs(). If the user didn't select
108 // any files, we will simply read all the entries from the
109 // current working directory.
113 if (fSelectedFiles
.FindRef("refs", fCurrentRef
, &fileRef
) == B_OK
) {
114 entry
.SetTo(&fileRef
, fRecurseLinks
);
117 } else if (fCurrentRef
> 0) {
118 // when we get here, we have processed
119 // all the refs from the message
121 } else if (fCurrentDir
!= NULL
) {
122 // examine the whole directory
123 return fCurrentDir
->GetNextEntry(&entry
, fRecurseLinks
) == B_OK
;
131 InitialIterator::FollowSubdir(BEntry
& entry
) const
137 char nameBuf
[B_FILE_NAME_LENGTH
];
138 if (entry
.GetName(nameBuf
) == B_OK
) {
148 // #pragma mark - private
152 InitialIterator::_GetNextEntry(BEntry
& entry
)
154 if (fDirectories
.CountItems() == 1)
155 return GetTopEntry(entry
);
157 return _GetSubEntry(entry
);
162 InitialIterator::_GetSubEntry(BEntry
& entry
)
167 if (fCurrentDir
->GetNextEntry(&entry
, fRecurseLinks
) == B_OK
)
170 // If we get here, there are no more entries in
171 // this subdir, so return to the parent directory.
173 fDirectories
.RemoveItem(fCurrentDir
);
175 fCurrentDir
= (BDirectory
*)fDirectories
.LastItem();
177 return _GetNextEntry(entry
);
182 InitialIterator::_ExamineSubdir(BEntry
& entry
)
184 if (!FollowSubdir(entry
))
187 BDirectory
* dir
= new (nothrow
) BDirectory(&entry
);
188 if (dir
== NULL
|| dir
->InitCheck() != B_OK
|| !fDirectories
.AddItem(dir
)) {