<commit_before>/*****************************************************************************
 *   MindTheGap: Integrated detection and assembly of insertion variants
 *   A tool from the GATB (Genome Assembly Tool Box)
 *   Copyright (C) 2014  INRIA
 *   Authors: C.Lemaitre, G.Rizk
 *
 *  This program 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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#ifndef _TOOL_FindBreakpoints_HPP_
#define _TOOL_FindBreakpoints_HPP_

/********************************************************************************/
#include <memory>
#include <gatb/gatb_core.hpp>
#include <Finder.hpp>

/********************************************************************************/

template<size_t type>
class IFindObserver;

template<size_t span>
class FindBreakpoints
{
public :

    typedef typename gatb::core::kmer::impl::Kmer<span>::ModelCanonical KmerModel;
    typedef typename KmerModel::Iterator KmerIterator;
    typedef typename gatb::core::kmer::impl::Kmer<span>::Type KmerType;

public :

    // Constructor
    FindBreakpoints(Finder * find);

    //Functor
    void operator()();

    // Observable
    void notify(bool in_graph);
    void addObserver(IFindObserver<span>* new_obs);

    /** writes a given breakpoint in the output file
     */
    void writeBreakpoint(int bkt_id, string& chrom_name, uint64_t position, string& kmer_begin, string& kmer_end, int repeat_size);

    /*Getter*/
    uint64_t breakpoint_id();
    uint64_t position();
    char * chrom_seq();
    string& chrom_name();

    KmerModel& model();
    KmerType& previous_kmer();
    KmerIterator& it_kmer();

    size_t kmer_size();
    int max_repeat();

    /*Setter*/
    uint64_t breakpoint_id_iterate();

    int homo_fuzzy_iterate();
    int homo_clean_iterate();
    int hetero_fuzzy_iterate();
    int hetero_clean_iterate();

public :

    /*Kmer related object*/
    KmerType kmer_begin;
    KmerType kmer_end;

    /*Gap type detection*/
    uint64_t solid_stretch_size;
    uint64_t gap_stretch_size;

    Finder * finder;

private :

    /*Observable membre*/
    std::vector<std::unique_ptr<IFindObserver<span> > > list_obs;

    /*Find breakpoint membre*/
    /*Write breakpoint*/
    uint64_t m_breakpoint_id;
    uint64_t m_position;
    char * m_chrom_sequence;
    string m_chrom_name;

    /*Kmer related object*/
    KmerModel m_model;
    KmerType m_previous_kmer;
    KmerIterator m_it_kmer;
};

template<size_t span>
FindBreakpoints<span>::FindBreakpoints(Finder * find) : list_obs(), m_model(find->_kmerSize), m_it_kmer(m_model)
{
    this->m_breakpoint_id = 0;
    this->m_position = 0;
    this->m_chrom_sequence = NULL;
    this->m_chrom_name = "";

    this->solid_stretch_size = 0;
    this->gap_stretch_size = 0;

    this->finder = find;
}

template<size_t span>
void FindBreakpoints<span>::operator()()
{
    // We create an iterator over this bank
    BankFasta::Iterator it_seq(*(finder->_refBank));

    // We loop over sequences
    for (it_seq.first(); !it_seq.isDone(); it_seq.next())
    {
	this->solid_stretch_size = 0;
	this->gap_stretch_size = 0;

        //Method : an homozyguous breakpoint is detected as a gap_stretch (ie. consecutive kmers on the sequence, that are not indexed in the graph) of particular sizes.
	//BUT there are some False Positives when we query the graph : when we ask the graph if a kmer is indexed (when starting from a previous not indexed kmer) it may wrongly answer yes
	//(the gatb dbg is exact only if the kmer we query is the neighbor of a truly solid kmer)
	//FP are likely to be isolated, ie. surrounded by not indexed kmers, therefore they can be detected as solid_stretches of size 1.
	// See FindObserver for code

	// We set the data from which we want to extract kmers.
	m_it_kmer.setData (it_seq->getData());
	this->m_chrom_sequence = it_seq->getDataBuffer();
	this->m_chrom_name = it_seq->getComment();
	this->m_position = 0;

	// We iterate the kmers.
	for (m_it_kmer.first(); !m_it_kmer.isDone(); m_it_kmer.next(), m_position++)
	{
	    //we need to convert the kmer in a node to query the graph.
	    Node node(Node::Value(m_it_kmer->value()));
	    this->notify(this->finder->_graph.contains(node));
	    m_previous_kmer = m_it_kmer->forward();
	}
    }
}

template<size_t span>
void FindBreakpoints<span>::notify(bool in_graph)
{
    if(in_graph)
    {
	solid_stretch_size++;
    }

    for(auto it = this->list_obs.begin(); it != this->list_obs.end(); it++)
    {
	(*it)->update(in_graph);
    }

    if(!in_graph)
    {
        gap_stretch_size++;
	solid_stretch_size = 0;
    }
}

template<size_t span>
void FindBreakpoints<span>::addObserver(IFindObserver<span>* new_obs)
{
    this->list_obs.push_back(std::unique_ptr<IFindObserver<span> >(new_obs));
}

template<size_t span>
void FindBreakpoints<span>::writeBreakpoint(int bkt_id, string& chrom_name, uint64_t position, string& kmer_begin, string& kmer_end, int repeat_size){
	fprintf(this->finder->_breakpoint_file,">left_contig_%i_%s_pos_%lli_repeat_%i\n%s\n>right_contig_%i_%s_pos_%lli_repeat_%i\n%s\n",
			bkt_id,
			chrom_name.c_str(),
			position,
			repeat_size,
			kmer_begin.c_str(),
			bkt_id,
			chrom_name.c_str(),
			position,
			repeat_size,
			kmer_end.c_str()
	);
}

/*Getter*/
template<size_t span>
uint64_t FindBreakpoints<span>::breakpoint_id()
{
    return this->m_breakpoint_id;
}

template<size_t span>
uint64_t FindBreakpoints<span>::position()
{
    return this->m_position;
}

template<size_t span>
char * FindBreakpoints<span>::chrom_seq()
{
    return this->m_chrom_sequence;
}

template<size_t span>
string& FindBreakpoints<span>::chrom_name()
{
    return this->m_chrom_name;
}

template<size_t span>
typename FindBreakpoints<span>::KmerModel& FindBreakpoints<span>::model()
{
    return this->m_model;
}

template<size_t span>
typename FindBreakpoints<span>::KmerType& FindBreakpoints<span>::previous_kmer()
{
    return this->m_previous_kmer;
}

template<size_t span>
typename FindBreakpoints<span>::KmerIterator& FindBreakpoints<span>::it_kmer()
{
    return this->m_it_kmer;
}

template<size_t span>
size_t FindBreakpoints<span>::kmer_size()
{
    return this->finder->_kmerSize;
}

template<size_t span>
int FindBreakpoints<span>::max_repeat()
{
    return this->finder->_max_repeat;
}

/*Setter*/
template<size_t span>
uint64_t  FindBreakpoints<span>::breakpoint_id_iterate()
{
    return this->m_breakpoint_id++;
}

template<size_t span>
int FindBreakpoints<span>::homo_fuzzy_iterate()
{
    return this->finder->_nb_homo_fuzzy++;
}

template<size_t span>
int FindBreakpoints<span>::homo_clean_iterate()
{
    return this->finder->_nb_homo_clean++;
}

template<size_t span>
int FindBreakpoints<span>::hetero_fuzzy_iterate()
{
    return this->finder->_nb_hetero_fuzzy++;
}

template<size_t span>
int FindBreakpoints<span>::hetero_clean_iterate()
{
    return this->finder->_nb_hetero_clean++;
}

#endif /* _TOOL_FindBreakpoints_HPP_ */
<commit_msg>Forget some return, in getter method<commit_after>/*****************************************************************************
 *   MindTheGap: Integrated detection and assembly of insertion variants
 *   A tool from the GATB (Genome Assembly Tool Box)
 *   Copyright (C) 2014  INRIA
 *   Authors: C.Lemaitre, G.Rizk
 *
 *  This program 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.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

#ifndef _TOOL_FindBreakpoints_HPP_
#define _TOOL_FindBreakpoints_HPP_

/********************************************************************************/
#include <memory>
#include <gatb/gatb_core.hpp>
#include <Finder.hpp>

/********************************************************************************/

template<size_t type>
class IFindObserver;

template<size_t span>
class FindBreakpoints
{
public :

    typedef typename gatb::core::kmer::impl::Kmer<span>::ModelCanonical KmerModel;
    typedef typename KmerModel::Iterator KmerIterator;
    typedef typename gatb::core::kmer::impl::Kmer<span>::Type KmerType;

public :

    // Constructor
    FindBreakpoints(Finder * find);

    //Functor
    void operator()();

    // Observable
    void notify(bool in_graph);
    void addObserver(IFindObserver<span>* new_obs);

    /** writes a given breakpoint in the output file
     */
    void writeBreakpoint(int bkt_id, string& chrom_name, uint64_t position, string& kmer_begin, string& kmer_end, int repeat_size);

    /*Getter*/
    uint64_t breakpoint_id();
    uint64_t position();
    char * chrom_seq();
    string& chrom_name();

    KmerModel& model();
    KmerType& previous_kmer();
    KmerIterator& it_kmer();

    size_t kmer_size();
    int max_repeat();

    /*Setter*/
    uint64_t breakpoint_id_iterate();

    int homo_fuzzy_iterate();
    int homo_clean_iterate();
    int hetero_fuzzy_iterate();
    int hetero_clean_iterate();

public :

    /*Kmer related object*/
    KmerType kmer_begin;
    KmerType kmer_end;

    /*Gap type detection*/
    uint64_t solid_stretch_size;
    uint64_t gap_stretch_size;

    Finder * finder;

private :

    /*Observable membre*/
    std::vector<std::unique_ptr<IFindObserver<span> > > list_obs;

    /*Find breakpoint membre*/
    /*Write breakpoint*/
    uint64_t m_breakpoint_id;
    uint64_t m_position;
    char * m_chrom_sequence;
    string m_chrom_name;

    /*Kmer related object*/
    KmerModel m_model;
    KmerType m_previous_kmer;
    KmerIterator m_it_kmer;
};

template<size_t span>
FindBreakpoints<span>::FindBreakpoints(Finder * find) : list_obs(), m_model(find->_kmerSize), m_it_kmer(m_model)
{
    this->m_breakpoint_id = 0;
    this->m_position = 0;
    this->m_chrom_sequence = NULL;
    this->m_chrom_name = "";

    this->solid_stretch_size = 0;
    this->gap_stretch_size = 0;

    this->finder = find;
}

template<size_t span>
void FindBreakpoints<span>::operator()()
{
    // We create an iterator over this bank
    BankFasta::Iterator it_seq(*(finder->_refBank));

    // We loop over sequences
    for (it_seq.first(); !it_seq.isDone(); it_seq.next())
    {
	this->solid_stretch_size = 0;
	this->gap_stretch_size = 0;

        //Method : an homozyguous breakpoint is detected as a gap_stretch (ie. consecutive kmers on the sequence, that are not indexed in the graph) of particular sizes.
	//BUT there are some False Positives when we query the graph : when we ask the graph if a kmer is indexed (when starting from a previous not indexed kmer) it may wrongly answer yes
	//(the gatb dbg is exact only if the kmer we query is the neighbor of a truly solid kmer)
	//FP are likely to be isolated, ie. surrounded by not indexed kmers, therefore they can be detected as solid_stretches of size 1.
	// See FindObserver for code

	// We set the data from which we want to extract kmers.
	m_it_kmer.setData (it_seq->getData());
	this->m_chrom_sequence = it_seq->getDataBuffer();
	this->m_chrom_name = it_seq->getComment();
	this->m_position = 0;

	// We iterate the kmers.
	for (m_it_kmer.first(); !m_it_kmer.isDone(); m_it_kmer.next(), m_position++)
	{
	    //we need to convert the kmer in a node to query the graph.
	    Node node(Node::Value(m_it_kmer->value()));
	    this->notify(this->finder->_graph.contains(node));
	    m_previous_kmer = m_it_kmer->forward();
	}
    }
}

template<size_t span>
void FindBreakpoints<span>::notify(bool in_graph)
{
    if(in_graph)
    {
	solid_stretch_size++;
    }

    for(auto it = this->list_obs.begin(); it != this->list_obs.end(); it++)
    {
	(*it)->update(in_graph);
    }

    if(!in_graph)
    {
        gap_stretch_size++;
	solid_stretch_size = 0;
    }
}

template<size_t span>
void FindBreakpoints<span>::addObserver(IFindObserver<span>* new_obs)
{
    this->list_obs.push_back(std::unique_ptr<IFindObserver<span> >(new_obs));
}

template<size_t span>
void FindBreakpoints<span>::writeBreakpoint(int bkt_id, string& chrom_name, uint64_t position, string& kmer_begin, string& kmer_end, int repeat_size){
	fprintf(this->finder->_breakpoint_file,">left_contig_%i_%s_pos_%lli_repeat_%i\n%s\n>right_contig_%i_%s_pos_%lli_repeat_%i\n%s\n",
			bkt_id,
			chrom_name.c_str(),
			position,
			repeat_size,
			kmer_begin.c_str(),
			bkt_id,
			chrom_name.c_str(),
			position,
			repeat_size,
			kmer_end.c_str()
	);
}

/*Getter*/
template<size_t span>
uint64_t FindBreakpoints<span>::breakpoint_id()
{
    return this->m_breakpoint_id;
}

template<size_t span>
uint64_t FindBreakpoints<span>::position()
{
    return this->m_position;
}

template<size_t span>
char * FindBreakpoints<span>::chrom_seq()
{
    return this->m_chrom_sequence;
}

template<size_t span>
string& FindBreakpoints<span>::chrom_name()
{
    return this->m_chrom_name;
}

template<size_t span>
typename FindBreakpoints<span>::KmerModel& FindBreakpoints<span>::model()
{
    return this->m_model;
}

template<size_t span>
typename FindBreakpoints<span>::KmerType& FindBreakpoints<span>::previous_kmer()
{
    return this->m_previous_kmer;
}

template<size_t span>
typename FindBreakpoints<span>::KmerIterator& FindBreakpoints<span>::it_kmer()
{
    return this->m_it_kmer;
}

template<size_t span>
size_t FindBreakpoints<span>::kmer_size()
{
    return this->finder->_kmerSize;
}

template<size_t span>
int FindBreakpoints<span>::max_repeat()
{
    return this->finder->_max_repeat;
}

/*Setter*/
template<size_t span>
uint64_t  FindBreakpoints<span>::breakpoint_id_iterate()
{
    return this->m_breakpoint_id++;
}

template<size_t span>
int FindBreakpoints<span>::homo_fuzzy_iterate()
{
    return this->finder->_nb_homo_fuzzy++;
}

template<size_t span>
int FindBreakpoints<span>::homo_clean_iterate()
{
    return this->finder->_nb_homo_clean++;
}

template<size_t span>
int FindBreakpoints<span>::hetero_fuzzy_iterate()
{
    return this->finder->_nb_hetero_fuzzy++;
}

template<size_t span>
int FindBreakpoints<span>::hetero_clean_iterate()
{
    return this->finder->_nb_hetero_clean++;
}

#endif /* _TOOL_FindBreakpoints_HPP_ */
<|endoftext|>


<commit_before>// This file was automatically generated

/*
	Nazara Engine - Graphics module

	Copyright (C) 2020 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

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

#pragma once

#ifndef NAZARA_GLOBAL_GRAPHICS_HPP
#define NAZARA_GLOBAL_GRAPHICS_HPP

#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/BakedFrameGraph.hpp>
#include <Nazara/Graphics/BasicMaterial.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/CullingList.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/ForwardFramePipeline.hpp>
#include <Nazara/Graphics/FrameGraph.hpp>
#include <Nazara/Graphics/FramePass.hpp>
#include <Nazara/Graphics/FramePassAttachment.hpp>
#include <Nazara/Graphics/FramePipeline.hpp>
#include <Nazara/Graphics/GraphicalMesh.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/MaterialPass.hpp>
#include <Nazara/Graphics/MaterialPipeline.hpp>
#include <Nazara/Graphics/MaterialSettings.hpp>
#include <Nazara/Graphics/Model.hpp>
#include <Nazara/Graphics/PhongLightingMaterial.hpp>
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Graphics/UberShader.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>

#endif // NAZARA_GLOBAL_GRAPHICS_HPP
<commit_msg>Regenerate global headers<commit_after>// This file was automatically generated

/*
	Nazara Engine - Graphics module

	Copyright (C) 2020 Jérôme "Lynix" Leclercq (Lynix680@gmail.com)

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

#pragma once

#ifndef NAZARA_GLOBAL_GRAPHICS_HPP
#define NAZARA_GLOBAL_GRAPHICS_HPP

#include <Nazara/Graphics/AbstractViewer.hpp>
#include <Nazara/Graphics/BakedFrameGraph.hpp>
#include <Nazara/Graphics/BasicMaterial.hpp>
#include <Nazara/Graphics/Camera.hpp>
#include <Nazara/Graphics/Config.hpp>
#include <Nazara/Graphics/CullingList.hpp>
#include <Nazara/Graphics/ElementRenderer.hpp>
#include <Nazara/Graphics/Enums.hpp>
#include <Nazara/Graphics/ForwardFramePipeline.hpp>
#include <Nazara/Graphics/FrameGraph.hpp>
#include <Nazara/Graphics/FramePass.hpp>
#include <Nazara/Graphics/FramePassAttachment.hpp>
#include <Nazara/Graphics/FramePipeline.hpp>
#include <Nazara/Graphics/GraphicalMesh.hpp>
#include <Nazara/Graphics/Graphics.hpp>
#include <Nazara/Graphics/InstancedRenderable.hpp>
#include <Nazara/Graphics/Material.hpp>
#include <Nazara/Graphics/MaterialPass.hpp>
#include <Nazara/Graphics/MaterialPassRegistry.hpp>
#include <Nazara/Graphics/MaterialPipeline.hpp>
#include <Nazara/Graphics/MaterialSettings.hpp>
#include <Nazara/Graphics/Model.hpp>
#include <Nazara/Graphics/PhongLightingMaterial.hpp>
#include <Nazara/Graphics/PredefinedShaderStructs.hpp>
#include <Nazara/Graphics/RenderElement.hpp>
#include <Nazara/Graphics/RenderQueue.hpp>
#include <Nazara/Graphics/RenderQueueRegistry.hpp>
#include <Nazara/Graphics/RenderSubmesh.hpp>
#include <Nazara/Graphics/SubmeshRenderer.hpp>
#include <Nazara/Graphics/TextureSamplerCache.hpp>
#include <Nazara/Graphics/UberShader.hpp>
#include <Nazara/Graphics/ViewerInstance.hpp>
#include <Nazara/Graphics/WorldInstance.hpp>

#endif // NAZARA_GLOBAL_GRAPHICS_HPP
<|endoftext|>


<commit_before>#ifndef FIELD_TYPE_INCLUDED
#define FIELD_TYPE_INCLUDED

#include "celltype.hpp"

namespace cells
{

  //array class
  class field {
  public:
    field(unsigned char); //constructor, log_dim è il logaritmo in base 2 del lato
                          //max log_dim = 15
    unsigned int lenght; //il numero di celle
    unsigned int index(unsigned int, unsigned int); //l'indice alla cella x,y
    unsigned int side;
    cell items; // i dati veri e propri
    inline cell* get_start_cell() { return CloneCell(&items); }; //return copy of start cell
  private:
    unsigned char log_dim;
  };

}

#endif
<commit_msg>updated field.hpp with boundaries and file procs<commit_after>#ifndef FIELD_TYPE_INCLUDED
#define FIELD_TYPE_INCLUDED

#include "celltype.hpp"

namespace cells
{

  //array class
  class field {
  public:
    field(unsigned char); //constructor, log_dim è il logaritmo in base 2 del lato
                          //max log_dim = 15
    unsigned int lenght; //il numero di celle
    unsigned int index(unsigned int, unsigned int); //l'indice alla cella x,y
    unsigned int side;

    struct {
      float xmin, xmax;
      float ymin, ymax;
    } boundaries; // i limiti della simulazione

    cell items; // i dati veri e propri
    inline cell* get_start_cell() { return CloneCell(&items); }; //return copy of start cell

    void to_file(char*); //save this array to a file
    void from_file(char*);
  private:
    unsigned char log_dim;
  };

}

#endif
<|endoftext|>


<commit_before>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "VkSurfaceKHR.hpp"

#include "Vulkan/VkDestroy.hpp"

#include <algorithm>

namespace {

static const VkSurfaceFormatKHR surfaceFormats[] = {
	{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
	{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
};

static const VkPresentModeKHR presentModes[] = {
	// FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
	// with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
	// should convert to using the Present extension, which allows us to request presentation
	// at particular msc values. Will need a similar solution on Windows - possibly interact
	// with DXGI directly.
	VK_PRESENT_MODE_FIFO_KHR,
	VK_PRESENT_MODE_MAILBOX_KHR,
};

}  // namespace

namespace vk {

VkResult PresentImage::createImage(VkDevice device, const VkImageCreateInfo &createInfo)
{
	VkImage image;
	VkResult status = vkCreateImage(device, &createInfo, nullptr, &image);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	this->image = Cast(image);

	return status;
}

VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
{
	ASSERT(image);

	VkDeviceMemory deviceMemory;
	VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, &deviceMemory);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	imageMemory = Cast(deviceMemory);
	vkBindImageMemory(device, *image, deviceMemory, 0);
	imageStatus = AVAILABLE;

	return VK_SUCCESS;
}

void PresentImage::release()
{
	if(imageMemory)
	{
		vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
		imageMemory = nullptr;
	}

	if(image)
	{
		vk::destroy(static_cast<VkImage>(*image), nullptr);
		image = nullptr;
	}

	imageStatus = NONEXISTENT;
}

VkImage PresentImage::asVkImage() const
{
	return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
}

uint32_t SurfaceKHR::getSurfaceFormatsCount() const
{
	return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
}

VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
{
	uint32_t count = getSurfaceFormatsCount();

	uint32_t i;
	for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
	{
		pSurfaceFormats[i] = surfaceFormats[i];
	}

	*pSurfaceFormatCount = i;

	if(*pSurfaceFormatCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

uint32_t SurfaceKHR::getPresentModeCount() const
{
	return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
}

VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
{
	uint32_t count = getPresentModeCount();

	uint32_t i;
	for(i = 0; i < std::min(*pPresentModeCount, count); i++)
	{
		pPresentModes[i] = presentModes[i];
	}

	*pPresentModeCount = i;

	if(*pPresentModeCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
{
	associatedSwapchain = swapchain;
}

void SurfaceKHR::disassociateSwapchain()
{
	associatedSwapchain = nullptr;
}

bool SurfaceKHR::hasAssociatedSwapchain()
{
	return (associatedSwapchain != nullptr);
}

VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
{
	if(!pRects)
	{
		*pRectCount = 1;
		return VK_SUCCESS;
	}

	if(*pRectCount < 1)
	{
		return VK_INCOMPLETE;
	}

	VkSurfaceCapabilitiesKHR capabilities;
	getSurfaceCapabilities(&capabilities);

	pRects[0].offset = { 0, 0 };
	pRects[0].extent = capabilities.currentExtent;
	*pRectCount = 1;

	return VK_SUCCESS;
}

void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
	pSurfaceCapabilities->minImageCount = 1;
	pSurfaceCapabilities->maxImageCount = 0;

	pSurfaceCapabilities->maxImageArrayLayers = 1;

	pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	pSurfaceCapabilities->supportedUsageFlags =
	    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
	    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
	    VK_IMAGE_USAGE_SAMPLED_BIT |
	    VK_IMAGE_USAGE_STORAGE_BIT;
}

}  // namespace vk<commit_msg>Report input attachment usage capability for surface images<commit_after>// Copyright 2018 The SwiftShader Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "VkSurfaceKHR.hpp"

#include "Vulkan/VkDestroy.hpp"

#include <algorithm>

namespace {

static const VkSurfaceFormatKHR surfaceFormats[] = {
	{ VK_FORMAT_B8G8R8A8_UNORM, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
	{ VK_FORMAT_B8G8R8A8_SRGB, VK_COLOR_SPACE_SRGB_NONLINEAR_KHR },
};

static const VkPresentModeKHR presentModes[] = {
	// FIXME(b/124265819): Make present modes behave correctly. Currently we use XPutImage
	// with no synchronization, which behaves more like VK_PRESENT_MODE_IMMEDIATE_KHR. We
	// should convert to using the Present extension, which allows us to request presentation
	// at particular msc values. Will need a similar solution on Windows - possibly interact
	// with DXGI directly.
	VK_PRESENT_MODE_FIFO_KHR,
	VK_PRESENT_MODE_MAILBOX_KHR,
};

}  // namespace

namespace vk {

VkResult PresentImage::createImage(VkDevice device, const VkImageCreateInfo &createInfo)
{
	VkImage image;
	VkResult status = vkCreateImage(device, &createInfo, nullptr, &image);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	this->image = Cast(image);

	return status;
}

VkResult PresentImage::allocateAndBindImageMemory(VkDevice device, const VkMemoryAllocateInfo &allocateInfo)
{
	ASSERT(image);

	VkDeviceMemory deviceMemory;
	VkResult status = vkAllocateMemory(device, &allocateInfo, nullptr, &deviceMemory);
	if(status != VK_SUCCESS)
	{
		return status;
	}

	imageMemory = Cast(deviceMemory);
	vkBindImageMemory(device, *image, deviceMemory, 0);
	imageStatus = AVAILABLE;

	return VK_SUCCESS;
}

void PresentImage::release()
{
	if(imageMemory)
	{
		vk::destroy(static_cast<VkDeviceMemory>(*imageMemory), nullptr);
		imageMemory = nullptr;
	}

	if(image)
	{
		vk::destroy(static_cast<VkImage>(*image), nullptr);
		image = nullptr;
	}

	imageStatus = NONEXISTENT;
}

VkImage PresentImage::asVkImage() const
{
	return image ? static_cast<VkImage>(*image) : VkImage({ VK_NULL_HANDLE });
}

uint32_t SurfaceKHR::getSurfaceFormatsCount() const
{
	return static_cast<uint32_t>(sizeof(surfaceFormats) / sizeof(surfaceFormats[0]));
}

VkResult SurfaceKHR::getSurfaceFormats(uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) const
{
	uint32_t count = getSurfaceFormatsCount();

	uint32_t i;
	for(i = 0; i < std::min(*pSurfaceFormatCount, count); i++)
	{
		pSurfaceFormats[i] = surfaceFormats[i];
	}

	*pSurfaceFormatCount = i;

	if(*pSurfaceFormatCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

uint32_t SurfaceKHR::getPresentModeCount() const
{
	return static_cast<uint32_t>(sizeof(presentModes) / sizeof(presentModes[0]));
}

VkResult SurfaceKHR::getPresentModes(uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) const
{
	uint32_t count = getPresentModeCount();

	uint32_t i;
	for(i = 0; i < std::min(*pPresentModeCount, count); i++)
	{
		pPresentModes[i] = presentModes[i];
	}

	*pPresentModeCount = i;

	if(*pPresentModeCount < count)
	{
		return VK_INCOMPLETE;
	}

	return VK_SUCCESS;
}

void SurfaceKHR::associateSwapchain(SwapchainKHR *swapchain)
{
	associatedSwapchain = swapchain;
}

void SurfaceKHR::disassociateSwapchain()
{
	associatedSwapchain = nullptr;
}

bool SurfaceKHR::hasAssociatedSwapchain()
{
	return (associatedSwapchain != nullptr);
}

VkResult SurfaceKHR::getPresentRectangles(uint32_t *pRectCount, VkRect2D *pRects) const
{
	if(!pRects)
	{
		*pRectCount = 1;
		return VK_SUCCESS;
	}

	if(*pRectCount < 1)
	{
		return VK_INCOMPLETE;
	}

	VkSurfaceCapabilitiesKHR capabilities;
	getSurfaceCapabilities(&capabilities);

	pRects[0].offset = { 0, 0 };
	pRects[0].extent = capabilities.currentExtent;
	*pRectCount = 1;

	return VK_SUCCESS;
}

void SurfaceKHR::setCommonSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
{
	pSurfaceCapabilities->minImageCount = 1;
	pSurfaceCapabilities->maxImageCount = 0;

	pSurfaceCapabilities->maxImageArrayLayers = 1;

	pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
	pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
	pSurfaceCapabilities->supportedUsageFlags =
	    VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
	    VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT |
	    VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
	    VK_IMAGE_USAGE_TRANSFER_DST_BIT |
	    VK_IMAGE_USAGE_SAMPLED_BIT |
	    VK_IMAGE_USAGE_STORAGE_BIT;
}

}  // namespace vk<|endoftext|>


<commit_before>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
const int IP_HEADR_OFFSET = 14;
const int IP_HEADER_SIZE = 20;
const int UDP_HEADER_OFFSET = 34;
const int UDP_HEADER_SIZE = 8;
const int UDP_DATA_OFFSET = 42;

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == nullptr) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == nullptr) {
    return -1;
  }

  while (true) {
    int RetVal;
    pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  printf("Total packets        %" PRIu64 "\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<commit_msg>Update prototype2/tools/ReaderPcap.cpp<commit_after>/** Copyright (C) 2016, 2017 European Spallation Source ERIC */

#include <algorithm>
#include <arpa/inet.h>
#include <cassert>
#include <cinttypes>
#include <cstring>
#include <tools/ReaderPcap.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <fmt/format.h>

// GCOVR_EXCL_START

// Protocol identifiers
const int ETHERTYPE_ARP = 0x0806;
const int ETHERTYPE_IPV4 = 0x0800;
const int IPPROTO_UDP = 17;
// Header and data location specifications
const int ETHERTYPE_OFFSET = 12;
const int ETHERNET_HEADER_SIZE = 14;
const int IP_HEADR_OFFSET = 14;
const int IP_HEADER_SIZE = 20;
const int UDP_HEADER_OFFSET = 34;
const int UDP_HEADER_SIZE = 8;
const int UDP_DATA_OFFSET = 42;

ReaderPcap::ReaderPcap(std::string filename)
  : FileName(filename) {
  memset(&Stats, 0, sizeof(stats_t));
}

ReaderPcap::~ReaderPcap() {
  if (PcapHandle != NULL ) {
    pcap_close(PcapHandle);
  }
}

int ReaderPcap::open() {
  char errbuff[PCAP_ERRBUF_SIZE];
  PcapHandle = pcap_open_offline(FileName.c_str(), errbuff);
  if (PcapHandle == nullptr) {
    return -1;
  }
  return 0;
}

int ReaderPcap::validatePacket(pcap_pkthdr *header, const unsigned char *data) {
  Stats.PacketsTotal++; /**< total packets in pcap file */
  Stats.BytesTotal += header->len;

  if (header->len != header->caplen) {
    Stats.PacketsTruncated++;
    return 0;
  }

  uint16_t type = ntohs(*(uint16_t *)&data[ETHERTYPE_OFFSET]);
  // printf("packet header len %d, type %x\n", header->len, type);

  if (type == ETHERTYPE_ARP) {
    Stats.EtherTypeArp++;
  } else if (type == ETHERTYPE_IPV4) {
    Stats.EtherTypeIpv4++;
  } else {
    Stats.EtherTypeUnknown++;
  }

  if (type != ETHERTYPE_IPV4) { // must be ipv4
    return 0;
  }

  ip *ip = (ip *)&data[IP_HEADR_OFFSET];

  // IPv4 header length must be 20, ip version 4, ipproto must be UDP
  if ((ip->ip_hl != 5) or (ip->ip_v != 4) or (ip->ip_p != IPPROTO_UDP)) {
    Stats.IpProtoUnknown++;
    return 0;
  }
  Stats.IpProtoUDP++;

  assert(header->len > ETHERNET_HEADER_SIZE + IP_HEADER_SIZE + UDP_HEADER_SIZE);
  assert(Stats.PacketsTotal == Stats.EtherTypeIpv4 + Stats.EtherTypeArp + Stats.EtherTypeUnknown);
  assert(Stats.EtherTypeIpv4 == Stats.IpProtoUDP + Stats.IpProtoUnknown);

  udphdr *udp = (udphdr *)&data[UDP_HEADER_OFFSET];
  #ifndef __FAVOR_BSD // Why is __FAVOR_BSD not defined here?
  uint16_t UdpLen = htons(udp->len);
  #else
  uint16_t UdpLen = htons(udp->uh_ulen);
  #endif
  assert(UdpLen >= UDP_HEADER_SIZE);

  #if 0
  printf("UDP Payload, Packet %" PRIu64 ", time: %d:%d seconds, size: %d bytes\n",
       Stats.PacketsTotal, (int)header->ts.tv_sec, (int)header->ts.tv_usec,
       (int)header->len);
  printf("ip src->dest: 0x%08x:%d ->0x%08x:%d\n",
         ntohl(*(uint32_t*)&ip->ip_src), ntohs(udp->uh_sport),
         ntohl(*(uint32_t*)&ip->ip_dst), ntohs(udp->uh_dport));
  #endif

  return UdpLen;
}

int ReaderPcap::read(char *buffer, size_t bufferlen) {
  if (PcapHandle == nullptr) {
    return -1;
  }

  pcap_pkthdr *Header;
  const unsigned char *Data;
  int ret = pcap_next_ex(PcapHandle, &Header, &Data);
  if (ret < 0) {
    return -1;
  }

  int UdpDataLength;
  if ((UdpDataLength = validatePacket(Header, Data)) <= 0) {
    return UdpDataLength;
  }

  auto DataLength = std::min((size_t)(UdpDataLength - UDP_HEADER_SIZE), bufferlen);
  std::memcpy(buffer, &Data[UDP_DATA_OFFSET], DataLength);

  return DataLength;
}

int ReaderPcap::getStats() {
  if (PcapHandle == nullptr) {
    return -1;
  }

  while (true) {
    int RetVal;
    pcap_pkthdr *Header;
    const unsigned char *Data;
    if ((RetVal = pcap_next_ex(PcapHandle, &Header, &Data))  < 0) {
      break;
    }
    validatePacket(Header, Data);
  }
  return 0;
}

void ReaderPcap::printPacket(unsigned char *data, size_t len) {
  for (unsigned int i = 0; i < len; i++) {
    if ((i % 16) == 0 && i != 0) {
      printf("\n");
    }
    printf("%.2x ", data[i]);
  }
  printf("\n");
}

void ReaderPcap::printStats() {
  fmt::print("Total packets        {}\n", Stats.PacketsTotal);
  printf("Truncated packets    %" PRIu64 "\n", Stats.PacketsTruncated);
  printf("Ethertype IPv4       %" PRIu64 "\n", Stats.EtherTypeIpv4);
  printf("  ipproto UDP        %" PRIu64 "\n", Stats.IpProtoUDP);
  printf("  ipproto other      %" PRIu64 "\n", Stats.IpProtoUnknown);
  printf("Ethertype unknown    %" PRIu64 "\n", Stats.EtherTypeUnknown);
  printf("Ethertype ARP        %" PRIu64 "\n", Stats.EtherTypeArp);
  printf("Total bytes          %" PRIu64 "\n", Stats.BytesTotal);

}
// GCOVR_EXCL_STOP
<|endoftext|>


<commit_before>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2019, INRIA
 */

#ifndef __eigenpy_details_hpp__
#define __eigenpy_details_hpp__

#include "eigenpy/fwd.hpp"

#include <patchlevel.h> // For PY_MAJOR_VERSION
#include <numpy/arrayobject.h>
#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/registration.hpp"
#include "eigenpy/map.hpp"

#define GET_PY_ARRAY_TYPE(array) PyArray_ObjectType(reinterpret_cast<PyObject *>(array), 0)

namespace eigenpy
{
  template <typename SCALAR>  struct NumpyEquivalentType {};
  template <> struct NumpyEquivalentType<double>  { enum { type_code = NPY_DOUBLE };};
  template <> struct NumpyEquivalentType<int>     { enum { type_code = NPY_INT    };};
  template <> struct NumpyEquivalentType<long>     { enum { type_code = NPY_LONG    };};
  template <> struct NumpyEquivalentType<float>   { enum { type_code = NPY_FLOAT  };};

  template <typename SCALAR1, typename SCALAR2>
  struct FromTypeToType : public boost::false_type {};

  template <typename SCALAR>
  struct FromTypeToType<SCALAR,SCALAR> : public boost::true_type {};

  template <> struct FromTypeToType<int,long> : public boost::true_type {};
  template <> struct FromTypeToType<int,float> : public boost::true_type {};
  template <> struct FromTypeToType<int,double> : public boost::true_type {};

  template <> struct FromTypeToType<long,float> : public boost::true_type {};
  template <> struct FromTypeToType<long,double> : public boost::true_type {};

  template <> struct FromTypeToType<float,double> : public boost::true_type {};

  namespace bp = boost::python;

  struct NumpyType
  {

    static NumpyType & getInstance()
    {
      static NumpyType instance;
      return instance;
    }

    operator bp::object () { return CurrentNumpyType; }

    bp::object make(PyArrayObject* pyArray, bool copy = false)
    { return make((PyObject*)pyArray,copy); }

    bp::object make(PyObject* pyObj, bool copy = false)
    {
      bp::object m;
      if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyMatrixType))
        m = NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
//        m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
      else if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyArrayType))
        m = bp::object(bp::handle<>(pyObj)); // nothing to do here

      Py_INCREF(m.ptr());
      return m;
    }

    static void setNumpyType(bp::object & obj)
    {
      PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
      if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
        getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
      else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
        getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
    }

    static void switchToNumpyArray()
    {
      getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
    }

    static void switchToNumpyMatrix()
    {
      getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
    }

  protected:
    NumpyType()
    {
      pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
      // TODO I don't know why this Py_INCREF is necessary.
      // Without it, the destructor of NumpyType SEGV sometimes.
      Py_INCREF(pyModule.ptr());
#endif

      NumpyMatrixObject = pyModule.attr("matrix");
      NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
      NumpyArrayObject = pyModule.attr("ndarray");
      NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
      NumpyAsMatrixObject = pyModule.attr("asmatrix");
      NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());

      CurrentNumpyType = NumpyMatrixObject; // default conversion
    }

    bp::object CurrentNumpyType;
    bp::object pyModule;

    // Numpy types
    bp::object NumpyMatrixObject; PyTypeObject * NumpyMatrixType;
    bp::object NumpyAsMatrixObject; PyTypeObject * NumpyAsMatrixType;
    bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;
  };

  template<typename MatType>
  struct EigenObjectAllocator
  {
    typedef MatType Type;
    typedef typename MatType::Scalar Scalar;

    static void allocate(PyArrayObject * pyArray, void * storage)
    {
      const int rows = (int)PyArray_DIMS(pyArray)[0];
      const int cols = (int)PyArray_DIMS(pyArray)[1];

      Type * mat_ptr = new(storage) Type(rows,cols);
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        *mat_ptr = MapNumpy<MatType,int>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        *mat_ptr = MapNumpy<MatType,long>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        *mat_ptr = MapNumpy<MatType,float>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        *mat_ptr = MapNumpy<MatType,double>::map(pyArray).template cast<Scalar>();
    }

    static void convert(Type const & mat , PyArrayObject * pyArray)
    {
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
    }
  };

#if EIGEN_VERSION_AT_LEAST(3,2,0)
  template<typename MatType>
  struct EigenObjectAllocator< eigenpy::Ref<MatType> >
  {
    typedef eigenpy::Ref<MatType> Type;
    typedef typename MatType::Scalar Scalar;

    static void allocate(PyArrayObject * pyArray, void * storage)
    {
      typename MapNumpy<MatType,Scalar>::EigenMap numpyMap = MapNumpy<MatType,Scalar>::map(pyArray);
      new(storage) Type(numpyMap);
    }

    static void convert(Type const & mat , PyArrayObject * pyArray)
    {
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
    }
  };
#endif

  /* --- TO PYTHON -------------------------------------------------------------- */
  template<typename MatType>
  struct EigenToPy
  {
    static PyObject* convert(MatType const& mat)
    {
      typedef typename MatType::Scalar T;
      assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
	      && "Matrix range larger than int ... should never happen." );
      const int R  = (int)mat.rows(), C = (int)mat.cols();

      npy_intp shape[2] = { R,C };
      PyArrayObject* pyArray = (PyArrayObject*)
      PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);

      EigenObjectAllocator<MatType>::convert(mat,pyArray);

      return NumpyType::getInstance().make(pyArray).ptr();
    }
  };

  /* --- FROM PYTHON ------------------------------------------------------------ */

  template<typename MatType>
  struct EigenFromPy
  {
    // Determine if obj_ptr can be converted in a Eigenvec
    static void* convertible(PyArrayObject* obj_ptr)
    {
      if (!PyArray_Check(obj_ptr))
        return 0;

      if(MatType::IsVectorAtCompileTime)
      {
        // Special care of scalar matrix of dimension 1x1.
        if(PyArray_DIMS(obj_ptr)[0] == 1 && PyArray_DIMS(obj_ptr)[1] == 1)
          return obj_ptr;

        if(PyArray_DIMS(obj_ptr)[0] > 1 && PyArray_DIMS(obj_ptr)[1] > 1)
        {
#ifndef NDEBUG
          std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl;
#endif
          return 0;
        }

        if(((PyArray_DIMS(obj_ptr)[0] == 1) && (MatType::ColsAtCompileTime == 1))
           || ((PyArray_DIMS(obj_ptr)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
        {
#ifndef NDEBUG
          if(MatType::ColsAtCompileTime == 1)
            std::cerr << "The object is not a column vector" << std::endl;
          else
            std::cerr << "The object is not a row vector" << std::endl;
#endif
          return 0;
        }
      }

      if (PyArray_NDIM(obj_ptr) != 2)
      {
        if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
        {
#ifndef NDEBUG
          std::cerr << "The number of dimension of the object is not correct." << std::endl;
#endif
          return 0;
        }
      }

      if (PyArray_NDIM(obj_ptr) == 2)
      {
        const int R = (int)PyArray_DIMS(obj_ptr)[0];
        const int C = (int)PyArray_DIMS(obj_ptr)[1];

        if( (MatType::RowsAtCompileTime!=R)
           && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
          return 0;
        if( (MatType::ColsAtCompileTime!=C)
           && (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
          return 0;
      }

      // Check if the Scalar type of the obj_ptr is compatible with the Scalar type of MatType
      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_INT)
      {
        if(not FromTypeToType<int,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (int) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_LONG)
      {
        if(not FromTypeToType<long,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (long) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_FLOAT)
      {
        if(not FromTypeToType<float,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (float) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_DOUBLE)
      {
        if(not FromTypeToType<double,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar (double) type cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision." << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0))
          != NumpyEquivalentType<typename MatType::Scalar>::type_code)
      {
#ifndef NDEBUG
        std::cerr << "The internal type as no Eigen equivalent." << std::endl;
#endif

        return 0;
      }

#ifdef NPY_1_8_API_VERSION
      if (!(PyArray_FLAGS(obj_ptr)))
#else
        if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
#endif
        {
#ifndef NDEBUG
          std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
#endif
          return 0;
        }

      return obj_ptr;
    }

    // Convert obj_ptr into an Eigen::Vector
    static void construct(PyObject* pyObj,
                          bp::converter::rvalue_from_python_stage1_data* memory)
    {
      using namespace Eigen;

      PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
      assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));

      void* storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
                       ((void*)memory))->storage.bytes;

      EigenObjectAllocator<MatType>::allocate(pyArray,storage);

      memory->convertible = storage;
    }
  };

#define numpy_import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } }

  template<typename MatType,typename EigenEquivalentType>
  void enableEigenPySpecific()
  {
    enableEigenPySpecific<MatType>();
  }

  template<typename MatType>
  struct EigenFromPyConverter
  {
    static void registration()
    {
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id<MatType>());

      // Add also conversion to Eigen::MatrixBase<MatType>
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id< Eigen::MatrixBase<MatType> >());
    }
  };

#if EIGEN_VERSION_AT_LEAST(3,2,0)
  /// Template specialization for Eigen::Ref
  template<typename MatType>
  struct EigenFromPyConverter< eigenpy::Ref<MatType> >
  {
    static void registration()
    {
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id<MatType>());
    }
  };
#endif

  template<typename MatType>
  void enableEigenPySpecific()
  {
    numpy_import_array();
    if(check_registration<MatType>()) return;

    bp::to_python_converter<MatType,EigenToPy<MatType> >();
    EigenFromPyConverter<MatType>::registration();

  }

} // namespace eigenpy

#endif // ifndef __eigenpy_details_hpp__
<commit_msg>core: comment not used lines<commit_after>/*
 * Copyright 2014-2019, CNRS
 * Copyright 2018-2019, INRIA
 */

#ifndef __eigenpy_details_hpp__
#define __eigenpy_details_hpp__

#include "eigenpy/fwd.hpp"

#include <patchlevel.h> // For PY_MAJOR_VERSION
#include <numpy/arrayobject.h>
#include <iostream>

#include "eigenpy/eigenpy.hpp"
#include "eigenpy/registration.hpp"
#include "eigenpy/map.hpp"

#define GET_PY_ARRAY_TYPE(array) PyArray_ObjectType(reinterpret_cast<PyObject *>(array), 0)

namespace eigenpy
{
  template <typename SCALAR>  struct NumpyEquivalentType {};
  template <> struct NumpyEquivalentType<double>  { enum { type_code = NPY_DOUBLE };};
  template <> struct NumpyEquivalentType<int>     { enum { type_code = NPY_INT    };};
  template <> struct NumpyEquivalentType<long>     { enum { type_code = NPY_LONG    };};
  template <> struct NumpyEquivalentType<float>   { enum { type_code = NPY_FLOAT  };};

  template <typename SCALAR1, typename SCALAR2>
  struct FromTypeToType : public boost::false_type {};

  template <typename SCALAR>
  struct FromTypeToType<SCALAR,SCALAR> : public boost::true_type {};

  template <> struct FromTypeToType<int,long> : public boost::true_type {};
  template <> struct FromTypeToType<int,float> : public boost::true_type {};
  template <> struct FromTypeToType<int,double> : public boost::true_type {};

  template <> struct FromTypeToType<long,float> : public boost::true_type {};
  template <> struct FromTypeToType<long,double> : public boost::true_type {};

  template <> struct FromTypeToType<float,double> : public boost::true_type {};

  namespace bp = boost::python;

  struct NumpyType
  {

    static NumpyType & getInstance()
    {
      static NumpyType instance;
      return instance;
    }

    operator bp::object () { return CurrentNumpyType; }

    bp::object make(PyArrayObject* pyArray, bool copy = false)
    { return make((PyObject*)pyArray,copy); }

    bp::object make(PyObject* pyObj, bool copy = false)
    {
      bp::object m;
      if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyMatrixType))
        m = NumpyMatrixObject(bp::object(bp::handle<>(pyObj)), bp::object(), copy);
//        m = NumpyAsMatrixObject(bp::object(bp::handle<>(pyObj)));
      else if(PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(CurrentNumpyType.ptr()),NumpyArrayType))
        m = bp::object(bp::handle<>(pyObj)); // nothing to do here

      Py_INCREF(m.ptr());
      return m;
    }

    static void setNumpyType(bp::object & obj)
    {
      PyTypeObject * obj_type = PyType_Check(obj.ptr()) ? reinterpret_cast<PyTypeObject*>(obj.ptr()) : obj.ptr()->ob_type;
      if(PyType_IsSubtype(obj_type,getInstance().NumpyMatrixType))
        getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
      else if(PyType_IsSubtype(obj_type,getInstance().NumpyArrayType))
        getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
    }

    static void switchToNumpyArray()
    {
      getInstance().CurrentNumpyType = getInstance().NumpyArrayObject;
    }

    static void switchToNumpyMatrix()
    {
      getInstance().CurrentNumpyType = getInstance().NumpyMatrixObject;
    }

  protected:
    NumpyType()
    {
      pyModule = bp::import("numpy");
#if PY_MAJOR_VERSION >= 3
      // TODO I don't know why this Py_INCREF is necessary.
      // Without it, the destructor of NumpyType SEGV sometimes.
      Py_INCREF(pyModule.ptr());
#endif

      NumpyMatrixObject = pyModule.attr("matrix");
      NumpyMatrixType = reinterpret_cast<PyTypeObject*>(NumpyMatrixObject.ptr());
      NumpyArrayObject = pyModule.attr("ndarray");
      NumpyArrayType = reinterpret_cast<PyTypeObject*>(NumpyArrayObject.ptr());
      //NumpyAsMatrixObject = pyModule.attr("asmatrix");
      //NumpyAsMatrixType = reinterpret_cast<PyTypeObject*>(NumpyAsMatrixObject.ptr());

      CurrentNumpyType = NumpyMatrixObject; // default conversion
    }

    bp::object CurrentNumpyType;
    bp::object pyModule;

    // Numpy types
    bp::object NumpyMatrixObject; PyTypeObject * NumpyMatrixType;
    //bp::object NumpyAsMatrixObject; PyTypeObject * NumpyAsMatrixType;
    bp::object NumpyArrayObject; PyTypeObject * NumpyArrayType;
  };

  template<typename MatType>
  struct EigenObjectAllocator
  {
    typedef MatType Type;
    typedef typename MatType::Scalar Scalar;

    static void allocate(PyArrayObject * pyArray, void * storage)
    {
      const int rows = (int)PyArray_DIMS(pyArray)[0];
      const int cols = (int)PyArray_DIMS(pyArray)[1];

      Type * mat_ptr = new(storage) Type(rows,cols);
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        *mat_ptr = MapNumpy<MatType,int>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        *mat_ptr = MapNumpy<MatType,long>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        *mat_ptr = MapNumpy<MatType,float>::map(pyArray).template cast<Scalar>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        *mat_ptr = MapNumpy<MatType,double>::map(pyArray).template cast<Scalar>();
    }

    static void convert(Type const & mat , PyArrayObject * pyArray)
    {
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
    }
  };

#if EIGEN_VERSION_AT_LEAST(3,2,0)
  template<typename MatType>
  struct EigenObjectAllocator< eigenpy::Ref<MatType> >
  {
    typedef eigenpy::Ref<MatType> Type;
    typedef typename MatType::Scalar Scalar;

    static void allocate(PyArrayObject * pyArray, void * storage)
    {
      typename MapNumpy<MatType,Scalar>::EigenMap numpyMap = MapNumpy<MatType,Scalar>::map(pyArray);
      new(storage) Type(numpyMap);
    }

    static void convert(Type const & mat , PyArrayObject * pyArray)
    {
      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_INT)
        MapNumpy<MatType,int>::map(pyArray) = mat.template cast<int>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_LONG)
        MapNumpy<MatType,long>::map(pyArray) = mat.template cast<long>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_FLOAT)
        MapNumpy<MatType,float>::map(pyArray) = mat.template cast<float>();

      if(GET_PY_ARRAY_TYPE(pyArray) == NPY_DOUBLE)
        MapNumpy<MatType,double>::map(pyArray) = mat.template cast<double>();
    }
  };
#endif

  /* --- TO PYTHON -------------------------------------------------------------- */
  template<typename MatType>
  struct EigenToPy
  {
    static PyObject* convert(MatType const& mat)
    {
      typedef typename MatType::Scalar T;
      assert( (mat.rows()<INT_MAX) && (mat.cols()<INT_MAX)
	      && "Matrix range larger than int ... should never happen." );
      const int R  = (int)mat.rows(), C = (int)mat.cols();

      npy_intp shape[2] = { R,C };
      PyArrayObject* pyArray = (PyArrayObject*)
      PyArray_SimpleNew(2, shape, NumpyEquivalentType<T>::type_code);

      EigenObjectAllocator<MatType>::convert(mat,pyArray);

      return NumpyType::getInstance().make(pyArray).ptr();
    }
  };

  /* --- FROM PYTHON ------------------------------------------------------------ */

  template<typename MatType>
  struct EigenFromPy
  {
    // Determine if obj_ptr can be converted in a Eigenvec
    static void* convertible(PyArrayObject* obj_ptr)
    {
      if (!PyArray_Check(obj_ptr))
        return 0;

      if(MatType::IsVectorAtCompileTime)
      {
        // Special care of scalar matrix of dimension 1x1.
        if(PyArray_DIMS(obj_ptr)[0] == 1 && PyArray_DIMS(obj_ptr)[1] == 1)
          return obj_ptr;

        if(PyArray_DIMS(obj_ptr)[0] > 1 && PyArray_DIMS(obj_ptr)[1] > 1)
        {
#ifndef NDEBUG
          std::cerr << "The number of dimension of the object does not correspond to a vector" << std::endl;
#endif
          return 0;
        }

        if(((PyArray_DIMS(obj_ptr)[0] == 1) && (MatType::ColsAtCompileTime == 1))
           || ((PyArray_DIMS(obj_ptr)[1] == 1) && (MatType::RowsAtCompileTime == 1)))
        {
#ifndef NDEBUG
          if(MatType::ColsAtCompileTime == 1)
            std::cerr << "The object is not a column vector" << std::endl;
          else
            std::cerr << "The object is not a row vector" << std::endl;
#endif
          return 0;
        }
      }

      if (PyArray_NDIM(obj_ptr) != 2)
      {
        if ( (PyArray_NDIM(obj_ptr) !=1) || (! MatType::IsVectorAtCompileTime) )
        {
#ifndef NDEBUG
          std::cerr << "The number of dimension of the object is not correct." << std::endl;
#endif
          return 0;
        }
      }

      if (PyArray_NDIM(obj_ptr) == 2)
      {
        const int R = (int)PyArray_DIMS(obj_ptr)[0];
        const int C = (int)PyArray_DIMS(obj_ptr)[1];

        if( (MatType::RowsAtCompileTime!=R)
           && (MatType::RowsAtCompileTime!=Eigen::Dynamic) )
          return 0;
        if( (MatType::ColsAtCompileTime!=C)
           && (MatType::ColsAtCompileTime!=Eigen::Dynamic) )
          return 0;
      }

      // Check if the Scalar type of the obj_ptr is compatible with the Scalar type of MatType
      if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_INT)
      {
        if(not FromTypeToType<int,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (int) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_LONG)
      {
        if(not FromTypeToType<long,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (long) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_FLOAT)
      {
        if(not FromTypeToType<float,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar type (float) cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision" << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0)) == NPY_DOUBLE)
      {
        if(not FromTypeToType<double,typename MatType::Scalar>::value)
        {
#ifndef NDEBUG
          std::cerr << "The Python matrix scalar (double) type cannot be converted into the scalar type of the Eigen matrix. Loss of arithmetic precision." << std::endl;
#endif
          return 0;
        }
      }
      else if ((PyArray_ObjectType(reinterpret_cast<PyObject *>(obj_ptr), 0))
          != NumpyEquivalentType<typename MatType::Scalar>::type_code)
      {
#ifndef NDEBUG
        std::cerr << "The internal type as no Eigen equivalent." << std::endl;
#endif

        return 0;
      }

#ifdef NPY_1_8_API_VERSION
      if (!(PyArray_FLAGS(obj_ptr)))
#else
        if (!(PyArray_FLAGS(obj_ptr) & NPY_ALIGNED))
#endif
        {
#ifndef NDEBUG
          std::cerr << "NPY non-aligned matrices are not implemented." << std::endl;
#endif
          return 0;
        }

      return obj_ptr;
    }

    // Convert obj_ptr into an Eigen::Vector
    static void construct(PyObject* pyObj,
                          bp::converter::rvalue_from_python_stage1_data* memory)
    {
      using namespace Eigen;

      PyArrayObject * pyArray = reinterpret_cast<PyArrayObject*>(pyObj);
      assert((PyArray_DIMS(pyArray)[0]<INT_MAX) && (PyArray_DIMS(pyArray)[1]<INT_MAX));

      void* storage = ((bp::converter::rvalue_from_python_storage<MatType>*)
                       ((void*)memory))->storage.bytes;

      EigenObjectAllocator<MatType>::allocate(pyArray,storage);

      memory->convertible = storage;
    }
  };

#define numpy_import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); } }

  template<typename MatType,typename EigenEquivalentType>
  void enableEigenPySpecific()
  {
    enableEigenPySpecific<MatType>();
  }

  template<typename MatType>
  struct EigenFromPyConverter
  {
    static void registration()
    {
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id<MatType>());

      // Add also conversion to Eigen::MatrixBase<MatType>
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id< Eigen::MatrixBase<MatType> >());
    }
  };

#if EIGEN_VERSION_AT_LEAST(3,2,0)
  /// Template specialization for Eigen::Ref
  template<typename MatType>
  struct EigenFromPyConverter< eigenpy::Ref<MatType> >
  {
    static void registration()
    {
      bp::converter::registry::push_back
      (reinterpret_cast<void *(*)(_object *)>(&EigenFromPy<MatType>::convertible),
       &EigenFromPy<MatType>::construct,bp::type_id<MatType>());
    }
  };
#endif

  template<typename MatType>
  void enableEigenPySpecific()
  {
    numpy_import_array();
    if(check_registration<MatType>()) return;

    bp::to_python_converter<MatType,EigenToPy<MatType> >();
    EigenFromPyConverter<MatType>::registration();

  }

} // namespace eigenpy

#endif // ifndef __eigenpy_details_hpp__
<|endoftext|>


<commit_before>/*****************************************************************************

    (c) 2013 Hobu, Inc. hobu.inc@gmail.com

    Author: Andrew Bell andrew.bell.ia at gmail.com

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#pragma once

#include <boost/function.hpp>
#include <vector>

#include "GridInfo.hpp"
#include "Path.hpp"

namespace hexer
{
    typedef boost::function<bool(double&, double&)> PointReader;
    typedef boost::function<bool(int&, int&)> HexReader;

    void process(const std::vector<GridInfo *>& infos, PointReader);
    void processHexes(const std::vector<GridInfo *>& infos, HexReader);
} // namespace hexer
<commit_msg>pass a void* ctx into the callback function so we can hang a member function as the reader<commit_after>/*****************************************************************************

    (c) 2013 Hobu, Inc. hobu.inc@gmail.com

    Author: Andrew Bell andrew.bell.ia at gmail.com

    This is free software; you can redistribute and/or modify it under the
    terms of the GNU Lesser General Licence as published by the Free Software
    Foundation. See the COPYING file for more information.

    This software is distributed WITHOUT ANY WARRANTY and without even the
    implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

*****************************************************************************/

#pragma once

#include <boost/function.hpp>
#include <vector>

#include "GridInfo.hpp"
#include "Path.hpp"

namespace hexer
{
    typedef boost::function<bool(double&, double&, void*)> PointReader;
    typedef boost::function<bool(int&, int&, void*)> HexReader;

    void process(const std::vector<GridInfo *>& infos, PointReader);
    void processHexes(const std::vector<GridInfo *>& infos, HexReader);
} // namespace hexer
<|endoftext|>


<commit_before>#include <cstdint>

#include <Mapper1.h>

uint8_t Mapper1::readPrg(uint16_t addr) {
    if (addr > 0x8000) {
	int index = decodePrgRomAddress(addr);
	return prg[index];
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	return ram[index];
    }
    else {
	return 0;
    }
}

void Mapper1::writePrg(uint16_t addr, uint8_t value) {
    if (addr > 0x8000) {
	if (value & 0x80) {
	    shiftRegister = 0x10;
	}
	else {
	    if (shiftRegister & 1) {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
		loadRegister(addr, value);
		shiftRegister = 0x10;
	    }
	    else {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
	    }
	}
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	ram[index] = value;
    }
}

uint8_t Mapper1::readChr(uint16_t addr) {
    int index = decodeChrRomAddress(addr);
    return chr[index];
}

void Mapper1::writeChr(uint16_t addr, uint8_t value) {
    if (chrIsRam) {
	int index = addr % chr.size();
        chr[index] = value;
    }
}

void Mapper1::loadRegister(uint16_t addr, uint8_t value) {
    if (addr >= 0xE000) {
	prgRomBank = value & 0b01111;
	prgRamDisable = !!(value & 0b10000);
    }
    else if (addr >= 0xC000) {
	chrRomBank1 = value & 0x1F;
    }
    else if (addr >= 0xA000) {
	chrRomBank0 = value & 0x1F;
    }
    else if (addr >= 0x8000) {
	switch(value & 0b00011) {
	case 0: mirroring = Mirroring::MIRROR_LOWER_BANK; break;
	case 1: mirroring = Mirroring::MIRROR_UPPER_BANK; break;
	case 2: mirroring = Mirroring::MIRROR_VERTICAL;   break;
	case 3: mirroring = Mirroring::MIRROR_HORIZONTAL; break;
	}
	switch(value & 0b01100) {
	case 0:
	case 1: prgMode = PrgMode::PRG_32KB;       break;
	case 2: prgMode = PrgMode::FIX_FIRST_16KB; break;
	case 3: prgMode = PrgMode::FIX_LAST_16KB;  break;
	}
	switch(value & 0b10000) {
	case 0: chrMode = ChrMode::CHR_8KB; break;
	case 1: chrMode = ChrMode::CHR_4KB; break;
	}
    }
    updateBankAddresses();
}

void Mapper1::updateBankAddresses() {
    switch (prgMode) {
    case PrgMode::PRG_32KB:
	prg16kBankAddresses[0] = (prgRomBank % 2) * 0x4000;
	prg16kBankAddresses[1] = (prgRomBank | 1) * 0x4000;
	break;
    case PrgMode::FIX_FIRST_16KB:
	prg16kBankAddresses[0] = 0;
	prg16kBankAddresses[1] = prgRomBank * 0x4000;
	break;
    case PrgMode::FIX_LAST_16KB:
	prg16kBankAddresses[0] = prgRomBank * 0x4000;
	prg16kBankAddresses[1] = prg.size() - 0x4000;
	break;
    }

    switch(chrMode) {
    case ChrMode::CHR_8KB:
	chr4kBankAddresses[0] = (chrRomBank0 % 2) * 0x1000;
	chr4kBankAddresses[1] = (chrRomBank0 | 1) * 0x1000;
	break;
    case ChrMode::CHR_4KB:
	chr4kBankAddresses[0] = chrRomBank0 * 0x1000;
	chr4kBankAddresses[1] = chrRomBank1 * 0x1000;
	break;
    }
}

int Mapper1::decodePrgRomAddress(uint16_t addr) {
    // int bankNum;
    // int offset;
    // if (prgMode == PrgMode::32KB_BANKS) {
    // 	offset = addr % 0x8000;
    // 	bankNum = prgRomBank & 0xFFFE;
    // }
    // else {
    // 	offset = addr % 0x4000;
    // 	if (addr >= 0xC000) {
    // 	    if (prgMode == PrgMode::FIX_LAST_16KB) {
    // 		bankNum = (prg.size() / 0x4000) - 1;
    // 	    }
    // 	    else {
    // 		bankNum = prgRomBank;
    // 	    }
    // 	}
    // 	else {
    // 	    if (prgMode == PrgMode::FIX_FIRST_16KB) {
    // 		bankNum = 0;
    // 	    }
    // 	    else {
    // 		bankNum = prgRomBank;
    // 	    }
    // 	}
    // }

    // int prgRomIndex = (bankNum*0x4000) + offset;
    // return prgRomIndex;
    return prg16kBankAddresses[addr & 0x4000] + (addr % 0x4000);
}

int Mapper1::decodeChrRomAddress(uint16_t addr) {
    // int bankNum;
    // int offset;
    // if (chrMode == ChrMode::8KB_BANKS) {
    // 	offset = addr % 0x2000;
    // 	bankNum = chrRomBank0 & 0xFFFE;
    // }
    // else {
    // 	offset = addr % 0x1000;
    // 	if (addr >= 0x1000) {
    // 	    bankNum = chrRomBank1;
    // 	}
    // 	else {
    // 	    bankNum = chrRomBank0;
    // 	}
    // }

    // int chrRomIndex = (bankNum*0x1000) + offset;
    // return chrRomIndex;
    return chr4kBankAddresses[addr & 0x1000] + (addr % 0x1000);
}
<commit_msg>Remove old mapper 1 comments<commit_after>#include <cstdint>

#include <Mapper1.h>

uint8_t Mapper1::readPrg(uint16_t addr) {
    if (addr > 0x8000) {
	int index = decodePrgRomAddress(addr);
	return prg[index];
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	return ram[index];
    }
    else {
	return 0;
    }
}

void Mapper1::writePrg(uint16_t addr, uint8_t value) {
    if (addr > 0x8000) {
	if (value & 0x80) {
	    shiftRegister = 0x10;
	}
	else {
	    if (shiftRegister & 1) {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
		loadRegister(addr, value);
		shiftRegister = 0x10;
	    }
	    else {
		shiftRegister >>= 1;
		shiftRegister |= ((value << 4) & 0x10);
	    }
	}
    }
    else if (addr > 0x6000) {
	int index = addr % 0x2000;
	ram[index] = value;
    }
}

uint8_t Mapper1::readChr(uint16_t addr) {
    int index = decodeChrRomAddress(addr);
    return chr[index];
}

void Mapper1::writeChr(uint16_t addr, uint8_t value) {
    if (chrIsRam) {
	int index = addr % chr.size();
        chr[index] = value;
    }
}

void Mapper1::loadRegister(uint16_t addr, uint8_t value) {
    if (addr >= 0xE000) {
	prgRomBank = value & 0b01111;
	prgRamDisable = !!(value & 0b10000);
    }
    else if (addr >= 0xC000) {
	chrRomBank1 = value & 0x1F;
    }
    else if (addr >= 0xA000) {
	chrRomBank0 = value & 0x1F;
    }
    else if (addr >= 0x8000) {
	switch(value & 0b00011) {
	case 0: mirroring = Mirroring::MIRROR_LOWER_BANK; break;
	case 1: mirroring = Mirroring::MIRROR_UPPER_BANK; break;
	case 2: mirroring = Mirroring::MIRROR_VERTICAL;   break;
	case 3: mirroring = Mirroring::MIRROR_HORIZONTAL; break;
	}
	switch(value & 0b01100) {
	case 0:
	case 1: prgMode = PrgMode::PRG_32KB;       break;
	case 2: prgMode = PrgMode::FIX_FIRST_16KB; break;
	case 3: prgMode = PrgMode::FIX_LAST_16KB;  break;
	}
	switch(value & 0b10000) {
	case 0: chrMode = ChrMode::CHR_8KB; break;
	case 1: chrMode = ChrMode::CHR_4KB; break;
	}
    }
    updateBankAddresses();
}

void Mapper1::updateBankAddresses() {
    switch (prgMode) {
    case PrgMode::PRG_32KB:
	prg16kBankAddresses[0] = (prgRomBank % 2) * 0x4000;
	prg16kBankAddresses[1] = (prgRomBank | 1) * 0x4000;
	break;
    case PrgMode::FIX_FIRST_16KB:
	prg16kBankAddresses[0] = 0;
	prg16kBankAddresses[1] = prgRomBank * 0x4000;
	break;
    case PrgMode::FIX_LAST_16KB:
	prg16kBankAddresses[0] = prgRomBank * 0x4000;
	prg16kBankAddresses[1] = prg.size() - 0x4000;
	break;
    }

    switch(chrMode) {
    case ChrMode::CHR_8KB:
	chr4kBankAddresses[0] = (chrRomBank0 % 2) * 0x1000;
	chr4kBankAddresses[1] = (chrRomBank0 | 1) * 0x1000;
	break;
    case ChrMode::CHR_4KB:
	chr4kBankAddresses[0] = chrRomBank0 * 0x1000;
	chr4kBankAddresses[1] = chrRomBank1 * 0x1000;
	break;
    }
}

int Mapper1::decodePrgRomAddress(uint16_t addr) {
    return prg16kBankAddresses[addr & 0x4000] + (addr % 0x4000);
}

int Mapper1::decodeChrRomAddress(uint16_t addr) {
    return chr4kBankAddresses[addr & 0x1000] + (addr % 0x1000);
}
<|endoftext|>


<commit_before>#pragma once

#include <type_traits>

#include "detail/utils.hpp"

namespace kgr {

struct Single {
	Single() = default;
	~Single() = default;
	Single(const Single&) = delete;
	Single& operator=(const Single&) = delete;
	Single(Single&&) = default;
	Single& operator=(Single&&) = default;
};

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

template<typename... Args>
struct Dependency {};

namespace detail {

template<typename T>
struct InjectType {
	using Type = typename std::conditional<std::is_base_of<Single, T>::value, T&, T&&>::type;
};

template<typename T> using InjectType_t = typename InjectType<T>::Type;

template<typename...>
struct Injector;

template<typename CRTP, typename... Deps>
struct Injector<CRTP, Dependency<Deps...>> {
	static CRTP construct(InjectType_t<Deps>... deps) {
		using C = typename CRTP::C;
		return C::makeService(deps.forward()...);
	}
};

template<typename CRTP>
struct Injector<CRTP> {
	static CRTP construct() {
		using C = typename CRTP::C;
		return C::makeService();
	}
};

template<typename CRTP, typename ContainedType>
struct BaseGenericService {
	BaseGenericService() = default;
	BaseGenericService(BaseGenericService&&) = default;
	BaseGenericService(const BaseGenericService&) = default;
	BaseGenericService& operator=(const BaseGenericService&) = default;
	BaseGenericService(ContainedType instance) {
		setInstance(std::move(instance));
	}

	~BaseGenericService() {
		if (_initiated) {
			getInstance().~ContainedType();
		}
	}

	template<typename T, typename = typename std::enable_if<std::is_base_of<CRTP, T>::value>::type>
	operator T () const & {
		T service;

		if (_initiated) {
			service.setInstance(getInstance());
		}

		return service;
	}

	template<typename T, typename = typename std::enable_if<std::is_base_of<CRTP, T>::value>::type>
	operator T () && {
		T service;

		if (_initiated) {
			service.setInstance(std::move(getInstance()));
		}

		return service;
	}

protected:
	ContainedType& getInstance() {
		return *reinterpret_cast<ContainedType*>(&_instance);
	}

	template<typename F, F f, typename... T>
	void autocall(InjectType_t<T>... others) {
		(getInstance().*f)(others.forward()...);
	}

private:
	void setInstance(ContainedType instance) {
		new (&_instance) ContainedType(std::move(instance));
		_initiated = true;
	}

	bool _initiated = false;
	typename std::aligned_storage<sizeof(ContainedType), alignof(ContainedType)>::type _instance;
};

template<typename Original, typename Service>
struct ServiceOverride : Service {
    virtual ~ServiceOverride() {}
    ServiceOverride(Original& service) : _service {service} {}

    ServiceType<Service> forward() override {
        return static_cast<ServiceType<Service>>(_service.forward());
    }

private:
    Original& _service;
};

}

template<typename...>
struct GenericService;

template<typename CRTP, typename ContainedType, typename... Deps>
struct GenericService<CRTP, ContainedType, Dependency<Deps...>> :
                detail::Injector<GenericService<CRTP, ContainedType, Dependency<Deps...>>, Dependency<Deps...>>,
                detail::BaseGenericService<CRTP, ContainedType>
{
    template<typename...> friend struct detail::Injector;
    using Self = GenericService<CRTP, ContainedType, Dependency<Deps...>>;
    using detail::BaseGenericService<CRTP, ContainedType>::BaseGenericService;

private:
    using C = CRTP;
};

template<typename CRTP, typename ContainedType>
struct GenericService<CRTP, ContainedType> :
        detail::Injector<GenericService<CRTP, ContainedType>>,
                detail::BaseGenericService<CRTP, ContainedType>
{
    template<typename...> friend struct detail::Injector;
    using Self = GenericService<CRTP, ContainedType>;
    using detail::BaseGenericService<CRTP, ContainedType>::BaseGenericService;

private:
    using C = CRTP;
};

template<typename...>
struct SingleService;

template<typename Type>
struct SingleService<Type> : GenericService<SingleService<Type>, Type>, Single {
    using Parent = GenericService<SingleService<Type>, Type>;
    virtual ~SingleService() = default;
    SingleService() = default;
    SingleService(SingleService&&) = default;
    SingleService& operator=(SingleService&&) = default;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    virtual Type& forward() {
        return this->getInstance();
    }
};

template<typename Type, typename... Deps>
struct SingleService<Type, Dependency<Deps...>> : GenericService<SingleService<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>, Single {
    using Parent = GenericService<SingleService<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>;
    virtual ~SingleService() = default;
    SingleService() = default;
    SingleService(SingleService&&) = default;
    SingleService& operator=(SingleService&&) = default;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent(Type(std::forward<Args>(args)...));
    }

    virtual Type& forward() {
        return this->getInstance();
    }
};

template<typename...>
struct Service;

template<typename Type>
struct Service<Type> : GenericService<Service<Type>, Type> {
    using Parent = GenericService<Service<Type>, Type>;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    Type forward() {
        return std::move(this->getInstance());
    }
};

template<typename Type, typename... Deps>
struct Service<Type, Dependency<Deps...>> : GenericService<Service<Type, Dependency<Deps...>>, Type, Dependency<Deps...>> {
    using Parent = GenericService<Service<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    Type forward() {
        return std::move(this->getInstance());
    }
};

template<typename T>
struct AbstractService : Single {
    virtual T& forward() = 0;
};

}
<commit_msg>fix copy and move constructor not being called<commit_after>#pragma once

#include <type_traits>

#include "detail/utils.hpp"

namespace kgr {

struct Single {
	Single() = default;
	~Single() = default;
	Single(const Single&) = delete;
	Single& operator=(const Single&) = delete;
	Single(Single&&) = default;
	Single& operator=(Single&&) = default;
};

template<typename... Types>
struct Overrides : Single {
	using ParentTypes = std::tuple<Types...>;
};

template<typename... Args>
struct Dependency {};

namespace detail {

template<typename T> using InjectType_t = typename std::conditional<std::is_base_of<Single, T>::value, T&, T&&>::type;

template<typename...>
struct Injector;

template<typename CRTP, typename... Deps>
struct Injector<CRTP, Dependency<Deps...>> {
	static CRTP construct(InjectType_t<Deps>... deps) {
		using C = typename CRTP::C;
		return C::makeService(deps.forward()...);
	}
};

template<typename CRTP>
struct Injector<CRTP> {
	static CRTP construct() {
		using C = typename CRTP::C;
		return C::makeService();
	}
};

template<typename CRTP, typename ContainedType>
struct BaseGenericService {
	BaseGenericService() = default;

    BaseGenericService(BaseGenericService&& other) {
		setInstance(std::move(other.getInstance()));
    }

    BaseGenericService& operator=(BaseGenericService&& other) {
		setInstance(std::move(other.getInstance()));
		return *this;
    }

	BaseGenericService(const BaseGenericService& other) {
		setInstance(other.getInstance());
	}

	BaseGenericService& operator=(const BaseGenericService& other) {
		setInstance(other.getInstance());
		return *this;
	}

	BaseGenericService(ContainedType instance) {
		setInstance(std::move(instance));
	}

	~BaseGenericService() {
		if (_initiated) {
			getInstance().~ContainedType();
		}
	}

	template<typename T, typename = typename std::enable_if<std::is_base_of<CRTP, T>::value>::type>
	operator T () const & {
		T service;

		if (_initiated) {
			service.setInstance(getInstance());
		}

		return service;
	}

	template<typename T, typename = typename std::enable_if<std::is_base_of<CRTP, T>::value>::type>
	operator T () && {
		T service;

		if (_initiated) {
			service.setInstance(std::move(getInstance()));
		}

		return service;
	}

protected:
	ContainedType& getInstance() {
		return *reinterpret_cast<ContainedType*>(&_instance);
	}

	template<typename F, F f, typename... T>
	void autocall(InjectType_t<T>... others) {
		(getInstance().*f)(others.forward()...);
	}

private:
	void setInstance(ContainedType instance) {
		new (&_instance) ContainedType(std::move(instance));
		_initiated = true;
	}

	bool _initiated = false;
	typename std::aligned_storage<sizeof(ContainedType), alignof(ContainedType)>::type _instance;
};

template<typename Original, typename Service>
struct ServiceOverride : Service {
    virtual ~ServiceOverride() {}
    ServiceOverride(Original& service) : _service {service} {}

    ServiceType<Service> forward() override {
        return static_cast<ServiceType<Service>>(_service.forward());
    }

private:
    Original& _service;
};

}

template<typename...>
struct GenericService;

template<typename CRTP, typename ContainedType, typename... Deps>
struct GenericService<CRTP, ContainedType, Dependency<Deps...>> :
                detail::Injector<GenericService<CRTP, ContainedType, Dependency<Deps...>>, Dependency<Deps...>>,
                detail::BaseGenericService<CRTP, ContainedType>
{
    template<typename...> friend struct detail::Injector;
    using Self = GenericService<CRTP, ContainedType, Dependency<Deps...>>;
    using detail::BaseGenericService<CRTP, ContainedType>::BaseGenericService;

private:
    using C = CRTP;
};

template<typename CRTP, typename ContainedType>
struct GenericService<CRTP, ContainedType> :
        detail::Injector<GenericService<CRTP, ContainedType>>,
                detail::BaseGenericService<CRTP, ContainedType>
{
    template<typename...> friend struct detail::Injector;
    using Self = GenericService<CRTP, ContainedType>;
    using detail::BaseGenericService<CRTP, ContainedType>::BaseGenericService;

private:
    using C = CRTP;
};

template<typename...>
struct SingleService;

template<typename Type>
struct SingleService<Type> : GenericService<SingleService<Type>, Type>, Single {
    using Parent = GenericService<SingleService<Type>, Type>;
    virtual ~SingleService() = default;
    SingleService() = default;
    SingleService(SingleService&&) = default;
    SingleService& operator=(SingleService&&) = default;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    virtual Type& forward() {
        return this->getInstance();
    }
};

template<typename Type, typename... Deps>
struct SingleService<Type, Dependency<Deps...>> : GenericService<SingleService<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>, Single {
    using Parent = GenericService<SingleService<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>;
    virtual ~SingleService() = default;
    SingleService() = default;
    SingleService(SingleService&&) = default;
    SingleService& operator=(SingleService&&) = default;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent(Type(std::forward<Args>(args)...));
    }

    virtual Type& forward() {
        return this->getInstance();
    }
};

template<typename...>
struct Service;

template<typename Type>
struct Service<Type> : GenericService<Service<Type>, Type> {
    using Parent = GenericService<Service<Type>, Type>;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    Type forward() {
        return std::move(this->getInstance());
    }
};

template<typename Type, typename... Deps>
struct Service<Type, Dependency<Deps...>> : GenericService<Service<Type, Dependency<Deps...>>, Type, Dependency<Deps...>> {
    using Parent = GenericService<Service<Type, Dependency<Deps...>>, Type, Dependency<Deps...>>;

    template<typename... Args>
    static Parent makeService(Args&&... args) {
        return Parent {Type{std::forward<Args>(args)...}};
    }

    Type forward() {
        return std::move(this->getInstance());
    }
};

template<typename T>
struct AbstractService : Single {
    virtual T& forward() = 0;
};

}
<|endoftext|>