|
/*
***************************************************************************
kis v 1
(c) 2002-2006, Florin DUMITRESCU
mailto: fdproxy@gmail.com
$Workfile: kis_Action.cpp $
***************************************************************************
*/
#include "stdafx.h"
#include <deque>
#include <vector>
#include <assert.h>
#define protected public
#include "kis.h"
namespace
{
using namespace kis;
//-------------------------------------------------------------------------
/** [To be supplied.] */
class C_StackOfSPAction
{
public:
C_StackOfSPAction()
:
m_MaxBytesCount( 0xffff ),
m_UsedBytesCount( 0 )
{
// nop
}
~C_StackOfSPAction()
{
// nop
}
void SetMaxBytesCount( const unsigned int a_MaxBytesCount )
{
if ( m_MaxBytesCount == a_MaxBytesCount )
return;
m_MaxBytesCount = a_MaxBytesCount;
while ( ! m_Deque.empty() && m_UsedBytesCount > m_MaxBytesCount )
_PopFront();
}
unsigned int GetMaxBytesCount() const
{
return m_MaxBytesCount;
}
unsigned int GetUsedBytesCount() const
{
return m_UsedBytesCount;
}
unsigned int GetCount() const
{
return static_cast< unsigned int >( m_Deque.size() );
}
bool HasRoom( const SP_Action a_spAction ) const
{
if ( m_MaxBytesCount == 0 )
return true;
else
return m_MaxBytesCount >= a_spAction->GetBytesCount();
}
/** Returns true if the action was stored. */
bool Push( SP_Action a_spAction )
{
// fake store
if ( m_MaxBytesCount == 0 )
return true;
// how much space needed?
unsigned int ActionBytesCount = a_spAction->GetBytesCount();
// make room
while ( ! m_Deque.empty() && (m_MaxBytesCount - m_UsedBytesCount) < ActionBytesCount )
_PopFront();
// got enough space?
if ( (m_MaxBytesCount - m_UsedBytesCount) < ActionBytesCount )
return false; // i guess not
m_Deque.push_back( a_spAction );
m_UsedBytesCount += ActionBytesCount;
return true;
}
void Pop()
{
if ( m_Deque.empty() )
return;
assert( m_UsedBytesCount );
m_UsedBytesCount -= m_Deque.back()->GetBytesCount();
m_Deque.pop_back();
}
SP_Action Top()
{
assert( ! IsEmpty() );
return m_Deque.back();
}
bool IsEmpty() const
{
return m_Deque.size() <= 0;
}
void Empty()
{
while ( m_Deque.size() )
Pop();
}
const SP_Action At( unsigned int a_Idx ) const
{
unsigned int Idx = static_cast< unsigned int >( m_Deque.size() - a_Idx - 1 );
return m_Deque[ Idx ];
}
protected:
unsigned int m_MaxBytesCount;
unsigned int m_UsedBytesCount;
std::deque< SP_Action > m_Deque;
void _PopFront()
{
if ( m_Deque.empty() )
return;
assert( m_UsedBytesCount );
m_UsedBytesCount -= m_Deque.back()->GetBytesCount();
m_Deque.pop_front();
}
};
//-------------------------------------------------------------------------
/** [To be supplied.] */
class C_ActionExecutor_Default : public kis::C_ActionExecutor
{
public:
C_ActionExecutor_Default()
:
m_RefCount( 0 )
{
//
}
/*override*/ unsigned long AddRef()
{
return ++m_RefCount;
}
/*override*/ unsigned long Release()
{
if ( ! --m_RefCount )
{
delete this;
return 0;
}
return m_RefCount;
}
/*override*/ void SetMaxBytesCount( unsigned int a_MaxBytesCount )
{
m_UnexecuteStack.SetMaxBytesCount( a_MaxBytesCount );
m_ReexecuteStack.SetMaxBytesCount( a_MaxBytesCount );
}
/*override*/ unsigned int GetMaxBytesCount() const
{
return m_UnexecuteStack.GetMaxBytesCount();
}
/*override*/ void Execute( const SP_Action a_spAction )
{
if ( ! a_spAction )
return;
SP_Action spAction = a_spAction->Clone();
if ( ! spAction->HasInput() )
if ( ! spAction->AcquireInput() )
return;
if ( spAction->IsNull() )
return;
if ( spAction->Execute() )
{
if ( spAction->IsUnexecutable() )
{
m_ReexecuteStack.Empty(); // the action was executed: the reexecute stack is now invalid
if ( spAction->HasUnexecute() )
{
if ( m_UnexecuteStack.HasRoom( spAction ) )
{
m_UnexecuteStack.Push( spAction ); // unexecute information has been built: store it
}
else
{
// todo: call back: not enough space
m_UnexecuteStack.Empty(); // unexecute information could not be pushed: the unexecute stack is invalid
}
}
else
{
m_UnexecuteStack.Empty(); // unexecute information has not been built: the unexecute stack is invalid
}
}
}
}
/*override*/ void Unexecute( const unsigned int a_ActionsCount )
{
for ( unsigned int i = 0; i < a_ActionsCount && ! m_UnexecuteStack.IsEmpty(); ++i )
{
SP_Action spAction = m_UnexecuteStack.Top();
m_UnexecuteStack.Pop();
spAction->Unexecute();
if ( spAction->HasReexecute() )
{
if ( ! m_ReexecuteStack.Push( spAction ) )
m_ReexecuteStack.Empty();
}
else
{
m_ReexecuteStack.Empty();
}
}
}
/*override*/ unsigned int GetUnexecuteCount() const
{
return m_UnexecuteStack.GetCount();
}
/*override*/ void GetUnexecuteName( unsigned char* a_Name, const unsigned char a_MaxNameLen, const unsigned int a_Idx ) const
{
m_UnexecuteStack.At( a_Idx )->GetName( a_Name, a_MaxNameLen );
}
/*override*/ void Reexecute( const unsigned int a_ActionsCount )
{
for ( unsigned int i = 0; i < a_ActionsCount && ! m_ReexecuteStack.IsEmpty(); ++i )
{
SP_Action spAction = m_ReexecuteStack.Top();
m_ReexecuteStack.Pop();
spAction->Reexecute();
if ( spAction->HasUnexecute() )
{
if ( ! m_UnexecuteStack.Push( spAction ) )
m_UnexecuteStack.Empty();
}
else
{
m_UnexecuteStack.Empty();
}
}
}
/*override*/ unsigned int GetReexecuteCount() const
{
return m_ReexecuteStack.GetCount();
}
/*override*/ void GetReexecuteName( unsigned char* a_Name, const unsigned char a_MaxNameLen, const unsigned int a_Idx ) const
{
m_ReexecuteStack.At( a_Idx )->GetName( a_Name, a_MaxNameLen );
}
protected:
unsigned long m_RefCount;
C_StackOfSPAction m_UnexecuteStack;
C_StackOfSPAction m_ReexecuteStack;
/*override*/ ~C_ActionExecutor_Default()
{
//
}
};
} // namespace
KIS_BEG
//-------------------------------------------------------------------------
/** [To be supplied.] */
KIS_API SP_ActionExecutor CreateActionExecutor_Default()
{
return SP_ActionExecutor( new C_ActionExecutor_Default );
}
KIS_END
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.