root/src/add-ons/kernel/file_systems/ramfs/AttributeIterator.cpp
/*
 * Copyright 2007, Ingo Weinhold, ingo_weinhold@gmx.de.
 * All rights reserved. Distributed under the terms of the MIT license.
 */

#include "AttributeIterator.h"

#include <util/AutoLock.h>

#include "Node.h"
#include "Volume.h"


AttributeIterator::AttributeIterator(Node *node)
        : fNode(node),
          fAttribute(NULL),
          fSuspended(false),
          fIsNext(false),
          fDone(false)
{
}


AttributeIterator::~AttributeIterator()
{
        Unset();
}


status_t
AttributeIterator::SetTo(Node *node)
{
        Unset();

        if (node == NULL)
                return B_BAD_VALUE;

        fNode = node;
        fAttribute = NULL;
        fSuspended = false;
        fIsNext = false;
        fDone = false;
        return B_OK;
}


void
AttributeIterator::Unset()
{
        if (fNode && fSuspended)
                Resume();

        fNode = NULL;
        fAttribute = NULL;
        fSuspended = false;
        fIsNext = false;
        fDone = false;
}


status_t
AttributeIterator::Suspend()
{
        if (fNode == NULL)
                return B_ERROR;

        RecursiveLocker locker(fNode->GetVolume()->GetAttributeIteratorLock());
        if (!locker.IsLocked())
                return B_ERROR;

        if (fSuspended)
                return B_ERROR;

        if (fAttribute)
                fAttribute->AttachAttributeIterator(this);
        fSuspended = true;

        return B_OK;
}


status_t
AttributeIterator::Resume()
{
        if (fNode == NULL)
                return B_ERROR;

        RecursiveLocker locker(fNode->GetVolume()->GetAttributeIteratorLock());
        if (!locker.IsLocked())
                return B_ERROR;

        if (!fSuspended)
                return B_ERROR;

        if (fAttribute)
                fAttribute->DetachAttributeIterator(this);
        fSuspended = false;

        return B_OK;
}


status_t
AttributeIterator::GetNext(Attribute **attribute)
{
        if (attribute == NULL)
                return B_BAD_VALUE;

        status_t error = B_ENTRY_NOT_FOUND;
        if (!fDone && fNode != NULL) {
                if (fIsNext) {
                        fIsNext = false;
                        if (fAttribute)
                                error = B_OK;
                } else
                        error = fNode->GetNextAttribute(&fAttribute);
                *attribute = fAttribute;
        }
        fDone = (error != B_OK);
        return error;
}


status_t
AttributeIterator::Rewind()
{
        if (fNode == NULL)
                return B_ERROR;

        RecursiveLocker locker(fNode->GetVolume()->GetAttributeIteratorLock());
        if (!locker.IsLocked())
                return B_ERROR;

        if (fSuspended && fAttribute)
                fAttribute->DetachAttributeIterator(this);
        fAttribute = NULL;
        fIsNext = false;
        fDone = false;
        return B_OK;
}


void
AttributeIterator::SetCurrent(Attribute *attribute, bool isNext)
{
        fIsNext = isNext;
        fAttribute = attribute;
        fDone = !fAttribute;
}