<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"

#include "base/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_factory.h"
#include "chrome/browser/renderer_host/render_widget_host_view_views.h"
#include "chrome/browser/tab_contents/interstitial_page.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/views/sad_tab_view.h"
#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
#include "gfx/canvas_skia_paint.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "gfx/size.h"
#include "views/controls/native/native_view_host.h"
#include "views/fill_layout.h"
#include "views/focus/focus_manager.h"
#include "views/focus/view_storage.h"
#include "views/screen.h"
#include "views/widget/widget.h"

using WebKit::WebDragOperation;
using WebKit::WebDragOperationsMask;
using WebKit::WebInputEvent;

// static
TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
  return new TabContentsViewViews(tab_contents);
}

TabContentsViewViews::TabContentsViewViews(TabContents* tab_contents)
    : TabContentsView(tab_contents),
      sad_tab_(NULL),
      ignore_next_char_event_(false) {
  last_focused_view_storage_id_ =
      views::ViewStorage::GetSharedInstance()->CreateStorageID();
  SetLayoutManager(new views::FillLayout());
}

TabContentsViewViews::~TabContentsViewViews() {
  // Make sure to remove any stored view we may still have in the ViewStorage.
  //
  // It is possible the view went away before us, so we only do this if the
  // view is registered.
  views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
  if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
    view_storage->RemoveView(last_focused_view_storage_id_);
}

void TabContentsViewViews::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  // TODO(anicolao): reimplement all dialogs as DOMUI
  NOTIMPLEMENTED();
}

void TabContentsViewViews::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  // TODO(anicolao): reimplement all dialogs as DOMUI
  NOTIMPLEMENTED();
}

void TabContentsViewViews::CreateView(const gfx::Size& initial_size) {
  SetBounds(gfx::Rect(bounds().origin(), initial_size));
}

RenderWidgetHostView* TabContentsViewViews::CreateViewForWidget(
    RenderWidgetHost* render_widget_host) {
  if (render_widget_host->view()) {
    // During testing, the view will already be set up in most cases to the
    // test view, so we don't want to clobber it with a real one. To verify that
    // this actually is happening (and somebody isn't accidentally creating the
    // view twice), we check for the RVH Factory, which will be set when we're
    // making special ones (which go along with the special views).
    DCHECK(RenderViewHostFactory::has_factory());
    return render_widget_host->view();
  }

  // If we were showing sad tab, remove it now.
  if (sad_tab_ != NULL) {
    RemoveChildView(sad_tab_);
    AddChildView(new views::View());
    sad_tab_ = NULL;
  }

  RenderWidgetHostViewViews* view =
      new RenderWidgetHostViewViews(render_widget_host);
  AddChildView(view);
  view->Show();
  view->InitAsChild();

  // TODO(anicolao): implement drag'n'drop hooks if needed

  return view;
}

gfx::NativeView TabContentsViewViews::GetNativeView() const {
  return GetWidget()->GetNativeView();
}

gfx::NativeView TabContentsViewViews::GetContentNativeView() const {
  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (!rwhv)
    return NULL;
  return rwhv->GetNativeView();
}

gfx::NativeWindow TabContentsViewViews::GetTopLevelNativeWindow() const {
  GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
  return window ? GTK_WINDOW(window) : NULL;
}

void TabContentsViewViews::GetContainerBounds(gfx::Rect* out) const {
  *out = bounds();
}

void TabContentsViewViews::StartDragging(const WebDropData& drop_data,
                                         WebDragOperationsMask ops,
                                         const SkBitmap& image,
                                         const gfx::Point& image_offset) {
  // TODO(anicolao): implement dragging
}

void TabContentsViewViews::SetPageTitle(const std::wstring& title) {
  // TODO(anicolao): figure out if there's anything useful to do here
}

void TabContentsViewViews::OnTabCrashed() {
}

void TabContentsViewViews::SizeContents(const gfx::Size& size) {
  WasSized(size);

  // We need to send this immediately.
  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (rwhv)
    rwhv->SetSize(size);
}

void TabContentsViewViews::Focus() {
  if (tab_contents()->interstitial_page()) {
    tab_contents()->interstitial_page()->Focus();
    return;
  }

  if (tab_contents()->is_crashed() && sad_tab_ != NULL) {
    sad_tab_->RequestFocus();
    return;
  }

  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  gtk_widget_grab_focus(rwhv ? rwhv->GetNativeView() : GetNativeView());
}

void TabContentsViewViews::SetInitialFocus() {
  if (tab_contents()->FocusLocationBarByDefault())
    tab_contents()->SetFocusToLocationBar(false);
  else
    Focus();
}

void TabContentsViewViews::StoreFocus() {
  views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();

  if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
    view_storage->RemoveView(last_focused_view_storage_id_);

  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
  if (focus_manager) {
    // |focus_manager| can be NULL if the tab has been detached but still
    // exists.
    views::View* focused_view = focus_manager->GetFocusedView();
    if (focused_view)
      view_storage->StoreView(last_focused_view_storage_id_, focused_view);
  }
}

void TabContentsViewViews::RestoreFocus() {
  views::ViewStorage* view_storage = views::ViewStorage::GetSharedInstance();
  views::View* last_focused_view =
      view_storage->RetrieveView(last_focused_view_storage_id_);
  if (!last_focused_view) {
    SetInitialFocus();
  } else {
    views::FocusManager* focus_manager =
        views::FocusManager::GetFocusManagerForNativeView(GetNativeView());

    // If you hit this DCHECK, please report it to Jay (jcampan).
    DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";

    if (last_focused_view->IsFocusableInRootView() && focus_manager &&
        focus_manager->ContainsView(last_focused_view)) {
      last_focused_view->RequestFocus();
    } else {
      // The focused view may not belong to the same window hierarchy (e.g.
      // if the location bar was focused and the tab is dragged out), or it may
      // no longer be focusable (e.g. if the location bar was focused and then
      // we switched to fullscreen mode).  In that case we default to the
      // default focus.
      SetInitialFocus();
    }
    view_storage->RemoveView(last_focused_view_storage_id_);
  }
}

void TabContentsViewViews::DidChangeBounds(const gfx::Rect& previous,
                                           const gfx::Rect& current) {
  if (IsVisibleInRootView())
    WasSized(gfx::Size(current.width(), current.height()));
}

void TabContentsViewViews::Paint(gfx::Canvas* canvas) {
}

void TabContentsViewViews::UpdateDragCursor(WebDragOperation operation) {
  NOTIMPLEMENTED();
  // It's not even clear a drag cursor will make sense for touch.
  // TODO(anicolao): implement dragging
}

void TabContentsViewViews::GotFocus() {
  if (tab_contents()->delegate())
    tab_contents()->delegate()->TabContentsFocused(tab_contents());
}

void TabContentsViewViews::TakeFocus(bool reverse) {
  if (tab_contents()->delegate() &&
      !tab_contents()->delegate()->TakeFocus(reverse)) {

    views::FocusManager* focus_manager =
        views::FocusManager::GetFocusManagerForNativeView(GetNativeView());

    // We may not have a focus manager if the tab has been switched before this
    // message arrived.
    if (focus_manager)
      focus_manager->AdvanceFocus(reverse);
  }
}

void TabContentsViewViews::VisibilityChanged(views::View *, bool is_visible) {
  if (is_visible) {
    WasShown();
  } else {
    WasHidden();
  }
}

void TabContentsViewViews::ShowContextMenu(const ContextMenuParams& params) {
  // Allow delegates to handle the context menu operation first.
  if (tab_contents()->delegate()->HandleContextMenu(params))
    return;

  context_menu_.reset(new RenderViewContextMenuViews(tab_contents(), params));
  context_menu_->Init();

  gfx::Point screen_point(params.x, params.y);
  RenderWidgetHostViewViews* rwhv = static_cast<RenderWidgetHostViewViews*>
      (tab_contents()->GetRenderWidgetHostView());
  if (rwhv) {
    views::View::ConvertPointToScreen(rwhv, &screen_point);
  }

  // Enable recursive tasks on the message loop so we can get updates while
  // the context menu is being displayed.
  bool old_state = MessageLoop::current()->NestableTasksAllowed();
  MessageLoop::current()->SetNestableTasksAllowed(true);
  context_menu_->RunMenuAt(screen_point.x(), screen_point.y());
  MessageLoop::current()->SetNestableTasksAllowed(old_state);
}

void TabContentsViewViews::ShowPopupMenu(const gfx::Rect& bounds,
                                         int item_height,
                                         double item_font_size,
                                         int selected_item,
                                         const std::vector<WebMenuItem>& items,
                                         bool right_aligned) {
  // External popup menus are only used on Mac.
  NOTREACHED();
}

void TabContentsViewViews::WasHidden() {
  tab_contents()->HideContents();
}

void TabContentsViewViews::WasShown() {
  tab_contents()->ShowContents();
}

void TabContentsViewViews::WasSized(const gfx::Size& size) {
  // We have to check that the RenderWidgetHostView is the proper size.
  // It can be wrong in cases where the renderer has died and the host
  // view needed to be recreated.
  bool needs_resize = size != size_;

  if (needs_resize) {
    size_ = size;
    if (tab_contents()->interstitial_page())
      tab_contents()->interstitial_page()->SetSize(size);
  }

  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (rwhv && rwhv->GetViewBounds().size() != size)
    rwhv->SetSize(size);

  if (needs_resize)
    SetFloatingPosition(size);
}

void TabContentsViewViews::SetFloatingPosition(const gfx::Size& size) {
  // TODO(anicolao): rework this once we have DOMUI views for dialogs
  SetBounds(x(), y(), size.width(), size.height());
}
<commit_msg>Compile fix for touchui.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/views/tab_contents/tab_contents_view_views.h"

#include "base/string_util.h"
#include "build/build_config.h"
#include "chrome/browser/download/download_shelf.h"
#include "chrome/browser/renderer_host/render_view_host.h"
#include "chrome/browser/renderer_host/render_view_host_factory.h"
#include "chrome/browser/renderer_host/render_widget_host_view_views.h"
#include "chrome/browser/tab_contents/interstitial_page.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/tab_contents/tab_contents_delegate.h"
#include "chrome/browser/views/sad_tab_view.h"
#include "chrome/browser/views/tab_contents/render_view_context_menu_views.h"
#include "gfx/canvas_skia_paint.h"
#include "gfx/point.h"
#include "gfx/rect.h"
#include "gfx/size.h"
#include "views/controls/native/native_view_host.h"
#include "views/fill_layout.h"
#include "views/focus/focus_manager.h"
#include "views/focus/view_storage.h"
#include "views/screen.h"
#include "views/widget/widget.h"

using WebKit::WebDragOperation;
using WebKit::WebDragOperationsMask;
using WebKit::WebInputEvent;

// static
TabContentsView* TabContentsView::Create(TabContents* tab_contents) {
  return new TabContentsViewViews(tab_contents);
}

TabContentsViewViews::TabContentsViewViews(TabContents* tab_contents)
    : TabContentsView(tab_contents),
      sad_tab_(NULL),
      ignore_next_char_event_(false) {
  last_focused_view_storage_id_ =
      views::ViewStorage::GetInstance()->CreateStorageID();
  SetLayoutManager(new views::FillLayout());
}

TabContentsViewViews::~TabContentsViewViews() {
  // Make sure to remove any stored view we may still have in the ViewStorage.
  //
  // It is possible the view went away before us, so we only do this if the
  // view is registered.
  views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
  if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
    view_storage->RemoveView(last_focused_view_storage_id_);
}

void TabContentsViewViews::AttachConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  // TODO(anicolao): reimplement all dialogs as DOMUI
  NOTIMPLEMENTED();
}

void TabContentsViewViews::RemoveConstrainedWindow(
    ConstrainedWindowGtk* constrained_window) {
  // TODO(anicolao): reimplement all dialogs as DOMUI
  NOTIMPLEMENTED();
}

void TabContentsViewViews::CreateView(const gfx::Size& initial_size) {
  SetBounds(gfx::Rect(bounds().origin(), initial_size));
}

RenderWidgetHostView* TabContentsViewViews::CreateViewForWidget(
    RenderWidgetHost* render_widget_host) {
  if (render_widget_host->view()) {
    // During testing, the view will already be set up in most cases to the
    // test view, so we don't want to clobber it with a real one. To verify that
    // this actually is happening (and somebody isn't accidentally creating the
    // view twice), we check for the RVH Factory, which will be set when we're
    // making special ones (which go along with the special views).
    DCHECK(RenderViewHostFactory::has_factory());
    return render_widget_host->view();
  }

  // If we were showing sad tab, remove it now.
  if (sad_tab_ != NULL) {
    RemoveChildView(sad_tab_);
    AddChildView(new views::View());
    sad_tab_ = NULL;
  }

  RenderWidgetHostViewViews* view =
      new RenderWidgetHostViewViews(render_widget_host);
  AddChildView(view);
  view->Show();
  view->InitAsChild();

  // TODO(anicolao): implement drag'n'drop hooks if needed

  return view;
}

gfx::NativeView TabContentsViewViews::GetNativeView() const {
  return GetWidget()->GetNativeView();
}

gfx::NativeView TabContentsViewViews::GetContentNativeView() const {
  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (!rwhv)
    return NULL;
  return rwhv->GetNativeView();
}

gfx::NativeWindow TabContentsViewViews::GetTopLevelNativeWindow() const {
  GtkWidget* window = gtk_widget_get_ancestor(GetNativeView(), GTK_TYPE_WINDOW);
  return window ? GTK_WINDOW(window) : NULL;
}

void TabContentsViewViews::GetContainerBounds(gfx::Rect* out) const {
  *out = bounds();
}

void TabContentsViewViews::StartDragging(const WebDropData& drop_data,
                                         WebDragOperationsMask ops,
                                         const SkBitmap& image,
                                         const gfx::Point& image_offset) {
  // TODO(anicolao): implement dragging
}

void TabContentsViewViews::SetPageTitle(const std::wstring& title) {
  // TODO(anicolao): figure out if there's anything useful to do here
}

void TabContentsViewViews::OnTabCrashed() {
}

void TabContentsViewViews::SizeContents(const gfx::Size& size) {
  WasSized(size);

  // We need to send this immediately.
  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (rwhv)
    rwhv->SetSize(size);
}

void TabContentsViewViews::Focus() {
  if (tab_contents()->interstitial_page()) {
    tab_contents()->interstitial_page()->Focus();
    return;
  }

  if (tab_contents()->is_crashed() && sad_tab_ != NULL) {
    sad_tab_->RequestFocus();
    return;
  }

  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  gtk_widget_grab_focus(rwhv ? rwhv->GetNativeView() : GetNativeView());
}

void TabContentsViewViews::SetInitialFocus() {
  if (tab_contents()->FocusLocationBarByDefault())
    tab_contents()->SetFocusToLocationBar(false);
  else
    Focus();
}

void TabContentsViewViews::StoreFocus() {
  views::ViewStorage* view_storage = views::ViewStorage::GetInstance();

  if (view_storage->RetrieveView(last_focused_view_storage_id_) != NULL)
    view_storage->RemoveView(last_focused_view_storage_id_);

  views::FocusManager* focus_manager =
      views::FocusManager::GetFocusManagerForNativeView(GetNativeView());
  if (focus_manager) {
    // |focus_manager| can be NULL if the tab has been detached but still
    // exists.
    views::View* focused_view = focus_manager->GetFocusedView();
    if (focused_view)
      view_storage->StoreView(last_focused_view_storage_id_, focused_view);
  }
}

void TabContentsViewViews::RestoreFocus() {
  views::ViewStorage* view_storage = views::ViewStorage::GetInstance();
  views::View* last_focused_view =
      view_storage->RetrieveView(last_focused_view_storage_id_);
  if (!last_focused_view) {
    SetInitialFocus();
  } else {
    views::FocusManager* focus_manager =
        views::FocusManager::GetFocusManagerForNativeView(GetNativeView());

    // If you hit this DCHECK, please report it to Jay (jcampan).
    DCHECK(focus_manager != NULL) << "No focus manager when restoring focus.";

    if (last_focused_view->IsFocusableInRootView() && focus_manager &&
        focus_manager->ContainsView(last_focused_view)) {
      last_focused_view->RequestFocus();
    } else {
      // The focused view may not belong to the same window hierarchy (e.g.
      // if the location bar was focused and the tab is dragged out), or it may
      // no longer be focusable (e.g. if the location bar was focused and then
      // we switched to fullscreen mode).  In that case we default to the
      // default focus.
      SetInitialFocus();
    }
    view_storage->RemoveView(last_focused_view_storage_id_);
  }
}

void TabContentsViewViews::DidChangeBounds(const gfx::Rect& previous,
                                           const gfx::Rect& current) {
  if (IsVisibleInRootView())
    WasSized(gfx::Size(current.width(), current.height()));
}

void TabContentsViewViews::Paint(gfx::Canvas* canvas) {
}

void TabContentsViewViews::UpdateDragCursor(WebDragOperation operation) {
  NOTIMPLEMENTED();
  // It's not even clear a drag cursor will make sense for touch.
  // TODO(anicolao): implement dragging
}

void TabContentsViewViews::GotFocus() {
  if (tab_contents()->delegate())
    tab_contents()->delegate()->TabContentsFocused(tab_contents());
}

void TabContentsViewViews::TakeFocus(bool reverse) {
  if (tab_contents()->delegate() &&
      !tab_contents()->delegate()->TakeFocus(reverse)) {

    views::FocusManager* focus_manager =
        views::FocusManager::GetFocusManagerForNativeView(GetNativeView());

    // We may not have a focus manager if the tab has been switched before this
    // message arrived.
    if (focus_manager)
      focus_manager->AdvanceFocus(reverse);
  }
}

void TabContentsViewViews::VisibilityChanged(views::View *, bool is_visible) {
  if (is_visible) {
    WasShown();
  } else {
    WasHidden();
  }
}

void TabContentsViewViews::ShowContextMenu(const ContextMenuParams& params) {
  // Allow delegates to handle the context menu operation first.
  if (tab_contents()->delegate()->HandleContextMenu(params))
    return;

  context_menu_.reset(new RenderViewContextMenuViews(tab_contents(), params));
  context_menu_->Init();

  gfx::Point screen_point(params.x, params.y);
  RenderWidgetHostViewViews* rwhv = static_cast<RenderWidgetHostViewViews*>
      (tab_contents()->GetRenderWidgetHostView());
  if (rwhv) {
    views::View::ConvertPointToScreen(rwhv, &screen_point);
  }

  // Enable recursive tasks on the message loop so we can get updates while
  // the context menu is being displayed.
  bool old_state = MessageLoop::current()->NestableTasksAllowed();
  MessageLoop::current()->SetNestableTasksAllowed(true);
  context_menu_->RunMenuAt(screen_point.x(), screen_point.y());
  MessageLoop::current()->SetNestableTasksAllowed(old_state);
}

void TabContentsViewViews::ShowPopupMenu(const gfx::Rect& bounds,
                                         int item_height,
                                         double item_font_size,
                                         int selected_item,
                                         const std::vector<WebMenuItem>& items,
                                         bool right_aligned) {
  // External popup menus are only used on Mac.
  NOTREACHED();
}

void TabContentsViewViews::WasHidden() {
  tab_contents()->HideContents();
}

void TabContentsViewViews::WasShown() {
  tab_contents()->ShowContents();
}

void TabContentsViewViews::WasSized(const gfx::Size& size) {
  // We have to check that the RenderWidgetHostView is the proper size.
  // It can be wrong in cases where the renderer has died and the host
  // view needed to be recreated.
  bool needs_resize = size != size_;

  if (needs_resize) {
    size_ = size;
    if (tab_contents()->interstitial_page())
      tab_contents()->interstitial_page()->SetSize(size);
  }

  RenderWidgetHostView* rwhv = tab_contents()->GetRenderWidgetHostView();
  if (rwhv && rwhv->GetViewBounds().size() != size)
    rwhv->SetSize(size);

  if (needs_resize)
    SetFloatingPosition(size);
}

void TabContentsViewViews::SetFloatingPosition(const gfx::Size& size) {
  // TODO(anicolao): rework this once we have DOMUI views for dialogs
  SetBounds(x(), y(), size.width(), size.height());
}
<|endoftext|>


<commit_before>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 */

#include <kdbthread.hpp>

#include <kdbprivate.h>

#include <gtest/gtest.h>

using namespace kdb;

struct test_contextual_update : ::testing::Test
{
	test_contextual_update ()
	: ks (), gc (), c (gc), i (ks, c, Key ("/ignore/id", KEY_META, "default", "my", KEY_END)),
	  x (ks, c, Key ("/%id%/key", KEY_META, "default", "33", KEY_END)){};

	KeySet ks;
	Coordinator gc;
	ThreadContext c;
	ThreadValue<std::string> i;
	ThreadValue<int> x;
};

TEST_F (test_contextual_update, activate)
{
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_TRUE (ks.lookup ("/%/key"));
	c.template activate (i);
	ASSERT_EQ (x.getName (), "/my/key");
	ASSERT_TRUE (ks.lookup ("/my/key"));
}

TEST_F (test_contextual_update, changeKey)
{
	ks.append (Key ("/other/key", KEY_VALUE, "88", KEY_END));
	i = "other";
	c.template activate (i);
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_TRUE (ks.lookup ("/other/key"));
	ASSERT_EQ (x, 88);
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "88");

	ks.lookup ("/other/key").setString ("100");

	c.syncLayers ();
	ASSERT_EQ (x, 88) << "should not influence cache";
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "100");

	x.syncCache ();
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "100");
	ASSERT_EQ (x, 100) << "cache should be updated";
}

TEST_F (test_contextual_update, syncCache)
{
	ks.append (Key ("/%/key", KEY_VALUE, "111", KEY_END));

	x.syncCache ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "111");
	ASSERT_EQ (x, 111) << "reevaluated context, should have found new key";
}

TEST_F (test_contextual_update, notifyAllEvents)
{
	ks.append (Key ("/%/key", KEY_VALUE, "133", KEY_END));

	c.notifyAllEvents ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (x, 33) << "should not be changed (optimization)";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "133") << "nothing done, so its not changed";
}

TEST_F (test_contextual_update, notifyAllEventsChange)
{
	ASSERT_EQ (ks.size (), 2);
	ks.append (Key ("/other/key", KEY_VALUE, "133", KEY_END));
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id") << "nothing done, so its not changed";

	i = "other";
	c.template activate (i);
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (x, 133);
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "133") << "nothing done, so its not changed";
	ASSERT_EQ (ks.size (), 4);
	EXPECT_EQ (ks.at (0).getName (), "/%/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (2).getName (), "/other/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (3).getName (), "user/ignore/id") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (3).getString (), "other");
}

TEST_F (test_contextual_update, notifyKeySetUpdate)
{
	ASSERT_EQ (ks.size (), 2);
	ks.append (Key ("/%/key", KEY_VALUE, "144", KEY_END));
	ASSERT_EQ (ks.size (), 2);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");

	c.notifyKeySetUpdate ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (x, 144) << "reevaluated context, should have found new key";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "144");
	ASSERT_EQ (ks.size (), 2);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
}

TEST_F (test_contextual_update, notifyAssignKeySetUpdate)
{
	x = 5;
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (0).getString (), "33");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
	EXPECT_EQ (ks.at (2).getName (), "user/%/key");
	EXPECT_EQ (ks.at (2).getString (), "5");

	ks.append (Key ("user/%/key", KEY_VALUE, "144", KEY_END));

	c.notifyKeySetUpdate ();
	ASSERT_EQ (x.getName (), "user/%/key");
	ASSERT_EQ (x, 144) << "reevaluated context, should have found new key";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "144");
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (0).getString (), "33");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
	EXPECT_EQ (ks.at (2).getName (), "user/%/key");
	EXPECT_EQ (ks.at (2).getString (), "144");
}
<commit_msg>clang: remove .template outside of template<commit_after>/**
 * @file
 *
 * @brief
 *
 * @copyright BSD License (see doc/COPYING or http://www.libelektra.org)
 */

#include <kdbthread.hpp>

#include <kdbprivate.h>

#include <gtest/gtest.h>

using namespace kdb;

struct test_contextual_update : ::testing::Test
{
	test_contextual_update ()
	: ks (), gc (), c (gc), i (ks, c, Key ("/ignore/id", KEY_META, "default", "my", KEY_END)),
	  x (ks, c, Key ("/%id%/key", KEY_META, "default", "33", KEY_END)){};

	KeySet ks;
	Coordinator gc;
	ThreadContext c;
	ThreadValue<std::string> i;
	ThreadValue<int> x;
};

TEST_F (test_contextual_update, activate)
{
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_TRUE (ks.lookup ("/%/key"));
	c.activate (i);
	ASSERT_EQ (x.getName (), "/my/key");
	ASSERT_TRUE (ks.lookup ("/my/key"));
}

TEST_F (test_contextual_update, changeKey)
{
	ks.append (Key ("/other/key", KEY_VALUE, "88", KEY_END));
	i = "other";
	c.activate (i);
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_TRUE (ks.lookup ("/other/key"));
	ASSERT_EQ (x, 88);
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "88");

	ks.lookup ("/other/key").setString ("100");

	c.syncLayers ();
	ASSERT_EQ (x, 88) << "should not influence cache";
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "100");

	x.syncCache ();
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "100");
	ASSERT_EQ (x, 100) << "cache should be updated";
}

TEST_F (test_contextual_update, syncCache)
{
	ks.append (Key ("/%/key", KEY_VALUE, "111", KEY_END));

	x.syncCache ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "111");
	ASSERT_EQ (x, 111) << "reevaluated context, should have found new key";
}

TEST_F (test_contextual_update, notifyAllEvents)
{
	ks.append (Key ("/%/key", KEY_VALUE, "133", KEY_END));

	c.notifyAllEvents ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (x, 33) << "should not be changed (optimization)";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "133") << "nothing done, so its not changed";
}

TEST_F (test_contextual_update, notifyAllEventsChange)
{
	ASSERT_EQ (ks.size (), 2);
	ks.append (Key ("/other/key", KEY_VALUE, "133", KEY_END));
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id") << "nothing done, so its not changed";

	i = "other";
	c.activate (i);
	ASSERT_EQ (x.getName (), "/other/key");
	ASSERT_EQ (x, 133);
	ASSERT_EQ (ks.lookup ("/other/key").getString (), "133") << "nothing done, so its not changed";
	ASSERT_EQ (ks.size (), 4);
	EXPECT_EQ (ks.at (0).getName (), "/%/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (2).getName (), "/other/key") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (3).getName (), "user/ignore/id") << "nothing done, so its not changed";
	EXPECT_EQ (ks.at (3).getString (), "other");
}

TEST_F (test_contextual_update, notifyKeySetUpdate)
{
	ASSERT_EQ (ks.size (), 2);
	ks.append (Key ("/%/key", KEY_VALUE, "144", KEY_END));
	ASSERT_EQ (ks.size (), 2);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");

	c.notifyKeySetUpdate ();
	ASSERT_EQ (x.getName (), "/%/key");
	ASSERT_EQ (x, 144) << "reevaluated context, should have found new key";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "144");
	ASSERT_EQ (ks.size (), 2);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
}

TEST_F (test_contextual_update, notifyAssignKeySetUpdate)
{
	x = 5;
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (0).getString (), "33");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
	EXPECT_EQ (ks.at (2).getName (), "user/%/key");
	EXPECT_EQ (ks.at (2).getString (), "5");

	ks.append (Key ("user/%/key", KEY_VALUE, "144", KEY_END));

	c.notifyKeySetUpdate ();
	ASSERT_EQ (x.getName (), "user/%/key");
	ASSERT_EQ (x, 144) << "reevaluated context, should have found new key";
	ASSERT_EQ (ks.lookup ("/%/key").getString (), "144");
	ASSERT_EQ (ks.size (), 3);
	EXPECT_EQ (ks.at (0).getName (), "/%/key");
	EXPECT_EQ (ks.at (0).getString (), "33");
	EXPECT_EQ (ks.at (1).getName (), "/ignore/id");
	EXPECT_EQ (ks.at (2).getName (), "user/%/key");
	EXPECT_EQ (ks.at (2).getString (), "144");
}
<|endoftext|>


<commit_before>#include <itkImageRegionConstIterator.h>
#include <itkStreamingImageFilter.h>

#include "rtkTestConfiguration.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"
#include "rtkFieldOfViewImageFilter.h"

#ifdef USE_CUDA
#  include "rtkCudaFDKConeBeamReconstructionFilter.h"
#elif USE_OPENCL
#  include "rtkOpenCLFDKConeBeamReconstructionFilter.h"
#else
#  include "rtkFDKConeBeamReconstructionFilter.h"
#endif

template<class TImage>
#if FAST_TESTS_NO_CHECKS
void CheckImageQuality(typename TImage::Pointer itkNotUsed(recon), typename TImage::Pointer itkNotUsed(ref))
{
}
#else
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();
    TestError += vcl_abs(RefVal - TestVal);
    EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(2.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (2.0-ErrorPerPixel)/2.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
  if (ErrorPerPixel > 0.03)
  {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 0.03." << std::endl;
    exit( EXIT_FAILURE);
  }
  if (PSNR < 26.)
  {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 26" << std::endl;
    exit( EXIT_FAILURE);
  }
}
#endif

/**
 * \file rtkfdktest.cxx
 *
 * \brief Functional test for classes performing FDK reconstructions
 *
 * This test generates the projections of a simulated Shepp-Logan phantom.
 * A CT image is reconstructed from each set of generated projection images
 * using the FDK algorithm and the reconstructed CT image is compared to the
 * expected results which is analytically computed.
 *
 * \author Simon Rit and Marc Vila
 */

int main(int, char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
#ifdef USE_CUDA
  typedef itk::CudaImage< OutputPixelType, Dimension > OutputImageType;
#else
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
#endif

#if FAST_TESTS_NO_CHECKS
  const unsigned int NumberOfProjectionImages = 3;
#else
  const unsigned int NumberOfProjectionImages = 180;
#endif

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  ConstantImageSourceType::Pointer tomographySource  = ConstantImageSourceType::New();
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 32;
  size[1] = 32;
  size[2] = 32;
  spacing[0] = 8.;
  spacing[1] = 8.;
  spacing[2] = 8.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = 128;
  spacing[0] = 2.;
  spacing[1] = 2.;
  spacing[2] = 2.;
#endif
  tomographySource->SetOrigin( origin );
  tomographySource->SetSpacing( spacing );
  tomographySource->SetSize( size );
  tomographySource->SetConstant( 0. );

  ConstantImageSourceType::Pointer projectionsSource = ConstantImageSourceType::New();
  origin[0] = -254.;
  origin[1] = -254.;
  origin[2] = -254.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 32;
  size[1] = 32;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 32.;
  spacing[1] = 32.;
  spacing[2] = 32.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
#endif
  projectionsSource->SetOrigin( origin );
  projectionsSource->SetSpacing( spacing );
  projectionsSource->SetSize( size );
  projectionsSource->SetConstant( 0. );

  std::cout << "\n\n****** Case 1: No streaming ******" << std::endl;

  // Geometry object
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int noProj=0; noProj<NumberOfProjectionImages; noProj++)
    geometry->AddProjection(600., 1200., noProj*360./NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);

  // Shepp Logan projections filter
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp=SLPType::New();
  slp->SetInput( projectionsSource->GetOutput() );
  slp->SetGeometry(geometry);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( slp->Update() );

  // Create a reference object (in this case a 3D phantom reference).
  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->SetInput( tomographySource->GetOutput() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )

  // FDK reconstruction filtering
#ifdef USE_CUDA
  typedef rtk::CudaFDKConeBeamReconstructionFilter                FDKType;
#elif USE_OPENCL
  typedef rtk::OpenCLFDKConeBeamReconstructionFilter              FDKType;
#else
  typedef rtk::FDKConeBeamReconstructionFilter< OutputImageType > FDKType;
#endif
  FDKType::Pointer feldkamp = FDKType::New();
  feldkamp->SetInput( 0, tomographySource->GetOutput() );
  feldkamp->SetInput( 1, slp->GetOutput() );
  feldkamp->SetGeometry( geometry );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );

  // FOV
  typedef rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType> FOVFilterType;
  FOVFilterType::Pointer fov=FOVFilterType::New();
  fov->SetInput(0, feldkamp->GetOutput());
  fov->SetProjectionsStack(slp->GetOutput());
  fov->SetGeometry( geometry );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

  std::cout << "\n\n****** Case 2: perpendicular direction ******" << std::endl;

  ConstantImageSourceType::OutputImageType::DirectionType direction;
  direction[0][0] = 0;
  direction[0][1] = 1;
  direction[0][2] = 0;
  direction[1][0] = -1;
  direction[1][1] = 0;
  direction[1][2] = 0;
  direction[2][0] = 0;
  direction[2][1] = 0;
  direction[2][2] = 1;
  tomographySource->SetDirection(direction);
  origin[0] = -127.;
  origin[1] =  127.;
  origin[2] = -127.;
  tomographySource->SetOrigin( origin );
  fov->GetOutput()->ResetPipeline();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

   std::cout << "\n\n****** Case 3: 45 degree tilt direction ******" << std::endl;

  direction[0][0] = 0.70710678118;
  direction[0][1] = -0.70710678118;
  direction[0][2] = 0.70710678118;
  direction[1][0] = 0.70710678118;
  direction[1][1] = 0;
  direction[1][2] = 0;
  direction[2][0] = 0;
  direction[2][1] = 0;
  direction[2][2] = 1;
  tomographySource->SetDirection(direction);
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
  tomographySource->SetOrigin( origin );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

 std::cout << "\n\n****** Case 4: streaming ******" << std::endl;

  // Make sure that the data will be recomputed by releasing them
  fov->GetOutput()->ReleaseData();

  typedef itk::StreamingImageFilter<OutputImageType, OutputImageType> StreamingType;
  StreamingType::Pointer streamer = StreamingType::New();
  streamer->SetInput(0, fov->GetOutput());
  streamer->SetNumberOfStreamDivisions(8);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( streamer->Update() );

  CheckImageQuality<OutputImageType>(streamer->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

  std::cout << "\n\n****** Case 5: small ROI ******" << std::endl;
  origin[0] = -5.;
  origin[1] = -13.;
  origin[2] = -20.;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  tomographySource->SetOrigin( origin );
  tomographySource->SetSize( size );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->UpdateLargestPossibleRegion() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->UpdateLargestPossibleRegion() )
  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>STYLE: Fixed indentation<commit_after>#include <itkImageRegionConstIterator.h>
#include <itkStreamingImageFilter.h>

#include "rtkTestConfiguration.h"
#include "rtkSheppLoganPhantomFilter.h"
#include "rtkDrawSheppLoganFilter.h"
#include "rtkConstantImageSource.h"
#include "rtkFieldOfViewImageFilter.h"

#ifdef USE_CUDA
#  include "rtkCudaFDKConeBeamReconstructionFilter.h"
#elif USE_OPENCL
#  include "rtkOpenCLFDKConeBeamReconstructionFilter.h"
#else
#  include "rtkFDKConeBeamReconstructionFilter.h"
#endif

template<class TImage>
#if FAST_TESTS_NO_CHECKS
void CheckImageQuality(typename TImage::Pointer itkNotUsed(recon), typename TImage::Pointer itkNotUsed(ref))
{
}
#else
void CheckImageQuality(typename TImage::Pointer recon, typename TImage::Pointer ref)
{
  typedef itk::ImageRegionConstIterator<TImage> ImageIteratorType;
  ImageIteratorType itTest( recon, recon->GetBufferedRegion() );
  ImageIteratorType itRef( ref, ref->GetBufferedRegion() );

  typedef double ErrorType;
  ErrorType TestError = 0.;
  ErrorType EnerError = 0.;

  itTest.GoToBegin();
  itRef.GoToBegin();

  while( !itRef.IsAtEnd() )
    {
    typename TImage::PixelType TestVal = itTest.Get();
    typename TImage::PixelType RefVal = itRef.Get();
    TestError += vcl_abs(RefVal - TestVal);
    EnerError += vcl_pow(ErrorType(RefVal - TestVal), 2.);
    ++itTest;
    ++itRef;
    }
  // Error per Pixel
  ErrorType ErrorPerPixel = TestError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "\nError per Pixel = " << ErrorPerPixel << std::endl;
  // MSE
  ErrorType MSE = EnerError/ref->GetBufferedRegion().GetNumberOfPixels();
  std::cout << "MSE = " << MSE << std::endl;
  // PSNR
  ErrorType PSNR = 20*log10(2.0) - 10*log10(MSE);
  std::cout << "PSNR = " << PSNR << "dB" << std::endl;
  // QI
  ErrorType QI = (2.0-ErrorPerPixel)/2.0;
  std::cout << "QI = " << QI << std::endl;

  // Checking results
  if (ErrorPerPixel > 0.03)
  {
    std::cerr << "Test Failed, Error per pixel not valid! "
              << ErrorPerPixel << " instead of 0.03." << std::endl;
    exit( EXIT_FAILURE);
  }
  if (PSNR < 26.)
  {
    std::cerr << "Test Failed, PSNR not valid! "
              << PSNR << " instead of 26" << std::endl;
    exit( EXIT_FAILURE);
  }
}
#endif

/**
 * \file rtkfdktest.cxx
 *
 * \brief Functional test for classes performing FDK reconstructions
 *
 * This test generates the projections of a simulated Shepp-Logan phantom.
 * A CT image is reconstructed from each set of generated projection images
 * using the FDK algorithm and the reconstructed CT image is compared to the
 * expected results which is analytically computed.
 *
 * \author Simon Rit and Marc Vila
 */

int main(int, char** )
{
  const unsigned int Dimension = 3;
  typedef float                                    OutputPixelType;
#ifdef USE_CUDA
  typedef itk::CudaImage< OutputPixelType, Dimension > OutputImageType;
#else
  typedef itk::Image< OutputPixelType, Dimension > OutputImageType;
#endif

#if FAST_TESTS_NO_CHECKS
  const unsigned int NumberOfProjectionImages = 3;
#else
  const unsigned int NumberOfProjectionImages = 180;
#endif

  // Constant image sources
  typedef rtk::ConstantImageSource< OutputImageType > ConstantImageSourceType;
  ConstantImageSourceType::PointType origin;
  ConstantImageSourceType::SizeType size;
  ConstantImageSourceType::SpacingType spacing;

  ConstantImageSourceType::Pointer tomographySource  = ConstantImageSourceType::New();
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 32;
  size[1] = 32;
  size[2] = 32;
  spacing[0] = 8.;
  spacing[1] = 8.;
  spacing[2] = 8.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = 128;
  spacing[0] = 2.;
  spacing[1] = 2.;
  spacing[2] = 2.;
#endif
  tomographySource->SetOrigin( origin );
  tomographySource->SetSpacing( spacing );
  tomographySource->SetSize( size );
  tomographySource->SetConstant( 0. );

  ConstantImageSourceType::Pointer projectionsSource = ConstantImageSourceType::New();
  origin[0] = -254.;
  origin[1] = -254.;
  origin[2] = -254.;
#if FAST_TESTS_NO_CHECKS
  size[0] = 32;
  size[1] = 32;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 32.;
  spacing[1] = 32.;
  spacing[2] = 32.;
#else
  size[0] = 128;
  size[1] = 128;
  size[2] = NumberOfProjectionImages;
  spacing[0] = 4.;
  spacing[1] = 4.;
  spacing[2] = 4.;
#endif
  projectionsSource->SetOrigin( origin );
  projectionsSource->SetSpacing( spacing );
  projectionsSource->SetSize( size );
  projectionsSource->SetConstant( 0. );

  std::cout << "\n\n****** Case 1: No streaming ******" << std::endl;

  // Geometry object
  typedef rtk::ThreeDCircularProjectionGeometry GeometryType;
  GeometryType::Pointer geometry = GeometryType::New();
  for(unsigned int noProj=0; noProj<NumberOfProjectionImages; noProj++)
    geometry->AddProjection(600., 1200., noProj*360./NumberOfProjectionImages, 0, 0, 0, 0, 20, 15);

  // Shepp Logan projections filter
  typedef rtk::SheppLoganPhantomFilter<OutputImageType, OutputImageType> SLPType;
  SLPType::Pointer slp=SLPType::New();
  slp->SetInput( projectionsSource->GetOutput() );
  slp->SetGeometry(geometry);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( slp->Update() );

  // Create a reference object (in this case a 3D phantom reference).
  typedef rtk::DrawSheppLoganFilter<OutputImageType, OutputImageType> DSLType;
  DSLType::Pointer dsl = DSLType::New();
  dsl->SetInput( tomographySource->GetOutput() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )

  // FDK reconstruction filtering
#ifdef USE_CUDA
  typedef rtk::CudaFDKConeBeamReconstructionFilter                FDKType;
#elif USE_OPENCL
  typedef rtk::OpenCLFDKConeBeamReconstructionFilter              FDKType;
#else
  typedef rtk::FDKConeBeamReconstructionFilter< OutputImageType > FDKType;
#endif
  FDKType::Pointer feldkamp = FDKType::New();
  feldkamp->SetInput( 0, tomographySource->GetOutput() );
  feldkamp->SetInput( 1, slp->GetOutput() );
  feldkamp->SetGeometry( geometry );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( feldkamp->Update() );

  // FOV
  typedef rtk::FieldOfViewImageFilter<OutputImageType, OutputImageType> FOVFilterType;
  FOVFilterType::Pointer fov=FOVFilterType::New();
  fov->SetInput(0, feldkamp->GetOutput());
  fov->SetProjectionsStack(slp->GetOutput());
  fov->SetGeometry( geometry );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

  std::cout << "\n\n****** Case 2: perpendicular direction ******" << std::endl;

  ConstantImageSourceType::OutputImageType::DirectionType direction;
  direction[0][0] = 0;
  direction[0][1] = 1;
  direction[0][2] = 0;
  direction[1][0] = -1;
  direction[1][1] = 0;
  direction[1][2] = 0;
  direction[2][0] = 0;
  direction[2][1] = 0;
  direction[2][2] = 1;
  tomographySource->SetDirection(direction);
  origin[0] = -127.;
  origin[1] =  127.;
  origin[2] = -127.;
  tomographySource->SetOrigin( origin );
  fov->GetOutput()->ResetPipeline();
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

   std::cout << "\n\n****** Case 3: 45 degree tilt direction ******" << std::endl;

  direction[0][0] = 0.70710678118;
  direction[0][1] = -0.70710678118;
  direction[0][2] = 0.70710678118;
  direction[1][0] = 0.70710678118;
  direction[1][1] = 0;
  direction[1][2] = 0;
  direction[2][0] = 0;
  direction[2][1] = 0;
  direction[2][2] = 1;
  tomographySource->SetDirection(direction);
  origin[0] = -127.;
  origin[1] = -127.;
  origin[2] = -127.;
  tomographySource->SetOrigin( origin );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->Update() )
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->Update() );

  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

  std::cout << "\n\n****** Case 4: streaming ******" << std::endl;

  // Make sure that the data will be recomputed by releasing them
  fov->GetOutput()->ReleaseData();

  typedef itk::StreamingImageFilter<OutputImageType, OutputImageType> StreamingType;
  StreamingType::Pointer streamer = StreamingType::New();
  streamer->SetInput(0, fov->GetOutput());
  streamer->SetNumberOfStreamDivisions(8);
  TRY_AND_EXIT_ON_ITK_EXCEPTION( streamer->Update() );

  CheckImageQuality<OutputImageType>(streamer->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;

  std::cout << "\n\n****** Case 5: small ROI ******" << std::endl;
  origin[0] = -5.;
  origin[1] = -13.;
  origin[2] = -20.;
  size[0] = 64;
  size[1] = 64;
  size[2] = 64;
  tomographySource->SetOrigin( origin );
  tomographySource->SetSize( size );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( fov->UpdateLargestPossibleRegion() );
  TRY_AND_EXIT_ON_ITK_EXCEPTION( dsl->UpdateLargestPossibleRegion() )
  CheckImageQuality<OutputImageType>(fov->GetOutput(), dsl->GetOutput());
  std::cout << "Test PASSED! " << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <string>
#include "plugin.hxx"
#include "compat.hxx"

//
// We don't like using C-style casts in C++ code
//

namespace {

QualType resolvePointers(QualType type) {
    while (type->isPointerType()) {
        type = type->getAs<PointerType>()->getPointeeType();
    }
    return type;
}

class CStyleCast:
    public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
{
public:
    explicit CStyleCast(InstantiationData const & data): Plugin(data) {}

    virtual void run() override {
        if (compiler.getLangOpts().CPlusPlus) {
            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
        }
    }

    bool VisitCStyleCastExpr(const CStyleCastExpr * expr);
};

static const char * recommendedFix(clang::CastKind ck) {
    switch(ck) {
        case CK_IntegralToPointer: return "reinterpret_cast";
        case CK_PointerToIntegral: return "reinterpret_cast";
        case CK_BaseToDerived: return "static_cast";
        default: return "???";
    }
}

bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
    if (ignoreLocation(expr)) {
        return true;
    }
    // casting to void is typically used when a parameter or field is only used in
    // debug mode, and we want to eliminate an "unused" warning
    if( expr->getCastKind() == CK_ToVoid ) {
        return true;
    }
    // ignore integral-type conversions for now, there is unsufficient agreement about
    // the merits of C++ style casting in this case
    if( expr->getCastKind() == CK_IntegralCast ) {
        return true;
    }
    if( expr->getCastKind() == CK_NoOp ) {
        return true;
    }
    std::string incompFrom;
    std::string incompTo;
    if( expr->getCastKind() == CK_BitCast ) {
        QualType t1 = resolvePointers(expr->getSubExprAsWritten()->getType());
        QualType t2 = resolvePointers(expr->getType());
        // Ignore "safe" casts for now that do not involve incomplete types (and
        // can thus not be interpreted as either a static_cast or a
        // reinterpret_cast, with potentially different results):
        if (t1->isVoidType() || t2->isVoidType()
            || !(t1->isIncompleteType() || t2->isIncompleteType()))
        {
            return true;
        }
        if (t1->isIncompleteType()) {
            incompFrom = "incomplete ";
        }
        if (t2->isIncompleteType()) {
            incompTo = "incomplete ";
        }
    }
    // ignore stuff from inside templates for now
    if( expr->getCastKind() == CK_Dependent ) {
        return true;
    }
    SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
                              expr->getLocStart());
    StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
    // ignore C code
    if ( filename.endswith(".h") ) {
        return true;
    }
    if ( compat::isInMainFile(compiler.getSourceManager(), spellingLocation) ) {
        if (filename.startswith(SRCDIR "/sal/") // sal has tons of weird stuff going on that I don't understand enough to fix
           || filename.startswith(SRCDIR "/bridges")) { // I'm not messing with this code - far too dangerous
            return true;
        }
    } else {
        if (filename.startswith(SRCDIR "/include/tools/solar.h")
           || filename.startswith(SRCDIR "/include/cppuhelper/")
           || ((StringRef(
                    compiler.getSourceManager().getFileEntryForID(
                        compiler.getSourceManager().getMainFileID())
                    ->getName())
                == SRCDIR "/jurt/source/pipe/staticsalhack.cxx")
               && filename.startswith(SRCDIR "/sal/"))) {
            return true;
        }
    }
    report(
        DiagnosticsEngine::Warning,
        "c-style cast, type=%0, from=%1%2, to=%3%4, recommendedFix=%5",
        expr->getSourceRange().getBegin())
      << expr->getCastKind()
      << incompFrom << expr->getSubExprAsWritten()->getType()
      << incompTo << expr->getType()
      << recommendedFix(expr->getCastKind())
      << expr->getSourceRange();
    return true;
}

loplugin::Plugin::Registration< CStyleCast > X("cstylecast");

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>Minor beautification<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include <string>
#include "plugin.hxx"
#include "compat.hxx"

//
// We don't like using C-style casts in C++ code
//

namespace {

QualType resolvePointers(QualType type) {
    while (type->isPointerType()) {
        type = type->getAs<PointerType>()->getPointeeType();
    }
    return type;
}

class CStyleCast:
    public RecursiveASTVisitor<CStyleCast>, public loplugin::Plugin
{
public:
    explicit CStyleCast(InstantiationData const & data): Plugin(data) {}

    virtual void run() override {
        if (compiler.getLangOpts().CPlusPlus) {
            TraverseDecl(compiler.getASTContext().getTranslationUnitDecl());
        }
    }

    bool VisitCStyleCastExpr(const CStyleCastExpr * expr);
};

static const char * recommendedFix(clang::CastKind ck) {
    switch(ck) {
        case CK_IntegralToPointer: return "reinterpret_cast";
        case CK_PointerToIntegral: return "reinterpret_cast";
        case CK_BaseToDerived: return "static_cast";
        default: return "???";
    }
}

bool CStyleCast::VisitCStyleCastExpr(const CStyleCastExpr * expr) {
    if (ignoreLocation(expr)) {
        return true;
    }
    // casting to void is typically used when a parameter or field is only used in
    // debug mode, and we want to eliminate an "unused" warning
    if( expr->getCastKind() == CK_ToVoid ) {
        return true;
    }
    // ignore integral-type conversions for now, there is unsufficient agreement about
    // the merits of C++ style casting in this case
    if( expr->getCastKind() == CK_IntegralCast ) {
        return true;
    }
    if( expr->getCastKind() == CK_NoOp ) {
        return true;
    }
    std::string incompFrom;
    std::string incompTo;
    if( expr->getCastKind() == CK_BitCast ) {
        QualType t1 = resolvePointers(expr->getSubExprAsWritten()->getType());
        QualType t2 = resolvePointers(expr->getType());
        // Ignore "safe" casts for now that do not involve incomplete types (and
        // can thus not be interpreted as either a static_cast or a
        // reinterpret_cast, with potentially different results):
        if (t1->isVoidType() || t2->isVoidType()
            || !(t1->isIncompleteType() || t2->isIncompleteType()))
        {
            return true;
        }
        if (t1->isIncompleteType()) {
            incompFrom = "incomplete ";
        }
        if (t2->isIncompleteType()) {
            incompTo = "incomplete ";
        }
    }
    // ignore stuff from inside templates for now
    if( expr->getCastKind() == CK_Dependent ) {
        return true;
    }
    SourceLocation spellingLocation = compiler.getSourceManager().getSpellingLoc(
                              expr->getLocStart());
    StringRef filename = compiler.getSourceManager().getFilename(spellingLocation);
    // ignore C code
    if ( filename.endswith(".h") ) {
        return true;
    }
    if ( compat::isInMainFile(compiler.getSourceManager(), spellingLocation) ) {
        if (filename.startswith(SRCDIR "/sal/") // sal has tons of weird stuff going on that I don't understand enough to fix
           || filename.startswith(SRCDIR "/bridges/")) { // I'm not messing with this code - far too dangerous
            return true;
        }
    } else {
        if (filename == SRCDIR "/include/tools/solar.h"
           || filename.startswith(SRCDIR "/include/cppuhelper/")
           || ((StringRef(
                    compiler.getSourceManager().getFileEntryForID(
                        compiler.getSourceManager().getMainFileID())
                    ->getName())
                == SRCDIR "/jurt/source/pipe/staticsalhack.cxx")
               && filename.startswith(SRCDIR "/sal/"))) {
            return true;
        }
    }
    report(
        DiagnosticsEngine::Warning,
        "c-style cast, type=%0, from=%1%2, to=%3%4, recommendedFix=%5",
        expr->getSourceRange().getBegin())
      << expr->getCastKind()
      << incompFrom << expr->getSubExprAsWritten()->getType()
      << incompTo << expr->getType()
      << recommendedFix(expr->getCastKind())
      << expr->getSourceRange();
    return true;
}

loplugin::Plugin::Registration< CStyleCast > X("cstylecast");

}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>// Copyright 2010-2016 RethinkDB, all rights reserved.
#include "clustering/administration/main/memory_checker.hpp"

#include <math.h>
#include <sys/time.h>
#include <sys/resource.h>

#include "clustering/administration/metadata.hpp"
#include "clustering/table_manager/table_meta_client.hpp"
#include "logger.hpp"
#include "rdb_protocol/env.hpp"
#include "rdb_protocol/pseudo_time.hpp"

static const int64_t delay_time = 60*1000;
static const int64_t reset_checks = 10;

static const int64_t practice_runs = 2;

memory_checker_t::memory_checker_t() :
    checks_until_reset(0),
    swap_usage(0),
    print_log_message(true),
    practice_runs_remaining(practice_runs),
    timer(delay_time, this)
{
    coro_t::spawn_sometime(std::bind(&memory_checker_t::do_check,
                                     this,
                                     drainer.lock()));
}

void memory_checker_t::do_check(UNUSED auto_drainer_t::lock_t keepalive) {
#if defined(__MACH__) || defined(_WIN32)
    size_t new_swap_usage = 0;
#else
    struct rusage current_usage;

    int res = getrusage(RUSAGE_SELF, &current_usage);

    if (res == -1) {
        logWRN("Error in swap usage detection: %d\n", get_errno());
        return;
    }
    size_t new_swap_usage = current_usage.ru_majflt;
#endif

    if (practice_runs_remaining == practice_runs) {
        swap_usage = new_swap_usage;
    }

    const std::string error_message =
        "RethinkDB has been accessing a lot of swap memory in the past ten"
        " minutes. This may impact performace.";

    if (new_swap_usage > swap_usage + 200 && practice_runs_remaining == 0) {
        // We've started using more swap
        if (print_log_message) {
            logWRN("RethinkDB has been accessing a lot of swap memory in the past ten"
                   " minutes. This may impact performace.");

            print_log_message = false;
        }
        checks_until_reset = reset_checks;
        memory_issue_tracker.report_error(error_message);
    } else if (checks_until_reset == 0) {
        // We haven't had more than 200 major page faults per minute for the last 10m.
        memory_issue_tracker.report_success();
        print_log_message = true;
    }

    swap_usage = new_swap_usage;

    if (checks_until_reset > 0) {
        --checks_until_reset;
    }
    if (practice_runs_remaining > 0) {
        --practice_runs_remaining;
    }
}

<commit_msg>Removed unused sys/time.h header (doesn't exist on Windows).<commit_after>// Copyright 2010-2016 RethinkDB, all rights reserved.
#include "clustering/administration/main/memory_checker.hpp"

#include <math.h>
#include <sys/resource.h>

#include "clustering/administration/metadata.hpp"
#include "clustering/table_manager/table_meta_client.hpp"
#include "logger.hpp"
#include "rdb_protocol/env.hpp"
#include "rdb_protocol/pseudo_time.hpp"

static const int64_t delay_time = 60*1000;
static const int64_t reset_checks = 10;

static const int64_t practice_runs = 2;

memory_checker_t::memory_checker_t() :
    checks_until_reset(0),
    swap_usage(0),
    print_log_message(true),
    practice_runs_remaining(practice_runs),
    timer(delay_time, this)
{
    coro_t::spawn_sometime(std::bind(&memory_checker_t::do_check,
                                     this,
                                     drainer.lock()));
}

void memory_checker_t::do_check(UNUSED auto_drainer_t::lock_t keepalive) {
#if defined(__MACH__) || defined(_WIN32)
    size_t new_swap_usage = 0;
#else
    struct rusage current_usage;

    int res = getrusage(RUSAGE_SELF, &current_usage);

    if (res == -1) {
        logWRN("Error in swap usage detection: %d\n", get_errno());
        return;
    }
    size_t new_swap_usage = current_usage.ru_majflt;
#endif

    if (practice_runs_remaining == practice_runs) {
        swap_usage = new_swap_usage;
    }

    const std::string error_message =
        "RethinkDB has been accessing a lot of swap memory in the past ten"
        " minutes. This may impact performace.";

    if (new_swap_usage > swap_usage + 200 && practice_runs_remaining == 0) {
        // We've started using more swap
        if (print_log_message) {
            logWRN("RethinkDB has been accessing a lot of swap memory in the past ten"
                   " minutes. This may impact performace.");

            print_log_message = false;
        }
        checks_until_reset = reset_checks;
        memory_issue_tracker.report_error(error_message);
    } else if (checks_until_reset == 0) {
        // We haven't had more than 200 major page faults per minute for the last 10m.
        memory_issue_tracker.report_success();
        print_log_message = true;
    }

    swap_usage = new_swap_usage;

    if (checks_until_reset > 0) {
        --checks_until_reset;
    }
    if (practice_runs_remaining > 0) {
        --practice_runs_remaining;
    }
}

<|endoftext|>


<commit_before><commit_msg>Fix lint<commit_after><|endoftext|>


<commit_before>#include "pixelboost/framework/game.h"
#include "pixelboost/graphics/components/sprite.h"
#include "pixelboost/graphics/renderer/common/renderer.h"
#include "pixelboost/graphics/renderer/sprite/sprite.h"
#include "pixelboost/graphics/renderer/sprite/spriteRenderer.h"
#include "pixelboost/logic/component/transform.h"
#include "pixelboost/logic/message/transform.h"
#include "pixelboost/logic/system/graphics/render/render.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/scene.h"

using namespace pb;

SpriteComponent::SpriteComponent(Entity* parent, const std::string& sprite)
    : Component(parent)
{
    _Renderable = new SpriteRenderable(parent->GetUid());
    _Renderable->Sprite = pb::Game::Instance()->GetSpriteRenderer()->GetSprite(sprite);

    GetScene()->GetSystemByType<pb::RenderSystem>()->AddItem(_Renderable);

    GetParent()->RegisterMessageHandler(TransformChangedMessage::GetStaticType(), Entity::MessageHandler(this, &SpriteComponent::OnTransformChanged));

    UpdateTransform();
}

SpriteComponent::~SpriteComponent()
{
    GetParent()->UnregisterMessageHandler(TransformChangedMessage::GetStaticType(), Entity::MessageHandler(this, &SpriteComponent::OnTransformChanged));

    GetScene()->GetSystemByType<pb::RenderSystem>()->RemoveItem(_Renderable);

    delete _Renderable;
}

Uid SpriteComponent::GetType()
{
    return GetStaticType();
}

Uid SpriteComponent::GetStaticType()
{
    return TypeHash("sprite");
}

glm::vec2 SpriteComponent::GetSize()
{
    if (_Renderable->Sprite)
        return _Renderable->Sprite->_Dimension;

    return glm::vec2(0,0);
}

void SpriteComponent::SetLayer(int layer)
{
    _Renderable->SetLayer(layer);
}

void SpriteComponent::SetSprite(const std::string& sprite)
{
    _Renderable->Sprite = pb::Game::Instance()->GetSpriteRenderer()->GetSprite(sprite);
}

void SpriteComponent::SetTint(const glm::vec4& tint)
{
    _Renderable->Tint = tint;
}

void SpriteComponent::SetLocalTransform(const glm::mat4x4& transform)
{
    _LocalTransform = transform;

    UpdateTransform();
}

void SpriteComponent::OnTransformChanged(Uid sender, Message& message)
{
    UpdateTransform();
}

void SpriteComponent::UpdateTransform()
{
    TransformComponent* transform = GetParent()->GetComponentByType<TransformComponent>();

    if (transform)
    {
        _Renderable->Transform = _LocalTransform * transform->GetMatrix();
    }
}
<commit_msg>Fix transform order for local sprite component matrices<commit_after>#include "pixelboost/framework/game.h"
#include "pixelboost/graphics/components/sprite.h"
#include "pixelboost/graphics/renderer/common/renderer.h"
#include "pixelboost/graphics/renderer/sprite/sprite.h"
#include "pixelboost/graphics/renderer/sprite/spriteRenderer.h"
#include "pixelboost/logic/component/transform.h"
#include "pixelboost/logic/message/transform.h"
#include "pixelboost/logic/system/graphics/render/render.h"
#include "pixelboost/logic/entity.h"
#include "pixelboost/logic/scene.h"

using namespace pb;

SpriteComponent::SpriteComponent(Entity* parent, const std::string& sprite)
    : Component(parent)
{
    _Renderable = new SpriteRenderable(parent->GetUid());
    _Renderable->Sprite = pb::Game::Instance()->GetSpriteRenderer()->GetSprite(sprite);

    GetScene()->GetSystemByType<pb::RenderSystem>()->AddItem(_Renderable);

    GetParent()->RegisterMessageHandler(TransformChangedMessage::GetStaticType(), Entity::MessageHandler(this, &SpriteComponent::OnTransformChanged));

    UpdateTransform();
}

SpriteComponent::~SpriteComponent()
{
    GetParent()->UnregisterMessageHandler(TransformChangedMessage::GetStaticType(), Entity::MessageHandler(this, &SpriteComponent::OnTransformChanged));

    GetScene()->GetSystemByType<pb::RenderSystem>()->RemoveItem(_Renderable);

    delete _Renderable;
}

Uid SpriteComponent::GetType()
{
    return GetStaticType();
}

Uid SpriteComponent::GetStaticType()
{
    return TypeHash("sprite");
}

glm::vec2 SpriteComponent::GetSize()
{
    if (_Renderable->Sprite)
        return _Renderable->Sprite->_Dimension;

    return glm::vec2(0,0);
}

void SpriteComponent::SetLayer(int layer)
{
    _Renderable->SetLayer(layer);
}

void SpriteComponent::SetSprite(const std::string& sprite)
{
    _Renderable->Sprite = pb::Game::Instance()->GetSpriteRenderer()->GetSprite(sprite);
}

void SpriteComponent::SetTint(const glm::vec4& tint)
{
    _Renderable->Tint = tint;
}

void SpriteComponent::SetLocalTransform(const glm::mat4x4& transform)
{
    _LocalTransform = transform;

    UpdateTransform();
}

void SpriteComponent::OnTransformChanged(Uid sender, Message& message)
{
    UpdateTransform();
}

void SpriteComponent::UpdateTransform()
{
    TransformComponent* transform = GetParent()->GetComponentByType<TransformComponent>();

    if (transform)
    {
        _Renderable->Transform = transform->GetMatrix() * _LocalTransform;
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "compiler/rewriter/tools/dataflow_annotations.h"
#include "compiler/semantic_annotations/annotation_keys.h"
#include "compiler/semantic_annotations/tsv_annotation.h"
#include "types/typeops.h"
#include "context/static_context.h"

namespace zorba {

#define SORTED_NODES(e) e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, TSVAnnotationValue::TRUE_VAL)
#define DISTINCT_NODES(e) e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, TSVAnnotationValue::TRUE_VAL)
#define PROPOGATE_SORTED_NODES(src, tgt) tgt->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, src->get_annotation(AnnotationKey::PRODUCES_SORTED_NODES))
#define PROPOGATE_DISTINCT_NODES(src, tgt) tgt->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, src->get_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES))
#define LOOKUP_FN( pfx, local, arity ) static_cast<function *> (m_ctx->lookup_fn (pfx, local, arity))

void DataflowAnnotationsComputer::compute(expr *e)
{
  switch(e->get_expr_kind()) {
    case sequential_expr_kind:
      compute_sequential_expr(static_cast<sequential_expr *>(e));
      break;

    case wrapper_expr_kind:
      compute_wrapper_expr(static_cast<wrapper_expr *>(e));
      break;

    case constructor_expr_kind:
      compute_constructor_expr(static_cast<constructor_expr *>(e));
      break;

    case var_expr_kind:
      compute_var_expr(static_cast<var_expr *>(e));
      break;

    case flwor_expr_kind:
      compute_flwor_expr(static_cast<flwor_expr *>(e));
      break;

    case trycatch_expr_kind:
      compute_trycatch_expr(static_cast<trycatch_expr *>(e));
      break;

    case promote_expr_kind:
      compute_promote_expr(static_cast<promote_expr *>(e));
      break;

    case typeswitch_expr_kind:
      compute_typeswitch_expr(static_cast<typeswitch_expr *>(e));
      break;

    case if_expr_kind:
      compute_if_expr(static_cast<if_expr *>(e));
      break;

    case function_def_expr_kind:
      compute_function_def_expr(static_cast<function_def_expr *>(e));
      break;

    case fo_expr_kind:
      compute_fo_expr(static_cast<fo_expr *>(e));
      break;

    case ft_contains_expr_kind:
      compute_ft_contains_expr(static_cast<ft_contains_expr *>(e));
      break;

    case instanceof_expr_kind:
      compute_instanceof_expr(static_cast<instanceof_expr *>(e));
      break;

    case treat_expr_kind:
      compute_treat_expr(static_cast<treat_expr *>(e));
      break;

    case castable_expr_kind:
      compute_castable_expr(static_cast<castable_expr *>(e));
      break;

    case cast_expr_kind:
      compute_cast_expr(static_cast<cast_expr *>(e));
      break;

    case name_cast_expr_kind:
      compute_name_cast_expr(static_cast<name_cast_expr *>(e));
      break;

    case validate_expr_kind:
      compute_validate_expr(static_cast<validate_expr *>(e));
      break;

    case extension_expr_kind:
      compute_extension_expr(static_cast<extension_expr *>(e));
      break;

    case relpath_expr_kind:
      compute_relpath_expr(static_cast<relpath_expr *>(e));
      break;

    case axis_step_expr_kind:
      compute_axis_step_expr(static_cast<axis_step_expr *>(e));
      break;

    case match_expr_kind:
      compute_match_expr(static_cast<match_expr *>(e));
      break;

    case const_expr_kind:
      compute_const_expr(static_cast<const_expr *>(e));
      break;

    case order_expr_kind:
      compute_order_expr(static_cast<order_expr *>(e));
      break;

    case elem_expr_kind:
      compute_elem_expr(static_cast<elem_expr *>(e));
      break;

    case doc_expr_kind:
      compute_doc_expr(static_cast<doc_expr *>(e));
      break;

    case attr_expr_kind:
      compute_attr_expr(static_cast<attr_expr *>(e));
      break;

    case text_expr_kind:
      compute_text_expr(static_cast<text_expr *>(e));
      break;

    case pi_expr_kind:
      compute_pi_expr(static_cast<pi_expr *>(e));
      break;

    default:
      break;
  }
}

void DataflowAnnotationsComputer::compute_sequential_expr(sequential_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_wrapper_expr(wrapper_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_constructor_expr(constructor_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_var_expr(var_expr *e)
{
  if (!generic_compute(e)) {
    if (e->get_kind() == var_expr::let_var) {
      PROPOGATE_SORTED_NODES(e->get_flwor_clause()->get_expr().getp(), e);
      PROPOGATE_DISTINCT_NODES(e->get_flwor_clause()->get_expr().getp(), e);
    }
  }
}

void DataflowAnnotationsComputer::compute_flwor_expr(flwor_expr *e)
{
  flwor_expr::clause_list_t::iterator ci = e->clause_begin();
  flwor_expr::clause_list_t::iterator cend = e->clause_end();
  while(ci != cend) {
    flwor_expr::forletref_t& flc = *ci;
    compute(flc->get_expr().getp());
    ++ci;
  }
  expr *where = e->get_where().getp();
  if (where != NULL) {
    compute(where);
  }

  flwor_expr::orderspec_list_t::iterator oi = e->orderspec_begin();
  flwor_expr::orderspec_list_t::iterator oend = e->orderspec_end();
  while(oi != oend) {
    flwor_expr::orderspec_t& ospec = *oi;
    compute(ospec.first);
    ++oi;
  }

  compute(e->get_retval().getp());
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_trycatch_expr(trycatch_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_promote_expr(promote_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_typeswitch_expr(typeswitch_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_if_expr(if_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_function_def_expr(function_def_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_fo_expr(fo_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    const function *f = e->get_func();
    if (f == LOOKUP_FN("fn", "doc", 1)) {
      SORTED_NODES(e);
      DISTINCT_NODES(e);
    }
  }
}

void DataflowAnnotationsComputer::compute_ft_contains_expr(ft_contains_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_instanceof_expr(instanceof_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_treat_expr(treat_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_castable_expr(castable_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_cast_expr(cast_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_name_cast_expr(name_cast_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_validate_expr(validate_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_expr().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_expr().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_extension_expr(extension_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_expr().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_expr().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_relpath_expr(relpath_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    int sz = e->size();
    bool non_single_fwd_axis = false;
    bool reverse_axis = false;
    for(int i = 1; i < sz; ++i) {
      axis_step_expr *ase = dynamic_cast<axis_step_expr *>((*e)[i].getp());
      if (ase == NULL) {
        return;
      }
      reverse_axis = reverse_axis || ase->is_reverse_axis();
      non_single_fwd_axis = non_single_fwd_axis || ((ase->getAxis() != axis_kind_child) && (ase->getAxis() != axis_kind_attribute));
    }
    if (!non_single_fwd_axis) {
      Annotation::value_ref_t sortedAnnot = (*e)[0]->get_annotation(AnnotationKey::PRODUCES_SORTED_NODES);
      if (sortedAnnot != NULL) {
        e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, sortedAnnot);
      }
      Annotation::value_ref_t distinctAnnot = (*e)[0]->get_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES);
      if (distinctAnnot != NULL) {
        e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, distinctAnnot);
      }
    } else {
      xqtref_t crt = (*e)[0]->return_type(m_ctx);
      if (TypeOps::type_max_cnt(*crt) <= 1) {
        bool sorted = false;
        bool distinct = false;
        if (sz == 2) {
          distinct = true;
          sorted = !reverse_axis;
        } else {
          if (!non_single_fwd_axis) {
            sorted = true;
            distinct = true;
          }
        }
        e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, TSVAnnotationValue::from_bool(sorted));
        e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, TSVAnnotationValue::from_bool(distinct));
      }
    }
  }
}

void DataflowAnnotationsComputer::compute_axis_step_expr(axis_step_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_match_expr(match_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_const_expr(const_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_order_expr(order_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_elem_expr(elem_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_doc_expr(doc_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_attr_expr(attr_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_text_expr(text_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_pi_expr(pi_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::default_walk(expr *e)
{
  expr_iterator i = e->expr_begin();
  while(!i.done()) {
    expr *child = (*i).getp();
    if (child != NULL) {
      compute(child);
    }
    ++i;
  }
}

/**
 * Checks if the expression has a return type with a quantifier of
 * ONE or QUESTION. If so, the expression cannot have dup nodes
 * or nodes out of sorted order.
 */
bool DataflowAnnotationsComputer::generic_compute(expr *e)
{
  xqtref_t rt = e->return_type(m_ctx);
  TypeConstants::quantifier_t quant = TypeOps::quantifier(*rt);
  if (quant == TypeConstants::QUANT_ONE || quant == TypeConstants::QUANT_QUESTION) {
    SORTED_NODES(e);
    DISTINCT_NODES(e);
    return true;
  }
  return false;
}

}
/* vim:set ts=2 sw=2: */
<commit_msg>Fixed missing annotation propogation across wrapper expressions<commit_after>/*
 * Copyright 2006-2008 The FLWOR Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "compiler/rewriter/tools/dataflow_annotations.h"
#include "compiler/semantic_annotations/annotation_keys.h"
#include "compiler/semantic_annotations/tsv_annotation.h"
#include "types/typeops.h"
#include "context/static_context.h"

namespace zorba {

#define SORTED_NODES(e) e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, TSVAnnotationValue::TRUE_VAL)
#define DISTINCT_NODES(e) e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, TSVAnnotationValue::TRUE_VAL)
#define PROPOGATE_SORTED_NODES(src, tgt) tgt->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, src->get_annotation(AnnotationKey::PRODUCES_SORTED_NODES))
#define PROPOGATE_DISTINCT_NODES(src, tgt) tgt->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, src->get_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES))
#define LOOKUP_FN( pfx, local, arity ) static_cast<function *> (m_ctx->lookup_fn (pfx, local, arity))

void DataflowAnnotationsComputer::compute(expr *e)
{
  switch(e->get_expr_kind()) {
    case sequential_expr_kind:
      compute_sequential_expr(static_cast<sequential_expr *>(e));
      break;

    case wrapper_expr_kind:
      compute_wrapper_expr(static_cast<wrapper_expr *>(e));
      break;

    case constructor_expr_kind:
      compute_constructor_expr(static_cast<constructor_expr *>(e));
      break;

    case var_expr_kind:
      compute_var_expr(static_cast<var_expr *>(e));
      break;

    case flwor_expr_kind:
      compute_flwor_expr(static_cast<flwor_expr *>(e));
      break;

    case trycatch_expr_kind:
      compute_trycatch_expr(static_cast<trycatch_expr *>(e));
      break;

    case promote_expr_kind:
      compute_promote_expr(static_cast<promote_expr *>(e));
      break;

    case typeswitch_expr_kind:
      compute_typeswitch_expr(static_cast<typeswitch_expr *>(e));
      break;

    case if_expr_kind:
      compute_if_expr(static_cast<if_expr *>(e));
      break;

    case function_def_expr_kind:
      compute_function_def_expr(static_cast<function_def_expr *>(e));
      break;

    case fo_expr_kind:
      compute_fo_expr(static_cast<fo_expr *>(e));
      break;

    case ft_contains_expr_kind:
      compute_ft_contains_expr(static_cast<ft_contains_expr *>(e));
      break;

    case instanceof_expr_kind:
      compute_instanceof_expr(static_cast<instanceof_expr *>(e));
      break;

    case treat_expr_kind:
      compute_treat_expr(static_cast<treat_expr *>(e));
      break;

    case castable_expr_kind:
      compute_castable_expr(static_cast<castable_expr *>(e));
      break;

    case cast_expr_kind:
      compute_cast_expr(static_cast<cast_expr *>(e));
      break;

    case name_cast_expr_kind:
      compute_name_cast_expr(static_cast<name_cast_expr *>(e));
      break;

    case validate_expr_kind:
      compute_validate_expr(static_cast<validate_expr *>(e));
      break;

    case extension_expr_kind:
      compute_extension_expr(static_cast<extension_expr *>(e));
      break;

    case relpath_expr_kind:
      compute_relpath_expr(static_cast<relpath_expr *>(e));
      break;

    case axis_step_expr_kind:
      compute_axis_step_expr(static_cast<axis_step_expr *>(e));
      break;

    case match_expr_kind:
      compute_match_expr(static_cast<match_expr *>(e));
      break;

    case const_expr_kind:
      compute_const_expr(static_cast<const_expr *>(e));
      break;

    case order_expr_kind:
      compute_order_expr(static_cast<order_expr *>(e));
      break;

    case elem_expr_kind:
      compute_elem_expr(static_cast<elem_expr *>(e));
      break;

    case doc_expr_kind:
      compute_doc_expr(static_cast<doc_expr *>(e));
      break;

    case attr_expr_kind:
      compute_attr_expr(static_cast<attr_expr *>(e));
      break;

    case text_expr_kind:
      compute_text_expr(static_cast<text_expr *>(e));
      break;

    case pi_expr_kind:
      compute_pi_expr(static_cast<pi_expr *>(e));
      break;

    default:
      break;
  }
}

void DataflowAnnotationsComputer::compute_sequential_expr(sequential_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_wrapper_expr(wrapper_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_expr().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_expr().getp(), e);
}

void DataflowAnnotationsComputer::compute_constructor_expr(constructor_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_var_expr(var_expr *e)
{
  if (!generic_compute(e)) {
    if (e->get_kind() == var_expr::let_var) {
      PROPOGATE_SORTED_NODES(e->get_flwor_clause()->get_expr().getp(), e);
      PROPOGATE_DISTINCT_NODES(e->get_flwor_clause()->get_expr().getp(), e);
    }
  }
}

void DataflowAnnotationsComputer::compute_flwor_expr(flwor_expr *e)
{
  flwor_expr::clause_list_t::iterator ci = e->clause_begin();
  flwor_expr::clause_list_t::iterator cend = e->clause_end();
  while(ci != cend) {
    flwor_expr::forletref_t& flc = *ci;
    compute(flc->get_expr().getp());
    ++ci;
  }
  expr *where = e->get_where().getp();
  if (where != NULL) {
    compute(where);
  }

  flwor_expr::orderspec_list_t::iterator oi = e->orderspec_begin();
  flwor_expr::orderspec_list_t::iterator oend = e->orderspec_end();
  while(oi != oend) {
    flwor_expr::orderspec_t& ospec = *oi;
    compute(ospec.first);
    ++oi;
  }

  compute(e->get_retval().getp());
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_trycatch_expr(trycatch_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_promote_expr(promote_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_typeswitch_expr(typeswitch_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_if_expr(if_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_function_def_expr(function_def_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_fo_expr(fo_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    const function *f = e->get_func();
    if (f == LOOKUP_FN("fn", "doc", 1)) {
      SORTED_NODES(e);
      DISTINCT_NODES(e);
    }
  }
}

void DataflowAnnotationsComputer::compute_ft_contains_expr(ft_contains_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_instanceof_expr(instanceof_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_treat_expr(treat_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_castable_expr(castable_expr *e)
{
  default_walk(e);
  PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
  PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
}

void DataflowAnnotationsComputer::compute_cast_expr(cast_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_name_cast_expr(name_cast_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_input().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_input().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_validate_expr(validate_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_expr().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_expr().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_extension_expr(extension_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    PROPOGATE_SORTED_NODES(e->get_expr().getp(), e);
    PROPOGATE_DISTINCT_NODES(e->get_expr().getp(), e);
  }
}

void DataflowAnnotationsComputer::compute_relpath_expr(relpath_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
    int sz = e->size();
    bool non_single_fwd_axis = false;
    bool reverse_axis = false;
    for(int i = 1; i < sz; ++i) {
      axis_step_expr *ase = dynamic_cast<axis_step_expr *>((*e)[i].getp());
      if (ase == NULL) {
        return;
      }
      reverse_axis = reverse_axis || ase->is_reverse_axis();
      non_single_fwd_axis = non_single_fwd_axis || ((ase->getAxis() != axis_kind_child) && (ase->getAxis() != axis_kind_attribute));
    }
    if (!non_single_fwd_axis) {
      Annotation::value_ref_t sortedAnnot = (*e)[0]->get_annotation(AnnotationKey::PRODUCES_SORTED_NODES);
      if (sortedAnnot != NULL) {
        e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, sortedAnnot);
      }
      Annotation::value_ref_t distinctAnnot = (*e)[0]->get_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES);
      if (distinctAnnot != NULL) {
        e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, distinctAnnot);
      }
    } else {
      xqtref_t crt = (*e)[0]->return_type(m_ctx);
      if (TypeOps::type_max_cnt(*crt) <= 1) {
        bool sorted = false;
        bool distinct = false;
        if (sz == 2) {
          distinct = true;
          sorted = !reverse_axis;
        } else {
          if (!non_single_fwd_axis) {
            sorted = true;
            distinct = true;
          }
        }
        e->put_annotation(AnnotationKey::PRODUCES_SORTED_NODES, TSVAnnotationValue::from_bool(sorted));
        e->put_annotation(AnnotationKey::PRODUCES_DISTINCT_NODES, TSVAnnotationValue::from_bool(distinct));
      }
    }
  }
}

void DataflowAnnotationsComputer::compute_axis_step_expr(axis_step_expr *e)
{
  default_walk(e);
  if (!generic_compute(e)) {
  }
}

void DataflowAnnotationsComputer::compute_match_expr(match_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_const_expr(const_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_order_expr(order_expr *e)
{
  default_walk(e);
  generic_compute(e);
}

void DataflowAnnotationsComputer::compute_elem_expr(elem_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_doc_expr(doc_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_attr_expr(attr_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_text_expr(text_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::compute_pi_expr(pi_expr *e)
{
  default_walk(e);
  SORTED_NODES(e);
  DISTINCT_NODES(e);
}

void DataflowAnnotationsComputer::default_walk(expr *e)
{
  expr_iterator i = e->expr_begin();
  while(!i.done()) {
    expr *child = (*i).getp();
    if (child != NULL) {
      compute(child);
    }
    ++i;
  }
}

/**
 * Checks if the expression has a return type with a quantifier of
 * ONE or QUESTION. If so, the expression cannot have dup nodes
 * or nodes out of sorted order.
 */
bool DataflowAnnotationsComputer::generic_compute(expr *e)
{
  xqtref_t rt = e->return_type(m_ctx);
  TypeConstants::quantifier_t quant = TypeOps::quantifier(*rt);
  if (quant == TypeConstants::QUANT_ONE || quant == TypeConstants::QUANT_QUESTION) {
    SORTED_NODES(e);
    DISTINCT_NODES(e);
    return true;
  }
  return false;
}

}
/* vim:set ts=2 sw=2: */
<|endoftext|>