<commit_before>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace boostfs = boost::filesystem;

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boostfs::current_path().root_name().string() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  bool
  path::is_dir() const
  {
    return boostfs::is_directory(to_string());
  }

  bool
  path::is_reg() const
  {
    return boostfs::is_regular_file(to_string());
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = i->string();
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += i->string();
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boostfs::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boostfs::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boostfs::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boostfs::last_write_time(boostfs::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boostfs::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boostfs::rename(value_, dst);
    }
    catch (const boostfs::filesystem_error& e)
    {
      throw Exception(libport::format("cannot rename directory %s: %s",
                                      *this, format_error(e)));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(i->string());

    return path_;
  }

  std::string
  format_error(const boostfs::filesystem_error& e)
  {
    std::string res = e.code().message();
    res[0] = tolower(res[0]);
    // Boost includes quotes in the error messages, which does not
    // match our style.
    if (!e.path1().empty())
      res += libport::format(": %s", e.path1());
    if (!e.path2().empty())
      res += libport::format(": %s", e.path2());
    return res;
  }
}
<commit_msg>Path: more portability fixes.<commit_after>/*
 * Copyright (C) 2008-2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

/**
 ** \file libport/path.cc
 ** \brief Implement libport::path.
 */

#include <cctype>
#include <iostream>
#include <libport/cstdio>
#include <libport/debug.hh>
#include <libport/detect-win32.h>
#include <libport/exception.hh>
#include <libport/fcntl.h>
#include <libport/format.hh>
#include <libport/path.hh>
#include <libport/sys/stat.h>
#include <libport/sys/types.h>
#include <libport/unistd.h>

GD_CATEGORY(Libport.Path);

// Implementation detail: if components() is empty and not absolute
// then the path is '.'.

namespace boostfs = boost::filesystem;

namespace libport
{
  path::path(const std::string& p)
  {
    init(p);
  }

  path::path(const char* p)
  {
    init(p);
  }

  path::path(const value_type& p)
  {
    init(p.string());
  }

  void
  path::init(const std::string& p)
  {
    if (p.empty())
      throw invalid_path("Path can't be empty.");
#ifdef WIN32
    // We want "/" to mean "the root of the current volume" on windows.
    if (p[0] == '/')
      value_ = boostfs::current_path().root_name().string() + p;
    else
#endif
    value_ = p;
    value_ = clean();
  }

  path&
  path::operator=(const path& rhs)
  {
    value_ = rhs.value_;
    return *this;
  }

  path&
  path::operator/=(const path& rhs)
  {
    if (rhs.absolute_get())
      throw invalid_path(
        "Rhs of concatenation is absolute: " + rhs.to_string());
#ifdef WIN32
    if (!rhs.volume_get().empty())
      throw invalid_path("concatenation of path with volume: " +
			 rhs.to_string());
#endif
    value_ /= rhs.value_;
    value_ = clean();
    return *this;
  }

  path
  path::operator/(const path& rhs) const
  {
    path res = *this;
    return res /= rhs;
  }

  std::string
  path::to_string() const
  {
    if (!value_.is_complete() && components().empty())
      return WIN32_IF(volume_get().empty() ? "." : volume_get(), ".");

    return value_.string();
  }

  bool
  path::operator==(const path& rhs) const
  {
    return (volume_get() == rhs.volume_get()
            && absolute_get() == rhs.absolute_get()
            && components() == rhs.components());
  }

  std::ostream&
  path::dump(std::ostream& o) const
  {
    return o << operator std::string();
  }

  bool
  path::is_dir() const
  {
    return boostfs::is_directory(to_string());
  }

  bool
  path::is_reg() const
  {
    return boostfs::is_regular_file(to_string());
  }

  std::string
  path::clean() const
  {
    std::string res;
    value_type::iterator i = value_.begin();
    value_type::iterator i_end = value_.end();
    if (i == i_end)
      return ".";

    bool first = true;
    if (absolute_get())
    {
      res = i->string();
      ++i;
#ifdef WIN32
      // Add a "\" after the drive letter or network share.
      first = false;
#endif
    }

    for (;i != i_end; ++i)
    {
      // Remove the "." and empty components.
      if (!i->empty() && *i != ".")
      {
        if (!first)
          res += separator_;
        first = false;
        res += i->string();
      }
    }
    return res.empty() ? "." : res;
  }

  std::string
  path::volume_get() const
  {
#ifndef WIN32
    return "";
#else
    std::string res = value_.root_name().string();
    if (res.find("//") == 0)
      res.replace(0, 2, "\\\\");
    return res;
#endif
  }

  path
  path::dirname() const
  {
    // dirname of / is /, dirname of . is .
    if (components().empty())
      return *this;

    std::string res = value_.parent_path().string();
    return path(res.empty() ? "." : res);
  }

  bool path::exists() const
  {
    bool res;
    try
    {
      res = boostfs::exists(value_);
    }
    catch (...)
    {
      res = false;
    }
    GD_FINFO_DUMP("exists: %-5s: %s", res ? "true" : "false", to_string());
    return res;
  }

  path
  path::cwd()
  {
    return path(boostfs::current_path().string());
  }

  bool
  path::is_root() const
  {
    return to_string() == (volume_get() + separator_);
  }

  path
  path::parent() const
  {
    if (is_root())
      return path(volume_get().append(1, separator_));

    const std::string parent_path =
      boostfs::path(to_string()).parent_path().string();

    if (parent_path.empty())
      return cwd();

    return parent_path;
  }

  std::time_t
  path::last_write_time() const
  {
    return boostfs::last_write_time(boostfs::path(to_string()));
  }

  bool path::create() const
  {
    int fd = open(to_string().c_str(),
                  O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd == -1)
      return false;
    close(fd);
    return true;
  }

  path
  path::temporary_file()
  {
#ifndef WIN32
    char tmp_name[] = "/tmp/tmp.XXXXXX";
    int fd = mkstemp(tmp_name);
    close (fd);
#else
    char tmp_dir[MAX_PATH];
    char tmp_name[MAX_PATH];

    if(GetTempPathA(sizeof(tmp_dir), tmp_dir) == 0
       || GetTempFileNameA(tmp_dir, "$$$", 0, tmp_name) == 0)
      throw Exception("cannot generate path for temporary file");
#endif
    return path(tmp_name);
  }

  void
  path::remove() const
  {
    if (!boostfs::remove(value_))
      throw Exception(libport::format("cannot unlink file %s", *this));
  }

  void
  path::rename(const std::string& dst)
  {
    try
    {
      boostfs::rename(value_, dst);
    }
    catch (const boostfs::filesystem_error& e)
    {
      throw Exception(libport::format("cannot rename directory %s: %s",
                                      *this, format_error(e)));
    }

    *this = dst;
  }

  path::path_type
  path::components() const
  {
    path_type path_;
    value_type::iterator
      i = value_.begin(),
      i_end = value_.end();
    if (i == i_end)
      return path_;

    // Skip volume information.
    if (absolute_get())
    {
      ++i;
#ifdef WIN32 // Skip a / after the volume information.
      ++i;
#endif
    }
    for (;i != i_end; ++i)
      if (!i->empty() && *i != ".")
        path_.push_back(i->string());

    return path_;
  }

  std::string
  format_error(const boostfs::filesystem_error& e)
  {
    std::string res = e.code().message();
    res[0] = tolower(res[0]);
    // Boost includes quotes in the error messages, which does not
    // match our style.
    if (!e.path1().empty())
      res += libport::format(": %s", e.path1());
    if (!e.path2().empty())
      res += libport::format(": %s", e.path2());
    return res;
  }
}
<|endoftext|>


<commit_before>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP

#include "../container.hpp"
#include "lazy_storage.hpp"

namespace kgr {
namespace detail {

template<typename CRTP, typename T>
struct LazyBase {
private:
	using ref = typename std::remove_reference<ServiceType<T>>::type&;
	using rref = typename std::remove_reference<ServiceType<T>>::type&&;
	using ptr = decay_t<ServiceType<T>>*;

	static constexpr bool nothrow_get =
		noexcept(std::declval<Container>().service<T>()) &&
		noexcept(std::declval<LazyStorage<ServiceType<T>>>().construct(std::declval<ServiceType<T>>()));

public:
	ref get() noexcept(nothrow_get) {
		if (!_service) {
			_service.construct(static_cast<CRTP*>(this)->container().template service<T>());
		}

		return _service.value();
	}

	ref operator*() & noexcept(nothrow_get) {
		return get();
	}

	ptr operator->() noexcept(nothrow_get) {
		return &get();
	}

	rref operator*() && noexcept(nothrow_get) {
		return std::move(get());
	}

private:
	LazyStorage<ServiceType<T>> _service;
};

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP
<commit_msg>Changed nothrow_get to a constexpr function instead of a variable<commit_after>#ifndef KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP
#define KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP

#include "../container.hpp"
#include "lazy_storage.hpp"

namespace kgr {
namespace detail {

template<typename CRTP, typename T>
struct LazyBase {
private:
	using ref = typename std::remove_reference<ServiceType<T>>::type&;
	using rref = typename std::remove_reference<ServiceType<T>>::type&&;
	using ptr = decay_t<ServiceType<T>>*;

	static constexpr bool nothrow_get() {
		return noexcept(std::declval<Container>().service<T>()) &&
			noexcept(std::declval<LazyStorage<ServiceType<T>>>().construct(std::declval<ServiceType<T>>()));
	}

public:
	ref get() noexcept(nothrow_get()) {
		if (!_service) {
			_service.construct(static_cast<CRTP*>(this)->container().template service<T>());
		}

		return _service.value();
	}

	ref operator*() & noexcept(nothrow_get()) {
		return get();
	}

	ptr operator->() noexcept(nothrow_get()) {
		return &get();
	}

	rref operator*() && noexcept(nothrow_get()) {
		return std::move(get());
	}

private:
	LazyStorage<ServiceType<T>> _service;
};

} // namespace detail
} // namespace kgr

#endif // KGR_KANGARU_INCLUDE_KANGARU_DETAIL_LAZY_BASE_HPP
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef ALLOCATOR_STATIC_HXX
# define ALLOCATOR_STATIC_HXX

# include <iostream>

# include <libport/algorithm>
# include <libport/cassert>

namespace libport
{
  template <typename Exact,unsigned Chunk>
  void*
  StaticallyAllocated<Exact, Chunk>::operator new(size_t size)
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    LIBPORT_USE(size);

    // Allocations exceeds the chunk size.
    assert_le(size, Exact::allocator_static_max_size);

    if (size_ == storage_size_)
      _grow();
    // Allocations exceeds the chunk size.
    assert_le(size_, storage_size_);

    size_++;
    void* res = 0;
    std::swap(res, pointers_[where_]);
    POOL_ALLOC(pool_header, res, size);
    aver(res);
    where_ = (where_ + 1) % storage_size_;
    return res;
  }

  template <typename Exact, unsigned Chunk>
  void
  StaticallyAllocated<Exact, Chunk>::operator delete(void* obj)
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    aver(obj != 0);
    unsigned w = where_ - size_;

    // Fix overflow // i-e w < 0, or where_ < size_
    if (w > storage_size_)
      w += storage_size_;
    std::swap(pointers_[w], obj);
    POOL_FREE(pool_header, pointers_[w]);
    aver(obj == 0);
    size_--;
  }

  template <typename Exact, unsigned Chunk>
  void
  StaticallyAllocated<Exact, Chunk>::_grow()
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    char* pool = reinterpret_cast<char*>
      (malloc(chunk_size_ * Exact::allocator_static_max_size));
    if (!pool)
      throw std::bad_alloc();
    pointers_.resize(storage_size_ + chunk_size_);
    for (unsigned i = 0; i < chunk_size_; ++i)
    {
      pointers_[storage_size_ + i] =
        pool + i * Exact::allocator_static_max_size;
      *(unsigned*) pointers_[storage_size_ + i] = 0x0C0C0C0C;
    }
    where_ = storage_size_;
    storage_size_ += chunk_size_;
    chunk_size_ *= 2;
  }

  template <typename Exact, unsigned Chunk>
  std::vector<void*> StaticallyAllocated<Exact, Chunk>::pointers_;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::where_ = 0;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::size_ = 0;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::storage_size_ = 0;

  template <typename Exact, unsigned Chunk>
  unsigned StaticallyAllocated<Exact, Chunk>::chunk_size_ = Chunk;

# if DEBUG_SA_UNIQ_THREAD_CHECK
  template <typename Exact, unsigned Chunk>
  pthread_t StaticallyAllocated<Exact, Chunk>::thread = pthread_self();
# endif

# ifndef NVALGRIND
  template <typename Exact, unsigned Chunk>
  int* StaticallyAllocated<Exact, Chunk>::initialize_pool()
  {
    int* header = reinterpret_cast<int*>(malloc(sizeof(int)));
    POOL_CREATE(header, 0, false);
    return header;
  }

  template <typename Exact, unsigned Chunk>
  int* StaticallyAllocated<Exact, Chunk>::pool_header = initialize_pool();
# endif
}

#endif
<commit_msg>Remove unused pattern.<commit_after>/*
 * Copyright (C) 2011, Gostai S.A.S.
 *
 * This software is provided "as is" without warranty of any kind,
 * either expressed or implied, including but not limited to the
 * implied warranties of fitness for a particular purpose.
 *
 * See the LICENSE file for more information.
 */

#ifndef ALLOCATOR_STATIC_HXX
# define ALLOCATOR_STATIC_HXX

# include <iostream>

# include <libport/algorithm>
# include <libport/cassert>

namespace libport
{
  template <typename Exact,unsigned Chunk>
  void*
  StaticallyAllocated<Exact, Chunk>::operator new(size_t size)
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    LIBPORT_USE(size);

    // Allocations exceeds the chunk size.
    assert_le(size, Exact::allocator_static_max_size);

    if (size_ == storage_size_)
      _grow();
    // Allocations exceeds the chunk size.
    assert_le(size_, storage_size_);

    size_++;
    void* res = 0;
    std::swap(res, pointers_[where_]);
    POOL_ALLOC(pool_header, res, size);
    aver(res);
    where_ = (where_ + 1) % storage_size_;
    return res;
  }

  template <typename Exact, unsigned Chunk>
  void
  StaticallyAllocated<Exact, Chunk>::operator delete(void* obj)
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    aver(obj != 0);
    unsigned w = where_ - size_;

    // Fix overflow // i-e w < 0, or where_ < size_
    if (w > storage_size_)
      w += storage_size_;
    std::swap(pointers_[w], obj);
    POOL_FREE(pool_header, pointers_[w]);
    aver(obj == 0);
    size_--;
  }

  template <typename Exact, unsigned Chunk>
  void
  StaticallyAllocated<Exact, Chunk>::_grow()
  {
# if DEBUG_SA_UNIQ_THREAD_CHECK
    aver_eq(thread, pthread_self());
# endif
    char* pool = reinterpret_cast<char*>
      (malloc(chunk_size_ * Exact::allocator_static_max_size));
    if (!pool)
      throw std::bad_alloc();
    pointers_.resize(storage_size_ + chunk_size_);
    for (unsigned i = 0; i < chunk_size_; ++i)
      pointers_[storage_size_ + i] =
        pool + i * Exact::allocator_static_max_size;
    where_ = storage_size_;
    storage_size_ += chunk_size_;
    chunk_size_ *= 2;
  }

  template <typename Exact, unsigned Chunk>
  std::vector<void*> StaticallyAllocated<Exact, Chunk>::pointers_;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::where_ = 0;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::size_ = 0;

  template <typename Exact, unsigned Chunk>
  volatile unsigned StaticallyAllocated<Exact, Chunk>::storage_size_ = 0;

  template <typename Exact, unsigned Chunk>
  unsigned StaticallyAllocated<Exact, Chunk>::chunk_size_ = Chunk;

# if DEBUG_SA_UNIQ_THREAD_CHECK
  template <typename Exact, unsigned Chunk>
  pthread_t StaticallyAllocated<Exact, Chunk>::thread = pthread_self();
# endif

# ifndef NVALGRIND
  template <typename Exact, unsigned Chunk>
  int* StaticallyAllocated<Exact, Chunk>::initialize_pool()
  {
    int* header = reinterpret_cast<int*>(malloc(sizeof(int)));
    POOL_CREATE(header, 0, false);
    return header;
  }

  template <typename Exact, unsigned Chunk>
  int* StaticallyAllocated<Exact, Chunk>::pool_header = initialize_pool();
# endif
}

#endif
<|endoftext|>


<commit_before>#include <babylon/gamepads/xbox_360_pad.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/interfaces/ibrowser_gamepad.h>

namespace BABYLON {

Xbox360Pad::Xbox360Pad(const std::string& iId, int iIndex,
                       const IBrowserGamepadPtr& gamepad, bool xboxOne)
    : Gamepad(iId, iIndex, gamepad, 0, 1, 2, 3)
    , leftTrigger{this, &Xbox360Pad::get_leftTrigger,
                  &Xbox360Pad::set_leftTrigger}
    , rightTrigger{this, &Xbox360Pad::get_rightTrigger,
                   &Xbox360Pad::set_rightTrigger}
    , buttonA{this, &Xbox360Pad::get_buttonA, &Xbox360Pad::set_buttonA}
    , buttonB{this, &Xbox360Pad::get_buttonB, &Xbox360Pad::set_buttonB}
    , buttonX{this, &Xbox360Pad::get_buttonX, &Xbox360Pad::set_buttonX}
    , buttonY{this, &Xbox360Pad::get_buttonY, &Xbox360Pad::set_buttonY}
    , buttonStart{this, &Xbox360Pad::get_buttonStart,
                  &Xbox360Pad::set_buttonStart}
    , buttonBack{this, &Xbox360Pad::get_buttonBack, &Xbox360Pad::set_buttonBack}
    , buttonLB{this, &Xbox360Pad::get_buttonLB, &Xbox360Pad::set_buttonLB}
    , buttonRB{this, &Xbox360Pad::get_buttonRB, &Xbox360Pad::set_buttonRB}
    , buttonLeftStick{this, &Xbox360Pad::get_buttonLeftStick,
                      &Xbox360Pad::set_buttonLeftStick}
    , buttonRightStick{this, &Xbox360Pad::get_buttonRightStick,
                       &Xbox360Pad::set_buttonRightStick}
    , dPadUp{this, &Xbox360Pad::get_dPadUp, &Xbox360Pad::set_dPadUp}
    , dPadDown{this, &Xbox360Pad::get_dPadDown, &Xbox360Pad::set_dPadDown}
    , dPadLeft{this, &Xbox360Pad::get_dPadLeft, &Xbox360Pad::set_dPadLeft}
    , dPadRight{this, &Xbox360Pad::get_dPadRight, &Xbox360Pad::set_dPadRight}
    , _leftTrigger{0}
    , _rightTrigger{0}
    , _buttonA{0}
    , _buttonB{0}
    , _buttonX{0}
    , _buttonY{0}
    , _buttonBack{0}
    , _buttonStart{0}
    , _buttonLB{0}
    , _buttonRB{0}
    , _buttonLeftStick{0}
    , _buttonRightStick{0}
    , _dPadUp{0}
    , _dPadDown{0}
    , _dPadLeft{0}
    , _dPadRight{0}
    , _isXboxOnePad{xboxOne}
{
  type = Gamepad::XBOX;
}

Xbox360Pad::~Xbox360Pad()
{
}

void Xbox360Pad::setOnlefttriggerchanged(
  const std::function<void(float value)>& callback)
{
  _onlefttriggerchanged = callback;
}

void Xbox360Pad::onrighttriggerchanged(
  const std::function<void(float value)>& callback)
{
  _onrighttriggerchanged = callback;
}

float Xbox360Pad::get_leftTrigger() const
{
  return _leftTrigger;
}

void Xbox360Pad::set_leftTrigger(float newValue)
{
  if (_onlefttriggerchanged
      && !stl_util::almost_equal(_leftTrigger, newValue)) {
    _onlefttriggerchanged(newValue);
  }
  _leftTrigger = newValue;
}

float Xbox360Pad::get_rightTrigger() const
{
  return _rightTrigger;
}

void Xbox360Pad::set_rightTrigger(float newValue)
{
  if (_onrighttriggerchanged
      && !stl_util::almost_equal(_rightTrigger, newValue)) {
    _onrighttriggerchanged(newValue);
  }
  _rightTrigger = newValue;
}

void Xbox360Pad::onbuttondown(
  const std::function<void(Xbox360Button buttonPressed)>& callback)
{
  _onbuttondown = callback;
}

void Xbox360Pad::onbuttonup(
  const std::function<void(Xbox360Button buttonReleased)>& callback)
{
  _onbuttonup = callback;
}

void Xbox360Pad::ondpaddown(
  const std::function<void(Xbox360Dpad dPadPressed)>& callback)
{
  _ondpaddown = callback;
}

void Xbox360Pad::ondpadup(
  const std::function<void(Xbox360Dpad dPadReleased)>& callback)
{
  _ondpadup = callback;
}

unsigned int Xbox360Pad::_setButtonValue(unsigned int newValue,
                                         unsigned int currentValue,
                                         Xbox360Button buttonType)
{
  if (newValue != currentValue) {
    if (newValue == 1) {
      if (_onbuttondown) {
        _onbuttondown(buttonType);
      }

      onButtonDownObservable.notifyObservers(&buttonType);
    }
    if (newValue == 0) {

      if (_onbuttonup) {
        _onbuttonup(buttonType);
      }

      onButtonUpObservable.notifyObservers(&buttonType);
    }
  }
  return newValue;
}

unsigned int Xbox360Pad::_setDPadValue(unsigned int newValue,
                                       unsigned int currentValue,
                                       Xbox360Dpad buttonType)
{
  if (newValue != currentValue) {
    if (newValue == 1) {
      if (_ondpaddown) {
        _ondpaddown(buttonType);
      }

      onPadDownObservable.notifyObservers(&buttonType);
    }
    if (newValue == 0) {
      if (_ondpadup) {
        _ondpadup(buttonType);
      }

      onPadUpObservable.notifyObservers(&buttonType);
    }
  }
  return newValue;
}

unsigned int Xbox360Pad::get_buttonA() const
{
  return _buttonA;
}

void Xbox360Pad::set_buttonA(unsigned int value)
{
  _buttonA = _setButtonValue(value, _buttonA, Xbox360Button::A);
}

unsigned int Xbox360Pad::get_buttonB() const
{
  return _buttonB;
}

void Xbox360Pad::set_buttonB(unsigned int value)
{
  _buttonB = _setButtonValue(value, _buttonB, Xbox360Button::B);
}

unsigned int Xbox360Pad::get_buttonX() const
{
  return _buttonX;
}

void Xbox360Pad::set_buttonX(unsigned int value)
{
  _buttonX = _setButtonValue(value, _buttonX, Xbox360Button::X);
}

unsigned int Xbox360Pad::get_buttonY() const
{
  return _buttonY;
}

void Xbox360Pad::set_buttonY(unsigned int value)
{
  _buttonY = _setButtonValue(value, _buttonY, Xbox360Button::Y);
}

unsigned int Xbox360Pad::get_buttonStart() const
{
  return _buttonStart;
}

void Xbox360Pad::set_buttonStart(unsigned int value)
{
  _buttonStart = _setButtonValue(value, _buttonStart, Xbox360Button::Start);
}

unsigned int Xbox360Pad::get_buttonBack() const
{
  return _buttonBack;
}

void Xbox360Pad::set_buttonBack(unsigned int value)
{
  _buttonBack = _setButtonValue(value, _buttonBack, Xbox360Button::Back);
}

unsigned int Xbox360Pad::get_buttonLB() const
{
  return _buttonLB;
}

void Xbox360Pad::set_buttonLB(unsigned int value)
{
  _buttonLB = _setButtonValue(value, _buttonLB, Xbox360Button::LB);
}

unsigned int Xbox360Pad::get_buttonRB() const
{
  return _buttonRB;
}

void Xbox360Pad::set_buttonRB(unsigned int value)
{
  _buttonRB = _setButtonValue(value, _buttonRB, Xbox360Button::RB);
}

unsigned int Xbox360Pad::get_buttonLeftStick() const
{
  return _buttonLeftStick;
}

void Xbox360Pad::set_buttonLeftStick(unsigned int value)
{
  _buttonLeftStick
    = _setButtonValue(value, _buttonLeftStick, Xbox360Button::LeftStick);
}

unsigned int Xbox360Pad::get_buttonRightStick() const
{
  return _buttonRightStick;
}

void Xbox360Pad::set_buttonRightStick(unsigned int value)
{
  _buttonRightStick
    = _setButtonValue(value, _buttonRightStick, Xbox360Button::RightStick);
}

unsigned int Xbox360Pad::get_dPadUp() const
{
  return _dPadUp;
}

void Xbox360Pad::set_dPadUp(unsigned int value)
{
  _dPadUp = _setDPadValue(value, _dPadUp, Xbox360Dpad::Up);
}

unsigned int Xbox360Pad::get_dPadDown() const
{
  return _dPadDown;
}

void Xbox360Pad::set_dPadDown(unsigned int value)
{
  _dPadDown = _setDPadValue(value, _dPadDown, Xbox360Dpad::Down);
}

unsigned int Xbox360Pad::get_dPadLeft() const
{
  return _dPadLeft;
}

void Xbox360Pad::set_dPadLeft(unsigned int value)
{
  _dPadLeft = _setDPadValue(value, _dPadLeft, Xbox360Dpad::Left);
}

unsigned int Xbox360Pad::get_dPadRight() const
{
  return _dPadRight;
}

void Xbox360Pad::set_dPadRight(unsigned int value)
{
  _dPadRight = _setDPadValue(value, _dPadRight, Xbox360Dpad::Right);
}

void Xbox360Pad::update()
{
  Gamepad::update();
  if (_isXboxOnePad) {
    buttonA          = browserGamepad->buttons[0].value;
    buttonB          = browserGamepad->buttons[1].value;
    buttonX          = browserGamepad->buttons[2].value;
    buttonY          = browserGamepad->buttons[3].value;
    buttonLB         = browserGamepad->buttons[4].value;
    buttonRB         = browserGamepad->buttons[5].value;
    leftTrigger      = browserGamepad->axes[2];
    rightTrigger     = browserGamepad->axes[5];
    buttonBack       = browserGamepad->buttons[9].value;
    buttonStart      = browserGamepad->buttons[8].value;
    buttonLeftStick  = browserGamepad->buttons[6].value;
    buttonRightStick = browserGamepad->buttons[7].value;
    dPadUp           = browserGamepad->buttons[11].value;
    dPadDown         = browserGamepad->buttons[12].value;
    dPadLeft         = browserGamepad->buttons[13].value;
    dPadRight        = browserGamepad->buttons[14].value;
  }
  else {
    buttonA          = browserGamepad->buttons[0].value;
    buttonB          = browserGamepad->buttons[1].value;
    buttonX          = browserGamepad->buttons[2].value;
    buttonY          = browserGamepad->buttons[3].value;
    buttonLB         = browserGamepad->buttons[4].value;
    buttonRB         = browserGamepad->buttons[5].value;
    leftTrigger      = static_cast<float>(browserGamepad->buttons[6].value);
    rightTrigger     = static_cast<float>(browserGamepad->buttons[7].value);
    buttonBack       = browserGamepad->buttons[8].value;
    buttonStart      = browserGamepad->buttons[9].value;
    buttonLeftStick  = browserGamepad->buttons[10].value;
    buttonRightStick = browserGamepad->buttons[11].value;
    dPadUp           = browserGamepad->buttons[12].value;
    dPadDown         = browserGamepad->buttons[13].value;
    dPadLeft         = browserGamepad->buttons[14].value;
    dPadRight        = browserGamepad->buttons[15].value;
  }
}

void Xbox360Pad::dispose()
{
  Gamepad::dispose();
  onButtonDownObservable.clear();
  onButtonUpObservable.clear();
  onPadDownObservable.clear();
  onPadUpObservable.clear();
}

} // end of namespace BABYLON
<commit_msg>Updated Xbox360Pad triggers<commit_after>#include <babylon/gamepads/xbox_360_pad.h>

#include <babylon/babylon_stl_util.h>
#include <babylon/interfaces/ibrowser_gamepad.h>

namespace BABYLON {

Xbox360Pad::Xbox360Pad(const std::string& iId, int iIndex,
                       const IBrowserGamepadPtr& gamepad, bool xboxOne)
    : Gamepad(iId, iIndex, gamepad, 0, 1, 2, 3)
    , leftTrigger{this, &Xbox360Pad::get_leftTrigger,
                  &Xbox360Pad::set_leftTrigger}
    , rightTrigger{this, &Xbox360Pad::get_rightTrigger,
                   &Xbox360Pad::set_rightTrigger}
    , buttonA{this, &Xbox360Pad::get_buttonA, &Xbox360Pad::set_buttonA}
    , buttonB{this, &Xbox360Pad::get_buttonB, &Xbox360Pad::set_buttonB}
    , buttonX{this, &Xbox360Pad::get_buttonX, &Xbox360Pad::set_buttonX}
    , buttonY{this, &Xbox360Pad::get_buttonY, &Xbox360Pad::set_buttonY}
    , buttonStart{this, &Xbox360Pad::get_buttonStart,
                  &Xbox360Pad::set_buttonStart}
    , buttonBack{this, &Xbox360Pad::get_buttonBack, &Xbox360Pad::set_buttonBack}
    , buttonLB{this, &Xbox360Pad::get_buttonLB, &Xbox360Pad::set_buttonLB}
    , buttonRB{this, &Xbox360Pad::get_buttonRB, &Xbox360Pad::set_buttonRB}
    , buttonLeftStick{this, &Xbox360Pad::get_buttonLeftStick,
                      &Xbox360Pad::set_buttonLeftStick}
    , buttonRightStick{this, &Xbox360Pad::get_buttonRightStick,
                       &Xbox360Pad::set_buttonRightStick}
    , dPadUp{this, &Xbox360Pad::get_dPadUp, &Xbox360Pad::set_dPadUp}
    , dPadDown{this, &Xbox360Pad::get_dPadDown, &Xbox360Pad::set_dPadDown}
    , dPadLeft{this, &Xbox360Pad::get_dPadLeft, &Xbox360Pad::set_dPadLeft}
    , dPadRight{this, &Xbox360Pad::get_dPadRight, &Xbox360Pad::set_dPadRight}
    , _leftTrigger{0}
    , _rightTrigger{0}
    , _buttonA{0}
    , _buttonB{0}
    , _buttonX{0}
    , _buttonY{0}
    , _buttonBack{0}
    , _buttonStart{0}
    , _buttonLB{0}
    , _buttonRB{0}
    , _buttonLeftStick{0}
    , _buttonRightStick{0}
    , _dPadUp{0}
    , _dPadDown{0}
    , _dPadLeft{0}
    , _dPadRight{0}
    , _isXboxOnePad{xboxOne}
{
  type = Gamepad::XBOX;
}

Xbox360Pad::~Xbox360Pad()
{
}

void Xbox360Pad::setOnlefttriggerchanged(
  const std::function<void(float value)>& callback)
{
  _onlefttriggerchanged = callback;
}

void Xbox360Pad::onrighttriggerchanged(
  const std::function<void(float value)>& callback)
{
  _onrighttriggerchanged = callback;
}

float Xbox360Pad::get_leftTrigger() const
{
  return _leftTrigger;
}

void Xbox360Pad::set_leftTrigger(float newValue)
{
  if (_onlefttriggerchanged
      && !stl_util::almost_equal(_leftTrigger, newValue)) {
    _onlefttriggerchanged(newValue);
  }
  _leftTrigger = newValue;
}

float Xbox360Pad::get_rightTrigger() const
{
  return _rightTrigger;
}

void Xbox360Pad::set_rightTrigger(float newValue)
{
  if (_onrighttriggerchanged
      && !stl_util::almost_equal(_rightTrigger, newValue)) {
    _onrighttriggerchanged(newValue);
  }
  _rightTrigger = newValue;
}

void Xbox360Pad::onbuttondown(
  const std::function<void(Xbox360Button buttonPressed)>& callback)
{
  _onbuttondown = callback;
}

void Xbox360Pad::onbuttonup(
  const std::function<void(Xbox360Button buttonReleased)>& callback)
{
  _onbuttonup = callback;
}

void Xbox360Pad::ondpaddown(
  const std::function<void(Xbox360Dpad dPadPressed)>& callback)
{
  _ondpaddown = callback;
}

void Xbox360Pad::ondpadup(
  const std::function<void(Xbox360Dpad dPadReleased)>& callback)
{
  _ondpadup = callback;
}

unsigned int Xbox360Pad::_setButtonValue(unsigned int newValue,
                                         unsigned int currentValue,
                                         Xbox360Button buttonType)
{
  if (newValue != currentValue) {
    if (newValue == 1) {
      if (_onbuttondown) {
        _onbuttondown(buttonType);
      }

      onButtonDownObservable.notifyObservers(&buttonType);
    }
    if (newValue == 0) {

      if (_onbuttonup) {
        _onbuttonup(buttonType);
      }

      onButtonUpObservable.notifyObservers(&buttonType);
    }
  }
  return newValue;
}

unsigned int Xbox360Pad::_setDPadValue(unsigned int newValue,
                                       unsigned int currentValue,
                                       Xbox360Dpad buttonType)
{
  if (newValue != currentValue) {
    if (newValue == 1) {
      if (_ondpaddown) {
        _ondpaddown(buttonType);
      }

      onPadDownObservable.notifyObservers(&buttonType);
    }
    if (newValue == 0) {
      if (_ondpadup) {
        _ondpadup(buttonType);
      }

      onPadUpObservable.notifyObservers(&buttonType);
    }
  }
  return newValue;
}

unsigned int Xbox360Pad::get_buttonA() const
{
  return _buttonA;
}

void Xbox360Pad::set_buttonA(unsigned int value)
{
  _buttonA = _setButtonValue(value, _buttonA, Xbox360Button::A);
}

unsigned int Xbox360Pad::get_buttonB() const
{
  return _buttonB;
}

void Xbox360Pad::set_buttonB(unsigned int value)
{
  _buttonB = _setButtonValue(value, _buttonB, Xbox360Button::B);
}

unsigned int Xbox360Pad::get_buttonX() const
{
  return _buttonX;
}

void Xbox360Pad::set_buttonX(unsigned int value)
{
  _buttonX = _setButtonValue(value, _buttonX, Xbox360Button::X);
}

unsigned int Xbox360Pad::get_buttonY() const
{
  return _buttonY;
}

void Xbox360Pad::set_buttonY(unsigned int value)
{
  _buttonY = _setButtonValue(value, _buttonY, Xbox360Button::Y);
}

unsigned int Xbox360Pad::get_buttonStart() const
{
  return _buttonStart;
}

void Xbox360Pad::set_buttonStart(unsigned int value)
{
  _buttonStart = _setButtonValue(value, _buttonStart, Xbox360Button::Start);
}

unsigned int Xbox360Pad::get_buttonBack() const
{
  return _buttonBack;
}

void Xbox360Pad::set_buttonBack(unsigned int value)
{
  _buttonBack = _setButtonValue(value, _buttonBack, Xbox360Button::Back);
}

unsigned int Xbox360Pad::get_buttonLB() const
{
  return _buttonLB;
}

void Xbox360Pad::set_buttonLB(unsigned int value)
{
  _buttonLB = _setButtonValue(value, _buttonLB, Xbox360Button::LB);
}

unsigned int Xbox360Pad::get_buttonRB() const
{
  return _buttonRB;
}

void Xbox360Pad::set_buttonRB(unsigned int value)
{
  _buttonRB = _setButtonValue(value, _buttonRB, Xbox360Button::RB);
}

unsigned int Xbox360Pad::get_buttonLeftStick() const
{
  return _buttonLeftStick;
}

void Xbox360Pad::set_buttonLeftStick(unsigned int value)
{
  _buttonLeftStick
    = _setButtonValue(value, _buttonLeftStick, Xbox360Button::LeftStick);
}

unsigned int Xbox360Pad::get_buttonRightStick() const
{
  return _buttonRightStick;
}

void Xbox360Pad::set_buttonRightStick(unsigned int value)
{
  _buttonRightStick
    = _setButtonValue(value, _buttonRightStick, Xbox360Button::RightStick);
}

unsigned int Xbox360Pad::get_dPadUp() const
{
  return _dPadUp;
}

void Xbox360Pad::set_dPadUp(unsigned int value)
{
  _dPadUp = _setDPadValue(value, _dPadUp, Xbox360Dpad::Up);
}

unsigned int Xbox360Pad::get_dPadDown() const
{
  return _dPadDown;
}

void Xbox360Pad::set_dPadDown(unsigned int value)
{
  _dPadDown = _setDPadValue(value, _dPadDown, Xbox360Dpad::Down);
}

unsigned int Xbox360Pad::get_dPadLeft() const
{
  return _dPadLeft;
}

void Xbox360Pad::set_dPadLeft(unsigned int value)
{
  _dPadLeft = _setDPadValue(value, _dPadLeft, Xbox360Dpad::Left);
}

unsigned int Xbox360Pad::get_dPadRight() const
{
  return _dPadRight;
}

void Xbox360Pad::set_dPadRight(unsigned int value)
{
  _dPadRight = _setDPadValue(value, _dPadRight, Xbox360Dpad::Right);
}

void Xbox360Pad::update()
{
  Gamepad::update();
  if (_isXboxOnePad) {
    buttonA          = browserGamepad->buttons[0].value;
    buttonB          = browserGamepad->buttons[1].value;
    buttonX          = browserGamepad->buttons[2].value;
    buttonY          = browserGamepad->buttons[3].value;
    buttonLB         = browserGamepad->buttons[4].value;
    buttonRB         = browserGamepad->buttons[5].value;
    leftTrigger      = browserGamepad->buttons[6].value;
    rightTrigger     = browserGamepad->buttons[7].value;
    buttonBack       = browserGamepad->buttons[8].value;
    buttonStart      = browserGamepad->buttons[9].value;
    buttonLeftStick  = browserGamepad->buttons[10].value;
    buttonRightStick = browserGamepad->buttons[11].value;
    dPadUp           = browserGamepad->buttons[12].value;
    dPadDown         = browserGamepad->buttons[13].value;
    dPadLeft         = browserGamepad->buttons[14].value;
    dPadRight        = browserGamepad->buttons[15].value;
  }
  else {
    buttonA          = browserGamepad->buttons[0].value;
    buttonB          = browserGamepad->buttons[1].value;
    buttonX          = browserGamepad->buttons[2].value;
    buttonY          = browserGamepad->buttons[3].value;
    buttonLB         = browserGamepad->buttons[4].value;
    buttonRB         = browserGamepad->buttons[5].value;
    leftTrigger      = static_cast<float>(browserGamepad->buttons[6].value);
    rightTrigger     = static_cast<float>(browserGamepad->buttons[7].value);
    buttonBack       = browserGamepad->buttons[8].value;
    buttonStart      = browserGamepad->buttons[9].value;
    buttonLeftStick  = browserGamepad->buttons[10].value;
    buttonRightStick = browserGamepad->buttons[11].value;
    dPadUp           = browserGamepad->buttons[12].value;
    dPadDown         = browserGamepad->buttons[13].value;
    dPadLeft         = browserGamepad->buttons[14].value;
    dPadRight        = browserGamepad->buttons[15].value;
  }
}

void Xbox360Pad::dispose()
{
  Gamepad::dispose();
  onButtonDownObservable.clear();
  onButtonUpObservable.clear();
  onPadDownObservable.clear();
  onPadUpObservable.clear();
}

} // end of namespace BABYLON
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "formeditoritem.h"
#include "formeditorscene.h"

#include <modelnode.h>

#include <QDebug>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QTimeLine>

#include <cmath>

namespace QmlDesigner {

FormEditorScene *FormEditorItem::scene() const {
    return qobject_cast<FormEditorScene*>(QGraphicsItem::scene());
}

FormEditorItem::FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
    : QGraphicsObject(scene->formLayerItem()),
    m_snappingLineCreator(this),
    m_qmlItemNode(qmlItemNode),
    m_borderWidth(1.0),
    m_highlightBoundingRect(false),
    m_isContentVisible(true),
    m_isFormEditorVisible(true)
{
    setCacheMode(QGraphicsItem::DeviceCoordinateCache);
    setup();
}

void FormEditorItem::setup()
{
    if (qmlItemNode().hasInstanceParent()) {
        setParentItem(scene()->itemForQmlItemNode(qmlItemNode().instanceParent().toQmlItemNode()));
        setOpacity(qmlItemNode().instanceValue("opacity").toDouble());
    }

    setFlag(QGraphicsItem::ItemClipsChildrenToShape, qmlItemNode().instanceValue("clip").toBool());

    if (QGraphicsItem::parentItem() == scene()->formLayerItem())
        m_borderWidth = 0.0;

    setContentVisible(qmlItemNode().instanceValue("visible").toBool());

    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
    updateGeometry();
    updateVisibilty();
}

QRectF FormEditorItem::boundingRect() const
{
    return m_boundingRect;
}

void FormEditorItem::updateGeometry()
{
    prepareGeometryChange();
    m_boundingRect = qmlItemNode().instancePaintedBoundingRect().adjusted(0, 0, 1., 1.);
    setTransform(qmlItemNode().instanceTransform());
    setTransform(m_attentionTransform, true);
    //the property for zValue is called z in QGraphicsObject
    if (qmlItemNode().instanceValue("z").isValid())
        setZValue(qmlItemNode().instanceValue("z").toDouble());
}

void FormEditorItem::updateVisibilty()
{
//    setVisible(nodeInstance().isVisible());
//    setOpacity(nodeInstance().opacity());
}

void FormEditorItem::showAttention()
{
    if (m_attentionTimeLine.isNull()) {
        m_attentionTimeLine = new QTimeLine(500, this);
        m_attentionTimeLine->setCurveShape(QTimeLine::SineCurve);
        connect(m_attentionTimeLine.data(), SIGNAL(valueChanged(qreal)), SLOT(changeAttention(qreal)));
        connect(m_attentionTimeLine.data(), SIGNAL(finished()), m_attentionTimeLine.data(), SLOT(deleteLater()));

        m_attentionTimeLine->start();
    }
}

void FormEditorItem::changeAttention(qreal value)
{
    if (QGraphicsItem::parentItem() == scene()->formLayerItem()) {
        setAttentionHighlight(value);
    } else {
        setAttentionHighlight(value);
        setAttentionScale(value);
    }
}

FormEditorView *FormEditorItem::formEditorView() const
{
    return scene()->editorView();
}

void FormEditorItem::setAttentionScale(double sinusScale)
{
    if (!qFuzzyIsNull(sinusScale)) {
        double scale = std::sqrt(sinusScale);
        m_attentionTransform.reset();
        QPointF centerPoint(qmlItemNode().instanceBoundingRect().center());
        m_attentionTransform.translate(centerPoint.x(), centerPoint.y());
        m_attentionTransform.scale(scale * 0.15 + 1.0, scale * 0.15 + 1.0);
        m_attentionTransform.translate(-centerPoint.x(), -centerPoint.y());
        m_inverseAttentionTransform = m_attentionTransform.inverted();
        prepareGeometryChange();
        setTransform(qmlItemNode().instanceTransform());
        setTransform(m_attentionTransform, true);
    } else {
        m_attentionTransform.reset();
        prepareGeometryChange();
        setTransform(qmlItemNode().instanceTransform());
    }
}

void FormEditorItem::setAttentionHighlight(double value)
{
    if (QGraphicsItem::parentItem() == scene()->formLayerItem())
        m_borderWidth = value * 4;
    else
        m_borderWidth = 1. + value * 3;

    update();
}

void FormEditorItem::setHighlightBoundingRect(bool highlight)
{
    if (m_highlightBoundingRect != highlight) {
        m_highlightBoundingRect = highlight;
        update();
    }
}

void FormEditorItem::setContentVisible(bool visible)
{
    if (visible == m_isContentVisible)
        return;

    m_isContentVisible = visible;
    update();
}

bool FormEditorItem::isContentVisible() const
{
    if (parentItem())
        return parentItem()->isContentVisible() && m_isContentVisible;

    return m_isContentVisible;
}

bool FormEditorItem::isFormEditorVisible() const
{
    return m_isFormEditorVisible;
}
void FormEditorItem::setFormEditorVisible(bool isVisible)
{
    m_isFormEditorVisible = isVisible;
    setVisible(isVisible);
}

FormEditorItem::~FormEditorItem()
{
    scene()->removeItemFromHash(this);
}

/* \brief returns the parent item skipping all proxyItem*/
FormEditorItem *FormEditorItem::parentItem() const
{
    return qgraphicsitem_cast<FormEditorItem*> (QGraphicsItem::parentItem());
}

FormEditorItem* FormEditorItem::fromQGraphicsItem(QGraphicsItem *graphicsItem)
{
    return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
}

//static QRectF alignedRect(const QRectF &rect)
//{
//    QRectF alignedRect(rect);
//    alignedRect.setTop(std::floor(rect.top()) + 0.5);
//    alignedRect.setBottom(std::floor(rect.bottom()) + 0.5);
//    alignedRect.setLeft(std::floor(rect.left()) + 0.5);
//    alignedRect.setRight(std::floor(rect.right()) + 0.5);
//
//    return alignedRect;
//}

void FormEditorItem::paintBoundingRect(QPainter *painter) const
{
    if (!boundingRect().isValid()
        || (QGraphicsItem::parentItem() == scene()->formLayerItem() && qFuzzyIsNull(m_borderWidth)))
          return;

     if (boundingRect().width() < 8 || boundingRect().height() < 8)
         return;

    QPen pen;
    pen.setJoinStyle(Qt::MiterJoin);
    pen.setStyle(Qt::DotLine);

    QColor frameColor("#AAAAAA");

    if (scene()->showBoundingRects()) {
        if (m_highlightBoundingRect)
            pen.setColor(frameColor);
        else
            pen.setColor(frameColor.darker(150));
    } else {
        if (m_highlightBoundingRect)
            pen.setColor(frameColor);
        else
            pen.setColor(Qt::transparent);
    }

    painter->setPen(pen);
//    int offset =  m_borderWidth / 2;

    painter->drawRect(boundingRect().adjusted(0., 0., -1., -1.));
}

void FormEditorItem::paintPlaceHolderForInvisbleItem(QPainter *painter) const
{
    qreal stripesWidth = 12;

    QRegion innerRegion = QRegion(boundingRect().adjusted(stripesWidth, stripesWidth, -stripesWidth, -stripesWidth).toRect());
    QRegion outerRegion  = QRegion(boundingRect().toRect()) - innerRegion;

    painter->setClipRegion(outerRegion);
    painter->setClipping(true);
    painter->fillRect(boundingRect().adjusted(1, 1, -1, -1), Qt::BDiagPattern);
    painter->setClipping(false);

    QString displayText = qmlItemNode().id();

    if (displayText.isEmpty())
        displayText = qmlItemNode().simplifiedTypeName();

    QTextOption textOption;
    textOption.setAlignment(Qt::AlignTop);
    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

    if (boundingRect().height() > 60) {
        painter->save();

        QFont font;
        font.setStyleHint(QFont::SansSerif);
        font.setBold(true);
        font.setPixelSize(12);
        painter->setFont(font);

        QFontMetrics fm(font);
        painter->rotate(90);
        if (fm.width(displayText) > (boundingRect().height() - 32) && displayText.length() > 4) {

            displayText = fm.elidedText(displayText, Qt::ElideRight, boundingRect().height() - 32, Qt::TextShowMnemonic);
        }

        QRectF rotatedBoundingBox;
        rotatedBoundingBox.setWidth(boundingRect().height());
        rotatedBoundingBox.setHeight(12);
        rotatedBoundingBox.setY(-boundingRect().width() + 12);
        rotatedBoundingBox.setX(20);

        painter->setFont(font);
        painter->setPen(QColor(48, 48, 96, 255));
        painter->drawText(rotatedBoundingBox, displayText, textOption);

        painter->restore();
    }
}

void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    if (!painter->isActive())
        return;

    if (!qmlItemNode().isValid())
        return;

    painter->save();

    if (qmlItemNode().instanceIsRenderPixmapNull() || !isContentVisible()) {
        if (scene()->showBoundingRects() && boundingRect().width() > 15 && boundingRect().height() > 15)
            paintPlaceHolderForInvisbleItem(painter);
    } else {
        qmlItemNode().paintInstance(painter);
    }

    if (!qmlItemNode().isRootModelNode())
        paintBoundingRect(painter);

    painter->restore();
}

AbstractFormEditorTool* FormEditorItem::tool() const
{
    return static_cast<FormEditorScene*>(scene())->currentTool();
}

SnapLineMap FormEditorItem::topSnappingLines() const
{
    return m_snappingLineCreator.topLines();
}

SnapLineMap FormEditorItem::bottomSnappingLines() const
{
    return m_snappingLineCreator.bottomLines();
}

SnapLineMap FormEditorItem::leftSnappingLines() const
{
    return m_snappingLineCreator.leftLines();
}

SnapLineMap FormEditorItem::rightSnappingLines() const
{
    return m_snappingLineCreator.rightLines();
}

SnapLineMap FormEditorItem::horizontalCenterSnappingLines() const
{
    return m_snappingLineCreator.horizontalCenterLines();
}

SnapLineMap FormEditorItem::verticalCenterSnappingLines() const
{
    return m_snappingLineCreator.verticalCenterLines();
}

SnapLineMap FormEditorItem::topSnappingOffsets() const
{
    return m_snappingLineCreator.topOffsets();
}

SnapLineMap FormEditorItem::bottomSnappingOffsets() const
{
    return m_snappingLineCreator.bottomOffsets();
}

SnapLineMap FormEditorItem::leftSnappingOffsets() const
{
    return m_snappingLineCreator.leftOffsets();
}

SnapLineMap FormEditorItem::rightSnappingOffsets() const
{
    return m_snappingLineCreator.rightOffsets();
}

void FormEditorItem::updateSnappingLines(const QList<FormEditorItem*> &exceptionList,
                                         FormEditorItem *transformationSpaceItem)
{
    m_snappingLineCreator.update(exceptionList, transformationSpaceItem);
}

QList<FormEditorItem*> FormEditorItem::childFormEditorItems() const
{
    QList<FormEditorItem*> formEditorItemList;

    foreach (QGraphicsItem *item, childItems()) {
        FormEditorItem *formEditorItem = fromQGraphicsItem(item);
        if (formEditorItem)
            formEditorItemList.append(formEditorItem);
    }

    return formEditorItemList;
}

bool FormEditorItem::isContainer() const
{
    return true;
}

QmlItemNode FormEditorItem::qmlItemNode() const
{
    return m_qmlItemNode;
}

}

<commit_msg>QmlDesigner: Use bounding rectangle instead of painted rectangle<commit_after>/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "formeditoritem.h"
#include "formeditorscene.h"

#include <modelnode.h>

#include <QDebug>
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QTimeLine>

#include <cmath>

namespace QmlDesigner {

FormEditorScene *FormEditorItem::scene() const {
    return qobject_cast<FormEditorScene*>(QGraphicsItem::scene());
}

FormEditorItem::FormEditorItem(const QmlItemNode &qmlItemNode, FormEditorScene* scene)
    : QGraphicsObject(scene->formLayerItem()),
    m_snappingLineCreator(this),
    m_qmlItemNode(qmlItemNode),
    m_borderWidth(1.0),
    m_highlightBoundingRect(false),
    m_isContentVisible(true),
    m_isFormEditorVisible(true)
{
    setCacheMode(QGraphicsItem::DeviceCoordinateCache);
    setup();
}

void FormEditorItem::setup()
{
    if (qmlItemNode().hasInstanceParent()) {
        setParentItem(scene()->itemForQmlItemNode(qmlItemNode().instanceParent().toQmlItemNode()));
        setOpacity(qmlItemNode().instanceValue("opacity").toDouble());
    }

    setFlag(QGraphicsItem::ItemClipsChildrenToShape, qmlItemNode().instanceValue("clip").toBool());

    if (QGraphicsItem::parentItem() == scene()->formLayerItem())
        m_borderWidth = 0.0;

    setContentVisible(qmlItemNode().instanceValue("visible").toBool());

    setFlag(QGraphicsItem::ItemIsMovable, true);
    setFlag(QGraphicsItem::ItemNegativeZStacksBehindParent, true);
    updateGeometry();
    updateVisibilty();
}

QRectF FormEditorItem::boundingRect() const
{
    return m_boundingRect;
}

void FormEditorItem::updateGeometry()
{
    prepareGeometryChange();
    m_boundingRect = qmlItemNode().instanceBoundingRect().adjusted(0, 0, 1., 1.);
    setTransform(qmlItemNode().instanceTransform());
    setTransform(m_attentionTransform, true);
    //the property for zValue is called z in QGraphicsObject
    if (qmlItemNode().instanceValue("z").isValid())
        setZValue(qmlItemNode().instanceValue("z").toDouble());
}

void FormEditorItem::updateVisibilty()
{
//    setVisible(nodeInstance().isVisible());
//    setOpacity(nodeInstance().opacity());
}

void FormEditorItem::showAttention()
{
    if (m_attentionTimeLine.isNull()) {
        m_attentionTimeLine = new QTimeLine(500, this);
        m_attentionTimeLine->setCurveShape(QTimeLine::SineCurve);
        connect(m_attentionTimeLine.data(), SIGNAL(valueChanged(qreal)), SLOT(changeAttention(qreal)));
        connect(m_attentionTimeLine.data(), SIGNAL(finished()), m_attentionTimeLine.data(), SLOT(deleteLater()));

        m_attentionTimeLine->start();
    }
}

void FormEditorItem::changeAttention(qreal value)
{
    if (QGraphicsItem::parentItem() == scene()->formLayerItem()) {
        setAttentionHighlight(value);
    } else {
        setAttentionHighlight(value);
        setAttentionScale(value);
    }
}

FormEditorView *FormEditorItem::formEditorView() const
{
    return scene()->editorView();
}

void FormEditorItem::setAttentionScale(double sinusScale)
{
    if (!qFuzzyIsNull(sinusScale)) {
        double scale = std::sqrt(sinusScale);
        m_attentionTransform.reset();
        QPointF centerPoint(qmlItemNode().instanceBoundingRect().center());
        m_attentionTransform.translate(centerPoint.x(), centerPoint.y());
        m_attentionTransform.scale(scale * 0.15 + 1.0, scale * 0.15 + 1.0);
        m_attentionTransform.translate(-centerPoint.x(), -centerPoint.y());
        m_inverseAttentionTransform = m_attentionTransform.inverted();
        prepareGeometryChange();
        setTransform(qmlItemNode().instanceTransform());
        setTransform(m_attentionTransform, true);
    } else {
        m_attentionTransform.reset();
        prepareGeometryChange();
        setTransform(qmlItemNode().instanceTransform());
    }
}

void FormEditorItem::setAttentionHighlight(double value)
{
    if (QGraphicsItem::parentItem() == scene()->formLayerItem())
        m_borderWidth = value * 4;
    else
        m_borderWidth = 1. + value * 3;

    update();
}

void FormEditorItem::setHighlightBoundingRect(bool highlight)
{
    if (m_highlightBoundingRect != highlight) {
        m_highlightBoundingRect = highlight;
        update();
    }
}

void FormEditorItem::setContentVisible(bool visible)
{
    if (visible == m_isContentVisible)
        return;

    m_isContentVisible = visible;
    update();
}

bool FormEditorItem::isContentVisible() const
{
    if (parentItem())
        return parentItem()->isContentVisible() && m_isContentVisible;

    return m_isContentVisible;
}

bool FormEditorItem::isFormEditorVisible() const
{
    return m_isFormEditorVisible;
}
void FormEditorItem::setFormEditorVisible(bool isVisible)
{
    m_isFormEditorVisible = isVisible;
    setVisible(isVisible);
}

FormEditorItem::~FormEditorItem()
{
    scene()->removeItemFromHash(this);
}

/* \brief returns the parent item skipping all proxyItem*/
FormEditorItem *FormEditorItem::parentItem() const
{
    return qgraphicsitem_cast<FormEditorItem*> (QGraphicsItem::parentItem());
}

FormEditorItem* FormEditorItem::fromQGraphicsItem(QGraphicsItem *graphicsItem)
{
    return qgraphicsitem_cast<FormEditorItem*>(graphicsItem);
}

//static QRectF alignedRect(const QRectF &rect)
//{
//    QRectF alignedRect(rect);
//    alignedRect.setTop(std::floor(rect.top()) + 0.5);
//    alignedRect.setBottom(std::floor(rect.bottom()) + 0.5);
//    alignedRect.setLeft(std::floor(rect.left()) + 0.5);
//    alignedRect.setRight(std::floor(rect.right()) + 0.5);
//
//    return alignedRect;
//}

void FormEditorItem::paintBoundingRect(QPainter *painter) const
{
    if (!boundingRect().isValid()
        || (QGraphicsItem::parentItem() == scene()->formLayerItem() && qFuzzyIsNull(m_borderWidth)))
          return;

     if (boundingRect().width() < 8 || boundingRect().height() < 8)
         return;

    QPen pen;
    pen.setJoinStyle(Qt::MiterJoin);
    pen.setStyle(Qt::DotLine);

    QColor frameColor("#AAAAAA");

    if (scene()->showBoundingRects()) {
        if (m_highlightBoundingRect)
            pen.setColor(frameColor);
        else
            pen.setColor(frameColor.darker(150));
    } else {
        if (m_highlightBoundingRect)
            pen.setColor(frameColor);
        else
            pen.setColor(Qt::transparent);
    }

    painter->setPen(pen);
//    int offset =  m_borderWidth / 2;

    painter->drawRect(boundingRect().adjusted(0., 0., -1., -1.));
}

void FormEditorItem::paintPlaceHolderForInvisbleItem(QPainter *painter) const
{
    qreal stripesWidth = 12;

    QRegion innerRegion = QRegion(boundingRect().adjusted(stripesWidth, stripesWidth, -stripesWidth, -stripesWidth).toRect());
    QRegion outerRegion  = QRegion(boundingRect().toRect()) - innerRegion;

    painter->setClipRegion(outerRegion);
    painter->setClipping(true);
    painter->fillRect(boundingRect().adjusted(1, 1, -1, -1), Qt::BDiagPattern);
    painter->setClipping(false);

    QString displayText = qmlItemNode().id();

    if (displayText.isEmpty())
        displayText = qmlItemNode().simplifiedTypeName();

    QTextOption textOption;
    textOption.setAlignment(Qt::AlignTop);
    textOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);

    if (boundingRect().height() > 60) {
        painter->save();

        QFont font;
        font.setStyleHint(QFont::SansSerif);
        font.setBold(true);
        font.setPixelSize(12);
        painter->setFont(font);

        QFontMetrics fm(font);
        painter->rotate(90);
        if (fm.width(displayText) > (boundingRect().height() - 32) && displayText.length() > 4) {

            displayText = fm.elidedText(displayText, Qt::ElideRight, boundingRect().height() - 32, Qt::TextShowMnemonic);
        }

        QRectF rotatedBoundingBox;
        rotatedBoundingBox.setWidth(boundingRect().height());
        rotatedBoundingBox.setHeight(12);
        rotatedBoundingBox.setY(-boundingRect().width() + 12);
        rotatedBoundingBox.setX(20);

        painter->setFont(font);
        painter->setPen(QColor(48, 48, 96, 255));
        painter->drawText(rotatedBoundingBox, displayText, textOption);

        painter->restore();
    }
}

void FormEditorItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
    if (!painter->isActive())
        return;

    if (!qmlItemNode().isValid())
        return;

    painter->save();

    if (qmlItemNode().instanceIsRenderPixmapNull() || !isContentVisible()) {
        if (scene()->showBoundingRects() && boundingRect().width() > 15 && boundingRect().height() > 15)
            paintPlaceHolderForInvisbleItem(painter);
    } else {
        qmlItemNode().paintInstance(painter);
    }

    if (!qmlItemNode().isRootModelNode())
        paintBoundingRect(painter);

    painter->restore();
}

AbstractFormEditorTool* FormEditorItem::tool() const
{
    return static_cast<FormEditorScene*>(scene())->currentTool();
}

SnapLineMap FormEditorItem::topSnappingLines() const
{
    return m_snappingLineCreator.topLines();
}

SnapLineMap FormEditorItem::bottomSnappingLines() const
{
    return m_snappingLineCreator.bottomLines();
}

SnapLineMap FormEditorItem::leftSnappingLines() const
{
    return m_snappingLineCreator.leftLines();
}

SnapLineMap FormEditorItem::rightSnappingLines() const
{
    return m_snappingLineCreator.rightLines();
}

SnapLineMap FormEditorItem::horizontalCenterSnappingLines() const
{
    return m_snappingLineCreator.horizontalCenterLines();
}

SnapLineMap FormEditorItem::verticalCenterSnappingLines() const
{
    return m_snappingLineCreator.verticalCenterLines();
}

SnapLineMap FormEditorItem::topSnappingOffsets() const
{
    return m_snappingLineCreator.topOffsets();
}

SnapLineMap FormEditorItem::bottomSnappingOffsets() const
{
    return m_snappingLineCreator.bottomOffsets();
}

SnapLineMap FormEditorItem::leftSnappingOffsets() const
{
    return m_snappingLineCreator.leftOffsets();
}

SnapLineMap FormEditorItem::rightSnappingOffsets() const
{
    return m_snappingLineCreator.rightOffsets();
}

void FormEditorItem::updateSnappingLines(const QList<FormEditorItem*> &exceptionList,
                                         FormEditorItem *transformationSpaceItem)
{
    m_snappingLineCreator.update(exceptionList, transformationSpaceItem);
}

QList<FormEditorItem*> FormEditorItem::childFormEditorItems() const
{
    QList<FormEditorItem*> formEditorItemList;

    foreach (QGraphicsItem *item, childItems()) {
        FormEditorItem *formEditorItem = fromQGraphicsItem(item);
        if (formEditorItem)
            formEditorItemList.append(formEditorItem);
    }

    return formEditorItemList;
}

bool FormEditorItem::isContainer() const
{
    return true;
}

QmlItemNode FormEditorItem::qmlItemNode() const
{
    return m_qmlItemNode;
}

}

<|endoftext|>


<commit_before>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_STACK_H_
#define LUWRA_STACK_H_

#include "common.hpp"
#include "types.hpp"

#include <utility>
#include <functional>

LUWRA_NS_BEGIN

namespace internal {
	template <typename T>
	struct Layout {
		static_assert(
			sizeof(T) == -1,
			"Parameter to Layout is not a function signature"
		);
	};

	template <typename R, typename T>
	struct Layout<R(T)> {
		template <typename F, typename... A> static inline
		R direct(State* state, int n, F hook, A&&... args) {
			return hook(
				std::forward<A>(args)...,
				Value<T>::read(state, n)
			);
		}
	};

	template <typename R, typename T1, typename... TR>
	struct Layout<R(T1, TR...)> {
		template <typename F, typename... A> static inline
		R direct(State* state, int n, F hook, A&&... args) {
			return Layout<R(TR...)>::direct(
				state,
				n + 1,
				hook,
				std::forward<A>(args)...,
				Value<T1>::read(state, n)
			);
		}
	};
}

/**
 * Assuming a stack layout as follows (where A = A0, A1 ... An):
 *
 *   Position | Parameter
 * 	----------+-----------
 *   pos + n  | An xn
 *   ...      | ...
 *   pos + 1  | A1 x1
 *   pos + 0  | A0 x0
 *   ...      | ...
 *
 * Given a function `R f(A0, A1, ... An)` you are able to map over
 * the values on the stack on the stack like so:
 *
 *   R my_result = apply(lua_state, pos, f);
 *
 * which is equivalent to
 *
 *   R my_result = f(x0, x1, ... xn);
 *
 * where x0, x1, ... xn are the values on the stack.
 */
template <typename R, typename... A> static inline
R apply(State* state, int pos, R (*function_pointer)(A...)) {
	return internal::Layout<R(A...)>::direct(state, pos, function_pointer);
}

/**
 * Same as `apply(state, 1, function_pointer)`.
 */
template <typename R, typename... A> static inline
R apply(State* state, R (*function_pointer)(A...)) {
	return apply(state, 1, function_pointer);
}

/**
 * Specialization of `apply` which works for `std::function`.
 */
template <typename R, typename... A> static inline
R apply(State* state, int pos, std::function<R(A...)> function_object) {
	return internal::Layout<R(A...)>::direct(state, pos, function_object);
}

/**
 * Same as `apply(state, 1, function_object)`.
 */
template <typename R, typename... A> static inline
R apply(State* state, std::function<R(A...)> function_object) {
	return apply(state, 1, function_object);
}

/**
 * Check if two values are equal.
 */
static inline
bool equal(State* state, int index1, int index2) {
#if LUA_VERSION_NUM <= 501
	return lua_equal(state, index1, index2);
#else
	return lua_compare(state, index1, index2, LUA_OPEQ);
#endif
}

/**
 * Register a value as a global.
 */
template <typename T> static inline
void register_global(State* state, const char* name, T value) {
	Value<T>::push(state, value);
	lua_setglobal(state, name);
}

LUWRA_NS_END

#endif
<commit_msg>Improve 'apply' overload which operates on function onjects<commit_after>/* Luwra
 * Minimal-overhead Lua wrapper for C++
 *
 * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
 */

#ifndef LUWRA_STACK_H_
#define LUWRA_STACK_H_

#include "common.hpp"
#include "types.hpp"

#include <utility>
#include <functional>

LUWRA_NS_BEGIN

namespace internal {
	template <typename T>
	struct Layout {
		static_assert(
			sizeof(T) == -1,
			"Parameter to Layout is not a function signature"
		);
	};

	template <typename R, typename T>
	struct Layout<R(T)> {
		template <typename F, typename... A> static inline
		R direct(State* state, int n, F hook, A&&... args) {
			return hook(
				std::forward<A>(args)...,
				Value<T>::read(state, n)
			);
		}
	};

	template <typename R, typename T1, typename... TR>
	struct Layout<R(T1, TR...)> {
		template <typename F, typename... A> static inline
		R direct(State* state, int n, F hook, A&&... args) {
			return Layout<R(TR...)>::direct(
				state,
				n + 1,
				hook,
				std::forward<A>(args)...,
				Value<T1>::read(state, n)
			);
		}
	};
}

/**
 * Assuming a stack layout as follows (where A = A0, A1 ... An):
 *
 *   Position | Parameter
 * 	----------+-----------
 *   pos + n  | An xn
 *   ...      | ...
 *   pos + 1  | A1 x1
 *   pos + 0  | A0 x0
 *   ...      | ...
 *
 * Given a function `R f(A0, A1, ... An)` you are able to map over
 * the values on the stack on the stack like so:
 *
 *   R my_result = apply(lua_state, pos, f);
 *
 * which is equivalent to
 *
 *   R my_result = f(x0, x1, ... xn);
 *
 * where x0, x1, ... xn are the values on the stack.
 */
template <typename R, typename... A> static inline
R apply(State* state, int pos, R (*function_pointer)(A...)) {
	return internal::Layout<R(A...)>::direct(state, pos, function_pointer);
}

/**
 * Same as `apply(state, 1, function_pointer)`.
 */
template <typename R, typename... A> static inline
R apply(State* state, R (*function_pointer)(A...)) {
	return apply(state, 1, function_pointer);
}

/**
 * Specialization of `apply` which works for `std::function`.
 */
template <typename R, typename... A> static inline
R apply(State* state, int pos, const std::function<R(A...)>& function_object) {
	return internal::Layout<R(A...)>::direct(state, pos, function_object);
}

/**
 * Same as `apply(state, 1, function_object)`.
 */
template <typename R, typename... A> static inline
R apply(State* state, const std::function<R(A...)>& function_object) {
	return apply(state, 1, function_object);
}

/**
 * Check if two values are equal.
 */
static inline
bool equal(State* state, int index1, int index2) {
#if LUA_VERSION_NUM <= 501
	return lua_equal(state, index1, index2);
#else
	return lua_compare(state, index1, index2, LUA_OPEQ);
#endif
}

/**
 * Register a value as a global.
 */
template <typename T> static inline
void register_global(State* state, const char* name, T value) {
	Value<T>::push(state, value);
	lua_setglobal(state, name);
}

LUWRA_NS_END

#endif
<|endoftext|>


<commit_before>#include <monsoon/xdr/xdr.h>
#include <algorithm>

namespace monsoon {
namespace xdr {

const std::size_t xdr_istream::BUFFER_SIZE = 65536u;

xdr_istream::xdr_istream(xdr_istream&& o) noexcept
: buffer_(std::move(o.buffer_)),
  buffer_off_(std::exchange(o.buffer_off_, 0u))
{}

xdr_istream& xdr_istream::operator=(xdr_istream&& o) noexcept {
  buffer_ = std::move(o.buffer_);
  buffer_off_ = std::exchange(o.buffer_off_, 0u);
  return *this;
}

xdr_istream::~xdr_istream() noexcept {}

void xdr_istream::get_raw_bytes_(void* dst_ptr, std::size_t len) {
  std::uint8_t* dst = reinterpret_cast<std::uint8_t*>(dst_ptr);

  while (len > 0u) {
    if (buffer_off_ < buffer_.size()) {
      const std::size_t rlen = std::min(buffer_.size() - buffer_off_, len);
      std::copy_n(buffer_.data() + buffer_off_, rlen, dst);
      len -= rlen;
      dst += rlen;
      buffer_off_ += rlen;
    }

    if (len > 0u && buffer_off_ == buffer_.size()) {
      if (len > BUFFER_SIZE) { // Pass-through read.
        const std::size_t rlen = get_raw_bytes(dst, len);
        assert(rlen <= len);
        len -= rlen;
        dst += rlen;
        if (rlen == 0u && at_end_()) throw xdr_stream_end();
      } else { // Fill buffer.
        buffer_off_ = 0u;
        buffer_.resize(BUFFER_SIZE);
        const std::size_t rlen = get_raw_bytes(buffer_.data(), buffer_.size());
        assert(rlen <= buffer.size());
        buffer_.resize(rlen);
        if (rlen == 0u && at_end_()) throw xdr_stream_end();
      }
    }
  }
}

bool xdr_istream::at_end() const {
  return buffer_off_ == buffer_.size() && at_end_();
}

xdr_ostream::~xdr_ostream() noexcept {}

xdr_exception::xdr_exception() {}

xdr_exception::~xdr_exception() {}

const char* xdr_exception::what() const noexcept {
  return (what_ == nullptr ? "monsoon::xdr::xdr_exception" : what_);
}

xdr_stream_end::xdr_stream_end() noexcept
: xdr_exception("monsoon::xdr::xdr_stream_end")
{}

xdr_stream_end::~xdr_stream_end() {}

}} /* namespace monsoon::xdr */
<commit_msg>Fix assertion.<commit_after>#include <monsoon/xdr/xdr.h>
#include <algorithm>

namespace monsoon {
namespace xdr {

const std::size_t xdr_istream::BUFFER_SIZE = 65536u;

xdr_istream::xdr_istream(xdr_istream&& o) noexcept
: buffer_(std::move(o.buffer_)),
  buffer_off_(std::exchange(o.buffer_off_, 0u))
{}

xdr_istream& xdr_istream::operator=(xdr_istream&& o) noexcept {
  buffer_ = std::move(o.buffer_);
  buffer_off_ = std::exchange(o.buffer_off_, 0u);
  return *this;
}

xdr_istream::~xdr_istream() noexcept {}

void xdr_istream::get_raw_bytes_(void* dst_ptr, std::size_t len) {
  std::uint8_t* dst = reinterpret_cast<std::uint8_t*>(dst_ptr);

  while (len > 0u) {
    if (buffer_off_ < buffer_.size()) {
      const std::size_t rlen = std::min(buffer_.size() - buffer_off_, len);
      std::copy_n(buffer_.data() + buffer_off_, rlen, dst);
      len -= rlen;
      dst += rlen;
      buffer_off_ += rlen;
    }

    if (len > 0u && buffer_off_ == buffer_.size()) {
      if (len > BUFFER_SIZE) { // Pass-through read.
        const std::size_t rlen = get_raw_bytes(dst, len);
        assert(rlen <= len);
        len -= rlen;
        dst += rlen;
        if (rlen == 0u && at_end_()) throw xdr_stream_end();
      } else { // Fill buffer.
        buffer_off_ = 0u;
        buffer_.resize(BUFFER_SIZE);
        const std::size_t rlen = get_raw_bytes(buffer_.data(), buffer_.size());
        assert(rlen <= buffer_.size());
        buffer_.resize(rlen);
        if (rlen == 0u && at_end_()) throw xdr_stream_end();
      }
    }
  }
}

bool xdr_istream::at_end() const {
  return buffer_off_ == buffer_.size() && at_end_();
}

xdr_ostream::~xdr_ostream() noexcept {}

xdr_exception::xdr_exception() {}

xdr_exception::~xdr_exception() {}

const char* xdr_exception::what() const noexcept {
  return (what_ == nullptr ? "monsoon::xdr::xdr_exception" : what_);
}

xdr_stream_end::xdr_stream_end() noexcept
: xdr_exception("monsoon::xdr::xdr_stream_end")
{}

xdr_stream_end::~xdr_stream_end() {}

}} /* namespace monsoon::xdr */
<|endoftext|>


<commit_before>/*
Copyright 2016 Colin Girling

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.
*/

#ifndef OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP
#define OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP

#include <fstream>
#include <iostream>

namespace ocl
{

struct TestStdioFileFunctor
{
    TestStdioFileFunctor(char const* file_name)
    {
        m_ostream.open(file_name, std::ofstream::out | std::ofstream::app);
    }

    ~TestStdioFileFunctor()
    {
        m_ostream.close();
    }

    /// This functor is called from FunctorTestLog::Write.
    void operator()(char const* str)
    {
        m_ostream << str;
        if (*str != '\n')
            std::cout << str;
        else
            std::cout << std::endl;
    }

private:
    std::ofstream m_ostream;
};

} // namespace ocl

#endif // OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP
<commit_msg>Minor update to use initialiser list.<commit_after>/*
Copyright 2016 Colin Girling

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.
*/

#ifndef OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP
#define OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP

#include <fstream>
#include <iostream>

namespace ocl
{

struct TestStdioFileFunctor
{
    TestStdioFileFunctor(char const* file_name)
        : m_ostream(file_name, std::ofstream::out | std::ofstream::app)
    {
    }

    ~TestStdioFileFunctor()
    {
        m_ostream.close();
    }

    /// This functor is called from FunctorTestLog::Write.
    void operator()(char const* str)
    {
        m_ostream << str;
        if (*str != '\n')
            std::cout << str;
        else
            std::cout << std::endl;
    }

private:
    std::ofstream m_ostream;
};

} // namespace ocl

#endif // OCL_GUARD_TEST_TESTSTDIOFILEFUNCTOR_HPP
<|endoftext|>