<commit_before>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2018)

#ifndef DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH
#define DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH

#include <dune/geometry/quadraturerules.hh>

#include <dune/gdt/local/integrands/interfaces.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {

/**
 * For an explanation of the template arguments \sa LocalElementBilinearFormInterface
 */
template <class E,
          size_t t_r = 1,
          size_t t_rC = 1,
          class TR = double,
          class F = double,
          size_t a_r = t_r,
          size_t a_rC = t_rC,
          class AR = TR>
class LocalElementIntegralBilinearForm : public LocalElementBilinearFormInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>
{
  using ThisType = LocalElementIntegralBilinearForm<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;
  using BaseType = LocalElementBilinearFormInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;

public:
  using typename BaseType::D;
  using BaseType::d;
  using typename BaseType::LocalTestBasisType;
  using typename BaseType::LocalAnsatzBasisType;

  using IntegrandType = LocalBinaryElementIntegrandInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;

  LocalElementIntegralBilinearForm(const IntegrandType& integrand, const int over_integrate = 0)
    : BaseType(integrand.parameter_type())
    , integrand_(integrand.copy())
    , over_integrate_(over_integrate)
  {
  }

  LocalElementIntegralBilinearForm(const ThisType& other)
    : BaseType(other.parameter_type())
    , integrand_(other.integrand_->copy())
    , over_integrate_(other.over_integrate_)
  {
  }

  LocalElementIntegralBilinearForm(ThisType&& source) = default;

  std::unique_ptr<BaseType> copy() const override final
  {
    return std::make_unique<ThisType>(*this);
  }

  using BaseType::apply2;

  void apply2(const LocalTestBasisType& test_basis,
              const LocalAnsatzBasisType& ansatz_basis,
              DynamicMatrix<F>& result,
              const XT::Common::Parameter& param = {}) const override final
  {
    // prepare integand
    const auto& element = ansatz_basis.element();
    assert(test_basis.element() == element && "This must not happen!");
    integrand_->bind(element);
    // prepare storage
    const size_t rows = test_basis.size(param);
    const size_t cols = ansatz_basis.size(param);
    if (result.rows() < rows || result.cols() < cols)
      result.resize(rows, cols);
    result *= 0;
    // loop over all quadrature points
    const size_t integrand_order = integrand_->order(test_basis, ansatz_basis) + over_integrate_;
    for (const auto& quadrature_point : QuadratureRules<D, d>::rule(element.geometry().type(), integrand_order)) {
      const auto point_in_reference_element = quadrature_point.position();
      // integration factors
      const auto integration_factor = element.geometry().integrationElement(point_in_reference_element);
      const auto quadrature_weight = quadrature_point.weight();
      // evaluate the integrand
      integrand_->evaluate(test_basis, ansatz_basis, point_in_reference_element, integrand_values_, param);
      assert(integrand_values_.rows() >= rows && "This must not happen!");
      assert(integrand_values_.cols() >= cols && "This must not happen!");
      // compute integral
      for (size_t ii = 0; ii < rows; ++ii)
        for (size_t jj = 0; jj < cols; ++jj)
          result[ii][jj] += integrand_values_[ii][jj] * integration_factor * quadrature_weight;
    } // loop over all quadrature points
  } // ... apply(...)

private:
  mutable std::unique_ptr<IntegrandType> integrand_;
  const int over_integrate_;
  mutable DynamicMatrix<F> integrand_values_;
}; // class LocalElementIntegralBilinearForm

/**
 * For an explanation of the template arguments \sa LocalIntersectionBilinearFormInterface
 */
template <class I,
          size_t t_r = 1,
          size_t t_rC = 1,
          class TR = double,
          class F = double,
          size_t a_r = t_r,
          size_t a_rC = t_rC,
          class AR = TR>
class LocalIntersectionIntegralBilinearForm
    : public LocalIntersectionBilinearFormInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>
{
  using ThisType = LocalIntersectionIntegralBilinearForm<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;
  using BaseType = LocalIntersectionBilinearFormInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;

public:
  using typename BaseType::D;
  using BaseType::d;
  using typename BaseType::IntersectionType;
  using typename BaseType::LocalTestBasisType;
  using typename BaseType::LocalAnsatzBasisType;

  using IntegrandType = LocalQuaternaryIntersectionIntegrandInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;

  LocalIntersectionIntegralBilinearForm(const IntegrandType& integrand, const int over_integrate = 0)
    : BaseType(integrand.parameter_type())
    , integrand_(integrand.copy())
    , over_integrate_(over_integrate)
  {
  }

  LocalIntersectionIntegralBilinearForm(const ThisType& other)
    : BaseType(other.parameter_type())
    , integrand_(other.integrand_->copy())
    , over_integrate_(other.over_integrate_)
  {
  }

  LocalIntersectionIntegralBilinearForm(ThisType&& source) = default;

  std::unique_ptr<BaseType> copy() const override final
  {
    return std::make_unique<ThisType>(*this);
  }

  using BaseType::apply2;

  void apply2(const IntersectionType& intersection,
              const LocalTestBasisType& test_basis_inside,
              const LocalAnsatzBasisType& ansatz_basis_inside,
              const LocalTestBasisType& test_basis_outside,
              const LocalAnsatzBasisType& ansatz_basis_outside,
              DynamicMatrix<F>& result_in_in,
              DynamicMatrix<F>& result_in_out,
              DynamicMatrix<F>& result_out_in,
              DynamicMatrix<F>& result_out_out,
              const XT::Common::Parameter& param = {}) const override final
  {
    // prepare integand
    integrand_->bind(intersection);
    // prepare storage
    const size_t rows_in = test_basis_inside.size(param);
    const size_t rows_out = test_basis_outside.size(param);
    const size_t cols_in = ansatz_basis_inside.size(param);
    const size_t cols_out = ansatz_basis_outside.size(param);
    const auto ensure_size_and_clear = [](auto& m, const auto& r, const auto& c) {
      if (m.rows() < r || m.cols() < c)
        m.resize(r, c);
      m *= 0;
    };
    ensure_size_and_clear(result_in_in, rows_in, cols_in);
    ensure_size_and_clear(result_in_out, rows_in, cols_out);
    ensure_size_and_clear(result_out_in, rows_out, cols_in);
    ensure_size_and_clear(result_out_out, rows_out, cols_out);
    // loop over all quadrature points
    const size_t integrand_order =
        integrand_->order(test_basis_inside, ansatz_basis_inside, test_basis_outside, ansatz_basis_outside)
        + over_integrate_;
    for (const auto& quadrature_point :
         QuadratureRules<D, d - 1>::rule(intersection.geometry().type(), integrand_order)) {
      const auto point_in_reference_intersection = quadrature_point.position();
      // integration factors
      const auto integration_factor = intersection.geometry().integrationElement(point_in_reference_intersection);
      const auto quadrature_weight = quadrature_point.weight();
      // evaluate the integrand
      integrand_->evaluate(test_basis_inside,
                           ansatz_basis_inside,
                           test_basis_outside,
                           ansatz_basis_outside,
                           point_in_reference_intersection,
                           integrand_values_in_in_,
                           integrand_values_in_out_,
                           integrand_values_out_in_,
                           integrand_values_out_out_,
                           param);
      assert(integrand_values_in_in_.rows() >= rows_in && "This must not happen!");
      assert(integrand_values_in_in_.cols() >= cols_in && "This must not happen!");
      assert(integrand_values_in_out_.rows() >= rows_in && "This must not happen!");
      assert(integrand_values_in_out_.cols() >= cols_out && "This must not happen!");
      assert(integrand_values_out_in_.rows() >= rows_out && "This must not happen!");
      assert(integrand_values_out_in_.cols() >= cols_in && "This must not happen!");
      assert(integrand_values_out_out_.rows() >= rows_out && "This must not happen!");
      assert(integrand_values_out_out_.cols() >= cols_out && "This must not happen!");
      // compute integral
      for (size_t ii = 0; ii < rows_in; ++ii) {
        for (size_t jj = 0; jj < cols_in; ++jj)
          result_in_in[ii][jj] += integrand_values_in_in_[ii][jj] * integration_factor * quadrature_weight;
        for (size_t jj = 0; jj < cols_out; ++jj)
          result_in_out[ii][jj] += integrand_values_in_out_[ii][jj] * integration_factor * quadrature_weight;
      }
      for (size_t ii = 0; ii < rows_out; ++ii) {
        for (size_t jj = 0; jj < cols_in; ++jj)
          result_out_in[ii][jj] += integrand_values_out_in_[ii][jj] * integration_factor * quadrature_weight;
        for (size_t jj = 0; jj < cols_out; ++jj)
          result_out_out[ii][jj] += integrand_values_out_out_[ii][jj] * integration_factor * quadrature_weight;
      }
    } // loop over all quadrature points
  } // ... apply(...)

private:
  mutable std::unique_ptr<IntegrandType> integrand_;
  const int over_integrate_;
  mutable DynamicMatrix<F> integrand_values_in_in_;
  mutable DynamicMatrix<F> integrand_values_in_out_;
  mutable DynamicMatrix<F> integrand_values_out_in_;
  mutable DynamicMatrix<F> integrand_values_out_out_;
}; // class LocalIntersectionIntegralBilinearForm

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH
<commit_msg>update doc<commit_after>// This file is part of the dune-gdt project:
//   https://github.com/dune-community/dune-gdt
// Copyright 2010-2018 dune-gdt developers and contributors. All rights reserved.
// License: Dual licensed as BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)
//      or  GPL-2.0+ (http://opensource.org/licenses/gpl-license)
//          with "runtime exception" (http://www.dune-project.org/license.html)
// Authors:
//   Felix Schindler (2018)

#ifndef DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH
#define DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH

#include <dune/geometry/quadraturerules.hh>

#include <dune/gdt/local/integrands/interfaces.hh>

#include "interfaces.hh"

namespace Dune {
namespace GDT {

/**
 * For an explanation of the template arguments \sa LocalElementBilinearFormInterface
 */
template <class E,
          size_t t_r = 1,
          size_t t_rC = 1,
          class TR = double,
          class F = double,
          size_t a_r = t_r,
          size_t a_rC = t_rC,
          class AR = TR>
class LocalElementIntegralBilinearForm : public LocalElementBilinearFormInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>
{
  using ThisType = LocalElementIntegralBilinearForm<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;
  using BaseType = LocalElementBilinearFormInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;

public:
  using typename BaseType::D;
  using BaseType::d;
  using typename BaseType::LocalTestBasisType;
  using typename BaseType::LocalAnsatzBasisType;

  using IntegrandType = LocalBinaryElementIntegrandInterface<E, t_r, t_rC, TR, F, a_r, a_rC, AR>;

  LocalElementIntegralBilinearForm(const IntegrandType& integrand, const int over_integrate = 0)
    : BaseType(integrand.parameter_type())
    , integrand_(integrand.copy())
    , over_integrate_(over_integrate)
  {
  }

  LocalElementIntegralBilinearForm(const ThisType& other)
    : BaseType(other.parameter_type())
    , integrand_(other.integrand_->copy())
    , over_integrate_(other.over_integrate_)
  {
  }

  LocalElementIntegralBilinearForm(ThisType&& source) = default;

  std::unique_ptr<BaseType> copy() const override final
  {
    return std::make_unique<ThisType>(*this);
  }

  using BaseType::apply2;

  void apply2(const LocalTestBasisType& test_basis,
              const LocalAnsatzBasisType& ansatz_basis,
              DynamicMatrix<F>& result,
              const XT::Common::Parameter& param = {}) const override final
  {
    // prepare integand
    const auto& element = ansatz_basis.element();
    assert(test_basis.element() == element && "This must not happen!");
    integrand_->bind(element);
    // prepare storage
    const size_t rows = test_basis.size(param);
    const size_t cols = ansatz_basis.size(param);
    if (result.rows() < rows || result.cols() < cols)
      result.resize(rows, cols);
    result *= 0;
    // loop over all quadrature points
    const size_t integrand_order = integrand_->order(test_basis, ansatz_basis) + over_integrate_;
    for (const auto& quadrature_point : QuadratureRules<D, d>::rule(element.geometry().type(), integrand_order)) {
      const auto point_in_reference_element = quadrature_point.position();
      // integration factors
      const auto integration_factor = element.geometry().integrationElement(point_in_reference_element);
      const auto quadrature_weight = quadrature_point.weight();
      // evaluate the integrand
      integrand_->evaluate(test_basis, ansatz_basis, point_in_reference_element, integrand_values_, param);
      assert(integrand_values_.rows() >= rows && "This must not happen!");
      assert(integrand_values_.cols() >= cols && "This must not happen!");
      // compute integral
      for (size_t ii = 0; ii < rows; ++ii)
        for (size_t jj = 0; jj < cols; ++jj)
          result[ii][jj] += integrand_values_[ii][jj] * integration_factor * quadrature_weight;
    } // loop over all quadrature points
  } // ... apply(...)

private:
  mutable std::unique_ptr<IntegrandType> integrand_;
  const int over_integrate_;
  mutable DynamicMatrix<F> integrand_values_;
}; // class LocalElementIntegralBilinearForm

/**
 * For an explanation of the template arguments \sa LocalIntersectionBilinearFormInterface
 */
template <class I,
          size_t t_r = 1,
          size_t t_rC = 1,
          class TR = double,
          class F = double,
          size_t a_r = t_r,
          size_t a_rC = t_rC,
          class AR = TR>
class LocalIntersectionIntegralBilinearForm
    : public LocalIntersectionBilinearFormInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>
{
  using ThisType = LocalIntersectionIntegralBilinearForm<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;
  using BaseType = LocalIntersectionBilinearFormInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;

public:
  using typename BaseType::D;
  using BaseType::d;
  using typename BaseType::IntersectionType;
  using typename BaseType::LocalTestBasisType;
  using typename BaseType::LocalAnsatzBasisType;

  using IntegrandType = LocalQuaternaryIntersectionIntegrandInterface<I, t_r, t_rC, TR, F, a_r, a_rC, AR>;

  LocalIntersectionIntegralBilinearForm(const IntegrandType& integrand, const int over_integrate = 0)
    : BaseType(integrand.parameter_type())
    , integrand_(integrand.copy())
    , over_integrate_(over_integrate)
  {
  }

  LocalIntersectionIntegralBilinearForm(const ThisType& other)
    : BaseType(other.parameter_type())
    , integrand_(other.integrand_->copy())
    , over_integrate_(other.over_integrate_)
  {
  }

  LocalIntersectionIntegralBilinearForm(ThisType&& source) = default;

  std::unique_ptr<BaseType> copy() const override final
  {
    return std::make_unique<ThisType>(*this);
  }

  using BaseType::apply2;

  void apply2(const IntersectionType& intersection,
              const LocalTestBasisType& test_basis_inside,
              const LocalAnsatzBasisType& ansatz_basis_inside,
              const LocalTestBasisType& test_basis_outside,
              const LocalAnsatzBasisType& ansatz_basis_outside,
              DynamicMatrix<F>& result_in_in,
              DynamicMatrix<F>& result_in_out,
              DynamicMatrix<F>& result_out_in,
              DynamicMatrix<F>& result_out_out,
              const XT::Common::Parameter& param = {}) const override final
  {
    // prepare integand
    integrand_->bind(intersection);
    // prepare storage
    const size_t rows_in = test_basis_inside.size(param);
    const size_t rows_out = test_basis_outside.size(param);
    const size_t cols_in = ansatz_basis_inside.size(param);
    const size_t cols_out = ansatz_basis_outside.size(param);
    const auto ensure_size_and_clear = [](auto& m, const auto& r, const auto& c) {
      if (m.rows() < r || m.cols() < c)
        m.resize(r, c);
      m *= 0;
    };
    ensure_size_and_clear(result_in_in, rows_in, cols_in);
    ensure_size_and_clear(result_in_out, rows_in, cols_out);
    ensure_size_and_clear(result_out_in, rows_out, cols_in);
    ensure_size_and_clear(result_out_out, rows_out, cols_out);
    // loop over all quadrature points
    const size_t integrand_order =
        integrand_->order(test_basis_inside, ansatz_basis_inside, test_basis_outside, ansatz_basis_outside)
        + over_integrate_;
    for (const auto& quadrature_point :
         QuadratureRules<D, d - 1>::rule(intersection.geometry().type(), integrand_order)) {
      const auto point_in_reference_intersection = quadrature_point.position();
      // integration factors
      const auto integration_factor = intersection.geometry().integrationElement(point_in_reference_intersection);
      const auto quadrature_weight = quadrature_point.weight();
      // evaluate the integrand
      integrand_->evaluate(test_basis_inside,
                           ansatz_basis_inside,
                           test_basis_outside,
                           ansatz_basis_outside,
                           point_in_reference_intersection,
                           integrand_values_in_in_,
                           integrand_values_in_out_,
                           integrand_values_out_in_,
                           integrand_values_out_out_,
                           param);
      assert(integrand_values_in_in_.rows() >= rows_in && "This must not happen!");
      assert(integrand_values_in_in_.cols() >= cols_in && "This must not happen!");
      assert(integrand_values_in_out_.rows() >= rows_in && "This must not happen!");
      assert(integrand_values_in_out_.cols() >= cols_out && "This must not happen!");
      assert(integrand_values_out_in_.rows() >= rows_out && "This must not happen!");
      assert(integrand_values_out_in_.cols() >= cols_in && "This must not happen!");
      assert(integrand_values_out_out_.rows() >= rows_out && "This must not happen!");
      assert(integrand_values_out_out_.cols() >= cols_out && "This must not happen!");
      // compute integral
      for (size_t ii = 0; ii < rows_in; ++ii) {
        for (size_t jj = 0; jj < cols_in; ++jj)
          result_in_in[ii][jj] += integrand_values_in_in_[ii][jj] * integration_factor * quadrature_weight;
        for (size_t jj = 0; jj < cols_out; ++jj)
          result_in_out[ii][jj] += integrand_values_in_out_[ii][jj] * integration_factor * quadrature_weight;
      }
      for (size_t ii = 0; ii < rows_out; ++ii) {
        for (size_t jj = 0; jj < cols_in; ++jj)
          result_out_in[ii][jj] += integrand_values_out_in_[ii][jj] * integration_factor * quadrature_weight;
        for (size_t jj = 0; jj < cols_out; ++jj)
          result_out_out[ii][jj] += integrand_values_out_out_[ii][jj] * integration_factor * quadrature_weight;
      }
    } // loop over all quadrature points
  } // ... apply2(...)

private:
  mutable std::unique_ptr<IntegrandType> integrand_;
  const int over_integrate_;
  mutable DynamicMatrix<F> integrand_values_in_in_;
  mutable DynamicMatrix<F> integrand_values_in_out_;
  mutable DynamicMatrix<F> integrand_values_out_in_;
  mutable DynamicMatrix<F> integrand_values_out_out_;
}; // class LocalIntersectionIntegralBilinearForm

} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_LOCAL_BILINEAR_FORMS_INTEGRALS_HH
<|endoftext|>


<commit_before>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH

#include <type_traits>

#include <dune/common/typetraits.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/version.hh>

#include <dune/stuff/common/disable_warnings.hh>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif
#include <dune/common/typetraits.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/common/exceptions.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

// forward, to allow for specialization
template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class ContinuousLagrangeBase
{
  static_assert(AlwaysFalse<ImpTraits>::value, "Untested for these dimensions!");
};

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim>
class ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> : public SpaceInterface<ImpTraits>
{
  typedef SpaceInterface<ImpTraits> BaseType;
  typedef ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  virtual ~ContinuousLagrangeBase()
  {
  }

  using BaseType::compute_pattern;

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  }

  virtual std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    // get the basis and reference element
    const auto basis              = this->base_function_set(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

  virtual std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view()->indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view()->iend(entity);
    for (auto intersection_it = this->grid_view()->ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], this->tmp_basis_values_);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs(...)

private:
  template <class T, bool set_row>
  void compute_local_constraints(const SpaceInterface<T>& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, set_row>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.boundary_info());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.set_size(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows_);
      other.mapper().globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      const RangeFieldType zero(0);
      for (const size_t& localDirichletDofIndex : localDirichletDofs) {
        ret.global_row(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.global_col(jj) = tmpMappedCols_[jj];
          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
            ret.value(localRow, jj) = set_row ? RangeFieldType(1) : RangeFieldType(0);
          else
            ret.value(localRow, jj) = zero;
        }
        ++localRow;
      }
    } else {
      ret.set_size(0, 0);
    }
  } // ... compute_local_constraints(..., Dirichlet< ..., true >)

public:
  using BaseType::local_constraints;

  template <class C, class R>
  void local_constraints(const ThisType& /*other*/, const EntityType& /*entity*/,
                         ConstraintsInterface<C, R>& /*ret*/) const
  {
    static_assert(AlwaysFalse<C>::value, "Not implemented for arbitrary constraints!");
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, true>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

  virtual void local_constraints(const ThisType& other, const EntityType& entity,
                                 Constraints::Dirichlet<IntersectionType, RangeFieldType, false>& ret) const
  {
    compute_local_constraints(other, entity, ret);
  }

protected:
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class ContinuousLagrangeBase

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
<commit_msg>[spces.cg.base] fixed constraints handling<commit_after>// This file is part of the dune-gdt project:
//   http://users.dune-project.org/projects/dune-gdt
// Copyright holders: Felix Schindler
// License: BSD 2-Clause License (http://opensource.org/licenses/BSD-2-Clause)

#ifndef DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
#define DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH

#include <type_traits>

#include <dune/common/typetraits.hh>
#include <dune/common/dynvector.hh>
#include <dune/common/version.hh>

#include <dune/stuff/common/disable_warnings.hh>
#if DUNE_VERSION_NEWER(DUNE_COMMON, 3, 9) // EXADUNE
#include <dune/geometry/referenceelements.hh>
#else
#include <dune/geometry/genericreferenceelements.hh>
#endif
#include <dune/common/typetraits.hh>
#include <dune/stuff/common/reenable_warnings.hh>

#include <dune/stuff/common/exceptions.hh>

#include "../interface.hh"

namespace Dune {
namespace GDT {
namespace Spaces {

// forward, to allow for specialization
template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim, int rangeDimCols = 1>
class ContinuousLagrangeBase
{
  static_assert(AlwaysFalse<ImpTraits>::value, "Untested for these dimensions!");
};

template <class ImpTraits, int domainDim, class RangeFieldImp, int rangeDim>
class ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> : public SpaceInterface<ImpTraits>
{
  typedef SpaceInterface<ImpTraits> BaseType;
  typedef ContinuousLagrangeBase<ImpTraits, domainDim, RangeFieldImp, rangeDim, 1> ThisType;

  static constexpr RangeFieldImp compare_tolerance_ = 1e-13;

public:
  typedef ImpTraits Traits;

  using BaseType::polOrder;

  using typename BaseType::DomainFieldType;
  using BaseType::dimDomain;
  using typename BaseType::DomainType;

  typedef typename Traits::RangeFieldType RangeFieldType;
  using BaseType::dimRange;
  using BaseType::dimRangeCols;

  using typename BaseType::EntityType;
  using typename BaseType::IntersectionType;
  using typename BaseType::BoundaryInfoType;
  using typename BaseType::PatternType;

  virtual ~ContinuousLagrangeBase()
  {
  }

  using BaseType::compute_pattern;

  template <class G, class S>
  PatternType compute_pattern(const GridView<G>& local_grid_view, const SpaceInterface<S>& ansatz_space) const
  {
    return BaseType::compute_volume_pattern(local_grid_view, ansatz_space);
  }

  virtual std::vector<DomainType> lagrange_points(const EntityType& entity) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    // get the basis and reference element
    const auto basis              = this->base_function_set(entity);
    const auto& reference_element = ReferenceElements<DomainFieldType, dimDomain>::general(entity.type());
    const int num_vertices = reference_element.size(dimDomain);
    assert(num_vertices >= 0);
    assert(size_t(num_vertices) == basis.size() && "This should not happen with polOrder 1!");
    // prepare return vector
    std::vector<DomainType> local_vertices(num_vertices, DomainType(0));
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    // loop over all vertices
    for (int ii = 0; ii < num_vertices; ++ii) {
      // get the local coordinate of the iith vertex
      const auto local_vertex = reference_element.position(ii, dimDomain);
      // evaluate the basefunctionset
      basis.evaluate(local_vertex, this->tmp_basis_values_);
      // find the basis function that evaluates to one here (has to be only one!)
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          local_vertices[jj] = local_vertex;
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return local_vertices;
  } // ... lagrange_points(...)

  virtual std::set<size_t> local_dirichlet_DoFs(const EntityType& entity, const BoundaryInfoType& boundaryInfo) const
  {
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    // check
    assert(this->grid_view()->indexSet().contains(entity));
    // prepare
    std::set<size_t> localDirichletDofs;
    std::vector<DomainType> dirichlet_vertices;
    // get all dirichlet vertices of this entity, therefore
    // * loop over all intersections
    const auto intersection_it_end = this->grid_view()->iend(entity);
    for (auto intersection_it = this->grid_view()->ibegin(entity); intersection_it != intersection_it_end;
         ++intersection_it) {
      // only work on dirichlet ones
      const auto& intersection = *intersection_it;
      // actual dirichlet intersections + process boundaries for parallel runs
      if (boundaryInfo.dirichlet(intersection) || (!intersection.neighbor() && !intersection.boundary())) {
        // and get the vertices of the intersection
        const auto geometry = intersection.geometry();
        for (int cc = 0; cc < geometry.corners(); ++cc)
          dirichlet_vertices.emplace_back(entity.geometry().local(geometry.corner(cc)));
      } // only work on dirichlet ones
    } // loop over all intersections
    // find the corresponding basis functions
    const auto basis = this->base_function_set(entity);
    if (this->tmp_basis_values_.size() < basis.size())
      this->tmp_basis_values_.resize(basis.size());
    for (size_t cc = 0; cc < dirichlet_vertices.size(); ++cc) {
      // find the basis function that evaluates to one here (has to be only one!)
      basis.evaluate(dirichlet_vertices[cc], this->tmp_basis_values_);
      size_t ones     = 0;
      size_t zeros    = 0;
      size_t failures = 0;
      for (size_t jj = 0; jj < basis.size(); ++jj) {
        if (std::abs(this->tmp_basis_values_[jj][0] - RangeFieldType(1)) < compare_tolerance_) {
          localDirichletDofs.insert(jj);
          ++ones;
        } else if (std::abs(this->tmp_basis_values_[jj][0]) < compare_tolerance_)
          ++zeros;
        else
          ++failures;
      }
      assert(ones == 1 && zeros == (basis.size() - 1) && failures == 0 && "This must not happen for polOrder 1!");
    }
    return localDirichletDofs;
  } // ... local_dirichlet_DoFs(...)

  using BaseType::local_constraints;

  template <class S, class ConstraintsType>
  void local_constraints(const SpaceInterface<S>& /*other*/, const EntityType& /*entity*/,
                         ConstraintsType& /*ret*/) const
  {
    static_assert(AlwaysFalse<S>::value, "Not implemented for these constraints!");
  }

  template <class S>
  void local_constraints(const SpaceInterface<S>& other, const EntityType& entity,
                         Constraints::Dirichlet<IntersectionType, RangeFieldType>& ret) const
  {
    // check
    static_assert(polOrder == 1, "Not tested for higher polynomial orders!");
    if (dimRange != 1)
      DUNE_THROW(NotImplemented, "Does not work for higher dimensions");
    assert(this->grid_view()->indexSet().contains(entity));
    const std::set<size_t> localDirichletDofs = this->local_dirichlet_DoFs(entity, ret.boundary_info());
    const size_t numRows = localDirichletDofs.size();
    if (numRows > 0) {
      const size_t numCols = this->mapper().numDofs(entity);
      ret.set_size(numRows, numCols);
      this->mapper().globalIndices(entity, tmpMappedRows_);
      other.mapper().globalIndices(entity, tmpMappedCols_);
      size_t localRow = 0;
      for (const size_t& localDirichletDofIndex : localDirichletDofs) {
        ret.global_row(localRow) = tmpMappedRows_[localDirichletDofIndex];
        for (size_t jj = 0; jj < ret.cols(); ++jj) {
          ret.global_col(jj) = tmpMappedCols_[jj];
          if (tmpMappedCols_[jj] == tmpMappedRows_[localDirichletDofIndex])
            ret.value(localRow, jj) = ret.set_row() ? 1 : 0;
          else
            ret.value(localRow, jj) = 0;
        }
        ++localRow;
      }
    } else {
      ret.set_size(0, 0);
    }
  } // ... local_constraints(..., Constraints::Dirichlet< ... > ...)

protected:
  mutable Dune::DynamicVector<size_t> tmpMappedRows_;
  mutable Dune::DynamicVector<size_t> tmpMappedCols_;
}; // class ContinuousLagrangeBase

} // namespace Spaces
} // namespace GDT
} // namespace Dune

#endif // DUNE_GDT_SPACES_CONTINUOUSLAGRANGE_BASE_HH
<|endoftext|>


<commit_before>#ifndef _FILERROR_HXX_

namespace fileaccess {

// Error codes used to deliver the resulting exceptions
#define LOWEST_FREE_ERROR                               72

#define TASKHANDLER_NO_ERROR                            0
#define TASKHANDLER_UNSUPPORTED_COMMAND                 1
#define TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT   2
#define TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT   3
#define TASKHANDLING_WRONG_OPEN_ARGUMENT                4
#define TASKHANDLING_WRONG_DELETE_ARGUMENT              5
#define TASKHANDLING_WRONG_TRANSFER_ARGUMENT            6
#define TASKHANDLING_WRONG_INSERT_ARGUMENT              7

#define TASKHANDLING_UNSUPPORTED_OPEN_MODE              8

#define TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND      9
#define TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND    10

#define TASKHANDLING_OPEN_FILE_FOR_PAGING              11
#define TASKHANDLING_NOTCONNECTED_FOR_PAGING           12
#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING     13
#define TASKHANDLING_IOEXCEPTION_FOR_PAGING            14
#define TASKHANDLING_READING_FILE_FOR_PAGING           15

#define TASKHANDLING_OPEN_FOR_INPUTSTREAM              16
#define TASKHANDLING_OPEN_FOR_STREAM                   17
#define TASKHANDLING_OPEN_FOR_DIRECTORYLISTING         18

#define TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND   22
#define TASKHANDLING_NONAMESET_INSERT_COMMAND          23
#define TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND      24

#define TASKHANDLING_ANYOTHER_WRITE                    25   // not used
#define TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE        26
#define TASKHANDLING_NO_OPEN_FILE_FOR_WRITE            27
#define TASKHANDLING_NOTCONNECTED_FOR_WRITE            28
#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE      29
#define TASKHANDLING_IOEXCEPTION_FOR_WRITE             30
#define TASKHANDLING_FILEIOERROR_FOR_WRITE             31
#define TASKHANDLING_FILEIOERROR_FOR_NO_SPACE          71
#define TASKHANDLING_FILESIZE_FOR_WRITE                32
#define TASKHANDLING_INPUTSTREAM_FOR_WRITE             33
#define TASKHANDLING_NOREPLACE_FOR_WRITE               34
#define TASKHANDLING_ENSUREDIR_FOR_WRITE               35

#define TASKHANDLING_FOLDER_EXISTS_MKDIR               69
#define TASKHANDLING_INVALID_NAME_MKDIR                70
#define TASKHANDLING_CREATEDIRECTORY_MKDIR             36

#define TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE        38
#define TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE        39
#define TASKHANDLING_OPENDIRECTORY_FOR_REMOVE          40
#define TASKHANDLING_DELETEFILE_FOR_REMOVE             41
#define TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE        42
#define TASKHANDLING_FILETYPE_FOR_REMOVE               43
#define TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE   44
#define TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE     45

#define TASKHANDLING_TRANSFER_ACCESSINGROOT            46
#define TASKHANDLING_TRANSFER_INVALIDSCHEME            47
#define TASKHANDLING_TRANSFER_INVALIDURL               48
#define TASKHANDLING_TRANSFER_DESTFILETYPE             50
#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCE           51
#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT       52
#define TASKHANDLING_KEEPERROR_FOR_MOVE                53
#define TASKHANDLING_NAMECLASH_FOR_MOVE                54
#define TASKHANDLING_NAMECLASHMOVE_FOR_MOVE            55
#define TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE         56
#define TASKHANDLING_OVERWRITE_FOR_MOVE                57
#define TASKHANDLING_RENAME_FOR_MOVE                   58
#define TASKHANDLING_RENAMEMOVE_FOR_MOVE               59

#define TASKHANDLING_TRANSFER_BY_COPY_SOURCE           60
#define TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT       61
#define TASKHANDLING_KEEPERROR_FOR_COPY                62
#define TASKHANDLING_OVERWRITE_FOR_COPY                63
#define TASKHANDLING_RENAME_FOR_COPY                   64
#define TASKHANDLING_RENAMEMOVE_FOR_COPY               65
#define TASKHANDLING_NAMECLASH_FOR_COPY                66
#define TASKHANDLING_NAMECLASHMOVE_FOR_COPY            67
#define TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY         68

}

#endif

<commit_msg>INTEGRATION: CWS abi08 (1.7.34); FILE MERGED 2004/10/22 14:34:06 abi 1.7.34.1: #i31221,95725# flush now syncs, headers included<commit_after> /*************************************************************************
 *
 *  $RCSfile: filerror.hxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: obo $ $Date: 2004-11-17 09:55:33 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _FILERROR_HXX_

namespace fileaccess {

// Error codes used to deliver the resulting exceptions
#define LOWEST_FREE_ERROR                               72

#define TASKHANDLER_NO_ERROR                            0
#define TASKHANDLER_UNSUPPORTED_COMMAND                 1
#define TASKHANDLING_WRONG_SETPROPERTYVALUES_ARGUMENT   2
#define TASKHANDLING_WRONG_GETPROPERTYVALUES_ARGUMENT   3
#define TASKHANDLING_WRONG_OPEN_ARGUMENT                4
#define TASKHANDLING_WRONG_DELETE_ARGUMENT              5
#define TASKHANDLING_WRONG_TRANSFER_ARGUMENT            6
#define TASKHANDLING_WRONG_INSERT_ARGUMENT              7

#define TASKHANDLING_UNSUPPORTED_OPEN_MODE              8

#define TASKHANDLING_DELETED_STATE_IN_OPEN_COMMAND      9
#define TASKHANDLING_INSERTED_STATE_IN_OPEN_COMMAND    10

#define TASKHANDLING_OPEN_FILE_FOR_PAGING              11
#define TASKHANDLING_NOTCONNECTED_FOR_PAGING           12
#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_PAGING     13
#define TASKHANDLING_IOEXCEPTION_FOR_PAGING            14
#define TASKHANDLING_READING_FILE_FOR_PAGING           15

#define TASKHANDLING_OPEN_FOR_INPUTSTREAM              16
#define TASKHANDLING_OPEN_FOR_STREAM                   17
#define TASKHANDLING_OPEN_FOR_DIRECTORYLISTING         18

#define TASKHANDLING_NOFRESHINSERT_IN_INSERT_COMMAND   22
#define TASKHANDLING_NONAMESET_INSERT_COMMAND          23
#define TASKHANDLING_NOCONTENTTYPE_INSERT_COMMAND      24

#define TASKHANDLING_ANYOTHER_WRITE                    25   // not used
#define TASKHANDLING_NO_OPEN_FILE_FOR_OVERWRITE        26
#define TASKHANDLING_NO_OPEN_FILE_FOR_WRITE            27
#define TASKHANDLING_NOTCONNECTED_FOR_WRITE            28
#define TASKHANDLING_BUFFERSIZEEXCEEDED_FOR_WRITE      29
#define TASKHANDLING_IOEXCEPTION_FOR_WRITE             30
#define TASKHANDLING_FILEIOERROR_FOR_WRITE             31
#define TASKHANDLING_FILEIOERROR_FOR_NO_SPACE          71
#define TASKHANDLING_FILESIZE_FOR_WRITE                32
#define TASKHANDLING_INPUTSTREAM_FOR_WRITE             33
#define TASKHANDLING_NOREPLACE_FOR_WRITE               34
#define TASKHANDLING_ENSUREDIR_FOR_WRITE               35

#define TASKHANDLING_FOLDER_EXISTS_MKDIR               69
#define TASKHANDLING_INVALID_NAME_MKDIR                70
#define TASKHANDLING_CREATEDIRECTORY_MKDIR             36

#define TASKHANDLING_NOSUCHFILEORDIR_FOR_REMOVE        38
#define TASKHANDLING_VALIDFILESTATUS_FOR_REMOVE        39
#define TASKHANDLING_OPENDIRECTORY_FOR_REMOVE          40
#define TASKHANDLING_DELETEFILE_FOR_REMOVE             41
#define TASKHANDLING_DELETEDIRECTORY_FOR_REMOVE        42
#define TASKHANDLING_FILETYPE_FOR_REMOVE               43
#define TASKHANDLING_VALIDFILESTATUSWHILE_FOR_REMOVE   44
#define TASKHANDLING_DIRECTORYEXHAUSTED_FOR_REMOVE     45

#define TASKHANDLING_TRANSFER_ACCESSINGROOT            46
#define TASKHANDLING_TRANSFER_INVALIDSCHEME            47
#define TASKHANDLING_TRANSFER_INVALIDURL               48
#define TASKHANDLING_TRANSFER_DESTFILETYPE             50
#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCE           51
#define TASKHANDLING_TRANSFER_BY_MOVE_SOURCESTAT       52
#define TASKHANDLING_KEEPERROR_FOR_MOVE                53
#define TASKHANDLING_NAMECLASH_FOR_MOVE                54
#define TASKHANDLING_NAMECLASHMOVE_FOR_MOVE            55
#define TASKHANDLING_NAMECLASHSUPPORT_FOR_MOVE         56
#define TASKHANDLING_OVERWRITE_FOR_MOVE                57
#define TASKHANDLING_RENAME_FOR_MOVE                   58
#define TASKHANDLING_RENAMEMOVE_FOR_MOVE               59

#define TASKHANDLING_TRANSFER_BY_COPY_SOURCE           60
#define TASKHANDLING_TRANSFER_BY_COPY_SOURCESTAT       61
#define TASKHANDLING_KEEPERROR_FOR_COPY                62
#define TASKHANDLING_OVERWRITE_FOR_COPY                63
#define TASKHANDLING_RENAME_FOR_COPY                   64
#define TASKHANDLING_RENAMEMOVE_FOR_COPY               65
#define TASKHANDLING_NAMECLASH_FOR_COPY                66
#define TASKHANDLING_NAMECLASHMOVE_FOR_COPY            67
#define TASKHANDLING_NAMECLASHSUPPORT_FOR_COPY         68

}

#endif

<|endoftext|>


<commit_before>/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * @author Intel, Mikhail Y. Fursov
 * @version $Revision: 1.10.24.4 $
 *
 */

//
// Decides whether or not to "accept" a method based on an environment
// variable and an optional file.
//
// Assume FOO is the environment variable that gives the information.
//
// FOO=file:range_list
//
// "file" is the name of the file that contains the list of all
// methods.
//
// If "range_list" is empty, no methods are jitted, and the list of
// methods is printed to "file".
//
// "range_list" contains a list of methods and ranges, separated by
// commas.  A single number denotes a one-based index into the method
// list.  A range (start-end) denotes a range of indices into the
// method list.
// The string "class::method" denotes a specific method.
// "class::" matches all methods of the given class.
// "method" (not containing a colon) matches that method of
// any class.
// A "-" preceding a list element means to exclude that method(s) from
// the list of methods to jit.
//
// FOO=c:\tmp\mlist:  (jit nothing, create a method list file)
// FOO=mlist:  (jit nothing, create a file in the current directory)
// FOO=list:1-1000 (jit the first 1000 methods from file "list")
// FOO=java/lang/Object::<init>  (jit just a single method)
// FOO=-<init>,-<clinit> (jit all but initializers)
// FOO=list:1-100,-50-60 (jit methods 1-49 and 61-100)
// FOO=(I)  (jit only methods with a single int in the signature)
// FOO=(Ljava/lang/Object;)
// FOO=(L;)  (jit only methods with a single class ptr in signature)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "VMInterface.h"
#include "Type.h"
#include "methodtable.h"

namespace Jitrino {

#define CLASS_METHOD_SEPARATOR_CHAR ':'
#define DESCRIPTOR_START_CHAR '('
#define DESCRIPTOR_END_CHAR ')'
#define REF_START_CHAR 'L'
#define REF_END_CHAR ';'
#define FILE_CHAR ':'

char* strdup(MemoryManager& mm , const char* str) {
    size_t len  = strlen(str);
    char* newstr = new (mm) char[len+1];
    strncpy(newstr, str, len);
    newstr[len]='\0';
    return newstr;
}

void Method_Table::make_filename(char *str, int len)
{
    _method_file = new (_mm) char[1+len];
    strncpy(_method_file, str, len);
    _method_file[len] = '\0';
}

// Decides whether two signatures match.  The strictest test is
// strcmp(), but we are more lenient by allowing "L;" instead of,
// e.g., "Ljava/lang/Object;".  Anything following the ')' (i.e.,
// the return value) of either string is ignored.
static bool matching_signature(const char *lenient, const char *exact)
{
    int i, j;
    int len1 = (int) strlen(lenient);
    int len2 = (int) strlen(exact);
    for (i=j=0; i<len1 && j<len2; i++,j++)
    {
        if (lenient[i] != exact[j])
            return false;
        if (lenient[i] == DESCRIPTOR_END_CHAR)
            return true;
        if (lenient[i] == REF_START_CHAR)
        {
            i++; j++;
            if (lenient[i] == REF_END_CHAR) // accept any classname
            {
                while (j < len2 && exact[j] != REF_END_CHAR)
                    j ++;
            }
            else
            {
                while (i < len1 && j < len2 && lenient[i] != REF_END_CHAR)
                {
                    if (lenient[i] != exact[j])
                        return false;
                    i++; j++;
                }
            }
        }
    }
    return (i == len1 && j == len2);
}

// [class::][method][(signature)]
static void parse_method_string(MemoryManager& _mm, char *str, Method_Table::method_record *rec)
{
    int i;
    int len = (int) strlen(str);

    rec->class_name = rec->method_name = rec->signature = NULL;
    if (len == 0)
        return;

    bool is_at_class_method_separator = false;
    // Search forward for CLASS_METHOD_SEPARATOR_CHAR or DESCRIPTOR_START_CHAR
    for (i=0; i<len; i++)
    {
        is_at_class_method_separator =
            (str[i] == CLASS_METHOD_SEPARATOR_CHAR && str[i+1] == CLASS_METHOD_SEPARATOR_CHAR);
        if (is_at_class_method_separator)
        {
            i ++; // make i point to the last character of the separator
            break;
        }
        if (str[i] == DESCRIPTOR_START_CHAR)
            break;
    }
    if (i >= len) // no class or descriptor
    {
        if (str[0] != '\0')
            rec->method_name = strdup(_mm, str);
        return;
    }
    if (is_at_class_method_separator)
    {
        // extract the class
        rec->class_name = new (_mm) char[i-1 + 1];
        strncpy(rec->class_name, str, i-1);
        rec->class_name[i-1] = '\0';
        // skip ahead to the descriptor
        str += (i+1);
        len -= (i+1);
        for (i=0; i<len; i++)
        {
            if (str[i] == DESCRIPTOR_START_CHAR)
                break;
        }
        if (i >= len) // no descriptor
        {
            if (str[0] != '\0')
                rec->method_name = strdup(_mm, str);
            return;
        }
    }
    // we're at the start of the signature, with the method name preceding
    if (i > 0)
    {
        rec->method_name = new (_mm) char[i+1];
        strncpy(rec->method_name, str, i);
        rec->method_name[i] = '\0';
    }
    rec->signature = strdup(_mm, &str[i]);
}

// Returns true on success, false on failure
bool Method_Table::read_method_table()
{
    char buf[1000];
    FILE *file = fopen(_method_file, "r");
    if (file == NULL)
    {
        fprintf(stderr, "Couldn't open method table file %s\n", _method_file);
        return false;
    }
    while (fgets(buf, 1000, file) != NULL)
    {
        // strip out any newline at the end
        int buflen = (int) strlen(buf);
        if (buf[buflen-1] == '\n')
            buf[buflen-1] = '\0';
        if (buf[buflen-2] == '\r') // file generated on NT and used on Linux,
            buf[buflen-2] = '\0';    // this case happens
        method_record* rec = new (_mm) method_record();
        parse_method_string(_mm, buf, rec);
        _method_table.push_back(rec);
    }
    fclose(file);
    return true;
}

static bool matches(Method_Table::method_record *test_entry,
                    const char *class_name, const char *method_name, const char *signature)
{
    if (test_entry->class_name != NULL && strcmp(test_entry->class_name, class_name) != 0)
        return false;
    if (test_entry->method_name != NULL && strcmp(test_entry->method_name, method_name) != 0)
        return false;
    if (test_entry->signature != NULL && !matching_signature(test_entry->signature, signature))
        return false;
    return true;
}

void Method_Table::init(const char *default_envvar, const char *envvarname)
{

    char *rangestr;

    char *envvar = (char*)default_envvar;

    if (envvar == NULL || envvar[0] == '\0')
    {
        return;
    }
    // strip away double-quote characters
    if (envvar[0] == '"')
        envvar ++;
    if (envvar[strlen(envvar)-1] == '"')
        envvar[strlen(envvar)-1] = '\0';

    int evlen = (int) strlen(envvar);
    int i;
    for (i=evlen-1; i>=0; i--)
    {
        if (FILE_CHAR == CLASS_METHOD_SEPARATOR_CHAR)
        {
            // If we are looking at FILE_CHAR and the character to the left is not FILE_CHAR,
            // then this is a legitimate FILE_CHAR.
            if (envvar[i] == FILE_CHAR && (i == 0 || envvar[i-1] != FILE_CHAR))
                break;
            // If we are looking at FILE_CHAR and the character to the left is also FILE_CHAR,
            // then we are actually looking at a double CLASS_METHOD_SEPARATOR_CHAR, which
            // we should skip over.
            if (envvar[i] == FILE_CHAR && i != 0 && envvar[i-1] == FILE_CHAR)
                i --;
        } else {
            if (envvar[i] == FILE_CHAR)
                break;
        }
    }
    if (i == 0) // no legitimate filename given
    {
        return;
    }
    else if (i == evlen-1) // filename only, no ranges
    {
        make_filename(envvar, evlen-1);
        _dump_to_file = true;
        FILE *file = fopen(_method_file, "w");
        if (file == NULL)
        {
            fprintf(stderr, "Couldn't truncate method table file %s\n",
                _method_file);
            _dump_to_file = false;
        }
        else
            fclose(file);
        return;
    }
    else if (i >= 0) // filename plus ranges
    {
        make_filename(envvar, i);
        rangestr = &envvar[i+1];
        read_method_table();
    }
    else // no filename, only ranges
    {
        rangestr = envvar;
    }
    // parse the ranges in rangestr
    for (rangestr=strtok(rangestr, ","); rangestr!=NULL; rangestr=strtok(NULL, ","))
    {
        int opposite = 0;
        int start, end;
        if (rangestr[0] == '-')
        {
            opposite = 1;
            rangestr ++;
        }
        else
        {
            _default_decision = mt_rejected;
        }
        if (rangestr[0] >= '0' && rangestr[0] <= '9') {
            // look for a range of numbers
            sscanf(rangestr, "%d", &start);
            end = start;
            while (rangestr[0] != '\0' && rangestr[0] != '-') {
                rangestr ++;
            }
            if (rangestr[0] == '-') {
                sscanf(rangestr+1, "%d", &end);
            }
            start --;
            if (start < 0) {
                start = 0;
            }
            end --;
            for (i=start; i<=end && i<(int)_method_table.size(); i++) {
                _method_table[i]->decision = (opposite ? mt_rejected : mt_accepted);
            }
        } else {
            method_record* rec = new (_mm) method_record();
            parse_method_string(_mm, rangestr, rec);
            rec->decision = (opposite ? mt_rejected : mt_accepted);
            _decision_table.push_back(rec);
        }
    }

    // change all "undecided" to default decision
    for (i=0; i<(int)_method_table.size(); i++) {
        if (_method_table[i]->decision == mt_undecided) {
            _method_table[i]->decision = _default_decision;
        }
    }

}

Method_Table::Method_Table(MemoryManager& memManager,
                           const char *default_envvar,
                           const char *envvarname,
                           bool accept_by_default):
  _mm(memManager),
  _method_table     (_mm),
  _decision_table   (_mm),
  _dump_to_file     (false),
  _method_file      (NULL)
{
    _default_decision = accept_by_default ? mt_accepted : mt_rejected;
    init(default_envvar, envvarname);
}

bool Method_Table::accept_this_method(MethodDesc &md) {
    const char* classname = md.getParentType()->getName();
    const char *methodname = md.getName();
    const char *signature = md.getSignatureString();

    return accept_this_method(classname, methodname, signature);
}

bool Method_Table::accept_this_method(const char* classname, const char *methodname, const char *signature)
{
    int i;

    if (_dump_to_file)
    {
        FILE *file = fopen(_method_file, "a");
        if (file != NULL)
        {
            fprintf(file, "%s%c%c%s%s\n", classname, CLASS_METHOD_SEPARATOR_CHAR, CLASS_METHOD_SEPARATOR_CHAR, methodname, signature);
            fclose(file);
        }
        return false;
    }

    // First look through the decision_table strings.
    for (i=0; i<(int)_decision_table.size(); i++)
    {
        if (matches(_decision_table[i], classname, methodname, signature)) {
            return (_decision_table[i]->decision == mt_accepted);
        }
    }

    // Then look through the method table.
    for (i=0; i<(int)_method_table.size(); i++) {
        if ((_method_table[i]->class_name==NULL || !strcmp(_method_table[i]->class_name, classname)) &&
            (_method_table[i]->method_name==NULL || !strcmp(_method_table[i]->method_name, methodname)) &&
            (_method_table[i]->signature==NULL || matching_signature(_method_table[i]->signature, signature)))
        {
            return (_method_table[i]->decision == mt_accepted);
        }
    }
    return (_default_decision == mt_rejected ? false : true);
}

bool Method_Table::is_in_list_generation_mode() {
    return _dump_to_file;
}

void Method_Table::add_method_record(const char* className, const char* methodName, const char* signature, Method_Table::Decision decision, bool copyVals) {
    method_record* rec = new (_mm) method_record();
    if (copyVals) {
        size_t len = strlen(className)+1; //+1 == '\0' char
        rec->class_name = new (_mm) char[len];
        strncpy(rec->class_name, className, len);

        len = strlen(methodName)+1; //+1 == '\0' char
        rec->method_name= new (_mm) char[len];
        strncpy(rec->method_name, methodName, len);

        len = strlen(signature)+1; //+1 == '\0' char
        rec->signature= new (_mm) char[len];
        strncpy(rec->signature, signature, len);
    } else {
        rec->class_name = (char*)className;
        rec->method_name = (char*)methodName;
        rec->signature = (char*)signature;
    }
    rec->decision = decision;
    _method_table.push_back(rec);
}

} //namespace Jitrino

<commit_msg>Fixed HARMONY-5124 [drlvm][jitrino] Bugs in the implementation of Method_Table class<commit_after>/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/**
 * @author Intel, Mikhail Y. Fursov
 * @version $Revision: 1.10.24.4 $
 *
 */

//
// Decides whether or not to "accept" a method based on an environment
// variable and an optional file.
//
// Assume FOO is the environment variable that gives the information.
//
// FOO=file:range_list
//
// "file" is the name of the file that contains the list of all
// methods.
//
// If "range_list" is empty, no methods are jitted, and the list of
// methods is printed to "file".
//
// "range_list" contains a list of methods and ranges, separated by
// commas.  A single number denotes a one-based index into the method
// list.  A range (start-end) denotes a range of indices into the
// method list.
// The string "class::method" denotes a specific method.
// "class::" matches all methods of the given class.
// "method" (not containing a colon) matches that method of
// any class.
// A "-" preceding a list element means to exclude that method(s) from
// the list of methods to jit.
//
// FOO=c:\tmp\mlist:  (jit nothing, create a method list file)
// FOO=mlist:  (jit nothing, create a file in the current directory)
// FOO=list:1-1000 (jit the first 1000 methods from file "list")
// FOO=java/lang/Object::<init>  (jit just a single method)
// FOO=-<init>,-<clinit> (jit all but initializers)
// FOO=list:1-100,-50-60 (jit methods 1-49 and 61-100)
// FOO=(I)  (jit only methods with a single int in the signature)
// FOO=(Ljava/lang/Object;)
// FOO=(L;)  (jit only methods with a single class ptr in signature)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "VMInterface.h"
#include "Type.h"
#include "methodtable.h"

namespace Jitrino {

#define CLASS_METHOD_SEPARATOR_CHAR ':'
#define DESCRIPTOR_START_CHAR '('
#define DESCRIPTOR_END_CHAR ')'
#define REF_START_CHAR 'L'
#define REF_END_CHAR ';'
#define FILE_CHAR ':'

char* strdup(MemoryManager& mm , const char* str) {
    size_t len  = strlen(str);
    char* newstr = new (mm) char[len+1];
    strncpy(newstr, str, len);
    newstr[len]='\0';
    return newstr;
}

void Method_Table::make_filename(char *str, int len)
{
    _method_file = new (_mm) char[1+len];
    strncpy(_method_file, str, len);
    _method_file[len] = '\0';
}

// Decides whether two signatures match.  The strictest test is
// strcmp(), but we are more lenient by allowing "L;" instead of,
// e.g., "Ljava/lang/Object;".  Anything following the ')' (i.e.,
// the return value) of either string is ignored.
static bool matching_signature(const char *lenient, const char *exact)
{
    int i, j;
    int len1 = (int) strlen(lenient);
    int len2 = (int) strlen(exact);
    for (i=j=0; i<len1 && j<len2; i++,j++)
    {
        if (lenient[i] != exact[j])
            return false;
        if (lenient[i] == DESCRIPTOR_END_CHAR)
            return true;
        if (lenient[i] == REF_START_CHAR)
        {
            i++; j++;
            if (lenient[i] == REF_END_CHAR) // accept any classname
            {
                while (j < len2 && exact[j] != REF_END_CHAR)
                    j ++;
            }
            else
            {
                while (i < len1 && j < len2 && lenient[i] != REF_END_CHAR)
                {
                    if (lenient[i] != exact[j])
                        return false;
                    i++; j++;
                }
            }
        }
    }
    return (i == len1 && j == len2);
}

// [class::][method][(signature)]
static void parse_method_string(MemoryManager& _mm, char *str, Method_Table::method_record *rec)
{
    int i;
    int len = (int) strlen(str);

    rec->class_name = rec->method_name = rec->signature = NULL;
    if (len == 0)
        return;

    bool is_at_class_method_separator = false;
    // Search forward for CLASS_METHOD_SEPARATOR_CHAR or DESCRIPTOR_START_CHAR
    for (i=0; i<len; i++)
    {
        is_at_class_method_separator =
            (str[i] == CLASS_METHOD_SEPARATOR_CHAR && str[i+1] == CLASS_METHOD_SEPARATOR_CHAR);
        if (is_at_class_method_separator)
        {
            i ++; // make i point to the last character of the separator
            break;
        }
        if (str[i] == DESCRIPTOR_START_CHAR)
            break;
    }
    if (i >= len) // no class or descriptor
    {
        if (str[0] != '\0')
            rec->method_name = strdup(_mm, str);
        return;
    }
    if (is_at_class_method_separator)
    {
        // extract the class
        rec->class_name = new (_mm) char[i-1 + 1];
        strncpy(rec->class_name, str, i-1);
        rec->class_name[i-1] = '\0';
        // skip ahead to the descriptor
        str += (i+1);
        len -= (i+1);
        for (i=0; i<len; i++)
        {
            if (str[i] == DESCRIPTOR_START_CHAR)
                break;
        }
        if (i >= len) // no descriptor
        {
            if (str[0] != '\0')
                rec->method_name = strdup(_mm, str);
            return;
        }
    }
    // we're at the start of the signature, with the method name preceding
    if (i > 0)
    {
        rec->method_name = new (_mm) char[i+1];
        strncpy(rec->method_name, str, i);
        rec->method_name[i] = '\0';
    }
    rec->signature = strdup(_mm, &str[i]);
}

// Returns true on success, false on failure
bool Method_Table::read_method_table()
{
    const size_t max_size = 1000;
    char buf[max_size];
    FILE *file = fopen(_method_file, "r");
    if (file == NULL)
    {
        fprintf(stderr, "Couldn't open method table file %s\n", _method_file);
        return false;
    }
    while (fgets(buf, max_size, file) != NULL)
    {
        // strip out any newline at the end
        int buflen = (int) strlen(buf);
        if (buf[buflen-1] == '\n')
            buf[buflen-1] = '\0';
        if (buf[buflen-2] == '\r') // file generated on NT and used on Linux,
            buf[buflen-2] = '\0';    // this case happens
        method_record* rec = new (_mm) method_record();
        parse_method_string(_mm, buf, rec);
        _method_table.push_back(rec);
    }
    fclose(file);
    return true;
}

static bool matches(Method_Table::method_record *test_entry,
                    const char *class_name, const char *method_name, const char *signature)
{
    if (test_entry->class_name != NULL && strcmp(test_entry->class_name, class_name) != 0)
        return false;
    if (test_entry->method_name != NULL && strcmp(test_entry->method_name, method_name) != 0)
        return false;
    if (test_entry->signature != NULL && !matching_signature(test_entry->signature, signature))
        return false;
    return true;
}

void Method_Table::init(const char *default_envvar, const char *envvarname)
{
    if (default_envvar == NULL || default_envvar[0] == '\0')
    {
        return;
    }

    char *rangestr;
    char *envvar = strdup(_mm, default_envvar);

   // strip away double-quote characters
    if (envvar[0] == '"') {
        envvar ++;
    }
    int evlen = (int) strlen(envvar);
    if (evlen > 0 && envvar[evlen-1] == '"') {
        envvar[--evlen] = '\0';
    }
    if (evlen == 0) {
        return;
    }
    int i;
    for (i=evlen-1; i>=0; i--)
    {
        if (FILE_CHAR == CLASS_METHOD_SEPARATOR_CHAR)
        {
            // If we are looking at FILE_CHAR and the character to the left is not FILE_CHAR,
            // then this is a legitimate FILE_CHAR.
            if (envvar[i] == FILE_CHAR && (i == 0 || envvar[i-1] != FILE_CHAR))
                break;
            // If we are looking at FILE_CHAR and the character to the left is also FILE_CHAR,
            // then we are actually looking at a double CLASS_METHOD_SEPARATOR_CHAR, which
            // we should skip over.
            if (envvar[i] == FILE_CHAR && i != 0 && envvar[i-1] == FILE_CHAR)
                i --;
        } else {
            if (envvar[i] == FILE_CHAR)
                break;
        }
    }
    if (i == 0) // no legitimate filename given
    {
        return;
    }
    else if (i == evlen-1) // filename only, no ranges
    {
        make_filename(envvar, evlen-1);
        _dump_to_file = true;
        FILE *file = fopen(_method_file, "w");
        if (file == NULL)
        {
            fprintf(stderr, "Couldn't truncate method table file %s\n",
                _method_file);
            _dump_to_file = false;
        }
        else
            fclose(file);
        return;
    }
    else if (i >= 0) // filename plus ranges
    {
        make_filename(envvar, i);
        rangestr = &envvar[i+1];
        read_method_table();
    }
    else // no filename, only ranges
    {
        rangestr = envvar;
    }
    // parse the ranges in rangestr
    for (rangestr=strtok(rangestr, ","); rangestr!=NULL; rangestr=strtok(NULL, ","))
    {
        int opposite = 0;
        int start, end;
        if (rangestr[0] == '-')
        {
            opposite = 1;
            rangestr ++;
        }
        else
        {
            _default_decision = mt_rejected;
        }
        if (rangestr[0] >= '0' && rangestr[0] <= '9') {
            // look for a range of numbers
            sscanf(rangestr, "%d", &start);
            end = start;
            while (rangestr[0] != '\0' && rangestr[0] != '-') {
                rangestr ++;
            }
            if (rangestr[0] == '-') {
                sscanf(rangestr+1, "%d", &end);
            }
            start --;
            if (start < 0) {
                start = 0;
            }
            end --;
            for (i=start; i<=end && i<(int)_method_table.size(); i++) {
                _method_table[i]->decision = (opposite ? mt_rejected : mt_accepted);
            }
        } else {
            method_record* rec = new (_mm) method_record();
            parse_method_string(_mm, rangestr, rec);
            rec->decision = (opposite ? mt_rejected : mt_accepted);
            _decision_table.push_back(rec);
        }
    }

    // change all "undecided" to default decision
    for (i=0; i<(int)_method_table.size(); i++) {
        if (_method_table[i]->decision == mt_undecided) {
            _method_table[i]->decision = _default_decision;
        }
    }

}

Method_Table::Method_Table(MemoryManager& memManager,
                           const char *default_envvar,
                           const char *envvarname,
                           bool accept_by_default):
  _mm(memManager),
  _method_table     (_mm),
  _decision_table   (_mm),
  _dump_to_file     (false),
  _method_file      (NULL)
{
    _default_decision = accept_by_default ? mt_accepted : mt_rejected;
    init(default_envvar, envvarname);
}

bool Method_Table::accept_this_method(MethodDesc &md) {
    const char* classname = md.getParentType()->getName();
    const char *methodname = md.getName();
    const char *signature = md.getSignatureString();

    return accept_this_method(classname, methodname, signature);
}

bool Method_Table::accept_this_method(const char* classname, const char *methodname, const char *signature)
{
    int i;

    if (_dump_to_file)
    {
        FILE *file = fopen(_method_file, "a");
        if (file != NULL)
        {
            fprintf(file, "%s%c%c%s%s\n", classname, CLASS_METHOD_SEPARATOR_CHAR, CLASS_METHOD_SEPARATOR_CHAR, methodname, signature);
            fclose(file);
        }
        return false;
    }

    // First look through the decision_table strings.
    for (i=0; i<(int)_decision_table.size(); i++)
    {
        if (matches(_decision_table[i], classname, methodname, signature)) {
            return (_decision_table[i]->decision == mt_accepted);
        }
    }

    // Then look through the method table.
    for (i=0; i<(int)_method_table.size(); i++) {
        if ((_method_table[i]->class_name==NULL || !strcmp(_method_table[i]->class_name, classname)) &&
            (_method_table[i]->method_name==NULL || !strcmp(_method_table[i]->method_name, methodname)) &&
            (_method_table[i]->signature==NULL || matching_signature(_method_table[i]->signature, signature)))
        {
            return (_method_table[i]->decision == mt_accepted);
        }
    }
    return (_default_decision == mt_rejected ? false : true);
}

bool Method_Table::is_in_list_generation_mode() {
    return _dump_to_file;
}

void Method_Table::add_method_record(const char* className, const char* methodName, const char* signature, Method_Table::Decision decision, bool copyVals) {
    method_record* rec = new (_mm) method_record();
    if (copyVals) {
        size_t len = strlen(className)+1; //+1 == '\0' char
        rec->class_name = new (_mm) char[len];
        strncpy(rec->class_name, className, len);

        len = strlen(methodName)+1; //+1 == '\0' char
        rec->method_name= new (_mm) char[len];
        strncpy(rec->method_name, methodName, len);

        len = strlen(signature)+1; //+1 == '\0' char
        rec->signature= new (_mm) char[len];
        strncpy(rec->signature, signature, len);
    } else {
        rec->class_name = (char*)className;
        rec->method_name = (char*)methodName;
        rec->signature = (char*)signature;
    }
    rec->decision = decision;
    _method_table.push_back(rec);
}

} //namespace Jitrino

<|endoftext|>


<commit_before>/*
MIT License
Copyright (c) 2018 Arlen Keshabyan (arlen.albert@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <algorithm>
#include <exception>
#include <iostream>
#include <chrono>
#include <ctime>
#include <map>
#include <memory>
#include <csignal>
#include <string>
#include <string_view>
#include <sstream>
#include "http_resource_manager.hpp"
#include "utilities.hpp"

using namespace std::string_literals;

std::condition_variable cv;

void signint_handler(int) { cv.notify_all(); }

using namespace nstd::net;

int main(int argc, char *argv[])
{
    using M = http_request_parser::http_method_id;
    using S = http_resource_manager::response::http_status_codes;

    http_resource_manager mgr;

    mgr.add_route(M::GET, R"(^\/services\/([^/]+)\/([^/]+))", [](auto &&req) // /services/v8/user
	{
		http_resource_manager::response resp { S::OK };
		std::string service_name { req->match[2] };

		resp.content << std::string("
Service: ") + service_name + "
";
		resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
	});

    mgr.add_route(M::GET, R"(^\/$)", [](auto &&req) // /
	{
        auto full_path { req->manager->get_root_path() };

        full_path += "/index.html"s;

        std::cout << full_path << std::endl;

        if (fs::exists(full_path) && fs::is_regular_file(full_path))
        {
            http_resource_manager::response resp { S::TemporaryRedirect };

            std::cout << full_path << std::endl;

            resp.add_header("Location", "/index.html").send_response(req->client);

            std::cout << full_path << std::endl;
        }
        else
        {
            http_resource_manager::response resp { S::OK };

            resp.content << "
Index
";
            resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
        }
	});

    mgr.add_route(M::GET, R"(^\/time$)", [](auto &&req) // /time
	{
		http_resource_manager::response resp { S::OK };
		auto cur_time { std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) };

		resp.content << std::string("
") + std::ctime(&cur_time) + "
";
		resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
	});

    mgr.add_route(M::GET, R"(^\/throw$)", [](auto &&req) // /throw
	{
		throw std::runtime_error("Test exception");
	});

    mgr.add_status_handler(http_resource_manager::response::http_status_codes::NotFound, [](auto &&req)
	{
        auto full_path { req->manager->get_root_path() / ("."s + req->resource) };

        if (fs::exists(full_path) && fs::is_regular_file(full_path))
        {
            http_resource_manager::response resp { S::OK };
            auto data { nstd::utilities::read_file_content(full_path) };

            resp.content.write(std::data(data), std::size(data));
            resp.add_content_type_header(fs::path { full_path }.extension().string().substr(1)).add_header("Connection", "Closed").send_response(req->client);
        }
        else
        {
            http_resource_manager::response resp { S::NotFound };

            resp.content << "<title>Not Found</title>
404 Not Found
";
            resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
        }
	});

    std::cout << "Press Ctrl+C to exit..." << std::endl << std::endl;

    mgr.start("127.0.0.1", 3001);

    std::signal(SIGINT, &signint_handler);

    std::mutex mtx;
    std::unique_lock<std::mutex> lock(mtx);

    cv.wait(lock);

    return 0;
}
<commit_msg>small refinements<commit_after>/*
MIT License
Copyright (c) 2018 Arlen Keshabyan (arlen.albert@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include <algorithm>
#include <exception>
#include <iostream>
#include <chrono>
#include <ctime>
#include <map>
#include <memory>
#include <csignal>
#include <string>
#include <string_view>
#include <sstream>
#include "http_resource_manager.hpp"
#include "utilities.hpp"

using namespace std::string_literals;

std::condition_variable cv;

void signint_handler(int) { cv.notify_all(); }

using namespace nstd::net;

int main(int argc, char *argv[])
{
    using M = http_request_parser::http_method_id;
    using S = http_resource_manager::response::http_status_codes;

    http_resource_manager mgr;

    mgr.add_route(M::GET, R"(^\/services\/([^/]+)\/([^/]+))", [](auto &&req) // /services/v8/user
	{
		http_resource_manager::response resp { S::OK };
		std::string service_name { req->match[2] };

		resp.content << std::string("
Service: ") + service_name + "
";
		resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
	});

    mgr.add_route(M::GET, R"(^\/$)", [](auto &&req) // /
	{
        auto full_path { req->manager->get_root_path() };

        full_path += "/index.html"s;

        if (fs::exists(full_path) && fs::is_regular_file(full_path))
        {
            http_resource_manager::response resp { S::TemporaryRedirect };

            resp.content << "
Redirect link: click here
";
            resp.add_content_type_header("html", "utf-8").add_header("Location", "/index.html").send_response(req->client);
        }
        else
        {
            http_resource_manager::response resp { S::OK };

            resp.content << "
Index
";
            resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
        }
	});

    mgr.add_route(M::GET, R"(^\/time$)", [](auto &&req) // /time
	{
		http_resource_manager::response resp { S::OK };
		auto cur_time { std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()) };

		resp.content << std::string("
") + std::ctime(&cur_time) + "
";
		resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
	});

    mgr.add_route(M::GET, R"(^\/throw$)", [](auto &&req) // /throw
	{
		throw std::runtime_error("Test exception");
	});

    mgr.add_status_handler(http_resource_manager::response::http_status_codes::NotFound, [](auto &&req)
	{
        auto full_path { req->manager->get_root_path() / ("."s + req->resource) };

        if (fs::exists(full_path) && fs::is_regular_file(full_path))
        {
            http_resource_manager::response resp { S::OK };
            auto data { nstd::utilities::read_file_content(full_path) };

            resp.content.write(std::data(data), std::size(data));
            resp.add_content_type_header(fs::path { full_path }.extension().string().substr(1)).add_header("Connection", "Closed").send_response(req->client);
        }
        else
        {
            http_resource_manager::response resp { S::NotFound };

            resp.content << "<title>Not Found</title>
404 Not Found
";
            resp.add_content_type_header("html", "utf-8").add_header("Connection", "Closed").send_response(req->client);
        }
	});

    std::cout << "Press Ctrl+C to exit..." << std::endl << std::endl;

    mgr.start("127.0.0.1", 3001);

    std::signal(SIGINT, &signint_handler);

    std::mutex mtx;
    std::unique_lock<std::mutex> lock(mtx);

    cv.wait(lock);

    return 0;
}
<|endoftext|>


<commit_before>// Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file LifespanSubscriber.cpp
 *
 */

#include "LifespanSubscriber.h"

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/subscriber/SampleInfo.hpp>
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>

using namespace eprosima::fastdds::dds;
using namespace eprosima::fastrtps::rtps;

LifespanSubscriber::LifespanSubscriber()
    : participant_(nullptr)
    , subscriber_(nullptr)
    , topic_(nullptr)
    , reader_(nullptr)
    , type_(new LifespanType())
{
}

bool LifespanSubscriber::init(
        uint32_t lifespan_ms)
{
    //Create Participant
    DomainParticipantQos pqos;
    pqos.wire_protocol().builtin.discovery_config.leaseDuration = eprosima::fastrtps::c_TimeInfinite;
    pqos.name("Participant_sub");

    participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);
    if (participant_ == nullptr)
    {
        return false;
    }

    //Register Type
    type_.register_type(participant_);

    //Create Subscriber
    subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT);

    if (subscriber_ == nullptr)
    {
        return false;
    }

    //Create Topic
    topic_ = participant_->create_topic("LifespanTopic", "Lifespan", TOPIC_QOS_DEFAULT);

    if (topic_ == nullptr)
    {
        return false;
    }

    //Create DataReader
    DataReaderQos rqos;
    rqos.history().kind = KEEP_ALL_HISTORY_QOS;
    rqos.history().depth = 30;
    rqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
    rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
    rqos.lifespan().duration = lifespan_ms * 1e-3;

    reader_ = subscriber_->create_datareader(topic_, rqos, &listener);
    if (reader_ == nullptr)
    {
        return false;
    }

    return true;
}

LifespanSubscriber::~LifespanSubscriber()
{
    if (reader_ != nullptr)
    {
        subscriber_->delete_datareader(reader_);
    }
    if (topic_ != nullptr)
    {
        participant_->delete_topic(topic_);
    }
    if (subscriber_ != nullptr)
    {
        participant_->delete_subscriber(subscriber_);
    }
    DomainParticipantFactory::get_instance()->delete_participant(participant_);
}

void LifespanSubscriber::SubListener::on_subscription_matched(
        DataReader*,
        const SubscriptionMatchedStatus& info)
{
    if (info.current_count_change == 1)
    {
        n_matched = info.total_count;
        std::cout << "Subscriber matched." << std::endl;
    }
    else if (info.current_count_change == -1)
    {
        n_matched = info.total_count;
        std::cout << "Subscriber unmatched." << std::endl;
    }
    else
    {
        std::cout << info.current_count_change
                  << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl;
    }
}

void LifespanSubscriber::SubListener::on_data_available(
        DataReader* reader)
{
    SampleInfo info;
    if (reader->take_next_sample(&hello, &info) == ReturnCode_t::RETCODE_OK)
    {
        if (info.instance_state == eprosima::fastdds::dds::ALIVE)
        {
            this->n_samples++;
            // Print your structure data here.
            std::cout << "Message " << hello.message() << " " << hello.index() << " RECEIVED" << std::endl;
        }
    }
}

void LifespanSubscriber::run(
        uint32_t number,
        uint32_t sleep_ms)
{
    std::cout << "Subscriber running until " << number << " samples have been received" << std::endl;
    while ( number > this->listener.n_samples )
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    // Now wait and try to remove from history
    std::cout << std::endl << "Subscriber waiting for " << sleep_ms << " milliseconds" << std::endl << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));

    LifespanType::type data;
    SampleInfo info;

    for ( uint32_t i = 0; i < listener.n_samples; i++ )
    {
        if (reader_->take_next_sample((void*) &data, &info) == ReturnCode_t::RETCODE_OK)
        {
            std::cout << "Message " << data.message() << " " << data.index() << " read from history" << std::endl;
        }
        else
        {
            std::cout << "Could not read message " << i << " from history" << std::endl;
        }
    }
}
<commit_msg>Fixed DDS lifespan example (#1302)<commit_after>// Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @file LifespanSubscriber.cpp
 *
 */

#include "LifespanSubscriber.h"

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/subscriber/SampleInfo.hpp>
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>

using namespace eprosima::fastdds::dds;
using namespace eprosima::fastrtps::rtps;

LifespanSubscriber::LifespanSubscriber()
    : participant_(nullptr)
    , subscriber_(nullptr)
    , topic_(nullptr)
    , reader_(nullptr)
    , type_(new LifespanType())
{
}

bool LifespanSubscriber::init(
        uint32_t lifespan_ms)
{
    //Create Participant
    DomainParticipantQos pqos;
    pqos.wire_protocol().builtin.discovery_config.leaseDuration = eprosima::fastrtps::c_TimeInfinite;
    pqos.name("Participant_sub");

    participant_ = DomainParticipantFactory::get_instance()->create_participant(0, pqos);
    if (participant_ == nullptr)
    {
        return false;
    }

    //Register Type
    type_.register_type(participant_);

    //Create Subscriber
    subscriber_ = participant_->create_subscriber(SUBSCRIBER_QOS_DEFAULT);

    if (subscriber_ == nullptr)
    {
        return false;
    }

    //Create Topic
    topic_ = participant_->create_topic("LifespanTopic", "Lifespan", TOPIC_QOS_DEFAULT);

    if (topic_ == nullptr)
    {
        return false;
    }

    //Create DataReader
    DataReaderQos rqos;
    rqos.history().kind = KEEP_ALL_HISTORY_QOS;
    rqos.history().depth = 30;
    rqos.reliability().kind = RELIABLE_RELIABILITY_QOS;
    rqos.durability().kind = TRANSIENT_LOCAL_DURABILITY_QOS;
    rqos.lifespan().duration = lifespan_ms * 1e-3;

    reader_ = subscriber_->create_datareader(topic_, rqos, &listener);
    if (reader_ == nullptr)
    {
        return false;
    }

    return true;
}

LifespanSubscriber::~LifespanSubscriber()
{
    if (reader_ != nullptr)
    {
        subscriber_->delete_datareader(reader_);
    }
    if (topic_ != nullptr)
    {
        participant_->delete_topic(topic_);
    }
    if (subscriber_ != nullptr)
    {
        participant_->delete_subscriber(subscriber_);
    }
    DomainParticipantFactory::get_instance()->delete_participant(participant_);
}

void LifespanSubscriber::SubListener::on_subscription_matched(
        DataReader*,
        const SubscriptionMatchedStatus& info)
{
    if (info.current_count_change == 1)
    {
        n_matched = info.total_count;
        std::cout << "Subscriber matched." << std::endl;
    }
    else if (info.current_count_change == -1)
    {
        n_matched = info.total_count;
        std::cout << "Subscriber unmatched." << std::endl;
    }
    else
    {
        std::cout << info.current_count_change
                  << " is not a valid value for SubscriptionMatchedStatus current count change" << std::endl;
    }
}

void LifespanSubscriber::SubListener::on_data_available(
        DataReader* reader)
{
    SampleInfo info;
    if (reader->read_next_sample(&hello, &info) == ReturnCode_t::RETCODE_OK)
    {
        if (info.instance_state == eprosima::fastdds::dds::ALIVE)
        {
            this->n_samples++;
            // Print your structure data here.
            std::cout << "Message " << hello.message() << " " << hello.index() << " RECEIVED" << std::endl;
        }
    }
}

void LifespanSubscriber::run(
        uint32_t number,
        uint32_t sleep_ms)
{
    std::cout << "Subscriber running until " << number << " samples have been received" << std::endl;
    while ( number > this->listener.n_samples )
    {
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }

    // Now wait and try to remove from history
    std::cout << std::endl << "Subscriber waiting for " << sleep_ms << " milliseconds" << std::endl << std::endl;
    std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));

    LifespanType::type data;
    SampleInfo info;

    for ( uint32_t i = 0; i < listener.n_samples; i++ )
    {
        if (reader_->take_next_sample((void*) &data, &info) == ReturnCode_t::RETCODE_OK)
        {
            std::cout << "Message " << data.message() << " " << data.index() << " read from history" << std::endl;
        }
        else
        {
            std::cout << "Could not read message " << i << " from history" << std::endl;
        }
    }
}
<|endoftext|>