<commit_before>// Copyright (c) 2012 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 "content/browser/accessibility/browser_accessibility_manager.h"

#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/common/accessibility_messages.h"

namespace content {

BrowserAccessibility* BrowserAccessibilityFactory::Create() {
  return BrowserAccessibility::Create();
}

#if !defined(OS_MACOSX) && \
    !defined(OS_WIN) && \
    !defined(TOOLKIT_GTK) && \
    !defined(OS_ANDROID) \
// We have subclassess of BrowserAccessibilityManager on Mac, Linux/GTK,
// and Win. For any other platform, instantiate the base class.
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
    const AccessibilityNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory) {
  return new BrowserAccessibilityManager(src, delegate, factory);
}
#endif

BrowserAccessibilityManager::BrowserAccessibilityManager(
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
}

BrowserAccessibilityManager::BrowserAccessibilityManager(
    const AccessibilityNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
  Initialize(src);
}

BrowserAccessibilityManager::~BrowserAccessibilityManager() {
  if (root_)
    root_->Destroy();
}

void BrowserAccessibilityManager::Initialize(const AccessibilityNodeData src) {
  std::vector<AccessibilityNodeData> nodes;
  nodes.push_back(src);
  if (!UpdateNodes(nodes))
    return;
  if (!focus_)
    SetFocus(root_, false);
}

// static
AccessibilityNodeData BrowserAccessibilityManager::GetEmptyDocument() {
  AccessibilityNodeData empty_document;
  empty_document.id = 0;
  empty_document.role = blink::WebAXRoleRootWebArea;
  return empty_document;
}

BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
  return root_;
}

BrowserAccessibility* BrowserAccessibilityManager::GetFromRendererID(
    int32 renderer_id) {
  base::hash_map<int32, BrowserAccessibility*>::iterator iter =
      renderer_id_map_.find(renderer_id);
  if (iter != renderer_id_map_.end())
    return iter->second;
  return NULL;
}

void BrowserAccessibilityManager::GotFocus(bool touch_event_context) {
  if (!touch_event_context)
    osk_state_ = OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED;

  if (!focus_)
    return;

  NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}

void BrowserAccessibilityManager::WasHidden() {
  osk_state_ = OSK_DISALLOWED_BECAUSE_TAB_HIDDEN;
}

void BrowserAccessibilityManager::GotMouseDown() {
  osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
  NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}

bool BrowserAccessibilityManager::IsOSKAllowed(const gfx::Rect& bounds) {
  if (!delegate_ || !delegate_->HasFocus())
    return false;

  gfx::Point touch_point = delegate_->GetLastTouchEventLocation();
  return bounds.Contains(touch_point);
}

bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
  return true;
}

void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
  if (node == focus_)
    SetFocus(root_, false);
  int renderer_id = node->renderer_id();
  renderer_id_map_.erase(renderer_id);
}

void BrowserAccessibilityManager::OnAccessibilityEvents(
    const std::vector<AccessibilityHostMsg_EventParams>& params) {
  for (uint32 index = 0; index < params.size(); index++) {
    const AccessibilityHostMsg_EventParams& param = params[index];

    // Update nodes that changed.
    if (!UpdateNodes(param.nodes))
      return;

    // Find the node corresponding to the id that's the target of the
    // event (which may not be the root of the update tree).
    BrowserAccessibility* node = GetFromRendererID(param.id);
    if (!node)
      continue;

    blink::WebAXEvent event_type = param.event_type;
    if (event_type == blink::WebAXEventFocus ||
        event_type == blink::WebAXEventBlur) {
      SetFocus(node, false);

      if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
          osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
        osk_state_ = OSK_ALLOWED;

      // Don't send a native focus event if the window itself doesn't
      // have focus.
      if (delegate_ && !delegate_->HasFocus())
        continue;
    }

    // Send the event event to the operating system.
    NotifyAccessibilityEvent(event_type, node);

    // Set initial focus when a page is loaded.
    if (event_type == blink::WebAXEventLoadComplete) {
      if (!focus_)
        SetFocus(root_, false);
      if (!delegate_ || delegate_->HasFocus())
        NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
    }
  }
}

BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
    BrowserAccessibility* root) {
  if (focus_ && (!root || focus_->IsDescendantOf(root)))
    return focus_;

  return NULL;
}

void BrowserAccessibilityManager::SetFocus(
    BrowserAccessibility* node, bool notify) {
  if (focus_ != node)
    focus_ = node;

  if (notify && node && delegate_)
    delegate_->SetAccessibilityFocus(node->renderer_id());
}

void BrowserAccessibilityManager::SetRoot(BrowserAccessibility* node) {
  root_ = node;
  NotifyRootChanged();
}

void BrowserAccessibilityManager::DoDefaultAction(
    const BrowserAccessibility& node) {
  if (delegate_)
    delegate_->AccessibilityDoDefaultAction(node.renderer_id());
}

void BrowserAccessibilityManager::ScrollToMakeVisible(
    const BrowserAccessibility& node, gfx::Rect subfocus) {
  if (delegate_) {
    delegate_->AccessibilityScrollToMakeVisible(node.renderer_id(), subfocus);
  }
}

void BrowserAccessibilityManager::ScrollToPoint(
    const BrowserAccessibility& node, gfx::Point point) {
  if (delegate_) {
    delegate_->AccessibilityScrollToPoint(node.renderer_id(), point);
  }
}

void BrowserAccessibilityManager::SetTextSelection(
    const BrowserAccessibility& node, int start_offset, int end_offset) {
  if (delegate_) {
    delegate_->AccessibilitySetTextSelection(
        node.renderer_id(), start_offset, end_offset);
  }
}

gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
  if (delegate_)
    return delegate_->GetViewBounds();
  return gfx::Rect();
}

void BrowserAccessibilityManager::UpdateNodesForTesting(
    const AccessibilityNodeData& node1,
    const AccessibilityNodeData& node2 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node3 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node4 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node5 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node6 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node7 /* = AccessibilityNodeData() */) {
  std::vector<AccessibilityNodeData> nodes;
  nodes.push_back(node1);
  if (node2.id != AccessibilityNodeData().id)
    nodes.push_back(node2);
  if (node3.id != AccessibilityNodeData().id)
    nodes.push_back(node3);
  if (node4.id != AccessibilityNodeData().id)
    nodes.push_back(node4);
  if (node5.id != AccessibilityNodeData().id)
    nodes.push_back(node5);
  if (node6.id != AccessibilityNodeData().id)
    nodes.push_back(node6);
  if (node7.id != AccessibilityNodeData().id)
    nodes.push_back(node7);
  UpdateNodes(nodes);
}

bool BrowserAccessibilityManager::UpdateNodes(
    const std::vector<AccessibilityNodeData>& nodes) {
  bool success = true;

  // First, update all of the nodes in the tree.
  for (size_t i = 0; i < nodes.size() && success; i++) {
    if (!UpdateNode(nodes[i]))
      success = false;
  }

  // In a second pass, call PostInitialize on each one - this must
  // be called after all of each node's children are initialized too.
  for (size_t i = 0; i < nodes.size() && success; i++) {
    // Note: it's not a bug for nodes[i].id to not be found in the tree.
    // Consider this example:
    // Before:
    // A
    //   B
    //     C
    //   D
    //     E
    //       F
    // After:
    // A
    //   B
    //     C
    //       F
    //   D
    // In this example, F is being reparented. The renderer scans the tree
    // in order. If can't update "C" to add "F" as a child, when "F" is still
    // a child of "E". So it first updates "E", to remove "F" as a child.
    // Later, it ends up deleting "E". So when we get here, "E" was updated as
    // part of this sequence but it no longer exists in the final tree, so
    // there's nothing to postinitialize.
    BrowserAccessibility* instance = GetFromRendererID(nodes[i].id);
    if (instance)
      instance->PostInitialize();
  }

  if (!success) {
    // A bad accessibility tree could lead to memory corruption.
    // Ask the delegate to crash the renderer, or if not available,
    // crash the browser.
    if (delegate_)
      delegate_->FatalAccessibilityTreeError();
    else
      CHECK(false);
  }

  return success;
}

BrowserAccessibility* BrowserAccessibilityManager::CreateNode(
    BrowserAccessibility* parent,
    int32 renderer_id,
    int32 index_in_parent) {
  BrowserAccessibility* node = factory_->Create();
  node->InitializeTreeStructure(
      this, parent, renderer_id, index_in_parent);
  AddNodeToMap(node);
  return node;
}

void BrowserAccessibilityManager::AddNodeToMap(BrowserAccessibility* node) {
  renderer_id_map_[node->renderer_id()] = node;
}

bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
  // This method updates one node in the tree based on serialized data
  // received from the renderer.

  // Create a set of child ids in |src| for fast lookup. If a duplicate id is
  // found, exit now with a fatal error before changing anything else.
  std::set<int32> new_child_ids;
  for (size_t i = 0; i < src.child_ids.size(); ++i) {
    if (new_child_ids.find(src.child_ids[i]) != new_child_ids.end())
      return false;
    new_child_ids.insert(src.child_ids[i]);
  }

  // Look up the node by id. If it's not found, then either the root
  // of the tree is being swapped, or we're out of sync with the renderer
  // and this is a serious error.
  BrowserAccessibility* instance = GetFromRendererID(src.id);
  if (!instance) {
    if (src.role != blink::WebAXRoleRootWebArea)
      return false;
    instance = CreateNode(NULL, src.id, 0);
  }

  // TODO(dmazzoni): avoid a linear scan here.
  for (size_t i = 0; i < src.bool_attributes.size(); i++) {
    if (src.bool_attributes[i].first ==
        AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) {
      instance->SetLocation(src.location);
      return true;
    }
  }

  // Update all of the node-specific data, like its role, state, name, etc.
  instance->InitializeData(src);

  //
  // Update the children in three steps:
  //
  // 1. Iterate over the old children and delete nodes that are no longer
  //    in the tree.
  // 2. Build up a vector of new children, reusing children that haven't
  //    changed (but may have been reordered) and adding new empty
  //    objects for new children.
  // 3. Swap in the new children vector for the old one.

  // Delete any previous children of this instance that are no longer
  // children first. We make a deletion-only pass first to prevent a
  // node that's being reparented from being the child of both its old
  // parent and new parent, which could lead to a double-free.
  // If a node is reparented, the renderer will always send us a fresh
  // copy of the node.
  const std::vector<BrowserAccessibility*>& old_children = instance->children();
  for (size_t i = 0; i < old_children.size(); ++i) {
    int old_id = old_children[i]->renderer_id();
    if (new_child_ids.find(old_id) == new_child_ids.end())
      old_children[i]->Destroy();
  }

  // Now build a vector of new children, reusing objects that were already
  // children of this node before.
  std::vector<BrowserAccessibility*> new_children;
  bool success = true;
  for (size_t i = 0; i < src.child_ids.size(); i++) {
    int32 child_renderer_id = src.child_ids[i];
    int32 index_in_parent = static_cast<int32>(i);
    BrowserAccessibility* child = GetFromRendererID(child_renderer_id);
    if (child) {
      if (child->parent() != instance) {
        // This is a serious error - nodes should never be reparented.
        // If this case occurs, continue so this node isn't left in an
        // inconsistent state, but return failure at the end.
        success = false;
        continue;
      }
      child->UpdateParent(instance, index_in_parent);
    } else {
      child = CreateNode(instance, child_renderer_id, index_in_parent);
    }
    new_children.push_back(child);
  }

  // Finally, swap in the new children vector for the old.
  instance->SwapChildren(new_children);

  // Handle the case where this node is the new root of the tree.
  if (src.role == blink::WebAXRoleRootWebArea &&
      (!root_ || root_->renderer_id() != src.id)) {
    if (root_)
      root_->Destroy();
    if (focus_ == root_)
      SetFocus(instance, false);
    SetRoot(instance);
  }

  // Keep track of what node is focused.
  if (src.role != blink::WebAXRoleRootWebArea &&
      src.role != blink::WebAXRoleWebArea &&
      (src.state >> blink::WebAXStateFocused & 1)) {
    SetFocus(instance, false);
  }
  return success;
}

}  // namespace content
<commit_msg>Update accessibility tree before sending events.<commit_after>// Copyright (c) 2012 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 "content/browser/accessibility/browser_accessibility_manager.h"

#include "base/logging.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/common/accessibility_messages.h"

namespace content {

BrowserAccessibility* BrowserAccessibilityFactory::Create() {
  return BrowserAccessibility::Create();
}

#if !defined(OS_MACOSX) && \
    !defined(OS_WIN) && \
    !defined(TOOLKIT_GTK) && \
    !defined(OS_ANDROID) \
// We have subclassess of BrowserAccessibilityManager on Mac, Linux/GTK,
// and Win. For any other platform, instantiate the base class.
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
    const AccessibilityNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory) {
  return new BrowserAccessibilityManager(src, delegate, factory);
}
#endif

BrowserAccessibilityManager::BrowserAccessibilityManager(
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
}

BrowserAccessibilityManager::BrowserAccessibilityManager(
    const AccessibilityNodeData& src,
    BrowserAccessibilityDelegate* delegate,
    BrowserAccessibilityFactory* factory)
    : delegate_(delegate),
      factory_(factory),
      root_(NULL),
      focus_(NULL),
      osk_state_(OSK_ALLOWED) {
  Initialize(src);
}

BrowserAccessibilityManager::~BrowserAccessibilityManager() {
  if (root_)
    root_->Destroy();
}

void BrowserAccessibilityManager::Initialize(const AccessibilityNodeData src) {
  std::vector<AccessibilityNodeData> nodes;
  nodes.push_back(src);
  if (!UpdateNodes(nodes))
    return;
  if (!focus_)
    SetFocus(root_, false);
}

// static
AccessibilityNodeData BrowserAccessibilityManager::GetEmptyDocument() {
  AccessibilityNodeData empty_document;
  empty_document.id = 0;
  empty_document.role = blink::WebAXRoleRootWebArea;
  return empty_document;
}

BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
  return root_;
}

BrowserAccessibility* BrowserAccessibilityManager::GetFromRendererID(
    int32 renderer_id) {
  base::hash_map<int32, BrowserAccessibility*>::iterator iter =
      renderer_id_map_.find(renderer_id);
  if (iter != renderer_id_map_.end())
    return iter->second;
  return NULL;
}

void BrowserAccessibilityManager::GotFocus(bool touch_event_context) {
  if (!touch_event_context)
    osk_state_ = OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED;

  if (!focus_)
    return;

  NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}

void BrowserAccessibilityManager::WasHidden() {
  osk_state_ = OSK_DISALLOWED_BECAUSE_TAB_HIDDEN;
}

void BrowserAccessibilityManager::GotMouseDown() {
  osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
  NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
}

bool BrowserAccessibilityManager::IsOSKAllowed(const gfx::Rect& bounds) {
  if (!delegate_ || !delegate_->HasFocus())
    return false;

  gfx::Point touch_point = delegate_->GetLastTouchEventLocation();
  return bounds.Contains(touch_point);
}

bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
  return true;
}

void BrowserAccessibilityManager::RemoveNode(BrowserAccessibility* node) {
  if (node == focus_)
    SetFocus(root_, false);
  int renderer_id = node->renderer_id();
  renderer_id_map_.erase(renderer_id);
}

void BrowserAccessibilityManager::OnAccessibilityEvents(
    const std::vector<AccessibilityHostMsg_EventParams>& params) {
  bool should_send_initial_focus = false;

  // Process all changes to the accessibility tree first.
  for (uint32 index = 0; index < params.size(); index++) {
    const AccessibilityHostMsg_EventParams& param = params[index];
    if (!UpdateNodes(param.nodes))
      return;

    // Set initial focus when a page is loaded.
    blink::WebAXEvent event_type = param.event_type;
    if (event_type == blink::WebAXEventLoadComplete) {
      if (!focus_) {
        SetFocus(root_, false);
        should_send_initial_focus = true;
      }
    }
  }

  if (should_send_initial_focus &&
      (!delegate_ || delegate_->HasFocus())) {
    NotifyAccessibilityEvent(blink::WebAXEventFocus, focus_);
  }

  // Now iterate over the events again and fire the events.
  for (uint32 index = 0; index < params.size(); index++) {
    const AccessibilityHostMsg_EventParams& param = params[index];

    // Find the node corresponding to the id that's the target of the
    // event (which may not be the root of the update tree).
    BrowserAccessibility* node = GetFromRendererID(param.id);
    if (!node)
      continue;

    blink::WebAXEvent event_type = param.event_type;
    if (event_type == blink::WebAXEventFocus ||
        event_type == blink::WebAXEventBlur) {
      SetFocus(node, false);

      if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
          osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
        osk_state_ = OSK_ALLOWED;

      // Don't send a native focus event if the window itself doesn't
      // have focus.
      if (delegate_ && !delegate_->HasFocus())
        continue;
    }

    // Send the event event to the operating system.
    NotifyAccessibilityEvent(event_type, node);
  }
}

BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
    BrowserAccessibility* root) {
  if (focus_ && (!root || focus_->IsDescendantOf(root)))
    return focus_;

  return NULL;
}

void BrowserAccessibilityManager::SetFocus(
    BrowserAccessibility* node, bool notify) {
  if (focus_ != node)
    focus_ = node;

  if (notify && node && delegate_)
    delegate_->SetAccessibilityFocus(node->renderer_id());
}

void BrowserAccessibilityManager::SetRoot(BrowserAccessibility* node) {
  root_ = node;
  NotifyRootChanged();
}

void BrowserAccessibilityManager::DoDefaultAction(
    const BrowserAccessibility& node) {
  if (delegate_)
    delegate_->AccessibilityDoDefaultAction(node.renderer_id());
}

void BrowserAccessibilityManager::ScrollToMakeVisible(
    const BrowserAccessibility& node, gfx::Rect subfocus) {
  if (delegate_) {
    delegate_->AccessibilityScrollToMakeVisible(node.renderer_id(), subfocus);
  }
}

void BrowserAccessibilityManager::ScrollToPoint(
    const BrowserAccessibility& node, gfx::Point point) {
  if (delegate_) {
    delegate_->AccessibilityScrollToPoint(node.renderer_id(), point);
  }
}

void BrowserAccessibilityManager::SetTextSelection(
    const BrowserAccessibility& node, int start_offset, int end_offset) {
  if (delegate_) {
    delegate_->AccessibilitySetTextSelection(
        node.renderer_id(), start_offset, end_offset);
  }
}

gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
  if (delegate_)
    return delegate_->GetViewBounds();
  return gfx::Rect();
}

void BrowserAccessibilityManager::UpdateNodesForTesting(
    const AccessibilityNodeData& node1,
    const AccessibilityNodeData& node2 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node3 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node4 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node5 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node6 /* = AccessibilityNodeData() */,
    const AccessibilityNodeData& node7 /* = AccessibilityNodeData() */) {
  std::vector<AccessibilityNodeData> nodes;
  nodes.push_back(node1);
  if (node2.id != AccessibilityNodeData().id)
    nodes.push_back(node2);
  if (node3.id != AccessibilityNodeData().id)
    nodes.push_back(node3);
  if (node4.id != AccessibilityNodeData().id)
    nodes.push_back(node4);
  if (node5.id != AccessibilityNodeData().id)
    nodes.push_back(node5);
  if (node6.id != AccessibilityNodeData().id)
    nodes.push_back(node6);
  if (node7.id != AccessibilityNodeData().id)
    nodes.push_back(node7);
  UpdateNodes(nodes);
}

bool BrowserAccessibilityManager::UpdateNodes(
    const std::vector<AccessibilityNodeData>& nodes) {
  bool success = true;

  // First, update all of the nodes in the tree.
  for (size_t i = 0; i < nodes.size() && success; i++) {
    if (!UpdateNode(nodes[i]))
      success = false;
  }

  // In a second pass, call PostInitialize on each one - this must
  // be called after all of each node's children are initialized too.
  for (size_t i = 0; i < nodes.size() && success; i++) {
    // Note: it's not a bug for nodes[i].id to not be found in the tree.
    // Consider this example:
    // Before:
    // A
    //   B
    //     C
    //   D
    //     E
    //       F
    // After:
    // A
    //   B
    //     C
    //       F
    //   D
    // In this example, F is being reparented. The renderer scans the tree
    // in order. If can't update "C" to add "F" as a child, when "F" is still
    // a child of "E". So it first updates "E", to remove "F" as a child.
    // Later, it ends up deleting "E". So when we get here, "E" was updated as
    // part of this sequence but it no longer exists in the final tree, so
    // there's nothing to postinitialize.
    BrowserAccessibility* instance = GetFromRendererID(nodes[i].id);
    if (instance)
      instance->PostInitialize();
  }

  if (!success) {
    // A bad accessibility tree could lead to memory corruption.
    // Ask the delegate to crash the renderer, or if not available,
    // crash the browser.
    if (delegate_)
      delegate_->FatalAccessibilityTreeError();
    else
      CHECK(false);
  }

  return success;
}

BrowserAccessibility* BrowserAccessibilityManager::CreateNode(
    BrowserAccessibility* parent,
    int32 renderer_id,
    int32 index_in_parent) {
  BrowserAccessibility* node = factory_->Create();
  node->InitializeTreeStructure(
      this, parent, renderer_id, index_in_parent);
  AddNodeToMap(node);
  return node;
}

void BrowserAccessibilityManager::AddNodeToMap(BrowserAccessibility* node) {
  renderer_id_map_[node->renderer_id()] = node;
}

bool BrowserAccessibilityManager::UpdateNode(const AccessibilityNodeData& src) {
  // This method updates one node in the tree based on serialized data
  // received from the renderer.

  // Create a set of child ids in |src| for fast lookup. If a duplicate id is
  // found, exit now with a fatal error before changing anything else.
  std::set<int32> new_child_ids;
  for (size_t i = 0; i < src.child_ids.size(); ++i) {
    if (new_child_ids.find(src.child_ids[i]) != new_child_ids.end())
      return false;
    new_child_ids.insert(src.child_ids[i]);
  }

  // Look up the node by id. If it's not found, then either the root
  // of the tree is being swapped, or we're out of sync with the renderer
  // and this is a serious error.
  BrowserAccessibility* instance = GetFromRendererID(src.id);
  if (!instance) {
    if (src.role != blink::WebAXRoleRootWebArea)
      return false;
    instance = CreateNode(NULL, src.id, 0);
  }

  // TODO(dmazzoni): avoid a linear scan here.
  for (size_t i = 0; i < src.bool_attributes.size(); i++) {
    if (src.bool_attributes[i].first ==
        AccessibilityNodeData::ATTR_UPDATE_LOCATION_ONLY) {
      instance->SetLocation(src.location);
      return true;
    }
  }

  // Update all of the node-specific data, like its role, state, name, etc.
  instance->InitializeData(src);

  //
  // Update the children in three steps:
  //
  // 1. Iterate over the old children and delete nodes that are no longer
  //    in the tree.
  // 2. Build up a vector of new children, reusing children that haven't
  //    changed (but may have been reordered) and adding new empty
  //    objects for new children.
  // 3. Swap in the new children vector for the old one.

  // Delete any previous children of this instance that are no longer
  // children first. We make a deletion-only pass first to prevent a
  // node that's being reparented from being the child of both its old
  // parent and new parent, which could lead to a double-free.
  // If a node is reparented, the renderer will always send us a fresh
  // copy of the node.
  const std::vector<BrowserAccessibility*>& old_children = instance->children();
  for (size_t i = 0; i < old_children.size(); ++i) {
    int old_id = old_children[i]->renderer_id();
    if (new_child_ids.find(old_id) == new_child_ids.end())
      old_children[i]->Destroy();
  }

  // Now build a vector of new children, reusing objects that were already
  // children of this node before.
  std::vector<BrowserAccessibility*> new_children;
  bool success = true;
  for (size_t i = 0; i < src.child_ids.size(); i++) {
    int32 child_renderer_id = src.child_ids[i];
    int32 index_in_parent = static_cast<int32>(i);
    BrowserAccessibility* child = GetFromRendererID(child_renderer_id);
    if (child) {
      if (child->parent() != instance) {
        // This is a serious error - nodes should never be reparented.
        // If this case occurs, continue so this node isn't left in an
        // inconsistent state, but return failure at the end.
        success = false;
        continue;
      }
      child->UpdateParent(instance, index_in_parent);
    } else {
      child = CreateNode(instance, child_renderer_id, index_in_parent);
    }
    new_children.push_back(child);
  }

  // Finally, swap in the new children vector for the old.
  instance->SwapChildren(new_children);

  // Handle the case where this node is the new root of the tree.
  if (src.role == blink::WebAXRoleRootWebArea &&
      (!root_ || root_->renderer_id() != src.id)) {
    if (root_)
      root_->Destroy();
    if (focus_ == root_)
      SetFocus(instance, false);
    SetRoot(instance);
  }

  // Keep track of what node is focused.
  if (src.role != blink::WebAXRoleRootWebArea &&
      src.role != blink::WebAXRoleWebArea &&
      (src.state >> blink::WebAXStateFocused & 1)) {
    SetFocus(instance, false);
  }
  return success;
}

}  // namespace content
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_BOOTSTRAP_THEME_HPP
#define CPM_BOOTSTRAP_THEME_HPP

#include "cpm/io.hpp"
#include "cpm/data.hpp"

namespace cpm {

struct bootstrap_theme {
    const reports_data& data;
    cxxopts::Options& options;
    std::ostream& stream;
    std::string current_compiler;
    std::string current_configuration;

    bootstrap_theme(const reports_data& data, cxxopts::Options& options, std::ostream& stream, std::string compiler, std::string configuration)
        : data(data), options(options), stream(stream), current_compiler(std::move(compiler)), current_configuration(std::move(configuration)) {}

    void include(){
        stream << "\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\" rel=\"stylesheet\">\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n";
    }

    void header(){
        stream << R"=====(

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
            Toggle navigation

            </button>
            Results

Home

Generated with CPM

        )=====";
    }

    void footer(){
        stream << R"=====(

Generated with CPM

        )=====";
    }

    void before_information(){
        stream << "
\n";
        stream << "
\n";
    }

    void after_information(){
        stream << "
\n";
        stream << "
\n";
        stream << "
\n";
    }

    void compiler_buttons(){
        stream << R"=====(
)=====";
        stream << R"=====(
)=====";

        stream << R"=====(Select compiler: )=====";

        stream << R"=====(
)=====";
        for(auto& compiler : data.compilers){
            if(compiler == current_compiler){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    void configuration_buttons(){
        if(data.compilers.size() > 1){
            stream << R"=====(
)=====";
        } else {
            stream << R"=====(
)=====";
        }

        stream << R"=====(
)=====";

        stream << R"=====(Select configuration: )=====";

        stream << R"=====(
)=====";
        for(auto& configuration : data.configurations){
            if(configuration == current_configuration){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    virtual void start_column(const std::string& style = ""){
        std::size_t columns = 1; //Always the first grapah

        if(data.documents.size() > 1 && !options.count("disable-time")){
            ++columns;
        }

        if(data.compilers.size() > 1 && !options.count("disable-compiler")){
            ++columns;
        }

        if(data.configurations.size() > 1 && !options.count("disable-configuration")){
            ++columns;
        }

        if(!options.count("disable-summary")){
            ++columns;
        }

        stream << "<div class=\"col-xs-" << 12 / columns << "\"" << style << ">\n";
    }

    virtual void close_column(){
        stream << "
\n";
    }

    void before_graph(std::size_t id){
        start_column();

        stream << "<div id=\"chart_" << id << "\" style=\"height: 400px;\">
\n";
    }

    void after_graph(){
        close_column();
    }

    void before_result(const std::string& title, bool sub = false){
        stream << "
\n";
        stream << "
" << title << "
\n";
        stream << "
\n";

        if(sub){
            stream << "
\n";
        } else {
            stream << "
\n";
        }
    }

    void after_result(){
        stream << "
\n";
    }

    void before_sub_graphs(std::size_t id, std::vector<std::string> graphs){
        start_column("style=\"align-self: flex-start; \"");

        stream << "
\n";
        stream << "
\n";

        std::string active = "class=\"active\"";
        std::size_t sub = 0;
        for(auto& g : graphs){
            auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub++);
            stream << "<li " << active << " role=\"presentation\"><a href=\"#" << sub_id << "\" aria-controls=\""
                << sub_id << "\" role=\"tab\" data-toggle=\"tab\">" << g << "
\n";
            active = "";
        }

        stream << "
\n";
        stream << "
\n";
    }

    void after_sub_graphs(){
        stream << "
\n";
        stream << "
\n";

        close_column();
    }

    void before_sub_graph(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }
        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";

        stream << "<div id=\"chart_" << id << "-" << sub << "\" style=\"height: 400px;\">
\n";
    }

    void after_sub_graph(){
        stream << "
\n";
    }

    void before_summary(){
        start_column();

        stream << "
\n";
    }

    void after_summary(){
        stream << "
\n";

        close_column();
    }

    void before_sub_summary(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }

        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";
        stream << "
\n";
    }

    void after_sub_summary(){
        stream << "
\n";
        stream << "
\n";
    }

    void cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    void red_cell(const std::string& v){
        stream << ""<< v << "	\n";
    }

    void green_cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    template<typename T>
    bootstrap_theme& operator<<(const T& v){
        stream << v;
        return *this;
    }
};

} //end of namespace cpm

#endif //CPM_BOOTSTRAP_THEME_HPP
<commit_msg>Improve the theme<commit_after>//=======================================================================
// Copyright (c) 2015 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef CPM_BOOTSTRAP_THEME_HPP
#define CPM_BOOTSTRAP_THEME_HPP

#include "cpm/io.hpp"
#include "cpm/data.hpp"

namespace cpm {

struct bootstrap_theme {
    const reports_data& data;
    cxxopts::Options& options;
    std::ostream& stream;
    std::string current_compiler;
    std::string current_configuration;

    std::size_t current_column = 0;

    bootstrap_theme(const reports_data& data, cxxopts::Options& options, std::ostream& stream, std::string compiler, std::string configuration)
        : data(data), options(options), stream(stream), current_compiler(std::move(compiler)), current_configuration(std::move(configuration)) {}

    void include(){
        stream << "\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css\" rel=\"stylesheet\">\n";
        stream << "<link href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap-theme.min.css\" rel=\"stylesheet\">\n";
    }

    void header(){
        stream << R"=====(

            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbarCollapse">
            Toggle navigation

            </button>
            Results

Home

Generated with CPM

        )=====";
    }

    void footer(){
        stream << R"=====(

Generated with CPM

        )=====";
    }

    void before_information(){
        stream << "
\n";
        stream << "
\n";
    }

    void after_information(){
        stream << "
\n";
        stream << "
\n";
        stream << "
\n";
    }

    void compiler_buttons(){
        stream << R"=====(
)=====";
        stream << R"=====(
)=====";

        stream << R"=====(Select compiler: )=====";

        stream << R"=====(
)=====";
        for(auto& compiler : data.compilers){
            if(compiler == current_compiler){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(compiler, current_configuration)  << "\">" << compiler << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    void configuration_buttons(){
        if(data.compilers.size() > 1){
            stream << R"=====(
)=====";
        } else {
            stream << R"=====(
)=====";
        }

        stream << R"=====(
)=====";

        stream << R"=====(Select configuration: )=====";

        stream << R"=====(
)=====";
        for(auto& configuration : data.configurations){
            if(configuration == current_configuration){
                stream << "<a class=\"btn btn-primary\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            } else {
                stream << "<a class=\"btn btn-default\" href=\"" << cpm::filify(current_compiler, configuration)  << "\">" << configuration << "\n";
            }
        }
        stream << "
\n";

        stream << "
\n";
        stream << "
\n";
    }

    virtual void start_column(const std::string& style = ""){
        std::size_t columns = 1; //Always the first grapah

        if(data.documents.size() > 1 && !options.count("disable-time")){
            ++columns;
        }

        if(data.compilers.size() > 1 && !options.count("disable-compiler")){
            ++columns;
        }

        if(data.configurations.size() > 1 && !options.count("disable-configuration")){
            ++columns;
        }

        if(!options.count("disable-summary")){
            ++columns;
        }

        if(columns < 4){
            stream << "<div class=\"col-xs-" << 12 / columns << "\"" << style << ">\n";
        } else if(columns == 4){
            if(current_column == 2){
                stream << "
\n";
                stream << "
\n";
            }

            stream << "<div class=\"col-xs-6\"" << style << ">\n";
        } else if(columns == 5){
            if(current_column == 3){
                stream << "
\n";
                stream << "
\n";
            }

            if(current_column < 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 3){
                stream << "<div class=\"col-xs-4\"" << style << ">\n";
            } else if(current_column == 4){
                stream << "<div class=\"col-xs-8\"" << style << ">\n";
            }
        }

        ++current_column;
    }

    virtual void close_column(){
        stream << "
\n";
    }

    void before_graph(std::size_t id){
        start_column();

        stream << "<div id=\"chart_" << id << "\" style=\"height: 400px;\">
\n";
    }

    void after_graph(){
        close_column();
    }

    void before_result(const std::string& title, bool sub = false){
        stream << "
\n";
        stream << "
" << title << "
\n";
        stream << "
\n";

        if(sub){
            stream << "
\n";
        } else {
            stream << "
\n";
        }

        current_column = 0;
    }

    void after_result(){
        stream << "
\n";
    }

    void before_sub_graphs(std::size_t id, std::vector<std::string> graphs){
        start_column("style=\"align-self: flex-start; \"");

        stream << "
\n";
        stream << "
\n";

        std::string active = "class=\"active\"";
        std::size_t sub = 0;
        for(auto& g : graphs){
            auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub++);
            stream << "<li " << active << " role=\"presentation\"><a href=\"#" << sub_id << "\" aria-controls=\""
                << sub_id << "\" role=\"tab\" data-toggle=\"tab\">" << g << "
\n";
            active = "";
        }

        stream << "
\n";
        stream << "
\n";
    }

    void after_sub_graphs(){
        stream << "
\n";
        stream << "
\n";

        close_column();
    }

    void before_sub_graph(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }
        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";

        stream << "<div id=\"chart_" << id << "-" << sub << "\" style=\"height: 400px;\">
\n";
    }

    void after_sub_graph(){
        stream << "
\n";
    }

    void before_summary(){
        start_column();

        stream << "
\n";
    }

    void after_summary(){
        stream << "
\n";

        close_column();
    }

    void before_sub_summary(std::size_t id, std::size_t sub){
        auto sub_id = std::string("sub") + std::to_string(id) + "-" + std::to_string(sub);
        std::string active;
        if(sub == 0){
            active = " active";
        }

        stream << "<div role=\"tabpanel\" class=\"tab-pane" << active << "\" id=\"" << sub_id << "\">\n";
        stream << "
\n";
    }

    void after_sub_summary(){
        stream << "
\n";
        stream << "
\n";
    }

    void cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    void red_cell(const std::string& v){
        stream << ""<< v << "	\n";
    }

    void green_cell(const std::string& v){
        stream << "" << v << "	\n";
    }

    template<typename T>
    bootstrap_theme& operator<<(const T& v){
        stream << v;
        return *this;
    }
};

} //end of namespace cpm

#endif //CPM_BOOTSTRAP_THEME_HPP
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: gtkdata.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2004-05-10 15:54:49 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _VCL_GTKDATA_HXX
#define _VCL_GTKDATA_HXX

#include <prex.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <postx.h>

#include <saldisp.hxx>
#include <saldata.hxx>
#include <ptrstyle.hxx>

#include <list>

class GtkData : public SalData
{
public:
    GtkData() {}
    virtual ~GtkData();

    virtual void Init();

    virtual void initNWF();
    virtual void deInitNWF();
};

class GtkSalFrame;

class GtkSalDisplay : public SalDisplay
{
    GdkDisplay*                     m_pGdkDisplay;
    GdkCursor                      *m_aCursors[ POINTER_COUNT ];
    GdkCursor* getFromXPM( const char *pBitmap, const char *pMask,
                           int nWidth, int nHeight, int nXHot, int nYHot );
public:
             GtkSalDisplay( GdkDisplay* pDisplay, Visual* pVis, Colormap aCol );
    virtual ~GtkSalDisplay();

    GdkDisplay* GetGdkDisplay() const { return m_pGdkDisplay; }

    virtual void deregisterFrame( SalFrame* pFrame );
    GdkCursor *getCursor( PointerStyle ePointerStyle );
    virtual int CaptureMouse( SalFrame* pFrame );
    virtual long Dispatch( XEvent *pEvent );

    static GdkFilterReturn filterGdkEvent( GdkXEvent* sys_event,
                                           GdkEvent* event,
                                           gpointer data );
    inline bool HasMoreEvents()     { return m_aUserEvents.size() > 1; }
    inline void EventGuardAcquire() { osl_acquireMutex( hEventGuard_ ); }
    inline void EventGuardRelease() { osl_releaseMutex( hEventGuard_ ); }
};

#endif // _VCL_GTKDATA_HXX
<commit_msg>INTEGRATION: CWS ooo19126 (1.3.454); FILE MERGED 2005/09/05 14:45:33 rt 1.3.454.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: gtkdata.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 12:51:01 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _VCL_GTKDATA_HXX
#define _VCL_GTKDATA_HXX

#include <prex.h>
#include <gdk/gdk.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <postx.h>

#include <saldisp.hxx>
#include <saldata.hxx>
#include <ptrstyle.hxx>

#include <list>

class GtkData : public SalData
{
public:
    GtkData() {}
    virtual ~GtkData();

    virtual void Init();

    virtual void initNWF();
    virtual void deInitNWF();
};

class GtkSalFrame;

class GtkSalDisplay : public SalDisplay
{
    GdkDisplay*                     m_pGdkDisplay;
    GdkCursor                      *m_aCursors[ POINTER_COUNT ];
    GdkCursor* getFromXPM( const char *pBitmap, const char *pMask,
                           int nWidth, int nHeight, int nXHot, int nYHot );
public:
             GtkSalDisplay( GdkDisplay* pDisplay, Visual* pVis, Colormap aCol );
    virtual ~GtkSalDisplay();

    GdkDisplay* GetGdkDisplay() const { return m_pGdkDisplay; }

    virtual void deregisterFrame( SalFrame* pFrame );
    GdkCursor *getCursor( PointerStyle ePointerStyle );
    virtual int CaptureMouse( SalFrame* pFrame );
    virtual long Dispatch( XEvent *pEvent );

    static GdkFilterReturn filterGdkEvent( GdkXEvent* sys_event,
                                           GdkEvent* event,
                                           gpointer data );
    inline bool HasMoreEvents()     { return m_aUserEvents.size() > 1; }
    inline void EventGuardAcquire() { osl_acquireMutex( hEventGuard_ ); }
    inline void EventGuardRelease() { osl_releaseMutex( hEventGuard_ ); }
};

#endif // _VCL_GTKDATA_HXX
<|endoftext|>


<commit_before>/**
 * \file
 * \brief FifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-12-09
 */

#ifndef INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_FIFOQUEUE_HPP_

#include "distortos/scheduler/FifoQueueBase.hpp"

namespace distortos
{

/**
 * \brief FifoQueue class is a simple FIFO queue for thread-thread, thread-interrupt or interrupt-interrupt
 * communication. It supports multiple readers and multiple writers. It is implemented as a thin wrapper for
 * scheduler::FifoQueueBase.
 *
 * \param T is the type of data in queue
 */

template<typename T>
class FifoQueue : private scheduler::FifoQueueBase
{
public:

	/// type of uninitialized storage for data
	using Storage = Storage<T>;

	/**
	 * \brief FifoQueue's constructor
	 *
	 * \param [in] storage is an array of Storage elements
	 * \param [in] maxElements is the number of elements in storage array
	 */

	FifoQueue(Storage* const storage, const size_t maxElements) :
			FifoQueueBase{storage, maxElements, TypeTag<T>{}}
	{

	}

	/**
	 * \brief Pops the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::pop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int pop(T& value)
	{
		return FifoQueueBase::pop(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(const T& value)
	{
		return FifoQueueBase::push(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(T&& value)
	{
		return FifoQueueBase::push(std::move(value));
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPop(T& value)
	{
		return FifoQueueBase::tryPop(value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(const T& value)
	{
		return FifoQueueBase::tryPush(value);
	}
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
<commit_msg>FifoQueue: add FifoQueue::tryPush(T&&)<commit_after>/**
 * \file
 * \brief FifoQueue class header
 *
 * \author Copyright (C) 2014 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * 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/.
 *
 * \date 2014-12-09
 */

#ifndef INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
#define INCLUDE_DISTORTOS_FIFOQUEUE_HPP_

#include "distortos/scheduler/FifoQueueBase.hpp"

namespace distortos
{

/**
 * \brief FifoQueue class is a simple FIFO queue for thread-thread, thread-interrupt or interrupt-interrupt
 * communication. It supports multiple readers and multiple writers. It is implemented as a thin wrapper for
 * scheduler::FifoQueueBase.
 *
 * \param T is the type of data in queue
 */

template<typename T>
class FifoQueue : private scheduler::FifoQueueBase
{
public:

	/// type of uninitialized storage for data
	using Storage = Storage<T>;

	/**
	 * \brief FifoQueue's constructor
	 *
	 * \param [in] storage is an array of Storage elements
	 * \param [in] maxElements is the number of elements in storage array
	 */

	FifoQueue(Storage* const storage, const size_t maxElements) :
			FifoQueueBase{storage, maxElements, TypeTag<T>{}}
	{

	}

	/**
	 * \brief Pops the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::pop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int pop(T& value)
	{
		return FifoQueueBase::pop(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(const T& value)
	{
		return FifoQueueBase::push(value);
	}

	/**
	 * \brief Pushes the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::push(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::wait();
	 * - error codes returned by Semaphore::post();
	 */

	int push(T&& value)
	{
		return FifoQueueBase::push(std::move(value));
	}

	/**
	 * \brief Tries to pop the oldest (first) element from the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPop(T&)
	 *
	 * \param [out] value is a reference to object that will be used to return popped value, its contents are swapped
	 * with the value in the queue's storage and destructed when no longer needed
	 *
	 * \return zero if element was popped successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPop(T& value)
	{
		return FifoQueueBase::tryPop(value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(const T&)
	 *
	 * \param [in] value is a reference to object that will be pushed, value in queue's storage is copy-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(const T& value)
	{
		return FifoQueueBase::tryPush(value);
	}

	/**
	 * \brief Tries to push the element to the queue.
	 *
	 * Wrapper for scheduler::FifoQueueBase::tryPush(T&&)
	 *
	 * \param [in] value is a rvalue reference to object that will be pushed, value in queue's storage is
	 * move-constructed
	 *
	 * \return zero if element was pushed successfully, error code otherwise:
	 * - error codes returned by Semaphore::tryWait();
	 * - error codes returned by Semaphore::post();
	 */

	int tryPush(T&& value)
	{
		return FifoQueueBase::tryPush(std::move(value));
	}
};

}	// namespace distortos

#endif	// INCLUDE_DISTORTOS_FIFOQUEUE_HPP_
<|endoftext|>


<commit_before>/**
 *  Jsonpack - Reals traits for json operations
 *
 *  Copyright (c) 2015 Yadiel Martinez Gonzalez <ymglez2015@gmail.com>
 *
 *  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.
 */

#ifndef JSONPACK_REALS_HPP
#define JSONPACK_REALS_HPP

#include "jsonpack/type/json_traits_base.hpp"

JSONPACK_API_BEGIN_NAMESPACE
TYPE_BEGIN_NAMESPACE

//-------------------------- FLOAT --------------------------------
template<>
struct json_traits<float>
{

    static void append(buffer &json, const char *key, const float &value)
    {
        util::json_builder::append_real(json, key, value);
    }

    static void append(buffer &json, const float &value)
    {
        util::json_builder::append_real(json, value);
    }
};

template<>
struct json_traits<float&>
{
    static void extract(const object_t &json, char* json_ptr, const char *key, const std::size_t &len, float &value)
    {
        jsonpack::key k;
        k._bytes = len;
        k._ptr = key;

        object_t::const_iterator found = json.find(k);
        if( found != json.end() )    // exist the current key
        {
            if( match_token_type(found->second) )
            {
                extract(found->second, json_ptr, value);
            }
            else
            {
                std::string msg = "Invalid float value for key: ";
                msg += key;
                throw type_error( msg.data() );
            }
        }
    }

    static void extract(const jsonpack::value &v, char* json_ptr, float &value)
    {
        position p = v._pos;

        char * str_value = json_ptr+p._pos;   //pointing to the start
        char buffer[DOUBLE_MAX_DIGITS + 1];
        memcpy(buffer, str_value, p._count < DOUBLE_MAX_DIGITS + 1 ? p._count : DOUBLE_MAX_DIGITS + 1);
        buffer[p._count] = '\0';        //null-terminated

#ifndef _MSC_VER
        value = std::strtof(buffer, nullptr);
        if(errno) // check range
            throw type_error("Float out of range");
#else
        double v_cpy = std::strtod(buffer, nullptr);
        if(errno ||
                v_cpy > std::numeric_limits<float>::max() ||
                v_cpy < std::numeric_limits<float>::min() )
            throw type_error("Float out of range");
		value = static_cast<float>(v_cpy);
#endif
    }

    static bool match_token_type(const jsonpack::value &v)
    {
        return (v._field == _POS &&
                (v._pos._type == JTK_INTEGER || v._pos._type == JTK_REAL ) );
    }

};

//-------------------------- DOUBLE --------------------------------
template<>
struct json_traits<double>
{
    static void append(buffer &json, const char *key, const double &value)
    {
        util::json_builder::append_real(json, key, value);
    }

    static void append(buffer &json, const double &value)
    {
        util::json_builder::append_real(json, value);
    }
};

template<>
struct json_traits<double&>
{
    static void extract(const object_t &json, char* json_ptr, const char *key, const std::size_t &len, double &value)
    {
        jsonpack::key k;
        k._bytes = len;
        k._ptr = key;

        object_t::const_iterator found = json.find(k);
        if( found != json.end() )    // exist the current key
        {
            if( match_token_type(found->second) )
            {
                extract(found->second, json_ptr, value);
            }
            else
            {
                std::string msg = "Invalid double value for key: ";
                msg += key;
                throw type_error( msg.data() );
            }
        }
    }

    static void extract(const jsonpack::value &v, char* json_ptr, double &value)
    {
        position p = v._pos;
        char * str_value = json_ptr+p._pos;   //pointing to the start

        char buffer[DOUBLE_MAX_DIGITS + 1];
        memcpy(buffer, str_value, p._count < DOUBLE_MAX_DIGITS + 1 ? p._count : DOUBLE_MAX_DIGITS + 1);
        buffer[p._count] = '\0';        //null-terminated

        value = std::strtod(buffer, nullptr);

        if(errno) // check range
            throw type_error("Double out of range");
    }

    static bool match_token_type(const jsonpack::value &v)
    {
        return (v._field == _POS &&
                (v._pos._type == JTK_INTEGER || v._pos._type == JTK_REAL ) );
    }

};

JSONPACK_API_END_NAMESPACE //type
JSONPACK_API_END_NAMESPACE //jsonpack

#endif // JSONPACK_REALS_HPP

<commit_msg>Fix size check in reals<commit_after>/**
 *  Jsonpack - Reals traits for json operations
 *
 *  Copyright (c) 2015 Yadiel Martinez Gonzalez <ymglez2015@gmail.com>
 *
 *  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.
 */

#ifndef JSONPACK_REALS_HPP
#define JSONPACK_REALS_HPP

#include "jsonpack/type/json_traits_base.hpp"

JSONPACK_API_BEGIN_NAMESPACE
TYPE_BEGIN_NAMESPACE

//-------------------------- FLOAT --------------------------------
template<>
struct json_traits<float>
{

    static void append(buffer &json, const char *key, const float &value)
    {
        util::json_builder::append_real(json, key, value);
    }

    static void append(buffer &json, const float &value)
    {
        util::json_builder::append_real(json, value);
    }
};

template<>
struct json_traits<float&>
{
    static void extract(const object_t &json, char* json_ptr, const char *key, const std::size_t &len, float &value)
    {
        jsonpack::key k;
        k._bytes = len;
        k._ptr = key;

        object_t::const_iterator found = json.find(k);
        if( found != json.end() )    // exist the current key
        {
            if( match_token_type(found->second) )
            {
                extract(found->second, json_ptr, value);
            }
            else
            {
                std::string msg = "Invalid float value for key: ";
                msg += key;
                throw type_error( msg.data() );
            }
        }
    }

    static void extract(const jsonpack::value &v, char* json_ptr, float &value)
    {
        position p = v._pos;

        char * str_value = json_ptr + p._pos;   //pointing to the start
        char buffer[DOUBLE_MAX_DIGITS + 1];
        const unsigned long len = p._count < DOUBLE_MAX_DIGITS + 1 ? p._count : DOUBLE_MAX_DIGITS ;
        memcpy(buffer, str_value, len);
        buffer[len] = '\0';    //null-terminated

#ifndef _MSC_VER
        value = std::strtof(buffer, nullptr);
        if(errno) // check range
            throw type_error("Float out of range");
#else
        double v_cpy = std::strtod(buffer, nullptr);
        if(errno ||
                v_cpy > std::numeric_limits<float>::max() ||
                v_cpy < std::numeric_limits<float>::min() )
            throw type_error("Float out of range");
		value = static_cast<float>(v_cpy);
#endif
    }

    static bool match_token_type(const jsonpack::value &v)
    {
        return (v._field == _POS &&
                (v._pos._type == JTK_INTEGER || v._pos._type == JTK_REAL ) );
    }

};

//-------------------------- DOUBLE --------------------------------
template<>
struct json_traits<double>
{
    static void append(buffer &json, const char *key, const double &value)
    {
        util::json_builder::append_real(json, key, value);
    }

    static void append(buffer &json, const double &value)
    {
        util::json_builder::append_real(json, value);
    }
};

template<>
struct json_traits<double&>
{
    static void extract(const object_t &json, char* json_ptr, const char *key, const std::size_t &len, double &value)
    {
        jsonpack::key k;
        k._bytes = len;
        k._ptr = key;

        object_t::const_iterator found = json.find(k);
        if( found != json.end() )    // exist the current key
        {
            if( match_token_type(found->second) )
            {
                extract(found->second, json_ptr, value);
            }
            else
            {
                std::string msg = "Invalid double value for key: ";
                msg += key;
                throw type_error( msg.data() );
            }
        }
    }

    static void extract(const jsonpack::value &v, char* json_ptr, double &value)
    {
        position p = v._pos;
        char * str_value = json_ptr + p._pos; //pointing to the start
        char buffer[DOUBLE_MAX_DIGITS + 1];
        const unsigned long len = p._count < DOUBLE_MAX_DIGITS + 1 ? p._count : DOUBLE_MAX_DIGITS ;
        memcpy(buffer, str_value, len);
        buffer[len] = '\0';     //null-terminated

        value = std::strtod(buffer, nullptr);

        if(errno) // check range
            throw type_error("Double out of range");
    }

    static bool match_token_type(const jsonpack::value &v)
    {
        return (v._field == _POS &&
                (v._pos._type == JTK_INTEGER || v._pos._type == JTK_REAL ) );
    }

};

JSONPACK_API_END_NAMESPACE //type
JSONPACK_API_END_NAMESPACE //jsonpack

#endif // JSONPACK_REALS_HPP

<|endoftext|>


<commit_before>/*

Copyright (c) 2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_IP_VOTER_HPP_INCLUDED
#define TORRENT_IP_VOTER_HPP_INCLUDED

#include <vector>
#include "libtorrent/address.hpp"
#include "libtorrent/bloom_filter.hpp"

namespace libtorrent
{
	// this is an object that keeps the state for a single external IP
	// based on peoples votes
	struct TORRENT_EXTRA_EXPORT ip_voter
	{
		// returns true if a different IP is the top vote now
		// i.e. we changed our idea of what our external IP is
		bool cast_vote(address const& ip, int source_type, address const& sorce);

		address external_address() const { return m_external_address; }

	private:

		struct external_ip_t
		{
			external_ip_t(): sources(0), num_votes(0) {}

			bool add_vote(sha1_hash const& k, int type);
			bool operator<(external_ip_t const& rhs) const
			{
				if (num_votes < rhs.num_votes) return true;
				if (num_votes > rhs.num_votes) return false;
				return sources < rhs.sources;
			}

			// this is a bloom filter of the IPs that have
			// reported this address
			bloom_filter<16> voters;
			// this is the actual external address
			address addr;
			// a bitmask of sources the reporters have come from
			boost::uint16_t sources;
			// the total number of votes for this IP
			boost::uint16_t num_votes;
		};

		// this is a bloom filter of all the IPs that have
		// been the first to report an external address. Each
		// IP only gets to add a new item once.
		bloom_filter<32> m_external_address_voters;
		std::vector<external_ip_t> m_external_addresses;
		address m_external_address;
	};

	// this keeps track of multiple external IPs (for now, just IPv6 and IPv4, but
	// it could be extended to deal with loopback and local network addresses as well)
	struct external_ip
	{
		// returns true if a different IP is the top vote now
		// i.e. we changed our idea of what our external IP is
		bool cast_vote(address const& ip, int source_type, address const& source);

		// the external IP as it would be observed from `ip`
		address external_address(address const& ip) const;

	private:

		// for now, assume one external IPv4 and one external IPv6 address
		// 0 = IPv4 1 = IPv6
		// TODO: instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
		ip_voter m_vote_group[2];
	};

}

#endif

<commit_msg>fix mingw test link issue<commit_after>/*

Copyright (c) 2013, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TORRENT_IP_VOTER_HPP_INCLUDED
#define TORRENT_IP_VOTER_HPP_INCLUDED

#include <vector>
#include "libtorrent/address.hpp"
#include "libtorrent/bloom_filter.hpp"

namespace libtorrent
{
	// this is an object that keeps the state for a single external IP
	// based on peoples votes
	struct TORRENT_EXTRA_EXPORT ip_voter
	{
		// returns true if a different IP is the top vote now
		// i.e. we changed our idea of what our external IP is
		bool cast_vote(address const& ip, int source_type, address const& sorce);

		address external_address() const { return m_external_address; }

	private:

		struct external_ip_t
		{
			external_ip_t(): sources(0), num_votes(0) {}

			bool add_vote(sha1_hash const& k, int type);
			bool operator<(external_ip_t const& rhs) const
			{
				if (num_votes < rhs.num_votes) return true;
				if (num_votes > rhs.num_votes) return false;
				return sources < rhs.sources;
			}

			// this is a bloom filter of the IPs that have
			// reported this address
			bloom_filter<16> voters;
			// this is the actual external address
			address addr;
			// a bitmask of sources the reporters have come from
			boost::uint16_t sources;
			// the total number of votes for this IP
			boost::uint16_t num_votes;
		};

		// this is a bloom filter of all the IPs that have
		// been the first to report an external address. Each
		// IP only gets to add a new item once.
		bloom_filter<32> m_external_address_voters;
		std::vector<external_ip_t> m_external_addresses;
		address m_external_address;
	};

	// this keeps track of multiple external IPs (for now, just IPv6 and IPv4, but
	// it could be extended to deal with loopback and local network addresses as well)
	struct TORRENT_EXTRA_EXPORT external_ip
	{
		// returns true if a different IP is the top vote now
		// i.e. we changed our idea of what our external IP is
		bool cast_vote(address const& ip, int source_type, address const& source);

		// the external IP as it would be observed from `ip`
		address external_address(address const& ip) const;

	private:

		// for now, assume one external IPv4 and one external IPv6 address
		// 0 = IPv4 1 = IPv6
		// TODO: instead, have one instance per possible subnet, global IPv4, global IPv6, loopback, 192.168.x.x, 10.x.x.x, etc.
		ip_voter m_vote_group[2];
	};

}

#endif

<|endoftext|>


<commit_before>// Flaschenautomazt.v.6.0.cpp : Definiert den Einstiegspunkt fr die Konsolenanwendung.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
int auswahlGetraenkeSorte();
int eingabeMenge();
float ermittlePreis(int sorte);
void bezahlen (float zuZahlen);
void ausgabeGetraenke(int sorte, int menge);

int main()
{
	cout << "Getraenkeautomat v.6.0" << endl;

	int sorte, menge, bezahlen;
	float preis, zuZahlen;

	sorte = auswahlGetraenkeSorte();
	preis = ermittlePreis(sorte);
	menge = eingabeMenge();
	zuZahlen = preis * menge;
	float bezahlen(zuZahlen);

	ausgabeGetraenke(sorte, menge);
	cout << "Vielen Dank, bitte entnehmen Sie ihre Getrnke" << endl;

	getchar();
	getchar();
	return 0;
}

// Funktionen
int auswahlGetraenkeSorte() {
	int sorte;
	cout("Waehlen sie ihr Getraenk aus:\n");
	cout("1) Wasser (0,50 Euro)\n");
	cout("2) Limonade (1,00 Euro)\n");
	cout("3) Bier (2,00 Euro)\n\n");
	cout("Geben sie 1, 2 oder 3 ein: ");
	cin >> sorte;
	return sorte;
}
int eingabeMenge() {
	int menge = 1;
	cout << "Geben sie die gewuenschte Menge ein: ";
	cin >> menge;
	return menge;
}
/*	ermittelt den Preis zu einer Sorte
Parameter:	sorte, Nummer der Sorte
Return-Value:	Preis
*/
float ermittlePreis(int sorte) {
	float preis = 0;
	switch (sorte) {
	case 1: preis = 0.5; break;
	case 2: preis = 1.0; break;
	case 3: preis = 2.0; break;
	}
	return preis;
}
bool bezahlen (float zuZahlen) {
	cout << "--- Bezahlvorgang ---" << endl;
	cout << "Bezahlvorgang abbrechen mit 0";
	float einwurf;
	do {
		cout << "Es fehlen noch " << zuZahlen <<" Euro.";
		cout << "Bitte werfen sie ein Geldstueck ein: ";
		cin >>einwurf;
		// eingeworfenen Betrag anrechnen
		zuZahlen -= einwurf;
	} while (zuZahlen > 0.0);
	return true;
}
void ausgabeGetraenke(int sorte, int menge) {
	cout << "--- Getraenkeausgabe ---" <<endl;
	int i;
	for (i = 0; i < menge; i++) {
		cout << " Flasche " << i << "von " << menge << " der Sorte " << sorte << " wurde ausgegeben.",
			i + 1, menge, sorte;
	}
}

<commit_msg>fixed and done<commit_after>// Flaschenautomazt.v.6.0.cpp : Definiert den Einstiegspunkt fr die Konsolenanwendung.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
int auswahlGetraenkeSorte();
int eingabeMenge();
float ermittlePreis(int sorte);
void bezahlen (float zuZahlen);
void ausgabeGetraenke(int sorte, int menge);

int main()
{
	cout << "Getraenkeautomat v.6.0" << endl;

	int sorte, menge;
	float preis, zuZahlen;

	sorte = auswahlGetraenkeSorte();
	preis = ermittlePreis(sorte);
	menge = eingabeMenge();
	zuZahlen = preis * menge;
	bezahlen (zuZahlen);

	ausgabeGetraenke(sorte, menge);
	cout << "Vielen Dank, bitte entnehmen Sie ihre Getrnke" << endl;

	getchar();
	getchar();
	return 0;
}

// Funktionen
int auswahlGetraenkeSorte() {
	int sorte;
	cout <<"Waehlen sie ihr Getraenk aus:\n";
	cout <<"1) Wasser (0,50 Euro)\n";
	cout <<"2) Limonade (1,00 Euro)\n";
	cout <<"3) Bier (2,00 Euro)\n\n";
	cout <<"Geben sie 1, 2 oder 3 ein: ";
	cin >> sorte;
	return sorte;
}
int eingabeMenge() {
	int menge = 1;
	cout << "Geben sie die gewuenschte Menge ein: ";
	cin >> menge;
	return menge;
}
/*	ermittelt den Preis zu einer Sorte
Parameter:	sorte, Nummer der Sorte
Return-Value:	Preis
*/
float ermittlePreis(int sorte) {
	float preis = 0;
	switch (sorte) {
	case 1: preis = 0.5; break;
	case 2: preis = 1.0; break;
	case 3: preis = 2.0; break;
	}
	return preis;
}
void bezahlen (float zuZahlen) {
	cout << "--- Bezahlvorgang ---" << endl;
	cout << "Bezahlvorgang abbrechen mit 0";
	float einwurf;
	do {
		cout << "Es fehlen noch " << zuZahlen <<" Euro.";
		cout << "Bitte werfen sie ein Geldstueck ein: ";
		cin >>einwurf;
		// eingeworfenen Betrag anrechnen
		zuZahlen -= einwurf;
	} while (zuZahlen > 0.0);
	return;
}
void ausgabeGetraenke(int sorte, int menge) {
	cout << "--- Getraenkeausgabe ---" <<endl;
	int i;
	for (i = 0; i < menge; i++) {
		cout << " Flasche " << i << "von " << menge << " der Sorte " << sorte << " wurde ausgegeben.",
			i + 1, menge, sorte;
	}
}

<|endoftext|>


<commit_before>#ifndef __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_
#define __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_

#include <function>
#include <map>
#include <string>

#include <os/os.hpp>
#include <processor/memory.hpp>
#include <processor/register/register_file.hpp>
#include <processor/register/register.hpp>

// These are the states the processor can be in.

#define MIPS_IF 0
#define MIPS_ID 1
#define MIPS_EX 2
#define MIPS_MEM 3
#define MIPS_WB 4

class MIPSProcessor
{
public:
	// CONSTRUCTORS

	/**
	 * @brief Construct a MIPS processor with references to the necessary
	 *        components.
	 *
	 * @param[in]
	 */
	MIPSProcessor (Memory& memory, RegisterFile& register_file);

	// DESTRUCTORS

	/**
	 * @brief Destructor.
	 */
	~MIPSProcessor ();

	// FUNCTIONS

	// /**
	//  * @brief Begin execution.
	//  *
	//  * Start executing the program that was loaded into memory (this must be
	//  * done by the OS).
	//  */
	// void
	// begin_execution ();

	/**
	 * @brief Execute the functionality at the current state this
	 *        MIPSProcessor is in.
	 */
	void
	tick ();

private:
	// Friend required classes.

	friend class RegisterFile;

	// FUNCTIONS

	/**
	 * @brief What this processor does in the if state.
	 */
	void
	mips_if ();

	/**
	 * @brief What this processor does in the id state.
	 */
	void
	mips_id ();

	/**
	 * @brief What this processor does in the ex state.
	 */
	void
	mips_ex ();

	/**
	 * @brief What this processor does in the mem state.
	 */
	void
	mips_mem ();

	/**
	 * @brief What this processor does in the wb state.
	 */
	void
	mips_wb ();

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS add operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_add (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addi operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_addi (Register& rd, const Register& rs, int immediate);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addiu operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_addiu (Register& rd, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addu operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_addu (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief if (R[rs] == R[rt]) PC = PC + 4 + BranchAddr
	 * MIPS beq operation.
	 * @param[in] rs             The first source register.
	 * @param[in] rt             The second source register.
	 * @param[in] branch_address The branch address.
	 */
	void
	mips_beq (const Register& rs, const Register& rt, unsigned branch_address);

	/**
	 * @brief PC = JumpAddr
	 * MIPS j operation.
	 * @param[in] jump_address The jump address.
	 */
	void
	mips_j (unsigned jump_address);

	/**
	 * @brief R[31] = PC + 8; PC = JumpAddr
	 * MIPS jal operation.
	 * @param[in] jump_address The jump address.
	 */
	void
	mips_jal (unsigned jump_address);

	/**
	 * @brief PC = R[rs]
	 * MIPS jal operation.
	 * @param[in]  rs The source register.
	 */
	void
	mips_jr (const Register& rs);

	/**
	 * @brief R[rt] = {imm, 16'b0}
	 * MIPS lui operation.
	 * @param[out] rt        The destination register.
	 * @param[in]  rs        The source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_lui (Register& rt, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rt] = M[R[rs] + SignExtImm]
	 * MIPS lw operation.
	 * @param[out] rt     The destination register.
	 * @param[in]  rs     The source register.
	 * @param[in]  offset The offset (default 0)..
	 */
	void
	mips_lw (Register& rt, const Register& rs, int offset = 0);

	/**
	 * @brief R[rd] = Hi
	 * MIPS mfhi operation.
	 * @param[out] rd The destination register.
	 */
	void
	mips_mfhi (Register& rd);

	/**
	 * @brief R[rd] = Lo
	 * MIPS mflo operation.
	 * @param[out] rd The destination register.
	 */
	void
	mips_mflo (Register& rd);

	/**
	 * @brief {Hi, Lo} = R[rs] * R[rt]
	 * MIPS mult operation.
	 * @param[out] rs The first source register.
	 * @param[out] rt The second source register.
	 */
	void
	mips_mult (const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] | ZeroExtImm
	 * MIPS ori operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_ori (Register& rd, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rd] = R[rs] << shamt
	 * MIPS sll operation.
	 * @param[out] rd    The destination register.
	 * @param[in]  rs    The first source register.
	 * @param[in]  shamt The shift amount.
	 */
	void
	mips_sll (Register& rd, const Register& rs, unsigned shamt);

	/**
	 * @brief R[rd] = (R[rs] < R[rt]) ? 1 : 0
	 * MIPS slt operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_slt (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = (R[rs] < SignExtImm) ? 1 : 0
	 * MIPS slti operation.
	 * @param[out] rd       The destination register.
	 * @param[in]  rs       The source register.
	 * @param[in] immediate The immediate.
	 */
	void
	mips_slti (Register& rd, const Register& rs, int immediate);

	/**
	 * @brief R[rd] = R[rs] - SignExtImm
	 * MIPS sub operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_sub (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] - SignExtImm
	 * MIPS subu operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_subu (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief M[R[rs] + SignExtImm] = R[rt]
	 * MIPS sw operation.
	 * @param[out] rt     The destination register.
	 * @param[in]  rs     The source register.
	 * @param[in]  offset The offset (default 0)..
	 */
	void
	mips_sw (const Register& rt, const Register& rs, int offset = 0);

	/**
	 * @brief MIPS syscall operation.
	 */
	void
	mips_syscall ();

	/**
	 * @brief Exit simulation.
	 *
	 * Transfer control to the OS and exit this simulation.
	 */
	void
	mips_syscall_exit ();

	// VARIABLES

	/** The state in the instruction pipeline we are in. */
	int m_processor_state;
	/** The memory for this MIPSProcessor. */
	Memory& m_memory;
	/** The register file for this MIPSProcessor. */
	RegisterFile& m_register_file;
	/** The functions at each state in this MIPSProcessor. */
	std::map<std::string, std::function<void()> > m_state_functions;
	/** The operations that this MIPSProcessor supports. */
	std::map<std::string, std::function<void()> > m_operations;
	/** The syscalls that this MIPSProcessor supports. */
	std::map<int, std::function<void()> > m_syscalls;

	// Temporary registers.
};

#endif // __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_
<commit_msg>Refactoring...<commit_after>#ifndef __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_
#define __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_

#include <function>
#include <map>
#include <string>

#include <os/os.hpp>
#include <processor/memory.hpp>
#include <processor/register/register_file.hpp>
#include <processor/register/register.hpp>

// These are the states the processor can be in.

#define MIPS_IF 0
#define MIPS_ID 1
#define MIPS_EX 2
#define MIPS_MEM 3
#define MIPS_WB 4

class MIPSProcessor
{
public:
	// CONSTRUCTORS

	/**
	 * @brief Construct a MIPS processor with references to the necessary
	 *        components.
	 *
	 * @param[in]
	 */
	MIPSProcessor (Memory& memory, RegisterFile& register_file);

	// DESTRUCTORS

	/**
	 * @brief Destructor.
	 */
	~MIPSProcessor ();

	// FUNCTIONS

	/**
	 * @brief Execute the functionality at the current state this
	 *        MIPSProcessor is in.
	 */
	void
	tick ();

private:
	// Friend required classes.

	friend class RegisterFile;

	// FUNCTIONS

	/**
	 * @brief What this processor does in the if state.
	 */
	void
	mips_if ();

	/**
	 * @brief What this processor does in the id state.
	 */
	void
	mips_id ();

	/**
	 * @brief What this processor does in the ex state.
	 */
	void
	mips_ex ();

	/**
	 * @brief What this processor does in the mem state.
	 */
	void
	mips_mem ();

	/**
	 * @brief What this processor does in the wb state.
	 */
	void
	mips_wb ();

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS add operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_add (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addi operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_addi (Register& rd, const Register& rs, int immediate);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addiu operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_addiu (Register& rd, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rd] = R[rs] + SignExtImm
	 * MIPS addu operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_addu (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief if (R[rs] == R[rt]) PC = PC + 4 + BranchAddr
	 * MIPS beq operation.
	 * @param[in] rs             The first source register.
	 * @param[in] rt             The second source register.
	 * @param[in] branch_address The branch address.
	 */
	void
	mips_beq (const Register& rs, const Register& rt, unsigned branch_address);

	/**
	 * @brief PC = JumpAddr
	 * MIPS j operation.
	 * @param[in] jump_address The jump address.
	 */
	void
	mips_j (unsigned jump_address);

	/**
	 * @brief R[31] = PC + 8; PC = JumpAddr
	 * MIPS jal operation.
	 * @param[in] jump_address The jump address.
	 */
	void
	mips_jal (unsigned jump_address);

	/**
	 * @brief PC = R[rs]
	 * MIPS jal operation.
	 * @param[in]  rs The source register.
	 */
	void
	mips_jr (const Register& rs);

	/**
	 * @brief R[rt] = {imm, 16'b0}
	 * MIPS lui operation.
	 * @param[out] rt        The destination register.
	 * @param[in]  rs        The source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_lui (Register& rt, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rt] = M[R[rs] + SignExtImm]
	 * MIPS lw operation.
	 * @param[out] rt     The destination register.
	 * @param[in]  rs     The source register.
	 * @param[in]  offset The offset (default 0)..
	 */
	void
	mips_lw (Register& rt, const Register& rs, int offset = 0);

	/**
	 * @brief R[rd] = Hi
	 * MIPS mfhi operation.
	 * @param[out] rd The destination register.
	 */
	void
	mips_mfhi (Register& rd);

	/**
	 * @brief R[rd] = Lo
	 * MIPS mflo operation.
	 * @param[out] rd The destination register.
	 */
	void
	mips_mflo (Register& rd);

	/**
	 * @brief {Hi, Lo} = R[rs] * R[rt]
	 * MIPS mult operation.
	 * @param[out] rs The first source register.
	 * @param[out] rt The second source register.
	 */
	void
	mips_mult (const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] | ZeroExtImm
	 * MIPS ori operation.
	 * @param[out] rd        The destination register.
	 * @param[in]  rs        The first source register.
	 * @param[in]  immediate The immediate.
	 */
	void
	mips_ori (Register& rd, const Register& rs, unsigned immediate);

	/**
	 * @brief R[rd] = R[rs] << shamt
	 * MIPS sll operation.
	 * @param[out] rd    The destination register.
	 * @param[in]  rs    The first source register.
	 * @param[in]  shamt The shift amount.
	 */
	void
	mips_sll (Register& rd, const Register& rs, unsigned shamt);

	/**
	 * @brief R[rd] = (R[rs] < R[rt]) ? 1 : 0
	 * MIPS slt operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_slt (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = (R[rs] < SignExtImm) ? 1 : 0
	 * MIPS slti operation.
	 * @param[out] rd       The destination register.
	 * @param[in]  rs       The source register.
	 * @param[in] immediate The immediate.
	 */
	void
	mips_slti (Register& rd, const Register& rs, int immediate);

	/**
	 * @brief R[rd] = R[rs] - SignExtImm
	 * MIPS sub operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_sub (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief R[rd] = R[rs] - SignExtImm
	 * MIPS subu operation.
	 * @param[out] rd The destination register.
	 * @param[in]  rs The first source register.
	 * @param[in]  rt The second source register.
	 */
	void
	mips_subu (Register& rd, const Register& rs, const Register& rt);

	/**
	 * @brief M[R[rs] + SignExtImm] = R[rt]
	 * MIPS sw operation.
	 * @param[out] rt     The destination register.
	 * @param[in]  rs     The source register.
	 * @param[in]  offset The offset (default 0)..
	 */
	void
	mips_sw (const Register& rt, const Register& rs, int offset = 0);

	/**
	 * @brief MIPS syscall operation.
	 */
	void
	mips_syscall ();

	/**
	 * @brief Exit simulation.
	 *
	 * Transfer control to the OS and exit this simulation.
	 */
	void
	mips_syscall_exit ();

	// VARIABLES

	/** The state in the instruction pipeline we are in. */
	int m_processor_state;
	/** The memory for this MIPSProcessor. */
	Memory& m_memory;
	/** The register file for this MIPSProcessor. */
	RegisterFile& m_register_file;
	/** The functions at each state in this MIPSProcessor. */
	std::map<std::string, std::function<void()> > m_state_functions;
	/** The operations that this MIPSProcessor supports. */
	std::map<std::string, std::function<void()> > m_operations;
	/** The syscalls that this MIPSProcessor supports. */
	std::map<int, std::function<void()> > m_syscalls;

	// Temporary registers.
};

#endif // __MIPSSIMULATOR_PROCESSOR_MIPSPROCESSOR_HPP_
<|endoftext|>