<commit_before>#ifndef EBITEN_GRAPHICS_AFFINE_MATRIX_HPP
#define EBITEN_GRAPHICS_AFFINE_MATRIX_HPP

#include <array>
#include <cassert>
#include <mutex>

namespace ebiten {
namespace graphics {

/*
 * | e00, e01, ..., e0D |
 * | e10, e11, ..., e1D |
 * |  : ,  : ,    ,  :  |
 * | eD0, eD1, ..., eDD |
 */
template<class Float, std::size_t Dimension, class Self>
class affine_matrix {
  static_assert(0 < Dimension, "Dimension must be more than 0");
#ifdef EBITEN_TEST
private:
  FRIEND_TEST(affine_matrix, element);
  FRIEND_TEST(affine_matrix, is_identity);
  FRIEND_TEST(affine_matrix, multiply);
#endif
private:
  static std::size_t const size_ = Dimension * (Dimension - 1);
  typedef std::array<Float, size_> elements_type;
  static std::once_flag identity_once_flag_;
protected:
  elements_type elements_;
protected:
  affine_matrix() {
    this->elements_.fill(0);
  }
public:
  template<std::size_t I, std::size_t J>
  Float
  element() const {
    static_assert(I < Dimension, "I must be less than Dimension");
    static_assert(J < Dimension, "J must be less than Dimension");
    if (I == Dimension - 1) {
      if (J == Dimension - 1) {
        return 1;
      }
      return 0;
    }
    return this->elements_[I * Dimension + J];
  }
  template<std::size_t I, std::size_t J>
  Float
  set_element(Float element) {
    static_assert(I < Dimension - 1, "I must be less than Dimension - 1");
    static_assert(J < Dimension,     "J must be less than Dimension");
    return this->elements_[I * Dimension + J] = element;
  }
  bool
  is_identity() const {
    typename elements_type::const_iterator it = this->elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          if (*it != 1) {
            return false;
          }
        } else {
          if (*it != 0) {
            return false;
          }
        }
      }
    }
    return true;
  }
  static Self
  identity() {
    static Self identity_;
    std::call_once(identity_once_flag_, initialize_identity, std::ref<Self>(identity_));
    return identity_;
  }
  Self
  concat(Self const& other) const {
    Self result;
    elements_type const& lhs_elements = other.elements_;
    elements_type const& rhs_elements = this->elements_;
    typename elements_type::iterator it = result.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        Float e = 0;
        for (std::size_t k = 0; k < Dimension - 1; ++k) {
          e += lhs_elements[i * Dimension + k] * rhs_elements[k * Dimension + j];
        }
        if (j == Dimension - 1) {
          e += lhs_elements[i * Dimension + Dimension - 1];
        }
        *it = e;
      }
    }
    return result;
  }
private:
  static void
  initialize_identity(Self& identity) {
    typename elements_type::iterator it = identity.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          *it = 1;
        } else {
          *it = 0;
        }
      }
    }
  }
};

template<class Float, std::size_t Dimension, class Self>
std::once_flag affine_matrix<Float, Dimension, Self>::identity_once_flag_;

}
}

#ifdef EBITEN_TEST

namespace ebiten {
namespace graphics {

template<class Float, std::size_t Dimension>
class affine_matrix_impl : public affine_matrix<Float,
                                                Dimension,
                                                affine_matrix_impl<Float, Dimension>> {
};

TEST(affine_matrix, element) {
  affine_matrix_impl<double, 4> m;
  m.set_element<0, 0>(1);
  m.set_element<0, 1>(2);
  m.set_element<0, 2>(3);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(0, (m.element<1, 0>()));
  EXPECT_EQ(0, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(0, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
  m.set_element<1, 0>(4);
  m.set_element<1, 1>(5);
  m.set_element<2, 3>(6);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(4, (m.element<1, 0>()));
  EXPECT_EQ(5, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(6, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
}

TEST(affine_matrix, is_identity) {
  affine_matrix_impl<double, 4> m1;
  m1.set_element<0, 0>(1);
  m1.set_element<1, 1>(1);
  m1.set_element<2, 2>(1);
  EXPECT_TRUE(m1.is_identity());
  affine_matrix_impl<double, 4> m2 = m1;
  EXPECT_TRUE(m2.is_identity());
  m2.set_element<0, 1>(1);
  EXPECT_FALSE(m2.is_identity());
}

TEST(affine_matrix, multiply) {
  {
    affine_matrix_impl<double, 3> m1 = affine_matrix_impl<double, 3>::identity();
    affine_matrix_impl<double, 3> m2 = affine_matrix_impl<double, 3>::identity();
    m1.set_element<0, 0>(2);
    m1.set_element<1, 1>(2);
    m2.set_element<0, 2>(1);
    m2.set_element<1, 2>(1);
    {
      affine_matrix_impl<double, 3> m3 = m1.concat(m2);
      EXPECT_EQ(2, (m3.element<0, 0>()));
      EXPECT_EQ(0, (m3.element<0, 1>()));
      EXPECT_EQ(1, (m3.element<0, 2>()));
      EXPECT_EQ(0, (m3.element<1, 0>()));
      EXPECT_EQ(2, (m3.element<1, 1>()));
      EXPECT_EQ(1, (m3.element<1, 2>()));
      EXPECT_EQ(0, (m3.element<2, 0>()));
      EXPECT_EQ(0, (m3.element<2, 1>()));
      EXPECT_EQ(1, (m3.element<2, 2>()));
    }
    {
      affine_matrix_impl<double, 3> m3 = m2.concat(m1);
      EXPECT_EQ(2, (m3.element<0, 0>()));
      EXPECT_EQ(0, (m3.element<0, 1>()));
      EXPECT_EQ(2, (m3.element<0, 2>()));
      EXPECT_EQ(0, (m3.element<1, 0>()));
      EXPECT_EQ(2, (m3.element<1, 1>()));
      EXPECT_EQ(2, (m3.element<1, 2>()));
      EXPECT_EQ(0, (m3.element<2, 0>()));
      EXPECT_EQ(0, (m3.element<2, 1>()));
      EXPECT_EQ(1, (m3.element<2, 2>()));
    }
  }
  {
    affine_matrix_impl<double, 4> m1;
    affine_matrix_impl<double, 4> m2;
    m1.set_element<0, 0>(1);
    m1.set_element<0, 1>(2);
    m1.set_element<0, 2>(3);
    m1.set_element<0, 3>(4);
    m1.set_element<1, 0>(5);
    m1.set_element<1, 1>(6);
    m1.set_element<1, 2>(7);
    m1.set_element<1, 3>(8);
    m1.set_element<2, 0>(9);
    m1.set_element<2, 1>(10);
    m1.set_element<2, 2>(11);
    m1.set_element<2, 3>(12);
    m2.set_element<0, 0>(13);
    m2.set_element<0, 1>(14);
    m2.set_element<0, 2>(15);
    m2.set_element<0, 3>(16);
    m2.set_element<1, 0>(17);
    m2.set_element<1, 1>(18);
    m2.set_element<1, 2>(19);
    m2.set_element<1, 3>(20);
    m2.set_element<2, 0>(21);
    m2.set_element<2, 1>(22);
    m2.set_element<2, 2>(23);
    m2.set_element<2, 3>(24);
    {
      affine_matrix_impl<double, 4> m3 = m1.concat(m2);
      EXPECT_EQ(218, (m3.element<0, 0>()));
      EXPECT_EQ(260, (m3.element<0, 1>()));
      EXPECT_EQ(302, (m3.element<0, 2>()));
      EXPECT_EQ(360, (m3.element<0, 3>()));
      EXPECT_EQ(278, (m3.element<1, 0>()));
      EXPECT_EQ(332, (m3.element<1, 1>()));
      EXPECT_EQ(386, (m3.element<1, 2>()));
      EXPECT_EQ(460, (m3.element<1, 3>()));
      EXPECT_EQ(338, (m3.element<2, 0>()));
      EXPECT_EQ(404, (m3.element<2, 1>()));
      EXPECT_EQ(470, (m3.element<2, 2>()));
      EXPECT_EQ(560, (m3.element<2, 3>()));
      EXPECT_EQ(0,   (m3.element<3, 0>()));
      EXPECT_EQ(0,   (m3.element<3, 1>()));
      EXPECT_EQ(0,   (m3.element<3, 2>()));
      EXPECT_EQ(1,   (m3.element<3, 3>()));
    }
    {
      affine_matrix_impl<double, 4> m3 = m2.concat(m1);
      EXPECT_EQ(110, (m3.element<0, 0>()));
      EXPECT_EQ(116, (m3.element<0, 1>()));
      EXPECT_EQ(122, (m3.element<0, 2>()));
      EXPECT_EQ(132, (m3.element<0, 3>()));
      EXPECT_EQ(314, (m3.element<1, 0>()));
      EXPECT_EQ(332, (m3.element<1, 1>()));
      EXPECT_EQ(350, (m3.element<1, 2>()));
      EXPECT_EQ(376, (m3.element<1, 3>()));
      EXPECT_EQ(518, (m3.element<2, 0>()));
      EXPECT_EQ(548, (m3.element<2, 1>()));
      EXPECT_EQ(578, (m3.element<2, 2>()));
      EXPECT_EQ(620, (m3.element<2, 3>()));
      EXPECT_EQ(0,   (m3.element<3, 0>()));
      EXPECT_EQ(0,   (m3.element<3, 1>()));
      EXPECT_EQ(0,   (m3.element<3, 2>()));
      EXPECT_EQ(1,   (m3.element<3, 3>()));
    }
  }
}

}
}

#endif

#endif
<commit_msg>Added a protected destructor to affine_matrix<commit_after>#ifndef EBITEN_GRAPHICS_AFFINE_MATRIX_HPP
#define EBITEN_GRAPHICS_AFFINE_MATRIX_HPP

#include <array>
#include <cassert>
#include <mutex>

namespace ebiten {
namespace graphics {

/*
 * | e00, e01, ..., e0D |
 * | e10, e11, ..., e1D |
 * |  : ,  : ,    ,  :  |
 * | eD0, eD1, ..., eDD |
 */
template<class Float, std::size_t Dimension, class Self>
class affine_matrix {
  static_assert(0 < Dimension, "Dimension must be more than 0");
#ifdef EBITEN_TEST
private:
  FRIEND_TEST(affine_matrix, element);
  FRIEND_TEST(affine_matrix, is_identity);
  FRIEND_TEST(affine_matrix, multiply);
#endif
private:
  static std::size_t const size_ = Dimension * (Dimension - 1);
  typedef std::array<Float, size_> elements_type;
  static std::once_flag identity_once_flag_;
protected:
  elements_type elements_;
protected:
  affine_matrix() {
    this->elements_.fill(0);
  }
  ~affine_matrix() {
  }
public:
  template<std::size_t I, std::size_t J>
  Float
  element() const {
    static_assert(I < Dimension, "I must be less than Dimension");
    static_assert(J < Dimension, "J must be less than Dimension");
    if (I == Dimension - 1) {
      if (J == Dimension - 1) {
        return 1;
      }
      return 0;
    }
    return this->elements_[I * Dimension + J];
  }
  template<std::size_t I, std::size_t J>
  Float
  set_element(Float element) {
    static_assert(I < Dimension - 1, "I must be less than Dimension - 1");
    static_assert(J < Dimension,     "J must be less than Dimension");
    return this->elements_[I * Dimension + J] = element;
  }
  bool
  is_identity() const {
    typename elements_type::const_iterator it = this->elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          if (*it != 1) {
            return false;
          }
        } else {
          if (*it != 0) {
            return false;
          }
        }
      }
    }
    return true;
  }
  static Self
  identity() {
    static Self identity_;
    std::call_once(identity_once_flag_, initialize_identity, std::ref<Self>(identity_));
    return identity_;
  }
  Self
  concat(Self const& other) const {
    Self result;
    elements_type const& lhs_elements = other.elements_;
    elements_type const& rhs_elements = this->elements_;
    typename elements_type::iterator it = result.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        Float e = 0;
        for (std::size_t k = 0; k < Dimension - 1; ++k) {
          e += lhs_elements[i * Dimension + k] * rhs_elements[k * Dimension + j];
        }
        if (j == Dimension - 1) {
          e += lhs_elements[i * Dimension + Dimension - 1];
        }
        *it = e;
      }
    }
    return result;
  }
private:
  static void
  initialize_identity(Self& identity) {
    typename elements_type::iterator it = identity.elements_.begin();
    for (std::size_t i = 0; i < Dimension - 1; ++i) {
      for (std::size_t j = 0; j < Dimension; ++j, ++it) {
        if (i == j) {
          *it = 1;
        } else {
          *it = 0;
        }
      }
    }
  }
};

template<class Float, std::size_t Dimension, class Self>
std::once_flag affine_matrix<Float, Dimension, Self>::identity_once_flag_;

}
}

#ifdef EBITEN_TEST

namespace ebiten {
namespace graphics {

template<class Float, std::size_t Dimension>
class affine_matrix_impl : public affine_matrix<Float,
                                                Dimension,
                                                affine_matrix_impl<Float, Dimension>> {
};

TEST(affine_matrix, element) {
  affine_matrix_impl<double, 4> m;
  m.set_element<0, 0>(1);
  m.set_element<0, 1>(2);
  m.set_element<0, 2>(3);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(0, (m.element<1, 0>()));
  EXPECT_EQ(0, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(0, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
  m.set_element<1, 0>(4);
  m.set_element<1, 1>(5);
  m.set_element<2, 3>(6);
  EXPECT_EQ(1, (m.element<0, 0>()));
  EXPECT_EQ(2, (m.element<0, 1>()));
  EXPECT_EQ(3, (m.element<0, 2>()));
  EXPECT_EQ(0, (m.element<0, 3>()));
  EXPECT_EQ(4, (m.element<1, 0>()));
  EXPECT_EQ(5, (m.element<1, 1>()));
  EXPECT_EQ(0, (m.element<1, 2>()));
  EXPECT_EQ(0, (m.element<1, 3>()));
  EXPECT_EQ(0, (m.element<2, 0>()));
  EXPECT_EQ(0, (m.element<2, 1>()));
  EXPECT_EQ(0, (m.element<2, 2>()));
  EXPECT_EQ(6, (m.element<2, 3>()));
  EXPECT_EQ(0, (m.element<3, 0>()));
  EXPECT_EQ(0, (m.element<3, 1>()));
  EXPECT_EQ(0, (m.element<3, 2>()));
  EXPECT_EQ(1, (m.element<3, 3>()));
}

TEST(affine_matrix, is_identity) {
  affine_matrix_impl<double, 4> m1;
  m1.set_element<0, 0>(1);
  m1.set_element<1, 1>(1);
  m1.set_element<2, 2>(1);
  EXPECT_TRUE(m1.is_identity());
  affine_matrix_impl<double, 4> m2 = m1;
  EXPECT_TRUE(m2.is_identity());
  m2.set_element<0, 1>(1);
  EXPECT_FALSE(m2.is_identity());
}

TEST(affine_matrix, multiply) {
  {
    affine_matrix_impl<double, 3> m1 = affine_matrix_impl<double, 3>::identity();
    affine_matrix_impl<double, 3> m2 = affine_matrix_impl<double, 3>::identity();
    m1.set_element<0, 0>(2);
    m1.set_element<1, 1>(2);
    m2.set_element<0, 2>(1);
    m2.set_element<1, 2>(1);
    {
      affine_matrix_impl<double, 3> m3 = m1.concat(m2);
      EXPECT_EQ(2, (m3.element<0, 0>()));
      EXPECT_EQ(0, (m3.element<0, 1>()));
      EXPECT_EQ(1, (m3.element<0, 2>()));
      EXPECT_EQ(0, (m3.element<1, 0>()));
      EXPECT_EQ(2, (m3.element<1, 1>()));
      EXPECT_EQ(1, (m3.element<1, 2>()));
      EXPECT_EQ(0, (m3.element<2, 0>()));
      EXPECT_EQ(0, (m3.element<2, 1>()));
      EXPECT_EQ(1, (m3.element<2, 2>()));
    }
    {
      affine_matrix_impl<double, 3> m3 = m2.concat(m1);
      EXPECT_EQ(2, (m3.element<0, 0>()));
      EXPECT_EQ(0, (m3.element<0, 1>()));
      EXPECT_EQ(2, (m3.element<0, 2>()));
      EXPECT_EQ(0, (m3.element<1, 0>()));
      EXPECT_EQ(2, (m3.element<1, 1>()));
      EXPECT_EQ(2, (m3.element<1, 2>()));
      EXPECT_EQ(0, (m3.element<2, 0>()));
      EXPECT_EQ(0, (m3.element<2, 1>()));
      EXPECT_EQ(1, (m3.element<2, 2>()));
    }
  }
  {
    affine_matrix_impl<double, 4> m1;
    affine_matrix_impl<double, 4> m2;
    m1.set_element<0, 0>(1);
    m1.set_element<0, 1>(2);
    m1.set_element<0, 2>(3);
    m1.set_element<0, 3>(4);
    m1.set_element<1, 0>(5);
    m1.set_element<1, 1>(6);
    m1.set_element<1, 2>(7);
    m1.set_element<1, 3>(8);
    m1.set_element<2, 0>(9);
    m1.set_element<2, 1>(10);
    m1.set_element<2, 2>(11);
    m1.set_element<2, 3>(12);
    m2.set_element<0, 0>(13);
    m2.set_element<0, 1>(14);
    m2.set_element<0, 2>(15);
    m2.set_element<0, 3>(16);
    m2.set_element<1, 0>(17);
    m2.set_element<1, 1>(18);
    m2.set_element<1, 2>(19);
    m2.set_element<1, 3>(20);
    m2.set_element<2, 0>(21);
    m2.set_element<2, 1>(22);
    m2.set_element<2, 2>(23);
    m2.set_element<2, 3>(24);
    {
      affine_matrix_impl<double, 4> m3 = m1.concat(m2);
      EXPECT_EQ(218, (m3.element<0, 0>()));
      EXPECT_EQ(260, (m3.element<0, 1>()));
      EXPECT_EQ(302, (m3.element<0, 2>()));
      EXPECT_EQ(360, (m3.element<0, 3>()));
      EXPECT_EQ(278, (m3.element<1, 0>()));
      EXPECT_EQ(332, (m3.element<1, 1>()));
      EXPECT_EQ(386, (m3.element<1, 2>()));
      EXPECT_EQ(460, (m3.element<1, 3>()));
      EXPECT_EQ(338, (m3.element<2, 0>()));
      EXPECT_EQ(404, (m3.element<2, 1>()));
      EXPECT_EQ(470, (m3.element<2, 2>()));
      EXPECT_EQ(560, (m3.element<2, 3>()));
      EXPECT_EQ(0,   (m3.element<3, 0>()));
      EXPECT_EQ(0,   (m3.element<3, 1>()));
      EXPECT_EQ(0,   (m3.element<3, 2>()));
      EXPECT_EQ(1,   (m3.element<3, 3>()));
    }
    {
      affine_matrix_impl<double, 4> m3 = m2.concat(m1);
      EXPECT_EQ(110, (m3.element<0, 0>()));
      EXPECT_EQ(116, (m3.element<0, 1>()));
      EXPECT_EQ(122, (m3.element<0, 2>()));
      EXPECT_EQ(132, (m3.element<0, 3>()));
      EXPECT_EQ(314, (m3.element<1, 0>()));
      EXPECT_EQ(332, (m3.element<1, 1>()));
      EXPECT_EQ(350, (m3.element<1, 2>()));
      EXPECT_EQ(376, (m3.element<1, 3>()));
      EXPECT_EQ(518, (m3.element<2, 0>()));
      EXPECT_EQ(548, (m3.element<2, 1>()));
      EXPECT_EQ(578, (m3.element<2, 2>()));
      EXPECT_EQ(620, (m3.element<2, 3>()));
      EXPECT_EQ(0,   (m3.element<3, 0>()));
      EXPECT_EQ(0,   (m3.element<3, 1>()));
      EXPECT_EQ(0,   (m3.element<3, 2>()));
      EXPECT_EQ(1,   (m3.element<3, 3>()));
    }
  }
}

}
}

#endif

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/log.h"

#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/thread.h"

namespace dart {

DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");

// The following flag is useful when debugging on Android, since
// adb logcat truncates messages that are "too long" (and always
// flushing would result in too many short messages).
DEFINE_FLAG(
    int,
    force_log_flush_at_size,
    0,
    "Flush log messages when buffer exceeds given size (disabled when 0).");

DEFINE_FLAG(charp,
            isolate_log_filter,
            nullptr,
            "Log isolates whose name include the filter. "
            "Default: service isolate log messages are suppressed "
            "(specify 'vm-service' to log them).");

Log::Log(LogPrinter printer)
    : printer_(printer), manual_flush_(0), buffer_(0) {}

Log::~Log() {
  // Did someone enable manual flushing and then forgot to Flush?
  ASSERT(cursor() == 0);
}

Log* Log::Current() {
  Thread* thread = Thread::Current();
  if (thread == nullptr) {
    OSThread* os_thread = OSThread::Current();
    ASSERT(os_thread != nullptr);
    return os_thread->log();
  }
  IsolateGroup* isolate_group = thread->isolate_group();
  if ((isolate_group != nullptr) &&
      Log::ShouldLogForIsolateGroup(isolate_group)) {
    OSThread* os_thread = thread->os_thread();
    ASSERT(os_thread != nullptr);
    return os_thread->log();
  } else {
    return Log::NoOpLog();
  }
}

void Log::Print(const char* format, ...) {
  if (this == NoOpLog()) {
    return;
  }

  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}

void Log::VPrint(const char* format, va_list args) {
  if (this == NoOpLog()) {
    return;
  }

  // Measure.
  va_list measure_args;
  va_copy(measure_args, args);
  intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
  va_end(measure_args);

  // Print.
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  va_list print_args;
  va_copy(print_args, args);
  Utils::VSNPrint(buffer, (len + 1), format, print_args);
  va_end(print_args);

  // Append.
  // NOTE: does not append the '\0' character.
  for (intptr_t i = 0; i < len; i++) {
    buffer_.Add(buffer[i]);
  }
  free(buffer);

  if (ShouldFlush()) {
    Flush();
  }
}

void Log::Flush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }
  if (buffer_.is_empty()) {
    return;
  }
  if (buffer_.length() <= cursor) {
    return;
  }
  TerminateString();
  const char* str = &buffer_[cursor];
  ASSERT(str != nullptr);
  printer_("%s", str);
  buffer_.TruncateTo(cursor);
}

void Log::Clear() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.TruncateTo(0);
}

intptr_t Log::cursor() const {
  return buffer_.length();
}

bool Log::ShouldLogForIsolateGroup(const IsolateGroup* isolate_group) {
  if (FLAG_isolate_log_filter == nullptr) {
    if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
      // By default, do not log for the service or kernel isolates.
      return false;
    }
    return true;
  }
  const char* name = isolate_group->source()->name;
  ASSERT(name != nullptr);
  if (strstr(name, FLAG_isolate_log_filter) == nullptr) {
    // Filter does not match, do not log for this isolate.
    return false;
  }
  return true;
}

Log Log::noop_log_;
Log* Log::NoOpLog() {
  return &noop_log_;
}

void Log::TerminateString() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.Add('\0');
}

void Log::EnableManualFlush() {
  if (this == NoOpLog()) {
    return;
  }
  manual_flush_++;
}

void Log::DisableManualFlush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }

  manual_flush_--;
  ASSERT(manual_flush_ >= 0);
  if (manual_flush_ == 0) {
    Flush(cursor);
  }
}

bool Log::ShouldFlush() const {
  return ((manual_flush_ == 0) || FLAG_force_log_flush ||
          ((FLAG_force_log_flush_at_size > 0) &&
           (cursor() > FLAG_force_log_flush_at_size)));
}

void LogBlock::Initialize() {
  log_->EnableManualFlush();
}

LogBlock::~LogBlock() {
  log_->DisableManualFlush(cursor_);
}

}  // namespace dart
<commit_msg>[vm] Eagerly flush logs on Android<commit_after>// Copyright (c) 2015, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "vm/log.h"

#include "vm/flags.h"
#include "vm/isolate.h"
#include "vm/thread.h"

namespace dart {

DEFINE_FLAG(bool, force_log_flush, false, "Always flush log messages.");

// The following flag is useful when debugging on Android, since
// adb logcat truncates messages that are "too long" (and always
// flushing would result in too many short messages).
DEFINE_FLAG(
    int,
    force_log_flush_at_size,
    0,
    "Flush log messages when buffer exceeds given size (disabled when 0).");

DEFINE_FLAG(charp,
            isolate_log_filter,
            nullptr,
            "Log isolates whose name include the filter. "
            "Default: service isolate log messages are suppressed "
            "(specify 'vm-service' to log them).");

Log::Log(LogPrinter printer)
    : printer_(printer), manual_flush_(0), buffer_(0) {}

Log::~Log() {
  // Did someone enable manual flushing and then forgot to Flush?
  ASSERT(cursor() == 0);
}

Log* Log::Current() {
  Thread* thread = Thread::Current();
  if (thread == nullptr) {
    OSThread* os_thread = OSThread::Current();
    ASSERT(os_thread != nullptr);
    return os_thread->log();
  }
  IsolateGroup* isolate_group = thread->isolate_group();
  if ((isolate_group != nullptr) &&
      Log::ShouldLogForIsolateGroup(isolate_group)) {
    OSThread* os_thread = thread->os_thread();
    ASSERT(os_thread != nullptr);
    return os_thread->log();
  } else {
    return Log::NoOpLog();
  }
}

void Log::Print(const char* format, ...) {
  if (this == NoOpLog()) {
    return;
  }

  va_list args;
  va_start(args, format);
  VPrint(format, args);
  va_end(args);
}

void Log::VPrint(const char* format, va_list args) {
  if (this == NoOpLog()) {
    return;
  }

  // Measure.
  va_list measure_args;
  va_copy(measure_args, args);
  intptr_t len = Utils::VSNPrint(nullptr, 0, format, measure_args);
  va_end(measure_args);

  // Print.
  char* buffer = reinterpret_cast<char*>(malloc(len + 1));
  va_list print_args;
  va_copy(print_args, args);
  Utils::VSNPrint(buffer, (len + 1), format, print_args);
  va_end(print_args);

  // Append.
  // NOTE: does not append the '\0' character.
  for (intptr_t i = 0; i < len; i++) {
    buffer_.Add(buffer[i]);
  }
  free(buffer);

  if (ShouldFlush()) {
    Flush();
  }
}

void Log::Flush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }
  if (buffer_.is_empty()) {
    return;
  }
  if (buffer_.length() <= cursor) {
    return;
  }
  TerminateString();
  const char* str = &buffer_[cursor];
  ASSERT(str != nullptr);
  printer_("%s", str);
  buffer_.TruncateTo(cursor);
}

void Log::Clear() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.TruncateTo(0);
}

intptr_t Log::cursor() const {
  return buffer_.length();
}

bool Log::ShouldLogForIsolateGroup(const IsolateGroup* isolate_group) {
  if (FLAG_isolate_log_filter == nullptr) {
    if (IsolateGroup::IsSystemIsolateGroup(isolate_group)) {
      // By default, do not log for the service or kernel isolates.
      return false;
    }
    return true;
  }
  const char* name = isolate_group->source()->name;
  ASSERT(name != nullptr);
  if (strstr(name, FLAG_isolate_log_filter) == nullptr) {
    // Filter does not match, do not log for this isolate.
    return false;
  }
  return true;
}

Log Log::noop_log_;
Log* Log::NoOpLog() {
  return &noop_log_;
}

void Log::TerminateString() {
  if (this == NoOpLog()) {
    return;
  }
  buffer_.Add('\0');
}

void Log::EnableManualFlush() {
  if (this == NoOpLog()) {
    return;
  }
  manual_flush_++;
}

void Log::DisableManualFlush(const intptr_t cursor) {
  if (this == NoOpLog()) {
    return;
  }

  manual_flush_--;
  ASSERT(manual_flush_ >= 0);
  if (manual_flush_ == 0) {
    Flush(cursor);
  }
}

bool Log::ShouldFlush() const {
#ifdef DART_TARGET_OS_ANDROID
  // Android truncates on 1023 characters, flush more eagerly.
  // Flush on newlines, because otherwise Android inserts newlines everywhere.
  if (*(buffer_.end() - 1) == '\n') {
    return true;
  }
#endif  // DART_TARGET_OS_ANDROID
  return ((manual_flush_ == 0) || FLAG_force_log_flush ||
          ((FLAG_force_log_flush_at_size > 0) &&
           (cursor() > FLAG_force_log_flush_at_size)));
}

void LogBlock::Initialize() {
  log_->EnableManualFlush();
}

LogBlock::~LogBlock() {
  log_->DisableManualFlush(cursor_);
}

}  // namespace dart
<|endoftext|>


<commit_before>/*
* (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"

#if defined(BOTAN_HAS_ASN1)
   #include <botan/der_enc.h>
   #include <botan/ber_dec.h>
   #include <botan/asn1_str.h>
#endif

namespace Botan_Tests {

#if defined(BOTAN_HAS_ASN1)

namespace {

Test::Result test_ber_stack_recursion()
   {
   Test::Result result("BER stack recursion");

   // OSS-Fuzz #813 GitHub #989

   try
      {
      const std::vector<uint8_t> in(10000000, 0);
      Botan::DataSource_Memory input(in.data(), in.size());
      Botan::BER_Decoder dec(input);

      while(dec.more_items())
         {
         Botan::BER_Object obj;
         dec.get_next(obj);
         }
      }
   catch(Botan::Decoding_Error&)
      {
      }

   result.test_success("No crash");

   return result;
   }

}

Test::Result test_asn1_utf8_ascii_parsing()
   {
      Test::Result result("ASN.1 ASCII parsing");

      try
         {
            // \x13 - ASN1 tag for 'printable string'
            // \x06 - 6 characters of payload
            // ...  - UTF-8 encoded (ASCII chars only) word 'Moscow'
            const std::string moscow =
               "\x13\x06\x4D\x6F\x73\x63\x6F\x77";
            const std::string moscow_plain = "Moscow";
            Botan::DataSource_Memory input(moscow.data());
            Botan::BER_Decoder dec(input);

            Botan::ASN1_String str;
            str.decode_from(dec);

            result.test_eq("value()", str.value(), moscow_plain);
         }
      catch(const Botan::Decoding_Error &ex)
         {
            result.test_failure(ex.what());
         }

      return result;
   }

Test::Result test_asn1_utf8_parsing()
   {
      Test::Result result("ASN.1 UTF-8 parsing");

      try
         {
            // \x0C - ASN1 tag for 'UTF8 string'
            // \x0C - 12 characters of payload
            // ...  - UTF-8 encoded russian word for Moscow in cyrillic script
            const std::string moscow =
               "\x0C\x0C\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
            const std::string moscow_plain =
               "\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
            Botan::DataSource_Memory input(moscow.data());
            Botan::BER_Decoder dec(input);

            Botan::ASN1_String str;
            str.decode_from(dec);

            result.test_eq("value()", str.value(), moscow_plain);
         }
      catch(const Botan::Decoding_Error &ex)
         {
            result.test_failure(ex.what());
         }

      return result;
   }

Test::Result test_asn1_ascii_encoding()
   {
      Test::Result result("ASN.1 ASCII encoding");

      try
         {
            // UTF-8 encoded (ASCII chars only) word 'Moscow'
            const std::string moscow =
               "\x4D\x6F\x73\x63\x6F\x77";
            Botan::ASN1_String str(moscow);

            Botan::DER_Encoder enc;

            str.encode_into(enc);
            auto encodingResult = enc.get_contents();

            // \x13 - ASN1 tag for 'printable string'
            // \x06 - 6 characters of payload
            const auto moscowEncoded = Botan::hex_decode("13064D6F73636F77");
            result.test_eq("encoding result", encodingResult, moscowEncoded);

            result.test_success("No crash");
         }
      catch(const std::exception &ex)
         {
            result.test_failure(ex.what());
         }

      return result;
   }

Test::Result test_asn1_utf8_encoding()
   {
      Test::Result result("ASN.1 UTF-8 encoding");

      try
         {
            // UTF-8 encoded russian word for Moscow in cyrillic script
            const std::string moscow =
               "\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
            Botan::ASN1_String str(moscow);

            Botan::DER_Encoder enc;

            str.encode_into(enc);
            auto encodingResult = enc.get_contents();

            // \x0C - ASN1 tag for 'UTF8 string'
            // \x0C - 12 characters of payload
            const auto moscowEncoded =
               Botan::hex_decode("0C0CD09CD0BED181D0BAD0B2D0B0");
            result.test_eq("encoding result", encodingResult, moscowEncoded);

            result.test_success("No crash");
         }
      catch(const std::exception &ex)
         {
            result.test_failure(ex.what());
         }

      return result;
   }

Test::Result test_asn1_ascii_encoding()
   {
   Test::Result result("ASN.1 ASCII encoding");

   try
      {
      // UTF-8 encoded (ASCII chars only) word 'Moscow'
      const std::string moscow =
         "\x4D\x6F\x73\x63\x6F\x77";
      Botan::ASN1_String str(moscow);

      Botan::DER_Encoder enc;

      str.encode_into(enc);
      auto encodingResult = enc.get_contents();

      // \x13 - ASN1 tag for 'printable string'
      // \x06 - 6 characters of payload
      const auto moscowEncoded = Botan::hex_decode("13064D6F73636F77");
      result.test_eq("encoding result", encodingResult, moscowEncoded);

      result.test_success("No crash");
      }
   catch(const std::exception &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_utf8_encoding()
   {
   Test::Result result("ASN.1 UTF-8 encoding");

   try
      {
      // UTF-8 encoded russian word for Moscow in cyrillic script
      const std::string moscow =
         "\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      Botan::ASN1_String str(moscow);

      Botan::DER_Encoder enc;

      str.encode_into(enc);
      auto encodingResult = enc.get_contents();

      // \x0C - ASN1 tag for 'UTF8 string'
      // \x0C - 12 characters of payload
      const auto moscowEncoded =
         Botan::hex_decode("0C0CD09CD0BED181D0BAD0B2D0B0");
      result.test_eq("encoding result", encodingResult, moscowEncoded);

      result.test_success("No crash");
      }
   catch(const std::exception &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

class ASN1_Tests final : public Test
   {
   public:
      std::vector<Test::Result> run() override
         {
         std::vector<Test::Result> results;

         results.push_back(test_ber_stack_recursion());
         results.push_back(test_asn1_utf8_ascii_parsing());
         results.push_back(test_asn1_utf8_parsing());
         results.push_back(test_asn1_ucs2_parsing());
         results.push_back(test_asn1_ucs4_parsing());
         results.push_back(test_asn1_ascii_encoding());
         results.push_back(test_asn1_utf8_encoding());

         return results;
         }
   };

BOTAN_REGISTER_TEST("asn1", ASN1_Tests);

#endif

}

<commit_msg>FIX: coding style<commit_after>/*
* (C) 2017 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/

#include "tests.h"

#if defined(BOTAN_HAS_ASN1)
   #include <botan/der_enc.h>
   #include <botan/ber_dec.h>
   #include <botan/asn1_str.h>
#endif

namespace Botan_Tests {

#if defined(BOTAN_HAS_ASN1)

namespace {

Test::Result test_ber_stack_recursion()
   {
   Test::Result result("BER stack recursion");

   // OSS-Fuzz #813 GitHub #989

   try
      {
      const std::vector<uint8_t> in(10000000, 0);
      Botan::DataSource_Memory input(in.data(), in.size());
      Botan::BER_Decoder dec(input);

      while(dec.more_items())
         {
         Botan::BER_Object obj;
         dec.get_next(obj);
         }
      }
   catch(Botan::Decoding_Error&)
      {
      }

   result.test_success("No crash");

   return result;
   }

}

Test::Result test_asn1_utf8_ascii_parsing()
   {
   Test::Result result("ASN.1 ASCII parsing");

   try
      {
      // \x13 - ASN1 tag for 'printable string'
      // \x06 - 6 characters of payload
      // ...  - UTF-8 encoded (ASCII chars only) word 'Moscow'
      const std::string moscow =
         "\x13\x06\x4D\x6F\x73\x63\x6F\x77";
      const std::string moscow_plain = "Moscow";
      Botan::DataSource_Memory input(moscow.data());
      Botan::BER_Decoder dec(input);

      Botan::ASN1_String str;
      str.decode_from(dec);

      result.test_eq("value()", str.value(), moscow_plain);
      }
   catch(const Botan::Decoding_Error &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_utf8_parsing()
   {
   Test::Result result("ASN.1 UTF-8 parsing");

   try
      {
      // \x0C - ASN1 tag for 'UTF8 string'
      // \x0C - 12 characters of payload
      // ...  - UTF-8 encoded russian word for Moscow in cyrillic script
      const std::string moscow =
         "\x0C\x0C\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      const std::string moscow_plain =
         "\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      Botan::DataSource_Memory input(moscow.data());
      Botan::BER_Decoder dec(input);

      Botan::ASN1_String str;
      str.decode_from(dec);

      result.test_eq("value()", str.value(), moscow_plain);
      }
   catch(const Botan::Decoding_Error &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_ucs2_parsing()
   {
   Test::Result result("ASN.1 BMP string (UCS-2) parsing");

   try
      {
      // \x1E     - ASN1 tag for 'BMP (UCS-2) string'
      // \x0E     - 14 characters of payload (includes BOM)
      // \xFF\xFE - Byte Order Mark (BOM)
      // ...      - UCS-2 encoding for Moscow in cyrillic script
      const std::string moscow =
         "\x1E\x0E\xFF\xFE\x1C\x04\x3E\x04"
         "\x41\x04\x3A\x04\x32\x04\x30\x04";
      const std::string moscow_plain =  // with BOM (EF BB BF)
         "\xEF\xBB\xBF\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      Botan::DataSource_Memory input(moscow.data());
      Botan::BER_Decoder dec(input);

      Botan::ASN1_String str;
      str.decode_from(dec);

      result.test_eq("value()", str.value(), moscow_plain);
      }
   catch(const Botan::Decoding_Error &ex)
      {
         result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_ucs4_parsing()
   {
   Test::Result result("ASN.1 universal string (UTF-32 LE) parsing");

   try
      {
      // \x1C - ASN1 tag for 'universal string'
      // \x1C - 28 characters of payload (with BOM - FF FE 00 00)
      // ...  - UTF-32 LE encoding for Moscow in cyrillic script
      const Botan::byte moscow[] =
         "\x1C\x1C\xFF\xFE\x00\x00\x1C\x04\x00\x00\x3E\x04\x00\x00\x41"
         "\x04\x00\x00\x3A\x04\x00\x00\x32\x04\x00\x00\x30\x04\x00\x00";
      const std::string moscow_plain =  // with BOM (EF BB BF)
         "\xEF\xBB\xBF\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      Botan::DataSource_Memory input(moscow, sizeof(moscow));
      Botan::BER_Decoder dec(input);

      Botan::ASN1_String str;
      str.decode_from(dec);

      result.test_eq("value()", str.value(), moscow_plain);
      }
   catch(const Botan::Decoding_Error &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_ascii_encoding()
   {
   Test::Result result("ASN.1 ASCII encoding");

   try
      {
      // UTF-8 encoded (ASCII chars only) word 'Moscow'
      const std::string moscow =
         "\x4D\x6F\x73\x63\x6F\x77";
      Botan::ASN1_String str(moscow);

      Botan::DER_Encoder enc;

      str.encode_into(enc);
      auto encodingResult = enc.get_contents();

      // \x13 - ASN1 tag for 'printable string'
      // \x06 - 6 characters of payload
      const auto moscowEncoded = Botan::hex_decode("13064D6F73636F77");
      result.test_eq("encoding result", encodingResult, moscowEncoded);

      result.test_success("No crash");
      }
   catch(const std::exception &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

Test::Result test_asn1_utf8_encoding()
   {
   Test::Result result("ASN.1 UTF-8 encoding");

   try
      {
      // UTF-8 encoded russian word for Moscow in cyrillic script
      const std::string moscow =
         "\xD0\x9C\xD0\xBE\xD1\x81\xD0\xBA\xD0\xB2\xD0\xB0";
      Botan::ASN1_String str(moscow);

      Botan::DER_Encoder enc;

      str.encode_into(enc);
      auto encodingResult = enc.get_contents();

      // \x0C - ASN1 tag for 'UTF8 string'
      // \x0C - 12 characters of payload
      const auto moscowEncoded =
         Botan::hex_decode("0C0CD09CD0BED181D0BAD0B2D0B0");
      result.test_eq("encoding result", encodingResult, moscowEncoded);

      result.test_success("No crash");
      }
   catch(const std::exception &ex)
      {
      result.test_failure(ex.what());
      }

   return result;
   }

class ASN1_Tests final : public Test
   {
   public:
      std::vector<Test::Result> run() override
         {
         std::vector<Test::Result> results;

         results.push_back(test_ber_stack_recursion());
         results.push_back(test_asn1_utf8_ascii_parsing());
         results.push_back(test_asn1_utf8_parsing());
         results.push_back(test_asn1_ucs2_parsing());
         results.push_back(test_asn1_ucs4_parsing());
         results.push_back(test_asn1_ascii_encoding());
         results.push_back(test_asn1_utf8_encoding());

         return results;
         }
   };

BOTAN_REGISTER_TEST("asn1", ASN1_Tests);

#endif

}

<|endoftext|>


<commit_before>/*
 * Copyright 2009-2018 The VOTCA Development Team (http://www.votca.org)
 *
 * 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.
 *
 */
#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE table_test
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <exception>
#include <iostream>
#include <votca/tools/table.h>

using namespace std;
using namespace votca::tools;

BOOST_AUTO_TEST_SUITE(table_test)

BOOST_AUTO_TEST_CASE(create_test) {
  Table tb;
}

BOOST_AUTO_TEST_CASE(size_test) {
  Table tb;
  BOOST_CHECK_EQUAL(tb.size(),0);
}

BOOST_AUTO_TEST_CASE(pushback_test){
  Table tb;
  for(double x=0;x<10;++x){
    double y = 2*x;
    tb.push_back(x,y);
  }
  BOOST_CHECK_EQUAL(tb.size(),10);
}

BOOST_AUTO_TEST_CASE(xy_test){
  Table tb;
  for(double x=0;x<10;++x){
    double y = 2*x;
    tb.push_back(x,y);
  }

  auto x_v = tb.x();
  auto y_v = tb.y();
  for(int i=0;i<10;++i){
    int x = i;
    int y = 2*x;
    BOOST_CHECK_EQUAL(boost::lexical_cast<int>(x_v(i)),boost::lexical_cast<int>(tb.x(i)));
    BOOST_CHECK_EQUAL(boost::lexical_cast<int>(y_v(i)),boost::lexical_cast<int>(tb.y(i)));
    BOOST_CHECK_EQUAL(x,boost::lexical_cast<int>(tb.x(i)));
    BOOST_CHECK_EQUAL(y,boost::lexical_cast<int>(tb.y(i)));
    BOOST_CHECK_EQUAL(x,boost::lexical_cast<int>(x_v(i)));
    BOOST_CHECK_EQUAL(y,boost::lexical_cast<int>(y_v(i)));
  }
}

BOOST_AUTO_TEST_CASE(getMinMax_test){
  Table tb;
  for(double x=0;x<10;++x){
    double y = 2*x;
    tb.push_back(x,y);
  }
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMinX()),0);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMaxX()),9);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMinY()),0);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMaxY()),18);
}

BOOST_AUTO_TEST_SUITE_END()
<commit_msg>Formatted test_table<commit_after>/*
 * Copyright 2009-2018 The VOTCA Development Team (http://www.votca.org)
 *
 * 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.
 *
 */
#define BOOST_TEST_MAIN

#define BOOST_TEST_MODULE table_test
#include <boost/test/unit_test.hpp>
#include <boost/lexical_cast.hpp>
#include <exception>
#include <iostream>
#include <votca/tools/table.h>

using namespace std;
using namespace votca::tools;

BOOST_AUTO_TEST_SUITE(table_test)

BOOST_AUTO_TEST_CASE(create_test) { Table tb; }

BOOST_AUTO_TEST_CASE(size_test) {
  Table tb;
  BOOST_CHECK_EQUAL(tb.size(), 0);
}

BOOST_AUTO_TEST_CASE(pushback_test) {
  Table tb;
  for (double x = 0; x < 10; ++x) {
    double y = 2 * x;
    tb.push_back(x, y);
  }
  BOOST_CHECK_EQUAL(tb.size(), 10);
}

BOOST_AUTO_TEST_CASE(xy_test) {
  Table tb;
  for (double x = 0; x < 10; ++x) {
    double y = 2 * x;
    tb.push_back(x, y);
  }

  auto x_v = tb.x();
  auto y_v = tb.y();
  for (int i = 0; i < 10; ++i) {
    int x = i;
    int y = 2 * x;
    BOOST_CHECK_EQUAL(boost::lexical_cast<int>(x_v(i)),
                      boost::lexical_cast<int>(tb.x(i)));
    BOOST_CHECK_EQUAL(boost::lexical_cast<int>(y_v(i)),
                      boost::lexical_cast<int>(tb.y(i)));
    BOOST_CHECK_EQUAL(x, boost::lexical_cast<int>(tb.x(i)));
    BOOST_CHECK_EQUAL(y, boost::lexical_cast<int>(tb.y(i)));
    BOOST_CHECK_EQUAL(x, boost::lexical_cast<int>(x_v(i)));
    BOOST_CHECK_EQUAL(y, boost::lexical_cast<int>(y_v(i)));
  }
}

BOOST_AUTO_TEST_CASE(getMinMax_test) {
  Table tb;
  for (double x = 0; x < 10; ++x) {
    double y = 2 * x;
    tb.push_back(x, y);
  }
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMinX()), 0);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMaxX()), 9);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMinY()), 0);
  BOOST_CHECK_EQUAL(boost::lexical_cast<int>(tb.getMaxY()), 18);
}

BOOST_AUTO_TEST_SUITE_END()
<|endoftext|>


<commit_before>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Ioan Sucan */

#include <gtest/gtest.h>
#include "ompl/datastructures/NearestNeighborsSqrtApprox.h"
#include "ompl/base/ScopedState.h"
#include "ompl/base/manifolds/SE3StateManifold.h"

using namespace ompl;

template<typename T>
double distance(const T* manifold, base::State* const &s0, base::State* const &s1)
{
    return manifold->distance(s0,s1);
}

TEST(NearestNeighbors, Linear)
{
    int i, n=1000;
    base::SE3StateManifold SE3;
    base::ManifoldStateSamplerPtr sampler;
    base::RealVectorBounds b(3);
    std::vector<base::State*> states(n), nghbr(10);
    NearestNeighborsLinear<base::State*> proximity;
    base::State* s;

    b.setLow(0);
    b.setHigh(1);
    SE3.setBounds(b);
    sampler = SE3.allocStateSampler();

    proximity.setDistanceFunction(boost::bind(&distance<base::SE3StateManifold>, &SE3, _1, _2));

    for(i=0; i<n; ++i)
    {
        states[i] = SE3.allocState();
        sampler->sampleUniform(states[i]);
        proximity.add(states[i]);
    }

    EXPECT_EQ((int)proximity.size(), n);

    for(i=0; i<n; ++i)
    {
        s = proximity.nearest(states[i]);
        EXPECT_EQ(s, states[i]);

        proximity.nearestK(states[i], 10, nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(), 10u);

        proximity.nearestR(states[i], 1000., nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(),proximity.size());
    }

    proximity.list(nghbr);
    EXPECT_EQ(nghbr.size(),proximity.size());
    for(i=0; i<n; ++i)
        EXPECT_EQ(states[i], nghbr[i]);

    for(i=n-1; i>=0; --i)
    {
        proximity.remove(states[i]);
        EXPECT_EQ((int)proximity.size(), i);
    }
    try
    {
        s = proximity.nearest(states[0]);
    }
    catch (std::exception& e)
    {
        EXPECT_STREQ("No elements found", e.what());
    }
}

TEST(NearestNeighbors, SqrtApprox)
{
    int i, j, n=1000;
    base::SE3StateManifold SE3;
    base::ManifoldStateSamplerPtr sampler;
    base::RealVectorBounds b(3);
    std::vector<base::State*> states(n), nghbr(10);
    NearestNeighborsSqrtApprox<base::State*> proximity;
    base::State* s;

    b.setLow(0);
    b.setHigh(1);
    SE3.setBounds(b);
    sampler = SE3.allocStateSampler();

    proximity.setDistanceFunction(boost::bind(&distance<base::SE3StateManifold>, &SE3, _1, _2));

    for(i=0; i<n; ++i)
    {
        states[i] = SE3.allocState();
        sampler->sampleUniform(states[i]);
        proximity.add(states[i]);
    }

    EXPECT_EQ((int)proximity.size(), n);

    for(i=0,j=0; i<n; ++i)
    {
        s = proximity.nearest(states[i]);
        if (s==states[i]) j++;

        proximity.nearestK(states[i], 10, nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(), 10u);

        proximity.nearestR(states[i], 1000., nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(),proximity.size());
    }
    EXPECT_GE(j, 10);

    proximity.list(nghbr);
    EXPECT_EQ(nghbr.size(),proximity.size());
    for(i=0; i<n; ++i)
        EXPECT_EQ(states[i], nghbr[i]);

    for(i=n-1; i>=0; --i)
    {
        proximity.remove(states[i]);
        EXPECT_EQ((int)proximity.size(), i);
    }
    try
    {
        s = proximity.nearest(states[0]);
    }
    catch (std::exception& e)
    {
        EXPECT_STREQ("No elements found", e.what());
    }
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<commit_msg>decreasing test size to have faster 'make test'<commit_after>/*********************************************************************
* Software License Agreement (BSD License)
*
*  Copyright (c) 2010, Rice University
*  All rights reserved.
*
*  Redistribution and use in source and binary forms, with or without
*  modification, are permitted provided that the following conditions
*  are met:
*
*   * Redistributions of source code must retain the above copyright
*     notice, this list of conditions and the following disclaimer.
*   * Redistributions in binary form must reproduce the above
*     copyright notice, this list of conditions and the following
*     disclaimer in the documentation and/or other materials provided
*     with the distribution.
*   * Neither the name of the Rice University nor the names of its
*     contributors may be used to endorse or promote products derived
*     from this software without specific prior written permission.
*
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
*  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
*  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
*  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
*  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
*  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
*  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
*  POSSIBILITY OF SUCH DAMAGE.
*********************************************************************/

/* Author: Mark Moll */

#include <gtest/gtest.h>
#include "ompl/datastructures/NearestNeighborsSqrtApprox.h"
#include "ompl/base/ScopedState.h"
#include "ompl/base/manifolds/SE3StateManifold.h"

using namespace ompl;

template<typename T>
double distance(const T* manifold, base::State* const &s0, base::State* const &s1)
{
    return manifold->distance(s0,s1);
}

TEST(NearestNeighbors, Linear)
{
    int i, n = 200;
    base::SE3StateManifold SE3;
    base::ManifoldStateSamplerPtr sampler;
    base::RealVectorBounds b(3);
    std::vector<base::State*> states(n), nghbr(10);
    NearestNeighborsLinear<base::State*> proximity;
    base::State* s;

    b.setLow(0);
    b.setHigh(1);
    SE3.setBounds(b);
    sampler = SE3.allocStateSampler();

    proximity.setDistanceFunction(boost::bind(&distance<base::SE3StateManifold>, &SE3, _1, _2));

    for(i=0; i<n; ++i)
    {
        states[i] = SE3.allocState();
        sampler->sampleUniform(states[i]);
        proximity.add(states[i]);
    }

    EXPECT_EQ((int)proximity.size(), n);

    for(i=0; i<n; ++i)
    {
        s = proximity.nearest(states[i]);
        EXPECT_EQ(s, states[i]);

        proximity.nearestK(states[i], 10, nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(), 10u);

        proximity.nearestR(states[i], 1000., nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(),proximity.size());
    }

    proximity.list(nghbr);
    EXPECT_EQ(nghbr.size(),proximity.size());
    for(i=0; i<n; ++i)
        EXPECT_EQ(states[i], nghbr[i]);

    for(i=n-1; i>=0; --i)
    {
        proximity.remove(states[i]);
        EXPECT_EQ((int)proximity.size(), i);
    }
    try
    {
        s = proximity.nearest(states[0]);
    }
    catch (std::exception& e)
    {
        EXPECT_STREQ("No elements found", e.what());
    }
}

TEST(NearestNeighbors, SqrtApprox)
{
    int i, j, n = 200;
    base::SE3StateManifold SE3;
    base::ManifoldStateSamplerPtr sampler;
    base::RealVectorBounds b(3);
    std::vector<base::State*> states(n), nghbr(10);
    NearestNeighborsSqrtApprox<base::State*> proximity;
    base::State* s;

    b.setLow(0);
    b.setHigh(1);
    SE3.setBounds(b);
    sampler = SE3.allocStateSampler();

    proximity.setDistanceFunction(boost::bind(&distance<base::SE3StateManifold>, &SE3, _1, _2));

    for(i=0; i<n; ++i)
    {
        states[i] = SE3.allocState();
        sampler->sampleUniform(states[i]);
        proximity.add(states[i]);
    }

    EXPECT_EQ((int)proximity.size(), n);

    for(i=0,j=0; i<n; ++i)
    {
        s = proximity.nearest(states[i]);
        if (s==states[i]) j++;

        proximity.nearestK(states[i], 10, nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(), 10u);

        proximity.nearestR(states[i], 1000., nghbr);
        EXPECT_EQ(nghbr[0], states[i]);
        EXPECT_EQ(nghbr.size(),proximity.size());
    }
    EXPECT_GE(j, 10);

    proximity.list(nghbr);
    EXPECT_EQ(nghbr.size(),proximity.size());
    for(i=0; i<n; ++i)
        EXPECT_EQ(states[i], nghbr[i]);

    for(i=n-1; i>=0; --i)
    {
        proximity.remove(states[i]);
        EXPECT_EQ((int)proximity.size(), i);
    }
    try
    {
        s = proximity.nearest(states[0]);
    }
    catch (std::exception& e)
    {
        EXPECT_STREQ("No elements found", e.what());
    }
}

int main(int argc, char **argv)
{
    testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include "libtorrent/pch.hpp"

#include <vector>
#include <cctype>

#include <boost/bind.hpp>

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/aux_/session_impl.hpp"

using namespace libtorrent;
using boost::tuples::make_tuple;
using boost::tuples::tuple;
using boost::bind;

namespace
{
	enum
	{
		minimum_tracker_response_length = 3,
		http_buffer_size = 2048
	};

}

namespace libtorrent
{
	timeout_handler::timeout_handler(io_service& ios)
		: m_start_time(time_now())
		, m_read_time(time_now())
		, m_timeout(ios)
		, m_completion_timeout(0)
		, m_read_timeout(0)
		, m_abort(false)
	{}

	void timeout_handler::set_timeout(int completion_timeout, int read_timeout)
	{
		m_completion_timeout = completion_timeout;
		m_read_timeout = read_timeout;
		m_start_time = m_read_time = time_now();

		if (m_abort) return;

		int timeout = (std::min)(
			m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
		error_code ec;
		m_timeout.expires_at(m_read_time + seconds(timeout), ec);
		m_timeout.async_wait(bind(
			&timeout_handler::timeout_callback, self(), _1));
	}

	void timeout_handler::restart_read_timeout()
	{
		m_read_time = time_now();
	}

	void timeout_handler::cancel()
	{
		m_abort = true;
		m_completion_timeout = 0;
		error_code ec;
		m_timeout.cancel(ec);
	}

	void timeout_handler::timeout_callback(error_code const& error)
	{
		if (error) return;
		if (m_completion_timeout == 0) return;

		ptime now(time_now());
		time_duration receive_timeout = now - m_read_time;
		time_duration completion_timeout = now - m_start_time;

		if (m_read_timeout
			< total_seconds(receive_timeout)
			|| m_completion_timeout
			< total_seconds(completion_timeout))
		{
			on_timeout();
			return;
		}

		if (m_abort) return;

		int timeout = (std::min)(
			m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
		error_code ec;
		m_timeout.expires_at(m_read_time + seconds(timeout), ec);
		m_timeout.async_wait(
			bind(&timeout_handler::timeout_callback, self(), _1));
	}

	tracker_connection::tracker_connection(
		tracker_manager& man
		, tracker_request const& req
		, io_service& ios
		, boost::weak_ptr<request_callback> r)
		: timeout_handler(ios)
		, m_requester(r)
		, m_man(man)
		, m_req(req)
	{}

	boost::shared_ptr<request_callback> tracker_connection::requester()
	{
		return m_requester.lock();
	}

	void tracker_connection::fail(int code, char const* msg)
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (cb) cb->tracker_request_error(m_req, code, msg);
		close();
	}

	void tracker_connection::sent_bytes(int bytes)
	{
		m_man.sent_bytes(bytes);
	}

	void tracker_connection::received_bytes(int bytes)
	{
		m_man.received_bytes(bytes);
	}

	void tracker_connection::fail_timeout()
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (cb) cb->tracker_request_timed_out(m_req);
		close();
	}

	void tracker_connection::close()
	{
		cancel();
		m_man.remove_request(this);
	}

	tracker_manager::~tracker_manager()
	{
		TORRENT_ASSERT(m_abort);
		abort_all_requests(true);
	}

	void tracker_manager::sent_bytes(int bytes)
	{
//		aux::session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
		m_ses.m_stat.sent_tracker_bytes(bytes);
	}

	void tracker_manager::received_bytes(int bytes)
	{
		aux::session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
		m_ses.m_stat.received_tracker_bytes(bytes);
	}

	void tracker_manager::remove_request(tracker_connection const* c)
	{
		mutex_t::scoped_lock l(m_mutex);

		tracker_connections_t::iterator i = std::find(m_connections.begin()
			, m_connections.end(), boost::intrusive_ptr<const tracker_connection>(c));
		if (i == m_connections.end()) return;

		m_connections.erase(i);
	}

	void tracker_manager::queue_request(
		io_service& ios
		, connection_queue& cc
		, tracker_request req
		, std::string const& auth
		, boost::weak_ptr<request_callback> c)
	{
		mutex_t::scoped_lock l(m_mutex);
		TORRENT_ASSERT(req.num_want >= 0);
		TORRENT_ASSERT(!m_abort);
		if (m_abort) return;
		if (req.event == tracker_request::stopped)
			req.num_want = 0;

		TORRENT_ASSERT(!m_abort || req.event == tracker_request::stopped);
		if (m_abort && req.event != tracker_request::stopped)
			return;

		std::string protocol = req.url.substr(0, req.url.find(':'));

		boost::intrusive_ptr<tracker_connection> con;

#ifdef TORRENT_USE_OPENSSL
		if (protocol == "http" || protocol == "https")
#else
		if (protocol == "http")
#endif
		{
			con = new http_tracker_connection(
				ios, cc, *this, req, c
				, m_ses, m_proxy, auth);
		}
		else if (protocol == "udp")
		{
			con = new udp_tracker_connection(
				ios, cc, *this, req , c, m_ses
				, m_proxy);
		}
		else
		{
			if (boost::shared_ptr<request_callback> r = c.lock())
				r->tracker_request_error(req, -1, "unknown protocol in tracker url: "
					+ req.url);
			return;
		}

		m_connections.push_back(con);

		boost::shared_ptr<request_callback> cb = con->requester();
		if (cb) cb->m_manager = this;
		con->start();
	}

	void tracker_manager::abort_all_requests(bool all)
	{
		// removes all connections from m_connections
		// except 'event=stopped'-requests
		mutex_t::scoped_lock l(m_mutex);

		m_abort = true;
		tracker_connections_t keep_connections;

		while (!m_connections.empty())
		{
			boost::intrusive_ptr<tracker_connection>& c = m_connections.back();
			if (!c)
			{
				m_connections.pop_back();
				continue;
			}
			tracker_request const& req = c->tracker_req();
			if (req.event == tracker_request::stopped && !all)
			{
				keep_connections.push_back(c);
				m_connections.pop_back();
				continue;
			}
			// close will remove the entry from m_connections
			// so no need to pop

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			boost::shared_ptr<request_callback> rc = c->requester();
			if (rc) rc->debug_log("aborting: " + req.url);
#endif
			c->close();
		}

		std::swap(m_connections, keep_connections);
	}

	bool tracker_manager::empty() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_connections.empty();
	}

	int tracker_manager::num_requests() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_connections.size();
	}
}
<commit_msg>fixed shutdown issue when trackers times out (introduced with the timer optimization)<commit_after>/*

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

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

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

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

*/

#include "libtorrent/pch.hpp"

#include <vector>
#include <cctype>

#include <boost/bind.hpp>

#include "libtorrent/tracker_manager.hpp"
#include "libtorrent/http_tracker_connection.hpp"
#include "libtorrent/udp_tracker_connection.hpp"
#include "libtorrent/entry.hpp"
#include "libtorrent/bencode.hpp"
#include "libtorrent/torrent.hpp"
#include "libtorrent/peer_connection.hpp"
#include "libtorrent/aux_/session_impl.hpp"

using namespace libtorrent;
using boost::tuples::make_tuple;
using boost::tuples::tuple;
using boost::bind;

namespace
{
	enum
	{
		minimum_tracker_response_length = 3,
		http_buffer_size = 2048
	};

}

namespace libtorrent
{
	timeout_handler::timeout_handler(io_service& ios)
		: m_start_time(time_now_hires())
		, m_read_time(m_start_time)
		, m_timeout(ios)
		, m_completion_timeout(0)
		, m_read_timeout(0)
		, m_abort(false)
	{}

	void timeout_handler::set_timeout(int completion_timeout, int read_timeout)
	{
		m_completion_timeout = completion_timeout;
		m_read_timeout = read_timeout;
		m_start_time = m_read_time = time_now_hires();

		if (m_abort) return;

		int timeout = (std::min)(
			m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
		error_code ec;
		m_timeout.expires_at(m_read_time + seconds(timeout), ec);
		m_timeout.async_wait(bind(
			&timeout_handler::timeout_callback, self(), _1));
	}

	void timeout_handler::restart_read_timeout()
	{
		m_read_time = time_now_hires();
	}

	void timeout_handler::cancel()
	{
		m_abort = true;
		m_completion_timeout = 0;
		error_code ec;
		m_timeout.cancel(ec);
	}

	void timeout_handler::timeout_callback(error_code const& error)
	{
		if (error) return;
		if (m_completion_timeout == 0) return;

		ptime now = time_now_hires();
		time_duration receive_timeout = now - m_read_time;
		time_duration completion_timeout = now - m_start_time;

		if (m_read_timeout
			< total_seconds(receive_timeout)
			|| m_completion_timeout
			< total_seconds(completion_timeout))
		{
			on_timeout();
			return;
		}

		if (m_abort) return;

		int timeout = (std::min)(
			m_read_timeout, (std::min)(m_completion_timeout, m_read_timeout));
		error_code ec;
		m_timeout.expires_at(m_read_time + seconds(timeout), ec);
		m_timeout.async_wait(
			bind(&timeout_handler::timeout_callback, self(), _1));
	}

	tracker_connection::tracker_connection(
		tracker_manager& man
		, tracker_request const& req
		, io_service& ios
		, boost::weak_ptr<request_callback> r)
		: timeout_handler(ios)
		, m_requester(r)
		, m_man(man)
		, m_req(req)
	{}

	boost::shared_ptr<request_callback> tracker_connection::requester()
	{
		return m_requester.lock();
	}

	void tracker_connection::fail(int code, char const* msg)
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (cb) cb->tracker_request_error(m_req, code, msg);
		close();
	}

	void tracker_connection::sent_bytes(int bytes)
	{
		m_man.sent_bytes(bytes);
	}

	void tracker_connection::received_bytes(int bytes)
	{
		m_man.received_bytes(bytes);
	}

	void tracker_connection::fail_timeout()
	{
		boost::shared_ptr<request_callback> cb = requester();
		if (cb) cb->tracker_request_timed_out(m_req);
		close();
	}

	void tracker_connection::close()
	{
		cancel();
		m_man.remove_request(this);
	}

	tracker_manager::~tracker_manager()
	{
		TORRENT_ASSERT(m_abort);
		abort_all_requests(true);
	}

	void tracker_manager::sent_bytes(int bytes)
	{
//		aux::session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
		m_ses.m_stat.sent_tracker_bytes(bytes);
	}

	void tracker_manager::received_bytes(int bytes)
	{
		aux::session_impl::mutex_t::scoped_lock l(m_ses.m_mutex);
		m_ses.m_stat.received_tracker_bytes(bytes);
	}

	void tracker_manager::remove_request(tracker_connection const* c)
	{
		mutex_t::scoped_lock l(m_mutex);

		tracker_connections_t::iterator i = std::find(m_connections.begin()
			, m_connections.end(), boost::intrusive_ptr<const tracker_connection>(c));
		if (i == m_connections.end()) return;

		m_connections.erase(i);
	}

	void tracker_manager::queue_request(
		io_service& ios
		, connection_queue& cc
		, tracker_request req
		, std::string const& auth
		, boost::weak_ptr<request_callback> c)
	{
		mutex_t::scoped_lock l(m_mutex);
		TORRENT_ASSERT(req.num_want >= 0);
		TORRENT_ASSERT(!m_abort);
		if (m_abort) return;
		if (req.event == tracker_request::stopped)
			req.num_want = 0;

		TORRENT_ASSERT(!m_abort || req.event == tracker_request::stopped);
		if (m_abort && req.event != tracker_request::stopped)
			return;

		std::string protocol = req.url.substr(0, req.url.find(':'));

		boost::intrusive_ptr<tracker_connection> con;

#ifdef TORRENT_USE_OPENSSL
		if (protocol == "http" || protocol == "https")
#else
		if (protocol == "http")
#endif
		{
			con = new http_tracker_connection(
				ios, cc, *this, req, c
				, m_ses, m_proxy, auth);
		}
		else if (protocol == "udp")
		{
			con = new udp_tracker_connection(
				ios, cc, *this, req , c, m_ses
				, m_proxy);
		}
		else
		{
			if (boost::shared_ptr<request_callback> r = c.lock())
				r->tracker_request_error(req, -1, "unknown protocol in tracker url: "
					+ req.url);
			return;
		}

		m_connections.push_back(con);

		boost::shared_ptr<request_callback> cb = con->requester();
		if (cb) cb->m_manager = this;
		con->start();
	}

	void tracker_manager::abort_all_requests(bool all)
	{
		// removes all connections from m_connections
		// except 'event=stopped'-requests
		mutex_t::scoped_lock l(m_mutex);

		m_abort = true;
		tracker_connections_t keep_connections;

		while (!m_connections.empty())
		{
			boost::intrusive_ptr<tracker_connection>& c = m_connections.back();
			if (!c)
			{
				m_connections.pop_back();
				continue;
			}
			tracker_request const& req = c->tracker_req();
			if (req.event == tracker_request::stopped && !all)
			{
				keep_connections.push_back(c);
				m_connections.pop_back();
				continue;
			}
			// close will remove the entry from m_connections
			// so no need to pop

#if defined TORRENT_VERBOSE_LOGGING || defined TORRENT_LOGGING || defined TORRENT_ERROR_LOGGING
			boost::shared_ptr<request_callback> rc = c->requester();
			if (rc) rc->debug_log("aborting: " + req.url);
#endif
			c->close();
		}

		std::swap(m_connections, keep_connections);
	}

	bool tracker_manager::empty() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_connections.empty();
	}

	int tracker_manager::num_requests() const
	{
		mutex_t::scoped_lock l(m_mutex);
		return m_connections.size();
	}
}
<|endoftext|>


<commit_before>namespace mant {
  inline arma::Mat<double>::fixed<2, 2> get2DRotation(
      const double angle) noexcept;

  inline arma::Mat<double>::fixed<3, 3> get3DRotation(
      const double rollAngle,
      const double pitchAngle,
      const double yawAngle) noexcept;

  inline arma::Col<double>::fixed<2> getCircleCircleIntersection(
      const arma::Col<double>::fixed<2>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<2>& secondCenter,
      const double secondRadius);

  inline arma::Col<double>::fixed<3> getCircleSphereIntersection(
      const arma::Col<double>::fixed<3>& circleCenter,
      const double circleRadius,
      const arma::Col<double>::fixed<3>& circleNormal,
      const arma::Col<double>::fixed<3>& sphereCenter,
      const double sphereRadius);

  inline arma::Col<double>::fixed<3> getTriangulation(
      const arma::Col<double>::fixed<3>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<3>& secondCenter,
      const double secondRadius,
      const arma::Col<double>::fixed<3>& thirdCenter,
      const double thirdRadius);

  //
  // Implementation
  //

  inline arma::Mat<double>::fixed<2, 2> get2DRotation(
      const double angle) noexcept {
    double sineAngle = std::sin(angle);
    double cosineAngle = std::cos(angle);

    return arma::Mat<double>::fixed<2, 2>({
      cosineAngle, -sineAngle,
      sineAngle, cosineAngle
    });
  }

  inline arma::Mat<double>::fixed<3, 3> get3DRotation(
      const double rollAngle,
      const double pitchAngle,
      const double yawAngle) noexcept {
    double sineRollAngle = std::sin(rollAngle);
    double cosineRollAngle = std::cos(rollAngle);
    double sinePitchAngle = std::sin(pitchAngle);
    double cosinePitchAngle = std::cos(pitchAngle);
    double sineYawAngle = std::sin(yawAngle);
    double cosineYawAngle = std::cos(yawAngle);

    // Avoids Rz*Ry*Rx, as this will suffer from singularities.
    return arma::Mat<double>::fixed<3, 3>({
      cosineYawAngle * cosinePitchAngle, cosineYawAngle * sinePitchAngle * sineRollAngle - sineYawAngle * cosineRollAngle, cosineYawAngle * sinePitchAngle * cosineRollAngle + sineYawAngle * sineRollAngle,
      sineYawAngle * cosinePitchAngle, sineYawAngle * sinePitchAngle * sineRollAngle + cosineYawAngle * cosineRollAngle, sineYawAngle * sinePitchAngle * cosineRollAngle - cosineYawAngle * sineRollAngle,
      -sinePitchAngle, cosinePitchAngle * sineRollAngle, cosinePitchAngle * cosineRollAngle
    });
  }

  inline arma::Col<double>::fixed<2> getCircleCircleIntersection(
      const arma::Col<double>::fixed<2>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<2>& secondCenter,
      const double secondRadius) {
    double distance = arma::norm(secondCenter - firstCenter);

    if(firstRadius <= 0) {
      throw std::logic_error("The radius of the first circle (" + std::to_string(firstRadius) + ") must be strict greater than 0.");
    } else if(secondRadius <= 0) {
      throw std::logic_error("The radius of the second circle (" + std::to_string(secondRadius) + ") must be strict greater than 0.");
    } else if (distance == 0 || distance >= firstRadius + secondRadius || distance <= std::max(firstRadius, secondRadius) - std::min(firstRadius, secondRadius)) {
      throw std::logic_error("Only intersections with exactly two intersections are considered valid.");
    }

    double cosine = (std::pow(firstRadius, 2.0) - std::pow(secondRadius, 2.0) + std::pow(distance, 2.0)) / (2.0 * distance);
    double sine = std::sqrt(std::pow(firstRadius, 2.0) - std::pow(cosine, 2.0));

    arma::Col<double>::fixed<2> normal = arma::normalise(secondCenter - firstCenter);

    return firstCenter + arma::Col<double>::fixed<2>({
      normal(0) * cosine + normal(1) * sine,
      normal(1) * cosine - normal(0) * sine
    });
  }

  inline arma::Col<double>::fixed<3> getCircleSphereIntersection(
      const arma::Col<double>::fixed<3>& circleCenter,
      const double circleRadius,
      const arma::Col<double>::fixed<3>& circleNormal,
      const arma::Col<double>::fixed<3>& sphereCenter,
      const double sphereRadius) {
    // Distance between the spheres center and the intersection circle within the sphere
    const double innerDistance = arma::dot(circleNormal, sphereCenter - circleCenter);

    if(circleRadius <= 0) {
      throw std::logic_error("The radius of the circle (" + std::to_string(circleRadius) + ") must be strict greater than 0.");
    } else if(sphereRadius <= 0) {
      throw std::logic_error("The radius of the sphere (" + std::to_string(sphereRadius) + ") must be strict greater than 0.");
    } else if (std::abs(innerDistance) >= sphereRadius) {
      throw std::logic_error("Only intersections with exactly two solutions are considered valid.");
    }

    const arma::Col<double>::fixed<3>& innerCenter = sphereCenter + innerDistance * circleNormal;
    const double innerRadius = std::sqrt(std::pow(sphereRadius, 2.0) - std::pow(innerDistance, 2.0));

    const double distance = arma::norm(innerCenter - circleCenter);

    if (distance == 0 || distance >= circleRadius + innerRadius || distance <= std::max(circleRadius, innerRadius) - std::min(circleRadius, innerRadius)) {
      throw std::logic_error("Only intersections with exactly two solutions are considered valid.");
    }

    const arma::Col<double>::fixed<3>& normal = arma::normalise(arma::cross(innerCenter - circleCenter, circleNormal));

    const double intersectionDistance = (std::pow(circleRadius, 2.0) - std::pow(innerRadius, 2.0) + std::pow(distance, 2.0)) / (2.0 * distance);

    return circleCenter + intersectionDistance / distance * (innerCenter - circleCenter) + normal * std::sqrt(std::pow(circleRadius, 2.0) - std::pow(intersectionDistance, 2.0));
  }

  inline arma::Col<double>::fixed<3> getTriangulation(
      const arma::Col<double>::fixed<3>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<3>& secondCenter,
      const double secondRadius,
      const arma::Col<double>::fixed<3>& thirdCenter,
      const double thirdRadius) {
    const arma::Col<double>::fixed<3>& firstToSecondCenter = secondCenter - firstCenter;
    const arma::Col<double>::fixed<3>& firstToThirdCenter = thirdCenter - firstCenter;

    const arma::Col<double>::fixed<3>& normal = arma::cross(firstToSecondCenter, firstToThirdCenter);
    const double normalLength = arma::norm(normal);

    const arma::Col<double>::fixed<3>& firstToInnerCenter = (arma::cross((std::pow(arma::norm(firstToSecondCenter), 2.0) + std::pow(firstRadius, 2.0) - std::pow(secondRadius, 2.0)) * firstToThirdCenter - (std::pow(arma::norm(firstToThirdCenter), 2.0) + std::pow(firstRadius, 2.0) - std::pow(thirdRadius, 2.0)) * firstToSecondCenter, normal)) / std::pow(normalLength, 2.0);
    const arma::Col<double>::fixed<3>& innerCenterToIntercection = std::sqrt(std::pow(firstRadius, 2.0) - std::pow(arma::norm(firstToInnerCenter), 2.0)) * normal / normalLength;

    return firstCenter + firstToInnerCenter + innerCenterToIntercection;
  }
}
<commit_msg>Unified exception handling<commit_after>namespace mant {
  inline arma::Mat<double>::fixed<2, 2> get2DRotation(
      const double angle) noexcept;

  inline arma::Mat<double>::fixed<3, 3> get3DRotation(
      const double rollAngle,
      const double pitchAngle,
      const double yawAngle) noexcept;

  inline arma::Col<double>::fixed<2> getCircleCircleIntersection(
      const arma::Col<double>::fixed<2>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<2>& secondCenter,
      const double secondRadius);

  inline arma::Col<double>::fixed<3> getCircleSphereIntersection(
      const arma::Col<double>::fixed<3>& circleCenter,
      const double circleRadius,
      const arma::Col<double>::fixed<3>& circleNormal,
      const arma::Col<double>::fixed<3>& sphereCenter,
      const double sphereRadius);

  inline arma::Col<double>::fixed<3> getTriangulation(
      const arma::Col<double>::fixed<3>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<3>& secondCenter,
      const double secondRadius,
      const arma::Col<double>::fixed<3>& thirdCenter,
      const double thirdRadius);

  //
  // Implementation
  //

  inline arma::Mat<double>::fixed<2, 2> get2DRotation(
      const double angle) noexcept {
    double sineAngle = std::sin(angle);
    double cosineAngle = std::cos(angle);

    return arma::Mat<double>::fixed<2, 2>({
      cosineAngle, -sineAngle,
      sineAngle, cosineAngle
    });
  }

  inline arma::Mat<double>::fixed<3, 3> get3DRotation(
      const double rollAngle,
      const double pitchAngle,
      const double yawAngle) noexcept {
    double sineRollAngle = std::sin(rollAngle);
    double cosineRollAngle = std::cos(rollAngle);
    double sinePitchAngle = std::sin(pitchAngle);
    double cosinePitchAngle = std::cos(pitchAngle);
    double sineYawAngle = std::sin(yawAngle);
    double cosineYawAngle = std::cos(yawAngle);

    // Avoids Rz*Ry*Rx, as this will suffer from singularities.
    return arma::Mat<double>::fixed<3, 3>({
      cosineYawAngle * cosinePitchAngle, cosineYawAngle * sinePitchAngle * sineRollAngle - sineYawAngle * cosineRollAngle, cosineYawAngle * sinePitchAngle * cosineRollAngle + sineYawAngle * sineRollAngle,
      sineYawAngle * cosinePitchAngle, sineYawAngle * sinePitchAngle * sineRollAngle + cosineYawAngle * cosineRollAngle, sineYawAngle * sinePitchAngle * cosineRollAngle - cosineYawAngle * sineRollAngle,
      -sinePitchAngle, cosinePitchAngle * sineRollAngle, cosinePitchAngle * cosineRollAngle
    });
  }

  inline arma::Col<double>::fixed<2> getCircleCircleIntersection(
      const arma::Col<double>::fixed<2>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<2>& secondCenter,
      const double secondRadius) {
    verify(firstRadius > 0, "The radius of the first circle must be strict greater than 0.");
    verify(secondRadius > 0, "The radius of the second circle must be strict greater than 0.");

    double distance = arma::norm(secondCenter - firstCenter);
    verify(distance > 0, "The distance between both circle centres must be strict greater than 0.");
    verify(distance < firstRadius + secondRadius, "The distance between both circles centres must be strict less than the sum of their radii.");
    verify(distance > std::max(firstRadius, secondRadius) - std::min(firstRadius, secondRadius), "The distance between both centres must be strict greater than the difference in their radii.");

    double cosine = (std::pow(firstRadius, 2.0) - std::pow(secondRadius, 2.0) + std::pow(distance, 2.0)) / (2.0 * distance);
    double sine = std::sqrt(std::pow(firstRadius, 2.0) - std::pow(cosine, 2.0));

    arma::Col<double>::fixed<2> normal = arma::normalise(secondCenter - firstCenter);

    return firstCenter + arma::Col<double>::fixed<2>({
      normal(0) * cosine + normal(1) * sine,
      normal(1) * cosine - normal(0) * sine
    });
  }

  inline arma::Col<double>::fixed<3> getCircleSphereIntersection(
      const arma::Col<double>::fixed<3>& circleCenter,
      const double circleRadius,
      const arma::Col<double>::fixed<3>& circleNormal,
      const arma::Col<double>::fixed<3>& sphereCenter,
      const double sphereRadius) {
    verify(circleRadius > 0, "The radius of the circle must be strict greater than 0.");
    verify(sphereRadius > 0, "The radius of the sphere must be strict greater than 0.");

    // Distance between the spheres center and the intersection circle within the sphere
    const double innerDistance = arma::dot(circleNormal, sphereCenter - circleCenter);
    verify(std::abs(innerDistance) < sphereRadius, "Only intersections with exactly two solutions are considered valid.");

    const arma::Col<double>::fixed<3>& innerCenter = sphereCenter + innerDistance * circleNormal;
    const double innerRadius = std::sqrt(std::pow(sphereRadius, 2.0) - std::pow(innerDistance, 2.0));

    const double distance = arma::norm(innerCenter - circleCenter);
    verify(distance > 0, "The distance between both circle centres must be strict greater than 0. Note: The second circle is defnied by a plane/sphere intesection.");
    verify(distance < circleRadius + innerRadius, "The distance between both circles centres must be strict less than the sum of their radii. Note: The second circle is defnied by a plane/sphere intesection.");
    verify(distance > std::max(circleRadius, innerRadius) - std::min(circleRadius, innerRadius), "The distance between both centres must be strict greater than the difference in their radii. Note: The second circle is defnied by a plane/sphere intesection.");

    const arma::Col<double>::fixed<3>& normal = arma::normalise(arma::cross(innerCenter - circleCenter, circleNormal));

    const double intersectionDistance = (std::pow(circleRadius, 2.0) - std::pow(innerRadius, 2.0) + std::pow(distance, 2.0)) / (2.0 * distance);

    return circleCenter + intersectionDistance / distance * (innerCenter - circleCenter) + normal * std::sqrt(std::pow(circleRadius, 2.0) - std::pow(intersectionDistance, 2.0));
  }

  inline arma::Col<double>::fixed<3> getTriangulation(
      const arma::Col<double>::fixed<3>& firstCenter,
      const double firstRadius,
      const arma::Col<double>::fixed<3>& secondCenter,
      const double secondRadius,
      const arma::Col<double>::fixed<3>& thirdCenter,
      const double thirdRadius) {
    const arma::Col<double>::fixed<3>& firstToSecondCenter = secondCenter - firstCenter;
    const arma::Col<double>::fixed<3>& firstToThirdCenter = thirdCenter - firstCenter;

    const arma::Col<double>::fixed<3>& normal = arma::cross(firstToSecondCenter, firstToThirdCenter);
    const double normalLength = arma::norm(normal);

    const arma::Col<double>::fixed<3>& firstToInnerCenter = (arma::cross((std::pow(arma::norm(firstToSecondCenter), 2.0) + std::pow(firstRadius, 2.0) - std::pow(secondRadius, 2.0)) * firstToThirdCenter - (std::pow(arma::norm(firstToThirdCenter), 2.0) + std::pow(firstRadius, 2.0) - std::pow(thirdRadius, 2.0)) * firstToSecondCenter, normal)) / std::pow(normalLength, 2.0);
    const arma::Col<double>::fixed<3>& innerCenterToIntercection = std::sqrt(std::pow(firstRadius, 2.0) - std::pow(arma::norm(firstToInnerCenter), 2.0)) * normal / normalLength;

    return firstCenter + firstToInnerCenter + innerCenterToIntercection;
  }
}
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_ITEMBAR_HPP
#define RJ_GAME_EDITOR_ITEMBAR_HPP

#include "button_item.hpp"
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>
#include <rectojump/ui/connected_buttons.hpp>

namespace rj
{
	template<typename Game_Handler>
	class itembar
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		data_manager& m_datamgr;

		sf::RectangleShape m_shape;
		std::vector<sf::Texture> m_button_textures;
		ui::connected_buttons m_buttons;
		const vec2f m_buttonsize{64.f, 64.f};

	public:
		mlk::slot<ui::base_btn_ptr&> on_item_click;

		itembar(Game_Handler& gh, const vec2f& size) :
			m_gamehandler{gh},
			m_render{gh.get_render()},
			m_datamgr{gh.get_datamgr()},
			m_shape{size},
			m_button_textures{m_datamgr.get_all_containing_as<sf::Texture>("editor_item")}
		{this->init();}

		void update(dur duration)
		{
			m_buttons.update(duration);
		}

		void render()
		{m_render(m_shape, m_buttons);}

		void deselect_all() noexcept
		{m_buttons.inactivate();}

		const sf::Texture& get_current_texture() const noexcept
		{return *m_buttons.get_active_btn()->get_texture();}

		auto get_bounds() const noexcept
		-> decltype(m_shape.getGlobalBounds())
		{return m_shape.getGlobalBounds();}

		const vec2f& get_size() const noexcept
		{return m_shape.getSize();}

	private:
		void init()
		{
			auto& rec_size(m_shape.getSize());
			m_shape.setOrigin(rec_size / 2.f);
			m_shape.setPosition(rec_size / 2.f);
			m_shape.setFillColor(settings::get_color_default_light());

			auto pos_x(150.f);
			for(auto& a : m_button_textures)
			{
				auto ptr(m_buttons.add_button<button_item>(m_buttonsize, vec2f{pos_x, m_shape.getPosition().y}));
				ptr->set_origin(m_buttonsize / 2.f);
				ptr->set_texture(&a);
				pos_x += 100.f;
			}

			m_buttons.on_active_button =
			[this](ui::base_btn_ptr& b)
			{
				b->set_color(settings::get_color_light());
				b->set_outlinecolor(settings::get_color_light());
				on_item_click(b);
			};

			m_buttons.on_inactive_button =
			[](ui::base_btn_ptr& b)
			{
				b->set_color(settings::get_color_default_dark());
				b->set_outlinecolor(settings::get_color_default_dark());
			};
		}
	};
}

#endif // RJ_GAME_EDITOR_ITEMBAR_HPP
<commit_msg>itembar: adding the textures manualy with the right entity_figure 'index'<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_ITEMBAR_HPP
#define RJ_GAME_EDITOR_ITEMBAR_HPP

#include "button_item.hpp"
#include <rectojump/game/entity_groups.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>
#include <rectojump/ui/connected_buttons.hpp>

namespace rj
{
	template<typename Game_Handler>
	class itembar
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		data_manager& m_datamgr;

		sf::RectangleShape m_shape;
		std::vector<sf::Texture> m_button_textures;
		ui::connected_buttons m_buttons;
		const vec2f m_buttonsize{64.f, 64.f};

	public:
		mlk::slot<ui::base_btn_ptr&> on_item_click;

		itembar(Game_Handler& gh, const vec2f& size) :
			m_gamehandler{gh},
			m_render{gh.get_render()},
			m_datamgr{gh.get_datamgr()},
			m_shape{size}
		{this->init();}

		void update(dur duration)
		{
			m_buttons.update(duration);
		}

		void render()
		{m_render(m_shape, m_buttons);}

		void deselect_all() noexcept
		{m_buttons.inactivate();}

		const sf::Texture& get_current_texture() const noexcept
		{return *m_buttons.get_active_btn()->get_texture();}

		entity_figure get_current_figure() const noexcept
		{return std::static_pointer_cast<button_item>(m_buttons.get_active_btn())->get_figure();}

		auto get_bounds() const noexcept
		-> decltype(m_shape.getGlobalBounds())
		{return m_shape.getGlobalBounds();}

		const vec2f& get_size() const noexcept
		{return m_shape.getSize();}

	private:
		void init()
		{
			auto& rec_size(m_shape.getSize());
			m_shape.setOrigin(rec_size / 2.f);
			m_shape.setPosition(rec_size / 2.f);
			m_shape.setFillColor(settings::get_color_default_light());

			m_button_textures.emplace_back(m_datamgr.get_as<sf::Texture>("editor_item_rect.png"));
			m_button_textures.emplace_back(m_datamgr.get_as<sf::Texture>("editor_item_triangle.png"));
			m_button_textures.emplace_back(m_datamgr.get_as<sf::Texture>("editor_item_triangles4.png"));

			auto pos_x(150.f);
			std::size_t index{0};
			for(auto& a : m_button_textures)
			{
				auto rect_ptr(m_buttons.add_button<button_item>(m_buttonsize, vec2f{pos_x, m_shape.getPosition().y}));
				rect_ptr->set_origin(m_buttonsize / 2.f);
				rect_ptr->set_texture(&a);
				rect_ptr->set_figure(static_cast<entity_figure>(index));
				pos_x += 100.f;
				++index;
			}

			m_buttons.on_active_button =
			[this](ui::base_btn_ptr& b)
			{
				b->set_color(settings::get_color_light());
				b->set_outlinecolor(settings::get_color_light());
			};

			m_buttons.on_inactive_button =
			[](ui::base_btn_ptr& b)
			{
				b->set_color(settings::get_color_default_dark());
				b->set_outlinecolor(settings::get_color_default_dark());
			};

			m_buttons.on_press = [this](ui::base_btn_ptr& b){on_item_click(b);};
		}
	};
}

#endif // RJ_GAME_EDITOR_ITEMBAR_HPP
<|endoftext|>


<commit_before>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_ITEMBAR_HPP
#define RJ_GAME_EDITOR_ITEMBAR_HPP

#include "button_item.hpp"
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>
#include <rectojump/ui/connected_buttons.hpp>

namespace rj
{
	template<typename Game_Handler>
	class itembar
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		data_manager& m_datamgr;

		sf::RectangleShape m_shape;
		std::vector<sf::Texture> m_button_textures;
		connected_buttons m_buttons;
		const vec2f m_buttonsize{64.f, 64.f};

	public:
		mlk::slot<base_btn_ptr&> on_item_click;

		itembar(Game_Handler& gh) :
			m_gamehandler{gh},
			m_render{gh.get_render()},
			m_datamgr{gh.get_datamgr()},
			m_button_textures{m_datamgr.get_all_containing_as<sf::Texture>("editor_item")}
		{this->init();}

		void update(dur duration)
		{
			m_buttons.update(duration);
		}

		void render()
		{m_render(m_shape, m_buttons);}

		void deselect_all() noexcept
		{m_buttons.inactivate();}

		const sf::Texture& get_current_texture() const noexcept
		{return *m_buttons.get_active_btn()->get_texture();}

		auto get_bounds() const noexcept
		-> decltype(m_shape.getGlobalBounds())
		{return m_shape.getGlobalBounds();}

	private:
		void init()
		{
			auto window_size(settings::get_window_size<vec2f>());
			vec2f rec_size{window_size.x, 100.f};
			m_shape.setOrigin(rec_size / 2.f);
			m_shape.setSize(rec_size);
			m_shape.setPosition({window_size.x / 2.f, window_size.y - rec_size.y / 2.f});
			m_shape.setFillColor(settings::get_color_default_light());

			auto pos_x(150.f);
			for(auto& a : m_button_textures)
			{
				auto ptr(m_buttons.add_button<button_item>(m_buttonsize, vec2f{pos_x, m_shape.getPosition().y}));
				ptr->set_origin(m_buttonsize / 2.f);
				ptr->set_texture(&a);
				pos_x += 100.f;
			}

			m_buttons.on_active_button =
			[this](base_btn_ptr& b)
			{
				b->set_color(settings::get_color_light());
				b->set_outlinecolor(settings::get_color_light());
				on_item_click(b);
			};

			m_buttons.on_inactive_button =
			[](base_btn_ptr& b)
			{
				b->set_color(settings::get_color_default_dark());
				b->set_outlinecolor(settings::get_color_default_dark());
			};
		}
	};
}

#endif // RJ_GAME_EDITOR_ITEMBAR_HPP
<commit_msg>editor - itembar: adapted positions to camera<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_ITEMBAR_HPP
#define RJ_GAME_EDITOR_ITEMBAR_HPP

#include "button_item.hpp"
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>
#include <rectojump/ui/connected_buttons.hpp>

namespace rj
{
	template<typename Game_Handler>
	class itembar
	{
		Game_Handler& m_gamehandler;
		rndr& m_render;
		data_manager& m_datamgr;

		sf::RectangleShape m_shape;
		std::vector<sf::Texture> m_button_textures;
		connected_buttons m_buttons;
		const vec2f m_buttonsize{64.f, 64.f};

	public:
		mlk::slot<base_btn_ptr&> on_item_click;

		itembar(Game_Handler& gh, const vec2f& size) :
			m_gamehandler{gh},
			m_render{gh.get_render()},
			m_datamgr{gh.get_datamgr()},
			m_shape{size},
			m_button_textures{m_datamgr.get_all_containing_as<sf::Texture>("editor_item")}
		{this->init();}

		void update(dur duration)
		{
			m_buttons.update(duration);
		}

		void render()
		{m_render(m_shape, m_buttons);}

		void deselect_all() noexcept
		{m_buttons.inactivate();}

		const sf::Texture& get_current_texture() const noexcept
		{return *m_buttons.get_active_btn()->get_texture();}

		auto get_bounds() const noexcept
		-> decltype(m_shape.getGlobalBounds())
		{return m_shape.getGlobalBounds();}

	private:
		void init()
		{
			auto window_size(settings::get_window_size<vec2f>());
			auto& rec_size(m_shape.getSize());
			m_shape.setOrigin(rec_size / 2.f);
			m_shape.setPosition({window_size.x / 2.f, rec_size.y / 2.f});
			m_shape.setFillColor(settings::get_color_default_light());

			auto pos_x(150.f);
			for(auto& a : m_button_textures)
			{
				auto ptr(m_buttons.add_button<button_item>(m_buttonsize, vec2f{pos_x, m_shape.getPosition().y}));
				ptr->set_origin(m_buttonsize / 2.f);
				ptr->set_texture(&a);
				pos_x += 100.f;
			}

			m_buttons.on_active_button =
			[this](base_btn_ptr& b)
			{
				b->set_color(settings::get_color_light());
				b->set_outlinecolor(settings::get_color_light());
				on_item_click(b);
			};

			m_buttons.on_inactive_button =
			[](base_btn_ptr& b)
			{
				b->set_color(settings::get_color_default_dark());
				b->set_outlinecolor(settings::get_color_default_dark());
			};
		}
	};
}

#endif // RJ_GAME_EDITOR_ITEMBAR_HPP
<|endoftext|>