<commit_before>/*

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

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

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

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

*/

#ifndef NODE_HPP
#define NODE_HPP

#include <algorithm>
#include <map>
#include <set>

#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/find_data.hpp>

#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/thread.hpp>

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/ref.hpp>
#include <boost/optional.hpp>

#include "libtorrent/socket.hpp"

namespace libtorrent {

	namespace aux { struct session_impl; }
	struct session_status;

}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif

class traversal_algorithm;

struct key_desc_t
{
	char const* name;
	int type;
	int size;
	int flags;

	enum { optional = 1};
};

bool TORRENT_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
	, int size , char* error, int error_size);

// this is the entry for every peer
// the timestamp is there to make it possible
// to remove stale peers
struct peer_entry
{
	tcp::endpoint addr;
	ptime added;
};

// this is a group. It contains a set of group members
struct torrent_entry
{
	std::set<peer_entry> peers;
};

// this is the entry for a torrent that has been published
// in the DHT.
struct search_torrent_entry
{
	// the tags of the torrent. The key of
	// this entry is the sha-1 hash of one of
	// these tags. The counter is the number of
	// times a tag has been included in a publish
	// call. The counters are periodically
	// decremented by a factor, so that the
	// popularity ratio between the tags is
	// maintained. The decrement is rounded down.
	std::map<std::string, int> tags;

	// this is the sum of all values in the tags
	// map. It is only an optimization to avoid
	// recalculating it constantly
	int total_tag_points;

	// the name of the torrent
	std::map<std::string, int> name;
	int total_name_points;

	// increase the popularity counters for this torrent
	void publish(std::string const& name, char const* in_tags[], int num_tags);

	// return a score of how well this torrent matches
	// the given set of tags. Each word in the string
	// (separated by a space) is considered a tag.
	// tags with 2 letters or fewer are ignored
	int match(char const* tags[], int num_tags) const;

	// this is called once every hour, and will
	// decrement the popularity counters of the
	// tags. Returns true if this entry should
	// be deleted
	bool tick();

	void get_name(std::string& t) const;
	void get_tags(std::string& t) const;
};

inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{
	return lhs.addr.address() == rhs.addr.address()
		? lhs.addr.port() < rhs.addr.port()
		: lhs.addr.address() < rhs.addr.address();
}

struct null_type {};

class announce_observer : public observer
{
public:
	announce_observer(boost::intrusive_ptr<traversal_algorithm> const& algo)
		: observer(algo)
	{}

	void reply(msg const&) { m_done = true; }
};

struct count_peers
{
	int& count;
	count_peers(int& c): count(c) {}
	void operator()(std::pair<libtorrent::dht::node_id
		, libtorrent::dht::torrent_entry> const& t)
	{
		count += t.second.peers.size();
	}
};

class node_impl : boost::noncopyable
{
typedef std::map<node_id, torrent_entry> table_t;
typedef std::map<std::pair<node_id, sha1_hash>, search_torrent_entry> search_table_t;
public:
	node_impl(libtorrent::aux::session_impl& ses
		, bool (*f)(void*, entry const&, udp::endpoint const&, int)
		, dht_settings const& settings, boost::optional<node_id> nid
		, void* userdata);

	virtual ~node_impl() {}

	void refresh(node_id const& id, find_data::nodes_callback const& f);
	void bootstrap(std::vector<udp::endpoint> const& nodes
		, find_data::nodes_callback const& f);
	void add_router_node(udp::endpoint router);

	void unreachable(udp::endpoint const& ep);
	void incoming(msg const& m);

	int num_torrents() const { return m_map.size(); }
	int num_peers() const
	{
		int ret = 0;
		std::for_each(m_map.begin(), m_map.end(), count_peers(ret));
		return ret;
	}

	void refresh();
	void refresh_bucket(int bucket);
	int bucket_size(int bucket);

	typedef routing_table::iterator iterator;

	iterator begin() const { return m_table.begin(); }
	iterator end() const { return m_table.end(); }

	node_id const& nid() const { return m_id; }

	boost::tuple<int, int> size() const{ return m_table.size(); }
	size_type num_global_nodes() const
	{ return m_table.num_global_nodes(); }

	int data_size() const { return int(m_map.size()); }

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	void print_state(std::ostream& os) const
	{ m_table.print_state(os); }
#endif

	void announce(sha1_hash const& info_hash, int listen_port
		, boost::function<void(std::vector<tcp::endpoint> const&)> f);

	bool verify_token(std::string const& token, char const* info_hash
		, udp::endpoint const& addr);

	std::string generate_token(udp::endpoint const& addr, char const* info_hash);

	// the returned time is the delay until connection_timeout()
	// should be called again the next time
	time_duration connection_timeout();
	time_duration refresh_timeout();

	// generates a new secret number used to generate write tokens
	void new_write_key();

	// pings the given node, and adds it to
	// the routing table if it respons and if the
	// bucket is not full.
	void add_node(udp::endpoint node);

	void replacement_cache(bucket_t& nodes) const
	{ m_table.replacement_cache(nodes); }

	int branch_factor() const { return m_settings.search_branching; }

	void add_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.insert(a);
	}

	void remove_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.erase(a);
	}

	void status(libtorrent::session_status& s);

protected:
	// is called when a find data request is received. Should
	// return false if the data is not stored on this node. If
	// the data is stored, it should be serialized into 'data'.
	bool lookup_peers(sha1_hash const& info_hash, entry& reply) const;
	bool lookup_torrents(sha1_hash const& target, entry& reply
		, char* tags) const;

	dht_settings const& m_settings;

	// the maximum number of peers to send in a get_peers
	// reply. Ordinary trackers usually limit this to 50.
	// 50 => 6 * 50 = 250 bytes + packet overhead
	int m_max_peers_reply;

private:
	typedef libtorrent::mutex mutex_t;
	mutex_t m_mutex;

	// this list must be destructed after the rpc manager
	// since it might have references to it
	std::set<traversal_algorithm*> m_running_requests;

	void incoming_request(msg const& h, entry& e);

	node_id m_id;

public:
	routing_table m_table;
	rpc_manager m_rpc;

private:
	table_t m_map;
	search_table_t m_search_map;

	ptime m_last_tracker_tick;

	// secret random numbers used to create write tokens
	int m_secret[2];

	libtorrent::aux::session_impl& m_ses;
	bool (*m_send)(void*, entry const&, udp::endpoint const&, int);
	void* m_userdata;
};

} } // namespace libtorrent::dht

#endif // NODE_HPP

<commit_msg>dht fix<commit_after>/*

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

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

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

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

*/

#ifndef NODE_HPP
#define NODE_HPP

#include <algorithm>
#include <map>
#include <set>

#include <libtorrent/kademlia/routing_table.hpp>
#include <libtorrent/kademlia/rpc_manager.hpp>
#include <libtorrent/kademlia/node_id.hpp>
#include <libtorrent/kademlia/msg.hpp>
#include <libtorrent/kademlia/find_data.hpp>

#include <libtorrent/io.hpp>
#include <libtorrent/session_settings.hpp>
#include <libtorrent/assert.hpp>
#include <libtorrent/thread.hpp>

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/iterator/transform_iterator.hpp>
#include <boost/ref.hpp>
#include <boost/optional.hpp>

#include "libtorrent/socket.hpp"

namespace libtorrent {

	namespace aux { struct session_impl; }
	struct session_status;

}

namespace libtorrent { namespace dht
{

#ifdef TORRENT_DHT_VERBOSE_LOGGING
TORRENT_DECLARE_LOG(node);
#endif

class traversal_algorithm;

struct key_desc_t
{
	char const* name;
	int type;
	int size;
	int flags;

	enum { optional = 1};
};

bool TORRENT_EXPORT verify_message(lazy_entry const* msg, key_desc_t const desc[], lazy_entry const* ret[]
	, int size , char* error, int error_size);

// this is the entry for every peer
// the timestamp is there to make it possible
// to remove stale peers
struct peer_entry
{
	tcp::endpoint addr;
	ptime added;
};

// this is a group. It contains a set of group members
struct torrent_entry
{
	std::set<peer_entry> peers;
};

// this is the entry for a torrent that has been published
// in the DHT.
struct search_torrent_entry
{
	search_torrent_entry(): total_tag_points(0), total_name_points(0) {}

	// the tags of the torrent. The key of
	// this entry is the sha-1 hash of one of
	// these tags. The counter is the number of
	// times a tag has been included in a publish
	// call. The counters are periodically
	// decremented by a factor, so that the
	// popularity ratio between the tags is
	// maintained. The decrement is rounded down.
	std::map<std::string, int> tags;

	// this is the sum of all values in the tags
	// map. It is only an optimization to avoid
	// recalculating it constantly
	int total_tag_points;

	// the name of the torrent
	std::map<std::string, int> name;
	int total_name_points;

	// increase the popularity counters for this torrent
	void publish(std::string const& name, char const* in_tags[], int num_tags);

	// return a score of how well this torrent matches
	// the given set of tags. Each word in the string
	// (separated by a space) is considered a tag.
	// tags with 2 letters or fewer are ignored
	int match(char const* tags[], int num_tags) const;

	// this is called once every hour, and will
	// decrement the popularity counters of the
	// tags. Returns true if this entry should
	// be deleted
	bool tick();

	void get_name(std::string& t) const;
	void get_tags(std::string& t) const;
};

inline bool operator<(peer_entry const& lhs, peer_entry const& rhs)
{
	return lhs.addr.address() == rhs.addr.address()
		? lhs.addr.port() < rhs.addr.port()
		: lhs.addr.address() < rhs.addr.address();
}

struct null_type {};

class announce_observer : public observer
{
public:
	announce_observer(boost::intrusive_ptr<traversal_algorithm> const& algo)
		: observer(algo)
	{}

	void reply(msg const&) { m_done = true; }
};

struct count_peers
{
	int& count;
	count_peers(int& c): count(c) {}
	void operator()(std::pair<libtorrent::dht::node_id
		, libtorrent::dht::torrent_entry> const& t)
	{
		count += t.second.peers.size();
	}
};

class node_impl : boost::noncopyable
{
typedef std::map<node_id, torrent_entry> table_t;
typedef std::map<std::pair<node_id, sha1_hash>, search_torrent_entry> search_table_t;
public:
	node_impl(libtorrent::aux::session_impl& ses
		, bool (*f)(void*, entry const&, udp::endpoint const&, int)
		, dht_settings const& settings, boost::optional<node_id> nid
		, void* userdata);

	virtual ~node_impl() {}

	void refresh(node_id const& id, find_data::nodes_callback const& f);
	void bootstrap(std::vector<udp::endpoint> const& nodes
		, find_data::nodes_callback const& f);
	void add_router_node(udp::endpoint router);

	void unreachable(udp::endpoint const& ep);
	void incoming(msg const& m);

	int num_torrents() const { return m_map.size(); }
	int num_peers() const
	{
		int ret = 0;
		std::for_each(m_map.begin(), m_map.end(), count_peers(ret));
		return ret;
	}

	void refresh();
	void refresh_bucket(int bucket);
	int bucket_size(int bucket);

	typedef routing_table::iterator iterator;

	iterator begin() const { return m_table.begin(); }
	iterator end() const { return m_table.end(); }

	node_id const& nid() const { return m_id; }

	boost::tuple<int, int> size() const{ return m_table.size(); }
	size_type num_global_nodes() const
	{ return m_table.num_global_nodes(); }

	int data_size() const { return int(m_map.size()); }

#ifdef TORRENT_DHT_VERBOSE_LOGGING
	void print_state(std::ostream& os) const
	{ m_table.print_state(os); }
#endif

	void announce(sha1_hash const& info_hash, int listen_port
		, boost::function<void(std::vector<tcp::endpoint> const&)> f);

	bool verify_token(std::string const& token, char const* info_hash
		, udp::endpoint const& addr);

	std::string generate_token(udp::endpoint const& addr, char const* info_hash);

	// the returned time is the delay until connection_timeout()
	// should be called again the next time
	time_duration connection_timeout();
	time_duration refresh_timeout();

	// generates a new secret number used to generate write tokens
	void new_write_key();

	// pings the given node, and adds it to
	// the routing table if it respons and if the
	// bucket is not full.
	void add_node(udp::endpoint node);

	void replacement_cache(bucket_t& nodes) const
	{ m_table.replacement_cache(nodes); }

	int branch_factor() const { return m_settings.search_branching; }

	void add_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.insert(a);
	}

	void remove_traversal_algorithm(traversal_algorithm* a)
	{
		mutex_t::scoped_lock l(m_mutex);
		m_running_requests.erase(a);
	}

	void status(libtorrent::session_status& s);

protected:
	// is called when a find data request is received. Should
	// return false if the data is not stored on this node. If
	// the data is stored, it should be serialized into 'data'.
	bool lookup_peers(sha1_hash const& info_hash, entry& reply) const;
	bool lookup_torrents(sha1_hash const& target, entry& reply
		, char* tags) const;

	dht_settings const& m_settings;

	// the maximum number of peers to send in a get_peers
	// reply. Ordinary trackers usually limit this to 50.
	// 50 => 6 * 50 = 250 bytes + packet overhead
	int m_max_peers_reply;

private:
	typedef libtorrent::mutex mutex_t;
	mutex_t m_mutex;

	// this list must be destructed after the rpc manager
	// since it might have references to it
	std::set<traversal_algorithm*> m_running_requests;

	void incoming_request(msg const& h, entry& e);

	node_id m_id;

public:
	routing_table m_table;
	rpc_manager m_rpc;

private:
	table_t m_map;
	search_table_t m_search_map;

	ptime m_last_tracker_tick;

	// secret random numbers used to create write tokens
	int m_secret[2];

	libtorrent::aux::session_impl& m_ses;
	bool (*m_send)(void*, entry const&, udp::endpoint const&, int);
	void* m_userdata;
};

} } // namespace libtorrent::dht

#endif // NODE_HPP

<|endoftext|>


<commit_before>#ifndef MOS_RENDERER_H
#define MOS_RENDERER_H

#include <GL/glew.h>
#include <optional.hpp>
#include <initializer_list>
#include <unordered_map>
#include <optional.hpp>
#include <array>
#include <mos/render/render_scene.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>
#include <mos/render/model.hpp>
#include <mos/render/text.hpp>
#include <mos/render/particles.hpp>
#include <mos/render/light.hpp>
#include <mos/render/render_target.hpp>
#include <mos/render/render_camera.hpp>
#include <mos/render/environment_light.hpp>
#include <mos/render/fog.hpp>
#include <mos/render/render_box.hpp>
#include <mos/render/decal.hpp>

namespace mos {

/**
 * @brief Render geometry.
 * Talks to OpenGL, and renders Model objects.
 */
class RenderSystem {
public:
  using Decals = std::vector<Decal>;

  /**
   * @brief Renderer constructor.
   * Inits the renderer, in this implementation also creates a
   * valid OpenGL context with GLEW.
   */
  RenderSystem(const glm::vec4 &color = glm::vec4(.0f));
  /**
   * @brief Renderer destructor.
   * Deletes all allocated GPU memory. Textures, Shaders, Buffers.
   */
  ~RenderSystem();

  // Temporary method
  void update_depth(const Model &model, const glm::mat4 &parent_transform,
                    const glm::mat4 &view, const glm::mat4 &projection,
                    const glm::vec2 &resolution);

  /**
   * @brief load a model into renderers own memory.
   * @param model
   */
  void load(const Model &model);

  /**
   * @brief unload a model from renderers own memory.
   * @param model
   */
  void unload(const Model &model);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTexture &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTexture &texture);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTextureCube &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTextureCube &texture);

  void render_scenes(const std::initializer_list<RenderScene> &scenes_init,
                     const glm::vec4 &color = glm::vec4(.0f),
                     const OptTarget &target = OptTarget());

  template<class Ts>
  void render_scenes(Ts scenes_begin,
                     Ts scenes_end,
                     const glm::vec4 &color = {.0f, .0f, .0f, 1.0f},
                     const OptTarget &target = OptTarget()) {
    render_target(target);
    if (target && target->texture_cube) {
      auto texture_id = texture_cubes_[target->id()];
        for (auto it = scenes_begin; it != scenes_end; it++) {
          for (auto c_it = it->cameras.begin(); c_it != it->cameras.end(); c_it++){
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                   GL_TEXTURE_CUBE_MAP_POSITIVE_X + std::distance(it->cameras.begin(), c_it), texture_id, 0);
            clear(color);
          render_scene(*c_it, *it);
        }
      }
      glBindTexture(GL_TEXTURE_CUBE_MAP, texture_id);
      glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    }

    clear(color);
    for (auto it = scenes_begin; it != scenes_end; it++) {
      for (auto &camera : it->cameras) {
        render_scene(camera, *it);
      }
    }
  }

  /**
   * @brief Clear all internal buffers.
   */
  void clear_buffers();

  /*
   * For multisampled render target
  void render_target_reset(unsigned int width, unsigned int height) {
    glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  */

  /**
   * @brief Set lightmap use.
   */
  void lightmaps(const bool lightmaps);

  /**
   * @brief Check if lightmaps is enabled.
   * @return True if lightmaps are enabled.
   */
  bool lightmaps() const;

  // TODO: Private
  GLuint depth_texture_;
  GLuint depth_frame_buffer_;

private:
  /**
   * @brief models_batch rendering.
   * @param render_scene
   */
  void render_scene(const RenderCamera &camera, const RenderScene &render_scene);

  /**
   * @brief Updates render state of model.
   * @param model
   * @param transform Additional transform matrix.
   * @param view View matrix of the camera
   * @param projection Projection matrix of the camera
   * @param program_name Either "text" or "standard"
   * @param light One dynamic light to use.
   */
  void render(const Model &model,
              const Decals &diffuse_decals,
              const glm::mat4 &transform,
              const RenderCamera &camera,
              const Light &light,
              const EnvironmentLight &environment,
              const Fog &fog,
              const RenderScene::Shader &shader,
              const RenderScene::Draw &draw);

  /**
   * @brief render_target
   * @param target
   */
  void render_target(const OptTarget &target);

  /**
   * @brief clear
   * @param color
   */
  void clear(const glm::vec4 &color);

  /**
   * @brief The ParticleProgramData struct, uniforms for the particle shader
   * program.
   */
  struct ParticleProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  /**
   * @brief The BoxProgramData struct, uniforms for the bounding box shader
   * program.
   */
  struct BoxProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  struct DepthProgramData {
    GLuint program;
    GLint mvp;
  };

  /**
   * @brief The VertexProgramData struct, uniforms for the standard shader.
   */
  class VertexProgramData {
  public:
    //TODO make all const
    VertexProgramData() {};
    VertexProgramData(const GLuint program);
    GLuint program;
    GLint model_view_projection_matrix;
    GLint model_view_matrix;
    GLint model_matrix;
    GLint view_matrix;
    GLint normal_matrix;
    GLint depth_bias_mvp;

    GLint shadow_map;

    std::array<GLint, 20> decal_mvps;
    std::array<GLint, 20> decal_material_diffuse_maps;

    GLint environment_map;
    GLint environment_position;
    GLint environment_extent;

    GLint material_diffuse_map;
    GLint material_light_map;
    GLint material_normal_map;
    GLint material_ambient_color;
    GLint material_diffuse_color;
    GLint material_specular_color;
    GLint material_specular_exponent;
    GLint material_opacity;

    GLint camera_resolution;
    GLint camera_position;

    GLint light_position;
    GLint light_diffuse_color;
    GLint light_specular_color;
    GLint light_view;
    GLint light_projection;
    GLint light_linear_attenuation_factor;
    GLint light_quadratic_attenuation_factor;

    GLint fog_color_near;
    GLint fog_color_far;
    GLint fog_near;
    GLint fog_far;
    GLint fog_linear_factor;
    GLint fog_exponential_factor;
    GLint fog_exponential_power;
    GLint fog_exponential_attenuation_factor;
  };

  using VertexProgramPair = std::pair<RenderScene::Shader, VertexProgramData>;
  using ParticleProgramPair = std::pair<std::string, ParticleProgramData>;
  using BoxProgramPair = std::pair<std::string, BoxProgramData>;

  bool lightmaps_;
  void add_vertex_program(const RenderScene::Shader shader,
                          const std::string vertex_shader_source,
                          const std::string fragment_shader_source,
                          const std::string &vert_file_name = "",
                          const std::string &frag_file_name = "");

  void add_particle_program(const std::string name, const std::string vs_source,
                            const std::string fs_source, const std::string &vs_file = "",
                            const std::string &fs_file = "");

  unsigned int create_shader(const std::string &source,
                             const unsigned int type);
  bool check_shader(const unsigned int shader, const std::string &name = "");

  bool check_program(const unsigned int program);

  unsigned int create_texture(const SharedTexture &texture);

  unsigned int create_texture_cube(const SharedTextureCube &texture);

  unsigned int
  create_texture_and_pbo(const SharedTexture &texture);
  void add_box_program(const std::string &name, const std::string &vs_source,
                       const std::string &fs_source, const std::string &vs_file,
                       const std::string &fs_file);

  void create_depth_program();

  std::map<RenderScene::Shader, VertexProgramData> vertex_programs_;
  std::unordered_map<std::string, ParticleProgramData> particle_programs_;
  std::unordered_map<std::string, BoxProgramData> box_programs_;
  DepthProgramData depth_program_;

  std::unordered_map<unsigned int, GLuint> frame_buffers_;
  std::unordered_map<unsigned int, GLuint> render_buffers;
  std::unordered_map<unsigned int, GLuint> pixel_buffers_;
  std::unordered_map<unsigned int, GLuint> textures_;
  std::unordered_map<unsigned int, GLuint> texture_cubes_;
  std::unordered_map<unsigned int, GLuint> array_buffers_;
  std::unordered_map<unsigned int, GLuint> element_array_buffers_;
  std::unordered_map<unsigned int, GLuint> vertex_arrays_;

  GLuint empty_texture_;
  GLuint box_vbo;
  GLuint box_ebo;
  GLuint box_va;
};
}
#endif /* MOS_RENDERER_H */
<commit_msg>Check<commit_after>#ifndef MOS_RENDERER_H
#define MOS_RENDERER_H

#include <GL/glew.h>
#include <optional.hpp>
#include <initializer_list>
#include <unordered_map>
#include <optional.hpp>
#include <array>
#include <mos/render/render_scene.hpp>
#include <mos/render/texture_2d.hpp>
#include <mos/render/texture_cube.hpp>
#include <mos/render/model.hpp>
#include <mos/render/text.hpp>
#include <mos/render/particles.hpp>
#include <mos/render/light.hpp>
#include <mos/render/render_target.hpp>
#include <mos/render/render_camera.hpp>
#include <mos/render/environment_light.hpp>
#include <mos/render/fog.hpp>
#include <mos/render/render_box.hpp>
#include <mos/render/decal.hpp>
#include "texture.hpp"

namespace mos {

/**
 * @brief Render geometry.
 * Talks to OpenGL, and renders Model objects.
 */
class RenderSystem {
public:
  using Decals = std::vector<Decal>;

  /**
   * @brief Renderer constructor.
   * Inits the renderer, in this implementation also creates a
   * valid OpenGL context with GLEW.
   */
  RenderSystem(const glm::vec4 &color = glm::vec4(.0f));
  /**
   * @brief Renderer destructor.
   * Deletes all allocated GPU memory. Textures, Shaders, Buffers.
   */
  ~RenderSystem();

  // Temporary method
  void update_depth(const Model &model, const glm::mat4 &parent_transform,
                    const glm::mat4 &view, const glm::mat4 &projection,
                    const glm::vec2 &resolution);

  /**
   * @brief load a model into renderers own memory.
   * @param model
   */
  void load(const Model &model);

  /**
   * @brief unload a model from renderers own memory.
   * @param model
   */
  void unload(const Model &model);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTexture &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTexture &texture);

  /**
   * @brief Load a texture into renderer memory.
   * @param texture The texture.
   */
  void load(const SharedTextureCube &texture);

  /**
   * @brief unload a texture from renderer memory.
   * @param texture The texture.
   */
  void unload(const SharedTextureCube &texture);

  void render_scenes(const std::initializer_list<RenderScene> &scenes_init,
                     const glm::vec4 &color = glm::vec4(.0f),
                     const OptTarget &target = OptTarget());

  template<class Ts>
  void render_scenes(Ts scenes_begin,
                     Ts scenes_end,
                     const glm::vec4 &color = {.0f, .0f, .0f, 1.0f},
                     const OptTarget &target = OptTarget()) {
    render_target(target);
    if (target && target->texture_cube) {
      auto texture_id = texture_cubes_[target->id()];
        for (auto it = scenes_begin; it != scenes_end; it++) {
          for (auto c_it = it->cameras.begin(); c_it != it->cameras.end(); c_it++){
            glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                                   GL_TEXTURE_CUBE_MAP_POSITIVE_X + std::distance(it->cameras.begin(), c_it), texture_id, 0);
            clear(color);
          render_scene(*c_it, *it);
        }
      }
      glBindTexture(GL_TEXTURE_CUBE_MAP, texture_id);
      glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
      glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
    }

    clear(color);
    for (auto it = scenes_begin; it != scenes_end; it++) {
      for (auto &camera : it->cameras) {
        render_scene(camera, *it);
      }
    }
  }

  /**
   * @brief Clear all internal buffers.
   */
  void clear_buffers();

  /*
   * For multisampled render target
  void render_target_reset(unsigned int width, unsigned int height) {
    glBindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);
    glBlitFramebuffer(0, 0, width, height, 0, 0, width, height,
                      GL_COLOR_BUFFER_BIT, GL_NEAREST);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
  }
  */

  /**
   * @brief Set lightmap use.
   */
  void lightmaps(const bool lightmaps);

  /**
   * @brief Check if lightmaps is enabled.
   * @return True if lightmaps are enabled.
   */
  bool lightmaps() const;

  // TODO: Private
  GLuint depth_texture_;
  GLuint depth_frame_buffer_;

private:
  /**
   * @brief models_batch rendering.
   * @param render_scene
   */
  void render_scene(const RenderCamera &camera, const RenderScene &render_scene);

  /**
   * @brief Updates render state of model.
   * @param model
   * @param transform Additional transform matrix.
   * @param view View matrix of the camera
   * @param projection Projection matrix of the camera
   * @param program_name Either "text" or "standard"
   * @param light One dynamic light to use.
   */
  void render(const Model &model,
              const Decals &diffuse_decals,
              const glm::mat4 &transform,
              const RenderCamera &camera,
              const Light &light,
              const EnvironmentLight &environment,
              const Fog &fog,
              const RenderScene::Shader &shader,
              const RenderScene::Draw &draw);

  /**
   * @brief render_target
   * @param target
   */
  void render_target(const OptTarget &target);

  /**
   * @brief clear
   * @param color
   */
  void clear(const glm::vec4 &color);

  /**
   * @brief The ParticleProgramData struct, uniforms for the particle shader
   * program.
   */
  struct ParticleProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  /**
   * @brief The BoxProgramData struct, uniforms for the bounding box shader
   * program.
   */
  struct BoxProgramData {
    GLuint program;
    GLint mvp;
    GLint mv;
  };

  struct DepthProgramData {
    GLuint program;
    GLint mvp;
  };

  /**
   * @brief The VertexProgramData struct, uniforms for the standard shader.
   */
  class VertexProgramData {
  public:
    //TODO make all const
    VertexProgramData() {};
    VertexProgramData(const GLuint program);
    GLuint program;
    GLint model_view_projection_matrix;
    GLint model_view_matrix;
    GLint model_matrix;
    GLint view_matrix;
    GLint normal_matrix;
    GLint depth_bias_mvp;

    GLint shadow_map;

    std::array<GLint, 20> decal_mvps;
    std::array<GLint, 20> decal_material_diffuse_maps;

    GLint environment_map;
    GLint environment_position;
    GLint environment_extent;

    GLint material_diffuse_map;
    GLint material_light_map;
    GLint material_normal_map;
    GLint material_ambient_color;
    GLint material_diffuse_color;
    GLint material_specular_color;
    GLint material_specular_exponent;
    GLint material_opacity;

    GLint camera_resolution;
    GLint camera_position;

    GLint light_position;
    GLint light_diffuse_color;
    GLint light_specular_color;
    GLint light_view;
    GLint light_projection;
    GLint light_linear_attenuation_factor;
    GLint light_quadratic_attenuation_factor;

    GLint fog_color_near;
    GLint fog_color_far;
    GLint fog_near;
    GLint fog_far;
    GLint fog_linear_factor;
    GLint fog_exponential_factor;
    GLint fog_exponential_power;
    GLint fog_exponential_attenuation_factor;
  };

  using VertexProgramPair = std::pair<RenderScene::Shader, VertexProgramData>;
  using ParticleProgramPair = std::pair<std::string, ParticleProgramData>;
  using BoxProgramPair = std::pair<std::string, BoxProgramData>;

  bool lightmaps_;
  void add_vertex_program(const RenderScene::Shader shader,
                          const std::string vertex_shader_source,
                          const std::string fragment_shader_source,
                          const std::string &vert_file_name = "",
                          const std::string &frag_file_name = "");

  void add_particle_program(const std::string name, const std::string vs_source,
                            const std::string fs_source, const std::string &vs_file = "",
                            const std::string &fs_file = "");

  unsigned int create_shader(const std::string &source,
                             const unsigned int type);
  bool check_shader(const unsigned int shader, const std::string &name = "");

  bool check_program(const unsigned int program);

  unsigned int create_texture(const SharedTexture &texture);

  unsigned int create_texture_cube(const SharedTextureCube &texture);

  unsigned int
  create_texture_and_pbo(const SharedTexture &texture);
  void add_box_program(const std::string &name, const std::string &vs_source,
                       const std::string &fs_source, const std::string &vs_file,
                       const std::string &fs_file);

  void create_depth_program();

  std::map<RenderScene::Shader, VertexProgramData> vertex_programs_;
  std::unordered_map<std::string, ParticleProgramData> particle_programs_;
  std::unordered_map<std::string, BoxProgramData> box_programs_;
  DepthProgramData depth_program_;

  std::unordered_map<unsigned int, GLuint> frame_buffers_;
  std::unordered_map<unsigned int, GLuint> render_buffers;
  std::unordered_map<unsigned int, GLuint> pixel_buffers_;
  std::unordered_map<unsigned int, GLuint> textures_;
  std::unordered_map<unsigned int, GLuint> texture_cubes_;
  std::unordered_map<unsigned int, GLuint> array_buffers_;
  std::unordered_map<unsigned int, GLuint> element_array_buffers_;
  std::unordered_map<unsigned int, GLuint> vertex_arrays_;

  GLuint empty_texture_;
  GLuint box_vbo;
  GLuint box_ebo;
  GLuint box_va;
};

}
#endif /* MOS_RENDERER_H */
<|endoftext|>


<commit_before>/** Type/template metaprogramming utilities for use internally in libpqxx
 *
 * Copyright (c) 2000-2019, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 */
#ifndef PQXX_H_TYPE_UTILS
#define PQXX_H_TYPE_UTILS

#include <memory>
#include <type_traits>

#include <optional>

namespace pqxx::internal
{
/// Replicate std::void_t<> (available in C++17).
template<typename... T> using void_t = void;

/// Extract the content type held by an `optional`-like wrapper type.
template<typename T> using inner_type = typename std::remove_reference<
  decltype(*std::declval<T>())
>::type;

/// Does the given type have an `operator *()`?
template<typename T, typename = void> struct is_derefable : std::false_type {};
template<typename T> struct is_derefable<T, void_t<
  // Disable for arrays so they don't erroneously decay to pointers.
  inner_type<typename std::enable_if<not std::is_array<T>::value, T>::type>
>> : std::true_type {};

/// Should the given type be treated as an optional-value wrapper type?
template<typename T, typename = void> struct is_optional : std::false_type {};
template<typename T> struct is_optional<T, typename std::enable_if<(
  is_derefable<T>::value
  // Check if an `explicit operator bool` exists for this type
  && std::is_constructible<bool, T>::value
)>::type> : std::true_type {};

/// Can `nullopt_t` implicitly convert to type T?
template<
  typename T,
  typename = void
> struct takes_std_nullopt : std::false_type {};

template<typename T> struct takes_std_nullopt<
    T,
    typename std::enable_if<std::is_assignable<T, std::nullopt_t>::value>::type
> : std::true_type {};

/// Is type T a `std::tuple<>`?
template<typename T, typename = void> struct is_tuple : std::false_type {};
template<typename T> struct is_tuple<
  T,
  typename std::enable_if<(std::tuple_size<T>::value >= 0)>::type
> : std::true_type {};

/// Is type T an iterable container?
template<typename T, typename = void> struct is_container : std::false_type {};
template<typename T> struct is_container<
  T,
  void_t<
    decltype(std::begin(std::declval<T>())),
    decltype(std::end(std::declval<T>())),
    // Some people might implement a `std::tuple<>` specialization that is
    // iterable when all the contained types are the same ;)
    typename std::enable_if<not is_tuple<T>::value>::type
  >
> : std::true_type {};

/// Get an appropriate null value for the given type.
/**
 * pointer types                         `nullptr`
 * `std::optional<>`-like                `std::nullopt`
 * `std::experimental::optional<>`-like  `std::experimental::nullopt`
 * other types                           `pqxx::string_traits<>::null()`
 * Users may add support for their own wrapper types following this pattern.
 */
template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    (
      is_optional<T>::value
      && not takes_std_nullopt<T>::value
      && std::is_assignable<T, std::nullptr_t>::value
    ),
    std::nullptr_t
  >::type
{ return nullptr; }

template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    (not is_optional<T>::value && not takes_std_nullopt<T>::value),
    decltype(pqxx::string_traits<T>::null())
  >::type
{ return pqxx::string_traits<T>::null(); }

template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    takes_std_nullopt<T>::value,
    std::nullopt_t
  >::type
{ return std::nullopt; }

/// Construct an optional-like type from the stored type.
/**
 * While these may seem redundant, they are necessary to support smart pointers
 * as optional storage types in a generic manner.  It is suggested NOT to
 * provide a version for `inner_type<T>*` as that will almost certainly leak
 * memory.
 * Users may add support for their own wrapper types following this pattern.
 */
// Enabled if the wrapper type can be directly constructed from the wrapped type
// (e.g. `std::optional<>`); explicitly disabled for raw pointers in case the
// inner type is convertible to a pointer (e.g. `int`)
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    not std::is_same<T, inner_type<T>*>::value,
    decltype(T(std::forward<V>(v)))
  >::type
{ return T(std::forward<V>(v)); }
// Enabled if T is a specialization of `std::unique_ptr<>`.
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    std::is_same<T, std::unique_ptr<inner_type<T>>>::value,
    std::unique_ptr<inner_type<T>>
  >::type
{
  return std::unique_ptr<inner_type<T>>(new inner_type<T>(std::forward<V>(v)));
}
// Enabled if T is a specialization of `std::shared_ptr<>`.
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    std::is_same<T, std::shared_ptr<inner_type<T>>>::value,
    std::shared_ptr<inner_type<T>>
  >::type
{ return std::make_shared<inner_type<T>>(std::forward<V>(v)); }

} // namespace pqxx::internal

// TODO: Move?
namespace pqxx
{
/// Meta `pqxx::string_traits` for std::optional-like types.
template<typename T> struct string_traits<
  T,
  typename std::enable_if<internal::is_optional<T>::value>::type
>
{
  static constexpr bool has_null() noexcept { return true; }
  static bool is_null(const T& v)
    { return (not v || string_traits<I>::is_null(*v)); }
  static constexpr T null() { return internal::null_value<T>(); }
  static void from_string(std::string_view str, T &obj)
  {
    if (str.data() == nullptr) obj = null();
    else
    {
      I inner;
      string_traits<I>::from_string(str, inner);
      // Utilize existing memory if possible (e.g. for pointer types).
      if (obj) *obj = inner;
      // Important to assign to set valid flag for smart optional types.
      else obj = internal::make_optional<T>(inner);
    }
  }
  static std::string to_string(const T& Obj)
  {
    if (is_null(Obj)) internal::throw_null_conversion(type_name<T>);
    return string_traits<I>::to_string(*Obj);
  }

private:
  using I = internal::inner_type<T>;
};
} // namespace pqxx
#endif
<commit_msg>Fix `pqxx::internal::inner_type<>` not drilling down past const/volatile (prevented consts from being passed to `exec_params()` etc.) (#193)<commit_after>/** Type/template metaprogramming utilities for use internally in libpqxx
 *
 * Copyright (c) 2000-2019, Jeroen T. Vermeulen.
 *
 * See COPYING for copyright license.  If you did not receive a file called
 * COPYING with this source code, please notify the distributor of this mistake,
 * or contact the author.
 */
#ifndef PQXX_H_TYPE_UTILS
#define PQXX_H_TYPE_UTILS

#include <memory>
#include <type_traits>

#include <optional>

namespace pqxx::internal
{
/// Replicate std::void_t<> (available in C++17).
template<typename... T> using void_t = void;

/// Extract the content type held by an `optional`-like wrapper type.
/* Replace nested `std::remove_*`s with `std::remove_cvref` in C++20 */
template<typename T> using inner_type = typename std::remove_cv<
  typename std::remove_reference<
    decltype(*std::declval<T>())
  >::type
>::type;

/// Does the given type have an `operator *()`?
template<typename T, typename = void> struct is_derefable : std::false_type {};
template<typename T> struct is_derefable<T, void_t<
  // Disable for arrays so they don't erroneously decay to pointers.
  inner_type<typename std::enable_if<not std::is_array<T>::value, T>::type>
>> : std::true_type {};

/// Should the given type be treated as an optional-value wrapper type?
template<typename T, typename = void> struct is_optional : std::false_type {};
template<typename T> struct is_optional<T, typename std::enable_if<(
  is_derefable<T>::value
  // Check if an `explicit operator bool` exists for this type
  && std::is_constructible<bool, T>::value
)>::type> : std::true_type {};

/// Can `nullopt_t` implicitly convert to type T?
template<
  typename T,
  typename = void
> struct takes_std_nullopt : std::false_type {};

template<typename T> struct takes_std_nullopt<
    T,
    typename std::enable_if<std::is_assignable<T, std::nullopt_t>::value>::type
> : std::true_type {};

/// Is type T a `std::tuple<>`?
template<typename T, typename = void> struct is_tuple : std::false_type {};
template<typename T> struct is_tuple<
  T,
  typename std::enable_if<(std::tuple_size<T>::value >= 0)>::type
> : std::true_type {};

/// Is type T an iterable container?
template<typename T, typename = void> struct is_container : std::false_type {};
template<typename T> struct is_container<
  T,
  void_t<
    decltype(std::begin(std::declval<T>())),
    decltype(std::end(std::declval<T>())),
    // Some people might implement a `std::tuple<>` specialization that is
    // iterable when all the contained types are the same ;)
    typename std::enable_if<not is_tuple<T>::value>::type
  >
> : std::true_type {};

/// Get an appropriate null value for the given type.
/**
 * pointer types                         `nullptr`
 * `std::optional<>`-like                `std::nullopt`
 * `std::experimental::optional<>`-like  `std::experimental::nullopt`
 * other types                           `pqxx::string_traits<>::null()`
 * Users may add support for their own wrapper types following this pattern.
 */
template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    (
      is_optional<T>::value
      && not takes_std_nullopt<T>::value
      && std::is_assignable<T, std::nullptr_t>::value
    ),
    std::nullptr_t
  >::type
{ return nullptr; }

template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    (not is_optional<T>::value && not takes_std_nullopt<T>::value),
    decltype(pqxx::string_traits<T>::null())
  >::type
{ return pqxx::string_traits<T>::null(); }

template<typename T> constexpr auto null_value()
  -> typename std::enable_if<
    takes_std_nullopt<T>::value,
    std::nullopt_t
  >::type
{ return std::nullopt; }

/// Construct an optional-like type from the stored type.
/**
 * While these may seem redundant, they are necessary to support smart pointers
 * as optional storage types in a generic manner.  It is suggested NOT to
 * provide a version for `inner_type<T>*` as that will almost certainly leak
 * memory.
 * Users may add support for their own wrapper types following this pattern.
 */
// Enabled if the wrapper type can be directly constructed from the wrapped type
// (e.g. `std::optional<>`); explicitly disabled for raw pointers in case the
// inner type is convertible to a pointer (e.g. `int`)
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    not std::is_same<T, inner_type<T>*>::value,
    decltype(T(std::forward<V>(v)))
  >::type
{ return T(std::forward<V>(v)); }
// Enabled if T is a specialization of `std::unique_ptr<>`.
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    std::is_same<T, std::unique_ptr<inner_type<T>>>::value,
    std::unique_ptr<inner_type<T>>
  >::type
{
  return std::unique_ptr<inner_type<T>>(new inner_type<T>(std::forward<V>(v)));
}
// Enabled if T is a specialization of `std::shared_ptr<>`.
template<typename T, typename V> constexpr auto make_optional(V&& v)
  -> typename std::enable_if<
    std::is_same<T, std::shared_ptr<inner_type<T>>>::value,
    std::shared_ptr<inner_type<T>>
  >::type
{ return std::make_shared<inner_type<T>>(std::forward<V>(v)); }

} // namespace pqxx::internal

// TODO: Move?
namespace pqxx
{
/// Meta `pqxx::string_traits` for std::optional-like types.
template<typename T> struct string_traits<
  T,
  typename std::enable_if<internal::is_optional<T>::value>::type
>
{
  static constexpr bool has_null() noexcept { return true; }
  static bool is_null(const T& v)
    { return (not v || string_traits<I>::is_null(*v)); }
  static constexpr T null() { return internal::null_value<T>(); }
  static void from_string(std::string_view str, T &obj)
  {
    if (str.data() == nullptr) obj = null();
    else
    {
      I inner;
      string_traits<I>::from_string(str, inner);
      // Utilize existing memory if possible (e.g. for pointer types).
      if (obj) *obj = inner;
      // Important to assign to set valid flag for smart optional types.
      else obj = internal::make_optional<T>(inner);
    }
  }
  static std::string to_string(const T& Obj)
  {
    if (is_null(Obj)) internal::throw_null_conversion(type_name<T>);
    return string_traits<I>::to_string(*Obj);
  }

private:
  using I = internal::inner_type<T>;
};
} // namespace pqxx
#endif
<|endoftext|>


<commit_before>///
/// @file  malloc_vector
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MALLOC_VECTOR_HPP
#define MALLOC_VECTOR_HPP

#include <stdlib.h>
#include <algorithm>
#include <cstddef>
#include <new>

namespace primesieve {

/// malloc_vector is a dynamically growing array.
/// It has the same API (though not complete) as std::vector but it
/// uses malloc as its allocator.
///
template <typename T>
class malloc_vector
{
public:
  malloc_vector()
    : array_(0),
      size_(0),
      capacity_(0),
      is_free_(true)
  {
    resize(16);
  }

  malloc_vector(std::size_t n)
    : array_(0),
      size_(0),
      capacity_(0),
      is_free_(true)
  {
    resize(n);
  }

  ~malloc_vector()
  {
    if (is_free_)
      free((void*) array_);
  }

  void push_back(const T& val)
  {
    array_[size_++] = val;
    if (size_ >= capacity_)
      resize(size_ * 2);
  }

  void reserve(std::size_t n)
  {
    if (n > capacity_)
      resize(n);
  }

  void resize(std::size_t n)
  {
    capacity_ = std::max(n, (std::size_t) 16);
    size_ = std::min(size_, capacity_);
    array_ = (T*) realloc((void*) array_, capacity_ * sizeof(T));

    if (!array_)
    {
      size_ = 0;
      capacity_ = 0;
      throw std::bad_alloc();
    }
  }

  T& operator[] (T n)
  {
    return array_[n];
  }

  T* data()
  {
    return array_;
  }

  std::size_t size() const
  {
    return size_;
  }

  void disable_free()
  {
    is_free_ = false;
  }

public:
  typedef T value_type;

private:
  T* array_;
  std::size_t size_;
  std::size_t capacity_;
  bool is_free_;
};

} // namespace primesieve

#endif
<commit_msg>Make exception safe<commit_after>///
/// @file  malloc_vector
///
/// Copyright (C) 2015 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef MALLOC_VECTOR_HPP
#define MALLOC_VECTOR_HPP

#include <stdlib.h>
#include <algorithm>
#include <cstddef>
#include <new>

namespace primesieve {

/// malloc_vector is a dynamically growing array.
/// It has the same API (though not complete) as std::vector but it
/// uses malloc as its allocator.
///
template <typename T>
class malloc_vector
{
public:
  malloc_vector()
    : array_(0),
      size_(0),
      capacity_(0),
      is_free_(true)
  {
    resize(16);
  }

  malloc_vector(std::size_t n)
    : array_(0),
      size_(0),
      capacity_(0),
      is_free_(true)
  {
    resize(n);
  }

  ~malloc_vector()
  {
    if (is_free_)
      free((void*) array_);
  }

  void push_back(const T& val)
  {
    array_[size_++] = val;
    if (size_ >= capacity_)
      resize(size_ * 2);
  }

  void reserve(std::size_t n)
  {
    if (n > capacity_)
      resize(n);
  }

  void resize(std::size_t n)
  {
    n = std::max(n, (std::size_t) 16);
    T* new_array = (T*) realloc((void*) array_, n * sizeof(T));

    if (!new_array)
      throw std::bad_alloc();

    array_ = new_array;
    capacity_ = n;
    size_ = std::min(size_, capacity_);
  }

  T& operator[] (T n)
  {
    return array_[n];
  }

  T* data()
  {
    return array_;
  }

  std::size_t size() const
  {
    return size_;
  }

  void disable_free()
  {
    is_free_ = false;
  }

public:
  typedef T value_type;

private:
  T* array_;
  std::size_t size_;
  std::size_t capacity_;
  bool is_free_;
};

} // namespace primesieve

#endif
<|endoftext|>


<commit_before>#ifndef SIMDIFY_NAMED_ARRAY
#define SIMDIFY_NAMED_ARRAY

#include "expr.hpp"
#include "../util/inline.hpp"
#include <tuple>
#include <array>
#include <type_traits>

///////////////////////////////////////////////////////////////////////////////////////////////////
#define SIMDIFY_IDENTIFIER_PACK_DECLARATION(IDENTIFIER)                                           \
                                                                                \
template <typename T, id... Ids>                                                                  \
struct id_pack<T, id_sequence<id::IDENTIFIER, Ids...>> : id_pack<T, id_sequence<Ids...>> {        \
    using base_t = id_pack<T, id_sequence<Ids...>>;                                               \
                                                                                \
    SIMDIFY_FORCE_INLINE constexpr id_pack() = default;                                           \
    SIMDIFY_FORCE_INLINE constexpr id_pack(const id_pack&) = default;                             \
    SIMDIFY_FORCE_INLINE constexpr id_pack(id_pack&&) = default;                                  \
    SIMDIFY_FORCE_INLINE id_pack& operator=(const id_pack&) = default;                            \
    SIMDIFY_FORCE_INLINE id_pack& operator=(id_pack&&) = default;                                 \
                                                                                \
    template <typename... Args>                                                                   \
    SIMDIFY_FORCE_INLINE constexpr id_pack(const std::tuple<Args...>& t) :                        \
        base_t(t),                                                                                \
        IDENTIFIER(std::get<sizeof...(Ids)>(t)) {}                                                \
                                                                                \
    template <typename... Args>                                                                   \
    SIMDIFY_FORCE_INLINE id_pack& operator=(const std::tuple<Args...>& t) {                       \
        base_t::operator=(t);                                                                     \
        IDENTIFIER = std::get<sizeof...(Ids)>(t);                                                 \
        return *this;                                                                             \
    }                                                                                \
                                                                                \
    T IDENTIFIER;                                                                                \
};                                                                                \
                                                                                \
///////////////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////////////////////////
#define SIMDIFY_ADD_IDENTIFIER(ID)                                                                \
                                                                                \
namespace simd {                                                                                \
    namespace name {                                                                              \
        struct ID {                                                                               \
            enum : std::size_t { size = 1 };                                                      \
            using reverse = ID;                                                                   \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace sub {                                                                               \
        template <typename... T>                                                                  \
        struct ID;                                                                                \
    }                                                                                \
                                                                                \
    namespace detail {                                                                            \
        template <typename... T1, typename... T2>                                                 \
        struct join<sub::ID<T1...>, sub::ID<T2...>> {                                             \
            using type = sub::ID<T1..., T2...>;                                                   \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace sub {                                                                               \
        template <>                                                                               \
        struct ID<> {                                                                             \
            enum : std::size_t { size = 0 };                                                      \
            using reverse = ID<>;                                                                 \
        };                                                                                \
                                                                                \
        template <typename T1, typename... T>                                                     \
        struct ID<T1, T...> {                                                                     \
            enum : std::size_t { size = T1::size + ID<T...>::size };                              \
            using reverse = detail::join_t<typename ID<T...>::reverse, ID<typename T1::reverse>>; \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace detail {                                                                            \
        template <typename T, typename... Names>                                                  \
        struct pack<T, group<name::ID, Names...>> : pack<T, group<Names...>> {                    \
            using base_t = pack<T, group<Names...>>;                                              \
                                                                                \
            SIMDIFY_FORCE_INLINE constexpr pack() = default;                                      \
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;                           \
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;                                \
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;                          \
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;                               \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>& t) :                   \
                base_t(t),                                                                        \
                ID(std::get<sizeof...(Names)>(t)) {}                                              \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>& t) {                  \
                base_t::operator=(t);                                                             \
                ID = std::get<sizeof...(Names)>(t);                                               \
                return *this;                                                                     \
            }                                                                                \
                                                                                \
            T ID;                                                                                \
        };                                                                                \
                                                                                \
        template <typename T, typename... MyNames, typename... Names>                             \
        struct pack<T, group<sub::ID<MyNames...>, Names...>> : pack<T, group<Names...>> {         \
            using base_t = pack<T, group<Names...>>;                                              \
                                                                                \
            SIMDIFY_FORCE_INLINE constexpr pack() = default;                                      \
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;                           \
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;                                \
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;                          \
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;                               \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>& t) :                   \
                base_t(t),                                                                        \
                ID(std::get<sizeof...(Names)>(t)) {}                                              \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>& t) {                  \
                base_t::operator=(t);                                                             \
                ID = std::get<sizeof...(Names)>(t);                                               \
                return *this;                                                                     \
            }                                                                                \
                                                                                \
            pack<T, group<MyNames...>> ID;                                                        \
        };                                                                                \
    }                                                                                \
}                                                                                \
                                                                                \
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace simd {

    namespace detail {
        template <typename T1, typename T2>
        struct join;

        template <typename T1, typename T2>
        using join_t = typename join<T1, T2>::type;

        template <typename... T>
        struct group;

        template <typename... T1, typename... T2>
        struct join<group<T1...>, group<T2...>> {
            using type = group<T1..., T2...>;
        };

        template <>
        struct group<> {
            enum : std::size_t { size = 0 };
            using reverse = group<>;
        };

        template <typename T1, typename... T>
        struct group<T1, T...> {
            enum : std::size_t { size = T1::size + group<T...>::size };
            using reverse = detail::join_t<typename group<T...>::reverse, group<typename T1::reverse>>;
        };

        template <typename... T>
        using reverse_group = typename group<T...>::reverse;

        template <typename T, typename Group>
        struct pack;

        template <typename T>
        struct pack<T, group<>> {
            SIMDIFY_FORCE_INLINE constexpr pack() = default;
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;

            template <typename... Args>
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>&) {}

            template <typename... Args>
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>&) { return *this; }
        };
    }

    enum class id {
        a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z
    };

    template <id... Ids>
    struct id_sequence {};
}

SIMDIFY_ADD_IDENTIFIER(a);
SIMDIFY_ADD_IDENTIFIER(b);
SIMDIFY_ADD_IDENTIFIER(c);
SIMDIFY_ADD_IDENTIFIER(d);
SIMDIFY_ADD_IDENTIFIER(e);
SIMDIFY_ADD_IDENTIFIER(f);
SIMDIFY_ADD_IDENTIFIER(g);
SIMDIFY_ADD_IDENTIFIER(h);
SIMDIFY_ADD_IDENTIFIER(i);
SIMDIFY_ADD_IDENTIFIER(j);
SIMDIFY_ADD_IDENTIFIER(k);
SIMDIFY_ADD_IDENTIFIER(l);
SIMDIFY_ADD_IDENTIFIER(m);
SIMDIFY_ADD_IDENTIFIER(n);
SIMDIFY_ADD_IDENTIFIER(o);
SIMDIFY_ADD_IDENTIFIER(p);
SIMDIFY_ADD_IDENTIFIER(q);
SIMDIFY_ADD_IDENTIFIER(r);
SIMDIFY_ADD_IDENTIFIER(s);
SIMDIFY_ADD_IDENTIFIER(t);
SIMDIFY_ADD_IDENTIFIER(u);
SIMDIFY_ADD_IDENTIFIER(v);
SIMDIFY_ADD_IDENTIFIER(w);
SIMDIFY_ADD_IDENTIFIER(x);
SIMDIFY_ADD_IDENTIFIER(y);
SIMDIFY_ADD_IDENTIFIER(z);

namespace simd {
    namespace detail {
        template <typename... Args>
        SIMDIFY_FORCE_INLINE constexpr int no_op(Args&&...) { return 0; }

        template <typename T, typename IdSequence>
        struct id_pack;

        template <typename T>
        struct id_pack<T, id_sequence<>> {
            SIMDIFY_FORCE_INLINE constexpr id_pack() = default;
            SIMDIFY_FORCE_INLINE constexpr id_pack(const id_pack&) = default;
            SIMDIFY_FORCE_INLINE constexpr id_pack(id_pack&&) = default;
            SIMDIFY_FORCE_INLINE id_pack& operator=(const id_pack&) = default;
            SIMDIFY_FORCE_INLINE id_pack& operator=(id_pack&&) = default;

            template <typename... Args>
            SIMDIFY_FORCE_INLINE constexpr id_pack(const std::tuple<Args...>&) {}

            template <typename... Args>
            SIMDIFY_FORCE_INLINE id_pack& operator=(const std::tuple<Args...>&) { return *this; }
        };

        SIMDIFY_IDENTIFIER_PACK_DECLARATION(a);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(b);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(c);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(d);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(e);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(f);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(g);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(h);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(i);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(j);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(k);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(l);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(m);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(n);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(o);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(p);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(q);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(r);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(s);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(t);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(u);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(v);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(w);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(x);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(y);
        SIMDIFY_IDENTIFIER_PACK_DECLARATION(z);

        template <typename In, typename Out>
        struct reverse_impl;

        template <id... Out>
        struct reverse_impl<id_sequence<>, id_sequence<Out...>> {
            using type = id_sequence<Out...>;
        };

        template <id First, id... In, id... Out>
        struct reverse_impl<id_sequence<First, In...>, id_sequence<Out...>> :
            reverse_impl<id_sequence<In...>, id_sequence<First, Out...>> {};

        template <id... Ids>
        struct reverse : reverse_impl<id_sequence<Ids...>, id_sequence<>> {};

        template <id... Ids>
        using reverse_t = typename reverse<Ids...>::type;
    }

    template <typename T, typename... Names>
    struct named_array : detail::pack<T, detail::reverse_group<Names...>> {
        using group_t = detail::reverse_group<Names...>;
        using base_t = detail::pack<T, group_t>;
        enum : std::size_t { N = group_t::size };

        constexpr named_array() = default;
        constexpr named_array(const named_array&) = default;
        constexpr named_array(named_array&&) = default;
        named_array& operator=(const named_array&) = default;
        named_array& operator=(named_array&&) = default;

        template <typename... Args>
        SIMDIFY_FORCE_INLINE constexpr named_array(const std::tuple<Args...>& t) : base_t(t) {
            static_assert(sizeof...(Args) == sizeof...(Names), "named_array: incorrect number of parameters");
        }

        template <typename... Args>
        SIMDIFY_FORCE_INLINE named_array& operator=(const std::tuple<Args...>& t) {
            static_assert(sizeof...(Args) == sizeof...(Names), "named_array operator=: incorrect number of parameters");
            base_t::operator=(t);
            return *this;
        }

        T& operator[](std::size_t i) {
            auto& as_array = reinterpret_cast<std::array<T, N>&>(*this);
            return as_array[i];
        }

        const T& operator[](std::size_t i) const {
            auto& as_array = reinterpret_cast<const std::array<const T, N>&>(*this);
            return as_array[i];
        }

        template <std::size_t I = 0>
        T& get() {
            auto& as_array = reinterpret_cast<std::array<T, N>&>(*this);
            return std::get<I>(as_array);
        }

        template <std::size_t I = 0>
        const T& get() const {
            auto& as_array = reinterpret_cast<const std::array<const T, N>&>(*this);
            return std::get<I>(as_array);
        }
    };

    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr T& get(simd::named_array<T, Names...>& a) {
        return a.template get<I>();
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr T&& get(simd::named_array<T, Names...>&& a) {
        return std::move(a.template get<I>());
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr const T& get(const simd::named_array<T, Names...>& a) {
        return a.template get<I>();
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr const T&& get(const simd::named_array<T, Names...>&& a) {
        return std::move(a.template get<I>());
    }
}

#undef SIMDIFY_IDENTIFIER_PACK_DECLARATION

#endif // SIMDIFY_NAMED_ARRAY
<commit_msg>Removed id<commit_after>#ifndef SIMDIFY_NAMED_ARRAY
#define SIMDIFY_NAMED_ARRAY

#include "expr.hpp"
#include "../util/inline.hpp"
#include <tuple>
#include <array>
#include <type_traits>

///////////////////////////////////////////////////////////////////////////////////////////////////
#define SIMDIFY_ADD_IDENTIFIER(ID)                                                                \
                                                                                \
namespace simd {                                                                                \
    namespace name {                                                                              \
        struct ID {                                                                               \
            enum : std::size_t { size = 1 };                                                      \
            using reverse = ID;                                                                   \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace sub {                                                                               \
        template <typename... T>                                                                  \
        struct ID;                                                                                \
    }                                                                                \
                                                                                \
    namespace detail {                                                                            \
        template <typename... T1, typename... T2>                                                 \
        struct join<sub::ID<T1...>, sub::ID<T2...>> {                                             \
            using type = sub::ID<T1..., T2...>;                                                   \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace sub {                                                                               \
        template <>                                                                               \
        struct ID<> {                                                                             \
            enum : std::size_t { size = 0 };                                                      \
            using reverse = ID<>;                                                                 \
        };                                                                                \
                                                                                \
        template <typename T1, typename... T>                                                     \
        struct ID<T1, T...> {                                                                     \
            enum : std::size_t { size = T1::size + ID<T...>::size };                              \
            using reverse = detail::join_t<typename ID<T...>::reverse, ID<typename T1::reverse>>; \
        };                                                                                \
    }                                                                                \
                                                                                \
    namespace detail {                                                                            \
        template <typename T, typename... Names>                                                  \
        struct pack<T, group<name::ID, Names...>> : pack<T, group<Names...>> {                    \
            using base_t = pack<T, group<Names...>>;                                              \
                                                                                \
            SIMDIFY_FORCE_INLINE constexpr pack() = default;                                      \
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;                           \
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;                                \
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;                          \
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;                               \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>& t) :                   \
                base_t(t),                                                                        \
                ID(std::get<sizeof...(Names)>(t)) {}                                              \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>& t) {                  \
                base_t::operator=(t);                                                             \
                ID = std::get<sizeof...(Names)>(t);                                               \
                return *this;                                                                     \
            }                                                                                \
                                                                                \
            T ID;                                                                                \
        };                                                                                \
                                                                                \
        template <typename T, typename... MyNames, typename... Names>                             \
        struct pack<T, group<sub::ID<MyNames...>, Names...>> : pack<T, group<Names...>> {         \
            using base_t = pack<T, group<Names...>>;                                              \
                                                                                \
            SIMDIFY_FORCE_INLINE constexpr pack() = default;                                      \
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;                           \
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;                                \
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;                          \
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;                               \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>& t) :                   \
                base_t(t),                                                                        \
                ID(std::get<sizeof...(Names)>(t)) {}                                              \
                                                                                \
            template <typename... Args>                                                           \
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>& t) {                  \
                base_t::operator=(t);                                                             \
                ID = std::get<sizeof...(Names)>(t);                                               \
                return *this;                                                                     \
            }                                                                                \
                                                                                \
            pack<T, group<MyNames...>> ID;                                                        \
        };                                                                                \
    }                                                                                \
}                                                                                \
                                                                                \
///////////////////////////////////////////////////////////////////////////////////////////////////

namespace simd {

    namespace detail {
        template <typename T1, typename T2>
        struct join;

        template <typename T1, typename T2>
        using join_t = typename join<T1, T2>::type;

        template <typename... T>
        struct group;

        template <typename... T1, typename... T2>
        struct join<group<T1...>, group<T2...>> {
            using type = group<T1..., T2...>;
        };

        template <>
        struct group<> {
            enum : std::size_t { size = 0 };
            using reverse = group<>;
        };

        template <typename T1, typename... T>
        struct group<T1, T...> {
            enum : std::size_t { size = T1::size + group<T...>::size };
            using reverse = detail::join_t<typename group<T...>::reverse, group<typename T1::reverse>>;
        };

        template <typename... T>
        using reverse_group = typename group<T...>::reverse;

        template <typename T, typename Group>
        struct pack;

        template <typename T>
        struct pack<T, group<>> {
            SIMDIFY_FORCE_INLINE constexpr pack() = default;
            SIMDIFY_FORCE_INLINE constexpr pack(const pack&) = default;
            SIMDIFY_FORCE_INLINE constexpr pack(pack&&) = default;
            SIMDIFY_FORCE_INLINE pack& operator=(const pack&) = default;
            SIMDIFY_FORCE_INLINE pack& operator=(pack&&) = default;

            template <typename... Args>
            SIMDIFY_FORCE_INLINE constexpr pack(const std::tuple<Args...>&) {}

            template <typename... Args>
            SIMDIFY_FORCE_INLINE pack& operator=(const std::tuple<Args...>&) { return *this; }
        };
    }
}

SIMDIFY_ADD_IDENTIFIER(a);
SIMDIFY_ADD_IDENTIFIER(b);
SIMDIFY_ADD_IDENTIFIER(c);
SIMDIFY_ADD_IDENTIFIER(d);
SIMDIFY_ADD_IDENTIFIER(e);
SIMDIFY_ADD_IDENTIFIER(f);
SIMDIFY_ADD_IDENTIFIER(g);
SIMDIFY_ADD_IDENTIFIER(h);
SIMDIFY_ADD_IDENTIFIER(i);
SIMDIFY_ADD_IDENTIFIER(j);
SIMDIFY_ADD_IDENTIFIER(k);
SIMDIFY_ADD_IDENTIFIER(l);
SIMDIFY_ADD_IDENTIFIER(m);
SIMDIFY_ADD_IDENTIFIER(n);
SIMDIFY_ADD_IDENTIFIER(o);
SIMDIFY_ADD_IDENTIFIER(p);
SIMDIFY_ADD_IDENTIFIER(q);
SIMDIFY_ADD_IDENTIFIER(r);
SIMDIFY_ADD_IDENTIFIER(s);
SIMDIFY_ADD_IDENTIFIER(t);
SIMDIFY_ADD_IDENTIFIER(u);
SIMDIFY_ADD_IDENTIFIER(v);
SIMDIFY_ADD_IDENTIFIER(w);
SIMDIFY_ADD_IDENTIFIER(x);
SIMDIFY_ADD_IDENTIFIER(y);
SIMDIFY_ADD_IDENTIFIER(z);

namespace simd {
    namespace detail {
        template <typename... Args>
        SIMDIFY_FORCE_INLINE constexpr int no_op(Args&&...) { return 0; }
    }

    template <typename T, typename... Names>
    struct named_array : detail::pack<T, detail::reverse_group<Names...>> {
        using group_t = detail::reverse_group<Names...>;
        using base_t = detail::pack<T, group_t>;
        enum : std::size_t { N = group_t::size };

        constexpr named_array() = default;
        constexpr named_array(const named_array&) = default;
        constexpr named_array(named_array&&) = default;
        named_array& operator=(const named_array&) = default;
        named_array& operator=(named_array&&) = default;

        template <typename... Args>
        SIMDIFY_FORCE_INLINE constexpr named_array(const std::tuple<Args...>& t) : base_t(t) {
            static_assert(sizeof...(Args) == sizeof...(Names), "named_array: incorrect number of parameters");
        }

        template <typename... Args>
        SIMDIFY_FORCE_INLINE named_array& operator=(const std::tuple<Args...>& t) {
            static_assert(sizeof...(Args) == sizeof...(Names), "named_array operator=: incorrect number of parameters");
            base_t::operator=(t);
            return *this;
        }

        T& operator[](std::size_t i) {
            auto& as_array = reinterpret_cast<std::array<T, N>&>(*this);
            return as_array[i];
        }

        const T& operator[](std::size_t i) const {
            auto& as_array = reinterpret_cast<const std::array<const T, N>&>(*this);
            return as_array[i];
        }

        template <std::size_t I = 0>
        T& get() {
            auto& as_array = reinterpret_cast<std::array<T, N>&>(*this);
            return std::get<I>(as_array);
        }

        template <std::size_t I = 0>
        const T& get() const {
            auto& as_array = reinterpret_cast<const std::array<const T, N>&>(*this);
            return std::get<I>(as_array);
        }
    };

    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr T& get(simd::named_array<T, Names...>& a) {
        return a.template get<I>();
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr T&& get(simd::named_array<T, Names...>&& a) {
        return std::move(a.template get<I>());
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr const T& get(const simd::named_array<T, Names...>& a) {
        return a.template get<I>();
    }
    template <size_t I, typename T, typename... Names>
    SIMDIFY_FORCE_INLINE constexpr const T&& get(const simd::named_array<T, Names...>&& a) {
        return std::move(a.template get<I>());
    }
}

#endif // SIMDIFY_NAMED_ARRAY
<|endoftext|>


<commit_before>#ifndef MIMOSA_STREAM_STREAM_HH
# define MIMOSA_STREAM_STREAM_HH

# include "../ref-countable.hh"
# include "../non-copyable.hh"
# include "../runtime/time.hh"

namespace mimosa
{
  namespace stream
  {
    class Stream : public RefCountable<Stream>,
                   private NonCopyable
    {
    public:
      inline virtual ~Stream() {}

      virtual int64_t write(const char * data, uint64_t nbytes, runtime::Time timeout = 0) = 0;
      virtual int64_t writev(const struct iovec *iov, int iovcnt, runtime::Time timeout = 0);
      virtual int64_t read(char * data, uint64_t nbytes, runtime::Time timeout = 0) = 0;

      /** flushes the write buffer */
      virtual bool flush(runtime::Time timeout) {}
    };
  }
}

#endif /* !MIMOSA_STREAM_STREAM_HH */
<commit_msg>Added missing header to stream.hh<commit_after>#ifndef MIMOSA_STREAM_STREAM_HH
# define MIMOSA_STREAM_STREAM_HH

# include <sys/uio.h>

# include "../ref-countable.hh"
# include "../non-copyable.hh"
# include "../runtime/time.hh"

namespace mimosa
{
  namespace stream
  {
    class Stream : public RefCountable<Stream>,
                   private NonCopyable
    {
    public:
      inline virtual ~Stream() {}

      virtual int64_t write(const char * data, uint64_t nbytes, runtime::Time timeout = 0) = 0;
      virtual int64_t writev(const struct iovec *iov, int iovcnt, runtime::Time timeout = 0);
      virtual int64_t read(char * data, uint64_t nbytes, runtime::Time timeout = 0) = 0;

      /** flushes the write buffer */
      virtual bool flush(runtime::Time timeout) {}
    };
  }
}

#endif /* !MIMOSA_STREAM_STREAM_HH */
<|endoftext|>


<commit_before>#include <iostream>

using namespace std;

int main() {
    cout << "Hello, World!" << endl;
    return 0;
}<commit_msg>added yyparse in main<commit_after>#include <stdio.h>
#include <grammar/helen.parser.hpp>

int main(int argc, char** argv) {
    yyin = (argc == 1) ? stdin : fopen(argv[1], "r");
    yyparse();
    return 0;
}<|endoftext|>


<commit_before>
#include <stdio.h>
#include <iostream>
#include <memory>

/// Spherical harmonics coefficients extractor for a HDR cubemap.

/// The main function

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

	std::cout << "Processing... " << std::flush;

	std::cout << "Done. " << std::endl;

	return 0;
}

<commit_msg>Tool to extract spherical harmonics coefficients from a HDR cubemap.<commit_after>#include "../Config.hpp"
#include "../helpers/GLUtilities.hpp"

#include <stdio.h>
#include <iostream>
#include <memory>
#include <string>
#include <map>
#include <vector>
#include <fstream>

/// Spherical harmonics coefficients extractor for a HDR cubemap.

/// The main function

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

	// Arguments parsing.
	std::map<std::string, std::string> arguments;
	Config::parseFromArgs(argc, argv, arguments);
	if(arguments.count("map") == 0){
		std::cerr << "Specify path to envmap." << std::endl;
		return 1;
	}
	const std::string rootPath = arguments["map"];

	// Paths for each side.
	const std::vector<std::string> paths { rootPath + "_px.exr", rootPath + "_nx.exr", rootPath + "_py.exr", rootPath + "_ny.exr", rootPath + "_pz.exr", rootPath + "_nz.exr" };

	/// Load cubemap sides.
	std::cout << "[SHExtractor] Loading envmap at path " << rootPath << " ..." << std::endl;

	float* sides[6];
	int width = 0;
	int height = 0;
	for(size_t side = 0; side < 6; ++side){
		const char *err;
		int ret = GLUtilities::loadEXRHelper(&(sides[side]), &width, &height, paths[side].c_str(), &err);
		if (ret != 0) {
			std::cerr << "[Resources] Unable to load the texture at path " << paths[side] << "." << std::endl;
			return 1;
		}

	}

	/// Indices conversions from cubemap UVs to direction.
	const std::vector<int> axisIndices = { 0, 0, 1, 1, 2, 2 };
	const std::vector<float> axisMul = { 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, -1.0f};

	const std::vector<int> horizIndices = { 2, 2, 0, 0, 0, 0};
	const std::vector<float> horizMul = { -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f};

	const std::vector<int> vertIndices = { 1, 1, 2, 2, 1, 1};
	const std::vector<float> vertMul = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f};

	/// Spherical harmonics coefficients.
	std::cout << "[SHExtractor] Computing SH coefficients." << std::endl;
	glm::vec3 LCoeffs[9];
	for(int i = 0; i < 9; ++i){
		LCoeffs[i] = glm::vec3(0.0f,0.0f,0.0f);
	}

	const float y0 = 0.282095f;
	const float y1 = 0.488603f;
	const float y2 = 1.092548f;
	const float y3 = 0.315392f;
	const float y4 = 0.546274f;

	float denom = 0.0f;
	for(int i = 0; i < 6; ++i){
		for(int y = 0; y < height; ++y){
			for(int x = 0; x < width; ++x){

				const float v = -1.0f + 1.0f/float(width) + float(y) * 2.0f/float(width);
				const float u = -1.0f + 1.0f/float(width) + float(x) * 2.0f/float(width);

				glm::vec3 pos = glm::vec3(0.0f,0.0f,0.0f);
				pos[axisIndices[i]] = axisMul[i];
				pos[horizIndices[i]] = horizMul[i] * u;
				pos[vertIndices[i]] = vertMul[i] * v;
				pos = glm::normalize(pos);

				// Normalization factor.
				const float fTmp = 1.0f + u*u + v*v;
				const float weight = 4.0f/(sqrt(fTmp)*fTmp);
				denom += weight;

				// HDR color.
				const glm::vec3 hdr = weight * glm::vec3(sides[i][(y*width+x)*3+0],
														 sides[i][(y*width+x)*3+1],
														 sides[i][(y*width+x)*3+2]);

				 // Y0,0  = 0.282095
				 LCoeffs[0] += hdr * y0;
				 // Y1,-1 = 0.488603 y
				 LCoeffs[1] += hdr * (y1 * pos[1]);
				 // Y1,0  = 0.488603 z
				 LCoeffs[2] += hdr * (y1 * pos[2]);
				 // Y1,1  = 0.488603 x
				 LCoeffs[3] += hdr * (y1 * pos[0]);
				 // Y2,-2 = 1.092548 xy
				 LCoeffs[4] += hdr * (y2 * (pos[0] * pos[1]));
				 // Y2,-1 = 1.092548 yz
				 LCoeffs[5] += hdr * (y2 * pos[1] * pos[2]);
				 // Y2,0  = 0.315392 (3z^2 - 1)
				 LCoeffs[6] += hdr * (y3 * (3.0f * pos[2] * pos[2] - 1.0f));
				 // Y2,1  = 1.092548 xz
				 LCoeffs[7] += hdr * (y2 * pos[0] * pos[2]);
				 // Y2,2  = 0.546274 (x^2 - y^2)
				 LCoeffs[8] += hdr * (y4 * (pos[0] * pos[0] - pos[1] * pos[1]));

			}
		}
	}

	// Normalization.
	for(int i = 0; i < 9; ++i){
		LCoeffs[i] *= 4.0/denom;
	}

	/// Final coefficients.
	std::cout << "[SHExtractor] Computing final coefficients." << std::endl;

	// To go from radiance to irradiance, we need to apply a cosine lobe convolution on the sphere in spatial domain.
	// This can be expressed as a product in frequency (on the SH basis) domain, with constant pre-computed coefficients.
	// See:	Ramamoorthi, Ravi, and Pat Hanrahan. "An efficient representation for irradiance environment maps."
	//		Proceedings of the 28th annual conference on Computer graphics and interactive techniques. ACM, 2001.

	const float c1 = 0.429043f;
	const float c2 = 0.511664f;
	const float c3 = 0.743125f;
	const float c4 = 0.886227f;
	const float c5 = 0.247708f;

	glm::vec3 SCoeffs[9];
	SCoeffs[0] = c4 * LCoeffs[0] - c5 * LCoeffs[6];
	SCoeffs[1] = 2.0f * c2 * LCoeffs[1];
	SCoeffs[2] = 2.0f * c2 * LCoeffs[2];
	SCoeffs[3] = 2.0f * c2 * LCoeffs[3];
	SCoeffs[4] = 2.0f * c1 * LCoeffs[4];
	SCoeffs[5] = 2.0f * c1 * LCoeffs[5];
	SCoeffs[6] = c3 * LCoeffs[6];
	SCoeffs[7] = 2.0f * c1 * LCoeffs[7];
	SCoeffs[8] = c1 * LCoeffs[8];

	std::cout << "[SHExtractor] Done. " << std::endl;

	// Output.
	const std::string destinationPath = rootPath + "_shcoeffs.txt";
	std::ofstream outputFile(destinationPath);
	if(!outputFile.is_open()){
		std::cerr << "[SHExtractor] Unable to open output file at path " << destinationPath << "." << std::endl;
		return 2;
	}

	for(int i = 0; i < 9; ++i){
		outputFile << SCoeffs[i][0] << " " << SCoeffs[i][1] << " " << SCoeffs[i][2] << std::endl;
 	}
	outputFile.close();
	return 0;
}

<|endoftext|>