<commit_before>#ifndef OSRM_PARTITION_MULTI_LEVEL_GRAPH_HPP
#define OSRM_PARTITION_MULTI_LEVEL_GRAPH_HPP

#include "partition/multi_level_partition.hpp"

#include "util/static_graph.hpp"

#include <tbb/parallel_sort.h>

#include <boost/iterator/permutation_iterator.hpp>
#include <boost/range/combine.hpp>

namespace osrm
{
namespace partition
{
template <typename EdgeDataT, bool UseSharedMemory> class MultiLevelGraph;

namespace io
{
template <typename EdgeDataT, bool UseSharedMemory>
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);

template <typename EdgeDataT, bool UseSharedMemory>
void write(const boost::filesystem::path &path,
           const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
}

template <typename EdgeDataT, bool UseSharedMemory>
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
{
  private:
    using SuperT = util::StaticGraph<EdgeDataT, UseSharedMemory>;
    template <typename T> using Vector = typename util::ShM<T, UseSharedMemory>::vector;

  public:
    // We limit each node to have 255 edges
    // this is very generous, we could probably pack this
    using EdgeOffset = std::uint8_t;

    MultiLevelGraph() = default;

    MultiLevelGraph(Vector<typename SuperT::NodeArrayEntry> node_array_,
                    Vector<typename SuperT::EdgeArrayEntry> edge_array_,
                    Vector<EdgeOffset> node_to_edge_offset_)
        : SuperT(std::move(node_array_), std::move(edge_array_)),
          node_to_edge_offset(std::move(node_to_edge_offset_))
    {
    }

    template <typename ContainerT>
    MultiLevelGraph(const MultiLevelPartition &mlp,
                    const std::uint32_t num_nodes,
                    const ContainerT &edges)
    {
        auto highest_border_level = GetHighestBorderLevel(mlp, edges);
        auto permutation = SortEdgesByHighestLevel(highest_border_level, edges);
        auto sorted_edges_begin =
            boost::make_permutation_iterator(edges.begin(), permutation.begin());
        auto sorted_edges_end = boost::make_permutation_iterator(edges.begin(), permutation.end());
        SuperT::InitializeFromSortedEdgeRange(num_nodes, sorted_edges_begin, sorted_edges_end);

        // if the node ordering is sorting the border nodes first,
        // the id of the maximum border node will be rather low
        // enabling us to save some memory here
        auto max_border_node_id = 0u;
        for (auto edge_index : util::irange<std::size_t>(0, edges.size()))
        {
            if (highest_border_level[edge_index] > 0)
            {
                max_border_node_id =
                    std::max(max_border_node_id,
                             std::max(edges[edge_index].source, edges[edge_index].target));
            }
        }
        BOOST_ASSERT(max_border_node_id < num_nodes);

        auto edge_and_level_range = boost::combine(edges, highest_border_level);
        auto sorted_edge_and_level_begin =
            boost::make_permutation_iterator(edge_and_level_range.begin(), permutation.begin());
        auto sorted_edge_and_level_end =
            boost::make_permutation_iterator(edge_and_level_range.begin(), permutation.end());
        InitializeOffsetsFromSortedEdges(
            mlp, max_border_node_id, sorted_edge_and_level_begin, sorted_edge_and_level_end);
    }

    // Fast scan over all relevant border edges
    // For level 0 this yield the same result as GetAdjacentEdgeRange
    auto GetBorderEdgeRange(const LevelID level, const NodeID node) const
    {
        auto begin = BeginBorderEdges(level, node);
        auto end = SuperT::EndEdges(node);
        return util::irange<EdgeID>(begin, end);
    }

    // Fast scan over all relevant internal edges, that is edges that will not
    // leave the cell of that node at the given level
    // For level 0 this returns an empty edge range
    auto GetInternalEdgeRange(const LevelID level, const NodeID node) const
    {
        auto begin = SuperT::BeginEdges(node);
        auto end = BeginBorderEdges(level, node);
        return util::irange<EdgeID>(begin, end);
    }

    EdgeID BeginBorderEdges(const LevelID level, const NodeID node) const
    {
        auto index = node * GetNumberOfLevels();
        // `node_to_edge_offset` has size `max_border_node_id + 1`
        // which can be smaller then the total number of nodes.
        // this will save memory in case we sort the border nodes first
        if (index >= node_to_edge_offset.size() - 1)
            return SuperT::BeginEdges(node);
        else
            return SuperT::BeginEdges(node) + node_to_edge_offset[index + level];
    }

    // We save the level as sentinel at the end
    LevelID GetNumberOfLevels() const { return node_to_edge_offset.back(); }

  private:
    template <typename ContainerT>
    auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
    {
        std::vector<LevelID> highest_border_level(edges.size());
        std::transform(
            edges.begin(), edges.end(), highest_border_level.begin(), [&mlp](const auto &edge) {
                return mlp.GetHighestDifferentLevel(edge.source, edge.target);
            });
        return highest_border_level;
    }

    template <typename ContainerT>
    auto SortEdgesByHighestLevel(const std::vector<LevelID> &highest_border_level,
                                 const ContainerT &edges) const
    {
        std::vector<std::uint32_t> permutation(edges.size());
        std::iota(permutation.begin(), permutation.end(), 0);
        tbb::parallel_sort(
            permutation.begin(),
            permutation.end(),
            [&edges, &highest_border_level](const auto &lhs, const auto &rhs) {
                // sort by source node and then by level in ascending order
                return std::tie(edges[lhs].source, highest_border_level[lhs], edges[lhs].target) <
                       std::tie(edges[rhs].source, highest_border_level[rhs], edges[rhs].target);
            });

        return permutation;
    }

    template <typename ZipIterT>
    auto InitializeOffsetsFromSortedEdges(const MultiLevelPartition &mlp,
                                          const NodeID max_border_node_id,
                                          ZipIterT edge_and_level_begin,
                                          ZipIterT edge_and_level_end)
    {

        auto num_levels = mlp.GetNumberOfLevels();
        // we save one sentinel element at the end
        node_to_edge_offset.reserve(num_levels * (max_border_node_id + 1) + 1);
        auto iter = edge_and_level_begin;
        for (auto node : util::irange<NodeID>(0, max_border_node_id + 1))
        {
            node_to_edge_offset.push_back(0);
            auto level_begin = iter;
            for (auto level : util::irange<LevelID>(0, mlp.GetNumberOfLevels()))
            {
                iter = std::find_if(
                    iter, edge_and_level_end, [node, level](const auto &edge_and_level) {
                        return boost::get<0>(edge_and_level).source != node ||
                               boost::get<1>(edge_and_level) != level;
                    });
                EdgeOffset offset = std::distance(level_begin, iter);
                node_to_edge_offset.push_back(offset);
            }
            node_to_edge_offset.pop_back();
        }
        BOOST_ASSERT(node_to_edge_offset.size() ==
                     mlp.GetNumberOfLevels() * (max_border_node_id + 1));
        // save number of levels as last element so we can reconstruct the stride
        node_to_edge_offset.push_back(mlp.GetNumberOfLevels());
    }

    friend void
    io::read<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
                                         MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
    friend void
    io::write<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
                                          const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);

    Vector<EdgeOffset> node_to_edge_offset;
};
}
}

#endif
<commit_msg>Fix internal edges for nodes not in the boundary<commit_after>#ifndef OSRM_PARTITION_MULTI_LEVEL_GRAPH_HPP
#define OSRM_PARTITION_MULTI_LEVEL_GRAPH_HPP

#include "partition/multi_level_partition.hpp"

#include "util/static_graph.hpp"

#include <tbb/parallel_sort.h>

#include <boost/iterator/permutation_iterator.hpp>
#include <boost/range/combine.hpp>

namespace osrm
{
namespace partition
{
template <typename EdgeDataT, bool UseSharedMemory> class MultiLevelGraph;

namespace io
{
template <typename EdgeDataT, bool UseSharedMemory>
void read(const boost::filesystem::path &path, MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);

template <typename EdgeDataT, bool UseSharedMemory>
void write(const boost::filesystem::path &path,
           const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
}

template <typename EdgeDataT, bool UseSharedMemory>
class MultiLevelGraph : public util::StaticGraph<EdgeDataT, UseSharedMemory>
{
  private:
    using SuperT = util::StaticGraph<EdgeDataT, UseSharedMemory>;
    template <typename T> using Vector = typename util::ShM<T, UseSharedMemory>::vector;

  public:
    // We limit each node to have 255 edges
    // this is very generous, we could probably pack this
    using EdgeOffset = std::uint8_t;

    MultiLevelGraph() = default;

    MultiLevelGraph(Vector<typename SuperT::NodeArrayEntry> node_array_,
                    Vector<typename SuperT::EdgeArrayEntry> edge_array_,
                    Vector<EdgeOffset> node_to_edge_offset_)
        : SuperT(std::move(node_array_), std::move(edge_array_)),
          node_to_edge_offset(std::move(node_to_edge_offset_))
    {
    }

    template <typename ContainerT>
    MultiLevelGraph(const MultiLevelPartition &mlp,
                    const std::uint32_t num_nodes,
                    const ContainerT &edges)
    {
        auto highest_border_level = GetHighestBorderLevel(mlp, edges);
        auto permutation = SortEdgesByHighestLevel(highest_border_level, edges);
        auto sorted_edges_begin =
            boost::make_permutation_iterator(edges.begin(), permutation.begin());
        auto sorted_edges_end = boost::make_permutation_iterator(edges.begin(), permutation.end());
        SuperT::InitializeFromSortedEdgeRange(num_nodes, sorted_edges_begin, sorted_edges_end);

        // if the node ordering is sorting the border nodes first,
        // the id of the maximum border node will be rather low
        // enabling us to save some memory here
        auto max_border_node_id = 0u;
        for (auto edge_index : util::irange<std::size_t>(0, edges.size()))
        {
            if (highest_border_level[edge_index] > 0)
            {
                max_border_node_id =
                    std::max(max_border_node_id,
                             std::max(edges[edge_index].source, edges[edge_index].target));
            }
        }
        BOOST_ASSERT(max_border_node_id < num_nodes);

        auto edge_and_level_range = boost::combine(edges, highest_border_level);
        auto sorted_edge_and_level_begin =
            boost::make_permutation_iterator(edge_and_level_range.begin(), permutation.begin());
        auto sorted_edge_and_level_end =
            boost::make_permutation_iterator(edge_and_level_range.begin(), permutation.end());
        InitializeOffsetsFromSortedEdges(
            mlp, max_border_node_id, sorted_edge_and_level_begin, sorted_edge_and_level_end);
    }

    // Fast scan over all relevant border edges
    // For level 0 this yield the same result as GetAdjacentEdgeRange
    auto GetBorderEdgeRange(const LevelID level, const NodeID node) const
    {
        auto begin = BeginBorderEdges(level, node);
        auto end = SuperT::EndEdges(node);
        return util::irange<EdgeID>(begin, end);
    }

    // Fast scan over all relevant internal edges, that is edges that will not
    // leave the cell of that node at the given level
    // For level 0 this returns an empty edge range
    auto GetInternalEdgeRange(const LevelID level, const NodeID node) const
    {
        auto begin = SuperT::BeginEdges(node);
        auto end = BeginBorderEdges(level, node);
        return util::irange<EdgeID>(begin, end);
    }

    EdgeID BeginBorderEdges(const LevelID level, const NodeID node) const
    {
        auto index = node * GetNumberOfLevels();
        // `node_to_edge_offset` has size `max_border_node_id + 1`
        // which can be smaller then the total number of nodes.
        // this will save memory in case we sort the border nodes first
        if (index >= node_to_edge_offset.size() - 1)
        {
            // On level 0 all edges are border edges
            if (level == 0)
                return SuperT::BeginEdges(node);
            else
                return SuperT::EndEdges(node);
        }
        else
        {
            return SuperT::BeginEdges(node) + node_to_edge_offset[index + level];
        }
    }

    // We save the level as sentinel at the end
    LevelID GetNumberOfLevels() const { return node_to_edge_offset.back(); }

  private:
    template <typename ContainerT>
    auto GetHighestBorderLevel(const MultiLevelPartition &mlp, const ContainerT &edges) const
    {
        std::vector<LevelID> highest_border_level(edges.size());
        std::transform(
            edges.begin(), edges.end(), highest_border_level.begin(), [&mlp](const auto &edge) {
                return mlp.GetHighestDifferentLevel(edge.source, edge.target);
            });
        return highest_border_level;
    }

    template <typename ContainerT>
    auto SortEdgesByHighestLevel(const std::vector<LevelID> &highest_border_level,
                                 const ContainerT &edges) const
    {
        std::vector<std::uint32_t> permutation(edges.size());
        std::iota(permutation.begin(), permutation.end(), 0);
        tbb::parallel_sort(
            permutation.begin(),
            permutation.end(),
            [&edges, &highest_border_level](const auto &lhs, const auto &rhs) {
                // sort by source node and then by level in ascending order
                return std::tie(edges[lhs].source, highest_border_level[lhs], edges[lhs].target) <
                       std::tie(edges[rhs].source, highest_border_level[rhs], edges[rhs].target);
            });

        return permutation;
    }

    template <typename ZipIterT>
    auto InitializeOffsetsFromSortedEdges(const MultiLevelPartition &mlp,
                                          const NodeID max_border_node_id,
                                          ZipIterT edge_and_level_begin,
                                          ZipIterT edge_and_level_end)
    {

        auto num_levels = mlp.GetNumberOfLevels();
        // we save one sentinel element at the end
        node_to_edge_offset.reserve(num_levels * (max_border_node_id + 1) + 1);
        auto iter = edge_and_level_begin;
        for (auto node : util::irange<NodeID>(0, max_border_node_id + 1))
        {
            node_to_edge_offset.push_back(0);
            auto level_begin = iter;
            for (auto level : util::irange<LevelID>(0, mlp.GetNumberOfLevels()))
            {
                iter = std::find_if(
                    iter, edge_and_level_end, [node, level](const auto &edge_and_level) {
                        return boost::get<0>(edge_and_level).source != node ||
                               boost::get<1>(edge_and_level) != level;
                    });
                EdgeOffset offset = std::distance(level_begin, iter);
                node_to_edge_offset.push_back(offset);
            }
            node_to_edge_offset.pop_back();
        }
        BOOST_ASSERT(node_to_edge_offset.size() ==
                     mlp.GetNumberOfLevels() * (max_border_node_id + 1));
        // save number of levels as last element so we can reconstruct the stride
        node_to_edge_offset.push_back(mlp.GetNumberOfLevels());
    }

    friend void
    io::read<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
                                         MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);
    friend void
    io::write<EdgeDataT, UseSharedMemory>(const boost::filesystem::path &path,
                                          const MultiLevelGraph<EdgeDataT, UseSharedMemory> &graph);

    Vector<EdgeOffset> node_to_edge_offset;
};
}
}

#endif
<|endoftext|>


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

#ifndef RJ_CORE_GAME_HANDLER_HPP
#define RJ_CORE_GAME_HANDLER_HPP

#include "game.hpp"
#include "game_window.hpp"
#include "render.hpp"
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/editor/editor.hpp>
#include <rectojump/game/game_menu/game_menu.hpp>
#include <rectojump/game/main_menu/main_menu.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/data_store.hpp>
#include <rectojump/shared/error_handler.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/tools/bitset.h>

namespace rj
{
	class game_handler
	{
	public:
		// type decls
		using data_store_type = data_store<sf::Texture, sf::Font, sf::Font>;

	private:
		game_window& m_game_window;
		error_handler& m_errorhandler;
		data_manager& m_datamgr;
		level_manager& m_lvmgr;

		data_store_type m_datastore{m_datamgr.get_all_containing_as_map_as<sf::Texture>(".png"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".otf"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".ttf")};
		camera m_default_camera;
		render<game_handler> m_render;
		background_manager m_backgroundmgr;
		game<game_handler> m_game;
		editor<game_handler, decltype(m_game)> m_editor;
		main_menu<game_handler> m_mainmenu;
		game_menu<game_handler> m_gamemenu;
		popup_manager<game_handler> m_popupmgr;
		debug_info<game_handler, decltype(m_game)> m_debug_info;

		mlk::ebitset<state, state::num> m_current_states;

	public:
		game_handler(game_window& gw, error_handler& eh, data_manager& dm, level_manager& lm) :
			m_game_window{gw},
			m_errorhandler{eh},
			m_datamgr{dm},
			m_lvmgr{lm},
			m_default_camera{gw, {settings::get_window_size<vec2f>() / 2.f, settings::get_window_size<vec2f>()}},
			m_render{*this},
			m_backgroundmgr{m_render},
			m_game{*this},
			m_editor{*this},
			m_mainmenu{*this},
			m_gamemenu{*this},
			m_popupmgr{*this},
			m_debug_info{*this}
		{this->init();}

		void load_level(const level_id& id)
		{
			auto& lv(m_lvmgr.get_level(id));
			if(!lv.is_valid())
			{
				m_popupmgr.create_popup<popup_type::error>("Failed to load level: not a valid level");
				return;
			}

			// (de)activate right states
			this->deactivate_state(state::main_menu);
			this->activate_state(state::game);

			// load background
			m_backgroundmgr.clear();
			auto& lv_bg(lv.background);
			auto& bgshape(m_backgroundmgr.bg_shape());
			bgshape.set_startcolor(lv_bg.get_startcolor());
			bgshape.set_endcolor(lv_bg.get_endcolor());
			bgshape.set_gradient_points(lv_bg.get_pointcount());

			// load level to gameworld
			m_game.load_level(lv);
		}

		template<typename... Args>
		void render_object(Args&&... args)
		{m_game_window.draw(std::forward<Args>(args)...);}

		template<state active_state, typename On_Input, typename... Input_Type_Args>
		void add_input(On_Input&& func, Input_Type_Args&&... keys_btns)
		{
			static_assert(sizeof...(keys_btns) > 0, "at least one key/button/wheel argument needed");
			add_input_helper<(sizeof...(keys_btns) > 1), typename std::tuple_element<0, std::tuple<Input_Type_Args...>>::type, active_state, On_Input, Input_Type_Args...>
			{*this, std::forward<On_Input>(func), std::forward<Input_Type_Args>(keys_btns)...};
		}

		// getters
		auto& rendermgr() noexcept
		{return m_render;}

		auto& gamewindow() noexcept
		{return m_game_window;}

		auto& game() noexcept
		{return m_game;}

		auto& backgroundmgr() noexcept
		{return m_backgroundmgr;}

		auto& mainmenu() noexcept
		{return m_mainmenu;}

		auto& gamemenu() noexcept
		{return m_gamemenu;}

		auto& datastore() noexcept
		{return m_datastore;}

		auto& datamgr() noexcept
		{return m_datamgr;}

		auto& levelmgr() noexcept
		{return m_lvmgr;}

		auto& debuginfo() noexcept
		{return m_debug_info;}

		auto& popupmgr() noexcept
		{return m_popupmgr;}

	private:
		void init()
		{
			m_current_states |= state::main_menu;

			m_game_window.get_updater().on_update += [this](dur duration){this->update(duration);};
			m_game_window.get_updater().on_render += [this]{this->render();};

			settings::on_changed() +=
			[this]{m_game_window.set_size(settings::get_window_size());};

			m_mainmenu.mmenu_start()->get_items().on_event("editor",
			[this]
			{
				this->deactivate_state(state::main_menu);
				this->activate_state(state::editor);
				m_editor.on_activate();
			});

			this->init_errors();
			this->init_pointers();
			this->init_input();
		}

		void init_errors() noexcept
		{
			auto& font(m_datastore.get<sf::Font>("Ubuntu-R.ttf"));

			// add the error instances
			m_errorhandler.create_error_instance(errors::cl_nullptr_access,
			"Something went wrong during program execution.\nPlease consider to make a bugreport at:\nhttps://github.com/Malekblubb/rectojump\n(Please attach 'log.log' and 'error.log'.)",
			font,
			[this]{this->set_only_state(state::error);});

			// TODO: add homepage here
			m_errorhandler.create_error_instance(errors::cl_data, "Some data wasn't loaded, can't run the game.\nPlease download a full release at: ",
			font,
			[this]{this->set_only_state(state::error);});

			// checking font
			if(!m_datamgr.exists_id("Fipps-Regular.otf"))
				mlk::exit_with("main font ('Fipps-Regular.otf') not loaded", EXIT_FAILURE, mlk::lerr(errors::cl_data)["rj::game_handler"]);

			// checking data
			if(!m_datamgr.exists_ids({"debug_font.png", "Fipps-Regular.otf", "Ubuntu-R.ttf", "arrow.png",
									  "editor_item_rect.png", "editor_item_triangle.png", "editor_item_triangles4.png",
									  "menu_side.png"}))
				mlk::lerr(errors::cl_data);
		}

		void init_pointers() noexcept
		{
			m_game.set_levelmgr(&m_lvmgr);
		}

		void init_input()
		{
			// input update
			inp::on_input_update() +=
			[this]{this->update_input();};

			// global input
			inp::on_keys_pressed(key::LShift, key::F) +=
			[this]
			{
				m_game_window.toggle_fullscreen();
				rj::settings::set_fullscreen(m_game_window.get_fullscreen());
			};

			inp::on_keys_pressed(key::LShift, key::T) +=
			[this]{m_game_window.toggle_titlebar();};

			inp::on_keys_pressed(key::LShift, key::D) +=
			[this]{this->toggle_state(state::debug_info);};

			inp::on_keys_pressed(key::LShift, key::Q) +=
			[this]{m_game_window.stop();};

			// game input
			// pause / game_menu
			auto pause_fnc(
			[this]
			{
				if(!this->is_active(state::main_menu))
					m_current_states.toggle(state::game_menu);
			});

			inp::on_key_pressed(key::Escape) += pause_fnc;
			inp::on_key_pressed(key::P) += pause_fnc;

			inp::on_key_pressed(key::D) +=
			[this]{if(!this->is_active(state::game)) return; m_game.world().c_player();};
		}

		void activate_state(state s)
		{m_current_states |= s;}

		void deactivate_state(state s)
		{m_current_states.remove(s);}

		void toggle_state(state s)
		{m_current_states.toggle(s);}

		bool is_active(state s) const
		{return m_current_states & s;}

		void set_only_state(state s)
		{
			m_current_states.remove_all();
			m_current_states |= s;
		}

		void update(dur duration)
		{
			if(this->is_active(state::error))
				return;

			m_backgroundmgr.update(duration);

			if(this->is_active(state::game) && !this->is_active(state::game_menu))
				m_game.update(duration);

			else if(this->is_active(state::editor) && !this->is_active(state::game_menu))
			{
				m_editor.update(duration);
				m_game.world().entityhandler().update(duration);
			}

			else if(this->is_active(state::main_menu))
				m_mainmenu.update(duration);

			else if(this->is_active(state::game_menu))
				m_gamemenu.update(duration);

			if(this->is_active(state::debug_info))
				m_debug_info.update(duration);

			m_popupmgr.update(duration);
		}

		void update_input()
		{
			m_editor.update_input();
		}

		void render()
		{
			if(this->is_active(state::error))
			{
				m_render(m_errorhandler.get_current_error_instance().error_text);
				return;
			}

			m_default_camera.activate();
			m_backgroundmgr.render();

			m_default_camera.activate();
			// render game when in game menu
			if(this->is_active(state::game))
				m_game.render();

			else if(this->is_active(state::editor))
				m_editor.render();

			else if(this->is_active(state::main_menu))
				m_mainmenu.render();

			if(this->is_active(state::game_menu))
			{
				m_default_camera.activate();
				m_gamemenu.render();
			}

			m_default_camera.activate();
			if(this->is_active(state::debug_info))
				m_debug_info.render();

			m_popupmgr.render();
		}

		// multi_args: true, Input_Type = key
		template<bool multi_args, typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... keys)
			{
				inp::on_keys_pressed(std::forward<Input_Type_Args>(keys)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = key
		template<typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, Input_Type, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... k)
			{
				inp::on_key_pressed(std::forward<Input_Type_Args>(k)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = btn
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, btn, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... b)
			{
				inp::on_btn_pressed(std::forward<Input_Type_Args>(b)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};

		// multi_args: false, Input_Type = wheel
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, wheel, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... w)
			{
				inp::on_mousewheel(std::forward<Input_Type_Args>(w)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};
	};
}

#endif // RJ_CORE_GAME_HANDLER_HPP
<commit_msg>game_handler: added button 'LControl' for global events; preventing textinput shift events<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_CORE_GAME_HANDLER_HPP
#define RJ_CORE_GAME_HANDLER_HPP

#include "game.hpp"
#include "game_window.hpp"
#include "render.hpp"
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/camera.hpp>
#include <rectojump/game/editor/editor.hpp>
#include <rectojump/game/game_menu/game_menu.hpp>
#include <rectojump/game/main_menu/main_menu.hpp>
#include <rectojump/game/popup_manager.hpp>
#include <rectojump/global/common.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/level_manager/level_manager.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/data_store.hpp>
#include <rectojump/shared/error_handler.hpp>

#include <mlk/containers/container_utl.h>
#include <mlk/tools/bitset.h>

namespace rj
{
	class game_handler
	{
	public:
		// type decls
		using data_store_type = data_store<sf::Texture, sf::Font, sf::Font>;

	private:
		game_window& m_game_window;
		error_handler& m_errorhandler;
		data_manager& m_datamgr;
		level_manager& m_lvmgr;

		data_store_type m_datastore{m_datamgr.get_all_containing_as_map_as<sf::Texture>(".png"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".otf"), m_datamgr.get_all_containing_as_map_as<sf::Font>(".ttf")};
		camera m_default_camera;
		render<game_handler> m_render;
		background_manager m_backgroundmgr;
		game<game_handler> m_game;
		editor<game_handler, decltype(m_game)> m_editor;
		main_menu<game_handler> m_mainmenu;
		game_menu<game_handler> m_gamemenu;
		popup_manager<game_handler> m_popupmgr;
		debug_info<game_handler, decltype(m_game)> m_debug_info;

		mlk::ebitset<state, state::num> m_current_states;

	public:
		game_handler(game_window& gw, error_handler& eh, data_manager& dm, level_manager& lm) :
			m_game_window{gw},
			m_errorhandler{eh},
			m_datamgr{dm},
			m_lvmgr{lm},
			m_default_camera{gw, {settings::get_window_size<vec2f>() / 2.f, settings::get_window_size<vec2f>()}},
			m_render{*this},
			m_backgroundmgr{m_render},
			m_game{*this},
			m_editor{*this},
			m_mainmenu{*this},
			m_gamemenu{*this},
			m_popupmgr{*this},
			m_debug_info{*this}
		{this->init();}

		void load_level(const level_id& id)
		{
			auto& lv(m_lvmgr.get_level(id));
			if(!lv.is_valid())
			{
				m_popupmgr.create_popup<popup_type::error>("Failed to load level: not a valid level");
				return;
			}

			// (de)activate right states
			this->deactivate_state(state::main_menu);
			this->activate_state(state::game);

			// load background
			m_backgroundmgr.clear();
			auto& lv_bg(lv.background);
			auto& bgshape(m_backgroundmgr.bg_shape());
			bgshape.set_startcolor(lv_bg.get_startcolor());
			bgshape.set_endcolor(lv_bg.get_endcolor());
			bgshape.set_gradient_points(lv_bg.get_pointcount());

			// load level to gameworld
			m_game.load_level(lv);
		}

		template<typename... Args>
		void render_object(Args&&... args)
		{m_game_window.draw(std::forward<Args>(args)...);}

		template<state active_state, typename On_Input, typename... Input_Type_Args>
		void add_input(On_Input&& func, Input_Type_Args&&... keys_btns)
		{
			static_assert(sizeof...(keys_btns) > 0, "at least one key/button/wheel argument needed");
			add_input_helper<(sizeof...(keys_btns) > 1), typename std::tuple_element<0, std::tuple<Input_Type_Args...>>::type, active_state, On_Input, Input_Type_Args...>
			{*this, std::forward<On_Input>(func), std::forward<Input_Type_Args>(keys_btns)...};
		}

		// getters
		auto& rendermgr() noexcept
		{return m_render;}

		auto& gamewindow() noexcept
		{return m_game_window;}

		auto& game() noexcept
		{return m_game;}

		auto& backgroundmgr() noexcept
		{return m_backgroundmgr;}

		auto& mainmenu() noexcept
		{return m_mainmenu;}

		auto& gamemenu() noexcept
		{return m_gamemenu;}

		auto& datastore() noexcept
		{return m_datastore;}

		auto& datamgr() noexcept
		{return m_datamgr;}

		auto& levelmgr() noexcept
		{return m_lvmgr;}

		auto& debuginfo() noexcept
		{return m_debug_info;}

		auto& popupmgr() noexcept
		{return m_popupmgr;}

	private:
		void init()
		{
			m_current_states |= state::main_menu;

			m_game_window.get_updater().on_update += [this](dur duration){this->update(duration);};
			m_game_window.get_updater().on_render += [this]{this->render();};

			settings::on_changed() +=
			[this]{m_game_window.set_size(settings::get_window_size());};

			m_mainmenu.mmenu_start()->get_items().on_event("editor",
			[this]
			{
				this->deactivate_state(state::main_menu);
				this->activate_state(state::editor);
				m_editor.on_activate();
			});

			this->init_errors();
			this->init_pointers();
			this->init_input();
		}

		void init_errors() noexcept
		{
			auto& font(m_datastore.get<sf::Font>("Ubuntu-R.ttf"));

			// add the error instances
			m_errorhandler.create_error_instance(errors::cl_nullptr_access,
			"Something went wrong during program execution.\nPlease consider to make a bugreport at:\nhttps://github.com/Malekblubb/rectojump\n(Please attach 'log.log' and 'error.log'.)",
			font,
			[this]{this->set_only_state(state::error);});

			// TODO: add homepage here
			m_errorhandler.create_error_instance(errors::cl_data, "Some data wasn't loaded, can't run the game.\nPlease download a full release at: ",
			font,
			[this]{this->set_only_state(state::error);});

			// checking font
			if(!m_datamgr.exists_id("Fipps-Regular.otf"))
				mlk::exit_with("main font ('Fipps-Regular.otf') not loaded", EXIT_FAILURE, mlk::lerr(errors::cl_data)["rj::game_handler"]);

			// checking data
			if(!m_datamgr.exists_ids({"debug_font.png", "Fipps-Regular.otf", "Ubuntu-R.ttf", "arrow.png",
									  "editor_item_rect.png", "editor_item_triangle.png", "editor_item_triangles4.png",
									  "menu_side.png"}))
				mlk::lerr(errors::cl_data);
		}

		void init_pointers() noexcept
		{
			m_game.set_levelmgr(&m_lvmgr);
		}

		void init_input()
		{
			// input update
			inp::on_input_update() +=
			[this]{this->update_input();};

			// global input
			inp::on_keys_pressed(key::LShift, key::LControl, key::F) +=
			[this]
			{
				m_game_window.toggle_fullscreen();
				rj::settings::set_fullscreen(m_game_window.get_fullscreen());
			};

			inp::on_keys_pressed(key::LShift, key::LControl, key::T) +=
			[this]{m_game_window.toggle_titlebar();};

			inp::on_keys_pressed(key::LShift, key::LControl, key::D) +=
			[this]{this->toggle_state(state::debug_info);};

			inp::on_keys_pressed(key::LShift, key::LControl, key::Q) +=
			[this]{m_game_window.stop();};

			// game input
			// pause / game_menu
			auto pause_fnc(
			[this]
			{
				if(!this->is_active(state::main_menu))
					m_current_states.toggle(state::game_menu);
			});

			inp::on_key_pressed(key::Escape) += pause_fnc;
			inp::on_key_pressed(key::P) += pause_fnc;

			inp::on_key_pressed(key::D) +=
			[this]{if(!this->is_active(state::game)) return; m_game.world().c_player();};
		}

		void activate_state(state s)
		{m_current_states |= s;}

		void deactivate_state(state s)
		{m_current_states.remove(s);}

		void toggle_state(state s)
		{m_current_states.toggle(s);}

		bool is_active(state s) const
		{return m_current_states & s;}

		void set_only_state(state s)
		{
			m_current_states.remove_all();
			m_current_states |= s;
		}

		void update(dur duration)
		{
			if(this->is_active(state::error))
				return;

			m_backgroundmgr.update(duration);

			if(this->is_active(state::game) && !this->is_active(state::game_menu))
				m_game.update(duration);

			else if(this->is_active(state::editor) && !this->is_active(state::game_menu))
			{
				m_editor.update(duration);
				m_game.world().entityhandler().update(duration);
			}

			else if(this->is_active(state::main_menu))
				m_mainmenu.update(duration);

			else if(this->is_active(state::game_menu))
				m_gamemenu.update(duration);

			if(this->is_active(state::debug_info))
				m_debug_info.update(duration);

			m_popupmgr.update(duration);
		}

		void update_input()
		{
			m_editor.update_input();
		}

		void render()
		{
			if(this->is_active(state::error))
			{
				m_render(m_errorhandler.get_current_error_instance().error_text);
				return;
			}

			m_default_camera.activate();
			m_backgroundmgr.render();

			m_default_camera.activate();
			// render game when in game menu
			if(this->is_active(state::game))
				m_game.render();

			else if(this->is_active(state::editor))
				m_editor.render();

			else if(this->is_active(state::main_menu))
				m_mainmenu.render();

			if(this->is_active(state::game_menu))
			{
				m_default_camera.activate();
				m_gamemenu.render();
			}

			m_default_camera.activate();
			if(this->is_active(state::debug_info))
				m_debug_info.render();

			m_popupmgr.render();
		}

		// multi_args: true, Input_Type = key
		template<bool multi_args, typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... keys)
			{
				inp::on_keys_pressed(std::forward<Input_Type_Args>(keys)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = key
		template<typename Input_Type, state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, Input_Type, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... k)
			{
				inp::on_key_pressed(std::forward<Input_Type_Args>(k)...) +=
				[&gh, func]{if(gh.is_active(s)) func();};
			}
		};

		// multi_args: false, Input_Type = btn
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, btn, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... b)
			{
				inp::on_btn_pressed(std::forward<Input_Type_Args>(b)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};

		// multi_args: false, Input_Type = wheel
		template<state s, typename On_Input, typename... Input_Type_Args>
		struct add_input_helper<false, wheel, s, On_Input, Input_Type_Args...>
		{
			add_input_helper(const game_handler& gh, On_Input&& func, Input_Type_Args&&... w)
			{
				inp::on_mousewheel(std::forward<Input_Type_Args>(w)...) +=
				[&gh, func](const vec2f& pos){if(gh.is_active(s)) func(pos);};
			}
		};
	};
}

#endif // RJ_CORE_GAME_HANDLER_HPP
<|endoftext|>


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

#ifndef RJ_GAME_EDITOR_MOUSE_HPP
#define RJ_GAME_EDITOR_MOUSE_HPP

#include "editor_entity.hpp"
#include <rectojump/shared/input.hpp>
#include <rectojump/global/config_settings.hpp>

namespace rj
{
	class editor_mouse
	{
		rndr& m_render;

		editor_entity m_mouse_shape{{0.f, 0.f}};
		bool m_active{true};

	public:
		editor_mouse(rndr& r) :
			m_render{r}
		{

		}

		void update(dur duration)
		{
			auto mousepos(get_mousepos());
			vec2f new_pos{round_to(mousepos.x, 48.f), round_to(mousepos.y, 48.f)};
			m_mouse_shape.render_object().setPosition(new_pos);
		}

		void render()
		{
			if(m_active)
				m_render(m_mouse_shape.render_object());
		}

		void clear() noexcept
		{m_mouse_shape.render_object().setTexture(nullptr); m_active = false;}

		void set_texture(const sf::Texture* tx) noexcept
		{m_mouse_shape.render_object().setTexture(tx); m_active = true;}

		const sf::Texture* get_texture() noexcept
		{return m_mouse_shape.render_object().getTexture();}
	};
}

#endif // RJ_GAME_EDITOR_MOUSE_HPP
<commit_msg>editor - mouse: getting mousepos of current view<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_EDITOR_MOUSE_HPP
#define RJ_GAME_EDITOR_MOUSE_HPP

#include "editor_entity.hpp"
#include <rectojump/game/camera.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/input.hpp>

namespace rj
{
	class editor_mouse
	{
		rndr& m_render;

		editor_entity m_mouse_shape{{0.f, 0.f}};
		bool m_active{true};

	public:
		editor_mouse(rndr& r) :
			m_render{r}
		{ }

		void update(dur)
		{
			auto mousepos(get_mousepos_current_view());
			vec2f new_pos{round_to(mousepos.x, 48.f), round_to(mousepos.y, 48.f)};
			m_mouse_shape.render_object().setPosition(new_pos);
		}

		void render()
		{
			if(m_active)
				m_render(m_mouse_shape.render_object());
		}

		void clear() noexcept
		{m_mouse_shape.render_object().setTexture(nullptr); m_active = false;}

		void set_texture(const sf::Texture* tx) noexcept
		{m_mouse_shape.render_object().setTexture(tx); m_active = true;}

		const sf::Texture* get_texture() noexcept
		{return m_mouse_shape.render_object().getTexture();}
	};
}

#endif // RJ_GAME_EDITOR_MOUSE_HPP
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/formats/base64.hpp>

#include <cstdint>
#include <string>
#include <bitcoin/bitcoin/utility/data.hpp>

// This implementation derived from public domain:
// en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64

namespace libbitcoin {

const static char pad = '=';

const static char table[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

std::string encode_base64(data_slice unencoded)
{
    std::string encoded;
    auto size = unencoded.size();
    encoded.reserve(((size / 3) + (size % 3 > 0)) * 4);

    uint32_t value;
    auto cursor = unencoded.begin();
    for (size_t position = 0; position < size / 3; position++)
    {
        // Convert to big endian.
        value = (*cursor++) << 16;

        value += (*cursor++) << 8;
        value += (*cursor++);
        encoded.append(1, table[(value & 0x00FC0000) >> 18]);
        encoded.append(1, table[(value & 0x0003F000) >> 12]);
        encoded.append(1, table[(value & 0x00000FC0) >> 6]);
        encoded.append(1, table[(value & 0x0000003F) >> 0]);
    }

    switch (size % 3)
    {
        case 1:
            // Convert to big endian.
            value = (*cursor++) << 16;

            encoded.append(1, table[(value & 0x00FC0000) >> 18]);
            encoded.append(1, table[(value & 0x0003F000) >> 12]);
            encoded.append(2, pad);
            break;
        case 2:
            // Convert to big endian.
            value = (*cursor++) << 16;

            value += (*cursor++) << 8;
            encoded.append(1, table[(value & 0x00FC0000) >> 18]);
            encoded.append(1, table[(value & 0x0003F000) >> 12]);
            encoded.append(1, table[(value & 0x00000FC0) >> 6]);
            encoded.append(1, pad);
            break;
    }

    return encoded;
}

bool decode_base64(data_chunk& out, const std::string& in)
{
    const static uint32_t mask = 0x000000FF;

    auto length = in.length();
    if ((length % 4) != 0)
        return false;

    size_t padding = 0;
    if (length > 0)
    {
        if (in[length - 1] == pad)
            padding++;
        if (in[length - 2] == pad)
            padding++;
    }

    data_chunk decoded;
    decoded.reserve(((length / 4) * 3) - padding);

    uint32_t value = 0;
    for (auto cursor = in.begin(); cursor < in.end();)
    {
        for (size_t position = 0; position < 4; position++)
        {
            value <<= 6;
            if (*cursor >= 0x41 && *cursor <= 0x5A)
                value |= *cursor - 0x41;
            else if (*cursor >= 0x61 && *cursor <= 0x7A)
                value |= *cursor - 0x47;
            else if (*cursor >= 0x30 && *cursor <= 0x39)
                value |= *cursor + 0x04;
            else if (*cursor == 0x2B)
                value |= 0x3E;
            else if (*cursor == 0x2F)
                value |= 0x3F;
            else if (*cursor == pad)
            {
                // Handle 1 or 2 pad characters.
                switch (in.end() - cursor)
                {
                    case 1:
                        decoded.push_back((value >> 16) & mask);
                        decoded.push_back((value >> 8) & mask);
                        out = decoded;
                        return true;
                    case 2:
                        decoded.push_back((value >> 10) & mask);
                        out = decoded;
                        return true;
                    default:
                        return false;
                }
            }
            else
                return false;

            cursor++;
        }

        decoded.push_back((value >> 16) & mask);
        decoded.push_back((value >> 8) & mask);
        decoded.push_back((value >> 0) & mask);
    }

    out = decoded;
    return true;
}

} // namespace libbitcoin

<commit_msg>Use const.<commit_after>/*
 * Copyright (c) 2011-2014 libbitcoin developers (see AUTHORS)
 *
 * This file is part of libbitcoin.
 *
 * libbitcoin is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License with
 * additional permissions to the one published by the Free Software
 * Foundation, either version 3 of the License, or (at your option)
 * any later version. For more information see LICENSE.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 */
#include <bitcoin/bitcoin/formats/base64.hpp>

#include <cstdint>
#include <string>
#include <bitcoin/bitcoin/utility/data.hpp>

// This implementation derived from public domain:
// en.wikibooks.org/wiki/Algorithm_Implementation/Miscellaneous/Base64

namespace libbitcoin {

const static char pad = '=';

const static char table[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

std::string encode_base64(data_slice unencoded)
{
    std::string encoded;
    const auto size = unencoded.size();
    encoded.reserve(((size / 3) + (size % 3 > 0)) * 4);

    uint32_t value;
    auto cursor = unencoded.begin();
    for (size_t position = 0; position < size / 3; position++)
    {
        // Convert to big endian.
        value = (*cursor++) << 16;

        value += (*cursor++) << 8;
        value += (*cursor++);
        encoded.append(1, table[(value & 0x00FC0000) >> 18]);
        encoded.append(1, table[(value & 0x0003F000) >> 12]);
        encoded.append(1, table[(value & 0x00000FC0) >> 6]);
        encoded.append(1, table[(value & 0x0000003F) >> 0]);
    }

    switch (size % 3)
    {
        case 1:
            // Convert to big endian.
            value = (*cursor++) << 16;

            encoded.append(1, table[(value & 0x00FC0000) >> 18]);
            encoded.append(1, table[(value & 0x0003F000) >> 12]);
            encoded.append(2, pad);
            break;
        case 2:
            // Convert to big endian.
            value = (*cursor++) << 16;

            value += (*cursor++) << 8;
            encoded.append(1, table[(value & 0x00FC0000) >> 18]);
            encoded.append(1, table[(value & 0x0003F000) >> 12]);
            encoded.append(1, table[(value & 0x00000FC0) >> 6]);
            encoded.append(1, pad);
            break;
    }

    return encoded;
}

bool decode_base64(data_chunk& out, const std::string& in)
{
    const static uint32_t mask = 0x000000FF;

    const auto length = in.length();
    if ((length % 4) != 0)
        return false;

    size_t padding = 0;
    if (length > 0)
    {
        if (in[length - 1] == pad)
            padding++;
        if (in[length - 2] == pad)
            padding++;
    }

    data_chunk decoded;
    decoded.reserve(((length / 4) * 3) - padding);

    uint32_t value = 0;
    for (auto cursor = in.begin(); cursor < in.end();)
    {
        for (size_t position = 0; position < 4; position++)
        {
            value <<= 6;
            if (*cursor >= 0x41 && *cursor <= 0x5A)
                value |= *cursor - 0x41;
            else if (*cursor >= 0x61 && *cursor <= 0x7A)
                value |= *cursor - 0x47;
            else if (*cursor >= 0x30 && *cursor <= 0x39)
                value |= *cursor + 0x04;
            else if (*cursor == 0x2B)
                value |= 0x3E;
            else if (*cursor == 0x2F)
                value |= 0x3F;
            else if (*cursor == pad)
            {
                // Handle 1 or 2 pad characters.
                switch (in.end() - cursor)
                {
                    case 1:
                        decoded.push_back((value >> 16) & mask);
                        decoded.push_back((value >> 8) & mask);
                        out = decoded;
                        return true;
                    case 2:
                        decoded.push_back((value >> 10) & mask);
                        out = decoded;
                        return true;
                    default:
                        return false;
                }
            }
            else
                return false;

            cursor++;
        }

        decoded.push_back((value >> 16) & mask);
        decoded.push_back((value >> 8) & mask);
        decoded.push_back((value >> 0) & mask);
    }

    out = decoded;
    return true;
}

} // namespace libbitcoin

<|endoftext|>


<commit_before>//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides a possible implementation of PCH support for Clang that is
// based on caching lexed tokens and identifiers.
//
//===----------------------------------------------------------------------===//

#include "clang.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"

using namespace clang;

typedef llvm::DenseMap<const FileEntry*,uint64_t> PCHMap;
typedef llvm::DenseMap<const IdentifierInfo*,uint64_t> IDMap;

static void Emit32(llvm::raw_ostream& Out, uint32_t V) {
#if 0
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  Out << (unsigned char)(V >> 24);
#else
  Out << V;
#endif
}

static void Emit64(llvm::raw_ostream& Out, uint64_t V) {
  Out << V;
}

static void EmitOffset(llvm::raw_ostream& Out, uint64_t V) {
  assert(((uint32_t) V) == V && "Offset exceeds 32 bits.");
  Emit32(Out, (uint32_t) V);
}

static void Emit8(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
}

static void EmitBuf(llvm::raw_ostream& Out, const char* I, const char* E) {
  for ( ; I != E ; ++I) Out << *I;
}

static uint32_t ResolveID(IDMap& IM, uint32_t& idx, const IdentifierInfo* II) {
  IDMap::iterator I = IM.find(II);

  if (I == IM.end()) {
    IM[II] = idx;
    return idx++;
  }

  return I->second;
}

static void EmitToken(llvm::raw_ostream& Out, const Token& T,
                      uint32_t& idcount, IDMap& IM) {
  Emit8(Out, T.getKind());
  Emit8(Out, T.getFlags());
  Emit32(Out, ResolveID(IM, idcount, T.getIdentifierInfo()));
  Emit32(Out, T.getLocation().getRawEncoding());
  Emit32(Out, T.getLength());
}

static void EmitIdentifier(llvm::raw_ostream& Out, const IdentifierInfo& II) {
  uint32_t X = (uint32_t) II.getTokenID() << 19;
  X |= (uint32_t) II.getBuiltinID() << 9;
  X |= (uint32_t) II.getObjCKeywordID() << 4;
  if (II.hasMacroDefinition()) X |= 0x8;
  if (II.isExtensionToken()) X |= 0x4;
  if (II.isPoisoned()) X |= 0x2;
  if (II.isCPlusPlusOperatorKeyword()) X |= 0x1;

  Emit32(Out, X);
}

struct IDData {
  const IdentifierInfo* II;
  uint32_t FileOffset;
  const IdentifierTable::const_iterator::value_type* Str;
};

static std::pair<uint64_t,uint64_t>
EmitIdentifierTable(llvm::raw_fd_ostream& Out, uint32_t max,
                    const IdentifierTable& T, const IDMap& IM) {

  // Build an inverse map from persistent IDs -> IdentifierInfo*.
  typedef std::vector< IDData > InverseIDMap;
  InverseIDMap IIDMap;
  IIDMap.reserve(max);

  // Generate mapping from persistent IDs -> IdentifierInfo*.
  for (IDMap::const_iterator I=IM.begin(), E=IM.end(); I!=E; ++I)
    IIDMap[I->second].II = I->first;

  // Get the string data associated with the IdentifierInfo.
  for (IdentifierTable::const_iterator I=T.begin(), E=T.end(); I!=E; ++I) {
    IDMap::const_iterator IDI = IM.find(&(I->getValue()));
    if (IDI == IM.end()) continue;
    IIDMap[IDI->second].Str = &(*I);
  }

  uint64_t DataOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I) {
    I->FileOffset = Out.tell();      // Record the location for this data.
    EmitIdentifier(Out, *(I->II));   // Write out the identifier data.
    unsigned len = I->Str->getKeyLength();  // Write out the keyword.
    Emit32(Out, len);
    const char* buf = I->Str->getKeyData();
    EmitBuf(Out, buf, buf+len);
  }

  // Now emit the table mapping from persistent IDs to PTH file offsets.
  uint64_t IDOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I)
    EmitOffset(Out, I->FileOffset);

  return std::make_pair(DataOff, IDOff);
}

static uint64_t EmitFileTable(llvm::raw_fd_ostream& Out, SourceManager& SM,
                              PCHMap& PM) {

  uint64_t off = Out.tell();

  // Output the size of the table.
  Emit32(Out, PM.size());

  for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
    // For now emit inode information.  In the future we should utilize
    // the FileManager's internal mechanism of uniquing files, which differs
    // for Windows and Unix-like systems.
    const FileEntry* FE = I->first;
    Emit64(Out, FE->getDevice());
    Emit64(Out, FE->getInode());
    Emit32(Out, I->second);
  }

  return off;
}

static uint64_t LexTokens(llvm::raw_fd_ostream& Out, Lexer& L, Preprocessor& PP,
                          uint32_t& idcount, IDMap& IM) {

  // Record the location within the token file.
  uint64_t off = Out.tell();

  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
    }
    else if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      EmitToken(Out, Tok, idcount, IM);
      L.LexFromRawLexer(Tok);

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      if (K == tok::pp_include || K == tok::pp_import ||
          K == tok::pp_include_next) {

        // Save the 'include' token.
        EmitToken(Out, Tok, idcount, IM);

        // Lex the next token as an include string.
        L.setParsingPreprocessorDirective(true);
        L.LexIncludeFilename(Tok);
        L.setParsingPreprocessorDirective(false);

        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
      }
    }
  }
  while (EmitToken(Out, Tok, idcount, IM), Tok.isNot(tok::eof));

  return off;
}

void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
  // Lex through the entire file.  This will populate SourceManager with
  // all of the header information.
  Token Tok;
  PP.EnterMainSourceFile();
  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));

  // Iterate over all the files in SourceManager.  Create a lexer
  // for each file and cache the tokens.
  SourceManager& SM = PP.getSourceManager();
  const LangOptions& LOpts = PP.getLangOptions();
  llvm::raw_ostream& os = llvm::errs();

  PCHMap PM;
  IDMap  IM;
  uint32_t idcount = 0;

  std::string ErrMsg;
  llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);

  if (!ErrMsg.empty()) {
    os << "PCH error: " << ErrMsg << "\n";
    return;
  }

  for (SourceManager::fileid_iterator I=SM.fileid_begin(), E=SM.fileid_end();
       I!=E; ++I) {

    const SrcMgr::ContentCache* C = I.getFileIDInfo().getContentCache();
    if (!C) continue;

    const FileEntry* FE = C->Entry;    // Does this entry correspond to a file?
    if (!FE) continue;

    PCHMap::iterator PI = PM.find(FE); // Have we already processed this file?
    if (PI != PM.end()) continue;

    const llvm::MemoryBuffer* B = C->Buffer;
    if (!B) continue;

    Lexer L(SourceLocation::getFileLoc(I.getFileID(), 0), LOpts,
            B->getBufferStart(), B->getBufferEnd(), B);

    PM[FE] = LexTokens(Out, L, PP, idcount, IM);
  }

  // Write out the identifier table.
  std::pair<uint64_t,uint64_t> IdTableOff =
    EmitIdentifierTable(Out, idcount, PP.getIdentifierTable(), IM);

  // Write out the file table.
  uint64_t FileTableOff = EmitFileTable(Out, SM, PM);

  // Finally, write out the offset table at the end.
  EmitOffset(Out, IdTableOff.first);
  EmitOffset(Out, IdTableOff.second);
  EmitOffset(Out, FileTableOff);
}
<commit_msg>PTH emission: - Output 32 bit integers using bit-shifting + write of individual bytes.   This is motivated because we aren't guaranteed to load 32-bit ints of the mmaped PTH file at 4-byte offsets. - Don't emit flags for IdentifierInfos.  These are lazily populated by the Preprocessor/Parser. - Only write out tokens for files with absolute paths.  This is potentially temporary, but simplifies things for now.<commit_after>//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This provides a possible implementation of PCH support for Clang that is
// based on caching lexed tokens and identifiers.
//
//===----------------------------------------------------------------------===//

#include "clang.h"
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Lex/Lexer.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/System/Path.h"

using namespace clang;

typedef uint32_t Offset;

typedef llvm::DenseMap<const FileEntry*,Offset> PCHMap;
typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;

static void Emit32(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
  Out << (unsigned char)(V >>  8);
  Out << (unsigned char)(V >> 16);
  Out << (unsigned char)(V >> 24);
}

static void Emit8(llvm::raw_ostream& Out, uint32_t V) {
  Out << (unsigned char)(V);
}

static void EmitBuf(llvm::raw_ostream& Out, const char* I, const char* E) {
  for ( ; I != E ; ++I) Out << *I;
}

static uint32_t ResolveID(IDMap& IM, uint32_t& idx, const IdentifierInfo* II) {

  // Null IdentifierInfo's map to the persistent ID 0.
  if (!II)
    return 0;

  IDMap::iterator I = IM.find(II);

  if (I == IM.end()) {
    IM[II] = ++idx; // Pre-increment since '0' is reserved for NULL.
    return idx;
  }

  return I->second; // We've already added 1.
}

static void EmitToken(llvm::raw_ostream& Out, const Token& T,
                      const SourceManager& SMgr,
                      uint32_t& idcount, IDMap& IM) {

  Emit8(Out, T.getKind());
  Emit8(Out, T.getFlags());
  Emit32(Out, ResolveID(IM, idcount, T.getIdentifierInfo()));
  Emit32(Out, SMgr.getFullFilePos(T.getLocation()));
  Emit32(Out, T.getLength());
}

struct IDData {
  const IdentifierInfo* II;
  uint32_t FileOffset;
  const IdentifierTable::const_iterator::value_type* Str;
};

static std::pair<Offset,Offset>
EmitIdentifierTable(llvm::raw_fd_ostream& Out, uint32_t max,
                    const IdentifierTable& T, const IDMap& IM) {

  // Build an inverse map from persistent IDs -> IdentifierInfo*.
  typedef std::vector<IDData> InverseIDMap;
  InverseIDMap IIDMap;
  IIDMap.resize(max);

  // Generate mapping from persistent IDs -> IdentifierInfo*.
  for (IDMap::const_iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
    // Decrement by 1 because we are using a vector for the lookup and
    // 0 is reserved for NULL.
    assert(I->second > 0);
    assert(I->second-1 < IIDMap.size());
    IIDMap[I->second-1].II = I->first;
  }

  // Get the string data associated with the IdentifierInfo.
  for (IdentifierTable::const_iterator I=T.begin(), E=T.end(); I!=E; ++I) {
    IDMap::const_iterator IDI = IM.find(&(I->getValue()));
    if (IDI == IM.end()) continue;
    IIDMap[IDI->second-1].Str = &(*I);
  }

  Offset DataOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I) {
    // Record the location for this data.
    I->FileOffset = Out.tell();
    // Write out the keyword.
    unsigned len = I->Str->getKeyLength();
    Emit32(Out, len);
    const char* buf = I->Str->getKeyData();
    EmitBuf(Out, buf, buf+len);
  }

  // Now emit the table mapping from persistent IDs to PTH file offsets.
  Offset IDOff = Out.tell();

  for (InverseIDMap::iterator I=IIDMap.begin(), E=IIDMap.end(); I!=E; ++I)
    Emit32(Out, I->FileOffset);

  return std::make_pair(DataOff, IDOff);
}

Offset EmitFileTable(llvm::raw_fd_ostream& Out, SourceManager& SM, PCHMap& PM) {

  Offset off = (Offset) Out.tell();

  // Output the size of the table.
  Emit32(Out, PM.size());

  for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
    const FileEntry* FE = I->first;
    llvm::sys::Path P(FE->getName());
    assert(P.isAbsolute());
    Emit32(Out, P.size());
    const char* buf = P.c_str();
    EmitBuf(Out, buf, buf+P.size());
    Emit32(Out, I->second);
  }

  return off;
}

static Offset LexTokens(llvm::raw_fd_ostream& Out, Lexer& L, Preprocessor& PP,
                        uint32_t& idcount, IDMap& IM) {

  // Record the location within the token file.
  Offset off = (Offset) Out.tell();
  SourceManager& SMgr = PP.getSourceManager();

  Token Tok;

  do {
    L.LexFromRawLexer(Tok);

    if (Tok.is(tok::identifier)) {
      Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
    }
    else if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
      // Special processing for #include.  Store the '#' token and lex
      // the next token.
      EmitToken(Out, Tok, SMgr, idcount, IM);
      L.LexFromRawLexer(Tok);

      // Did we see 'include'/'import'/'include_next'?
      if (!Tok.is(tok::identifier))
        continue;

      IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
      Tok.setIdentifierInfo(II);
      tok::PPKeywordKind K = II->getPPKeywordID();

      if (K == tok::pp_include || K == tok::pp_import ||
          K == tok::pp_include_next) {

        // Save the 'include' token.
        EmitToken(Out, Tok, SMgr, idcount, IM);

        // Lex the next token as an include string.
        L.setParsingPreprocessorDirective(true);
        L.LexIncludeFilename(Tok);
        L.setParsingPreprocessorDirective(false);

        if (Tok.is(tok::identifier))
          Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
      }
    }
  }
  while (EmitToken(Out, Tok, SMgr, idcount, IM), Tok.isNot(tok::eof));

  return off;
}

void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
  // Lex through the entire file.  This will populate SourceManager with
  // all of the header information.
  Token Tok;
  PP.EnterMainSourceFile();
  do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));

  // Iterate over all the files in SourceManager.  Create a lexer
  // for each file and cache the tokens.
  SourceManager& SM = PP.getSourceManager();
  const LangOptions& LOpts = PP.getLangOptions();
  llvm::raw_ostream& os = llvm::errs();

  PCHMap PM;
  IDMap  IM;
  uint32_t idcount = 0;

  std::string ErrMsg;
  llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);

  if (!ErrMsg.empty()) {
    os << "PTH error: " << ErrMsg << "\n";
    return;
  }

  for (SourceManager::fileid_iterator I=SM.fileid_begin(), E=SM.fileid_end();
       I!=E; ++I) {

    const SrcMgr::ContentCache* C = I.getFileIDInfo().getContentCache();
    if (!C) continue;

    const FileEntry* FE = C->Entry;    // Does this entry correspond to a file?
    if (!FE) continue;

    // FIXME: Handle files with non-absolute paths.
    llvm::sys::Path P(FE->getName());
    if (!P.isAbsolute())
      continue;

    PCHMap::iterator PI = PM.find(FE); // Have we already processed this file?
    if (PI != PM.end()) continue;

    const llvm::MemoryBuffer* B = C->Buffer;
    if (!B) continue;

    Lexer L(SourceLocation::getFileLoc(I.getFileID(), 0), LOpts,
            B->getBufferStart(), B->getBufferEnd(), B);

    PM[FE] = LexTokens(Out, L, PP, idcount, IM);
  }

  // Write out the identifier table.
  std::pair<Offset,Offset> IdTableOff =
    EmitIdentifierTable(Out, idcount, PP.getIdentifierTable(), IM);

  // Write out the file table.
  Offset FileTableOff = EmitFileTable(Out, SM, PM);

  // Finally, write out the offset table at the end.
  Emit32(Out, IdTableOff.first);
  Emit32(Out, IdTableOff.second);
  Emit32(Out, FileTableOff);
}
<|endoftext|>


<commit_before>/*!
 * @file  logger_implement_access.cpp
 * @brief logger module implementation class For access log.
 *
 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
 * Copyright (C) 2009  NTT COMWARE Corporation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 **********************************************************************/

#include <iostream>
#include <sstream>
#include <iomanip>
#include <limits.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
#include <log4cxx/rolling/timebasedrollingpolicy.h>
#include <log4cxx/consoleappender.h>
#include <errno.h>
#include <stdexcept>
#include <boost/lexical_cast.hpp>

#include "logger_implement_access.h"

bool l7vs::logger_implement_access::rtn_init_flag;

bool l7vs::logger_implement_access::rtn_checkRotateParameterComp_flag;

bool l7vs::logger_implement_access::rtn_setAcLoggerConf_flag;

l7vs::logger_implement_access::logger_implement_access(const std::string &access_log_file_name)
            :rotate_default_flag( false ),
            access_cnt(1)
{
    access_log_file_name_ = access_log_file_name;
    aclog_args.clear();

}

bool l7vs::logger_implement_access::init(const bool rotate_default_flag,const appender_property& access_log_default_property,accesslog_rotate_map_type& rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_init_flag;

    return (rtn);

}

bool l7vs::logger_implement_access::setAcLoggerConf(const appender_property& access_log_default_property,accesslog_rotate_map_type& rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_setAcLoggerConf_flag;

    return(rtn);

}

void l7vs::logger_implement_access::addRef()
{
    access_cnt++;
}

void l7vs::logger_implement_access::releaseRef()
{
    access_cnt--;
}

bool l7vs::logger_implement_access::operator<=(const int access_num )
{
    return( access_cnt <= access_num );
}

std::string l7vs::logger_implement_access::getAcLogFileName()
{
    return( access_log_file_name_ );
}

bool l7vs::logger_implement_access::checkRotateParameterComp(accesslog_rotate_map_type &rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_checkRotateParameterComp_flag;

    return(rtn);
}

bool l7vs::logger_implement_access::is_rotate_default_flag()
{
    bool rtn = rotate_default_flag;

    return(rtn);
}

// OtH[}bg 2008/12/07 20:08:31 [INFO] [[AccessLog] (CL)192.168.2.1 --> 192.168.2.2 --UM-- 192.168.1.101:37259 --> (RS-DST)192.168.1.106:80 ]
/*!
 * output access info log.
 *
 * @param   virtualservice endpoint info
 * @param   client endpoint info
 * @param   realserver connect origin info
 * @param   realserver connect destination info
 * @param   add msg
 * @retrun  void
 */
void l7vs::logger_implement_access::putLog(
                            const std::string& vsinfo,
                            const std::string& cl_con_org,
                            const std::string& rs_con_org,
                            const std::string& rs_con_dest,
                            const std::string& msg){

    std::stringstream    buf;
    buf << boost::format( "[ [AccessLog] (CL)%s --> %s --UM-- %s --> (RS-DST)%s %s]" )
        % LOGGER_ACCESS_PROCESS_ID
        % vsinfo
        % cl_con_org
        % rs_con_org
        % rs_con_dest
        % msg;

    try {
        log4cxx::Logger::getLogger( access_log_file_name_ )->forcedLog(    log4cxx::Level::getInfo(),
                                                                    buf.str(),
                                                                    log4cxx::spi::LocationInfo("", "", 0));
    }
    catch (const std::exception& ex) {
        std::ostringstream oss;
        oss << "Logging Error (Access Log) : " << ex.what();
        std::cout << oss.str() << "\n";
    }

}
<commit_msg>Change char code ( S-JIS => UTF-8).<commit_after>/*!
 * @file  logger_implement_access.cpp
 * @brief logger module implementation class For access log.
 *
 * L7VSD: Linux Virtual Server for Layer7 Load Balancing
 * Copyright (C) 2009  NTT COMWARE Corporation.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA
 *
 **********************************************************************/

#include <iostream>
#include <sstream>
#include <iomanip>
#include <limits.h>
#include <log4cxx/logmanager.h>
#include <log4cxx/helpers/loglog.h>
#include <log4cxx/rolling/rollingfileappender.h>
#include <log4cxx/rolling/fixedwindowrollingpolicy.h>
#include <log4cxx/rolling/sizebasedtriggeringpolicy.h>
#include <log4cxx/rolling/timebasedrollingpolicy.h>
#include <log4cxx/consoleappender.h>
#include <errno.h>
#include <stdexcept>
#include <boost/lexical_cast.hpp>

#include "logger_implement_access.h"

bool l7vs::logger_implement_access::rtn_init_flag;

bool l7vs::logger_implement_access::rtn_checkRotateParameterComp_flag;

bool l7vs::logger_implement_access::rtn_setAcLoggerConf_flag;

l7vs::logger_implement_access::logger_implement_access(const std::string &access_log_file_name)
            :rotate_default_flag( false ),
            access_cnt(1)
{
    access_log_file_name_ = access_log_file_name;
    aclog_args.clear();

}

bool l7vs::logger_implement_access::init(const bool rotate_default_flag,const appender_property& access_log_default_property,accesslog_rotate_map_type& rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_init_flag;

    return (rtn);

}

bool l7vs::logger_implement_access::setAcLoggerConf(const appender_property& access_log_default_property,accesslog_rotate_map_type& rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_setAcLoggerConf_flag;

    return(rtn);

}

void l7vs::logger_implement_access::addRef()
{
    access_cnt++;
}

void l7vs::logger_implement_access::releaseRef()
{
    access_cnt--;
}

bool l7vs::logger_implement_access::operator<=(const int access_num )
{
    return( access_cnt <= access_num );
}

std::string l7vs::logger_implement_access::getAcLogFileName()
{
    return( access_log_file_name_ );
}

bool l7vs::logger_implement_access::checkRotateParameterComp(accesslog_rotate_map_type &rotatedata)
{
    bool rtn = l7vs::logger_implement_access::rtn_checkRotateParameterComp_flag;

    return(rtn);
}

bool l7vs::logger_implement_access::is_rotate_default_flag()
{
    bool rtn = rotate_default_flag;

    return(rtn);
}

// ログフォーマット 2008/12/07 20:08:31 [INFO] [[AccessLog] (CL)192.168.2.1 --> 192.168.2.2 --UM-- 192.168.1.101:37259 --> (RS-DST)192.168.1.106:80 ]
/*!
 * output access info log.
 *
 * @param   virtualservice endpoint info
 * @param   client endpoint info
 * @param   realserver connect origin info
 * @param   realserver connect destination info
 * @param   add msg
 * @retrun  void
 */
void l7vs::logger_implement_access::putLog(
                            const std::string& vsinfo,
                            const std::string& cl_con_org,
                            const std::string& rs_con_org,
                            const std::string& rs_con_dest,
                            const std::string& msg){

    std::stringstream    buf;
    buf << boost::format( "[ [AccessLog] (CL)%s --> %s --UM-- %s --> (RS-DST)%s %s]" )
        % LOGGER_ACCESS_PROCESS_ID
        % vsinfo
        % cl_con_org
        % rs_con_org
        % rs_con_dest
        % msg;

    try {
        log4cxx::Logger::getLogger( access_log_file_name_ )->forcedLog(    log4cxx::Level::getInfo(),
                                                                    buf.str(),
                                                                    log4cxx::spi::LocationInfo("", "", 0));
    }
    catch (const std::exception& ex) {
        std::ostringstream oss;
        oss << "Logging Error (Access Log) : " << ex.what();
        std::cout << oss.str() << "\n";
    }

}
<|endoftext|>


<commit_before>//
// Display a color cube
//
// Colors are assigned to each vertex and then the rasterizer interpolates
//   those colors across the triangles.  We us an orthographic projection
//   as the default projetion.

#include "../include/Angel.h"
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cerrno>

typedef Angel::vec4  color4;
typedef Angel::vec4  point4;
typedef struct OBJFile{
    char mtllib[100];
    char mtl_ver[100];
    long vertices_num;
    long faces_num;
    int ** faces;
    point4 * vertices;
} OBJFile;

void readObjFile ( const char * , OBJFile * );
void renderObj ( OBJFile * , point4 ** );

OBJFile objFile;
point4 * points;

//OpenGL initialization
void init ( ) {
    //Points buffer

    //Read in file "teapot.obj" and then render to points buffer
    readObjFile ( "teapot.obj" , &objFile );
    renderObj ( &objFile , &points );

    //Create a vertex array object
    GLuint vao[1];
    _glGenVertexArrays ( 1 , vao );
    _glBindVertexArray ( vao[0] );

    //Create and initialize a buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, 3*sizeof(point4)*objFile.faces_num, points, GL_STATIC_DRAW );

    //Load shaders and use the resulting shader program
    GLuint program = InitShader( "vshader.glsl", "fshader.glsl" );
    glUseProgram( program );

    GLint location = glGetAttribLocation ( program , "vPosition" );
    glEnableVertexAttribArray ( location );
    glVertexAttribPointer ( location , 4 , GL_FLOAT , GL_FALSE ,
                          0 , BUFFER_OFFSET ( 0 ) );

    glEnable ( GL_DEPTH_TEST );

    glClearColor( 0.0f , 0.0f , 0.0f , 1.0f );

}

//----------------------------------------------------------------------------

void display( )
{
    glPolygonMode( GL_FRONT_AND_BACK , GL_LINE ) ;

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    mat4  transform = Scale( .50 , .50 , .50 );
    point4 * transformed_points = (point4*)malloc(sizeof(point4) * 3 * objFile.faces_num );

    for ( int i = 0; i < (3 * objFile.faces_num); ++i ) {
        points[i] = transform*points[i];
    }

    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(point4) * 3 * objFile.faces_num, points );

    glDrawArrays( GL_TRIANGLES, 0, objFile.faces_num * 3 * sizeof(point4) );

    glutSwapBuffers();

}

//----------------------------------------------------------------------------

void keyboard( unsigned char key , int x , int y ) {
    switch( key ) {
    	case 033: // Escape Key
    	case 'q':
        case 'Q':
    	    exit( EXIT_SUCCESS );
    	break;
    }
}

void readObjFile ( const char * filename , OBJFile * objFile ) {
    //Counter
    long i;

    //Open handle for filename
    FILE * fp = fopen ( filename , "r" );

    //Make sure it was opened correctly.
    if ( !fp ) {
        perror ( "fopen" );
        return;
    }

    char buffer[512];

    objFile->vertices_num = 1;
    objFile->faces_num = 0;

    //Count all vertices and faces
    while ( fgets ( buffer , sizeof(buffer) , fp ) ) {
        if ( strstr ( buffer , "v" ) ) {
            objFile->vertices_num ++;
        } else
        if ( strstr ( buffer , "f" ) ) {
            objFile->faces_num ++;
        }
    }

    //Allocate memory for vertices and faces
    //printf ( "Vertices: %ld \n" , objFile->vertices_num );
    objFile->vertices = (point4*)malloc ( sizeof(point4) * objFile->vertices_num );
    if ( !objFile->vertices ) {
        perror ( "malloc" );
        return;
    }

    //printf ( "Faces: %ld \n" , objFile->faces_num );
    objFile->faces = (int**)malloc ( sizeof(int*) * objFile->faces_num );
    if ( !objFile->faces ) {
        perror ( "malloc" );
        return;
    }

    for ( i = 0 ; i < objFile->faces_num ; i ++ ) {
        objFile->faces[i] = (int*)malloc ( sizeof(int) * 3 );
        if ( !objFile->faces[i] ) {
            perror ( "malloc" );
            return;
        }
    }

    //Go back to beginning of file
    rewind ( fp );

    //Begin reading in data and store into OBJFile struct

    //Read in mtllib type
    if ( fscanf ( fp , "%s %s" , buffer , objFile->mtllib ) ) {
        //printf ( "%s\n", objFile->mtllib );
    }

    //Read in mtl version
    if ( fscanf ( fp , "%s %s" , buffer , objFile->mtl_ver ) ) {
        //printf ( "%s\n", objFile->mtl_ver );
    }

    //Read in vertices
    for ( i = 0 ; i < objFile->vertices_num ; i ++ ) {
        fscanf ( fp , "v" );
        fscanf ( fp , "%f %f %f" , &objFile->vertices[i][0] , &objFile->vertices[i][1] , &objFile->vertices[i][2] );
        fscanf ( fp , " " );
        objFile->vertices[i][3] = 1.0f;
        //printf ( "%f %f %f\n" , objFile->vertices[i][0] , objFile->vertices[i][1] , objFile->vertices[i][2] );
    }

    //Read in faces
    for ( i = 0 ; i < objFile->faces_num ; i ++ ) {
        fscanf ( fp , "f" );
        fscanf ( fp , "%i %i %i" , &objFile->faces[i][0] , &objFile->faces[i][1] , &objFile->faces[i][2] );
        fscanf ( fp , " " );
        //printf ( "%d %d %d\n" , objFile->faces[i][0] , objFile->faces[i][1] , objFile->faces[i][2] );
    }

}

void renderObj ( OBJFile * obj , point4 ** points) {
    //Counters
    long i , pt;

    //Create enough memory to store points of triangles
    *points = (point4*)malloc ( sizeof(point4) * 3 * obj->faces_num );

    for ( i = 0 , pt = 0 ; i < obj->faces_num ; i ++ ) {
        (*points)[pt] = obj->vertices[obj->faces[i][0]];
        (*points)[pt++] = obj->vertices[obj->faces[i][1]];
        (*points)[pt++] = obj->vertices[obj->faces[i][2]];
    }

}

int main( int argc , char **argv ) {
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
    glutInitWindowSize( 512, 512 );
    glutInitWindowPosition(0,0);
    glutCreateWindow( "Color Cube" );

#ifndef __APPLE__
    glewInit ( );
#endif

    init();

    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutMainLoop();

    return 0;
}
<commit_msg>Removed some old comments from another version of the homework.<commit_after>#include "../include/Angel.h"
#include <unistd.h>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <cerrno>

typedef Angel::vec4  color4;
typedef Angel::vec4  point4;
typedef struct OBJFile{
    char mtllib[100];
    char mtl_ver[100];
    long vertices_num;
    long faces_num;
    int ** faces;
    point4 * vertices;
} OBJFile;

void readObjFile ( const char * , OBJFile * );
void renderObj ( OBJFile * , point4 ** );

OBJFile objFile;
point4 * points;

//OpenGL initialization
void init ( ) {
    //Points buffer

    //Read in file "teapot.obj" and then render to points buffer
    readObjFile ( "teapot.obj" , &objFile );
    renderObj ( &objFile , &points );

    //Create a vertex array object
    GLuint vao[1];
    _glGenVertexArrays ( 1 , vao );
    _glBindVertexArray ( vao[0] );

    //Create and initialize a buffer object
    GLuint buffer;
    glGenBuffers( 1, &buffer );
    glBindBuffer( GL_ARRAY_BUFFER, buffer );
    glBufferData( GL_ARRAY_BUFFER, 3*sizeof(point4)*objFile.faces_num, points, GL_STATIC_DRAW );

    //Load shaders and use the resulting shader program
    GLuint program = InitShader( "vshader.glsl", "fshader.glsl" );
    glUseProgram( program );

    GLint location = glGetAttribLocation ( program , "vPosition" );
    glEnableVertexAttribArray ( location );
    glVertexAttribPointer ( location , 4 , GL_FLOAT , GL_FALSE ,
                          0 , BUFFER_OFFSET ( 0 ) );

    glEnable ( GL_DEPTH_TEST );

    glClearColor( 0.0f , 0.0f , 0.0f , 1.0f );

}

//----------------------------------------------------------------------------

void display( )
{
    glPolygonMode( GL_FRONT_AND_BACK , GL_LINE ) ;

    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    mat4  transform = Scale( .50 , .50 , .50 );
    point4 * transformed_points = (point4*)malloc(sizeof(point4) * 3 * objFile.faces_num );

    for ( int i = 0; i < (3 * objFile.faces_num); ++i ) {
        points[i] = transform*points[i];
    }

    glBufferSubData( GL_ARRAY_BUFFER, 0, sizeof(point4) * 3 * objFile.faces_num, points );

    glDrawArrays( GL_TRIANGLES, 0, objFile.faces_num * 3 * sizeof(point4) );

    glutSwapBuffers();

}

//----------------------------------------------------------------------------

void keyboard( unsigned char key , int x , int y ) {
    switch( key ) {
    	case 033: // Escape Key
    	case 'q':
        case 'Q':
    	    exit( EXIT_SUCCESS );
    	break;
    }
}

void readObjFile ( const char * filename , OBJFile * objFile ) {
    //Counter
    long i;

    //Open handle for filename
    FILE * fp = fopen ( filename , "r" );

    //Make sure it was opened correctly.
    if ( !fp ) {
        perror ( "fopen" );
        return;
    }

    char buffer[512];

    objFile->vertices_num = 1;
    objFile->faces_num = 0;

    //Count all vertices and faces
    while ( fgets ( buffer , sizeof(buffer) , fp ) ) {
        if ( strstr ( buffer , "v" ) ) {
            objFile->vertices_num ++;
        } else
        if ( strstr ( buffer , "f" ) ) {
            objFile->faces_num ++;
        }
    }

    //Allocate memory for vertices and faces
    //printf ( "Vertices: %ld \n" , objFile->vertices_num );
    objFile->vertices = (point4*)malloc ( sizeof(point4) * objFile->vertices_num );
    if ( !objFile->vertices ) {
        perror ( "malloc" );
        return;
    }

    //printf ( "Faces: %ld \n" , objFile->faces_num );
    objFile->faces = (int**)malloc ( sizeof(int*) * objFile->faces_num );
    if ( !objFile->faces ) {
        perror ( "malloc" );
        return;
    }

    for ( i = 0 ; i < objFile->faces_num ; i ++ ) {
        objFile->faces[i] = (int*)malloc ( sizeof(int) * 3 );
        if ( !objFile->faces[i] ) {
            perror ( "malloc" );
            return;
        }
    }

    //Go back to beginning of file
    rewind ( fp );

    //Begin reading in data and store into OBJFile struct

    //Read in mtllib type
    if ( fscanf ( fp , "%s %s" , buffer , objFile->mtllib ) ) {
        //printf ( "%s\n", objFile->mtllib );
    }

    //Read in mtl version
    if ( fscanf ( fp , "%s %s" , buffer , objFile->mtl_ver ) ) {
        //printf ( "%s\n", objFile->mtl_ver );
    }

    //Read in vertices
    for ( i = 0 ; i < objFile->vertices_num ; i ++ ) {
        fscanf ( fp , "v" );
        fscanf ( fp , "%f %f %f" , &objFile->vertices[i][0] , &objFile->vertices[i][1] , &objFile->vertices[i][2] );
        fscanf ( fp , " " );
        objFile->vertices[i][3] = 1.0f;
        //printf ( "%f %f %f\n" , objFile->vertices[i][0] , objFile->vertices[i][1] , objFile->vertices[i][2] );
    }

    //Read in faces
    for ( i = 0 ; i < objFile->faces_num ; i ++ ) {
        fscanf ( fp , "f" );
        fscanf ( fp , "%i %i %i" , &objFile->faces[i][0] , &objFile->faces[i][1] , &objFile->faces[i][2] );
        fscanf ( fp , " " );
        //printf ( "%d %d %d\n" , objFile->faces[i][0] , objFile->faces[i][1] , objFile->faces[i][2] );
    }

}

void renderObj ( OBJFile * obj , point4 ** points) {
    //Counters
    long i , pt;

    //Create enough memory to store points of triangles
    *points = (point4*)malloc ( sizeof(point4) * 3 * obj->faces_num );

    for ( i = 0 , pt = 0 ; i < obj->faces_num ; i ++ ) {
        (*points)[pt] = obj->vertices[obj->faces[i][0]];
        (*points)[pt++] = obj->vertices[obj->faces[i][1]];
        (*points)[pt++] = obj->vertices[obj->faces[i][2]];
    }

}

int main( int argc , char **argv ) {
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH );
    glutInitWindowSize( 512, 512 );
    glutInitWindowPosition(0,0);
    glutCreateWindow( "Color Cube" );

#ifndef __APPLE__
    glewInit ( );
#endif

    init();

    glutDisplayFunc( display );
    glutKeyboardFunc( keyboard );
    glutMainLoop();

    return 0;
}
<|endoftext|>