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

#include "chrome/browser/performance_monitor/startup_timer.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"

namespace performance_monitor {

namespace {
// Needed because Database::AddMetric is overloaded, so base::Bind doesn't work.
void AddMetricToDatabaseOnBackgroundThread(Database* database,
                                           const Metric& metric) {
  database->AddMetric(metric);
}

}  // namespace

// static
StartupTimer* StartupTimer::g_startup_timer_ = NULL;

StartupTimer::StartupTimer() : startup_begin_(base::TimeTicks::Now()),
                               startup_type_(STARTUP_NORMAL),
                               performance_monitor_initialized_(false) {
  CHECK(!g_startup_timer_);
  g_startup_timer_ = this;

  // We need this check because, under certain rare circumstances,
  // NotificationService::current() will return null, and this will cause a
  // segfault in NotificationServiceImpl::AddObserver(). Currently, this only
  // happens as a result of the child process launched by BrowserMainTest.
  // WarmConnectionFieldTrial_Invalid.
  if (content::NotificationService::current()) {
    registrar_.Add(this, chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
                   content::NotificationService::AllSources());
  }
}

StartupTimer::~StartupTimer() {
  DCHECK(this == g_startup_timer_);
  g_startup_timer_ = NULL;
}

bool StartupTimer::SignalStartupComplete(StartupType startup_type) {
  DCHECK(elapsed_startup_time_ == base::TimeDelta());

  startup_type_ = startup_type;

  elapsed_startup_time_ =
      base::TimeTicks::Now() - total_pause_ - startup_begin_;

  if (performance_monitor_initialized_)
    InsertElapsedStartupTime();

  return true;
}

// static
void StartupTimer::PauseTimer() {
  // Check that the timer is not already paused.
  DCHECK(g_startup_timer_->pause_started_ == base::TimeTicks());

  g_startup_timer_->pause_started_ = base::TimeTicks::Now();
}

// static
void StartupTimer::UnpauseTimer() {
  // Check that the timer has been paused.
  DCHECK(g_startup_timer_->pause_started_ != base::TimeTicks());

  g_startup_timer_->total_pause_ += base::TimeTicks::Now() -
                                    g_startup_timer_->pause_started_;

  g_startup_timer_->pause_started_ = base::TimeTicks();
}

void StartupTimer::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  CHECK(type == chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED);
  performance_monitor_initialized_ = true;

  if (PerformanceMonitor::GetInstance()->database_logging_enabled()) {
    if (elapsed_startup_time_ != base::TimeDelta())
      InsertElapsedStartupTime();
    if (elapsed_session_restore_times_.size())
      InsertElapsedSessionRestoreTime();
  }
}

// static
void StartupTimer::SetElapsedSessionRestoreTime(
    const base::TimeDelta& elapsed_session_restore_time) {
  g_startup_timer_->elapsed_session_restore_times_.push_back(
      elapsed_session_restore_time);

  if (g_startup_timer_->performance_monitor_initialized_)
    g_startup_timer_->InsertElapsedSessionRestoreTime();
}

void StartupTimer::InsertElapsedStartupTime() {
  content::BrowserThread::PostBlockingPoolSequencedTask(
      Database::kDatabaseSequenceToken,
      FROM_HERE,
      base::Bind(
          &AddMetricToDatabaseOnBackgroundThread,
          base::Unretained(PerformanceMonitor::GetInstance()->database()),
          Metric(startup_type_ == STARTUP_NORMAL ? METRIC_STARTUP_TIME
                                                 : METRIC_TEST_STARTUP_TIME,
                 base::Time::Now(),
                 static_cast<double>(
                     elapsed_startup_time_.ToInternalValue()))));
}

void StartupTimer::InsertElapsedSessionRestoreTime() {
  for (std::vector<base::TimeDelta>::const_iterator iter =
           elapsed_session_restore_times_.begin();
       iter != elapsed_session_restore_times_.end(); ++iter) {
    content::BrowserThread::PostBlockingPoolSequencedTask(
        Database::kDatabaseSequenceToken,
        FROM_HERE,
        base::Bind(
            &AddMetricToDatabaseOnBackgroundThread,
            base::Unretained(PerformanceMonitor::GetInstance()->database()),
            Metric(METRIC_SESSION_RESTORE_TIME,
                   base::Time::Now(),
                   static_cast<double>(iter->ToInternalValue()))));
  }
}

}  // namespace performance_monitor
<commit_msg>Fix for a startup crash when restoring the session if a specific performance monitoring flag was disabled.<commit_after>// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/performance_monitor/startup_timer.h"

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/notification_types.h"

namespace performance_monitor {

namespace {
// Needed because Database::AddMetric is overloaded, so base::Bind doesn't work.
void AddMetricToDatabaseOnBackgroundThread(Database* database,
                                           const Metric& metric) {
  database->AddMetric(metric);
}

}  // namespace

// static
StartupTimer* StartupTimer::g_startup_timer_ = NULL;

StartupTimer::StartupTimer() : startup_begin_(base::TimeTicks::Now()),
                               startup_type_(STARTUP_NORMAL),
                               performance_monitor_initialized_(false) {
  CHECK(!g_startup_timer_);
  g_startup_timer_ = this;

  // We need this check because, under certain rare circumstances,
  // NotificationService::current() will return null, and this will cause a
  // segfault in NotificationServiceImpl::AddObserver(). Currently, this only
  // happens as a result of the child process launched by BrowserMainTest.
  // WarmConnectionFieldTrial_Invalid.
  if (content::NotificationService::current()) {
    registrar_.Add(this, chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
                   content::NotificationService::AllSources());
  }
}

StartupTimer::~StartupTimer() {
  DCHECK(this == g_startup_timer_);
  g_startup_timer_ = NULL;
}

bool StartupTimer::SignalStartupComplete(StartupType startup_type) {
  DCHECK(elapsed_startup_time_ == base::TimeDelta());

  startup_type_ = startup_type;

  elapsed_startup_time_ =
      base::TimeTicks::Now() - total_pause_ - startup_begin_;

  if (performance_monitor_initialized_)
    InsertElapsedStartupTime();

  return true;
}

// static
void StartupTimer::PauseTimer() {
  // Check that the timer is not already paused.
  DCHECK(g_startup_timer_->pause_started_ == base::TimeTicks());

  g_startup_timer_->pause_started_ = base::TimeTicks::Now();
}

// static
void StartupTimer::UnpauseTimer() {
  // Check that the timer has been paused.
  DCHECK(g_startup_timer_->pause_started_ != base::TimeTicks());

  g_startup_timer_->total_pause_ += base::TimeTicks::Now() -
                                    g_startup_timer_->pause_started_;

  g_startup_timer_->pause_started_ = base::TimeTicks();
}

void StartupTimer::Observe(int type,
                           const content::NotificationSource& source,
                           const content::NotificationDetails& details) {
  CHECK(type == chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED);
  performance_monitor_initialized_ = true;

  if (PerformanceMonitor::GetInstance()->database_logging_enabled()) {
    if (elapsed_startup_time_ != base::TimeDelta())
      InsertElapsedStartupTime();
    if (elapsed_session_restore_times_.size())
      InsertElapsedSessionRestoreTime();
  }
}

// static
void StartupTimer::SetElapsedSessionRestoreTime(
    const base::TimeDelta& elapsed_session_restore_time) {
  if (PerformanceMonitor::GetInstance()->database_logging_enabled()) {
    g_startup_timer_->elapsed_session_restore_times_.push_back(
        elapsed_session_restore_time);

    if (g_startup_timer_->performance_monitor_initialized_)
      g_startup_timer_->InsertElapsedSessionRestoreTime();
  }
}

void StartupTimer::InsertElapsedStartupTime() {
  content::BrowserThread::PostBlockingPoolSequencedTask(
      Database::kDatabaseSequenceToken,
      FROM_HERE,
      base::Bind(
          &AddMetricToDatabaseOnBackgroundThread,
          base::Unretained(PerformanceMonitor::GetInstance()->database()),
          Metric(startup_type_ == STARTUP_NORMAL ? METRIC_STARTUP_TIME
                                                 : METRIC_TEST_STARTUP_TIME,
                 base::Time::Now(),
                 static_cast<double>(
                     elapsed_startup_time_.ToInternalValue()))));
}

void StartupTimer::InsertElapsedSessionRestoreTime() {
  for (std::vector<base::TimeDelta>::const_iterator iter =
           elapsed_session_restore_times_.begin();
       iter != elapsed_session_restore_times_.end(); ++iter) {
    content::BrowserThread::PostBlockingPoolSequencedTask(
        Database::kDatabaseSequenceToken,
        FROM_HERE,
        base::Bind(
            &AddMetricToDatabaseOnBackgroundThread,
            base::Unretained(PerformanceMonitor::GetInstance()->database()),
            Metric(METRIC_SESSION_RESTORE_TIME,
                   base::Time::Now(),
                   static_cast<double>(iter->ToInternalValue()))));
  }
}

}  // namespace performance_monitor
<|endoftext|>


<commit_before>#ifndef BENCHMARK_UTILITY_HPP
#define BENCHMARK_UTILITY_HPP

#include <chrono>
#include <random>
#include <tuple>

#ifdef _WIN32
#define NOINLINE(s) __declspec(noinline) s
#elif __unix__
#define NOINLINE(s) s __attribute__ ((noinline))
#else
#define NOINLINE(s) s
#endif

extern std::size_t g_limit;
const std::size_t c_jlsignal_max = 1024;

typedef std::minstd_rand Rng;

typedef std::chrono::nanoseconds Timer_u;
typedef std::chrono::milliseconds Limit_u;
typedef std::chrono::duration<double, std::milli> Delta_u;

struct IncrementFill
{
    std::size_t i = 0;
    std::size_t operator()() { return i++; }
};

//------------------------------------------------------------------------------

// based stackoverflow

template <unsigned int N>
struct tee_stream
{
    template <typename ...Args, typename T>
    static std::tuple<Args...>& print(std::tuple<Args...>& t, T&& x)
    {
        std::get<sizeof...(Args) - N>(t) << x;
        tee_stream<N - 1>::print(t, std::forward<T>(x));
        return t;
    }
};

template <>
struct tee_stream<0>
{
    template <typename ...Args, typename T>
    static std::tuple<Args...>& print(std::tuple<Args...>& t, T&& x)
    {
        return t;
    }
};
template <typename ...Args, typename T>
std::tuple<Args...>& operator<< (std::tuple<Args...>& t, T&& x)
{
    return tee_stream<sizeof...(Args)>::print(t, std::forward<T>(x));
}
template <typename ...Args, typename T>
std::tuple<Args...>& operator<< (std::tuple<Args...>&& t, T&& x)
{
    return tee_stream<sizeof...(Args)>::print(t, std::forward<T>(x));
}

//------------------------------------------------------------------------------

template <typename Iterator> struct RangeHelper
{
    Iterator lhs;
    Iterator rhs;

    Iterator cbegin() const { return lhs; }
    Iterator begin() const { return lhs; }
    Iterator cend() const { return rhs; }
    Iterator end() const { return rhs; }
};
template <typename Iterator>
static RangeHelper<Iterator> Range(Iterator lhs,
                                   Iterator rhs)
{
    return { lhs, rhs };
}

//------------------------------------------------------------------------------

class chrono_timer
{
    std::chrono::time_point<std::chrono::high_resolution_clock> m_start;

    public:

    void reset()
    {
        m_start = std::chrono::high_resolution_clock::now();
    }
    template <typename T>
    std::size_t count() const
    {
        return std::chrono::duration_cast<T>
          (std::chrono::high_resolution_clock::now() - m_start).count();
    }
};

#endif // BENCHMARK_UTILITY_HPP
<commit_msg>How did this get in here?<commit_after><|endoftext|>


<commit_before>//                          MFEM Example 1 - NURBS Version
//
// Compile with: make ex1
//
// Sample runs:  ex1 -m ../../data/square-disc.mesh
//               ex1 -m ../../data/star.mesh
//               ex1 -m ../../data/escher.mesh
//               ex1 -m ../../data/fichera.mesh
//               ex1 -m ../../data/square-disc-p2.vtk -o 2
//               ex1 -m ../../data/square-disc-p3.mesh -o 3
//               ex1 -m ../../data/square-disc-nurbs.mesh -o -1
//               ex1 -m ../../data/disc-nurbs.mesh -o -1
//               ex1 -m ../../data/pipe-nurbs.mesh -o -1
//               ex1 -m ../../data/star-surf.mesh
//               ex1 -m ../../data/square-disc-surf.mesh
//               ex1 -m ../../data/inline-segment.mesh
//               ex1 -m ../../data/amr-quad.mesh
//               ex1 -m ../../data/amr-hex.mesh
//               ex1 -m ../../data/fichera-amr.mesh
//               ex1 -m ../../data/mobius-strip.mesh
//               ex1 -m ../../data/mobius-strip.mesh -o -1 -sc
//               ex1 -m ../../data/beam-hex-nurbs.mesh -pm 1 -ps 2y
//
// Description:  This example code demonstrates the use of MFEM to define a
//               simple finite element discretization of the Laplace problem
//               -Delta u = 1 with homogeneous Dirichlet boundary conditions.
//               Specifically, we discretize using a FE space of the specified
//               order, or if order < 1 using an isoparametric/isogeometric
//               space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
//               NURBS mesh, etc.)
//
//               The example highlights the use of mesh refinement, finite
//               element grid functions, as well as linear and bilinear forms
//               corresponding to the left-hand side and right-hand side of the
//               discrete linear system. We also cover the explicit elimination
//               of essential boundary conditions, static condensation, and the
//               optional connection to the GLVis tool for visualization.

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

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../../data/star.mesh";
   const char *per_file  = "none";
   Array<int> master(0);
   Array<int> slave(0);
   bool static_cond = false;
   bool visualization = 1;
   Array<int> order(1);
   order[0] = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&per_file, "-p", "--per",
                  "Periodic BCS file.");
   args.AddOption(&master, "-pm", "--master",
                  "Master boundaries for periodic BCs");
   args.AddOption(&slave, "-ps", "--slave",
                  "Slave boundaries for periodic BCs");
   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(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // 2. Read the mesh from the given mesh file. We can handle triangular,
   //    quadrilateral, tetrahedral, hexahedral, surface and volume meshes with
   //    the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   int dim = mesh->Dimension();

   // 3. Refine the mesh to increase the resolution. In this example we do
   //    'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
   //    largest number that gives a final mesh with no more than 50,000
   //    elements.
   {
      int ref_levels =
         (int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 4. Define a finite element space on the mesh. Here we use continuous
   //    Lagrange finite elements of the specified order. If order < 1, we
   //    instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   NURBSExtension *NURBSext = NULL;
   int own_fec = 0;

   if (mesh->NURBSext)
   {
      fec = new NURBSFECollection(order[0]);
      own_fec = 1;

      int nkv = mesh->NURBSext->GetNKV();
      if (order.Size() == 1)
      {
         int tmp = order[0];
         order.SetSize(nkv);
         order = tmp;
      }

      if (order.Size() != nkv ) { mfem_error("Wrong number of orders set."); }
      NURBSext = new NURBSExtension(mesh->NURBSext, order);

      // Read periodic BCs from file
      std::ifstream in;
      in.open(per_file, std::ifstream::in);
      if (in.is_open())
      {
         int psize;
         in >> psize;
         master.SetSize(psize);
         slave.SetSize(psize);
         master.Load(in, psize);
         slave.Load(in, psize);
         in.close();
      }
      master.Print();
      slave.Print();
      NURBSext->ConnectBoundaries(master,slave);
   }
   else if (order[0] == -1) // Isoparametric
   {
      if (mesh->GetNodes())
      {
         fec = mesh->GetNodes()->OwnFEC();
         own_fec = 0;
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
      else
      {
         cout <<"Mesh does not have FEs --> Assume order 1.\n";
         fec = new H1_FECollection(1, dim);
         own_fec = 1;
      }
   }
   else
   {
      if (order.Size() > 1) { cout <<"Wrong number of orders set, needs one.\n"; }
      fec = new H1_FECollection(abs(order[0]), dim);
      own_fec = 1;
   }
   FiniteElementSpace *fespace = new FiniteElementSpace(mesh, NURBSext, fec);
   cout << "Number of finite element unknowns: "
        << fespace->GetTrueVSize() << endl;

   // 5. Determine the list of true (i.e. conforming) essential boundary dofs.
   //    In this example, the boundary conditions are defined by marking all
   //    the boundary attributes from the mesh as essential (Dirichlet) and
   //    converting them to a list of true dofs.
   Array<int> ess_tdof_list;
   if (mesh->bdr_attributes.Size())
   {
      Array<int> ess_bdr(mesh->bdr_attributes.Max());
      ess_bdr = 1;
      // Remove periodic BCs
      for (int i = 0; i < master.Size(); i++)
      {
         ess_bdr[master[i]-1] = 0;
         ess_bdr[slave[i]-1] = 0;
      }
      fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 6. Set up the linear form b(.) which corresponds to the right-hand side of
   //    the FEM linear system, which in this case is (1,phi_i) where phi_i are
   //    the basis functions in the finite element fespace.
   LinearForm *b = new LinearForm(fespace);
   ConstantCoefficient one(1.0);
   b->AddDomainIntegrator(new DomainLFIntegrator(one));
   b->Assemble();

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

   // 8. Set up the bilinear form a(.,.) on the finite element space
   //    corresponding to the Laplacian operator -Delta, by adding the Diffusion
   //    domain integrator.
   BilinearForm *a = new BilinearForm(fespace);
   a->AddDomainIntegrator(new DiffusionIntegrator(one));

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

   SparseMatrix A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);

   cout << "Size of linear system: " << A.Height() << endl;

#ifndef MFEM_USE_SUITESPARSE
   // 10. Define a simple symmetric Gauss-Seidel preconditioner and use it to
   //     solve the system A X = B with PCG.
   GSSmoother M(A);
   PCG(A, M, B, X, 1, 200, 1e-12, 0.0);
#else
   // 10. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
   UMFPackSolver umf_solver;
   umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
   umf_solver.SetOperator(A);
   umf_solver.Mult(B, X);
#endif

   // 11. Recover the solution as a finite element grid function.
   a->RecoverFEMSolution(X, *b, x);

   // 12. Save the refined mesh and the solution. This output can be viewed later
   //     using GLVis: "glvis -m refined.mesh -g sol.gf".
   ofstream mesh_ofs("refined.mesh");
   mesh_ofs.precision(8);
   mesh->Print(mesh_ofs);
   ofstream sol_ofs("sol.gf");
   sol_ofs.precision(8);
   x.Save(sol_ofs);

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

   // 14. Save data in the VisIt format
   VisItDataCollection visit_dc("Example1", mesh);
   visit_dc.RegisterField("solution", &x);
   visit_dc.Save();

   // 15. Free the used memory.
   delete a;
   delete b;
   delete fespace;
   if (own_fec) { delete fec; }
   delete mesh;

   return 0;
}
<commit_msg>Fix a typo in miniapps/nurbs/ex1.cpp<commit_after>//                          MFEM Example 1 - NURBS Version
//
// Compile with: make ex1
//
// Sample runs:  ex1 -m ../../data/square-disc.mesh
//               ex1 -m ../../data/star.mesh
//               ex1 -m ../../data/escher.mesh
//               ex1 -m ../../data/fichera.mesh
//               ex1 -m ../../data/square-disc-p2.vtk -o 2
//               ex1 -m ../../data/square-disc-p3.mesh -o 3
//               ex1 -m ../../data/square-disc-nurbs.mesh -o -1
//               ex1 -m ../../data/disc-nurbs.mesh -o -1
//               ex1 -m ../../data/pipe-nurbs.mesh -o -1
//               ex1 -m ../../data/star-surf.mesh
//               ex1 -m ../../data/square-disc-surf.mesh
//               ex1 -m ../../data/inline-segment.mesh
//               ex1 -m ../../data/amr-quad.mesh
//               ex1 -m ../../data/amr-hex.mesh
//               ex1 -m ../../data/fichera-amr.mesh
//               ex1 -m ../../data/mobius-strip.mesh
//               ex1 -m ../../data/mobius-strip.mesh -o -1 -sc
//               ex1 -m ../../data/beam-hex-nurbs.mesh -pm 1 -ps 2
//
// Description:  This example code demonstrates the use of MFEM to define a
//               simple finite element discretization of the Laplace problem
//               -Delta u = 1 with homogeneous Dirichlet boundary conditions.
//               Specifically, we discretize using a FE space of the specified
//               order, or if order < 1 using an isoparametric/isogeometric
//               space (i.e. quadratic for quadratic curvilinear mesh, NURBS for
//               NURBS mesh, etc.)
//
//               The example highlights the use of mesh refinement, finite
//               element grid functions, as well as linear and bilinear forms
//               corresponding to the left-hand side and right-hand side of the
//               discrete linear system. We also cover the explicit elimination
//               of essential boundary conditions, static condensation, and the
//               optional connection to the GLVis tool for visualization.

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

using namespace std;
using namespace mfem;

int main(int argc, char *argv[])
{
   // 1. Parse command-line options.
   const char *mesh_file = "../../data/star.mesh";
   const char *per_file  = "none";
   Array<int> master(0);
   Array<int> slave(0);
   bool static_cond = false;
   bool visualization = 1;
   Array<int> order(1);
   order[0] = 1;

   OptionsParser args(argc, argv);
   args.AddOption(&mesh_file, "-m", "--mesh",
                  "Mesh file to use.");
   args.AddOption(&per_file, "-p", "--per",
                  "Periodic BCS file.");
   args.AddOption(&master, "-pm", "--master",
                  "Master boundaries for periodic BCs");
   args.AddOption(&slave, "-ps", "--slave",
                  "Slave boundaries for periodic BCs");
   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(&visualization, "-vis", "--visualization", "-no-vis",
                  "--no-visualization",
                  "Enable or disable GLVis visualization.");
   args.Parse();
   if (!args.Good())
   {
      args.PrintUsage(cout);
      return 1;
   }
   args.PrintOptions(cout);

   // 2. Read the mesh from the given mesh file. We can handle triangular,
   //    quadrilateral, tetrahedral, hexahedral, surface and volume meshes with
   //    the same code.
   Mesh *mesh = new Mesh(mesh_file, 1, 1);
   int dim = mesh->Dimension();

   // 3. Refine the mesh to increase the resolution. In this example we do
   //    'ref_levels' of uniform refinement. We choose 'ref_levels' to be the
   //    largest number that gives a final mesh with no more than 50,000
   //    elements.
   {
      int ref_levels =
         (int)floor(log(50000./mesh->GetNE())/log(2.)/dim);
      for (int l = 0; l < ref_levels; l++)
      {
         mesh->UniformRefinement();
      }
   }

   // 4. Define a finite element space on the mesh. Here we use continuous
   //    Lagrange finite elements of the specified order. If order < 1, we
   //    instead use an isoparametric/isogeometric space.
   FiniteElementCollection *fec;
   NURBSExtension *NURBSext = NULL;
   int own_fec = 0;

   if (mesh->NURBSext)
   {
      fec = new NURBSFECollection(order[0]);
      own_fec = 1;

      int nkv = mesh->NURBSext->GetNKV();
      if (order.Size() == 1)
      {
         int tmp = order[0];
         order.SetSize(nkv);
         order = tmp;
      }

      if (order.Size() != nkv ) { mfem_error("Wrong number of orders set."); }
      NURBSext = new NURBSExtension(mesh->NURBSext, order);

      // Read periodic BCs from file
      std::ifstream in;
      in.open(per_file, std::ifstream::in);
      if (in.is_open())
      {
         int psize;
         in >> psize;
         master.SetSize(psize);
         slave.SetSize(psize);
         master.Load(in, psize);
         slave.Load(in, psize);
         in.close();
      }
      master.Print();
      slave.Print();
      NURBSext->ConnectBoundaries(master,slave);
   }
   else if (order[0] == -1) // Isoparametric
   {
      if (mesh->GetNodes())
      {
         fec = mesh->GetNodes()->OwnFEC();
         own_fec = 0;
         cout << "Using isoparametric FEs: " << fec->Name() << endl;
      }
      else
      {
         cout <<"Mesh does not have FEs --> Assume order 1.\n";
         fec = new H1_FECollection(1, dim);
         own_fec = 1;
      }
   }
   else
   {
      if (order.Size() > 1) { cout <<"Wrong number of orders set, needs one.\n"; }
      fec = new H1_FECollection(abs(order[0]), dim);
      own_fec = 1;
   }
   FiniteElementSpace *fespace = new FiniteElementSpace(mesh, NURBSext, fec);
   cout << "Number of finite element unknowns: "
        << fespace->GetTrueVSize() << endl;

   // 5. Determine the list of true (i.e. conforming) essential boundary dofs.
   //    In this example, the boundary conditions are defined by marking all
   //    the boundary attributes from the mesh as essential (Dirichlet) and
   //    converting them to a list of true dofs.
   Array<int> ess_tdof_list;
   if (mesh->bdr_attributes.Size())
   {
      Array<int> ess_bdr(mesh->bdr_attributes.Max());
      ess_bdr = 1;
      // Remove periodic BCs
      for (int i = 0; i < master.Size(); i++)
      {
         ess_bdr[master[i]-1] = 0;
         ess_bdr[slave[i]-1] = 0;
      }
      fespace->GetEssentialTrueDofs(ess_bdr, ess_tdof_list);
   }

   // 6. Set up the linear form b(.) which corresponds to the right-hand side of
   //    the FEM linear system, which in this case is (1,phi_i) where phi_i are
   //    the basis functions in the finite element fespace.
   LinearForm *b = new LinearForm(fespace);
   ConstantCoefficient one(1.0);
   b->AddDomainIntegrator(new DomainLFIntegrator(one));
   b->Assemble();

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

   // 8. Set up the bilinear form a(.,.) on the finite element space
   //    corresponding to the Laplacian operator -Delta, by adding the Diffusion
   //    domain integrator.
   BilinearForm *a = new BilinearForm(fespace);
   a->AddDomainIntegrator(new DiffusionIntegrator(one));

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

   SparseMatrix A;
   Vector B, X;
   a->FormLinearSystem(ess_tdof_list, x, *b, A, X, B);

   cout << "Size of linear system: " << A.Height() << endl;

#ifndef MFEM_USE_SUITESPARSE
   // 10. Define a simple symmetric Gauss-Seidel preconditioner and use it to
   //     solve the system A X = B with PCG.
   GSSmoother M(A);
   PCG(A, M, B, X, 1, 200, 1e-12, 0.0);
#else
   // 10. If MFEM was compiled with SuiteSparse, use UMFPACK to solve the system.
   UMFPackSolver umf_solver;
   umf_solver.Control[UMFPACK_ORDERING] = UMFPACK_ORDERING_METIS;
   umf_solver.SetOperator(A);
   umf_solver.Mult(B, X);
#endif

   // 11. Recover the solution as a finite element grid function.
   a->RecoverFEMSolution(X, *b, x);

   // 12. Save the refined mesh and the solution. This output can be viewed later
   //     using GLVis: "glvis -m refined.mesh -g sol.gf".
   ofstream mesh_ofs("refined.mesh");
   mesh_ofs.precision(8);
   mesh->Print(mesh_ofs);
   ofstream sol_ofs("sol.gf");
   sol_ofs.precision(8);
   x.Save(sol_ofs);

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

   // 14. Save data in the VisIt format
   VisItDataCollection visit_dc("Example1", mesh);
   visit_dc.RegisterField("solution", &x);
   visit_dc.Save();

   // 15. Free the used memory.
   delete a;
   delete b;
   delete fespace;
   if (own_fec) { delete fec; }
   delete mesh;

   return 0;
}
<|endoftext|>


<commit_before>
#include "webgetter.h"
#include "net.h"

#include "asio/asio.hpp"

#include <coreutils/utils.h>
#include <coreutils/log.h>
#include <coreutils/file.h>

#include <vector>
#include <functional>
#include <cstdint>
#include <unordered_map>

using asio::ip::tcp;
using namespace std;
using namespace utils;

namespace net {

struct HttpSession::State {

	int chunkSize = 1024;
	int total;
	bool oneShot = false;
	std::string url;
	std::string host;
	std::string path;
	int port;
	std::function<void(const asio::error_code &e, size_t n)> handler;
	Callback callback;
	//std::vector<uint8_t> buffer;
	//std::shared_ptr<utils::File> file;
	Connection c;
	asio::streambuf data;
	std::unordered_map<std::string, std::string> header;
	int code;
	int headerSize;
	int cntSize;
	enum { NONE, CONNECT, HEADERS, DONE, EMPTY } state = NONE;

};

HttpSession::HttpSession(const string &url) : impl(make_shared<State>()) {

	int hostStart = 0;
	impl->port = 80;

	impl->url = url;

	LOGD("URL:%s", url);

	auto parts = split(url, "://");

	if(parts.size() == 2) {

	}

	if(startsWith(url, "http://"))
		hostStart = 7;

	int firstSlash = url.find_first_of('/', hostStart);
	impl->host = url.substr(hostStart, firstSlash - hostStart);
	impl->path = url.substr(firstSlash);
	int lastColon = impl->host.find_last_of(':');
	if(lastColon != string::npos) {
		impl->port = stol(impl->host.substr(lastColon+1));
		impl->host = impl->host.substr(0, lastColon);
	}

	LOGD("CONNECT %s %d", impl->host, impl->port);
	impl->c.connect(impl->host, impl->port);
	sendRequest(impl->path, impl->host);
}

HttpSession::HttpSession(HttpSession &&h) : impl(std::move(h.impl)) {
}

HttpSession& HttpSession::operator=(HttpSession &&h) {
	impl = std::move(h.impl);
	return *this;
}

void HttpSession::sendRequest(const string &path, const string &host) {
	string req = utils::format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", path, host);
	LOGD("REQ %p:\n%s", this, req);
	LOGD("%d", impl->data.size());
	impl->c.write(req);
	impl->state = State::CONNECT;
	asio::async_read_until(impl->c.getSocket(), impl->data, "\r\n\r\n", [=](const asio::error_code &e, size_t n) {
		//LOGD("Read %d bytes", n);
		parseHeader();
		impl->state = State::HEADERS;
		readContent();
	});
}

void HttpSession::parseHeader() {
	istream is(&impl->data);
	string line;
	getline(is, line);
	auto rc = split(line, " ");
	impl->code = stol(rc[1]);
	LOGD(">>%s", line);
	while(!is.eof()) {
		getline(is, line);
		if(line == "" || line == "\r")
			break;
		LOGD("%s", line);
		auto parts = split(line, ": ", 2);
		if(parts.size() == 2) {
			parts[1] = rstrip(rstrip(parts[1], '\n'), '\r');
			impl->header[parts[0]] = parts[1];
		}
	}
	auto cl = impl->header["Content-Length"];
	impl->cntSize = cl != "" ? stol(impl->header["Content-Length"]) : 0;
	if(isRedirect()) {
		LOGD("Should redirect to '%s'", impl->header["Location"]);
		//sleepms(500);
	}
}

int HttpSession::contentSize() const { return impl->cntSize; }

void HttpSession::stream(const Callback &cb) {
	impl->callback = cb;
}

void HttpSession::getData(const Callback &cb) {
	impl->oneShot = true;
	impl->callback = cb;
}

HttpSession::Callback HttpSession::getCallback() const {
	return impl->callback;
}

bool HttpSession::isRedirect() const { return impl->code == 303 || impl->code == 302 || impl->code == 307; }

int HttpSession::returnCode() const { return impl->code; }

int HttpSession::getPort() const { return impl->port; }
string HttpSession::getHost() const { return impl->host; }

bool HttpSession::gotHeaders() const { return impl->state == State::HEADERS || impl->state == State::DONE || impl->state == State::EMPTY; }
bool HttpSession::done() const { return impl->state == State::DONE || impl->state == State::EMPTY; }

std::string HttpSession::getUrl() const { return impl->url; }

void HttpSession::stop() { impl->state = State::DONE; }

void HttpSession::readContent() {
	int size = impl->cntSize - impl->data.in_avail();
	if(size <= 0) {
		LOGD("EMPTY");
		impl->state = State::EMPTY;
		if(!isRedirect()) {
			vector<uint8_t> v;
			impl->callback(*this, v);
		}
		return;
	}

	if(!impl->callback || impl->oneShot) {
		LOGD("ALL AT ONCE");
		asio::async_read(impl->c.getSocket(), impl->data, asio::transfer_exactly(size), [&](const asio::error_code &e, size_t n) {
			impl->state = State::DONE;
			if(impl->oneShot) {
				auto v8 = getContent();
				impl->callback(*this, v8);
			}
		});
		return;
	}

	//filled = data.in_avail();
	impl->total = 0;
	//buffer.reserve(chunkSize);

	impl->handler = [=](const asio::error_code &e, size_t n) {
		impl->data.commit(n);
		//LOGD("Read %d bytes, avail %d", n, impl->data.size());
		//n += filled;
		vector<uint8_t> buffer(impl->data.size());
		auto bufs = impl->data.data();
		copy(asio::buffers_begin(bufs), asio::buffers_end(bufs), buffer.begin());
		impl->total += impl->data.size();
		//LOGD("Total %d", impl->total);

		if(n == 0 || impl->total == impl->cntSize) {
			impl->state = State::DONE;
			LOGD("Done reading");
		}

		impl->callback(*this, buffer);

		if(impl->state == State::DONE) {
			LOGD("Request stop");
			return;
		}

		impl->data.consume(impl->data.size());
		auto mutableBuffer = impl->data.prepare(16384);
		impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
	};

	auto mutableBuffer = impl->data.prepare(16384);
	impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
}

vector<uint8_t> HttpSession::getContent() {
	auto sz = contentSize();
	vector<uint8_t> v8(sz);
	istream is(&impl->data);
	is.read((char*)&v8[0], sz);
	return v8;
}

string HttpSession::getHeader(const string &what) const {
	return impl->header[what];
}

void WebGetter::update() {

	lock_guard<mutex>{m};

	Connection::run();
	auto it = sessions.begin();
	while(it != sessions.end()) {
		auto s = *it;
		if(s->gotHeaders() && s->isRedirect()) {
			auto location = s->getHeader("Location");
			if(!startsWith(location, "http://")) {
				location = format("http://%s:%d%s", s->getHost(), s->getPort(), urlencode(location, ":\\?;+ "));
			}
			LOGD("Redirecting to '%s'", location);
			auto callback = s->getCallback();
			it = sessions.erase(it);
			sessions.emplace_back(make_shared<HttpSession>(location));
			sessions.back()->stream(callback);
			it = sessions.end();
			continue;
		}
		if(s->done()) {
			it = sessions.erase(it);
			LOGD("Session done");
		} else
			it++;
	}
}

WebGetter::WebGetter(const string &cacheDir) : cacheDir(cacheDir) {
	sessions.reserve(4);
	quit = false;
	workerThread = thread([&]() {
		while(!quit) {
			sleepms(50);
			update();
		}
	});
}

void WebGetter::getFile(const string &url, function<void(const File&)> callback) {

	string u = url;
	auto target = make_shared<File>(cacheDir + "/" + urlencode(url, ":/\\?;"));
	if(target->exists()) {
		callback(*target);
		return;
	}
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) {
		target->write(v);
		if(session.done()) {
			auto finalUrl = session.getUrl();
			target->close();
			if(finalUrl != url) {
				auto finalTarget = make_shared<File>(cacheDir + "/" + urlencode(finalUrl, ":/\\?;"));
				std::rename(target->getName().c_str(), finalTarget->getName().c_str());
				symlink(finalTarget->getName().c_str(), target->getName().c_str());
				callback(*finalTarget);
			} else
				callback(*target);
		}

	});
}

WebGetter::~WebGetter() {
	quit = true;
	workerThread.join();
}

void WebGetter::streamData(const string &url, function<bool(const uint8_t *data, int size)> callback) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	bool sizeReported = false;
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) mutable {
		if(!sizeReported) {
			sizeReported = true;
			LOGD("SIZE:%d", session.contentSize());
			if(!callback(nullptr, session.contentSize())) {
				session.stop();
				return;
			}
		}
		if(!callback(&v[0], v.size()))
			session.stop();
		else
		if(session.done())
			callback(nullptr, 0);
	});
}

int WebGetter::inProgress() { return 0; }

bool WebGetter::inCache(const std::string &url) const {
	auto target = File(cacheDir + "/" + urlencode(url, ":/\\?;"));
	return target.exists();
}

void WebGetter::getData(const std::string &url, std::function<void(const std::vector<uint8_t> &data)> cb) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->getData([=](HttpSession &session, const vector<uint8_t> &v) {
		cb(v);
	});

}

}
<commit_msg>urlencode and error handling for http get<commit_after>
#include "webgetter.h"
#include "net.h"

#include "asio/asio.hpp"

#include <coreutils/utils.h>
#include <coreutils/log.h>
#include <coreutils/file.h>

#include <vector>
#include <functional>
#include <cstdint>
#include <unordered_map>

using asio::ip::tcp;
using namespace std;
using namespace utils;

namespace net {

struct HttpSession::State {

	int chunkSize = 1024;
	int total;
	bool oneShot = false;
	std::string url;
	std::string host;
	std::string path;
	int port;
	std::function<void(const asio::error_code &e, size_t n)> handler;
	Callback callback;
	//std::vector<uint8_t> buffer;
	//std::shared_ptr<utils::File> file;
	Connection c;
	asio::streambuf data;
	std::unordered_map<std::string, std::string> header;
	int code;
	int headerSize;
	int cntSize;
	enum { NONE, CONNECT, HEADERS, DONE, EMPTY } state = NONE;

};

HttpSession::HttpSession(const string &url) : impl(make_shared<State>()) {

	int hostStart = 0;
	impl->port = 80;

	impl->url = url;

	LOGD("URL:%s", url);

	auto parts = split(url, "://");

	if(parts.size() == 2) {

	}

	if(startsWith(url, "http://"))
		hostStart = 7;

	int firstSlash = url.find_first_of('/', hostStart);
	impl->host = url.substr(hostStart, firstSlash - hostStart);
	impl->path = url.substr(firstSlash);
	int lastColon = impl->host.find_last_of(':');
	if(lastColon != string::npos) {
		impl->port = stol(impl->host.substr(lastColon+1));
		impl->host = impl->host.substr(0, lastColon);
	}

	LOGD("CONNECT %s %d", impl->host, impl->port);
	impl->c.connect(impl->host, impl->port);
	sendRequest(impl->path, impl->host);
}

HttpSession::HttpSession(HttpSession &&h) : impl(std::move(h.impl)) {
}

HttpSession& HttpSession::operator=(HttpSession &&h) {
	impl = std::move(h.impl);
	return *this;
}

void HttpSession::sendRequest(const string &path, const string &host) {
	string req = utils::format("GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", urlencode(path, ":\\?;+ "), host);
	LOGD("REQ %p:\n%s", this, req);
	LOGD("%d", impl->data.size());
	impl->c.write(req);
	impl->state = State::CONNECT;
	asio::async_read_until(impl->c.getSocket(), impl->data, "\r\n\r\n", [=](const asio::error_code &e, size_t n) {
		//LOGD("Read %d bytes", n);
		parseHeader();
		impl->state = State::HEADERS;
		//if(impl->code == 200)
		readContent();
		//else
		//	impl->state = State::ERROR;
	});
}

void HttpSession::parseHeader() {
	istream is(&impl->data);
	string line;
	getline(is, line);
	auto rc = split(line, " ");
	impl->code = stol(rc[1]);
	LOGD(">>%s", line);
	while(!is.eof()) {
		getline(is, line);
		if(line == "" || line == "\r")
			break;
		LOGD("%s", line);
		auto parts = split(line, ": ", 2);
		if(parts.size() == 2) {
			parts[1] = rstrip(rstrip(parts[1], '\n'), '\r');
			impl->header[parts[0]] = parts[1];
		}
	}
	auto cl = impl->header["Content-Length"];
	impl->cntSize = cl != "" ? stol(impl->header["Content-Length"]) : 0;
	if(isRedirect()) {
		LOGD("Should redirect to '%s'", impl->header["Location"]);
		//sleepms(500);
	}
}

int HttpSession::contentSize() const { return impl->cntSize; }

void HttpSession::stream(const Callback &cb) {
	impl->callback = cb;
}

void HttpSession::getData(const Callback &cb) {
	impl->oneShot = true;
	impl->callback = cb;
}

HttpSession::Callback HttpSession::getCallback() const {
	return impl->callback;
}

bool HttpSession::isRedirect() const { return impl->code == 303 || impl->code == 302 || impl->code == 307; }

int HttpSession::returnCode() const { return impl->code; }

int HttpSession::getPort() const { return impl->port; }
string HttpSession::getHost() const { return impl->host; }

bool HttpSession::gotHeaders() const { return impl->state == State::HEADERS || impl->state == State::DONE || impl->state == State::EMPTY; }
bool HttpSession::done() const { return impl->state == State::DONE || impl->state == State::EMPTY; }

std::string HttpSession::getUrl() const { return impl->url; }

void HttpSession::stop() { impl->state = State::DONE; }

void HttpSession::readContent() {
	int size = impl->cntSize - impl->data.in_avail();
	if(size <= 0) {
		LOGD("EMPTY");
		impl->state = State::EMPTY;
		if(!isRedirect()) {
			vector<uint8_t> v;
			impl->callback(*this, v);
		}
		return;
	}

	if(!impl->callback || impl->oneShot) {
		LOGD("ALL AT ONCE");
		asio::async_read(impl->c.getSocket(), impl->data, asio::transfer_exactly(size), [&](const asio::error_code &e, size_t n) {
			impl->state = State::DONE;
			if(impl->oneShot) {
				auto v8 = getContent();
				impl->callback(*this, v8);
			}
		});
		return;
	}

	//filled = data.in_avail();
	impl->total = 0;
	//buffer.reserve(chunkSize);

	impl->handler = [=](const asio::error_code &e, size_t n) {
		impl->data.commit(n);
		//LOGD("Read %d bytes, avail %d", n, impl->data.size());
		//n += filled;
		vector<uint8_t> buffer(impl->data.size());
		auto bufs = impl->data.data();
		copy(asio::buffers_begin(bufs), asio::buffers_end(bufs), buffer.begin());
		impl->total += impl->data.size();
		//LOGD("Total %d", impl->total);

		if(n == 0 || impl->total == impl->cntSize) {
			impl->state = State::DONE;
			LOGD("Done reading");
		}

		impl->callback(*this, buffer);

		if(impl->state == State::DONE) {
			LOGD("Request stop");
			return;
		}

		impl->data.consume(impl->data.size());
		auto mutableBuffer = impl->data.prepare(16384);
		impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
	};

	auto mutableBuffer = impl->data.prepare(16384);
	impl->c.getSocket().async_read_some(asio::buffer(mutableBuffer), impl->handler);
}

vector<uint8_t> HttpSession::getContent() {
	auto sz = contentSize();
	vector<uint8_t> v8(sz);
	istream is(&impl->data);
	is.read((char*)&v8[0], sz);
	return v8;
}

string HttpSession::getHeader(const string &what) const {
	return impl->header[what];
}

void WebGetter::update() {

	lock_guard<mutex>{m};

	Connection::run();
	auto it = sessions.begin();
	while(it != sessions.end()) {
		auto s = *it;
		if(s->gotHeaders() && s->isRedirect()) {
			auto location = s->getHeader("Location");
			if(!startsWith(location, "http://")) {
				location = format("http://%s:%d%s", s->getHost(), s->getPort(), urlencode(location, ":\\?;+ "));
			}
			LOGD("Redirecting to '%s'", location);
			auto callback = s->getCallback();
			it = sessions.erase(it);
			sessions.emplace_back(make_shared<HttpSession>(location));
			sessions.back()->stream(callback);
			it = sessions.end();
			continue;
		}
		if(s->done()) {
			it = sessions.erase(it);
			LOGD("Session done");
		} else
			it++;
	}
}

WebGetter::WebGetter(const string &cacheDir) : cacheDir(cacheDir) {
	sessions.reserve(4);
	quit = false;
	workerThread = thread([&]() {
		while(!quit) {
			sleepms(50);
			update();
		}
	});
}

void WebGetter::getFile(const string &url, function<void(const File&)> callback) {

	string u = url;
	auto target = make_shared<File>(cacheDir + "/" + urlencode(url, ":/\\?;"));
	if(target->exists() && target->getSize() > 0) {
		callback(*target);
		return;
	}
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) {
		target->write(v);
		if(session.done()) {
			auto finalUrl = session.getUrl();
			target->close();
			if(session.returnCode() != 200) {
				target->remove();
				callback(File::NO_FILE);
			} else
			if(finalUrl != url) {
				auto finalTarget = make_shared<File>(cacheDir + "/" + urlencode(finalUrl, ":/\\?;"));
				std::rename(target->getName().c_str(), finalTarget->getName().c_str());
				symlink(finalTarget->getName().c_str(), target->getName().c_str());
				callback(*finalTarget);
			} else
				callback(*target);
		}

	});
}

WebGetter::~WebGetter() {
	quit = true;
	workerThread.join();
}

void WebGetter::streamData(const string &url, function<bool(const uint8_t *data, int size)> callback) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	bool sizeReported = false;
	sessions.back()->stream([=](HttpSession &session, const vector<uint8_t> &v) mutable {
		if(!sizeReported) {
			sizeReported = true;
			LOGD("SIZE:%d", session.contentSize());
			if(!callback(nullptr, session.contentSize())) {
				session.stop();
				return;
			}
		}
		if(!callback(&v[0], v.size()))
			session.stop();
		else
		if(session.done())
			callback(nullptr, 0);
	});
}

int WebGetter::inProgress() { return 0; }

bool WebGetter::inCache(const std::string &url) const {
	auto target = File(cacheDir + "/" + urlencode(url, ":/\\?;"));
	return target.exists();
}

void WebGetter::getData(const std::string &url, std::function<void(const std::vector<uint8_t> &data)> cb) {
	lock_guard<mutex>{m};
	sessions.emplace_back(make_shared<HttpSession>(url));
	sessions.back()->getData([=](HttpSession &session, const vector<uint8_t> &v) {
		cb(v);
	});

}

}
<|endoftext|>


<commit_before>#include "mapper_001.h"

#include <cassert>
#include <cstdio>
#include <cstring>

Mapper_001::Mapper_001(const ROM_File& rom_file)
: Mapper(1, "MMC1", rom_file, 0x4000, 0x1000)
, prg_ram(0x2000)
{ this->initial_mirror_mode = rom_file.meta.mirror_mode; }

// reading has no side-effects
u8 Mapper_001::peek(u16 addr) const {
  // Wired to the PPU MMU
  if (in_range(addr, 0x0000, 0x0FFF)) return this->chr_lo->peek(addr - 0x0000);
  if (in_range(addr, 0x1000, 0x1FFF)) return this->chr_hi->peek(addr - 0x1000);

  // Wired to the CPU MMU
  if (in_range(addr, 0x4020, 0x5FFF)) return 0x00; // Nothing in "Expansion ROM"
  if (in_range(addr, 0x6000, 0x7FFF)) return this->reg.prg.ram_enable == 0
                                           ? this->prg_ram.peek(addr - 0x6000)
                                           : 0x00; // should be open bus...
  if (in_range(addr, 0x8000, 0xBFFF)) return this->prg_lo->peek(addr - 0x8000);
  if (in_range(addr, 0xC000, 0xFFFF)) return this->prg_hi->peek(addr - 0xC000);

  assert(false);
  return 0x00;
}

void Mapper_001::write(u16 addr, u8 val) {
  // If writing to RAM, do it, and then return
  if (in_range(addr, 0x0000, 0x0FFF)) return this->chr_lo->write(addr - 0x0000, val);
  if (in_range(addr, 0x1000, 0x1FFF)) return this->chr_hi->write(addr - 0x1000, val);
  if (in_range(addr, 0x4020, 0x5FFF)) return; // do nothing to expansion ROM
  if (in_range(addr, 0x6000, 0x7FFF)) {
    // 0 means RAM is _enabled_. because fuck you that's why.
    return (this->reg.prg.ram_enable == 0)
      ? this->prg_ram.write(addr - 0x6000, val)
      : void();
  }

  // Otherwise, handle writing to registers

  if (this->write_just_happened) return;
  this->write_just_happened = 6;

  // "Unlike almost all other mappers, the MMC1 is configured through a serial
  //  port in order to reduce pin count." - Wiki
  // Yep, that's right! There is not direct writes to internal registers!
  // Instead, one carfeuly loads data into an internal shift register by writing
  // to the cartridge's address space 5 times, with the address of the final
  // write designating which internal register to load the shift register into!
  // WEEEEEE
  //
  // Anywhere from 0x8000 ... 0xFFFF
  // 7  bit  0
  // ---- ----
  // Rxxx xxxD
  // |       |
  // |       +- Data bit to be shifted into shift register, LSB first
  // +--------- 1: Reset shift register and write Control with (Control OR $0C),
  //               locking PRG ROM at $C000-$FFFF to the last bank.

  if (nth_bit(val, 7) == 1) {
    // Reset SR
    this->reg.sr = 0x10;
    this->reg.control.prg_bank_mode = 3;
  } else {
    bool done = this->reg.sr & 1; // sentinel bit
    // Just to make life interesting, the shift register is filled from LSB to
    // MSB, which complicates loading a little bit.
    this->reg.sr >>= 1;
    this->reg.sr |= (val & 1) << 4;
    if (done) {
      // Write the shift register to the appropriate internal register based on
      // what range this final write occured in.
      const u8 sr = this->reg.sr;
      if (in_range(addr, 0x8000, 0x9FFF)) { this->reg.control.val = sr; }
      if (in_range(addr, 0xA000, 0xBFFF)) { this->reg.chr0.val    = sr; }
      if (in_range(addr, 0xC000, 0xDFFF)) { this->reg.chr1.val    = sr; }
      if (in_range(addr, 0xE000, 0xFFFF)) { this->reg.prg.val     = sr; }
      this->reg.sr = 0x10; // and reset the shift-register

      this->update_banks();
    }
  }
}

void Mapper_001::update_banks() {
  // Update PRG Banks
  switch(u8(this->reg.control.prg_bank_mode)) {
  case 0: case 1: {
    // switch 32 KB at $8000, ignoring low bit of bank number
    this->prg_lo = &this->get_prg_bank(this->reg.prg.bank & 0xFE);
    this->prg_hi = &this->get_prg_bank(this->reg.prg.bank | 0x01);
  } break;
  case 2: {
    // fix first bank at $8000 and switch 16 KB bank at $C000;
    this->prg_lo = &this->get_prg_bank(0);
    this->prg_hi = &this->get_prg_bank(this->reg.prg.bank);
  } break;
  case 3: {
    // fix last bank at $C000 and switch 16 KB bank at $8000
    this->prg_lo = &this->get_prg_bank(this->reg.prg.bank);
    this->prg_hi = &this->get_prg_bank(this->get_prg_bank_len() - 1);
  } break;
  default:
    // This should never happen. 2 bits == 4 possible states.
    fprintf(stderr, "[Mapper_001] Unhandled bank mode case %u. Dying...\n",
      u8(this->reg.control.prg_bank_mode));
    assert(false);
    break;
  }

  // Update CHR Banks
  if (this->reg.control.chr_bank_mode == 0) {
    // switch 8 KB at a time (ignoring low bit)
    this->chr_lo = &this->get_chr_bank(this->reg.chr0.bank & 0xFE);
    this->chr_hi = &this->get_chr_bank(this->reg.chr0.bank | 0x01);
  } else {
    // switch two separate 4 KB banks
    this->chr_lo = &this->get_chr_bank(this->reg.chr0.bank);
    this->chr_hi = &this->get_chr_bank(this->reg.chr1.bank);
  }
}

Mirroring::Type Mapper_001::mirroring() const {
  switch(u8(this->reg.control.mirroring)) {
  case 0: return Mirroring::SingleScreenLo;
  case 1: return Mirroring::SingleScreenHi;
  case 2: return Mirroring::Vertical;
  case 3: return Mirroring::Horizontal;
  default:
    // This should never happen. 2 bits == 4 possible states.
    fprintf(stderr, "[Mapper_001] Unhandled mirroring case %u. Dying...\n",
      u8(this->reg.control.mirroring));
    assert(false);
    return Mirroring::INVALID;
  }
}

void Mapper_001::cycle() {
  if (this->write_just_happened)
    this->write_just_happened--;
}

void Mapper_001::power_cycle() {
  this->write_just_happened = 0;
  Mapper::power_cycle();
}

void Mapper_001::reset() {
  memset(&this->reg, 0, sizeof this->reg);
  this->reg.sr = 0x10;

  // This isn't documented anywhere, but seems to be needed...
  this->reg.control.prg_bank_mode = 3;

  // Set back to initial mirroring mode
  switch(this->initial_mirror_mode) {
  case Mirroring::SingleScreenLo: this->reg.control.mirroring = 0; break;
  case Mirroring::SingleScreenHi: this->reg.control.mirroring = 1; break;
  case Mirroring::Vertical:       this->reg.control.mirroring = 2; break;
  case Mirroring::Horizontal:     this->reg.control.mirroring = 3; break;
  default:
    fprintf(stderr, "[Mapper_001] Invalid initial mirroring mode!\n");
    assert(false);
    break;
  }
}

<commit_msg>Update mapper_001.cc<commit_after>#include "mapper_001.h"

#include <cassert>
#include <cstdio>
#include <cstring>

Mapper_001::Mapper_001(const ROM_File& rom_file)
: Mapper(1, "MMC1", rom_file, 0x4000, 0x1000)
, prg_ram(0x2000)
{ this->initial_mirror_mode = rom_file.meta.mirror_mode; }

// reading has no side-effects
u8 Mapper_001::peek(u16 addr) const {
  // Wired to the PPU MMU
  if (in_range(addr, 0x0000, 0x0FFF)) return this->chr_lo->peek(addr - 0x0000);
  if (in_range(addr, 0x1000, 0x1FFF)) return this->chr_hi->peek(addr - 0x1000);

  // Wired to the CPU MMU
  if (in_range(addr, 0x4020, 0x5FFF)) return 0x00; // Nothing in "Expansion ROM"
  if (in_range(addr, 0x6000, 0x7FFF)) return this->reg.prg.ram_enable == 0
                                           ? this->prg_ram.peek(addr - 0x6000)
                                           : 0x00; // should be open bus...
  if (in_range(addr, 0x8000, 0xBFFF)) return this->prg_lo->peek(addr - 0x8000);
  if (in_range(addr, 0xC000, 0xFFFF)) return this->prg_hi->peek(addr - 0xC000);

  assert(false);
  return 0x00;
}

void Mapper_001::write(u16 addr, u8 val) {
  // If writing to RAM, do it, and then return
  if (in_range(addr, 0x0000, 0x0FFF)) return this->chr_lo->write(addr - 0x0000, val);
  if (in_range(addr, 0x1000, 0x1FFF)) return this->chr_hi->write(addr - 0x1000, val);
  if (in_range(addr, 0x4020, 0x5FFF)) return; // do nothing to expansion ROM
  if (in_range(addr, 0x6000, 0x7FFF)) {
    // 0 means RAM is _enabled_. because fuck you that's why.
    return (this->reg.prg.ram_enable == 0)
      ? this->prg_ram.write(addr - 0x6000, val)
      : void();
  }

  // Otherwise, handle writing to registers

  if (this->write_just_happened) return;
  this->write_just_happened = 6;

  // "Unlike almost all other mappers, the MMC1 is configured through a serial
  //  port in order to reduce pin count." - Wiki
  // Yep, that's right! There is not direct writes to internal registers!
  // Instead, one carfeuly loads data into an internal shift register by writing
  // to the cartridge's address space 5 times, with the address of the final
  // write designating which internal register to load the shift register into!
  // WEEEEEE
  //
  // Anywhere from 0x8000 ... 0xFFFF
  // 7  bit  0
  // ---- ----
  // Rxxx xxxD
  // |       |
  // |       +- Data bit to be shifted into shift register, LSB first
  // +--------- 1: Reset shift register and write Control with (Control OR $0C),
  //               locking PRG ROM at $C000-$FFFF to the last bank.

  if (nth_bit(val, 7) == 1) {
    // Reset SR
    this->reg.sr = 0x10;
    this->reg.control.prg_bank_mode = 3;
  } else {
    bool done = this->reg.sr & 1; // sentinel bit
    // Just to make life interesting, the shift register is filled from LSB to
    // MSB, which complicates loading a little bit.
    this->reg.sr >>= 1;
    this->reg.sr |= (val & 1) << 4;
    if (done) {
      // Write the shift register to the appropriate internal register based on
      // what range this final write occured in.
      const u8 sr = this->reg.sr;
      if (in_range(addr, 0x8000, 0x9FFF)) { this->reg.control.val = sr; }
      if (in_range(addr, 0xA000, 0xBFFF)) { this->reg.chr0.val    = sr; }
      if (in_range(addr, 0xC000, 0xDFFF)) { this->reg.chr1.val    = sr; }
      if (in_range(addr, 0xE000, 0xFFFF)) { this->reg.prg.val     = sr; }
      this->reg.sr = 0x10; // and reset the shift-register

      this->update_banks();
    }
  }
}

void Mapper_001::update_banks() {
  // Update PRG Banks
  switch(u8(this->reg.control.prg_bank_mode)) {
  case 0: case 1: {
    // switch 32 KB at $8000, ignoring low bit of bank number
    this->prg_lo = &this->get_prg_bank(this->reg.prg.bank & 0xFE);
    this->prg_hi = &this->get_prg_bank(this->reg.prg.bank | 0x01);
  } break;
  case 2: {
    // fix first bank at $8000 and switch 16 KB bank at $C000;
    this->prg_lo = &this->get_prg_bank(0);
    this->prg_hi = &this->get_prg_bank(this->reg.prg.bank);
  } break;
  case 3: {
    // fix last bank at $C000 and switch 16 KB bank at $8000
    this->prg_lo = &this->get_prg_bank(this->reg.prg.bank);
    this->prg_hi = &this->get_prg_bank(this->get_prg_bank_len() - 1);
  } break;
  default:
    // This should never happen. 2 bits == 4 possible states.
    fprintf(stderr, "[Mapper_001] Unhandled bank mode case %u. Dying...\n",
      u8(this->reg.control.prg_bank_mode));
    assert(false);
    break;
  }

  // Update CHR Banks
  if (this->reg.control.chr_bank_mode == 0) {
    // switch 8 KB at a time (ignoring low bit)
    this->chr_lo = &this->get_chr_bank(this->reg.chr0.bank & 0xFE);
    this->chr_hi = &this->get_chr_bank(this->reg.chr0.bank | 0x01);
  } else {
    // switch two separate 4 KB banks
    this->chr_lo = &this->get_chr_bank(this->reg.chr0.bank);
    this->chr_hi = &this->get_chr_bank(this->reg.chr1.bank);
  }
}

Mirroring::Type Mapper_001::mirroring() const {
  switch(u8(this->reg.control.mirroring)) {
  case 0: return Mirroring::SingleScreenLo;
  case 1: return Mirroring::SingleScreenHi;
  case 2: return Mirroring::Vertical;
  case 3: return Mirroring::Horizontal;
  default:
    // This should never happen. 2 bits == 4 possible states.
    fprintf(stderr, "[Mapper_001] Unhandled mirroring case %u. Dying...\n",
      u8(this->reg.control.mirroring));
    assert(false);
    return Mirroring::INVALID;
  }
}

void Mapper_001::cycle() {
  if (this->write_just_happened)
    this->write_just_happened--;
}

void Mapper_001::power_cycle() {
  this->write_just_happened = 0;
  Mapper::power_cycle();
}

void Mapper_001::reset() {
  memset((char*)&this->reg, 0, sizeof this->reg);
  this->reg.sr = 0x10;

  // This isn't documented anywhere, but seems to be needed...
  this->reg.control.prg_bank_mode = 3;

  // Set back to initial mirroring mode
  switch(this->initial_mirror_mode) {
  case Mirroring::SingleScreenLo: this->reg.control.mirroring = 0; break;
  case Mirroring::SingleScreenHi: this->reg.control.mirroring = 1; break;
  case Mirroring::Vertical:       this->reg.control.mirroring = 2; break;
  case Mirroring::Horizontal:     this->reg.control.mirroring = 3; break;
  default:
    fprintf(stderr, "[Mapper_001] Invalid initial mirroring mode!\n");
    assert(false);
    break;
  }
}

<|endoftext|>


<commit_before>#include "FSM.h"
#include "oled_func.h"
#include "images.h"

void State_Machine(void)
{
	if (strcmp(str_ClientState, "PRE_GAME") == 0)
	{
		//update_oled_pregame(); Hier evtl Team Bekanntgabe? Oder Punkteanzeige (also wie viel pkt pro kill oder so?)
	}
	else if (strcmp(str_ClientState, "STARTING_GAME") == 0)
	{
		//10Sekunden OLED runterzaehlen -> Funktion von Philipp??
	else if (strcmp(str_ClientState, "IN_GAME"))
	{
		update_oled_active();
		if (i_GotHit != 0)
		{
			update_oled_hit();
		}
	}
	else if (strcmp(str_ClientState, "END_GAME") == 0)
	{
		// funktion zur Bekanntgabe der Points bzw. Kill/Ratio?
	}
	else
	{
		// Funktion das Verbindung abgebrochen ist?
		// oder versuchen neue verbindung aufzubauen?
	}
}
<commit_msg>1. Änderung der States in die korrekte form "-" als Bindeglied, nicht "_", sonst error beim String parsen. 2. einfügen der oled_lage zum regelmäßigen updaten, sonst volle prozessorauslastung durch oled 3. Kommentare geändert und unnötige includes entfernt<commit_after>#include "FSM.h"

void State_Machine(void)
{
	if (strcmp(str_ClientState, "PRE-GAME") == 0)
	{
		if (oled_flag == 1)
		{
			//update_oled_pregame(); Hier evtl Team Bekanntgabe? Oder Punkteanzeige (also wie viel pkt pro kill oder so?)
			update_oled_wifidata();
		}
	}
	else if (strcmp(str_ClientState, "STARTING-GAME") == 0)
	{
		if (oled_flag == 1)
		{
			//update_oled_startinggame();
			//10Sekunden OLED runterzaehlen -> Funktion von Philipp??
		}
	}

	else if (strcmp(str_ClientState, "IN-GAME"))
	{
		if (oled_flag == 1)
		{
			if (i_GotHit != 0)
			{
				//update_oled_hit();
			}
			else
			{
				//update_oled_active();
			}
			oled_flag = 0;
		}
	}
	else if (strcmp(str_ClientState, "END-GAME") == 0)
	{
		if (oled_flag == 1)
		{
			// funktion zur Bekanntgabe der Points bzw. Kill/Ratio?
			//update_oled_endgame();
		}
	}
	else
	{
	// kein gltiger state? evlt error_function();
	}
}
<|endoftext|>


<commit_before>#include "logvisor/logvisor.hpp"
#include "boo/boo.hpp"
#include "specter/specter.hpp"
#include "hecl/CVarManager.hpp"
#include "Runtime/CBasics.hpp"
#include "ViewManager.hpp"
#include "hecl/hecl.hpp"
#include "hecl/CVarCommons.hpp"
#include "hecl/Console.hpp"
#include "fmt/chrono.h"

static logvisor::Module AthenaLog("Athena");
static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, fmt::string_view fmt,
                      fmt::format_args args) {
  AthenaLog.vreport(logvisor::Level(level), fmt, args);
}

namespace urde {
static logvisor::Module Log{"URDE"};

static hecl::SystemString CPUFeatureString(const zeus::CPUInfo& cpuInf) {
  hecl::SystemString features;
  auto AddFeature = [&features](const hecl::SystemChar* str) {
    if (!features.empty())
      features += _SYS_STR(", ");
    features += str;
  };
#if __x86_64__
  if (cpuInf.AESNI)
    AddFeature(_SYS_STR("AES-NI"));
  if (cpuInf.SSE1)
    AddFeature(_SYS_STR("SSE"));
  if (cpuInf.SSE2)
    AddFeature(_SYS_STR("SSE2"));
  if (cpuInf.SSE3)
    AddFeature(_SYS_STR("SSE3"));
  if (cpuInf.SSSE3)
    AddFeature(_SYS_STR("SSSE3"));
  if (cpuInf.SSE4a)
    AddFeature(_SYS_STR("SSE4a"));
  if (cpuInf.SSE41)
    AddFeature(_SYS_STR("SSE4.1"));
  if (cpuInf.SSE42)
    AddFeature(_SYS_STR("SSE4.2"));
  if (cpuInf.AVX)
    AddFeature(_SYS_STR("AVX"));
  if (cpuInf.AVX2)
    AddFeature(_SYS_STR("AVX2"));
#endif
  return features;
}

struct Application : boo::IApplicationCallback {
  hecl::Runtime::FileStoreManager& m_fileMgr;
  hecl::CVarManager& m_cvarManager;
  hecl::CVarCommons& m_cvarCommons;
  std::unique_ptr<ViewManager> m_viewManager;

  std::atomic_bool m_running = {true};

  Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
  : m_fileMgr(fileMgr)
  , m_cvarManager(cvarMgr)
  , m_cvarCommons(cvarCmns)
  , m_viewManager(std::make_unique<ViewManager>(m_fileMgr, m_cvarManager)) {}

  virtual ~Application() = default;

  int appMain(boo::IApplication* app) override {
    initialize(app);
    m_viewManager->init(app);
    while (m_running.load()) {
      if (!m_viewManager->proc())
        break;
    }
    m_viewManager->stop();
    m_viewManager->projectManager().saveProject();
    m_cvarManager.serialize();
    m_viewManager.reset();
    return 0;
  }
  void appQuitting(boo::IApplication*) override { m_running.store(false); }
  void appFilesOpen(boo::IApplication*, const std::vector<boo::SystemString>& paths) override {
    for (const auto& path : paths) {
      hecl::ProjectRootPath projPath = hecl::SearchForProject(path);
      if (projPath) {
        m_viewManager->deferOpenProject(path);
        break;
      }
    }
  }

  void initialize(boo::IApplication* app) {
    zeus::detectCPU();

    for (const boo::SystemString& arg : app->getArgs()) {
      if (arg.find(_SYS_STR("--verbosity=")) == 0 || arg.find(_SYS_STR("-v=")) == 0) {
        hecl::SystemUTF8Conv utf8Arg(arg.substr(arg.find_last_of('=') + 1));
        hecl::VerbosityLevel = atoi(utf8Arg.c_str());
        hecl::LogModule.report(logvisor::Info, FMT_STRING("Set verbosity level to {}"), hecl::VerbosityLevel);
      }
    }

    const zeus::CPUInfo& cpuInf = zeus::cpuFeatures();
    Log.report(logvisor::Info, FMT_STRING("CPU Name: {}"), cpuInf.cpuBrand);
    Log.report(logvisor::Info, FMT_STRING("CPU Vendor: {}"), cpuInf.cpuVendor);
    Log.report(logvisor::Info, FMT_STRING(_SYS_STR("CPU Features: {}")), CPUFeatureString(cpuInf));
  }

  std::string getGraphicsApi() const { return m_cvarCommons.getGraphicsApi(); }

  uint32_t getSamples() const { return m_cvarCommons.getSamples(); }

  uint32_t getAnisotropy() const { return m_cvarCommons.getAnisotropy(); }

  bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }

  int64_t getTargetFrameTime() { return m_cvarCommons.getVariableFrameTime() ? 0 : 1000000000L / 60; }
};

} // namespace urde

static hecl::SystemChar CwdBuf[1024];
hecl::SystemString ExeDir;

static void SetupBasics(bool logging) {
  auto result = zeus::validateCPU();
  if (!result.first) {
#if _WIN32 && !WINDOWS_STORE
    std::wstring msg = fmt::format(FMT_STRING(L"ERROR: This build of URDE requires the following CPU features:\n{}\n"),
                                   urde::CPUFeatureString(result.second));
    MessageBoxW(nullptr, msg.c_str(), L"CPU error", MB_OK | MB_ICONERROR);
#else
    fmt::print(stderr, FMT_STRING("ERROR: This build of URDE requires the following CPU features:\n{}\n"),
               urde::CPUFeatureString(result.second));
#endif
    exit(1);
  }

  logvisor::RegisterStandardExceptions();
  if (logging)
    logvisor::RegisterConsoleLogger();
  atSetExceptionHandler(AthenaExc);
}

static bool IsClientLoggingEnabled(int argc, const boo::SystemChar** argv) {
  for (int i = 1; i < argc; ++i)
    if (!hecl::StrNCmp(argv[i], _SYS_STR("-l"), 2))
      return true;
  return false;
}

#if !WINDOWS_STORE
#if _WIN32
int wmain(int argc, const boo::SystemChar** argv)
#else
int main(int argc, const boo::SystemChar** argv)
#endif
{
  if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) {
    fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE);
    return 100;
  }

  SetupBasics(IsClientLoggingEnabled(argc, argv));
  hecl::Runtime::FileStoreManager fileMgr{_SYS_STR("urde")};
  hecl::CVarManager cvarMgr{fileMgr};
  hecl::CVarCommons cvarCmns{cvarMgr};

  std::vector<boo::SystemString> args;
  for (int i = 1; i < argc; ++i)
    args.push_back(argv[i]);
  cvarMgr.parseCommandLine(args);

  hecl::SystemString logFile{hecl::SystemStringConv(cvarCmns.getLogFile()).c_str()};
  hecl::SystemString logFilePath;
  if (!logFile.empty()) {
    std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    char buf[100];
    std::strftime(buf, 100, "%Y-%m-%d_%H-%M-%S\0", std::localtime(&time));
    hecl::SystemString timeStr = hecl::SystemStringConv(buf).c_str();
    logFilePath = fmt::format(FMT_STRING(_SYS_STR("{}/{}-{}")), fileMgr.getStoreRoot(), timeStr, logFile);
    logvisor::RegisterFileLogger(logFilePath.c_str());
  }

  if (hecl::SystemChar* cwd = hecl::Getcwd(CwdBuf, 1024)) {
    if (hecl::PathRelative(argv[0]))
      ExeDir = hecl::SystemString(cwd) + _SYS_STR('/');
    hecl::SystemString Argv0(argv[0]);
    hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\"));
    if (lastIdx != hecl::SystemString::npos)
      ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx);
  }

  /* Handle -j argument */
  hecl::SetCpuCountOverride(argc, argv);

  urde::Application appCb(fileMgr, cvarMgr, cvarCmns);
  int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, appCb, _SYS_STR("urde"), _SYS_STR("URDE"), argc,
                                argv, appCb.getGraphicsApi(), appCb.getSamples(), appCb.getAnisotropy(),
                                appCb.getDeepColor(), appCb.getTargetFrameTime(), false);
  // printf("IM DYING!!\n");
  return ret;
}
#endif

#if WINDOWS_STORE
#include "boo/UWPViewProvider.hpp"
using namespace Windows::ApplicationModel::Core;

[Platform::MTAThread] int WINAPIV main(Platform::Array<Platform::String ^> ^ params) {
  SetupBasics(false);
  urde::Application appCb;
  auto viewProvider =
      ref new boo::ViewProvider(appCb, _SYS_STR("urde"), _SYS_STR("URDE"), _SYS_STR("urde"), params, false);
  CoreApplication::Run(viewProvider);
  return 0;
}

#elif _WIN32
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) {
  int argc = 0;
  const boo::SystemChar** argv;
  if (lpCmdLine[0])
    argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
  static boo::SystemChar selfPath[1024];
  GetModuleFileNameW(nullptr, selfPath, 1024);
  static const boo::SystemChar* booArgv[32] = {};
  booArgv[0] = selfPath;
  for (int i = 0; i < argc; ++i)
    booArgv[i + 1] = argv[i];

  const DWORD outType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
  if (IsClientLoggingEnabled(argc + 1, booArgv) && outType == FILE_TYPE_UNKNOWN)
    logvisor::CreateWin32Console();
  return wmain(argc + 1, booArgv);
}
#endif
<commit_msg>Editor: GCC warning fixes<commit_after>#include "logvisor/logvisor.hpp"
#include "boo/boo.hpp"
#include "specter/specter.hpp"
#include "hecl/CVarManager.hpp"
#include "Runtime/CBasics.hpp"
#include "ViewManager.hpp"
#include "hecl/hecl.hpp"
#include "hecl/CVarCommons.hpp"
#include "hecl/Console.hpp"
#include "fmt/chrono.h"

static logvisor::Module AthenaLog("Athena");
static void AthenaExc(athena::error::Level level, const char* file, const char*, int line, fmt::string_view fmt,
                      fmt::format_args args) {
  AthenaLog.vreport(logvisor::Level(level), fmt, args);
}

namespace urde {
static logvisor::Module Log{"URDE"};

static hecl::SystemString CPUFeatureString(const zeus::CPUInfo& cpuInf) {
  hecl::SystemString features;
#if __x86_64__
  auto AddFeature = [&features](const hecl::SystemChar* str) {
    if (!features.empty())
      features += _SYS_STR(", ");
    features += str;
  };
  if (cpuInf.AESNI)
    AddFeature(_SYS_STR("AES-NI"));
  if (cpuInf.SSE1)
    AddFeature(_SYS_STR("SSE"));
  if (cpuInf.SSE2)
    AddFeature(_SYS_STR("SSE2"));
  if (cpuInf.SSE3)
    AddFeature(_SYS_STR("SSE3"));
  if (cpuInf.SSSE3)
    AddFeature(_SYS_STR("SSSE3"));
  if (cpuInf.SSE4a)
    AddFeature(_SYS_STR("SSE4a"));
  if (cpuInf.SSE41)
    AddFeature(_SYS_STR("SSE4.1"));
  if (cpuInf.SSE42)
    AddFeature(_SYS_STR("SSE4.2"));
  if (cpuInf.AVX)
    AddFeature(_SYS_STR("AVX"));
  if (cpuInf.AVX2)
    AddFeature(_SYS_STR("AVX2"));
#endif
  return features;
}

struct Application : boo::IApplicationCallback {
  hecl::Runtime::FileStoreManager& m_fileMgr;
  hecl::CVarManager& m_cvarManager;
  hecl::CVarCommons& m_cvarCommons;
  std::unique_ptr<ViewManager> m_viewManager;

  std::atomic_bool m_running = {true};

  Application(hecl::Runtime::FileStoreManager& fileMgr, hecl::CVarManager& cvarMgr, hecl::CVarCommons& cvarCmns)
  : m_fileMgr(fileMgr)
  , m_cvarManager(cvarMgr)
  , m_cvarCommons(cvarCmns)
  , m_viewManager(std::make_unique<ViewManager>(m_fileMgr, m_cvarManager)) {}

  virtual ~Application() = default;

  int appMain(boo::IApplication* app) override {
    initialize(app);
    m_viewManager->init(app);
    while (m_running.load()) {
      if (!m_viewManager->proc())
        break;
    }
    m_viewManager->stop();
    m_viewManager->projectManager().saveProject();
    m_cvarManager.serialize();
    m_viewManager.reset();
    return 0;
  }
  void appQuitting(boo::IApplication*) override { m_running.store(false); }
  void appFilesOpen(boo::IApplication*, const std::vector<boo::SystemString>& paths) override {
    for (const auto& path : paths) {
      hecl::ProjectRootPath projPath = hecl::SearchForProject(path);
      if (projPath) {
        m_viewManager->deferOpenProject(path);
        break;
      }
    }
  }

  void initialize(boo::IApplication* app) {
    zeus::detectCPU();

    for (const boo::SystemString& arg : app->getArgs()) {
      if (arg.find(_SYS_STR("--verbosity=")) == 0 || arg.find(_SYS_STR("-v=")) == 0) {
        hecl::SystemUTF8Conv utf8Arg(arg.substr(arg.find_last_of('=') + 1));
        hecl::VerbosityLevel = atoi(utf8Arg.c_str());
        hecl::LogModule.report(logvisor::Info, FMT_STRING("Set verbosity level to {}"), hecl::VerbosityLevel);
      }
    }

    const zeus::CPUInfo& cpuInf = zeus::cpuFeatures();
    Log.report(logvisor::Info, FMT_STRING("CPU Name: {}"), cpuInf.cpuBrand);
    Log.report(logvisor::Info, FMT_STRING("CPU Vendor: {}"), cpuInf.cpuVendor);
    Log.report(logvisor::Info, FMT_STRING(_SYS_STR("CPU Features: {}")), CPUFeatureString(cpuInf));
  }

  std::string getGraphicsApi() const { return m_cvarCommons.getGraphicsApi(); }

  uint32_t getSamples() const { return m_cvarCommons.getSamples(); }

  uint32_t getAnisotropy() const { return m_cvarCommons.getAnisotropy(); }

  bool getDeepColor() const { return m_cvarCommons.getDeepColor(); }

  int64_t getTargetFrameTime() { return m_cvarCommons.getVariableFrameTime() ? 0 : 1000000000L / 60; }
};

} // namespace urde

static hecl::SystemChar CwdBuf[1024];
hecl::SystemString ExeDir;

static void SetupBasics(bool logging) {
  auto result = zeus::validateCPU();
  if (!result.first) {
#if _WIN32 && !WINDOWS_STORE
    std::wstring msg = fmt::format(FMT_STRING(L"ERROR: This build of URDE requires the following CPU features:\n{}\n"),
                                   urde::CPUFeatureString(result.second));
    MessageBoxW(nullptr, msg.c_str(), L"CPU error", MB_OK | MB_ICONERROR);
#else
    fmt::print(stderr, FMT_STRING("ERROR: This build of URDE requires the following CPU features:\n{}\n"),
               urde::CPUFeatureString(result.second));
#endif
    exit(1);
  }

  logvisor::RegisterStandardExceptions();
  if (logging)
    logvisor::RegisterConsoleLogger();
  atSetExceptionHandler(AthenaExc);
}

static bool IsClientLoggingEnabled(int argc, const boo::SystemChar** argv) {
  for (int i = 1; i < argc; ++i)
    if (!hecl::StrNCmp(argv[i], _SYS_STR("-l"), 2))
      return true;
  return false;
}

#if !WINDOWS_STORE
#if _WIN32
int wmain(int argc, const boo::SystemChar** argv)
#else
int main(int argc, const boo::SystemChar** argv)
#endif
{
  if (argc > 1 && !hecl::StrCmp(argv[1], _SYS_STR("--dlpackage"))) {
    fmt::print(FMT_STRING("{}\n"), URDE_DLPACKAGE);
    return 100;
  }

  SetupBasics(IsClientLoggingEnabled(argc, argv));
  hecl::Runtime::FileStoreManager fileMgr{_SYS_STR("urde")};
  hecl::CVarManager cvarMgr{fileMgr};
  hecl::CVarCommons cvarCmns{cvarMgr};

  std::vector<boo::SystemString> args;
  for (int i = 1; i < argc; ++i)
    args.push_back(argv[i]);
  cvarMgr.parseCommandLine(args);

  hecl::SystemString logFile{hecl::SystemStringConv(cvarCmns.getLogFile()).c_str()};
  hecl::SystemString logFilePath;
  if (!logFile.empty()) {
    std::time_t time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
    char buf[100];
    std::strftime(buf, 100, "%Y-%m-%d_%H-%M-%S", std::localtime(&time));
    hecl::SystemString timeStr = hecl::SystemStringConv(buf).c_str();
    logFilePath = fmt::format(FMT_STRING(_SYS_STR("{}/{}-{}")), fileMgr.getStoreRoot(), timeStr, logFile);
    logvisor::RegisterFileLogger(logFilePath.c_str());
  }

  if (hecl::SystemChar* cwd = hecl::Getcwd(CwdBuf, 1024)) {
    if (hecl::PathRelative(argv[0]))
      ExeDir = hecl::SystemString(cwd) + _SYS_STR('/');
    hecl::SystemString Argv0(argv[0]);
    hecl::SystemString::size_type lastIdx = Argv0.find_last_of(_SYS_STR("/\\"));
    if (lastIdx != hecl::SystemString::npos)
      ExeDir.insert(ExeDir.end(), Argv0.begin(), Argv0.begin() + lastIdx);
  }

  /* Handle -j argument */
  hecl::SetCpuCountOverride(argc, argv);

  urde::Application appCb(fileMgr, cvarMgr, cvarCmns);
  int ret = boo::ApplicationRun(boo::IApplication::EPlatformType::Auto, appCb, _SYS_STR("urde"), _SYS_STR("URDE"), argc,
                                argv, appCb.getGraphicsApi(), appCb.getSamples(), appCb.getAnisotropy(),
                                appCb.getDeepColor(), appCb.getTargetFrameTime(), false);
  // printf("IM DYING!!\n");
  return ret;
}
#endif

#if WINDOWS_STORE
#include "boo/UWPViewProvider.hpp"
using namespace Windows::ApplicationModel::Core;

[Platform::MTAThread] int WINAPIV main(Platform::Array<Platform::String ^> ^ params) {
  SetupBasics(false);
  urde::Application appCb;
  auto viewProvider =
      ref new boo::ViewProvider(appCb, _SYS_STR("urde"), _SYS_STR("URDE"), _SYS_STR("urde"), params, false);
  CoreApplication::Run(viewProvider);
  return 0;
}

#elif _WIN32
int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE, LPWSTR lpCmdLine, int) {
  int argc = 0;
  const boo::SystemChar** argv;
  if (lpCmdLine[0])
    argv = (const wchar_t**)(CommandLineToArgvW(lpCmdLine, &argc));
  static boo::SystemChar selfPath[1024];
  GetModuleFileNameW(nullptr, selfPath, 1024);
  static const boo::SystemChar* booArgv[32] = {};
  booArgv[0] = selfPath;
  for (int i = 0; i < argc; ++i)
    booArgv[i + 1] = argv[i];

  const DWORD outType = GetFileType(GetStdHandle(STD_OUTPUT_HANDLE));
  if (IsClientLoggingEnabled(argc + 1, booArgv) && outType == FILE_TYPE_UNKNOWN)
    logvisor::CreateWin32Console();
  return wmain(argc + 1, booArgv);
}
#endif
<|endoftext|>


<commit_before>#pragma once

#include "ConcatIterator.hpp"
#include "Last.hpp"
#include "SelectIterator.hpp"
#include "Skip.hpp"
#include "TakeIterator.hpp"
#include "WhereIterator.hpp"
#include "ZipIterator.hpp"

#include <algorithm>
#include <iterator>
#include <numeric>
#include <vector>

namespace Linqpp
{
    template <class Iterator>
    class Enumeration;

    template <class Iterator>
    auto From(Iterator first, Iterator last)
    {
        return Enumeration<Iterator>(first, last);
    }

    template <class Container>
    auto From(Container&& container)
    {
        return From(std::begin(std::forward<Container>(container)), std::end(std::forward<Container>(container)));
    }

    template <class Iterator>
    class Enumeration
    {
    private:
        Iterator _first;
        Iterator _last;

    public:
        using value_type = typename std::iterator_traits<Iterator>::value_type;

    public:
        Enumeration(Iterator first, Iterator last) : _first(first), _last(last) { }

    public:
        auto begin() const { return _first; }
        auto end() const { return _last; }

    public:
        template <class Seed, class BinaryFunction>
        auto Aggregate(Seed const& seed, BinaryFunction binaryFunction) const { return std::accumulate(_first, _last, seed, binaryFunction); }

        template <class BinaryFunction>
        auto Aggregate(BinaryFunction binaryFunction) const { return Aggregate(First(), binaryFunction); }

        bool Any() const { return _first != _last; }

        template <class Predicate>
        bool Any(Predicate predicate) const { return std::any_of(_first, _last, predicate); }

        template <class Predicate>
        bool All(Predicate predicate) const { return std::all_of(_first, _last, predicate); }

        template <class Container>
        auto Concat(Container&& container) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));
            auto first = CreateConcatIterator(_first, _last, cBegin, cBegin);
            auto last = CreateConcatIterator(_last, _last, cBegin, cEnd);

            return From(first, last);
        }

        template <class T, class CompareFunction>
        auto Contains(T const& t, CompareFunction compareFunction) const { return Any([=](const auto& t2) { return compareFunction(t, t2); }); }

        template <class T>
        auto Contains(T const& t) const { return Contains(t, std::equal_to<>()); }

        size_t Count() const { return std::distance(_first, _last); }

        decltype(auto) First() const { return *_first; }
        value_type FirstOrDefault() const { return Any() ? First() : value_type(); }

        decltype(auto) Last() const { return Linqpp::Last(_first, _last); }
        value_type LastOrDefault() const { return Any() ? Last() : value_type(); }

        template <class UnaryFunction>
        auto Select(UnaryFunction unaryFunction) const { return From(CreateSelectIterator(_first, unaryFunction), CreateSelectIterator(_last, unaryFunction)); }

        auto Skip(size_t n) const { return From(Linqpp::Skip(_first, n, _last), _last); }

        auto Take(size_t n) const { return GetEnumeratorFromTake(_first, n, _last); }

        auto ToVector() const { return std::vector<value_type>(_first, _last); }

        template <class Predicate>
        auto Where(Predicate predicate) const
        {
            auto first = CreateWhereIterator(_first, _last, predicate);
            auto last = CreateWhereIterator(_last, _last, predicate);
            return From(first, last);
        }

        template <class Container, class BinaryFunction>
        auto Zip(Container&& container, BinaryFunction binaryFunction) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));

            return From(CreateZipIterator(_first, cBegin, binaryFunction), CreateZipIterator(_last, cEnd, binaryFunction));
        }
    };
}
<commit_msg>added Count with predicate<commit_after>#pragma once

#include "ConcatIterator.hpp"
#include "Last.hpp"
#include "SelectIterator.hpp"
#include "Skip.hpp"
#include "TakeIterator.hpp"
#include "WhereIterator.hpp"
#include "ZipIterator.hpp"

#include <algorithm>
#include <iterator>
#include <numeric>
#include <vector>

namespace Linqpp
{
    template <class Iterator>
    class Enumeration;

    template <class Iterator>
    auto From(Iterator first, Iterator last)
    {
        return Enumeration<Iterator>(first, last);
    }

    template <class Container>
    auto From(Container&& container)
    {
        return From(std::begin(std::forward<Container>(container)), std::end(std::forward<Container>(container)));
    }

    template <class Iterator>
    class Enumeration
    {
    private:
        Iterator _first;
        Iterator _last;

    public:
        using value_type = typename std::iterator_traits<Iterator>::value_type;

    public:
        Enumeration(Iterator first, Iterator last) : _first(first), _last(last) { }

    public:
        auto begin() const { return _first; }
        auto end() const { return _last; }

    public:
        template <class Seed, class BinaryFunction>
        auto Aggregate(Seed const& seed, BinaryFunction binaryFunction) const { return std::accumulate(_first, _last, seed, binaryFunction); }

        template <class BinaryFunction>
        auto Aggregate(BinaryFunction binaryFunction) const { return Aggregate(First(), binaryFunction); }

        bool Any() const { return _first != _last; }

        template <class Predicate>
        bool Any(Predicate predicate) const { return std::any_of(_first, _last, predicate); }

        template <class Predicate>
        bool All(Predicate predicate) const { return std::all_of(_first, _last, predicate); }

        template <class Container>
        auto Concat(Container&& container) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));
            auto first = CreateConcatIterator(_first, _last, cBegin, cBegin);
            auto last = CreateConcatIterator(_last, _last, cBegin, cEnd);

            return From(first, last);
        }

        template <class T, class CompareFunction>
        auto Contains(T const& t, CompareFunction compareFunction) const { return Any([=](const auto& t2) { return compareFunction(t, t2); }); }

        template <class T>
        auto Contains(T const& t) const { return Contains(t, std::equal_to<>()); }

        size_t Count() const { return std::distance(_first, _last); }

        template <class Predicate>
        size_t Count(Predicate predicate) const { return std::count_if(_first, _last, predicate); }

        decltype(auto) First() const { return *_first; }
        value_type FirstOrDefault() const { return Any() ? First() : value_type(); }

        decltype(auto) Last() const { return Linqpp::Last(_first, _last); }
        value_type LastOrDefault() const { return Any() ? Last() : value_type(); }

        template <class UnaryFunction>
        auto Select(UnaryFunction unaryFunction) const { return From(CreateSelectIterator(_first, unaryFunction), CreateSelectIterator(_last, unaryFunction)); }

        auto Skip(size_t n) const { return From(Linqpp::Skip(_first, n, _last), _last); }

        auto Take(size_t n) const { return GetEnumeratorFromTake(_first, n, _last); }

        auto ToVector() const { return std::vector<value_type>(_first, _last); }

        template <class Predicate>
        auto Where(Predicate predicate) const
        {
            auto first = CreateWhereIterator(_first, _last, predicate);
            auto last = CreateWhereIterator(_last, _last, predicate);
            return From(first, last);
        }

        template <class Container, class BinaryFunction>
        auto Zip(Container&& container, BinaryFunction binaryFunction) const
        {
            auto cBegin = std::begin(std::forward<Container>(container));
            auto cEnd = std::end(std::forward<Container>(container));

            return From(CreateZipIterator(_first, cBegin, binaryFunction), CreateZipIterator(_last, cEnd, binaryFunction));
        }
    };
}
<|endoftext|>


<commit_before>#include "FatFilename.h"
#include <string>

using namespace std;

// Offset of letters position in a special "long file name" entry
static unsigned char longFilePos[] = {
    30, 28, 24, 22, 20, 18, 16, 14, 9, 7, 5, 3, 1
};

string FatFilename::getFilename()
{
    string filename = string(data.rbegin(), data.rend());
    data = "";

    return filename;
}

void FatFilename::append(char *buffer)
{
    int i;
    for (i=0; i<sizeof(longFilePos); i++) {
        unsigned char c = buffer[longFilePos[i]];
        if (c != 0 && c != 0xff) {
            data += c;
        }
    }
}

<commit_msg>Fixing long file names<commit_after>#include "FatFilename.h"
#include <string>

using namespace std;

// Offset of letters position in a special "long file name" entry
static unsigned char longFilePos[] = {
    30, 28, 24, 22, 20, 18, 16, 14, 9, 7, 5, 3, 1
};

string FatFilename::getFilename()
{
    string filename = string(data.rbegin(), data.rend());
    data = "";

    return filename;
}

void FatFilename::append(char *buffer)
{
    if (buffer[0]&0x40) {
        data = "";
    }

    int i;
    for (i=0; i<sizeof(longFilePos); i++) {
        unsigned char c = buffer[longFilePos[i]];
        if (c != 0 && c != 0xff) {
            data += c;
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2014 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 "athena/system/shutdown_dialog.h"

#include "athena/screen/public/screen_manager.h"
#include "athena/strings/grit/athena_strings.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/font_list.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"

namespace athena {
namespace {

// The amount of time that the power button must be held to shut down the
// device after shutdown dialog is shown.
const int kShutdownTimeoutMs = 4000;

class ModalWidgetDelegate : public views::WidgetDelegate {
 public:
  explicit ModalWidgetDelegate(views::View* contents_view)
      : contents_view_(contents_view) {}
  ~ModalWidgetDelegate() override {}

  // Overridden from WidgetDelegate:
  virtual views::Widget* GetWidget() override {
    return contents_view_->GetWidget();
  }
  virtual const views::Widget* GetWidget() const override {
    return contents_view_->GetWidget();
  }
  virtual views::View* GetContentsView() override { return contents_view_; }
  virtual ui::ModalType GetModalType() const override {
    return ui::MODAL_TYPE_SYSTEM;
  }

 private:
  views::View* contents_view_;

  DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate);
};

}  // namespace

ShutdownDialog::ShutdownDialog() : state_(STATE_OTHER) {
  InputManager::Get()->AddPowerButtonObserver(this);
}

ShutdownDialog::~ShutdownDialog() {
  InputManager::Get()->RemovePowerButtonObserver(this);
}

void ShutdownDialog::ShowShutdownWarningDialog() {
  state_ = STATE_SHUTDOWN_WARNING_VISIBLE;

  views::Label* label =
      new views::Label(l10n_util::GetStringUTF16(IDS_ATHENA_SHUTDOWN_WARNING));
  label->SetBackgroundColor(SK_ColorWHITE);
  label->SetFontList(gfx::FontList().DeriveWithStyle(gfx::Font::BOLD));

  views::View* container = new views::View;
  container->AddChildView(label);

  const int kBorderSpacing = 50;
  container->SetLayoutManager(new views::BoxLayout(
      views::BoxLayout::kHorizontal, kBorderSpacing, kBorderSpacing, 0));
  container->set_background(
      views::Background::CreateSolidBackground(SK_ColorWHITE));
  container->SetBorder(views::Border::CreateSolidBorder(1, SK_ColorBLACK));

  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.delegate = new ModalWidgetDelegate(container);
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.context = ScreenManager::Get()->GetContext();
  // Use top most modal container.
  params.keep_on_top = true;

  shutdown_warning_message_.reset(new views::Widget);
  shutdown_warning_message_->Init(params);
  shutdown_warning_message_->Show();
  shutdown_warning_message_->CenterWindow(container->GetPreferredSize());

  timer_.Start(FROM_HERE,
               base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
               this,
               &ShutdownDialog::Shutdown);
}

void ShutdownDialog::Shutdown() {
  state_ = STATE_SHUTDOWN_REQUESTED;
  chromeos::DBusThreadManager::Get()
      ->GetPowerManagerClient()
      ->RequestShutdown();
}

void ShutdownDialog::OnPowerButtonStateChanged(
    PowerButtonObserver::State state) {
  if (state_ == STATE_SHUTDOWN_REQUESTED)
    return;

  switch (state) {
    case PRESSED:
      state_ = STATE_SUSPEND_ON_RELEASE;
      break;
    case LONG_PRESSED:
      ShowShutdownWarningDialog();
      break;
    case RELEASED:
      if (state_ == STATE_SUSPEND_ON_RELEASE) {
        chromeos::DBusThreadManager::Get()
            ->GetPowerManagerClient()
            ->RequestSuspend();
      }
      state_ = STATE_OTHER;
      timer_.Stop();
      shutdown_warning_message_.reset();
      break;
  }
}

}  // namespace athena
<commit_msg>Fix leak in shutdown dialog<commit_after>// Copyright 2014 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 "athena/system/shutdown_dialog.h"

#include "athena/screen/public/screen_manager.h"
#include "athena/strings/grit/athena_strings.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/power_manager_client.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/font_list.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/label.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_delegate.h"

namespace athena {
namespace {

// The amount of time that the power button must be held to shut down the
// device after shutdown dialog is shown.
const int kShutdownTimeoutMs = 4000;

class ModalWidgetDelegate : public views::WidgetDelegate {
 public:
  explicit ModalWidgetDelegate(views::View* contents_view)
      : contents_view_(contents_view) {}
  ~ModalWidgetDelegate() override {}

  // Overridden from WidgetDelegate:
  void DeleteDelegate() override { delete this; }
  views::Widget* GetWidget() override { return contents_view_->GetWidget(); }
  const views::Widget* GetWidget() const override {
    return contents_view_->GetWidget();
  }
  views::View* GetContentsView() override { return contents_view_; }
  ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_SYSTEM; }

 private:
  views::View* contents_view_;

  DISALLOW_COPY_AND_ASSIGN(ModalWidgetDelegate);
};

}  // namespace

ShutdownDialog::ShutdownDialog() : state_(STATE_OTHER) {
  InputManager::Get()->AddPowerButtonObserver(this);
}

ShutdownDialog::~ShutdownDialog() {
  InputManager::Get()->RemovePowerButtonObserver(this);
}

void ShutdownDialog::ShowShutdownWarningDialog() {
  state_ = STATE_SHUTDOWN_WARNING_VISIBLE;

  views::Label* label =
      new views::Label(l10n_util::GetStringUTF16(IDS_ATHENA_SHUTDOWN_WARNING));
  label->SetBackgroundColor(SK_ColorWHITE);
  label->SetFontList(gfx::FontList().DeriveWithStyle(gfx::Font::BOLD));

  views::View* container = new views::View;
  container->AddChildView(label);

  const int kBorderSpacing = 50;
  container->SetLayoutManager(new views::BoxLayout(
      views::BoxLayout::kHorizontal, kBorderSpacing, kBorderSpacing, 0));
  container->set_background(
      views::Background::CreateSolidBackground(SK_ColorWHITE));
  container->SetBorder(views::Border::CreateSolidBorder(1, SK_ColorBLACK));

  views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
  params.delegate = new ModalWidgetDelegate(container);
  params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
  params.context = ScreenManager::Get()->GetContext();
  // Use top most modal container.
  params.keep_on_top = true;

  shutdown_warning_message_.reset(new views::Widget);
  shutdown_warning_message_->Init(params);
  shutdown_warning_message_->Show();
  shutdown_warning_message_->CenterWindow(container->GetPreferredSize());

  timer_.Start(FROM_HERE,
               base::TimeDelta::FromMilliseconds(kShutdownTimeoutMs),
               this,
               &ShutdownDialog::Shutdown);
}

void ShutdownDialog::Shutdown() {
  state_ = STATE_SHUTDOWN_REQUESTED;
  chromeos::DBusThreadManager::Get()
      ->GetPowerManagerClient()
      ->RequestShutdown();
}

void ShutdownDialog::OnPowerButtonStateChanged(
    PowerButtonObserver::State state) {
  if (state_ == STATE_SHUTDOWN_REQUESTED)
    return;

  switch (state) {
    case PRESSED:
      state_ = STATE_SUSPEND_ON_RELEASE;
      break;
    case LONG_PRESSED:
      ShowShutdownWarningDialog();
      break;
    case RELEASED:
      if (state_ == STATE_SUSPEND_ON_RELEASE) {
        chromeos::DBusThreadManager::Get()
            ->GetPowerManagerClient()
            ->RequestSuspend();
      }
      state_ = STATE_OTHER;
      timer_.Stop();
      shutdown_warning_message_.reset();
      break;
  }
}

}  // namespace athena
<|endoftext|>