<commit_before>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "sparse_merge_function.h"
#include "generic_merge.h"
#include <vespa/eval/eval/fast_value.hpp>
#include <vespa/vespalib/util/typify.h>

namespace vespalib::eval {

using namespace tensor_function;
using namespace operation;
using namespace instruction;

namespace {

template <typename CT, bool single_dim, typename Fun>
const Value& my_fast_sparse_merge(const FastAddrMap &a_map, const FastAddrMap &b_map,
                                  const CT *a_cells, const CT *b_cells,
                                  const MergeParam &params,
                                  Stash &stash)
{
    Fun fun(params.function);
    size_t guess_size = a_map.size() + b_map.size();
    auto &result = stash.create<FastValue<CT,true>>(params.res_type, params.num_mapped_dimensions, 1u, guess_size);
    if constexpr (single_dim) {
        string_id cur_label;
        ConstArrayRef<string_id> addr(&cur_label, 1);
        const auto &a_labels = a_map.labels();
        for (size_t i = 0; i < a_labels.size(); ++i) {
            cur_label = a_labels[i];
            result.add_mapping(addr, cur_label.hash());
            result.my_cells.push_back_fast(a_cells[i]);
        }
        const auto &b_labels = b_map.labels();
        for (size_t i = 0; i < b_labels.size(); ++i) {
            cur_label = b_labels[i];
            auto result_subspace = result.my_index.map.lookup_singledim(cur_label);
            if (result_subspace == FastAddrMap::npos()) {
                result.add_mapping(addr, cur_label.hash());
                result.my_cells.push_back_fast(b_cells[i]);
            } else {
                CT *out_cell = result.my_cells.get(result_subspace);
                out_cell[0] = fun(out_cell[0], b_cells[i]);
            }
        }
    } else {
        a_map.each_map_entry([&](auto lhs_subspace, auto hash)
        {
            result.add_mapping(a_map.get_addr(lhs_subspace), hash);
            result.my_cells.push_back_fast(a_cells[lhs_subspace]);
        });
        b_map.each_map_entry([&](auto rhs_subspace, auto hash)
        {
            auto rhs_addr = b_map.get_addr(rhs_subspace);
            auto result_subspace = result.my_index.map.lookup(rhs_addr, hash);
            if (result_subspace == FastAddrMap::npos()) {
                result.add_mapping(rhs_addr, hash);
                result.my_cells.push_back_fast(b_cells[rhs_subspace]);
            } else {
                CT *out_cell = result.my_cells.get(result_subspace);
                out_cell[0] = fun(out_cell[0], b_cells[rhs_subspace]);
            }
        });
    }
    return result;
}

template <typename CT, bool single_dim, typename Fun>
void my_sparse_merge_op(InterpretedFunction::State &state, uint64_t param_in) {
    const auto &param = unwrap_param<MergeParam>(param_in);
    assert(param.dense_subspace_size == 1u);
    const Value &a = state.peek(1);
    const Value &b = state.peek(0);
    const auto &a_idx = a.index();
    const auto &b_idx = b.index();
    if (__builtin_expect(are_fast(a_idx, b_idx), true)) {
        auto a_cells = a.cells().typify<CT>();
        auto b_cells = b.cells().typify<CT>();
        const Value &v = my_fast_sparse_merge<CT,single_dim,Fun>(as_fast(a_idx).map, as_fast(b_idx).map,
                                                                 a_cells.cbegin(), b_cells.cbegin(),
                                                                 param, state.stash);
        state.pop_pop_push(v);
    } else {
        auto up = generic_mixed_merge<CT,CT,CT,Fun>(a, b, param);
        state.pop_pop_push(*state.stash.create<std::unique_ptr<Value>>(std::move(up)));
    }
}

struct SelectSparseMergeOp {
    template <typename CT, typename SINGLE_DIM, typename Fun>
    static auto invoke() { return my_sparse_merge_op<CT,SINGLE_DIM::value,Fun>; }
};

using MyTypify = TypifyValue<TypifyCellType,TypifyBool,operation::TypifyOp2>;

} // namespace <unnamed>

SparseMergeFunction::SparseMergeFunction(const tensor_function::Merge &original)
  : tensor_function::Merge(original.result_type(),
                           original.lhs(),
                           original.rhs(),
                           original.function())
{
    assert(compatible_types(result_type(), lhs().result_type(), rhs().result_type()));
}

InterpretedFunction::Instruction
SparseMergeFunction::compile_self(const ValueBuilderFactory &factory, Stash &stash) const
{
    const auto &param = stash.create<MergeParam>(result_type(),
                                                 lhs().result_type(), rhs().result_type(),
                                                 function(), factory);
    size_t num_dims = result_type().count_mapped_dimensions();
    auto op = typify_invoke<3,MyTypify,SelectSparseMergeOp>(result_type().cell_type(),
                                                            num_dims == 1,
                                                            function());
    return InterpretedFunction::Instruction(op, wrap_param<MergeParam>(param));
}

bool
SparseMergeFunction::compatible_types(const ValueType &res, const ValueType &lhs, const ValueType &rhs)
{
    if ((lhs.cell_type() == rhs.cell_type())
        && (lhs.count_mapped_dimensions() > 0)
        && (lhs.dense_subspace_size() == 1))
    {
        assert(res == lhs);
        assert(res == rhs);
        return true;
    }
    return false;
}

const TensorFunction &
SparseMergeFunction::optimize(const TensorFunction &expr, Stash &stash)
{
    if (auto merge = as<Merge>(expr)) {
        const TensorFunction &lhs = merge->lhs();
        const TensorFunction &rhs = merge->rhs();
        if (compatible_types(expr.result_type(), lhs.result_type(), rhs.result_type())) {
            return stash.create<SparseMergeFunction>(*merge);
        }
    }
    return expr;
}

} // namespace
<commit_msg>use TypifyCellMeta in sparse merge optimizer<commit_after>// Copyright Verizon Media. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.

#include "sparse_merge_function.h"
#include "generic_merge.h"
#include <vespa/eval/eval/fast_value.hpp>
#include <vespa/vespalib/util/typify.h>

namespace vespalib::eval {

using namespace tensor_function;
using namespace operation;
using namespace instruction;

namespace {

template <typename CT, bool single_dim, typename Fun>
const Value& my_fast_sparse_merge(const FastAddrMap &a_map, const FastAddrMap &b_map,
                                  const CT *a_cells, const CT *b_cells,
                                  const MergeParam &params,
                                  Stash &stash)
{
    Fun fun(params.function);
    size_t guess_size = a_map.size() + b_map.size();
    auto &result = stash.create<FastValue<CT,true>>(params.res_type, params.num_mapped_dimensions, 1u, guess_size);
    if constexpr (single_dim) {
        string_id cur_label;
        ConstArrayRef<string_id> addr(&cur_label, 1);
        const auto &a_labels = a_map.labels();
        for (size_t i = 0; i < a_labels.size(); ++i) {
            cur_label = a_labels[i];
            result.add_mapping(addr, cur_label.hash());
            result.my_cells.push_back_fast(a_cells[i]);
        }
        const auto &b_labels = b_map.labels();
        for (size_t i = 0; i < b_labels.size(); ++i) {
            cur_label = b_labels[i];
            auto result_subspace = result.my_index.map.lookup_singledim(cur_label);
            if (result_subspace == FastAddrMap::npos()) {
                result.add_mapping(addr, cur_label.hash());
                result.my_cells.push_back_fast(b_cells[i]);
            } else {
                CT *out_cell = result.my_cells.get(result_subspace);
                out_cell[0] = fun(out_cell[0], b_cells[i]);
            }
        }
    } else {
        a_map.each_map_entry([&](auto lhs_subspace, auto hash)
        {
            result.add_mapping(a_map.get_addr(lhs_subspace), hash);
            result.my_cells.push_back_fast(a_cells[lhs_subspace]);
        });
        b_map.each_map_entry([&](auto rhs_subspace, auto hash)
        {
            auto rhs_addr = b_map.get_addr(rhs_subspace);
            auto result_subspace = result.my_index.map.lookup(rhs_addr, hash);
            if (result_subspace == FastAddrMap::npos()) {
                result.add_mapping(rhs_addr, hash);
                result.my_cells.push_back_fast(b_cells[rhs_subspace]);
            } else {
                CT *out_cell = result.my_cells.get(result_subspace);
                out_cell[0] = fun(out_cell[0], b_cells[rhs_subspace]);
            }
        });
    }
    return result;
}

template <typename CT, bool single_dim, typename Fun>
void my_sparse_merge_op(InterpretedFunction::State &state, uint64_t param_in) {
    const auto &param = unwrap_param<MergeParam>(param_in);
    assert(param.dense_subspace_size == 1u);
    const Value &a = state.peek(1);
    const Value &b = state.peek(0);
    const auto &a_idx = a.index();
    const auto &b_idx = b.index();
    if (__builtin_expect(are_fast(a_idx, b_idx), true)) {
        auto a_cells = a.cells().typify<CT>();
        auto b_cells = b.cells().typify<CT>();
        const Value &v = my_fast_sparse_merge<CT,single_dim,Fun>(as_fast(a_idx).map, as_fast(b_idx).map,
                                                                 a_cells.cbegin(), b_cells.cbegin(),
                                                                 param, state.stash);
        state.pop_pop_push(v);
    } else {
        auto up = generic_mixed_merge<CT,CT,CT,Fun>(a, b, param);
        state.pop_pop_push(*state.stash.create<std::unique_ptr<Value>>(std::move(up)));
    }
}

struct SelectSparseMergeOp {
    template <typename R1, typename SINGLE_DIM, typename Fun>
    static auto invoke() {
        using CT = CellValueType<R1::value.cell_type>;
        return my_sparse_merge_op<CT,SINGLE_DIM::value,Fun>;
    }
};

using MyTypify = TypifyValue<TypifyCellMeta,TypifyBool,operation::TypifyOp2>;

} // namespace <unnamed>

SparseMergeFunction::SparseMergeFunction(const tensor_function::Merge &original)
  : tensor_function::Merge(original.result_type(),
                           original.lhs(),
                           original.rhs(),
                           original.function())
{
    assert(compatible_types(result_type(), lhs().result_type(), rhs().result_type()));
}

InterpretedFunction::Instruction
SparseMergeFunction::compile_self(const ValueBuilderFactory &factory, Stash &stash) const
{
    const auto &param = stash.create<MergeParam>(result_type(),
                                                 lhs().result_type(), rhs().result_type(),
                                                 function(), factory);
    size_t num_dims = result_type().count_mapped_dimensions();
    auto op = typify_invoke<3,MyTypify,SelectSparseMergeOp>(result_type().cell_meta().limit(),
                                                            num_dims == 1,
                                                            function());
    return InterpretedFunction::Instruction(op, wrap_param<MergeParam>(param));
}

bool
SparseMergeFunction::compatible_types(const ValueType &res, const ValueType &lhs, const ValueType &rhs)
{
    if ((lhs.cell_type() == rhs.cell_type())
        && (lhs.cell_type() == res.cell_type())
        && (lhs.count_mapped_dimensions() > 0)
        && (lhs.dense_subspace_size() == 1))
    {
        assert(res == lhs);
        assert(res == rhs);
        return true;
    }
    return false;
}

const TensorFunction &
SparseMergeFunction::optimize(const TensorFunction &expr, Stash &stash)
{
    if (auto merge = as<Merge>(expr)) {
        const TensorFunction &lhs = merge->lhs();
        const TensorFunction &rhs = merge->rhs();
        if (compatible_types(expr.result_type(), lhs.result_type(), rhs.result_type())) {
            return stash.create<SparseMergeFunction>(*merge);
        }
    }
    return expr;
}

} // namespace
<|endoftext|>


<commit_before>#pragma once
#include <opencv2/core/cuda.hpp>

#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/device_ptr.h>

/*
	@Brief step_functor is an object to correctly step a thrust iterator according to the stride of a matrix
*/
//! [step_functor]
template<typename T> struct step_functor : public thrust::unary_function<int, int>
{
	int columns;
	int step;
	int channels;
	__host__ __device__ step_functor(int columns_, int step_, int channels_ = 1) : columns(columns_), step(step_), channels(channels_)	{	};
	__host__ step_functor(cv::cuda::GpuMat& mat)
	{
		CV_Assert(mat.depth() == cv::DataType<T>::depth);
		columns = mat.cols;
		step = mat.step / sizeof(T);
		channels = mat.channels();
	}
	__host__ __device__
		int operator()(int x) const
	{
		int row = x / columns;
		int idx = (row * step) + (x % columns)*channels;
		return idx;
	}
};
//! [step_functor]
//! [begin_itr]
/*
	@Brief GpuMatBeginItr returns a thrust compatible iterator to the beginning of a GPU mat's memory.
	@Param mat is the input matrix
	@Param channel is the channel of the matrix that the iterator is accessing.  If set to -1, the iterator will access every element in sequential order
*/
template<typename T>
thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<step_functor<T>, thrust::counting_iterator<int>>>  GpuMatBeginItr(cv::cuda::GpuMat mat, int channel = 0)
{
	if (channel == -1)
		mat = mat.reshape(1);
	CV_Assert(mat.depth() == cv::DataType<T>::depth);
	CV_Assert(channel < mat.channels());
	return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
		thrust::make_transform_iterator(thrust::make_counting_iterator(0), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
}
//! [begin_itr]
//! [end_itr]
/*
@Brief GpuMatEndItr returns a thrust compatible iterator to the end of a GPU mat's memory.
@Param mat is the input matrix
@Param channel is the channel of the matrix that the iterator is accessing.  If set to -1, the iterator will access every element in sequential order
*/
template<typename T>
thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<step_functor<T>, thrust::counting_iterator<int>>>  GpuMatEndItr(cv::cuda::GpuMat mat, int channel = 0)
{
	if (channel == -1)
		mat = mat.reshape(1);
	CV_Assert(mat.depth() == cv::DataType<T>::depth);
	CV_Assert(channel < mat.channels());
	return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
		thrust::make_transform_iterator(thrust::make_counting_iterator(mat.rows*mat.cols), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
}
//! [end_itr]

<commit_msg>More whitespace fixes.<commit_after>#pragma once
#include <opencv2/core/cuda.hpp>

#include <thrust/iterator/permutation_iterator.h>
#include <thrust/iterator/transform_iterator.h>
#include <thrust/iterator/counting_iterator.h>
#include <thrust/device_ptr.h>

/*
	@Brief step_functor is an object to correctly step a thrust iterator according to the stride of a matrix
*/
//! [step_functor]
template<typename T> struct step_functor : public thrust::unary_function<int, int>
{
	int columns;
	int step;
	int channels;
	__host__ __device__ step_functor(int columns_, int step_, int channels_ = 1) : columns(columns_), step(step_), channels(channels_)	{	};
	__host__ step_functor(cv::cuda::GpuMat& mat)
	{
		CV_Assert(mat.depth() == cv::DataType<T>::depth);
		columns = mat.cols;
		step = mat.step / sizeof(T);
		channels = mat.channels();
	}
	__host__ __device__
		int operator()(int x) const
	{
		int row = x / columns;
		int idx = (row * step) + (x % columns)*channels;
		return idx;
	}
};
//! [step_functor]
//! [begin_itr]
/*
	@Brief GpuMatBeginItr returns a thrust compatible iterator to the beginning of a GPU mat's memory.
	@Param mat is the input matrix
	@Param channel is the channel of the matrix that the iterator is accessing.  If set to -1, the iterator will access every element in sequential order
*/
template<typename T>
thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<step_functor<T>, thrust::counting_iterator<int>>>  GpuMatBeginItr(cv::cuda::GpuMat mat, int channel = 0)
{
	if (channel == -1)
		mat = mat.reshape(1);
	CV_Assert(mat.depth() == cv::DataType<T>::depth);
	CV_Assert(channel < mat.channels());
	return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
		thrust::make_transform_iterator(thrust::make_counting_iterator(0), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
}
//! [begin_itr]
//! [end_itr]
/*
@Brief GpuMatEndItr returns a thrust compatible iterator to the end of a GPU mat's memory.
@Param mat is the input matrix
@Param channel is the channel of the matrix that the iterator is accessing.  If set to -1, the iterator will access every element in sequential order
*/
template<typename T>
thrust::permutation_iterator<thrust::device_ptr<T>, thrust::transform_iterator<step_functor<T>, thrust::counting_iterator<int>>>  GpuMatEndItr(cv::cuda::GpuMat mat, int channel = 0)
{
	if (channel == -1)
		mat = mat.reshape(1);
	CV_Assert(mat.depth() == cv::DataType<T>::depth);
	CV_Assert(channel < mat.channels());
	return thrust::make_permutation_iterator(thrust::device_pointer_cast(mat.ptr<T>(0) + channel),
		thrust::make_transform_iterator(thrust::make_counting_iterator(mat.rows*mat.cols), step_functor<T>(mat.cols, mat.step / sizeof(T), mat.channels())));
}
//! [end_itr]<|endoftext|>


<commit_before>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "console/console.h"

#include "SDL.h"
#include "windowManager/sdl/sdlWindow.h"

static SDL_Window* gSplashWindow = nullptr;
static SDL_Surface* gSplashImage = nullptr;
static SDL_Texture* gSplashTexture = nullptr;
static SDL_Renderer* gSplashRenderer = nullptr;

bool Platform::displaySplashWindow( String path )
{
   if(path.isEmpty())
      return false;

   gSplashImage = SDL_LoadBMP(path);

   //now the pop-up window
   gSplashWindow = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
      gSplashImage->w, gSplashImage->h, SDL_WINDOW_BORDERLESS | SDL_WINDOW_SHOWN);

   gSplashRenderer = SDL_CreateRenderer(gSplashWindow, -1, SDL_RENDERER_ACCELERATED);

   gSplashTexture = SDL_CreateTextureFromSurface(gSplashRenderer, gSplashImage);

   SDL_RenderCopy(gSplashRenderer, gSplashTexture, NULL, NULL);

   SDL_RenderPresent(gSplashRenderer);

	return true;
}

bool Platform::closeSplashWindow()
{
   SDL_DestroyTexture(gSplashTexture);
   SDL_FreeSurface(gSplashImage);
   SDL_DestroyRenderer(gSplashRenderer);
   SDL_DestroyWindow(gSplashWindow);

   return true;
}<commit_msg>Also adds a sanity check in the event a splash image isn't found.<commit_after>//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

#include "platform/platform.h"
#include "console/console.h"

#include "SDL.h"
#include "windowManager/sdl/sdlWindow.h"

static SDL_Window* gSplashWindow = nullptr;
static SDL_Surface* gSplashImage = nullptr;
static SDL_Texture* gSplashTexture = nullptr;
static SDL_Renderer* gSplashRenderer = nullptr;

bool Platform::displaySplashWindow( String path )
{
   if(path.isEmpty())
      return false;

   gSplashImage = SDL_LoadBMP(path);

   //now the pop-up window
   if (gSplashImage)
   {
      gSplashWindow = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
         gSplashImage->w, gSplashImage->h, SDL_WINDOW_BORDERLESS | SDL_WINDOW_SHOWN);

      gSplashRenderer = SDL_CreateRenderer(gSplashWindow, -1, SDL_RENDERER_ACCELERATED);

      gSplashTexture = SDL_CreateTextureFromSurface(gSplashRenderer, gSplashImage);

      SDL_RenderCopy(gSplashRenderer, gSplashTexture, NULL, NULL);

      SDL_RenderPresent(gSplashRenderer);
   }

	return true;
}

bool Platform::closeSplashWindow()
{
   SDL_DestroyTexture(gSplashTexture);
   SDL_FreeSurface(gSplashImage);
   SDL_DestroyRenderer(gSplashRenderer);
   SDL_DestroyWindow(gSplashWindow);

   return true;
}<|endoftext|>


<commit_before>#include "ProjectWidgetDemoWindow.h"
#include "Required/Project/ProjectSerializer.h"
#include "Required/Project/ProjectException.h"
#include "Required/Project/FileCategory.h"
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QRegExp>

ProjectWidgetDemoWindow::ProjectWidgetDemoWindow(QWidget *parent) :
    QMainWindow(parent)
{
    Required::FileCategory::registerCategory("txt", "Text files", QRegExp("*.txt", Qt::CaseSensitive, QRegExp::Wildcard));
    Required::FileCategory::registerCategory("json", "JSON data", QRegExp("*.json", Qt::CaseSensitive, QRegExp::Wildcard));

    // load project data from file
    QFile file("project.xml");
    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        Required::ProjectSerializer serializer(&file);
        try
        {
            m_project = serializer.deserialize();
        }
        catch (Required::ProjectException& e)
        {
            m_project = new Required::Project(this);
            m_project->setName("My Awesome Project");
        }
        file.close();
    }
    else
    {
        m_project = new Required::Project(this);
        m_project->setName("My Awesome Project");
    }

    m_project->setParent(this);
    m_projectWidget = new Required::ProjectWidget(this);
    m_projectWidget->setProject(m_project);
    setCentralWidget(m_projectWidget);

    connect(m_projectWidget, &Required::ProjectWidget::fileOpened, [&](QString filename) {
        QMessageBox::information(this, "File opened!", filename);
    });
}

void ProjectWidgetDemoWindow::closeEvent(QCloseEvent* event)
{
    // store project data in file
    QFile file("project.xml");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        Required::ProjectSerializer serializer(&file);
        try
        {
            serializer.serialize(*m_project);
        }
        catch (Required::ProjectException& e)
        {
            qDebug() << e.what();
        }
        file.close();
    }
}
<commit_msg>Back to default regexp syntax in project_widget example.<commit_after>#include "ProjectWidgetDemoWindow.h"
#include "Required/Project/ProjectSerializer.h"
#include "Required/Project/ProjectException.h"
#include "Required/Project/FileCategory.h"
#include <QDebug>
#include <QFile>
#include <QMessageBox>
#include <QRegExp>

ProjectWidgetDemoWindow::ProjectWidgetDemoWindow(QWidget *parent) :
    QMainWindow(parent)
{
    Required::FileCategory::registerCategory("txt", "Text files", QRegExp(".*\\.txt$"));
    Required::FileCategory::registerCategory("json", "JSON data", QRegExp(".*\\.json$"));

    // load project data from file
    QFile file("project.xml");
    if (file.open(QIODevice::ReadOnly | QIODevice::Text))
    {
        Required::ProjectSerializer serializer(&file);
        try
        {
            m_project = serializer.deserialize();
        }
        catch (Required::ProjectException& e)
        {
            m_project = new Required::Project(this);
            m_project->setName("My Awesome Project");
        }
        file.close();
    }
    else
    {
        m_project = new Required::Project(this);
        m_project->setName("My Awesome Project");
    }

    m_project->setParent(this);
    m_projectWidget = new Required::ProjectWidget(this);
    m_projectWidget->setProject(m_project);
    setCentralWidget(m_projectWidget);

    connect(m_projectWidget, &Required::ProjectWidget::fileOpened, [&](QString filename) {
        QMessageBox::information(this, "File opened!", filename);
    });
}

void ProjectWidgetDemoWindow::closeEvent(QCloseEvent* event)
{
    // store project data in file
    QFile file("project.xml");
    if (file.open(QIODevice::WriteOnly | QIODevice::Text))
    {
        Required::ProjectSerializer serializer(&file);
        try
        {
            serializer.serialize(*m_project);
        }
        catch (Required::ProjectException& e)
        {
            qDebug() << e.what();
        }
        file.close();
    }
}
<|endoftext|>


<commit_before>#ifndef SiconosVisitables_hpp
#define SiconosVisitables_hpp

#undef REGISTER
#define SICONOS_VISITABLES()                                 \
  REGISTER(DynamicalSystem)                                  \
  REGISTER(DynamicalSystemXML)                               \
  REGISTER(DiskPlanR)                                        \
  REGISTER(DiskMovingPlanR)                                  \
  REGISTER(CircleCircleR)                                    \
  REGISTER(DiskDiskR)                                        \
  REGISTER(SphereNEDSPlanR)                                  \
  REGISTER(SphereNEDSSphereNEDSR)                            \
  REGISTER(SphereLDSSphereLDSR)                              \
  REGISTER(SphereLDSPlanR)                                   \
  REGISTER(NonSmoothLaw)                                     \
  REGISTER(MixedComplementarityConditionNSL)                 \
  REGISTER(EqualityConditionNSL)                             \
  REGISTER(ComplementarityConditionNSL)                      \
  REGISTER(RelayNSL)                                         \
  REGISTER(NewtonImpactNSL)                                  \
  REGISTER(NewtonImpactFrictionNSL)                          \
  REGISTER(Simulation)                                       \
  REGISTER(TimeStepping)                                     \
  REGISTER(EventDriven)                                      \
  REGISTER(OneStepNSProblem)                                 \
  REGISTER(LCP)                                              \
  REGISTER(FrictionContact)                                  \
  REGISTER(SimpleVector)                                     \
  REGISTER(BlockVector)                                      \
  REGISTER(LagrangianDS)                                     \
  REGISTER(LagrangianLinearTIDS)                             \
  REGISTER(FirstOrderLinearDS)                               \
  REGISTER(FirstOrderNonLinearDS)                            \
  REGISTER(FirstOrderLinearTIDS)                             \
  REGISTER(FirstOrderType1R)                                 \
  REGISTER(FirstOrderType2R)                                 \
  REGISTER(FirstOrderLinearR)                                \
  REGISTER(FirstOrderLinearTIR)                              \
  REGISTER(LagrangianScleronomousR)                          \
  REGISTER(LagrangianRheonomousR)                            \
  REGISTER(LagrangianCompliantR)                             \
  REGISTER(LagrangianLinearTIR)                              \
  REGISTER(NewtonEulerDS)                                    \
  REGISTER(NewtonEulerR)                                     \
  REGISTER_BASE(ExternalBody, LagrangianDS)                  \
  REGISTER_BASE(Lmgc2DDSK, LagrangianDS)                     \
  REGISTER_BASE(Disk, LagrangianDS)                          \
  REGISTER_BASE(Circle, LagrangianDS)                        \
  REGISTER_BASE(SphereLDS, LagrangianDS)                     \
  REGISTER_BASE(SphereNEDS, NewtonEulerDS)                   \

#endif
<commit_msg>add Lmgc2DPOLYG<commit_after>#ifndef SiconosVisitables_hpp
#define SiconosVisitables_hpp

#undef REGISTER
#define SICONOS_VISITABLES()                                 \
  REGISTER(DynamicalSystem)                                  \
  REGISTER(DynamicalSystemXML)                               \
  REGISTER(DiskPlanR)                                        \
  REGISTER(DiskMovingPlanR)                                  \
  REGISTER(CircleCircleR)                                    \
  REGISTER(DiskDiskR)                                        \
  REGISTER(SphereNEDSPlanR)                                  \
  REGISTER(SphereNEDSSphereNEDSR)                            \
  REGISTER(SphereLDSSphereLDSR)                              \
  REGISTER(SphereLDSPlanR)                                   \
  REGISTER(NonSmoothLaw)                                     \
  REGISTER(MixedComplementarityConditionNSL)                 \
  REGISTER(EqualityConditionNSL)                             \
  REGISTER(ComplementarityConditionNSL)                      \
  REGISTER(RelayNSL)                                         \
  REGISTER(NewtonImpactNSL)                                  \
  REGISTER(NewtonImpactFrictionNSL)                          \
  REGISTER(Simulation)                                       \
  REGISTER(TimeStepping)                                     \
  REGISTER(EventDriven)                                      \
  REGISTER(OneStepNSProblem)                                 \
  REGISTER(LCP)                                              \
  REGISTER(FrictionContact)                                  \
  REGISTER(SimpleVector)                                     \
  REGISTER(BlockVector)                                      \
  REGISTER(LagrangianDS)                                     \
  REGISTER(LagrangianLinearTIDS)                             \
  REGISTER(FirstOrderLinearDS)                               \
  REGISTER(FirstOrderNonLinearDS)                            \
  REGISTER(FirstOrderLinearTIDS)                             \
  REGISTER(FirstOrderType1R)                                 \
  REGISTER(FirstOrderType2R)                                 \
  REGISTER(FirstOrderLinearR)                                \
  REGISTER(FirstOrderLinearTIR)                              \
  REGISTER(LagrangianScleronomousR)                          \
  REGISTER(LagrangianRheonomousR)                            \
  REGISTER(LagrangianCompliantR)                             \
  REGISTER(LagrangianLinearTIR)                              \
  REGISTER(NewtonEulerDS)                                    \
  REGISTER(NewtonEulerR)                                     \
  REGISTER_BASE(ExternalBody, LagrangianDS)                  \
  REGISTER_BASE(Lmgc2DDSK, LagrangianDS)                     \
  REGISTER_BASE(Lmgc2DPOLYG, LagrangianDS)                   \
  REGISTER_BASE(Disk, LagrangianDS)                          \
  REGISTER_BASE(Circle, LagrangianDS)                        \
  REGISTER_BASE(SphereLDS, LagrangianDS)                     \
  REGISTER_BASE(SphereNEDS, NewtonEulerDS)                   \

#endif
<|endoftext|>


<commit_before>#pragma once
#include "screenrect.hpp"
#include "../updater.hpp"
#include "../glresource.hpp"

namespace rs {
	namespace util {
		class PostEffect : public DrawableObjT<PostEffect> {
			private:
				using base_t = DrawableObjT<PostEffect>;
				using ParamF = std::function<void (IEffect&)>;
				using ParamFV = std::vector<std::pair<IdValue, ParamF>>;
				IdValue			_idTech;
				ParamFV			_param;
				ScreenRect		_rect;

				void _applyParam(IEffect& e) const;
			public:
				PostEffect(IdValue idTech, Priority dprio);
				template <class T>
				void setParam(IdValue id, const T& t) {
					setParamFunc(id, [id,tv=t](auto& e){ e.setUniform(id, tv); });
				}
				void setParamFunc(IdValue id, const ParamF& f);
				void clearParam();
				void onDraw(IEffect& e) const override;
		};
		class FBSwitch : public DrawableObjT<FBSwitch> {
			private:
				HLFb			_hlFb;
				using ClearParam_OP = spn::Optional<draw::ClearParam>;
				ClearParam_OP	_cparam;
			public:
				FBSwitch(Priority dprio, HFb hFb, const ClearParam_OP& p=spn::none);
				void onDraw(IEffect& e) const override;
				void setClearParam(const ClearParam_OP& p);
		};
		class FBClear : public DrawableObjT<FBClear> {
			private:
				draw::ClearParam _param;
			public:
				FBClear(Priority dprio,
						const draw::ClearParam& p);
				void onDraw(IEffect& e) const override;
		};
	}
}
#include "luaimport.hpp"
DEF_LUAIMPORT(rs::util::FBSwitch)
DEF_LUAIMPORT(rs::util::FBClear)
<commit_msg>インクルードパスの修正<commit_after>#pragma once
#include "screenrect.hpp"
#include "../updater.hpp"
#include "../glresource.hpp"

namespace rs {
	namespace util {
		class PostEffect : public DrawableObjT<PostEffect> {
			private:
				using base_t = DrawableObjT<PostEffect>;
				using ParamF = std::function<void (IEffect&)>;
				using ParamFV = std::vector<std::pair<IdValue, ParamF>>;
				IdValue			_idTech;
				ParamFV			_param;
				ScreenRect		_rect;

				void _applyParam(IEffect& e) const;
			public:
				PostEffect(IdValue idTech, Priority dprio);
				template <class T>
				void setParam(IdValue id, const T& t) {
					setParamFunc(id, [id,tv=t](auto& e){ e.setUniform(id, tv); });
				}
				void setParamFunc(IdValue id, const ParamF& f);
				void clearParam();
				void onDraw(IEffect& e) const override;
		};
		class FBSwitch : public DrawableObjT<FBSwitch> {
			private:
				HLFb			_hlFb;
				using ClearParam_OP = spn::Optional<draw::ClearParam>;
				ClearParam_OP	_cparam;
			public:
				FBSwitch(Priority dprio, HFb hFb, const ClearParam_OP& p=spn::none);
				void onDraw(IEffect& e) const override;
				void setClearParam(const ClearParam_OP& p);
		};
		class FBClear : public DrawableObjT<FBClear> {
			private:
				draw::ClearParam _param;
			public:
				FBClear(Priority dprio,
						const draw::ClearParam& p);
				void onDraw(IEffect& e) const override;
		};
	}
}
#include "../luaimport.hpp"
DEF_LUAIMPORT(rs::util::FBSwitch)
DEF_LUAIMPORT(rs::util::FBClear)
<|endoftext|>


<commit_before>/* Copyright 2014 Peter Goodman, all rights reserved. */

#define GRANARY_INTERNAL
#define GRANARY_ARCH_INTERNAL

#include "granary/base/string.h"

#include "granary/cfg/basic_block.h"
#include "granary/cfg/control_flow_graph.h"
#include "granary/cfg/instruction.h"

#include "granary/code/inline_assembly.h"

#include "granary/arch/x86-64/instruction.h"
#include "granary/arch/x86-64/select.h"

#include "granary/breakpoint.h"

namespace granary {

namespace arch {

// Categories of every iclass.
extern xed_category_enum_t ICLASS_CATEGORIES[];

// Number of implicit operands for each iclass.
extern const int NUM_IMPLICIT_OPERANDS[];

}  // namespace arch

namespace {

// Not very pretty, but implements a simple top-down parser for parsing
// Granary's inline assembly instructions.
class InlineAssemblyParser {
 public:
  InlineAssemblyParser(LocalControlFlowGraph *cfg_,
                       InlineAssemblyScope *scope_,
                       DecodedBasicBlock *block_,
                       Instruction *instr_,
                       const char *ch_)
      : op(nullptr),
        num_immediates(0),
        cfg(cfg_),
        scope(scope_),
        block(block_),
        instr(instr_),
        ch(ch_),
        branch_target(nullptr) {}

  // Parse the inline assembly as a sequence of instructions.
  void ParseInstructions(void) {
    char buff[20] = {'\0'};
    while (*ch) {
      ConsumeWhiteSpace();
      ParseWord(buff);
      if (buff[0]) {
        if (StringsMatch(buff, "LABEL")) {
          ParseLabel();
          Accept(':');
        } else {
          memset(&data, 0, sizeof data);
          auto iclass = str2xed_iclass_enum_t(buff);
          GRANARY_ASSERT(XED_ICLASS_INVALID != iclass);
          data.iclass = iclass;
          data.category = arch::ICLASS_CATEGORIES[iclass];
          op = &(data.ops[0]);
          num_immediates = 0;
          branch_target = nullptr;
          do {
            if (Peek(',')) {
              Accept(',');
            }
            ConsumeWhiteSpace();
          } while (ParseOperand());
          Accept(';');
          FinalizeInstruction();
        }
      }
    }
  }

 private:

  bool Peek(char next) {
    return *ch == next;
  }

  void Accept(char GRANARY_IF_DEBUG(next)) {
    GRANARY_ASSERT(Peek(next));
    ch++;
  }

  bool PeekWhitespace(void) {
    return ' ' == *ch || '\t' == *ch || '\n' == *ch;
  }

  void ConsumeWhiteSpace(void) {
    for (; *ch && PeekWhitespace(); ++ch) {}
  }

  void ParseWord(char *buff) {
    for (; *ch; ) {
      if (PeekWhitespace() || Peek(';') || Peek(',') || Peek(':')) {
        break;
      }
      *buff++ = *ch++;
    }
    *buff = '\0';
  }

  // Get a label.
  LabelInstruction *GetLabel(unsigned var_num)  {
    if (!scope->var_is_initialized.Get(var_num)) {
      scope->var_is_initialized.Set(var_num, true);
      scope->vars[var_num].label = new LabelInstruction();
    }
    return scope->vars[var_num].label;
  }

  void ParseLabel(void) {
    ConsumeWhiteSpace();
    auto var_num = ParseVar();
    auto label = GetLabel(var_num);
    instr->InsertBefore(std::unique_ptr<Instruction>(label));
  }

  int ParseNumber(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    int num = -1;
    GRANARY_IF_DEBUG( auto got = ) DeFormat(buff, "%d", &num);
    GRANARY_ASSERT(1 == got);
    return num;
  }

  unsigned ParseVar(void) {
    Accept('%');
    auto num = ParseNumber();
    GRANARY_ASSERT(0 <= num && MAX_NUM_INLINE_VARS > num);
    return static_cast<unsigned>(num);
  }

  int ParseWidth(void) {
    auto width = ParseNumber();
    GRANARY_ASSERT(8 == width || 16 == width || 32 == width || 64 == width);
    return width;
  }

  void ParseArchReg(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    auto reg = str2xed_reg_enum_t(buff);
    GRANARY_ASSERT(XED_REG_INVALID != reg);
    op->reg.DecodeFromNative(static_cast<int>(reg));
  }

  void ParseInPlaceOp(void) {
    auto var_num = ParseVar();
    GRANARY_ASSERT(scope->var_is_initialized.Get(var_num));
    auto &untyped_op(scope->vars[var_num].mem);  // Operand containers overlap.
    memcpy(op, untyped_op->Extract(), sizeof *op);
  }

  // TODO(pag): Only supports base form right now, i.e. `[%0]` and not the full
  //            `segment:[disp + base + index * scale]` form.
  void ParseMemoryOp(void) {
    Accept('[');
    ConsumeWhiteSpace();
    auto var_num = ParseVar();
    GRANARY_ASSERT(scope->var_is_initialized.Get(var_num));
    auto &reg_op(scope->vars[var_num].reg);
    op->type = XED_ENCODER_OPERAND_TYPE_MEM;
    op->reg = reg_op->Register();
    ConsumeWhiteSpace();
    Accept(']');
  }

  // Like labels, this will create/initialize a new reg op if it isn't already
  // initialized.
  void ParseRegOp(void) {
    auto var_num = ParseVar();
    auto &reg_op(scope->vars[var_num].reg);
    if (!scope->var_is_initialized.Get(var_num)) {
      op->type = XED_ENCODER_OPERAND_TYPE_REG;
      op->reg = block->AllocateVirtualRegister();
      reg_op->UnsafeReplace(op);
      scope->var_is_initialized.Set(var_num, true);
    } else {
      memcpy(op, reg_op->Extract(), sizeof *op);
    }
  }

  void ParseImmediate(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    auto negate = false;
    auto offset = 0;

    if (buff[0] == '-') {
      negate = true;
      offset = 1;
    }

    auto format = "%lu";
    if ('0' == buff[offset] &&
        ('x' == buff[offset + 1] || 'X' == buff[offset + 1])) {
      offset += 2;
      format = "%lx";
    }

    auto num = 0UL;
    GRANARY_IF_DEBUG( auto got = ) DeFormat(&(buff[offset]), format, &num);
    GRANARY_ASSERT(1 == got);

    if (!num_immediates) {
      op->type = negate ? XED_ENCODER_OPERAND_TYPE_SIMM0
                        : XED_ENCODER_OPERAND_TYPE_IMM0;
      num = negate ? static_cast<unsigned long>(-static_cast<long>(num)) : num;
      num_immediates++;
    } else {
      op->type = XED_ENCODER_OPERAND_TYPE_IMM1;

    }
    op->imm.as_uint = num;
  }

  // Parse an inline assembly operand.
  bool ParseOperand(void) {
    auto op_type = *ch++;
    if ('l' == op_type) {  // Handle labels as special cases.
      ConsumeWhiteSpace();
      branch_target = GetLabel(ParseVar());
      op->type = XED_ENCODER_OPERAND_TYPE_BRDISP;
      op->rw = XED_OPERAND_ACTION_R;
    } else if ('m' == op_type || 'i' == op_type || 'r' == op_type) {
      auto width = ParseWidth();
      ConsumeWhiteSpace();
      switch (op_type) {
        case 'm':  // Memory.
          if (Peek('%')) {
            ParseInPlaceOp();
          } else {
            ParseMemoryOp();
          }
          break;
        case 'i':  // Immediate.
          if (Peek('%')) {
            ParseInPlaceOp();
          } else {
            ParseImmediate();
          }
          break;
        case 'r':  // Register.
          if (Peek('%')) {
            ParseRegOp();
          } else {
            ParseArchReg();
          }
          op->reg.Widen(width / 8);
          break;
        default: break;
      }
      op->width = static_cast<decltype(op->width)>(width);
    } else {
      ch--;
      return false;
    }
    ++data.num_explicit_ops;
    ++op;
    return true;
  }

  // Fix-up the operands by matching the instruction to a specific instruction
  // selection, and then super-imposing the r/w actions of those operands onto
  // the assembled operands.
  void FixupOperands(void) {
    auto xedi = SelectInstruction(&data);
    GRANARY_ASSERT(nullptr != xedi);
    auto i = 0U;
    for (auto &instr_op : data.ops) {
      if (XED_ENCODER_OPERAND_TYPE_INVALID == instr_op.type) {
        break;
      } else {
        auto xedi_op = xed_inst_operand(xedi, i++);
        instr_op.rw = xed_operand_rw(xedi_op);
        instr_op.is_explicit = true;
      }
    }
  }

  // Finalize the instruction by adding it to the basic block's instruction
  // list.
  void FinalizeInstruction(void) {
    std::unique_ptr<Instruction> new_instr;
    FixupOperands();

    // Don't allow instructions the read or modify the stack pointer as this
    // will break invariants set up by early mangling about stack pointer
    // definedness.
    data.AnalyzeStackUsage();
    GRANARY_ASSERT(!data.ReadsFromStackPointer() &&
                   !data.WritesToStackPointer());

    if (data.IsJump()) {
      GRANARY_ASSERT(nullptr != branch_target);
      new_instr.reset(new BranchInstruction(&data, branch_target));
    } else if (data.IsFunctionCall()) {
      auto bb = new NativeBasicBlock(
          data.HasIndirectTarget() ? nullptr : data.BranchTargetPC());
      cfg->AddBlock(bb);
      new_instr.reset(new ControlFlowInstruction(&data, bb));
    } else if (data.IsFunctionReturn()) {
      auto bb = new ReturnBasicBlock(nullptr /* no meta-data */);
      cfg->AddBlock(bb);
      new_instr.reset(new ControlFlowInstruction(&data, bb));
    } else {
      new_instr.reset(new NativeInstruction(&data));
    }
    instr->InsertBefore(std::move(new_instr));
  }

  // Holds an in-progress instructions.
  arch::Instruction data;

  // The next operand to decode.
  arch::Operand *op;

  // The number of immediates already seen.
  int num_immediates;

  // The control-flow graph; used to materialize basic blocks.
  LocalControlFlowGraph *cfg;

  // Scope from which local/input variables can be looked up.
  InlineAssemblyScope * const scope;

  // Basic block into which instructions are being placed. Used to allocate
  // new virtual registers.
  DecodedBasicBlock * const block;

  // Instruction before which all assembly instructions will be placed.
  Instruction * const instr;

  // The next character to parse.
  const char *ch;

  // Label that is the target of this instruction, in the event that this
  // instruction is a branch.
  LabelInstruction *branch_target;
};
}  // namespace

// Compile this inline assembly into some instructions within the block
// `block`. This places the inlined instructions before `instr`, which is
// assumed to be the `AnnotationInstruction` containing the inline assembly
// instructions.
void CompileInlineAssemblyBlock(LocalControlFlowGraph *cfg,
                                DecodedBasicBlock *block,
                                Instruction *instr,
                                InlineAssemblyBlock *asm_block) {
  InlineAssemblyParser parser(cfg, asm_block->scope, block,
                              instr, asm_block->assembly);
  parser.ParseInstructions();
}

}  // namespace granary
<commit_msg>Added an extra check into the step 0 of assembly that compiles the inline assembly. The step is an early check that the direction flag is not modified by inline assembly. This check mirrors a similar check in step 5.<commit_after>/* Copyright 2014 Peter Goodman, all rights reserved. */

#define GRANARY_INTERNAL
#define GRANARY_ARCH_INTERNAL

#include "granary/base/string.h"

#include "granary/cfg/basic_block.h"
#include "granary/cfg/control_flow_graph.h"
#include "granary/cfg/instruction.h"

#include "granary/code/inline_assembly.h"

#include "granary/arch/x86-64/instruction.h"
#include "granary/arch/x86-64/select.h"

#include "granary/breakpoint.h"

namespace granary {

namespace arch {

// Categories of every iclass.
extern xed_category_enum_t ICLASS_CATEGORIES[];

// Number of implicit operands for each iclass.
extern const int NUM_IMPLICIT_OPERANDS[];

// Table mapping each iclass to the set of read and written flags by *any*
// selection of that iclass.
extern FlagsSet ICLASS_FLAGS[];

}  // namespace arch

namespace {

// Not very pretty, but implements a simple top-down parser for parsing
// Granary's inline assembly instructions.
class InlineAssemblyParser {
 public:
  InlineAssemblyParser(LocalControlFlowGraph *cfg_,
                       InlineAssemblyScope *scope_,
                       DecodedBasicBlock *block_,
                       Instruction *instr_,
                       const char *ch_)
      : op(nullptr),
        num_immediates(0),
        cfg(cfg_),
        scope(scope_),
        block(block_),
        instr(instr_),
        ch(ch_),
        branch_target(nullptr) {}

  // Parse the inline assembly as a sequence of instructions.
  void ParseInstructions(void) {
    char buff[20] = {'\0'};
    while (*ch) {
      ConsumeWhiteSpace();
      ParseWord(buff);
      if (buff[0]) {
        if (StringsMatch(buff, "LABEL")) {
          ParseLabel();
          Accept(':');
        } else {
          memset(&data, 0, sizeof data);
          auto iclass = str2xed_iclass_enum_t(buff);
          GRANARY_ASSERT(XED_ICLASS_INVALID != iclass);
          data.iclass = iclass;
          data.category = arch::ICLASS_CATEGORIES[iclass];
          op = &(data.ops[0]);
          num_immediates = 0;
          branch_target = nullptr;
          do {
            if (Peek(',')) {
              Accept(',');
            }
            ConsumeWhiteSpace();
          } while (ParseOperand());
          Accept(';');
          FinalizeInstruction();
        }
      }
    }
  }

 private:

  bool Peek(char next) {
    return *ch == next;
  }

  void Accept(char GRANARY_IF_DEBUG(next)) {
    GRANARY_ASSERT(Peek(next));
    ch++;
  }

  bool PeekWhitespace(void) {
    return ' ' == *ch || '\t' == *ch || '\n' == *ch;
  }

  void ConsumeWhiteSpace(void) {
    for (; *ch && PeekWhitespace(); ++ch) {}
  }

  void ParseWord(char *buff) {
    for (; *ch; ) {
      if (PeekWhitespace() || Peek(';') || Peek(',') || Peek(':')) {
        break;
      }
      *buff++ = *ch++;
    }
    *buff = '\0';
  }

  // Get a label.
  LabelInstruction *GetLabel(unsigned var_num)  {
    if (!scope->var_is_initialized.Get(var_num)) {
      scope->var_is_initialized.Set(var_num, true);
      scope->vars[var_num].label = new LabelInstruction();
    }
    return scope->vars[var_num].label;
  }

  void ParseLabel(void) {
    ConsumeWhiteSpace();
    auto var_num = ParseVar();
    auto label = GetLabel(var_num);
    instr->InsertBefore(std::unique_ptr<Instruction>(label));
  }

  int ParseNumber(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    int num = -1;
    GRANARY_IF_DEBUG( auto got = ) DeFormat(buff, "%d", &num);
    GRANARY_ASSERT(1 == got);
    return num;
  }

  unsigned ParseVar(void) {
    Accept('%');
    auto num = ParseNumber();
    GRANARY_ASSERT(0 <= num && MAX_NUM_INLINE_VARS > num);
    return static_cast<unsigned>(num);
  }

  int ParseWidth(void) {
    auto width = ParseNumber();
    GRANARY_ASSERT(8 == width || 16 == width || 32 == width || 64 == width);
    return width;
  }

  void ParseArchReg(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    auto reg = str2xed_reg_enum_t(buff);
    GRANARY_ASSERT(XED_REG_INVALID != reg);
    op->reg.DecodeFromNative(static_cast<int>(reg));
  }

  void ParseInPlaceOp(void) {
    auto var_num = ParseVar();
    GRANARY_ASSERT(scope->var_is_initialized.Get(var_num));
    auto &untyped_op(scope->vars[var_num].mem);  // Operand containers overlap.
    memcpy(op, untyped_op->Extract(), sizeof *op);
  }

  // TODO(pag): Only supports base form right now, i.e. `[%0]` and not the full
  //            `segment:[disp + base + index * scale]` form.
  void ParseMemoryOp(void) {
    Accept('[');
    ConsumeWhiteSpace();
    auto var_num = ParseVar();
    GRANARY_ASSERT(scope->var_is_initialized.Get(var_num));
    auto &reg_op(scope->vars[var_num].reg);
    op->type = XED_ENCODER_OPERAND_TYPE_MEM;
    op->reg = reg_op->Register();
    ConsumeWhiteSpace();
    Accept(']');
  }

  // Like labels, this will create/initialize a new reg op if it isn't already
  // initialized.
  void ParseRegOp(void) {
    auto var_num = ParseVar();
    auto &reg_op(scope->vars[var_num].reg);
    if (!scope->var_is_initialized.Get(var_num)) {
      op->type = XED_ENCODER_OPERAND_TYPE_REG;
      op->reg = block->AllocateVirtualRegister();
      reg_op->UnsafeReplace(op);
      scope->var_is_initialized.Set(var_num, true);
    } else {
      memcpy(op, reg_op->Extract(), sizeof *op);
    }
  }

  void ParseImmediate(void) {
    char buff[20] = {'\0'};
    ParseWord(buff);
    auto negate = false;
    auto offset = 0;

    if (buff[0] == '-') {
      negate = true;
      offset = 1;
    }

    auto format = "%lu";
    if ('0' == buff[offset] &&
        ('x' == buff[offset + 1] || 'X' == buff[offset + 1])) {
      offset += 2;
      format = "%lx";
    }

    auto num = 0UL;
    GRANARY_IF_DEBUG( auto got = ) DeFormat(&(buff[offset]), format, &num);
    GRANARY_ASSERT(1 == got);

    if (!num_immediates) {
      op->type = negate ? XED_ENCODER_OPERAND_TYPE_SIMM0
                        : XED_ENCODER_OPERAND_TYPE_IMM0;
      num = negate ? static_cast<unsigned long>(-static_cast<long>(num)) : num;
      num_immediates++;
    } else {
      op->type = XED_ENCODER_OPERAND_TYPE_IMM1;

    }
    op->imm.as_uint = num;
  }

  // Parse an inline assembly operand.
  bool ParseOperand(void) {
    auto op_type = *ch++;
    if ('l' == op_type) {  // Handle labels as special cases.
      ConsumeWhiteSpace();
      branch_target = GetLabel(ParseVar());
      op->type = XED_ENCODER_OPERAND_TYPE_BRDISP;
      op->rw = XED_OPERAND_ACTION_R;
    } else if ('m' == op_type || 'i' == op_type || 'r' == op_type) {
      auto width = ParseWidth();
      ConsumeWhiteSpace();
      switch (op_type) {
        case 'm':  // Memory.
          if (Peek('%')) {
            ParseInPlaceOp();
          } else {
            ParseMemoryOp();
          }
          break;
        case 'i':  // Immediate.
          if (Peek('%')) {
            ParseInPlaceOp();
          } else {
            ParseImmediate();
          }
          break;
        case 'r':  // Register.
          if (Peek('%')) {
            ParseRegOp();
          } else {
            ParseArchReg();
          }
          op->reg.Widen(width / 8);
          break;
        default: break;
      }
      op->width = static_cast<decltype(op->width)>(width);
    } else {
      ch--;
      return false;
    }
    ++data.num_explicit_ops;
    ++op;
    return true;
  }

  // Fix-up the operands by matching the instruction to a specific instruction
  // selection, and then super-imposing the r/w actions of those operands onto
  // the assembled operands.
  void FixupOperands(void) {
    auto xedi = SelectInstruction(&data);
    GRANARY_ASSERT(nullptr != xedi);
    auto i = 0U;
    for (auto &instr_op : data.ops) {
      if (XED_ENCODER_OPERAND_TYPE_INVALID == instr_op.type) {
        break;
      } else {
        auto xedi_op = xed_inst_operand(xedi, i++);
        instr_op.rw = xed_operand_rw(xedi_op);
        instr_op.is_explicit = true;
      }
    }
  }

  // Finalize the instruction by adding it to the basic block's instruction
  // list.
  void FinalizeInstruction(void) {
    std::unique_ptr<Instruction> new_instr;
    FixupOperands();

    // Don't allow instructions the read or modify the stack pointer as this
    // will break invariants set up by early mangling about stack pointer
    // definedness.
    data.AnalyzeStackUsage();
    GRANARY_ASSERT(!data.ReadsFromStackPointer() &&
                   !data.WritesToStackPointer());

    // Ensure that instrumentation instructions do not alter the direction
    // flag! This is because we have no reliable way of saving and restoring
    // the direction flag (lest we use `PUSHF` and `POPF`) when the stack
    // pointer is not known to be valid.
    GRANARY_IF_DEBUG( auto flags = arch::ICLASS_FLAGS[data.iclass]; )
    GRANARY_ASSERT(!flags.written.s.df);

    if (data.IsJump()) {
      GRANARY_ASSERT(nullptr != branch_target);
      new_instr.reset(new BranchInstruction(&data, branch_target));
    } else if (data.IsFunctionCall()) {
      auto bb = new NativeBasicBlock(
          data.HasIndirectTarget() ? nullptr : data.BranchTargetPC());
      cfg->AddBlock(bb);
      new_instr.reset(new ControlFlowInstruction(&data, bb));
    } else if (data.IsFunctionReturn()) {
      auto bb = new ReturnBasicBlock(nullptr /* no meta-data */);
      cfg->AddBlock(bb);
      new_instr.reset(new ControlFlowInstruction(&data, bb));
    } else {
      new_instr.reset(new NativeInstruction(&data));
    }
    instr->InsertBefore(std::move(new_instr));
  }

  // Holds an in-progress instructions.
  arch::Instruction data;

  // The next operand to decode.
  arch::Operand *op;

  // The number of immediates already seen.
  int num_immediates;

  // The control-flow graph; used to materialize basic blocks.
  LocalControlFlowGraph *cfg;

  // Scope from which local/input variables can be looked up.
  InlineAssemblyScope * const scope;

  // Basic block into which instructions are being placed. Used to allocate
  // new virtual registers.
  DecodedBasicBlock * const block;

  // Instruction before which all assembly instructions will be placed.
  Instruction * const instr;

  // The next character to parse.
  const char *ch;

  // Label that is the target of this instruction, in the event that this
  // instruction is a branch.
  LabelInstruction *branch_target;
};
}  // namespace

// Compile this inline assembly into some instructions within the block
// `block`. This places the inlined instructions before `instr`, which is
// assumed to be the `AnnotationInstruction` containing the inline assembly
// instructions.
void CompileInlineAssemblyBlock(LocalControlFlowGraph *cfg,
                                DecodedBasicBlock *block,
                                Instruction *instr,
                                InlineAssemblyBlock *asm_block) {
  InlineAssemblyParser parser(cfg, asm_block->scope, block,
                              instr, asm_block->assembly);
  parser.ParseInstructions();
}

}  // namespace granary
<|endoftext|>


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

// mapnik
#include <mapnik/json/extract_bounding_box_grammar.hpp>
#include <mapnik/geometry_fusion_adapted.hpp>
// boost
#include <boost/spirit/include/qi_omit.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
// stl
#include <iostream>
#include <string>

namespace mapnik { namespace json {

struct calculate_bounding_box_impl
{
    using result_type = void;
    template <typename T0, typename T1>
    result_type operator() (T0 & bbox, T1 const& pos) const
    {
        if (pos)
        {
            typename T0::value_type x = pos->x;
            typename T0::value_type y = pos->y;
            if (!bbox.valid())
            {
                bbox.init(x, y);
            }
            else
            {
                bbox.expand_to_include(x, y);
            }
        }
    }
};

struct push_box_impl
{
    using result_type = void;
    template <typename T0, typename T1, typename T2, typename T3>
    void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
    {
        if (box.valid()) boxes.emplace_back(box,
                                            std::make_pair(std::distance(begin,
                                                                         range.begin()),
                                                           std::distance(range.begin(), range.end())));
    }
};

namespace repo = boost::spirit::repository;

template <typename Iterator, typename Boxes, typename ErrorHandler>
extract_bounding_box_grammar<Iterator, Boxes, ErrorHandler>::extract_bounding_box_grammar()
    : extract_bounding_box_grammar::base_type(start, "GeoJSON bounding boxes")
{
    qi::lit_type lit;
    qi::double_type double_;
    qi::_val_type _val;
    qi::_1_type _1;
    qi::_2_type _2;
    qi::_3_type _3;
    qi::_4_type _4;
    qi::omit_type omit;
    qi::_r1_type _r1;
    qi::_r2_type _r2;
    qi::_a_type _a;
    qi::_b_type _b;
    qi::eps_type eps;
    qi::raw_type raw;
    qi::char_type char_;
    qi::no_skip_type no_skip;
    boost::spirit::repository::qi::iter_pos_type iter_pos;
    using qi::fail;
    using qi::on_error;

    // phoenix functions
    boost::phoenix::function<push_box_impl> push_box;
    boost::phoenix::function<calculate_bounding_box_impl> calculate_bounding_box;
    // error handler
    boost::phoenix::function<ErrorHandler> const error_handler;

    start = features(_r1)
        ;

    features = no_skip[iter_pos[_a = _1]] >> -(lit('{')
                                               >> *((json.key_value - lit("\"features\"")) >> lit(','))
                                               >> lit("\"features\"")
                                               >> lit(':'))
                                          >> lit('[') >> (feature(_r1,_a) % lit(',')) >> lit(']')
        ;

    feature = raw[lit('{')[_a = 1]
                  >> *(eps(_a > 0) >> (
                           lit("\"FeatureCollection\"") > eps(false) // fail if nested FeatureCollection
                           |
                           lit('{')[_a += 1]
                           |
                           lit('}')[_a -= 1]
                           |
                           coords[_b = _1]
                           |
                           json.string_
                           |
                           char_))][push_box(_r1, _r2, _b, _1)]
        ;

    coords = lit("\"coordinates\"")
        >> lit(':') >> (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a]
        ;

    pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']')
        ;

    ring = lit('[') >> pos[calculate_bounding_box(_r1,_1)] % lit(',') > lit(']')
        ;

    rings = lit('[') >> ring(_r1)  % lit(',') > lit(']')
        ;

    rings_array = lit('[') >> rings(_r1) % lit(',') > lit(']')
        ;

    // generic json types
    json.value = json.object | json.array | json.string_ | json.number
        ;

    json.key_value = json.string_ >> lit(':') >> json.value
        ;

    json.object = lit('{') >>  json.key_value % lit(',') >> lit('}')
        ;

    json.array = lit('[')
        >> json.value >> *(lit(',') >> json.value)
        >> lit(']')
        ;

    json.number = json.strict_double
        | json.int__
        | lit("true")
        | lit("false")
        | lit("null")
        ;

    coords.name("Coordinates");
    pos.name("Position");
    ring.name("Ring");
    rings.name("Rings");
    rings_array.name("Rings array");

    // error handler
    on_error<fail>(coords, error_handler(_1, _2, _3, _4));
}

}}
<commit_msg>extract_bounding_box_grammar - make features optional / ref #3463<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2015 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// mapnik
#include <mapnik/json/extract_bounding_box_grammar.hpp>
#include <mapnik/geometry_fusion_adapted.hpp>
// boost
#include <boost/spirit/include/qi_omit.hpp>
#include <boost/spirit/include/phoenix_object.hpp>
#include <boost/spirit/include/phoenix_stl.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/spirit/repository/include/qi_iter_pos.hpp>
#include <boost/spirit/include/phoenix_function.hpp>
// stl
#include <iostream>
#include <string>

namespace mapnik { namespace json {

struct calculate_bounding_box_impl
{
    using result_type = void;
    template <typename T0, typename T1>
    result_type operator() (T0 & bbox, T1 const& pos) const
    {
        if (pos)
        {
            typename T0::value_type x = pos->x;
            typename T0::value_type y = pos->y;
            if (!bbox.valid())
            {
                bbox.init(x, y);
            }
            else
            {
                bbox.expand_to_include(x, y);
            }
        }
    }
};

struct push_box_impl
{
    using result_type = void;
    template <typename T0, typename T1, typename T2, typename T3>
    void operator() (T0 & boxes, T1 const& begin, T2 const& box, T3 const& range) const
    {
        if (box.valid()) boxes.emplace_back(box,
                                            std::make_pair(std::distance(begin,
                                                                         range.begin()),
                                                           std::distance(range.begin(), range.end())));
    }
};

namespace repo = boost::spirit::repository;

template <typename Iterator, typename Boxes, typename ErrorHandler>
extract_bounding_box_grammar<Iterator, Boxes, ErrorHandler>::extract_bounding_box_grammar()
    : extract_bounding_box_grammar::base_type(start, "GeoJSON bounding boxes")
{
    qi::lit_type lit;
    qi::double_type double_;
    qi::_val_type _val;
    qi::_1_type _1;
    qi::_2_type _2;
    qi::_3_type _3;
    qi::_4_type _4;
    qi::omit_type omit;
    qi::_r1_type _r1;
    qi::_r2_type _r2;
    qi::_a_type _a;
    qi::_b_type _b;
    qi::eps_type eps;
    qi::raw_type raw;
    qi::char_type char_;
    qi::no_skip_type no_skip;
    boost::spirit::repository::qi::iter_pos_type iter_pos;
    using qi::fail;
    using qi::on_error;

    // phoenix functions
    boost::phoenix::function<push_box_impl> push_box;
    boost::phoenix::function<calculate_bounding_box_impl> calculate_bounding_box;
    // error handler
    boost::phoenix::function<ErrorHandler> const error_handler;

    start = features(_r1)
        ;

    features = no_skip[iter_pos[_a = _1]] >> -(lit('{')
                                               >> *((json.key_value - lit("\"features\"")) >> lit(','))
                                               >> lit("\"features\"")
                                               >> lit(':'))
                                          >> lit('[') >> -(feature(_r1,_a) % lit(',')) >> lit(']')
        ;

    feature = raw[lit('{')[_a = 1]
                  >> *(eps(_a > 0) >> (
                           lit("\"FeatureCollection\"") > eps(false) // fail if nested FeatureCollection
                           |
                           lit('{')[_a += 1]
                           |
                           lit('}')[_a -= 1]
                           |
                           coords[_b = _1]
                           |
                           json.string_
                           |
                           char_))][push_box(_r1, _r2, _b, _1)]
        ;

    coords = lit("\"coordinates\"")
        >> lit(':') >> (rings_array(_a) | rings (_a) | ring(_a) | pos[calculate_bounding_box(_a,_1)])[_val = _a]
        ;

    pos = lit('[') > -(double_ > lit(',') > double_) > omit[*(lit(',') > double_)] > lit(']')
        ;

    ring = lit('[') >> pos[calculate_bounding_box(_r1,_1)] % lit(',') > lit(']')
        ;

    rings = lit('[') >> ring(_r1)  % lit(',') > lit(']')
        ;

    rings_array = lit('[') >> rings(_r1) % lit(',') > lit(']')
        ;

    // generic json types
    json.value = json.object | json.array | json.string_ | json.number
        ;

    json.key_value = json.string_ >> lit(':') >> json.value
        ;

    json.object = lit('{') >>  json.key_value % lit(',') >> lit('}')
        ;

    json.array = lit('[')
        >> json.value >> *(lit(',') >> json.value)
        >> lit(']')
        ;

    json.number = json.strict_double
        | json.int__
        | lit("true")
        | lit("false")
        | lit("null")
        ;

    coords.name("Coordinates");
    pos.name("Position");
    ring.name("Ring");
    rings.name("Rings");
    rings_array.name("Rings array");

    // error handler
    on_error<fail>(coords, error_handler(_1, _2, _3, _4));
}

}}
<|endoftext|>


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

#ifndef RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP
#define RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP

#include <rectojump/core/game_window.hpp>
#include <rectojump/core/render.hpp>
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/components/star5.hpp>
#include <rectojump/game/components/triangles4.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>

#include <mlk/time/simple_timer.h>
#include <mlk/tools/random_utl.h>

namespace rj
{
	template<typename Main_Menu>
	class background_main_menu
	{
		Main_Menu& m_mainmenu;
		background_manager& m_backgroundmgr;

		sf::Texture m_sides_tx;
		const sf::Color& m_fillcolor;
		mlk::tm::simple_timer m_timer{300};

	public:
		background_main_menu(Main_Menu& mm) :
			m_mainmenu{mm},
			m_backgroundmgr{mm.get_gamehandler().get_backgroundmgr()},
			m_sides_tx{mm.get_gamehandler().get_datamgr().template get_as<sf::Texture>("menu_side.png")},
			m_fillcolor{mm.get_act_fontcolor()}
		{this->init();}

		void update(dur duration)
		{
			this->update_bg_objs(duration);
		}

		void update_bg_objs(dur duration) noexcept
		{
			if(m_timer.timed_out())
			{
				auto size(settings::get_window_size<vec2f>());
				auto pos_x(mlk::rnd(0.f, size.x));
				auto length(mlk::rnd(30.f, 60.f));
				auto rotatestep(mlk::rnd(-0.1f, 0.5f));
				vec2f movestep{mlk::rnd(-0.1f, 0.5f), mlk::rnd(0.05f, 0.5f)};

				auto object_type(mlk::rnd(0, 1));

				if(object_type)
				{
					auto ptr(m_backgroundmgr.create_object<star5>(vec2f{pos_x, 0.f}, vec2f{0.f, length}, 5000, rotatestep, movestep));
					ptr->render_object().setFillColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
				}
				else
				{
//					auto ptr(m_backgroundmgr.create_object<sf::RectangleShape>(vec2f{pos_x, 0.f}, vec2f{50.f, 50.f}, 5000, rotatestep, movestep));
//					ptr->render_object().setFillColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
//					ptr->render_object().setOrigin(ptr->render_object().getSize() / 2.f);
//					m_timer.restart(mlk::rnd<mlk::ullong>(100, 300));

					auto ptr(m_backgroundmgr.create_object<triangles4>(vec2f{pos_x, 0.f}, vec2f{15.5f, 30.f}, 5000, rotatestep, movestep));
					ptr->render_object().setColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
//					ptr->render_object().setOrigin(ptr->render_object().getSize() / 2.f);
				}
				m_timer.restart(static_cast<mlk::ullong>(mlk::rnd<mlk::ullong>(100, 300) / duration));
			}
		}

		void render()
		{ }

	private:
		void init()
		{
			auto size(settings::get_window_size<vec2f>());

			// nova
			auto triangles(m_backgroundmgr.create_object<triangles4>(vec2f{size.x / 2.f, size.y}, vec2f{200.f, 900.f}, 0, 0.1f, vec2f{0.f, 0.f}));
			triangles->render_object().setColor(to_rgb("#bdbdbd", 100));

			// background
			sf::RectangleShape tx_shape{size};
			tx_shape.setTexture(&m_sides_tx);
			m_backgroundmgr.set_tx_shape(tx_shape);
			m_backgroundmgr.set_bg_shape({size, to_rgb("#e3e3e3"), to_rgb("#e3e3e3"), 1});

			// timer
			m_timer.run();
		}
	};
}

#endif // RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP
<commit_msg>background_main_menu: fixed nova size<commit_after>//
// Copyright (c) 2013-2014 Christoph Malek
// See LICENSE for more information.
//

#ifndef RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP
#define RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP

#include <rectojump/core/game_window.hpp>
#include <rectojump/core/render.hpp>
#include <rectojump/game/background/background_manager.hpp>
#include <rectojump/game/components/star5.hpp>
#include <rectojump/game/components/triangles4.hpp>
#include <rectojump/global/config_settings.hpp>
#include <rectojump/shared/data_manager.hpp>
#include <rectojump/shared/utils.hpp>

#include <mlk/time/simple_timer.h>
#include <mlk/tools/random_utl.h>

namespace rj
{
	template<typename Main_Menu>
	class background_main_menu
	{
		Main_Menu& m_mainmenu;
		background_manager& m_backgroundmgr;

		sf::Texture m_sides_tx;
		const sf::Color& m_fillcolor;
		mlk::tm::simple_timer m_timer{300};

	public:
		background_main_menu(Main_Menu& mm) :
			m_mainmenu{mm},
			m_backgroundmgr{mm.get_gamehandler().get_backgroundmgr()},
			m_sides_tx{mm.get_gamehandler().get_datamgr().template get_as<sf::Texture>("menu_side.png")},
			m_fillcolor{mm.get_act_fontcolor()}
		{this->init();}

		void update(dur duration)
		{
			this->update_bg_objs(duration);
		}

		void update_bg_objs(dur duration) noexcept
		{
			if(m_timer.timed_out())
			{
				auto size(settings::get_window_size<vec2f>());
				auto pos_x(mlk::rnd(0.f, size.x));
				auto length(mlk::rnd(30.f, 60.f));
				auto rotatestep(mlk::rnd(-0.1f, 0.5f));
				vec2f movestep{mlk::rnd(-0.1f, 0.5f), mlk::rnd(0.05f, 0.5f)};

				auto object_type(mlk::rnd(0, 1));

				if(object_type)
				{
					auto ptr(m_backgroundmgr.create_object<star5>(vec2f{pos_x, 0.f}, vec2f{0.f, length}, 5000, rotatestep, movestep));
					ptr->render_object().setFillColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
				}
				else
				{
//					auto ptr(m_backgroundmgr.create_object<sf::RectangleShape>(vec2f{pos_x, 0.f}, vec2f{50.f, 50.f}, 5000, rotatestep, movestep));
//					ptr->render_object().setFillColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
//					ptr->render_object().setOrigin(ptr->render_object().getSize() / 2.f);
//					m_timer.restart(mlk::rnd<mlk::ullong>(100, 300));

					auto ptr(m_backgroundmgr.create_object<triangles4>(vec2f{pos_x, 0.f}, vec2f{15.5f, 30.f}, 5000, rotatestep, movestep));
					ptr->render_object().setColor({m_fillcolor.r, m_fillcolor.g, m_fillcolor.b, 100});
//					ptr->render_object().setOrigin(ptr->render_object().getSize() / 2.f);
				}
				m_timer.restart(static_cast<mlk::ullong>(mlk::rnd<mlk::ullong>(100, 300) / duration));
			}
		}

		void render()
		{ }

	private:
		void init()
		{
			auto window_size(settings::get_window_size<vec2f>());

			// nova
			auto nova(m_backgroundmgr.create_object<triangles4>(vec2f{window_size.x / 2.f, window_size.y}, vec2f{window_size.y / 3.f, window_size.x}, 0, 0.1f, vec2f{0.f, 0.f}));
			nova->render_object().setColor(to_rgb("#bdbdbd", 100));

			// background
			sf::RectangleShape tx_shape{window_size};
			tx_shape.setTexture(&m_sides_tx);
			m_backgroundmgr.set_tx_shape(tx_shape);
			m_backgroundmgr.set_bg_shape({window_size, to_rgb("#e3e3e3"), to_rgb("#e3e3e3"), 1});

			// timer
			m_timer.run();
		}
	};
}

#endif // RJ_GAME_MAIN_MENU_BACKGROUND_MAIN_MENU_HPP
<|endoftext|>


<commit_before>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "mysqlbrowser.h"
#include "Log.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <stdarg.h>
#include <mysql/mysql.h>

MySQLBrowser::MySQLBrowser(const char* username, const char* password, const char* database, const char* hostname):
	_username(NULL),
	_password(NULL),
	_database(NULL),
	_hostname(NULL),
	_conn(NULL),
	_fields(NULL),
	_nr_of_fields(0),
	_current_field(0){

	set_username(username);
	set_password(password);
	set_database(database);
	set_hostname(hostname);

	connect();
}

MySQLBrowser::~MySQLBrowser(){
	disconnect();

	clear_fields();

	free(_username);
	free(_password);
	free(_database);
	free(_hostname);
}

const char* MySQLBrowser::get_next_file(){
	return get_field(_current_field++);;
}

void MySQLBrowser::set_username(const char* username){
	free(_username);
	assert( username && "Must supply a mysql username using the --db_user flag" );
	_username = (char*)malloc( strlen(username) + 1 );
	strcpy( _username, username);
}

void MySQLBrowser::set_password(const char* password){
	free(_password);
	assert( password && "Must supply a mysql password using the --db_pass flag" );
	_password = (char*)malloc( strlen(password) + 1 );
	strcpy( _password, password);
}

void MySQLBrowser::set_database(const char* database){
	free(_database);
	assert( database && "Must supply a mysql database using the --db_name flag" );
	_database = (char*)malloc( strlen(database) + 1 );
	strcpy( _database, database);
}

void MySQLBrowser::set_hostname(const char* hostname){
	free(_hostname);
	assert( hostname );
	_hostname = (char*)malloc( strlen(hostname) + 1 );
	strcpy( _hostname, hostname);
}

void MySQLBrowser::connect(){
	_conn = mysql_init(NULL);

	if (!mysql_real_connect(_conn, _hostname, _username, _password, _database, 0, NULL, 0)) {
		Log::message(Log::Fatal, "MySQLBrowser: Could not connect to database: %s\n", mysql_error(_conn));
		exit(2);
	}
}

void MySQLBrowser::disconnect(){
	mysql_close(_conn);
}

struct st_mysql_res* MySQLBrowser::query(const char* str, ...){
	va_list arg;
	va_start(arg, str);

	char* query_str;
	vasprintf(&query_str, str, arg);

	if ( mysql_query(_conn, query_str) != 0 ) {
		Log::message(Log::Warning, "MySQLBrowser: Could not execute query '%s': %s\n", query_str, mysql_error(_conn));
	}

	free(query_str);

	va_end(arg);

	return mysql_store_result(_conn);
}

void MySQLBrowser::reload(){
	clear_fields();

	MYSQL_RES *res = query("SELECT fullpath FROM files WHERE bin_id = %d AND active = true ORDER BY id", current_bin());
	MYSQL_ROW row;

	_nr_of_fields = mysql_num_rows(res);

	allocate_fields( _nr_of_fields + 1 ); // The last field is set to NULL

	unsigned int i;
	for ( i = 0; i < _nr_of_fields; i++ ){
		row = mysql_fetch_row(res);
		assert(row);

		set_field(i, row[0]);
	}
	set_field(i, NULL);

	mysql_free_result(res);
}

void MySQLBrowser::clear_fields(){
	if ( !_fields ){
		return;
	}

	unsigned int index = 0;

	while ( _fields[index] ){
		free(_fields[index]);
		_fields[index] = NULL;

		index++;
	}

	free(_fields);
	_fields = NULL;
}

void MySQLBrowser::allocate_fields(unsigned int n){
	_fields = (char**)malloc( sizeof(char*) * n );

	for ( unsigned int i = 0; i < 0; i++ ){
		_fields[i] = NULL;
	}
}

void MySQLBrowser::set_field(unsigned int n, const char* str){
	if ( !str ){
		_fields[n] = NULL;
		return;
	}

	_fields[n] = (char*)malloc( strlen(str)+1);
	strcpy( _fields[n], str );
}

const char* MySQLBrowser::get_field(unsigned int n){
	if ( _nr_of_fields == 0 ){
		return NULL;
	}

	return _fields[n % _nr_of_fields];
}

void MySQLBrowser::dump_queue(){
	Log::message(Log::Debug, "MySQLBrowser: Dumping queue\n");

	unsigned int index = 0;

	while ( _fields[index] ){
		Log::message(Log::Debug, "  %s\n", _fields[index++]);
	}
}
<commit_msg>Daemon must order by sortorder to maintain same order as frontend<commit_after>/**
 * This file is part of Slideshow.
 * Copyright (C) 2008 David Sveningsson <ext@sidvind.com>
 *
 * Slideshow is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * Slideshow 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 Slideshow.  If not, see <http://www.gnu.org/licenses/>.
 */

#include "mysqlbrowser.h"
#include "Log.h"
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <stdarg.h>
#include <mysql/mysql.h>

MySQLBrowser::MySQLBrowser(const char* username, const char* password, const char* database, const char* hostname):
	_username(NULL),
	_password(NULL),
	_database(NULL),
	_hostname(NULL),
	_conn(NULL),
	_fields(NULL),
	_nr_of_fields(0),
	_current_field(0){

	set_username(username);
	set_password(password);
	set_database(database);
	set_hostname(hostname);

	connect();
}

MySQLBrowser::~MySQLBrowser(){
	disconnect();

	clear_fields();

	free(_username);
	free(_password);
	free(_database);
	free(_hostname);
}

const char* MySQLBrowser::get_next_file(){
	return get_field(_current_field++);;
}

void MySQLBrowser::set_username(const char* username){
	free(_username);
	assert( username && "Must supply a mysql username using the --db_user flag" );
	_username = (char*)malloc( strlen(username) + 1 );
	strcpy( _username, username);
}

void MySQLBrowser::set_password(const char* password){
	free(_password);
	assert( password && "Must supply a mysql password using the --db_pass flag" );
	_password = (char*)malloc( strlen(password) + 1 );
	strcpy( _password, password);
}

void MySQLBrowser::set_database(const char* database){
	free(_database);
	assert( database && "Must supply a mysql database using the --db_name flag" );
	_database = (char*)malloc( strlen(database) + 1 );
	strcpy( _database, database);
}

void MySQLBrowser::set_hostname(const char* hostname){
	free(_hostname);
	assert( hostname );
	_hostname = (char*)malloc( strlen(hostname) + 1 );
	strcpy( _hostname, hostname);
}

void MySQLBrowser::connect(){
	_conn = mysql_init(NULL);

	if (!mysql_real_connect(_conn, _hostname, _username, _password, _database, 0, NULL, 0)) {
		Log::message(Log::Fatal, "MySQLBrowser: Could not connect to database: %s\n", mysql_error(_conn));
		exit(2);
	}
}

void MySQLBrowser::disconnect(){
	mysql_close(_conn);
}

struct st_mysql_res* MySQLBrowser::query(const char* str, ...){
	va_list arg;
	va_start(arg, str);

	char* query_str;
	vasprintf(&query_str, str, arg);

	if ( mysql_query(_conn, query_str) != 0 ) {
		Log::message(Log::Warning, "MySQLBrowser: Could not execute query '%s': %s\n", query_str, mysql_error(_conn));
	}

	free(query_str);

	va_end(arg);

	return mysql_store_result(_conn);
}

void MySQLBrowser::reload(){
	clear_fields();

	MYSQL_RES *res = query("SELECT fullpath FROM files WHERE bin_id = %d AND active = true ORDER BY sortorder, id", current_bin());
	MYSQL_ROW row;

	_nr_of_fields = mysql_num_rows(res);

	allocate_fields( _nr_of_fields + 1 ); // The last field is set to NULL

	unsigned int i;
	for ( i = 0; i < _nr_of_fields; i++ ){
		row = mysql_fetch_row(res);
		assert(row);

		set_field(i, row[0]);
	}
	set_field(i, NULL);

	mysql_free_result(res);
}

void MySQLBrowser::clear_fields(){
	if ( !_fields ){
		return;
	}

	unsigned int index = 0;

	while ( _fields[index] ){
		free(_fields[index]);
		_fields[index] = NULL;

		index++;
	}

	free(_fields);
	_fields = NULL;
}

void MySQLBrowser::allocate_fields(unsigned int n){
	_fields = (char**)malloc( sizeof(char*) * n );

	for ( unsigned int i = 0; i < 0; i++ ){
		_fields[i] = NULL;
	}
}

void MySQLBrowser::set_field(unsigned int n, const char* str){
	if ( !str ){
		_fields[n] = NULL;
		return;
	}

	_fields[n] = (char*)malloc( strlen(str)+1);
	strcpy( _fields[n], str );
}

const char* MySQLBrowser::get_field(unsigned int n){
	if ( _nr_of_fields == 0 ){
		return NULL;
	}

	return _fields[n % _nr_of_fields];
}

void MySQLBrowser::dump_queue(){
	Log::message(Log::Debug, "MySQLBrowser: Dumping queue\n");

	unsigned int index = 0;

	while ( _fields[index] ){
		Log::message(Log::Debug, "  %s\n", _fields[index++]);
	}
}
<|endoftext|>


<commit_before>// fastmap.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"
#include <map>
#include <string>

BZ_GET_PLUGIN_VERSION

class FastMapEventHandler;

class FastMapClient : public bz_NonPlayerConnectionHandler
{
public:
  FastMapClient( int connectionID = -1, FastMapEventHandler *h = NULL);
  virtual ~FastMapClient();
  virtual void pending ( int connectionID, void *d, unsigned int s );
  virtual void disconnect ( int connectionID );

  void startTransfer ( unsigned char * d, unsigned int s );
  bool updateTransfer ( void );

  int conID;

  unsigned char *data;
  unsigned int size;
  unsigned int currerntPos;

  std::string command;

  FastMapEventHandler* handler;
};

class FastMapEventHandler : public bz_EventHandler
{
public:
  FastMapEventHandler();
  virtual ~FastMapEventHandler();

  virtual void process ( bz_EventData *eventData );

  void updateHTTPServer ( void );
  void killHTTPServer ( void );

  std::string	mapName;

  std::map<int,FastMapClient*> clients;

  unsigned char* mapData;
  unsigned int mapDataSize;
};

FastMapEventHandler fastMapEventHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* /*commandLine*/ )
{
  bz_debugMessage(4,"fastmap plugin loaded");
  bz_registerEvent (bz_eWorldFinalized,&fastMapEventHandler);
  bz_registerEvent (bz_eTickEvent,&fastMapEventHandler);
  bz_registerEvent (bz_eListServerUpdateEvent,&fastMapEventHandler);
  bz_registerEvent (bz_eNewNonPlayerConnection,&fastMapEventHandler);
return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
  fastMapEventHandler.killHTTPServer();

  bz_debugMessage(4,"fastmap plugin unloaded");
  bz_removeEvent (bz_eWorldFinalized,&fastMapEventHandler);
  bz_removeEvent (bz_eTickEvent,&fastMapEventHandler);
  bz_removeEvent (bz_eListServerUpdateEvent,&fastMapEventHandler);
  bz_removeEvent (bz_eNewNonPlayerConnection,&fastMapEventHandler);
return 0;
}

FastMapEventHandler::FastMapEventHandler()
{
  mapName = format("PrivateMap%d",(unsigned int)this);

  mapData = NULL;
  mapDataSize = 0;
}

FastMapEventHandler::~FastMapEventHandler()
{
  killHTTPServer();
}

void FastMapEventHandler::process ( bz_EventData *eventData )
{
  if ( eventData->eventType == bz_eListServerUpdateEvent )
  {
    bz_ListServerUpdateEvent_V1 *updateData = (bz_ListServerUpdateEvent_V1*)eventData;
    mapName = format("%s%d",updateData->address,(unsigned int)this);
  }
  else if ( eventData->eventType == bz_eWorldFinalized )
  {
    killHTTPServer();

    if (!bz_getPublic() || bz_getClientWorldDowloadURL().size())
      return;

    mapDataSize = bz_getWorldCacheSize();
    mapData = (unsigned char*)malloc(mapDataSize);
    bz_getWorldCacheData(mapData);

    if (mapDataSize)
      bz_setClientWorldDowloadURL(format("HTTP:/%s/%s",bz_getPublicAddr().c_str(),mapName.c_str()).c_str());
  }
  else if ( eventData->eventType == bz_eTickEvent)
  {
    if ( mapDataSize )
      updateHTTPServer();
  }
  else if ( eventData->eventType == bz_eNewNonPlayerConnection )
  {
    if ( mapDataSize )
    {
      bz_NewNonPlayerConnectionEventData_V1 *connData = (bz_NewNonPlayerConnectionEventData_V1*)eventData;
      if (connData->size >= 3 && strncmp((const char*)connData->data,"GET",3))
      {
	FastMapClient * handler = new FastMapClient(connData->connectionID,this);

	if(bz_registerNonPlayerConnectionHandler ( connData->connectionID, handler ) )
	{
	  clients[connData->connectionID] = handler;
	  handler->pending (connData->connectionID,connData->data, connData->size);
	}
	else
	  delete(handler);
      }
    }
  }
  else if ( eventData->eventType == bz_eIdleNewNonPlayerConnection )
  {
    bz_NewNonPlayerConnectionEventData_V1 *connData = (bz_NewNonPlayerConnectionEventData_V1*)eventData;

    std::map<int,FastMapClient*>::iterator itr = clients.find(connData->connectionID);
    if( itr != clients.end() )
    {
      bz_removeNonPlayerConnectionHandler ( itr->second->conID, itr->second );
      delete(itr->second);
      clients.erase(itr);
    }
    bz_disconectNonPlayerConnection ( connData->connectionID );
 }
}

void FastMapEventHandler::updateHTTPServer ( void )
{
  std::vector<int> killList;

  std::map<int,FastMapClient*>::iterator itr = clients.begin();
  while (itr != clients.end())
  {
    if(itr->second->conID == -1 || !itr->second->updateTransfer() )
      killList.push_back(itr->first);
    itr++;
  }

  for ( unsigned int i = 0; i < (unsigned int)killList.size(); i++)
    clients.erase(clients.find(killList[i]));

  if (clients.size())
    bz_setMaxWaitTime(0.001f);
  else
    bz_setMaxWaitTime(2.0f);
}

void FastMapEventHandler::killHTTPServer ( void )
{
  if ( mapData )
    free(mapData);

  mapData = NULL;
  mapDataSize = 0;
}

FastMapClient::FastMapClient( int connectionID, FastMapEventHandler *h )
{
  conID = connectionID;

  data = NULL;
  size = 0;
  currerntPos = 0;
  handler = h;
}

FastMapClient::~FastMapClient()
{
  if (data)
    free(data);
}

void FastMapClient::pending ( int connectionID, void *s, unsigned int d )
{
  if ( connectionID != conID )
    return;

  char *c = (char*)malloc(d+1);
  memcpy(c,s,d);
  c[d] = 0;
  command += c;
  free (c);

  // parse the command
  std::vector<std::string> commandList = tokenize(command,std::string("\r\n"),0,false);

  if ( commandList.size() == 1 && commandList[0].size() == command.size() ) // there were no delims, we are done.
    return;

  for (unsigned int i = 0; i < (unsigned int)commandList.size();i++)
  {
    command.erase(command.begin(),command.begin()+commandList[i].size());

    std::string thisLine = commandList[i];

    if (strncmp(thisLine.c_str(),"GET",3) == 0 && !data) // it's a get and we arn't in a transfer
    {
      std::vector<std::string> params = tokenize(thisLine,std::string(" "),0,false);
      if ( params.size() <= 3 )
      {
	std::string urlPath = params[1];

	if (urlPath.size()>2 && handler->mapName == urlPath.c_str()+1 )
	{
	  startTransfer(handler->mapData,handler->mapDataSize);
	}
      }
    }
  }
}

void FastMapClient::disconnect ( int connectionID )
{
  if (connectionID != conID)
    return;

  bz_removeNonPlayerConnectionHandler ( conID, this );
  bz_disconectNonPlayerConnection ( conID );
  conID = -1;

}
void FastMapClient::startTransfer ( unsigned char * d, unsigned int s )
{
  if (data)
    free (data);
  data = NULL;
  size = 0;
  currerntPos = 0;

  if (!s)
    return;

  data = (unsigned char*)malloc(s);
  memcpy(data,d,s);
  size = s;

  if (!updateTransfer())
    disconnect(conID);
}

bool FastMapClient::updateTransfer ( void )
{
  int chunkToSend = 1000;

  if ( currerntPos <= size )
    return false;

  // wait till the current data is sent
  if (bz_getNonPlayerConnectionOutboundPacketCount(conID) != 0)
    return true;

  if ( currerntPos + chunkToSend > size)
    chunkToSend = size-currerntPos;

  bool worked = bz_sendNonPlayerData ( conID, data+currerntPos, chunkToSend );

  currerntPos += chunkToSend;

  return worked;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<commit_msg>send out the HTTP responce headers when sending back a map.<commit_after>// fastmap.cpp : Defines the entry point for the DLL application.
//

#include "bzfsAPI.h"
#include "plugin_utils.h"
#include <map>
#include <string>

BZ_GET_PLUGIN_VERSION

class FastMapEventHandler;

class FastMapClient : public bz_NonPlayerConnectionHandler
{
public:
  FastMapClient( int connectionID = -1, FastMapEventHandler *h = NULL);
  virtual ~FastMapClient();
  virtual void pending ( int connectionID, void *d, unsigned int s );
  virtual void disconnect ( int connectionID );

  void startTransfer ( unsigned char * d, unsigned int s );
  bool updateTransfer ( void );

  int conID;

  unsigned char *data;
  unsigned int size;
  unsigned int currerntPos;

  std::string command;

  FastMapEventHandler* handler;
};

class FastMapEventHandler : public bz_EventHandler
{
public:
  FastMapEventHandler();
  virtual ~FastMapEventHandler();

  virtual void process ( bz_EventData *eventData );

  void updateHTTPServer ( void );
  void killHTTPServer ( void );

  std::string	mapName;

  std::map<int,FastMapClient*> clients;

  unsigned char* mapData;
  unsigned int mapDataSize;
};

FastMapEventHandler fastMapEventHandler;

BZF_PLUGIN_CALL int bz_Load ( const char* /*commandLine*/ )
{
  bz_debugMessage(4,"fastmap plugin loaded");
  bz_registerEvent (bz_eWorldFinalized,&fastMapEventHandler);
  bz_registerEvent (bz_eTickEvent,&fastMapEventHandler);
  bz_registerEvent (bz_eListServerUpdateEvent,&fastMapEventHandler);
  bz_registerEvent (bz_eNewNonPlayerConnection,&fastMapEventHandler);
return 0;
}

BZF_PLUGIN_CALL int bz_Unload ( void )
{
  fastMapEventHandler.killHTTPServer();

  bz_debugMessage(4,"fastmap plugin unloaded");
  bz_removeEvent (bz_eWorldFinalized,&fastMapEventHandler);
  bz_removeEvent (bz_eTickEvent,&fastMapEventHandler);
  bz_removeEvent (bz_eListServerUpdateEvent,&fastMapEventHandler);
  bz_removeEvent (bz_eNewNonPlayerConnection,&fastMapEventHandler);
return 0;
}

FastMapEventHandler::FastMapEventHandler()
{
  mapName = format("PrivateMap%d",(unsigned int)this);

  mapData = NULL;
  mapDataSize = 0;
}

FastMapEventHandler::~FastMapEventHandler()
{
  killHTTPServer();
}

void FastMapEventHandler::process ( bz_EventData *eventData )
{
  if ( eventData->eventType == bz_eListServerUpdateEvent )
  {
    bz_ListServerUpdateEvent_V1 *updateData = (bz_ListServerUpdateEvent_V1*)eventData;
    mapName = format("%s%d",updateData->address,(unsigned int)this);
  }
  else if ( eventData->eventType == bz_eWorldFinalized )
  {
    killHTTPServer();

    if (!bz_getPublic() || bz_getClientWorldDowloadURL().size())
      return;

    mapDataSize = bz_getWorldCacheSize();
    mapData = (unsigned char*)malloc(mapDataSize);
    bz_getWorldCacheData(mapData);

    if (mapDataSize)
      bz_setClientWorldDowloadURL(format("HTTP:/%s/%s",bz_getPublicAddr().c_str(),mapName.c_str()).c_str());
  }
  else if ( eventData->eventType == bz_eTickEvent)
  {
    if ( mapDataSize )
      updateHTTPServer();
  }
  else if ( eventData->eventType == bz_eNewNonPlayerConnection )
  {
    if ( mapDataSize )
    {
      bz_NewNonPlayerConnectionEventData_V1 *connData = (bz_NewNonPlayerConnectionEventData_V1*)eventData;
      if (connData->size >= 3 && strncmp((const char*)connData->data,"GET",3))
      {
	FastMapClient * handler = new FastMapClient(connData->connectionID,this);

	if(bz_registerNonPlayerConnectionHandler ( connData->connectionID, handler ) )
	{
	  clients[connData->connectionID] = handler;
	  handler->pending (connData->connectionID,connData->data, connData->size);
	}
	else
	  delete(handler);
      }
    }
  }
  else if ( eventData->eventType == bz_eIdleNewNonPlayerConnection )
  {
    bz_NewNonPlayerConnectionEventData_V1 *connData = (bz_NewNonPlayerConnectionEventData_V1*)eventData;

    std::map<int,FastMapClient*>::iterator itr = clients.find(connData->connectionID);
    if( itr != clients.end() )
    {
      bz_removeNonPlayerConnectionHandler ( itr->second->conID, itr->second );
      delete(itr->second);
      clients.erase(itr);
    }
    bz_disconectNonPlayerConnection ( connData->connectionID );
 }
}

void FastMapEventHandler::updateHTTPServer ( void )
{
  std::vector<int> killList;

  std::map<int,FastMapClient*>::iterator itr = clients.begin();
  while (itr != clients.end())
  {
    if(itr->second->conID == -1 || !itr->second->updateTransfer() )
      killList.push_back(itr->first);
    itr++;
  }

  for ( unsigned int i = 0; i < (unsigned int)killList.size(); i++)
    clients.erase(clients.find(killList[i]));

  if (clients.size())
    bz_setMaxWaitTime(0.001f);
  else
    bz_setMaxWaitTime(2.0f);
}

void FastMapEventHandler::killHTTPServer ( void )
{
  if ( mapData )
    free(mapData);

  mapData = NULL;
  mapDataSize = 0;
}

FastMapClient::FastMapClient( int connectionID, FastMapEventHandler *h )
{
  conID = connectionID;

  data = NULL;
  size = 0;
  currerntPos = 0;
  handler = h;
}

FastMapClient::~FastMapClient()
{
  if (data)
    free(data);
}

void FastMapClient::pending ( int connectionID, void *s, unsigned int d )
{
  if ( connectionID != conID )
    return;

  char *c = (char*)malloc(d+1);
  memcpy(c,s,d);
  c[d] = 0;
  command += c;
  free (c);

  // parse the command
  std::vector<std::string> commandList = tokenize(command,std::string("\r\n"),0,false);

  if ( commandList.size() == 1 && commandList[0].size() == command.size() ) // there were no delims, we are done.
    return;

  for (unsigned int i = 0; i < (unsigned int)commandList.size();i++)
  {
    command.erase(command.begin(),command.begin()+commandList[i].size());

    std::string thisLine = commandList[i];

    if (strncmp(thisLine.c_str(),"GET",3) == 0 && !data) // it's a get and we arn't in a transfer
    {
      std::vector<std::string> params = tokenize(thisLine,std::string(" "),0,false);
      if ( params.size() <= 3 )
      {
	std::string urlPath = params[1];

	if (urlPath.size()>2 && handler->mapName == urlPath.c_str()+1 )
	{
	  startTransfer(handler->mapData,handler->mapDataSize);
	}
      }
    }
  }
}

void FastMapClient::disconnect ( int connectionID )
{
  if (connectionID != conID)
    return;

  bz_removeNonPlayerConnectionHandler ( conID, this );
  bz_disconectNonPlayerConnection ( conID );
  conID = -1;

}
void FastMapClient::startTransfer ( unsigned char * d, unsigned int s )
{
  if (data)
    free (data);
  data = NULL;
  size = 0;
  currerntPos = 0;

  if (!s)
    return;

  data = (unsigned char*)malloc(s);
  memcpy(data,d,s);
  size = s;

  std::string httpHeaders;
  httpHeaders += "HTTP/1.1 200 OK\n";
  httpHeaders += format("Content-Length: %d\n", size);
  httpHeaders += "Connection: close\n";
  httpHeaders += "Content-Type: application/binary\n";
  httpHeaders += "\n";

  if (!bz_sendNonPlayerData ( conID, httpHeaders.c_str(), httpHeaders.size() ) || !updateTransfer())
    disconnect(conID);
}

bool FastMapClient::updateTransfer ( void )
{
  int chunkToSend = 1000;

  if ( currerntPos <= size )
    return false;

  // wait till the current data is sent
  if (bz_getNonPlayerConnectionOutboundPacketCount(conID) != 0)
    return true;

  if ( currerntPos + chunkToSend > size)
    chunkToSend = size-currerntPos;

  bool worked = bz_sendNonPlayerData ( conID, data+currerntPos, chunkToSend );

  currerntPos += chunkToSend;

  return worked;
}

// Local Variables: ***
// mode:C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
<|endoftext|>