BTRFS: Implement BTree::Path and change _Find.
[haiku.git] / src / apps / text_search / InitialIterator.cpp
blobbbb63b41e14024fbf522a78b3ab63db0ea5d97bf
1 /*
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.
5 */
7 #include "InitialIterator.h"
9 #include <new>
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <string.h>
14 #include <Directory.h>
16 #include "Model.h"
18 using std::nothrow;
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)
27 : FileIterator(),
28 fDirectories(32),
29 fCurrentDir(new (nothrow) BDirectory(&model->fDirectory)),
30 fCurrentRef(0),
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)) {
40 // init error
41 delete fCurrentDir;
42 fCurrentDir = NULL;
47 InitialIterator::~InitialIterator()
49 for (int32 i = fDirectories.CountItems() - 1; i >= 0; i--)
50 delete (BDirectory*)fDirectories.ItemAt(i);
54 bool
55 InitialIterator::IsValid() const
57 return fCurrentDir != NULL;
61 bool
62 InitialIterator::GetNextName(char* buffer)
64 BEntry entry;
65 struct stat fileStat;
67 while (true) {
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))
73 return false;
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)) {
83 // subdir
84 _ExamineSubdir(entry);
85 } else {
86 // file or a (non-traversed) symbolic link
87 if (_ExamineFile(entry, buffer, fTextOnly))
88 return true;
95 bool
96 InitialIterator::NotifyNegatives() const
98 return false;
102 bool
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.
111 entry_ref fileRef;
113 if (fSelectedFiles.FindRef("refs", fCurrentRef, &fileRef) == B_OK) {
114 entry.SetTo(&fileRef, fRecurseLinks);
115 ++fCurrentRef;
116 return true;
117 } else if (fCurrentRef > 0) {
118 // when we get here, we have processed
119 // all the refs from the message
120 return false;
121 } else if (fCurrentDir != NULL) {
122 // examine the whole directory
123 return fCurrentDir->GetNextEntry(&entry, fRecurseLinks) == B_OK;
126 return false;
130 bool
131 InitialIterator::FollowSubdir(BEntry& entry) const
133 if (!fRecurseDirs)
134 return false;
136 if (fSkipDotDirs) {
137 char nameBuf[B_FILE_NAME_LENGTH];
138 if (entry.GetName(nameBuf) == B_OK) {
139 if (*nameBuf == '.')
140 return false;
144 return true;
148 // #pragma mark - private
151 bool
152 InitialIterator::_GetNextEntry(BEntry& entry)
154 if (fDirectories.CountItems() == 1)
155 return GetTopEntry(entry);
156 else
157 return _GetSubEntry(entry);
161 bool
162 InitialIterator::_GetSubEntry(BEntry& entry)
164 if (!fCurrentDir)
165 return false;
167 if (fCurrentDir->GetNextEntry(&entry, fRecurseLinks) == B_OK)
168 return true;
170 // If we get here, there are no more entries in
171 // this subdir, so return to the parent directory.
173 fDirectories.RemoveItem(fCurrentDir);
174 delete fCurrentDir;
175 fCurrentDir = (BDirectory*)fDirectories.LastItem();
177 return _GetNextEntry(entry);
181 void
182 InitialIterator::_ExamineSubdir(BEntry& entry)
184 if (!FollowSubdir(entry))
185 return;
187 BDirectory* dir = new (nothrow) BDirectory(&entry);
188 if (dir == NULL || dir->InitCheck() != B_OK || !fDirectories.AddItem(dir)) {
189 // clean up
190 delete dir;
191 return;
194 fCurrentDir = dir;