<commit_before>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <cstring>

#include <functional>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

constexpr auto const default_forwarder_noexcept =
#if __cpp_exceptions
false;
#else
true;
#endif // __cpp_exceptions

constexpr auto const default_forwarder_size = 4 * sizeof(void*);

template <typename F,
  ::std::size_t N = default_forwarder_size,
  bool NE = default_forwarder_noexcept
>
class forwarder;

template <typename R, typename ...A, ::std::size_t N, bool NE>
class forwarder<R (A...), N, NE> : public detail::forwarder::argument_types
{
  R (*stub_)(void const*, A&&...) noexcept(NE) {};

  ::std::aligned_storage_t<N> store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type = R;

  static constexpr auto const size = N;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder(F&& f) noexcept
  {
    assign(::std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder& operator=(F&& f) noexcept
  {
    assign(::std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward(args)...)))
  {
    //assert(stub_);
    return stub_(&store_, ::std::forward(args)...);
  }

  void assign(::std::nullptr_t) noexcept
  {
    reset();
  }

  template <typename F>
  void assign(F&& f) noexcept
  {
    using functor_type = ::std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<F>(f));

    stub_ = [](void const* const ptr, A&&... args) noexcept(
        noexcept(
        (
#if __cplusplus <= 201402L
          (*static_cast<functor_type const*>(ptr))(
            ::std::forward(args)...)
#else
          ::std::invoke(*static_cast<functor_type const*>(ptr),
            ::std::forward(args)...)
#endif // __cplusplus
        )
      )
    ) -> R
    {
#if __cplusplus <= 201402L
      return (*static_cast<functor_type const*>(ptr))(
        ::std::forward(args)...);
#else
      return ::std::invoke(*static_cast<functor_type const*>(ptr),
        ::std::forward(args)...);
#endif // __cplusplus
    };
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <cstring>

#include <functional>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

constexpr auto const default_forwarder_noexcept =
#if __cpp_exceptions
false;
#else
true;
#endif // __cpp_exceptions

constexpr auto const default_forwarder_size = 4 * sizeof(void*);

template <typename F,
  ::std::size_t N = default_forwarder_size,
  bool NE = default_forwarder_noexcept
>
class forwarder;

template <typename R, typename ...A, ::std::size_t N, bool NE>
class forwarder<R (A...), N, NE> : public detail::forwarder::argument_types
{
  R (*stub_)(void*, A&&...) noexcept(NE) {};

  ::std::aligned_storage_t<N> store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type = R;

  static constexpr auto const size = N;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder(F&& f) noexcept
  {
    assign(::std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder& operator=(F&& f) noexcept
  {
    assign(::std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward(args)...)))
  {
    //assert(stub_);
    return stub_(const_cast<void*>(static_cast<void const*>(&store_)),
      ::std::forward(args)...
    );
  }

  void assign(::std::nullptr_t) noexcept
  {
    reset();
  }

  template <typename F>
  void assign(F&& f) noexcept
  {
    using functor_type = ::std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<F>(f));

    stub_ = [](void* const ptr, A&&... args) noexcept(
        noexcept(
        (
#if __cplusplus <= 201402L
          (*static_cast<functor_type*>(ptr))(
            ::std::forward(args)...)
#else
          ::std::invoke(*static_cast<functor_type*>(ptr),
            ::std::forward(args)...)
#endif // __cplusplus
        )
      )
    ) -> R
    {
#if __cplusplus <= 201402L
      return (*static_cast<functor_type*>(ptr))(
        ::std::forward(args)...);
#else
      return ::std::invoke(*static_cast<functor_type*>(ptr),
        ::std::forward(args)...);
#endif // __cplusplus
    };
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<|endoftext|>


<commit_before>#ifndef GNR_FORWARDER_HPP
# define GNR_FORWARDER_HPP
# pragma once

#include <cassert>

// std::size_t
#include <cstddef>

#include <functional>

#include <type_traits>

#include <utility>

namespace gnr
{

namespace detail::forwarder
{

enum : std::size_t { default_size = 4 * sizeof(void*) };

template <typename, std::size_t, bool>
class forwarder_impl2;

template <typename R, typename ...A, std::size_t N, bool E>
class forwarder_impl2<R (A...), N, E>
{
protected:
  R (*stub_)(void*, A&&...) noexcept(E) {};

  std::aligned_storage_t<N> store_;

public:
  using result_type = R;

public:
  R operator()(A... args) const noexcept(E)
  {
    //assert(stub_);
    return stub_(const_cast<decltype(store_)*>(std::addressof(store_)),
      std::forward<A>(args)...);
  }

  template <typename F,
    typename = std::enable_if_t<std::is_invocable_r_v<R, F, A...>>
  >
  void assign(F&& f)
#ifndef __GNUC__
  noexcept(noexcept(std::decay_t<F>(std::forward<F>(f))))
#endif
  {
    using functor_type = std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (std::addressof(store_)) functor_type(std::forward<F>(f));

    stub_ = [](void* const ptr, A&&... args) noexcept(E) -> R
    {
      return std::invoke(*static_cast<functor_type*>(ptr),
        std::forward<A>(args)...);
    };
  }
};

template <typename, std::size_t>
class forwarder_impl;

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...), N> :
  public forwarder_impl2<R (A...), N, false>
{
};

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...) noexcept, N> :
  public forwarder_impl2<R (A...), N, true>
{
};

}

template <typename A, std::size_t N = detail::forwarder::default_size>
class forwarder : public detail::forwarder::forwarder_impl<A, N>
{
  using inherited_t = detail::forwarder::forwarder_impl<A, N>;

public:
  enum : std::size_t { size = N };

  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F,
    typename = std::enable_if_t<
      !std::is_same_v<std::decay_t<F>, forwarder> &&
      std::is_invocable_v<
        decltype(&inherited_t::template assign<F>), inherited_t&, F
      >
    >
  >
  forwarder(F&& f) noexcept(noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    inherited_t::assign(std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F>
  forwarder& operator=(F&& f) noexcept(
    noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    static_assert(std::is_invocable_v<
        decltype(&inherited_t::template assign<F>), inherited_t&, F
      >
    );

    inherited_t::assign(std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept
  {
    return inherited_t::stub_;
  }

  bool operator==(std::nullptr_t) noexcept
  {
    return *this;
  }

  bool operator!=(std::nullptr_t) noexcept
  {
    return !operator==(nullptr);
  }

  void assign(std::nullptr_t) noexcept
  {
    reset();
  }

  void reset() noexcept
  {
    inherited_t::stub_ = {};
  }

  void swap(forwarder& other) noexcept
  {
    std::swap(*this, other);
  }

  void swap(forwarder&& other) noexcept
  {
    std::swap(*this, std::move(other));
  }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(std::addressof(inherited_t::store_));
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(std::addressof(inherited_t::store_));
  }
};

}

#endif // GNR_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GNR_FORWARDER_HPP
# define GNR_FORWARDER_HPP
# pragma once

#include <cassert>

// std::size_t
#include <cstddef>

#include <functional>

#include <type_traits>

#include <utility>

namespace gnr
{

namespace detail::forwarder
{

enum : std::size_t { default_size = 4 * sizeof(void*) };

template <typename, std::size_t, bool>
class forwarder_impl2;

template <typename R, typename ...A, std::size_t N, bool E>
class forwarder_impl2<R (A...), N, E>
{
protected:
  R (*stub_)(void*, A&&...) noexcept(E) {};

  std::aligned_storage_t<N> store_;

public:
  using result_type = R;

public:
  R operator()(A... args) const noexcept(E)
  {
    //assert(stub_);
    return stub_(const_cast<decltype(store_)*>(std::addressof(store_)),
      std::forward<A>(args)...);
  }

  template <typename F,
    typename = std::enable_if_t<std::is_invocable_r_v<R, F, A...>>
  >
  void assign(F&& f)
#if !defined(__GNUC__) || defined(__clang__)
  noexcept(noexcept(std::decay_t<F>(std::forward<F>(f))))
#endif
  {
    using functor_type = std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (std::addressof(store_)) functor_type(std::forward<F>(f));

    stub_ = [](void* const ptr, A&&... args) noexcept(E) -> R
    {
      return std::invoke(*static_cast<functor_type*>(ptr),
        std::forward<A>(args)...);
    };
  }
};

template <typename, std::size_t>
class forwarder_impl;

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...), N> :
  public forwarder_impl2<R (A...), N, false>
{
};

template <typename R, typename ...A, std::size_t N>
class forwarder_impl<R (A...) noexcept, N> :
  public forwarder_impl2<R (A...), N, true>
{
};

}

template <typename A, std::size_t N = detail::forwarder::default_size>
class forwarder : public detail::forwarder::forwarder_impl<A, N>
{
  using inherited_t = detail::forwarder::forwarder_impl<A, N>;

public:
  enum : std::size_t { size = N };

  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F,
    typename = std::enable_if_t<
      !std::is_same_v<std::decay_t<F>, forwarder> &&
      std::is_invocable_v<
        decltype(&inherited_t::template assign<F>), inherited_t&, F
      >
    >
  >
  forwarder(F&& f) noexcept(noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    inherited_t::assign(std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F>
  forwarder& operator=(F&& f) noexcept(
    noexcept(inherited_t::assign(std::forward<F>(f))))
  {
    static_assert(std::is_invocable_v<
        decltype(&inherited_t::template assign<F>), inherited_t&, F
      >
    );

    inherited_t::assign(std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept
  {
    return inherited_t::stub_;
  }

  bool operator==(std::nullptr_t) noexcept
  {
    return *this;
  }

  bool operator!=(std::nullptr_t) noexcept
  {
    return !operator==(nullptr);
  }

  void assign(std::nullptr_t) noexcept
  {
    reset();
  }

  void reset() noexcept
  {
    inherited_t::stub_ = {};
  }

  void swap(forwarder& other) noexcept
  {
    std::swap(*this, other);
  }

  void swap(forwarder&& other) noexcept
  {
    std::swap(*this, std::move(other));
  }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(std::addressof(inherited_t::store_));
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(std::addressof(inherited_t::store_));
  }
};

}

#endif // GNR_FORWARDER_HPP
<|endoftext|>


<commit_before>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <cstring>

#include <functional>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

constexpr auto const default_forwarder_noexcept =
#if __cpp_exceptions
false;
#else
true;
#endif // __cpp_exceptions

constexpr auto const default_forwarder_size = 4 * sizeof(void*);

template <typename F,
  ::std::size_t N = default_forwarder_size,
  bool NE = default_forwarder_noexcept
>
class forwarder;

template <typename R, typename ...A, ::std::size_t N, bool NE>
class forwarder<R (A...), N, NE> : public detail::forwarder::argument_types
{
  R (*stub_)(void*, A&&...) noexcept(NE) {};

  ::std::aligned_storage_t<N> store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type = R;

  static constexpr auto const size = N;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder(F&& f) noexcept
  {
    assign(::std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder& operator=(F&& f) noexcept
  {
    assign(::std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(noexcept(stub_(&store_, ::std::forward(args)...)))
  {
    //assert(stub_);
    return stub_(const_cast<void*>(static_cast<void const*>(&store_)),
      ::std::forward(args)...
    );
  }

  void assign(::std::nullptr_t) noexcept
  {
    reset();
  }

  template <typename F>
  void assign(F&& f) noexcept
  {
    using functor_type = ::std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<F>(f));

    stub_ = [](void* const ptr, A&&... args) noexcept(
        noexcept(
        (
#if __cplusplus <= 201402L
          (*static_cast<functor_type*>(ptr))(
            ::std::forward(args)...)
#else
          ::std::invoke(*static_cast<functor_type*>(ptr),
            ::std::forward(args)...)
#endif // __cplusplus
        )
      )
    ) -> R
    {
#if __cplusplus <= 201402L
      return (*static_cast<functor_type*>(ptr))(
        ::std::forward(args)...);
#else
      return ::std::invoke(*static_cast<functor_type*>(ptr),
        ::std::forward(args)...);
#endif // __cplusplus
    };
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<commit_msg>some fixes<commit_after>#ifndef GENERIC_FORWARDER_HPP
# define GENERIC_FORWARDER_HPP
# pragma once

#include <cassert>

// ::std::size_t
#include <cstddef>

#include <cstring>

#include <functional>

#include <type_traits>

#include <utility>

namespace generic
{

namespace detail
{

namespace forwarder
{

template <typename ...A>
struct argument_types
{
};

template <typename A>
struct argument_types
{
  using argument_type = A;
};

template <typename A, typename B>
struct argument_types
{
  using first_argument_type = A;
  using second_argument_type = B;
};

}

}

constexpr auto const default_forwarder_noexcept =
#if __cpp_exceptions
false;
#else
true;
#endif // __cpp_exceptions

constexpr auto const default_forwarder_size = 4 * sizeof(void*);

template <typename F,
  ::std::size_t N = default_forwarder_size,
  bool NE = default_forwarder_noexcept
>
class forwarder;

template <typename R, typename ...A, ::std::size_t N, bool NE>
class forwarder<R (A...), N, NE> : public detail::forwarder::argument_types
{
  R (*stub_)(void*, A&&...) noexcept(NE) {};

  ::std::aligned_storage_t<N> store_;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator==(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(forwarder<T (U...), M> const&,
    ::std::nullptr_t) noexcept;
  template<typename T, typename ...U, ::std::size_t M>
  friend bool operator!=(::std::nullptr_t,
    forwarder<T (U...), M> const&) noexcept;

public:
  using result_type = R;

  static constexpr auto const size = N;

public:
  forwarder() = default;

  forwarder(forwarder const&) = default;

  forwarder(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder(F&& f) noexcept
  {
    assign(::std::forward<F>(f));
  }

  forwarder& operator=(forwarder const&) = default;

  forwarder& operator=(forwarder&&) = default;

  template <typename F, typename =
    ::std::enable_if_t<!::std::is_same<::std::decay_t<F>, forwarder>{}>
  >
  forwarder& operator=(F&& f) noexcept
  {
    assign(::std::forward<F>(f));

    return *this;
  }

  explicit operator bool() const noexcept { return stub_; }

  R operator()(A... args) const
    noexcept(
        noexcept(stub_(const_cast<void*>(static_cast<void const*>(&store_)),
          ::std::forward(args)...
        )
      )
    )
  {
    //assert(stub_);
    return stub_(const_cast<void*>(static_cast<void const*>(&store_)),
      ::std::forward(args)...
    );
  }

  void assign(::std::nullptr_t) noexcept
  {
    reset();
  }

  template <typename F>
  void assign(F&& f) noexcept
  {
    using functor_type = ::std::decay_t<F>;

    static_assert(sizeof(functor_type) <= sizeof(store_),
      "functor too large");
    static_assert(::std::is_trivially_copyable<functor_type>{},
      "functor not trivially copyable");

    ::new (static_cast<void*>(&store_)) functor_type(::std::forward<F>(f));

    stub_ = [](void* const ptr, A&&... args) noexcept(
        noexcept(
        (
#if __cplusplus <= 201402L
          (*static_cast<functor_type*>(ptr))(
            ::std::forward(args)...)
#else
          ::std::invoke(*static_cast<functor_type*>(ptr),
            ::std::forward(args)...)
#endif // __cplusplus
        )
      )
    ) -> R
    {
#if __cplusplus <= 201402L
      return (*static_cast<functor_type*>(ptr))(
        ::std::forward(args)...);
#else
      return ::std::invoke(*static_cast<functor_type*>(ptr),
        ::std::forward(args)...);
#endif // __cplusplus
    };
  }

  void reset() noexcept { stub_ = nullptr; }

  void swap(forwarder& other) noexcept { ::std::swap(*this, other); }

  template <typename T>
  auto target() noexcept
  {
    return reinterpret_cast<T*>(&store_);
  }

  template <typename T>
  auto target() const noexcept
  {
    return reinterpret_cast<T const*>(&store_);
  }
};

template<typename R, typename ...A, ::std::size_t N>
bool operator==(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator==(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return f.stub_ == nullptr;
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(forwarder<R (A...), N> const& f,
  ::std::nullptr_t const) noexcept
{
  return !operator==(f, nullptr);
}

template<typename R, typename ...A, ::std::size_t N>
bool operator!=(::std::nullptr_t const,
  forwarder<R (A...), N> const& f) noexcept
{
  return !operator==(f, nullptr);
}

}

#endif // GENERIC_FORWARDER_HPP
<|endoftext|>


<commit_before>#include <rbutil/conf/cmd/command_line.hpp>
#include <pito/interceptor/application.hpp>
#include <pito/config.hpp>

#include <iostream>

#define PITO_PROGRAM_VERSION "0.9.1"

namespace pito {

namespace jail = interceptor::jail;
namespace cmd_line = rb::util::conf::cmd;
using rb::util::conf::value;

bool verbose = false;

inline int main(int argc, char *argv[]) {
    {
        using cmd_line::options_description;
        // TODO: make all arguments from second positional and inclusive the
        //       new argv/argc
        options_description options;

        bool showHelp = false;
        bool silent = false;
        options.add_options()
            ("v,verbose", verbose, "increase verbosity")
            .help("pito " PITO_PROGRAM_VERSION "\nusage: pito [arguments] "
                  "<wrapper library name> <program> [program arguments]")
            ("s,silent", silent, "don't say anything")
            ("l,library-dir", value(jail::preload), "pito library directory")
            ;

        try {
            int nPositionals = silent ?
                cmd_line::parser(argc, argv, options)().n_positionals() :
                cmd_line::parser(argc, argv, options)(std::cerr).n_positionals();

            if (nPositionals < 2) {
                if (! silent) {
                    if (1 == nPositionals)
                        std::cout << "missing <program> argument, see --help" << std::endl;
                    else
                        std::cout << "missing <wrapper library name> and <program> arguments, see --help" << std::endl;
                }
                return 1;
            }
        }
        catch (cmd_line::invalid_arguments& ) {
            return 1;
        }

        std::string libraryFileName = "libpito_";
        libraryFileName.append(argv[1]);

        interceptor::search_for_preload_library(libraryFileName, jail::preload, jail::preload);

        if (jail::preload.empty()) {
            if (! silent) std::cerr << "library " << libraryFileName << " could not be found at"
                                    " install location or in $" PITO_LD_LIBRARY_PATH << std::endl;
        }
        else {
            if (verbose) std::cerr << "load interceptor library (" << jail::preload << ")" << std::endl;
            jail::enforce_environment();
            // consider setting argv[2] based on path and use execv
            execvp(argv[2], argv + 2);
        }
        return 1;
    }
}

}

int main(int argc, char *argv[]) {
    return pito::main(argc, argv);
}
<commit_msg>display help after bad options<commit_after>#include <rbutil/conf/cmd/command_line.hpp>
#include <pito/interceptor/application.hpp>
#include <pito/config.hpp>

#include <iostream>

#define PITO_PROGRAM_VERSION "0.9.1"

namespace pito {

namespace jail = interceptor::jail;
namespace cmd_line = rb::util::conf::cmd;
using rb::util::conf::value;

bool verbose = false;

inline int main(int argc, char *argv[]) {
    {
        using cmd_line::options_description;
        // TODO: make all arguments from second positional and inclusive the
        //       new argv/argc
        options_description options;

        bool showHelp = false;
        bool silent = false;
        options.add_options()
            ("v,verbose", verbose, "increase verbosity")
            .help("pito " PITO_PROGRAM_VERSION "\nusage: pito [arguments] "
                  "<wrapper library name> <program> [program arguments]")
            ("s,silent", silent, "don't say anything")
            ("l,library-dir", value(jail::preload), "pito library directory")
            ;

        try {
            int nPositionals = silent ?
                cmd_line::parser(argc, argv, options)().n_positionals() :
                cmd_line::parser(argc, argv, options)(std::cerr).n_positionals();

            if (nPositionals < 2) {
                if (! silent) {
                    if (1 == nPositionals)
                        std::cerr << "missing <program> argument" << std::endl;
                    else
                        std::cerr << "missing <wrapper library name> and <program> arguments" << std::endl;
                    std::cerr << options << std::endl;
                }
                return 1;
            }
        }
        catch (cmd_line::invalid_arguments& ) {
            return 1;
        }

        std::string libraryFileName = "libpito_";
        libraryFileName.append(argv[1]);

        interceptor::search_for_preload_library(libraryFileName, jail::preload, jail::preload);

        if (jail::preload.empty()) {
            if (! silent) std::cerr << "library " << libraryFileName << " could not be found at"
                                    " install location or in $" PITO_LD_LIBRARY_PATH << std::endl;
        }
        else {
            if (verbose) std::cerr << "load interceptor library (" << jail::preload << ")" << std::endl;
            jail::enforce_environment();
            // consider setting argv[2] based on path and use execv
            execvp(argv[2], argv + 2);
        }
        return 1;
    }
}

}

int main(int argc, char *argv[]) {
    return pito::main(argc, argv);
}
<|endoftext|>


<commit_before>/******************************************************************************
* Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "stateevent.h"

using namespace QMatrixClient;

// Aside from the normal factory to instantiate StateEventBase inheritors
// StateEventBase itself can be instantiated if there's a state_key JSON key
// but the event type is unknown.
[[gnu::unused]] static auto stateEventTypeInitialised =
    RoomEvent::factory_t::addMethod(
        [] (const QJsonObject& json, const QString& matrixType)
        {
            if (auto e = StateEventBase::factory_t::make(json, matrixType))
                return e;
            return json.contains("state_key")
                   ? makeEvent<StateEventBase>(unknownEventTypeId(), json)
                   : nullptr;
        });

bool StateEventBase::repeatsState() const
{
    const auto prevContentJson = unsignedJson().value(PrevContentKeyL);
    return fullJson().value(ContentKeyL) == prevContentJson;
}

QString StateEventBase::replacedState() const
{
    return unsignedJson().value("replaces_state"_ls).toString();
}

void StateEventBase::dumpTo(QDebug dbg) const
{
    if (!stateKey().isEmpty())
        dbg << '<' << stateKey() << "> ";
    if (unsignedJson().contains(PrevContentKeyL))
        dbg << QJsonDocument(unsignedJson()[PrevContentKeyL].toObject())
               .toJson(QJsonDocument::Compact) << " -> ";
    RoomEvent::dumpTo(dbg);
}
<commit_msg>Security fix: require that state events have state_key<commit_after>/******************************************************************************
* Copyright (C) 2018 Kitsune Ral <kitsune-ral@users.sf.net>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "stateevent.h"

using namespace QMatrixClient;

// Aside from the normal factory to instantiate StateEventBase inheritors
// StateEventBase itself can be instantiated if there's a state_key JSON key
// but the event type is unknown.
[[gnu::unused]] static auto stateEventTypeInitialised =
    RoomEvent::factory_t::addMethod(
        [] (const QJsonObject& json, const QString& matrixType) -> StateEventPtr
        {
            if (!json.contains("state_key"))
                return nullptr;

            if (auto e = StateEventBase::factory_t::make(json, matrixType))
                return e;

            return makeEvent<StateEventBase>(unknownEventTypeId(), json);
        });

bool StateEventBase::repeatsState() const
{
    const auto prevContentJson = unsignedJson().value(PrevContentKeyL);
    return fullJson().value(ContentKeyL) == prevContentJson;
}

QString StateEventBase::replacedState() const
{
    return unsignedJson().value("replaces_state"_ls).toString();
}

void StateEventBase::dumpTo(QDebug dbg) const
{
    if (!stateKey().isEmpty())
        dbg << '<' << stateKey() << "> ";
    if (unsignedJson().contains(PrevContentKeyL))
        dbg << QJsonDocument(unsignedJson()[PrevContentKeyL].toObject())
               .toJson(QJsonDocument::Compact) << " -> ";
    RoomEvent::dumpTo(dbg);
}
<|endoftext|>


<commit_before>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
#ident "Copyright (c) 2011 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include <config.h>
#include <toku_pthread.h>
#include "kibbutz.h"
#include "includes.h"

// A Kibbutz is a collection of workers and some work to do.
struct todo {
    void (*f)(void *extra);
    void *extra;
    struct todo *next;
    struct todo *prev;
};

struct kid {
    struct kibbutz *k;
};

struct kibbutz {
    toku_mutex_t mutex;
    toku_cond_t  cond;
    bool please_shutdown;
    struct todo *head, *tail; // head is the next thing to do.
    int n_workers;
    pthread_t *workers; // an array of n_workers
    struct kid *ids;    // pass this in when creating a worker so it knows who it is.
};

static void *work_on_kibbutz (void *);

KIBBUTZ toku_kibbutz_create (int n_workers) {
    KIBBUTZ XMALLOC(k);
    toku_mutex_init(&k->mutex, NULL);
    toku_cond_init(&k->cond, NULL);
    k->please_shutdown = false;
    k->head = NULL;
    k->tail = NULL;
    k->n_workers = n_workers;
    XMALLOC_N(n_workers, k->workers);
    XMALLOC_N(n_workers, k->ids);
    for (int i=0; i<n_workers; i++) {
        k->ids[i].k = k;
        int r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]);
        assert(r==0);
    }
    return k;
}

static void klock (KIBBUTZ k) {
    toku_mutex_lock(&k->mutex);
}
static void kunlock (KIBBUTZ k) {
    toku_mutex_unlock(&k->mutex);
}
static void kwait (KIBBUTZ k) {
    toku_cond_wait(&k->cond, &k->mutex);
}
static void ksignal (KIBBUTZ k) {
    toku_cond_signal(&k->cond);
}

//
// pops the tail of the kibbutz off the list and works on it
// Note that in toku_kibbutz_enq, items are enqueued at the head,
// making the work be done in FIFO order. This is necessary
// to avoid deadlocks in flusher threads.
//
static void *work_on_kibbutz (void *kidv) {
    struct kid *CAST_FROM_VOIDP(kid, kidv);
    KIBBUTZ k = kid->k;
    klock(k);
    while (1) {
        while (k->tail) {
            struct todo *item = k->tail;
            k->tail = item->prev;
            if (k->tail==NULL) {
                k->head=NULL;
            } else {
                // if there are other things to do, then wake up the next guy, if there is one.
                ksignal(k);
            }
            kunlock(k);
            item->f(item->extra);
            toku_free(item);
            klock(k);
            // if there's another item on k->head, then we'll just go grab it now, without waiting for a signal.
        }
        if (k->please_shutdown) {
            // Don't follow this unless the work is all done, so that when we set please_shutdown, all the work finishes before any threads quit.
            ksignal(k); // must wake up anyone else who is waiting, so they can shut down.
            kunlock(k);
            return NULL;
        }
        // There is no work to do and it's not time to shutdown, so wait.
        kwait(k);
    }
}

//
// adds work to the head of the kibbutz
// Note that in work_on_kibbutz, items are popped off the tail for work,
// making the work be done in FIFO order. This is necessary
// to avoid deadlocks in flusher threads.
//
void toku_kibbutz_enq (KIBBUTZ k, void (*f)(void*), void *extra) {
    struct todo *XMALLOC(td);
    td->f = f;
    td->extra = extra;
    klock(k);
    assert(!k->please_shutdown);
    td->next = k->head;
    td->prev = NULL;
    if (k->head) {
        assert(k->head->prev == NULL);
        k->head->prev = td;
    }
    k->head = td;
    if (k->tail==NULL) k->tail = td;
    ksignal(k);
    kunlock(k);
}

void toku_kibbutz_destroy (KIBBUTZ k)
// Effect: wait for all the enqueued work to finish, and then destroy the kibbutz.
//  Note: It is an error for to perform kibbutz_enq operations after this is called.
{
    klock(k);
    assert(!k->please_shutdown);
    k->please_shutdown = true;
    ksignal(k); // must wake everyone up to tell them to shutdown.
    kunlock(k);
    for (int i=0; i<k->n_workers; i++) {
        void *result;
        int r = toku_pthread_join(k->workers[i], &result);
        assert(r==0);
        assert(result==NULL);
    }
    toku_free(k->workers);
    toku_free(k->ids);
    toku_cond_destroy(&k->cond);
    toku_mutex_destroy(&k->mutex);
    toku_free(k);
}
<commit_msg>refs #5507 clear kibbutz mutex<commit_after>/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
#ident "$Id$"
#ident "Copyright (c) 2011 Tokutek Inc.  All rights reserved."
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."

#include <config.h>
#include <toku_pthread.h>
#include "kibbutz.h"
#include "includes.h"

// A Kibbutz is a collection of workers and some work to do.
struct todo {
    void (*f)(void *extra);
    void *extra;
    struct todo *next;
    struct todo *prev;
};

struct kid {
    struct kibbutz *k;
};

struct kibbutz {
    toku_mutex_t mutex;
    toku_cond_t  cond;
    bool please_shutdown;
    struct todo *head, *tail; // head is the next thing to do.
    int n_workers;
    pthread_t *workers; // an array of n_workers
    struct kid *ids;    // pass this in when creating a worker so it knows who it is.
};

static void *work_on_kibbutz (void *);

KIBBUTZ toku_kibbutz_create (int n_workers) {
    KIBBUTZ XCALLOC(k);
    toku_mutex_init(&k->mutex, NULL);
    toku_cond_init(&k->cond, NULL);
    k->please_shutdown = false;
    k->head = NULL;
    k->tail = NULL;
    k->n_workers = n_workers;
    XMALLOC_N(n_workers, k->workers);
    XMALLOC_N(n_workers, k->ids);
    for (int i=0; i<n_workers; i++) {
        k->ids[i].k = k;
        int r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]);
        assert(r==0);
    }
    return k;
}

static void klock (KIBBUTZ k) {
    toku_mutex_lock(&k->mutex);
}
static void kunlock (KIBBUTZ k) {
    toku_mutex_unlock(&k->mutex);
}
static void kwait (KIBBUTZ k) {
    toku_cond_wait(&k->cond, &k->mutex);
}
static void ksignal (KIBBUTZ k) {
    toku_cond_signal(&k->cond);
}

//
// pops the tail of the kibbutz off the list and works on it
// Note that in toku_kibbutz_enq, items are enqueued at the head,
// making the work be done in FIFO order. This is necessary
// to avoid deadlocks in flusher threads.
//
static void *work_on_kibbutz (void *kidv) {
    struct kid *CAST_FROM_VOIDP(kid, kidv);
    KIBBUTZ k = kid->k;
    klock(k);
    while (1) {
        while (k->tail) {
            struct todo *item = k->tail;
            k->tail = item->prev;
            if (k->tail==NULL) {
                k->head=NULL;
            } else {
                // if there are other things to do, then wake up the next guy, if there is one.
                ksignal(k);
            }
            kunlock(k);
            item->f(item->extra);
            toku_free(item);
            klock(k);
            // if there's another item on k->head, then we'll just go grab it now, without waiting for a signal.
        }
        if (k->please_shutdown) {
            // Don't follow this unless the work is all done, so that when we set please_shutdown, all the work finishes before any threads quit.
            ksignal(k); // must wake up anyone else who is waiting, so they can shut down.
            kunlock(k);
            return NULL;
        }
        // There is no work to do and it's not time to shutdown, so wait.
        kwait(k);
    }
}

//
// adds work to the head of the kibbutz
// Note that in work_on_kibbutz, items are popped off the tail for work,
// making the work be done in FIFO order. This is necessary
// to avoid deadlocks in flusher threads.
//
void toku_kibbutz_enq (KIBBUTZ k, void (*f)(void*), void *extra) {
    struct todo *XMALLOC(td);
    td->f = f;
    td->extra = extra;
    klock(k);
    assert(!k->please_shutdown);
    td->next = k->head;
    td->prev = NULL;
    if (k->head) {
        assert(k->head->prev == NULL);
        k->head->prev = td;
    }
    k->head = td;
    if (k->tail==NULL) k->tail = td;
    ksignal(k);
    kunlock(k);
}

void toku_kibbutz_destroy (KIBBUTZ k)
// Effect: wait for all the enqueued work to finish, and then destroy the kibbutz.
//  Note: It is an error for to perform kibbutz_enq operations after this is called.
{
    klock(k);
    assert(!k->please_shutdown);
    k->please_shutdown = true;
    ksignal(k); // must wake everyone up to tell them to shutdown.
    kunlock(k);
    for (int i=0; i<k->n_workers; i++) {
        void *result;
        int r = toku_pthread_join(k->workers[i], &result);
        assert(r==0);
        assert(result==NULL);
    }
    toku_free(k->workers);
    toku_free(k->ids);
    toku_cond_destroy(&k->cond);
    toku_mutex_destroy(&k->mutex);
    toku_free(k);
}
<|endoftext|>


<commit_before>//WinAPI
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>

//Qt
#include <QtCore>

//Project
#include "functions.h"

bool isSubPath(const QString &dir, const QString &path)
{
    if ( dir.isEmpty() ) return false;

    QString nativeDir = QDir::toNativeSeparators(dir);
    QString nativePath = QDir::toNativeSeparators(path);

    if( nativeDir.lastIndexOf(QDir::separator()) != nativeDir.size()-1 )
    {
        nativeDir += QDir::separator();
    }

    return !nativePath.indexOf( nativeDir, Qt::CaseInsensitive );
}

bool getModulesListFromProcessID(qint32 PID, QList<QString> &modules)
{
    auto w2s = [](const wchar_t *str)->const QString
    {
        return QString::fromWCharArray( str );
    };

    MODULEENTRY32 me32;
    me32.dwSize = sizeof(MODULEENTRY32);

    HANDLE hSnap;
    hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
    if(hSnap != NULL)
    {
        if (Module32First(hSnap, &me32))
        {
            while(Module32Next(hSnap, &me32))
            {
                modules.append( w2s(me32.szExePath) );
            }

            CloseHandle(hSnap);
            return true;
        }
        CloseHandle(hSnap);
        return false;
    }

    return false;
}

bool getProcessList(QList<ProcessInfo> &list)
{
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

    if( hProcessSnap == INVALID_HANDLE_VALUE) return false;
    if( Process32First(hProcessSnap, &pe32) )
    {
        do
        {
            QString tmpName =  QString::fromWCharArray( pe32.szExeFile );
            qint32 tmpPID = pe32.th32ProcessID;
            list.append({tmpName, tmpPID});
        }
        while ( Process32Next(hProcessSnap, &pe32) );

        CloseHandle(hProcessSnap);
        return true;
    }

    CloseHandle(hProcessSnap);
    return false;
}

bool getFilePathFromPID(qint32 PID, QString &fileName)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, PID);
    if( hProcess == 0 ) return false;

    wchar_t bufPath[MAX_PATH+1]{};
    DWORD result = GetModuleFileNameEx(hProcess, NULL, bufPath, MAX_PATH);
    CloseHandle(hProcess);
    if( result == 0 ) return false;

    fileName = QString::fromWCharArray( bufPath );
    return true;
}

bool getPIDFromHWND(qint32 hWnd, qint32 &PID)
{
    DWORD tmpPID;
    DWORD result = GetWindowThreadProcessId( reinterpret_cast<HWND>(hWnd), &tmpPID);
    if( result == 0 ) return false;

    PID = tmpPID;
    return true;
}

bool getHWindowFromPoint(const QPoint &point, qint64 &hWnd)
{
    POINT tmpPoint = {point.x(), point.y()};
    HWND tmpHWnd = WindowFromPoint( tmpPoint );
    if( tmpHWnd == 0 ) return false;

    hWnd = reinterpret_cast<qint64>( tmpHWnd );
    return true;
}

QString getWinDir()
{
    return QString( qgetenv("WINDIR") );
}

bool copyFile(const QString &filePath, const QString &outDir)
{
    QFile file(filePath);
    QFileInfo fileInfo(file);
    QString copyFilePath = outDir + QDir::separator() + fileInfo.fileName();

    return file.copy( copyFilePath );
}
<commit_msg>Update code<commit_after>//WinAPI
#include <windows.h>
#include <psapi.h>
#include <tlhelp32.h>

//Qt
#include <QtCore>

//Project
#include "functions.h"

bool isSubPath(const QString &dir, const QString &path)
{
    if ( dir.isEmpty() ) return false;

    QString nativeDir = QDir::toNativeSeparators(dir);
    QString nativePath = QDir::toNativeSeparators(path);

    if( nativeDir.lastIndexOf(QDir::separator()) != nativeDir.size()-1 )
    {
        nativeDir += QDir::separator();
    }

    return !nativePath.indexOf( nativeDir, Qt::CaseInsensitive );
}

bool getModulesListFromProcessID(qint32 PID, QList<QString> &modules)
{
    auto w2s = [](const wchar_t *str)
    {
        return QString::fromWCharArray( str );
    };

    MODULEENTRY32 me32;
    me32.dwSize = sizeof(MODULEENTRY32);

    HANDLE hSnap;
    hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);
    if(hSnap != NULL)
    {
        if (Module32First(hSnap, &me32))
        {
            while(Module32Next(hSnap, &me32))
            {
                modules.append( w2s(me32.szExePath) );
            }

            CloseHandle(hSnap);
            return true;
        }
        CloseHandle(hSnap);
        return false;
    }

    return false;
}

bool getProcessList(QList<ProcessInfo> &list)
{
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);

    HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);

    if( hProcessSnap == INVALID_HANDLE_VALUE) return false;
    if( Process32First(hProcessSnap, &pe32) )
    {
        do
        {
            QString tmpName =  QString::fromWCharArray( pe32.szExeFile );
            qint32 tmpPID = pe32.th32ProcessID;
            list.append({tmpName, tmpPID});
        }
        while ( Process32Next(hProcessSnap, &pe32) );

        CloseHandle(hProcessSnap);
        return true;
    }

    CloseHandle(hProcessSnap);
    return false;
}

bool getFilePathFromPID(qint32 PID, QString &fileName)
{
    HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, PID);
    if( hProcess == 0 ) return false;

    wchar_t bufPath[MAX_PATH+1]{};
    DWORD result = GetModuleFileNameEx(hProcess, NULL, bufPath, MAX_PATH);
    CloseHandle(hProcess);
    if( result == 0 ) return false;

    fileName = QString::fromWCharArray( bufPath );
    return true;
}

bool getPIDFromHWND(qint32 hWnd, qint32 &PID)
{
    DWORD tmpPID;
    DWORD result = GetWindowThreadProcessId( reinterpret_cast<HWND>(hWnd), &tmpPID);
    if( result == 0 ) return false;

    PID = tmpPID;
    return true;
}

bool getHWindowFromPoint(const QPoint &point, qint64 &hWnd)
{
    POINT tmpPoint = {point.x(), point.y()};
    HWND tmpHWnd = WindowFromPoint( tmpPoint );
    if( tmpHWnd == 0 ) return false;

    hWnd = reinterpret_cast<qint64>( tmpHWnd );
    return true;
}

QString getWinDir()
{
    return QString( qgetenv("WINDIR") );
}

bool copyFile(const QString &filePath, const QString &outDir)
{
    QFile file(filePath);
    QFileInfo fileInfo(file);
    QString copyFilePath = outDir + QDir::separator() + fileInfo.fileName();

    return file.copy( copyFilePath );
}
<|endoftext|>


<commit_before>#pragma once

namespace oh {
  namespace math {

template<typename T>
T min(T a, T b) {
  return a < b ? a : b;
}

template<typename T>
T max(T a, T b) {
  return a > b ? a : b;
}

}}
// ~~ oh::math::
<commit_msg>Adding method for testing floating-point value equality.<commit_after>#pragma once

#include <cmath>
#include <limits>

namespace oh {
  namespace math {

const float PI_F = 3.14159265358979f;

inline bool IsEqual(float x, float y)
{
  return std::abs(x - y) <= std::numeric_limits<float>::epsilon() * std::abs(x);
}

template<typename T>
inline T min(T a, T b) {
  return a < b ? a : b;
}

template<typename T>
inline T max(T a, T b) {
  return a > b ? a : b;
}

}}
// ~~ oh::math::
<|endoftext|>


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

#include <cstdint>
#include <sstream>
#include <string>
#include <string_view>

namespace loxcc {

using nil_t   = std::nullptr_t;
using i8_t    = std::int8_t;
using u8_t    = std::uint8_t;
using i16_t   = std::int16_t;
using u16_t   = std::uint16_t;
using i32_t   = std::int32_t;
using u32_t   = std::uint32_t;
using i64_t   = std::int64_t;
using u64_t   = std::uint64_t;
using ssz_t   = std::int32_t;
using sz_t    = std::size_t;
using str_t   = std::string;
using strv_t  = std::string_view;

class Copyable {
protected:
  Copyable(void) noexcept = default;
  ~Copyable(void) noexcept = default;
};

class UnCopyable {
  UnCopyable(const UnCopyable&) noexcept = delete;
  UnCopyable& operator=(const UnCopyable&) noexcept = delete;
protected:
  UnCopyable(void) noexcept = default;
  ~UnCopyable(void) noexcept = default;
};

namespace Xt {
  template <typename I, typename E>
  inline I as_type(E x) { return static_cast<I>(x); }

  template <typename T, typename S>
  inline T* cast(S* x) { return static_cast<T*>(x); }

  template <typename T, typename S>
  inline T* down(S* x) { return dynamic_cast<T*>(x); }

  template <typename T, typename S>
  inline T* const_down(const S* x) { return down<T>(const_cast<S*>(x)); }

  inline u32_t hasher(const char* s, int n) {
    // FNV-1a hash. See: http://www.isthe.com/chongo/tech/comp/fnv/
    u32_t hash = 2166136261u;
    for (int i = 0; i < n; ++i) {
      hash ^= s[i];
      hash *= 16777619;
    }
    return hash;
  }

  template <typename T>
  inline double to_decimal(T x) { return static_cast<double>(x); }

  inline str_t to_string(double d) {
    std::stringstream ss;
    ss << d;
    return ss.str();
  }
}

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

#include <cstdint>
#include <sstream>
#include <string>
#include <string_view>

namespace loxcc {

using nil_t   = std::nullptr_t;
using i8_t    = std::int8_t;
using u8_t    = std::uint8_t;
using i16_t   = std::int16_t;
using u16_t   = std::uint16_t;
using i32_t   = std::int32_t;
using u32_t   = std::uint32_t;
using i64_t   = std::int64_t;
using u64_t   = std::uint64_t;
using ssz_t   = std::int32_t;
using sz_t    = std::size_t;
using str_t   = std::string;
using strv_t  = std::string_view;

class Copyable {
protected:
  Copyable(void) noexcept = default;
  ~Copyable(void) noexcept = default;
};

class UnCopyable {
  UnCopyable(const UnCopyable&) noexcept = delete;
  UnCopyable& operator=(const UnCopyable&) noexcept = delete;
protected:
  UnCopyable(void) noexcept = default;
  ~UnCopyable(void) noexcept = default;
};

namespace Xt {
  template <typename I, typename E>
  inline I as_type(E x) { return static_cast<I>(x); }

  template <typename T>
  inline T* as_ptr(const T* x) { return const_cast<T*>(x); }

  template <typename T, typename S>
  inline T* cast(S* x) { return static_cast<T*>(x); }

  template <typename T, typename S>
  inline T* down(S* x) { return dynamic_cast<T*>(x); }

  template <typename T, typename S>
  inline T* const_down(const S* x) { return down<T>(const_cast<S*>(x)); }

  inline u32_t hasher(const char* s, int n) {
    // FNV-1a hash. See: http://www.isthe.com/chongo/tech/comp/fnv/
    u32_t hash = 2166136261u;
    for (int i = 0; i < n; ++i) {
      hash ^= s[i];
      hash *= 16777619;
    }
    return hash;
  }

  template <typename T>
  inline double to_decimal(T x) { return static_cast<double>(x); }

  inline str_t to_string(double d) {
    std::stringstream ss;
    ss << d;
    return ss.str();
  }
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"

struct WaterVert
{
	Vec3 pos;
	Vec3 normal;
};

struct WaterRipple
{
	WaterRipple()
	{
		generatedTime = -10000;
	}
	double generatedTime;
	Vec2 centerPos;
};

struct WaterSurfaceClassicUBO {
	Mat matW, matV, matP;
	float time;
	float padding[3];
};

class WaterSurfaceES2
{
	WaterSurfaceClassicUBO uboBuf;
	AFRenderStates renderStateWater;
	AFRenderStates renderStatePostProcess;
	int lines;
	void UpdateVert(std::vector<WaterVert>& vert);
	void UpdateRipple();
	WaterRipple ripples[2];
	int ripplesNext;
	double elapsedTime = 0;
	double lastTime;
	double nextTime;
	VBOID vbo, vboFullScr;
	IBOID ibo, iboFullScr;
	VAOID vao, vaoFullScr;
	int nIndi;
	AFRenderTarget rt;
	std::vector<SRVID> texIds;
public:
	WaterSurfaceES2();
	~WaterSurfaceES2();
	void Destroy();
	void Init();
	void Update();
	void Draw();
	void CreateRipple(Vec2 pos);
};

static const char* waterSurfaceClassName = "WaterSurfaceES2";
#define GET_WSC \
	WaterSurfaceES2* p = (WaterSurfaceES2*)luaL_checkudata(L, 1, waterSurfaceClassName);	\
	if (!p) {	\
		return 0;	\
	}

class WaterSurfaceClassicBinder {
public:
	WaterSurfaceClassicBinder() {
		GetLuaBindFuncContainer().push_back([](lua_State* L) {
			static luaL_Reg methods[] = {
				{ "__gc", [](lua_State* L) { GET_WSC p->~WaterSurfaceES2(); return 0; } },
				{ "Update", [](lua_State* L) { GET_WSC p->Update(); return 0; } },
				{ "Draw", [](lua_State* L) { GET_WSC p->Draw(); return 0; }},
				{ nullptr, nullptr },
			};
			aflBindClass(L, waterSurfaceClassName, methods, [](lua_State* L) { void* u = lua_newuserdata(L, sizeof(WaterSurfaceES2)); new (u) WaterSurfaceES2(); return 1; });
		});
	}
} static waterSurfaceClassicBinder;

struct TexFiles
{
	const char *name;
};

static TexFiles texFiles[] = {
	{ "rose.jpg" },
	{ "autumn.jpg" },
	{ "pangyo.jpg" },
	{ "timeline.png" },
	{ "delaymap.png" },
	{ "sphere.jpg"},
};

const int tileMax = 50;
const int vertMax = tileMax + 1;
const float pitch = 2.0f / tileMax;
const float repeat = 2;
const float halflife = 1.5f;
//const float heightUnit = 0.00375f;
const float heightUnit = 0.02f;
const float rippleSpeed = 0.7f;
const float loopTime = 20.0;

static Vec3 MakePos(int x, int z, float hmap[vertMax][vertMax])
{
	float height = hmap[std::max(0,std::min(tileMax, x))][std::max(0,std::min(tileMax, z))];
	return Vec3(((float)x - tileMax / 2) * pitch, height, ((float)z - tileMax / 2) * pitch);
}

void WaterSurfaceES2::CreateRipple(Vec2 scrPos)
{
	Vec3 surfacePos = transform(Vec3(scrPos.x, scrPos.y, 0), inv(uboBuf.matV * uboBuf.matP));

	WaterRipple r;
	r.generatedTime = elapsedTime;
	r.centerPos = Vec2(surfacePos.x, surfacePos.y);
	ripples[ripplesNext++] = r;
	ripplesNext %= dimof(ripples);
}

void WaterSurfaceES2::UpdateVert(std::vector<WaterVert>& vert)
{
	struct RandWave {
		float degreePerSec;
		float xShift;
		float xMul;
		float timeMul;
		float strength;
	} static randWave[10];
	static bool t;
	if (!t) {
		t = true;
		for (int i = 0; i < (int)dimof(randWave); i++) {
			RandWave& r = randWave[i];
			r.degreePerSec = Random() * 15 - 7.5f;
			r.xShift = Random();
			r.xMul = 2 + std::pow(2.f, 1 + 3 * Random());
			r.timeMul = 2 + std::pow(2.f, 0.5f + 2 * Random());
			r.strength = 0.005f * std::pow(2.f, 0.1f + 0.3f * Random());
		}
	}
	float hmap[vertMax][vertMax];
	memset(hmap, 0, sizeof(hmap));
	for (int z = 0; z <= tileMax; z++) {
		for (int x = 0; x <= tileMax; x++) {
			Vec2 pos = Vec2((float)x, (float)z) / (float)tileMax * 2.0f - Vec2(1, 1);
			for (int i = 0; i < (int)dimof(ripples); i++) {
				const WaterRipple& r = ripples[i];
				float lifeTime = (float)(elapsedTime - r.generatedTime);
				float timeAfterArrived = lifeTime - length(r.centerPos - pos) / rippleSpeed;
				float h = timeAfterArrived > 0 ? std::sin(timeAfterArrived * ((float)M_PI * 2) * repeat) * heightUnit : 0;
				h *= std::min(1.0f, std::pow(0.5f, lifeTime / halflife));

				hmap[x][z] += h;
			}
#if 0
			for (int i = 0; i < (int)dimof(randWave); i++) {
				const RandWave& r = randWave[i];
				float rad = (elapsedTime * r.degreePerSec) * XM_2PI / 180;
				Vec2 posRot = pos * cosf(rad) + Vec2(-pos.y, pos.x) * sinf(rad);
				hmap[x][z] += sinf(r.xShift + posRot.x * r.xMul + elapsedTime * r.timeMul) * r.strength;
			}
#endif
		}
	}

	for (int z = 0; z <= tileMax; z++) {
		for (int x = 0; x <= tileMax; x++) {
			WaterVert v;
			v.pos = MakePos(x, z, hmap);
			Vec3 v1 = MakePos(x, z - 1, hmap);
			Vec3 v2 = MakePos(x - 1, z, hmap);
			Vec3 v3 = MakePos(x + 1, z + 1, hmap);
			v.normal = cross(v2 - v1, v3 - v2);
			vert.push_back(v);
		}
	}
}

WaterSurfaceES2::WaterSurfaceES2()
{
	ripplesNext = 0;
	Init();
}

WaterSurfaceES2::~WaterSurfaceES2()
{
	Destroy();
}

void WaterSurfaceES2::Destroy()
{
	afSafeDeleteBuffer(vbo);
	afSafeDeleteBuffer(ibo);
	afSafeDeleteBuffer(vboFullScr);
	afSafeDeleteBuffer(iboFullScr);
	afSafeDeleteVAO(vao);
	afSafeDeleteVAO(vaoFullScr);
	for (auto& it : texIds) {
		afSafeDeleteTexture(it);
	}
	rt.Destroy();
}

static const InputElement elements[] = {
	CInputElement("vPosition", SF_R32G32B32_FLOAT, 0),
	CInputElement("vNormal", SF_R32G32B32_FLOAT, 12),
};

static const InputElement elementsFullScr[] = {
	CInputElement("POSITION", SF_R32G32_FLOAT, 0),
};

static const SamplerType samplers[] = {
	AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP
};

void WaterSurfaceES2::Init()
{
	assert(dimof(samplers) >= dimof(texFiles));
	Destroy();

	lastTime = GetTime();

	std::vector<AFIndex> indi;
	std::vector<WaterVert> vert;
	UpdateVert(vert);

	for (int z = 0; z < tileMax; z++) {
		if (z != 0) {
			indi.push_back(z * vertMax);
		}
		indi.push_back(z * vertMax);
		for (int x = 0; x < tileMax; x++) {
			indi.push_back((z + 1) * vertMax + x);
			indi.push_back(z * vertMax + x + 1);
		}
		indi.push_back((z + 1) * vertMax + vertMax - 1);
		if (z != tileMax - 1) {
			indi.push_back((z + 1) * vertMax + vertMax - 1);
		}
	}

	lines = indi.size() / 2;
	nIndi = indi.size();

	vbo = afCreateDynamicVertexBuffer(vert.size() * sizeof(WaterVert));
	ibo = afCreateIndexBuffer(&indi[0], indi.size());

	AFIndex iboFullScrSrc[] = { 0, 1, 2, 3 };
	Vec2 vboFullScrSrc[] = {{-1, 1}, {-1, -1}, {1, 1}, {1, -1}};

	vboFullScr = afCreateVertexBuffer(sizeof(vboFullScrSrc), &vboFullScrSrc[0]);
	iboFullScr = afCreateIndexBuffer(&iboFullScrSrc[0], dimof(iboFullScrSrc));

	renderStateWater.Create("water_es2", dimof(elements), elements, BM_NONE, DSM_DISABLE, CM_DISABLE, dimof(samplers), samplers);

	const char* shaderName = "vivid";
//	const char* shaderName = "letterbox";
	renderStatePostProcess.Create(shaderName, dimof(elementsFullScr), elementsFullScr, BM_NONE, DSM_DISABLE, CM_DISABLE, dimof(samplers), samplers);

	texIds.resize(dimof(texFiles));
	for (int i = 0; i < (int)dimof(texFiles); i++) {
		texIds[i] = texMan.Create(texFiles[i].name);
	}

	rt.Init(systemMisc.GetScreenSize(), AFDT_R5G6B5_UINT);

	VBOID vertexBufferIds[] = { vbo };
	int strides[] = { sizeof(WaterVert) };
	vao = afCreateVAO(elements, dimof(elements), 1, vertexBufferIds, strides, ibo);

	VBOID vertexBufferIdsFullScr[] = { vboFullScr };
	int stridesFullScr[] = { sizeof(Vec2) };
	vaoFullScr = afCreateVAO(elementsFullScr, dimof(elementsFullScr), 1, vertexBufferIdsFullScr, stridesFullScr, iboFullScr);
}

void WaterSurfaceES2::UpdateRipple()
{
	double now = GetTime();
	elapsedTime += now - lastTime;
	lastTime = now;

	if (inputMan.GetInputCount(1) == 1) {
		Vec2 pos = (Vec2)systemMisc.GetMousePos() / (Vec2)systemMisc.GetScreenSize() * Vec2(2, -2) + Vec2(-1, 1);
		CreateRipple(pos);
	}

	std::vector<WaterVert> vert;
	UpdateVert(vert);
	afWriteBuffer(vbo, &vert[0], vert.size() * sizeof(WaterVert));
}

void WaterSurfaceES2::Update()
{
	IVec2 scrSize = systemMisc.GetScreenSize();
	float offset = 0.5f;
	float aspect = (float)scrSize.y / scrSize.x;
	if (aspect < 1) {
		uboBuf.matV = fastInv(translate(0, 0.5f * (1 - aspect), 0));
		uboBuf.matP = Mat(
			1, 0, 0, 0,
			0, 1 / aspect, 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1);
	} else {
		uboBuf.matV = fastInv(translate(offset * (1 - 1 / aspect), 0, 0));
		uboBuf.matP = Mat(
			aspect, 0, 0, 0,
			0, 1, 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1);
	}
	uboBuf.matW = q2m(Quat(Vec3(1, 0, 0), (float)M_PI / 180 * -90));
	double dummy;
	uboBuf.time = (float)modf(elapsedTime * (1.0f / loopTime), &dummy) * loopTime;
}

void WaterSurfaceES2::Draw()
{
	UpdateRipple();

	renderStateWater.Apply();
	for (int i = 0; i < (int)dimof(texFiles); i++) {
		afBindTextureToBindingPoint(texIds[i], i);
	}
	rt.BeginRenderToThis();
	UBOID ubo = afBindCbv0(&uboBuf, sizeof(uboBuf));
	afBindVAO(vao);
	afDrawIndexed(PT_TRIANGLESTRIP, nIndi);
	afBindVAO(0);
	afSafeDeleteBuffer(ubo);

	AFRenderTarget rtDefault;
	rtDefault.InitForDefaultRenderTarget();
	rtDefault.BeginRenderToThis();
	renderStatePostProcess.Apply();
	afBindSrv0(rt.GetTexture());
	afBindVAO(vaoFullScr);
	afDrawIndexed(PT_TRIANGLESTRIP, 4);
	afBindVAO(0);
}
<commit_msg>NDC for DirectX.<commit_after>#include "stdafx.h"

struct WaterVert
{
	Vec3 pos;
	Vec3 normal;
};

struct WaterRipple
{
	WaterRipple()
	{
		generatedTime = -10000;
	}
	double generatedTime;
	Vec2 centerPos;
};

struct WaterSurfaceClassicUBO {
	Mat matW, matV, matP;
	float time;
	float padding[3];
};

class WaterSurfaceES2
{
	WaterSurfaceClassicUBO uboBuf;
	AFRenderStates renderStateWater;
	AFRenderStates renderStatePostProcess;
	int lines;
	void UpdateVert(std::vector<WaterVert>& vert);
	void UpdateRipple();
	WaterRipple ripples[2];
	int ripplesNext;
	double elapsedTime = 0;
	double lastTime;
	double nextTime;
	VBOID vbo, vboFullScr;
	IBOID ibo, iboFullScr;
	VAOID vao, vaoFullScr;
	int nIndi;
	AFRenderTarget rt;
	std::vector<SRVID> texIds;
public:
	WaterSurfaceES2();
	~WaterSurfaceES2();
	void Destroy();
	void Init();
	void Update();
	void Draw();
	void CreateRipple(Vec2 pos);
};

static const char* waterSurfaceClassName = "WaterSurfaceES2";
#define GET_WSC \
	WaterSurfaceES2* p = (WaterSurfaceES2*)luaL_checkudata(L, 1, waterSurfaceClassName);	\
	if (!p) {	\
		return 0;	\
	}

class WaterSurfaceClassicBinder {
public:
	WaterSurfaceClassicBinder() {
		GetLuaBindFuncContainer().push_back([](lua_State* L) {
			static luaL_Reg methods[] = {
				{ "__gc", [](lua_State* L) { GET_WSC p->~WaterSurfaceES2(); return 0; } },
				{ "Update", [](lua_State* L) { GET_WSC p->Update(); return 0; } },
				{ "Draw", [](lua_State* L) { GET_WSC p->Draw(); return 0; }},
				{ nullptr, nullptr },
			};
			aflBindClass(L, waterSurfaceClassName, methods, [](lua_State* L) { void* u = lua_newuserdata(L, sizeof(WaterSurfaceES2)); new (u) WaterSurfaceES2(); return 1; });
		});
	}
} static waterSurfaceClassicBinder;

struct TexFiles
{
	const char *name;
};

static TexFiles texFiles[] = {
	{ "rose.jpg" },
	{ "autumn.jpg" },
	{ "pangyo.jpg" },
	{ "timeline.png" },
	{ "delaymap.png" },
	{ "sphere.jpg"},
};

const int tileMax = 50;
const int vertMax = tileMax + 1;
const float pitch = 2.0f / tileMax;
const float repeat = 2;
const float halflife = 1.5f;
//const float heightUnit = 0.00375f;
const float heightUnit = 0.02f;
const float rippleSpeed = 0.7f;
const float loopTime = 20.0;

static Vec3 MakePos(int x, int z, float hmap[vertMax][vertMax])
{
	float height = hmap[std::max(0,std::min(tileMax, x))][std::max(0,std::min(tileMax, z))];
	return Vec3(((float)x - tileMax / 2) * pitch, height, ((float)z - tileMax / 2) * pitch);
}

void WaterSurfaceES2::CreateRipple(Vec2 scrPos)
{
	Vec3 surfacePos = transform(Vec3(scrPos.x, scrPos.y, 0), inv(uboBuf.matV * uboBuf.matP));

	WaterRipple r;
	r.generatedTime = elapsedTime;
	r.centerPos = Vec2(surfacePos.x, surfacePos.y);
	ripples[ripplesNext++] = r;
	ripplesNext %= dimof(ripples);
}

void WaterSurfaceES2::UpdateVert(std::vector<WaterVert>& vert)
{
	struct RandWave {
		float degreePerSec;
		float xShift;
		float xMul;
		float timeMul;
		float strength;
	} static randWave[10];
	static bool t;
	if (!t) {
		t = true;
		for (int i = 0; i < (int)dimof(randWave); i++) {
			RandWave& r = randWave[i];
			r.degreePerSec = Random() * 15 - 7.5f;
			r.xShift = Random();
			r.xMul = 2 + std::pow(2.f, 1 + 3 * Random());
			r.timeMul = 2 + std::pow(2.f, 0.5f + 2 * Random());
			r.strength = 0.005f * std::pow(2.f, 0.1f + 0.3f * Random());
		}
	}
	float hmap[vertMax][vertMax];
	memset(hmap, 0, sizeof(hmap));
	for (int z = 0; z <= tileMax; z++) {
		for (int x = 0; x <= tileMax; x++) {
			Vec2 pos = Vec2((float)x, (float)z) / (float)tileMax * 2.0f - Vec2(1, 1);
			for (int i = 0; i < (int)dimof(ripples); i++) {
				const WaterRipple& r = ripples[i];
				float lifeTime = (float)(elapsedTime - r.generatedTime);
				float timeAfterArrived = lifeTime - length(r.centerPos - pos) / rippleSpeed;
				float h = timeAfterArrived > 0 ? std::sin(timeAfterArrived * ((float)M_PI * 2) * repeat) * heightUnit : 0;
				h *= std::min(1.0f, std::pow(0.5f, lifeTime / halflife));

				hmap[x][z] += h;
			}
#if 0
			for (int i = 0; i < (int)dimof(randWave); i++) {
				const RandWave& r = randWave[i];
				float rad = (elapsedTime * r.degreePerSec) * XM_2PI / 180;
				Vec2 posRot = pos * cosf(rad) + Vec2(-pos.y, pos.x) * sinf(rad);
				hmap[x][z] += sinf(r.xShift + posRot.x * r.xMul + elapsedTime * r.timeMul) * r.strength;
			}
#endif
		}
	}

	for (int z = 0; z <= tileMax; z++) {
		for (int x = 0; x <= tileMax; x++) {
			WaterVert v;
			v.pos = MakePos(x, z, hmap);
			Vec3 v1 = MakePos(x, z - 1, hmap);
			Vec3 v2 = MakePos(x - 1, z, hmap);
			Vec3 v3 = MakePos(x + 1, z + 1, hmap);
			v.normal = cross(v2 - v1, v3 - v2);
			vert.push_back(v);
		}
	}
}

WaterSurfaceES2::WaterSurfaceES2()
{
	ripplesNext = 0;
	Init();
}

WaterSurfaceES2::~WaterSurfaceES2()
{
	Destroy();
}

void WaterSurfaceES2::Destroy()
{
	afSafeDeleteBuffer(vbo);
	afSafeDeleteBuffer(ibo);
	afSafeDeleteBuffer(vboFullScr);
	afSafeDeleteBuffer(iboFullScr);
	afSafeDeleteVAO(vao);
	afSafeDeleteVAO(vaoFullScr);
	for (auto& it : texIds) {
		afSafeDeleteTexture(it);
	}
	rt.Destroy();
}

static const InputElement elements[] = {
	CInputElement("vPosition", SF_R32G32B32_FLOAT, 0),
	CInputElement("vNormal", SF_R32G32B32_FLOAT, 12),
};

static const InputElement elementsFullScr[] = {
	CInputElement("POSITION", SF_R32G32_FLOAT, 0),
};

static const SamplerType samplers[] = {
	AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP, AFST_LINEAR_CLAMP
};

void WaterSurfaceES2::Init()
{
	assert(dimof(samplers) >= dimof(texFiles));
	Destroy();

	lastTime = GetTime();

	std::vector<AFIndex> indi;
	std::vector<WaterVert> vert;
	UpdateVert(vert);

	for (int z = 0; z < tileMax; z++) {
		if (z != 0) {
			indi.push_back(z * vertMax);
		}
		indi.push_back(z * vertMax);
		for (int x = 0; x < tileMax; x++) {
			indi.push_back((z + 1) * vertMax + x);
			indi.push_back(z * vertMax + x + 1);
		}
		indi.push_back((z + 1) * vertMax + vertMax - 1);
		if (z != tileMax - 1) {
			indi.push_back((z + 1) * vertMax + vertMax - 1);
		}
	}

	lines = indi.size() / 2;
	nIndi = indi.size();

	vbo = afCreateDynamicVertexBuffer(vert.size() * sizeof(WaterVert));
	ibo = afCreateIndexBuffer(&indi[0], indi.size());

	AFIndex iboFullScrSrc[] = { 0, 1, 2, 3 };
	Vec2 vboFullScrSrc[] = {{-1, 1}, {-1, -1}, {1, 1}, {1, -1}};

	vboFullScr = afCreateVertexBuffer(sizeof(vboFullScrSrc), &vboFullScrSrc[0]);
	iboFullScr = afCreateIndexBuffer(&iboFullScrSrc[0], dimof(iboFullScrSrc));

	renderStateWater.Create("water_es2", dimof(elements), elements, BM_NONE, DSM_DISABLE, CM_DISABLE, dimof(samplers), samplers);

	const char* shaderName = "vivid";
//	const char* shaderName = "letterbox";
	renderStatePostProcess.Create(shaderName, dimof(elementsFullScr), elementsFullScr, BM_NONE, DSM_DISABLE, CM_DISABLE, dimof(samplers), samplers);

	texIds.resize(dimof(texFiles));
	for (int i = 0; i < (int)dimof(texFiles); i++) {
		texIds[i] = texMan.Create(texFiles[i].name);
	}

	rt.Init(systemMisc.GetScreenSize(), AFDT_R5G6B5_UINT);

	VBOID vertexBufferIds[] = { vbo };
	int strides[] = { sizeof(WaterVert) };
	vao = afCreateVAO(elements, dimof(elements), 1, vertexBufferIds, strides, ibo);

	VBOID vertexBufferIdsFullScr[] = { vboFullScr };
	int stridesFullScr[] = { sizeof(Vec2) };
	vaoFullScr = afCreateVAO(elementsFullScr, dimof(elementsFullScr), 1, vertexBufferIdsFullScr, stridesFullScr, iboFullScr);
}

void WaterSurfaceES2::UpdateRipple()
{
	double now = GetTime();
	elapsedTime += now - lastTime;
	lastTime = now;

	if (inputMan.GetInputCount(1) == 1) {
		Vec2 pos = (Vec2)systemMisc.GetMousePos() / (Vec2)systemMisc.GetScreenSize() * Vec2(2, -2) + Vec2(-1, 1);
		CreateRipple(pos);
	}

	std::vector<WaterVert> vert;
	UpdateVert(vert);
	afWriteBuffer(vbo, &vert[0], vert.size() * sizeof(WaterVert));
}

void WaterSurfaceES2::Update()
{
	IVec2 scrSize = systemMisc.GetScreenSize();
	float offset = 0.5f;
	float aspect = (float)scrSize.y / scrSize.x;
	if (aspect < 1) {
		uboBuf.matV = fastInv(translate(0, 0.5f * (1 - aspect), 0));
		uboBuf.matP = Mat(
			1, 0, 0, 0,
			0, 1 / aspect, 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1);
	} else {
		uboBuf.matV = fastInv(translate(offset * (1 - 1 / aspect), 0, 0));
		uboBuf.matP = Mat(
			aspect, 0, 0, 0,
			0, 1, 0, 0,
			0, 0, 1, 0,
			0, 0, 0, 1);
	}
#ifndef GL_TURE
	uboBuf.matP *= Mat(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -0.5, 0, 0, 0, 0.5, 1);
#endif

	uboBuf.matW = q2m(Quat(Vec3(1, 0, 0), (float)M_PI / 180 * -90));
	double dummy;
	uboBuf.time = (float)modf(elapsedTime * (1.0f / loopTime), &dummy) * loopTime;
}

void WaterSurfaceES2::Draw()
{
	UpdateRipple();

	renderStateWater.Apply();
	for (int i = 0; i < (int)dimof(texFiles); i++) {
		afBindTextureToBindingPoint(texIds[i], i);
	}
	rt.BeginRenderToThis();
	UBOID ubo = afBindCbv0(&uboBuf, sizeof(uboBuf));
	afBindVAO(vao);
	afDrawIndexed(PT_TRIANGLESTRIP, nIndi);
	afBindVAO(0);
	afSafeDeleteBuffer(ubo);

	AFRenderTarget rtDefault;
	rtDefault.InitForDefaultRenderTarget();
	rtDefault.BeginRenderToThis();
	renderStatePostProcess.Apply();
	afBindSrv0(rt.GetTexture());
	afBindVAO(vaoFullScr);
	afDrawIndexed(PT_TRIANGLESTRIP, 4);
	afBindVAO(0);
}
<|endoftext|>


<commit_before>#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
#include <cctype>
using namespace std;

enum direction{
	UP,
	DOWN,
	LEFT,
	RIGHT,
	UP_LEFT,
	UP_RIGHT,
	DOWN_LEFT,
	DOWN_RIGHT
};

struct point{int i,k;}; //Declare a point structure that represents a point on the grid

class Generator{
	char grid[10][10]; //Create a 10x10 grid
	char NULL_CHAR; //The character that represents a null value
	public:
	Generator();
	char GenerateRandomChar();
	bool CanInsert(char* word, point start, direction d);
	void InsertWord(char* word, point start, direction d);
	void ClearGrid();
	void FillGrid();
	void PrintGrid();
	point ShiftPoint(point start, direction d);
};

Generator::Generator(){
	NULL_CHAR = 'x'; //Sets the null char to a lowercase x
}

char Generator::GenerateRandomChar(){
	return 'A' + rand()%26;
}

//Sets all values in grid to a null character
void Generator::ClearGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			grid[i][k] = NULL_CHAR; //Every empty value will be a lowercase x
		}
	}
}

//Checks if word can be inserted in the grid at the given start point
bool Generator::CanInsert(char* word, point start, direction d){
	int i = 0;
	point newPoint = start;
	printf("Length of the word %s: %d\n",word,(int)strlen(word));
	while(i < (int)strlen(word))
	{
		//Attempt to shift the point
		try{
			newPoint = ShiftPoint(newPoint,d);
			i++;
		}
		catch(const char* msg) //Returns false if the out of bounds error occurs
		{
			return false;
		}
	}
	return true;
}

//Replaces empty tiles with a random character
void Generator::FillGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			if(grid[i][k] == NULL_CHAR){
				grid[i][k] = GenerateRandomChar(); //Set every null value to a random character
			}
		}
	}
}

//Prints the grid to stdout
void Generator::PrintGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			if(k == 9){
				printf("%c\n",grid[i][k]); //Append a newline if it is on the last column
			}
			else{
				printf("%c",grid[i][k]);
			}
		}
	}
}

//Shifts the point depending on the direction
point Generator::ShiftPoint(point start, direction d){
	int i = start.i;
	int k = start.k;
	point newPoint;
	switch(d){
		case UP:
			newPoint.i = i-1;
			newPoint.k = k;
			break;
		case DOWN:
			newPoint.i = i+1;
			newPoint.k = k;
			break;
		case LEFT:
			newPoint.i = i;
			newPoint.k = k-1;
			break;
		case RIGHT:
			newPoint.i = i;
			newPoint.k = k+1;
			break;
		case UP_LEFT:
			newPoint.i = i-1;
			newPoint.k = k-1;
			break;
		case UP_RIGHT:
			newPoint.i = i-1;
			newPoint.k = k+1;
			break;
		case DOWN_LEFT:
			newPoint.i = i+1;
			newPoint.k = k-1;
			break;
		case DOWN_RIGHT:
			newPoint.i = i+1;
			newPoint.k = k+1;
			break;
		default:
			newPoint.i = i;
			newPoint.k = k;
			break;
	}
	//Handle out of bounds errors
	if(newPoint.i < 0 || newPoint.i > 9 || newPoint.k < 0 || newPoint.k > 9)
	{
		throw "Out of Bounds";
	}
	return newPoint;
}

void Generator::InsertWord(char* word, point start, direction d){
	if(CanInsert(word,start,d)){
		int i = 0;
		point newPoint = start;
		while(i < (int)strlen(word))
		{
			newPoint = ShiftPoint(newPoint,d);
			grid[newPoint.i][newPoint.k] = (char)toupper(word[i]);
			i++;
		}
	}
}

int main(){
	/* initialize random seed: */
	srand (time(NULL));
	Generator gen;
	gen.ClearGrid();
	point startPoint;
	startPoint.i = 5;
	startPoint.k = 5;
	char* word = "Test";
	gen.InsertWord(word,startPoint,DOWN_RIGHT);
	gen.FillGrid();
	gen.PrintGrid();
	return 0;
}
<commit_msg>insert function now inserts at a random position with a random direction<commit_after>#include <iostream>
#include <cstdio>
#include <stdlib.h>
#include <cstring>
#include <cctype>
using namespace std;

enum direction{
	UP,
	DOWN,
	LEFT,
	RIGHT,
	UP_LEFT,
	UP_RIGHT,
	DOWN_LEFT,
	DOWN_RIGHT
};

struct point{int i,k;}; //Declare a point structure that represents a point on the grid

class Generator{
	char grid[10][10]; //Create a 10x10 grid
	char NULL_CHAR; //The character that represents a null value
	public:
	Generator();
	char GenerateRandomChar();
	bool CanInsert(char* word, point start, direction d);
	void InsertWord(char* word);
	void ClearGrid();
	void FillGrid();
	void PrintGrid();
	point ShiftPoint(point start, direction d);
};

Generator::Generator(){
	NULL_CHAR = 'x'; //Sets the null char to a lowercase x
}

char Generator::GenerateRandomChar(){
	return 'A' + rand()%26;
}

//Sets all values in grid to a null character
void Generator::ClearGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			grid[i][k] = NULL_CHAR; //Every empty value will be a lowercase x
		}
	}
}

//Checks if word can be inserted in the grid at the given start point
bool Generator::CanInsert(char* word, point start, direction d){
	int i = 0;
	point newPoint = start;
	while(i < (int)strlen(word))
	{
		//Attempt to shift the point
		try{
			if(grid[newPoint.i][newPoint.k] == NULL_CHAR){
				newPoint = ShiftPoint(newPoint,d);
				i++;
			}
			else{
				return false;
			}
		}
		catch(const char* msg) //Returns false if the out of bounds error occurs
		{
			/*cout << "Cannot insert one of the words.  Please try again or choose a new word." << endl;
			exit(1);*/
			return false;
		}
	}
	return true;
}

//Replaces empty tiles with a random character
void Generator::FillGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			if(grid[i][k] == NULL_CHAR){
				grid[i][k] = GenerateRandomChar(); //Set every null value to a random character
			}
		}
	}
}

//Prints the grid to stdout
void Generator::PrintGrid(){
	for(int i=0;i<10;i++){
		for(int k=0;k<10;k++){
			if(k == 9){
				printf("%c \n",grid[i][k]); //Append a newline if it is on the last column
			}
			else{
				printf("%c ",grid[i][k]);
			}
		}
	}
}

//Shifts the point depending on the direction
point Generator::ShiftPoint(point start, direction d){
	int i = start.i;
	int k = start.k;
	point newPoint;
	switch(d){
		case UP:
			newPoint.i = i-1;
			newPoint.k = k;
			break;
		case DOWN:
			newPoint.i = i+1;
			newPoint.k = k;
			break;
		case LEFT:
			newPoint.i = i;
			newPoint.k = k-1;
			break;
		case RIGHT:
			newPoint.i = i;
			newPoint.k = k+1;
			break;
		case UP_LEFT:
			newPoint.i = i-1;
			newPoint.k = k-1;
			break;
		case UP_RIGHT:
			newPoint.i = i-1;
			newPoint.k = k+1;
			break;
		case DOWN_LEFT:
			newPoint.i = i+1;
			newPoint.k = k-1;
			break;
		case DOWN_RIGHT:
			newPoint.i = i+1;
			newPoint.k = k+1;
			break;
		default:
			newPoint.i = i;
			newPoint.k = k;
			break;
	}
	//Handle out of bounds errors
	if(newPoint.i < -1 || newPoint.i > 10 || newPoint.k < -1 || newPoint.k > 10)
	{
		throw "Out of Bounds";
	}
	return newPoint;
}

void Generator::InsertWord(char* word){
	point start;
	direction d;
	do{
		start.i = rand() % 10;
		start.k = rand() % 10;
		d = direction(rand() % 8);
	}
	while(!CanInsert(word,start,d));
	int i = 0;
	point newPoint = start;
	while(i < (int)strlen(word))
	{
		grid[newPoint.i][newPoint.k] = (char)toupper(word[i]);
		newPoint = ShiftPoint(newPoint,d);
		i++;
	}
}

int main(){
	/* initialize random seed: */
	srand (time(NULL));
	Generator gen;
	gen.ClearGrid();
	char* word = "testword";
	gen.InsertWord(word);
	word = "potato";
	gen.InsertWord(word);
	word = "dingus";
	gen.InsertWord(word);
	word = "derp";
	gen.InsertWord(word);
	gen.FillGrid();
	gen.PrintGrid();
	return 0;
}
<|endoftext|>