* Copyright 2011, Ingo Weinhold, ingo_weinhold@gmx.de.
* Distributed under the terms of the MIT License.
*/
#include "NameIndex.h"
#include <TypeConstants.h>
#include "DebugSupport.h"
#include "IndexImpl.h"
#include "Node.h"
#include "TwoKeyAVLTree.h"
#include "Volume.h"
class NameIndexPrimaryKey {
public:
NameIndexPrimaryKey(const Node* entry, const char* name = NULL)
:
entry(entry),
name(name ? name : entry->Name())
{
}
NameIndexPrimaryKey(const char* name)
:
entry(NULL),
name(name)
{
}
const Node* entry;
const char* name;
};
class NameIndexGetPrimaryKey {
public:
inline NameIndexPrimaryKey operator()(const Node* a)
{
return NameIndexPrimaryKey(a);
}
inline NameIndexPrimaryKey operator()(const Node* a) const
{
return NameIndexPrimaryKey(a);
}
};
class NameIndexPrimaryKeyCompare {
public:
inline int operator()(const NameIndexPrimaryKey &a,
const NameIndexPrimaryKey &b) const
{
if (a.entry != NULL && a.entry == b.entry)
return 0;
return strcmp(a.name, b.name);
}
};
typedef TwoKeyAVLTree<Node*, NameIndexPrimaryKey, NameIndexPrimaryKeyCompare,
NameIndexGetPrimaryKey> _EntryTree;
class NameIndex::EntryTree : public _EntryTree {
};
struct NameIndex::IteratorPolicy {
typedef NameIndex Index;
typedef const char* Value;
typedef NameIndex::EntryTree NodeTree;
typedef GenericIndexIteratorTreePolicy<IteratorPolicy> TreePolicy;
static NodeTree* GetNodeTree(Index* index)
{
return index->fEntries;
}
static void GetNodeValue(Node* node, void* buffer, size_t* _keyLength)
{
strlcpy((char*)buffer, node->Name(), kMaxIndexKeyLength);
*_keyLength = strlen(node->Name());
}
};
struct NameIndex::Iterator : public GenericIndexIterator<IteratorPolicy> {
};
NameIndex::NameIndex()
:
Index(),
fEntries(NULL)
{
}
NameIndex::~NameIndex()
{
if (IsListening())
fVolume->RemoveNodeListener(this);
delete fEntries;
}
status_t
NameIndex::Init(Volume* volume)
{
status_t error = Index::Init(volume, "name", B_STRING_TYPE, false);
if (error != B_OK)
return error;
fVolume->AddNodeListener(this, NULL);
fEntries = new(std::nothrow) EntryTree;
if (fEntries == NULL)
return B_NO_MEMORY;
return B_OK;
}
int32
NameIndex::CountEntries() const
{
return fEntries->CountItems();
}
void
NameIndex::NodeAdded(Node* node)
{
fEntries->Insert(node);
_UpdateLiveQueries(node, NULL, node->Name());
}
void
NameIndex::NodeRemoved(Node* node)
{
fEntries->Remove(node, node);
_UpdateLiveQueries(node, node->Name(), NULL);
}
void
NameIndex::NodeChanged(Node* node, uint32 statFields,
const OldNodeAttributes& oldAttributes)
{
}
AbstractIndexIterator*
NameIndex::InternalGetIterator()
{
Iterator* iterator = new(std::nothrow) Iterator;
if (iterator != NULL) {
if (!iterator->SetTo(this, NULL, true)) {
delete iterator;
iterator = NULL;
}
}
return iterator;
}
AbstractIndexIterator*
NameIndex::InternalFind(const void* _key, size_t length)
{
if (length == 0)
return NULL;
const char* key = (const char*)_key;
char clonedKey[kMaxIndexKeyLength];
if (key[length - 1] != '\0') {
if (length >= kMaxIndexKeyLength)
length = kMaxIndexKeyLength - 1;
memcpy(clonedKey, key, length);
clonedKey[length] = '\0';
length++;
key = clonedKey;
}
Iterator* iterator = new(std::nothrow) Iterator;
if (iterator != NULL) {
if (!iterator->SetTo(this, (const char*)key)) {
delete iterator;
iterator = NULL;
}
}
return iterator;
}
void
NameIndex::_UpdateLiveQueries(Node* entry, const char* oldName,
const char* newName)
{
fVolume->UpdateLiveQueries(entry, Name(), Type(),
oldName, oldName ? strlen(oldName) : 0,
newName, newName ? strlen(newName) : 0);
}