<commit_before>/**
  \file   main.cc
  \brief  Main file fir the finite element example.
  **/
// disable warnings about problems in dune headers
#include <dune/fem-tools/header/disablewarnings.hh>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <iostream>
#include <vector>

// dune-common includes
#include <dune/common/exceptions.hh>
#include <dune/common/fmatrix.hh>

// dune-grid includes
#include <dune/grid/utility/gridtype.hh>

// dune-istl includes
#include <dune/istl/solvers.hh>

// dune-fem includes
#include <dune/fem/misc/mpimanager.hh>
#include <dune/fem/gridpart/gridpart.hh>
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>

// reenable warnings
#include <dune/fem-tools/header/enablewarnings.hh>

// dune-functionals includes
#include <dune/functionals/discretefunctionspace/continuous/lagrange.hh>
#include <dune/functionals/discretefunctionspace/subspace/linear.hh>
#include <dune/functionals/discretefunctionspace/subspace/affine.hh>
#include <dune/functionals/discreteoperator/local/codim0/integral.hh>
#include <dune/functionals/discretefunctional/local/codim0/integral.hh>
#include <dune/functionals/container/factory.hh>
#include <dune/functionals/assembler/local/finiteelement.hh>
#include <dune/functionals/assembler/generic.hh>

// dune-fem-tools includes
#include <dune/fem-tools/common/string.hh>
#include <dune/fem-tools/function/runtimefunction.hh>
#include <dune/fem-tools/function/functiontools.hh>

using namespace Dune::Functionals;

#ifndef POLORDER
const int polOrder = 1;
#else
const int polOrder = POLORDER;
#endif

/**
  \brief  This represents the operation \f$fv\f$.

          \f$f\f$ is a given right hand side (in this case 1) and \f$v\f$ may be a local function, i.e. a
          testfunction.
  \tparam FunctionSpaceImp
          Type of the function space, where \f$f\f$ and \f$v\f$ live in.
  **/
template< class FunctionSpaceImp >
class ProductEvaluation
{
public:

  typedef FunctionSpaceImp
    FunctionSpaceType;

  typedef typename FunctionSpaceType::DomainType
    DomainType;

  typedef typename FunctionSpaceType::RangeFieldType
    RangeFieldType;

  typedef typename FunctionSpaceType::RangeType
    RangeType;

  typedef Dune::FemTools::Function::Runtime< FunctionSpaceType >
    InducingFunctionType;

  //! constructor, takes the inducing functions expression as a runtime parameter
  ProductEvaluation( const std::string expression = "[1.0;1.0;1.0]" )
    : inducingFunction_( expression )
  {
  }

  //! copy constructor
  ProductEvaluation( const ProductEvaluation& other )
    : inducingFunction_( other.inducingFunction() )
  {
  }

  //! returns the inducing function
  const InducingFunctionType& inducingFunction() const
  {
    return inducingFunction_;
  }

  /**
    \brief      Evaluates \f$f(x)v(x)\f$ for a given local point \f$x\f$.

    \tparam     LocalTestFunctionType
                Type of the local function \f$v\f$, i.e. Dune::LocalFunction.
    \tparam     LocalPointType
                Type of the local point \f$x\f$, i.e. Dune::FieldVector.
    \param[in]  localTestFunction
                The local function \f$v\f$.
    \param[in]  localPoint
                The local point \f$x\f$. This point is local in the sense, that this is a point on a reference
                element.
    \return     \f$f(x)v(x)\f$
    **/
  template< class LocalTestFunctionType >
  const RangeFieldType evaluate(  const LocalTestFunctionType& localTestFunction,
                                  const DomainType& localPoint ) const
  {
    // get global point
    const DomainType globalPoint = localTestFunction.entity().geometry().global( localPoint );

    // evaluate local function
    RangeType localTestFunctionValue( 0.0 );
    localTestFunction.evaluate( localPoint, localTestFunctionValue );

    // evaluate inducing function
    RangeType functionValue( 0.0 );
    inducingFunction_.evaluate( globalPoint, functionValue );

    // f(x) * v(x)
    const RangeFieldType ret = functionValue * localTestFunctionValue;

    return ret;
  }

private:

  const InducingFunctionType inducingFunction_;
}; // end class ProductEvaluation

/**
  \brief  This represents the operation \f$a\nabla u \nabla v\f$.

          \f$a\f$ is a given scalar function (in this case 1) and \f$u\f$ and \f$u\f$ may be local functions, i.e.
          ansatz- and testfunctions.
  \tparam FunctionSpaceImp
          Type of the function space, where \f$f\f$, \f$u\f$ and \f$v\f$ live in.
  **/
template< class FunctionSpaceImp >
class EllipticEvaluation
{
public:

  typedef FunctionSpaceImp
    FunctionSpaceType;

  typedef typename FunctionSpaceType::RangeFieldType
    RangeFieldType;

  typedef typename FunctionSpaceType::RangeType
    RangeType;

  typedef typename FunctionSpaceType::DomainType
    DomainType;

  typedef typename FunctionSpaceType::JacobianRangeType
    JacobianRangeType;

  typedef Dune::FemTools::Function::Runtime< FunctionSpaceType >
    InducingFunctionType;

  //! constructor, takes the inducing functions expression as a runtime parameter
  EllipticEvaluation( const std::string expression = "[1.0;1.0;1.0]" )
    : inducingFunction_( expression )
  {
  }

  //! copy constructor
  EllipticEvaluation( const EllipticEvaluation& other )
    : inducingFunction_( other.inducingFunction() )
  {
  }

  //! returns the inducing function
  const InducingFunctionType& inducingFunction() const
  {
    return inducingFunction_;
  }

  /**
    * \brief      Evaluates \f$a(x)\nabla u(x) \nabla v(x)\f$ for a given local point \f$x\f$.
    *
    * \tparam     LocalAnsatzFunctionType
    *             Type of the local ansatz function \f$u\f$, i.e. Dune::LocalFunction.
    * \tparam     LocalTestFunctionType
    *             Type of the local test function \f$v\f$, i.e. Dune::LocalFunction.
    * \tparam     LocalPointType
    *             Type of the local point \f$x\f$, i.e. Dune::FieldVector.
    * \param[in]  localAnsatzFunction
    *             The local function \f$u\f$.
    * \param[in]  localTestFunction
    *             The local function \f$v\f$.
    * \param[in]  localPoint
    *             The local point \f$x\f$. This point is local in the sense, that this is a point on a reference
    *             element.
    * \return     \f$a(x)\nabla u(x) \nabla v(x)\f$
    **/
  template< class LocalAnsatzFunctionType, class LocalTestFunctionType >
  const RangeFieldType evaluate(  const LocalAnsatzFunctionType& localAnsatzFunction,
                                  const LocalTestFunctionType& localTestFunction,
                                  const DomainType& localPoint ) const
  {
    // get global point
    const DomainType globalPoint = localAnsatzFunction.entity().geometry().global( localPoint );

    // evaluate first gradient
    JacobianRangeType gradientLocalAnsatzFunction( 0.0 );
    localAnsatzFunction.jacobian( localPoint, gradientLocalAnsatzFunction );

    // evaluate second gradient
    JacobianRangeType gradientLocalTestFunction( 0.0 );
    localTestFunction.jacobian( localPoint, gradientLocalTestFunction );

    const RangeType gradientProduct = gradientLocalAnsatzFunction[0] * gradientLocalTestFunction[0];

    // evaluate inducing function
    RangeType functionValue( 0.0 );
    inducingFunction_.evaluate( globalPoint, functionValue );

    // a(x) * \gradient u(x) * \gradient v(x)
    const RangeFieldType ret = functionValue * gradientProduct;

    return ret;
  }

private:

  const InducingFunctionType inducingFunction_;
}; // end class EllipticEvalaution

int main( int argc, char** argv )
{
  try{

    // MPI manager
    Dune::MPIManager::initialize ( argc, argv );

    // grid
    static const unsigned int dimRange = 1;

    typedef Dune::GridSelector::GridType
      GridType;

    typedef Dune::AdaptiveLeafGridPart< GridType >
      GridPartType;

    const std::string dgfFilename = "../macrogrids/unitcube" + Dune::FemTools::String::toString( GRIDDIM ) + ".dgf";

    Dune::GridPtr< GridType > gridPtr( dgfFilename );

    GridPartType gridPart( *gridPtr );

    // function space
    typedef Dune::FunctionSpace< double, double, GridType::dimension, dimRange >
      FunctionSpaceType;

    typedef typename FunctionSpaceType::RangeFieldType
      RangeFieldType;

    // discrete function space
    typedef DiscreteFunctionSpace::Continuous::Lagrange< FunctionSpaceType, GridPartType, polOrder >
      DiscreteH1Type;

    const DiscreteH1Type discreteH1( gridPart );

    typedef DiscreteFunctionSpace::Subspace::Linear::Dirichlet< DiscreteH1Type >
      DiscreteH10Type;

    const DiscreteH10Type discreteH10( discreteH1 );

    typedef DiscreteFunctionSpace::Subspace::Affine::Dirichlet< DiscreteH10Type >
      DiscreteH1GType;

    const DiscreteH1GType discreteH1G( discreteH10, "[x+y;y;z]" );

    // local evaluation
    typedef ProductEvaluation< FunctionSpaceType >
      ProductEvaluationType;

    ProductEvaluationType productEvaluation( "[1.0;1.0;1.0]" );

    typedef EllipticEvaluation< FunctionSpaceType >
      EllipticEvaluationType;

    EllipticEvaluationType ellipticEvaluation( "[1.0;1.0;1.0]" );

    // operator and functional
    typedef Dune::Functionals::DiscreteOperator::Local::Codim0::Integral< EllipticEvaluationType >
      LocalEllipticOperatorType;

    const LocalEllipticOperatorType localEllipticOperator( ellipticEvaluation );

    typedef Dune::Functionals::DiscreteFunctional::Local::Codim0::Integral< ProductEvaluationType >
      LocalL2FunctionalType;

    const LocalL2FunctionalType localL2Functional( productEvaluation );

    // matrix, rhs and solution storage
    //! \todo the matrix factory should get two spaces (ansatz and test)
    typedef Dune::Functionals::Container::Matrix::Defaults< RangeFieldType, dimRange, dimRange >::BCRSMatrix
      MatrixFactory;

    typedef typename MatrixFactory::AutoPtrType
      MatrixPtrType;

    MatrixPtrType A = MatrixFactory::create( discreteH1 );

    typedef Dune::Functionals::Container::Vector::Defaults< RangeFieldType, dimRange >::BlockVector
      VectorFactory;

    typedef typename VectorFactory::AutoPtrType
      VectorPtrType;

    VectorPtrType F = VectorFactory::create( discreteH1 );

    VectorPtrType G = VectorFactory::create( discreteH1 );

    // assembler
//    typedef Dune::Functionals::Assembler::Local::Matrix::ContinuousFiniteElement< LocalEllipticOperatorType >
//      LocalMatrixAssemblerType;

//    const LocalMatrixAssemblerType localMatrixAssembler( localEllipticOperator );

//    typedef Dune::Functionals::Assembler::Local::Vector::ContinuousFiniteElement< LocalL2FunctionalType >
//      LocalVectorAssemblerType;

//    const LocalVectorAssemblerType localVectorAssembler( localL2Functional );

//    typedef Dune::Functionals::Assembler::System< DiscreteH1GType, DiscreteH10Type >
//      SystemAssemblerType;

//    SystemAssemblerType systemAssembler( discreteH1G, discreteH10 );

//    systemAssembler.assemble( localMatrixAssembler, A, localVectorAssembler, F );

    // preconditioner and solver
//    typedef Dune::MatrixAdapter< MatrixContainer, VectorContainer, VectorContainer >
//      MatrixAdapterType;

//    MatrixAdapterType op( *A );

//    typedef Dune::SeqILU0< MatrixContainer, VectorContainer, VectorContainer, 1 >
//      SeqILU0Type;

//    SeqILU0Type prec( *A, 1.0 );

//    typedef Dune::CGSolver< VectorContainer >
//      CG;

//    CG cg( op, prec, 1e-4, 100, 2 );

//    Dune::InverseOperatorResult res;

//    // u_0 = A^(-1) ( F - G )
//    cg.apply( *u0, *F, res );

//    // postprocessing
//    DiscreteFunctionType solution = Dune::FemTools::discreteFunctionFactory< DiscreteFunctionType >( discreteH1, *u0 );
    Dune::FemTools::Function::writeToVTK( discreteH1G.affineShift(), "boundaryData" );

    return 0;
  }
  catch (Dune::Exception &e){
    std::cerr << "Dune reported error: " << e << std::endl;
  }
  catch (...){
    std::cerr << "Unknown exception thrown!" << std::endl;
  }
}
<commit_msg>made use of using namespace Dune::Functionals; in main<commit_after>/**
  \file   main.cc
  \brief  Main file fir the finite element example.
  **/
// disable warnings about problems in dune headers
#include <dune/fem-tools/header/disablewarnings.hh>

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <iostream>
#include <vector>

// dune-common includes
#include <dune/common/exceptions.hh>
#include <dune/common/fmatrix.hh>

// dune-grid includes
#include <dune/grid/utility/gridtype.hh>

// dune-istl includes
#include <dune/istl/solvers.hh>

// dune-fem includes
#include <dune/fem/misc/mpimanager.hh>
#include <dune/fem/gridpart/gridpart.hh>
#include <dune/fem/gridpart/adaptiveleafgridpart.hh>

// reenable warnings
#include <dune/fem-tools/header/enablewarnings.hh>

// dune-functionals includes
#include <dune/functionals/discretefunctionspace/continuous/lagrange.hh>
#include <dune/functionals/discretefunctionspace/subspace/linear.hh>
#include <dune/functionals/discretefunctionspace/subspace/affine.hh>
#include <dune/functionals/discreteoperator/local/codim0/integral.hh>
#include <dune/functionals/discretefunctional/local/codim0/integral.hh>
#include <dune/functionals/container/factory.hh>
#include <dune/functionals/assembler/local/finiteelement.hh>
#include <dune/functionals/assembler/generic.hh>

// dune-fem-tools includes
#include <dune/fem-tools/common/string.hh>
#include <dune/fem-tools/function/runtimefunction.hh>
#include <dune/fem-tools/function/functiontools.hh>

using namespace Dune::Functionals;

#ifndef POLORDER
const int polOrder = 1;
#else
const int polOrder = POLORDER;
#endif

/**
  \brief  This represents the operation \f$fv\f$.

          \f$f\f$ is a given right hand side (in this case 1) and \f$v\f$ may be a local function, i.e. a
          testfunction.
  \tparam FunctionSpaceImp
          Type of the function space, where \f$f\f$ and \f$v\f$ live in.
  **/
template< class FunctionSpaceImp >
class ProductEvaluation
{
public:

  typedef FunctionSpaceImp
    FunctionSpaceType;

  typedef typename FunctionSpaceType::DomainType
    DomainType;

  typedef typename FunctionSpaceType::RangeFieldType
    RangeFieldType;

  typedef typename FunctionSpaceType::RangeType
    RangeType;

  typedef Dune::FemTools::Function::Runtime< FunctionSpaceType >
    InducingFunctionType;

  //! constructor, takes the inducing functions expression as a runtime parameter
  ProductEvaluation( const std::string expression = "[1.0;1.0;1.0]" )
    : inducingFunction_( expression )
  {
  }

  //! copy constructor
  ProductEvaluation( const ProductEvaluation& other )
    : inducingFunction_( other.inducingFunction() )
  {
  }

  //! returns the inducing function
  const InducingFunctionType& inducingFunction() const
  {
    return inducingFunction_;
  }

  /**
    \brief      Evaluates \f$f(x)v(x)\f$ for a given local point \f$x\f$.

    \tparam     LocalTestFunctionType
                Type of the local function \f$v\f$, i.e. Dune::LocalFunction.
    \tparam     LocalPointType
                Type of the local point \f$x\f$, i.e. Dune::FieldVector.
    \param[in]  localTestFunction
                The local function \f$v\f$.
    \param[in]  localPoint
                The local point \f$x\f$. This point is local in the sense, that this is a point on a reference
                element.
    \return     \f$f(x)v(x)\f$
    **/
  template< class LocalTestFunctionType >
  const RangeFieldType evaluate(  const LocalTestFunctionType& localTestFunction,
                                  const DomainType& localPoint ) const
  {
    // get global point
    const DomainType globalPoint = localTestFunction.entity().geometry().global( localPoint );

    // evaluate local function
    RangeType localTestFunctionValue( 0.0 );
    localTestFunction.evaluate( localPoint, localTestFunctionValue );

    // evaluate inducing function
    RangeType functionValue( 0.0 );
    inducingFunction_.evaluate( globalPoint, functionValue );

    // f(x) * v(x)
    const RangeFieldType ret = functionValue * localTestFunctionValue;

    return ret;
  }

private:

  const InducingFunctionType inducingFunction_;
}; // end class ProductEvaluation

/**
  \brief  This represents the operation \f$a\nabla u \nabla v\f$.

          \f$a\f$ is a given scalar function (in this case 1) and \f$u\f$ and \f$u\f$ may be local functions, i.e.
          ansatz- and testfunctions.
  \tparam FunctionSpaceImp
          Type of the function space, where \f$f\f$, \f$u\f$ and \f$v\f$ live in.
  **/
template< class FunctionSpaceImp >
class EllipticEvaluation
{
public:

  typedef FunctionSpaceImp
    FunctionSpaceType;

  typedef typename FunctionSpaceType::RangeFieldType
    RangeFieldType;

  typedef typename FunctionSpaceType::RangeType
    RangeType;

  typedef typename FunctionSpaceType::DomainType
    DomainType;

  typedef typename FunctionSpaceType::JacobianRangeType
    JacobianRangeType;

  typedef Dune::FemTools::Function::Runtime< FunctionSpaceType >
    InducingFunctionType;

  //! constructor, takes the inducing functions expression as a runtime parameter
  EllipticEvaluation( const std::string expression = "[1.0;1.0;1.0]" )
    : inducingFunction_( expression )
  {
  }

  //! copy constructor
  EllipticEvaluation( const EllipticEvaluation& other )
    : inducingFunction_( other.inducingFunction() )
  {
  }

  //! returns the inducing function
  const InducingFunctionType& inducingFunction() const
  {
    return inducingFunction_;
  }

  /**
    * \brief      Evaluates \f$a(x)\nabla u(x) \nabla v(x)\f$ for a given local point \f$x\f$.
    *
    * \tparam     LocalAnsatzFunctionType
    *             Type of the local ansatz function \f$u\f$, i.e. Dune::LocalFunction.
    * \tparam     LocalTestFunctionType
    *             Type of the local test function \f$v\f$, i.e. Dune::LocalFunction.
    * \tparam     LocalPointType
    *             Type of the local point \f$x\f$, i.e. Dune::FieldVector.
    * \param[in]  localAnsatzFunction
    *             The local function \f$u\f$.
    * \param[in]  localTestFunction
    *             The local function \f$v\f$.
    * \param[in]  localPoint
    *             The local point \f$x\f$. This point is local in the sense, that this is a point on a reference
    *             element.
    * \return     \f$a(x)\nabla u(x) \nabla v(x)\f$
    **/
  template< class LocalAnsatzFunctionType, class LocalTestFunctionType >
  const RangeFieldType evaluate(  const LocalAnsatzFunctionType& localAnsatzFunction,
                                  const LocalTestFunctionType& localTestFunction,
                                  const DomainType& localPoint ) const
  {
    // get global point
    const DomainType globalPoint = localAnsatzFunction.entity().geometry().global( localPoint );

    // evaluate first gradient
    JacobianRangeType gradientLocalAnsatzFunction( 0.0 );
    localAnsatzFunction.jacobian( localPoint, gradientLocalAnsatzFunction );

    // evaluate second gradient
    JacobianRangeType gradientLocalTestFunction( 0.0 );
    localTestFunction.jacobian( localPoint, gradientLocalTestFunction );

    const RangeType gradientProduct = gradientLocalAnsatzFunction[0] * gradientLocalTestFunction[0];

    // evaluate inducing function
    RangeType functionValue( 0.0 );
    inducingFunction_.evaluate( globalPoint, functionValue );

    // a(x) * \gradient u(x) * \gradient v(x)
    const RangeFieldType ret = functionValue * gradientProduct;

    return ret;
  }

private:

  const InducingFunctionType inducingFunction_;
}; // end class EllipticEvalaution

int main( int argc, char** argv )
{
  try{

    // MPI manager
    Dune::MPIManager::initialize ( argc, argv );

    // grid
    static const unsigned int dimRange = 1;

    typedef Dune::GridSelector::GridType
      GridType;

    typedef Dune::AdaptiveLeafGridPart< GridType >
      GridPartType;

    const std::string dgfFilename = "../macrogrids/unitcube" + Dune::FemTools::String::toString( GRIDDIM ) + ".dgf";

    Dune::GridPtr< GridType > gridPtr( dgfFilename );

    GridPartType gridPart( *gridPtr );

    // function space
    typedef Dune::FunctionSpace< double, double, GridType::dimension, dimRange >
      FunctionSpaceType;

    typedef typename FunctionSpaceType::RangeFieldType
      RangeFieldType;

    // discrete function space
    typedef DiscreteFunctionSpace::Continuous::Lagrange< FunctionSpaceType, GridPartType, polOrder >
      DiscreteH1Type;

    const DiscreteH1Type discreteH1( gridPart );

    typedef DiscreteFunctionSpace::Subspace::Linear::Dirichlet< DiscreteH1Type >
      DiscreteH10Type;

    const DiscreteH10Type discreteH10( discreteH1 );

    typedef DiscreteFunctionSpace::Subspace::Affine::Dirichlet< DiscreteH10Type >
      DiscreteH1GType;

    const DiscreteH1GType discreteH1G( discreteH10, "[x+y;y;z]" );

    // local evaluation
    typedef ProductEvaluation< FunctionSpaceType >
      ProductEvaluationType;

    ProductEvaluationType productEvaluation( "[1.0;1.0;1.0]" );

    typedef EllipticEvaluation< FunctionSpaceType >
      EllipticEvaluationType;

    EllipticEvaluationType ellipticEvaluation( "[1.0;1.0;1.0]" );

    // operator and functional
    typedef DiscreteOperator::Local::Codim0::Integral< EllipticEvaluationType >
      LocalEllipticOperatorType;

    const LocalEllipticOperatorType localEllipticOperator( ellipticEvaluation );

    typedef DiscreteFunctional::Local::Codim0::Integral< ProductEvaluationType >
      LocalL2FunctionalType;

    const LocalL2FunctionalType localL2Functional( productEvaluation );

    // matrix, rhs and solution storage
    //! \todo the matrix factory should get two spaces (ansatz and test)
    typedef Container::Matrix::Defaults< RangeFieldType, dimRange, dimRange >::BCRSMatrix
      MatrixFactory;

    typedef typename MatrixFactory::AutoPtrType
      MatrixPtrType;

    MatrixPtrType A = MatrixFactory::create( discreteH1 );

    typedef Container::Vector::Defaults< RangeFieldType, dimRange >::BlockVector
      VectorFactory;

    typedef typename VectorFactory::AutoPtrType
      VectorPtrType;

    VectorPtrType F = VectorFactory::create( discreteH1 );

    VectorPtrType G = VectorFactory::create( discreteH1 );

    // assembler
//    typedef Dune::Functionals::Assembler::Local::Matrix::ContinuousFiniteElement< LocalEllipticOperatorType >
//      LocalMatrixAssemblerType;

//    const LocalMatrixAssemblerType localMatrixAssembler( localEllipticOperator );

//    typedef Dune::Functionals::Assembler::Local::Vector::ContinuousFiniteElement< LocalL2FunctionalType >
//      LocalVectorAssemblerType;

//    const LocalVectorAssemblerType localVectorAssembler( localL2Functional );

//    typedef Dune::Functionals::Assembler::System< DiscreteH1GType, DiscreteH10Type >
//      SystemAssemblerType;

//    SystemAssemblerType systemAssembler( discreteH1G, discreteH10 );

//    systemAssembler.assemble( localMatrixAssembler, A, localVectorAssembler, F );

    // preconditioner and solver
//    typedef Dune::MatrixAdapter< MatrixContainer, VectorContainer, VectorContainer >
//      MatrixAdapterType;

//    MatrixAdapterType op( *A );

//    typedef Dune::SeqILU0< MatrixContainer, VectorContainer, VectorContainer, 1 >
//      SeqILU0Type;

//    SeqILU0Type prec( *A, 1.0 );

//    typedef Dune::CGSolver< VectorContainer >
//      CG;

//    CG cg( op, prec, 1e-4, 100, 2 );

//    Dune::InverseOperatorResult res;

//    // u_0 = A^(-1) ( F - G )
//    cg.apply( *u0, *F, res );

//    // postprocessing
//    DiscreteFunctionType solution = Dune::FemTools::discreteFunctionFactory< DiscreteFunctionType >( discreteH1, *u0 );
    Dune::FemTools::Function::writeToVTK( discreteH1G.affineShift(), "boundaryData" );

    return 0;
  }
  catch (Dune::Exception &e){
    std::cerr << "Dune reported error: " << e << std::endl;
  }
  catch (...){
    std::cerr << "Unknown exception thrown!" << std::endl;
  }
}
<|endoftext|>


<commit_before>// Scintilla source code edit control
/** @file LexCSS.cxx
 ** Lexer for Cascading Style Sheets
 ** Written by Jakub Vrna
 ** Improved by Philippe Lhoste (CSS2)
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const unsigned int ch) {
	return (isalnum(ch) || ch == '-' || ch == '_' || ch >= 161); // _ is not in fact correct CSS word-character
}

inline bool IsCssOperator(const char ch) {
	if (!isalnum(ch) &&
		(ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
		 ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
		 /* CSS2 */
		 ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' ||
		 ch == '[' || ch == ']' || ch == '(' || ch == ')')) {
		return true;
	}
	return false;
}

static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
	WordList &keywords = *keywordlists[0];
	WordList &pseudoClasses = *keywordlists[1];
	WordList &keywords2 = *keywordlists[2];

	StyleContext sc(startPos, length, initStyle, styler);

	int lastState = -1; // before operator
	int lastStateC = -1; // before comment
	int op = ' '; // last operator

	for (; sc.More(); sc.Forward()) {
		if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
			if (lastStateC == -1) {
				// backtrack to get last state:
				// comments are like whitespace, so we must return to the previous state
				unsigned int i = startPos;
				for (; i > 0; i--) {
					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
						if (lastStateC == SCE_CSS_OPERATOR) {
							op = styler.SafeGetCharAt(i-1);
							while (--i) {
								lastState = styler.StyleAt(i-1);
								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
									break;
							}
							if (i == 0)
								lastState = SCE_CSS_DEFAULT;
						}
						break;
					}
				}
				if (i == 0)
					lastStateC = SCE_CSS_DEFAULT;
			}
			sc.Forward();
			sc.ForwardSetState(lastStateC);
		}

		if (sc.state == SCE_CSS_COMMENT)
			continue;

		if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
			if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
				continue;
			unsigned int i = sc.currentPos;
			while (i && styler[i-1] == '\\')
				i--;
			if ((sc.currentPos - i) % 2 == 1)
				continue;
			sc.ForwardSetState(SCE_CSS_VALUE);
		}

		if (sc.state == SCE_CSS_OPERATOR) {
			if (op == ' ') {
				unsigned int i = startPos;
				op = styler.SafeGetCharAt(i-1);
				while (--i) {
					lastState = styler.StyleAt(i-1);
					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
						break;
				}
			}
			switch (op) {
			case '@':
				if (lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_DIRECTIVE);
				break;
			case '{':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '}':
				if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT ||
					lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ':':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_PSEUDOCLASS);
				else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
					sc.SetState(SCE_CSS_VALUE);
				break;
			case '.':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_CLASS);
				break;
			case '#':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_ID);
				break;
			case ',':
				if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ';':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '!':
				if (lastState == SCE_CSS_VALUE)
					sc.SetState(SCE_CSS_IMPORTANT);
				break;
			}
		}

		if (IsAWordChar(sc.ch)) {
			if (sc.state == SCE_CSS_DEFAULT)
				sc.SetState(SCE_CSS_TAG);
			continue;
		}

		if (IsAWordChar(sc.chPrev) && (
			sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2
			|| sc.state == SCE_CSS_UNKNOWN_IDENTIFIER
			|| sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
			|| sc.state == SCE_CSS_IMPORTANT
		)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			char *s2 = s;
			while (*s2 && !IsAWordChar(*s2))
				s2++;
			switch (sc.state) {
			case SCE_CSS_IDENTIFIER:
				if (!keywords.InList(s2)) {
					if (keywords2.InList(s2)) {
						sc.ChangeState(SCE_CSS_IDENTIFIER2);
					} else {
						sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
					}
				}
				break;
			case SCE_CSS_UNKNOWN_IDENTIFIER:
				if (keywords.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER);
				else if (keywords2.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER2);
				break;
			case SCE_CSS_PSEUDOCLASS:
				if (!pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
				break;
			case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				if (pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOCLASS);
				break;
			case SCE_CSS_IMPORTANT:
				if (strcmp(s2, "important") != 0)
					sc.ChangeState(SCE_CSS_VALUE);
				break;
			}
		}

		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID))
			sc.SetState(SCE_CSS_TAG);

		if (sc.Match('/', '*')) {
			lastStateC = sc.state;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
			sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
		} else if (IsCssOperator(static_cast<char>(sc.ch))
			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
			&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
		) {
			if (sc.state != SCE_CSS_OPERATOR)
				lastState = sc.state;
			sc.SetState(SCE_CSS_OPERATOR);
			op = sc.ch;
		}
	}

	sc.Complete();
}

static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment) {
			if (!inComment && (style == SCE_CSS_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_CSS_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_CSS_COMMENT);
		}
		if (style == SCE_CSS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const cssWordListDesc[] = {
	"CSS1 Keywords",
	"Pseudo classes",
	"CSS2 Keywords",
	0
};

LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);
<commit_msg>Patch from Jakub Vrana to upgrade CSS support to CSS2.<commit_after>// Scintilla source code edit control
/** @file LexCSS.cxx
 ** Lexer for Cascading Style Sheets
 ** Written by Jakub Vrna
 ** Improved by Philippe Lhoste (CSS2)
 **/
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

static inline bool IsAWordChar(const unsigned int ch) {
	return (isalnum(ch) || ch == '-' || ch == '_' || ch >= 161); // _ is not in fact correct CSS word-character
}

inline bool IsCssOperator(const char ch) {
	if (!isalnum(ch) &&
		(ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' ||
		 ch == '.' || ch == '#' || ch == '!' || ch == '@' ||
		 /* CSS2 */
		 ch == '*' || ch == '>' || ch == '+' || ch == '=' || ch == '~' || ch == '|' ||
		 ch == '[' || ch == ']' || ch == '(' || ch == ')')) {
		return true;
	}
	return false;
}

static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
	WordList &keywords = *keywordlists[0];
	WordList &pseudoClasses = *keywordlists[1];
	WordList &keywords2 = *keywordlists[2];

	StyleContext sc(startPos, length, initStyle, styler);

	int lastState = -1; // before operator
	int lastStateC = -1; // before comment
	int op = ' '; // last operator

	for (; sc.More(); sc.Forward()) {
		if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) {
			if (lastStateC == -1) {
				// backtrack to get last state:
				// comments are like whitespace, so we must return to the previous state
				unsigned int i = startPos;
				for (; i > 0; i--) {
					if ((lastStateC = styler.StyleAt(i-1)) != SCE_CSS_COMMENT) {
						if (lastStateC == SCE_CSS_OPERATOR) {
							op = styler.SafeGetCharAt(i-1);
							while (--i) {
								lastState = styler.StyleAt(i-1);
								if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
									break;
							}
							if (i == 0)
								lastState = SCE_CSS_DEFAULT;
						}
						break;
					}
				}
				if (i == 0)
					lastStateC = SCE_CSS_DEFAULT;
			}
			sc.Forward();
			sc.ForwardSetState(lastStateC);
		}

		if (sc.state == SCE_CSS_COMMENT)
			continue;

		if (sc.state == SCE_CSS_DOUBLESTRING || sc.state == SCE_CSS_SINGLESTRING) {
			if (sc.ch != (sc.state == SCE_CSS_DOUBLESTRING ? '\"' : '\''))
				continue;
			unsigned int i = sc.currentPos;
			while (i && styler[i-1] == '\\')
				i--;
			if ((sc.currentPos - i) % 2 == 1)
				continue;
			sc.ForwardSetState(SCE_CSS_VALUE);
		}

		if (sc.state == SCE_CSS_OPERATOR) {
			if (op == ' ') {
				unsigned int i = startPos;
				op = styler.SafeGetCharAt(i-1);
				while (--i) {
					lastState = styler.StyleAt(i-1);
					if (lastState != SCE_CSS_OPERATOR && lastState != SCE_CSS_COMMENT)
						break;
				}
			}
			switch (op) {
			case '@':
				if (lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_DIRECTIVE);
				break;
			case '*':
				if (lastState == SCE_CSS_DEFAULT)
					sc.SetState(SCE_CSS_TAG);
				break;
			case '>':
			case '+':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_CLASS
					|| lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case '[':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_ATTRIBUTE);
				break;
			case ']':
				if (lastState == SCE_CSS_ATTRIBUTE)
					sc.SetState(SCE_CSS_TAG);
				break;
			case '{':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '}':
				if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT ||
					lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ':':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_PSEUDOCLASS);
				else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_UNKNOWN_IDENTIFIER)
					sc.SetState(SCE_CSS_VALUE);
				break;
			case '.':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_CLASS);
				break;
			case '#':
				if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
					lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
					sc.SetState(SCE_CSS_ID);
				break;
			case ',':
				if (lastState == SCE_CSS_TAG)
					sc.SetState(SCE_CSS_DEFAULT);
				break;
			case ';':
				if (lastState == SCE_CSS_DIRECTIVE)
					sc.SetState(SCE_CSS_DEFAULT);
				else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT)
					sc.SetState(SCE_CSS_IDENTIFIER);
				break;
			case '!':
				if (lastState == SCE_CSS_VALUE)
					sc.SetState(SCE_CSS_IMPORTANT);
				break;
			}
		}

		if (IsAWordChar(sc.ch)) {
			if (sc.state == SCE_CSS_DEFAULT)
				sc.SetState(SCE_CSS_TAG);
			continue;
		}

		if (IsAWordChar(sc.chPrev) && (
			sc.state == SCE_CSS_IDENTIFIER || sc.state == SCE_CSS_IDENTIFIER2
			|| sc.state == SCE_CSS_UNKNOWN_IDENTIFIER
			|| sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS
			|| sc.state == SCE_CSS_IMPORTANT
		)) {
			char s[100];
			sc.GetCurrentLowered(s, sizeof(s));
			char *s2 = s;
			while (*s2 && !IsAWordChar(*s2))
				s2++;
			switch (sc.state) {
			case SCE_CSS_IDENTIFIER:
				if (!keywords.InList(s2)) {
					if (keywords2.InList(s2)) {
						sc.ChangeState(SCE_CSS_IDENTIFIER2);
					} else {
						sc.ChangeState(SCE_CSS_UNKNOWN_IDENTIFIER);
					}
				}
				break;
			case SCE_CSS_UNKNOWN_IDENTIFIER:
				if (keywords.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER);
				else if (keywords2.InList(s2))
					sc.ChangeState(SCE_CSS_IDENTIFIER2);
				break;
			case SCE_CSS_PSEUDOCLASS:
				if (!pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_UNKNOWN_PSEUDOCLASS);
				break;
			case SCE_CSS_UNKNOWN_PSEUDOCLASS:
				if (pseudoClasses.InList(s2))
					sc.ChangeState(SCE_CSS_PSEUDOCLASS);
				break;
			case SCE_CSS_IMPORTANT:
				if (strcmp(s2, "important") != 0)
					sc.ChangeState(SCE_CSS_VALUE);
				break;
			}
		}

		if (sc.ch != '.' && sc.ch != ':' && sc.ch != '#' && (sc.state == SCE_CSS_CLASS || sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || sc.state == SCE_CSS_ID))
			sc.SetState(SCE_CSS_TAG);

		if (sc.Match('/', '*')) {
			lastStateC = sc.state;
			sc.SetState(SCE_CSS_COMMENT);
			sc.Forward();
		} else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
			sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
		} else if (IsCssOperator(static_cast<char>(sc.ch))
			&& (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
			&& (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
		) {
			if (sc.state != SCE_CSS_OPERATOR)
				lastState = sc.state;
			sc.SetState(SCE_CSS_OPERATOR);
			op = sc.ch;
		}
	}

	sc.Complete();
}

static void FoldCSSDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
	bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	unsigned int endPos = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool inComment = (styler.StyleAt(startPos-1) == SCE_CSS_COMMENT);
	for (unsigned int i = startPos; i < endPos; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styler.StyleAt(i);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (foldComment) {
			if (!inComment && (style == SCE_CSS_COMMENT))
				levelCurrent++;
			else if (inComment && (style != SCE_CSS_COMMENT))
				levelCurrent--;
			inComment = (style == SCE_CSS_COMMENT);
		}
		if (style == SCE_CSS_OPERATOR) {
			if (ch == '{') {
				levelCurrent++;
			} else if (ch == '}') {
				levelCurrent--;
			}
		}
		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact)
				lev |= SC_FOLDLEVELWHITEFLAG;
			if ((levelCurrent > levelPrev) && (visibleChars > 0))
				lev |= SC_FOLDLEVELHEADERFLAG;
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch))
			visibleChars++;
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later
	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const cssWordListDesc[] = {
	"CSS1 Keywords",
	"Pseudo classes",
	"CSS2 Keywords",
	0
};

LexerModule lmCss(SCLEX_CSS, ColouriseCssDoc, "css", FoldCSSDoc, cssWordListDesc);
<|endoftext|>


<commit_before>/* Copyright (C) 2016 Matthew Giordano
 * You may use, distribute, and modify this code under the
 * terms of the GPL license.
 *
 * You should have recieved a copy of the GPL license with
 * this file. If not, please visit https://github.com/matthewpipie/Comets
 */
#include "stdafx.h"
#include "CollisionCalculator.h"

CollisionCalculator::CollisionCalculator(Comet *comet1, Comet *comet2) {
	_comet1 = comet1;
	_comet2 = comet2;
}

CollisionCalculator::~CollisionCalculator() {}

double CollisionCalculator::getFinalX() {
	return calculate(_comet1, _comet2, [](double d) {return std::cos(d); });
}
double CollisionCalculator::getFinalY() {
	return calculate(_comet1, _comet2, [](double d) {return std::sin(d); });
}
double CollisionCalculator::getSwappedX() {
	return calculate(_comet2, _comet1, [](double d) {return std::cos(d); });
}
double CollisionCalculator::getSwappedY() {
	return calculate(_comet2, _comet1, [](double d) {return std::sin(d); });
}

double CollisionCalculator::getCollisionAngle() {
	return atan((_comet1->getY() - _comet2->getY())
		/ (_comet1->getX() - _comet2->getX()));
}

double CollisionCalculator::calculate(Comet *comet1, Comet *comet2, std::function<double(double)> func) {
	double comet1XSpeedInit = comet1->getXSpeed();
	double comet1YSpeedInit = comet1->getYSpeed();
	double comet1ScalarSpeed = comet1->getSpeed();
	double comet1Mass = comet1->getR();
	int comet1Angle = comet1->getRealAngle();
	double comet2XSpeedInit = comet2->getXSpeed();
	double comet2YSpeedInit = comet2->getYSpeed();
	double comet2ScalarSpeed = comet2->getSpeed();
	double comet2Mass = comet2->getR();
	int comet2Angle = comet2->getRealAngle();

	//double collisionPointX = ((getX() * resolveComet->getR()) + (resolveComet->getX() * getR())) / (getR() + resolveComet->getR());
	//double collisionPointY = ((getY() * resolveComet->getR()) + (resolveComet->getY() * getR())) / (getR() + resolveComet->getR());

	double collisionAngle = getCollisionAngle();

	return ((comet1ScalarSpeed
			* std::cos(static_cast<double>(comet1Angle) - collisionAngle)
			* (comet1Mass - comet2Mass) + (2 * comet2Mass * comet2ScalarSpeed
			* std::cos(static_cast<double>(comet2Angle) - collisionAngle)))
			/ (comet1Mass + comet2Mass)) * func(collisionAngle)
			+ (comet1ScalarSpeed * std::sin(static_cast<double>(comet1Angle)
			- collisionAngle) * func(static_cast<double>(collisionAngle) + M_PI / 2));
}
<commit_msg>starting to split stuff<commit_after>/* Copyright (C) 2016 Matthew Giordano
 * You may use, distribute, and modify this code under the
 * terms of the GPL license.
 *
 * You should have recieved a copy of the GPL license with
 * this file. If not, please visit https://github.com/matthewpipie/Comets
 */
#include "stdafx.h"
#include "CollisionCalculator.h"

CollisionCalculator::CollisionCalculator(Comet *comet1, Comet *comet2) {
	_comet1 = comet1;
	_comet2 = comet2;
}

CollisionCalculator::~CollisionCalculator() {}

double CollisionCalculator::getFinalX() {
	return calculate(_comet1, _comet2, [](double d) {return std::cos(d); });
}
double CollisionCalculator::getFinalY() {
	return calculate(_comet1, _comet2, [](double d) {return std::sin(d); });
}
double CollisionCalculator::getSwappedX() {
	return calculate(_comet2, _comet1, [](double d) {return std::cos(d); });
}
double CollisionCalculator::getSwappedY() {
	return calculate(_comet2, _comet1, [](double d) {return std::sin(d); });
}

double CollisionCalculator::getCollisionAngle() {
	return atan((_comet1->getY() - _comet2->getY())
		/ (_comet1->getX() - _comet2->getX()));
}

double CollisionCalculator::calculate(Comet *comet1, Comet *comet2, std::function<double(double)> func) {
	double comet1XSpeedInit = comet1->getXSpeed();
	double comet1YSpeedInit = comet1->getYSpeed();
	double comet1ScalarSpeed = comet1->getSpeed();
	double comet1Mass = comet1->getR();
	double comet1Angle = static_cast<double>(comet1->getRealAngle());
	double comet2XSpeedInit = comet2->getXSpeed();
	double comet2YSpeedInit = comet2->getYSpeed();
	double comet2ScalarSpeed = comet2->getSpeed();
	double comet2Mass = comet2->getR();
	double comet2Angle = static_cast<double>(comet2->getRealAngle());

	//double collisionPointX = ((getX() * resolveComet->getR()) + (resolveComet->getX() * getR())) / (getR() + resolveComet->getR());
	//double collisionPointY = ((getY() * resolveComet->getR()) + (resolveComet->getY() * getR())) / (getR() + resolveComet->getR());

	double collisionAngle = getCollisionAngle();

	// Thanks to https://en.wikipedia.org/wiki/Elastic_collision#Two-dimensional_collision_with_two_moving_objects

	double numerator = comet1ScalarSpeed * std::cos(comet1Angle - collisionAngle) * (comet1Mass - comet2Mass) + 2 * comet1Mass * comet2Mass * std::cos(comet2Angle - collisionAngle);

	return ((comet1ScalarSpeed
			* std::cos(static_cast<double>(comet1Angle) - collisionAngle)
			* (comet1Mass - comet2Mass) + (2 * comet2Mass * comet2ScalarSpeed
			* std::cos(static_cast<double>(comet2Angle) - collisionAngle)))
			/ (comet1Mass + comet2Mass)) * func(collisionAngle)
			+ (comet1ScalarSpeed * std::sin(static_cast<double>(comet1Angle)
			- collisionAngle) * func(static_cast<double>(collisionAngle) + M_PI / 2));
}
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include <algorithm>
#include "libtorrent/entry.hpp"
#include <boost/bind.hpp>
#include <boost/next_prior.hpp>

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		assert(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		char const*	integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().end()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) throw type_error("key not found");
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}

	entry::entry(const dictionary_type& v)
	{
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(const string_type& v)
	{
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(const list_type& v)
	{
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(const integer_type& v)
	{
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(const dictionary_type& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	void entry::operator=(const string_type& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
	}

	void entry::operator=(const list_type& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
	}

	void entry::operator=(const integer_type& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			assert(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		m_type = t;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			assert(m_type == undefined_t);
			m_type = undefined_t;
		}
	}

	void entry::copy(const entry& e)
	{
		m_type = e.m_type;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			m_type = undefined_t;
		}
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			assert(m_type == undefined_t);
			break;
		}
	}

	void entry::print(std::ostream& os, int indent) const
	{
		assert(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t && i->second.type() != entry::int_t) os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}
<commit_msg>optimizations to entry (using std::maps find instead of linear search)<commit_after>/*

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

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

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

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

*/

#include <algorithm>
#include "libtorrent/entry.hpp"
#include <boost/bind.hpp>
#include <boost/next_prior.hpp>

#if defined(_MSC_VER)
namespace std
{
	using ::isprint;
}
#define for if (false) {} else for
#endif

namespace
{
	template <class T>
	void call_destructor(T* o)
	{
		assert(o);
		o->~T();
	}

	struct compare_string
	{
		compare_string(char const* s): m_str(s)  {}

		bool operator()(
			std::pair<std::string
			, libtorrent::entry> const& e) const
		{
			return e.first == m_str;
		}
		char const* m_str;
	};
}

namespace libtorrent
{
	namespace detail
	{
		char const*	integer_to_str(char* buf, int size, entry::integer_type val)
		{
			int sign = 0;
			if (val < 0)
			{
				sign = 1;
				val = -val;
			}
			buf[--size] = '\0';
			if (val == 0) buf[--size] = '0';
			for (; size > sign && val != 0;)
			{
				buf[--size] = '0' + char(val % 10);
				val /= 10;
			}
			if (sign) buf[--size] = '-';
			return buf + size;
		}
	}

	entry& entry::operator[](char const* key)
	{
		dictionary_type::iterator i = dict().find(key);
		if (i != dict().end()) return i->second;
		dictionary_type::iterator ret = dict().insert(
			dict().begin()
			, std::make_pair(std::string(key), entry()));
		return ret->second;
	}

	entry& entry::operator[](std::string const& key)
	{
		return (*this)[key.c_str()];
	}

	entry* entry::find_key(char const* key)
	{
		dictionary_type::iterator i = std::find_if(
			dict().begin()
			, dict().end()
			, compare_string(key));
		if (i == dict().end()) return 0;
		return &i->second;

	}

	entry const* entry::find_key(char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) return 0;
		return &i->second;
	}

	const entry& entry::operator[](char const* key) const
	{
		dictionary_type::const_iterator i = dict().find(key);
		if (i == dict().end()) throw type_error(
			(std::string("key not found: ") + key).c_str());
		return i->second;
	}

	const entry& entry::operator[](std::string const& key) const
	{
		return (*this)[key.c_str()];
	}

	entry::entry(const dictionary_type& v)
	{
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	entry::entry(const string_type& v)
	{
		new(data) string_type(v);
		m_type = string_t;
	}

	entry::entry(const list_type& v)
	{
		new(data) list_type(v);
		m_type = list_t;
	}

	entry::entry(const integer_type& v)
	{
		new(data) integer_type(v);
		m_type = int_t;
	}

	void entry::operator=(const dictionary_type& v)
	{
		destruct();
		new(data) dictionary_type(v);
		m_type = dictionary_t;
	}

	void entry::operator=(const string_type& v)
	{
		destruct();
		new(data) string_type(v);
		m_type = string_t;
	}

	void entry::operator=(const list_type& v)
	{
		destruct();
		new(data) list_type(v);
		m_type = list_t;
	}

	void entry::operator=(const integer_type& v)
	{
		destruct();
		new(data) integer_type(v);
		m_type = int_t;
	}

	bool entry::operator==(entry const& e) const
	{
		if (m_type != e.m_type) return false;

		switch(m_type)
		{
		case int_t:
			return integer() == e.integer();
		case string_t:
			return string() == e.string();
		case list_t:
			return list() == e.list();
		case dictionary_t:
			return dict() == e.dict();
		default:
			assert(m_type == undefined_t);
			return true;
		}
	}

	void entry::construct(data_type t)
	{
		m_type = t;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type;
			break;
		case string_t:
			new(data) string_type;
			break;
		case list_t:
			new(data) list_type;
			break;
		case dictionary_t:
			new (data) dictionary_type;
			break;
		default:
			assert(m_type == undefined_t);
			m_type = undefined_t;
		}
	}

	void entry::copy(const entry& e)
	{
		m_type = e.m_type;
		switch(m_type)
		{
		case int_t:
			new(data) integer_type(e.integer());
			break;
		case string_t:
			new(data) string_type(e.string());
			break;
		case list_t:
			new(data) list_type(e.list());
			break;
		case dictionary_t:
			new (data) dictionary_type(e.dict());
			break;
		default:
			m_type = undefined_t;
		}
	}

	void entry::destruct()
	{
		switch(m_type)
		{
		case int_t:
			call_destructor(reinterpret_cast<integer_type*>(data));
			break;
		case string_t:
			call_destructor(reinterpret_cast<string_type*>(data));
			break;
		case list_t:
			call_destructor(reinterpret_cast<list_type*>(data));
			break;
		case dictionary_t:
			call_destructor(reinterpret_cast<dictionary_type*>(data));
			break;
		default:
			assert(m_type == undefined_t);
			break;
		}
	}

	void entry::print(std::ostream& os, int indent) const
	{
		assert(indent >= 0);
		for (int i = 0; i < indent; ++i) os << " ";
		switch (m_type)
		{
		case int_t:
			os << integer() << "\n";
			break;
		case string_t:
			{
				bool binary_string = false;
				for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
				{
					if (!std::isprint(static_cast<unsigned char>(*i)))
					{
						binary_string = true;
						break;
					}
				}
				if (binary_string)
				{
					os.unsetf(std::ios_base::dec);
					os.setf(std::ios_base::hex);
					for (std::string::const_iterator i = string().begin(); i != string().end(); ++i)
						os << static_cast<unsigned int>((unsigned char)*i);
					os.unsetf(std::ios_base::hex);
					os.setf(std::ios_base::dec);
					os << "\n";
				}
				else
				{
					os << string() << "\n";
				}
			} break;
		case list_t:
			{
				os << "list\n";
				for (list_type::const_iterator i = list().begin(); i != list().end(); ++i)
				{
					i->print(os, indent+1);
				}
			} break;
		case dictionary_t:
			{
				os << "dictionary\n";
				for (dictionary_type::const_iterator i = dict().begin(); i != dict().end(); ++i)
				{
					for (int j = 0; j < indent+1; ++j) os << " ";
					os << "[" << i->first << "]";
					if (i->second.type() != entry::string_t && i->second.type() != entry::int_t) os << "\n";
					else os << " ";
					i->second.print(os, indent+2);
				}
			} break;
		default:
			os << "<uninitialized>\n";
		}
	}
}

<|endoftext|>


<commit_before>#include "Pessoa.h"
#include "Banheiro.h"
#include <mutex>

void Pessoa::entraNoBanheiro(sexo){

    if (sexo == 'M') {

        while (true){

            entrada.lock; // Entra na fila

            if ( mulheresNoBanheiro > 0 ){
                homensDormindo++;
                entrada.unlock;
                homem.lock;
            }

            homensNoBanheiro++; // Entra no banheiro

            mulheresConsecutivos = 0;
            homensConsecutivos++;

            // Antes do signal, apenas um processo executa por vez

            // SIGNAL - AJUSTAR RESTRIÇÕES
            if (homensNoBanheiro == 0 && mulheresDormindo > 0) {
                mulheresDormindo--;
                mulher.unlock;
            } else if (mulheresNoBanheiro == 0 && homensNoBanheiro == 0 && homensDormindo > 0) {
                homensDormindo--;
                homem.unlock;
            } else {
                entrada.unlock;
            }

            /*
             SECAO CRITICA
            */

            entrada.lock;

            homensNoBanheiro--;

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (homensNoBanheiro == 0 && mulheresDormindo > 0) {
                mulheresDormindo--;
                mulher.unlock;
            } else if (mulheresNoBanheiro == 0 && homensNoBanheiro == 0 && homensDormindo > 0) {
                homensDormindo--;
                homem.unlock;
            } else {
                entrada.unlock;
            }

            // FICA MOSCANDO - NON CRITICAL

        }

    } else if (sexo == 'F') {

        while (true){

            entrada.lock; // Formação da fila

            if ( utilizacaoGeral == MAX_UTILIZACAO ) {

                // destroy thread
                return 1; // DUVIDA

            } else ( homensNoBanheiro > 0 || mulheresNoBanheiro == CAPACIDADE_BANHEIRO ){
                mulheresDormindo++; // Espera na fila
                entrada.unlock; // Libera entrada na fila

                //if ( !(homensDormindo > 0 && mulheresConsecutivos >= UTILIZACAO_CONSEC ) ) { // DUVIDA
                    mulher.lock; // Permite a mulher entrar no banheiro
                //} else {
                    mulheresDormindo--; // Tira mulher da fila

                //}
            }

            mulheresNoBanheiro++; // Mulher entra no WC

            homensConsecutivos = 0; // Zera homens no WC

            mulheresConsecutivos++; // Incrementa nº de mulheres no WC

            utilzacaoGeral++; // Incrementa o nº de utilizações

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (mulheresNoBanheiro <= CAPACIDADE_BANHEIRO) {

                if ( homensDormindo == 0 && mulheresConsecutivos < UTILIZACAO_CONSEC && mulheresDormindo > 0 ){

                    //mulheresDormindo--; // Tira mulher da fila
                    mulher.unlock; // Permite entrada no WC

                } else {

                    entrada.unlock; // Libera entrada na fila

                }

            } else {

                entrada.unlock; // Libera entrada na fila

            }

            /*
             SECAO CRITICA
            */

            entrada.lock; // DÚVIDA

            mulheresNoBanheiro--;

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (mulheresConsecutivos >= UTILIZACAO_CONSEC && homensDormindo > 0 && mulheresNoBanheiro == 0) { // Libera Homem

                homensDormindo--;
                homem.unlock;

            else if (mulheresConsecutivos < UTILIZACAO_CONSEC && mulheresDormindo > 0 && homensDormindo == 0){

                mulheresDormindo--;
                mulher.unlock;

            } else { // Libera entrada na fila

                entrada.unlock;

            }

            // FICA MOSCANDO - NON CRITICAL

        }

    } else {

        cout << endl << "Sexo indefinido." << endl;

    }

}
<commit_msg>Versão nova 2<commit_after>#include "Pessoa.h"
#include "Banheiro.h"
#include <mutex>

void Pessoa::entraNoBanheiro(sexo){

    if (sexo == 'M') {

        while (true){

            entrada.lock; // Entra na fila

            if ( mulheresNoBanheiro > 0 ){
                homensDormindo++;
                entrada.unlock;
                homem.lock;
            }

            homensNoBanheiro++; // Entra no banheiro

            mulheresConsecutivos = 0;
            homensConsecutivos++;

            // Antes do signal, apenas um processo executa por vez

            // SIGNAL - AJUSTAR RESTRIÇÕES
            if (homensNoBanheiro == 0 && mulheresDormindo > 0) {
                mulheresDormindo--;
                mulher.unlock;
            } else if (mulheresNoBanheiro == 0 && homensNoBanheiro == 0 && homensDormindo > 0) {
                homensDormindo--;
                homem.unlock;
            } else {
                entrada.unlock;
            }

            /*
             SECAO CRITICA
            */

            entrada.lock;

            homensNoBanheiro--;

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (homensNoBanheiro == 0 && mulheresDormindo > 0) {
                mulheresDormindo--;
                mulher.unlock;
            } else if (mulheresNoBanheiro == 0 && homensNoBanheiro == 0 && homensDormindo > 0) {
                homensDormindo--;
                homem.unlock;
            } else {
                entrada.unlock;
            }

            // FICA MOSCANDO - NON CRITICAL

        }

    } else if (sexo == 'F') {

        while (true){

            entrada.lock; // Formação da fila

            if ( utilizacaoGeral == MAX_UTILIZACAO ) {

                // destroy thread
                return 1; // DUVIDA

            } else ( homensNoBanheiro > 0 || mulheresNoBanheiro == CAPACIDADE_BANHEIRO ){
                mulheresDormindo++; // Espera na fila
                entrada.unlock; // Libera entrada na fila

                //if ( !(homensDormindo > 0 && mulheresConsecutivos >= UTILIZACAO_CONSEC ) ) { // DUVIDA
                    mulher.lock; // Permite a mulher entrar no banheiro
                //} else {
                     // Tira mulher da fila

                //}
            }

            mulheresNoBanheiro++; // Mulher entra no WC

            homensConsecutivos = 0; // Zera homens no WC

            mulheresConsecutivos++; // Incrementa nº de mulheres no WC

            utilzacaoGeral++; // Incrementa o nº de utilizações

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (mulheresNoBanheiro < CAPACIDADE_BANHEIRO) {

                if (mulheresConsecutivos < UTILIZACAO_CONSEC && mulheresDormindo > 0 ){

                    mulheresDormindo--; // Tira mulher da fila
                    mulher.unlock; // Permite entrada no WC

                } else {

                    entrada.unlock; // Libera entrada na fila

                }

            } else {

                entrada.unlock; // Libera entrada na fila

            }

            /*
             SECAO CRITICA
            */

            entrada.lock; // DÚVIDA

            mulheresNoBanheiro--;

            //SIGNAL- AJUSTAR RESTRIÇÕES
            if (mulheresConsecutivos >= UTILIZACAO_CONSEC && homensDormindo > 0 && mulheresNoBanheiro == 0) { // Libera Homem

                homensDormindo--;
                homem.unlock;

            else if ((mulheresConsecutivos < UTILIZACAO_CONSEC && mulheresDormindo > 0 && homensDormindo == 0) || (mulheresConsecutivos > UTILIZACAO_CONSEC && homensDormindo == 0)){

                mulheresDormindo--;
                mulher.unlock;

            } else { // Libera entrada na fila

                entrada.unlock;

            }

            // FICA MOSCANDO - NON CRITICAL

        }

    } else {

        cout << endl << "Sexo indefinido." << endl;

    }

}
<|endoftext|>


<commit_before>#include "Player.h"
#include "PlayerManager.h"

Player::Player(std::string sName, unsigned int uiHandSize)
	:m_sName(sName)
	,m_uiHandSize(uiHandSize)
{
}

Player::~Player()
{
}

bool Player::isSolved() const
{
	return m_setOwnedCards.size() == m_uiHandSize;
}

void Player::addGuess(const AnsweredGuess &answeredGuess)
{
    //push_back makes a copy. It's a small struct, it's fine
    m_lAnsweredGuesses.push_back(answeredGuess);
}

void Player::addCard(uint32_t uiCardToAdd)
{
	m_setOwnedCards.insert(uiCardToAdd);
}

bool Player::ownsCard(uint32_t uiCard) const
{
	return m_setOwnedCards.find(uiCard) != m_setOwnedCards.end();
}

bool Player::ownsOneOfTheseCards(const AnsweredGuess &answeredGuess) const
{
    if (ownsCard(answeredGuess.m_uiPerson) ||
        ownsCard(answeredGuess.m_uiPlace) ||
        ownsCard(answeredGuess.m_uiWeapon)) {
        return true;
    }
	return false;
}

void Player::addPassedCards(const Guess &guess)
{
    m_setPassedCards.insert(guess.m_uiPerson);
    m_setPassedCards.insert(guess.m_uiPlace);
    m_setPassedCards.insert(guess.m_uiWeapon);
}

bool Player::hasBeenPassedOn(uint32_t uiCard) const
{
	return m_setPassedCards.find(uiCard) != m_setPassedCards.end();
}

//Here we return an internal enum. We could return a bool based on whether we need to remove the
//  guess or not, but then we wouldn't be able to tell the difference between a trash guess we are
//  throwing away, and the actual gain of knowledge that requires a recalc
Player::eGuessState Player::processStoredGuess(AnsweredGuess &answeredGuess, PlayerManager* pPlayerManager)
{
	//If I know I own any of these cards, the guess can provide me no more information
	if (ownsOneOfTheseCards(answeredGuess))
	{
		return Player::eTrash;
	}
	//If someone ELSE owns any of these cards, zero them out
	if (pPlayerManager->isOwned(answeredGuess.m_uiPlace))
	{
		answeredGuess.m_uiPlace = 0;
	}
	if (pPlayerManager->isOwned(answeredGuess.m_uiPerson))
	{
		answeredGuess.m_uiPerson = 0;
	}
	if (pPlayerManager->isOwned(answeredGuess.m_uiWeapon))
	{
		answeredGuess.m_uiWeapon = 0;
	}
    //If I know for a fact that I don't own this card (I've passed on a guess with it in it),
    //  I can remove that from the guess as well
	if (hasBeenPassedOn(answeredGuess.m_uiPlace))
	{
		answeredGuess.m_uiPlace = 0;
	}
	if (hasBeenPassedOn(answeredGuess.m_uiPerson))
	{
		answeredGuess.m_uiPerson = 0;
	}
	if (hasBeenPassedOn(answeredGuess.m_uiWeapon))
	{
		answeredGuess.m_uiWeapon = 0;
	}
    //If we know the answer in the center, we can eliminate that from all guesses.
    uint32_t uiSolvedPlace = pPlayerManager->isTypeSolved(Rules::ePlace);
    if (uiSolvedPlace != 0) {
		answeredGuess.m_uiPlace = 0;
    }
    uint32_t uiSolvedPerson = pPlayerManager->isTypeSolved(Rules::ePerson);
    if (uiSolvedPerson != 0) {
		answeredGuess.m_uiPerson = 0;
    }
    uint32_t uiSolvedWeapon = pPlayerManager->isTypeSolved(Rules::eWeapon);
    if (uiSolvedWeapon != 0) {
		answeredGuess.m_uiWeapon = 0;
    }
	//Finally, if there's only one card left in the guess, ITS MINE!!! YES!
	if (answeredGuess.isSolved())
	{
		uint32_t uiSolvedCard = answeredGuess.getSolved();
		addCard(uiSolvedCard);
		return Player::eSolved;
	}
    //If there are no cards left, this guess is no longer useful to me. Junk it.
	if (answeredGuess.isEmpty())
	{
		return Player::eTrash;
	}
	return Player::eNotSolved;
}

bool Player::checkForSolutions(PlayerManager* pPlayerManager)
{
    bool bSolutionFound = false;
	std::list<AnsweredGuess>::iterator i = m_lAnsweredGuesses.begin();
    Player::eGuessState eProcessGuessResult = Player::eTrash;
    //We're gonna be removing while we iterate, so we can't use the fancy foreach syntax
	while (i != m_lAnsweredGuesses.end())
	{
        eProcessGuessResult = processStoredGuess((*i), pPlayerManager);
        //Technically, in the solved case, I could not break and just leak to the next
        //  switch statement. I just happen to think that's disgusting.
        switch (eProcessGuessResult) {
            case Player::eNotSolved :
                i++;
                break;
            case Player::eSolved :
                bSolutionFound = true;
                i = m_lAnsweredGuesses.erase(i);
                break;
            case Player::eTrash :
                i = m_lAnsweredGuesses.erase(i);
                break;
            default:
                std::cout << "Player::" << __FUNCTION__ << ", ERROR: Not defined player guess result";
                break;
        }
	}
    return bSolutionFound;
}

//---------------------ANSWERED GUESS METHODS-------------------------
bool Player::AnsweredGuess::isSolved()
{
	uint32_t uiStillPresent = 0;
	if (m_uiPlace != 0)
	{
		++uiStillPresent;
	}
	if (m_uiPerson != 0)
	{
		++uiStillPresent;
	}
	if (m_uiWeapon != 0)
	{
		++uiStillPresent;
	}
	return uiStillPresent == 1;
}

uint32_t Player::AnsweredGuess::getSolved()
{
    //There's a little bit of code duplication here. We'll likely call this before getting solved anyways.
    //But having this check helps me sleep at night
    if (!isSolved())
    {
        return 0;
    }
	if (m_uiPlace != 0)
	{
		return m_uiPlace;
	}
	if (m_uiPerson != 0)
	{
		return m_uiPerson;
	}
	if (m_uiWeapon != 0)
	{
		return m_uiWeapon;
	}
	return 0;
}
<commit_msg>Cleaned up some processStoredGuess state that had repeating lines<commit_after>#include "Player.h"
#include "PlayerManager.h"

Player::Player(std::string sName, unsigned int uiHandSize)
	:m_sName(sName)
	,m_uiHandSize(uiHandSize)
{
}

Player::~Player()
{
}

bool Player::isSolved() const
{
	return m_setOwnedCards.size() == m_uiHandSize;
}

void Player::addGuess(const AnsweredGuess &answeredGuess)
{
    //push_back makes a copy. It's a small struct, it's fine
    m_lAnsweredGuesses.push_back(answeredGuess);
}

void Player::addCard(uint32_t uiCardToAdd)
{
	m_setOwnedCards.insert(uiCardToAdd);
}

bool Player::ownsCard(uint32_t uiCard) const
{
	return m_setOwnedCards.find(uiCard) != m_setOwnedCards.end();
}

bool Player::ownsOneOfTheseCards(const AnsweredGuess &answeredGuess) const
{
    if (ownsCard(answeredGuess.m_uiPerson) ||
        ownsCard(answeredGuess.m_uiPlace) ||
        ownsCard(answeredGuess.m_uiWeapon)) {
        return true;
    }
	return false;
}

void Player::addPassedCards(const Guess &guess)
{
    m_setPassedCards.insert(guess.m_uiPerson);
    m_setPassedCards.insert(guess.m_uiPlace);
    m_setPassedCards.insert(guess.m_uiWeapon);
}

bool Player::hasBeenPassedOn(uint32_t uiCard) const
{
	return m_setPassedCards.find(uiCard) != m_setPassedCards.end();
}

//Here we return an internal enum. We could return a bool based on whether we need to remove the
//  guess or not, but then we wouldn't be able to tell the difference between a trash guess we are
//  throwing away, and the actual gain of knowledge that requires a recalc
Player::eGuessState Player::processStoredGuess(AnsweredGuess &answeredGuess, PlayerManager* pPlayerManager)
{
	//If I know I own any of these cards, the guess can provide me no more information
	if (ownsOneOfTheseCards(answeredGuess))
	{
		return Player::eTrash;
	}

	//If someone ELSE owns any of these cards, zero them out
	if (pPlayerManager->isOwned(answeredGuess.m_uiPlace)
            //If I know for a fact that I don't own this card (I've passed on a guess with it in it),
            //  I can remove that from the guess as well
            || hasBeenPassedOn(answeredGuess.m_uiPlace)
            //If we know this card is in the center, it can't be in this player's hand
            || pPlayerManager->isTypeSolved(Rules::ePlace) == answeredGuess.m_uiPlace)
	{
		answeredGuess.m_uiPlace = 0;
	}
	if (pPlayerManager->isOwned(answeredGuess.m_uiPerson)
            || hasBeenPassedOn(answeredGuess.m_uiPerson)
            || pPlayerManager->isTypeSolved(Rules::ePerson) == answeredGuess.m_uiPerson)
	{
		answeredGuess.m_uiPerson = 0;
	}
	if (pPlayerManager->isOwned(answeredGuess.m_uiWeapon)
            || hasBeenPassedOn(answeredGuess.m_uiWeapon)
            || pPlayerManager->isTypeSolved(Rules::eWeapon) == answeredGuess.m_uiWeapon)
	{
		answeredGuess.m_uiWeapon = 0;
	}

	//Finally, if there's only one card left in the guess, ITS MINE!!! YES!
	if (answeredGuess.isSolved())
	{
		uint32_t uiSolvedCard = answeredGuess.getSolved();
		addCard(uiSolvedCard);
		return Player::eSolved;
	}
    //If there are no cards left, this guess is no longer useful to me. Junk it.
	if (answeredGuess.isEmpty())
	{
		return Player::eTrash;
	}
	return Player::eNotSolved;
}

bool Player::checkForSolutions(PlayerManager* pPlayerManager)
{
    bool bSolutionFound = false;
	std::list<AnsweredGuess>::iterator i = m_lAnsweredGuesses.begin();
    Player::eGuessState eProcessGuessResult = Player::eTrash;
    //We're gonna be removing while we iterate, so we can't use the fancy foreach syntax
	while (i != m_lAnsweredGuesses.end())
	{
        eProcessGuessResult = processStoredGuess((*i), pPlayerManager);
        //Technically, in the solved case, I could not break and just leak to the next
        //  switch statement. I just happen to think that's disgusting.
        switch (eProcessGuessResult) {
            case Player::eNotSolved :
                i++;
                break;
            case Player::eSolved :
                bSolutionFound = true;
                i = m_lAnsweredGuesses.erase(i);
                break;
            case Player::eTrash :
                i = m_lAnsweredGuesses.erase(i);
                break;
            default:
                std::cout << "Player::" << __FUNCTION__ << ", ERROR: Not defined player guess result";
                break;
        }
	}
    return bSolutionFound;
}

//---------------------ANSWERED GUESS METHODS-------------------------
bool Player::AnsweredGuess::isSolved()
{
	uint32_t uiStillPresent = 0;
	if (m_uiPlace != 0)
	{
		++uiStillPresent;
	}
	if (m_uiPerson != 0)
	{
		++uiStillPresent;
	}
	if (m_uiWeapon != 0)
	{
		++uiStillPresent;
	}
	return uiStillPresent == 1;
}

uint32_t Player::AnsweredGuess::getSolved()
{
    //There's a little bit of code duplication here. We'll likely call this before getting solved anyways.
    //But having this check helps me sleep at night
    if (!isSolved())
    {
        return 0;
    }
	if (m_uiPlace != 0)
	{
		return m_uiPlace;
	}
	if (m_uiPerson != 0)
	{
		return m_uiPerson;
	}
	if (m_uiWeapon != 0)
	{
		return m_uiWeapon;
	}
	return 0;
}
<|endoftext|>


<commit_before>
#include <libclientserver.h>

struct ControlPacket {
	uint32_t Command;
	int32_t fd;
};

Poller::Poller()
{
	m_loop = true;
	m_controlfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
	if (m_controlfd < 0)
		abort();
	m_modified = false;
	m_err_ebadf = 0;
	Thread::Start();
}

Poller::~Poller()
{
	m_loop = false;
	WakeUp(-1, false);
	Thread::Stop();

	do
	{
		ScopedLock lock = ScopedLock(&m_mutex);
	restart:
		m_modified = false;
		for(std::map<int, IPollable *>::iterator it = m_map.begin(); it != m_map.end(); it++)
		{
			it->second->DoClose(this);
			if (m_modified)
				goto restart;
		}
	} while(0);

	if (m_map.size() > 0)
	{
		abort(); //Tried to delete selector with items left in it
	}

	if (close(m_controlfd) < 0)
		abort();
}

void Poller::Add(IPollable *p)
{
	int fd = p->GetFD(this);
	if (fd < 0)
		abort(); //Invalid FD this is a bug
	if (m_map.find(fd) != m_map.end())
		abort(); //Duplicate FD?

	ScopedLock lock = ScopedLock(&m_mutex);

	m_modified = true;
	m_map[fd] = p;
	UpdateMap(fd);

	lock.Unlock();
	WakeUp();
}

void Poller::Update(IPollable *p) {
	//This can deadlock under strange conditions.
	//To attempt to take the lock if we can't. Send it to the ioloop to be updated (take slightly longer)
	if (false && m_mutex.TryLock()) {
		m_modified = true;
		UpdateMap(p->GetFD(this));
		m_mutex.Unlock();
		WakeUp();
	} else {
		WakeUp(p->GetFD(this));
	}
}

void Poller::Remove(IPollable *p)
{
	int fd = p->GetFD(this);
	if (fd < 0)
		abort(); //Invalid FD this is a bug
	if (m_map.find(fd) == m_map.end())
		abort(); //No FD to remove

	ScopedLock lock = ScopedLock(&m_mutex);
	m_modified = true;
	m_map.erase(m_map.find(fd));

	std::map<int, struct timespec>::iterator it = m_timeout.find(fd);
	if (it != m_timeout.end())
		m_timeout.erase(it);

	lock.Unlock();
	WakeUp();
}

void Poller::WakeUp(int fd, bool block) {
	struct ControlPacket packet = { 1, fd };
	if (!IsRunning())
		return;
restart:
	if (write(m_controlfd, &packet, sizeof(packet)) != sizeof(packet))
	{
		switch(errno) {
			case EAGAIN:
				struct pollfd tmp;
				tmp.fd = m_controlfd;
				tmp.events = POLLOUT;
				tmp.revents = 0;
				if (ppoll(&tmp, 1, NULL, NULL) < 0) {
					perror("ppoll");
					abort();
				}
				if (block) {
					goto restart;
				}
				break;
			default:
				printf("m_controlfd: %d, fd: %d sizeof(x): %lu error: %s\n", m_controlfd, fd, sizeof(packet), strerror(errno));
				abort();
		}
	}
}

void Poller::UpdateMap(int fd)
{
	std::map<int, IPollable *>::iterator it = m_map.find(fd);
	if (it == m_map.end())
		return; /* fd may have disappeared */

	if (it->second->CanTimeout(this))
	{
		struct timespec ts, now;
		it->second->GetTimeout(this, &ts);

		if (ts.tv_sec == 0 && ts.tv_nsec == 0)
		{
			std::map<int, struct timespec>::iterator it2 = m_timeout.find(fd);
			if (it2 != m_timeout.end())
				m_timeout.erase(it2);
		}

		if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
			abort();

		ts.tv_sec += now.tv_sec;
		ts.tv_nsec += now.tv_nsec;

		if (ts.tv_nsec > 999999999)
		{
			ts.tv_sec++;
			ts.tv_nsec -= 1000000000;
		}

		m_timeout[it->second->GetFD(this)] = ts;
	}
}

void Poller::ReadControl() {
	struct ControlPacket packet = { 1, -1 };
	int size = 0;
	do {
		size = read(m_controlfd, &packet, sizeof(packet));
		if (size < 0)
		{
			switch(errno)
			{
				case EAGAIN:
					size = 0;
					break;
				default:
					abort();
					break;
			}
		} else {
			if (size != sizeof(packet))
				abort();
			ScopedLock lock = ScopedLock(&m_mutex);
			m_modified = true;
			if (packet.fd >= 0)
			UpdateMap(packet.fd);
		}
	} while(size != 0);
}

void Poller::CalcTimeout(struct timespec *tv)
{
	struct timespec now;
	struct timespec lowest;

	lowest.tv_sec = LONG_MAX;
	lowest.tv_nsec = 0;

	tv->tv_sec = 0;
	tv->tv_nsec = 0;

	if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
		abort();
	std::map<int, struct timespec>::iterator it = m_timeout.begin();
	while(it != m_timeout.end())
	{
		if (Time::IsLess(&it->second, &lowest))
		{
			lowest.tv_sec = it->second.tv_sec;
			lowest.tv_nsec = it->second.tv_nsec;
		}
		it++;
	}

	Time::Sub(&lowest, &now, &lowest);
	if (lowest.tv_sec < 0)
		return;
	tv->tv_sec = lowest.tv_sec;
	tv->tv_nsec = lowest.tv_nsec;
}

void Poller::Run()
{
	struct pollfd *fds = NULL;
	size_t fds_size = 0;

	while(m_loop)
	{
		struct timespec timeout = {0, 0};
		//Rebuild Poll structure
		do
		{
			ScopedLock lock = ScopedLock(&m_mutex);
			if (fds_size != m_map.size() + 1 || fds == NULL)
			{
				fds_size = m_map.size() + 1;
				fds = (struct pollfd * ) realloc(fds, sizeof(*fds) * fds_size);
				if (fds == NULL) {
					abort(); //malloc failure.
					continue; //Hides clang static analyser warning for null deref
				}
			}

			//First item is special case for control
			fds[0].fd = m_controlfd;
			fds[0].events = POLLIN;
			fds[0].revents = 0;

			int idx = 1;
			std::map<int, IPollable *>::iterator it = m_map.begin();
			while(it != m_map.end())
			{
				fds[idx].fd = it->first;
				fds[idx].events = 0;
				if (it->second->CanRead(this))
					fds[idx].events |= POLLIN;
				if (it->second->CanWrite(this))
					fds[idx].events |= (POLLOUT | POLLERR);
				fds[idx].revents = 0;
				it++;
				idx++;
			}
			CalcTimeout(&timeout);
		} while(0);

		int ret = ppoll(fds, fds_size, &timeout, NULL);
		if (ret < 0)
		{
			switch(errno)
			{
				case EINTR:
					continue;
					break;
				case EBADF: /* It is posisble to have a bad fd because the set could have changed after the unlock */
					m_err_ebadf++;
					continue;
					break;
				default:
					abort();
					break;
			}
		}

		if (fds[0].revents & POLLIN) {
			ReadControl();
		}

		do {
			ScopedLock lock = ScopedLock(&m_mutex);
			m_modified = false;

			for(size_t i=1;i<fds_size;i++)
			{
				bool work = false;
				std::map<int, IPollable *>::iterator it = m_map.find(fds[i].fd);
				if (it == m_map.end())
					continue; //Item must have been removed while we were in poll so skip it.

				if ( (fds[i].revents & POLLIN) )
				{
					it->second->DoRead(this);
					if (m_modified)
						goto skip_to_end;
					work = true;
				}

				if ( (fds[i].revents & POLLOUT) || (fds[i].revents & POLLERR))
				{
					it->second->DoWrite(this);
					if (m_modified)
						goto skip_to_end;
					work = true;
				}

				if (work)
				{
					if (it->second->CanTimeout(this))
					{
						struct timespec ts, now;
						it->second->GetTimeout(this, &ts);

						if (ts.tv_sec == 0 && ts.tv_nsec == 0)
						{
							std::map<int, struct timespec>::iterator it2 = m_timeout.find(fds[i].fd);
							if (it2 != m_timeout.end())
								m_timeout.erase(it2);
						}

						if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
							abort();

						ts.tv_sec += now.tv_sec;
						ts.tv_nsec += now.tv_nsec;

						if (ts.tv_nsec > 999999999)
						{
							ts.tv_sec++;
							ts.tv_nsec -= 1000000000;
						}
						m_timeout[it->second->GetFD(this)] = ts;
					}
					else
					{
						std::map<int, struct timespec>::iterator it2 = m_timeout.find(fds[i].fd);
						if (it2 != m_timeout.end())
							m_timeout.erase(it2);
					}
				}
			}

			struct timespec now = {0, 0};
			if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
				abort();

			for(std::map<int, struct timespec>::iterator it = m_timeout.begin(); it != m_timeout.end(); it++)
			{
				if (Time::IsLess(&it->second, &now))
				{
					m_map[it->first]->DoTimeout(this);
					if (m_modified)
						goto skip_to_end;
					UpdateMap(it->first);
				}
			}

		} while(0);
skip_to_end:
		ReadControl();
	}
	free(fds);
}

<commit_msg>Remove printf<commit_after>
#include <libclientserver.h>

struct ControlPacket {
	uint32_t Command;
	int32_t fd;
};

Poller::Poller()
{
	m_loop = true;
	m_controlfd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
	if (m_controlfd < 0)
		abort();
	m_modified = false;
	m_err_ebadf = 0;
	Thread::Start();
}

Poller::~Poller()
{
	m_loop = false;
	WakeUp(-1, false);
	Thread::Stop();

	do
	{
		ScopedLock lock = ScopedLock(&m_mutex);
	restart:
		m_modified = false;
		for(std::map<int, IPollable *>::iterator it = m_map.begin(); it != m_map.end(); it++)
		{
			it->second->DoClose(this);
			if (m_modified)
				goto restart;
		}
	} while(0);

	if (m_map.size() > 0)
	{
		abort(); //Tried to delete selector with items left in it
	}

	if (close(m_controlfd) < 0)
		abort();
}

void Poller::Add(IPollable *p)
{
	int fd = p->GetFD(this);
	if (fd < 0)
		abort(); //Invalid FD this is a bug
	if (m_map.find(fd) != m_map.end())
		abort(); //Duplicate FD?

	ScopedLock lock = ScopedLock(&m_mutex);

	m_modified = true;
	m_map[fd] = p;
	UpdateMap(fd);

	lock.Unlock();
	WakeUp();
}

void Poller::Update(IPollable *p) {
	//This can deadlock under strange conditions.
	//To attempt to take the lock if we can't. Send it to the ioloop to be updated (take slightly longer)
	if (false && m_mutex.TryLock()) {
		m_modified = true;
		UpdateMap(p->GetFD(this));
		m_mutex.Unlock();
		WakeUp();
	} else {
		WakeUp(p->GetFD(this));
	}
}

void Poller::Remove(IPollable *p)
{
	int fd = p->GetFD(this);
	if (fd < 0)
		abort(); //Invalid FD this is a bug
	if (m_map.find(fd) == m_map.end())
		abort(); //No FD to remove

	ScopedLock lock = ScopedLock(&m_mutex);
	m_modified = true;
	m_map.erase(m_map.find(fd));

	std::map<int, struct timespec>::iterator it = m_timeout.find(fd);
	if (it != m_timeout.end())
		m_timeout.erase(it);

	lock.Unlock();
	WakeUp();
}

void Poller::WakeUp(int fd, bool block) {
	struct ControlPacket packet = { 1, fd };
	if (!IsRunning())
		return;
restart:
	if (write(m_controlfd, &packet, sizeof(packet)) != sizeof(packet))
	{
		switch(errno) {
			case EAGAIN:
				struct pollfd tmp;
				tmp.fd = m_controlfd;
				tmp.events = POLLOUT;
				tmp.revents = 0;
				if (ppoll(&tmp, 1, NULL, NULL) < 0) {
					perror("ppoll");
					abort();
				}
				if (block) {
					goto restart;
				}
				break;
			default:
				//printf("m_controlfd: %d, fd: %d sizeof(x): %lu error: %s\n", m_controlfd, fd, sizeof(packet), strerror(errno));
				abort();
		}
	}
}

void Poller::UpdateMap(int fd)
{
	std::map<int, IPollable *>::iterator it = m_map.find(fd);
	if (it == m_map.end())
		return; /* fd may have disappeared */

	if (it->second->CanTimeout(this))
	{
		struct timespec ts, now;
		it->second->GetTimeout(this, &ts);

		if (ts.tv_sec == 0 && ts.tv_nsec == 0)
		{
			std::map<int, struct timespec>::iterator it2 = m_timeout.find(fd);
			if (it2 != m_timeout.end())
				m_timeout.erase(it2);
		}

		if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
			abort();

		ts.tv_sec += now.tv_sec;
		ts.tv_nsec += now.tv_nsec;

		if (ts.tv_nsec > 999999999)
		{
			ts.tv_sec++;
			ts.tv_nsec -= 1000000000;
		}

		m_timeout[it->second->GetFD(this)] = ts;
	}
}

void Poller::ReadControl() {
	struct ControlPacket packet = { 1, -1 };
	int size = 0;
	do {
		size = read(m_controlfd, &packet, sizeof(packet));
		if (size < 0)
		{
			switch(errno)
			{
				case EAGAIN:
					size = 0;
					break;
				default:
					abort();
					break;
			}
		} else {
			if (size != sizeof(packet))
				abort();
			ScopedLock lock = ScopedLock(&m_mutex);
			m_modified = true;
			if (packet.fd >= 0)
			UpdateMap(packet.fd);
		}
	} while(size != 0);
}

void Poller::CalcTimeout(struct timespec *tv)
{
	struct timespec now;
	struct timespec lowest;

	lowest.tv_sec = LONG_MAX;
	lowest.tv_nsec = 0;

	tv->tv_sec = 0;
	tv->tv_nsec = 0;

	if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
		abort();
	std::map<int, struct timespec>::iterator it = m_timeout.begin();
	while(it != m_timeout.end())
	{
		if (Time::IsLess(&it->second, &lowest))
		{
			lowest.tv_sec = it->second.tv_sec;
			lowest.tv_nsec = it->second.tv_nsec;
		}
		it++;
	}

	Time::Sub(&lowest, &now, &lowest);
	if (lowest.tv_sec < 0)
		return;
	tv->tv_sec = lowest.tv_sec;
	tv->tv_nsec = lowest.tv_nsec;
}

void Poller::Run()
{
	struct pollfd *fds = NULL;
	size_t fds_size = 0;

	while(m_loop)
	{
		struct timespec timeout = {0, 0};
		//Rebuild Poll structure
		do
		{
			ScopedLock lock = ScopedLock(&m_mutex);
			if (fds_size != m_map.size() + 1 || fds == NULL)
			{
				fds_size = m_map.size() + 1;
				fds = (struct pollfd * ) realloc(fds, sizeof(*fds) * fds_size);
				if (fds == NULL) {
					abort(); //malloc failure.
					continue; //Hides clang static analyser warning for null deref
				}
			}

			//First item is special case for control
			fds[0].fd = m_controlfd;
			fds[0].events = POLLIN;
			fds[0].revents = 0;

			int idx = 1;
			std::map<int, IPollable *>::iterator it = m_map.begin();
			while(it != m_map.end())
			{
				fds[idx].fd = it->first;
				fds[idx].events = 0;
				if (it->second->CanRead(this))
					fds[idx].events |= POLLIN;
				if (it->second->CanWrite(this))
					fds[idx].events |= (POLLOUT | POLLERR);
				fds[idx].revents = 0;
				it++;
				idx++;
			}
			CalcTimeout(&timeout);
		} while(0);

		int ret = ppoll(fds, fds_size, &timeout, NULL);
		if (ret < 0)
		{
			switch(errno)
			{
				case EINTR:
					continue;
					break;
				case EBADF: /* It is posisble to have a bad fd because the set could have changed after the unlock */
					m_err_ebadf++;
					continue;
					break;
				default:
					abort();
					break;
			}
		}

		if (fds[0].revents & POLLIN) {
			ReadControl();
		}

		do {
			ScopedLock lock = ScopedLock(&m_mutex);
			m_modified = false;

			for(size_t i=1;i<fds_size;i++)
			{
				bool work = false;
				std::map<int, IPollable *>::iterator it = m_map.find(fds[i].fd);
				if (it == m_map.end())
					continue; //Item must have been removed while we were in poll so skip it.

				if ( (fds[i].revents & POLLIN) )
				{
					it->second->DoRead(this);
					if (m_modified)
						goto skip_to_end;
					work = true;
				}

				if ( (fds[i].revents & POLLOUT) || (fds[i].revents & POLLERR))
				{
					it->second->DoWrite(this);
					if (m_modified)
						goto skip_to_end;
					work = true;
				}

				if (work)
				{
					if (it->second->CanTimeout(this))
					{
						struct timespec ts, now;
						it->second->GetTimeout(this, &ts);

						if (ts.tv_sec == 0 && ts.tv_nsec == 0)
						{
							std::map<int, struct timespec>::iterator it2 = m_timeout.find(fds[i].fd);
							if (it2 != m_timeout.end())
								m_timeout.erase(it2);
						}

						if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
							abort();

						ts.tv_sec += now.tv_sec;
						ts.tv_nsec += now.tv_nsec;

						if (ts.tv_nsec > 999999999)
						{
							ts.tv_sec++;
							ts.tv_nsec -= 1000000000;
						}
						m_timeout[it->second->GetFD(this)] = ts;
					}
					else
					{
						std::map<int, struct timespec>::iterator it2 = m_timeout.find(fds[i].fd);
						if (it2 != m_timeout.end())
							m_timeout.erase(it2);
					}
				}
			}

			struct timespec now = {0, 0};
			if (clock_gettime(CLOCK_MONOTONIC, &now) < 0)
				abort();

			for(std::map<int, struct timespec>::iterator it = m_timeout.begin(); it != m_timeout.end(); it++)
			{
				if (Time::IsLess(&it->second, &now))
				{
					m_map[it->first]->DoTimeout(this);
					if (m_modified)
						goto skip_to_end;
					UpdateMap(it->first);
				}
			}

		} while(0);
skip_to_end:
		ReadControl();
	}
	free(fds);
}

<|endoftext|>


<commit_before>#include "FOXFIRE_Si70xx.h"

FOXFIRE_Si70xx::FOXFIRE_Si70xx()
{
	_addr = ID_SI7020;
}

boolean FOXFIRE_Si70xx::begin(void)
{
	Wire.begin();
	Wire.beginTransmission(addrI2C);
	return ( Wire.endTransmission(true) == 0 ? true : false );
}

float FOXFIRE_Si70xx::readTemperature(void)
{
	float temp;
	int32_t rawTemp;
	write8(CMD_MEASURE_TEMPERATURE_HOLD);

	rawTemp = read16(CMD_MEASURE_TEMPERATURE_HOLD);
	//temp = (rawTemp*175.72/65536) - 46.85; // Original
	temp = (rawTemp*175.72/65536) - 50.85; // Marcus' edit based on ODROID forum post, see notes directory in repo

	return temp;
}

float FOXFIRE_Si70xx::readHumidity(void)
{
	float humi;
	int32_t rawHumi;
	write8(CMD_MEASURE_HUMIDITY_HOLD);
	delay(10);
	rawHumi = read16(CMD_MEASURE_HUMIDITY_HOLD);
	delay(10);
	humi = (rawHumi*125.0/65536) - 6;

	return humi;
}

uint16_t FOXFIRE_Si70xx::read16(uint8_t addr)
{
	uint16_t ret;
	Wire.beginTransmission(_addr);
	Wire.write(addr);
	Wire.endTransmission();

	Wire.beginTransmission(_addr);
	Wire.requestFrom(_addr, 2);
	ret = Wire.read();
	ret <<= 8;
	ret |= Wire.read();
	Wire.endTransmission();

	return ret;
}

void FOXFIRE_Si70xx::write8(uint8_t addr)
{
	Wire.beginTransmission(_addr);
	Wire.write(addr);
	Wire.endTransmission();
}
<commit_msg>Bugfix<commit_after>#include "FOXFIRE_Si70xx.h"

FOXFIRE_Si70xx::FOXFIRE_Si70xx()
{
	_addr = ID_SI7020;
}

boolean FOXFIRE_Si70xx::begin(void)
{
	Wire.begin();
	Wire.beginTransmission(_addr);
	return ( Wire.endTransmission(true) == 0 ? true : false );
}

float FOXFIRE_Si70xx::readTemperature(void)
{
	float temp;
	int32_t rawTemp;
	write8(CMD_MEASURE_TEMPERATURE_HOLD);

	rawTemp = read16(CMD_MEASURE_TEMPERATURE_HOLD);
	//temp = (rawTemp*175.72/65536) - 46.85; // Original
	temp = (rawTemp*175.72/65536) - 50.85; // Marcus' edit based on ODROID forum post, see notes directory in repo

	return temp;
}

float FOXFIRE_Si70xx::readHumidity(void)
{
	float humi;
	int32_t rawHumi;
	write8(CMD_MEASURE_HUMIDITY_HOLD);
	delay(10);
	rawHumi = read16(CMD_MEASURE_HUMIDITY_HOLD);
	delay(10);
	humi = (rawHumi*125.0/65536) - 6;

	return humi;
}

uint16_t FOXFIRE_Si70xx::read16(uint8_t addr)
{
	uint16_t ret;
	Wire.beginTransmission(_addr);
	Wire.write(addr);
	Wire.endTransmission();

	Wire.beginTransmission(_addr);
	Wire.requestFrom(_addr, 2);
	ret = Wire.read();
	ret <<= 8;
	ret |= Wire.read();
	Wire.endTransmission();

	return ret;
}

void FOXFIRE_Si70xx::write8(uint8_t addr)
{
	Wire.beginTransmission(_addr);
	Wire.write(addr);
	Wire.endTransmission();
}
<|endoftext|>