<commit_before>//                       MFEM Example normal-bc - Parallel Version
//

/*
  square-disc attributes:

*/

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../data/square-disc.mesh";
   int order = 1;
   bool static_cond = false;
   bool pa = false;
   const char *device_config = "cpu";
   bool visualization = true;
   int boundary_attribute = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
                  "--no-partial-assembly", "Enable Partial Assembly.");
   args.AddOption(&device_config, "-d", "--device",
                  "Device configuration string, see Device::Configure().");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&boundary_attribute, "--boundary-attribute", "--boundary-attribute",
                  "Which attribute to apply essential conditions on.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   Device device(device_config);
   if (myid == 0) { device.Print(); }

   Mesh mesh(mesh_file, 1, 1);
   int dim = mesh.Dimension();

   {
      int ref_levels =
         (int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh.UniformRefinement();
      }
   }

   ParMesh pmesh(MPI_COMM_WORLD, mesh);
   mesh.Clear();
   {
      // int par_ref_levels = 2;
      int par_ref_levels = 0;
      for (int l = 0; l < par_ref_levels; l++)
      {
         pmesh.UniformRefinement();
      }
   }

   // 7. Define a parallel finite element space on the parallel mesh. Here we
   //    use continuous Lagrange finite elements of the specified order. If
   //    order < 1, we instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   bool delete_fec;
   if (order > 0)
   {
      fec = new H1_FECollection(order, dim);
      delete_fec = true;
   }
   else if (pmesh.GetNodes())
   {
      fec = pmesh.GetNodes()->OwnFEC();
      delete_fec = false;
      if (myid == 0)
      {
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
   }
   else
   {
      fec = new H1_FECollection(order = 1, dim);
      delete_fec = true;
   }
   ParFiniteElementSpace fespace(&pmesh, fec, dim); // vector space
   HYPRE_Int size = fespace.GlobalTrueVSize();
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   Array<int> ess_tdof_list;
   if (pmesh.bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh.bdr_attributes.Max());
      // ess_bdr = 1;
      ess_bdr = 0;
      ess_bdr[boundary_attribute - 1] = 1;
      fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   ParLinearForm b(&fespace);
   // ConstantCoefficient one(1.0);
   Vector rhs_direction(dim);
   rhs_direction = 0.0;
   rhs_direction[0] = 1.0;
   VectorConstantCoefficient rhs_coeff(rhs_direction);
   b.AddDomainIntegrator(new VectorDomainLFIntegrator(rhs_coeff));
   b.Assemble();

   // 10. Define the solution vector x as a parallel finite element grid function
   //     corresponding to fespace. Initialize x with initial guess of zero,
   //     which satisfies the boundary conditions.
   ParGridFunction x(&fespace);
   x = 0.0;

   // 11. Set up the parallel bilinear form a(.,.) on the finite element space
   //     corresponding to the Laplacian operator -Delta, by adding the Diffusion
   //     domain integrator.
   ParBilinearForm a(&fespace);
   if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
   // a.AddDomainIntegrator(new DiffusionIntegrator(one));
   Vector ones(dim);
   ones = 1.0;
   VectorConstantCoefficient coeff(ones);
   a.AddDomainIntegrator(new VectorMassIntegrator(coeff));

   // 12. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a.EnableStaticCondensation(); }
   a.Assemble();

   OperatorPtr A;
   Vector B, X;
   a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);

   // 13. Solve the linear system A X = B.
   //     * With full assembly, use the BoomerAMG preconditioner from hypre.
   //     * With partial assembly, use Jacobi smoothing, for now.
   Solver *prec = NULL;
   if (pa)
   {
      if (UsesTensorBasis(fespace))
      {
         prec = new OperatorJacobiSmoother(a, ess_tdof_list);
      }
   }
   else
   {
      auto h_prec = new HypreBoomerAMG;
      h_prec->SetPrintLevel(0);
      prec = h_prec;
   }
   CGSolver cg(MPI_COMM_WORLD);
   cg.SetRelTol(1e-12);
   cg.SetMaxIter(2000);
   cg.SetPrintLevel(1);
   if (prec) { cg.SetPreconditioner(*prec); }
   cg.SetOperator(*A);
   cg.Mult(B, X);
   delete prec;

   // 14. Recover the parallel grid function corresponding to X. This is the
   //     local finite element solution on each processor.
   a.RecoverFEMSolution(X, b, x);

   // 15. Save the refined mesh and the solution in parallel. This output can
   //     be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
   {
      std::stringstream visitname;
      visitname << "normal" << boundary_attribute;
      VisItDataCollection visit_dc(MPI_COMM_WORLD, visitname.str(), &pmesh);
      visit_dc.RegisterField("sol", &x);
      visit_dc.Save();
   }

   // 16. Send the solution by socket to a GLVis server.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock << "parallel " << num_procs << " " << myid << "\n";
      sol_sock.precision(8);
      sol_sock << "solution\n" << pmesh << x << flush;
   }

   // 17. Free the used memory.
   if (delete_fec)
   {
      delete fec;
   }
   MPI_Finalize();

   return 0;
}
<commit_msg>WIP: begin putting together constraint matrix<commit_after>//                       MFEM Example normal-bc - Parallel Version
//

/*
  square-disc attributes (not indices):

  1: south external
  2: east external
  3: north external
  4: west external
  5: southeast internal
  6: northeast internal
  7: northwest internal
  8: southwest internal
*/

#include "mfem.hpp"
#include <fstream>
#include <iostream>

using namespace std;
using namespace mfem;

SparseMatrix * BuildConstraints(FiniteElementSpace& fespace, Array<int> constrained_att)
{
   int dim = fespace.GetVDim();

   std::set<int> constrained_dofs;
   for (int i = 0; i < fespace.GetNBE(); ++i)
   {
      int att = fespace.GetBdrAttribute(i);
      if (constrained_att.FindSorted(att) != -1)
      {
         Array<int> dofs;
         fespace.GetBdrElementDofs(i, dofs);
         for (auto k : dofs)
         {
            constrained_dofs.insert(k);
         }
      }
   }

   std::map<int, int> dof_constraint;
   int n_constraints = 0;
   for (auto k : constrained_dofs)
   {
      dof_constraint[k] = n_constraints++;
   }
   SparseMatrix * out = new SparseMatrix(n_constraints, fespace.GetVSize());

   for (int i = 0; i < fespace.GetNBE(); ++i)
   {
      // todo: get normal!
      int att = fespace.GetBdrAttribute(i);
      if (constrained_att.FindSorted(att) != -1)
      {
         Array<int> dofs;
         fespace.GetBdrElementDofs(i, dofs);
         for (auto k : dofs)
         {
            int constraint = dof_constraint[k];
            for (int d = 0; d < dim; ++d)
            {
               int vdof = fespace.DofToVDof(k, d);
               double value = 1.0;
               out->Set(constraint, vdof, value);
            }
         }
      }
   }

   out->Finalize();
   return out;
}

int main(int argc, char *argv[])
{
   // 1. Initialize MPI.
   int num_procs, myid;
   MPI_Init(&argc, &argv);
   MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
   MPI_Comm_rank(MPI_COMM_WORLD, &myid);

   // 2. Parse command-line options.
   const char *mesh_file = "../data/square-disc.mesh";
   int order = 1;
   bool static_cond = false;
   bool pa = false;
   const char *device_config = "cpu";
   bool visualization = true;
   int boundary_attribute = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&order, "-o", "--order",
                  "Finite element order (polynomial degree) or -1 for"
                  " isoparametric space.");
   args.AddOption(&static_cond, "-sc", "--static-condensation", "-no-sc",
                  "--no-static-condensation", "Enable static condensation.");
   args.AddOption(&pa, "-pa", "--partial-assembly", "-no-pa",
                  "--no-partial-assembly", "Enable Partial Assembly.");
   args.AddOption(&device_config, "-d", "--device",
                  "Device configuration string, see Device::Configure().");
   args.AddOption(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.AddOption(&boundary_attribute, "--boundary-attribute", "--boundary-attribute",
                  "Which attribute to apply essential conditions on.");

   args.Parse();
   if (!args.Good())
   {
      if (myid == 0)
      {
         args.PrintUsage(cout);
      }
      MPI_Finalize();
      return 1;
   }
   if (myid == 0)
   {
      args.PrintOptions(cout);
   }

   Device device(device_config);
   if (myid == 0) { device.Print(); }

   Mesh mesh(mesh_file, 1, 1);
   int dim = mesh.Dimension();

   {
      int ref_levels =
         (int)floor(log(10000./mesh.GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh.UniformRefinement();
      }
   }

   ParMesh pmesh(MPI_COMM_WORLD, mesh);
   mesh.Clear();
   {
      // int par_ref_levels = 2;
      int par_ref_levels = 0;
      for (int l = 0; l < par_ref_levels; l++)
      {
         pmesh.UniformRefinement();
      }
   }

   // 7. Define a parallel finite element space on the parallel mesh. Here we
   //    use continuous Lagrange finite elements of the specified order. If
   //    order < 1, we instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   bool delete_fec;
   if (order > 0)
   {
      fec = new H1_FECollection(order, dim);
      delete_fec = true;
   }
   else if (pmesh.GetNodes())
   {
      fec = pmesh.GetNodes()->OwnFEC();
      delete_fec = false;
      if (myid == 0)
      {
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
   }
   else
   {
      fec = new H1_FECollection(order = 1, dim);
      delete_fec = true;
   }
   ParFiniteElementSpace fespace(&pmesh, fec, dim); // vector space
   HYPRE_Int size = fespace.GlobalTrueVSize();
   if (myid == 0)
   {
      cout << "Number of finite element unknowns: " << size << endl;
   }

   Array<int> ess_tdof_list;
   if (pmesh.bdr_attributes.Size())
   {
      Array<int> ess_bdr(pmesh.bdr_attributes.Max());
      // ess_bdr = 1;
      ess_bdr = 0;
      ess_bdr[boundary_attribute - 1] = 1;
      fespace.GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   {
      Array<int> circle_atts(4);
      circle_atts[0] = 5;
      circle_atts[1] = 6;
      circle_atts[2] = 7;
      circle_atts[3] = 8;
      SparseMatrix * B = BuildConstraints(fespace, circle_atts);
      std::ofstream out("constraint.sparsematrix");
      B->Print(out, 1);
   }

   ParLinearForm b(&fespace);
   // ConstantCoefficient one(1.0);
   Vector rhs_direction(dim);
   rhs_direction = 0.0;
   rhs_direction[0] = 1.0;
   VectorConstantCoefficient rhs_coeff(rhs_direction);
   b.AddDomainIntegrator(new VectorDomainLFIntegrator(rhs_coeff));
   b.Assemble();

   // 10. Define the solution vector x as a parallel finite element grid function
   //     corresponding to fespace. Initialize x with initial guess of zero,
   //     which satisfies the boundary conditions.
   ParGridFunction x(&fespace);
   x = 0.0;

   // 11. Set up the parallel bilinear form a(.,.) on the finite element space
   //     corresponding to the Laplacian operator -Delta, by adding the Diffusion
   //     domain integrator.
   ParBilinearForm a(&fespace);
   if (pa) { a.SetAssemblyLevel(AssemblyLevel::PARTIAL); }
   // a.AddDomainIntegrator(new DiffusionIntegrator(one));
   Vector ones(dim);
   ones = 1.0;
   VectorConstantCoefficient coeff(ones);
   a.AddDomainIntegrator(new VectorMassIntegrator(coeff));

   // 12. Assemble the parallel bilinear form and the corresponding linear
   //     system, applying any necessary transformations such as: parallel
   //     assembly, eliminating boundary conditions, applying conforming
   //     constraints for non-conforming AMR, static condensation, etc.
   if (static_cond) { a.EnableStaticCondensation(); }
   a.Assemble();

   OperatorPtr A;
   Vector B, X;
   a.FormLinearSystem(ess_tdof_list, x, b, A, X, B);

   // 13. Solve the linear system A X = B.
   //     * With full assembly, use the BoomerAMG preconditioner from hypre.
   //     * With partial assembly, use Jacobi smoothing, for now.
   Solver *prec = NULL;
   if (pa)
   {
      if (UsesTensorBasis(fespace))
      {
         prec = new OperatorJacobiSmoother(a, ess_tdof_list);
      }
   }
   else
   {
      auto h_prec = new HypreBoomerAMG;
      h_prec->SetPrintLevel(0);
      prec = h_prec;
   }
   CGSolver cg(MPI_COMM_WORLD);
   cg.SetRelTol(1e-12);
   cg.SetMaxIter(2000);
   cg.SetPrintLevel(1);
   if (prec) { cg.SetPreconditioner(*prec); }
   cg.SetOperator(*A);
   cg.Mult(B, X);
   delete prec;

   // 14. Recover the parallel grid function corresponding to X. This is the
   //     local finite element solution on each processor.
   a.RecoverFEMSolution(X, b, x);

   // 15. Save the refined mesh and the solution in parallel. This output can
   //     be viewed later using GLVis: "glvis -np <np> -m mesh -g sol".
   {
      // todo: might make more sense to .SetCycle() than to append boundary_attribute to name
      std::stringstream visitname;
      visitname << "normal" << boundary_attribute;
      VisItDataCollection visit_dc(MPI_COMM_WORLD, visitname.str(), &pmesh);
      visit_dc.RegisterField("sol", &x);
      visit_dc.Save();
   }

   // 16. Send the solution by socket to a GLVis server.
   if (visualization)
   {
      char vishost[] = "localhost";
      int  visport   = 19916;
      socketstream sol_sock(vishost, visport);
      sol_sock << "parallel " << num_procs << " " << myid << "\n";
      sol_sock.precision(8);
      sol_sock << "solution\n" << pmesh << x << flush;
   }

   // 17. Free the used memory.
   if (delete_fec)
   {
      delete fec;
   }
   MPI_Finalize();

   return 0;
}
<|endoftext|>


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

#include "xwalk/runtime/browser/ui/tizen_system_indicator.h"

#include "ui/gfx/canvas.h"
#include "content/public/browser/browser_thread.h"
#include "xwalk/runtime/browser/ui/tizen_system_indicator_watcher.h"

#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/root_view.h"
#include "ui/aura/root_window.h"

namespace {

SkColor kBGColor = SkColorSetARGB(255, 52, 52, 50);

}  // namespace

namespace xwalk {

TizenSystemIndicator::TizenSystemIndicator()
    : watcher_(new TizenSystemIndicatorWatcher(this)) {
  if (!watcher_->Connect()) {
    watcher_.reset();
    return;
  }

  set_background(views::Background::CreateSolidBackground(kBGColor));

  content::BrowserThread::PostTask(
      content::BrowserThread::IO, FROM_HERE,
      base::Bind(&TizenSystemIndicatorWatcher::StartWatching,
                 base::Unretained(watcher_.get())));
}

TizenSystemIndicator::~TizenSystemIndicator() {
}

bool TizenSystemIndicator::IsConnected() const {
  return watcher_;
}

void TizenSystemIndicator::OnPaint(gfx::Canvas* canvas) {
  View::OnPaint(canvas);

  if (image_.isNull())
    return;
  canvas->DrawImageInt(image_, 0, 0);
}

gfx::Size TizenSystemIndicator::GetPreferredSize() {
  return watcher_->GetSize();
}

void TizenSystemIndicator::SetImage(const gfx::ImageSkia& img) {
  image_ = img;
  SchedulePaint();
}

bool TizenSystemIndicator::OnMousePressed(const ui::MouseEvent& event) {
  watcher_->OnMouseDown();
  return true;
}

void TizenSystemIndicator::OnMouseReleased(const ui::MouseEvent& event) {
  watcher_->OnMouseUp();
}

void TizenSystemIndicator::OnTouchEvent(ui::TouchEvent* event) {
  const gfx::Point position = event->location();

  switch (event->type()) {
    case ui::ET_UNKNOWN:
    case ui::ET_MOUSE_PRESSED:
    case ui::ET_MOUSE_DRAGGED:
    case ui::ET_MOUSE_RELEASED:
    case ui::ET_MOUSE_MOVED:
    case ui::ET_MOUSE_ENTERED:
    case ui::ET_MOUSE_EXITED:
    case ui::ET_KEY_PRESSED:
    case ui::ET_KEY_RELEASED:
    case ui::ET_MOUSEWHEEL:
    case ui::ET_MOUSE_CAPTURE_CHANGED:
    case ui::ET_TOUCH_RELEASED:
      watcher_->OnMouseUp();
      break;
    case ui::ET_TOUCH_PRESSED:
      watcher_->OnMouseDown();
      break;
    case ui::ET_TOUCH_MOVED:
      watcher_->OnMouseMove(position.x(), position.y());
      break;
    case ui::ET_TOUCH_STATIONARY:
    case ui::ET_TOUCH_CANCELLED:
    case ui::ET_DROP_TARGET_EVENT:
    case ui::ET_TRANSLATED_KEY_PRESS:
    case ui::ET_TRANSLATED_KEY_RELEASE:
    case ui::ET_GESTURE_SCROLL_BEGIN:
    case ui::ET_GESTURE_SCROLL_END:
    case ui::ET_GESTURE_SCROLL_UPDATE:
    case ui::ET_GESTURE_TAP:
    case ui::ET_GESTURE_TAP_DOWN:
    case ui::ET_GESTURE_TAP_CANCEL:
    case ui::ET_GESTURE_BEGIN:
    case ui::ET_GESTURE_END:
    case ui::ET_GESTURE_TWO_FINGER_TAP:
    case ui::ET_GESTURE_PINCH_BEGIN:
    case ui::ET_GESTURE_PINCH_END:
    case ui::ET_GESTURE_PINCH_UPDATE:
    case ui::ET_GESTURE_LONG_PRESS:
    case ui::ET_GESTURE_LONG_TAP:
    case ui::ET_GESTURE_MULTIFINGER_SWIPE:
    case ui::ET_SCROLL:
    case ui::ET_SCROLL_FLING_START:
    case ui::ET_SCROLL_FLING_CANCEL:
    case ui::ET_CANCEL_MODE:
    case ui::ET_LAST:
      break;
  }
  event->SetHandled();
}

void TizenSystemIndicator::OnMouseMoved(const ui::MouseEvent& event) {
  const gfx::Point position = event.location();
  watcher_->OnMouseMove(position.x(), position.y());
}

}  // namespace xwalk
<commit_msg>Fix build introduced by tizen_system_indicator<commit_after>// Copyright (c) 2013 Intel Corporation. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "xwalk/runtime/browser/ui/tizen_system_indicator.h"

#include "ui/gfx/canvas.h"
#include "content/public/browser/browser_thread.h"
#include "xwalk/runtime/browser/ui/tizen_system_indicator_watcher.h"

#include "ui/views/widget/native_widget.h"
#include "ui/views/widget/root_view.h"
#include "ui/aura/root_window.h"

namespace {

SkColor kBGColor = SkColorSetARGB(255, 52, 52, 50);

}  // namespace

namespace xwalk {

TizenSystemIndicator::TizenSystemIndicator()
    : watcher_(new TizenSystemIndicatorWatcher(this)) {
  if (!watcher_->Connect()) {
    watcher_.reset();
    return;
  }

  set_background(views::Background::CreateSolidBackground(kBGColor));

  content::BrowserThread::PostTask(
      content::BrowserThread::IO, FROM_HERE,
      base::Bind(&TizenSystemIndicatorWatcher::StartWatching,
                 base::Unretained(watcher_.get())));
}

TizenSystemIndicator::~TizenSystemIndicator() {
}

bool TizenSystemIndicator::IsConnected() const {
  return watcher_;
}

void TizenSystemIndicator::OnPaint(gfx::Canvas* canvas) {
  View::OnPaint(canvas);

  if (image_.isNull())
    return;
  canvas->DrawImageInt(image_, 0, 0);
}

gfx::Size TizenSystemIndicator::GetPreferredSize() {
  return watcher_->GetSize();
}

void TizenSystemIndicator::SetImage(const gfx::ImageSkia& img) {
  image_ = img;
  SchedulePaint();
}

bool TizenSystemIndicator::OnMousePressed(const ui::MouseEvent& event) {
  watcher_->OnMouseDown();
  return true;
}

void TizenSystemIndicator::OnMouseReleased(const ui::MouseEvent& event) {
  watcher_->OnMouseUp();
}

void TizenSystemIndicator::OnTouchEvent(ui::TouchEvent* event) {
  const gfx::Point position = event->location();

  switch (event->type()) {
    case ui::ET_UNKNOWN:
    case ui::ET_MOUSE_PRESSED:
    case ui::ET_MOUSE_DRAGGED:
    case ui::ET_MOUSE_RELEASED:
    case ui::ET_MOUSE_MOVED:
    case ui::ET_MOUSE_ENTERED:
    case ui::ET_MOUSE_EXITED:
    case ui::ET_KEY_PRESSED:
    case ui::ET_KEY_RELEASED:
    case ui::ET_MOUSEWHEEL:
    case ui::ET_MOUSE_CAPTURE_CHANGED:
    case ui::ET_TOUCH_RELEASED:
      watcher_->OnMouseUp();
      break;
    case ui::ET_TOUCH_PRESSED:
      watcher_->OnMouseDown();
      break;
    case ui::ET_TOUCH_MOVED:
      watcher_->OnMouseMove(position.x(), position.y());
      break;
    case ui::ET_TOUCH_STATIONARY:
    case ui::ET_TOUCH_CANCELLED:
    case ui::ET_DROP_TARGET_EVENT:
    case ui::ET_TRANSLATED_KEY_PRESS:
    case ui::ET_TRANSLATED_KEY_RELEASE:
    case ui::ET_GESTURE_SCROLL_BEGIN:
    case ui::ET_GESTURE_SCROLL_END:
    case ui::ET_GESTURE_SCROLL_UPDATE:
    case ui::ET_GESTURE_TAP:
    case ui::ET_GESTURE_TAP_DOWN:
    case ui::ET_GESTURE_TAP_CANCEL:
    case ui::ET_GESTURE_BEGIN:
    case ui::ET_GESTURE_END:
    case ui::ET_GESTURE_TWO_FINGER_TAP:
    case ui::ET_GESTURE_PINCH_BEGIN:
    case ui::ET_GESTURE_PINCH_END:
    case ui::ET_GESTURE_PINCH_UPDATE:
    case ui::ET_GESTURE_LONG_PRESS:
    case ui::ET_GESTURE_LONG_TAP:
    case ui::ET_GESTURE_MULTIFINGER_SWIPE:
    case ui::ET_SCROLL:
    case ui::ET_SCROLL_FLING_START:
    case ui::ET_SCROLL_FLING_CANCEL:
    case ui::ET_CANCEL_MODE:
    case ui::ET_UMA_DATA:
    case ui::ET_LAST:
      break;
  }
  event->SetHandled();
}

void TizenSystemIndicator::OnMouseMoved(const ui::MouseEvent& event) {
  const gfx::Point position = event.location();
  watcher_->OnMouseMove(position.x(), position.y());
}

}  // namespace xwalk
<|endoftext|>


<commit_before>#pragma once

#include <iostream>
#include <string>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <typeinfo>
#include <cxxabi.h>
#include <sys/time.h>
#include <stdarg.h>

#include <zcm/zcm-cpp.hpp>

static bool __ZCM_DEBUG_ENABLED__ = (NULL != getenv("ZCM_DEBUG"));
#define ZCM_DEBUG(...) \
    do { \
        if (__ZCM_DEBUG_ENABLED__) \
            __ZCM_PRINT_OBFUSCATE__(std::cout, "ZCM-DEBUG: ", __VA_ARGS__, '\n'); \
    } while(0)

namespace zcm {

template <typename T>
class MessageTracker
{
  public:
    typedef void (*callback)(T* msg, uint64_t utime, void* usr);
    static const bool NONBLOCKING = false;
    static const bool BLOCKING = true;

  protected:
    virtual uint64_t getMsgUtime(const T* msg)
    {
        return hasUtime<T>::utime(msg);
    }

    // The returned value must be "new" in all cases
    virtual T* interpolate(uint64_t utimeTarget,
                           const T* A, uint64_t utimeA,
                           const T* B, uint64_t utimeB)
    {
        return utimeTarget - utimeA < utimeB - utimeTarget ? new T(*A) : new T(*B);
    }

  private:
    zcm::ZCM* zcmLocal = nullptr;

    std::atomic_bool done {false};

    std::deque<T*> buf;
    size_t bufMax;
    std::mutex bufLock;
    std::condition_variable newMsg;
    zcm::Subscription *s;

    std::mutex callbackLock;
    std::condition_variable callbackCv;
    T* callbackMsg = nullptr;
    std::thread *thr = nullptr;
    callback onMsg;
    void* usr;

    uint64_t maxTimeErr_us;

    void callbackThreadFunc()
    {
        std::unique_lock<std::mutex> lk(callbackLock);
        while (!done) {
            callbackCv.wait(lk, [&](){ return callbackMsg || done; });
            if (done) return;
            onMsg(callbackMsg, getMsgUtime(callbackMsg), usr);
            // Intentionally not deleting callbackMsg as it is the
            // responsibility of the callback to delete the memory
            callbackMsg = nullptr;
        }
    }

    void handle(const zcm::ReceiveBuffer* rbuf, const std::string& chan, const T* _msg)
    {
        if (done) return;

        T* tmp = new T(*_msg);

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (buf.size() == bufMax) buf.pop_front();

            while (!buf.empty()) {
                if (getMsgUtime(buf.front()) + maxTimeErr_us > getMsgUtime(_msg)) break;
                buf.pop_front();
            }

            buf.push_back(tmp);
        }
        newMsg.notify_all();

        if (callbackLock.try_lock()) {
            if (callbackMsg) delete callbackMsg;
            callbackMsg = new T(*_msg);
            callbackLock.unlock();
            callbackCv.notify_all();
        }
    }

    MessageTracker() {}

  public:
    MessageTracker(zcm::ZCM* zcmLocal, std::string channel,
                   double maxTimeErr = 0.25, size_t maxMsgs = 1,
                   callback onMsg = nullptr, void* usr = nullptr)
        : zcmLocal(zcmLocal), maxTimeErr_us(maxTimeErr * 1e6), onMsg(onMsg), usr(usr)
    {
        if (hasUtime<T>::present == true) {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using 'utime' field of zcmtype ", name);
        } else {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using local system receive utime for ",
                      "tracking zcmtype ", name);
        }

        bufMax = maxMsgs;

        if (onMsg != nullptr) thr = new std::thread(&MessageTracker<T>::callbackThreadFunc, this);
        s = zcmLocal->subscribe(channel, &MessageTracker<T>::handle, this);
    }

    virtual ~MessageTracker()
    {
        zcmLocal->unsubscribe(s);
        done = true;
        newMsg.notify_all();
        callbackCv.notify_all();
        if (thr) {
            thr->join();
            delete thr;
        }
        while (!buf.empty()) buf.pop_front();
    }

    // You must free the memory returned here
    virtual T* get(bool blocking = NONBLOCKING)
    {
        T* ret = nullptr;

        {
            std::unique_lock<std::mutex> lk(bufLock);
            if (blocking == BLOCKING) {
                if (buf.empty())
                    newMsg.wait(lk, [&]{ return !buf.empty() || done; });
                if (done) return nullptr;
            }
            if (!buf.empty())
                ret = new T(*buf.back());
        }

        return ret;
    }

    // This may return nullptr even in the blocking case
    // TODO: Should consider how to allow the user to ask for an extrapolated
    //       message if bracketted messages arent available
    virtual T* get(uint64_t utime, bool blocking = NONBLOCKING)
    {
        T *m0 = nullptr, *m1 = nullptr; // two poses bracketing the desired utime
        uint64_t m0Utime, m1Utime;

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (blocking == BLOCKING) {
                // XXX This is technically not okay. "done" can't be an
                //     atomic as it can change after we've checked it in the
                //     wait. If it does change, and we go back to sleep,
                //     we'll never wake up. In other words, if done changes
                //     to true between the "if (done) return false;" and the
                //     end of the wait function, we would go back to sleep and
                //     never wake up again because this class would have already
                //     cleaned up
                newMsg.wait(lk, [&]{
                            if (done) return true;
                            if (buf.empty()) return false;
                            uint64_t recentUtime = getMsgUtime(buf.back());
                            if (recentUtime < utime) return false;
                            return true;
                        });
                if (done) return nullptr;
            }

            size_t size = buf.size();

            const T *_m0 = nullptr;
            const T *_m1 = nullptr;

            // The reason why we do a linear search is to support the ability
            // to skip around in logs. We want to support messages with
            // non-monitonically increasing utimes and this is the easiest way.
            // This can be made much faster if needed
            for (size_t i = 0; i < size; ++i) {
                const T* m = buf[i];
                uint64_t mUtime = getMsgUtime(m);

                if (mUtime <= utime && (_m0 == nullptr || mUtime > m0Utime)) {
                    _m0 = m;
                    m0Utime = mUtime;
                }

                if (mUtime >= utime && (_m1 == nullptr || mUtime < m1Utime)) {
                    _m1 = m;
                    m1Utime = mUtime;
                }
            }

            if (_m0 != nullptr) m0 = new T(*_m0);
            if (_m1 != nullptr) m1 = new T(*_m1);

        }

        if (m0 && utime - m0Utime > maxTimeErr_us) {
            delete m0;
            m0 = nullptr;
        }

        if (m1 && m1Utime - utime > maxTimeErr_us) {
            delete m1;
            m1 = nullptr;
        }

        if (m0 && m1) {
            if (m0Utime == m1Utime) {
                delete m1;
                return m0;
            }

            T* elt = interpolate(utime, m0, m0Utime, m1, m1Utime);

            delete m0;
            delete m1;

            return elt;
        }

        if (m0) return m0;
        if (m1) return m1;

        return nullptr;
    }

  private:
    // *****************************************************************************
    // Insanely hacky trick to determine at compile time if a zcmtype has a
    // field called "utime"
    // TODO: I think c++11 has some utilities to make this a bit easier (I have not
    //       looked into them much at all, but worth looking at <type_traits>
    //       and what you can do with things like std::true_type and the like)
    template <typename F> struct hasUtime {
        struct Fallback { void* utime; }; // introduce member name "utime"
        struct Derived : F, Fallback {};

        template <typename C, C> struct ChT;

        template <typename C>
        static uint64_t _utime(ChT<void* Fallback::*, &C::utime>*, const F* msg)
        {
            struct timeval tv;
            gettimeofday(&tv, NULL);
            return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
        };
        template <typename C>
        static uint64_t _utime(void*, ...)
        {
            va_list args;
            va_start(args, 1);
            const F* msg = va_arg(args, const F*);
            va_end(args);
            return msg->utime;
        }

        template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
        template<typename C> static char (&f(...))[2];

        static bool const present = sizeof(f<Derived>(0)) == 2;

        static uint64_t const utime(const F* msg)
        {
            return _utime<Derived>(0,msg);
        }
    };

    template<typename F>
    static inline std::string getType(const F t) { return typeid(t).name(); }

    static inline std::string demangle(std::string name)
    {
        int status = -4; // some arbitrary value to eliminate the compiler warning
        std::unique_ptr<char, void(*)(void*)> res {
            abi::__cxa_demangle(name.c_str(), NULL, NULL, &status),
            std::free
        };
        return (status==0) ? res.get() : name ;
    }

    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o) { }

    template<typename First, typename ...Rest>
    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o, First && first, Rest && ...rest)
    {
        o << std::forward<First>(first);
        __ZCM_PRINT_OBFUSCATE__(o, std::forward<Rest>(rest)...);
    }
    // *****************************************************************************

};

}

#undef ZCM_DEBUG
<commit_msg>Cleaning up memory<commit_after>#pragma once

#include <iostream>
#include <string>
#include <deque>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <typeinfo>
#include <cxxabi.h>
#include <sys/time.h>
#include <stdarg.h>

#include <zcm/zcm-cpp.hpp>

static bool __ZCM_DEBUG_ENABLED__ = (NULL != getenv("ZCM_DEBUG"));
#define ZCM_DEBUG(...) \
    do { \
        if (__ZCM_DEBUG_ENABLED__) \
            __ZCM_PRINT_OBFUSCATE__(std::cout, "ZCM-DEBUG: ", __VA_ARGS__, '\n'); \
    } while(0)

namespace zcm {

template <typename T>
class MessageTracker
{
  public:
    typedef void (*callback)(T* msg, uint64_t utime, void* usr);
    static const bool NONBLOCKING = false;
    static const bool BLOCKING = true;

  protected:
    virtual uint64_t getMsgUtime(const T* msg)
    {
        return hasUtime<T>::utime(msg);
    }

    // The returned value must be "new" in all cases
    virtual T* interpolate(uint64_t utimeTarget,
                           const T* A, uint64_t utimeA,
                           const T* B, uint64_t utimeB)
    {
        return utimeTarget - utimeA < utimeB - utimeTarget ? new T(*A) : new T(*B);
    }

  private:
    zcm::ZCM* zcmLocal = nullptr;

    std::atomic_bool done {false};

    std::deque<T*> buf;
    size_t bufMax;
    std::mutex bufLock;
    std::condition_variable newMsg;
    zcm::Subscription *s;

    std::mutex callbackLock;
    std::condition_variable callbackCv;
    T* callbackMsg = nullptr;
    std::thread *thr = nullptr;
    callback onMsg;
    void* usr;

    uint64_t maxTimeErr_us;

    void callbackThreadFunc()
    {
        std::unique_lock<std::mutex> lk(callbackLock);
        while (!done) {
            callbackCv.wait(lk, [&](){ return callbackMsg || done; });
            if (done) return;
            onMsg(callbackMsg, getMsgUtime(callbackMsg), usr);
            // Intentionally not deleting callbackMsg as it is the
            // responsibility of the callback to delete the memory
            callbackMsg = nullptr;
        }
    }

    void handle(const zcm::ReceiveBuffer* rbuf, const std::string& chan, const T* _msg)
    {
        if (done) return;

        T* tmp = new T(*_msg);

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (buf.size() == bufMax){
                T* tmp = buf.front();
                delete tmp;
                buf.pop_front();
            }

            while (!buf.empty()) {
                if (getMsgUtime(buf.front()) + maxTimeErr_us > getMsgUtime(_msg)) break;
                T* tmp = buf.front();
                delete tmp;
                buf.pop_front();
            }

            buf.push_back(tmp);
        }
        newMsg.notify_all();

        if (callbackLock.try_lock()) {
            if (callbackMsg) delete callbackMsg;
            callbackMsg = new T(*_msg);
            callbackLock.unlock();
            callbackCv.notify_all();
        }
    }

    MessageTracker() {}

  public:
    MessageTracker(zcm::ZCM* zcmLocal, std::string channel,
                   double maxTimeErr = 0.25, size_t maxMsgs = 1,
                   callback onMsg = nullptr, void* usr = nullptr)
        : zcmLocal(zcmLocal), maxTimeErr_us(maxTimeErr * 1e6), onMsg(onMsg), usr(usr)
    {
        if (hasUtime<T>::present == true) {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using 'utime' field of zcmtype ", name);
        } else {
            T tmp;
            std::string name = demangle(getType(tmp));
            ZCM_DEBUG("Message trackers using local system receive utime for ",
                      "tracking zcmtype ", name);
        }

        bufMax = maxMsgs;

        if (onMsg != nullptr) thr = new std::thread(&MessageTracker<T>::callbackThreadFunc, this);
        s = zcmLocal->subscribe(channel, &MessageTracker<T>::handle, this);
    }

    virtual ~MessageTracker()
    {
        zcmLocal->unsubscribe(s);
        done = true;
        newMsg.notify_all();
        callbackCv.notify_all();
        if (thr) {
            thr->join();
            delete thr;
        }
        while (!buf.empty()) {
            T* tmp = buf.front();
            delete tmp;
            buf.pop_front();
        }
    }

    // You must free the memory returned here
    virtual T* get(bool blocking = NONBLOCKING)
    {
        T* ret = nullptr;

        {
            std::unique_lock<std::mutex> lk(bufLock);
            if (blocking == BLOCKING) {
                if (buf.empty())
                    newMsg.wait(lk, [&]{ return !buf.empty() || done; });
                if (done) return nullptr;
            }
            if (!buf.empty())
                ret = new T(*buf.back());
        }

        return ret;
    }

    // This may return nullptr even in the blocking case
    // TODO: Should consider how to allow the user to ask for an extrapolated
    //       message if bracketted messages arent available
    virtual T* get(uint64_t utime, bool blocking = NONBLOCKING)
    {
        T *m0 = nullptr, *m1 = nullptr; // two poses bracketing the desired utime
        uint64_t m0Utime, m1Utime;

        {
            std::unique_lock<std::mutex> lk(bufLock);

            if (blocking == BLOCKING) {
                // XXX This is technically not okay. "done" can't be an
                //     atomic as it can change after we've checked it in the
                //     wait. If it does change, and we go back to sleep,
                //     we'll never wake up. In other words, if done changes
                //     to true between the "if (done) return false;" and the
                //     end of the wait function, we would go back to sleep and
                //     never wake up again because this class would have already
                //     cleaned up
                newMsg.wait(lk, [&]{
                            if (done) return true;
                            if (buf.empty()) return false;
                            uint64_t recentUtime = getMsgUtime(buf.back());
                            if (recentUtime < utime) return false;
                            return true;
                        });
                if (done) return nullptr;
            }

            size_t size = buf.size();

            const T *_m0 = nullptr;
            const T *_m1 = nullptr;

            // The reason why we do a linear search is to support the ability
            // to skip around in logs. We want to support messages with
            // non-monitonically increasing utimes and this is the easiest way.
            // This can be made much faster if needed
            for (size_t i = 0; i < size; ++i) {
                const T* m = buf[i];
                uint64_t mUtime = getMsgUtime(m);

                if (mUtime <= utime && (_m0 == nullptr || mUtime > m0Utime)) {
                    _m0 = m;
                    m0Utime = mUtime;
                }

                if (mUtime >= utime && (_m1 == nullptr || mUtime < m1Utime)) {
                    _m1 = m;
                    m1Utime = mUtime;
                }
            }

            if (_m0 != nullptr) m0 = new T(*_m0);
            if (_m1 != nullptr) m1 = new T(*_m1);

        }

        if (m0 && utime - m0Utime > maxTimeErr_us) {
            delete m0;
            m0 = nullptr;
        }

        if (m1 && m1Utime - utime > maxTimeErr_us) {
            delete m1;
            m1 = nullptr;
        }

        if (m0 && m1) {
            if (m0Utime == m1Utime) {
                delete m1;
                return m0;
            }

            T* elt = interpolate(utime, m0, m0Utime, m1, m1Utime);

            delete m0;
            delete m1;

            return elt;
        }

        if (m0) return m0;
        if (m1) return m1;

        return nullptr;
    }

  private:
    // *****************************************************************************
    // Insanely hacky trick to determine at compile time if a zcmtype has a
    // field called "utime"
    // TODO: I think c++11 has some utilities to make this a bit easier (I have not
    //       looked into them much at all, but worth looking at <type_traits>
    //       and what you can do with things like std::true_type and the like)
    template <typename F> struct hasUtime {
        struct Fallback { void* utime; }; // introduce member name "utime"
        struct Derived : F, Fallback {};

        template <typename C, C> struct ChT;

        template <typename C>
        static uint64_t _utime(ChT<void* Fallback::*, &C::utime>*, const F* msg)
        {
            struct timeval tv;
            gettimeofday(&tv, NULL);
            return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;
        };
        template <typename C>
        static uint64_t _utime(void*, ...)
        {
            va_list args;
            va_start(args, 1);
            const F* msg = va_arg(args, const F*);
            va_end(args);
            return msg->utime;
        }

        template<typename C> static char (&f(ChT<int Fallback::*, &C::x>*))[1];
        template<typename C> static char (&f(...))[2];

        static bool const present = sizeof(f<Derived>(0)) == 2;

        static uint64_t const utime(const F* msg)
        {
            return _utime<Derived>(0,msg);
        }
    };

    template<typename F>
    static inline std::string getType(const F t) { return typeid(t).name(); }

    static inline std::string demangle(std::string name)
    {
        int status = -4; // some arbitrary value to eliminate the compiler warning
        std::unique_ptr<char, void(*)(void*)> res {
            abi::__cxa_demangle(name.c_str(), NULL, NULL, &status),
            std::free
        };
        return (status==0) ? res.get() : name ;
    }

    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o) { }

    template<typename First, typename ...Rest>
    static void __ZCM_PRINT_OBFUSCATE__(std::ostream& o, First && first, Rest && ...rest)
    {
        o << std::forward<First>(first);
        __ZCM_PRINT_OBFUSCATE__(o, std::forward<Rest>(rest)...);
    }
    // *****************************************************************************

};

}

#undef ZCM_DEBUG
<|endoftext|>


<commit_before>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "stopwatch.hxx"
#include "AllocatorPtr.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/ToString.hxx"
#include "io/Logger.hxx"
#include "util/WritableBuffer.hxx"

#include <boost/container/static_vector.hpp>

#include <chrono>

#include <time.h>
#include <assert.h>
#include <string.h>
#include <sys/resource.h>

enum {
    STOPWATCH_VERBOSE = 3,
};

struct StopwatchEvent {
    const char *name;

    std::chrono::steady_clock::time_point time;

    explicit StopwatchEvent(const char *_name) noexcept
        :name(_name), time(std::chrono::steady_clock::now()) {}
};

struct Stopwatch {
    AllocatorPtr alloc;

    const char *const name;

    boost::container::static_vector<StopwatchEvent, 16> events;

    /**
     * Our own resource usage, measured when the stopwatch was
     * started.
     */
    struct rusage self;

    Stopwatch(AllocatorPtr _alloc, const char *_name)
        :alloc(_alloc), name(_name) {
        events.emplace_back(name);

        getrusage(RUSAGE_SELF, &self);
    }
};

static bool stopwatch_enabled;

void
stopwatch_enable()
{
    assert(!stopwatch_enabled);

    stopwatch_enabled = true;
}

bool
stopwatch_is_enabled()
{
    return stopwatch_enabled && CheckLogLevel(STOPWATCH_VERBOSE);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, const char *name, const char *suffix)
{
    if (!stopwatch_is_enabled())
        return nullptr;

    if (suffix == nullptr)
        name = alloc.Dup(name);
    else
        name = alloc.Concat(name, suffix);

    constexpr size_t MAX_NAME = 96;
    if (strlen(name) > MAX_NAME)
        name = alloc.DupZ({name, MAX_NAME});

    return alloc.New<Stopwatch>(alloc, name);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, SocketAddress address, const char *suffix)
{
    char buffer[1024];

    if (!stopwatch_is_enabled())
        return nullptr;

    const char *name = ToString(buffer, sizeof(buffer), address, "unknown");
    return stopwatch_new(alloc, name, suffix);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, SocketDescriptor fd, const char *suffix)
{
    if (!stopwatch_is_enabled())
        return nullptr;

    const auto address = fd.GetPeerAddress();
    return address.IsDefined()
        ? stopwatch_new(alloc, address, suffix)
        : stopwatch_new(alloc, "unknown", suffix);
}

void
stopwatch_event(Stopwatch *stopwatch, const char *name)
{
    if (!stopwatch_is_enabled())
        return;

    assert(stopwatch != nullptr);
    assert(name != nullptr);

    if (stopwatch->events.size() >= stopwatch->events.capacity())
        /* array is full, do not record any more events */
        return;

    stopwatch->events.emplace_back(name);
}

static constexpr long
ToLongMs(std::chrono::steady_clock::duration d)
{
    return std::chrono::duration_cast<std::chrono::milliseconds>(d).count();
}

static long
timeval_diff_ms(const struct timeval *a, const struct timeval *b)
{
    return (a->tv_sec - b->tv_sec) * 1000 +
        (a->tv_usec - b->tv_usec) / 1000;
}

template<typename... Args>
static void
AppendFormat(WritableBuffer<char> &buffer, const char *fmt, Args&&... args)
{
    int r = snprintf(buffer.data, buffer.size, fmt, args...);
    if (r > 0)
        buffer.skip_front(std::min(size_t(r), buffer.size - 1));
}

void
stopwatch_dump(const Stopwatch *stopwatch)
{
    struct rusage self;

    if (!stopwatch_is_enabled())
        return;

    assert(stopwatch != nullptr);
    assert(!stopwatch->events.empty());

    if (stopwatch->events.size() < 2)
        /* nothing was recorded (except for the initial event) */
        return;

    char domain[128];
    snprintf(domain, sizeof(domain), "stopwatch %s", stopwatch->name);

    char message[1024];

    WritableBuffer<char> b(message, sizeof(message));

    for (const auto &i : stopwatch->events)
        AppendFormat(b, " %s=%ldms",
                     i.name,
                     ToLongMs(i.time - stopwatch->events.front().time));

    getrusage(RUSAGE_SELF, &self);
    AppendFormat(b, " (beng-proxy=%ld+%ldms)",
                 timeval_diff_ms(&self.ru_utime,
                                 &stopwatch->self.ru_utime),
                 timeval_diff_ms(&self.ru_stime,
                                 &stopwatch->self.ru_stime));

    LogConcat(STOPWATCH_VERBOSE, domain, message);
}
<commit_msg>Stopwatch: move code to Stopwatch methods<commit_after>/*
 * Copyright 2007-2019 Content Management AG
 * All rights reserved.
 *
 * author: Max Kellermann <mk@cm4all.com>
 *
 * 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.
 *
 * 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
 * FOUNDATION 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 "stopwatch.hxx"
#include "AllocatorPtr.hxx"
#include "net/SocketDescriptor.hxx"
#include "net/StaticSocketAddress.hxx"
#include "net/ToString.hxx"
#include "io/Logger.hxx"
#include "util/WritableBuffer.hxx"

#include <boost/container/static_vector.hpp>

#include <chrono>

#include <time.h>
#include <assert.h>
#include <string.h>
#include <sys/resource.h>

enum {
    STOPWATCH_VERBOSE = 3,
};

struct StopwatchEvent {
    const char *name;

    std::chrono::steady_clock::time_point time;

    explicit StopwatchEvent(const char *_name) noexcept
        :name(_name), time(std::chrono::steady_clock::now()) {}
};

struct Stopwatch {
    AllocatorPtr alloc;

    const char *const name;

    boost::container::static_vector<StopwatchEvent, 16> events;

    /**
     * Our own resource usage, measured when the stopwatch was
     * started.
     */
    struct rusage self;

    Stopwatch(AllocatorPtr _alloc, const char *_name)
        :alloc(_alloc), name(_name) {
        events.emplace_back(name);

        getrusage(RUSAGE_SELF, &self);
    }

    void RecordEvent(const char *name) noexcept;

    void Dump() const noexcept;
};

static bool stopwatch_enabled;

void
stopwatch_enable()
{
    assert(!stopwatch_enabled);

    stopwatch_enabled = true;
}

bool
stopwatch_is_enabled()
{
    return stopwatch_enabled && CheckLogLevel(STOPWATCH_VERBOSE);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, const char *name, const char *suffix)
{
    if (!stopwatch_is_enabled())
        return nullptr;

    if (suffix == nullptr)
        name = alloc.Dup(name);
    else
        name = alloc.Concat(name, suffix);

    constexpr size_t MAX_NAME = 96;
    if (strlen(name) > MAX_NAME)
        name = alloc.DupZ({name, MAX_NAME});

    return alloc.New<Stopwatch>(alloc, name);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, SocketAddress address, const char *suffix)
{
    char buffer[1024];

    if (!stopwatch_is_enabled())
        return nullptr;

    const char *name = ToString(buffer, sizeof(buffer), address, "unknown");
    return stopwatch_new(alloc, name, suffix);
}

Stopwatch *
stopwatch_new(AllocatorPtr alloc, SocketDescriptor fd, const char *suffix)
{
    if (!stopwatch_is_enabled())
        return nullptr;

    const auto address = fd.GetPeerAddress();
    return address.IsDefined()
        ? stopwatch_new(alloc, address, suffix)
        : stopwatch_new(alloc, "unknown", suffix);
}

inline void
Stopwatch::RecordEvent(const char *event_name) noexcept
{
    if (events.size() >= events.capacity())
        /* array is full, do not record any more events */
        return;

    events.emplace_back(event_name);
}

void
stopwatch_event(Stopwatch *stopwatch, const char *name)
{
    if (stopwatch != nullptr)
        stopwatch->RecordEvent(name);
}

static constexpr long
ToLongMs(std::chrono::steady_clock::duration d)
{
    return std::chrono::duration_cast<std::chrono::milliseconds>(d).count();
}

static long
timeval_diff_ms(const struct timeval *a, const struct timeval *b)
{
    return (a->tv_sec - b->tv_sec) * 1000 +
        (a->tv_usec - b->tv_usec) / 1000;
}

template<typename... Args>
static void
AppendFormat(WritableBuffer<char> &buffer, const char *fmt, Args&&... args)
{
    int r = snprintf(buffer.data, buffer.size, fmt, args...);
    if (r > 0)
        buffer.skip_front(std::min(size_t(r), buffer.size - 1));
}

inline void
Stopwatch::Dump() const noexcept
{
    assert(!events.empty());

    if (events.size() < 2)
        /* nothing was recorded (except for the initial event) */
        return;

    char domain[128];
    snprintf(domain, sizeof(domain), "stopwatch %s", name);

    char message[1024];

    WritableBuffer<char> b(message, sizeof(message));

    for (const auto &i : events)
        AppendFormat(b, " %s=%ldms",
                     i.name,
                     ToLongMs(i.time - events.front().time));

    struct rusage new_self;
    getrusage(RUSAGE_SELF, &new_self);
    AppendFormat(b, " (beng-proxy=%ld+%ldms)",
                 timeval_diff_ms(&new_self.ru_utime, &self.ru_utime),
                 timeval_diff_ms(&new_self.ru_stime, &self.ru_stime));

    LogConcat(STOPWATCH_VERBOSE, domain, message);
}

void
stopwatch_dump(const Stopwatch *stopwatch)
{
    if (stopwatch != nullptr)
        stopwatch->Dump();
}
<|endoftext|>


<commit_before><commit_msg>bad call to Init() TBR(cmasone)<commit_after><|endoftext|>


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

#include "chrome/browser/extensions/extension_dom_ui.h"

#include <set>

#include "net/base/file_stream.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/bindings_policy.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/url_constants.h"
#include "gfx/codec/png_codec.h"
#include "gfx/favicon_size.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace {

// De-dupes the items in |list|. Assumes the values are strings.
void CleanUpDuplicates(ListValue* list) {
  std::set<std::string> seen_values;

  // Loop backwards as we may be removing items.
  for (size_t i = list->GetSize() - 1; (i + 1) > 0; --i) {
    std::string value;
    if (!list->GetString(i, &value)) {
      NOTREACHED();
      continue;
    }

    if (seen_values.find(value) == seen_values.end())
      seen_values.insert(value);
    else
      list->Remove(i, NULL);
  }
}

// Helper class that is used to track the loading of the favicon of an
// extension.
class ExtensionDOMUIImageLoadingTracker : public ImageLoadingTracker::Observer {
 public:
  ExtensionDOMUIImageLoadingTracker(Profile* profile,
                                    FaviconService::GetFaviconRequest* request,
                                    const GURL& page_url)
      : ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
        request_(request),
        extension_(NULL) {
    // Even when the extensions service is enabled by default, it's still
    // disabled in incognito mode.
    ExtensionsService* service = profile->GetExtensionsService();
    if (service)
      extension_ = service->GetExtensionByURL(page_url);
  }

  void Init() {
    if (extension_) {
      ExtensionResource icon_resource =
          extension_->GetIconPath(Extension::EXTENSION_ICON_BITTY);

      tracker_.LoadImage(extension_, icon_resource,
                         gfx::Size(kFavIconSize, kFavIconSize),
                         ImageLoadingTracker::DONT_CACHE);
    } else {
      ForwardResult(NULL);
    }
  }

  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
                             int index) {
    if (image) {
      std::vector<unsigned char> image_data;
      if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_data)) {
        NOTREACHED() << "Could not encode extension favicon";
      }
      ForwardResult(RefCountedBytes::TakeVector(&image_data));
    } else {
      ForwardResult(NULL);
    }
  }

 private:
  ~ExtensionDOMUIImageLoadingTracker() {}

  // Forwards the result on the request. If no favicon was available then
  // |icon_data| may be backed by NULL. Once the result has been forwarded the
  // instance is deleted.
  void ForwardResult(scoped_refptr<RefCountedMemory> icon_data) {
    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
    request_->ForwardResultAsync(
        FaviconService::FaviconDataCallback::TupleType(request_->handle(),
            know_icon, icon_data, false, GURL()));
    delete this;
  }

  ImageLoadingTracker tracker_;
  scoped_refptr<FaviconService::GetFaviconRequest> request_;
  Extension* extension_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDOMUIImageLoadingTracker);
};

}  // namespace

const char ExtensionDOMUI::kExtensionURLOverrides[] =
    "extensions.chrome_url_overrides";

ExtensionDOMUI::ExtensionDOMUI(TabContents* tab_contents)
    : DOMUI(tab_contents) {
  should_hide_url_ = true;
  bindings_ = BindingsPolicy::EXTENSION;

  // For chrome:// overrides, some of the defaults are a little different.
  GURL url = tab_contents->GetURL();
  if (url.SchemeIs(chrome::kChromeUIScheme) &&
      url.host() == chrome::kChromeUINewTabHost) {
    focus_location_bar_by_default_ = true;
  }
}

void ExtensionDOMUI::ResetExtensionFunctionDispatcher(
    RenderViewHost* render_view_host) {
  // Use the NavigationController to get the URL rather than the TabContents
  // since this is the real underlying URL (see HandleChromeURLOverride).
  NavigationController& controller = tab_contents()->controller();
  const GURL& url = controller.GetActiveEntry()->url();
  extension_function_dispatcher_.reset(
      ExtensionFunctionDispatcher::Create(render_view_host, this, url));
  DCHECK(extension_function_dispatcher_.get());
}

void ExtensionDOMUI::ResetExtensionBookmarkManagerEventRouter() {
  // Hack: A few things we specialize just for the bookmark manager.
  if (extension_function_dispatcher_->extension_id() ==
      extension_misc::kBookmarkManagerId) {
    extension_bookmark_manager_event_router_.reset(
        new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents()));

    link_transition_type_ = PageTransition::AUTO_BOOKMARK;
  }
}

void ExtensionDOMUI::RenderViewCreated(RenderViewHost* render_view_host) {
  ResetExtensionFunctionDispatcher(render_view_host);
  ResetExtensionBookmarkManagerEventRouter();
}

void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) {
  ResetExtensionFunctionDispatcher(render_view_host);
  ResetExtensionBookmarkManagerEventRouter();
}

void ExtensionDOMUI::ProcessDOMUIMessage(
    const ViewHostMsg_DomMessage_Params& params) {
  extension_function_dispatcher_->HandleRequest(params);
}

Browser* ExtensionDOMUI::GetBrowser() const {
  // TODO(beng): This is an improper direct dependency on Browser. Route this
  // through some sort of delegate.
  return BrowserList::FindBrowserWithProfile(DOMUI::GetProfile());
}

Profile* ExtensionDOMUI::GetProfile() {
  return DOMUI::GetProfile();
}

gfx::NativeWindow ExtensionDOMUI::GetCustomFrameNativeWindow() {
  if (GetBrowser())
    return NULL;

  // If there was no browser associated with the function dispatcher delegate,
  // then this DOMUI may be hosted in an ExternalTabContainer, and a framing
  // window will be accessible through the tab_contents.
  TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
  if (tab_contents_delegate)
    return tab_contents_delegate->GetFrameNativeWindow();
  else
    return NULL;
}

gfx::NativeView ExtensionDOMUI::GetNativeViewOfHost() {
  return tab_contents()->GetRenderWidgetHostView()->GetNativeView();
}

////////////////////////////////////////////////////////////////////////////////
// chrome:// URL overrides

// static
void ExtensionDOMUI::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterDictionaryPref(kExtensionURLOverrides);
}

// static
bool ExtensionDOMUI::HandleChromeURLOverride(GURL* url, Profile* profile) {
  if (!url->SchemeIs(chrome::kChromeUIScheme))
    return false;

  // We can't handle chrome-extension URLs in incognito mode.
  if (profile->IsOffTheRecord())
    return false;

  const DictionaryValue* overrides =
      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
  std::string page = url->host();
  ListValue* url_list;
  if (!overrides || !overrides->GetList(page, &url_list))
    return false;

  ExtensionsService* service = profile->GetExtensionsService();
  if (!service->is_ready()) {
    // TODO(erikkay) So far, it looks like extensions load before the new tab
    // page.  I don't know if we have anything that enforces this, so add this
    // check for safety.
    NOTREACHED() << "Chrome URL override requested before extensions loaded";
    return false;
  }

  while (url_list->GetSize()) {
    Value* val;
    url_list->Get(0, &val);

    // Verify that the override value is good.  If not, unregister it and find
    // the next one.
    std::string override;
    if (!val->GetAsString(&override)) {
      NOTREACHED();
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }
    GURL extension_url(override);
    if (!extension_url.is_valid()) {
      NOTREACHED();
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }

    // Verify that the extension that's being referred to actually exists.
    Extension* extension = service->GetExtensionByURL(extension_url);
    if (!extension) {
      // This can currently happen if you use --load-extension one run, and
      // then don't use it the next.  It could also happen if an extension
      // were deleted directly from the filesystem, etc.
      LOG(WARNING) << "chrome URL override present for non-existant extension";
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }

    *url = extension_url;
    return true;
  }
  return false;
}

// static
void ExtensionDOMUI::RegisterChromeURLOverrides(
    Profile* profile, const Extension::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;

  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);

  // For each override provided by the extension, add it to the front of
  // the override list if it's not already in the list.
  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
  for (; iter != overrides.end(); ++iter) {
    const std::string& key = iter->first;
    ListValue* page_overrides;
    if (!all_overrides->GetList(key, &page_overrides)) {
      page_overrides = new ListValue();
      all_overrides->Set(key, page_overrides);
    } else {
      CleanUpDuplicates(page_overrides);

      // Verify that the override isn't already in the list.
      ListValue::iterator i = page_overrides->begin();
      for (; i != page_overrides->end(); ++i) {
        std::string override_val;
        if (!(*i)->GetAsString(&override_val)) {
          NOTREACHED();
          continue;
        }
        if (override_val == iter->second.spec())
          break;
      }
      // This value is already in the list, leave it alone.
      if (i != page_overrides->end())
        continue;
    }
    // Insert the override at the front of the list.  Last registered override
    // wins.
    page_overrides->Insert(0, new StringValue(iter->second.spec()));
  }
}

// static
void ExtensionDOMUI::UnregisterAndReplaceOverride(const std::string& page,
    Profile* profile, ListValue* list, Value* override) {
  int index = list->Remove(*override);
  if (index == 0) {
    // This is the active override, so we need to find all existing
    // tabs for this override and get them to reload the original URL.
    for (TabContentsIterator iterator; !iterator.done(); ++iterator) {
      TabContents* tab = *iterator;
      if (tab->profile() != profile)
        continue;

      GURL url = tab->GetURL();
      if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page)
        continue;

      // Don't use Reload() since |url| isn't the same as the internal URL
      // that NavigationController has.
      tab->controller().LoadURL(url, url, PageTransition::RELOAD);
    }
  }
}

// static
void ExtensionDOMUI::UnregisterChromeURLOverride(const std::string& page,
    Profile* profile, Value* override) {
  if (!override)
    return;
  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);
  ListValue* page_overrides;
  if (!all_overrides->GetList(page, &page_overrides)) {
    // If it's being unregistered, it should already be in the list.
    NOTREACHED();
    return;
  } else {
    UnregisterAndReplaceOverride(page, profile, page_overrides, override);
  }
}

// static
void ExtensionDOMUI::UnregisterChromeURLOverrides(
    Profile* profile, const Extension::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;
  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);
  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
  for (; iter != overrides.end(); ++iter) {
    const std::string& page = iter->first;
    ListValue* page_overrides;
    if (!all_overrides->GetList(page, &page_overrides)) {
      // If it's being unregistered, it should already be in the list.
      NOTREACHED();
      continue;
    } else {
      StringValue override(iter->second.spec());
      UnregisterAndReplaceOverride(iter->first, profile,
                                   page_overrides, &override);
    }
  }
}

// static
void ExtensionDOMUI::GetFaviconForURL(Profile* profile,
    FaviconService::GetFaviconRequest* request, const GURL& page_url) {
  // tracker deletes itself when done.
  ExtensionDOMUIImageLoadingTracker* tracker =
      new ExtensionDOMUIImageLoadingTracker(profile, request, page_url);
  tracker->Init();
}
<commit_msg>Add external host binding permission for Extension DOMUI.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/extensions/extension_dom_ui.h"

#include <set>

#include "net/base/file_stream.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/extensions/extension_bookmark_manager_api.h"
#include "chrome/browser/extensions/extensions_service.h"
#include "chrome/browser/extensions/image_loading_tracker.h"
#include "chrome/browser/pref_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_widget_host_view.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/bindings_policy.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/page_transition_types.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/extension_resource.h"
#include "chrome/common/url_constants.h"
#include "gfx/codec/png_codec.h"
#include "gfx/favicon_size.h"
#include "third_party/skia/include/core/SkBitmap.h"

namespace {

// De-dupes the items in |list|. Assumes the values are strings.
void CleanUpDuplicates(ListValue* list) {
  std::set<std::string> seen_values;

  // Loop backwards as we may be removing items.
  for (size_t i = list->GetSize() - 1; (i + 1) > 0; --i) {
    std::string value;
    if (!list->GetString(i, &value)) {
      NOTREACHED();
      continue;
    }

    if (seen_values.find(value) == seen_values.end())
      seen_values.insert(value);
    else
      list->Remove(i, NULL);
  }
}

// Helper class that is used to track the loading of the favicon of an
// extension.
class ExtensionDOMUIImageLoadingTracker : public ImageLoadingTracker::Observer {
 public:
  ExtensionDOMUIImageLoadingTracker(Profile* profile,
                                    FaviconService::GetFaviconRequest* request,
                                    const GURL& page_url)
      : ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
        request_(request),
        extension_(NULL) {
    // Even when the extensions service is enabled by default, it's still
    // disabled in incognito mode.
    ExtensionsService* service = profile->GetExtensionsService();
    if (service)
      extension_ = service->GetExtensionByURL(page_url);
  }

  void Init() {
    if (extension_) {
      ExtensionResource icon_resource =
          extension_->GetIconPath(Extension::EXTENSION_ICON_BITTY);

      tracker_.LoadImage(extension_, icon_resource,
                         gfx::Size(kFavIconSize, kFavIconSize),
                         ImageLoadingTracker::DONT_CACHE);
    } else {
      ForwardResult(NULL);
    }
  }

  virtual void OnImageLoaded(SkBitmap* image, ExtensionResource resource,
                             int index) {
    if (image) {
      std::vector<unsigned char> image_data;
      if (!gfx::PNGCodec::EncodeBGRASkBitmap(*image, false, &image_data)) {
        NOTREACHED() << "Could not encode extension favicon";
      }
      ForwardResult(RefCountedBytes::TakeVector(&image_data));
    } else {
      ForwardResult(NULL);
    }
  }

 private:
  ~ExtensionDOMUIImageLoadingTracker() {}

  // Forwards the result on the request. If no favicon was available then
  // |icon_data| may be backed by NULL. Once the result has been forwarded the
  // instance is deleted.
  void ForwardResult(scoped_refptr<RefCountedMemory> icon_data) {
    bool know_icon = icon_data.get() != NULL && icon_data->size() > 0;
    request_->ForwardResultAsync(
        FaviconService::FaviconDataCallback::TupleType(request_->handle(),
            know_icon, icon_data, false, GURL()));
    delete this;
  }

  ImageLoadingTracker tracker_;
  scoped_refptr<FaviconService::GetFaviconRequest> request_;
  Extension* extension_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionDOMUIImageLoadingTracker);
};

}  // namespace

const char ExtensionDOMUI::kExtensionURLOverrides[] =
    "extensions.chrome_url_overrides";

ExtensionDOMUI::ExtensionDOMUI(TabContents* tab_contents)
    : DOMUI(tab_contents) {
  should_hide_url_ = true;
  bindings_ = BindingsPolicy::EXTENSION;
  // Bind externalHost to Extension DOMUI loaded in Chrome Frame.
  const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
  if (browser_command_line.HasSwitch(switches::kChromeFrame))
    bindings_ |= BindingsPolicy::EXTERNAL_HOST;
  // For chrome:// overrides, some of the defaults are a little different.
  GURL url = tab_contents->GetURL();
  if (url.SchemeIs(chrome::kChromeUIScheme) &&
      url.host() == chrome::kChromeUINewTabHost) {
    focus_location_bar_by_default_ = true;
  }
}

void ExtensionDOMUI::ResetExtensionFunctionDispatcher(
    RenderViewHost* render_view_host) {
  // Use the NavigationController to get the URL rather than the TabContents
  // since this is the real underlying URL (see HandleChromeURLOverride).
  NavigationController& controller = tab_contents()->controller();
  const GURL& url = controller.GetActiveEntry()->url();
  extension_function_dispatcher_.reset(
      ExtensionFunctionDispatcher::Create(render_view_host, this, url));
  DCHECK(extension_function_dispatcher_.get());
}

void ExtensionDOMUI::ResetExtensionBookmarkManagerEventRouter() {
  // Hack: A few things we specialize just for the bookmark manager.
  if (extension_function_dispatcher_->extension_id() ==
      extension_misc::kBookmarkManagerId) {
    extension_bookmark_manager_event_router_.reset(
        new ExtensionBookmarkManagerEventRouter(GetProfile(), tab_contents()));

    link_transition_type_ = PageTransition::AUTO_BOOKMARK;
  }
}

void ExtensionDOMUI::RenderViewCreated(RenderViewHost* render_view_host) {
  ResetExtensionFunctionDispatcher(render_view_host);
  ResetExtensionBookmarkManagerEventRouter();
}

void ExtensionDOMUI::RenderViewReused(RenderViewHost* render_view_host) {
  ResetExtensionFunctionDispatcher(render_view_host);
  ResetExtensionBookmarkManagerEventRouter();
}

void ExtensionDOMUI::ProcessDOMUIMessage(
    const ViewHostMsg_DomMessage_Params& params) {
  extension_function_dispatcher_->HandleRequest(params);
}

Browser* ExtensionDOMUI::GetBrowser() const {
  // TODO(beng): This is an improper direct dependency on Browser. Route this
  // through some sort of delegate.
  return BrowserList::FindBrowserWithProfile(DOMUI::GetProfile());
}

Profile* ExtensionDOMUI::GetProfile() {
  return DOMUI::GetProfile();
}

gfx::NativeWindow ExtensionDOMUI::GetCustomFrameNativeWindow() {
  if (GetBrowser())
    return NULL;

  // If there was no browser associated with the function dispatcher delegate,
  // then this DOMUI may be hosted in an ExternalTabContainer, and a framing
  // window will be accessible through the tab_contents.
  TabContentsDelegate* tab_contents_delegate = tab_contents()->delegate();
  if (tab_contents_delegate)
    return tab_contents_delegate->GetFrameNativeWindow();
  else
    return NULL;
}

gfx::NativeView ExtensionDOMUI::GetNativeViewOfHost() {
  return tab_contents()->GetRenderWidgetHostView()->GetNativeView();
}

////////////////////////////////////////////////////////////////////////////////
// chrome:// URL overrides

// static
void ExtensionDOMUI::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterDictionaryPref(kExtensionURLOverrides);
}

// static
bool ExtensionDOMUI::HandleChromeURLOverride(GURL* url, Profile* profile) {
  if (!url->SchemeIs(chrome::kChromeUIScheme))
    return false;

  // We can't handle chrome-extension URLs in incognito mode.
  if (profile->IsOffTheRecord())
    return false;

  const DictionaryValue* overrides =
      profile->GetPrefs()->GetDictionary(kExtensionURLOverrides);
  std::string page = url->host();
  ListValue* url_list;
  if (!overrides || !overrides->GetList(page, &url_list))
    return false;

  ExtensionsService* service = profile->GetExtensionsService();
  if (!service->is_ready()) {
    // TODO(erikkay) So far, it looks like extensions load before the new tab
    // page.  I don't know if we have anything that enforces this, so add this
    // check for safety.
    NOTREACHED() << "Chrome URL override requested before extensions loaded";
    return false;
  }

  while (url_list->GetSize()) {
    Value* val;
    url_list->Get(0, &val);

    // Verify that the override value is good.  If not, unregister it and find
    // the next one.
    std::string override;
    if (!val->GetAsString(&override)) {
      NOTREACHED();
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }
    GURL extension_url(override);
    if (!extension_url.is_valid()) {
      NOTREACHED();
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }

    // Verify that the extension that's being referred to actually exists.
    Extension* extension = service->GetExtensionByURL(extension_url);
    if (!extension) {
      // This can currently happen if you use --load-extension one run, and
      // then don't use it the next.  It could also happen if an extension
      // were deleted directly from the filesystem, etc.
      LOG(WARNING) << "chrome URL override present for non-existant extension";
      UnregisterChromeURLOverride(page, profile, val);
      continue;
    }

    *url = extension_url;
    return true;
  }
  return false;
}

// static
void ExtensionDOMUI::RegisterChromeURLOverrides(
    Profile* profile, const Extension::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;

  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);

  // For each override provided by the extension, add it to the front of
  // the override list if it's not already in the list.
  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
  for (; iter != overrides.end(); ++iter) {
    const std::string& key = iter->first;
    ListValue* page_overrides;
    if (!all_overrides->GetList(key, &page_overrides)) {
      page_overrides = new ListValue();
      all_overrides->Set(key, page_overrides);
    } else {
      CleanUpDuplicates(page_overrides);

      // Verify that the override isn't already in the list.
      ListValue::iterator i = page_overrides->begin();
      for (; i != page_overrides->end(); ++i) {
        std::string override_val;
        if (!(*i)->GetAsString(&override_val)) {
          NOTREACHED();
          continue;
        }
        if (override_val == iter->second.spec())
          break;
      }
      // This value is already in the list, leave it alone.
      if (i != page_overrides->end())
        continue;
    }
    // Insert the override at the front of the list.  Last registered override
    // wins.
    page_overrides->Insert(0, new StringValue(iter->second.spec()));
  }
}

// static
void ExtensionDOMUI::UnregisterAndReplaceOverride(const std::string& page,
    Profile* profile, ListValue* list, Value* override) {
  int index = list->Remove(*override);
  if (index == 0) {
    // This is the active override, so we need to find all existing
    // tabs for this override and get them to reload the original URL.
    for (TabContentsIterator iterator; !iterator.done(); ++iterator) {
      TabContents* tab = *iterator;
      if (tab->profile() != profile)
        continue;

      GURL url = tab->GetURL();
      if (!url.SchemeIs(chrome::kChromeUIScheme) || url.host() != page)
        continue;

      // Don't use Reload() since |url| isn't the same as the internal URL
      // that NavigationController has.
      tab->controller().LoadURL(url, url, PageTransition::RELOAD);
    }
  }
}

// static
void ExtensionDOMUI::UnregisterChromeURLOverride(const std::string& page,
    Profile* profile, Value* override) {
  if (!override)
    return;
  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);
  ListValue* page_overrides;
  if (!all_overrides->GetList(page, &page_overrides)) {
    // If it's being unregistered, it should already be in the list.
    NOTREACHED();
    return;
  } else {
    UnregisterAndReplaceOverride(page, profile, page_overrides, override);
  }
}

// static
void ExtensionDOMUI::UnregisterChromeURLOverrides(
    Profile* profile, const Extension::URLOverrideMap& overrides) {
  if (overrides.empty())
    return;
  PrefService* prefs = profile->GetPrefs();
  DictionaryValue* all_overrides =
      prefs->GetMutableDictionary(kExtensionURLOverrides);
  Extension::URLOverrideMap::const_iterator iter = overrides.begin();
  for (; iter != overrides.end(); ++iter) {
    const std::string& page = iter->first;
    ListValue* page_overrides;
    if (!all_overrides->GetList(page, &page_overrides)) {
      // If it's being unregistered, it should already be in the list.
      NOTREACHED();
      continue;
    } else {
      StringValue override(iter->second.spec());
      UnregisterAndReplaceOverride(iter->first, profile,
                                   page_overrides, &override);
    }
  }
}

// static
void ExtensionDOMUI::GetFaviconForURL(Profile* profile,
    FaviconService::GetFaviconRequest* request, const GURL& page_url) {
  // tracker deletes itself when done.
  ExtensionDOMUIImageLoadingTracker* tracker =
      new ExtensionDOMUIImageLoadingTracker(profile, request, page_url);
  tracker->Init();
}
<|endoftext|>


<commit_before>#include <cstdio>
#include <cctype>
#include <climits>
#include <cstring>

void EmbedFile(FILE *cppFile, FILE *hFile, const char *inputFileName)
{
	char baseName[LINE_MAX];
	const char *n = inputFileName;
	size_t j = 0;
	while ((*n != '\0') && (j < (LINE_MAX - 1)))
	{
		const char c = *n++;
		baseName[j++] = isalnum(c) ? toupper(c) : '_';
	}
	baseName[j] = '\0';

	if (hFile != nullptr)
	{
		fprintf(hFile, "extern const Bond::FileData %s;\n", baseName);
	}

	if (cppFile != nullptr)
	{
		const unsigned BUFFER_SIZE = 16;
		unsigned char buffer[BUFFER_SIZE];
		FILE *inputFile = fopen(inputFileName, "rb");
		if (inputFile != nullptr)
		{
			fprintf(cppFile, "extern const uint8_t %s_DATA[] =\n{\n", baseName);

			while (!feof(inputFile))
			{
				const size_t numBytes = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, inputFile);

				if (numBytes > 0)
				{
					for (size_t i = 0; i < numBytes; ++i)
					{
						fprintf(cppFile, "%c0x%02X,", (i > 0) ? ' ' : '\t', buffer[i]);
					}
					fprintf(cppFile, "\n");
				}
			}

			fprintf(cppFile, "};\n\nextern const Bond::FileData %s(%s_DATA, sizeof(%s_DATA));\n\n\n", baseName, baseName, baseName);
			fclose(inputFile);
		}
	}
}

int main(int argc, const char *argv[])
{
	const size_t MAX_ENTRIES = 256;
	const char *cppFileName = nullptr;
	const char *hFileName = nullptr;
	const char *inputFileNames[MAX_ENTRIES];
	size_t numInputFiles = 0;

	bool error = false;
	for (int i = 1; i < argc; ++i)
	{
		if (strcmp(argv[i], "-c") == 0)
		{
			if (++i < argc)
			{
				cppFileName = argv[i];
			}
			else
			{
				fprintf(stderr, "Missing argument to -c\n");
				error = true;
			}
		}
		else if (strcmp(argv[i], "-h") == 0)
		{
			if (++i < argc)
			{
				hFileName = argv[i];
			}
			else
			{
				fprintf(stderr, "Missing argument to -h\n");
				error = true;
			}
		}
		else if (argv[i][0] == '-')
		{
			fprintf(stderr, "Unknown option '%s'\n", argv[i]);
			error = true;
		}
		else if (numInputFiles < MAX_ENTRIES)
		{
			inputFileNames[numInputFiles++] = argv[i];
		}
	}

	if (error)
	{
		return 1;
	}

	FILE *cppFile = nullptr;
	FILE *hFile = nullptr;

	if (cppFileName != nullptr)
	{
		cppFile = fopen(cppFileName, "w");
	}

	if (hFileName != nullptr)
	{
		hFile = fopen(hFileName, "w");
	}

	for (size_t i = 0; i < numInputFiles; ++i)
	{
		EmbedFile(cppFile, hFile, inputFileNames[i]);
	}

	fclose(cppFile);
	fclose(hFile);

	return 0;
}
<commit_msg>Removed executable bit on a source file.<commit_after>#include <cstdio>
#include <cctype>
#include <climits>
#include <cstring>

void EmbedFile(FILE *cppFile, FILE *hFile, const char *inputFileName)
{
	char baseName[LINE_MAX];
	const char *n = inputFileName;
	size_t j = 0;
	while ((*n != '\0') && (j < (LINE_MAX - 1)))
	{
		const char c = *n++;
		baseName[j++] = isalnum(c) ? toupper(c) : '_';
	}
	baseName[j] = '\0';

	if (hFile != nullptr)
	{
		fprintf(hFile, "extern const Bond::FileData %s;\n", baseName);
	}

	if (cppFile != nullptr)
	{
		const unsigned BUFFER_SIZE = 16;
		unsigned char buffer[BUFFER_SIZE];
		FILE *inputFile = fopen(inputFileName, "rb");
		if (inputFile != nullptr)
		{
			fprintf(cppFile, "extern const uint8_t %s_DATA[] =\n{\n", baseName);

			while (!feof(inputFile))
			{
				const size_t numBytes = fread(buffer, sizeof(unsigned char), BUFFER_SIZE, inputFile);

				if (numBytes > 0)
				{
					for (size_t i = 0; i < numBytes; ++i)
					{
						fprintf(cppFile, "%c0x%02X,", (i > 0) ? ' ' : '\t', buffer[i]);
					}
					fprintf(cppFile, "\n");
				}
			}

			fprintf(cppFile, "};\n\nextern const Bond::FileData %s(%s_DATA, sizeof(%s_DATA));\n\n\n", baseName, baseName, baseName);
			fclose(inputFile);
		}
	}
}

int main(int argc, const char *argv[])
{
	const size_t MAX_ENTRIES = 256;
	const char *cppFileName = nullptr;
	const char *hFileName = nullptr;
	const char *inputFileNames[MAX_ENTRIES];
	size_t numInputFiles = 0;

	bool error = false;
	for (int i = 1; i < argc; ++i)
	{
		if (strcmp(argv[i], "-c") == 0)
		{
			if (++i < argc)
			{
				cppFileName = argv[i];
			}
			else
			{
				fprintf(stderr, "Missing argument to -c\n");
				error = true;
			}
		}
		else if (strcmp(argv[i], "-h") == 0)
		{
			if (++i < argc)
			{
				hFileName = argv[i];
			}
			else
			{
				fprintf(stderr, "Missing argument to -h\n");
				error = true;
			}
		}
		else if (argv[i][0] == '-')
		{
			fprintf(stderr, "Unknown option '%s'\n", argv[i]);
			error = true;
		}
		else if (numInputFiles < MAX_ENTRIES)
		{
			inputFileNames[numInputFiles++] = argv[i];
		}
	}

	if (error)
	{
		return 1;
	}

	FILE *cppFile = nullptr;
	FILE *hFile = nullptr;

	if (cppFileName != nullptr)
	{
		cppFile = fopen(cppFileName, "w");
	}

	if (hFileName != nullptr)
	{
		hFile = fopen(hFileName, "w");
	}

	for (size_t i = 0; i < numInputFiles; ++i)
	{
		EmbedFile(cppFile, hFile, inputFileNames[i]);
	}

	fclose(cppFile);
	fclose(hFile);

	return 0;
}
<|endoftext|>


<commit_before>#include "physics/Body.h"

#include "physics/Physics.h"

using fei::Body;

Body::Body()
: _body(nullptr),
  _type(Type::DYNAMIC),
  _tag(0),
  _destroyed(false)
{
}

Body::Body(b2Body* b2bd, Type tp)
: _body(b2bd),
  _type(tp),
  _tag(0),
  _destroyed(false)
{
	_body->SetUserData(this);
}

void Body::setBody(b2Body* b2bd)
{
	_body = b2bd;
	_body->SetUserData(this);
}

const fei::Vec2 Body::getPosition() const
{
	auto b2v = _body->GetPosition();
	auto vec = fei::Vec2(b2v.x, b2v.y);
	return Physics::getInstance()->physicsToRender(vec);
}

float Body::getAngle() const
{
	return _body->GetAngle();
}

void Body::setSpeed(const fei::Vec2& sp)
{
	auto vec = Physics::getInstance()->renderToPhysics(sp);
	_body->SetLinearVelocity(b2Vec2(vec.x, vec.y));
}

const fei::Vec2 Body::getSpeed()
{
	auto vec = _body->GetLinearVelocity();
	auto ret = Physics::getInstance()->physicsToRender(fei::Vec2(vec.x, vec.y));
	return ret;
}

void Body::setTag(int tag)
{
	_tag = tag;
}

b2Fixture* Body::createFixture(const fei::Shape* shape)
{
	float density = 1.0f;
	if (Type::STATIC == _type) {
		density = 0.0f;
	}
	auto *b2shape = Physics::ShapeToB2Shape(shape);
	auto fixture = _body->CreateFixture(b2shape, density);
	if (b2shape) {
		delete b2shape;
	}
	return fixture;
}

const std::vector<b2Fixture*> Body::createFixture(const std::vector<fei::Shape*>& shapeList)
{
	std::vector<b2Fixture*> result;
	for (auto shape : shapeList) {
		result.push_back(createFixture(shape));
	}
	return result;
}

const std::vector<b2Fixture*> Body::createFixture(const fei::Polygon& poly)
{
	return createFixture(poly.box2dDecomposition());
}

const std::vector<b2Fixture*> Body::createFixture(const std::vector<fei::Polygon>& polyList)
{
	std::vector<b2Fixture*> result;
	for (auto poly : polyList) {
		result.push_back(createFixture(&poly));
	}
	return result;
}

b2Fixture* Body::createFixture(const b2FixtureDef& fixDef)
{
	return _body->CreateFixture(&fixDef);
}

void Body::destroyFixture(b2Fixture* fixture)
{
	_body->DestroyFixture(fixture);
}

void Body::destroyFixture(const std::vector<b2Fixture*>& fixtures)
{
	for (auto fixture : fixtures) {
		destroyFixture(fixture);
	}
}

void Body::setCategoryBitsAndMaskBits(uint16 cbits, uint16 mbits)
{
	for (b2Fixture* f = _body->GetFixtureList(); f; f = f->GetNext()) {
		b2Filter fd = f->GetFilterData();
		fd.categoryBits = cbits;
		fd.maskBits = mbits;
		f->SetFilterData(fd);
	}
}

void Body::setGroupIndex(int16 groupIndex)
{
	for (b2Fixture* f = _body->GetFixtureList(); f; f = f->GetNext()) {
		b2Filter fd = f->GetFilterData();
		fd.groupIndex = groupIndex;
		f->SetFilterData(fd);
	}
}

void Body::setCollisionCategory(int category)
{
	uint16 bits = 1 << category;
	setCategoryBitsAndMaskBits(bits, bits);
}

void Body::beginContact(Body* otherBody)
{
	if (_beginContactCallback) {
		_beginContactCallback(otherBody);
	}
}

bool Body::frameContact(Body* otherBody)
{
	bool ret = true;
	if (_frameContactCallback) {
		ret = _frameContactCallback(otherBody);
	}
	return ret;
}

void Body::endContact(Body* otherBody)
{
	if (_endContactCallback) {
		_endContactCallback(otherBody);
	}
}

void Body::setBeginContactCallback(std::function<void(Body*)> callbackFunc)
{
	_beginContactCallback = callbackFunc;
}

void Body::setFrameContactCallback(std::function<bool(Body*)> callbackFunc)
{
	_frameContactCallback = callbackFunc;
}

void Body::setEndContactCallback(std::function<void(Body*)> callbackFunc)
{
	_endContactCallback = callbackFunc;
}
<commit_msg>update Body::destroyFixture<commit_after>#include "physics/Body.h"

#include "physics/Physics.h"

using fei::Body;

Body::Body()
: _body(nullptr),
  _type(Type::DYNAMIC),
  _tag(0),
  _destroyed(false)
{
}

Body::Body(b2Body* b2bd, Type tp)
: _body(b2bd),
  _type(tp),
  _tag(0),
  _destroyed(false)
{
	_body->SetUserData(this);
}

void Body::setBody(b2Body* b2bd)
{
	_body = b2bd;
	_body->SetUserData(this);
}

const fei::Vec2 Body::getPosition() const
{
	auto b2v = _body->GetPosition();
	auto vec = fei::Vec2(b2v.x, b2v.y);
	return Physics::getInstance()->physicsToRender(vec);
}

float Body::getAngle() const
{
	return _body->GetAngle();
}

void Body::setSpeed(const fei::Vec2& sp)
{
	auto vec = Physics::getInstance()->renderToPhysics(sp);
	_body->SetLinearVelocity(b2Vec2(vec.x, vec.y));
}

const fei::Vec2 Body::getSpeed()
{
	auto vec = _body->GetLinearVelocity();
	auto ret = Physics::getInstance()->physicsToRender(fei::Vec2(vec.x, vec.y));
	return ret;
}

void Body::setTag(int tag)
{
	_tag = tag;
}

b2Fixture* Body::createFixture(const fei::Shape* shape)
{
	float density = 1.0f;
	if (Type::STATIC == _type) {
		density = 0.0f;
	}
	auto *b2shape = Physics::ShapeToB2Shape(shape);
	auto fixture = _body->CreateFixture(b2shape, density);
	if (b2shape) {
		delete b2shape;
	}
	return fixture;
}

const std::vector<b2Fixture*> Body::createFixture(const std::vector<fei::Shape*>& shapeList)
{
	std::vector<b2Fixture*> result;
	for (auto shape : shapeList) {
		result.push_back(createFixture(shape));
	}
	return result;
}

const std::vector<b2Fixture*> Body::createFixture(const fei::Polygon& poly)
{
	return createFixture(poly.box2dDecomposition());
}

const std::vector<b2Fixture*> Body::createFixture(const std::vector<fei::Polygon>& polyList)
{
	std::vector<b2Fixture*> result;
	for (auto poly : polyList) {
		result.push_back(createFixture(&poly));
	}
	return result;
}

b2Fixture* Body::createFixture(const b2FixtureDef& fixDef)
{
	return _body->CreateFixture(&fixDef);
}

void Body::destroyFixture(b2Fixture* fixture)
{
	if (_destroyed) {
		return;
	}
	_body->DestroyFixture(fixture);
}

void Body::destroyFixture(const std::vector<b2Fixture*>& fixtures)
{
	for (auto fixture : fixtures) {
		destroyFixture(fixture);
	}
}

void Body::setCategoryBitsAndMaskBits(uint16 cbits, uint16 mbits)
{
	for (b2Fixture* f = _body->GetFixtureList(); f; f = f->GetNext()) {
		b2Filter fd = f->GetFilterData();
		fd.categoryBits = cbits;
		fd.maskBits = mbits;
		f->SetFilterData(fd);
	}
}

void Body::setGroupIndex(int16 groupIndex)
{
	for (b2Fixture* f = _body->GetFixtureList(); f; f = f->GetNext()) {
		b2Filter fd = f->GetFilterData();
		fd.groupIndex = groupIndex;
		f->SetFilterData(fd);
	}
}

void Body::setCollisionCategory(int category)
{
	uint16 bits = 1 << category;
	setCategoryBitsAndMaskBits(bits, bits);
}

void Body::beginContact(Body* otherBody)
{
	if (_beginContactCallback) {
		_beginContactCallback(otherBody);
	}
}

bool Body::frameContact(Body* otherBody)
{
	bool ret = true;
	if (_frameContactCallback) {
		ret = _frameContactCallback(otherBody);
	}
	return ret;
}

void Body::endContact(Body* otherBody)
{
	if (_endContactCallback) {
		_endContactCallback(otherBody);
	}
}

void Body::setBeginContactCallback(std::function<void(Body*)> callbackFunc)
{
	_beginContactCallback = callbackFunc;
}

void Body::setFrameContactCallback(std::function<bool(Body*)> callbackFunc)
{
	_frameContactCallback = callbackFunc;
}

void Body::setEndContactCallback(std::function<void(Body*)> callbackFunc)
{
	_endContactCallback = callbackFunc;
}
<|endoftext|>


<commit_before>#include "GasCodeGenerator.h"

using namespace common;
using namespace std;

GasCodeGenerator::GasCodeGenerator(std::ostream &os) : visitor::CodeGenerator::CodeGenerator(os), os(os) {
}

void GasCodeGenerator::visit(Program *node) {

}

void GasCodeGenerator::visit(Function *node) {

}

void GasCodeGenerator::visit(Case *node) {

}

void GasCodeGenerator::visit(Or *node) {

}

void GasCodeGenerator::visit(And *node) {

}

void GasCodeGenerator::visit(Equal *node) {

}

void GasCodeGenerator::visit(NotEqual *node) {

}

void GasCodeGenerator::visit(Lesser *node) {

}

void GasCodeGenerator::visit(Greater *node) {

}

void GasCodeGenerator::visit(LesserEq *node) {

}

void GasCodeGenerator::visit(GreaterEq *node) {

}

void GasCodeGenerator::visit(Add *node) {

}

void GasCodeGenerator::visit(Sub *node) {

}

void GasCodeGenerator::visit(Mul *node) {

}

void GasCodeGenerator::visit(Div *node) {

}

void GasCodeGenerator::visit(Mod *node) {

}

void GasCodeGenerator::visit(ListAdd *node) {

}

void GasCodeGenerator::visit(Par *node) {

}

void GasCodeGenerator::visit(Not *node) {

}

void GasCodeGenerator::visit(Int *node) {

}

void GasCodeGenerator::visit(Float *node) {

}

void GasCodeGenerator::visit(Bool *node) {

}

void GasCodeGenerator::visit(Char *node) {

}

void GasCodeGenerator::visit(String *node) {

}

void GasCodeGenerator::visit(ListPattern *node) {

}

void GasCodeGenerator::visit(TuplePattern *node) {

}

void GasCodeGenerator::visit(ListSplit *node) {

}

void GasCodeGenerator::visit(List *node) {

}

void GasCodeGenerator::visit(Tuple *node) {

}

void GasCodeGenerator::visit(Id *node) {

}

void GasCodeGenerator::visit(Call *node) {

}

void GasCodeGenerator::visit(Type *node) {

}

string GasCodeGenerator::get_type(Type *) {

}<commit_msg>GasCodeGen: Now generates the base function body * Also generates jump points for cases<commit_after>#include "GasCodeGenerator.h"
#include <iostream>
#include <vector>

using namespace common;
using namespace std;

std::string function;

vector<string> funcVector;
vector<string> funcGlobl;

int caseCount = 0;

GasCodeGenerator::GasCodeGenerator(std::ostream &os) : visitor::CodeGenerator::CodeGenerator(os), os(os) {
}

void GasCodeGenerator::visit(Program *node) {
    // Visit all functions
    for (auto func : node->funcs) {
        func->accept(this);
    }

    // Print all functions to output stream
    for (auto s : funcVector) {
        std::cout << s << std::endl;
    }
}

void GasCodeGenerator::visit(Function *node) {
    string funcName = node->id;
    funcGlobl.push_back(funcName);
    function.append(funcName);
    function.append(":\n");
    function.append("pushl %ebp\n");
    function.append("movl %esp, %ebp\n");
    function.append(".");
    function.append(funcName);
    function.append("funcstart:\n");

    caseCount = 0;

    for (auto funcCase : node->cases) {
        funcCase->accept(this);
    }

    function.append(".");
    function.append(funcName);
    function.append("funcend:\n");
    function.append("movl %ebp, %esp\n");
    function.append("popl %ebp\n");
    function.append("leave\n");
    function.append("ret\n");

    funcVector.push_back(function);

    function.clear();
}

void GasCodeGenerator::visit(Case *node) {
    caseCount++;
    function.append(".case");
    function.append(to_string(caseCount));
    function.append(":\n");
}

void GasCodeGenerator::visit(Or *node) {

}

void GasCodeGenerator::visit(And *node) {

}

void GasCodeGenerator::visit(Equal *node) {

}

void GasCodeGenerator::visit(NotEqual *node) {

}

void GasCodeGenerator::visit(Lesser *node) {

}

void GasCodeGenerator::visit(Greater *node) {

}

void GasCodeGenerator::visit(LesserEq *node) {

}

void GasCodeGenerator::visit(GreaterEq *node) {

}

void GasCodeGenerator::visit(Add *node) {

}

void GasCodeGenerator::visit(Sub *node) {

}

void GasCodeGenerator::visit(Mul *node) {

}

void GasCodeGenerator::visit(Div *node) {

}

void GasCodeGenerator::visit(Mod *node) {

}

void GasCodeGenerator::visit(ListAdd *node) {

}

void GasCodeGenerator::visit(Par *node) {

}

void GasCodeGenerator::visit(Not *node) {

}

void GasCodeGenerator::visit(Int *node) {

}

void GasCodeGenerator::visit(Float *node) {

}

void GasCodeGenerator::visit(Bool *node) {

}

void GasCodeGenerator::visit(Char *node) {

}

void GasCodeGenerator::visit(String *node) {

}

void GasCodeGenerator::visit(ListPattern *node) {

}

void GasCodeGenerator::visit(TuplePattern *node) {

}

void GasCodeGenerator::visit(ListSplit *node) {

}

void GasCodeGenerator::visit(List *node) {

}

void GasCodeGenerator::visit(Tuple *node) {

}

void GasCodeGenerator::visit(Id *node) {

}

void GasCodeGenerator::visit(Call *node) {

}

void GasCodeGenerator::visit(Type *node) {

}

string GasCodeGenerator::get_type(Type *) {

}<|endoftext|>


<commit_before><commit_msg>Fix bustage caused by last change. enumeration changed name and got rid of _DELEGATE.<commit_after><|endoftext|>