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

 Program:   openCherry Platform
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

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

#include "cherryDetachedWindow.h"

#include "../cherryIWorkbenchPartConstants.h"
#include "../cherryISaveablePart.h"

#include "../cherryWorkbenchWindow.h"

#include "../tweaklets/cherryGuiWidgetsTweaklet.h"

#include "cherryWorkbenchConstants.h"
#include "cherryEditorManager.h"
#include "cherryDragUtil.h"

namespace cherry
{

DetachedWindow::ShellListener::ShellListener(DetachedWindow* wnd) :
  window(wnd)
{

}

void DetachedWindow::ShellListener::ShellClosed(ShellEvent::Pointer e)
{
  // only continue to close if the handleClose
  // wasn't canceled
  e->doit = window->HandleClose();
}

DetachedWindow::ShellControlListener::ShellControlListener(DetachedWindow* wnd) :
  window(wnd)
{

}

GuiTk::IControlListener::Events::Types DetachedWindow::ShellControlListener::GetEventTypes() const
{
  return Events::RESIZED;
}

void DetachedWindow::ShellControlListener::ControlResized(
    GuiTk::ControlEvent::Pointer e)
{
  window->folder->SetBounds(
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(e->item));
}

DetachedWindow::DetachedWindow(WorkbenchPage::Pointer workbenchPage)
{
  shellListener = new ShellListener(this);
  resizeListener = new ShellControlListener(this);

  this->page = workbenchPage;
  hideViewsOnClose = true;

  folder = new PartStack(page, false);
}

void DetachedWindow::PropertyChange(Object::Pointer /*source*/, int propId)
{
  if (propId == IWorkbenchPartConstants::PROP_TITLE)
  {
    this->UpdateTitle();
  }
  else if (propId == PartStack::PROP_SELECTION)
  {
    this->ActivePartChanged(this->GetPartReference(folder->GetSelection()));
  }
}

Shell::Pointer DetachedWindow::GetShell()
{
  return windowShell;
}

void DetachedWindow::Create()
{
  folder->AddListener(IPropertyChangeListener::Pointer(this));

  windowShell
      = page->GetWorkbenchWindow().Cast<WorkbenchWindow> () ->GetDetachedWindowPool()->AllocateShell(
          shellListener);
  windowShell->SetData(Object::Pointer(this));
  windowShell->SetText(""); //$NON-NLS-1$

  DragUtil::AddDragTarget(windowShell->GetControl(),
      IDragOverListener::Pointer(this));
  hideViewsOnClose = true;
  if (bounds.IsEmpty())
  {
    Rectangle windowRect = page->GetWorkbenchWindow()->GetShell()->GetBounds();
    Point center(windowRect.x + windowRect.width / 2, windowRect.y
        - windowRect.height / 2);
    bounds = Rectangle(center.x - 150, center.y + 100, 300, 200);
  }

  // Force the rect into the current display
  Rectangle dispBounds =
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetScreenSize();
  if (bounds.width > dispBounds.width)
    bounds.width = dispBounds.width;
  if (bounds.height > dispBounds.height)
    bounds.height = dispBounds.height;
  if (bounds.x + bounds.width > dispBounds.width)
    bounds.x = dispBounds.width - bounds.width;
  if (bounds.y + bounds.height > dispBounds.height)
    bounds.y = dispBounds.height - bounds.height;

  this->GetShell()->SetBounds(bounds);

  this->ConfigureShell(windowShell);

  this->CreateContents(windowShell->GetControl());
  //windowShell->Layout(true);
  //folder->SetBounds(Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(windowShell->GetControl()));
}

void DetachedWindow::Add(StackablePart::Pointer part)
{

  Shell::Pointer shell = this->GetShell();
  if (shell != 0)
  {
    part->Reparent(shell->GetControl());
  }
  folder->Add(part);
  this->UpdateMinimumSize();
}

bool DetachedWindow::BelongsToWorkbenchPage(
    IWorkbenchPage::Pointer workbenchPage)
{
  return (this->page == workbenchPage);
}

bool DetachedWindow::Close()
{
  hideViewsOnClose = false;
  Shell::Pointer shell = this->GetShell();
  if (shell != 0)
  {
    shell->Close();
  }
  return true;
}

IDropTarget::Pointer DetachedWindow::Drag(void* /*currentControl*/,
    Object::Pointer draggedObject, const Point& position, const Rectangle& /*dragRectangle*/)
{

  if (draggedObject.Cast<PartPane> () == 0)
  {
    return IDropTarget::Pointer(0);
  }

  PartPane::Pointer sourcePart = draggedObject.Cast<PartPane> ();

  if (sourcePart->GetWorkbenchWindow() != page->GetWorkbenchWindow())
  {
    return IDropTarget::Pointer(0);
  }

  // Only handle the event if the source part is acceptable to the particular PartStack
  IDropTarget::Pointer target;
  if (folder->AllowsDrop(sourcePart))
  {
    target = folder->GetDropTarget(draggedObject, position);

    if (target == 0)
    {
      Rectangle displayBounds =
          DragUtil::GetDisplayBounds(folder->GetControl());
      if (displayBounds.Contains(position))
      {
        StackDropResult::Pointer stackDropResult(new StackDropResult(
            displayBounds, Object::Pointer(0)));
        target = folder->CreateDropTarget(sourcePart, stackDropResult);
      }
      else
      {
        return IDropTarget::Pointer(0);
      }
    }
  }

  return target;
}

IStackableContainer::ChildrenType DetachedWindow::GetChildren() const
{
  return folder->GetChildren();
}

WorkbenchPage::Pointer DetachedWindow::GetWorkbenchPage()
{
  return this->page;
}

void DetachedWindow::RestoreState(IMemento::Pointer memento)
{
  // Read the bounds.
  int x = 0;
  memento->GetInteger(WorkbenchConstants::TAG_X, x);
  int y = 0;
  memento->GetInteger(WorkbenchConstants::TAG_Y, y);
  int width = 0;
  memento->GetInteger(WorkbenchConstants::TAG_WIDTH, width);
  int height = 0;
  memento->GetInteger(WorkbenchConstants::TAG_HEIGHT, height);

  // memento->GetInteger(WorkbenchConstants::TAG_FLOAT);

  // Set the bounds.
  bounds = Rectangle(x, y, width, height);
  if (GetShell())
  {
    GetShell()->SetBounds(bounds);
  }

  // Create the folder.
  IMemento::Pointer childMem =
      memento->GetChild(WorkbenchConstants::TAG_FOLDER);
  if (childMem)
  {
    folder->RestoreState(childMem);
  }
}

void DetachedWindow::SaveState(IMemento::Pointer memento)
{
  if (GetShell())
  {
    bounds = GetShell()->GetBounds();
  }

  // Save the bounds.
  memento->PutInteger(WorkbenchConstants::TAG_X, bounds.x);
  memento->PutInteger(WorkbenchConstants::TAG_Y, bounds.y);
  memento->PutInteger(WorkbenchConstants::TAG_WIDTH, bounds.width);
  memento->PutInteger(WorkbenchConstants::TAG_HEIGHT, bounds.height);

  // Save the views.
  IMemento::Pointer childMem = memento->CreateChild(
      WorkbenchConstants::TAG_FOLDER);
  folder->SaveState(childMem);
}

void* DetachedWindow::GetControl()
{
  return folder->GetControl();
}

int DetachedWindow::Open()
{

  if (this->GetShell() == 0)
  {
    this->Create();
  }

  Rectangle bounds = this->GetShell()->GetBounds();

  if (!(bounds == this->GetShell()->GetBounds()))
  {
    this->GetShell()->SetBounds(bounds);
  }

  this->GetShell()->SetVisible(true);

  folder->SetBounds(Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(this->GetShell()->GetControl()));

  return 0;
}

void DetachedWindow::ActivePartChanged(
    IWorkbenchPartReference::Pointer partReference)
{
  if (activePart == partReference)
  {
    return;
  }

  if (activePart != 0)
  {
    activePart->RemovePropertyListener(IPropertyChangeListener::Pointer(this));
  }
  activePart = partReference;
  if (partReference != 0)
  {
    partReference->AddPropertyListener(IPropertyChangeListener::Pointer(this));
  }
  this->UpdateTitle();
}

void DetachedWindow::ConfigureShell(Shell::Pointer shell)
{
  this->UpdateTitle();

  Tweaklets::Get(GuiWidgetsTweaklet::KEY)->AddControlListener(
      shell->GetControl(), resizeListener);
  //shell.addListener(SWT.Activate, activationListener);
  //shell.addListener(SWT.Deactivate, activationListener);

  //TODO DetachedWindow key bindings
  //  // Register this detached view as a window (for key bindings).
  //  IContextService contextService = (IContextService) getWorkbenchPage()
  //  .getWorkbenchWindow().getWorkbench().getService(IContextService.class);
  //  contextService.registerShell(shell, IContextService.TYPE_WINDOW);
  //
  //  page.getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(shell,
  //      IWorkbenchHelpContextIds.DETACHED_WINDOW);
}

void* DetachedWindow::CreateContents(void* parent)
{
  // Create the tab folder.
  folder->CreateControl(parent);

  // Reparent each view in the tab folder.
  std::list<PartPane::Pointer> detachedChildren;
  this->CollectViewPanes(detachedChildren, this->GetChildren());
  for (std::list<PartPane::Pointer>::iterator itr = detachedChildren.begin(); itr
      != detachedChildren.end(); ++itr)
  {
    PartPane::Pointer part = *itr;
    part->Reparent(parent);
  }

  //TODO DetachedWindow listen to folder events (update size?)
  //  if (folder->GetPresentation()
  //    instanceof TabbedStackPresentation)
  //    {
  //      TabbedStackPresentation stack = (TabbedStackPresentation) folder.getPresentation();
  //      AbstractTabFolder tabFolder = stack.getTabFolder();
  //      tabFolder.addListener(new TabFolderListener()
  //      {
  //      public void handleEvent(TabFolderEvent e)
  //        {
  //          switch (e.type)
  //          {
  //            case TabFolderEvent.EVENT_CLOSE:
  //            {
  //              updateMinimumSize();
  //              break;
  //            }
  //            case TabFolderEvent.EVENT_PREFERRED_SIZE:
  //            {
  //              updateMinimumSize();
  //              break;
  //            }
  //          }
  //        }
  //      });
  //    }

  // Return tab folder control.
  return folder->GetControl();
}

void DetachedWindow::UpdateTitle()
{
  if (activePart != 0)
  {
    // Uncomment to set the shell title to match the title of the active part
    //            String text = activePart.getTitle();
    //
    //            if (!text.equals(s.getText())) {
    //                s.setText(text);
    //            }
  }
}

void DetachedWindow::UpdateMinimumSize()
{
  //  // We can only do this for 'Tabbed' stacked presentations.
  //  if (folder.getPresentation().Cast<TabbedStackPresentation>() != 0)
  //  {
  //    TabbedStackPresentation stack = (TabbedStackPresentation) folder.getPresentation();
  //
  //    if (stack->GetPartList().size() == 1)
  //    {
  //      // Get the minimum space required for the part
  //      int width = stack->ComputePreferredSize(true, Constants::INF, Constants::INF, 0);
  //      int height = stack->ComputePreferredSize(false, Constants::INF, Constants::INF, 0);
  //
  //      // Take the current shell 'trim' into account
  //      int shellHeight = windowShell->GetBounds().height - windowShell->GetClientArea().height;
  //      int shellWidth = windowShell->GetBounds().width - windowShell->GetClientArea().width;
  //
  //      windowShell->SetMinimumSize(width + shellWidth, height + shellHeight);
  //    }
  //  }
}

IWorkbenchPartReference::Pointer DetachedWindow::GetPartReference(
    StackablePart::Pointer pane)
{

  if (pane == 0 || pane.Cast<PartPane> () == 0)
  {
    return IWorkbenchPartReference::Pointer(0);
  }

  return pane.Cast<PartPane> ()->GetPartReference();
}

bool DetachedWindow::HandleClose()
{

  if (hideViewsOnClose)
  {
    std::list<PartPane::Pointer> views;
    this->CollectViewPanes(views, this->GetChildren());

    // Save any drty views
    if (!this->HandleSaves(views))
    {
      return false; // User canceled the save
    }

    // OK, go on with the closing
    for (std::list<PartPane::Pointer>::iterator itr = views.begin(); itr
        != views.end(); ++itr)
    {
      PartPane::Pointer child = *itr;

      // Only close if closable...
      if (child->IsCloseable())
      {
        page->HideView(child->GetPartReference().Cast<IViewReference> ());

        // Was the close cancelled?
        if (child->GetContainer() != 0)
          return false;
      }
      else
      {
        page->AttachView(child->GetPartReference().Cast<IViewReference> ());
      }
    }
  }

  if (folder != 0)
  {
    folder->Dispose();
  }

  if (windowShell != 0)
  {
    Tweaklets::Get(GuiWidgetsTweaklet::KEY)->RemoveControlListener(
        windowShell->GetControl(), resizeListener);
    //    windowShell.removeListener(SWT.Activate, activationListener);
    //    windowShell.removeListener(SWT.Deactivate, activationListener);

    DragUtil::RemoveDragTarget(windowShell->GetControl(),
        IDragOverListener::Pointer(this));
    bounds = windowShell->GetBounds();

    //TODO DetachedWindow unregister key bindings
    //    // Unregister this detached view as a window (for key bindings).
    //    final IContextService contextService = (IContextService) getWorkbenchPage().getWorkbenchWindow().getWorkbench().getService(IContextService.class);
    //    contextService.unregisterShell(windowShell);

    windowShell->SetData(Object::Pointer(0));
    windowShell = 0;
  }

  return true;
}

bool DetachedWindow::HandleSaves(std::list<PartPane::Pointer> views)
{
  std::vector<IWorkbenchPart::Pointer> dirtyViews;
  for (std::list<PartPane::Pointer>::iterator iterator = views.begin(); iterator
      != views.end(); ++iterator)
  {
    PartPane::Pointer pane = *iterator;
    IViewReference::Pointer ref =
        pane->GetPartReference().Cast<IViewReference> ();
    IViewPart::Pointer part = ref->GetView(false);
    if (part.Cast<ISaveablePart> () != 0)
    {
      ISaveablePart::Pointer saveable = part.Cast<ISaveablePart> ();
      if (saveable->IsDirty() && saveable->IsSaveOnCloseNeeded())
      {
        dirtyViews.push_back(part);
      }
    }
  }

  // If there are any prompt to save -before- any closing happens
  // FIXME: This code will result in a double prompt if the user
  // decides not to save a particular view at this stage they'll
  // get a second one from the 'hideView' call...
  if (dirtyViews.size() > 0)
  {
    IWorkbenchWindow::Pointer window = page->GetWorkbenchWindow();
    bool success =
        EditorManager::SaveAll(dirtyViews, true, true, false, window);
    if (!success)
    {
      return false; // the user canceled.
    }
  }

  return true;
}

void DetachedWindow::CollectViewPanes(std::list<PartPane::Pointer>& result,
    const std::list<StackablePart::Pointer>& parts)
{
  for (std::list<StackablePart::Pointer>::const_iterator iter = parts.begin(); iter
      != parts.end(); ++iter)
  {
    StackablePart::Pointer part = *iter;
    if (part.Cast<PartPane> () != 0)
    {
      result.push_back(part.Cast<PartPane> ());
    }
  }
}

}
<commit_msg>FIX (#2031): added a temporary smartpointer which holds the detachted window alive as long as necessary<commit_after>/*=========================================================================

 Program:   openCherry Platform
 Language:  C++
 Date:      $Date$
 Version:   $Revision$

 Copyright (c) German Cancer Research Center, Division of Medical and
 Biological Informatics. All rights reserved.
 See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

 This software is distributed WITHOUT ANY WARRANTY; without even
 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
 PURPOSE.  See the above copyright notices for more information.

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

#include "cherryDetachedWindow.h"

#include "../cherryIWorkbenchPartConstants.h"
#include "../cherryISaveablePart.h"

#include "../cherryWorkbenchWindow.h"

#include "../tweaklets/cherryGuiWidgetsTweaklet.h"

#include "cherryWorkbenchConstants.h"
#include "cherryEditorManager.h"
#include "cherryDragUtil.h"

namespace cherry
{

DetachedWindow::ShellListener::ShellListener(DetachedWindow* wnd) :
  window(wnd)
{

}

void DetachedWindow::ShellListener::ShellClosed(ShellEvent::Pointer e)
{
  // hold on to a reference of the DetachedWindow instance
  // (otherwise, wnd->HandleClose() woulde delete the DetachedWindow
  // instance too early, trying to write to members afterwards)
  DetachedWindow::Pointer wnd(window);

  // only continue to close if the handleClose
  // wasn't canceled
  e->doit = wnd->HandleClose();
}

DetachedWindow::ShellControlListener::ShellControlListener(DetachedWindow* wnd) :
  window(wnd)
{

}

GuiTk::IControlListener::Events::Types DetachedWindow::ShellControlListener::GetEventTypes() const
{
  return Events::RESIZED;
}

void DetachedWindow::ShellControlListener::ControlResized(
    GuiTk::ControlEvent::Pointer e)
{
  window->folder->SetBounds(
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(e->item));
}

DetachedWindow::DetachedWindow(WorkbenchPage::Pointer workbenchPage)
{
  shellListener = new ShellListener(this);
  resizeListener = new ShellControlListener(this);

  this->page = workbenchPage;
  hideViewsOnClose = true;

  folder = new PartStack(page, false);
}

void DetachedWindow::PropertyChange(Object::Pointer /*source*/, int propId)
{
  if (propId == IWorkbenchPartConstants::PROP_TITLE)
  {
    this->UpdateTitle();
  }
  else if (propId == PartStack::PROP_SELECTION)
  {
    this->ActivePartChanged(this->GetPartReference(folder->GetSelection()));
  }
}

Shell::Pointer DetachedWindow::GetShell()
{
  return windowShell;
}

void DetachedWindow::Create()
{
  folder->AddListener(IPropertyChangeListener::Pointer(this));

  windowShell
      = page->GetWorkbenchWindow().Cast<WorkbenchWindow> () ->GetDetachedWindowPool()->AllocateShell(
          shellListener);
  windowShell->SetData(Object::Pointer(this));
  windowShell->SetText(""); //$NON-NLS-1$

  DragUtil::AddDragTarget(windowShell->GetControl(),
      IDragOverListener::Pointer(this));
  hideViewsOnClose = true;
  if (bounds.IsEmpty())
  {
    Rectangle windowRect = page->GetWorkbenchWindow()->GetShell()->GetBounds();
    Point center(windowRect.x + windowRect.width / 2, windowRect.y
        - windowRect.height / 2);
    bounds = Rectangle(center.x - 150, center.y + 100, 300, 200);
  }

  // Force the rect into the current display
  Rectangle dispBounds =
      Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetScreenSize();
  if (bounds.width > dispBounds.width)
    bounds.width = dispBounds.width;
  if (bounds.height > dispBounds.height)
    bounds.height = dispBounds.height;
  if (bounds.x + bounds.width > dispBounds.width)
    bounds.x = dispBounds.width - bounds.width;
  if (bounds.y + bounds.height > dispBounds.height)
    bounds.y = dispBounds.height - bounds.height;

  this->GetShell()->SetBounds(bounds);

  this->ConfigureShell(windowShell);

  this->CreateContents(windowShell->GetControl());
  //windowShell->Layout(true);
  //folder->SetBounds(Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(windowShell->GetControl()));
}

void DetachedWindow::Add(StackablePart::Pointer part)
{

  Shell::Pointer shell = this->GetShell();
  if (shell != 0)
  {
    part->Reparent(shell->GetControl());
  }
  folder->Add(part);
  this->UpdateMinimumSize();
}

bool DetachedWindow::BelongsToWorkbenchPage(
    IWorkbenchPage::Pointer workbenchPage)
{
  return (this->page == workbenchPage);
}

bool DetachedWindow::Close()
{
  hideViewsOnClose = false;
  Shell::Pointer shell = this->GetShell();
  if (shell != 0)
  {
    shell->Close();
  }
  return true;
}

IDropTarget::Pointer DetachedWindow::Drag(void* /*currentControl*/,
    Object::Pointer draggedObject, const Point& position, const Rectangle& /*dragRectangle*/)
{

  if (draggedObject.Cast<PartPane> () == 0)
  {
    return IDropTarget::Pointer(0);
  }

  PartPane::Pointer sourcePart = draggedObject.Cast<PartPane> ();

  if (sourcePart->GetWorkbenchWindow() != page->GetWorkbenchWindow())
  {
    return IDropTarget::Pointer(0);
  }

  // Only handle the event if the source part is acceptable to the particular PartStack
  IDropTarget::Pointer target;
  if (folder->AllowsDrop(sourcePart))
  {
    target = folder->GetDropTarget(draggedObject, position);

    if (target == 0)
    {
      Rectangle displayBounds =
          DragUtil::GetDisplayBounds(folder->GetControl());
      if (displayBounds.Contains(position))
      {
        StackDropResult::Pointer stackDropResult(new StackDropResult(
            displayBounds, Object::Pointer(0)));
        target = folder->CreateDropTarget(sourcePart, stackDropResult);
      }
      else
      {
        return IDropTarget::Pointer(0);
      }
    }
  }

  return target;
}

IStackableContainer::ChildrenType DetachedWindow::GetChildren() const
{
  return folder->GetChildren();
}

WorkbenchPage::Pointer DetachedWindow::GetWorkbenchPage()
{
  return this->page;
}

void DetachedWindow::RestoreState(IMemento::Pointer memento)
{
  // Read the bounds.
  int x = 0;
  memento->GetInteger(WorkbenchConstants::TAG_X, x);
  int y = 0;
  memento->GetInteger(WorkbenchConstants::TAG_Y, y);
  int width = 0;
  memento->GetInteger(WorkbenchConstants::TAG_WIDTH, width);
  int height = 0;
  memento->GetInteger(WorkbenchConstants::TAG_HEIGHT, height);

  // memento->GetInteger(WorkbenchConstants::TAG_FLOAT);

  // Set the bounds.
  bounds = Rectangle(x, y, width, height);
  if (GetShell())
  {
    GetShell()->SetBounds(bounds);
  }

  // Create the folder.
  IMemento::Pointer childMem =
      memento->GetChild(WorkbenchConstants::TAG_FOLDER);
  if (childMem)
  {
    folder->RestoreState(childMem);
  }
}

void DetachedWindow::SaveState(IMemento::Pointer memento)
{
  if (GetShell())
  {
    bounds = GetShell()->GetBounds();
  }

  // Save the bounds.
  memento->PutInteger(WorkbenchConstants::TAG_X, bounds.x);
  memento->PutInteger(WorkbenchConstants::TAG_Y, bounds.y);
  memento->PutInteger(WorkbenchConstants::TAG_WIDTH, bounds.width);
  memento->PutInteger(WorkbenchConstants::TAG_HEIGHT, bounds.height);

  // Save the views.
  IMemento::Pointer childMem = memento->CreateChild(
      WorkbenchConstants::TAG_FOLDER);
  folder->SaveState(childMem);
}

void* DetachedWindow::GetControl()
{
  return folder->GetControl();
}

int DetachedWindow::Open()
{

  if (this->GetShell() == 0)
  {
    this->Create();
  }

  Rectangle bounds = this->GetShell()->GetBounds();

  if (!(bounds == this->GetShell()->GetBounds()))
  {
    this->GetShell()->SetBounds(bounds);
  }

  this->GetShell()->SetVisible(true);

  folder->SetBounds(Tweaklets::Get(GuiWidgetsTweaklet::KEY)->GetClientArea(this->GetShell()->GetControl()));

  return 0;
}

void DetachedWindow::ActivePartChanged(
    IWorkbenchPartReference::Pointer partReference)
{
  if (activePart == partReference)
  {
    return;
  }

  if (activePart != 0)
  {
    activePart->RemovePropertyListener(IPropertyChangeListener::Pointer(this));
  }
  activePart = partReference;
  if (partReference != 0)
  {
    partReference->AddPropertyListener(IPropertyChangeListener::Pointer(this));
  }
  this->UpdateTitle();
}

void DetachedWindow::ConfigureShell(Shell::Pointer shell)
{
  this->UpdateTitle();

  Tweaklets::Get(GuiWidgetsTweaklet::KEY)->AddControlListener(
      shell->GetControl(), resizeListener);
  //shell.addListener(SWT.Activate, activationListener);
  //shell.addListener(SWT.Deactivate, activationListener);

  //TODO DetachedWindow key bindings
  //  // Register this detached view as a window (for key bindings).
  //  IContextService contextService = (IContextService) getWorkbenchPage()
  //  .getWorkbenchWindow().getWorkbench().getService(IContextService.class);
  //  contextService.registerShell(shell, IContextService.TYPE_WINDOW);
  //
  //  page.getWorkbenchWindow().getWorkbench().getHelpSystem().setHelp(shell,
  //      IWorkbenchHelpContextIds.DETACHED_WINDOW);
}

void* DetachedWindow::CreateContents(void* parent)
{
  // Create the tab folder.
  folder->CreateControl(parent);

  // Reparent each view in the tab folder.
  std::list<PartPane::Pointer> detachedChildren;
  this->CollectViewPanes(detachedChildren, this->GetChildren());
  for (std::list<PartPane::Pointer>::iterator itr = detachedChildren.begin(); itr
      != detachedChildren.end(); ++itr)
  {
    PartPane::Pointer part = *itr;
    part->Reparent(parent);
  }

  //TODO DetachedWindow listen to folder events (update size?)
  //  if (folder->GetPresentation()
  //    instanceof TabbedStackPresentation)
  //    {
  //      TabbedStackPresentation stack = (TabbedStackPresentation) folder.getPresentation();
  //      AbstractTabFolder tabFolder = stack.getTabFolder();
  //      tabFolder.addListener(new TabFolderListener()
  //      {
  //      public void handleEvent(TabFolderEvent e)
  //        {
  //          switch (e.type)
  //          {
  //            case TabFolderEvent.EVENT_CLOSE:
  //            {
  //              updateMinimumSize();
  //              break;
  //            }
  //            case TabFolderEvent.EVENT_PREFERRED_SIZE:
  //            {
  //              updateMinimumSize();
  //              break;
  //            }
  //          }
  //        }
  //      });
  //    }

  // Return tab folder control.
  return folder->GetControl();
}

void DetachedWindow::UpdateTitle()
{
  if (activePart != 0)
  {
    // Uncomment to set the shell title to match the title of the active part
    //            String text = activePart.getTitle();
    //
    //            if (!text.equals(s.getText())) {
    //                s.setText(text);
    //            }
  }
}

void DetachedWindow::UpdateMinimumSize()
{
  //  // We can only do this for 'Tabbed' stacked presentations.
  //  if (folder.getPresentation().Cast<TabbedStackPresentation>() != 0)
  //  {
  //    TabbedStackPresentation stack = (TabbedStackPresentation) folder.getPresentation();
  //
  //    if (stack->GetPartList().size() == 1)
  //    {
  //      // Get the minimum space required for the part
  //      int width = stack->ComputePreferredSize(true, Constants::INF, Constants::INF, 0);
  //      int height = stack->ComputePreferredSize(false, Constants::INF, Constants::INF, 0);
  //
  //      // Take the current shell 'trim' into account
  //      int shellHeight = windowShell->GetBounds().height - windowShell->GetClientArea().height;
  //      int shellWidth = windowShell->GetBounds().width - windowShell->GetClientArea().width;
  //
  //      windowShell->SetMinimumSize(width + shellWidth, height + shellHeight);
  //    }
  //  }
}

IWorkbenchPartReference::Pointer DetachedWindow::GetPartReference(
    StackablePart::Pointer pane)
{

  if (pane == 0 || pane.Cast<PartPane> () == 0)
  {
    return IWorkbenchPartReference::Pointer(0);
  }

  return pane.Cast<PartPane> ()->GetPartReference();
}

bool DetachedWindow::HandleClose()
{

  if (hideViewsOnClose)
  {
    std::list<PartPane::Pointer> views;
    this->CollectViewPanes(views, this->GetChildren());

    // Save any dirty views
    if (!this->HandleSaves(views))
    {
      return false; // User canceled the save
    }

    // OK, go on with the closing
    for (std::list<PartPane::Pointer>::iterator itr = views.begin(); itr
        != views.end(); ++itr)
    {
      PartPane::Pointer child = *itr;

      // Only close if closable...
      if (child->IsCloseable())
      {
        page->HideView(child->GetPartReference().Cast<IViewReference> ());

        // Was the close cancelled?
        if (child->GetContainer() != 0)
          return false;
      }
      else
      {
        page->AttachView(child->GetPartReference().Cast<IViewReference> ());
      }
    }
  }

  if (folder != 0)
  {
    folder->Dispose();
  }

  if (windowShell != 0)
  {
    Tweaklets::Get(GuiWidgetsTweaklet::KEY)->RemoveControlListener(
        windowShell->GetControl(), resizeListener);
    //    windowShell.removeListener(SWT.Activate, activationListener);
    //    windowShell.removeListener(SWT.Deactivate, activationListener);

    DragUtil::RemoveDragTarget(windowShell->GetControl(),
        IDragOverListener::Pointer(this));
    bounds = windowShell->GetBounds();

    //TODO DetachedWindow unregister key bindings
    //    // Unregister this detached view as a window (for key bindings).
    //    final IContextService contextService = (IContextService) getWorkbenchPage().getWorkbenchWindow().getWorkbench().getService(IContextService.class);
    //    contextService.unregisterShell(windowShell);

    windowShell->SetData(Object::Pointer(0));
    windowShell = 0;
  }

  return true;
}

bool DetachedWindow::HandleSaves(std::list<PartPane::Pointer> views)
{
  std::vector<IWorkbenchPart::Pointer> dirtyViews;
  for (std::list<PartPane::Pointer>::iterator iterator = views.begin(); iterator
      != views.end(); ++iterator)
  {
    PartPane::Pointer pane = *iterator;
    IViewReference::Pointer ref =
        pane->GetPartReference().Cast<IViewReference> ();
    IViewPart::Pointer part = ref->GetView(false);
    if (part.Cast<ISaveablePart> () != 0)
    {
      ISaveablePart::Pointer saveable = part.Cast<ISaveablePart> ();
      if (saveable->IsDirty() && saveable->IsSaveOnCloseNeeded())
      {
        dirtyViews.push_back(part);
      }
    }
  }

  // If there are any prompt to save -before- any closing happens
  // FIXME: This code will result in a double prompt if the user
  // decides not to save a particular view at this stage they'll
  // get a second one from the 'hideView' call...
  if (dirtyViews.size() > 0)
  {
    IWorkbenchWindow::Pointer window = page->GetWorkbenchWindow();
    bool success =
        EditorManager::SaveAll(dirtyViews, true, true, false, window);
    if (!success)
    {
      return false; // the user canceled.
    }
  }

  return true;
}

void DetachedWindow::CollectViewPanes(std::list<PartPane::Pointer>& result,
    const std::list<StackablePart::Pointer>& parts)
{
  for (std::list<StackablePart::Pointer>::const_iterator iter = parts.begin(); iter
      != parts.end(); ++iter)
  {
    StackablePart::Pointer part = *iter;
    if (part.Cast<PartPane> () != 0)
    {
      result.push_back(part.Cast<PartPane> ());
    }
  }
}

}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (C) 2005-2008 by the FIFE team                              *
 *   http://www.fifengine.de                                               *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or                 *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
 ***************************************************************************/

// Standard C++ library includes
#include <iostream>

// 3rd party library includes
#include <SDL.h>
#include <SDL_ttf.h>

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "util/base/exception.h"
#include "util/log/logger.h"
#include "util/time/timemanager.h"
#include "audio/soundmanager.h"
#include "gui/console/console.h"
#include "gui/guimanager.h"
#include "vfs/vfs.h"
#include "vfs/vfsdirectory.h"
#include "vfs/directoryprovider.h"
#ifdef HAVE_ZIP
#include "vfs/zip/zipprovider.h"
#endif
#include "eventchannel/eventmanager.h"
#include "video/imagepool.h"
#include "video/animationpool.h"
#include "audio/soundclippool.h"
#include "video/renderbackend.h"
#include "video/cursor.h"
#ifdef HAVE_OPENGL
#include "video/opengl/renderbackendopengl.h"
#include "gui/base/opengl/opengl_gui_graphics.h"
#endif
#include "gui/base/sdl/sdl_gui_graphics.h"
#include "gui/base/gui_font.h"
#include "video/sdl/renderbackendsdl.h"
#include "video/fonts/abstractfont.h"
#include "loaders/native/video_loaders/subimage_loader.h"
#include "loaders/native/video_loaders/image_loader.h"
#include "loaders/native/audio_loaders/ogg_loader.h"
#include "model/model.h"
#include "pathfinder/linearpather/linearpather.h"
#include "pathfinder/routepather/routepather.h"
#include "model/metamodel/grids/hexgrid.h"
#include "model/metamodel/grids/squaregrid.h"
#include "view/view.h"
#include "view/renderers/camerazonerenderer.h"
#include "view/renderers/quadtreerenderer.h"
#include "view/renderers/gridrenderer.h"
#include "view/renderers/instancerenderer.h"
#include "view/renderers/coordinaterenderer.h"
#include "view/renderers/floatingtextrenderer.h"
#include "view/renderers/cellselectionrenderer.h"
#include "view/renderers/blockinginforenderer.h"
#include "view/renderers/genericrenderer.h"
#include "engine.h"

#ifdef USE_COCOA
#include <dlfcn.h>

int main(int argc, char **argv)
{
    return 0;
}
#endif

namespace FIFE {
	static Logger _log(LM_CONTROLLER);

	Engine::Engine():
		m_renderbackend(0),
		m_guimanager(0),
		m_eventmanager(0),
		m_soundmanager(0),
		m_timemanager(0),
		m_imagepool(0),
		m_animpool(0),
		m_soundclippool(0),
		m_vfs(0),
		m_model(0),
		m_gui_graphics(0),
		m_view(0),
		m_logmanager(0),
		m_cursor(0),
		m_settings() {
#ifdef USE_COCOA
		// The next lines ensure that Cocoa is initialzed correctly.
		// This is needed for SDL to function properly on MAC OS X.
		void* cocoa_lib;
		cocoa_lib = dlopen( "/System/Library/Frameworks/Cocoa.framework/Cocoa", RTLD_LAZY );
		void (*nsappload)(void);
		nsappload = (void(*)()) dlsym( cocoa_lib, "NSApplicationLoad");
		nsappload();
#endif
		preInit();
	}

	EngineSettings& Engine::getSettings() {
		return m_settings;
	}

	void Engine::preInit() {
		m_logmanager = LogManager::instance();

		FL_LOG(_log, "================== Engine pre-init start =================");
		m_timemanager = new TimeManager();
		FL_LOG(_log, "Time manager created");

		FL_LOG(_log, "Creating VFS");
		m_vfs = new VFS();

		FL_LOG(_log, "Adding root directory to VFS");
		m_vfs->addSource( new VFSDirectory(m_vfs) );
		m_vfs->addProvider( new DirectoryProvider() );
#ifdef HAVE_ZIP
		FL_LOG(_log, "Adding zip provider to VFS");
		m_vfs->addProvider( new ZipProvider() );
#endif
		//m_vfs->addProvider(ProviderDAT2());
		//m_vfs->addProvider(ProviderDAT1());
		FL_LOG(_log, "Engine pre-init done");
	}

	void Engine::init() {
		FL_LOG(_log, "Engine initialize start");
		m_settings.validate();
		FL_LOG(_log, "Engine settings validated");

		// If failed to init SDL throw exception.
		if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_TIMER) < 0) {
			throw SDLException(SDL_GetError());
		}

		SDL_EnableUNICODE(1);
		SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
		TTF_Init();

		FL_LOG(_log, "Creating event manager");
		m_eventmanager = new EventManager();

		FL_LOG(_log, "Creating pools");
		m_imagepool = new ImagePool();
		m_animpool = new AnimationPool();
		m_soundclippool = new SoundClipPool();
		m_imagepool->addResourceLoader(new SubImageLoader());
		m_imagepool->addResourceLoader(new ImageLoader(m_vfs));
		m_soundclippool->addResourceLoader(new OggLoader(m_vfs));

		FL_LOG(_log, "Creating render backend");
		std::string rbackend(m_settings.getRenderBackend());
		if (rbackend == "SDL") {
			m_renderbackend = new RenderBackendSDL();
			FL_LOG(_log, "SDL Render backend created");
		} else {
#ifdef HAVE_OPENGL
			m_renderbackend = new RenderBackendOpenGL();
			FL_LOG(_log, "OpenGL Render backend created");
#else
			m_renderbackend = new RenderBackendSDL();
			// Remember  the choice so we pick the right graphics class.
			rbackend = "SDL";
			FL_WARN(_log, "Tried to select OpenGL, even though it is not compiled into the engine. Falling back to SDL Render backend");
#endif
		}
		FL_LOG(_log, "Initializing render backend");
		m_renderbackend->setChunkingSize(m_settings.getImageChunkingSize());
		m_renderbackend->init();

		FL_LOG(_log, "Creating main screen");
		m_renderbackend->createMainScreen(
			m_settings.getScreenWidth(),
			m_settings.getScreenHeight(),
			static_cast<unsigned char>(m_settings.getBitsPerPixel()),
			m_settings.isFullScreen(),
			m_settings.getWindowTitle(),
			m_settings.getWindowIcon());
		FL_LOG(_log, "Main screen created");

#ifdef HAVE_OPENGL
		if( rbackend != "SDL" ) {
			m_gui_graphics = new OpenGLGuiGraphics(*m_imagepool);
		}
#endif
		if( rbackend == "SDL" ) {
			m_gui_graphics = new SdlGuiGraphics(*m_imagepool);
		}
		FL_LOG(_log, "Constructing GUI manager");
		m_guimanager = new GUIManager(m_eventmanager, *m_imagepool);
		m_eventmanager->addSdlEventListener(m_guimanager);
		// keep guimanager as the first key listener so that it can evaluate guichan hits
		m_eventmanager->addKeyListener(m_guimanager);
		// keep guimanager as the first mouse listener so that it can evaluate guichan hits
		m_eventmanager->addMouseListener(m_guimanager);
		FL_LOG(_log, "Events bind to GUI manager");

		FL_LOG(_log, "Creating default font");
		m_defaultfont = m_guimanager->setDefaultFont(
			m_settings.getDefaultFontPath(),
			m_settings.getDefaultFontSize(),
			m_settings.getDefaultFontGlyphs());
		FL_LOG(_log, "Initializing GUI manager");
		m_guimanager->init(m_gui_graphics, m_settings.getScreenWidth(), m_settings.getScreenHeight());
		FL_LOG(_log, "GUI manager initialized");
		SDL_EnableUNICODE(1);

		FL_LOG(_log, "Creating sound manager");
		m_soundmanager = new SoundManager(m_soundclippool);
		m_soundmanager->setVolume(static_cast<float>(m_settings.getInitialVolume()) / 10);

		FL_LOG(_log, "Creating model");
		m_model = new Model();
		FL_LOG(_log, "Adding pathers to model");
		m_model->adoptPather(new LinearPather());
		m_model->adoptPather(new RoutePather());
		FL_LOG(_log, "Adding grid prototypes to model");
		m_model->adoptCellGrid(new SquareGrid());
		m_model->adoptCellGrid(new HexGrid());

		FL_LOG(_log, "Creating view");
		m_view = new View(m_renderbackend, m_imagepool, m_animpool);
		FL_LOG(_log, "Creating renderers to view");
		m_view->addRenderer(new CameraZoneRenderer(m_renderbackend, 0, m_imagepool));
		m_view->addRenderer(new InstanceRenderer(m_renderbackend, 10, m_imagepool, m_animpool));
		m_view->addRenderer(new GridRenderer(m_renderbackend, 20));
		m_view->addRenderer(new CellSelectionRenderer(m_renderbackend, 30));
		m_view->addRenderer(new BlockingInfoRenderer(m_renderbackend, 40));
		m_view->addRenderer(new FloatingTextRenderer(m_renderbackend, 50, dynamic_cast<AbstractFont*>(m_defaultfont)));
		m_view->addRenderer(new QuadTreeRenderer(m_renderbackend, 60));
		m_view->addRenderer(new CoordinateRenderer(m_renderbackend, 70, dynamic_cast<AbstractFont*>(m_defaultfont)));
		m_view->addRenderer(new GenericRenderer(m_renderbackend, 80, m_imagepool, m_animpool));
		m_cursor = new Cursor(m_imagepool, m_animpool, m_renderbackend);
		FL_LOG(_log, "Engine intialized");
	}

	Engine::~Engine() {
		FL_LOG(_log, "Destructing engine");
 		delete m_cursor;
 		delete m_view;
		delete m_model;
		delete m_soundmanager;
		delete m_guimanager;
		delete m_gui_graphics;

		m_renderbackend->deinit();
		delete m_renderbackend;

		// Note the dependancy between image and animation pools
		// as animations reference images they have to be deleted
		// before clearing the image pool.
		delete m_animpool;
		delete m_imagepool;
		delete m_eventmanager;

		delete m_vfs;

		delete m_timemanager;

		TTF_Quit();
		SDL_Quit();
		FL_LOG(_log, "================== Engine destructed ==================");
		//delete m_logmanager;
	}
	void Engine::initializePumping() {
		m_eventmanager->processEvents();
	}

	void Engine::pump() {
		m_renderbackend->startFrame();
		m_timemanager->update();
		m_model->update();
		m_view->update();
		m_guimanager->turn();
		m_cursor->draw();
		m_renderbackend->endFrame();
		SDL_Delay(1);
		m_eventmanager->processEvents();
	}

	void Engine::finalizePumping() {
		// nothing here at the moment..
	}
}//FIFE

/* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */
<commit_msg>increased felt responsiveness by first processing events and then drawing the screen<commit_after>/***************************************************************************
 *   Copyright (C) 2005-2008 by the FIFE team                              *
 *   http://www.fifengine.de                                               *
 *   This file is part of FIFE.                                            *
 *                                                                         *
 *   FIFE is free software; you can redistribute it and/or                 *
 *   modify it under the terms of the GNU Lesser General Public            *
 *   License as published by the Free Software Foundation; either          *
 *   version 2.1 of the License, or (at your option) any later version.    *
 *                                                                         *
 *   This library is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
 *   Lesser General Public License for more details.                       *
 *                                                                         *
 *   You should have received a copy of the GNU Lesser General Public      *
 *   License along with this library; if not, write to the                 *
 *   Free Software Foundation, Inc.,                                       *
 *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
 ***************************************************************************/

// Standard C++ library includes
#include <iostream>

// 3rd party library includes
#include <SDL.h>
#include <SDL_ttf.h>

// FIFE includes
// These includes are split up in two parts, separated by one empty line
// First block: files included from the FIFE root src directory
// Second block: files included from the same folder
#include "util/base/exception.h"
#include "util/log/logger.h"
#include "util/time/timemanager.h"
#include "audio/soundmanager.h"
#include "gui/console/console.h"
#include "gui/guimanager.h"
#include "vfs/vfs.h"
#include "vfs/vfsdirectory.h"
#include "vfs/directoryprovider.h"
#ifdef HAVE_ZIP
#include "vfs/zip/zipprovider.h"
#endif
#include "eventchannel/eventmanager.h"
#include "video/imagepool.h"
#include "video/animationpool.h"
#include "audio/soundclippool.h"
#include "video/renderbackend.h"
#include "video/cursor.h"
#ifdef HAVE_OPENGL
#include "video/opengl/renderbackendopengl.h"
#include "gui/base/opengl/opengl_gui_graphics.h"
#endif
#include "gui/base/sdl/sdl_gui_graphics.h"
#include "gui/base/gui_font.h"
#include "video/sdl/renderbackendsdl.h"
#include "video/fonts/abstractfont.h"
#include "loaders/native/video_loaders/subimage_loader.h"
#include "loaders/native/video_loaders/image_loader.h"
#include "loaders/native/audio_loaders/ogg_loader.h"
#include "model/model.h"
#include "pathfinder/linearpather/linearpather.h"
#include "pathfinder/routepather/routepather.h"
#include "model/metamodel/grids/hexgrid.h"
#include "model/metamodel/grids/squaregrid.h"
#include "view/view.h"
#include "view/renderers/camerazonerenderer.h"
#include "view/renderers/quadtreerenderer.h"
#include "view/renderers/gridrenderer.h"
#include "view/renderers/instancerenderer.h"
#include "view/renderers/coordinaterenderer.h"
#include "view/renderers/floatingtextrenderer.h"
#include "view/renderers/cellselectionrenderer.h"
#include "view/renderers/blockinginforenderer.h"
#include "view/renderers/genericrenderer.h"
#include "engine.h"

#ifdef USE_COCOA
#include <dlfcn.h>

int main(int argc, char **argv)
{
    return 0;
}
#endif

namespace FIFE {
	static Logger _log(LM_CONTROLLER);

	Engine::Engine():
		m_renderbackend(0),
		m_guimanager(0),
		m_eventmanager(0),
		m_soundmanager(0),
		m_timemanager(0),
		m_imagepool(0),
		m_animpool(0),
		m_soundclippool(0),
		m_vfs(0),
		m_model(0),
		m_gui_graphics(0),
		m_view(0),
		m_logmanager(0),
		m_cursor(0),
		m_settings() {
#ifdef USE_COCOA
		// The next lines ensure that Cocoa is initialzed correctly.
		// This is needed for SDL to function properly on MAC OS X.
		void* cocoa_lib;
		cocoa_lib = dlopen( "/System/Library/Frameworks/Cocoa.framework/Cocoa", RTLD_LAZY );
		void (*nsappload)(void);
		nsappload = (void(*)()) dlsym( cocoa_lib, "NSApplicationLoad");
		nsappload();
#endif
		preInit();
	}

	EngineSettings& Engine::getSettings() {
		return m_settings;
	}

	void Engine::preInit() {
		m_logmanager = LogManager::instance();

		FL_LOG(_log, "================== Engine pre-init start =================");
		m_timemanager = new TimeManager();
		FL_LOG(_log, "Time manager created");

		FL_LOG(_log, "Creating VFS");
		m_vfs = new VFS();

		FL_LOG(_log, "Adding root directory to VFS");
		m_vfs->addSource( new VFSDirectory(m_vfs) );
		m_vfs->addProvider( new DirectoryProvider() );
#ifdef HAVE_ZIP
		FL_LOG(_log, "Adding zip provider to VFS");
		m_vfs->addProvider( new ZipProvider() );
#endif
		//m_vfs->addProvider(ProviderDAT2());
		//m_vfs->addProvider(ProviderDAT1());
		FL_LOG(_log, "Engine pre-init done");
	}

	void Engine::init() {
		FL_LOG(_log, "Engine initialize start");
		m_settings.validate();
		FL_LOG(_log, "Engine settings validated");

		// If failed to init SDL throw exception.
		if (SDL_Init(SDL_INIT_NOPARACHUTE | SDL_INIT_TIMER) < 0) {
			throw SDLException(SDL_GetError());
		}

		SDL_EnableUNICODE(1);
		SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
		TTF_Init();

		FL_LOG(_log, "Creating event manager");
		m_eventmanager = new EventManager();

		FL_LOG(_log, "Creating pools");
		m_imagepool = new ImagePool();
		m_animpool = new AnimationPool();
		m_soundclippool = new SoundClipPool();
		m_imagepool->addResourceLoader(new SubImageLoader());
		m_imagepool->addResourceLoader(new ImageLoader(m_vfs));
		m_soundclippool->addResourceLoader(new OggLoader(m_vfs));

		FL_LOG(_log, "Creating render backend");
		std::string rbackend(m_settings.getRenderBackend());
		if (rbackend == "SDL") {
			m_renderbackend = new RenderBackendSDL();
			FL_LOG(_log, "SDL Render backend created");
		} else {
#ifdef HAVE_OPENGL
			m_renderbackend = new RenderBackendOpenGL();
			FL_LOG(_log, "OpenGL Render backend created");
#else
			m_renderbackend = new RenderBackendSDL();
			// Remember  the choice so we pick the right graphics class.
			rbackend = "SDL";
			FL_WARN(_log, "Tried to select OpenGL, even though it is not compiled into the engine. Falling back to SDL Render backend");
#endif
		}
		FL_LOG(_log, "Initializing render backend");
		m_renderbackend->setChunkingSize(m_settings.getImageChunkingSize());
		m_renderbackend->init();

		FL_LOG(_log, "Creating main screen");
		m_renderbackend->createMainScreen(
			m_settings.getScreenWidth(),
			m_settings.getScreenHeight(),
			static_cast<unsigned char>(m_settings.getBitsPerPixel()),
			m_settings.isFullScreen(),
			m_settings.getWindowTitle(),
			m_settings.getWindowIcon());
		FL_LOG(_log, "Main screen created");

#ifdef HAVE_OPENGL
		if( rbackend != "SDL" ) {
			m_gui_graphics = new OpenGLGuiGraphics(*m_imagepool);
		}
#endif
		if( rbackend == "SDL" ) {
			m_gui_graphics = new SdlGuiGraphics(*m_imagepool);
		}
		FL_LOG(_log, "Constructing GUI manager");
		m_guimanager = new GUIManager(m_eventmanager, *m_imagepool);
		m_eventmanager->addSdlEventListener(m_guimanager);
		// keep guimanager as the first key listener so that it can evaluate guichan hits
		m_eventmanager->addKeyListener(m_guimanager);
		// keep guimanager as the first mouse listener so that it can evaluate guichan hits
		m_eventmanager->addMouseListener(m_guimanager);
		FL_LOG(_log, "Events bind to GUI manager");

		FL_LOG(_log, "Creating default font");
		m_defaultfont = m_guimanager->setDefaultFont(
			m_settings.getDefaultFontPath(),
			m_settings.getDefaultFontSize(),
			m_settings.getDefaultFontGlyphs());
		FL_LOG(_log, "Initializing GUI manager");
		m_guimanager->init(m_gui_graphics, m_settings.getScreenWidth(), m_settings.getScreenHeight());
		FL_LOG(_log, "GUI manager initialized");
		SDL_EnableUNICODE(1);

		FL_LOG(_log, "Creating sound manager");
		m_soundmanager = new SoundManager(m_soundclippool);
		m_soundmanager->setVolume(static_cast<float>(m_settings.getInitialVolume()) / 10);

		FL_LOG(_log, "Creating model");
		m_model = new Model();
		FL_LOG(_log, "Adding pathers to model");
		m_model->adoptPather(new LinearPather());
		m_model->adoptPather(new RoutePather());
		FL_LOG(_log, "Adding grid prototypes to model");
		m_model->adoptCellGrid(new SquareGrid());
		m_model->adoptCellGrid(new HexGrid());

		FL_LOG(_log, "Creating view");
		m_view = new View(m_renderbackend, m_imagepool, m_animpool);
		FL_LOG(_log, "Creating renderers to view");
		m_view->addRenderer(new CameraZoneRenderer(m_renderbackend, 0, m_imagepool));
		m_view->addRenderer(new InstanceRenderer(m_renderbackend, 10, m_imagepool, m_animpool));
		m_view->addRenderer(new GridRenderer(m_renderbackend, 20));
		m_view->addRenderer(new CellSelectionRenderer(m_renderbackend, 30));
		m_view->addRenderer(new BlockingInfoRenderer(m_renderbackend, 40));
		m_view->addRenderer(new FloatingTextRenderer(m_renderbackend, 50, dynamic_cast<AbstractFont*>(m_defaultfont)));
		m_view->addRenderer(new QuadTreeRenderer(m_renderbackend, 60));
		m_view->addRenderer(new CoordinateRenderer(m_renderbackend, 70, dynamic_cast<AbstractFont*>(m_defaultfont)));
		m_view->addRenderer(new GenericRenderer(m_renderbackend, 80, m_imagepool, m_animpool));
		m_cursor = new Cursor(m_imagepool, m_animpool, m_renderbackend);
		FL_LOG(_log, "Engine intialized");
	}

	Engine::~Engine() {
		FL_LOG(_log, "Destructing engine");
 		delete m_cursor;
 		delete m_view;
		delete m_model;
		delete m_soundmanager;
		delete m_guimanager;
		delete m_gui_graphics;

		m_renderbackend->deinit();
		delete m_renderbackend;

		// Note the dependancy between image and animation pools
		// as animations reference images they have to be deleted
		// before clearing the image pool.
		delete m_animpool;
		delete m_imagepool;
		delete m_eventmanager;

		delete m_vfs;

		delete m_timemanager;

		TTF_Quit();
		SDL_Quit();
		FL_LOG(_log, "================== Engine destructed ==================");
		//delete m_logmanager;
	}
	void Engine::initializePumping() {
		m_eventmanager->processEvents();
	}

	void Engine::pump() {
		m_eventmanager->processEvents();
		m_renderbackend->startFrame();
		m_timemanager->update();
		m_model->update();
		m_view->update();
		m_guimanager->turn();
		m_cursor->draw();
		m_renderbackend->endFrame();
	}

	void Engine::finalizePumping() {
		// nothing here at the moment..
	}
}//FIFE

/* vim: set noexpandtab: set shiftwidth=2: set tabstop=2: */
<|endoftext|>


<commit_before>#ifndef PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP
#define PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP

#include <limits>

namespace pk
{
namespace graphs
{

template<const int V, class WeightType>
class shortest_paths_floyd_warshall
{
public:
    typedef WeightType weight_type;
    typedef const weight_type (*shortest_paths_matrix)[V];

    shortest_paths_floyd_warshall() : infinity(std::numeric_limits<weight_type>::max()) {}

    template<class graph_type>
    void run(const graph_type& g)
    {
        const int num_of_vertices = g.get_num_of_vertices();

        for(int i = 0; i < num_of_vertices; ++i)
        {
            for(int j = 0; j < num_of_vertices; ++j)
                shortest_paths[i][j] = infinity;

            shortest_paths[i][i] = weight_type(0);
        }

        for(int v = 0; v < num_of_vertices; ++v)
        {
            const typename graph_type::adjacency_list& adj_v = g.get_adjacency_list(v);
            for(int i = 0; i < adj_v.size(); ++i)
            {
                const int u = adj_v[i].to;
                shortest_paths[v][u] = adj_v[i].weight;
            }
        }

        for(int k = 0; k < num_of_vertices; ++k)
        {
            for(int i = 0; i < num_of_vertices; ++i)
            {
                for(int j = 0; j < num_of_vertices; ++j)
                {
                    if((shortest_paths[i][k] == infinity) || (shortest_paths[k][j] == infinity))
                        continue;

                    const weight_type w = shortest_paths[i][k] + shortest_paths[k][j];
                    if(w < shortest_paths[i][j])
                        shortest_paths[i][j] = w;
                }
            }
        }
    }

    shortest_paths_matrix get_shortest_paths_matrix() const
    {
        return shortest_paths;
    }

    const weight_type infinity;

private:
    weight_type shortest_paths[V][V];
};

} // namespace graphs
} // namespace pk

#endif // PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP
<commit_msg>Cleaner code<commit_after>#ifndef PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP
#define PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP

#include <limits>

namespace pk
{
namespace graphs
{

template<const int V, class WeightType>
class shortest_paths_floyd_warshall
{
public:
    typedef WeightType weight_type;
    typedef const weight_type (*shortest_paths_matrix)[V];

    shortest_paths_floyd_warshall() : infinity(std::numeric_limits<weight_type>::max()) {}

    template<class graph_type>
    void run(const graph_type& g)
    {
        num_of_vertices = g.get_num_of_vertices();

        initialize_all_paths_to_infinity_and_each_vertex_to_zero();
        set_initial_paths_to_neighbours(g);
        compute_shortest_paths();
    }

    shortest_paths_matrix get_shortest_paths_matrix() const
    {
        return shortest_paths;
    }

    const weight_type infinity;

private:
    void initialize_all_paths_to_infinity_and_each_vertex_to_zero()
    {
        for(int i = 0; i < num_of_vertices; ++i)
        {
            for(int j = 0; j < num_of_vertices; ++j)
                shortest_paths[i][j] = infinity;

            shortest_paths[i][i] = weight_type(0);
        }
    }

    template<class graph_type>
    void set_initial_paths_to_neighbours(const graph_type& g)
    {
        for(int v = 0; v < num_of_vertices; ++v)
        {
            const typename graph_type::adjacency_list& adj_v = g.get_adjacency_list(v);
            for(int i = 0; i < adj_v.size(); ++i)
            {
                const int u = adj_v[i].to;
                shortest_paths[v][u] = adj_v[i].weight;
            }
        }
    }

    void compute_shortest_paths()
    {
        for(int k = 0; k < num_of_vertices; ++k)
        {
            for(int i = 0; i < num_of_vertices; ++i)
            {
                for(int j = 0; j < num_of_vertices; ++j)
                {
                    if((shortest_paths[i][k] == infinity) || (shortest_paths[k][j] == infinity))
                        continue;

                    const weight_type w = shortest_paths[i][k] + shortest_paths[k][j];
                    if(w < shortest_paths[i][j])
                        shortest_paths[i][j] = w;
                }
            }
        }
    }

    weight_type shortest_paths[V][V];
    int num_of_vertices;
};

} // namespace graphs
} // namespace pk

#endif // PK_GRAPHS_SHORTESTPATHSFLOYDWARSHALL_HPP
<|endoftext|>


<commit_before>///
/// @file  Sigma.cpp
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <gourdon.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <imath.hpp>
#include <PiTable.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>

using namespace std;
using namespace primecount;

namespace {

template <typename T>
T Sigma0(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T pi_sqrtx = pi_legendre(isqrt(x), threads);

  return a - 1 + (pi_sqrtx * (pi_sqrtx - 1)) / 2 - (a * (a - 1)) / 2;
}

template <typename T>
T Sigma1(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T b = pi_legendre(iroot<3>(x), threads);

  return (a - b) * (a - b - 1) / 2;
}

template <typename T>
T Sigma2(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T b = pi_legendre(iroot<3>(x), threads);
  T c = pi_legendre(isqrt(x / y), threads);
  T x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  T d = pi_legendre(x_star, threads);

  return a * (b - c - (c * (c - 3)) / 2 + (d * (d - 3)) / 2);
}

template <typename T>
T Sigma3(T x, int64_t y, int threads)
{
  T b = pi_legendre(iroot<3>(x), threads);
  T x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  T d = pi_legendre(x_star, threads);

  return (b * (b - 1) * (2 * b - 1)) / 6 - b - (d * (d - 1) * (2 * d - 1)) / 6 + d;
}

/// Memory usage: O(x^(1/3)) or less
template <typename T>
T Sigma4(T x, int64_t y, int threads)
{
  T sum = 0;
  int64_t pi_y = pi_legendre(y, threads);
  int64_t x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  int64_t sqrt_xy = isqrt(x / y);

  PiTable pi(x / (x_star * (T) y));
  primesieve::iterator it(x_star, sqrt_xy);
  int64_t prime = it.next_prime();

  for (; prime <= sqrt_xy; prime = it.next_prime())
    sum += pi[x / (prime * (T) y)];

  return pi_y * sum;
}

/// Memory usage: O(y)
template <typename T>
T Sigma5(T x, int64_t y, int threads)
{
  T sum = 0;
  int64_t x13 = iroot<3>(x);
  int64_t sqrt_xy = isqrt(x / y);

  PiTable pi(y);
  primesieve::iterator it(sqrt_xy, x13);
  int64_t prime = it.next_prime();

  for (; prime <= x13; prime = it.next_prime())
    sum += pi[x / (prime * (T) prime)];

  return sum;
}

/// Memory usage: O(x^(3/8))
template <typename T>
T Sigma6(T x, int64_t y, int threads)
{
  T sum = 0;
  int64_t sqrtx = isqrt(x);
  int64_t x13 = iroot<3>(x);
  int64_t x_star = max(iroot<4>(x), x / ((T) y * (T) y));

  PiTable pi(sqrtx / isqrt(x_star));
  primesieve::iterator it(x_star, x13);
  int64_t prime = it.next_prime();

  for (; prime <= x13; prime = it.next_prime())
  {
    T pix = pi[sqrtx / isqrt(prime)];
    sum += pix * pix;
  }

  return -sum;
}

} // namespace

namespace primecount {

int64_t Sigma(int64_t x, int64_t y, int threads)
{
  print("");
  print("=== Sigma(x, y) ===");
  print(x, y, threads);

  double time = get_time();
  int64_t sum = Sigma0(x, y, threads) +
                Sigma1(x, y, threads) +
                Sigma2(x, y, threads) +
                Sigma3(x, y, threads) +
                Sigma4(x, y, threads) +
                Sigma5(x, y, threads) +
                Sigma6(x, y, threads);

  print("Sigma", sum, time);
  return sum;
}

#ifdef HAVE_INT128_T

int128_t Sigma(int128_t x, int64_t y, int threads)
{
  print("");
  print("=== Sigma(x, y) ===");
  print(x, y, threads);

  double time = get_time();
  int128_t sum = Sigma0(x, y, threads) +
                 Sigma1(x, y, threads) +
                 Sigma2(x, y, threads) +
                 Sigma3(x, y, threads) +
                 Sigma4(x, y, threads) +
                 Sigma5(x, y, threads) +
                 Sigma6(x, y, threads);

  print("Sigma", sum, time);
  return sum;
}

#endif

} // namespace
<commit_msg>Fix bug in Sigma6(x, a)<commit_after>///
/// @file  Sigma.cpp
///
/// Copyright (C) 2019 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <gourdon.hpp>
#include <primecount-internal.hpp>
#include <primesieve.hpp>
#include <int128_t.hpp>
#include <min.hpp>
#include <imath.hpp>
#include <PiTable.hpp>
#include <print.hpp>

#include <stdint.h>
#include <algorithm>

using namespace std;
using namespace primecount;

namespace {

template <typename T>
T Sigma0(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T pi_sqrtx = pi_legendre(isqrt(x), threads);

  return a - 1 + (pi_sqrtx * (pi_sqrtx - 1)) / 2 - (a * (a - 1)) / 2;
}

template <typename T>
T Sigma1(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T b = pi_legendre(iroot<3>(x), threads);

  return (a - b) * (a - b - 1) / 2;
}

template <typename T>
T Sigma2(T x, int64_t y, int threads)
{
  T a = pi_legendre(y, threads);
  T b = pi_legendre(iroot<3>(x), threads);
  T c = pi_legendre(isqrt(x / y), threads);
  T x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  T d = pi_legendre(x_star, threads);

  return a * (b - c - (c * (c - 3)) / 2 + (d * (d - 3)) / 2);
}

template <typename T>
T Sigma3(T x, int64_t y, int threads)
{
  T b = pi_legendre(iroot<3>(x), threads);
  T x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  T d = pi_legendre(x_star, threads);

  return (b * (b - 1) * (2 * b - 1)) / 6 - b - (d * (d - 1) * (2 * d - 1)) / 6 + d;
}

/// Memory usage: O(x^(1/3)) or less
template <typename T>
T Sigma4(T x, int64_t y, int threads)
{
  T sum = 0;
  int64_t pi_y = pi_legendre(y, threads);
  int64_t x_star = max(iroot<4>(x), x / ((T) y * (T) y));
  int64_t sqrt_xy = isqrt(x / y);

  PiTable pi(x / (x_star * (T) y));
  primesieve::iterator it(x_star, sqrt_xy);
  int64_t prime = it.next_prime();

  for (; prime <= sqrt_xy; prime = it.next_prime())
    sum += pi[x / (prime * (T) y)];

  return pi_y * sum;
}

/// Memory usage: O(y)
template <typename T>
T Sigma5(T x, int64_t y)
{
  T sum = 0;
  int64_t x13 = iroot<3>(x);
  int64_t sqrt_xy = isqrt(x / y);

  PiTable pi(y);
  primesieve::iterator it(sqrt_xy, x13);
  int64_t prime = it.next_prime();

  for (; prime <= x13; prime = it.next_prime())
    sum += pi[x / (prime * (T) prime)];

  return sum;
}

/// Memory usage: O(x^(3/8))
template <typename T>
T Sigma6(T x, int64_t y)
{
  T sum = 0;
  int64_t x13 = iroot<3>(x);
  int64_t x_star = max(iroot<4>(x), x / ((T) y * (T) y));

  PiTable pi(isqrt(x / x_star));
  primesieve::iterator it(x_star, x13);
  int64_t prime = it.next_prime();

  for (; prime <= x13; prime = it.next_prime())
  {
    // Note that in Xavier Gourdon's paper the actual
    // formula for Σ6 is: sum += pi(x^(1/2) / prime^(1/2))^2.
    // However when implemented this way using integers
    // the formula returns erroneous results.
    // Hence the formula must be implemented as below:
    T pix = pi[isqrt(x / prime)];
    sum += pix * pix;
  }

  return -sum;
}

} // namespace

namespace primecount {

int64_t Sigma(int64_t x, int64_t y, int threads)
{
  print("");
  print("=== Sigma(x, y) ===");
  print(x, y, threads);

  double time = get_time();
  int64_t sum = Sigma0(x, y, threads) +
                Sigma1(x, y, threads) +
                Sigma2(x, y, threads) +
                Sigma3(x, y, threads) +
                Sigma4(x, y, threads) +
                Sigma5(x, y) +
                Sigma6(x, y);

  print("Sigma", sum, time);
  return sum;
}

#ifdef HAVE_INT128_T

int128_t Sigma(int128_t x, int64_t y, int threads)
{
  print("");
  print("=== Sigma(x, y) ===");
  print(x, y, threads);

  double time = get_time();
  int128_t sum = Sigma0(x, y, threads) +
                 Sigma1(x, y, threads) +
                 Sigma2(x, y, threads) +
                 Sigma3(x, y, threads) +
                 Sigma4(x, y, threads) +
                 Sigma5(x, y) +
                 Sigma6(x, y);

  print("Sigma", sum, time);
  return sum;
}

#endif

} // namespace
<|endoftext|>


<commit_before>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE rodb
#include <boost/test/unit_test.hpp>

#include "rodb.h"

class WhatIs
{
public:
	WhatIs(char const *what): what_(what)
	{
	}

	bool operator ()(std::exception const &e)
	{
		return what_ == e.what();
	}

private:
	std::string what_;
};

class WhatStartsWith
{
public:
	WhatStartsWith(char const *what): what_(what)
	{
	}

	bool operator ()(std::exception const &e)
	{
		// Check that e.what() start with what_.  It's needed because e.what() might
		// have source file location information appended to it.
		// Example: Index is out of bounds in rodb.h, line 118
		return what_.compare(0, what_.size(), e.what(), 0, std::min(what_.size(), strlen(e.what()))) == 0;
	}

private:
	std::string what_;
};

#define YAML_FILENAME "unit_test.yaml"
#define RODB_FILENAME "unit_test.rodb"

char const *compile_rodb(char const *yaml)
{
	{
		std::ofstream out(YAML_FILENAME);
		out << yaml;
	}

	system("./yaml2rodb.rb " YAML_FILENAME " " RODB_FILENAME);

	return RODB_FILENAME;
}

#define DB(db, yaml) rodb::Database db(compile_rodb(yaml))

BOOST_AUTO_TEST_CASE(create_db)
{
	BOOST_CHECK(rodb::Database::load("") == 0);
	BOOST_REQUIRE_EXCEPTION(rodb::Database(""), std::runtime_error, WhatIs("Cannot open input file"));
}

BOOST_AUTO_TEST_CASE(scalar)
{
	DB(db, "[0]");

	BOOST_CHECK(db.root()[0].is_scalar());
	BOOST_CHECK(db.root()[0].size() == 1);
}

BOOST_AUTO_TEST_CASE(access_array)
{
	DB(db, "[0, 1, 2, 3, 4]");

	BOOST_CHECK(db.root().is_array());
	BOOST_CHECK(db.root().is_compound());

	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root()[0] == 0);
	BOOST_CHECK(db.root()[1] == 1);
	BOOST_CHECK(db.root()[2] == 2);
	BOOST_CHECK(db.root()[3] == 3);
	BOOST_CHECK(db.root()[4] == 4);

	BOOST_REQUIRE_EXCEPTION(db.root()[-1], std::runtime_error, WhatStartsWith("Index is out of bounds"));
	BOOST_REQUIRE_EXCEPTION(db.root()[5], std::runtime_error, WhatStartsWith("Index is out of bounds"));
}

BOOST_AUTO_TEST_CASE(access_map)
{
	DB(db, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db.root().is_map());
	BOOST_CHECK(db.root().is_compound());

	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root().keys().is_array());
	BOOST_CHECK(db.root().keys().size() == 5);

	BOOST_CHECK(strcmp(db.root().keys()[0], "key0") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[1], "key1") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[2], "key2") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[3], "key3") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[4], "key4") == 0);

	BOOST_CHECK(db.root().has_key("key0"));
	BOOST_CHECK(db.root().has_key("key1"));
	BOOST_CHECK(db.root().has_key("key2"));
	BOOST_CHECK(db.root().has_key("key3"));
	BOOST_CHECK(db.root().has_key("key4"));

	BOOST_CHECK(!db.root().has_key(""));
	BOOST_CHECK(!db.root().has_key("key5"));

	BOOST_CHECK(db.root().values().is_array());
	BOOST_CHECK(db.root().values().size() == 5);

	BOOST_CHECK(db.root().values()[0] == 0);
	BOOST_CHECK(db.root().values()[1] == 1);
	BOOST_CHECK(db.root().values()[2] == 2);
	BOOST_CHECK(db.root().values()[3] == 3);
	BOOST_CHECK(db.root().values()[4] == 4);

	BOOST_CHECK(db.root()["key0"] == 0);
	BOOST_CHECK(db.root()["key1"] == 1);
	BOOST_CHECK(db.root()["key2"] == 2);
	BOOST_CHECK(db.root()["key3"] == 3);
	BOOST_CHECK(db.root()["key4"] == 4);

	BOOST_REQUIRE_EXCEPTION(db.root()[""], std::runtime_error, WhatStartsWith("Key is not in the map"));
	BOOST_REQUIRE_EXCEPTION(db.root()["key5"], std::runtime_error, WhatStartsWith("Key is not in the map"));
}

BOOST_AUTO_TEST_CASE(map_sorted)
{
	DB(db, "{key4: 4, key0: 0, key2: 2, key1: 1, key3: 3}");

	BOOST_CHECK(strcmp(db.root().keys()[0], db.root().keys()[1]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[1], db.root().keys()[2]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[2], db.root().keys()[3]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[3], db.root().keys()[4]) <= 0);

	BOOST_CHECK(db.root()["key0"] == 0);
	BOOST_CHECK(db.root()["key1"] == 1);
	BOOST_CHECK(db.root()["key2"] == 2);
	BOOST_CHECK(db.root()["key3"] == 3);
	BOOST_CHECK(db.root()["key4"] == 4);
}

BOOST_AUTO_TEST_CASE(map_sorted_equal)
{
	DB(db1, "{key4: 4, key0: 0, key2: 2, key1: 1, key3: 3}");
	DB(db2, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db1.root() == db2.root());
}

BOOST_AUTO_TEST_CASE(numbers)
{
	DB(db, "[false, true, 0, 1000, 0x7fffffff, 0xffffffff, 0.0, 100.0, 1000.0, -10000.0]");

	// Bools
	BOOST_CHECK(db.root()[0].is_bool());
	BOOST_CHECK(db.root()[1].is_bool());

	BOOST_CHECK(!db.root()[0]);
	BOOST_CHECK(db.root()[1]);

	// Ints
	BOOST_CHECK(db.root()[2].is_int());
	BOOST_CHECK(db.root()[3].is_int());
	BOOST_CHECK(db.root()[4].is_int());
	BOOST_CHECK(db.root()[5].is_int());

	BOOST_CHECK(db.root()[2] == 0);
	BOOST_CHECK(db.root()[3] == 1000);
	BOOST_CHECK(db.root()[4] == 0x7fffffff);
	BOOST_CHECK(db.root()[5] == 0xffffffffu);

	// Floats
	BOOST_CHECK(db.root()[6].is_float());
	BOOST_CHECK(db.root()[7].is_float());
	BOOST_CHECK(db.root()[8].is_float());
	BOOST_CHECK(db.root()[9].is_float());

	BOOST_CHECK(db.root()[6] == 0.0f);
	BOOST_CHECK(db.root()[7] == 100.0f);
	BOOST_CHECK(db.root()[8] == 1000.0f);
	BOOST_CHECK(db.root()[9] == -10000.0f);
}

BOOST_AUTO_TEST_CASE(strings)
{
	DB(db, "[string0, string1, string2, string3]");

	BOOST_CHECK(db.root()[0].is_string());
	BOOST_CHECK(db.root()[1].is_string());
	BOOST_CHECK(db.root()[2].is_string());

	BOOST_CHECK(strcmp(db.root()[0], "string0") == 0);
	BOOST_CHECK(db.root()[0] == "string0");
	BOOST_CHECK("string0" == db.root()[0]);

	BOOST_CHECK(strcmp(db.root()[1], "string1") == 0);
	BOOST_CHECK(db.root()[1] == "string1");
	BOOST_CHECK("string1" == db.root()[1]);

	BOOST_CHECK(strcmp(db.root()[2], "string2") == 0);
	BOOST_CHECK(db.root()[2] == "string2");
	BOOST_CHECK("string2" == db.root()[2]);

	BOOST_CHECK(strcmp(db.root()[3], "string3") == 0);
	BOOST_CHECK(db.root()[3] == "string3");
	BOOST_CHECK("string3" == db.root()[3]);
}

BOOST_AUTO_TEST_CASE(nested_arrays)
{
	DB(db, "[[0], [1, 2], [3, 4, 5], [[0]], [[[0]]]]");

	BOOST_CHECK(db.root().is_array());
	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root()[0].is_array());
	BOOST_CHECK(db.root()[0].size() == 1);

	BOOST_CHECK(db.root()[1].is_array());
	BOOST_CHECK(db.root()[1].size() == 2);

	BOOST_CHECK(db.root()[2].is_array());
	BOOST_CHECK(db.root()[2].size() == 3);

	BOOST_CHECK(db.root()[3].is_array());
	BOOST_CHECK(db.root()[3][0].is_array());
	BOOST_CHECK(db.root()[3][0].size() == 1);

	BOOST_CHECK(db.root()[4].is_array());
	BOOST_CHECK(db.root()[4][0].is_array());
	BOOST_CHECK(db.root()[4][0].size() == 1);
	BOOST_CHECK(db.root()[4][0][0].size() == 1);
}

BOOST_AUTO_TEST_CASE(dump_yaml)
{
	DB(db1, "[[0], [1, 2], [3, 4, 5], [[0]], [[[0]]]]");

	std::ostringstream stream;
	db1.dump_yaml(stream);

	DB(db2, stream.str().c_str());
	BOOST_CHECK(db2.root().size() == 5);
	BOOST_CHECK(db2.root()[4][0][0][0] == 0);
}

BOOST_AUTO_TEST_CASE(comparison)
{
	DB(db, "[10, 10, [10], [10], [10, 20], [20, 10], {a: b, cc: dd}, {cc: dd, a: b}, {a: dd, cc: b}, {cc: dd, a: b}]");

	BOOST_CHECK(db.root()[0] == db.root()[1]);
	BOOST_CHECK(db.root()[2] == db.root()[3]);
	BOOST_CHECK(db.root()[4] != db.root()[5]);
	BOOST_CHECK(db.root()[6] == db.root()[7]);
	BOOST_CHECK(db.root()[8] != db.root()[9]);
	BOOST_CHECK(db.root()[0] != db.root()[2]);
	BOOST_CHECK(db.root()[1] != db.root()[6]);
	BOOST_CHECK(db.root()[4] != db.root()[9]);
}

BOOST_AUTO_TEST_CASE(direct_database_root_array_access)
{
	DB(db, "[0, 1, 2, 3, 4]");

	BOOST_CHECK(db[0] == 0);
	BOOST_CHECK(db[1] == 1);
	BOOST_CHECK(db[2] == 2);
	BOOST_CHECK(db[3] == 3);
	BOOST_CHECK(db[4] == 4);

	BOOST_CHECK(db[0] == db.root()[0]);
	BOOST_CHECK(db[1] == db.root()[1]);
	BOOST_CHECK(db[2] == db.root()[2]);
	BOOST_CHECK(db[3] == db.root()[3]);
	BOOST_CHECK(db[4] == db.root()[4]);
}

BOOST_AUTO_TEST_CASE(direct_database_root_map_access)
{
	DB(db, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db["key0"] == 0);
	BOOST_CHECK(db["key1"] == 1);
	BOOST_CHECK(db["key2"] == 2);
	BOOST_CHECK(db["key3"] == 3);
	BOOST_CHECK(db["key4"] == 4);

	BOOST_CHECK(db["key0"] == db.root()["key0"]);
	BOOST_CHECK(db["key1"] == db.root()["key1"]);
	BOOST_CHECK(db["key2"] == db.root()["key2"]);
	BOOST_CHECK(db["key3"] == db.root()["key3"]);
	BOOST_CHECK(db["key4"] == db.root()["key4"]);
}
<commit_msg>Test empty map<commit_after>#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE rodb
#include <boost/test/unit_test.hpp>

#include "rodb.h"

class WhatIs
{
public:
	WhatIs(char const *what): what_(what)
	{
	}

	bool operator ()(std::exception const &e)
	{
		return what_ == e.what();
	}

private:
	std::string what_;
};

class WhatStartsWith
{
public:
	WhatStartsWith(char const *what): what_(what)
	{
	}

	bool operator ()(std::exception const &e)
	{
		// Check that e.what() start with what_.  It's needed because e.what() might
		// have source file location information appended to it.
		// Example: Index is out of bounds in rodb.h, line 118
		return what_.compare(0, what_.size(), e.what(), 0, std::min(what_.size(), strlen(e.what()))) == 0;
	}

private:
	std::string what_;
};

#define YAML_FILENAME "unit_test.yaml"
#define RODB_FILENAME "unit_test.rodb"

char const *compile_rodb(char const *yaml)
{
	{
		std::ofstream out(YAML_FILENAME);
		out << yaml;
	}

	system("./yaml2rodb.rb " YAML_FILENAME " " RODB_FILENAME);

	return RODB_FILENAME;
}

#define DB(db, yaml) rodb::Database db(compile_rodb(yaml))

BOOST_AUTO_TEST_CASE(create_db)
{
	BOOST_CHECK(rodb::Database::load("") == 0);
	BOOST_REQUIRE_EXCEPTION(rodb::Database(""), std::runtime_error, WhatIs("Cannot open input file"));
}

BOOST_AUTO_TEST_CASE(scalar)
{
	DB(db, "[0]");

	BOOST_CHECK(db.root()[0].is_scalar());
	BOOST_CHECK(db.root()[0].size() == 1);
}

BOOST_AUTO_TEST_CASE(access_array)
{
	DB(db, "[0, 1, 2, 3, 4]");

	BOOST_CHECK(db.root().is_array());
	BOOST_CHECK(db.root().is_compound());

	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root()[0] == 0);
	BOOST_CHECK(db.root()[1] == 1);
	BOOST_CHECK(db.root()[2] == 2);
	BOOST_CHECK(db.root()[3] == 3);
	BOOST_CHECK(db.root()[4] == 4);

	BOOST_REQUIRE_EXCEPTION(db.root()[-1], std::runtime_error, WhatStartsWith("Index is out of bounds"));
	BOOST_REQUIRE_EXCEPTION(db.root()[5], std::runtime_error, WhatStartsWith("Index is out of bounds"));
}

BOOST_AUTO_TEST_CASE(access_map)
{
	DB(db, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db.root().is_map());
	BOOST_CHECK(db.root().is_compound());

	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root().keys().is_array());
	BOOST_CHECK(db.root().keys().size() == 5);

	BOOST_CHECK(strcmp(db.root().keys()[0], "key0") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[1], "key1") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[2], "key2") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[3], "key3") == 0);
	BOOST_CHECK(strcmp(db.root().keys()[4], "key4") == 0);

	BOOST_CHECK(db.root().has_key("key0"));
	BOOST_CHECK(db.root().has_key("key1"));
	BOOST_CHECK(db.root().has_key("key2"));
	BOOST_CHECK(db.root().has_key("key3"));
	BOOST_CHECK(db.root().has_key("key4"));

	BOOST_CHECK(!db.root().has_key(""));
	BOOST_CHECK(!db.root().has_key("key5"));

	BOOST_CHECK(db.root().values().is_array());
	BOOST_CHECK(db.root().values().size() == 5);

	BOOST_CHECK(db.root().values()[0] == 0);
	BOOST_CHECK(db.root().values()[1] == 1);
	BOOST_CHECK(db.root().values()[2] == 2);
	BOOST_CHECK(db.root().values()[3] == 3);
	BOOST_CHECK(db.root().values()[4] == 4);

	BOOST_CHECK(db.root()["key0"] == 0);
	BOOST_CHECK(db.root()["key1"] == 1);
	BOOST_CHECK(db.root()["key2"] == 2);
	BOOST_CHECK(db.root()["key3"] == 3);
	BOOST_CHECK(db.root()["key4"] == 4);

	BOOST_REQUIRE_EXCEPTION(db.root()[""], std::runtime_error, WhatStartsWith("Key is not in the map"));
	BOOST_REQUIRE_EXCEPTION(db.root()["key5"], std::runtime_error, WhatStartsWith("Key is not in the map"));
}

BOOST_AUTO_TEST_CASE(empty_map)
{
	DB(db, "{}");

	BOOST_CHECK(db.root().size() == 0);

	BOOST_CHECK(!db.root().has_key(""));
	BOOST_CHECK(!db.root().has_key("key0"));

	BOOST_REQUIRE_EXCEPTION(db.root()[""], std::runtime_error, WhatStartsWith("Key is not in the map"));
	BOOST_REQUIRE_EXCEPTION(db.root()["key0"], std::runtime_error, WhatStartsWith("Key is not in the map"));
}

BOOST_AUTO_TEST_CASE(map_sorted)
{
	DB(db, "{key4: 4, key0: 0, key2: 2, key1: 1, key3: 3}");

	BOOST_CHECK(strcmp(db.root().keys()[0], db.root().keys()[1]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[1], db.root().keys()[2]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[2], db.root().keys()[3]) <= 0);
	BOOST_CHECK(strcmp(db.root().keys()[3], db.root().keys()[4]) <= 0);

	BOOST_CHECK(db.root()["key0"] == 0);
	BOOST_CHECK(db.root()["key1"] == 1);
	BOOST_CHECK(db.root()["key2"] == 2);
	BOOST_CHECK(db.root()["key3"] == 3);
	BOOST_CHECK(db.root()["key4"] == 4);
}

BOOST_AUTO_TEST_CASE(map_sorted_equal)
{
	DB(db1, "{key4: 4, key0: 0, key2: 2, key1: 1, key3: 3}");
	DB(db2, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db1.root() == db2.root());
}

BOOST_AUTO_TEST_CASE(numbers)
{
	DB(db, "[false, true, 0, 1000, 0x7fffffff, 0xffffffff, 0.0, 100.0, 1000.0, -10000.0]");

	// Bools
	BOOST_CHECK(db.root()[0].is_bool());
	BOOST_CHECK(db.root()[1].is_bool());

	BOOST_CHECK(!db.root()[0]);
	BOOST_CHECK(db.root()[1]);

	// Ints
	BOOST_CHECK(db.root()[2].is_int());
	BOOST_CHECK(db.root()[3].is_int());
	BOOST_CHECK(db.root()[4].is_int());
	BOOST_CHECK(db.root()[5].is_int());

	BOOST_CHECK(db.root()[2] == 0);
	BOOST_CHECK(db.root()[3] == 1000);
	BOOST_CHECK(db.root()[4] == 0x7fffffff);
	BOOST_CHECK(db.root()[5] == 0xffffffffu);

	// Floats
	BOOST_CHECK(db.root()[6].is_float());
	BOOST_CHECK(db.root()[7].is_float());
	BOOST_CHECK(db.root()[8].is_float());
	BOOST_CHECK(db.root()[9].is_float());

	BOOST_CHECK(db.root()[6] == 0.0f);
	BOOST_CHECK(db.root()[7] == 100.0f);
	BOOST_CHECK(db.root()[8] == 1000.0f);
	BOOST_CHECK(db.root()[9] == -10000.0f);
}

BOOST_AUTO_TEST_CASE(strings)
{
	DB(db, "[string0, string1, string2, string3]");

	BOOST_CHECK(db.root()[0].is_string());
	BOOST_CHECK(db.root()[1].is_string());
	BOOST_CHECK(db.root()[2].is_string());

	BOOST_CHECK(strcmp(db.root()[0], "string0") == 0);
	BOOST_CHECK(db.root()[0] == "string0");
	BOOST_CHECK("string0" == db.root()[0]);

	BOOST_CHECK(strcmp(db.root()[1], "string1") == 0);
	BOOST_CHECK(db.root()[1] == "string1");
	BOOST_CHECK("string1" == db.root()[1]);

	BOOST_CHECK(strcmp(db.root()[2], "string2") == 0);
	BOOST_CHECK(db.root()[2] == "string2");
	BOOST_CHECK("string2" == db.root()[2]);

	BOOST_CHECK(strcmp(db.root()[3], "string3") == 0);
	BOOST_CHECK(db.root()[3] == "string3");
	BOOST_CHECK("string3" == db.root()[3]);
}

BOOST_AUTO_TEST_CASE(nested_arrays)
{
	DB(db, "[[0], [1, 2], [3, 4, 5], [[0]], [[[0]]]]");

	BOOST_CHECK(db.root().is_array());
	BOOST_CHECK(db.root().size() == 5);

	BOOST_CHECK(db.root()[0].is_array());
	BOOST_CHECK(db.root()[0].size() == 1);

	BOOST_CHECK(db.root()[1].is_array());
	BOOST_CHECK(db.root()[1].size() == 2);

	BOOST_CHECK(db.root()[2].is_array());
	BOOST_CHECK(db.root()[2].size() == 3);

	BOOST_CHECK(db.root()[3].is_array());
	BOOST_CHECK(db.root()[3][0].is_array());
	BOOST_CHECK(db.root()[3][0].size() == 1);

	BOOST_CHECK(db.root()[4].is_array());
	BOOST_CHECK(db.root()[4][0].is_array());
	BOOST_CHECK(db.root()[4][0].size() == 1);
	BOOST_CHECK(db.root()[4][0][0].size() == 1);
}

BOOST_AUTO_TEST_CASE(dump_yaml)
{
	DB(db1, "[[0], [1, 2], [3, 4, 5], [[0]], [[[0]]]]");

	std::ostringstream stream;
	db1.dump_yaml(stream);

	DB(db2, stream.str().c_str());
	BOOST_CHECK(db2.root().size() == 5);
	BOOST_CHECK(db2.root()[4][0][0][0] == 0);
}

BOOST_AUTO_TEST_CASE(comparison)
{
	DB(db, "[10, 10, [10], [10], [10, 20], [20, 10], {a: b, cc: dd}, {cc: dd, a: b}, {a: dd, cc: b}, {cc: dd, a: b}]");

	BOOST_CHECK(db.root()[0] == db.root()[1]);
	BOOST_CHECK(db.root()[2] == db.root()[3]);
	BOOST_CHECK(db.root()[4] != db.root()[5]);
	BOOST_CHECK(db.root()[6] == db.root()[7]);
	BOOST_CHECK(db.root()[8] != db.root()[9]);
	BOOST_CHECK(db.root()[0] != db.root()[2]);
	BOOST_CHECK(db.root()[1] != db.root()[6]);
	BOOST_CHECK(db.root()[4] != db.root()[9]);
}

BOOST_AUTO_TEST_CASE(direct_database_root_array_access)
{
	DB(db, "[0, 1, 2, 3, 4]");

	BOOST_CHECK(db[0] == 0);
	BOOST_CHECK(db[1] == 1);
	BOOST_CHECK(db[2] == 2);
	BOOST_CHECK(db[3] == 3);
	BOOST_CHECK(db[4] == 4);

	BOOST_CHECK(db[0] == db.root()[0]);
	BOOST_CHECK(db[1] == db.root()[1]);
	BOOST_CHECK(db[2] == db.root()[2]);
	BOOST_CHECK(db[3] == db.root()[3]);
	BOOST_CHECK(db[4] == db.root()[4]);
}

BOOST_AUTO_TEST_CASE(direct_database_root_map_access)
{
	DB(db, "{key0: 0, key1: 1, key2: 2, key3: 3, key4: 4}");

	BOOST_CHECK(db["key0"] == 0);
	BOOST_CHECK(db["key1"] == 1);
	BOOST_CHECK(db["key2"] == 2);
	BOOST_CHECK(db["key3"] == 3);
	BOOST_CHECK(db["key4"] == 4);

	BOOST_CHECK(db["key0"] == db.root()["key0"]);
	BOOST_CHECK(db["key1"] == db.root()["key1"]);
	BOOST_CHECK(db["key2"] == db.root()["key2"]);
	BOOST_CHECK(db["key3"] == db.root()["key3"]);
	BOOST_CHECK(db["key4"] == db.root()["key4"]);
}
<|endoftext|>


<commit_before>#include <mlopen/handle.hpp>
#include <mlopen/errors.hpp>
#include <algorithm>

namespace mlopen {

struct HandleImpl
{
    // typedef MLOPEN_MANAGE_PTR(hipStream_t, hipStreamDestroy) StreamPtr;
    typedef std::shared_ptr<typename std::remove_pointer<hipStream_t>::type> StreamPtr;

    StreamPtr create_stream()
    {
        hipStream_t result;
        auto status = hipStreamCreate(&result);
        if (status != hipSuccess) MLOPEN_THROW("Failed to allocate stream");
        return StreamPtr{result, &hipStreamDestroy};
    }

    static StreamPtr reference_stream(hipStream_t s)
    {
        return StreamPtr{s, null_deleter{}};
    }

    std::vector<StreamPtr> streams;
};

Handle::Handle (int numStreams, mlopenAcceleratorQueue_t *streams)
: impl(new HandleImpl())
{
    std::transform(streams, streams+numStreams, std::back_inserter(this->impl->streams), [](hipStream_t x) {
        return HandleImpl::reference_stream(x);
    });
}

Handle::Handle ()
: impl(new HandleImpl())
{
    this->impl->streams.push_back(impl->create_stream());
}

Handle::~Handle() {}

mlopenAcceleratorQueue_t Handle::GetStream() const
{
    return impl->streams.front().get();
}

void Handle::EnableProfiling(bool enable)
{
    // TODO
}

float Handle::GetKernelTime() const
{
    return 0.0;
}

ManageDataPtr Handle::Create(int sz)
{
    void * result;
    auto status = hipMalloc(&result, sz);
    if (status != hipSuccess) MLOPEN_THROW("Hip error creating buffer: " + std::to_string(status));
    return ManageDataPtr{result};
}
ManageDataPtr& Handle::WriteTo(const void* data, ManageDataPtr& ddata, int sz)
{
    auto status = hipMemcpy(ddata.get(), data, sz, hipMemcpyHostToDevice);
    if (status != hipSuccess) MLOPEN_THROW("Hip error writing to buffer: " + std::to_string(status));
    return ddata;
}
void Handle::ReadTo(void* data, const ManageDataPtr& ddata, int sz)
{
    auto status = hipMemcpy(data, ddata.get(), sz, hipMemcpyDeviceToHost);
    if (status != hipSuccess) MLOPEN_THROW("Hip error reading from buffer: " + std::to_string(status));
}
}

<commit_msg>Add flag for enabling profiling<commit_after>#include <mlopen/handle.hpp>
#include <mlopen/errors.hpp>
#include <algorithm>

namespace mlopen {

struct HandleImpl
{
    // typedef MLOPEN_MANAGE_PTR(hipStream_t, hipStreamDestroy) StreamPtr;
    typedef std::shared_ptr<typename std::remove_pointer<hipStream_t>::type> StreamPtr;

    StreamPtr create_stream()
    {
        hipStream_t result;
        auto status = hipStreamCreate(&result);
        if (status != hipSuccess) MLOPEN_THROW("Failed to allocate stream");
        return StreamPtr{result, &hipStreamDestroy};
    }

    static StreamPtr reference_stream(hipStream_t s)
    {
        return StreamPtr{s, null_deleter{}};
    }

    bool enable_profiling = false;
    std::vector<StreamPtr> streams;
};

Handle::Handle (int numStreams, mlopenAcceleratorQueue_t *streams)
: impl(new HandleImpl())
{
    std::transform(streams, streams+numStreams, std::back_inserter(this->impl->streams), [](hipStream_t x) {
        return HandleImpl::reference_stream(x);
    });
}

Handle::Handle ()
: impl(new HandleImpl())
{
    this->impl->streams.push_back(impl->create_stream());
}

Handle::~Handle() {}

mlopenAcceleratorQueue_t Handle::GetStream() const
{
    return impl->streams.front().get();
}

void Handle::EnableProfiling(bool enable)
{
    this->impl->enable_profiling = enable;
}

float Handle::GetKernelTime() const
{
    // TODO: Temporary hack until the kernels are added
    if (this->impl->enable_profiling) return 1.0;
    else return 0.0;
}

ManageDataPtr Handle::Create(int sz)
{
    void * result;
    auto status = hipMalloc(&result, sz);
    if (status != hipSuccess) MLOPEN_THROW("Hip error creating buffer: " + std::to_string(status));
    return ManageDataPtr{result};
}
ManageDataPtr& Handle::WriteTo(const void* data, ManageDataPtr& ddata, int sz)
{
    auto status = hipMemcpy(ddata.get(), data, sz, hipMemcpyHostToDevice);
    if (status != hipSuccess) MLOPEN_THROW("Hip error writing to buffer: " + std::to_string(status));
    return ddata;
}
void Handle::ReadTo(void* data, const ManageDataPtr& ddata, int sz)
{
    auto status = hipMemcpy(data, ddata.get(), sz, hipMemcpyDeviceToHost);
    if (status != hipSuccess) MLOPEN_THROW("Hip error reading from buffer: " + std::to_string(status));
}
}

<|endoftext|>


<commit_before>#ifndef UTILITY_H
#define UTILITY_H

#include <string>
#include <vector>
#include <sstream>
#include <omp.h>
#include <cstring>
#include <algorithm>
#include <unistd.h>
#include "vg.pb.h"
#include "sha1.hpp"
#include "Variant.h"

namespace vg {

using namespace std;

char reverse_complement(const char& c);
string reverse_complement(const string& seq);
int get_thread_count(void);
string wrap_text(const string& str, size_t width);
bool is_number(const string& s);

// split a string on any character found in the string of delimiters (delims)
std::vector<std::string>& split_delims(const std::string &s, const std::string& delims, std::vector<std::string> &elems);
std::vector<std::string> split_delims(const std::string &s, const std::string& delims);

const std::string sha1sum(const std::string& data);
const std::string sha1head(const std::string& data, size_t head);

bool allATGC(const string& s);
string nonATGCNtoN(const string& s);
void mapping_cigar(const Mapping& mapping, vector<pair<int, char> >& cigar);
string cigar_string(vector<pair<int, char> >& cigar);
string mapping_string(const string& source, const Mapping& mapping);
double median(std::vector<int> &v);

// Convert a probability to a natural log probability.
inline double prob_to_logprob(double prob) {
    return log(prob);
}
// Convert natural log probability to a probability
inline double logprob_to_prob(double logprob) {
    return exp(logprob);
}
// Add two probabilities (expressed as logprobs) together and return the result
// as a logprob.
inline double logprob_add(double logprob1, double logprob2) {
    // Pull out the larger one to avoid underflows
    double pulled_out = max(logprob1, logprob2);
    return pulled_out + prob_to_logprob(logprob_to_prob(logprob1 - pulled_out) + logprob_to_prob(logprob2 - pulled_out));
}
// Invert a logprob, and get the probability of its opposite.
inline double logprob_invert(double logprob) {
    return prob_to_logprob(1.0 - logprob_to_prob(logprob));
}

// Convert integer Phred quality score to probability of wrongness.
inline double phred_to_prob(int phred) {
    return pow(10, -((double)phred) / 10);
}

// Convert probability of wrongness to integer Phred quality score.
inline int prob_to_phred(double prob) {
    return round(-10.0 * log10(prob));
}

// Convert a Phred quality score directly to a natural log probability of wrongness.
inline double phred_to_logprob(int phred) {
    return (-((double)phred) / 10) / log10(exp(1.0));
}

// Convert a natural log probability of wrongness directly to a Phred quality score.
inline int logprob_to_phred(double logprob ) {
    return round(-10.0 * logprob * log10(exp(1.0)));
}

template<typename T, typename V>
set<T> map_keys_to_set(const map<T, V>& m) {
    set<T> r;
    for (auto p : m) r.insert(p.first);
    return r;
}

// pairwise maximum
template<typename T>
vector<T> pmax(const std::vector<T>& a, const std::vector<T>& b) {
    std::vector<T> c;
    assert(a.size() == b.size());
    c.reserve(a.size());
    std::transform(a.begin(), a.end(), b.begin(),
                   std::back_inserter(c),
                   [](T a, T b) { return std::max<T>(a, b); });
    return c;
}

// maximum of all vectors
template<typename T>
vector<T> vpmax(const std::vector<std::vector<T>>& vv) {
    std::vector<T> c;
    if (vv.empty()) return c;
    c = vv.front();
    typename std::vector<std::vector<T> >::const_iterator v = vv.begin();
    ++v; // skip the first element
    for ( ; v != vv.end(); ++v) {
        c = pmax(c, *v);
    }
    return c;
}

/**
 * Compute the sum of the values in a collection. Values must be default-
 * constructable (like numbers are).
 */
template<typename Collection>
typename Collection::value_type sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Make a new zero-valued item to hold the sum
    auto total = Item();
    for(auto& to_sum : collection) {
        total += to_sum;
    }

    return total;

}

/**
 * Compute the sum of the values in a collection, where the values are log
 * probabilities and the result is the log of the total probability. Items must
 * be convertible to/from doubles for math.
 */
template<typename Collection>
typename Collection::value_type logprob_sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Pull out the minimum value
    auto min_iterator = min_element(begin(collection), end(collection));

    if(min_iterator == end(collection)) {
        // Nothing there, p = 0
        return Item(prob_to_logprob(0));
    }

    auto check_iterator = begin(collection);
    ++check_iterator;
    if(check_iterator == end(collection)) {
        // We only have a single element anyway. We don't want to subtract it
        // out because we'll get 0s.
        return *min_iterator;
    }

    // Pull this much out of every logprob.
    Item pulled_out = *min_iterator;

    if(logprob_to_prob(pulled_out) == 0) {
        // Can't divide by 0!
        // TODO: fix this in selection
        pulled_out = prob_to_logprob(1);
    }

    Item total(0);
    for(auto& to_add : collection) {
        // Sum up all the scaled probabilities.
        total += logprob_to_prob(to_add - pulled_out);
    }

    // Re-log and re-scale
    return pulled_out + prob_to_logprob(total);
}

string tmpfilename(const string& base);

// Code to detect if a variant lacks an ID and give it a unique but repeatable
// one.
string get_or_make_variant_id(vcflib::Variant variant);

// Simple little tree
template<typename T>
struct TreeNode {
    T v;
    vector<TreeNode<T>*> children;
    ~TreeNode() { for (auto c : children) { delete c; } }
    void for_each_preorder(function<void(TreeNode<T>*)> lambda) {
        lambda(this);
        for (auto c : children) {
            c->for_each_preorder(lambda);
        }
    }
    void for_each_postorder(function<void(TreeNode<T>*)> lambda) {
        for (auto c : children) {
            c->for_each_preorder(lambda);
        }
        lambda(this);
    }
};

template<typename T>
struct Tree {
    typedef TreeNode<T> Node;
    Node* root;
    Tree(Node* r = 0) : root(r) {}
    ~Tree() { delete root; }
    void for_each_preorder(function<void(Node*)> lambda) {
        if (root) root->for_each_preorder(lambda);
    }
    void for_each_postorder(function<void(Node*)> lambda) {
       if (root) root->for_each_postorder(lambda);
    }

};

}

#endif
<commit_msg>Fix postorder to recurse as postorder and not preorder<commit_after>#ifndef UTILITY_H
#define UTILITY_H

#include <string>
#include <vector>
#include <sstream>
#include <omp.h>
#include <cstring>
#include <algorithm>
#include <unistd.h>
#include "vg.pb.h"
#include "sha1.hpp"
#include "Variant.h"

namespace vg {

using namespace std;

char reverse_complement(const char& c);
string reverse_complement(const string& seq);
int get_thread_count(void);
string wrap_text(const string& str, size_t width);
bool is_number(const string& s);

// split a string on any character found in the string of delimiters (delims)
std::vector<std::string>& split_delims(const std::string &s, const std::string& delims, std::vector<std::string> &elems);
std::vector<std::string> split_delims(const std::string &s, const std::string& delims);

const std::string sha1sum(const std::string& data);
const std::string sha1head(const std::string& data, size_t head);

bool allATGC(const string& s);
string nonATGCNtoN(const string& s);
void mapping_cigar(const Mapping& mapping, vector<pair<int, char> >& cigar);
string cigar_string(vector<pair<int, char> >& cigar);
string mapping_string(const string& source, const Mapping& mapping);
double median(std::vector<int> &v);

// Convert a probability to a natural log probability.
inline double prob_to_logprob(double prob) {
    return log(prob);
}
// Convert natural log probability to a probability
inline double logprob_to_prob(double logprob) {
    return exp(logprob);
}
// Add two probabilities (expressed as logprobs) together and return the result
// as a logprob.
inline double logprob_add(double logprob1, double logprob2) {
    // Pull out the larger one to avoid underflows
    double pulled_out = max(logprob1, logprob2);
    return pulled_out + prob_to_logprob(logprob_to_prob(logprob1 - pulled_out) + logprob_to_prob(logprob2 - pulled_out));
}
// Invert a logprob, and get the probability of its opposite.
inline double logprob_invert(double logprob) {
    return prob_to_logprob(1.0 - logprob_to_prob(logprob));
}

// Convert integer Phred quality score to probability of wrongness.
inline double phred_to_prob(int phred) {
    return pow(10, -((double)phred) / 10);
}

// Convert probability of wrongness to integer Phred quality score.
inline int prob_to_phred(double prob) {
    return round(-10.0 * log10(prob));
}

// Convert a Phred quality score directly to a natural log probability of wrongness.
inline double phred_to_logprob(int phred) {
    return (-((double)phred) / 10) / log10(exp(1.0));
}

// Convert a natural log probability of wrongness directly to a Phred quality score.
inline int logprob_to_phred(double logprob ) {
    return round(-10.0 * logprob * log10(exp(1.0)));
}

template<typename T, typename V>
set<T> map_keys_to_set(const map<T, V>& m) {
    set<T> r;
    for (auto p : m) r.insert(p.first);
    return r;
}

// pairwise maximum
template<typename T>
vector<T> pmax(const std::vector<T>& a, const std::vector<T>& b) {
    std::vector<T> c;
    assert(a.size() == b.size());
    c.reserve(a.size());
    std::transform(a.begin(), a.end(), b.begin(),
                   std::back_inserter(c),
                   [](T a, T b) { return std::max<T>(a, b); });
    return c;
}

// maximum of all vectors
template<typename T>
vector<T> vpmax(const std::vector<std::vector<T>>& vv) {
    std::vector<T> c;
    if (vv.empty()) return c;
    c = vv.front();
    typename std::vector<std::vector<T> >::const_iterator v = vv.begin();
    ++v; // skip the first element
    for ( ; v != vv.end(); ++v) {
        c = pmax(c, *v);
    }
    return c;
}

/**
 * Compute the sum of the values in a collection. Values must be default-
 * constructable (like numbers are).
 */
template<typename Collection>
typename Collection::value_type sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Make a new zero-valued item to hold the sum
    auto total = Item();
    for(auto& to_sum : collection) {
        total += to_sum;
    }

    return total;

}

/**
 * Compute the sum of the values in a collection, where the values are log
 * probabilities and the result is the log of the total probability. Items must
 * be convertible to/from doubles for math.
 */
template<typename Collection>
typename Collection::value_type logprob_sum(const Collection& collection) {

    // Set up an alias
    using Item = typename Collection::value_type;

    // Pull out the minimum value
    auto min_iterator = min_element(begin(collection), end(collection));

    if(min_iterator == end(collection)) {
        // Nothing there, p = 0
        return Item(prob_to_logprob(0));
    }

    auto check_iterator = begin(collection);
    ++check_iterator;
    if(check_iterator == end(collection)) {
        // We only have a single element anyway. We don't want to subtract it
        // out because we'll get 0s.
        return *min_iterator;
    }

    // Pull this much out of every logprob.
    Item pulled_out = *min_iterator;

    if(logprob_to_prob(pulled_out) == 0) {
        // Can't divide by 0!
        // TODO: fix this in selection
        pulled_out = prob_to_logprob(1);
    }

    Item total(0);
    for(auto& to_add : collection) {
        // Sum up all the scaled probabilities.
        total += logprob_to_prob(to_add - pulled_out);
    }

    // Re-log and re-scale
    return pulled_out + prob_to_logprob(total);
}

string tmpfilename(const string& base);

// Code to detect if a variant lacks an ID and give it a unique but repeatable
// one.
string get_or_make_variant_id(vcflib::Variant variant);

// Simple little tree
template<typename T>
struct TreeNode {
    T v;
    vector<TreeNode<T>*> children;
    ~TreeNode() { for (auto c : children) { delete c; } }
    void for_each_preorder(function<void(TreeNode<T>*)> lambda) {
        lambda(this);
        for (auto c : children) {
            c->for_each_preorder(lambda);
        }
    }
    void for_each_postorder(function<void(TreeNode<T>*)> lambda) {
        for (auto c : children) {
            c->for_each_postorder(lambda);
        }
        lambda(this);
    }
};

template<typename T>
struct Tree {
    typedef TreeNode<T> Node;
    Node* root;
    Tree(Node* r = 0) : root(r) {}
    ~Tree() { delete root; }
    void for_each_preorder(function<void(Node*)> lambda) {
        if (root) root->for_each_preorder(lambda);
    }
    void for_each_postorder(function<void(Node*)> lambda) {
       if (root) root->for_each_postorder(lambda);
    }

};

}

#endif
<|endoftext|>


<commit_before><commit_msg>Fix forwardJacDot calls in QPControllermex<commit_after><|endoftext|>