<commit_before>// ---------------------------------------------------------------------
//
// Copyright (C) 2013 - 2014 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/base/tensor.h>
#include <deal.II/lac/vector.h>
#include <cmath>

DEAL_II_NAMESPACE_OPEN

template <int dim, int spacedim>
SphericalManifold<dim,spacedim>::SphericalManifold(const Point<spacedim> center):
  ChartManifold<dim,spacedim,spacedim>(SphericalManifold<dim,spacedim>::get_periodicity()),
  center(center)
{}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::get_periodicity()
{
  Point<spacedim> periodicity;
  periodicity[spacedim-1] = 2*numbers::PI; // theta and phi period.
  return periodicity;
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::get_new_point(const Quadrature<spacedim> &quad) const
{
  if (spacedim == 2)
    return ChartManifold<dim,spacedim,spacedim>::get_new_point(quad);
  else
    {
      double rho_average = 0;
      Point<spacedim> mid_point;
      for (unsigned int i=0; i<quad.size(); ++i)
        {
          rho_average += quad.weight(i)*(quad.point(i)-center).norm();
          mid_point += quad.weight(i)*quad.point(i);
        }
      // Project the mid_pont back to the right location
      Point<spacedim> R = mid_point-center;
      // Scale it to have radius rho_average
      R *= rho_average/R.norm();
      // And return it.
      return center+R;
    }
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::push_forward(const Point<spacedim> &spherical_point) const
{
  Assert(spherical_point[0] >=0.0,
         ExcMessage("Negative radius for given point."));
  const double rho = spherical_point[0];
  const double theta = spherical_point[1];

  Point<spacedim> p;
  if (rho > 1e-10)
    switch (spacedim)
      {
      case 2:
        p[0] = rho*cos(theta);
        p[1] = rho*sin(theta);
        break;
      case 3:
      {
        const double &phi= spherical_point[2];
        p[0] = rho*sin(theta)*cos(phi);
        p[1] = rho*sin(theta)*sin(phi);
        p[2] = rho*cos(theta);
      }
      break;
      default:
        Assert(false, ExcInternalError());
      }
  return p+center;
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::pull_back(const Point<spacedim> &space_point) const
{
  const Point<spacedim> R = space_point-center;
  const double rho = R.norm();

  Point<spacedim> p;
  p[0] = rho;

  switch (spacedim)
    {
    case 2:
      p[1] = atan2(R[1],R[0]);
      if (p[1] < 0)
        p[1] += 2*numbers::PI;
      break;
    case 3:
    {
      const double z = R[2];
      p[2] = atan2(R[1],R[0]); // phi
      if (p[2] < 0)
        p[2] += 2*numbers::PI; // phi is periodic
      p[1] = atan2(sqrt(R[0]*R[0]+R[1]*R[1]),z);  // theta
    }
    break;
    default:
      Assert(false, ExcInternalError());
    }
  return p;
}

// ============================================================
// CylindricalManifold
// ============================================================

template <int dim, int spacedim>
CylindricalManifold<dim,spacedim>::CylindricalManifold(const unsigned int axis,
                                                       const double tolerance) :
  direction (Point<spacedim>::unit_vector(axis)),
  point_on_axis (Point<spacedim>()),
  tolerance(tolerance)
{
  Assert(spacedim > 1, ExcImpossibleInDim(1));
}

template <int dim, int spacedim>
CylindricalManifold<dim,spacedim>::CylindricalManifold(const Point<spacedim> &direction,
                                                       const Point<spacedim> &point_on_axis,
                                                       const double tolerance) :
  direction (direction),
  point_on_axis (point_on_axis),
  tolerance(tolerance)
{
  Assert(spacedim > 2, ExcImpossibleInDim(spacedim));
}

template <int dim, int spacedim>
Point<spacedim>
CylindricalManifold<dim,spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();

  // compute a proposed new point
  Point<spacedim> middle = flat_manifold.get_new_point(quad);

  double radius = 0;
  Point<spacedim> on_plane;

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    {
      on_plane = surrounding_points[i]-point_on_axis;
      on_plane = on_plane - (on_plane*direction) * direction;
      radius += weights[i]*on_plane.norm();
    }

  // we then have to project this point out to the given radius from
  // the axis. to this end, we have to take into account the offset
  // point_on_axis and the direction of the axis
  const Point<spacedim> vector_from_axis = (middle-point_on_axis) -
                                           ((middle-point_on_axis) * direction) * direction;

  // scale it to the desired length and put everything back together,
  // unless we have a point on the axis
  if (vector_from_axis.norm() <= tolerance * middle.norm())
    return middle;

  else
    return (vector_from_axis / vector_from_axis.norm() * radius +
            ((middle-point_on_axis) * direction) * direction +
            point_on_axis);
}

// ============================================================
// FunctionChartManifold
// ============================================================
template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::FunctionManifold
(const Function<chartdim> &push_forward_function,
 const Function<spacedim> &pull_back_function,
 const Point<chartdim> periodicity,
 const double tolerance):
  ChartManifold<dim,spacedim,chartdim>(periodicity),
  push_forward_function(&push_forward_function),
  pull_back_function(&pull_back_function),
  tolerance(tolerance),
  owns_pointers(false)
{
  AssertDimension(push_forward_function.n_components, spacedim);
  AssertDimension(pull_back_function.n_components, chartdim);
}

template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::FunctionManifold
(const std::string push_forward_expression,
 const std::string pull_back_expression,
 const Point<chartdim> periodicity,
 const typename FunctionParser<spacedim>::ConstMap const_map,
 const std::string chart_vars,
 const std::string space_vars,
 const double tolerance) :
  ChartManifold<dim,spacedim,chartdim>(periodicity),
  const_map(const_map),
  tolerance(tolerance),
  owns_pointers(true)
{
  FunctionParser<chartdim> *pf = new FunctionParser<chartdim>(spacedim);
  FunctionParser<spacedim> *pb = new FunctionParser<spacedim>(chartdim);
  pf->initialize(chart_vars, push_forward_expression, const_map);
  pb->initialize(space_vars, pull_back_expression, const_map);
  push_forward_function = pf;
  pull_back_function = pb;
}

template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::~FunctionManifold()
{
  if (owns_pointers == true)
    {
      const Function<chartdim> *pf = push_forward_function;
      push_forward_function = 0;
      delete pf;

      const Function<spacedim> *pb = pull_back_function;
      pull_back_function = 0;
      delete pb;
    }
}

template <int dim, int spacedim, int chartdim>
Point<spacedim>
FunctionManifold<dim,spacedim,chartdim>::push_forward(const Point<chartdim> &chart_point) const
{
  Vector<double> pf(spacedim);
  Point<spacedim> result;
  push_forward_function->vector_value(chart_point, pf);
  for (unsigned int i=0; i<spacedim; ++i)
    result[i] = pf[i];

#ifdef DEBUG
  Vector<double> pb(chartdim);
  pull_back_function->vector_value(result, pb);
  for (unsigned int i=0; i<chartdim; ++i)
    Assert((chart_point.norm() > tolerance &&
            (std::abs(pb[i]-chart_point[i]) < tolerance*chart_point.norm())) ||
           (std::abs(pb[i]-chart_point[i]) < tolerance),
           ExcMessage("The push forward is not the inverse of the pull back! Bailing out."));
#endif

  return result;
}

template <int dim, int spacedim, int chartdim>
Point<chartdim>
FunctionManifold<dim,spacedim,chartdim>::pull_back(const Point<spacedim> &space_point) const
{
  Vector<double> pb(chartdim);
  Point<chartdim> result;
  pull_back_function->vector_value(space_point, pb);
  for (unsigned int i=0; i<chartdim; ++i)
    result[i] = pb[i];
  return result;
}

// explicit instantiations
#include "manifold_lib.inst"

DEAL_II_NAMESPACE_CLOSE
<commit_msg>Fix up places where we use Point<dim> for directions when we should be using Tensor<1,dim>.<commit_after>// ---------------------------------------------------------------------
//
// Copyright (C) 2013 - 2015 by the deal.II authors
//
// This file is part of the deal.II library.
//
// The deal.II library is free software; you can use it, redistribute
// it, and/or modify it under the terms of the GNU Lesser General
// Public License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// The full text of the license can be found in the file LICENSE at
// the top level of the deal.II distribution.
//
// ---------------------------------------------------------------------

#include <deal.II/grid/tria.h>
#include <deal.II/grid/tria_iterator.h>
#include <deal.II/grid/tria_accessor.h>
#include <deal.II/grid/manifold_lib.h>
#include <deal.II/base/tensor.h>
#include <deal.II/lac/vector.h>
#include <cmath>

DEAL_II_NAMESPACE_OPEN

template <int dim, int spacedim>
SphericalManifold<dim,spacedim>::SphericalManifold(const Point<spacedim> center):
  ChartManifold<dim,spacedim,spacedim>(SphericalManifold<dim,spacedim>::get_periodicity()),
  center(center)
{}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::get_periodicity()
{
  Point<spacedim> periodicity;
  periodicity[spacedim-1] = 2*numbers::PI; // theta and phi period.
  return periodicity;
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::get_new_point(const Quadrature<spacedim> &quad) const
{
  if (spacedim == 2)
    return ChartManifold<dim,spacedim,spacedim>::get_new_point(quad);
  else
    {
      double rho_average = 0;
      Point<spacedim> mid_point;
      for (unsigned int i=0; i<quad.size(); ++i)
        {
          rho_average += quad.weight(i)*(quad.point(i)-center).norm();
          mid_point += quad.weight(i)*quad.point(i);
        }
      // Project the mid_pont back to the right location
      Point<spacedim> R = mid_point-center;
      // Scale it to have radius rho_average
      R *= rho_average/R.norm();
      // And return it.
      return center+R;
    }
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::push_forward(const Point<spacedim> &spherical_point) const
{
  Assert(spherical_point[0] >=0.0,
         ExcMessage("Negative radius for given point."));
  const double rho = spherical_point[0];
  const double theta = spherical_point[1];

  Point<spacedim> p;
  if (rho > 1e-10)
    switch (spacedim)
      {
      case 2:
        p[0] = rho*cos(theta);
        p[1] = rho*sin(theta);
        break;
      case 3:
      {
        const double &phi= spherical_point[2];
        p[0] = rho*sin(theta)*cos(phi);
        p[1] = rho*sin(theta)*sin(phi);
        p[2] = rho*cos(theta);
      }
      break;
      default:
        Assert(false, ExcInternalError());
      }
  return p+center;
}

template <int dim, int spacedim>
Point<spacedim>
SphericalManifold<dim,spacedim>::pull_back(const Point<spacedim> &space_point) const
{
  const Point<spacedim> R = space_point-center;
  const double rho = R.norm();

  Point<spacedim> p;
  p[0] = rho;

  switch (spacedim)
    {
    case 2:
      p[1] = atan2(R[1],R[0]);
      if (p[1] < 0)
        p[1] += 2*numbers::PI;
      break;
    case 3:
    {
      const double z = R[2];
      p[2] = atan2(R[1],R[0]); // phi
      if (p[2] < 0)
        p[2] += 2*numbers::PI; // phi is periodic
      p[1] = atan2(sqrt(R[0]*R[0]+R[1]*R[1]),z);  // theta
    }
    break;
    default:
      Assert(false, ExcInternalError());
    }
  return p;
}

// ============================================================
// CylindricalManifold
// ============================================================

template <int dim, int spacedim>
CylindricalManifold<dim,spacedim>::CylindricalManifold(const unsigned int axis,
                                                       const double tolerance) :
  direction (Point<spacedim>::unit_vector(axis)),
  point_on_axis (Point<spacedim>()),
  tolerance(tolerance)
{
  Assert(spacedim > 1, ExcImpossibleInDim(1));
}

template <int dim, int spacedim>
CylindricalManifold<dim,spacedim>::CylindricalManifold(const Point<spacedim> &direction,
                                                       const Point<spacedim> &point_on_axis,
                                                       const double tolerance) :
  direction (direction),
  point_on_axis (point_on_axis),
  tolerance(tolerance)
{
  Assert(spacedim > 2, ExcImpossibleInDim(spacedim));
}

template <int dim, int spacedim>
Point<spacedim>
CylindricalManifold<dim,spacedim>::
get_new_point (const Quadrature<spacedim> &quad) const
{
  const std::vector<Point<spacedim> > &surrounding_points = quad.get_points();
  const std::vector<double> &weights = quad.get_weights();

  // compute a proposed new point
  Point<spacedim> middle = flat_manifold.get_new_point(quad);

  double radius = 0;
  Tensor<1,spacedim> on_plane;

  for (unsigned int i=0; i<surrounding_points.size(); ++i)
    {
      on_plane = surrounding_points[i]-point_on_axis;
      on_plane = on_plane - (on_plane*direction) * direction;
      radius += weights[i]*on_plane.norm();
    }

  // we then have to project this point out to the given radius from
  // the axis. to this end, we have to take into account the offset
  // point_on_axis and the direction of the axis
  const Tensor<1,spacedim> vector_from_axis = (middle-point_on_axis) -
					      ((middle-point_on_axis) * direction) * direction;

  // scale it to the desired length and put everything back together,
  // unless we have a point on the axis
  if (vector_from_axis.norm() <= tolerance * middle.norm())
    return middle;

  else
    return (vector_from_axis / vector_from_axis.norm() * radius +
            ((middle-point_on_axis) * direction) * direction +
            point_on_axis);
}

// ============================================================
// FunctionChartManifold
// ============================================================
template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::FunctionManifold
(const Function<chartdim> &push_forward_function,
 const Function<spacedim> &pull_back_function,
 const Point<chartdim> periodicity,
 const double tolerance):
  ChartManifold<dim,spacedim,chartdim>(periodicity),
  push_forward_function(&push_forward_function),
  pull_back_function(&pull_back_function),
  tolerance(tolerance),
  owns_pointers(false)
{
  AssertDimension(push_forward_function.n_components, spacedim);
  AssertDimension(pull_back_function.n_components, chartdim);
}

template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::FunctionManifold
(const std::string push_forward_expression,
 const std::string pull_back_expression,
 const Point<chartdim> periodicity,
 const typename FunctionParser<spacedim>::ConstMap const_map,
 const std::string chart_vars,
 const std::string space_vars,
 const double tolerance) :
  ChartManifold<dim,spacedim,chartdim>(periodicity),
  const_map(const_map),
  tolerance(tolerance),
  owns_pointers(true)
{
  FunctionParser<chartdim> *pf = new FunctionParser<chartdim>(spacedim);
  FunctionParser<spacedim> *pb = new FunctionParser<spacedim>(chartdim);
  pf->initialize(chart_vars, push_forward_expression, const_map);
  pb->initialize(space_vars, pull_back_expression, const_map);
  push_forward_function = pf;
  pull_back_function = pb;
}

template <int dim, int spacedim, int chartdim>
FunctionManifold<dim,spacedim,chartdim>::~FunctionManifold()
{
  if (owns_pointers == true)
    {
      const Function<chartdim> *pf = push_forward_function;
      push_forward_function = 0;
      delete pf;

      const Function<spacedim> *pb = pull_back_function;
      pull_back_function = 0;
      delete pb;
    }
}

template <int dim, int spacedim, int chartdim>
Point<spacedim>
FunctionManifold<dim,spacedim,chartdim>::push_forward(const Point<chartdim> &chart_point) const
{
  Vector<double> pf(spacedim);
  Point<spacedim> result;
  push_forward_function->vector_value(chart_point, pf);
  for (unsigned int i=0; i<spacedim; ++i)
    result[i] = pf[i];

#ifdef DEBUG
  Vector<double> pb(chartdim);
  pull_back_function->vector_value(result, pb);
  for (unsigned int i=0; i<chartdim; ++i)
    Assert((chart_point.norm() > tolerance &&
            (std::abs(pb[i]-chart_point[i]) < tolerance*chart_point.norm())) ||
           (std::abs(pb[i]-chart_point[i]) < tolerance),
           ExcMessage("The push forward is not the inverse of the pull back! Bailing out."));
#endif

  return result;
}

template <int dim, int spacedim, int chartdim>
Point<chartdim>
FunctionManifold<dim,spacedim,chartdim>::pull_back(const Point<spacedim> &space_point) const
{
  Vector<double> pb(chartdim);
  Point<chartdim> result;
  pull_back_function->vector_value(space_point, pb);
  for (unsigned int i=0; i<chartdim; ++i)
    result[i] = pb[i];
  return result;
}

// explicit instantiations
#include "manifold_lib.inst"

DEAL_II_NAMESPACE_CLOSE
<|endoftext|>


<commit_before>// Copyright 2008, Google Inc.
// 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 Google Inc. 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.

#include "chrome/browser/views/first_run_bubble.h"

#include "chrome/app/locales/locale_settings.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/options_window.h"
#include "chrome/browser/standard_layout.h"
#include "chrome/browser/template_url_model.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/event.h"
#include "chrome/views/label.h"
#include "chrome/views/native_button.h"
#include "chrome/views/window.h"

#include "generated_resources.h"

namespace {

// How much extra padding to put around our content over what
// infobubble provides.
static const int kBubblePadding = 4;

// TODO(cpu): bug 1187517. It is possible that there is no default provider.
// we should make sure there is none at first run.
std::wstring GetDefaultSearchEngineName() {
  Browser* browser = BrowserList::GetLastActive();
  DCHECK(browser);
  const TemplateURL* const default_provider =
      browser->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
  DCHECK(default_provider);
  return default_provider->short_name();
}

}  // namespace

// Implements the client view inside the first run bubble. It is kind of a
// dialog-ish view, but is not a true dialog.
class FirstRunBubbleView : public ChromeViews::View,
                           public ChromeViews::NativeButton::Listener {
 public:
  explicit FirstRunBubbleView(FirstRunBubble* bubble_window)
      : bubble_window_(bubble_window),
        label1_(NULL),
        label2_(NULL),
        label3_(NULL),
        keep_button_(NULL),
        change_button_(NULL) {
    ChromeFont& font =
        ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);

    label1_ = new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE));
    label1_->SetFont(font.DeriveFont(3, ChromeFont::BOLD));
    label1_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    AddChildView(label1_);

    CSize ps;
    GetPreferredSize(&ps);

    label2_ =
        new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT));
    label2_->SetMultiLine(true);
    label2_->SetFont(font);
    label2_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    label2_->SizeToFit(ps.cx - kBubblePadding * 2);
    AddChildView(label2_);

    std::wstring question_str
        = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
                                GetDefaultSearchEngineName());
    label3_ = new ChromeViews::Label(question_str);
    label3_->SetMultiLine(true);
    label3_->SetFont(font);
    label3_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    label3_->SizeToFit(ps.cx - kBubblePadding * 2);
    AddChildView(label3_);

    std::wstring keep_str = l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
                                                  GetDefaultSearchEngineName());
    keep_button_ = new ChromeViews::NativeButton(keep_str, true);
    keep_button_->SetListener(this);
    AddChildView(keep_button_);

    std::wstring change_str = l10n_util::GetString(IDS_FR_BUBBLE_CHANGE);
    change_button_ = new ChromeViews::NativeButton(change_str);
    change_button_->SetListener(this);
    AddChildView(change_button_);
  }

  // Overridden from ChromeViews::View.
  virtual void DidChangeBounds(const CRect& previous, const CRect& current) {
    Layout();
  }

  // Overridden from NativeButton::Listener.
  virtual void ButtonPressed(ChromeViews::NativeButton* sender) {
    bubble_window_->Close();
    if (change_button_ == sender) {
      Browser* browser = BrowserList::GetLastActive();
      if (browser) {
        ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH,
                          browser->profile());
      }
    }
  }

  // Overridden from ChromeViews::View.
  virtual void Layout() {
    CSize canvas;
    GetPreferredSize(&canvas);

    CSize pref_size;
    label1_->GetPreferredSize(&pref_size);
    label1_->SetBounds(kBubblePadding, kBubblePadding, pref_size.cx,
                       pref_size.cy);

    int next_v_space = label1_->GetY() + label1_->GetHeight() +
                       kRelatedControlSmallVerticalSpacing;

    label2_->GetPreferredSize(&pref_size);
    label2_->SetBounds(kBubblePadding, next_v_space,
                       canvas.cx - kBubblePadding * 2,
                       pref_size.cy);

    next_v_space = label2_->GetY() + label2_->GetHeight() +
                   kPanelSubVerticalSpacing;

    label3_->GetPreferredSize(&pref_size);
    label3_->SetBounds(kBubblePadding, next_v_space,
                       canvas.cx - kBubblePadding * 2,
                       pref_size.cy);

    change_button_->GetPreferredSize(&pref_size);
    change_button_->SetBounds(canvas.cx - pref_size.cx - kBubblePadding,
                              canvas.cy - pref_size.cy - kButtonVEdgeMargin,
                              pref_size.cx, pref_size.cy);

    keep_button_->GetPreferredSize(&pref_size);
    keep_button_->SetBounds(change_button_->GetX() - pref_size.cx -
                            kRelatedButtonHSpacing, change_button_->GetY(),
                            pref_size.cx, pref_size.cy);
  }

  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child) {
    if (keep_button_)
      keep_button_->RequestFocus();
  }

  // Overridden from ChromeViews::View.
  virtual void GetPreferredSize(CSize *out) {
    DCHECK(out);
    *out = ChromeViews::Window::GetLocalizedContentsSize(
        IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
        IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES).ToSIZE();
  }

 private:
  FirstRunBubble* bubble_window_;
  ChromeViews::Label* label1_;
  ChromeViews::Label* label2_;
  ChromeViews::Label* label3_;
  ChromeViews::NativeButton* change_button_;
  ChromeViews::NativeButton* keep_button_;
  DISALLOW_EVIL_CONSTRUCTORS(FirstRunBubbleView);
};

// Keep the bubble around for kLingerTime milliseconds, to prevent accidental
// closure.
static const int kLingerTime = 1000;

void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // We might get re-enabled right before we are closed (sequence is: we get
  // deactivated, we call close, before we are actually closed we get
  // reactivated). Don't do the disabling of the parent in such cases.
  if (action == WA_ACTIVE && !has_been_activated_) {
    has_been_activated_ = true;

    // Disable the browser to prevent accidental rapid clicks from closing the
    // bubble.
    ::EnableWindow(GetParent(), false);

    MessageLoop::current()->PostDelayedTask(FROM_HERE,
        enable_window_method_factory_.NewRunnableMethod(
            &FirstRunBubble::EnableParent),
        kLingerTime);
  }
  InfoBubble::OnActivate(action, minimized, window);
}

void FirstRunBubble::InfoBubbleClosing(InfoBubble* info_bubble) {
  // Make sure our parent window is re-enabled.
  if (!IsWindowEnabled(GetParent()))
    ::EnableWindow(GetParent(), true);
  enable_window_method_factory_.RevokeAll();
}

FirstRunBubble* FirstRunBubble::Show(HWND parent_hwnd,
                                     const gfx::Rect& position_relative_to) {
  FirstRunBubble* window = new FirstRunBubble();
  ChromeViews::View* view = new FirstRunBubbleView(window);
  window->SetDelegate(window);
  window->Init(parent_hwnd, position_relative_to, view);
  BrowserWindow* frame = window->GetHostingWindow();
  DCHECK(frame);
  frame->InfoBubbleShowing();
  window->ShowWindow(SW_SHOW);
  return window;
}

void FirstRunBubble::EnableParent() {
  ::EnableWindow(GetParent(), true);
}
<commit_msg>Workaround for truncation of "Search from right here" text when using Hebrew Chrome on Vista. Will file separate bug so the root cause is fixed.<commit_after>// Copyright 2008, Google Inc.
// 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 Google Inc. 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.

#include "chrome/browser/views/first_run_bubble.h"

#include "chrome/app/locales/locale_settings.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/options_window.h"
#include "chrome/browser/standard_layout.h"
#include "chrome/browser/template_url_model.h"
#include "chrome/common/l10n_util.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/event.h"
#include "chrome/views/label.h"
#include "chrome/views/native_button.h"
#include "chrome/views/window.h"

#include "generated_resources.h"

namespace {

// How much extra padding to put around our content over what
// infobubble provides.
static const int kBubblePadding = 4;

// TODO(cpu): bug 1187517. It is possible that there is no default provider.
// we should make sure there is none at first run.
std::wstring GetDefaultSearchEngineName() {
  Browser* browser = BrowserList::GetLastActive();
  DCHECK(browser);
  const TemplateURL* const default_provider =
      browser->profile()->GetTemplateURLModel()->GetDefaultSearchProvider();
  DCHECK(default_provider);
  return default_provider->short_name();
}

}  // namespace

// Implements the client view inside the first run bubble. It is kind of a
// dialog-ish view, but is not a true dialog.
class FirstRunBubbleView : public ChromeViews::View,
                           public ChromeViews::NativeButton::Listener {
 public:
  explicit FirstRunBubbleView(FirstRunBubble* bubble_window)
      : bubble_window_(bubble_window),
        label1_(NULL),
        label2_(NULL),
        label3_(NULL),
        keep_button_(NULL),
        change_button_(NULL) {
    ChromeFont& font =
        ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::MediumFont);

    label1_ = new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_TITLE));
    label1_->SetFont(font.DeriveFont(3, ChromeFont::BOLD));
    label1_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    AddChildView(label1_);

    CSize ps;
    GetPreferredSize(&ps);

    label2_ =
        new ChromeViews::Label(l10n_util::GetString(IDS_FR_BUBBLE_SUBTEXT));
    label2_->SetMultiLine(true);
    label2_->SetFont(font);
    label2_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    label2_->SizeToFit(ps.cx - kBubblePadding * 2);
    AddChildView(label2_);

    std::wstring question_str
        = l10n_util::GetStringF(IDS_FR_BUBBLE_QUESTION,
                                GetDefaultSearchEngineName());
    label3_ = new ChromeViews::Label(question_str);
    label3_->SetMultiLine(true);
    label3_->SetFont(font);
    label3_->SetHorizontalAlignment(ChromeViews::Label::ALIGN_LEFT);
    label3_->SizeToFit(ps.cx - kBubblePadding * 2);
    AddChildView(label3_);

    std::wstring keep_str = l10n_util::GetStringF(IDS_FR_BUBBLE_OK,
                                                  GetDefaultSearchEngineName());
    keep_button_ = new ChromeViews::NativeButton(keep_str, true);
    keep_button_->SetListener(this);
    AddChildView(keep_button_);

    std::wstring change_str = l10n_util::GetString(IDS_FR_BUBBLE_CHANGE);
    change_button_ = new ChromeViews::NativeButton(change_str);
    change_button_->SetListener(this);
    AddChildView(change_button_);
  }

  // Overridden from ChromeViews::View.
  virtual void DidChangeBounds(const CRect& previous, const CRect& current) {
    Layout();
  }

  // Overridden from NativeButton::Listener.
  virtual void ButtonPressed(ChromeViews::NativeButton* sender) {
    bubble_window_->Close();
    if (change_button_ == sender) {
      Browser* browser = BrowserList::GetLastActive();
      if (browser) {
        ShowOptionsWindow(OPTIONS_PAGE_GENERAL, OPTIONS_GROUP_DEFAULT_SEARCH,
                          browser->profile());
      }
    }
  }

  // Overridden from ChromeViews::View.
  virtual void Layout() {
    CSize canvas;
    GetPreferredSize(&canvas);

    CSize pref_size;
    // The multiline business that follows is dirty hacks to get around
    // bug 1325257.
    label1_->SetMultiLine(false);
    label1_->GetPreferredSize(&pref_size);
    label1_->SetMultiLine(true);
    label1_->SizeToFit(canvas.cx - kBubblePadding * 2);
    label1_->SetBounds(kBubblePadding, kBubblePadding,
                       canvas.cx - kBubblePadding * 2,
                       pref_size.cy);

    int next_v_space = label1_->GetY() + pref_size.cy +
                       kRelatedControlSmallVerticalSpacing;

    label2_->GetPreferredSize(&pref_size);
    label2_->SetBounds(kBubblePadding, next_v_space,
                       canvas.cx - kBubblePadding * 2,
                       pref_size.cy);

    next_v_space = label2_->GetY() + label2_->GetHeight() +
                   kPanelSubVerticalSpacing;

    label3_->GetPreferredSize(&pref_size);
    label3_->SetBounds(kBubblePadding, next_v_space,
                       canvas.cx - kBubblePadding * 2,
                       pref_size.cy);

    change_button_->GetPreferredSize(&pref_size);
    change_button_->SetBounds(canvas.cx - pref_size.cx - kBubblePadding,
                              canvas.cy - pref_size.cy - kButtonVEdgeMargin,
                              pref_size.cx, pref_size.cy);

    keep_button_->GetPreferredSize(&pref_size);
    keep_button_->SetBounds(change_button_->GetX() - pref_size.cx -
                            kRelatedButtonHSpacing, change_button_->GetY(),
                            pref_size.cx, pref_size.cy);
  }

  virtual void ViewHierarchyChanged(bool is_add, View* parent, View* child) {
    if (keep_button_)
      keep_button_->RequestFocus();
  }

  // Overridden from ChromeViews::View.
  virtual void GetPreferredSize(CSize *out) {
    DCHECK(out);
    *out = ChromeViews::Window::GetLocalizedContentsSize(
        IDS_FIRSTRUNBUBBLE_DIALOG_WIDTH_CHARS,
        IDS_FIRSTRUNBUBBLE_DIALOG_HEIGHT_LINES).ToSIZE();
  }

 private:
  FirstRunBubble* bubble_window_;
  ChromeViews::Label* label1_;
  ChromeViews::Label* label2_;
  ChromeViews::Label* label3_;
  ChromeViews::NativeButton* change_button_;
  ChromeViews::NativeButton* keep_button_;
  DISALLOW_EVIL_CONSTRUCTORS(FirstRunBubbleView);
};

// Keep the bubble around for kLingerTime milliseconds, to prevent accidental
// closure.
static const int kLingerTime = 1000;

void FirstRunBubble::OnActivate(UINT action, BOOL minimized, HWND window) {
  // We might get re-enabled right before we are closed (sequence is: we get
  // deactivated, we call close, before we are actually closed we get
  // reactivated). Don't do the disabling of the parent in such cases.
  if (action == WA_ACTIVE && !has_been_activated_) {
    has_been_activated_ = true;

    // Disable the browser to prevent accidental rapid clicks from closing the
    // bubble.
    ::EnableWindow(GetParent(), false);

    MessageLoop::current()->PostDelayedTask(FROM_HERE,
        enable_window_method_factory_.NewRunnableMethod(
            &FirstRunBubble::EnableParent),
        kLingerTime);
  }
  InfoBubble::OnActivate(action, minimized, window);
}

void FirstRunBubble::InfoBubbleClosing(InfoBubble* info_bubble) {
  // Make sure our parent window is re-enabled.
  if (!IsWindowEnabled(GetParent()))
    ::EnableWindow(GetParent(), true);
  enable_window_method_factory_.RevokeAll();
}

FirstRunBubble* FirstRunBubble::Show(HWND parent_hwnd,
                                     const gfx::Rect& position_relative_to) {
  FirstRunBubble* window = new FirstRunBubble();
  ChromeViews::View* view = new FirstRunBubbleView(window);
  window->SetDelegate(window);
  window->Init(parent_hwnd, position_relative_to, view);
  BrowserWindow* frame = window->GetHostingWindow();
  DCHECK(frame);
  frame->InfoBubbleShowing();
  window->ShowWindow(SW_SHOW);
  return window;
}

void FirstRunBubble::EnableParent() {
  ::EnableWindow(GetParent(), true);
}
<|endoftext|>


<commit_before>
#include <assert.h>

#include "Schedule.h"
#include "PolledTimeout.h"
#include "interrupts.h"
#include "coredecls.h"

typedef std::function<void(void)> mSchedFuncT;
struct scheduled_fn_t
{
    scheduled_fn_t* mNext = nullptr;
    mSchedFuncT mFunc;
};

static scheduled_fn_t* sFirst = nullptr;
static scheduled_fn_t* sLast = nullptr;
static scheduled_fn_t* sUnused = nullptr;
static int sCount = 0;

typedef std::function<bool(void)> mRecFuncT;
struct recurrent_fn_t
{
    recurrent_fn_t* mNext = nullptr;
    mRecFuncT mFunc;
    esp8266::polledTimeout::periodicFastUs callNow;
    recurrent_fn_t (esp8266::polledTimeout::periodicFastUs interval): callNow(interval) { }
};

static recurrent_fn_t* rFirst = nullptr; // fifo not needed

// Returns a pointer to an unused sched_fn_t,
// or if none are available allocates a new one,
// or nullptr if limit is reached
IRAM_ATTR // called from ISR
static scheduled_fn_t* get_fn_unsafe ()
{
    scheduled_fn_t* result = nullptr;
    // try to get an item from unused items list
    if (sUnused)
    {
        result = sUnused;
        sUnused = sUnused->mNext;
    }
    // if no unused items, and count not too high, allocate a new one
    else if (sCount < SCHEDULED_FN_MAX_COUNT)
    {
        // calling malloc instead of new to avoid exception raising while in ISR
        // construct complex members in place (never raises exceptions)
        result = (scheduled_fn_t*)malloc(sizeof(scheduled_fn_t));
        if (result)
        {
            new (&result->mFunc) decltype(result->mFunc)();
            ++sCount;
        }
    }
    return result;
}

static void recycle_fn_unsafe (scheduled_fn_t* fn)
{
    fn->mFunc = nullptr; // special overload in c++ std lib
    fn->mNext = sUnused;
    sUnused = fn;
}

IRAM_ATTR // (not only) called from ISR
bool schedule_function (const std::function<void(void)>& fn)
{
    esp8266::InterruptLock lockAllInterruptsInThisScope;

    scheduled_fn_t* item = get_fn_unsafe();
    if (!item)
        return false;

    item->mFunc = fn;
    item->mNext = nullptr;

    if (sFirst)
        sLast->mNext = item;
    else
        sFirst = item;
    sLast = item;

    return true;
}

bool schedule_recurrent_function_us (const std::function<bool(void)>& fn, uint32_t repeat_us)
{
    assert(repeat_us < decltype(recurrent_fn_t::callNow)::neverExpires); //~26800000us (26.8s)

    esp8266::InterruptLock lockAllInterruptsInThisScope;

    recurrent_fn_t* item = new recurrent_fn_t(repeat_us);
    if (!item)
        return false;

    item->mFunc = fn;

    if (rFirst)
        item->mNext = rFirst;

    rFirst = item;

    return true;
}

void run_scheduled_functions ()
{
    esp8266::polledTimeout::periodicFastMs yieldNow(100); // yield every 100ms

    while (sFirst)
    {
        sFirst->mFunc();

        {
            esp8266::InterruptLock lockAllInterruptsInThisScope;

            auto to_recycle = sFirst;
            sFirst = sFirst->mNext;
            if (!sFirst)
                sLast = nullptr;
            recycle_fn_unsafe(to_recycle);
        }

        if (yieldNow)
        {
            // because scheduled function are allowed to last:
            // this is yield() in cont stack:
            esp_schedule();
            cont_yield(g_pcont);
        }
    }
}

void run_scheduled_recurrent_functions ()
{
    // Note to the reader:
    // There is no exposed API to remove a scheduled function:
    // Scheduled functions are removed only from this function, and
    // its purpose is that it is never called from an interrupt
    // (always on cont stack).

    if (!rFirst)
        return;

    static bool fence = false;
    {
        // fence is like a mutex but as we are never called from ISR,
        // locking is useless here. Leaving comment for reference.
        //esp8266::InterruptLock lockAllInterruptsInThisScope;

        if (fence)
            // prevent recursive calls from yield()
            // (even if they are not allowed)
            return;
        fence = true;
    }

    recurrent_fn_t* prev = nullptr;
    recurrent_fn_t* current = rFirst;

    while (current)
    {
        if (current->callNow && !current->mFunc())
        {
            // remove function from stack
            esp8266::InterruptLock lockAllInterruptsInThisScope;

            auto to_ditch = current;

            if (prev)
            {
                current = current->mNext;
                prev->mNext = current;
            }
            else
            {
                rFirst = rFirst->mNext;
                current = rFirst;
            }

            delete(to_ditch);
        }
        else
        {
            prev = current;
            current = current->mNext;
        }
    }

    fence = false;
}
<commit_msg>using std::nothrow instead of malloc (#6251)<commit_after>
#include <assert.h>

#include "Schedule.h"
#include "PolledTimeout.h"
#include "interrupts.h"
#include "coredecls.h"

typedef std::function<void(void)> mSchedFuncT;
struct scheduled_fn_t
{
    scheduled_fn_t* mNext = nullptr;
    mSchedFuncT mFunc;
};

static scheduled_fn_t* sFirst = nullptr;
static scheduled_fn_t* sLast = nullptr;
static scheduled_fn_t* sUnused = nullptr;
static int sCount = 0;

typedef std::function<bool(void)> mRecFuncT;
struct recurrent_fn_t
{
    recurrent_fn_t* mNext = nullptr;
    mRecFuncT mFunc;
    esp8266::polledTimeout::periodicFastUs callNow;
    recurrent_fn_t (esp8266::polledTimeout::periodicFastUs interval): callNow(interval) { }
};

static recurrent_fn_t* rFirst = nullptr; // fifo not needed

// Returns a pointer to an unused sched_fn_t,
// or if none are available allocates a new one,
// or nullptr if limit is reached
IRAM_ATTR // called from ISR
static scheduled_fn_t* get_fn_unsafe ()
{
    scheduled_fn_t* result = nullptr;
    // try to get an item from unused items list
    if (sUnused)
    {
        result = sUnused;
        sUnused = sUnused->mNext;
    }
    // if no unused items, and count not too high, allocate a new one
    else if (sCount < SCHEDULED_FN_MAX_COUNT)
    {
        result = new (std::nothrow) scheduled_fn_t;
        if (result)
            ++sCount;
    }
    return result;
}

static void recycle_fn_unsafe (scheduled_fn_t* fn)
{
    fn->mFunc = nullptr; // special overload in c++ std lib
    fn->mNext = sUnused;
    sUnused = fn;
}

IRAM_ATTR // (not only) called from ISR
bool schedule_function (const std::function<void(void)>& fn)
{
    esp8266::InterruptLock lockAllInterruptsInThisScope;

    scheduled_fn_t* item = get_fn_unsafe();
    if (!item)
        return false;

    item->mFunc = fn;
    item->mNext = nullptr;

    if (sFirst)
        sLast->mNext = item;
    else
        sFirst = item;
    sLast = item;

    return true;
}

bool schedule_recurrent_function_us (const std::function<bool(void)>& fn, uint32_t repeat_us)
{
    assert(repeat_us < decltype(recurrent_fn_t::callNow)::neverExpires); //~26800000us (26.8s)

    esp8266::InterruptLock lockAllInterruptsInThisScope;

    recurrent_fn_t* item = new (std::nothrow) recurrent_fn_t(repeat_us);
    if (!item)
        return false;

    item->mFunc = fn;

    if (rFirst)
        item->mNext = rFirst;

    rFirst = item;

    return true;
}

void run_scheduled_functions ()
{
    esp8266::polledTimeout::periodicFastMs yieldNow(100); // yield every 100ms

    while (sFirst)
    {
        sFirst->mFunc();

        {
            esp8266::InterruptLock lockAllInterruptsInThisScope;

            auto to_recycle = sFirst;
            sFirst = sFirst->mNext;
            if (!sFirst)
                sLast = nullptr;
            recycle_fn_unsafe(to_recycle);
        }

        if (yieldNow)
        {
            // because scheduled function are allowed to last:
            // this is yield() in cont stack:
            esp_schedule();
            cont_yield(g_pcont);
        }
    }
}

void run_scheduled_recurrent_functions ()
{
    // Note to the reader:
    // There is no exposed API to remove a scheduled function:
    // Scheduled functions are removed only from this function, and
    // its purpose is that it is never called from an interrupt
    // (always on cont stack).

    if (!rFirst)
        return;

    static bool fence = false;
    {
        // fence is like a mutex but as we are never called from ISR,
        // locking is useless here. Leaving comment for reference.
        //esp8266::InterruptLock lockAllInterruptsInThisScope;

        if (fence)
            // prevent recursive calls from yield()
            // (even if they are not allowed)
            return;
        fence = true;
    }

    recurrent_fn_t* prev = nullptr;
    recurrent_fn_t* current = rFirst;

    while (current)
    {
        if (current->callNow && !current->mFunc())
        {
            // remove function from stack
            esp8266::InterruptLock lockAllInterruptsInThisScope;

            auto to_ditch = current;

            if (prev)
            {
                current = current->mNext;
                prev->mNext = current;
            }
            else
            {
                rFirst = rFirst->mNext;
                current = rFirst;
            }

            delete(to_ditch);
        }
        else
        {
            prev = current;
            current = current->mNext;
        }
    }

    fence = false;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010 The Native Client 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 <assert.h>

#include <map>
#include <string>

#include "native_client/src/trusted/gdb_rsp/abi.h"
#include "native_client/src/trusted/port/platform.h"

using port::IPlatform;

namespace gdb_rsp {

#define MINIDEF(x, name, purpose) { #name, sizeof(x), Abi::purpose, 0, 0 }
#define BPDEF(x) { sizeof(x), x }

static Abi::RegDef RegsX86_64[] = {
  MINIDEF(uint64_t, rax, GENERAL),
  MINIDEF(uint64_t, rbx, GENERAL),
  MINIDEF(uint64_t, rcx, GENERAL),
  MINIDEF(uint64_t, rdx, GENERAL),
  MINIDEF(uint64_t, rsi, GENERAL),
  MINIDEF(uint64_t, rdi, GENERAL),
  MINIDEF(uint64_t, rbp, GENERAL),
  MINIDEF(uint64_t, rsp, GENERAL),
  MINIDEF(uint64_t, r8, GENERAL),
  MINIDEF(uint64_t, r9, GENERAL),
  MINIDEF(uint64_t, r10, GENERAL),
  MINIDEF(uint64_t, r11, GENERAL),
  MINIDEF(uint64_t, r12, GENERAL),
  MINIDEF(uint64_t, r13, GENERAL),
  MINIDEF(uint64_t, r14, GENERAL),
  MINIDEF(uint64_t, r15, GENERAL),
  MINIDEF(uint64_t, rip, INST_PTR),
  MINIDEF(uint32_t, eflags, FLAGS),
  MINIDEF(uint32_t, cs, SEGMENT),
  MINIDEF(uint32_t, ss, SEGMENT),
  MINIDEF(uint32_t, ds, SEGMENT),
  MINIDEF(uint32_t, es, SEGMENT),
  MINIDEF(uint32_t, fs, SEGMENT),
  MINIDEF(uint32_t, gs, SEGMENT),
};

static Abi::RegDef RegsX86_32[] = {
  MINIDEF(uint32_t, eax, GENERAL),
  MINIDEF(uint32_t, ecx, GENERAL),
  MINIDEF(uint32_t, edx, GENERAL),
  MINIDEF(uint32_t, ebx, GENERAL),
  MINIDEF(uint32_t, esp, GENERAL),
  MINIDEF(uint32_t, ebp, GENERAL),
  MINIDEF(uint32_t, esi, GENERAL),
  MINIDEF(uint32_t, edi, GENERAL),
  MINIDEF(uint32_t, eip, INST_PTR),
  MINIDEF(uint32_t, eflags, FLAGS),
  MINIDEF(uint32_t, cs, SEGMENT),
  MINIDEF(uint32_t, ss, SEGMENT),
  MINIDEF(uint32_t, ds, SEGMENT),
  MINIDEF(uint32_t, es, SEGMENT),
  MINIDEF(uint32_t, fs, SEGMENT),
  MINIDEF(uint32_t, gs, SEGMENT),
};

static Abi::RegDef RegsArm[] = {
  MINIDEF(uint32_t, r0, GENERAL),
  MINIDEF(uint32_t, r1, GENERAL),
  MINIDEF(uint32_t, r2, GENERAL),
  MINIDEF(uint32_t, r3, GENERAL),
  MINIDEF(uint32_t, r4, GENERAL),
  MINIDEF(uint32_t, r5, GENERAL),
  MINIDEF(uint32_t, r6, GENERAL),
  MINIDEF(uint32_t, r7, GENERAL),
  MINIDEF(uint32_t, r8, GENERAL),
  MINIDEF(uint32_t, r9, GENERAL),
  MINIDEF(uint32_t, r10, GENERAL),
  MINIDEF(uint32_t, r11, GENERAL),
  MINIDEF(uint32_t, r12, GENERAL),
  MINIDEF(uint32_t, sp, STACK_PTR),
  MINIDEF(uint32_t, lr, LINK_PTR),
  MINIDEF(uint32_t, pc, INST_PTR),
};

static uint8_t BPCodeX86[] = { 0xCC };

static Abi::BPDef BPX86 = BPDEF(BPCodeX86);

static AbiMap_t s_Abis;

// AbiInit & AbiIsAvailable
//   This pair of functions work together as singleton to
// ensure the module has been correctly initialized.  All
// dependant functions should call AbiIsAvailable to ensure
// the module is ready.
static bool AbiInit() {
  Abi::Register("i386", RegsX86_32, sizeof(RegsX86_32), &BPX86);
  Abi::Register("i386:x86-64", RegsX86_64, sizeof(RegsX86_64), &BPX86);

  // TODO(cbiffle) Figure out how to REALLY detect ARM, and define Breakpoint
  Abi::Register("iwmmxt", RegsArm, sizeof(RegsArm), NULL);

  return true;
}

static bool AbiIsAvailable() {
  static bool initialized_ = AbiInit();
  return initialized_;
}

Abi::Abi() {}
Abi::~Abi() {}

void Abi::Register(const char *name, RegDef *regs,
                   uint32_t bytes, const BPDef *bp) {
  uint32_t offs = 0;
  const uint32_t cnt = bytes / sizeof(RegDef);

  // Build indexes and offsets
  for (uint32_t loop = 0; loop < cnt; loop++) {
    regs[loop].index_ = loop;
    regs[loop].offset_ = offs;
    offs += regs[loop].bytes_;
  }

  Abi *abi = new Abi;

  abi->name_ = name;
  abi->regCnt_ = cnt;
  abi->regDefs_= regs;
  abi->ctxSize_ = offs;
  abi->bpDef_ = bp;

  s_Abis[name] = abi;
}

const Abi* Abi::Find(const char *name) {
  if (!AbiIsAvailable()) {
    IPlatform::LogError("Failed to initalize ABIs.");
    return NULL;
  }

  AbiMap_t::const_iterator itr = s_Abis.find(name);
  if (itr == s_Abis.end()) return NULL;

  return itr->second;
}

const Abi* Abi::Get() {
  static const Abi* abi = NULL;

  if ((NULL == abi) && AbiIsAvailable()) {
#ifdef GDB_RSP_ABI_ARM
    abi = Abi::Find("iwmmxt");
#elif GDB_RSP_ABI_X86_64
    abi = Abi::Find("i386:x86-64");
#elif GDB_RSP_ABI_X86
    abi = Abi::Find("i386");
#else
#error "Unknown CPU architecture."
#endif
  }

  return abi;
}

const char* Abi::GetName() const {
  return name_;
}

const Abi::BPDef *Abi::GetBreakpointDef() const {
  return bpDef_;
}

uint32_t Abi::GetContextSize() const {
  return ctxSize_;
}

uint32_t Abi::GetRegisterCount() const {
  return regCnt_;
}

const Abi::RegDef *Abi::GetRegisterDef(uint32_t index) const {
  if (index >= regCnt_) return NULL;

  return &regDefs_[index];
}

const Abi::RegDef *Abi::GetRegisterType(RegType rtype, uint32_t nth) const {
  uint32_t typeNum = 0;

  // Scan for the "nth" register of rtype;
  for (uint32_t regNum = 0; regNum < regCnt_; regNum++) {
    if (rtype == regDefs_[regNum].type_) {
      if (typeNum == nth) return &regDefs_[regNum];
      typeNum++;
    }
  }

  // Otherwise we failed to find it
  return NULL;
}

}  // namespace gdb_rsp

<commit_msg>Wrap the static constructor for AbiMap_t because it is a class type that uses a constructor.  This ensures that no code is executed statically by the debug stub.  In a review of the entire debug stub code, attached to the BUG below, this was the only statically executed code found in the gdb_rsp and debug_stub libraries.<commit_after>/*
 * Copyright (c) 2011 The Native Client 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 <assert.h>

#include <map>
#include <string>

#include "native_client/src/trusted/gdb_rsp/abi.h"
#include "native_client/src/trusted/port/platform.h"

using port::IPlatform;

namespace gdb_rsp {

#define MINIDEF(x, name, purpose) { #name, sizeof(x), Abi::purpose, 0, 0 }
#define BPDEF(x) { sizeof(x), x }

static Abi::RegDef RegsX86_64[] = {
  MINIDEF(uint64_t, rax, GENERAL),
  MINIDEF(uint64_t, rbx, GENERAL),
  MINIDEF(uint64_t, rcx, GENERAL),
  MINIDEF(uint64_t, rdx, GENERAL),
  MINIDEF(uint64_t, rsi, GENERAL),
  MINIDEF(uint64_t, rdi, GENERAL),
  MINIDEF(uint64_t, rbp, GENERAL),
  MINIDEF(uint64_t, rsp, GENERAL),
  MINIDEF(uint64_t, r8, GENERAL),
  MINIDEF(uint64_t, r9, GENERAL),
  MINIDEF(uint64_t, r10, GENERAL),
  MINIDEF(uint64_t, r11, GENERAL),
  MINIDEF(uint64_t, r12, GENERAL),
  MINIDEF(uint64_t, r13, GENERAL),
  MINIDEF(uint64_t, r14, GENERAL),
  MINIDEF(uint64_t, r15, GENERAL),
  MINIDEF(uint64_t, rip, INST_PTR),
  MINIDEF(uint32_t, eflags, FLAGS),
  MINIDEF(uint32_t, cs, SEGMENT),
  MINIDEF(uint32_t, ss, SEGMENT),
  MINIDEF(uint32_t, ds, SEGMENT),
  MINIDEF(uint32_t, es, SEGMENT),
  MINIDEF(uint32_t, fs, SEGMENT),
  MINIDEF(uint32_t, gs, SEGMENT),
};

static Abi::RegDef RegsX86_32[] = {
  MINIDEF(uint32_t, eax, GENERAL),
  MINIDEF(uint32_t, ecx, GENERAL),
  MINIDEF(uint32_t, edx, GENERAL),
  MINIDEF(uint32_t, ebx, GENERAL),
  MINIDEF(uint32_t, esp, GENERAL),
  MINIDEF(uint32_t, ebp, GENERAL),
  MINIDEF(uint32_t, esi, GENERAL),
  MINIDEF(uint32_t, edi, GENERAL),
  MINIDEF(uint32_t, eip, INST_PTR),
  MINIDEF(uint32_t, eflags, FLAGS),
  MINIDEF(uint32_t, cs, SEGMENT),
  MINIDEF(uint32_t, ss, SEGMENT),
  MINIDEF(uint32_t, ds, SEGMENT),
  MINIDEF(uint32_t, es, SEGMENT),
  MINIDEF(uint32_t, fs, SEGMENT),
  MINIDEF(uint32_t, gs, SEGMENT),
};

static Abi::RegDef RegsArm[] = {
  MINIDEF(uint32_t, r0, GENERAL),
  MINIDEF(uint32_t, r1, GENERAL),
  MINIDEF(uint32_t, r2, GENERAL),
  MINIDEF(uint32_t, r3, GENERAL),
  MINIDEF(uint32_t, r4, GENERAL),
  MINIDEF(uint32_t, r5, GENERAL),
  MINIDEF(uint32_t, r6, GENERAL),
  MINIDEF(uint32_t, r7, GENERAL),
  MINIDEF(uint32_t, r8, GENERAL),
  MINIDEF(uint32_t, r9, GENERAL),
  MINIDEF(uint32_t, r10, GENERAL),
  MINIDEF(uint32_t, r11, GENERAL),
  MINIDEF(uint32_t, r12, GENERAL),
  MINIDEF(uint32_t, sp, STACK_PTR),
  MINIDEF(uint32_t, lr, LINK_PTR),
  MINIDEF(uint32_t, pc, INST_PTR),
};

static uint8_t BPCodeX86[] = { 0xCC };

static Abi::BPDef BPX86 = BPDEF(BPCodeX86);

static AbiMap_t *GetAbis() {
  static AbiMap_t *_abis = new AbiMap_t();
  return _abis;
}

// AbiInit & AbiIsAvailable
//   This pair of functions work together as singleton to
// ensure the module has been correctly initialized.  All
// dependant functions should call AbiIsAvailable to ensure
// the module is ready.
static bool AbiInit() {
  Abi::Register("i386", RegsX86_32, sizeof(RegsX86_32), &BPX86);
  Abi::Register("i386:x86-64", RegsX86_64, sizeof(RegsX86_64), &BPX86);

  // TODO(cbiffle) Figure out how to REALLY detect ARM, and define Breakpoint
  Abi::Register("iwmmxt", RegsArm, sizeof(RegsArm), NULL);

  return true;
}

static bool AbiIsAvailable() {
  static bool initialized_ = AbiInit();
  return initialized_;
}

Abi::Abi() {}
Abi::~Abi() {}

void Abi::Register(const char *name, RegDef *regs,
                   uint32_t bytes, const BPDef *bp) {
  uint32_t offs = 0;
  const uint32_t cnt = bytes / sizeof(RegDef);

  // Build indexes and offsets
  for (uint32_t loop = 0; loop < cnt; loop++) {
    regs[loop].index_ = loop;
    regs[loop].offset_ = offs;
    offs += regs[loop].bytes_;
  }

  Abi *abi = new Abi;

  abi->name_ = name;
  abi->regCnt_ = cnt;
  abi->regDefs_= regs;
  abi->ctxSize_ = offs;
  abi->bpDef_ = bp;

  AbiMap_t *abis = GetAbis();
  (*abis)[name] = abi;
}

const Abi* Abi::Find(const char *name) {
  if (!AbiIsAvailable()) {
    IPlatform::LogError("Failed to initalize ABIs.");
    return NULL;
  }

  AbiMap_t::const_iterator itr = GetAbis()->find(name);
  if (itr == GetAbis()->end()) return NULL;

  return itr->second;
}

const Abi* Abi::Get() {
  static const Abi* abi = NULL;

  if ((NULL == abi) && AbiIsAvailable()) {
#ifdef GDB_RSP_ABI_ARM
    abi = Abi::Find("iwmmxt");
#elif GDB_RSP_ABI_X86_64
    abi = Abi::Find("i386:x86-64");
#elif GDB_RSP_ABI_X86
    abi = Abi::Find("i386");
#else
#error "Unknown CPU architecture."
#endif
  }

  return abi;
}

const char* Abi::GetName() const {
  return name_;
}

const Abi::BPDef *Abi::GetBreakpointDef() const {
  return bpDef_;
}

uint32_t Abi::GetContextSize() const {
  return ctxSize_;
}

uint32_t Abi::GetRegisterCount() const {
  return regCnt_;
}

const Abi::RegDef *Abi::GetRegisterDef(uint32_t index) const {
  if (index >= regCnt_) return NULL;

  return &regDefs_[index];
}

const Abi::RegDef *Abi::GetRegisterType(RegType rtype, uint32_t nth) const {
  uint32_t typeNum = 0;

  // Scan for the "nth" register of rtype;
  for (uint32_t regNum = 0; regNum < regCnt_; regNum++) {
    if (rtype == regDefs_[regNum].type_) {
      if (typeNum == nth) return &regDefs_[regNum];
      typeNum++;
    }
  }

  // Otherwise we failed to find it
  return NULL;
}

}  // namespace gdb_rsp
<|endoftext|>


<commit_before>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// 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.

// Internal Includes

// Library/third-party includes
#include <openvr_driver.h>
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <iostream>
#include <limits.h>
#include <string>
#include <vector>

#if _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

#if _MSC_VER >= 1800
#include <filesystem>
#else
#include <boost/filesystem.hpp>
#endif

#if defined(OSVR_WINDOWS)
static const auto DRIVER_DIRNAME_BASE = "win";
static const auto DRIVER_EXTENSION = ".dll";
#elif defined(OSVR_MACOSX)
/// @todo Note that there are no 64-bit steamvr runtimes or drivers on OS X
static const auto DRIVER_DIRNAME_BASE = "osx";
#elif defined(OSVR_LINUX)
static const auto DRIVER_DIRNAME_BASE = "linux";
#else
#error "Sorry, Valve does not produce a SteamVR runtime for your platform."
#endif

static const auto DRIVER_NAME = "lighthouse";

inline std::string getDriverDirname() {
    return DRIVER_DIRNAME_BASE + std::to_string(sizeof(void *) * CHAR_BIT);
}

namespace osvr {
namespace vive {

#if _MSC_VER == 1800 || _MSC_VER == 1900
    using std::tr2::sys::path;
    using std::tr2::sys::exists;
#else
    using boost::filesystem::path;
    using boost::filesystem::exists;
#endif

#if defined(OSVR_WINDOWS)

    inline std::vector<path> getSteamVRRoots() {
        /// @todo make this better - there's Windows API for that.
        return std::vector<path>{
            path{"C:\\Program Files\\Steam\\steamapps\\common\\SteamVR"},
            path{"C:\\Program "
                 "Files (x86)\\Steam\\steamapps\\common\\SteamVR"}};
    }
#elif defined(OSVR_MACOSX)
    inline std::vector<path> getSteamVRRoots() {
#error "implementation not complete"
    }
#elif defined(OSVR_LINUX)

    inline std::vector<path> getSteamVRRoots() {
#error "implementation not complete"
    }
#endif

    inline path getDriverFilePath(path const &root) {
        auto p = root;
        p /= "drivers";
        p /= DRIVER_NAME;
        p /= "bin";
        p /= getDriverDirname();
        p /= (std::string("driver_") + DRIVER_NAME + DRIVER_EXTENSION);
        return p;
    }

    inline path getDriverFilePath() {
        for (auto &root : getSteamVRRoots()) {
            auto driverFile = getDriverFilePath(root);
            if (exists(driverFile)) {
                return driverFile;
            }
        }
        return path{};
    }

    std::string tryLoading() {
        auto driverFile = getDriverFilePath();
        std::cout << "Will try to load driver from:\n"
                  << driverFile.string() << std::endl;
        if (exists(driverFile)) {
            std::cout << "It exists!" << std::endl;
            return driverFile.string();
        }
        std::cout << "It doesn't exist." << std::endl;
        return std::string();
    }

    static const auto ENTRY_POINT_FUNCTION_NAME = "HmdDriverFactory";
    class ViveLoader {
      public:
        ViveLoader(std::string const &driverFile) {
#if defined(OSVR_WINDOWS)
            driver_ = LoadLibraryA(driverFile.c_str());
            /// @todo check for NULL
            factory_ = reinterpret_cast<DriverFactory>(
                GetProcAddress(driver_, ENTRY_POINT_FUNCTION_NAME));
#else
#endif
            int returnCode = 0;
            void *ret =
                factory_(vr::IClientTrackedDeviceProvider_Version, &returnCode);
            if (ret) {
                std::cout
                    << "Successfully got the IClientTrackedDeviceProvider!";
                auto clientProvider =
                    static_cast<vr::IClientTrackedDeviceProvider *>(ret);
                auto isPresent = clientProvider->BIsHmdPresent(".");
                std::cout << " is present? " << std::boolalpha << isPresent
                          << std::endl;
            } else {
                std::cout << "Couldn't get it, error code " << returnCode
                          << std::endl;
            }
        }
        ~ViveLoader() {
#if defined(OSVR_WINDOWS)
            FreeLibrary(driver_);
#else
#endif
        }

      private:
        using DriverFactory = void *(*)(const char *, int *);
// typedef void *(DriverFactory)(const char *, int *);
#if defined(OSVR_WINDOWS)
        HMODULE driver_;
#else
#endif
        DriverFactory factory_;
    };

} // namespace vive
} // namespace osvr

int main() {
    auto driverLocation = osvr::vive::tryLoading();
    osvr::vive::ViveLoader vive(driverLocation);
    return 0;
}
<commit_msg>Add todo<commit_after>/** @file
    @brief Implementation

    @date 2016

    @author
    Sensics, Inc.
    <http://sensics.com/osvr>
*/

// Copyright 2016 Sensics, Inc.
//
// 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.

// Internal Includes

// Library/third-party includes
#include <openvr_driver.h>
#include <osvr/Util/PlatformConfig.h>

// Standard includes
#include <iostream>
#include <limits.h>
#include <string>
#include <vector>

#if _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif

#if _MSC_VER >= 1800
#include <filesystem>
#else
#include <boost/filesystem.hpp>
#endif

#if defined(OSVR_WINDOWS)
static const auto DRIVER_DIRNAME_BASE = "win";
static const auto DRIVER_EXTENSION = ".dll";
#elif defined(OSVR_MACOSX)
/// @todo Note that there are no 64-bit steamvr runtimes or drivers on OS X
static const auto DRIVER_DIRNAME_BASE = "osx";
#elif defined(OSVR_LINUX)
static const auto DRIVER_DIRNAME_BASE = "linux";
#else
#error "Sorry, Valve does not produce a SteamVR runtime for your platform."
#endif

static const auto DRIVER_NAME = "lighthouse";

inline std::string getDriverDirname() {
    return DRIVER_DIRNAME_BASE + std::to_string(sizeof(void *) * CHAR_BIT);
}

namespace osvr {
namespace vive {

#if _MSC_VER == 1800 || _MSC_VER == 1900
    using std::tr2::sys::path;
    using std::tr2::sys::exists;
#else
    using boost::filesystem::path;
    using boost::filesystem::exists;
#endif

#if defined(OSVR_WINDOWS)

    inline std::vector<path> getSteamVRRoots() {
        /// @todo make this better - there's Windows API for that.
        return std::vector<path>{
            path{"C:\\Program Files\\Steam\\steamapps\\common\\SteamVR"},
            path{"C:\\Program "
                 "Files (x86)\\Steam\\steamapps\\common\\SteamVR"}};
    }
#elif defined(OSVR_MACOSX)
    inline std::vector<path> getSteamVRRoots() {
#error "implementation not complete"
    }
#elif defined(OSVR_LINUX)

    inline std::vector<path> getSteamVRRoots() {
#error "implementation not complete"
    }
#endif

    inline path getDriverFilePath(path const &root) {
        auto p = root;
        p /= "drivers";
        p /= DRIVER_NAME;
        p /= "bin";
        p /= getDriverDirname();
        p /= (std::string("driver_") + DRIVER_NAME + DRIVER_EXTENSION);
        return p;
    }

    inline path getDriverFilePath() {
        for (auto &root : getSteamVRRoots()) {
            auto driverFile = getDriverFilePath(root);
            if (exists(driverFile)) {
                return driverFile;
            }
        }
        return path{};
    }

    std::string tryLoading() {
        auto driverFile = getDriverFilePath();
        std::cout << "Will try to load driver from:\n"
                  << driverFile.string() << std::endl;
        if (exists(driverFile)) {
            std::cout << "It exists!" << std::endl;
            return driverFile.string();
        }
        std::cout << "It doesn't exist." << std::endl;
        return std::string();
    }

    static const auto ENTRY_POINT_FUNCTION_NAME = "HmdDriverFactory";
    class ViveLoader {
      public:
        ViveLoader(std::string const& driverRoot, std::string const &driverFile) {
#if defined(OSVR_WINDOWS)
            /// @todo Set the PATH to include the driver directory so it can
            /// find its deps.
            driver_ = LoadLibraryA(driverFile.c_str());
            /// @todo check for NULL
            factory_ = reinterpret_cast<DriverFactory>(
                GetProcAddress(driver_, ENTRY_POINT_FUNCTION_NAME));
#else
#endif
            int returnCode = 0;
            void *ret =
                factory_(vr::IClientTrackedDeviceProvider_Version, &returnCode);
            if (ret) {
                std::cout
                    << "Successfully got the IClientTrackedDeviceProvider!";
                auto clientProvider =
                    static_cast<vr::IClientTrackedDeviceProvider *>(ret);
                auto isPresent = clientProvider->BIsHmdPresent(".");
                std::cout << " is present? " << std::boolalpha << isPresent
                          << std::endl;
            } else {
                std::cout << "Couldn't get it, error code " << returnCode
                          << std::endl;
            }
        }
        ~ViveLoader() {
#if defined(OSVR_WINDOWS)
            FreeLibrary(driver_);
#else
#endif
        }

      private:
        using DriverFactory = void *(*)(const char *, int *);
// typedef void *(DriverFactory)(const char *, int *);
#if defined(OSVR_WINDOWS)
        HMODULE driver_;
#else
#endif
        DriverFactory factory_;
    };

} // namespace vive
} // namespace osvr

int main() {
    auto driverLocation = osvr::vive::tryLoading();
    osvr::vive::ViveLoader vive("", driverLocation);
    return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-explorer.
 *
 * libbitcoin-explorer is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "command.hpp"

BX_USING_NAMESPACES()

BOOST_AUTO_TEST_SUITE(offline)
BOOST_AUTO_TEST_SUITE(input_sign__invoke)

// Vector A from sx.dyne.org/offlinetx.html
// The private key must correspond to the input for the signature to validate.
// The public key hash in the input (previous output) script is derived from
// the private key. The input is presumed to be from the transaction referred
// to by the tx input referenced by the index, but that cannot be validated
// here. The signature is deterministic only when the same nonce is used. In
// other words this signature will not match the sx example because the nonce
// was internal (not exposed) to the sx implementation.
#define INPUT_SIGN_NONCE_A "000102030405060708090a0b0c0d0e0f"
#define INPUT_SIGN_PRIVATE_KEY_A "ce8f4b713ffdd2658900845251890f30371856be201cd1f5b3d970f793634333"
#define INPUT_SIGN_PREVOUT_A "dup hash160 [ 88350574280395ad2c3e2ee20e322073d94e5e40 ] equalverify checksig"
#define INPUT_SIGN_TX_A "0100000001b3807042c92f449bbf79b33ca59d7dfec7f4cc71096704a9c526dddf496ee0970100000000ffffffff01905f0100000000001976a91418c0bd8d1818f1bf99cb1df2269c645318ef7b7388ac00000000"
#define INPUT_SIGN_ENDORSEMENT_A "3044022039a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c202201035fe810e283bcf394485c6a9dfd117ad9f684cdd83d36453718f5d0491b9dd01"

// Less than nonce minimum length of 16 bytes / 128 bits.
#define INPUT_SIGN_NONCE_B "000102030405060708090a0b0c0d0e"

// One input, no output.
// This is pathological case where a bitcoind bug is intentionally perpetuated.
#define INPUT_SIGN_TX_B "0100000001b3807042c92f449bbf79b33ca59d7dfec7f4cc71096704a9c526dddf496ee0970000000000ffffffff0000000000"
#define INPUT_SIGN_ENDORSEMENT_B "3044022039a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2022013d279c191f296349f59ba1cb6e17ea1f0db8f80a26714ef573e887818d544af01"

// This is not yet implemented in libbitcoin, should be soon.
#define INPUT_SIGN_ENDORSEMENT_DETERMINISTIC "3044022016516aabd04d3b27bec799bbadc55bad447db1e4bb663a32ed8ff6c6b7b6752602203651316e363b8c41c1b9db050690c6e5e9540ad04ded69184e710197734d3cf601"

//// Until that time and until we update this test vector, this determinstic test will fail.
//BOOST_AUTO_TEST_CASE(input_sign__invoke__deterministic_single_input_single_output__okay_output)
//{
//    BX_DECLARE_COMMAND(input_sign);
//    command.set_sign_type_option({ "all" });
//    command.set_transaction_argument({ INPUT_SIGN_TX_A });
//    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
//    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
//    BX_REQUIRE_OKAY(command.invoke(output, error));
//    BX_REQUIRE_OUTPUT(INPUT_SIGN_ENDORSEMENT_DETERMINISTIC "\n");
//}
//
//// TODO: finish non-deterministic sig in libbitcoin.
//BOOST_AUTO_TEST_CASE(input_sign__invoke__single_input_single_output__okay_output)
//{
//    BX_DECLARE_COMMAND(input_sign);
//    command.set_sign_type_option({ "all" });
//    command.set_nonce_option({ INPUT_SIGN_NONCE_A });
//    command.set_transaction_argument({ INPUT_SIGN_TX_A });
//    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
//    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
//    BX_REQUIRE_OKAY(command.invoke(output, error));
//    //BX_REQUIRE_OUTPUT(INPUT_SIGN_ENDORSEMENT_A "\n");
//}
//
//// TODO: finish non-deterministic sig in libbitcoin.
//BOOST_AUTO_TEST_CASE(input_sign__invoke__single_input_no_output__okay_output)
//{
//    BX_DECLARE_COMMAND(input_sign);
//    command.set_sign_type_option({ "all" });
//    command.set_nonce_option({ INPUT_SIGN_NONCE_A });
//    command.set_transaction_argument({ INPUT_SIGN_TX_B });
//    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
//    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
//    BX_REQUIRE_OKAY(command.invoke(output, error));
////    BX_REQUIRE_OUTPUT(INPUT_SIGN_ENDORSEMENT_B "\n");
//}
//
//BOOST_AUTO_TEST_CASE(input_sign__invoke__short_nonce__failure_error)
//{
//    BX_DECLARE_COMMAND(input_sign);
//    command.set_nonce_option({ INPUT_SIGN_NONCE_B });
//    command.set_transaction_argument({ INPUT_SIGN_TX_A });
//    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
//    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
//    BX_REQUIRE_FAILURE(command.invoke(output, error));
//    BX_REQUIRE_ERROR(BX_INPUT_SIGN_SHORT_NONCE "\n");
//}
//
//BOOST_AUTO_TEST_CASE(input_sign__invoke__invalid_index__failure_error)
//{
//    BX_DECLARE_COMMAND(input_sign);
//    command.set_index_option(42);
//    command.set_nonce_option({ INPUT_SIGN_NONCE_A });
//    command.set_transaction_argument({ INPUT_SIGN_TX_A });
//    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
//    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
//    BX_REQUIRE_FAILURE(command.invoke(output, error));
//    BX_REQUIRE_ERROR(BX_INPUT_SIGN_INDEX_OUT_OF_RANGE "\n");
//}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()<commit_msg>Restore input-sign tests as deterministic.<commit_after>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin-explorer.
 *
 * libbitcoin-explorer is free software: you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */

#include "command.hpp"

BX_USING_NAMESPACES()

BOOST_AUTO_TEST_SUITE(offline)
BOOST_AUTO_TEST_SUITE(input_sign__invoke)

// Vector A from sx.dyne.org/offlinetx.html
// The private key must correspond to the input for the signature to validate.
// The public key hash in the input (previous output) script is derived from
// the private key. The input is presumed to be from the transaction referred
// to by the tx input referenced by the index, but that cannot be validated
// here. This signature will not match the sx example because this signature is
// deterministic.
#define INPUT_SIGN_PRIVATE_KEY_A "ce8f4b713ffdd2658900845251890f30371856be201cd1f5b3d970f793634333"
#define INPUT_SIGN_PREVOUT_A "dup hash160 [ 88350574280395ad2c3e2ee20e322073d94e5e40 ] equalverify checksig"
#define INPUT_SIGN_TX_A "0100000001b3807042c92f449bbf79b33ca59d7dfec7f4cc71096704a9c526dddf496ee0970100000000ffffffff01905f0100000000001976a91418c0bd8d1818f1bf99cb1df2269c645318ef7b7388ac00000000"
//#define INPUT_SIGN_ENDORSEMENT_A "3044022039a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c202201035fe810e283bcf394485c6a9dfd117ad9f684cdd83d36453718f5d0491b9dd01"
#define INPUT_SIGN_ENDORSEMENT_A "3044022016516aabd04d3b27bec799bbadc55bad447db1e4bb663a32ed8ff6c6b7b6752602203651316e363b8c41c1b9db050690c6e5e9540ad04ded69184e710197734d3cf601"

// One input, no output.
// This is pathological case where a bitcoind bug is intentionally perpetuated.
#define INPUT_SIGN_TX_B "0100000001b3807042c92f449bbf79b33ca59d7dfec7f4cc71096704a9c526dddf496ee0970000000000ffffffff0000000000"
//#define INPUT_SIGN_ENDORSEMENT_B "3044022039a36013301597daef41fbe593a02cc513d0b55527ec2df1050e2e8ff49c85c2022013d279c191f296349f59ba1cb6e17ea1f0db8f80a26714ef573e887818d544af01"
#define INPUT_SIGN_ENDORSEMENT_B "304402204c8006959f65cb270f424521b34444198c2c80e7bf53b302085ef271b30eecf502202cf49e9136ded201e7268051eeb3838bb7e5763e0eb8aa5ed90d84a373aaaea301"

BOOST_AUTO_TEST_CASE(input_sign__invoke__single_input_single_output__okay_output)
{
    BX_DECLARE_COMMAND(input_sign);
    command.set_sign_type_option({ "all" });
    command.set_transaction_argument({ INPUT_SIGN_TX_A });
    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
    BX_REQUIRE_OKAY(command.invoke(output, error));
    BX_REQUIRE_OUTPUT(INPUT_SIGN_ENDORSEMENT_A "\n");
}

BOOST_AUTO_TEST_CASE(input_sign__invoke__single_input_no_output__okay_output)
{
    BX_DECLARE_COMMAND(input_sign);
    command.set_sign_type_option({ "all" });
    command.set_transaction_argument({ INPUT_SIGN_TX_B });
    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
    BX_REQUIRE_OKAY(command.invoke(output, error));
    BX_REQUIRE_OUTPUT(INPUT_SIGN_ENDORSEMENT_B "\n");
}

BOOST_AUTO_TEST_CASE(input_sign__invoke__invalid_index__failure_error)
{
    BX_DECLARE_COMMAND(input_sign);
    command.set_index_option(42);
    command.set_transaction_argument({ INPUT_SIGN_TX_A });
    command.set_prevout_script_argument({ INPUT_SIGN_PREVOUT_A });
    command.set_ec_private_key_argument({ INPUT_SIGN_PRIVATE_KEY_A });
    BX_REQUIRE_FAILURE(command.invoke(output, error));
    BX_REQUIRE_ERROR(BX_INPUT_SIGN_INDEX_OUT_OF_RANGE "\n");
}

BOOST_AUTO_TEST_SUITE_END()
BOOST_AUTO_TEST_SUITE_END()<|endoftext|>