<commit_before>#include "Quadrant.h"
#include <iostream>
#include "Globals.h"
#include <string>
#include <time.h>

Quadrant::Quadrant(QuadrantCoordinates* coordinates, double locationIntensity):particles()
{
	this->coordinates = coordinates;
	this->locationIntensity = locationIntensity;
	glm::vec3 v = glm::vec3(0.0,0.0,0.0);
	this->influenceVector = new InfluenceVector(0, glm::vec3(0.0,0.0,0.0));
	this->calculateInfluenceVector();
	srand((unsigned) time(NULL));
}

std::vector<Particle> Quadrant::getParticles()
{
	return std::vector<Particle>();
}

void Quadrant::addParticle(Particle *particle)
{
	this->particles.push_back(particle);
}

void Quadrant::clearParticles()
{
	this->particles.clear();
}

void Quadrant::setParticles(std::vector<Particle*> particles)
{
	this->particles = particles;
	this->calculateIntensity();
}

void Quadrant::calculateInfluenceVector()
{
	float x = -1 * this->coordinates->getX();
	float y = -1 * this->coordinates->getY();
	float z = -1 * this->coordinates->getZ();
	this->influenceVector->setVector(glm::vec3(x,y,z));
	this->influenceVector->setIntensity(this->calculateIntensity());
}

double Quadrant::calculateIntensity()
{
	double particle_influence = (double)this->particles.size() * PARTICLE_INFLUENCE;
	if (DEBUG) {
		std::cout
			<< "Q("
			<< this->coordinates->getX()
			<< ","
			<< this->coordinates->getY()
			<< ","
			<< this->coordinates->getZ()
			<< ") Intensity: "
			<< particle_influence + this->locationIntensity
			<< std::endl;
	}
	return this->locationIntensity + particle_influence;
}

glm::vec3 Quadrant::getPossibleDirections(Particle* p)
{
	float DimHalf = DIMENSION_LENGTH / 2;
	float x = getRandomFloat(-DimHalf + p->getBasePosition().x,
							 DimHalf - p->getBasePosition().x);
	float y = getRandomFloat(-DimHalf + p->getBasePosition().y,
							 DimHalf - p->getBasePosition().y);
	float z = getRandomFloat(-DimHalf + p->getBasePosition().z,
							 DimHalf - p->getBasePosition().z);
	return glm::vec3(x, y, z);
}

float Quadrant::getRandomFloat(float min, float max)
{
	float f = (float)rand() / RAND_MAX;
	return min + f * (max - min);
}

int Quadrant::getRandomInt(int min, int max)
{
	return std::rand() % (int) max - min;
}

void Quadrant::applyInflueneceVector()
{

	if (this->particles.size() >= THRESHOLD)
	{
		if (getRandomInt(1, 20) == 20)
			for (int i = 0; i < particles.size(); i++)
				particles[i]->addToDirectionVector(getPossibleDirections(this->particles[i]));
	}
	else
		for (int i = 0; i < particles.size(); i++)
			particles[i]->addToDirectionVector(this->influenceVector->getEffectiveVector(this->particles));
}

Quadrant::~Quadrant(void)
{
	delete coordinates;
}
<commit_msg>added DEBUG_FLAG<commit_after>#include "Quadrant.h"
#include <iostream>
#include "Globals.h"
#include <string>
#include <time.h>

Quadrant::Quadrant(QuadrantCoordinates* coordinates, double locationIntensity):particles()
{
	this->coordinates = coordinates;
	this->locationIntensity = locationIntensity;
	glm::vec3 v = glm::vec3(0.0,0.0,0.0);
	this->influenceVector = new InfluenceVector(0, glm::vec3(0.0,0.0,0.0));
	this->calculateInfluenceVector();
	srand((unsigned) time(NULL));
}

std::vector<Particle> Quadrant::getParticles()
{
	return std::vector<Particle>();
}

void Quadrant::addParticle(Particle *particle)
{
	this->particles.push_back(particle);
}

void Quadrant::clearParticles()
{
	this->particles.clear();
}

void Quadrant::setParticles(std::vector<Particle*> particles)
{
	this->particles = particles;
	this->calculateIntensity();
}

void Quadrant::calculateInfluenceVector()
{
	float x = -1 * this->coordinates->getX();
	float y = -1 * this->coordinates->getY();
	float z = -1 * this->coordinates->getZ();
	this->influenceVector->setVector(glm::vec3(x,y,z));
	this->influenceVector->setIntensity(this->calculateIntensity());
}

double Quadrant::calculateIntensity()
{
	double particle_influence = (double)this->particles.size() * PARTICLE_INFLUENCE;
	if (DEBUG_FLAG) {
		std::cout
			<< "Q("
			<< this->coordinates->getX()
			<< ","
			<< this->coordinates->getY()
			<< ","
			<< this->coordinates->getZ()
			<< ") Intensity: "
			<< particle_influence + this->locationIntensity
			<< std::endl;
	}
	return this->locationIntensity + particle_influence;
}

glm::vec3 Quadrant::getPossibleDirections(Particle* p)
{
	float DimHalf = DIMENSION_LENGTH / 2;
	float x = getRandomFloat(-DimHalf + p->getBasePosition().x,
							 DimHalf - p->getBasePosition().x);
	float y = getRandomFloat(-DimHalf + p->getBasePosition().y,
							 DimHalf - p->getBasePosition().y);
	float z = getRandomFloat(-DimHalf + p->getBasePosition().z,
							 DimHalf - p->getBasePosition().z);
	return glm::vec3(x, y, z);
}

float Quadrant::getRandomFloat(float min, float max)
{
	float f = (float)rand() / RAND_MAX;
	return min + f * (max - min);
}

int Quadrant::getRandomInt(int min, int max)
{
	return std::rand() % (int) max - min;
}

void Quadrant::applyInflueneceVector()
{

	if (this->particles.size() >= THRESHOLD)
	{
		if (getRandomInt(1, 20) == 20)
			for (int i = 0; i < particles.size(); i++)
				particles[i]->addToDirectionVector(getPossibleDirections(this->particles[i]));
	}
	else
		for (int i = 0; i < particles.size(); i++)
			particles[i]->addToDirectionVector(this->influenceVector->getEffectiveVector(this->particles));
}

Quadrant::~Quadrant(void)
{
	delete coordinates;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: resultcolumn.hxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2006-06-20 02:40:45 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _DBACORE_RESULTCOLUMN_HXX_
#define _DBACORE_RESULTCOLUMN_HXX_

#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_
#include <com/sun/star/sdbc/XResultSetMetaData.hdl>
#endif
#ifndef _DBA_COREAPI_COLUMN_HXX_
#include <column.hxx>
#endif
namespace dbaccess
{
    //************************************************************
    //  OResultColumn
    //************************************************************
    class OResultColumn : public OColumn,
                          public ::comphelper::OPropertyArrayUsageHelper < OResultColumn >
    {
    protected:
        ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >   m_xDBMetaData;
        sal_Int32                   m_nPos;
        ::com::sun::star::uno::Any  m_aIsRowVersion;

        virtual ~OResultColumn();
    public:
        OResultColumn(
            const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData,
            sal_Int32 _nPos,
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta );

    // com::sun::star::lang::XTypeProvider
        virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException);

    // com::sun::star::lang::XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

    // cppu::OComponentHelper
        virtual void SAL_CALL disposing(void);

    // comphelper::OPropertyArrayUsageHelper
        virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    // cppu::OPropertySetHelper
        virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
        virtual void SAL_CALL getFastPropertyValue(
                                    ::com::sun::star::uno::Any& rValue,
                                    sal_Int32 nHandle
                                         ) const;

    private:
        void    impl_determineIsRowVersion_nothrow();

    protected:
        using ::cppu::OPropertySetHelper::getFastPropertyValue;
    };
}
#endif // _DBACORE_RESULTCOLUMN_HXX_

<commit_msg>INTEGRATION: CWS changefileheader (1.7.308); FILE MERGED 2008/03/31 13:26:44 rt 1.7.308.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: resultcolumn.hxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org 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 version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef _DBACORE_RESULTCOLUMN_HXX_
#define _DBACORE_RESULTCOLUMN_HXX_

#ifndef _COM_SUN_STAR_SDBC_XRESULTSETMETADATA_HDL_
#include <com/sun/star/sdbc/XResultSetMetaData.hdl>
#endif
#ifndef _DBA_COREAPI_COLUMN_HXX_
#include <column.hxx>
#endif
namespace dbaccess
{
    //************************************************************
    //  OResultColumn
    //************************************************************
    class OResultColumn : public OColumn,
                          public ::comphelper::OPropertyArrayUsageHelper < OResultColumn >
    {
    protected:
        ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData > m_xMetaData;
        ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >   m_xDBMetaData;
        sal_Int32                   m_nPos;
        ::com::sun::star::uno::Any  m_aIsRowVersion;

        virtual ~OResultColumn();
    public:
        OResultColumn(
            const ::com::sun::star::uno::Reference < ::com::sun::star::sdbc::XResultSetMetaData >& _xMetaData,
            sal_Int32 _nPos,
            const ::com::sun::star::uno::Reference< ::com::sun::star::sdbc::XDatabaseMetaData >& _rxDBMeta );

    // com::sun::star::lang::XTypeProvider
        virtual ::com::sun::star::uno::Sequence< sal_Int8 > SAL_CALL getImplementationId() throw (::com::sun::star::uno::RuntimeException);

    // com::sun::star::lang::XServiceInfo
        virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw(::com::sun::star::uno::RuntimeException);
        virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw(::com::sun::star::uno::RuntimeException);

    // cppu::OComponentHelper
        virtual void SAL_CALL disposing(void);

    // comphelper::OPropertyArrayUsageHelper
        virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const;

    // cppu::OPropertySetHelper
        virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper();
        virtual void SAL_CALL getFastPropertyValue(
                                    ::com::sun::star::uno::Any& rValue,
                                    sal_Int32 nHandle
                                         ) const;

    private:
        void    impl_determineIsRowVersion_nothrow();

    protected:
        using ::cppu::OPropertySetHelper::getFastPropertyValue;
    };
}
#endif // _DBACORE_RESULTCOLUMN_HXX_

<|endoftext|>


<commit_before>//Mancala AI
//Copyright Matthew Chandler 2012

#include <iostream>
#include <iomanip>
#include <vector>
#include <limits>
#include <cstdlib>

#include "mancala.h"

//board:
//2 rows of 6 bowls
//2 larger bowls for scoring (stores)
//
//Rules
//play is CCW
//ending in player's own store yields extra turn
//ending in empty bowl earns that piece and all those in the bowl across from it
//game ends when a player has no legal moves left
//
//good heuristics:
//score - opponent's score
//possibly good:
//number of availible moves
//seeds in play
//seed distribution (large piles waiting to be collected? seed ratio between sides)
//possibilty of extra turns
//if we wanted to, we could use a genetic algorithm for determining the importance of each of these
//
//representation
//circular array?
//  11 10 9  8  7  6
//  0  1  2  3  4  5
//  p1 store, p2 store
//From there, we would need logic to add to player's own store and skip the opponents.
//if we abstract out the actual array indexes, we can use 2 starting pointers to easily flip the board
//With that in mind, it might be better to use a Digraph, so we can have a truly circular setup
//each node could have a next, prev, and across pointer, and one that points to the stores for the ends (NULL otherwise)
//
//
//
//If we wanted to get really fancy, we could do 3D graphics with particle physics for the seeds.

Board::Board(const int Num_bowls, const int Num_seeds):
num_bowls(Num_bowls), num_seeds(Num_seeds)
{
    bowls.resize(2 * num_bowls + 2);
    p1_start = 0;
    p1_store = num_bowls;
    p2_start = num_bowls + 1;
    p2_store = 2 * num_bowls + 1;

    for(size_t i = 0; i < bowls.size(); ++i)
    {
        if(i < bowls.size() - 1)
            bowls[i].next = i + 1;
        else
            bowls[i].next = 0;

        if(i != (size_t)num_bowls && i != 2 * (size_t)num_bowls + 1)
        {
            bowls[i].across = 2 * num_bowls - i;
            bowls[i].count = num_seeds;
        }
    }
}
//
//perform a move
//returns true if the move earns an extra turn
bool Board::move(int bowl)
{
    if(bowl < 0 || bowl >= num_bowls)
        return false;
    bowl += p1_start;
    int seeds = bowls[bowl].count;
    if(seeds == 0)
        return false;
    bowls[bowl].count = 0;
    //make the move
    for(int i = 0; i < seeds; ++i)
    {
        bowl = bowls[bowl].next;
        if(bowl == p2_store)
            bowl = bowls[bowl].next;
        bowls[bowl].count += 1;
    }
    //extra turn if we land in our own store
    if(bowl == p1_store)
        return true;

    //if we land in an empty bowl, we get the last seed sown and all the seeds from the bowl across
    if(bowls[bowl].count == 1 && bowls[bowls[bowl].across].count > 0)
    {
        bowls[p1_store].count += 1 + bowls[bowls[bowl].across].count;
        bowls[bowls[bowl].across].count = 0;
        bowls[bowl].count = 0;
    }
    return false;
}

//swap sides of the board
void Board::swapsides()
{
    std::swap(p1_start, p2_start);
    std::swap(p1_store, p2_store);
}

//is the game over
bool Board::finished() const
{
    int p1_side = 0;
    for(int i = p1_start; i < p1_start + 6; ++i)
        p1_side |= bowls[i].count;
    if(p1_side == 0)
        return true;
    int p2_side = 0;
    for(int i = p2_start; i < p2_start + 6; ++i)
        p2_side |= bowls[i].count;
    return p2_side == 0;
}

//heuristics to evaluate the board status
int Board::evaluate() const
{
    //simple
    return bowls[p1_store].count - bowls[p2_store].count;
}

void Board::crapprint() const //delete me!
{
    std::cout<<"    ";
    for(int i = p1_start; i < p1_start + 6; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[bowls[i].across].count<<" ";
    std::cout<<std::endl;
    std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[p2_store].count<<std::setw(3*7)<<" "<<std::setw(2)<<bowls[p1_store].count<<std::endl;
    std::cout<<"    ";
    for(int i = p1_start; i < p1_start + 6; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[i].count<<" ";
    std::cout<<std::endl;
    std::cout<<"    ";
    for(int i = 0; i < 6 ; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<i<<" ";
    std::cout<<std::endl;
}

enum PLAYER {PLAYER_MIN, PLAYER_MAX};

int choosemove_alphabeta(Board b, int depth, PLAYER player, int alpha, int beta)
{
    if(player == PLAYER_MAX)
    {
        if(depth == 0)
            return b.evaluate();
        //move toward closest win, avoid loss as long as possible
        if(b.finished())
        {
            int diff = b.evaluate();
            if(diff == 0)
                return depth;
            else if(diff > 0)
                return 1000 + diff + depth;
            else
                return -1000 + diff - depth;
        }
        for(int i = 0; i < 6; ++i)
        {
            if(b.bowls[b.p1_start + i].count == 0)
                continue;
            Board sub_b = b;
            int score = 0;
            if(sub_b.move(i)) // do we get another move?
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MAX, alpha, beta);
            else
            {
                sub_b.swapsides();
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MIN, alpha, beta);
            }
            if(score >= beta)
                return beta;
            if(score > alpha)
                alpha = score;
        }
        return alpha;
    }
    else
    {
        if(depth == 0)
            return -b.evaluate();
        //move toward closest win, avoid loss as long as possible
        if(b.finished())
        {
            int diff = b.evaluate();
            if(diff == 0)
                return -depth;
            else if(diff > 0)
                return -1000 - diff - depth;
            else
                return 1000 - diff + depth;
        }
        for(int i = 0; i < 6; ++i)
        {
            if(b.bowls[b.p1_start + i].count == 0)
                continue;
            Board sub_b = b;
            int score = 0;
            if(sub_b.move(i)) // do we get another move?
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MIN, alpha, beta);
            else
            {
                sub_b.swapsides();
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MAX, alpha, beta);
            }
            if(score <= alpha)
                return alpha;
            if(score < beta)
                beta = score;
        }
        return beta;
    }
}

int choosemove(Board b) //purposely doing pass by value here as to not corrupt passed board
{
    int best = std::numeric_limits<int>::min();
    std::vector<int> best_i;
    //loop over available moves
    for(int i =0; i < 6; ++i)
    {
        if(b.bowls[b.p1_start + i].count == 0)
            continue;
        Board sub_b = b;
        int score = 0;
        if(sub_b.move(i))
            score = choosemove_alphabeta(sub_b, 10, PLAYER_MAX, std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
        else
        {
            sub_b.swapsides();
            score = choosemove_alphabeta(sub_b, 10, PLAYER_MIN, std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
        }
        //std::cout<<"choose: "<<i<<" "<<score<<" "<<-sub_b.evaluate()<<std::endl;
        if(score > best)
        {
            best = score;
            best_i.clear();
            best_i.push_back(i);
        }
        if(score == best);
            best_i.push_back(i);
    }
    return best_i[rand() % best_i.size()];
}

int main()
{
    srand(time(0));
    Board b;
    //b.bowls=std::vector<Bowl>({Bowl(1,1,12), Bowl(0,2,11), Bowl(0,3,10), Bowl(0,4,9), Bowl(2,5,8), Bowl(1,6,7), Bowl(0,7,0), Bowl(0,8,5), Bowl(0,9,4), Bowl(0,10,3), Bowl(0,11,2), Bowl(0,12,1), Bowl(1,13,0), Bowl(0,0,0)});
    char nextmove = '\0';
    int player = 1;
    while(std::cin && !b.finished() && nextmove != 'q' && nextmove != 'Q')
    {
        std::cout<<"Player "<<player<<std::endl;
        b.crapprint();
        std::cout<<"Best move: "<<choosemove(b)<<std::endl;
        std::cout<<"Next move: ";
        std::cin>>nextmove;
        std::cout<<std::endl;
        if(nextmove == 'S' || nextmove == 's')
        {
            b.swapsides();
            player = (player == 1) ? 2 : 1;
        }
        if(nextmove >= '0' && nextmove <= '5')
        {
            if(!b.move(nextmove - '0'))
            {
                b.swapsides();
                player = (player == 1) ? 2 : 1;
            }
        }
    }
    if(b.finished())
    {
        std::cout<<"Player "<<player<<std::endl;
        b.crapprint();
        if(b.bowls[b.p1_store].count == b.bowls[b.p2_store].count)
            std::cout<<"Tie"<<std::endl;
        else if(player == 1)
            if(b.bowls[b.p1_store].count > b.bowls[b.p2_store].count)
                std::cout<<"Player 1 wins"<<std::endl;
            else
                std::cout<<"Player 2 wins"<<std::endl;
        else
            if(b.bowls[b.p1_store].count > b.bowls[b.p2_store].count)
                std::cout<<"Player 2 wins"<<std::endl;
            else
                std::cout<<"Player 1 wins"<<std::endl;
        if(abs(b.bowls[b.p1_store].count - b.bowls[b.p2_store].count) >= 10)
            std::cout<<"FATALITY"<<std::endl;
    }
    return 0;
}
<commit_msg>made choosemove board param const<commit_after>//Mancala AI
//Copyright Matthew Chandler 2012

#include <iostream>
#include <iomanip>
#include <vector>
#include <limits>
#include <cstdlib>

#include "mancala.h"

//board:
//2 rows of 6 bowls
//2 larger bowls for scoring (stores)
//
//Rules
//play is CCW
//ending in player's own store yields extra turn
//ending in empty bowl earns that piece and all those in the bowl across from it
//game ends when a player has no legal moves left
//
//good heuristics:
//score - opponent's score
//possibly good:
//number of availible moves
//seeds in play
//seed distribution (large piles waiting to be collected? seed ratio between sides)
//possibilty of extra turns
//if we wanted to, we could use a genetic algorithm for determining the importance of each of these
//
//representation
//circular array?
//  11 10 9  8  7  6
//  0  1  2  3  4  5
//  p1 store, p2 store
//From there, we would need logic to add to player's own store and skip the opponents.
//if we abstract out the actual array indexes, we can use 2 starting pointers to easily flip the board
//With that in mind, it might be better to use a Digraph, so we can have a truly circular setup
//each node could have a next, prev, and across pointer, and one that points to the stores for the ends (NULL otherwise)
//
//
//
//If we wanted to get really fancy, we could do 3D graphics with particle physics for the seeds.

Board::Board(const int Num_bowls, const int Num_seeds):
num_bowls(Num_bowls), num_seeds(Num_seeds)
{
    bowls.resize(2 * num_bowls + 2);
    p1_start = 0;
    p1_store = num_bowls;
    p2_start = num_bowls + 1;
    p2_store = 2 * num_bowls + 1;

    for(size_t i = 0; i < bowls.size(); ++i)
    {
        if(i < bowls.size() - 1)
            bowls[i].next = i + 1;
        else
            bowls[i].next = 0;

        if(i != (size_t)num_bowls && i != 2 * (size_t)num_bowls + 1)
        {
            bowls[i].across = 2 * num_bowls - i;
            bowls[i].count = num_seeds;
        }
    }
}
//
//perform a move
//returns true if the move earns an extra turn
bool Board::move(int bowl)
{
    if(bowl < 0 || bowl >= num_bowls)
        return false;
    bowl += p1_start;
    int seeds = bowls[bowl].count;
    if(seeds == 0)
        return false;
    bowls[bowl].count = 0;
    //make the move
    for(int i = 0; i < seeds; ++i)
    {
        bowl = bowls[bowl].next;
        if(bowl == p2_store)
            bowl = bowls[bowl].next;
        bowls[bowl].count += 1;
    }
    //extra turn if we land in our own store
    if(bowl == p1_store)
        return true;

    //if we land in an empty bowl, we get the last seed sown and all the seeds from the bowl across
    if(bowls[bowl].count == 1 && bowls[bowls[bowl].across].count > 0)
    {
        bowls[p1_store].count += 1 + bowls[bowls[bowl].across].count;
        bowls[bowls[bowl].across].count = 0;
        bowls[bowl].count = 0;
    }
    return false;
}

//swap sides of the board
void Board::swapsides()
{
    std::swap(p1_start, p2_start);
    std::swap(p1_store, p2_store);
}

//is the game over
bool Board::finished() const
{
    int p1_side = 0;
    for(int i = p1_start; i < p1_start + 6; ++i)
        p1_side |= bowls[i].count;
    if(p1_side == 0)
        return true;
    int p2_side = 0;
    for(int i = p2_start; i < p2_start + 6; ++i)
        p2_side |= bowls[i].count;
    return p2_side == 0;
}

//heuristics to evaluate the board status
int Board::evaluate() const
{
    //simple
    return bowls[p1_store].count - bowls[p2_store].count;
}

void Board::crapprint() const //delete me!
{
    std::cout<<"    ";
    for(int i = p1_start; i < p1_start + 6; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[bowls[i].across].count<<" ";
    std::cout<<std::endl;
    std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[p2_store].count<<std::setw(3*7)<<" "<<std::setw(2)<<bowls[p1_store].count<<std::endl;
    std::cout<<"    ";
    for(int i = p1_start; i < p1_start + 6; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<bowls[i].count<<" ";
    std::cout<<std::endl;
    std::cout<<"    ";
    for(int i = 0; i < 6 ; ++i)
        std::cout<<std::setw(2)<<std::setfill(' ')<<i<<" ";
    std::cout<<std::endl;
}

enum PLAYER {PLAYER_MIN, PLAYER_MAX};

int choosemove_alphabeta(const Board b, int depth, PLAYER player, int alpha, int beta)
{
    if(player == PLAYER_MAX)
    {
        if(depth == 0)
            return b.evaluate();
        //move toward closest win, avoid loss as long as possible
        if(b.finished())
        {
            int diff = b.evaluate();
            if(diff == 0)
                return depth;
            else if(diff > 0)
                return 1000 + diff + depth;
            else
                return -1000 + diff - depth;
        }
        for(int i = 0; i < 6; ++i)
        {
            if(b.bowls[b.p1_start + i].count == 0)
                continue;
            Board sub_b = b;
            int score = 0;
            if(sub_b.move(i)) // do we get another move?
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MAX, alpha, beta);
            else
            {
                sub_b.swapsides();
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MIN, alpha, beta);
            }
            if(score >= beta)
                return beta;
            if(score > alpha)
                alpha = score;
        }
        return alpha;
    }
    else
    {
        if(depth == 0)
            return -b.evaluate();
        //move toward closest win, avoid loss as long as possible
        if(b.finished())
        {
            int diff = b.evaluate();
            if(diff == 0)
                return -depth;
            else if(diff > 0)
                return -1000 - diff - depth;
            else
                return 1000 - diff + depth;
        }
        for(int i = 0; i < 6; ++i)
        {
            if(b.bowls[b.p1_start + i].count == 0)
                continue;
            Board sub_b = b;
            int score = 0;
            if(sub_b.move(i)) // do we get another move?
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MIN, alpha, beta);
            else
            {
                sub_b.swapsides();
                score = choosemove_alphabeta(sub_b, depth - 1, PLAYER_MAX, alpha, beta);
            }
            if(score <= alpha)
                return alpha;
            if(score < beta)
                beta = score;
        }
        return beta;
    }
}

int choosemove(const Board b) //purposely doing pass by value here as to not corrupt passed board
{
    int best = std::numeric_limits<int>::min();
    std::vector<int> best_i;
    //loop over available moves
    for(int i =0; i < 6; ++i)
    {
        if(b.bowls[b.p1_start + i].count == 0)
            continue;
        Board sub_b = b;
        int score = 0;
        if(sub_b.move(i))
            score = choosemove_alphabeta(sub_b, 10, PLAYER_MAX, std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
        else
        {
            sub_b.swapsides();
            score = choosemove_alphabeta(sub_b, 10, PLAYER_MIN, std::numeric_limits<int>::min(), std::numeric_limits<int>::max());
        }
        //std::cout<<"choose: "<<i<<" "<<score<<" "<<-sub_b.evaluate()<<std::endl;
        if(score > best)
        {
            best = score;
            best_i.clear();
            best_i.push_back(i);
        }
        if(score == best);
            best_i.push_back(i);
    }
    return best_i[rand() % best_i.size()];
}

int main()
{
    srand(time(0));
    Board b;
    //b.bowls=std::vector<Bowl>({Bowl(1,1,12), Bowl(0,2,11), Bowl(0,3,10), Bowl(0,4,9), Bowl(2,5,8), Bowl(1,6,7), Bowl(0,7,0), Bowl(0,8,5), Bowl(0,9,4), Bowl(0,10,3), Bowl(0,11,2), Bowl(0,12,1), Bowl(1,13,0), Bowl(0,0,0)});
    char nextmove = '\0';
    int player = 1;
    while(std::cin && !b.finished() && nextmove != 'q' && nextmove != 'Q')
    {
        std::cout<<"Player "<<player<<std::endl;
        b.crapprint();
        std::cout<<"Best move: "<<choosemove(b)<<std::endl;
        std::cout<<"Next move: ";
        std::cin>>nextmove;
        std::cout<<std::endl;
        if(nextmove == 'S' || nextmove == 's')
        {
            b.swapsides();
            player = (player == 1) ? 2 : 1;
        }
        if(nextmove >= '0' && nextmove <= '5')
        {
            if(!b.move(nextmove - '0'))
            {
                b.swapsides();
                player = (player == 1) ? 2 : 1;
            }
        }
    }
    if(b.finished())
    {
        std::cout<<"Player "<<player<<std::endl;
        b.crapprint();
        if(b.bowls[b.p1_store].count == b.bowls[b.p2_store].count)
            std::cout<<"Tie"<<std::endl;
        else if(player == 1)
            if(b.bowls[b.p1_store].count > b.bowls[b.p2_store].count)
                std::cout<<"Player 1 wins"<<std::endl;
            else
                std::cout<<"Player 2 wins"<<std::endl;
        else
            if(b.bowls[b.p1_store].count > b.bowls[b.p2_store].count)
                std::cout<<"Player 2 wins"<<std::endl;
            else
                std::cout<<"Player 1 wins"<<std::endl;
        if(abs(b.bowls[b.p1_store].count - b.bowls[b.p2_store].count) >= 10)
            std::cout<<"FATALITY"<<std::endl;
    }
    return 0;
}
<|endoftext|>


<commit_before>//https://code.google.com/p/nya-engine/

#include <stdio.h>
#include <string.h>
#include "log/log.h"
#include <D3Dcompiler.h>
#include <io.h>
#include <fcntl.h>

#pragma comment(lib, "D3DCompiler.lib")

const char *help="Usage: shader_compiler mode\n"
                 "accepts shader's code from stdin\n"
                 "stderr output begins with Error: if something goes wrong\n"
                 "outputs compiled shader/text assembly to stdout\n"
                 "modes:\n"
                 "hlsl - compiles hlsl shader\n"
                 "hlsl2asm - compiles hlsl shader and returns text assembly\n"
                 //"glsl - compiles glsl shader\n"
                 //"glsl2hlsl - converts glsl shader to hlsl\n"
                 //"nshvs - compiles vertex shader from nsh\n"
                 //"nshps - compiles pixel shader from nsh\n"
                 "\n";

                 //ToDo: allow sampler index assignment

bool copmile_hlsl_code(const char *code,bool text_asm)
{
    if(!code)
        return false;

    const bool is_ps=strstr(code,"SV_TARGET")!=0;
    const char *profile=is_ps?"ps_4_0_level_9_3":"vs_4_0_level_9_3";
    ID3D10Blob *compiled=0, *error=0;
    D3DCompile(code,strlen(code),0,0,0,"main",profile,0,0,&compiled,&error);
    if(error)
    {
        fprintf(stderr,"Error: can`t compile shader with profile %s\n",profile);
        std::string error_text((const char *)error->GetBufferPointer(),error->GetBufferSize());
        fprintf(stderr,"%s\n",error_text.c_str());
        error->Release();
        return false;
    }

    if(!compiled)
    {
        fprintf(stderr,"Error: unknown compile error\n");
        return false;
    }

    if(text_asm)
    {
        ID3D10Blob *asm_blob;
        D3DDisassemble(compiled->GetBufferPointer(),compiled->GetBufferSize(),
                       D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING,"",&asm_blob);
        if(!asm_blob)
            return false;

        fwrite(asm_blob->GetBufferPointer(),1,asm_blob->GetBufferSize(),stdout);
        asm_blob->Release();
    }
    else
        fwrite(compiled->GetBufferPointer(),1,compiled->GetBufferSize(),stdout);

    compiled->Release();
    return true;
}

int main(int argc, char* argv[])
{
    if(argc<2)
    {
        fprintf(stderr,"Error: no arguments\n");
        printf("%s",help);
        return 0;
    }

    setmode(fileno(stdout),O_BINARY);
    setmode(fileno(stdin),O_BINARY);

    nya_log::set_log(&nya_log::no_log());

    std::string shader_code;
    char buf[512];
    for(size_t size=fread(buf,1,sizeof(buf),stdin);size>0;size=fread(buf,1,sizeof(buf),stdin))
        shader_code.append(buf,size);

    if(shader_code.empty())
    {
        fprintf(stderr,"Error: empty stdin\n");
        printf("%s",help);
        return 0;
    }

    if(strcmp(argv[1],"hlsl")==0)
        return copmile_hlsl_code(shader_code.c_str(),false)?0:-1;

    if(strcmp(argv[1],"hlsl2asm")==0)
        return copmile_hlsl_code(shader_code.c_str(),true)?0:-1;

/*
    if(strcmp(argv[1],"nshvs")==0)
    {
    }
    else if(strcmp(argv[1],"nshps")==0)
    {
    }
    else if(strcmp(argv[1],"glsl")==0)
    {
    }
    else if(strcmp(argv[1],"glsl2hlsl")==0)
    {
    }
    */

    fprintf(stderr,"Error: invalid compile mode: %s\n",argv[1]);

	return -1;
}
<commit_msg>shader_compiler for dx11 cache<commit_after>//https://code.google.com/p/nya-engine/

#include <stdio.h>
#include <string.h>
#include "log/log.h"
#include "render/shader_code_parser.h"
#include <D3Dcompiler.h>
#include <io.h>
#include <fcntl.h>

#pragma comment(lib, "D3DCompiler.lib")
#pragma warning(disable: 4996)

const char *help="Usage: shader_compiler mode\n"
                 "accepts shader's code from stdin\n"
                 "stderr output begins with Error: if something goes wrong\n"
                 "outputs compiled shader/text assembly to stdout\n"
                 "modes:\n"
                 "hlsl - compiles hlsl shader\n"
                 "hlsl2asm - compiles hlsl shader and returns text assembly\n"
                 "glsl - compiles glsl shader\n"
                 "glsl2hlsl - converts glsl shader to hlsl\n"
                 //"nshvs - compiles vertex shader from nsh\n"
                 //"nshps - compiles pixel shader from nsh\n"
                 "\n";

                 //ToDo: allow sampler index assignment

bool compile_hlsl_code(const char *code,bool text_asm)
{
    if(!code)
        return false;

    const bool is_ps=strstr(code,"SV_TARGET")!=0;
    const char *profile=is_ps?"ps_4_0_level_9_3":"vs_4_0_level_9_3";
    ID3D10Blob *compiled=0, *error=0;
    D3DCompile(code,strlen(code),0,0,0,"main",profile,0,0,&compiled,&error);
    if(error)
    {
        fprintf(stderr,"Error: can`t compile shader with profile %s\n",profile);
        std::string error_text((const char *)error->GetBufferPointer(),error->GetBufferSize());
        fprintf(stderr,"%s\n",error_text.c_str());
        error->Release();
        return false;
    }

    if(!compiled)
    {
        fprintf(stderr,"Error: unknown compile error\n");
        return false;
    }

    if(text_asm)
    {
        ID3D10Blob *asm_blob;
        D3DDisassemble(compiled->GetBufferPointer(),compiled->GetBufferSize(),
                       D3D_DISASM_ENABLE_INSTRUCTION_NUMBERING,"",&asm_blob);
        if(!asm_blob)
            return false;

        fwrite(asm_blob->GetBufferPointer(),1,asm_blob->GetBufferSize(),stdout);
        asm_blob->Release();
    }
    else
        fwrite(compiled->GetBufferPointer(),1,compiled->GetBufferSize(),stdout);

    compiled->Release();
    return true;
}

int main(int argc, char* argv[])
{
    if(argc<2)
    {
        fprintf(stderr,"Error: no arguments\n");
        printf("%s",help);
        return 0;
    }

    setmode(fileno(stdout),O_BINARY);
    setmode(fileno(stdin),O_BINARY);

    nya_log::set_log(&nya_log::no_log());

    std::string shader_code;
    char buf[512];
    for(size_t size=fread(buf,1,sizeof(buf),stdin);size>0;size=fread(buf,1,sizeof(buf),stdin))
        shader_code.append(buf,size);

    if(shader_code.empty())
    {
        fprintf(stderr,"Error: empty stdin\n");
        printf("%s",help);
        return 0;
    }

    if(strcmp(argv[1],"hlsl")==0)
        return compile_hlsl_code(shader_code.c_str(),false)?0:-1;

    if(strcmp(argv[1],"hlsl2asm")==0)
        return compile_hlsl_code(shader_code.c_str(),true)?0:-1;

    const bool is_glsl2hlsl=strcmp(argv[1],"glsl2hlsl")==0;
    if(is_glsl2hlsl || strcmp(argv[1],"glsl")==0)
    {
        nya_render::shader_code_parser parser(shader_code.c_str());
        if(!parser.convert_to_hlsl())
        {
            fprintf(stderr,"Error: cannot convert to hlsl\n");
            return -1;
        }

        if(is_glsl2hlsl)
        {
            fwrite(parser.get_code(),1,strlen(parser.get_code()),stdout);
            return 0;
        }
        else
            return compile_hlsl_code(shader_code.c_str(),false)?0:-1;
    }
/*
    const bool is_nshvs=strcmp(argv[1],"nshvs")==0;
    if(is_nshvs || strcmp(argv[1],"nshps")==0)
    {
    }
*/
    fprintf(stderr,"Error: invalid compile mode: %s\n",argv[1]);

	return -1;
}
<|endoftext|>


<commit_before>// Copyright (c) 2013-2018 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Basic/Export.hpp"

namespace Pomdog {

struct GamepadState;
struct GamepadCapabilities;

class POMDOG_EXPORT Gamepad {
public:
    virtual ~Gamepad() = default;

    virtual GamepadCapabilities GetCapabilities() const = 0;

    virtual GamepadState GetState() const = 0;
};

} // namespace Pomdog
<commit_msg>Redesign Gamepad API<commit_after>// Copyright (c) 2013-2018 mogemimi. Distributed under the MIT license.

#pragma once

#include "Pomdog/Basic/Export.hpp"
#include "Pomdog/Input/PlayerIndex.hpp"

namespace Pomdog {

struct GamepadState;
struct GamepadCapabilities;

class POMDOG_EXPORT Gamepad {
public:
    virtual ~Gamepad() = default;

    virtual GamepadCapabilities GetCapabilities(PlayerIndex index) const = 0;

    virtual GamepadState GetState(PlayerIndex index) const = 0;
};

} // namespace Pomdog
<|endoftext|>


<commit_before>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC 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 General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_HXX
   #error Please #include <abc.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::_str_to_str_backend

namespace abc {

/** Base class for the specializations of to_str_backend for string types. Not using templates, so
the implementation can be in a cxx file. This is used by string literal types as well (see below).
*/
class ABCAPI _str_to_str_backend {
public:

   /** Constructor.

   sFormat
      Formatting options.
   */
   _str_to_str_backend(istr const & sFormat);

protected:

   /** Writes a string, applying the formatting options.

   p
      Pointer to the string to write.
   cb
      Size of the string pointed to by p, in bytes.
   enc
      Text encoding of the string pointed to by p.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(void const * p, size_t cb, text::encoding enc, io::text::writer * ptwOut);
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for character literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C) \
   /** Character literal. \
   */ \
   template <> \
   class ABCAPI to_str_backend<C> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Constructor.

      sFormat
         Formatting options.
      */ \
      to_str_backend(istr const & sFormat = istr()) : \
         _str_to_str_backend(sFormat) { \
      } \
   \
   \
      /** Writes a character, applying the formatting options.

      ch
         Character to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C ch, io::text::writer * ptwOut) { \
         _str_to_str_backend::write(&ch, sizeof(C), text::utf_traits<C>::host_encoding, ptwOut); \
      } \
   };
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char)
// Specialization for wchar_t, if it’s what char16_t or char32_t map to.
#if ABC_CXX_CHAR16 == 1 || ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t)
#endif
// Specializations for char16/32_t, if they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for string literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C) \
   /** String literal. \
   */ \
   template <size_t t_cch> \
   class to_str_backend<C [t_cch]> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Constructor.

      sFormat
         Formatting options.
      */ \
      to_str_backend(istr const & sFormat = istr()) : \
         _str_to_str_backend(sFormat) { \
      } \
   \
   \
      /** Writes a string, applying the formatting options.

      ach
         String to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C const (& ach)[t_cch], io::text::writer * ptwOut) { \
         ABC_ASSERT(ach[t_cch - 1 /*NUL*/] == '\0', SL("string literal must be NUL-terminated")); \
         _str_to_str_backend::write( \
            ach, sizeof(C) * (t_cch - 1 /*NUL*/), text::utf_traits<C>::host_encoding, ptwOut \
         ); \
      } \
   };
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char)
// Specialization for wchar_t, if it’s what char16_t or char32_t map to.
#if ABC_CXX_CHAR16 == 1 || ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t)
#endif
// Specializations for char16/32_t, if they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::str_base

namespace abc {

template <>
class ABCAPI to_str_backend<str_base> :
   public _str_to_str_backend {
public:

   /** Constructor.

   sFormat
      Formatting options.
   */
   to_str_backend(istr const & sFormat = istr()) :
      _str_to_str_backend(sFormat) {
   }

   /** Writes a string, applying the formatting options.

   s
      String to write.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(str_base const & s, io::text::writer * ptwOut) {
      _str_to_str_backend::write(
         s.cbegin().base(),
         size_t(reinterpret_cast<int8_t const *>(s.cend().base()) -
            reinterpret_cast<int8_t const *>(s.cbegin().base())),
         text::encoding::host, ptwOut
      );
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::istr

namespace abc {

template <>
class ABCAPI to_str_backend<istr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::mstr

namespace abc {

template <>
class ABCAPI to_str_backend<mstr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::dmstr

namespace abc {

template <>
class ABCAPI to_str_backend<dmstr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::smstr

namespace abc {

template <size_t t_cchStatic>
class to_str_backend<smstr<t_cchStatic>> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<commit_msg>Re-introduce specialization to work around MSC16 bug<commit_after>/* -*- coding: utf-8; mode: c++; tab-width: 3; indent-tabs-mode: nil -*-

Copyright 2010, 2011, 2012, 2013, 2014
Raffaello D. Di Napoli

This file is part of Application-Building Components (henceforth referred to as ABC).

ABC is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.

ABC 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 General Public
License for more details.

You should have received a copy of the GNU General Public License along with ABC. If not, see
<http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------------------------*/

#ifndef _ABC_HXX
   #error Please #include <abc.hxx> instead of this file
#endif

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::_str_to_str_backend

namespace abc {

/** Base class for the specializations of to_str_backend for string types. Not using templates, so
the implementation can be in a cxx file. This is used by string literal types as well (see below).
*/
class ABCAPI _str_to_str_backend {
public:

   /** Constructor.

   sFormat
      Formatting options.
   */
   _str_to_str_backend(istr const & sFormat);

protected:

   /** Writes a string, applying the formatting options.

   p
      Pointer to the string to write.
   cb
      Size of the string pointed to by p, in bytes.
   enc
      Text encoding of the string pointed to by p.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(void const * p, size_t cb, text::encoding enc, io::text::writer * ptwOut);
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for character literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C) \
   /** Character literal. \
   */ \
   template <> \
   class ABCAPI to_str_backend<C> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Constructor.

      sFormat
         Formatting options.
      */ \
      to_str_backend(istr const & sFormat = istr()) : \
         _str_to_str_backend(sFormat) { \
      } \
   \
   \
      /** Writes a character, applying the formatting options.

      ch
         Character to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C ch, io::text::writer * ptwOut) { \
         _str_to_str_backend::write(&ch, sizeof(C), text::utf_traits<C>::host_encoding, ptwOut); \
      } \
   };
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char)
// Specialization for wchar_t, if it’s what char16_t or char32_t map to.
#if ABC_CXX_CHAR16 == 1 || ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t)
#endif
// Specializations for char16/32_t, if they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for string literal types

namespace abc {

#define ABC_SPECIALIZE_to_str_backend_FOR_TYPE(C) \
   /** String literal. \
   */ \
   template <size_t t_cch> \
   class to_str_backend<C [t_cch]> : \
      public _str_to_str_backend { \
   public: \
   \
      /** Constructor.

      sFormat
         Formatting options.
      */ \
      to_str_backend(istr const & sFormat = istr()) : \
         _str_to_str_backend(sFormat) { \
      } \
   \
   \
      /** Writes a string, applying the formatting options.

      ach
         String to write.
      ptwOut
         Pointer to the writer to output to.
      */ \
      void write(C const (& ach)[t_cch], io::text::writer * ptwOut) { \
         ABC_ASSERT(ach[t_cch - 1 /*NUL*/] == '\0', SL("string literal must be NUL-terminated")); \
         _str_to_str_backend::write( \
            ach, sizeof(C) * (t_cch - 1 /*NUL*/), text::utf_traits<C>::host_encoding, ptwOut \
         ); \
      } \
   }; \
   \
   /** MSC16 BUG: this partial specialization is necessary. */ \
   template <size_t t_cch> \
   class to_str_backend<C const [t_cch]> : \
      public to_str_backend<C [t_cch]> { \
   public: \
   \
      /** Constructor.

      sFormat
         Formatting options.
      */ \
      to_str_backend(istr const & sFormat = istr()) : \
         to_str_backend<C [t_cch]>(sFormat) { \
      } \
   };
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char)
// Specialization for wchar_t, if it’s what char16_t or char32_t map to.
#if ABC_CXX_CHAR16 == 1 || ABC_CXX_CHAR32 == 1
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(wchar_t)
#endif
// Specializations for char16/32_t, if they’re native types.
#if ABC_CXX_CHAR16 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char16_t)
#endif
#if ABC_CXX_CHAR32 == 2
ABC_SPECIALIZE_to_str_backend_FOR_TYPE(char32_t)
#endif
#undef ABC_SPECIALIZE_to_str_backend_FOR_TYPE

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::str_base

namespace abc {

template <>
class ABCAPI to_str_backend<str_base> :
   public _str_to_str_backend {
public:

   /** Constructor.

   sFormat
      Formatting options.
   */
   to_str_backend(istr const & sFormat = istr()) :
      _str_to_str_backend(sFormat) {
   }

   /** Writes a string, applying the formatting options.

   s
      String to write.
   ptwOut
      Pointer to the writer to output to.
   */
   void write(str_base const & s, io::text::writer * ptwOut) {
      _str_to_str_backend::write(
         s.cbegin().base(),
         size_t(reinterpret_cast<int8_t const *>(s.cend().base()) -
            reinterpret_cast<int8_t const *>(s.cbegin().base())),
         text::encoding::host, ptwOut
      );
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::istr

namespace abc {

template <>
class ABCAPI to_str_backend<istr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::mstr

namespace abc {

template <>
class ABCAPI to_str_backend<mstr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::dmstr

namespace abc {

template <>
class ABCAPI to_str_backend<dmstr> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////
// abc::to_str_backend - specialization for abc::smstr

namespace abc {

template <size_t t_cchStatic>
class to_str_backend<smstr<t_cchStatic>> :
   public to_str_backend<str_base> {
public:

   /** Constructor. See to_str_backend<str_base>::to_str_backend().
   */
   to_str_backend(istr const & sFormat = istr()) :
      to_str_backend<str_base>(sFormat) {
   }
};

} //namespace abc

////////////////////////////////////////////////////////////////////////////////////////////////////

<|endoftext|>


<commit_before>/**
 * Copyright © 2016 IBM Corporation
 *
 * 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 <iostream>
#include <exception>
#include <chrono>
#include <log.hpp>
#include "manager.hpp"

using namespace std::literals::chrono_literals;

namespace phosphor
{
namespace inventory
{
namespace manager
{
/** @brief Fowrarding signal callback.
 *
 *  Extracts per-signal specific context and forwards the call to the manager
 *  instance.
 */
auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
{
    try
    {
        auto msg = sdbusplus::message::message(m);
        auto& args = *static_cast<Manager::SigArg*>(data);
        sd_bus_message_ref(m);
        auto& mgr = *std::get<0>(args);
        mgr.handleEvent(
            msg,
            static_cast<const DbusSignal&>(
                *std::get<1>(args)),
            *std::get<2>(args));
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

Manager::Manager(
    sdbusplus::bus::bus&& bus,
    const char* busname,
    const char* root,
    const char* iface) :
    ServerObject<ManagerIface>(bus, root),
    _shutdown(false),
    _root(root),
    _bus(std::move(bus)),
    _manager(sdbusplus::server::manager::manager(_bus, root))
{
    for (auto& group : _events)
    {
        for (auto pEvent : std::get<std::vector<EventBasePtr>>(
                 group))
        {
            if (pEvent->type !=
                Event::Type::DBUS_SIGNAL)
            {
                continue;
            }

            // Create a callback context for this event group.
            auto dbusEvent = static_cast<DbusSignal*>(
                                 pEvent.get());

            // Go ahead and store an iterator pointing at
            // the event data to avoid lookups later since
            // additional signal callbacks aren't added
            // after the manager is constructed.
            _sigargs.emplace_back(
                std::make_unique<SigArg>(
                    this,
                    dbusEvent,
                    &group));

            // Register our callback and the context for
            // each signal event.
            _matches.emplace_back(
                _bus,
                dbusEvent->signature,
                _signal,
                _sigargs.back().get());
        }
    }

    _bus.request_name(busname);
}

void Manager::shutdown() noexcept
{
    _shutdown = true;
}

void Manager::run() noexcept
{
    sdbusplus::message::message unusedMsg{nullptr};

    // Run startup events.
    for (auto& group : _events)
    {
        for (auto pEvent : std::get<std::vector<EventBasePtr>>(
                 group))
        {
            if (pEvent->type ==
                Event::Type::STARTUP)
            {
                handleEvent(unusedMsg, *pEvent, group);
            }
        }
    }

    while (!_shutdown)
    {
        try
        {
            _bus.process_discard();
            _bus.wait((5000000us).count());
        }
        catch (const std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
}

void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
{
    try
    {
        createObjects(objs);
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

void Manager::handleEvent(
    sdbusplus::message::message& msg,
    const Event& event,
    const EventInfo& info)
{
    auto& actions = std::get<1>(info);

    for (auto& f : event)
    {
        if (!f(_bus, msg, *this))
        {
            return;
        }
    }
    for (auto& action : actions)
    {
        action(_bus, *this);
    }
}

void Manager::destroyObjects(
    const std::vector<const char*>& paths)
{
    std::string p;

    for (const auto& path : paths)
    {
        p.assign(_root);
        p.append(path);
        _bus.emit_object_removed(p.c_str());
        _refs.erase(p);
    }
}

void Manager::createObjects(
    const std::map<sdbusplus::message::object_path, Object>& objs)
{
    std::string absPath;

    for (auto& o : objs)
    {
        try
        {
            auto& relPath = o.first;
            auto& ifaces = o.second;

            absPath.assign(_root);
            absPath.append(relPath);

            auto obj = _refs.find(absPath);
            if (obj != _refs.end())
            {
                // This object already exists...skip.
                continue;
            }

            // Create an interface holder for each interface
            // provided by the client and group them into
            // a container.
            InterfaceComposite ref;

            for (auto& iface : ifaces)
            {
                auto& props = iface.second;
                auto pMakers = _makers.find(iface.first.c_str());

                if (pMakers == _makers.end())
                {
                    // This interface is not known.
                    continue;
                }

                auto& maker = std::get<MakerType>(pMakers->second);

                ref.emplace(
                    iface.first,
                    maker(
                        _bus,
                        absPath.c_str(),
                        props));
            }

            if (!ref.empty())
            {
                // Hang on to a reference to the object (interfaces)
                // so it stays on the bus, and so we can make calls
                // to it if needed.
                _refs.emplace(
                    absPath, std::move(ref));
                _bus.emit_object_added(absPath.c_str());
            }
        }
        catch (const std::exception& e)
        {
            logging::log<logging::level::ERR>(e.what());
        }
    }
}

any_ns::any& Manager::getInterfaceHolder(
    const char* path, const char* interface)
{
    return const_cast<any_ns::any&>(
               const_cast<const Manager*>(
                   this)->getInterfaceHolder(path, interface));
}

const any_ns::any& Manager::getInterfaceHolder(
    const char* path, const char* interface) const
{
    std::string p{path};
    auto oit = _refs.find(_root + p);
    if (oit == _refs.end())
        throw std::runtime_error(
            _root + p + " was not found");

    auto& obj = oit->second;
    auto iit = obj.find(interface);
    if (iit == obj.end())
        throw std::runtime_error(
            "interface was not found");

    return iit->second;
}

} // namespace manager
} // namespace inventory
} // namespace phosphor

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>Update notify method to update interfaces<commit_after>/**
 * Copyright © 2016 IBM Corporation
 *
 * 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 <iostream>
#include <exception>
#include <chrono>
#include <log.hpp>
#include "manager.hpp"

using namespace std::literals::chrono_literals;

namespace phosphor
{
namespace inventory
{
namespace manager
{
/** @brief Fowrarding signal callback.
 *
 *  Extracts per-signal specific context and forwards the call to the manager
 *  instance.
 */
auto _signal(sd_bus_message* m, void* data, sd_bus_error* e) noexcept
{
    try
    {
        auto msg = sdbusplus::message::message(m);
        auto& args = *static_cast<Manager::SigArg*>(data);
        sd_bus_message_ref(m);
        auto& mgr = *std::get<0>(args);
        mgr.handleEvent(
            msg,
            static_cast<const DbusSignal&>(
                *std::get<1>(args)),
            *std::get<2>(args));
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }

    return 0;
}

Manager::Manager(
    sdbusplus::bus::bus&& bus,
    const char* busname,
    const char* root,
    const char* iface) :
    ServerObject<ManagerIface>(bus, root),
    _shutdown(false),
    _root(root),
    _bus(std::move(bus)),
    _manager(sdbusplus::server::manager::manager(_bus, root))
{
    for (auto& group : _events)
    {
        for (auto pEvent : std::get<std::vector<EventBasePtr>>(
                 group))
        {
            if (pEvent->type !=
                Event::Type::DBUS_SIGNAL)
            {
                continue;
            }

            // Create a callback context for this event group.
            auto dbusEvent = static_cast<DbusSignal*>(
                                 pEvent.get());

            // Go ahead and store an iterator pointing at
            // the event data to avoid lookups later since
            // additional signal callbacks aren't added
            // after the manager is constructed.
            _sigargs.emplace_back(
                std::make_unique<SigArg>(
                    this,
                    dbusEvent,
                    &group));

            // Register our callback and the context for
            // each signal event.
            _matches.emplace_back(
                _bus,
                dbusEvent->signature,
                _signal,
                _sigargs.back().get());
        }
    }

    _bus.request_name(busname);
}

void Manager::shutdown() noexcept
{
    _shutdown = true;
}

void Manager::run() noexcept
{
    sdbusplus::message::message unusedMsg{nullptr};

    // Run startup events.
    for (auto& group : _events)
    {
        for (auto pEvent : std::get<std::vector<EventBasePtr>>(
                 group))
        {
            if (pEvent->type ==
                Event::Type::STARTUP)
            {
                handleEvent(unusedMsg, *pEvent, group);
            }
        }
    }

    while (!_shutdown)
    {
        try
        {
            _bus.process_discard();
            _bus.wait((5000000us).count());
        }
        catch (const std::exception& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }
}

void Manager::notify(std::map<sdbusplus::message::object_path, Object> objs)
{
    updateObjects(objs);
}

void Manager::handleEvent(
    sdbusplus::message::message& msg,
    const Event& event,
    const EventInfo& info)
{
    auto& actions = std::get<1>(info);

    for (auto& f : event)
    {
        if (!f(_bus, msg, *this))
        {
            return;
        }
    }
    for (auto& action : actions)
    {
        action(_bus, *this);
    }
}

void Manager::destroyObjects(
    const std::vector<const char*>& paths)
{
    std::string p;

    for (const auto& path : paths)
    {
        p.assign(_root);
        p.append(path);
        _bus.emit_object_removed(p.c_str());
        _refs.erase(p);
    }
}

void Manager::createObjects(
    const std::map<sdbusplus::message::object_path, Object>& objs)
{
    updateObjects(objs);
}

any_ns::any& Manager::getInterfaceHolder(
    const char* path, const char* interface)
{
    return const_cast<any_ns::any&>(
               const_cast<const Manager*>(
                   this)->getInterfaceHolder(path, interface));
}

const any_ns::any& Manager::getInterfaceHolder(
    const char* path, const char* interface) const
{
    std::string p{path};
    auto oit = _refs.find(_root + p);
    if (oit == _refs.end())
        throw std::runtime_error(
            _root + p + " was not found");

    auto& obj = oit->second;
    auto iit = obj.find(interface);
    if (iit == obj.end())
        throw std::runtime_error(
            "interface was not found");

    return iit->second;
}

} // namespace manager
} // namespace inventory
} // namespace phosphor

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#include <cstddef>

namespace libtorrent
{

	struct page_aligned_allocator
	{
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;

		static char* malloc(const size_type bytes);
		static void free(char* const block);
	};

}

<commit_msg>added include guards to allocator.hpp<commit_after>/*

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

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

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

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

*/

#include <cstddef>

#ifndef TORRENT_ALLOCATOR_HPP_INCLUDED
#define TORRENT_ALLOCATOR_HPP_INCLUDED

namespace libtorrent
{

	struct page_aligned_allocator
	{
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;

		static char* malloc(const size_type bytes);
		static void free(char* const block);
	};

}

#endif

<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#ifndef TORRENT_FILE_POOL_HPP
#define TORRENT_FILE_POOL_HPP

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/intrusive_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <map>
#include "libtorrent/file.hpp"
#include "libtorrent/ptime.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/file_storage.hpp"

namespace libtorrent
{
	// this is an internal cache of open file handles. It's primarily used by
	// storage_interface implementations. It provides semi weak guarantees of
	// not opening more file handles than specified. Given multiple threads,
	// each with the ability to lock a file handle (via smart pointer), there
	// may be windows where more file handles are open.
	struct TORRENT_EXPORT file_pool : boost::noncopyable
	{
		// ``size`` specifies the number of allowed files handles
		// to hold open at any given time.
		file_pool(int size = 40);
		~file_pool();

		// return an open file handle to file at ``file_index`` in the
		// file_storage ``fs`` opened at save path ``p``. ``m`` is the
		// file open mode (see file::open_mode_t).
		boost::intrusive_ptr<file> open_file(void* st, std::string const& p
			, int file_index, file_storage const& fs, int m, error_code& ec);

		// release all files belonging to the specified storage_interface (``st``)
		// the overload that takes ``file_index`` releases only the file with
		// that index in storage ``st``.
		void release(void* st);
		void release(void* st, int file_index);

		// update the allowed number of open file handles to ``size``.
		void resize(int size);

		// returns the current limit of number of allowed open file handles held
		// by the file_pool.
		int size_limit() const { return m_size; }

		// internal
		void set_low_prio_io(bool b) { m_low_prio_io = b; }

	private:

		void remove_oldest();

		int m_size;
		bool m_low_prio_io;

		struct lru_file_entry
		{
			lru_file_entry(): key(0), last_use(time_now()), mode(0) {}
			mutable boost::intrusive_ptr<file> file_ptr;
			void* key;
			ptime last_use;
			int mode;
		};

		// maps storage pointer, file index pairs to the
		// lru entry for the file
		typedef std::map<std::pair<void*, int>, lru_file_entry> file_set;

		file_set m_files;
		mutex m_mutex;
#ifdef TORRENT_DEBUG
		int m_in_use;
#endif

#if TORRENT_CLOSE_MAY_BLOCK
		void closer_thread_fun();
		mutex m_closer_mutex;
		std::vector<boost::intrusive_ptr<file> > m_queued_for_close;
		bool m_stop_thread;

		// used to close files
		thread m_closer_thread;
#endif
	};
}

#endif
<commit_msg>fix release asserts build<commit_after>/*

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

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

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

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

*/

#ifndef TORRENT_FILE_POOL_HPP
#define TORRENT_FILE_POOL_HPP

#ifdef _MSC_VER
#pragma warning(push, 1)
#endif

#include <boost/intrusive_ptr.hpp>

#ifdef _MSC_VER
#pragma warning(pop)
#endif

#include <map>
#include "libtorrent/file.hpp"
#include "libtorrent/ptime.hpp"
#include "libtorrent/thread.hpp"
#include "libtorrent/file_storage.hpp"

namespace libtorrent
{
	// this is an internal cache of open file handles. It's primarily used by
	// storage_interface implementations. It provides semi weak guarantees of
	// not opening more file handles than specified. Given multiple threads,
	// each with the ability to lock a file handle (via smart pointer), there
	// may be windows where more file handles are open.
	struct TORRENT_EXPORT file_pool : boost::noncopyable
	{
		// ``size`` specifies the number of allowed files handles
		// to hold open at any given time.
		file_pool(int size = 40);
		~file_pool();

		// return an open file handle to file at ``file_index`` in the
		// file_storage ``fs`` opened at save path ``p``. ``m`` is the
		// file open mode (see file::open_mode_t).
		boost::intrusive_ptr<file> open_file(void* st, std::string const& p
			, int file_index, file_storage const& fs, int m, error_code& ec);

		// release all files belonging to the specified storage_interface (``st``)
		// the overload that takes ``file_index`` releases only the file with
		// that index in storage ``st``.
		void release(void* st);
		void release(void* st, int file_index);

		// update the allowed number of open file handles to ``size``.
		void resize(int size);

		// returns the current limit of number of allowed open file handles held
		// by the file_pool.
		int size_limit() const { return m_size; }

		// internal
		void set_low_prio_io(bool b) { m_low_prio_io = b; }

	private:

		void remove_oldest();

		int m_size;
		bool m_low_prio_io;

		struct lru_file_entry
		{
			lru_file_entry(): key(0), last_use(time_now()), mode(0) {}
			mutable boost::intrusive_ptr<file> file_ptr;
			void* key;
			ptime last_use;
			int mode;
		};

		// maps storage pointer, file index pairs to the
		// lru entry for the file
		typedef std::map<std::pair<void*, int>, lru_file_entry> file_set;

		file_set m_files;
		mutex m_mutex;
#if defined TORRENT_DEBUG || TORRENT_RELEASE_ASSERTS
		int m_in_use;
#endif

#if TORRENT_CLOSE_MAY_BLOCK
		void closer_thread_fun();
		mutex m_closer_mutex;
		std::vector<boost::intrusive_ptr<file> > m_queued_for_close;
		bool m_stop_thread;

		// used to close files
		thread m_closer_thread;
#endif
	};
}

#endif
<|endoftext|>


<commit_before>/*

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

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

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

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

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include <vector>
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"

namespace libtorrent
{
	struct peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20
		};
		unsigned int flags;
		address ip;
		float up_speed;
		float down_speed;
		unsigned int total_download;
		unsigned int total_upload;
		peer_id id;
		std::vector<bool> pieces;
		int upload_limit;
		int upload_ceiling;

		int load_balancing;

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;
	};

}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<commit_msg>*** empty log message ***<commit_after>/*

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

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

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

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

*/

#ifndef TORRENT_PEER_INFO_HPP_INCLUDED
#define TORRENT_PEER_INFO_HPP_INCLUDED

#include <vector>
#include "libtorrent/socket.hpp"
#include "libtorrent/peer_id.hpp"

namespace libtorrent
{
	struct peer_info
	{
		enum
		{
			interesting = 0x1,
			choked = 0x2,
			remote_interested = 0x4,
			remote_choked = 0x8,
			supports_extensions = 0x10,
			local_connection = 0x20
		};
		unsigned int flags;
		address ip;
		float up_speed;
		float down_speed;
		unsigned int total_download;
		unsigned int total_upload;
		peer_id id;
		std::vector<bool> pieces;
		int upload_limit; // from peer_connection
		int upload_ceiling; // from the global upload limiter

		int load_balancing;

		// this is the number of requests
		// we have sent to this peer
		// that we haven't got a response
		// for yet
		int download_queue_length;

		// the currently downloading piece
		// if piece index is -1 all associated
		// members are just set to 0
		int downloading_piece_index;
		int downloading_block_index;
		int downloading_progress;
		int downloading_total;
	};

}

#endif // TORRENT_PEER_INFO_HPP_INCLUDED
<|endoftext|>


<commit_before>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <array>
#include <memory>
#include <string>
#include <vector>
#include <cstddef>
#include <exception>
#include <type_traits>

#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/assert.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include <windows.h>

#include "hadesmem/error.hpp"
#include "hadesmem/protect.hpp"
#include "hadesmem/detail/read_impl.hpp"
#include "hadesmem/detail/type_traits.hpp"
#include "hadesmem/detail/query_region.hpp"
#include "hadesmem/detail/protect_guard.hpp"
#include "hadesmem/detail/static_assert.hpp"

// NOTE: Reads which span across region boundaries are not explicitly handled
// or supported. They may work simply by chance (or if the user changes the
// memory page protections preemptively in preparation for the read), however
// this is not guaranteed to work, even in the aforementioned scenario.

namespace hadesmem
{

class Process;

namespace detail
{

template <typename T>
T ReadUnchecked(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  T data;
  ReadUnchecked(process, address, std::addressof(data), sizeof(data));
  return data;
}

}

template <typename T>
T Read(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  T data;
  detail::Read(process, address, std::addressof(data), sizeof(data));
  return data;
}

template <typename T, std::size_t N>
std::array<T, N> Read(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_STATIC_ASSERT(detail::IsDefaultConstructible<T>::value);

  std::array<T, N> data;
  detail::Read(process, address, data.data(), sizeof(T) * N);
  return data;
}

// TODO: Clean up this function.
template <typename T>
std::basic_string<T> ReadString(Process const& process, PVOID address,
  std::size_t chunk_len = 128)
{
  HADESMEM_STATIC_ASSERT(detail::IsCharType<T>::value);

  BOOST_ASSERT(chunk_len != 0);

  detail::ProtectGuard protect_guard(process, address,
    detail::ProtectGuardType::kRead);

  std::basic_string<T> data;

  MEMORY_BASIC_INFORMATION const mbi = detail::Query(process, address);
  PVOID const region_end = static_cast<PBYTE>(mbi.BaseAddress) +
    mbi.RegionSize;

  T* cur = static_cast<T*>(address);
  while (cur + 1 < region_end)
  {
    std::size_t const len_to_end = reinterpret_cast<DWORD_PTR>(region_end) -
      reinterpret_cast<DWORD_PTR>(cur);
    std::size_t const buf_len_bytes = (std::min)(chunk_len * sizeof(T),
      len_to_end);
    std::size_t const buf_len = buf_len_bytes / sizeof(T);

    std::vector<T> buf(buf_len);
    detail::ReadUnchecked(process, cur, buf.data(), buf.size() * sizeof(T));

    auto const iter = std::find(std::begin(buf), std::end(buf), T());
    std::copy(std::begin(buf), iter, std::back_inserter(data));

    if (iter != std::end(buf))
    {
      protect_guard.Restore();
      return data;
    }

    cur += buf_len;
  }

  BOOST_THROW_EXCEPTION(Error() <<
    ErrorString("Attempt to read across a region boundary."));
}

template <typename T>
std::vector<T> ReadVector(Process const& process, PVOID address,
  std::size_t size)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_STATIC_ASSERT(detail::IsDefaultConstructible<T>::value);

  std::vector<T> data(size);
  detail::Read(process, address, data.data(), sizeof(T) * size);
  return data;
}

}
<commit_msg>* BOOST_THROW_EXCEPTION -> HADESMEM_THROW_EXCEPTION<commit_after>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#pragma once

#include <array>
#include <memory>
#include <string>
#include <vector>
#include <cstddef>
#include <exception>
#include <type_traits>

#include "hadesmem/detail/warning_disable_prefix.hpp"
#include <boost/assert.hpp>
#include "hadesmem/detail/warning_disable_suffix.hpp"

#include <windows.h>

#include "hadesmem/error.hpp"
#include "hadesmem/protect.hpp"
#include "hadesmem/detail/read_impl.hpp"
#include "hadesmem/detail/type_traits.hpp"
#include "hadesmem/detail/query_region.hpp"
#include "hadesmem/detail/protect_guard.hpp"
#include "hadesmem/detail/static_assert.hpp"

// NOTE: Reads which span across region boundaries are not explicitly handled
// or supported. They may work simply by chance (or if the user changes the
// memory page protections preemptively in preparation for the read), however
// this is not guaranteed to work, even in the aforementioned scenario.

namespace hadesmem
{

class Process;

namespace detail
{

template <typename T>
T ReadUnchecked(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  T data;
  ReadUnchecked(process, address, std::addressof(data), sizeof(data));
  return data;
}

}

template <typename T>
T Read(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  T data;
  detail::Read(process, address, std::addressof(data), sizeof(data));
  return data;
}

template <typename T, std::size_t N>
std::array<T, N> Read(Process const& process, PVOID address)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_STATIC_ASSERT(detail::IsDefaultConstructible<T>::value);

  std::array<T, N> data;
  detail::Read(process, address, data.data(), sizeof(T) * N);
  return data;
}

// TODO: Clean up this function.
template <typename T>
std::basic_string<T> ReadString(Process const& process, PVOID address,
  std::size_t chunk_len = 128)
{
  HADESMEM_STATIC_ASSERT(detail::IsCharType<T>::value);

  BOOST_ASSERT(chunk_len != 0);

  detail::ProtectGuard protect_guard(process, address,
    detail::ProtectGuardType::kRead);

  std::basic_string<T> data;

  MEMORY_BASIC_INFORMATION const mbi = detail::Query(process, address);
  PVOID const region_end = static_cast<PBYTE>(mbi.BaseAddress) +
    mbi.RegionSize;

  T* cur = static_cast<T*>(address);
  while (cur + 1 < region_end)
  {
    std::size_t const len_to_end = reinterpret_cast<DWORD_PTR>(region_end) -
      reinterpret_cast<DWORD_PTR>(cur);
    std::size_t const buf_len_bytes = (std::min)(chunk_len * sizeof(T),
      len_to_end);
    std::size_t const buf_len = buf_len_bytes / sizeof(T);

    std::vector<T> buf(buf_len);
    detail::ReadUnchecked(process, cur, buf.data(), buf.size() * sizeof(T));

    auto const iter = std::find(std::begin(buf), std::end(buf), T());
    std::copy(std::begin(buf), iter, std::back_inserter(data));

    if (iter != std::end(buf))
    {
      protect_guard.Restore();
      return data;
    }

    cur += buf_len;
  }

  HADESMEM_THROW_EXCEPTION(Error() <<
    ErrorString("Attempt to read across a region boundary."));
}

template <typename T>
std::vector<T> ReadVector(Process const& process, PVOID address,
  std::size_t size)
{
  HADESMEM_STATIC_ASSERT(detail::IsTriviallyCopyable<T>::value);

  HADESMEM_STATIC_ASSERT(detail::IsDefaultConstructible<T>::value);

  std::vector<T> data(size);
  detail::Read(process, address, data.data(), sizeof(T) * size);
  return data;
}

}
<|endoftext|>


<commit_before>/*
 * type_utils.hpp
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Jan 14, 2015
 */
#pragma once

#include <tuple>

namespace fakeit {

    template<class C>
    struct naked_type {
        typedef typename std::remove_cv<typename std::remove_reference<C>::type>::type type;
    };

    template< class T > struct tuple_arg         { typedef T  type; };
    template< class T > struct tuple_arg < T& >  { typedef T& type; };
    template< class T > struct tuple_arg < T&& > { typedef T&&  type; };

    //template<typename... arglist>
    //using ArgumentsTuple = std::tuple<typename tuple_arg<arglist>::type...>;

    template<typename... arglist>
    using ArgumentsTuple = std::tuple < arglist... > ;

    template< class T > struct test_arg         { typedef T& type; };
    template< class T > struct test_arg< T& >   { typedef T& type; };
    template< class T > struct test_arg< T&& >  { typedef T& type; };

    template< class T > struct production_arg         { typedef T& type; };
    template< class T > struct production_arg< T& >   { typedef T& type; };
    template< class T > struct production_arg< T&& >  { typedef T&&  type; };

	template <typename T>
	class is_ostreamable {
		struct no {};
		template <typename T1>
		static auto test(std::ostream &s, const T1 &t) -> decltype(s << t);
		static no test(...);
	public:
		static const bool value = std::is_same<decltype(test(*(std::ostream *)nullptr,
			std::declval<T>())), std::ostream &>::value;
	};

    template<typename R, typename... arglist>
    struct VTableMethodType {
#if defined (__GNUG__)
        typedef R(*type)(void *, arglist...);
#elif defined (_MSC_VER)
        typedef R(__thiscall *type)(void *, arglist...);
#endif
    };
}
<commit_msg>Work around MSVC 2013 compiler bugs<commit_after>/*
 * type_utils.hpp
 * Copyright (c) 2014 Eran Pe'er.
 *
 * This program is made available under the terms of the MIT License.
 *
 * Created on Jan 14, 2015
 */
#pragma once

#include <tuple>

namespace fakeit {

    template<class C>
    struct naked_type {
        typedef typename std::remove_cv<typename std::remove_reference<C>::type>::type type;
    };

    template< class T > struct tuple_arg         { typedef T  type; };
    template< class T > struct tuple_arg < T& >  { typedef T& type; };
    template< class T > struct tuple_arg < T&& > { typedef T&&  type; };

    //template<typename... arglist>
    //using ArgumentsTuple = std::tuple<typename tuple_arg<arglist>::type...>;

    template<typename... arglist>
    using ArgumentsTuple = std::tuple < arglist... > ;

    template< class T > struct test_arg         { typedef T& type; };
    template< class T > struct test_arg< T& >   { typedef T& type; };
    template< class T > struct test_arg< T&& >  { typedef T& type; };

    template< class T > struct production_arg         { typedef T& type; };
    template< class T > struct production_arg< T& >   { typedef T& type; };
    template< class T > struct production_arg< T&& >  { typedef T&&  type; };

    template <typename T>
    class is_ostreamable {
        struct no {};
#if defined(_MSC_VER) && _MSC_VER < 1900
        template <typename T1>
        static decltype(operator<<(std::declval<std::ostream&>(), std::declval<const T1>())) test(std::ostream &s, const T1 &t);
#else
        template <typename T1>
        static auto test(std::ostream &s, const T1 &t) -> decltype(s << t);
#endif
        static no test(...);
    public:
        // capture std::ostream operator<< members for the benefit of MSVC
        static const bool value =
            std::is_arithmetic<T>::value ||
            std::is_pointer<T>::value ||
            std::is_same<decltype(test(*(std::ostream *)nullptr,
                std::declval<T>())), std::ostream &>::value;
    };

    // capture std::ostream operator<< members for the benefit of MSVC
    template <>
    class is_ostreamable<std::ios_base& (*)(std::ios_base&)> {
    public:
        static const bool value = true;
    };

    template <typename CharT, typename Traits>
    class is_ostreamable<std::basic_ios<CharT,Traits>& (*)(std::basic_ios<CharT,Traits>&)> {
    public:
        static const bool value = true;
    };

    template <typename CharT, typename Traits>
    class is_ostreamable<std::basic_ostream<CharT,Traits>& (*)(std::basic_ostream<CharT,Traits>&)> {
    public:
        static const bool value = true;
    };

    template<typename R, typename... arglist>
    struct VTableMethodType {
#if defined (__GNUG__)
        typedef R(*type)(void *, arglist...);
#elif defined (_MSC_VER)
        typedef R(__thiscall *type)(void *, arglist...);
#endif
    };
}
<|endoftext|>