<commit_before>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkContourModelLiveWireInteractor.h"

#include "mitkToolManager.h"

#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"

#include <mitkPositionEvent.h>
#include <mitkStateEvent.h>

#include <mitkInteractionConst.h>

mitk::ContourModelLiveWireInteractor::ContourModelLiveWireInteractor(DataNode* dataNode)
:ContourModelInteractor(dataNode)
{
  m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New();

  mitk::ContourModel::Pointer m_ContourLeft = mitk::ContourModel::New();
  mitk::ContourModel::Pointer m_ContourRight = mitk::ContourModel::New();
  m_NextActiveVertexDown.Fill(0);
  m_NextActiveVertexUp.Fill(0);
}

mitk::ContourModelLiveWireInteractor::~ContourModelLiveWireInteractor()
{
}

bool mitk::ContourModelLiveWireInteractor::OnCheckPointClick( Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  mitk::StateEvent* newStateEvent = NULL;

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>(
    m_DataNode->GetData() );

  contour->Deselect();

  /*
  * Check distance to any vertex.
  * Transition YES if click close to a vertex
  */
  mitk::Point3D click = positionEvent->GetWorldPosition();

  if (contour->SelectVertexAt(click, 1.5, timestep) )
  {
    contour->SetSelectedVertexAcitve();

    assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
    mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
    newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent());
    m_lastMousePosition = click;

    mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

    //
    m_ContourLeft = mitk::ContourModel::New();

    //get coordinates of next active vertex downwards from selected vertex
    int downIndex = SplitContourFromSelectedVertex( contour, m_ContourLeft, false, timestep);

    mitk::ContourModel::VertexIterator itDown = contour->IteratorBegin() + downIndex;
    m_NextActiveVertexDown = (*itDown)->Coordinates;

    //
    m_ContourRight = mitk::ContourModel::New();

    //get coordinates of next active vertex upwards from selected vertex
    int upIndex = SplitContourFromSelectedVertex( contour, m_ContourRight, true, timestep);

    mitk::ContourModel::VertexIterator itUp = contour->IteratorBegin() + upIndex;
    m_NextActiveVertexUp = (*itUp)->Coordinates;

  }
  else
  {
    newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent());
  }

  this->HandleEvent( newStateEvent );

  return true;
}

bool mitk::ContourModelLiveWireInteractor::OnDeletePoint( Action* action, const StateEvent* stateEvent)
{

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

  mitk::ContourModel::Pointer newContour = mitk::ContourModel::New();
  newContour->Expand(contour->GetTimeSteps());
  newContour->Concatenate( m_ContourLeft, timestep );

  //recompute contour between neighbored two active control points
  this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown );
  this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp );
  this->m_LiveWireFilter->Update();

  mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New();
  liveWireContour = this->m_LiveWireFilter->GetOutput();

  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );

  newContour->Concatenate( m_ContourRight, timestep );

  newContour->SetIsClosed(contour->IsClosed(timestep), timestep);

  m_DataNode->SetData(newContour);

  assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );

  return true;
}

bool mitk::ContourModelLiveWireInteractor::OnMovePoint( Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

  mitk::ContourModel::Pointer newContour = mitk::ContourModel::New();
  newContour->Expand(contour->GetTimeSteps());

  newContour->Concatenate( m_ContourLeft, timestep );

  mitk::Point3D currentPosition = positionEvent->GetWorldPosition();

  /*+++++++++++++++ start computation ++++++++++++++++++++*/
  //recompute contour between previous active vertex and selected vertex
  this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown );
  this->m_LiveWireFilter->SetEndPoint( currentPosition );
  this->m_LiveWireFilter->Update();

  mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New();
  liveWireContour = this->m_LiveWireFilter->GetOutput();

  //avoid duplicate adding of current point where the mouse is
  liveWireContour->RemoveVertexAt(liveWireContour->GetNumberOfVertices(timestep)-1,timestep);

  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );

  //recompute contour between selected vertex and next active vertex
  this->m_LiveWireFilter->SetStartPoint( currentPosition );
  this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp );
  this->m_LiveWireFilter->Update();

  liveWireContour = this->m_LiveWireFilter->GetOutput();

  //make point at mouse position active again, so it is drawn
  const_cast<mitk::ContourModel::VertexType*>( liveWireContour->GetVertexAt(0, timestep) )->IsActive = true;

  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );
  /*------------------------------------------------*/

  newContour->Concatenate( m_ContourRight, timestep );

  newContour->SetIsClosed(contour->IsClosed(timestep), timestep);

  m_DataNode->SetData(newContour);

  this->m_lastMousePosition = positionEvent->GetWorldPosition();

  assert( positionEvent->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );

  return true;
}

int mitk::ContourModelLiveWireInteractor::SplitContourFromSelectedVertex(mitk::ContourModel* sourceContour, mitk::ContourModel* destinationContour, bool fromSelectedUpwards, int timestep)
{

  mitk::ContourModel::VertexIterator end =sourceContour->IteratorEnd();
  mitk::ContourModel::VertexIterator begin =sourceContour->IteratorBegin();

  //search next active control point to left and rigth and set as start and end point for filter
  mitk::ContourModel::VertexIterator itSelected = sourceContour->IteratorBegin();

  //move iterator to position
  while((*itSelected) != sourceContour->GetSelectedVertex())
  {
    itSelected++;
  }

  if(fromSelectedUpwards)
  {
    mitk::ContourModel::VertexIterator itUp = itSelected;

    if(itUp != end)
    {
      itUp++;//step once up otherwise the the loop breaks immediately
    }

    while( itUp != end && !((*itUp)->IsActive)){ itUp++; }

    mitk::ContourModel::VertexIterator it = itUp;

    //copy the rest of the original contour
    while(it != end)
    {
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //return the offset of iterator at next vertex upwards
    if(itUp != end)
    {
      return itUp._Myoff + 1;
    }
    else
    {
      return itUp._Myoff - 1;//take last vertex if iterator is at end
    }

  }
  else //downwards
  {
    mitk::ContourModel::VertexIterator itDown = itSelected;

    if(itDown != begin)
    {
      itDown--;//step once down otherwise the the loop breaks immediately
    }

    while( itDown != begin && !((*itDown)->IsActive)){ itDown--; }

    mitk::ContourModel::VertexIterator it = sourceContour->IteratorBegin();

    if(it != end)
    {
      //always add the first vertex
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //copy from begin to itDown
    while(it <= itDown)
    {
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //add vertex at itDown - it's not considered during while loop
    if( it != begin && it != end)
    {
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
    }

    //return the offset of iterator at next vertex downwards
    if( itDown != begin)
    {
      return itDown._Myoff - 1;//index of next vertex
    }
    else
    {
      return itDown._Myoff;
    }
  }
}
<commit_msg>livewire interaction on move vertex fixed<commit_after>/*===================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center,
Division of Medical and Biological Informatics.
All rights reserved.

This software is distributed WITHOUT ANY WARRANTY; without
even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE.

See LICENSE.txt or http://www.mitk.org for details.

===================================================================*/

#include "mitkContourModelLiveWireInteractor.h"

#include "mitkToolManager.h"

#include "mitkBaseRenderer.h"
#include "mitkRenderingManager.h"

#include <mitkPositionEvent.h>
#include <mitkStateEvent.h>

#include <mitkInteractionConst.h>

mitk::ContourModelLiveWireInteractor::ContourModelLiveWireInteractor(DataNode* dataNode)
:ContourModelInteractor(dataNode)
{
  m_LiveWireFilter = mitk::ImageLiveWireContourModelFilter::New();

  mitk::ContourModel::Pointer m_ContourLeft = mitk::ContourModel::New();
  mitk::ContourModel::Pointer m_ContourRight = mitk::ContourModel::New();
  m_NextActiveVertexDown.Fill(0);
  m_NextActiveVertexUp.Fill(0);
}

mitk::ContourModelLiveWireInteractor::~ContourModelLiveWireInteractor()
{
}

bool mitk::ContourModelLiveWireInteractor::OnCheckPointClick( Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  mitk::StateEvent* newStateEvent = NULL;

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>(
    m_DataNode->GetData() );

  contour->Deselect();

  /*
  * Check distance to any vertex.
  * Transition YES if click close to a vertex
  */
  mitk::Point3D click = positionEvent->GetWorldPosition();

  if (contour->SelectVertexAt(click, 1.5, timestep) )
  {
    contour->SetSelectedVertexAcitve();

    assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
    mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
    newStateEvent = new mitk::StateEvent(EIDYES, stateEvent->GetEvent());
    m_lastMousePosition = click;

    mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

    //
    m_ContourLeft = mitk::ContourModel::New();

    //get coordinates of next active vertex downwards from selected vertex
    int downIndex = SplitContourFromSelectedVertex( contour, m_ContourLeft, false, timestep);

    mitk::ContourModel::VertexIterator itDown = contour->IteratorBegin() + downIndex;
    m_NextActiveVertexDown = (*itDown)->Coordinates;

    //
    m_ContourRight = mitk::ContourModel::New();

    //get coordinates of next active vertex upwards from selected vertex
    int upIndex = SplitContourFromSelectedVertex( contour, m_ContourRight, true, timestep);

    mitk::ContourModel::VertexIterator itUp = contour->IteratorBegin() + upIndex;
    m_NextActiveVertexUp = (*itUp)->Coordinates;

  }
  else
  {
    newStateEvent = new mitk::StateEvent(EIDNO, stateEvent->GetEvent());
  }

  this->HandleEvent( newStateEvent );

  return true;
}

bool mitk::ContourModelLiveWireInteractor::OnDeletePoint( Action* action, const StateEvent* stateEvent)
{

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

  mitk::ContourModel::Pointer newContour = mitk::ContourModel::New();
  newContour->Expand(contour->GetTimeSteps());
  newContour->Concatenate( m_ContourLeft, timestep );

  //recompute contour between neighbored two active control points
  this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown );
  this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp );
  this->m_LiveWireFilter->Update();

  mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New();
  liveWireContour = this->m_LiveWireFilter->GetOutput();

  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );

  newContour->Concatenate( m_ContourRight, timestep );

  newContour->SetIsClosed(contour->IsClosed(timestep), timestep);

  m_DataNode->SetData(newContour);

  assert( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate( stateEvent->GetEvent()->GetSender()->GetRenderWindow() );

  return true;
}

bool mitk::ContourModelLiveWireInteractor::OnMovePoint( Action* action, const StateEvent* stateEvent)
{
  const PositionEvent* positionEvent = dynamic_cast<const PositionEvent*>(stateEvent->GetEvent());
  if (!positionEvent) return false;

  int timestep = stateEvent->GetEvent()->GetSender()->GetTimeStep();

  mitk::ContourModel *contour = dynamic_cast<mitk::ContourModel *>( m_DataNode->GetData() );

  mitk::ContourModel::Pointer newContour = mitk::ContourModel::New();
  newContour->Expand(contour->GetTimeSteps());

  /*++++++++++++++ concatenate LEFT ++++++++++++++++++++++++++++++*/
  newContour->Concatenate( m_ContourLeft, timestep );

  mitk::Point3D currentPosition = positionEvent->GetWorldPosition();

  /*+++++++++++++++ start computation ++++++++++++++++++++*/
  //recompute contour between previous active vertex and selected vertex
  this->m_LiveWireFilter->SetStartPoint( m_NextActiveVertexDown );
  this->m_LiveWireFilter->SetEndPoint( currentPosition );
  this->m_LiveWireFilter->Update();

  mitk::ContourModel::Pointer liveWireContour = mitk::ContourModel::New();
  liveWireContour = this->m_LiveWireFilter->GetOutput();

  /*++++++++++++++ concatenate LIVEWIRE ++++++++++++++++++++++++++++++*/
  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );

  //recompute contour between selected vertex and next active vertex
  this->m_LiveWireFilter->SetStartPoint( currentPosition );
  this->m_LiveWireFilter->SetEndPoint( m_NextActiveVertexUp );
  this->m_LiveWireFilter->Update();

  liveWireContour = this->m_LiveWireFilter->GetOutput();

  //make point at mouse position active again, so it is drawn
  const_cast<mitk::ContourModel::VertexType*>( liveWireContour->GetVertexAt(0, timestep) )->IsActive = true;

  /*++++++++++++++ concatenate RIGHT ++++++++++++++++++++++++++++++*/
  //insert new liveWire computed points
  newContour->Concatenate( liveWireContour, timestep );
  /*------------------------------------------------*/

  newContour->Concatenate( m_ContourRight, timestep );

  newContour->SetIsClosed(contour->IsClosed(timestep), timestep);

  m_DataNode->SetData(newContour);

  this->m_lastMousePosition = positionEvent->GetWorldPosition();

  assert( positionEvent->GetSender()->GetRenderWindow() );
  mitk::RenderingManager::GetInstance()->RequestUpdate( positionEvent->GetSender()->GetRenderWindow() );

  return true;
}

int mitk::ContourModelLiveWireInteractor::SplitContourFromSelectedVertex(mitk::ContourModel* sourceContour, mitk::ContourModel* destinationContour, bool fromSelectedUpwards, int timestep)
{

  mitk::ContourModel::VertexIterator end =sourceContour->IteratorEnd();
  mitk::ContourModel::VertexIterator begin =sourceContour->IteratorBegin();

  //search next active control point to left and rigth and set as start and end point for filter
  mitk::ContourModel::VertexIterator itSelected = sourceContour->IteratorBegin();

  //move iterator to position
  while((*itSelected) != sourceContour->GetSelectedVertex())
  {
    itSelected++;
  }

  if(fromSelectedUpwards)
  {
    mitk::ContourModel::VertexIterator itUp = itSelected;

    if(itUp != end)
    {
      itUp++;//step once up otherwise the the loop breaks immediately
    }

    while( itUp != end && !((*itUp)->IsActive)){ itUp++; }

    mitk::ContourModel::VertexIterator it = itUp;

    //copy the rest of the original contour
    while(it != end)
    {
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //return the offset of iterator at one before next-vertex-upwards
    if(itUp != begin)
    {
      return itUp._Myoff - 1;
    }
    else
    {
      return itUp._Myoff;
    }

  }
  else //downwards
  {
    mitk::ContourModel::VertexIterator itDown = itSelected;

    if(itDown != begin)
    {
      itDown--;//step once down otherwise the the loop breaks immediately
    }

    while( itDown != begin && !((*itDown)->IsActive)){ itDown--; }

    mitk::ContourModel::VertexIterator it = sourceContour->IteratorBegin();

    if(it != end)//if not empty
    {
      //always add the first vertex
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //copy from begin to itDown
    while(it <= itDown)
    {
      destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
      it++;
    }

    //add vertex at itDown - it's not considered during while loop
    if( it != begin && it != end)
    {
      //destinationContour->AddVertex( (*it)->Coordinates, (*it)->IsActive, timestep);
    }

    //return the offset of iterator at one after next-vertex-downwards
    if( itDown != end)
    {
      return itDown._Myoff + 1;//index of next vertex
    }
    else
    {
      return itDown._Myoff - 1;
    }
  }
}
<|endoftext|>


<commit_before>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
namespace Js
{
#ifdef SSE2MATH
    namespace SSE2
    {
#endif
        __inline Var JavascriptMath::Increment(Var aRight, ScriptContext* scriptContext)
        {
            return Increment_Full(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Decrement(Var aRight, ScriptContext* scriptContext)
        {
            return Decrement_Full(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Negate(Var aRight, ScriptContext* scriptContext)
        {
            return
                (TaggedInt::Is(aRight) && aRight != TaggedInt::ToVarUnchecked(0) && aRight != TaggedInt::MinVal()) ?
                    TaggedInt::NegateUnchecked(aRight) :
                    Negate_Full(aRight,scriptContext);
        }

        __inline Var JavascriptMath::Not(Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::Is(aRight) ?
                TaggedInt::Not(aRight,scriptContext) :
                Not_Full(aRight,scriptContext);
        }

        __inline Var JavascriptMath::Or(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Or(aLeft,aRight) :
                Or_Full(aLeft,aRight,scriptContext);
        }

        __inline Var JavascriptMath::And(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
#if FLOATVAR
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::And(aLeft,aRight) :
                And_Full(aLeft,aRight,scriptContext);
#else
            Var varSpeculative = TaggedInt::Speculative_And(aLeft, aRight);
            if (TaggedInt::Is(varSpeculative))
            {
                return varSpeculative;
            }

            return And_Full(aLeft, aRight, scriptContext);
#endif
        }

        __inline Var JavascriptMath::ShiftLeft(Var aLeft,Var aRight,ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftLeft(aLeft, aRight,scriptContext) :
                ShiftLeft_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::ShiftRight(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftRight(aLeft, aRight) :
                ShiftRight_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::ShiftRightU(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftRightU(aLeft, aRight, scriptContext) :
                ShiftRightU_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::Xor(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::Xor(aLeft, aRight) :
                Xor_Full(aLeft, aRight,scriptContext);
        }

        __inline double JavascriptMath::Decrement_Helper(Var aRight, ScriptContext* scriptContext)
        {
    #if defined(DBG)
            if (TaggedInt::Is(aRight))
            {
                // The only reason to be here is if TaggedInt increment underflowed
                AssertMsg(aRight == TaggedInt::MinVal(), "TaggedInt decrement should be handled in generated code.");
            }
    #endif

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return --value;
        }

        __inline double JavascriptMath::Increment_Helper(Var aRight, ScriptContext* scriptContext)
        {
    #if defined(DBG)
            if (TaggedInt::Is(aRight))
            {
                // The only reason to be here is if TaggedInt increment overflowed
                AssertMsg(aRight == TaggedInt::MaxVal(), "TaggedInt increment should be handled in generated code.");
            }
    #endif

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return ++value;
        }

        __inline double JavascriptMath::Negate_Helper(Var aRight,ScriptContext* scriptContext)
        {
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return -value;
        }

        __inline int32 JavascriptMath::And_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);
#if _M_IX86
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "TaggedInt bitwise and should have been handled already");
#endif

            int32 nLeft = JavascriptConversion::ToInt32(aLeft, scriptContext);
            int32 nRight = JavascriptConversion::ToInt32(aRight, scriptContext);
            return nLeft & nRight;
        }

        __inline int32 JavascriptMath::Or_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);
#if _M_IX86
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "TaggedInt bitwise or should have been handled already");
#endif
            int32 nLeft = JavascriptConversion::ToInt32(aLeft, scriptContext);
            int32 nRight = JavascriptConversion::ToInt32(aRight, scriptContext);
            return nLeft | nRight;
        }

        __inline double JavascriptMath::Add_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            AssertMsg( !JavascriptString::Is(aLeft), "Strings should have been handled already" );
            AssertMsg( !JavascriptString::Is(aRight), "Strings should have been handled already" );

            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return dblLeft + dblRight;
        }

        __inline Var JavascriptMath::Add(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Add(aLeft, aRight, scriptContext) :
                Add_Full(aLeft, aRight, scriptContext);
        }

        __inline Var JavascriptMath::Subtract(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Subtract(aLeft, aRight, scriptContext) :
                Subtract_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Subtract_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return dblLeft - dblRight;
        }

        __inline Var JavascriptMath::Multiply(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Multiply(aLeft, aRight, scriptContext) :
                Multiply_Full(aLeft, aRight, scriptContext);
        }

        __inline Var JavascriptMath::Exponentiation(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return Exponentiation_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Multiply_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            return JavascriptConversion::ToNumber(aLeft, scriptContext) * JavascriptConversion::ToNumber(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Divide(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            // The TaggedInt,TaggedInt case is handled within Divide_Full
            return Divide_Full(aLeft, aRight,scriptContext);
        }

        __inline double JavascriptMath::Divide_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

#if !defined(_M_ARM32_OR_ARM64)
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "Integer division should have been handled already");
#endif

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            return JavascriptConversion::ToNumber(aLeft, scriptContext) / JavascriptConversion::ToNumber(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Modulus(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return Modulus_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Modulus_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return NumberUtilities::Modulus(dblLeft, dblRight);
        }

#if defined(_M_ARM32_OR_ARM64)
        __inline int32 JavascriptMath::ToInt32Core(double T1)
        {
            // Try the int32 conversion first and only do the more expensive (& closer to spec)
            // i64 conversion if it fails.
            __int32 i32 = (__int32)T1;
            if ((i32 != 0x80000000) && (i32 != 0x7fffffff))
                return i32;     //No overflow so just return i32

            int64 T4_64 = TryToInt64(T1);
            if (!NumberUtilities::IsValidTryToInt64(T4_64)) // overflow
            {
                T4_64 = ToInt32ES5OverflowHelper(T1);
            }

            return static_cast<int32>(T4_64);
        }
#else
        __inline int32 JavascriptMath::ToInt32Core(double T1)
        {
            // ES5 Spec for ToUInt32
            //
            //  T3 = sign(T1) * floor(abs(T1))
            //  T4 = T3 % 2^32
            //
            // Casting gives equivalent result, except when T1 > INT64_MAX, or T1 < INT64_MIN (or NaN Inf Zero),
            // in which case we'll use slow path.

            // Try casting to int32 first. Results in 0x80000000 if it overflows.
            int32 T4_32 = static_cast<int32>(T1);
            if (T4_32 != 0x80000000)
            {
                return T4_32;
            }

            int64 T4_64 = TryToInt64(T1);
            if (T4_64 == 0x8000000000000000) // overflow && ES5
            {
                T4_64 = ToInt32ES5OverflowHelper(T1);
            }

            return static_cast<int32>(T4_64);
        }
#endif

        // Implements platform-agnostic part of handling overflow when converting Number to int32, ES5 version.
        __inline __int64 JavascriptMath::ToInt32ES5OverflowHelper(double d)
        {
            if (IsNanInfZero(d)) // ShortCut NaN Inf Zero
            {
                return 0;
            }
            const double k_2to32 = 4294967296.0;
            double floored;

#pragma prefast(suppress:6031, "We don't care about the fraction part")
            modf(d, &floored);                      // take out the floating point part.
            double m2to32 = fmod(floored, k_2to32); // divide modulo 2^32.
            __int64 result = TryToInt64(m2to32);

            AssertMsg(NumberUtilities::IsValidTryToInt64(result), "No more overflow expected");

            return result;
        }

        __inline BOOL JavascriptMath::IsNanInfZero(double v)
        {
            return JavascriptNumber::IsNan(v) || JavascriptNumber::IsZero(v) || JavascriptNumber::IsPosInf(v) || JavascriptNumber::IsNegInf(v);
        }

        __inline int64 JavascriptMath::TryToInt64(double T1)
        {
            return Js::NumberUtilities::TryToInt64(T1);
        }

        __inline int32 JavascriptMath::ToInt32_NoObjects(Var aValue, ScriptContext* scriptContext, bool& isObject)
        {
            if (JavascriptOperators::IsObject(aValue))
            {
                isObject = true; // jitted code should bailout
                return 0;
            }

            isObject = false;
            return ToInt32(aValue, scriptContext);
        }

        __inline int32 JavascriptMath::ToInt32(Var aValue, ScriptContext* scriptContext)
        {
            return
                TaggedInt::Is(aValue) ?
                TaggedInt::ToInt32(aValue) :
                ToInt32_Full(aValue, scriptContext);
        }
#ifdef SSE2MATH
    }
#endif
}
<commit_msg>[MERGE #686] update interpreter to use SSE2 div when possible<commit_after>//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------

#include "RuntimeMathPch.h"

namespace Js
{
#ifdef SSE2MATH
    namespace SSE2
    {
#endif
        __inline Var JavascriptMath::Increment(Var aRight, ScriptContext* scriptContext)
        {
            return Increment_Full(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Decrement(Var aRight, ScriptContext* scriptContext)
        {
            return Decrement_Full(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Negate(Var aRight, ScriptContext* scriptContext)
        {
            return
                (TaggedInt::Is(aRight) && aRight != TaggedInt::ToVarUnchecked(0) && aRight != TaggedInt::MinVal()) ?
                    TaggedInt::NegateUnchecked(aRight) :
                    Negate_Full(aRight,scriptContext);
        }

        __inline Var JavascriptMath::Not(Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::Is(aRight) ?
                TaggedInt::Not(aRight,scriptContext) :
                Not_Full(aRight,scriptContext);
        }

        __inline Var JavascriptMath::Or(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Or(aLeft,aRight) :
                Or_Full(aLeft,aRight,scriptContext);
        }

        __inline Var JavascriptMath::And(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
#if FLOATVAR
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::And(aLeft,aRight) :
                And_Full(aLeft,aRight,scriptContext);
#else
            Var varSpeculative = TaggedInt::Speculative_And(aLeft, aRight);
            if (TaggedInt::Is(varSpeculative))
            {
                return varSpeculative;
            }

            return And_Full(aLeft, aRight, scriptContext);
#endif
        }

        __inline Var JavascriptMath::ShiftLeft(Var aLeft,Var aRight,ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftLeft(aLeft, aRight,scriptContext) :
                ShiftLeft_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::ShiftRight(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftRight(aLeft, aRight) :
                ShiftRight_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::ShiftRightU(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::ShiftRightU(aLeft, aRight, scriptContext) :
                ShiftRightU_Full(aLeft, aRight,scriptContext);
        }

        __inline Var JavascriptMath::Xor(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft, aRight) ?
                TaggedInt::Xor(aLeft, aRight) :
                Xor_Full(aLeft, aRight,scriptContext);
        }

        __inline double JavascriptMath::Decrement_Helper(Var aRight, ScriptContext* scriptContext)
        {
    #if defined(DBG)
            if (TaggedInt::Is(aRight))
            {
                // The only reason to be here is if TaggedInt increment underflowed
                AssertMsg(aRight == TaggedInt::MinVal(), "TaggedInt decrement should be handled in generated code.");
            }
    #endif

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return --value;
        }

        __inline double JavascriptMath::Increment_Helper(Var aRight, ScriptContext* scriptContext)
        {
    #if defined(DBG)
            if (TaggedInt::Is(aRight))
            {
                // The only reason to be here is if TaggedInt increment overflowed
                AssertMsg(aRight == TaggedInt::MaxVal(), "TaggedInt increment should be handled in generated code.");
            }
    #endif

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return ++value;
        }

        __inline double JavascriptMath::Negate_Helper(Var aRight,ScriptContext* scriptContext)
        {
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            double value = JavascriptConversion::ToNumber(aRight, scriptContext);
            return -value;
        }

        __inline int32 JavascriptMath::And_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);
#if _M_IX86
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "TaggedInt bitwise and should have been handled already");
#endif

            int32 nLeft = JavascriptConversion::ToInt32(aLeft, scriptContext);
            int32 nRight = JavascriptConversion::ToInt32(aRight, scriptContext);
            return nLeft & nRight;
        }

        __inline int32 JavascriptMath::Or_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);
#if _M_IX86
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "TaggedInt bitwise or should have been handled already");
#endif
            int32 nLeft = JavascriptConversion::ToInt32(aLeft, scriptContext);
            int32 nRight = JavascriptConversion::ToInt32(aRight, scriptContext);
            return nLeft | nRight;
        }

        __inline double JavascriptMath::Add_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            AssertMsg( !JavascriptString::Is(aLeft), "Strings should have been handled already" );
            AssertMsg( !JavascriptString::Is(aRight), "Strings should have been handled already" );

            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return dblLeft + dblRight;
        }

        __inline Var JavascriptMath::Add(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Add(aLeft, aRight, scriptContext) :
                Add_Full(aLeft, aRight, scriptContext);
        }

        __inline Var JavascriptMath::Subtract(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return
                TaggedInt::IsPair(aLeft,aRight) ?
                TaggedInt::Subtract(aLeft, aRight, scriptContext) :
                Subtract_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Subtract_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return dblLeft - dblRight;
        }

        __inline Var JavascriptMath::Multiply(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            if (TaggedInt::IsPair(aLeft, aRight))
            {
                return TaggedInt::Multiply(aLeft, aRight, scriptContext);
            }
            else
            {
#if defined(_M_IX86) && !defined(SSE2MATH)
                if (AutoSystemInfo::Data.SSE2Available())
                {
                    return SSE2::JavascriptMath::Multiply_Full(aLeft, aRight, scriptContext);
                }
                else
#endif
                {
                    return Multiply_Full(aLeft, aRight, scriptContext);
                }
            }
        }

        __inline Var JavascriptMath::Exponentiation(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return Exponentiation_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Multiply_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            return JavascriptConversion::ToNumber(aLeft, scriptContext) * JavascriptConversion::ToNumber(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Divide(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
#if defined(_M_IX86) && !defined(SSE2MATH)
            if (AutoSystemInfo::Data.SSE2Available())
            {
                return SSE2::JavascriptMath::Divide_Full(aLeft, aRight, scriptContext);
            }
            else
#endif
            {
                // The TaggedInt,TaggedInt case is handled within Divide_Full
                return Divide_Full(aLeft, aRight, scriptContext);
            }
        }

        __inline double JavascriptMath::Divide_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            Assert(aLeft != nullptr);
            Assert(aRight != nullptr);
            Assert(scriptContext != nullptr);

#if !defined(_M_ARM32_OR_ARM64)
            AssertMsg(!TaggedInt::IsPair(aLeft, aRight), "Integer division should have been handled already");
#endif

            // The IEEE 754 floating point spec ensures that NaNs are preserved in all operations
            return JavascriptConversion::ToNumber(aLeft, scriptContext) / JavascriptConversion::ToNumber(aRight, scriptContext);
        }

        __inline Var JavascriptMath::Modulus(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            return Modulus_Full(aLeft, aRight, scriptContext);
        }

        __inline double JavascriptMath::Modulus_Helper(Var aLeft, Var aRight, ScriptContext* scriptContext)
        {
            double dblLeft = JavascriptConversion::ToNumber(aLeft, scriptContext);
            double dblRight = JavascriptConversion::ToNumber(aRight, scriptContext);
            return NumberUtilities::Modulus(dblLeft, dblRight);
        }

#if defined(_M_ARM32_OR_ARM64)
        __inline int32 JavascriptMath::ToInt32Core(double T1)
        {
            // Try the int32 conversion first and only do the more expensive (& closer to spec)
            // i64 conversion if it fails.
            __int32 i32 = (__int32)T1;
            if ((i32 != 0x80000000) && (i32 != 0x7fffffff))
                return i32;     //No overflow so just return i32

            int64 T4_64 = TryToInt64(T1);
            if (!NumberUtilities::IsValidTryToInt64(T4_64)) // overflow
            {
                T4_64 = ToInt32ES5OverflowHelper(T1);
            }

            return static_cast<int32>(T4_64);
        }
#else
        __inline int32 JavascriptMath::ToInt32Core(double T1)
        {
            // ES5 Spec for ToUInt32
            //
            //  T3 = sign(T1) * floor(abs(T1))
            //  T4 = T3 % 2^32
            //
            // Casting gives equivalent result, except when T1 > INT64_MAX, or T1 < INT64_MIN (or NaN Inf Zero),
            // in which case we'll use slow path.

            // Try casting to int32 first. Results in 0x80000000 if it overflows.
            int32 T4_32 = static_cast<int32>(T1);
            if (T4_32 != 0x80000000)
            {
                return T4_32;
            }

            int64 T4_64 = TryToInt64(T1);
            if (T4_64 == 0x8000000000000000) // overflow && ES5
            {
                T4_64 = ToInt32ES5OverflowHelper(T1);
            }

            return static_cast<int32>(T4_64);
        }
#endif

        // Implements platform-agnostic part of handling overflow when converting Number to int32, ES5 version.
        __inline __int64 JavascriptMath::ToInt32ES5OverflowHelper(double d)
        {
            if (IsNanInfZero(d)) // ShortCut NaN Inf Zero
            {
                return 0;
            }
            const double k_2to32 = 4294967296.0;
            double floored;

#pragma prefast(suppress:6031, "We don't care about the fraction part")
            modf(d, &floored);                      // take out the floating point part.
            double m2to32 = fmod(floored, k_2to32); // divide modulo 2^32.
            __int64 result = TryToInt64(m2to32);

            AssertMsg(NumberUtilities::IsValidTryToInt64(result), "No more overflow expected");

            return result;
        }

        __inline BOOL JavascriptMath::IsNanInfZero(double v)
        {
            return JavascriptNumber::IsNan(v) || JavascriptNumber::IsZero(v) || JavascriptNumber::IsPosInf(v) || JavascriptNumber::IsNegInf(v);
        }

        __inline int64 JavascriptMath::TryToInt64(double T1)
        {
            return Js::NumberUtilities::TryToInt64(T1);
        }

        __inline int32 JavascriptMath::ToInt32_NoObjects(Var aValue, ScriptContext* scriptContext, bool& isObject)
        {
            if (JavascriptOperators::IsObject(aValue))
            {
                isObject = true; // jitted code should bailout
                return 0;
            }

            isObject = false;
            return ToInt32(aValue, scriptContext);
        }

        __inline int32 JavascriptMath::ToInt32(Var aValue, ScriptContext* scriptContext)
        {
            return
                TaggedInt::Is(aValue) ?
                TaggedInt::ToInt32(aValue) :
                ToInt32_Full(aValue, scriptContext);
        }
#ifdef SSE2MATH
    }
#endif
}
<|endoftext|>


<commit_before>
#include "ImwPlatformWindow.h"

#include "ImwWindowManager.h"

namespace ImWindow
{
//SFF_BEGIN
	ImwPlatformWindow::ImwPlatformWindow(EPlatformWindowType eType, bool bCreateContext)
	{
		m_eType = eType;
		m_pContainer = new ImwContainer(this);
		m_pContext = NULL;
		m_pPreviousContext = NULL;
		m_bNeedRender = false;
		m_bShowContent = true;

		if ( bCreateContext )
		{
			ImGuiContext* pGlobalContext = ImGui::GetCurrentContext();
			IM_ASSERT(pGlobalContext != NULL);

			m_pContext = ImGui::CreateContext( pGlobalContext->IO.MemAllocFn, pGlobalContext->IO.MemFreeFn );

			ImGuiIO& oGlobalIO = pGlobalContext->IO;
			ImGuiIO& oNewIO = m_pContext->IO;

			memcpy(&(oNewIO.KeyMap), &(oGlobalIO.KeyMap ), sizeof( pGlobalContext->IO.KeyMap ));
			oNewIO.RenderDrawListsFn = NULL;
			oNewIO.GetClipboardTextFn = oGlobalIO.GetClipboardTextFn;
			oNewIO.SetClipboardTextFn = oGlobalIO.SetClipboardTextFn;
			oNewIO.ImeSetInputScreenPosFn = oGlobalIO.ImeSetInputScreenPosFn;
			oNewIO.IniFilename = NULL;
		}
	}

	ImwPlatformWindow::~ImwPlatformWindow()
	{
		ImwSafeDelete(m_pContainer);

		if (m_pContext != NULL)
		{
			m_pContext->IO.Fonts = NULL;
			SetContext(false);
			ImGui::Shutdown();
			RestoreContext(false);
			ImGui::DestroyContext(m_pContext);
			m_pContext = NULL;
		}
	}

	bool ImwPlatformWindow::Init(ImwPlatformWindow* /*pParent*/)
	{
		return true;
	}

	EPlatformWindowType ImwPlatformWindow::GetType() const
	{
		return m_eType;
	}

	const ImVec2 c_oVec2_0 = ImVec2(0,0);
	ImVec2 ImwPlatformWindow::GetPosition() const
	{
		return c_oVec2_0;
	}

	ImVec2 ImwPlatformWindow::GetSize() const
	{
		return ImGui::GetIO().DisplaySize;
	}

	ImVec2 ImwPlatformWindow::GetNormalPosition() const
	{
		return GetPosition();
	}

	ImVec2 ImwPlatformWindow::GetNormalSize() const
	{
		return GetSize();
	}

	bool ImwPlatformWindow::IsWindowMaximized() const
	{
		return false;
	}

	bool ImwPlatformWindow::IsWindowMinimized() const
	{
		return false;
	}

	void ImwPlatformWindow::Show(bool /*bShow*/)
	{
	}

	void ImwPlatformWindow::SetSize(int /*iWidth*/, int /*iHeight*/)
	{
	}

	void ImwPlatformWindow::SetPosition(int /*iX*/, int /*iY*/)
	{
	}

	void ImwPlatformWindow::SetWindowMaximized(bool /*bMaximized*/)
	{
	}

	void  ImwPlatformWindow::SetWindowMinimized()
	{
	}

	void ImwPlatformWindow::SetTitle(const char* /*pTtile*/)
	{
	}

	bool ImwPlatformWindow::IsShowContent() const
	{
		return m_bShowContent;
	}

	void ImwPlatformWindow::SetShowContent(bool bShow)
	{
		m_bShowContent = bShow;
	}

	void ImwPlatformWindow::PreUpdate()
	{
	}

	void ImwPlatformWindow::PreRender()
	{
	}

	void ImwPlatformWindow::OnOverlay()
	{
	}

	void ImwPlatformWindow::RenderDrawLists(ImDrawData* /*pDrawData */)
	{
	}

	void ImwPlatformWindow::Render()
	{
		if( m_bNeedRender )
		{
			m_bNeedRender = false;
			SetContext(false);
			ImGui::GetIO().DisplaySize = GetSize();
			PreRender();
			ImGui::Render();
			RenderDrawLists(ImGui::GetDrawData());
			RestoreContext(false);
		}
	}

	void ImwPlatformWindow::PaintContainer()
	{
		m_pContainer->Paint();
	}

	void ImwPlatformWindow::OnClose()
	{
		ImwWindowManager::GetInstance()->OnClosePlatformWindow(this);
	}

	bool ImwPlatformWindow::Save(JsonValue& oJson)
	{
		ImVec2 oSize = GetNormalSize();
		ImVec2 oPos = GetNormalPosition();

		oJson["Width"] = (long)oSize.x;
		oJson["Height"] = (long)oSize.y;
		oJson["Left"] = (long)oPos.x;
		oJson["Top"] = (long)oPos.y;
		oJson["Mode"] = (long)(IsWindowMaximized() ? 1 : (IsWindowMinimized() ? -1 : 0));

		return m_pContainer->Save(oJson["Container"]);
	}

	bool ImwPlatformWindow::Load(const JsonValue& oJson, bool bJustCheck)
	{
		if (!oJson["Width"].IsNumeric() || !oJson["Height"].IsNumeric() || !oJson["Left"].IsNumeric() || !oJson["Top"].IsNumeric() || !oJson["Maximized"].IsBoolean())
			return false;

		if (!bJustCheck)
		{
			SetSize((long)oJson["Width"], (long)oJson["Height"]);
			SetPosition((long)oJson["Left"], (long)oJson["Top"]);

			if (oJson["Mode"].IsNumeric())
			{
				long iMode = (long)oJson["Mode"];
				if (iMode < 0)
				{
					SetWindowMinimized();
				}
				else
				{
					SetWindowMaximized(iMode > 0);
				}
			}
			else if (oJson["Maximized"].IsBoolean())
			{
				SetWindowMaximized(oJson["Maximized"]);
			}
		}

		return m_pContainer->Load(oJson["Container"], bJustCheck);
	}

	static bool s_bContextPushed = false;

	bool ImwPlatformWindow::IsContextSet()
	{
		return s_bContextPushed;
	}

	bool ImwPlatformWindow::HasContext() const
	{
		return m_pContext != NULL;
	}

	void ImwPlatformWindow::SetContext(bool bCopyStyle)
	{
		IM_ASSERT(s_bContextPushed == false);
		s_bContextPushed = true;
		if (m_pContext != NULL)
		{
			IM_ASSERT( m_pPreviousContext == NULL );
			m_pPreviousContext = ImGui::GetCurrentContext();
			ImGui::SetCurrentContext(m_pContext);
			if (bCopyStyle)
			{
				//Copy style from Global context
				memcpy(&(m_pContext->Style), &(m_pPreviousContext->Style), sizeof(ImGuiStyle));
			}
		}
	}

	void ImwPlatformWindow::RestoreContext(bool bCopyStyle)
	{
		IM_ASSERT(s_bContextPushed == true);
		s_bContextPushed = false;
		if (m_pContext != NULL)
		{
			IM_ASSERT(m_pPreviousContext != NULL);
			if (bCopyStyle)
			{
				//Copy style to Global context
				memcpy(&(m_pPreviousContext->Style), &(m_pContext->Style), sizeof(ImGuiStyle));
			}
			ImGui::SetCurrentContext(m_pPreviousContext);
			m_pPreviousContext = NULL;
		}
	}

	void ImwPlatformWindow::OnLoseFocus()
	{
		if (NULL != m_pContext)
		{
			m_pContext->SetNextWindowPosCond = m_pContext->SetNextWindowSizeCond = m_pContext->SetNextWindowContentSizeCond = m_pContext->SetNextWindowCollapsedCond = m_pContext->SetNextWindowFocus = 0;
			m_pContext->ActiveId = 0;

			for (int i = 0; i < 512; ++i)
				m_pContext->IO.KeysDown[i] = false;

			for (int i = 0; i < 5; ++i)
				m_pContext->IO.MouseDown[i] = false;

			m_pContext->IO.KeyAlt = false;
			m_pContext->IO.KeyCtrl = false;
			m_pContext->IO.KeyShift = false;
		}
	}

	void ImwPlatformWindow::Dock(ImwWindow* pWindow)
	{
		m_pContainer->Dock(pWindow);
	}

	bool ImwPlatformWindow::UnDock(ImwWindow* pWindow)
	{
		return m_pContainer->UnDock(pWindow);
	}

	ImwContainer* ImwPlatformWindow::GetContainer()
	{
		return m_pContainer;
	}

	ImwContainer* ImwPlatformWindow::HasWindow(ImwWindow* pWindow)
	{
		return m_pContainer->HasWindow(pWindow);
	}

	bool ImwPlatformWindow::FocusWindow(ImwWindow* pWindow)
	{
		return m_pContainer->FocusWindow(pWindow);
	}
//SFF_END
}<commit_msg>Fix layout loading<commit_after>
#include "ImwPlatformWindow.h"

#include "ImwWindowManager.h"

namespace ImWindow
{
//SFF_BEGIN
	ImwPlatformWindow::ImwPlatformWindow(EPlatformWindowType eType, bool bCreateContext)
	{
		m_eType = eType;
		m_pContainer = new ImwContainer(this);
		m_pContext = NULL;
		m_pPreviousContext = NULL;
		m_bNeedRender = false;
		m_bShowContent = true;

		if ( bCreateContext )
		{
			ImGuiContext* pGlobalContext = ImGui::GetCurrentContext();
			IM_ASSERT(pGlobalContext != NULL);

			m_pContext = ImGui::CreateContext( pGlobalContext->IO.MemAllocFn, pGlobalContext->IO.MemFreeFn );

			ImGuiIO& oGlobalIO = pGlobalContext->IO;
			ImGuiIO& oNewIO = m_pContext->IO;

			memcpy(&(oNewIO.KeyMap), &(oGlobalIO.KeyMap ), sizeof( pGlobalContext->IO.KeyMap ));
			oNewIO.RenderDrawListsFn = NULL;
			oNewIO.GetClipboardTextFn = oGlobalIO.GetClipboardTextFn;
			oNewIO.SetClipboardTextFn = oGlobalIO.SetClipboardTextFn;
			oNewIO.ImeSetInputScreenPosFn = oGlobalIO.ImeSetInputScreenPosFn;
			oNewIO.IniFilename = NULL;
		}
	}

	ImwPlatformWindow::~ImwPlatformWindow()
	{
		ImwSafeDelete(m_pContainer);

		if (m_pContext != NULL)
		{
			m_pContext->IO.Fonts = NULL;
			SetContext(false);
			ImGui::Shutdown();
			RestoreContext(false);
			ImGui::DestroyContext(m_pContext);
			m_pContext = NULL;
		}
	}

	bool ImwPlatformWindow::Init(ImwPlatformWindow* /*pParent*/)
	{
		return true;
	}

	EPlatformWindowType ImwPlatformWindow::GetType() const
	{
		return m_eType;
	}

	const ImVec2 c_oVec2_0 = ImVec2(0,0);
	ImVec2 ImwPlatformWindow::GetPosition() const
	{
		return c_oVec2_0;
	}

	ImVec2 ImwPlatformWindow::GetSize() const
	{
		return ImGui::GetIO().DisplaySize;
	}

	ImVec2 ImwPlatformWindow::GetNormalPosition() const
	{
		return GetPosition();
	}

	ImVec2 ImwPlatformWindow::GetNormalSize() const
	{
		return GetSize();
	}

	bool ImwPlatformWindow::IsWindowMaximized() const
	{
		return false;
	}

	bool ImwPlatformWindow::IsWindowMinimized() const
	{
		return false;
	}

	void ImwPlatformWindow::Show(bool /*bShow*/)
	{
	}

	void ImwPlatformWindow::SetSize(int /*iWidth*/, int /*iHeight*/)
	{
	}

	void ImwPlatformWindow::SetPosition(int /*iX*/, int /*iY*/)
	{
	}

	void ImwPlatformWindow::SetWindowMaximized(bool /*bMaximized*/)
	{
	}

	void  ImwPlatformWindow::SetWindowMinimized()
	{
	}

	void ImwPlatformWindow::SetTitle(const char* /*pTtile*/)
	{
	}

	bool ImwPlatformWindow::IsShowContent() const
	{
		return m_bShowContent;
	}

	void ImwPlatformWindow::SetShowContent(bool bShow)
	{
		m_bShowContent = bShow;
	}

	void ImwPlatformWindow::PreUpdate()
	{
	}

	void ImwPlatformWindow::PreRender()
	{
	}

	void ImwPlatformWindow::OnOverlay()
	{
	}

	void ImwPlatformWindow::RenderDrawLists(ImDrawData* /*pDrawData */)
	{
	}

	void ImwPlatformWindow::Render()
	{
		if( m_bNeedRender )
		{
			m_bNeedRender = false;
			SetContext(false);
			ImGui::GetIO().DisplaySize = GetSize();
			PreRender();
			ImGui::Render();
			RenderDrawLists(ImGui::GetDrawData());
			RestoreContext(false);
		}
	}

	void ImwPlatformWindow::PaintContainer()
	{
		m_pContainer->Paint();
	}

	void ImwPlatformWindow::OnClose()
	{
		ImwWindowManager::GetInstance()->OnClosePlatformWindow(this);
	}

	bool ImwPlatformWindow::Save(JsonValue& oJson)
	{
		ImVec2 oSize = GetNormalSize();
		ImVec2 oPos = GetNormalPosition();

		oJson["Width"] = (long)oSize.x;
		oJson["Height"] = (long)oSize.y;
		oJson["Left"] = (long)oPos.x;
		oJson["Top"] = (long)oPos.y;
		oJson["Mode"] = (long)(IsWindowMaximized() ? 1 : (IsWindowMinimized() ? -1 : 0));

		return m_pContainer->Save(oJson["Container"]);
	}

	bool ImwPlatformWindow::Load(const JsonValue& oJson, bool bJustCheck)
	{
		if (!oJson["Width"].IsNumeric() || !oJson["Height"].IsNumeric() || !oJson["Left"].IsNumeric() || !oJson["Top"].IsNumeric() || (!oJson["Mode"].IsNumeric() && !oJson["Maximized"].IsBoolean()))
			return false;

		if (!bJustCheck)
		{
			SetSize((long)oJson["Width"], (long)oJson["Height"]);
			SetPosition((long)oJson["Left"], (long)oJson["Top"]);

			if (oJson["Mode"].IsNumeric())
			{
				long iMode = (long)oJson["Mode"];
				if (iMode < 0)
				{
					SetWindowMinimized();
				}
				else
				{
					SetWindowMaximized(iMode > 0);
				}
			}
			else if (oJson["Maximized"].IsBoolean())
			{
				SetWindowMaximized(oJson["Maximized"]);
			}
		}

		return m_pContainer->Load(oJson["Container"], bJustCheck);
	}

	static bool s_bContextPushed = false;

	bool ImwPlatformWindow::IsContextSet()
	{
		return s_bContextPushed;
	}

	bool ImwPlatformWindow::HasContext() const
	{
		return m_pContext != NULL;
	}

	void ImwPlatformWindow::SetContext(bool bCopyStyle)
	{
		IM_ASSERT(s_bContextPushed == false);
		s_bContextPushed = true;
		if (m_pContext != NULL)
		{
			IM_ASSERT( m_pPreviousContext == NULL );
			m_pPreviousContext = ImGui::GetCurrentContext();
			ImGui::SetCurrentContext(m_pContext);
			if (bCopyStyle)
			{
				//Copy style from Global context
				memcpy(&(m_pContext->Style), &(m_pPreviousContext->Style), sizeof(ImGuiStyle));
			}
		}
	}

	void ImwPlatformWindow::RestoreContext(bool bCopyStyle)
	{
		IM_ASSERT(s_bContextPushed == true);
		s_bContextPushed = false;
		if (m_pContext != NULL)
		{
			IM_ASSERT(m_pPreviousContext != NULL);
			if (bCopyStyle)
			{
				//Copy style to Global context
				memcpy(&(m_pPreviousContext->Style), &(m_pContext->Style), sizeof(ImGuiStyle));
			}
			ImGui::SetCurrentContext(m_pPreviousContext);
			m_pPreviousContext = NULL;
		}
	}

	void ImwPlatformWindow::OnLoseFocus()
	{
		if (NULL != m_pContext)
		{
			m_pContext->SetNextWindowPosCond = m_pContext->SetNextWindowSizeCond = m_pContext->SetNextWindowContentSizeCond = m_pContext->SetNextWindowCollapsedCond = m_pContext->SetNextWindowFocus = 0;
			m_pContext->ActiveId = 0;

			for (int i = 0; i < 512; ++i)
				m_pContext->IO.KeysDown[i] = false;

			for (int i = 0; i < 5; ++i)
				m_pContext->IO.MouseDown[i] = false;

			m_pContext->IO.KeyAlt = false;
			m_pContext->IO.KeyCtrl = false;
			m_pContext->IO.KeyShift = false;
		}
	}

	void ImwPlatformWindow::Dock(ImwWindow* pWindow)
	{
		m_pContainer->Dock(pWindow);
	}

	bool ImwPlatformWindow::UnDock(ImwWindow* pWindow)
	{
		return m_pContainer->UnDock(pWindow);
	}

	ImwContainer* ImwPlatformWindow::GetContainer()
	{
		return m_pContainer;
	}

	ImwContainer* ImwPlatformWindow::HasWindow(ImwWindow* pWindow)
	{
		return m_pContainer->HasWindow(pWindow);
	}

	bool ImwPlatformWindow::FocusWindow(ImwWindow* pWindow)
	{
		return m_pContainer->FocusWindow(pWindow);
	}
//SFF_END
}<|endoftext|>


<commit_before>#include "gtest/gtest.h"
#include <base/cpu.h>
#include <base/mactype.h>
#include <PowerCore.h>

#define BASE 0x1000
#define WORDS (ptr_from_longint<GUEST<uint16_t>*>(BASE))
#define LONGS (ptr_from_longint<GUEST<uint32_t>*>(BASE))

using namespace Executor;

TEST(CPU, execute68K)
{
    EM_D0 = 0;
    auto p = WORDS;
    *p++ = 0x4E71;  //  NOP
    *p++ = 0x303C;  //  MOVE.W ___, d0
    *p++ = 0x002A;  //         #42
    *p++ = 0x4E75;  //  RTS

    ROMlib_destroy_blocks(BASE, 32, false);
    execute68K(BASE);

    EXPECT_EQ(42, EM_D0);
}

TEST(CPU, executePPC)
{
    getPowerCore().r[3] = 0;
    auto p = LONGS;
    *p++ = 0x60000000;  //  nop
    *p++ = 0x38600036;  //  li r3, 54
    *p++ = 0x3860002a;  //  li r4, 42
    *p++ = 0x4e800020;  //  blr

    getPowerCore().flushCache();
    executePPC(BASE);

    EXPECT_EQ(42, getPowerCore().r[3]);
}

TEST(CPU, breakpoint68K)
{
    EM_D0 = 0;
    auto p = WORDS;
    *p++ = 0x4E71;  //  NOP
    *p++ = 0x303C;  //  MOVE.W ___, d0
    *p++ = 0x0036;  //         #54
    *p++ = 0x303C;  //  MOVE.W ___, d0
    *p++ = 0x002A;  //         #42
    *p++ = 0x4E75;  //  RTS

    thread_local int breakHit;
    thread_local syn68k_addr_t stoppedAddr, stoppedD0;
    breakHit = 0;
    stoppedAddr = stoppedD0 = 0;

    syn68k_debugger_callbacks.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
        if(breakHit == 0 && addr <= BASE + 6)
            return BASE + 6;
        else
            return 0xFFFFFFFF;
    };
    syn68k_debugger_callbacks.debugger = [](syn68k_addr_t addr) -> syn68k_addr_t {
        breakHit++;
        stoppedAddr = addr;
        stoppedD0 = EM_D0;
        destroy_blocks(0, ~0);
        return addr;
    };

    destroy_blocks(0, ~0);
    execute68K(BASE);

    EXPECT_EQ(42, EM_D0);
    EXPECT_EQ(1, breakHit);
    EXPECT_EQ(54, stoppedD0);
    EXPECT_EQ(BASE + 6, stoppedAddr);
}

TEST(CPU, breakpointPPC)
{
    auto& cpu = getPowerCore();
    cpu.r[3] = 0;
    auto p = LONGS;
    *p++ = 0x60000000;  //  nop
    *p++ = 0x38600036;  //  li r3, 54
    *p++ = 0x3860002a;  //  li r4, 42
    *p++ = 0x4e800020;  //  blr

    thread_local int breakHit;
    thread_local syn68k_addr_t stoppedAddr, stoppedR3;
    breakHit = 0;
    stoppedAddr = stoppedR3 = 0;

    cpu.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
        if(breakHit == 0 && addr <= BASE + 8)
            return BASE + 8;
        else
            return 0xFFFFFFFF;
    };
    cpu.debugger = [](PowerCore& cpu) {
        breakHit++;
        stoppedAddr = cpu.CIA;
        stoppedR3 = cpu.r[3];
        cpu.flushCache();
    };

    cpu.flushCache();
    executePPC(BASE);

    EXPECT_EQ(42, cpu.r[3]);
    EXPECT_EQ(1, breakHit);
    EXPECT_EQ(54, stoppedR3);
    EXPECT_EQ(BASE + 8, stoppedAddr);
}

TEST(CPU, fib68K)
{
    auto p = WORDS;

    *p++ = 0x7200;  //          moveq #0, %d1
    *p++ = 0x7401;  //          moveq #1, %d2
    *p++ = 0x4a00;  // loop:    tst.b %d0
    *p++ = 0x6708;  //          beq.s end
    *p++ = 0xd282;  //          add.l %d2, %d1
    *p++ = 0xc541;  //          exg %d2, %d1
    *p++ = 0x5340;  //          subq #1, %d0
    *p++ = 0x60f4;  //          bra.s loop
    *p++ = 0x4e75;  // end:     rts

    thread_local int breakHit;
    thread_local syn68k_addr_t stoppedAddr = 0;
    breakHit = 0;

    syn68k_debugger_callbacks.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
        if(stoppedAddr == addr)
            return addr + 1;
        else
            return addr;
    };
    syn68k_debugger_callbacks.debugger = [](syn68k_addr_t addr) -> syn68k_addr_t {
        breakHit++;
        stoppedAddr = addr;
        destroy_blocks(0, ~0);
        return addr;
    };

    EM_D0 = 7;
    destroy_blocks(0, ~0);
    execute68K(BASE);

    EXPECT_EQ(13, EM_D1);
}
<commit_msg>clean up cpu/debugger tests, add minimal failing test cases<commit_after>#include "gtest/gtest.h"
#include <base/cpu.h>
#include <base/mactype.h>
#include <PowerCore.h>

#define BASE 0x1000
#define WORDS (ptr_from_longint<GUEST<uint16_t>*>(BASE))
#define LONGS (ptr_from_longint<GUEST<uint32_t>*>(BASE))

using namespace Executor;

thread_local int breakHit;
thread_local syn68k_addr_t stoppedAddr;

class CPU : public testing::Test
{
public:
    void m68k(std::initializer_list<uint16_t> code)
    {
        auto p = ptr_from_longint<GUEST<uint16_t>*>(BASE);
        for(auto w : code)
            *p++ = w;

        m68k();
    }
    void m68k()
    {
        destroy_blocks(0, ~0);
        execute68K(BASE);
    }

    void ppc(std::initializer_list<uint32_t> code)
    {
        auto p = ptr_from_longint<GUEST<uint32_t>*>(BASE);
        for(auto w : code)
            *p++ = w;

        ppc();
    }

    void ppc()
    {
        getPowerCore().flushCache();
        executePPC(BASE);
    }
};

class CPUSingleStep : public CPU
{
public:
    CPUSingleStep()
    {
        breakHit = 0;
        stoppedAddr = 0;

        syn68k_debugger_callbacks.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
            if(stoppedAddr == addr)
                return addr + 1;
            else
                return addr;
        };
        syn68k_debugger_callbacks.debugger = [](syn68k_addr_t addr) -> syn68k_addr_t {
            breakHit++;
            stoppedAddr = addr;
            destroy_blocks(0, ~0);
            return addr;
        };
    }

    ~CPUSingleStep()
    {
        syn68k_debugger_callbacks.getNextBreakpoint = nullptr;
        syn68k_debugger_callbacks.debugger = nullptr;
    }
};

TEST_F(CPU, execute68K)
{
    EM_D0 = 0;

    m68k({
        0x4E71,  //  NOP
        0x303C,  //  MOVE.W ___, d0
        0x002A,  //         #42
        0x4E75   //  RTS
    });

    EXPECT_EQ(42, EM_D0);
}

TEST_F(CPU, executePPC)
{
    getPowerCore().r[3] = 0;
    ppc({
        0x60000000,  //  nop
        0x38600036,  //  li r3, 54
        0x3860002a,  //  li r4, 42
        0x4e800020   //  blr
    });

    EXPECT_EQ(42, getPowerCore().r[3]);
}

TEST_F(CPU, breakpoint68K)
{
    thread_local syn68k_addr_t stoppedD0;
    breakHit = 0;
    stoppedAddr = stoppedD0 = 0;

    syn68k_debugger_callbacks.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
        if(breakHit == 0 && addr <= BASE + 6)
            return BASE + 6;
        else
            return 0xFFFFFFFF;
    };
    syn68k_debugger_callbacks.debugger = [](syn68k_addr_t addr) -> syn68k_addr_t {
        breakHit++;
        stoppedAddr = addr;
        stoppedD0 = EM_D0;
        destroy_blocks(0, ~0);
        return addr;
    };

    EM_D0 = 0;
    m68k({
        0x4E71,  //  NOP
        0x303C,  //  MOVE.W ___, d0
        0x0036,  //         #54
        0x303C,  //  MOVE.W ___, d0
        0x002A,  //         #42
        0x4E75   //  RTS
    });

    EXPECT_EQ(42, EM_D0);
    EXPECT_EQ(1, breakHit);
    EXPECT_EQ(54, stoppedD0);
    EXPECT_EQ(BASE + 6, stoppedAddr);
}

TEST_F(CPU, breakpointPPC)
{
    auto& cpu = getPowerCore();
    cpu.r[3] = 0;

    thread_local int breakHit;
    thread_local syn68k_addr_t stoppedAddr, stoppedR3;
    breakHit = 0;
    stoppedAddr = stoppedR3 = 0;

    cpu.getNextBreakpoint = [](syn68k_addr_t addr) -> syn68k_addr_t {
        if(breakHit == 0 && addr <= BASE + 8)
            return BASE + 8;
        else
            return 0xFFFFFFFF;
    };
    cpu.debugger = [](PowerCore& cpu) {
        breakHit++;
        stoppedAddr = cpu.CIA;
        stoppedR3 = cpu.r[3];
        cpu.flushCache();
    };

    ppc({
        0x60000000,  //  nop
        0x38600036,  //  li r3, 54
        0x3860002a,  //  li r4, 42
        0x4e800020   //  blr
    });

    EXPECT_EQ(42, cpu.r[3]);
    EXPECT_EQ(1, breakHit);
    EXPECT_EQ(54, stoppedR3);
    EXPECT_EQ(BASE + 8, stoppedAddr);
}

TEST_F(CPUSingleStep, basic68K)
{
    m68k({
        0x702a,  //          moveq #42, %d0
        0x7215,  //          moveq #21, %d1
        0x4e75   //          rts
    });
    EXPECT_EQ(42, EM_D0);
    EXPECT_EQ(21, EM_D1);
    EXPECT_EQ(3, breakHit);
}

TEST_F(CPUSingleStep, braSinglestep68K)
{
    m68k({
        0x6002,  //         bra.s label
        0x4e71,  //         nop
        0x4e75   // label:  rts
    });
    EXPECT_EQ(2, breakHit);
}

TEST_F(CPUSingleStep, beqSinglestep68K)
{
    EM_D0 = 0;
    m68k({
        0x4a00,  //         tst.b %d0
        0x6702,  //         beq.s label
        0x4e71,  //         nop
        0x4e75   // label:  rts
    });
    EXPECT_EQ(3, breakHit);

    EM_D0 = 1;
    breakHit = 0;
    m68k();
    EXPECT_EQ(4, breakHit);
}

TEST_F(CPUSingleStep, fib68K)
{
    EM_D0 = 7;

    m68k({
        0x7200,  //         moveq #0, %d1
        0x7401,  //         moveq #1, %d2
        0x4a00,  // loop:   tst.b %d0
        0x6708,  //         beq.s end
        0xd282,  //         add.l %d2, %d1
        0xc541,  //         exg %d2, %d1
        0x5340,  //         subq #1, %d0
        0x60f4,  //         bra.s loop
        0x4e75   // end:    rts
    });

    EXPECT_EQ(13, EM_D1);
}
<|endoftext|>


<commit_before>#pragma once

#include <CorePCH.hpp>

#include "Engine.hpp"
#include "ComponentBase.hpp"
#include "Entity.hpp"
#include "World.hpp"

#include "TransformComponent.hpp"

#include "InputQueue.hpp"
#include "InputSystem.hpp"
#include "InputWorldComponent.hpp"
#include "KeyBindings.hpp"

#include "CameraComponent.hpp"
#include "MeshRenderingComponent.hpp"

#include "RenderingContext.hpp"

<commit_msg>Includes reordering.<commit_after>#pragma once

// Core
#include <CorePCH.hpp>

// Engine
#include "Engine.hpp"

// ECS
#include "ComponentBase.hpp"
#include "Entity.hpp"
#include "World.hpp"

// Rendering
#include "RenderingContext.hpp"

// Utils
#include "InputQueue.hpp"
#include "KeyBindings.hpp"

// Components
#include "TransformComponent.hpp"
#include "CameraComponent.hpp"
#include "MeshRenderingComponent.hpp"

// World Components
#include "InputWorldComponent.hpp"

// PLEASE DON'T INCLUDE SYSTEMS HERE!!!

<|endoftext|>


<commit_before>/*
Copyright (c) 2017 InversePalindrome
Memento Mori - SettingsState.cpp
InversePalindrome.com
*/

#include "SettingsState.hpp"
#include "StateMachine.hpp"

#include <SFGUI/Image.hpp>

SettingsState::SettingsState(StateMachine& stateMachine, SharedData& sharedData) :
	State(stateMachine, sharedData),
	background(sharedData.textures[Textures::ID::MainBackground]),
	controlCenter(sharedData.textures[Textures::ID::SettingsBackground]),
	backButton(sfg::Button::Create()),
	volumeLabel(sfg::Label::Create("Volume")),
	soundLabel(sfg::Label::Create("Sound")),
	musicLabel(sfg::Label::Create("Music")),
	soundSwitch(sfg::ToggleButton::Create()),
	musicSwitch(sfg::ToggleButton::Create()),
	moveUpButton(sfg::ToggleButton::Create()),
	moveDownButton(sfg::ToggleButton::Create()),
	moveRightButton(sfg::ToggleButton::Create()),
	moveLeftButton(sfg::ToggleButton::Create()),
	attackButton(sfg::ToggleButton::Create()),
	volumeBar(sfg::Scrollbar::Create()),
	volumeScale(sfg::Scale::Create(sfg::Scale::Orientation::VERTICAL)),
	volumeAdjustment(sfg::Adjustment::Create(sharedData.soundManager.getSoundProperties().volume, 0.f, 100.f, 1.f, 5.f, 2.5f)),
	actionKeys()
{
	background.setScale(static_cast<float>(sharedData.window.getSize().x) / background.getLocalBounds().width,
		static_cast<float>(sharedData.window.getSize().y) / background.getLocalBounds().height);

	controlCenter.setScale(1.1f, 1.1f);
	controlCenter.setPosition(690.f, 200.f);

	backButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::BackButton]));
	backButton->GetSignal(sfg::Widget::OnLeftClick).Connect([this] { transitionToMenu(); });

	soundLabel->SetPosition(sf::Vector2f(880.f, 725.f));

	soundSwitch->SetPosition(sf::Vector2f(1075.f, 750.f));
	soundSwitch->SetActive(sharedData.soundManager.isSoundEnabled());
	soundSwitch->GetSignal(sfg::Widget::OnLeftClick).Connect([this] { switchSounds(); });
	switchSounds();

	musicLabel->SetPosition(sf::Vector2f(1380.f, 725.f));

	musicSwitch->SetPosition(sf::Vector2f(1565.f, 750.f));
	musicSwitch->SetActive(sharedData.soundManager.isMusicEnabled());
	musicSwitch->GetSignal(sfg::Widget::OnLeftClick).Connect([this] { switchMusic(); });
	switchMusic();

	moveUpButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::MoveUp]));
	moveUpButton->SetPosition(sf::Vector2f(767.f, 500.f));

	moveDownButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::MoveDown]));
	moveDownButton->SetPosition(sf::Vector2f(967.f, 500.f));

	moveRightButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::MoveRight]));
	moveRightButton->SetPosition(sf::Vector2f(1167.f, 500.f));

	moveLeftButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::MoveLeft]));
	moveLeftButton->SetPosition(sf::Vector2f(1367.f, 500.f));

	attackButton->SetImage(sfg::Image::Create(sharedData.images[Images::ID::Attack]));
	attackButton->SetPosition(sf::Vector2f(1567.f, 500.f));

	volumeLabel->SetPosition(sf::Vector2f(1160.f, 922.f));

	volumeBar->SetRequisition(sf::Vector2f(1000.f, 75.f));
	volumeBar->SetPosition(sf::Vector2f(788.f, 850.f));
	volumeBar->SetAdjustment(volumeAdjustment);

	volumeScale->SetAdjustment(volumeAdjustment);

	volumeAdjustment->GetSignal(sfg::Adjustment::OnChange).Connect([this] { adjustVolume(); });

	actionKeys.emplace(ActionID::MoveUp, moveUpButton);
	actionKeys.emplace(ActionID::MoveDown, moveDownButton);
	actionKeys.emplace(ActionID::MoveRight, moveRightButton);
	actionKeys.emplace(ActionID::MoveLeft, moveLeftButton);
	actionKeys.emplace(ActionID::Attack, attackButton);

	sharedData.hud.SetProperty("Label", "FontSize", 80.f);
	sharedData.hud.SetProperty("Label", "FontName", "Resources/Fonts/WolfsBane.ttf");
	sharedData.hud.SetProperty("Label", "Color", sf::Color(14u, 208u, 78u, 255u));
	sharedData.hud.SetProperty("ToggleButton", "BackgroundColor", sf::Color::Transparent);
	sharedData.hud.SetProperty("ToggleButton", "BorderColor", sf::Color::Transparent);
	sharedData.hud.SetProperty("ToggleButton:PRELIGHT", "BackgroundColor", sf::Color::Transparent);
	sharedData.hud.SetProperty("Scrollbar", "BackgroundColor", sf::Color(14u, 208u, 78u, 255u));
	sharedData.hud.Add(backButton);
	sharedData.hud.Add(volumeLabel);
	sharedData.hud.Add(soundLabel);
	sharedData.hud.Add(musicLabel);
	sharedData.hud.Add(soundSwitch);
	sharedData.hud.Add(musicSwitch);
	sharedData.hud.Add(moveUpButton);
	sharedData.hud.Add(moveDownButton);
	sharedData.hud.Add(moveRightButton);
	sharedData.hud.Add(moveLeftButton);
	sharedData.hud.Add(attackButton);
	sharedData.hud.Add(volumeBar);
}

void SettingsState::handleEvent(const sf::Event& event)
{
	switch (event.type)
	{
	case sf::Event::KeyPressed:
		this->changeKey(event.key.code);
		break;
	}
}

void SettingsState::update(sf::Time deltaTime)
{
	this->backButton->Show(true);
}

void SettingsState::draw()
{
	this->sharedData.window.draw(this->background);
	this->sharedData.window.draw(this->controlCenter);
}

bool SettingsState::isTransparent()
{
	return false;
}

void SettingsState::switchSounds()
{
	if (this->soundSwitch->IsActive())
	{
		this->sharedData.soundManager.setSoundStatus(true);
		this->sharedData.soundManager.playAllSounds();

		soundSwitch->SetImage(sfg::Image::Create(sharedData.images[Images::ID::ToggleButtonOn]));
	}
	else
	{
		this->sharedData.soundManager.setSoundStatus(false);
		this->sharedData.soundManager.pauseAllSounds();

		soundSwitch->SetImage(sfg::Image::Create(sharedData.images[Images::ID::ToggleButtonOff]));
	}
}

void SettingsState::switchMusic()
{
	if (this->musicSwitch->IsActive())
	{
		this->sharedData.soundManager.setMusicStatus(true);
		this->sharedData.soundManager.playAllMusic();

		musicSwitch->SetImage(sfg::Image::Create(sharedData.images[Images::ID::ToggleButtonOn]));
	}
	else
	{
		this->sharedData.soundManager.setMusicStatus(false);
		this->sharedData.soundManager.pauseAllMusic();

		musicSwitch->SetImage(sfg::Image::Create(sharedData.images[Images::ID::ToggleButtonOff]));
	}
}

void SettingsState::adjustVolume()
{
	this->sharedData.soundManager.changeVolume(volumeScale->GetValue());
}

void SettingsState::changeKey(sf::Keyboard::Key key)
{
	for (auto& actionKey : this->actionKeys)
	{
		if (actionKey.second->IsActive())
		{
			this->sharedData.keyBindings.changeKey(actionKey.first, thor::Action(key));

			actionKey.second->SetActive(false);
		}
	}
}

void SettingsState::transitionToMenu()
{
	this->backButton->Show(false);
	this->volumeLabel->Show(false);
	this->soundLabel->Show(false);
	this->musicLabel->Show(false);
	this->soundSwitch->Show(false);
	this->musicSwitch->Show(false);
	this->moveUpButton->Show(false);
	this->moveDownButton->Show(false);
	this->moveRightButton->Show(false);
	this->moveLeftButton->Show(false);
	this->attackButton->Show(false);
	this->volumeBar->Show(false);

	this->stateMachine.popState();
}<commit_msg>Delete SettingsState.cpp<commit_after><|endoftext|>


<commit_before>#include "graph.h"
#include "offer.h"
#include "cert.h"
#include "alias.h"
#include "asset.h"
#include "assetallocation.h"
using namespace boost;
using namespace std;
typedef typename std::vector<int> container;
bool OrderBasedOnArrivalTime(std::vector<CTransactionRef>& blockVtx) {
	std::vector<vector<unsigned char> > vvchArgs;
	std::vector<vector<unsigned char> > vvchAliasArgs;
	std::vector<CTransactionRef> orderedVtx;
	int op;
	AssertLockHeld(cs_main);
	CCoinsViewCache view(pcoinsTip);
	// order the arrival times in ascending order using a map
	std::multimap<int64_t, int> orderedIndexes;
	for (unsigned int n = 0; n < blockVtx.size(); n++) {
		const CTransactionRef txRef = blockVtx[n];
		if (!txRef)
			continue;
		const CTransaction &tx = *txRef;
		if (tx.nVersion == SYSCOIN_TX_VERSION)
		{
			if (DecodeAssetAllocationTx(tx, op, vvchArgs))
			{
				if (!FindAliasInTx(view, tx, vvchAliasArgs)) {
					continue;
				}
				ArrivalTimesMap arrivalTimes;
				CAssetAllocation assetallocation(tx);
				CAssetAllocationTuple assetAllocationTuple(assetallocation.vchAsset, vvchAliasArgs[0]);
				passetallocationdb->ReadISArrivalTimes(assetAllocationTuple, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
			else if (DecodeOfferTx(tx, op, vvchArgs))
			{
				ArrivalTimesMap arrivalTimes;
				COffer offer(tx);
				pofferdb->ReadISArrivalTimes(offer.vchOffer, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
			else if (DecodeCertTx(tx, op, vvchArgs))
			{
				ArrivalTimesMap arrivalTimes;
				CCert cert(tx);
				pcertdb->ReadISArrivalTimes(cert.vchCert, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
		}
		// add normal tx's to orderedvtx,
		orderedVtx.emplace_back(txRef);
	}
	for (auto& orderedIndex : orderedIndexes) {
		orderedVtx.emplace_back(blockVtx[orderedIndex.second]);
	}
	if (blockVtx.size() != orderedVtx.size())
	{
		LogPrintf("OrderBasedOnArrivalTime: sorted block transaction count does not match unsorted block transaction count! sorted block count %d vs unsorted block count %d\n", orderedVtx.size(), blockVtx.size());
		return false;
	}
	blockVtx = orderedVtx;
	return true;
}
bool CreateGraphFromVTX(const std::vector<CTransactionRef>& blockVtx, Graph &graph, std::vector<vertex_descriptor> &vertices, IndexMap &mapTxIndex) {
	AliasMap mapAliasIndex;
	std::vector<vector<unsigned char> > vvchArgs;
	std::vector<vector<unsigned char> > vvchAliasArgs;
	int op;
	AssertLockHeld(cs_main);
	CCoinsViewCache view(pcoinsTip);
	for (unsigned int n = 0; n< blockVtx.size(); n++) {
		const CTransactionRef txRef = blockVtx[n];
		if (!txRef)
			continue;
		const CTransaction &tx = *txRef;
		if (tx.nVersion == SYSCOIN_TX_VERSION)
		{
			if (DecodeAssetAllocationTx(tx, op, vvchArgs))
			{

				if (!FindAliasInTx(view, tx, vvchAliasArgs)) {
					continue;
				}

				const string& sender = stringFromVch(vvchAliasArgs[0]);
				AliasMap::const_iterator it = mapAliasIndex.find(sender);
				if (it == mapAliasIndex.end()) {
					vertices.push_back(add_vertex(graph));
					mapAliasIndex[sender] = vertices.size() - 1;
				}
				mapTxIndex[mapAliasIndex[sender]].push_back(n);
				CAssetAllocation allocation(tx);
				if (!allocation.listSendingAllocationAmounts.empty()) {
					for (auto& allocationInstance : allocation.listSendingAllocationAmounts) {
						const string& receiver = stringFromVch(allocationInstance.first);
						AliasMap::const_iterator it = mapAliasIndex.find(receiver);
						if (it == mapAliasIndex.end()) {
							vertices.push_back(add_vertex(graph));
							mapAliasIndex[receiver] = vertices.size() - 1;
						}
						// the graph needs to be from index to index
						add_edge(vertices[mapAliasIndex[sender]], vertices[mapAliasIndex[receiver]], graph);
					}
				}
				else if (!allocation.listSendingAllocationInputs.empty()) {
					for (auto& allocationInstance : allocation.listSendingAllocationInputs) {
						const string& receiver = stringFromVch(allocationInstance.first);
						AliasMap::const_iterator it = mapAliasIndex.find(receiver);
						if (it == mapAliasIndex.end()) {
							vertices.push_back(add_vertex(graph));
							mapAliasIndex[receiver] = vertices.size() - 1;
						}
						// the graph needs to be from index to index
						add_edge(vertices[mapAliasIndex[sender]], vertices[mapAliasIndex[receiver]], graph);
					}
				}
			}
		}
	}
	return mapTxIndex.size() > 0;
}
// remove cycles in a graph and create a DAG, modify the blockVtx passed in to remove conflicts, the conflicts should be added back to the end of this vtx after toposort
void GraphRemoveCycles(const std::vector<CTransactionRef>& blockVtx, std::vector<int> &conflictedIndexes, Graph& graph, const std::vector<vertex_descriptor> &vertices, IndexMap &mapTxIndex) {
	sorted_vector<int> clearedVertices;
	cycle_visitor<sorted_vector<int> > visitor(clearedVertices);
	hawick_circuits(graph, visitor);
	for (auto& nVertex : clearedVertices) {
		IndexMap::const_iterator it = mapTxIndex.find(nVertex);
		if (it == mapTxIndex.end())
			continue;
		// remove from graph
		const int nVertexIndex = (*it).first;
		if (nVertexIndex >= vertices.size())
			continue;
		boost::clear_out_edges(vertices[nVertexIndex], graph);
		const std::vector<int> &vecTx = (*it).second;
		// mapTxIndex knows of the mapping between vertices and tx vout positions
		for (auto& nIndex : vecTx) {
			if (nIndex >= blockVtx.size())
				continue;
			conflictedIndexes.push_back(nIndex);
		}
		mapTxIndex.erase(it);
	}
	// block gives us the transactions in order by time so we want to ensure we preserve it
	std::sort(conflictedIndexes.begin(), conflictedIndexes.end());
}
bool DAGTopologicalSort(std::vector<CTransactionRef>& blockVtx, const std::vector<int> &conflictedIndexes, const Graph& graph, const IndexMap &mapTxIndex) {
	std::vector<CTransactionRef> newVtx;
	container c;
	try
	{
		topological_sort(graph, std::back_inserter(c));
	}
	catch (not_a_dag const& e){
		LogPrintf("DAGTopologicalSort: Not a DAG: %s\n", e.what());
		return false;
	}
	// add coinbase
	newVtx.emplace_back(blockVtx[0]);

	// add sys tx's to newVtx in reverse sorted order
	reverse(c.begin(), c.end());
	for (auto& nVertex : c) {
		// this may not find the vertex if its a receiver (we only want to process sender as tx is tied to sender)
		IndexMap::const_iterator it = mapTxIndex.find(nVertex);
		if (it == mapTxIndex.end())
			continue;
		const std::vector<int> &vecTx = (*it).second;
		// mapTxIndex knows of the mapping between vertices and tx index positions
		for (auto& nIndex : vecTx) {
			if (nIndex >= blockVtx.size())
				continue;
			newVtx.emplace_back(blockVtx[nIndex]);
		}
	}

	// add conflicting indexes next (should already be in order)
	for (auto& nIndex : conflictedIndexes) {
		if (nIndex >= blockVtx.size())
			continue;
		newVtx.emplace_back(blockVtx[nIndex]);
	}

	// add non-sys and other sys tx's to end of newVtx
	std::vector<vector<unsigned char> > vvchArgs;
	int op;
	for (unsigned int vOut = 1; vOut< blockVtx.size(); vOut++) {
		const CTransactionRef& txRef = blockVtx[vOut];
		const CTransaction& tx = *txRef;
		if (!DecodeAssetAllocationTx(tx, op, vvchArgs))
		{
			newVtx.emplace_back(txRef);
		}
	}
	if (blockVtx.size() != newVtx.size())
	{
		LogPrintf("DAGTopologicalSort: sorted block transaction count does not match unsorted block transaction count!\n");
		return false;
	}
	// set newVtx to block's vtx so block can process as normal
	blockVtx = newVtx;
	return true;
}<commit_msg>compile<commit_after>#include "graph.h"
#include "offer.h"
#include "cert.h"
#include "alias.h"
#include "asset.h"
#include "assetallocation.h"
#include "validation.h"
using namespace boost;
using namespace std;
typedef typename std::vector<int> container;
bool OrderBasedOnArrivalTime(std::vector<CTransactionRef>& blockVtx) {
	std::vector<vector<unsigned char> > vvchArgs;
	std::vector<vector<unsigned char> > vvchAliasArgs;
	std::vector<CTransactionRef> orderedVtx;
	int op;
	AssertLockHeld(cs_main);
	CCoinsViewCache view(pcoinsTip);
	// order the arrival times in ascending order using a map
	std::multimap<int64_t, int> orderedIndexes;
	for (unsigned int n = 0; n < blockVtx.size(); n++) {
		const CTransactionRef txRef = blockVtx[n];
		if (!txRef)
			continue;
		const CTransaction &tx = *txRef;
		if (tx.nVersion == SYSCOIN_TX_VERSION)
		{
			if (DecodeAssetAllocationTx(tx, op, vvchArgs))
			{
				if (!FindAliasInTx(view, tx, vvchAliasArgs)) {
					continue;
				}
				ArrivalTimesMap arrivalTimes;
				CAssetAllocation assetallocation(tx);
				CAssetAllocationTuple assetAllocationTuple(assetallocation.vchAsset, vvchAliasArgs[0]);
				passetallocationdb->ReadISArrivalTimes(assetAllocationTuple, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
			else if (DecodeOfferTx(tx, op, vvchArgs))
			{
				ArrivalTimesMap arrivalTimes;
				COffer offer(tx);
				pofferdb->ReadISArrivalTimes(offer.vchOffer, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
			else if (DecodeCertTx(tx, op, vvchArgs))
			{
				ArrivalTimesMap arrivalTimes;
				CCert cert(tx);
				pcertdb->ReadISArrivalTimes(cert.vchCert, arrivalTimes);
				ArrivalTimesMap::iterator it = arrivalTimes.find(tx.GetHash());
				if (it != arrivalTimes.end())
					orderedIndexes.insert(make_pair((*it).second, n));
				// we don't have this in our arrival times list, means it must be rejected via consensus so add it to the end
				else
					orderedIndexes.insert(make_pair(INT64_MAX, n));
				continue;
			}
		}
		// add normal tx's to orderedvtx,
		orderedVtx.emplace_back(txRef);
	}
	for (auto& orderedIndex : orderedIndexes) {
		orderedVtx.emplace_back(blockVtx[orderedIndex.second]);
	}
	if (blockVtx.size() != orderedVtx.size())
	{
		LogPrintf("OrderBasedOnArrivalTime: sorted block transaction count does not match unsorted block transaction count! sorted block count %d vs unsorted block count %d\n", orderedVtx.size(), blockVtx.size());
		return false;
	}
	blockVtx = orderedVtx;
	return true;
}
bool CreateGraphFromVTX(const std::vector<CTransactionRef>& blockVtx, Graph &graph, std::vector<vertex_descriptor> &vertices, IndexMap &mapTxIndex) {
	AliasMap mapAliasIndex;
	std::vector<vector<unsigned char> > vvchArgs;
	std::vector<vector<unsigned char> > vvchAliasArgs;
	int op;
	AssertLockHeld(cs_main);
	CCoinsViewCache view(pcoinsTip);
	for (unsigned int n = 0; n< blockVtx.size(); n++) {
		const CTransactionRef txRef = blockVtx[n];
		if (!txRef)
			continue;
		const CTransaction &tx = *txRef;
		if (tx.nVersion == SYSCOIN_TX_VERSION)
		{
			if (DecodeAssetAllocationTx(tx, op, vvchArgs))
			{

				if (!FindAliasInTx(view, tx, vvchAliasArgs)) {
					continue;
				}

				const string& sender = stringFromVch(vvchAliasArgs[0]);
				AliasMap::const_iterator it = mapAliasIndex.find(sender);
				if (it == mapAliasIndex.end()) {
					vertices.push_back(add_vertex(graph));
					mapAliasIndex[sender] = vertices.size() - 1;
				}
				mapTxIndex[mapAliasIndex[sender]].push_back(n);
				CAssetAllocation allocation(tx);
				if (!allocation.listSendingAllocationAmounts.empty()) {
					for (auto& allocationInstance : allocation.listSendingAllocationAmounts) {
						const string& receiver = stringFromVch(allocationInstance.first);
						AliasMap::const_iterator it = mapAliasIndex.find(receiver);
						if (it == mapAliasIndex.end()) {
							vertices.push_back(add_vertex(graph));
							mapAliasIndex[receiver] = vertices.size() - 1;
						}
						// the graph needs to be from index to index
						add_edge(vertices[mapAliasIndex[sender]], vertices[mapAliasIndex[receiver]], graph);
					}
				}
				else if (!allocation.listSendingAllocationInputs.empty()) {
					for (auto& allocationInstance : allocation.listSendingAllocationInputs) {
						const string& receiver = stringFromVch(allocationInstance.first);
						AliasMap::const_iterator it = mapAliasIndex.find(receiver);
						if (it == mapAliasIndex.end()) {
							vertices.push_back(add_vertex(graph));
							mapAliasIndex[receiver] = vertices.size() - 1;
						}
						// the graph needs to be from index to index
						add_edge(vertices[mapAliasIndex[sender]], vertices[mapAliasIndex[receiver]], graph);
					}
				}
			}
		}
	}
	return mapTxIndex.size() > 0;
}
// remove cycles in a graph and create a DAG, modify the blockVtx passed in to remove conflicts, the conflicts should be added back to the end of this vtx after toposort
void GraphRemoveCycles(const std::vector<CTransactionRef>& blockVtx, std::vector<int> &conflictedIndexes, Graph& graph, const std::vector<vertex_descriptor> &vertices, IndexMap &mapTxIndex) {
	sorted_vector<int> clearedVertices;
	cycle_visitor<sorted_vector<int> > visitor(clearedVertices);
	hawick_circuits(graph, visitor);
	for (auto& nVertex : clearedVertices) {
		IndexMap::const_iterator it = mapTxIndex.find(nVertex);
		if (it == mapTxIndex.end())
			continue;
		// remove from graph
		const int nVertexIndex = (*it).first;
		if (nVertexIndex >= vertices.size())
			continue;
		boost::clear_out_edges(vertices[nVertexIndex], graph);
		const std::vector<int> &vecTx = (*it).second;
		// mapTxIndex knows of the mapping between vertices and tx vout positions
		for (auto& nIndex : vecTx) {
			if (nIndex >= blockVtx.size())
				continue;
			conflictedIndexes.push_back(nIndex);
		}
		mapTxIndex.erase(it);
	}
	// block gives us the transactions in order by time so we want to ensure we preserve it
	std::sort(conflictedIndexes.begin(), conflictedIndexes.end());
}
bool DAGTopologicalSort(std::vector<CTransactionRef>& blockVtx, const std::vector<int> &conflictedIndexes, const Graph& graph, const IndexMap &mapTxIndex) {
	std::vector<CTransactionRef> newVtx;
	container c;
	try
	{
		topological_sort(graph, std::back_inserter(c));
	}
	catch (not_a_dag const& e){
		LogPrintf("DAGTopologicalSort: Not a DAG: %s\n", e.what());
		return false;
	}
	// add coinbase
	newVtx.emplace_back(blockVtx[0]);

	// add sys tx's to newVtx in reverse sorted order
	reverse(c.begin(), c.end());
	for (auto& nVertex : c) {
		// this may not find the vertex if its a receiver (we only want to process sender as tx is tied to sender)
		IndexMap::const_iterator it = mapTxIndex.find(nVertex);
		if (it == mapTxIndex.end())
			continue;
		const std::vector<int> &vecTx = (*it).second;
		// mapTxIndex knows of the mapping between vertices and tx index positions
		for (auto& nIndex : vecTx) {
			if (nIndex >= blockVtx.size())
				continue;
			newVtx.emplace_back(blockVtx[nIndex]);
		}
	}

	// add conflicting indexes next (should already be in order)
	for (auto& nIndex : conflictedIndexes) {
		if (nIndex >= blockVtx.size())
			continue;
		newVtx.emplace_back(blockVtx[nIndex]);
	}

	// add non-sys and other sys tx's to end of newVtx
	std::vector<vector<unsigned char> > vvchArgs;
	int op;
	for (unsigned int vOut = 1; vOut< blockVtx.size(); vOut++) {
		const CTransactionRef& txRef = blockVtx[vOut];
		const CTransaction& tx = *txRef;
		if (!DecodeAssetAllocationTx(tx, op, vvchArgs))
		{
			newVtx.emplace_back(txRef);
		}
	}
	if (blockVtx.size() != newVtx.size())
	{
		LogPrintf("DAGTopologicalSort: sorted block transaction count does not match unsorted block transaction count!\n");
		return false;
	}
	// set newVtx to block's vtx so block can process as normal
	blockVtx = newVtx;
	return true;
}<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_engine/test/auto_test/primitives/choice_helpers.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <algorithm>

namespace webrtc {

ChoiceBuilder::ChoiceBuilder(const std::string& title, const Choices& choices)
    : choices_(choices),
      input_helper_(TypedInput(title)) {
  input_helper_.WithInputValidator(
      new IntegerWithinRangeValidator(1, choices.size()));
  input_helper_.WithAdditionalInfo(MakeHumanReadableOptions());
}

int ChoiceBuilder::Choose() {
  std::string input = input_helper_.AskForInput();
  return atoi(input.c_str());
}

ChoiceBuilder& ChoiceBuilder::WithDefault(const std::string& default_choice) {
  Choices::const_iterator iterator = std::find(
      choices_.begin(), choices_.end(), default_choice);
  assert(iterator != choices_.end() && "No such choice.");

  // Store the value as the choice number, e.g. its index + 1.
  int choice_index = (iterator - choices_.begin()) + 1;
  char number[16];
  sprintf(number, "%d", choice_index);

  input_helper_.WithDefault(number);
  return *this;
}

ChoiceBuilder& ChoiceBuilder::WithInputSource(FILE* input_source) {
  input_helper_.WithInputSource(input_source);
  return *this;
}

std::string ChoiceBuilder::MakeHumanReadableOptions() {
  std::string result = "";
  Choices::const_iterator iterator = choices_.begin();
  for (int number = 1; iterator != choices_.end(); ++iterator, ++number) {
    char buffer[128];
    sprintf(buffer, "\n  %d. %s", number, (*iterator).c_str());
    result += buffer;
  }
  return result;
}

Choices SplitChoices(const std::string& raw_choices) {
  return Split(raw_choices, "\n");
}

ChoiceBuilder FromChoices(
    const std::string& title, const std::string& raw_choices) {
  return ChoiceBuilder(title, SplitChoices(raw_choices));
}

}  // namespace webrtc
<commit_msg>Fix for buffer overflow, WebRTC issue 1196 Review URL: https://webrtc-codereview.appspot.com/998004<commit_after>/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "video_engine/test/auto_test/primitives/choice_helpers.h"

#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <sstream>

namespace webrtc {

ChoiceBuilder::ChoiceBuilder(const std::string& title, const Choices& choices)
    : choices_(choices),
      input_helper_(TypedInput(title)) {
  input_helper_.WithInputValidator(
      new IntegerWithinRangeValidator(1, choices.size()));
  input_helper_.WithAdditionalInfo(MakeHumanReadableOptions());
}

int ChoiceBuilder::Choose() {
  std::string input = input_helper_.AskForInput();
  return atoi(input.c_str());
}

ChoiceBuilder& ChoiceBuilder::WithDefault(const std::string& default_choice) {
  Choices::const_iterator iterator = std::find(
      choices_.begin(), choices_.end(), default_choice);
  assert(iterator != choices_.end() && "No such choice.");

  // Store the value as the choice number, e.g. its index + 1.
  int choice_index = (iterator - choices_.begin()) + 1;
  char number[16];
  sprintf(number, "%d", choice_index);

  input_helper_.WithDefault(number);
  return *this;
}

ChoiceBuilder& ChoiceBuilder::WithInputSource(FILE* input_source) {
  input_helper_.WithInputSource(input_source);
  return *this;
}

std::string ChoiceBuilder::MakeHumanReadableOptions() {
  std::string result = "";
  Choices::const_iterator iterator = choices_.begin();
  for (int number = 1; iterator != choices_.end(); ++iterator, ++number) {
    std::ostringstream os;
    os << "\n  " << number << ". " << (*iterator).c_str();
    result += os.str();
  }
  return result;
}

Choices SplitChoices(const std::string& raw_choices) {
  return Split(raw_choices, "\n");
}

ChoiceBuilder FromChoices(
    const std::string& title, const std::string& raw_choices) {
  return ChoiceBuilder(title, SplitChoices(raw_choices));
}

}  // namespace webrtc
<|endoftext|>