BPicture: Fix archive constructor.
[haiku.git] / src / add-ons / kernel / file_systems / ramfs / NameIndex.cpp
blob473fdbba67a400705ce592bbf4fc8c2b48879a0d
1 // NameIndex.cpp
3 #include <TypeConstants.h>
5 #include "Debug.h"
6 #include "Entry.h"
7 #include "IndexImpl.h"
8 #include "NameIndex.h"
9 #include "ramfs.h"
10 #include "Volume.h"
12 // NameIndexPrimaryKey
13 class NameIndexPrimaryKey {
14 public:
15 NameIndexPrimaryKey(const Entry *entry,
16 const char *name = NULL)
17 : entry(entry), name(name ? name : entry->GetName()) {}
18 NameIndexPrimaryKey(const char *name)
19 : entry(NULL), name(name) {}
21 const Entry *entry;
22 const char *name;
25 // NameIndexGetPrimaryKey
26 class NameIndexGetPrimaryKey {
27 public:
28 inline NameIndexPrimaryKey operator()(const Entry *a)
30 return NameIndexPrimaryKey(a);
33 inline NameIndexPrimaryKey operator()(const Entry *a) const
35 return NameIndexPrimaryKey(a);
40 // NameIndexPrimaryKeyCompare
41 class NameIndexPrimaryKeyCompare
43 public:
44 inline int operator()(const NameIndexPrimaryKey &a,
45 const NameIndexPrimaryKey &b) const
47 if (a.entry != NULL && a.entry == b.entry)
48 return 0;
49 return strcmp(a.name, b.name);
54 // EntryTree
56 typedef TwoKeyAVLTree<Entry*, NameIndexPrimaryKey, NameIndexPrimaryKeyCompare,
57 NameIndexGetPrimaryKey>
58 _EntryTree;
60 class NameIndex::EntryTree : public _EntryTree {};
63 // NameIndexEntryIterator
64 class NameIndexEntryIterator : public AbstractIndexEntryIterator,
65 public EntryListener {
66 public:
67 NameIndexEntryIterator();
68 virtual ~NameIndexEntryIterator();
70 virtual Entry *GetCurrent();
71 virtual Entry *GetCurrent(uint8 *buffer, size_t *keyLength);
72 virtual Entry *GetPrevious();
73 virtual Entry *GetNext();
75 virtual status_t Suspend();
76 virtual status_t Resume();
78 bool SetTo(NameIndex *index, const char *name, bool ignoreValue = false);
80 virtual void EntryRemoved(Entry *entry);
82 private:
83 friend class NameIndex;
85 typedef AbstractIndexEntryIterator BaseClass;
87 private:
88 NameIndex *fIndex;
89 NameIndex::EntryTree::Iterator fIterator;
90 bool fSuspended;
91 bool fIsNext;
95 // NameIndex
97 // constructor
98 NameIndex::NameIndex(Volume *volume)
99 : Index(volume, "name", B_STRING_TYPE, false),
100 fEntries(new(nothrow) EntryTree)
102 if (fInitStatus == B_OK && !fEntries)
103 fInitStatus = B_NO_MEMORY;
104 if (fInitStatus == B_OK) {
105 fInitStatus = fVolume->AddEntryListener(this,
106 NULL, ENTRY_LISTEN_ANY_ENTRY | ENTRY_LISTEN_ALL);
110 // destructor
111 NameIndex::~NameIndex()
113 if (fVolume)
114 fVolume->RemoveEntryListener(this, NULL);
115 if (fEntries)
116 delete fEntries;
117 // Actually we would need to maintain a list of iterators and unset the
118 // still existing iterators here. But since the name index is deleted
119 // when the volume is unmounted, there shouldn't be any iterators left
120 // anymore.
123 // CountEntries
124 int32
125 NameIndex::CountEntries() const
127 return fEntries->CountItems();
130 // Changed
131 status_t
132 NameIndex::Changed(Entry *entry, const char *oldName)
134 status_t error = B_BAD_VALUE;
135 if (entry && oldName) {
136 EntryTree::Iterator it;
137 Entry **foundEntry
138 = fEntries->Find(NameIndexPrimaryKey(entry, oldName), entry, &it);
139 if (foundEntry && *foundEntry == entry) {
140 it.Remove();
141 error = fEntries->Insert(entry);
143 // udpate live queries
144 _UpdateLiveQueries(entry, oldName, entry->GetName());
147 return error;
150 // EntryAdded
151 void
152 NameIndex::EntryAdded(Entry *entry)
154 if (entry) {
155 fEntries->Insert(entry);
157 // udpate live queries
158 _UpdateLiveQueries(entry, NULL, entry->GetName());
162 // EntryRemoved
163 void
164 NameIndex::EntryRemoved(Entry *entry)
166 if (entry) {
167 fEntries->Remove(entry, entry);
169 // udpate live queries
170 _UpdateLiveQueries(entry, entry->GetName(), NULL);
174 // InternalGetIterator
175 AbstractIndexEntryIterator *
176 NameIndex::InternalGetIterator()
178 NameIndexEntryIterator *iterator = new(nothrow) NameIndexEntryIterator;
179 if (iterator) {
180 if (!iterator->SetTo(this, NULL, true)) {
181 delete iterator;
182 iterator = NULL;
185 return iterator;
188 // InternalFind
189 AbstractIndexEntryIterator *
190 NameIndex::InternalFind(const uint8 *key, size_t length)
192 if (!key || length == 0)
193 return NULL;
195 // if the key is not null-terminated, copy it
196 uint8 clonedKey[kMaxIndexKeyLength];
197 if (key[length - 1] != '\0') {
198 if (length >= kMaxIndexKeyLength)
199 length = kMaxIndexKeyLength - 1;
201 memcpy(clonedKey, key, length);
202 clonedKey[length] = '\0';
203 length++;
204 key = clonedKey;
207 NameIndexEntryIterator *iterator = new(nothrow) NameIndexEntryIterator;
208 if (iterator) {
209 if (!iterator->SetTo(this, (const char *)key)) {
210 delete iterator;
211 iterator = NULL;
214 return iterator;
217 // _UpdateLiveQueries
218 void
219 NameIndex::_UpdateLiveQueries(Entry* entry, const char* oldName,
220 const char* newName)
222 fVolume->UpdateLiveQueries(entry, entry->GetNode(), GetName(),
223 GetType(), (const uint8*)oldName, (oldName ? strlen(oldName) : 0),
224 (const uint8*)newName, (newName ? strlen(newName) : 0));
228 // NameIndexEntryIterator
230 // constructor
231 NameIndexEntryIterator::NameIndexEntryIterator()
232 : AbstractIndexEntryIterator(),
233 fIndex(NULL),
234 fIterator(),
235 fSuspended(false),
236 fIsNext(false)
240 // destructor
241 NameIndexEntryIterator::~NameIndexEntryIterator()
243 SetTo(NULL, NULL);
246 // GetCurrent
247 Entry *
248 NameIndexEntryIterator::GetCurrent()
250 return (fIndex && fIterator.GetCurrent() ? *fIterator.GetCurrent() : NULL);
253 // GetCurrent
254 Entry *
255 NameIndexEntryIterator::GetCurrent(uint8 *buffer, size_t *keyLength)
257 Entry *entry = GetCurrent();
258 if (entry) {
259 strncpy((char*)buffer, entry->GetName(), kMaxIndexKeyLength);
260 *keyLength = strlen(entry->GetName());
262 return entry;
265 // GetPrevious
266 Entry *
267 NameIndexEntryIterator::GetPrevious()
269 if (fSuspended)
270 return NULL;
271 if (!(fIterator.GetCurrent() && fIsNext))
272 fIterator.GetPrevious();
273 fIsNext = false;
274 return (fIndex && fIterator.GetCurrent() ? *fIterator.GetCurrent() : NULL);
277 // GetNext
278 Entry *
279 NameIndexEntryIterator::GetNext()
281 if (fSuspended)
282 return NULL;
283 if (!(fIterator.GetCurrent() && fIsNext))
284 fIterator.GetNext();
285 fIsNext = false;
286 return (fIndex && fIterator.GetCurrent() ? *fIterator.GetCurrent() : NULL);
289 // Suspend
290 status_t
291 NameIndexEntryIterator::Suspend()
293 status_t error = (!fSuspended ? B_OK : B_BAD_VALUE);
294 if (error == B_OK) {
295 if (fIterator.GetCurrent()) {
296 error = fIndex->GetVolume()->AddEntryListener(this,
297 *fIterator.GetCurrent(), ENTRY_LISTEN_REMOVED);
299 if (error == B_OK)
300 fSuspended = true;
302 return error;
305 // Resume
306 status_t
307 NameIndexEntryIterator::Resume()
309 status_t error = (fSuspended ? B_OK : B_BAD_VALUE);
310 if (error == B_OK) {
311 if (fIterator.GetCurrent()) {
312 error = fIndex->GetVolume()->RemoveEntryListener(this,
313 *fIterator.GetCurrent());
315 if (error == B_OK)
316 fSuspended = false;
318 return error;
321 // SetTo
322 bool
323 NameIndexEntryIterator::SetTo(NameIndex *index, const char *name,
324 bool ignoreValue)
326 Resume();
327 fIndex = index;
328 fSuspended = false;
329 fIsNext = false;
330 if (fIndex) {
331 if (ignoreValue) {
332 fIndex->fEntries->GetIterator(&fIterator);
333 return fIterator.GetCurrent();
335 return fIndex->fEntries->FindFirst(name, &fIterator);
337 return false;
340 // EntryRemoved
341 void
342 NameIndexEntryIterator::EntryRemoved(Entry */*entry*/)
344 Resume();
345 fIsNext = GetNext();
346 Suspend();