<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.16  2003/04/08 10:22:05  morsch
Rapidity shift calculated in Init().

Revision 1.15  2003/04/04 08:13:26  morsch
Boost method added.

Revision 1.14  2003/01/14 10:50:19  alibrary
Cleanup of STEER coding conventions

Revision 1.13  2002/10/14 14:55:35  hristov
Merging the VirtualMC branch to the main development branch (HEAD)

Revision 1.5.4.2  2002/07/24 08:56:28  alibrary
Updating EVGEN on TVirtulaMC

Revision 1.12  2002/07/19 11:42:33  morsch
Use CalcMass()

Revision 1.11  2002/06/06 15:26:24  morsch
Correct child-selection for kPhiKK

Revision 1.10  2002/06/05 14:05:46  morsch
Decayer option kPhiKK for forced phi->K+K- decay added.

Revision 1.9  2002/05/30 14:58:29  morsch
Add pointer to AliGeometry to handle geometrical acceptance. (G. MArtinez)

Revision 1.8  2002/04/26 10:42:35  morsch
Case kNoDecayHeavy added. (N. Carrer)

Revision 1.7  2002/04/17 10:32:32  morsch
Coding Rule violations corrected.

Revision 1.6  2002/03/26 14:19:36  morsch
Saver calculation of rapdity.

Revision 1.5  2002/03/12 17:02:20  morsch
Change in calculation of rapidity, include case in which numerically e == pz.

Revision 1.4  2001/11/27 13:13:07  morsch
Maximum lifetime for long-lived particles to be put on the stack is parameter.
It can be set via SetMaximumLifetime(..).

Revision 1.3  2001/10/16 08:48:56  morsch
Common vertex related code moved to base class AliGenerator.

Revision 1.2  2001/10/15 08:15:51  morsch
Event vertex and vertex truncation setting moved into AliMC.

Revision 1.1  2001/07/13 10:56:00  morsch
AliGenMC base class for AliGenParam and AliGenPythia commonalities.

*/

// Base class for generators using external MC generators.
// For example AliGenPythia using Pythia.
// Provides basic functionality: setting of kinematic cuts on
// decay products and particle selection.
// andreas.morsch@cern.ch

#include <TMath.h>
#include <TPDGCode.h>
#include <TParticle.h>

#include "AliGenMC.h"

 ClassImp(AliGenMC)

AliGenMC::AliGenMC()
                 :AliGenerator()
{
// Default Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
}

AliGenMC::AliGenMC(Int_t npart)
                 :AliGenerator(npart)
{
//  Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
//
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    for (Int_t i=0; i<8; i++) fParentSelect[i]=fChildSelect[i]=0;
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
}

AliGenMC::AliGenMC(const AliGenMC & mc)
{
// copy constructor
}

AliGenMC::~AliGenMC()
{
// Destructor
}

void AliGenMC::Init()
{
//
//  Initialization
    switch (fForceDecay) {
    case kSemiElectronic:
    case kDiElectron:
    case kBJpsiDiElectron:
    case kBPsiPrimeDiElectron:
	fChildSelect[0] = kElectron;
	break;
    case kSemiMuonic:
    case kDiMuon:
    case kBJpsiDiMuon:
    case kBPsiPrimeDiMuon:
    case kPiToMu:
    case kKaToMu:
	fChildSelect[0]=kMuonMinus;
	break;
    case kHadronicD:
	fChildSelect[0]=kPiPlus;
	fChildSelect[1]=kKPlus;
	break;
    case kPhiKK:
	fChildSelect[0]=kKPlus;
    case kOmega:
    case kAll:
    case kNoDecay:
    case kNoDecayHeavy:
	break;
    }

    if (fZTarget != 0 && fAProjectile != 0)
    {
	fDyBoost    = - 0.5 * TMath::Log(Double_t(fZProjectile) * Double_t(fATarget) /
					 (Double_t(fZTarget)    * Double_t(fAProjectile)));
    }
}

Bool_t AliGenMC::ParentSelected(Int_t ip) const
{
// True if particle is in list of parent particles to be selected
    for (Int_t i=0; i<8; i++)
    {
	if (fParentSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::ChildSelected(Int_t ip) const
{
// True if particle is in list of decay products to be selected
    for (Int_t i=0; i<5; i++)
    {
	if (fChildSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::KinematicSelection(TParticle *particle, Int_t flag) const
{
// Perform kinematic selection
    Float_t px    = particle->Px();
    Float_t py    = particle->Py();
    Float_t pz    = particle->Pz();
    Float_t  e    = particle->Energy();
    Float_t pt    = particle->Pt();
    Float_t p     = particle->P();
    Float_t theta = particle->Theta();
    Float_t mass  = particle->GetCalcMass();
    Float_t mt2   = pt * pt + mass * mass;

    Float_t phi   = Float_t(TMath::ATan2(Double_t(py),Double_t(px)));
    Double_t y, y0;

    if (TMath::Abs(pz) <  e) {
	y = 0.5*TMath::Log((e+pz)/(e-pz));
    } else {
	y = 1.e10;
    }

    if (mt2) {
	y0 = 0.5*TMath::Log((e+TMath::Abs(pz))*(e+TMath::Abs(pz))/mt2);
    } else {
	if (TMath::Abs(y) < 1.e10) {
	    y0 = y;
	} else {
	    y0 = 1.e10;
	}
    }

    y = (pz < 0) ? -y0 : y0;

    if (flag == 0) {
//
// Primary particle cuts
//
//  transverse momentum cut
	if (pt > fPtMax || pt < fPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fPMax || p < fPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fThetaMax || theta < fThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fYMax || y < fYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fPhiMax || phi < fPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	    return kFALSE;
	}
    } else {
//
// Decay product cuts
//
//  transverse momentum cut
	if (pt > fChildPtMax || pt < fChildPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fChildPtMin,fChildPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fChildPMax || p < fChildPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fChildPMin,fChildPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fChildThetaMax || theta < fChildThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fChildThetaMin,fChildThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fChildYMax || y < fChildYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fChildYMin,fChildYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fChildPhiMax || phi < fChildPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fChildPhiMin,fChildPhiMax);
	    return kFALSE;
	}
    }

    return kTRUE;
}

Bool_t AliGenMC::CheckAcceptanceGeometry(Int_t np, TClonesArray* particles)
{
  Bool_t Check ;  // All fPdgCodeParticleforAcceptanceCut particles are in in the fGeometryAcceptance acceptance
  Int_t NumberOfPdgCodeParticleforAcceptanceCut=0;
  Int_t NumberOfAcceptedPdgCodeParticleforAcceptanceCut=0;
  TParticle * particle;
  Int_t i;
  for (i=0; i<np; i++) {
    particle =  (TParticle *) particles->At(i);
    if( TMath::Abs( particle->GetPdgCode() ) == TMath::Abs( fPdgCodeParticleforAcceptanceCut ) ) {
      NumberOfPdgCodeParticleforAcceptanceCut++;
      if (fGeometryAcceptance->Impact(particle)) NumberOfAcceptedPdgCodeParticleforAcceptanceCut++;
    }
  }
  if ( NumberOfAcceptedPdgCodeParticleforAcceptanceCut > (fNumberOfAcceptedParticles-1) )
    Check = kTRUE;
  else
    Check = kFALSE;

  return Check;
}

Int_t AliGenMC::CheckPDGCode(Int_t pdgcode) const
{
//
//  If the particle is in a diffractive state, then take action accordingly
  switch (pdgcode) {
  case 91:
    return 92;
  case 110:
    //rho_diff0 -- difficult to translate, return rho0
    return 113;
  case 210:
    //pi_diffr+ -- change to pi+
    return 211;
  case 220:
    //omega_di0 -- change to omega0
    return 223;
  case 330:
    //phi_diff0 -- return phi0
    return 333;
  case 440:
    //J/psi_di0 -- return J/psi
    return 443;
  case 2110:
    //n_diffr -- return neutron
    return 2112;
  case 2210:
    //p_diffr+ -- return proton
    return 2212;
  }
  //non diffractive state -- return code unchanged
  return pdgcode;
}

void AliGenMC::Boost()
{
//
// Boost cms into LHC lab frame
//

    Double_t beta  = TMath::TanH(fDyBoost);
    Double_t gamma = 1./TMath::Sqrt(1.-beta*beta);
    Double_t gb    = gamma * beta;

    //    printf("\n Boosting particles to lab frame %f %f %f", fDyBoost, beta, gamma);

    Int_t i;
    Int_t np = fParticles->GetEntriesFast();
    for (i = 0; i < np; i++)
    {
	TParticle* iparticle = (TParticle*) fParticles->At(i);

	Double_t e   = iparticle->Energy();
	Double_t px  = iparticle->Px();
	Double_t py  = iparticle->Py();
	Double_t pz  = iparticle->Pz();

	Double_t eb  = gamma * e -      gb * pz;
	Double_t pzb =   -gb * e +   gamma * pz;

	iparticle->SetMomentum(px, py, pzb, eb);
    }
}

AliGenMC& AliGenMC::operator=(const  AliGenMC& rhs)
{
// Assignment operator
    return *this;
}

<commit_msg>Get phi from iparticle.<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/*
$Log$
Revision 1.17  2003/04/30 14:48:21  hristov
Changes related to the initialization of random numbers generators. Now one can use its own randoms for each module, particle generator, and/or tracking package. The interface with Fortran is simplified and some inter-library dependencies are avoided. Future improvements are welcome...

Revision 1.16  2003/04/08 10:22:05  morsch
Rapidity shift calculated in Init().

Revision 1.15  2003/04/04 08:13:26  morsch
Boost method added.

Revision 1.14  2003/01/14 10:50:19  alibrary
Cleanup of STEER coding conventions

Revision 1.13  2002/10/14 14:55:35  hristov
Merging the VirtualMC branch to the main development branch (HEAD)

Revision 1.5.4.2  2002/07/24 08:56:28  alibrary
Updating EVGEN on TVirtulaMC

Revision 1.12  2002/07/19 11:42:33  morsch
Use CalcMass()

Revision 1.11  2002/06/06 15:26:24  morsch
Correct child-selection for kPhiKK

Revision 1.10  2002/06/05 14:05:46  morsch
Decayer option kPhiKK for forced phi->K+K- decay added.

Revision 1.9  2002/05/30 14:58:29  morsch
Add pointer to AliGeometry to handle geometrical acceptance. (G. MArtinez)

Revision 1.8  2002/04/26 10:42:35  morsch
Case kNoDecayHeavy added. (N. Carrer)

Revision 1.7  2002/04/17 10:32:32  morsch
Coding Rule violations corrected.

Revision 1.6  2002/03/26 14:19:36  morsch
Saver calculation of rapdity.

Revision 1.5  2002/03/12 17:02:20  morsch
Change in calculation of rapidity, include case in which numerically e == pz.

Revision 1.4  2001/11/27 13:13:07  morsch
Maximum lifetime for long-lived particles to be put on the stack is parameter.
It can be set via SetMaximumLifetime(..).

Revision 1.3  2001/10/16 08:48:56  morsch
Common vertex related code moved to base class AliGenerator.

Revision 1.2  2001/10/15 08:15:51  morsch
Event vertex and vertex truncation setting moved into AliMC.

Revision 1.1  2001/07/13 10:56:00  morsch
AliGenMC base class for AliGenParam and AliGenPythia commonalities.

*/

// Base class for generators using external MC generators.
// For example AliGenPythia using Pythia.
// Provides basic functionality: setting of kinematic cuts on
// decay products and particle selection.
// andreas.morsch@cern.ch

#include <TMath.h>
#include <TPDGCode.h>
#include <TParticle.h>

#include "AliGenMC.h"

 ClassImp(AliGenMC)

AliGenMC::AliGenMC()
                 :AliGenerator()
{
// Default Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
}

AliGenMC::AliGenMC(Int_t npart)
                 :AliGenerator(npart)
{
//  Constructor
    SetCutOnChild();
    SetChildMomentumRange();
    SetChildPtRange();
    SetChildPhiRange();
    SetChildThetaRange();
    SetChildYRange();
//
    fParentSelect.Set(8);
    fChildSelect.Set(8);
    for (Int_t i=0; i<8; i++) fParentSelect[i]=fChildSelect[i]=0;
    SetMaximumLifetime();
    SetGeometryAcceptance();
    SetPdgCodeParticleforAcceptanceCut();
    SetNumberOfAcceptedParticles();
    SetTarget();
    SetProjectile();
}

AliGenMC::AliGenMC(const AliGenMC & mc)
{
// copy constructor
}

AliGenMC::~AliGenMC()
{
// Destructor
}

void AliGenMC::Init()
{
//
//  Initialization
    switch (fForceDecay) {
    case kSemiElectronic:
    case kDiElectron:
    case kBJpsiDiElectron:
    case kBPsiPrimeDiElectron:
	fChildSelect[0] = kElectron;
	break;
    case kSemiMuonic:
    case kDiMuon:
    case kBJpsiDiMuon:
    case kBPsiPrimeDiMuon:
    case kPiToMu:
    case kKaToMu:
	fChildSelect[0]=kMuonMinus;
	break;
    case kHadronicD:
	fChildSelect[0]=kPiPlus;
	fChildSelect[1]=kKPlus;
	break;
    case kPhiKK:
	fChildSelect[0]=kKPlus;
    case kOmega:
    case kAll:
    case kNoDecay:
    case kNoDecayHeavy:
	break;
    }

    if (fZTarget != 0 && fAProjectile != 0)
    {
	fDyBoost    = - 0.5 * TMath::Log(Double_t(fZProjectile) * Double_t(fATarget) /
					 (Double_t(fZTarget)    * Double_t(fAProjectile)));
    }
}

Bool_t AliGenMC::ParentSelected(Int_t ip) const
{
// True if particle is in list of parent particles to be selected
    for (Int_t i=0; i<8; i++)
    {
	if (fParentSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::ChildSelected(Int_t ip) const
{
// True if particle is in list of decay products to be selected
    for (Int_t i=0; i<5; i++)
    {
	if (fChildSelect.At(i) == ip) return kTRUE;
    }
    return kFALSE;
}

Bool_t AliGenMC::KinematicSelection(TParticle *particle, Int_t flag) const
{
// Perform kinematic selection
    Float_t pz    = particle->Pz();
    Float_t  e    = particle->Energy();
    Float_t pt    = particle->Pt();
    Float_t p     = particle->P();
    Float_t theta = particle->Theta();
    Float_t mass  = particle->GetCalcMass();
    Float_t mt2   = pt * pt + mass * mass;
    Float_t phi   = particle->Phi();

    Double_t y, y0;

    if (TMath::Abs(pz) <  e) {
	y = 0.5*TMath::Log((e+pz)/(e-pz));
    } else {
	y = 1.e10;
    }

    if (mt2) {
	y0 = 0.5*TMath::Log((e+TMath::Abs(pz))*(e+TMath::Abs(pz))/mt2);
    } else {
	if (TMath::Abs(y) < 1.e10) {
	    y0 = y;
	} else {
	    y0 = 1.e10;
	}
    }

    y = (pz < 0) ? -y0 : y0;

    if (flag == 0) {
//
// Primary particle cuts
//
//  transverse momentum cut
	if (pt > fPtMax || pt < fPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fPtMin,fPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fPMax || p < fPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fPMin,fPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fThetaMax || theta < fThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fThetaMin,fThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fYMax || y < fYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fYMin,fYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fPhiMax || phi < fPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fPhiMin,fPhiMax);
	    return kFALSE;
	}
    } else {
//
// Decay product cuts
//
//  transverse momentum cut
	if (pt > fChildPtMax || pt < fChildPtMin) {
//	    printf("\n failed pt cut %f %f %f \n",pt,fChildPtMin,fChildPtMax);
	    return kFALSE;
	}
//
// momentum cut
	if (p > fChildPMax || p < fChildPMin) {
//	    printf("\n failed p cut %f %f %f \n",p,fChildPMin,fChildPMax);
	    return kFALSE;
	}
//
// theta cut
	if (theta > fChildThetaMax || theta < fChildThetaMin) {
//	    printf("\n failed theta cut %f %f %f \n",theta,fChildThetaMin,fChildThetaMax);
	    return kFALSE;
	}
//
// rapidity cut
	if (y > fChildYMax || y < fChildYMin) {
//	    printf("\n failed y cut %f %f %f \n",y,fChildYMin,fChildYMax);
	    return kFALSE;
	}
//
// phi cut
	if (phi > fChildPhiMax || phi < fChildPhiMin) {
//	    printf("\n failed phi cut %f %f %f \n",phi,fChildPhiMin,fChildPhiMax);
	    return kFALSE;
	}
    }

    return kTRUE;
}

Bool_t AliGenMC::CheckAcceptanceGeometry(Int_t np, TClonesArray* particles)
{
  Bool_t Check ;  // All fPdgCodeParticleforAcceptanceCut particles are in in the fGeometryAcceptance acceptance
  Int_t NumberOfPdgCodeParticleforAcceptanceCut=0;
  Int_t NumberOfAcceptedPdgCodeParticleforAcceptanceCut=0;
  TParticle * particle;
  Int_t i;
  for (i=0; i<np; i++) {
    particle =  (TParticle *) particles->At(i);
    if( TMath::Abs( particle->GetPdgCode() ) == TMath::Abs( fPdgCodeParticleforAcceptanceCut ) ) {
      NumberOfPdgCodeParticleforAcceptanceCut++;
      if (fGeometryAcceptance->Impact(particle)) NumberOfAcceptedPdgCodeParticleforAcceptanceCut++;
    }
  }
  if ( NumberOfAcceptedPdgCodeParticleforAcceptanceCut > (fNumberOfAcceptedParticles-1) )
    Check = kTRUE;
  else
    Check = kFALSE;

  return Check;
}

Int_t AliGenMC::CheckPDGCode(Int_t pdgcode) const
{
//
//  If the particle is in a diffractive state, then take action accordingly
  switch (pdgcode) {
  case 91:
    return 92;
  case 110:
    //rho_diff0 -- difficult to translate, return rho0
    return 113;
  case 210:
    //pi_diffr+ -- change to pi+
    return 211;
  case 220:
    //omega_di0 -- change to omega0
    return 223;
  case 330:
    //phi_diff0 -- return phi0
    return 333;
  case 440:
    //J/psi_di0 -- return J/psi
    return 443;
  case 2110:
    //n_diffr -- return neutron
    return 2112;
  case 2210:
    //p_diffr+ -- return proton
    return 2212;
  }
  //non diffractive state -- return code unchanged
  return pdgcode;
}

void AliGenMC::Boost()
{
//
// Boost cms into LHC lab frame
//

    Double_t beta  = TMath::TanH(fDyBoost);
    Double_t gamma = 1./TMath::Sqrt(1.-beta*beta);
    Double_t gb    = gamma * beta;

    //    printf("\n Boosting particles to lab frame %f %f %f", fDyBoost, beta, gamma);

    Int_t i;
    Int_t np = fParticles->GetEntriesFast();
    for (i = 0; i < np; i++)
    {
	TParticle* iparticle = (TParticle*) fParticles->At(i);

	Double_t e   = iparticle->Energy();
	Double_t px  = iparticle->Px();
	Double_t py  = iparticle->Py();
	Double_t pz  = iparticle->Pz();

	Double_t eb  = gamma * e -      gb * pz;
	Double_t pzb =   -gb * e +   gamma * pz;

	iparticle->SetMomentum(px, py, pzb, eb);
    }
}

AliGenMC& AliGenMC::operator=(const  AliGenMC& rhs)
{
// Assignment operator
    return *this;
}

<|endoftext|>


<commit_before>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <deque>
#include <boost/asio.hpp>

int main(int argc, char* argv[]) {
  (void)argc, (void)argv;

  return 0;
}
<commit_msg>:sparkles: feat(chat.client): add chat client definitions<commit_after>// Copyright (c) 2017 ASMlover. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  * Redistributions of source code must retain the above copyright
//    notice, this list ofconditions and the following disclaimer.
//
//  * Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materialsprovided with the
//    distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
#include <cstdint>
#include <cstdio>
#include <iostream>
#include <deque>
#include <thread>
#include <boost/asio.hpp>
#include "chat_protocol.h"

using boost::asio::ip::tcp;
using ChatMessageQueue = std::deque<ChatMessage>;

class ChatClient : private boost::noncopyable {
  boost::asio::io_service& io_service_;
  tcp::socket socket_;
  ChatMessage readmsg_;
  ChatMessageQueue writmsg_queue_;
  std::string session_id_;

  void do_connect(tcp::resolver::iterator endpoint_iter) {
    // TODO:
  }

  void do_read_header(void) {
    // TODO:
  }

  void do_read_body(void) {
    // TODO:
  }

  void do_write(void) {
    // TODO:
  }
public:
  ChatClient(boost::asio::io_service& io_service)
    : io_service_(io_service)
    , socket_(io_service_) {
  }

  void start(tcp::resolver::iterator endpoint_iter) {
    // TODO:
  }

  void write(const char* buf, std::size_t len) {
    // TODO:
  }

  void write(const ChatMessage& msg) {
    // TODO:
  }

  void close(void) {
    io_service_.post([this](void) { socket_.close(); });
  }
};

int main(int argc, char* argv[]) {
  (void)argc, (void)argv;

  return 0;
}
<|endoftext|>


<commit_before>#include "EngineCore.h"

#include "Application.h"

namespace fse
{

	EngineCore::EngineCore()
	{

	}

	EngineCore::~EngineCore()
	{

	}

	int EngineCore::exec(Application * application)
	{

		application_ = application;

		if (show_window_)
		{
#ifdef ANDROID
			sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
            window.setFramerateLimit(60);
#else
			sf::RenderWindow window(sf::VideoMode(1280, 720), "FSE");
            window.setFramerateLimit(120);
#endif

			application_->setWindow(&window);
			application_->init();
			while (window.isOpen() && run_)
			{
				if (application_ != nullptr)
				{
					application_->update();
				}

			}

		} else {						//No window => Dedicated server....
			/////////// restrict update rate ///////////
			sf::Clock ApplicationTime;
			float ticktime = 1000 / 60.f;
			while (run_)
			{
				float time = ApplicationTime.restart().asSeconds();

				float sleeptime = ticktime - time * 1000;
				if (sleeptime > 0)
				{
					sf::sleep(sf::milliseconds(static_cast<sf::Int32>(sleeptime)));
				}
				/////////// timehandling end ///////////

				application_->update();
			}

		}

		return 0;
	}
}<commit_msg>Fix rttr registration of some sf:: classes<commit_after>#include "EngineCore.h"

#include "Application.h"

namespace fse
{

	EngineCore::EngineCore()
	{

	}

	EngineCore::~EngineCore()
	{

	}

	int EngineCore::exec(Application * application)
	{

		application_ = application;

		if (show_window_)
		{
#ifdef ANDROID
			sf::RenderWindow window(sf::VideoMode::getDesktopMode(), "");
			window.setFramerateLimit(60);
#else
			sf::RenderWindow window(sf::VideoMode(1280, 720), "FSE");
			window.setFramerateLimit(120);
#endif

			application_->setWindow(&window);
			application_->init();
			while (window.isOpen() && run_)
			{
				if (application_ != nullptr)
				{
					application_->update();
				}

			}

		} else {						//No window => Dedicated server....
			/////////// restrict update rate ///////////
			sf::Clock ApplicationTime;
			float ticktime = 1000 / 60.f;
			while (run_)
			{
				float time = ApplicationTime.restart().asSeconds();

				float sleeptime = ticktime - time * 1000;
				if (sleeptime > 0)
				{
					sf::sleep(sf::milliseconds(static_cast<sf::Int32>(sleeptime)));
				}
				/////////// timehandling end ///////////

				application_->update();
			}

		}

		return 0;
	}
}

#include <rttr/registration>
RTTR_REGISTRATION
{
	using namespace rttr;

registration::class_<sf::Vector2f>("sf::Vector2f")
.property("x", &sf::Vector2f::x)
.property("y", &sf::Vector2f::y)
;

registration::class_<sf::Vector2i>("sf::Vector2i")
.property("x", &sf::Vector2i::x)
.property("y", &sf::Vector2i::y)
;

registration::class_<sf::IntRect>("sf::IntRect")
.property("top", &sf::IntRect::top)
.property("left", &sf::IntRect::left)
.property("width", &sf::IntRect::width)
.property("height", &sf::IntRect::height)
;

registration::class_<sf::FloatRect>("sf::FloatRect")
.property("top", &sf::FloatRect::top)
.property("left", &sf::FloatRect::left)
.property("width", &sf::FloatRect::width)
.property("height", &sf::FloatRect::height)
;

registration::class_<sf::Color>("sf::Color")
.property("r", &sf::Color::r)
.property("g", &sf::Color::g)
.property("b", &sf::Color::b)
.property("a", &sf::Color::a)
;

}<|endoftext|>


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

#include "webkit/fileapi/file_system_path_manager.h"

#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/scoped_callback_factory.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
#include "webkit/glue/webkit_glue.h"

// We use some of WebKit types for conversions between storage identifiers
// and origin URLs.
using WebKit::WebFileSystem;
using WebKit::WebSecurityOrigin;
using WebKit::WebString;

using base::PlatformFileError;

namespace fileapi {

const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] =
    FILE_PATH_LITERAL("FileSystem");

const char FileSystemPathManager::kPersistentName[] = "Persistent";
const char FileSystemPathManager::kTemporaryName[] = "Temporary";

static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
    FILE_PATH_LITERAL("chrome-");
static const int kFileSystemUniqueLength = 16;
static const unsigned kFileSystemUniqueDirectoryNameLength =
    kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;

namespace {

// Restricted names.
// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
static const char* const kRestrictedNames[] = {
  "con", "prn", "aux", "nul",
  "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
  "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
};

// Restricted chars.
static const FilePath::CharType kRestrictedChars[] = {
  '/', '\\', '<', '>', ':', '?', '*', '"', '|',
};

inline std::string FilePathStringToASCII(
    const FilePath::StringType& path_string) {
#if defined(OS_WIN)
  return WideToASCII(path_string);
#elif defined(OS_POSIX)
  return path_string;
#endif
}

FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
  // This can be anything but need to be unpredictable.
  static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
  FilePath::StringType unique(kFileSystemUniqueNamePrefix);
  for (int i = 0; i < kFileSystemUniqueLength; ++i)
    unique += letters[base::RandInt(0, arraysize(letters) - 2)];
  return unique;
}

}  // anonymous namespace

class FileSystemPathManager::GetFileSystemRootPathTask
    : public base::RefCountedThreadSafe<
        FileSystemPathManager::GetFileSystemRootPathTask> {
 public:
  GetFileSystemRootPathTask(
      scoped_refptr<base::MessageLoopProxy> file_message_loop,
      const std::string& name,
      FileSystemPathManager::GetRootPathCallback* callback)
      : file_message_loop_(file_message_loop),
        origin_message_loop_proxy_(
            base::MessageLoopProxy::CreateForCurrentThread()),
        name_(name),
        callback_(callback) {
  }

  void Start(const GURL& origin_url,
             const FilePath& origin_base_path,
             bool create) {
    file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
        &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread,
        origin_url, origin_base_path, create));
  }

 private:
  void GetFileSystemRootPathOnFileThread(
      const GURL& origin_url,
      const FilePath& base_path,
      bool create) {
    FilePath root;
    if (ReadOriginDirectory(base_path, origin_url, &root)) {
      DispatchCallbackOnCallerThread(root);
      return;
    }

    if (!create) {
      DispatchCallbackOnCallerThread(FilePath());
      return;
    }

    // Creates the root directory.
    root = base_path.Append(CreateUniqueDirectoryName(origin_url));
    if (!file_util::CreateDirectory(root)) {
      DispatchCallbackOnCallerThread(FilePath());
      return;
    }
    DispatchCallbackOnCallerThread(root);
  }

  bool ReadOriginDirectory(const FilePath& base_path,
                           const GURL& origin_url,
                           FilePath* unique) {
    file_util::FileEnumerator file_enum(
        base_path, false /* recursive */,
        file_util::FileEnumerator::DIRECTORIES,
        FilePath::StringType(kFileSystemUniqueNamePrefix) +
            FILE_PATH_LITERAL("*"));
    FilePath current;
    bool found = false;
    while (!(current = file_enum.Next()).empty()) {
      if (current.BaseName().value().length() !=
          kFileSystemUniqueDirectoryNameLength)
        continue;
      if (found) {
        // TODO(kinuko): Should notify the user to ask for some action.
        LOG(WARNING) << "Unexpectedly found more than one FileSystem "
                     << "directories for " << origin_url;
        return false;
      }
      found = true;
      *unique = current;
    }
    return !unique->empty();
  }

  void DispatchCallbackOnCallerThread(const FilePath& root_path) {
    origin_message_loop_proxy_->PostTask(FROM_HERE,
        NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback,
                          root_path));
  }

  void DispatchCallback(const FilePath& root_path) {
    callback_->Run(!root_path.empty(), root_path, name_);
  }

  scoped_refptr<base::MessageLoopProxy> file_message_loop_;
  scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
  std::string name_;
  scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_;
};

FileSystemPathManager::FileSystemPathManager(
    scoped_refptr<base::MessageLoopProxy> file_message_loop,
    const FilePath& profile_path,
    bool is_incognito,
    bool allow_file_access_from_files)
    : file_message_loop_(file_message_loop),
      base_path_(profile_path.Append(kFileSystemDirectory)),
      is_incognito_(is_incognito),
      allow_file_access_from_files_(allow_file_access_from_files) {
}

FileSystemPathManager::~FileSystemPathManager() {}

void FileSystemPathManager::GetFileSystemRootPath(
    const GURL& origin_url, fileapi::FileSystemType type,
    bool create, GetRootPathCallback* callback_ptr) {
  scoped_ptr<GetRootPathCallback> callback(callback_ptr);
  if (is_incognito_) {
    // TODO(kinuko): return an isolated temporary directory.
    callback->Run(false, FilePath(), std::string());
    return;
  }

  if (!IsAllowedScheme(origin_url)) {
    callback->Run(false, FilePath(), std::string());
    return;
  }

  if (type != fileapi::kFileSystemTypeTemporary &&
      type != fileapi::kFileSystemTypePersistent) {
    LOG(WARNING) << "Unknown filesystem type is requested:" << type;
    callback->Run(false, FilePath(), std::string());
    return;
  }

  std::string storage_identifier = GetStorageIdentifierFromURL(origin_url);

  std::string type_string;
  if (type == fileapi::kFileSystemTypeTemporary)
    type_string = kTemporaryName;
  else if (type == fileapi::kFileSystemTypePersistent)
    type_string = kPersistentName;
  DCHECK(!type_string.empty());

  FilePath origin_base_path = base_path_.AppendASCII(storage_identifier)
                                        .AppendASCII(type_string);
  std::string name = storage_identifier + ":" + type_string;

  scoped_refptr<GetFileSystemRootPathTask> task =
      new GetFileSystemRootPathTask(file_message_loop_,
                                    name, callback.release());
  task->Start(origin_url, origin_base_path, create);
}

bool FileSystemPathManager::CrackFileSystemPath(
    const FilePath& path, GURL* origin_url, FileSystemType* type,
    FilePath* virtual_path) const {
  // Any paths that includes parent references are considered invalid.
  if (path.ReferencesParent())
    return false;

  // The path should be a child of the profile FileSystem path.
  FilePath relative;
  if (!base_path_.AppendRelativePath(path, &relative))
    return false;

  // The relative path from the profile FileSystem path should contain
  // at least three components, one for storage identifier, one for type
  // and one for the 'unique' part.
  std::vector<FilePath::StringType> components;
  relative.GetComponents(&components);
  if (components.size() < 3)
    return false;

  // The second component of the relative path to the root directory
  // must be kPersistent or kTemporary.
  if (!IsStringASCII(components[1]))
    return false;

  std::string ascii_type_component = FilePathStringToASCII(components[1]);
  FileSystemType cracked_type = kFileSystemTypeUnknown;
  if (ascii_type_component == kPersistentName)
    cracked_type = kFileSystemTypePersistent;
  else if (ascii_type_component == kTemporaryName)
    cracked_type = kFileSystemTypeTemporary;
  else
    return false;

  DCHECK(cracked_type != kFileSystemTypeUnknown);

  // The given |path| seems valid. Populates the |origin_url|, |type|
  // and |virtual_path| if they are given.

  if (origin_url) {
    WebSecurityOrigin web_security_origin =
        WebSecurityOrigin::createFromDatabaseIdentifier(
            webkit_glue::FilePathStringToWebString(components[0]));
    *origin_url = GURL(web_security_origin.toString());

    // We need this work-around for file:/// URIs as
    // createFromDatabaseIdentifier returns empty origin_url for them.
    if (allow_file_access_from_files_ && origin_url->spec().empty() &&
        components[0].find(FILE_PATH_LITERAL("file")) == 0)
      *origin_url = GURL("file:///");
  }

  if (type)
    *type = cracked_type;

  if (virtual_path) {
    virtual_path->clear();
    for (size_t i = 3; i < components.size(); ++i)
      *virtual_path = virtual_path->Append(components[i]);
  }

  return true;
}

bool FileSystemPathManager::IsRestrictedFileName(
    const FilePath& filename) const {
  if (filename.value().size() == 0)
    return false;

  if (IsWhitespace(filename.value()[filename.value().size() - 1]) ||
      filename.value()[filename.value().size() - 1] == '.')
    return true;

  std::string filename_lower = StringToLowerASCII(
      FilePathStringToASCII(filename.value()));

  for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
    // Exact match.
    if (filename_lower == kRestrictedNames[i])
      return true;
    // Starts with "RESTRICTED_NAME.".
    if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0)
      return true;
  }

  for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
    if (filename.value().find(kRestrictedChars[i]) !=
        FilePath::StringType::npos)
      return true;
  }

  return false;
}

bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const {
  // Basically we only accept http or https. We allow file:// URLs
  // only if --allow-file-access-from-files flag is given.
  return url.SchemeIs("http") || url.SchemeIs("https") ||
         (url.SchemeIsFile() && allow_file_access_from_files_);
}

std::string FileSystemPathManager::GetStorageIdentifierFromURL(
    const GURL& url) {
  WebKit::WebSecurityOrigin web_security_origin =
      WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
  return web_security_origin.databaseIdentifier().utf8();
}

}  // namespace fileapi

COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \
               int(fileapi::kFileSystemTypeTemporary), mismatching_enums);
COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \
               int(fileapi::kFileSystemTypePersistent), mismatching_enums);
<commit_msg>Release GetFileSystemRootPath callback on the correct thread.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "webkit/fileapi/file_system_path_manager.h"

#include "base/file_util.h"
#include "base/rand_util.h"
#include "base/logging.h"
#include "base/message_loop.h"
#include "base/message_loop_proxy.h"
#include "base/scoped_callback_factory.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "googleurl/src/gurl.h"
#include "third_party/WebKit/WebKit/chromium/public/WebCString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
#include "third_party/WebKit/WebKit/chromium/public/WebSecurityOrigin.h"
#include "webkit/glue/webkit_glue.h"

// We use some of WebKit types for conversions between storage identifiers
// and origin URLs.
using WebKit::WebFileSystem;
using WebKit::WebSecurityOrigin;
using WebKit::WebString;

using base::PlatformFileError;

namespace fileapi {

const FilePath::CharType FileSystemPathManager::kFileSystemDirectory[] =
    FILE_PATH_LITERAL("FileSystem");

const char FileSystemPathManager::kPersistentName[] = "Persistent";
const char FileSystemPathManager::kTemporaryName[] = "Temporary";

static const FilePath::CharType kFileSystemUniqueNamePrefix[] =
    FILE_PATH_LITERAL("chrome-");
static const int kFileSystemUniqueLength = 16;
static const unsigned kFileSystemUniqueDirectoryNameLength =
    kFileSystemUniqueLength + arraysize(kFileSystemUniqueNamePrefix) - 1;

namespace {

// Restricted names.
// http://dev.w3.org/2009/dap/file-system/file-dir-sys.html#naming-restrictions
static const char* const kRestrictedNames[] = {
  "con", "prn", "aux", "nul",
  "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8", "com9",
  "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
};

// Restricted chars.
static const FilePath::CharType kRestrictedChars[] = {
  '/', '\\', '<', '>', ':', '?', '*', '"', '|',
};

inline std::string FilePathStringToASCII(
    const FilePath::StringType& path_string) {
#if defined(OS_WIN)
  return WideToASCII(path_string);
#elif defined(OS_POSIX)
  return path_string;
#endif
}

FilePath::StringType CreateUniqueDirectoryName(const GURL& origin_url) {
  // This can be anything but need to be unpredictable.
  static const FilePath::CharType letters[] = FILE_PATH_LITERAL(
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789");
  FilePath::StringType unique(kFileSystemUniqueNamePrefix);
  for (int i = 0; i < kFileSystemUniqueLength; ++i)
    unique += letters[base::RandInt(0, arraysize(letters) - 2)];
  return unique;
}

}  // anonymous namespace

class FileSystemPathManager::GetFileSystemRootPathTask
    : public base::RefCountedThreadSafe<
        FileSystemPathManager::GetFileSystemRootPathTask> {
 public:
  GetFileSystemRootPathTask(
      scoped_refptr<base::MessageLoopProxy> file_message_loop,
      const std::string& name,
      FileSystemPathManager::GetRootPathCallback* callback)
      : file_message_loop_(file_message_loop),
        origin_message_loop_proxy_(
            base::MessageLoopProxy::CreateForCurrentThread()),
        name_(name),
        callback_(callback) {
  }

  void Start(const GURL& origin_url,
             const FilePath& origin_base_path,
             bool create) {
    file_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
        &GetFileSystemRootPathTask::GetFileSystemRootPathOnFileThread,
        origin_url, origin_base_path, create));
  }

 private:
  void GetFileSystemRootPathOnFileThread(
      const GURL& origin_url,
      const FilePath& base_path,
      bool create) {
    FilePath root;
    if (ReadOriginDirectory(base_path, origin_url, &root)) {
      DispatchCallbackOnCallerThread(root);
      return;
    }

    if (!create) {
      DispatchCallbackOnCallerThread(FilePath());
      return;
    }

    // Creates the root directory.
    root = base_path.Append(CreateUniqueDirectoryName(origin_url));
    if (!file_util::CreateDirectory(root)) {
      DispatchCallbackOnCallerThread(FilePath());
      return;
    }
    DispatchCallbackOnCallerThread(root);
  }

  bool ReadOriginDirectory(const FilePath& base_path,
                           const GURL& origin_url,
                           FilePath* unique) {
    file_util::FileEnumerator file_enum(
        base_path, false /* recursive */,
        file_util::FileEnumerator::DIRECTORIES,
        FilePath::StringType(kFileSystemUniqueNamePrefix) +
            FILE_PATH_LITERAL("*"));
    FilePath current;
    bool found = false;
    while (!(current = file_enum.Next()).empty()) {
      if (current.BaseName().value().length() !=
          kFileSystemUniqueDirectoryNameLength)
        continue;
      if (found) {
        // TODO(kinuko): Should notify the user to ask for some action.
        LOG(WARNING) << "Unexpectedly found more than one FileSystem "
                     << "directories for " << origin_url;
        return false;
      }
      found = true;
      *unique = current;
    }
    return !unique->empty();
  }

  void DispatchCallbackOnCallerThread(const FilePath& root_path) {
    origin_message_loop_proxy_->PostTask(FROM_HERE,
        NewRunnableMethod(this, &GetFileSystemRootPathTask::DispatchCallback,
                          root_path));
  }

  void DispatchCallback(const FilePath& root_path) {
    callback_->Run(!root_path.empty(), root_path, name_);
    callback_.reset();
  }

  scoped_refptr<base::MessageLoopProxy> file_message_loop_;
  scoped_refptr<base::MessageLoopProxy> origin_message_loop_proxy_;
  std::string name_;
  scoped_ptr<FileSystemPathManager::GetRootPathCallback> callback_;
};

FileSystemPathManager::FileSystemPathManager(
    scoped_refptr<base::MessageLoopProxy> file_message_loop,
    const FilePath& profile_path,
    bool is_incognito,
    bool allow_file_access_from_files)
    : file_message_loop_(file_message_loop),
      base_path_(profile_path.Append(kFileSystemDirectory)),
      is_incognito_(is_incognito),
      allow_file_access_from_files_(allow_file_access_from_files) {
}

FileSystemPathManager::~FileSystemPathManager() {}

void FileSystemPathManager::GetFileSystemRootPath(
    const GURL& origin_url, fileapi::FileSystemType type,
    bool create, GetRootPathCallback* callback_ptr) {
  scoped_ptr<GetRootPathCallback> callback(callback_ptr);
  if (is_incognito_) {
    // TODO(kinuko): return an isolated temporary directory.
    callback->Run(false, FilePath(), std::string());
    return;
  }

  if (!IsAllowedScheme(origin_url)) {
    callback->Run(false, FilePath(), std::string());
    return;
  }

  if (type != fileapi::kFileSystemTypeTemporary &&
      type != fileapi::kFileSystemTypePersistent) {
    LOG(WARNING) << "Unknown filesystem type is requested:" << type;
    callback->Run(false, FilePath(), std::string());
    return;
  }

  std::string storage_identifier = GetStorageIdentifierFromURL(origin_url);

  std::string type_string;
  if (type == fileapi::kFileSystemTypeTemporary)
    type_string = kTemporaryName;
  else if (type == fileapi::kFileSystemTypePersistent)
    type_string = kPersistentName;
  DCHECK(!type_string.empty());

  FilePath origin_base_path = base_path_.AppendASCII(storage_identifier)
                                        .AppendASCII(type_string);
  std::string name = storage_identifier + ":" + type_string;

  scoped_refptr<GetFileSystemRootPathTask> task =
      new GetFileSystemRootPathTask(file_message_loop_,
                                    name, callback.release());
  task->Start(origin_url, origin_base_path, create);
}

bool FileSystemPathManager::CrackFileSystemPath(
    const FilePath& path, GURL* origin_url, FileSystemType* type,
    FilePath* virtual_path) const {
  // Any paths that includes parent references are considered invalid.
  if (path.ReferencesParent())
    return false;

  // The path should be a child of the profile FileSystem path.
  FilePath relative;
  if (!base_path_.AppendRelativePath(path, &relative))
    return false;

  // The relative path from the profile FileSystem path should contain
  // at least three components, one for storage identifier, one for type
  // and one for the 'unique' part.
  std::vector<FilePath::StringType> components;
  relative.GetComponents(&components);
  if (components.size() < 3)
    return false;

  // The second component of the relative path to the root directory
  // must be kPersistent or kTemporary.
  if (!IsStringASCII(components[1]))
    return false;

  std::string ascii_type_component = FilePathStringToASCII(components[1]);
  FileSystemType cracked_type = kFileSystemTypeUnknown;
  if (ascii_type_component == kPersistentName)
    cracked_type = kFileSystemTypePersistent;
  else if (ascii_type_component == kTemporaryName)
    cracked_type = kFileSystemTypeTemporary;
  else
    return false;

  DCHECK(cracked_type != kFileSystemTypeUnknown);

  // The given |path| seems valid. Populates the |origin_url|, |type|
  // and |virtual_path| if they are given.

  if (origin_url) {
    WebSecurityOrigin web_security_origin =
        WebSecurityOrigin::createFromDatabaseIdentifier(
            webkit_glue::FilePathStringToWebString(components[0]));
    *origin_url = GURL(web_security_origin.toString());

    // We need this work-around for file:/// URIs as
    // createFromDatabaseIdentifier returns empty origin_url for them.
    if (allow_file_access_from_files_ && origin_url->spec().empty() &&
        components[0].find(FILE_PATH_LITERAL("file")) == 0)
      *origin_url = GURL("file:///");
  }

  if (type)
    *type = cracked_type;

  if (virtual_path) {
    virtual_path->clear();
    for (size_t i = 3; i < components.size(); ++i)
      *virtual_path = virtual_path->Append(components[i]);
  }

  return true;
}

bool FileSystemPathManager::IsRestrictedFileName(
    const FilePath& filename) const {
  if (filename.value().size() == 0)
    return false;

  if (IsWhitespace(filename.value()[filename.value().size() - 1]) ||
      filename.value()[filename.value().size() - 1] == '.')
    return true;

  std::string filename_lower = StringToLowerASCII(
      FilePathStringToASCII(filename.value()));

  for (size_t i = 0; i < arraysize(kRestrictedNames); ++i) {
    // Exact match.
    if (filename_lower == kRestrictedNames[i])
      return true;
    // Starts with "RESTRICTED_NAME.".
    if (filename_lower.find(std::string(kRestrictedNames[i]) + ".") == 0)
      return true;
  }

  for (size_t i = 0; i < arraysize(kRestrictedChars); ++i) {
    if (filename.value().find(kRestrictedChars[i]) !=
        FilePath::StringType::npos)
      return true;
  }

  return false;
}

bool FileSystemPathManager::IsAllowedScheme(const GURL& url) const {
  // Basically we only accept http or https. We allow file:// URLs
  // only if --allow-file-access-from-files flag is given.
  return url.SchemeIs("http") || url.SchemeIs("https") ||
         (url.SchemeIsFile() && allow_file_access_from_files_);
}

std::string FileSystemPathManager::GetStorageIdentifierFromURL(
    const GURL& url) {
  WebKit::WebSecurityOrigin web_security_origin =
      WebKit::WebSecurityOrigin::createFromString(UTF8ToUTF16(url.spec()));
  return web_security_origin.databaseIdentifier().utf8();
}

}  // namespace fileapi

COMPILE_ASSERT(int(WebFileSystem::TypeTemporary) == \
               int(fileapi::kFileSystemTypeTemporary), mismatching_enums);
COMPILE_ASSERT(int(WebFileSystem::TypePersistent) == \
               int(fileapi::kFileSystemTypePersistent), mismatching_enums);
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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.

// Creates an instance of the test_shell.
#include "build/build_config.h"

#include <stdlib.h>  // required by _set_abort_behavior

#if defined(OS_WIN)
#include <windows.h>
#include <commctrl.h>
#include "base/event_recorder.h"
#include "base/gfx/native_theme.h"
#include "base/resource_util.h"
#include "breakpad/src/client/windows/handler/exception_handler.h"
#include "webkit/tools/test_shell/foreground_helper.h"
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/icu_util.h"
#include "base/memory_debug.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/stack_container.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#include "base/trace_event.h"
#include "net/base/cookie_monster.h"
#include "net/base/net_module.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/window_open_disposition.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell.h"
#include "webkit/tools/test_shell/test_shell_request_context.h"
#include "webkit/tools/test_shell/test_shell_switches.h"

#include <iostream>
using namespace std;

#if defined(OS_WIN)
// This is only set for layout tests.
static wchar_t g_currentTestName[MAX_PATH];
#endif

namespace {

// StatsTable initialization parameters.
static const wchar_t* kStatsFile = L"testshell";
static int kStatsFileThreads = 20;
static int kStatsFileCounters = 200;

#if defined(OS_WIN)
std::string GetDataResource(HMODULE module, int resource_id) {
  void* data_ptr;
  size_t data_size;
  return base::GetDataResourceFromModule(module, resource_id, &data_ptr,
                                         &data_size) ?
      std::string(static_cast<char*>(data_ptr), data_size) : std::string();
}

// This is called indirectly by the network layer to access resources.
std::string NetResourceProvider(int key) {
  return GetDataResource(::GetModuleHandle(NULL), key);
}

void SetCurrentTestName(char* path)
{
    char* lastSlash = strrchr(path, '/');
    if (lastSlash) {
        ++lastSlash;
    } else {
        lastSlash = path;
    }

    wcscpy_s(g_currentTestName, arraysize(g_currentTestName),
             UTF8ToWide(lastSlash).c_str());
}

bool MinidumpCallback(const wchar_t *dumpPath,
                             const wchar_t *minidumpID,
                             void *context,
                             EXCEPTION_POINTERS *exinfo,
                             MDRawAssertionInfo *assertion,
                             bool succeeded)
{
    // Warning: Don't use the heap in this function.  It may be corrupted.
    if (!g_currentTestName[0])
        return false;

    // Try to rename the minidump file to include the crashed test's name.
    // StackString uses the stack but overflows onto the heap.  But we don't
    // care too much about being completely correct here, since most crashes
    // will be happening on developers' machines where they have debuggers.
    StackWString<MAX_PATH*2> origPath;
    origPath->append(dumpPath);
    origPath->push_back(file_util::kPathSeparator);
    origPath->append(minidumpID);
    origPath->append(L".dmp");

    StackWString<MAX_PATH*2>  newPath;
    newPath->append(dumpPath);
    newPath->push_back(file_util::kPathSeparator);
    newPath->append(g_currentTestName);
    newPath->append(L"-");
    newPath->append(minidumpID);
    newPath->append(L".dmp");

    // May use the heap, but oh well.  If this fails, we'll just have the
    // original dump file lying around.
    _wrename(origPath->c_str(), newPath->c_str());

    return false;
}
#endif

}  // namespace

int main(int argc, char* argv[]) {
  base::EnableTerminationOnHeapCorruption();
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#endif
  // Some tests may use base::Singleton<>, thus we need to instanciate
  // the AtExitManager or else we will leak objects.
  base::AtExitManager at_exit_manager;

#if defined(OS_LINUX)
  gtk_init(&argc, &argv);
  // Only parse the command line after GTK's had a crack at it.
  CommandLine::SetArgcArgv(argc, argv);
#endif

  CommandLine parsed_command_line;
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(test_shell::kStartupDialog))
      MessageBox(NULL, L"attach to me?", L"test_shell", MB_OK);
#endif

  // Allocate a message loop for this thread.  Although it is not used
  // directly, its constructor sets up some necessary state.
  MessageLoopForUI main_message_loop;

  bool suppress_error_dialogs = (
#if defined(OS_WIN)
       GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0) ||
#endif
       parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) ||
       parsed_command_line.HasSwitch(test_shell::kLayoutTests));
  bool layout_test_mode =
      parsed_command_line.HasSwitch(test_shell::kLayoutTests);

  TestShell::InitLogging(suppress_error_dialogs, layout_test_mode);

  // Set this early before we start using WebCore.
  webkit_glue::SetLayoutTestMode(layout_test_mode);

  // Suppress abort message in v8 library in debugging mode.
  // V8 calls abort() when it hits assertion errors.
#if defined(OS_WIN)
  if (suppress_error_dialogs) {
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
  }
#endif

  if (parsed_command_line.HasSwitch(test_shell::kEnableTracing))
    base::TraceLog::StartTracing();

#if defined(OS_WIN)
  // Make the selection of network stacks early on before any consumers try to
  // issue HTTP requests.
  if (parsed_command_line.HasSwitch(test_shell::kUseWinHttp))
    net::HttpNetworkLayer::UseWinHttp(true);
#endif

  net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL;
  bool playback_mode =
    parsed_command_line.HasSwitch(test_shell::kPlaybackMode);
  bool record_mode =
    parsed_command_line.HasSwitch(test_shell::kRecordMode);

  if (playback_mode)
    cache_mode = net::HttpCache::PLAYBACK;
  else if (record_mode)
    cache_mode = net::HttpCache::RECORD;

  if (layout_test_mode ||
      parsed_command_line.HasSwitch(test_shell::kEnableFileCookies))
    net::CookieMonster::EnableFileScheme();

  std::wstring cache_path =
      parsed_command_line.GetSwitchValue(test_shell::kCacheDir);
  if (cache_path.empty()) {
    PathService::Get(base::DIR_EXE, &cache_path);
    file_util::AppendToPath(&cache_path, L"cache");
  }

  // Initializing with a default context, which means no on-disk cookie DB,
  // and no support for directory listings.
  SimpleResourceLoaderBridge::Init(
      new TestShellRequestContext(cache_path, cache_mode));

  // Load ICU data tables
  icu_util::Initialize();

#if defined(OS_WIN)
  // Config the network module so it has access to a limited set of resources.
  net::NetModule::SetResourceProvider(NetResourceProvider);

  INITCOMMONCONTROLSEX InitCtrlEx;

  InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  InitCtrlEx.dwICC  = ICC_STANDARD_CLASSES;
  InitCommonControlsEx(&InitCtrlEx);

  // Register the Ahem font used by layout tests.
  DWORD num_fonts = 1;
  void* font_ptr;
  size_t font_size;
  if (base::GetDataResourceFromModule(::GetModuleHandle(NULL), IDR_AHEM_FONT,
                                      &font_ptr, &font_size)) {
    HANDLE rc = AddFontMemResourceEx(font_ptr, font_size, 0, &num_fonts);
    DCHECK(rc != 0);
  }
#endif

  bool interactive = !layout_test_mode;
  TestShell::InitializeTestShell(interactive);

  if (parsed_command_line.HasSwitch(test_shell::kAllowScriptsToCloseWindows))
    TestShell::SetAllowScriptsToCloseWindows();

  // Disable user themes for layout tests so pixel tests are consistent.
#if defined(OS_WIN)
  if (!interactive)
    gfx::NativeTheme::instance()->DisableTheming();
#endif

  if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) {
    const std::wstring timeout_str = parsed_command_line.GetSwitchValue(
        test_shell::kTestShellTimeOut);
    int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str()));
    if (timeout_ms > 0)
      TestShell::SetFileTestTimeout(timeout_ms);
  }

#if defined(OS_WIN)
  // Initialize global strings
  TestShell::RegisterWindowClass();
#endif

  // Treat the first loose value as the initial URL to open.
  std::wstring uri;

  // Default to a homepage if we're interactive.
  if (interactive) {
    PathService::Get(base::DIR_SOURCE_ROOT, &uri);
    file_util::AppendToPath(&uri, L"webkit");
    file_util::AppendToPath(&uri, L"data");
    file_util::AppendToPath(&uri, L"test_shell");
    file_util::AppendToPath(&uri, L"index.html");
  }

  if (parsed_command_line.GetLooseValueCount() > 0) {
    CommandLine::LooseValueIterator iter(
        parsed_command_line.GetLooseValuesBegin());
    uri = *iter;
  }

#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) {
    std::wstring dir(
        parsed_command_line.GetSwitchValue(test_shell::kCrashDumps));
    new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true);
  }
#endif

  std::wstring js_flags =
    parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags);
  // Test shell always exposes the GC.
  CommandLine::AppendSwitch(&js_flags, L"expose-gc");
  webkit_glue::SetJavaScriptFlags(js_flags);
  // Also expose GCController to JavaScript.
  webkit_glue::SetShouldExposeGCController(true);

  // load and initialize the stats table.
  StatsTable *table = new StatsTable(kStatsFile, kStatsFileThreads, kStatsFileCounters);
  StatsTable::set_current(table);

  TestShell* shell;
  if (TestShell::CreateNewWindow(uri, &shell)) {
#if defined(OS_WIN)
    if (record_mode || playback_mode) {
      // Move the window to the upper left corner for consistent
      // record/playback mode.  For automation, we want this to work
      // on build systems where the script invoking us is a background
      // process.  So for this case, make our window the topmost window
      // as well.
      ForegroundHelper::SetForeground(shell->mainWnd());
      ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0);
      // Tell webkit as well.
      webkit_glue::SetRecordPlaybackMode(true);
    }
#endif

    shell->Show(shell->webView(), NEW_WINDOW);

    if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable))
      shell->DumpStatsTableOnExit();

#if defined(OS_WIN)
    bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents);
    if ((record_mode || playback_mode) && !no_events) {
      std::wstring script_path = cache_path;
      // Create the cache directory in case it doesn't exist.
      file_util::CreateDirectory(cache_path);
      file_util::AppendToPath(&script_path, L"script.log");
      if (record_mode)
        base::EventRecorder::current()->StartRecording(script_path);
      if (playback_mode)
        base::EventRecorder::current()->StartPlayback(script_path);
    }
#endif

    if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) {
      base::MemoryDebug::SetMemoryInUseEnabled(true);
      // Dump all in use memory at startup
      base::MemoryDebug::DumpAllMemoryInUse();
    }

    // See if we need to run the tests.
    if (layout_test_mode) {
      // Set up for the kind of test requested.
      TestShell::TestParams params;
      if (parsed_command_line.HasSwitch(test_shell::kDumpPixels)) {
        // The pixel test flag also gives the image file name to use.
        params.dump_pixels = true;
        params.pixel_file_name = parsed_command_line.GetSwitchValue(
            test_shell::kDumpPixels);
        if (params.pixel_file_name.size() == 0) {
          fprintf(stderr, "No file specified for pixel tests");
          exit(1);
        }
      }
      if (parsed_command_line.HasSwitch(test_shell::kNoTree)) {
          params.dump_tree = false;
      }

      if (uri.length() == 0) {
        // Watch stdin for URLs.
        char filenameBuffer[2048];
        while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
          char *newLine = strchr(filenameBuffer, '\n');
          if (newLine)
            *newLine = '\0';
          if (!*filenameBuffer)
            continue;

#if defined(OS_WIN)
          SetCurrentTestName(filenameBuffer);
#endif

          if (!TestShell::RunFileTest(filenameBuffer, params))
            break;
        }
      } else {
        TestShell::RunFileTest(WideToUTF8(uri).c_str(), params);
      }

      shell->CallJSGC();
      shell->CallJSGC();
      if (shell) delete shell;
    } else {
      MessageLoop::current()->Run();
    }

    // Flush any remaining messages.  This ensures that any accumulated
    // Task objects get destroyed before we exit, which avoids noise in
    // purify leak-test results.
    MessageLoop::current()->RunAllPending();

#if defined(OS_WIN)
    if (record_mode)
      base::EventRecorder::current()->StopRecording();
    if (playback_mode)
      base::EventRecorder::current()->StopPlayback();
#endif
  }

  TestShell::ShutdownTestShell();
  TestShell::CleanupLogging();

  // Tear down shared StatsTable; prevents unit_tests from leaking it.
  StatsTable::set_current(NULL);
  delete table;

#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif
  return 0;
}
<commit_msg>Make test_shell stats table names unique. On Linux, our shared memory name can conflict across users.  For now, just try to make the name unique.  Eventually we should work towards improving our stats table implementation.<commit_after>// Copyright (c) 2006-2008 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.

// Creates an instance of the test_shell.
#include "build/build_config.h"

#include <stdlib.h>  // required by _set_abort_behavior

#if defined(OS_WIN)
#include <windows.h>
#include <commctrl.h>
#include "base/event_recorder.h"
#include "base/gfx/native_theme.h"
#include "base/resource_util.h"
#include "breakpad/src/client/windows/handler/exception_handler.h"
#include "webkit/tools/test_shell/foreground_helper.h"
#endif

#if defined(OS_LINUX)
#include <gtk/gtk.h>
#endif

#include "base/at_exit.h"
#include "base/basictypes.h"
#include "base/command_line.h"
#include "base/file_util.h"
#include "base/icu_util.h"
#include "base/memory_debug.h"
#include "base/message_loop.h"
#include "base/path_service.h"
#include "base/process_util.h"
#include "base/rand_util.h"
#include "base/stack_container.h"
#include "base/stats_table.h"
#include "base/string_util.h"
#include "base/trace_event.h"
#include "net/base/cookie_monster.h"
#include "net/base/net_module.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
#include "net/url_request/url_request_context.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/window_open_disposition.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"
#include "webkit/tools/test_shell/test_shell.h"
#include "webkit/tools/test_shell/test_shell_request_context.h"
#include "webkit/tools/test_shell/test_shell_switches.h"

#include <iostream>
using namespace std;

#if defined(OS_WIN)
// This is only set for layout tests.
static wchar_t g_currentTestName[MAX_PATH];
#endif

namespace {

// StatsTable initialization parameters.
static const wchar_t* kStatsFilePrefix = L"testshell_";
static int kStatsFileThreads = 20;
static int kStatsFileCounters = 200;

#if defined(OS_WIN)
std::string GetDataResource(HMODULE module, int resource_id) {
  void* data_ptr;
  size_t data_size;
  return base::GetDataResourceFromModule(module, resource_id, &data_ptr,
                                         &data_size) ?
      std::string(static_cast<char*>(data_ptr), data_size) : std::string();
}

// This is called indirectly by the network layer to access resources.
std::string NetResourceProvider(int key) {
  return GetDataResource(::GetModuleHandle(NULL), key);
}

void SetCurrentTestName(char* path)
{
    char* lastSlash = strrchr(path, '/');
    if (lastSlash) {
        ++lastSlash;
    } else {
        lastSlash = path;
    }

    wcscpy_s(g_currentTestName, arraysize(g_currentTestName),
             UTF8ToWide(lastSlash).c_str());
}

bool MinidumpCallback(const wchar_t *dumpPath,
                             const wchar_t *minidumpID,
                             void *context,
                             EXCEPTION_POINTERS *exinfo,
                             MDRawAssertionInfo *assertion,
                             bool succeeded)
{
    // Warning: Don't use the heap in this function.  It may be corrupted.
    if (!g_currentTestName[0])
        return false;

    // Try to rename the minidump file to include the crashed test's name.
    // StackString uses the stack but overflows onto the heap.  But we don't
    // care too much about being completely correct here, since most crashes
    // will be happening on developers' machines where they have debuggers.
    StackWString<MAX_PATH*2> origPath;
    origPath->append(dumpPath);
    origPath->push_back(file_util::kPathSeparator);
    origPath->append(minidumpID);
    origPath->append(L".dmp");

    StackWString<MAX_PATH*2>  newPath;
    newPath->append(dumpPath);
    newPath->push_back(file_util::kPathSeparator);
    newPath->append(g_currentTestName);
    newPath->append(L"-");
    newPath->append(minidumpID);
    newPath->append(L".dmp");

    // May use the heap, but oh well.  If this fails, we'll just have the
    // original dump file lying around.
    _wrename(origPath->c_str(), newPath->c_str());

    return false;
}
#endif

}  // namespace

int main(int argc, char* argv[]) {
  base::EnableTerminationOnHeapCorruption();
#ifdef _CRTDBG_MAP_ALLOC
  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
#endif
  // Some tests may use base::Singleton<>, thus we need to instanciate
  // the AtExitManager or else we will leak objects.
  base::AtExitManager at_exit_manager;

#if defined(OS_LINUX)
  gtk_init(&argc, &argv);
  // Only parse the command line after GTK's had a crack at it.
  CommandLine::SetArgcArgv(argc, argv);
#endif

  CommandLine parsed_command_line;
#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(test_shell::kStartupDialog))
      MessageBox(NULL, L"attach to me?", L"test_shell", MB_OK);
#endif

  // Allocate a message loop for this thread.  Although it is not used
  // directly, its constructor sets up some necessary state.
  MessageLoopForUI main_message_loop;

  bool suppress_error_dialogs = (
#if defined(OS_WIN)
       GetEnvironmentVariable(L"CHROME_HEADLESS", NULL, 0) ||
#endif
       parsed_command_line.HasSwitch(test_shell::kNoErrorDialogs) ||
       parsed_command_line.HasSwitch(test_shell::kLayoutTests));
  bool layout_test_mode =
      parsed_command_line.HasSwitch(test_shell::kLayoutTests);

  TestShell::InitLogging(suppress_error_dialogs, layout_test_mode);

  // Set this early before we start using WebCore.
  webkit_glue::SetLayoutTestMode(layout_test_mode);

  // Suppress abort message in v8 library in debugging mode.
  // V8 calls abort() when it hits assertion errors.
#if defined(OS_WIN)
  if (suppress_error_dialogs) {
    _set_abort_behavior(0, _WRITE_ABORT_MSG);
  }
#endif

  if (parsed_command_line.HasSwitch(test_shell::kEnableTracing))
    base::TraceLog::StartTracing();

#if defined(OS_WIN)
  // Make the selection of network stacks early on before any consumers try to
  // issue HTTP requests.
  if (parsed_command_line.HasSwitch(test_shell::kUseWinHttp))
    net::HttpNetworkLayer::UseWinHttp(true);
#endif

  net::HttpCache::Mode cache_mode = net::HttpCache::NORMAL;
  bool playback_mode =
    parsed_command_line.HasSwitch(test_shell::kPlaybackMode);
  bool record_mode =
    parsed_command_line.HasSwitch(test_shell::kRecordMode);

  if (playback_mode)
    cache_mode = net::HttpCache::PLAYBACK;
  else if (record_mode)
    cache_mode = net::HttpCache::RECORD;

  if (layout_test_mode ||
      parsed_command_line.HasSwitch(test_shell::kEnableFileCookies))
    net::CookieMonster::EnableFileScheme();

  std::wstring cache_path =
      parsed_command_line.GetSwitchValue(test_shell::kCacheDir);
  if (cache_path.empty()) {
    PathService::Get(base::DIR_EXE, &cache_path);
    file_util::AppendToPath(&cache_path, L"cache");
  }

  // Initializing with a default context, which means no on-disk cookie DB,
  // and no support for directory listings.
  SimpleResourceLoaderBridge::Init(
      new TestShellRequestContext(cache_path, cache_mode));

  // Load ICU data tables
  icu_util::Initialize();

#if defined(OS_WIN)
  // Config the network module so it has access to a limited set of resources.
  net::NetModule::SetResourceProvider(NetResourceProvider);

  INITCOMMONCONTROLSEX InitCtrlEx;

  InitCtrlEx.dwSize = sizeof(INITCOMMONCONTROLSEX);
  InitCtrlEx.dwICC  = ICC_STANDARD_CLASSES;
  InitCommonControlsEx(&InitCtrlEx);

  // Register the Ahem font used by layout tests.
  DWORD num_fonts = 1;
  void* font_ptr;
  size_t font_size;
  if (base::GetDataResourceFromModule(::GetModuleHandle(NULL), IDR_AHEM_FONT,
                                      &font_ptr, &font_size)) {
    HANDLE rc = AddFontMemResourceEx(font_ptr, font_size, 0, &num_fonts);
    DCHECK(rc != 0);
  }
#endif

  bool interactive = !layout_test_mode;
  TestShell::InitializeTestShell(interactive);

  if (parsed_command_line.HasSwitch(test_shell::kAllowScriptsToCloseWindows))
    TestShell::SetAllowScriptsToCloseWindows();

  // Disable user themes for layout tests so pixel tests are consistent.
#if defined(OS_WIN)
  if (!interactive)
    gfx::NativeTheme::instance()->DisableTheming();
#endif

  if (parsed_command_line.HasSwitch(test_shell::kTestShellTimeOut)) {
    const std::wstring timeout_str = parsed_command_line.GetSwitchValue(
        test_shell::kTestShellTimeOut);
    int timeout_ms = static_cast<int>(StringToInt64(timeout_str.c_str()));
    if (timeout_ms > 0)
      TestShell::SetFileTestTimeout(timeout_ms);
  }

#if defined(OS_WIN)
  // Initialize global strings
  TestShell::RegisterWindowClass();
#endif

  // Treat the first loose value as the initial URL to open.
  std::wstring uri;

  // Default to a homepage if we're interactive.
  if (interactive) {
    PathService::Get(base::DIR_SOURCE_ROOT, &uri);
    file_util::AppendToPath(&uri, L"webkit");
    file_util::AppendToPath(&uri, L"data");
    file_util::AppendToPath(&uri, L"test_shell");
    file_util::AppendToPath(&uri, L"index.html");
  }

  if (parsed_command_line.GetLooseValueCount() > 0) {
    CommandLine::LooseValueIterator iter(
        parsed_command_line.GetLooseValuesBegin());
    uri = *iter;
  }

#if defined(OS_WIN)
  if (parsed_command_line.HasSwitch(test_shell::kCrashDumps)) {
    std::wstring dir(
        parsed_command_line.GetSwitchValue(test_shell::kCrashDumps));
    new google_breakpad::ExceptionHandler(dir, 0, &MinidumpCallback, 0, true);
  }
#endif

  std::wstring js_flags =
    parsed_command_line.GetSwitchValue(test_shell::kJavaScriptFlags);
  // Test shell always exposes the GC.
  CommandLine::AppendSwitch(&js_flags, L"expose-gc");
  webkit_glue::SetJavaScriptFlags(js_flags);
  // Also expose GCController to JavaScript.
  webkit_glue::SetShouldExposeGCController(true);

  // Load and initialize the stats table.  Attempt to construct a somewhat
  // unique name to isolate separate instances from each other.
  StatsTable *table = new StatsTable(
      kStatsFilePrefix + Uint64ToWString(base::RandUint64()),
      kStatsFileThreads,
      kStatsFileCounters);
  StatsTable::set_current(table);

  TestShell* shell;
  if (TestShell::CreateNewWindow(uri, &shell)) {
#if defined(OS_WIN)
    if (record_mode || playback_mode) {
      // Move the window to the upper left corner for consistent
      // record/playback mode.  For automation, we want this to work
      // on build systems where the script invoking us is a background
      // process.  So for this case, make our window the topmost window
      // as well.
      ForegroundHelper::SetForeground(shell->mainWnd());
      ::SetWindowPos(shell->mainWnd(), HWND_TOP, 0, 0, 600, 800, 0);
      // Tell webkit as well.
      webkit_glue::SetRecordPlaybackMode(true);
    }
#endif

    shell->Show(shell->webView(), NEW_WINDOW);

    if (parsed_command_line.HasSwitch(test_shell::kDumpStatsTable))
      shell->DumpStatsTableOnExit();

#if defined(OS_WIN)
    bool no_events = parsed_command_line.HasSwitch(test_shell::kNoEvents);
    if ((record_mode || playback_mode) && !no_events) {
      std::wstring script_path = cache_path;
      // Create the cache directory in case it doesn't exist.
      file_util::CreateDirectory(cache_path);
      file_util::AppendToPath(&script_path, L"script.log");
      if (record_mode)
        base::EventRecorder::current()->StartRecording(script_path);
      if (playback_mode)
        base::EventRecorder::current()->StartPlayback(script_path);
    }
#endif

    if (parsed_command_line.HasSwitch(test_shell::kDebugMemoryInUse)) {
      base::MemoryDebug::SetMemoryInUseEnabled(true);
      // Dump all in use memory at startup
      base::MemoryDebug::DumpAllMemoryInUse();
    }

    // See if we need to run the tests.
    if (layout_test_mode) {
      // Set up for the kind of test requested.
      TestShell::TestParams params;
      if (parsed_command_line.HasSwitch(test_shell::kDumpPixels)) {
        // The pixel test flag also gives the image file name to use.
        params.dump_pixels = true;
        params.pixel_file_name = parsed_command_line.GetSwitchValue(
            test_shell::kDumpPixels);
        if (params.pixel_file_name.size() == 0) {
          fprintf(stderr, "No file specified for pixel tests");
          exit(1);
        }
      }
      if (parsed_command_line.HasSwitch(test_shell::kNoTree)) {
          params.dump_tree = false;
      }

      if (uri.length() == 0) {
        // Watch stdin for URLs.
        char filenameBuffer[2048];
        while (fgets(filenameBuffer, sizeof(filenameBuffer), stdin)) {
          char *newLine = strchr(filenameBuffer, '\n');
          if (newLine)
            *newLine = '\0';
          if (!*filenameBuffer)
            continue;

#if defined(OS_WIN)
          SetCurrentTestName(filenameBuffer);
#endif

          if (!TestShell::RunFileTest(filenameBuffer, params))
            break;
        }
      } else {
        TestShell::RunFileTest(WideToUTF8(uri).c_str(), params);
      }

      shell->CallJSGC();
      shell->CallJSGC();
      if (shell) delete shell;
    } else {
      MessageLoop::current()->Run();
    }

    // Flush any remaining messages.  This ensures that any accumulated
    // Task objects get destroyed before we exit, which avoids noise in
    // purify leak-test results.
    MessageLoop::current()->RunAllPending();

#if defined(OS_WIN)
    if (record_mode)
      base::EventRecorder::current()->StopRecording();
    if (playback_mode)
      base::EventRecorder::current()->StopPlayback();
#endif
  }

  TestShell::ShutdownTestShell();
  TestShell::CleanupLogging();

  // Tear down shared StatsTable; prevents unit_tests from leaking it.
  StatsTable::set_current(NULL);
  delete table;

#ifdef _CRTDBG_MAP_ALLOC
  _CrtDumpMemoryLeaks();
#endif
  return 0;
}
<|endoftext|>


<commit_before>#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <sys/mman.h>
#include <stdio.h>
// Physical base address of GPIO
const unsigned gpio_address = 0x400d0000;
// Length of memory-mapped IO window
const unsigned gpio_size = 0xff;
const int gpio_led1_offset = 0x12C; // Offset for LED1
const int gpio_led2_offset = 0x130; // Offset for LED2
const int gpio_led3_offset = 0x134; // Offset for LED3
const int gpio_led4_offset = 0x138; // Offset for LED4
const int gpio_led5_offset = 0x13C; // Offset for LED5
const int gpio_led6_offset = 0x140; // Offset for LED6
const int gpio_led7_offset = 0x144; // Offset for LED7
const int gpio_led8_offset = 0x148; // Offset for LED8
const int gpio_sw1_offset = 0x14C; // Offset for Switch 1
const int gpio_sw2_offset = 0x150; // Offset for Switch 2
const int gpio_sw3_offset = 0x154; // Offset for Switch 3
const int gpio_sw4_offset = 0x158; // Offset for Switch 4
const int gpio_sw5_offset = 0x15C; // Offset for Switch 5
const int gpio_sw6_offset = 0x160; // Offset for Switch 6
const int gpio_sw7_offset = 0x164; // Offset for Switch 7
const int gpio_sw8_offset = 0x168; // Offset for Switch 8
const int gpio_pbtnl_offset = 0x16C; // Offset for left push button
const int gpio_pbtnr_offset = 0x170; // Offset for right push button
const int gpio_pbtnu_offset = 0x174; // Offset for up push button
const int gpio_pbtnd_offset = 0x178; // Offset for down push button
const int gpio_pbtnc_offset = 0x17C; // Offset for center push button

/**
 * Write a 4-byte value at the specified general-purpose I/O location.
 *
 * @param ptr Base address returned by 'mmap'.
 * @parem offset Offset where device is mapped.
 * @param value Value to be written.
 */
void registerWrite(char *ptr, int offset, int value) {
	* (int *) (ptr + offset) = value;
}

/**
 * Read a 4-byte value from the specified general-purpose I/O location.
 *
 * @param ptr Base address returned by 'mmap'.
 * @param offset Offset where device is mapped.
 * @return Value read.
 */
int registerRead(char *ptr, int offset) {
	return * (int *) (ptr + offset);
}

/**
 * Initialize general-purpose I/O
 * - Opens access to physical memory /dev/mem
 * - Maps memory at offset 'gpio_address' into virtual address space
 *
 * @param fd
 * File descriptor passed by reference, where the result
 * of function 'open' will be stored.
 *
 * @return
 * Address to virtual memory which is mapped to physical,
 * or MAP_FAILED on error.
 */
char *initialize(int *fd) {
	*fd = open( "/dev/mem", O_RDWR);
	return (char *) mmap(
		NULL,
		gpio_size,
		PROT_READ | PROT_WRITE,
		MAP_SHARED,
		*fd,
		gpio_address);
}

/**
 * Close general-purpose I/O.
 *
 * @param ptr Virtual address where I/O was mapped.
 * @param fd File descriptor previously returned by 'open'.
 */
void finalize(char *ptr, int fd) {
	munmap(ptr, gpio_size);
	close(fd);
}

/**
 * Show lower 8 bits of integer value on LEDs
 *
 * @param ptr Base address of I/O
 * @param value Value to show on LEDs
 */
void setLedNumber(char *ptr, int value) {
	registerWrite(ptr, gpio_led1_offset, value % 2);
	registerWrite(ptr, gpio_led2_offset, (value / 2) % 2);
	registerWrite(ptr, gpio_led3_offset, (value / 4) % 2);
	registerWrite(ptr, gpio_led4_offset, (value / 8) % 2);
	registerWrite(ptr, gpio_led5_offset, (value / 16) % 2);
	registerWrite(ptr, gpio_led6_offset, (value / 32) % 2);
	registerWrite(ptr, gpio_led7_offset, (value / 64) % 2);
	registerWrite(ptr, gpio_led8_offset, (value / 128) % 2);
}

/** Set the state of the LED with the given index.
 *
 * @param ptr Base address for general-purpose I/O
 * @parem led_index LED index between 0 and 7
 * @param state Turn on (1) or off (0)
 */
void setLedState(char *ptr, int led_index, int state) {
	int offset;
	switch(led_index) {
		case 0:
			offset = gpio_led1_offset;
			break;
		case 1:
			offset = gpio_led2_offset;
			break;
		case 2:
			offset = gpio_led3_offset;
			break;
		case 3:
			offset = gpio_led4_offset;
			break;
		case 4:
			offset = gpio_led5_offset;
			break;
		case 5:
			offset = gpio_led6_offset;
			break;
		case 6:
			offset = gpio_led7_offset;
			break;
		case 7:
			offset = gpio_led8_offset;
			break;
		default:
			return;
	}
	* (int *) (ptr + offset) = state;
}

int readSwitch(char *ptr, int switch_index) {
	switch(switch_index) {
		case 0:
			return registerRead(ptr, gpio_sw1_offset);
		case 1:
			return registerRead(ptr, gpio_sw2_offset);
		case 2:
			return registerRead(ptr, gpio_sw3_offset);
		case 3:
			return registerRead(ptr, gpio_sw4_offset);
		case 4:
			return registerRead(ptr, gpio_sw5_offset);
		case 5:
			return registerRead(ptr, gpio_sw6_offset);
		case 6:
			return registerRead(ptr, gpio_sw7_offset);
		case 7:
			return registerRead(ptr, gpio_sw8_offset);
	}
	return -1;
}

int readDirection(char *ptr) {
	if(registerRead(ptr, gpio_pbtnu_offset)) {
		return 1;
	}
	if(registerRead(ptr, gpio_pbtnd_offset)) {
		return 2;
	}
	if(registerRead(ptr, gpio_pbtnl_offset)) {
		return 3;
	}
	if(registerRead(ptr, gpio_pbtnr_offset)) {
		return 4;
	}
	if(registerRead(ptr, gpio_pbtnc_offset)) {
		return 5;
	}
	return 0;
}

int getSwitchState(char *ptr) {
	int state = 0;
	for(int i = 0; i < 8; i++) {
		if(readSwitch(ptr, i)) {
			state += 0b1 << i;
		}
	}
	return state;
}

int main() {
	// Initialize
	int fd;
	char *ptr = initialize(&fd);

	int state = getSwitchState(ptr);

	bool pressed = false;
	while(true) {
		int direction = readDirection(ptr);
		if(!pressed && direction == 1) {
			pressed = true;
			state += 1;
		}
		else if(!pressed && direction == 2) {
			pressed = true;
			state -= 1;
		}
		else if(!pressed && direction == 3) {
			pressed = true;
			state <<= 1;
		}
		else if(!pressed && direction == 4) {
			pressed = true;
			state >>= 1;
		}
		else if(!pressed && direction == 5) {
			pressed = true;
			state = getSwitchState(ptr);
		}
		else if(direction == 0) {
			pressed = false;
		}

		for(int i = 0; i < 8; i++) {
			setLedState(ptr, i, (state >> i) & 1);
		}
	}

	return 0;
}
<commit_msg>Add sleep to account for inaccurate buttons<commit_after>#include <fcntl.h>
#include <unistd.h>
#include <iostream>
#include <sys/mman.h>
#include <stdio.h>
// Physical base address of GPIO
const unsigned gpio_address = 0x400d0000;
// Length of memory-mapped IO window
const unsigned gpio_size = 0xff;
const int gpio_led1_offset = 0x12C; // Offset for LED1
const int gpio_led2_offset = 0x130; // Offset for LED2
const int gpio_led3_offset = 0x134; // Offset for LED3
const int gpio_led4_offset = 0x138; // Offset for LED4
const int gpio_led5_offset = 0x13C; // Offset for LED5
const int gpio_led6_offset = 0x140; // Offset for LED6
const int gpio_led7_offset = 0x144; // Offset for LED7
const int gpio_led8_offset = 0x148; // Offset for LED8
const int gpio_sw1_offset = 0x14C; // Offset for Switch 1
const int gpio_sw2_offset = 0x150; // Offset for Switch 2
const int gpio_sw3_offset = 0x154; // Offset for Switch 3
const int gpio_sw4_offset = 0x158; // Offset for Switch 4
const int gpio_sw5_offset = 0x15C; // Offset for Switch 5
const int gpio_sw6_offset = 0x160; // Offset for Switch 6
const int gpio_sw7_offset = 0x164; // Offset for Switch 7
const int gpio_sw8_offset = 0x168; // Offset for Switch 8
const int gpio_pbtnl_offset = 0x16C; // Offset for left push button
const int gpio_pbtnr_offset = 0x170; // Offset for right push button
const int gpio_pbtnu_offset = 0x174; // Offset for up push button
const int gpio_pbtnd_offset = 0x178; // Offset for down push button
const int gpio_pbtnc_offset = 0x17C; // Offset for center push button

/**
 * Write a 4-byte value at the specified general-purpose I/O location.
 *
 * @param ptr Base address returned by 'mmap'.
 * @parem offset Offset where device is mapped.
 * @param value Value to be written.
 */
void registerWrite(char *ptr, int offset, int value) {
	* (int *) (ptr + offset) = value;
}

/**
 * Read a 4-byte value from the specified general-purpose I/O location.
 *
 * @param ptr Base address returned by 'mmap'.
 * @param offset Offset where device is mapped.
 * @return Value read.
 */
int registerRead(char *ptr, int offset) {
	return * (int *) (ptr + offset);
}

/**
 * Initialize general-purpose I/O
 * - Opens access to physical memory /dev/mem
 * - Maps memory at offset 'gpio_address' into virtual address space
 *
 * @param fd
 * File descriptor passed by reference, where the result
 * of function 'open' will be stored.
 *
 * @return
 * Address to virtual memory which is mapped to physical,
 * or MAP_FAILED on error.
 */
char *initialize(int *fd) {
	*fd = open( "/dev/mem", O_RDWR);
	return (char *) mmap(
		NULL,
		gpio_size,
		PROT_READ | PROT_WRITE,
		MAP_SHARED,
		*fd,
		gpio_address);
}

/**
 * Close general-purpose I/O.
 *
 * @param ptr Virtual address where I/O was mapped.
 * @param fd File descriptor previously returned by 'open'.
 */
void finalize(char *ptr, int fd) {
	munmap(ptr, gpio_size);
	close(fd);
}

/**
 * Show lower 8 bits of integer value on LEDs
 *
 * @param ptr Base address of I/O
 * @param value Value to show on LEDs
 */
void setLedNumber(char *ptr, int value) {
	registerWrite(ptr, gpio_led1_offset, value % 2);
	registerWrite(ptr, gpio_led2_offset, (value / 2) % 2);
	registerWrite(ptr, gpio_led3_offset, (value / 4) % 2);
	registerWrite(ptr, gpio_led4_offset, (value / 8) % 2);
	registerWrite(ptr, gpio_led5_offset, (value / 16) % 2);
	registerWrite(ptr, gpio_led6_offset, (value / 32) % 2);
	registerWrite(ptr, gpio_led7_offset, (value / 64) % 2);
	registerWrite(ptr, gpio_led8_offset, (value / 128) % 2);
}

/** Set the state of the LED with the given index.
 *
 * @param ptr Base address for general-purpose I/O
 * @parem led_index LED index between 0 and 7
 * @param state Turn on (1) or off (0)
 */
void setLedState(char *ptr, int led_index, int state) {
	int offset;
	switch(led_index) {
		case 0:
			offset = gpio_led1_offset;
			break;
		case 1:
			offset = gpio_led2_offset;
			break;
		case 2:
			offset = gpio_led3_offset;
			break;
		case 3:
			offset = gpio_led4_offset;
			break;
		case 4:
			offset = gpio_led5_offset;
			break;
		case 5:
			offset = gpio_led6_offset;
			break;
		case 6:
			offset = gpio_led7_offset;
			break;
		case 7:
			offset = gpio_led8_offset;
			break;
		default:
			return;
	}
	* (int *) (ptr + offset) = state;
}

int readSwitch(char *ptr, int switch_index) {
	switch(switch_index) {
		case 0:
			return registerRead(ptr, gpio_sw1_offset);
		case 1:
			return registerRead(ptr, gpio_sw2_offset);
		case 2:
			return registerRead(ptr, gpio_sw3_offset);
		case 3:
			return registerRead(ptr, gpio_sw4_offset);
		case 4:
			return registerRead(ptr, gpio_sw5_offset);
		case 5:
			return registerRead(ptr, gpio_sw6_offset);
		case 6:
			return registerRead(ptr, gpio_sw7_offset);
		case 7:
			return registerRead(ptr, gpio_sw8_offset);
	}
	return -1;
}

int readDirection(char *ptr) {
	if(registerRead(ptr, gpio_pbtnu_offset)) {
		return 1;
	}
	if(registerRead(ptr, gpio_pbtnd_offset)) {
		return 2;
	}
	if(registerRead(ptr, gpio_pbtnl_offset)) {
		return 3;
	}
	if(registerRead(ptr, gpio_pbtnr_offset)) {
		return 4;
	}
	if(registerRead(ptr, gpio_pbtnc_offset)) {
		return 5;
	}
	return 0;
}

int getSwitchState(char *ptr) {
	int state = 0;
	for(int i = 0; i < 8; i++) {
		if(readSwitch(ptr, i)) {
			state += 0b1 << i;
		}
	}
	return state;
}

int main() {
	// Initialize
	int fd;
	char *ptr = initialize(&fd);

	int state = getSwitchState(ptr);

	bool pressed = false;
	while(true) {
		int direction = readDirection(ptr);
		if(!pressed && direction == 1) {
			pressed = true;
			state += 1;
		}
		else if(!pressed && direction == 2) {
			pressed = true;
			state -= 1;
		}
		else if(!pressed && direction == 3) {
			pressed = true;
			state <<= 1;
		}
		else if(!pressed && direction == 4) {
			pressed = true;
			state >>= 1;
		}
		else if(!pressed && direction == 5) {
			pressed = true;
			state = getSwitchState(ptr);
		}
		else if(direction == 0) {
			pressed = false;
		}

		for(int i = 0; i < 8; i++) {
			setLedState(ptr, i, (state >> i) & 1);
		}
		usleep(100 * 1000);
	}

	return 0;
}
<|endoftext|>


<commit_before>#include "Thermostat.h"
#include "Andersen.h"
#include "Lowe_Andersen.h"
#include "Gaussian.h"
#include "Nose_Hoover.h"
#include "Thermostat_None.h"
#include "Berendsen.h"
#include "Bussi.h"

#include "Functions.h"
#include "consts.h"
using namespace consts;

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
using namespace std;

/* ######################### */
int main(int argc, char* argv[]) {
	//default für  p,Temp,dtime,runs,warmlauf,ausgabe   :jedes xte wird ausgegeben
	double a_para[]{4, 20, 1E-15, 1E6, 1E3, 1};
	int			i_para{ 1 };
	string s_para{}, s_therm{};
	string	s_temp{}, s_pos_vel{};
	ofstream dat_temp{}, dat_pos_vel{};
	Thermostat *thermostat{};

	// Bestimmen der Parameter zur Initialisierung von Poly und Thermostat
	for (i_para = 1; i_para < min(7, argc); ++i_para) {
		if (is_number(argv[i_para])) a_para[i_para - 1] = stod(argv[i_para]);
		else break;
	}
	a_para[2] /= ref_time;

	while (i_para < argc - 1 && is_number(argv[i_para])) ++i_para;
	int i_thermos = i_para;

	while (++i_para < argc - 1 && is_number(argv[i_para])) ++i_para;
	int i_poly_init = min(argc - 1, i_para);

	Polymer poly{ static_cast<unsigned> (a_para[0]), a_para[1] };
	if (strcmp(argv[i_poly_init], "one") == 0)
		poly.initiate_monomers_one();
	else
		poly.initiate_monomers_random();

	// Auswählen des Thermostats
	if (argc > 1 && i_thermos < argc) {
		if (strcmp(argv[i_thermos], "Andersen") == 0) {
			double nu{ set_param(1. / a_para[2] / a_para[0], argv, argc, i_thermos + 1) };
			thermostat = new Andersen{ poly, a_para[2], nu };
			s_therm = "Andersen";
		}
		else if (strcmp(argv[i_thermos], "Lowe_Andersen") == 0) {
			double nu{ set_param(1. / a_para[2] / a_para[0], argv, argc, i_thermos + 1) };
			thermostat = new Lowe_Andersen{ poly, a_para[2], nu };
			s_therm = "Lowe_Andersen";
		}
		else if (strcmp(argv[i_thermos], "Gaussian") == 0) {
			thermostat = new Gaussian{ poly, a_para[2] };
			s_therm = "Gaussian";
		}
		else if (strcmp(argv[i_thermos], "Nose_Hoover") == 0) {
			double q_def{ poly.monomers.size()*poly.target_temperature()*ref_time / 1E-14 };
			double q{ set_param(q_def, argv, argc, i_thermos + 1) };
			thermostat = new Nose_Hoover{ poly, a_para[2], q };
			s_therm = "Nose_Hoover";
		}
		else if (strcmp(argv[i_thermos], "Berendsen") == 0) {
			double couplingtime = 10 * a_para[2];
			thermostat = new Berendsen{ poly, a_para[2], couplingtime };
			s_therm = "Berendsen";
		}
		else if (strcmp(argv[i_thermos], "Bussi") == 0) {
			double couplingtime = 10 * a_para[2];
			thermostat = new Bussi{ poly, a_para[2], couplingtime };
			s_therm = "Bussi";
		}
		else {
			thermostat = new Thermostat_None{ poly, a_para[2] };
			s_therm = "None";
		}
	}
	else {
			thermostat = new Thermostat_None{ poly, a_para[2] };
		s_therm = "None";
	}

	s_para = "_p"; s_para += to_string((int)a_para[0]);
	s_para += "_T"; s_para += to_string((int)a_para[1]);

	s_temp = s_therm + "_temp" + s_para + ".dat";
	dat_temp.open(s_temp, ios::out | ios::trunc);

	s_pos_vel = s_therm + "_pos_vel" + s_para + ".dat";
	dat_pos_vel.open(s_pos_vel, ios::out | ios::trunc);

	// Simulation
	for (int i = 0; i < a_para[4]; ++i) thermostat->propagate();
	cout << "Warmlauf abgeschlossen" << endl;

	int index_print{ (int)(a_para[3] * 4E-1) };
	int index_to_file{ (int)a_para[5] };
	for (int i = 0; i < a_para[3]; i++) {
		if (!(i % index_to_file)) {
			dat_temp << i*a_para[2] << " " << poly.calculate_temp() << endl;
			dat_pos_vel << poly;
		}

		if (!(i % index_print)) {
			cout << i*a_para[2] << endl;
			cout << "Ekin: " << poly.update_ekin() << endl;
			cout << "T: " << poly.calculate_temp() << endl;
		}
		thermostat->propagate();
	}

	cout << "<< Die Datei '" << s_temp << "' wurde erstellt." << endl;
	cout << "<< Die Datei '" << s_pos_vel << "' wurde erstellt." << endl;

	dat_temp.close();
	dat_pos_vel.close();
	return 0;
}

<commit_msg>speicher freigeben<commit_after>#include "Thermostat.h"
#include "Andersen.h"
#include "Lowe_Andersen.h"
#include "Gaussian.h"
#include "Nose_Hoover.h"
#include "Thermostat_None.h"
#include "Berendsen.h"
#include "Bussi.h"

#include "Functions.h"
#include "consts.h"
using namespace consts;

#include <iostream>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
using namespace std;

/* ######################### */
int main(int argc, char* argv[]) {
	//default für  p,Temp,dtime,runs,warmlauf,ausgabe   :jedes xte wird ausgegeben
	double a_para[]{4, 20, 1E-15, 1E6, 1E3, 1};
	int			i_para{ 1 };
	string s_para{}, s_therm{};
	string	s_temp{}, s_pos_vel{};
	ofstream dat_temp{}, dat_pos_vel{};
	Thermostat *thermostat{};

	// Bestimmen der Parameter zur Initialisierung von Poly und Thermostat
	for (i_para = 1; i_para < min(7, argc); ++i_para) {
		if (is_number(argv[i_para])) a_para[i_para - 1] = stod(argv[i_para]);
		else break;
	}
	a_para[2] /= ref_time;

	while (i_para < argc - 1 && is_number(argv[i_para])) ++i_para;
	int i_thermos = i_para;

	while (++i_para < argc - 1 && is_number(argv[i_para])) ++i_para;
	int i_poly_init = min(argc - 1, i_para);

	Polymer poly{ static_cast<unsigned> (a_para[0]), a_para[1] };
	if (strcmp(argv[i_poly_init], "one") == 0)
		poly.initiate_monomers_one();
	else
		poly.initiate_monomers_random();

	// Auswählen des Thermostats
	if (argc > 1 && i_thermos < argc) {
		if (strcmp(argv[i_thermos], "Andersen") == 0) {
			double nu{ set_param(1. / a_para[2] / a_para[0], argv, argc, i_thermos + 1) };
			thermostat = new Andersen{ poly, a_para[2], nu };
			s_therm = "Andersen";
		}
		else if (strcmp(argv[i_thermos], "Lowe_Andersen") == 0) {
			double nu{ set_param(1. / a_para[2] / a_para[0], argv, argc, i_thermos + 1) };
			thermostat = new Lowe_Andersen{ poly, a_para[2], nu };
			s_therm = "Lowe_Andersen";
		}
		else if (strcmp(argv[i_thermos], "Gaussian") == 0) {
			thermostat = new Gaussian{ poly, a_para[2] };
			s_therm = "Gaussian";
		}
		else if (strcmp(argv[i_thermos], "Nose_Hoover") == 0) {
			double q_def{ poly.monomers.size()*poly.target_temperature()*ref_time / 1E-14 };
			double q{ set_param(q_def, argv, argc, i_thermos + 1) };
			thermostat = new Nose_Hoover{ poly, a_para[2], q };
			s_therm = "Nose_Hoover";
		}
		else if (strcmp(argv[i_thermos], "Berendsen") == 0) {
			double couplingtime = 10 * a_para[2];
			thermostat = new Berendsen{ poly, a_para[2], couplingtime };
			s_therm = "Berendsen";
		}
		else if (strcmp(argv[i_thermos], "Bussi") == 0) {
			double couplingtime = 10 * a_para[2];
			thermostat = new Bussi{ poly, a_para[2], couplingtime };
			s_therm = "Bussi";
		}
		else {
			thermostat = new Thermostat_None{ poly, a_para[2] };
			s_therm = "None";
		}
	}
	else {
			thermostat = new Thermostat_None{ poly, a_para[2] };
		s_therm = "None";
	}

	s_para = "_p"; s_para += to_string((int)a_para[0]);
	s_para += "_T"; s_para += to_string((int)a_para[1]);

	s_temp = s_therm + "_temp" + s_para + ".dat";
	dat_temp.open(s_temp, ios::out | ios::trunc);

	s_pos_vel = s_therm + "_pos_vel" + s_para + ".dat";
	dat_pos_vel.open(s_pos_vel, ios::out | ios::trunc);

	// Simulation
	for (int i = 0; i < a_para[4]; ++i) thermostat->propagate();
	cout << "Warmlauf abgeschlossen" << endl;

	int index_print{ (int)(a_para[3] * 4E-1) };
	int index_to_file{ (int)a_para[5] };
	for (int i = 0; i < a_para[3]; i++) {
		if (!(i % index_to_file)) {
			dat_temp << i*a_para[2] << " " << poly.calculate_temp() << endl;
			dat_pos_vel << poly;
		}

		if (!(i % index_print)) {
			cout << i*a_para[2] << endl;
			cout << "Ekin: " << poly.update_ekin() << endl;
			cout << "T: " << poly.calculate_temp() << endl;
		}
		thermostat->propagate();
	}
	delete thermostat;

	cout << "<< Die Datei '" << s_temp << "' wurde erstellt." << endl;
	cout << "<< Die Datei '" << s_pos_vel << "' wurde erstellt." << endl;

	dat_temp.close();
	dat_pos_vel.close();
	return 0;
}

<|endoftext|>