<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PythonMacros.h"
#include "Binding.h"
#include "Binding_SofaModule.h"

#include "Binding_Data.h"
#include "Binding_DisplayFlagsData.h"
#include "Binding_OptionsGroupData.h"
#include "Binding_DataFileName.h"
#include "Binding_DataFileNameVector.h"
#include "Binding_VectorLinearSpringData.h"
#include "Binding_Link.h"
#include "Binding_Base.h"
#include "Binding_BaseObject.h"
#include "Binding_BaseState.h"
#include "Binding_BaseContext.h"
#include "Binding_Context.h"
#include "Binding_Node.h"
#include "Binding_Vector.h"
#include "Binding_TopologyChange.h"
#include "Binding_BaseLoader.h"
#include "Binding_MeshLoader.h"
#include "Binding_Topology.h"
#include "Binding_BaseMeshTopology.h"
#include "Binding_MeshTopology.h"
#include "Binding_GridTopology.h"
#include "Binding_RegularGridTopology.h"
#include "Binding_BaseMechanicalState.h"
#include "Binding_MechanicalObject.h"
#include "Binding_PythonScriptController.h"
#include "Binding_LinearSpring.h"
#include "Binding_BaseTopologyObject.h"
#include "Binding_TriangleSetTopologyModifier.h"
#include "Binding_PointSetTopologyModifier.h"
#include "Binding_BaseMapping.h"
#include "Binding_SubsetMultiMapping.h"
#include "Binding_VisualModel.h"
#include "Binding_OBJExporter.h"
#include "Binding_STLExporter.h"
#include "Binding_DataEngine.h"
#include "PythonFactory.h"

using sofa::PythonFactory;

void bindSofaPythonModule()
{
    PythonFactory::s_sofaPythonModule = SP_INIT_MODULE(Sofa)

    /// non Base-Inherited types
    SP_ADD_CLASS_IN_SOFAMODULE(Data)

    /// special Data cases
    SP_ADD_CLASS_IN_FACTORY(DisplayFlagsData,sofa::core::objectmodel::Data<sofa::core::visual::DisplayFlags>)
    SP_ADD_CLASS_IN_FACTORY(OptionsGroupData,sofa::core::objectmodel::Data<sofa::helper::OptionsGroup>)
    SP_ADD_CLASS_IN_FACTORY(DataFileName,sofa::core::objectmodel::DataFileName)
    SP_ADD_CLASS_IN_FACTORY(DataFileNameVector,sofa::core::objectmodel::DataFileNameVector)
    SP_ADD_CLASS_IN_SOFAMODULE(PointAncestorElem)
    SP_ADD_CLASS_IN_FACTORY(VectorLinearSpringData,sofa::core::objectmodel::Data<sofa::helper::vector<sofa::component::interactionforcefield::LinearSpring<SReal>>>)

    SP_ADD_CLASS_IN_SOFAMODULE(Link)
    SP_ADD_CLASS_IN_SOFAMODULE(Vector3)
    SP_ADD_CLASS_IN_SOFAMODULE(LinearSpring)

    /// special component categories gettable by static_cast
    SP_ADD_CLASS_IN_SOFAMODULE(Base)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseContext)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseObject)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseTopologyObject)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseState)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMechanicalState)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMapping)
    SP_ADD_CLASS_IN_SOFAMODULE(DataEngine)
    SP_ADD_CLASS_IN_SOFAMODULE(VisualModel)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseLoader)
    SP_ADD_CLASS_IN_SOFAMODULE(Topology)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMeshTopology)

    /// regular component bindings
    SP_ADD_CLASS_IN_FACTORY(Context,sofa::core::objectmodel::Context)
    SP_ADD_CLASS_IN_FACTORY(Node,sofa::simulation::Node)
    SP_ADD_CLASS_IN_FACTORY(VisualModelImpl,sofa::component::visualmodel::VisualModelImpl)
    SP_ADD_CLASS_IN_FACTORY(MeshLoader,sofa::core::loader::MeshLoader)
    SP_ADD_CLASS_IN_FACTORY(MeshTopology,sofa::component::topology::MeshTopology)
    SP_ADD_CLASS_IN_FACTORY(GridTopology,sofa::component::topology::GridTopology)
    SP_ADD_CLASS_IN_FACTORY(RegularGridTopology,sofa::component::topology::RegularGridTopology)
    SP_ADD_CLASS_IN_FACTORY(OBJExporter,sofa::component::misc::OBJExporter)
    SP_ADD_CLASS_IN_FACTORY(STLExporter,sofa::component::misc::STLExporter)
    SP_ADD_CLASS_IN_FACTORY(PythonScriptController,sofa::component::controller::PythonScriptController)
    SP_ADD_CLASS_IN_FACTORY(PointSetTopologyModifier,sofa::component::topology::PointSetTopologyModifier)
    SP_ADD_CLASS_IN_FACTORY(TriangleSetTopologyModifier,sofa::component::topology::TriangleSetTopologyModifier)

    /// Custom Exception
    const char* name = "Sofa.SofaException";
    const char* doc = "Base exception class for the SofaPython module." ;
    PyObject* PyExc_SofaException = PyErr_NewExceptionWithDoc(
        (char*) "Sofa.SofaException",
        (char*) "Base exception class for the SofaPython module.",
        NULL, NULL);

    if ( PyExc_SofaException )
        PyModule_AddObject(PythonFactory::s_sofaPythonModule, "SofaException", PyExc_SofaException);
}

<commit_msg>[SofaPython] Fix unused char*.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, development version     *
*                (c) 2006-2017 INRIA, USTL, UJF, CNRS, MGH                    *
*                                                                             *
* This program is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this program. If not, see <http://www.gnu.org/licenses/>.        *
*******************************************************************************
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/
#include "PythonMacros.h"
#include "Binding.h"
#include "Binding_SofaModule.h"

#include "Binding_Data.h"
#include "Binding_DisplayFlagsData.h"
#include "Binding_OptionsGroupData.h"
#include "Binding_DataFileName.h"
#include "Binding_DataFileNameVector.h"
#include "Binding_VectorLinearSpringData.h"
#include "Binding_Link.h"
#include "Binding_Base.h"
#include "Binding_BaseObject.h"
#include "Binding_BaseState.h"
#include "Binding_BaseContext.h"
#include "Binding_Context.h"
#include "Binding_Node.h"
#include "Binding_Vector.h"
#include "Binding_TopologyChange.h"
#include "Binding_BaseLoader.h"
#include "Binding_MeshLoader.h"
#include "Binding_Topology.h"
#include "Binding_BaseMeshTopology.h"
#include "Binding_MeshTopology.h"
#include "Binding_GridTopology.h"
#include "Binding_RegularGridTopology.h"
#include "Binding_BaseMechanicalState.h"
#include "Binding_MechanicalObject.h"
#include "Binding_PythonScriptController.h"
#include "Binding_LinearSpring.h"
#include "Binding_BaseTopologyObject.h"
#include "Binding_TriangleSetTopologyModifier.h"
#include "Binding_PointSetTopologyModifier.h"
#include "Binding_BaseMapping.h"
#include "Binding_SubsetMultiMapping.h"
#include "Binding_VisualModel.h"
#include "Binding_OBJExporter.h"
#include "Binding_STLExporter.h"
#include "Binding_DataEngine.h"
#include "PythonFactory.h"

using sofa::PythonFactory;

void bindSofaPythonModule()
{
    PythonFactory::s_sofaPythonModule = SP_INIT_MODULE(Sofa)

    /// non Base-Inherited types
    SP_ADD_CLASS_IN_SOFAMODULE(Data)

    /// special Data cases
    SP_ADD_CLASS_IN_FACTORY(DisplayFlagsData,sofa::core::objectmodel::Data<sofa::core::visual::DisplayFlags>)
    SP_ADD_CLASS_IN_FACTORY(OptionsGroupData,sofa::core::objectmodel::Data<sofa::helper::OptionsGroup>)
    SP_ADD_CLASS_IN_FACTORY(DataFileName,sofa::core::objectmodel::DataFileName)
    SP_ADD_CLASS_IN_FACTORY(DataFileNameVector,sofa::core::objectmodel::DataFileNameVector)
    SP_ADD_CLASS_IN_SOFAMODULE(PointAncestorElem)
    SP_ADD_CLASS_IN_FACTORY(VectorLinearSpringData,sofa::core::objectmodel::Data<sofa::helper::vector<sofa::component::interactionforcefield::LinearSpring<SReal>>>)

    SP_ADD_CLASS_IN_SOFAMODULE(Link)
    SP_ADD_CLASS_IN_SOFAMODULE(Vector3)
    SP_ADD_CLASS_IN_SOFAMODULE(LinearSpring)

    /// special component categories gettable by static_cast
    SP_ADD_CLASS_IN_SOFAMODULE(Base)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseContext)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseObject)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseTopologyObject)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseState)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMechanicalState)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMapping)
    SP_ADD_CLASS_IN_SOFAMODULE(DataEngine)
    SP_ADD_CLASS_IN_SOFAMODULE(VisualModel)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseLoader)
    SP_ADD_CLASS_IN_SOFAMODULE(Topology)
    SP_ADD_CLASS_IN_SOFAMODULE(BaseMeshTopology)

    /// regular component bindings
    SP_ADD_CLASS_IN_FACTORY(Context,sofa::core::objectmodel::Context)
    SP_ADD_CLASS_IN_FACTORY(Node,sofa::simulation::Node)
    SP_ADD_CLASS_IN_FACTORY(VisualModelImpl,sofa::component::visualmodel::VisualModelImpl)
    SP_ADD_CLASS_IN_FACTORY(MeshLoader,sofa::core::loader::MeshLoader)
    SP_ADD_CLASS_IN_FACTORY(MeshTopology,sofa::component::topology::MeshTopology)
    SP_ADD_CLASS_IN_FACTORY(GridTopology,sofa::component::topology::GridTopology)
    SP_ADD_CLASS_IN_FACTORY(RegularGridTopology,sofa::component::topology::RegularGridTopology)
    SP_ADD_CLASS_IN_FACTORY(OBJExporter,sofa::component::misc::OBJExporter)
    SP_ADD_CLASS_IN_FACTORY(STLExporter,sofa::component::misc::STLExporter)
    SP_ADD_CLASS_IN_FACTORY(PythonScriptController,sofa::component::controller::PythonScriptController)
    SP_ADD_CLASS_IN_FACTORY(PointSetTopologyModifier,sofa::component::topology::PointSetTopologyModifier)
    SP_ADD_CLASS_IN_FACTORY(TriangleSetTopologyModifier,sofa::component::topology::TriangleSetTopologyModifier)

    /// Custom Exception
    PyObject* PyExc_SofaException = PyErr_NewExceptionWithDoc(
        (char*) "Sofa.SofaException",
        (char*) "Base exception class for the SofaPython module.",
        NULL, NULL);

    if ( PyExc_SofaException )
        PyModule_AddObject(PythonFactory::s_sofaPythonModule, "SofaException", PyExc_SofaException);
}

<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2012 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#define DBG 0

#include <string.h>
#include "rbuf.h"
#include "log.h"
#define CLASS_MODULE "rbuf"

#define dprintf(fmt, arg...) __dprintf(DBG_OUTPUT, fmt, ##arg)

rbuf::rbuf()
  : capacity(0)
  , p_data(NULL)
  , idx_read(0)
  , idx_write(0)
{
	dprintf("()");
	pthread_mutex_init(&mutex, 0);
}

rbuf::~rbuf()
{
	dprintf("()");
	pthread_mutex_lock(&mutex);

	if (p_data)
		delete p_data;

	pthread_mutex_unlock(&mutex);
	pthread_mutex_destroy(&mutex);
}

void rbuf::set_capacity(int cap)
{
	dprintf("(%d)", cap);
	pthread_mutex_lock(&mutex);

	if (p_data)
		delete p_data;

	p_data = new char[(capacity = cap)];
	__reset();

	pthread_mutex_unlock(&mutex);
}

int rbuf::get_capacity()
{
	dprintf("(%d)", capacity);
	return capacity;
}

int rbuf::get_size()
{
#if DBG
	dprintf("()");
#endif
	pthread_mutex_lock(&mutex);

	int ret = __get_size();

	pthread_mutex_unlock(&mutex);

	return ret;
}

void rbuf::reset()
{
	dprintf("()");
	pthread_mutex_lock(&mutex);

	__reset();

	pthread_mutex_unlock(&mutex);
}

int rbuf::get_write_ptr(void** p)
{
	pthread_mutex_lock(&mutex);

	return __get_write_ptr(p);
}

void rbuf::put_write_ptr(int size)
{
	__put_write_ptr(size);

	pthread_mutex_unlock(&mutex);
}

#if 0
bool rbuf::write(const void* p, int size)
{
	pthread_mutex_lock(&mutex);

	if (__get_size() + size > capacity)
		return false;

        if (idx_write + size > capacity) {
		int split = capacity - idx_write;
		memcpy(p_data + idx_write, p, split);
		idx_write = size - split;
		memcpy(p_data, (const char*) p + split, idx_write);
        } else {
		memcpy(p_data + idx_write, p, size);
		idx_write += size;
		if (idx_write == capacity)
			idx_write = 0;
        }
	pthread_mutex_unlock(&mutex);
        return true;
}
#else
bool rbuf::write(const void* p, int size)
{
	pthread_mutex_lock(&mutex);
	if (__get_size() + size > capacity)
		return false;

	void *q = NULL;
	char *r = (char*)p;
	int available;

	while (size) {
		available = __get_write_ptr(&q);
		if (available >= size) {
			memcpy(q, r, size);
			__put_write_ptr(size);
			size = 0;
		} else if (available > 0) {
			memcpy(q, r, available);
			__put_write_ptr(available);
			size -= available;
			r += available;
		}
#if 0
		else {
//			pthread_mutex_unlock(&mutex);
			return false;
		}
#endif
	}
	pthread_mutex_unlock(&mutex);
	return true;
}
#endif

int rbuf::get_read_ptr(void**p, int size)
{
	pthread_mutex_lock(&mutex);

	return __get_read_ptr(p, size);
}

void rbuf::put_read_ptr(int size)
{
	__put_read_ptr(size);

	pthread_mutex_unlock(&mutex);
}

int rbuf::read(void* p, int size)
{
	void *q = NULL;
	int newsize = get_read_ptr(&q, size);

	if (newsize)
		memcpy(p, q, newsize);

	put_read_ptr(newsize);
	return newsize;
}

int rbuf::__get_size()
{
	int ret = idx_write - idx_read;

	if (ret < 0)
		ret += capacity;

	return ret;
}

void rbuf::__reset()
{
	idx_read = idx_write = 0;
}

int rbuf::__get_write_ptr(void** p)
{
	int available = (idx_read <= idx_write) ? capacity - idx_write : idx_read - idx_write;

	if (available <= 0) {
		pthread_mutex_unlock(&mutex);
		return available;
	}
	*p = &p_data[idx_write];

	return available;
}

void rbuf::__put_write_ptr(int size)
{
	if (idx_write + size >= capacity) { // == should be enough FIXME!
		idx_write = 0;
	} else {
		idx_write += size;
	}
}

int rbuf::__get_read_ptr(void**p, int size)
{
	int max_size = __get_size();

	if (max_size == 0)
		return 0;

	if (size > max_size)
		size = max_size;

	if (idx_read + size >= capacity) {
		size = capacity - idx_read;
		*p = p_data + idx_read;
	} else {
		*p = p_data + idx_read;
	}
	return size;
}

void rbuf::__put_read_ptr(int size)
{
	if (idx_read + size >= capacity) {
		idx_read = 0;
	} else {
		idx_read += size;
	}
}
<commit_msg>rbuf: make get_capacity() less verbose<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2012 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/
#define DBG 0

#include <string.h>
#include "rbuf.h"
#include "log.h"
#define CLASS_MODULE "rbuf"

#define dprintf(fmt, arg...) __dprintf(DBG_OUTPUT, fmt, ##arg)

rbuf::rbuf()
  : capacity(0)
  , p_data(NULL)
  , idx_read(0)
  , idx_write(0)
{
	dprintf("()");
	pthread_mutex_init(&mutex, 0);
}

rbuf::~rbuf()
{
	dprintf("()");
	pthread_mutex_lock(&mutex);

	if (p_data)
		delete p_data;

	pthread_mutex_unlock(&mutex);
	pthread_mutex_destroy(&mutex);
}

void rbuf::set_capacity(int cap)
{
	dprintf("(%d)", cap);
	pthread_mutex_lock(&mutex);

	if (p_data)
		delete p_data;

	p_data = new char[(capacity = cap)];
	__reset();

	pthread_mutex_unlock(&mutex);
}

int rbuf::get_capacity()
{
#if DBG
	dprintf("(%d)", capacity);
#endif
	return capacity;
}

int rbuf::get_size()
{
#if DBG
	dprintf("()");
#endif
	pthread_mutex_lock(&mutex);

	int ret = __get_size();

	pthread_mutex_unlock(&mutex);

	return ret;
}

void rbuf::reset()
{
	dprintf("()");
	pthread_mutex_lock(&mutex);

	__reset();

	pthread_mutex_unlock(&mutex);
}

int rbuf::get_write_ptr(void** p)
{
	pthread_mutex_lock(&mutex);

	return __get_write_ptr(p);
}

void rbuf::put_write_ptr(int size)
{
	__put_write_ptr(size);

	pthread_mutex_unlock(&mutex);
}

#if 0
bool rbuf::write(const void* p, int size)
{
	pthread_mutex_lock(&mutex);

	if (__get_size() + size > capacity)
		return false;

        if (idx_write + size > capacity) {
		int split = capacity - idx_write;
		memcpy(p_data + idx_write, p, split);
		idx_write = size - split;
		memcpy(p_data, (const char*) p + split, idx_write);
        } else {
		memcpy(p_data + idx_write, p, size);
		idx_write += size;
		if (idx_write == capacity)
			idx_write = 0;
        }
	pthread_mutex_unlock(&mutex);
        return true;
}
#else
bool rbuf::write(const void* p, int size)
{
	pthread_mutex_lock(&mutex);
	if (__get_size() + size > capacity)
		return false;

	void *q = NULL;
	char *r = (char*)p;
	int available;

	while (size) {
		available = __get_write_ptr(&q);
		if (available >= size) {
			memcpy(q, r, size);
			__put_write_ptr(size);
			size = 0;
		} else if (available > 0) {
			memcpy(q, r, available);
			__put_write_ptr(available);
			size -= available;
			r += available;
		}
#if 0
		else {
//			pthread_mutex_unlock(&mutex);
			return false;
		}
#endif
	}
	pthread_mutex_unlock(&mutex);
	return true;
}
#endif

int rbuf::get_read_ptr(void**p, int size)
{
	pthread_mutex_lock(&mutex);

	return __get_read_ptr(p, size);
}

void rbuf::put_read_ptr(int size)
{
	__put_read_ptr(size);

	pthread_mutex_unlock(&mutex);
}

int rbuf::read(void* p, int size)
{
	void *q = NULL;
	int newsize = get_read_ptr(&q, size);

	if (newsize)
		memcpy(p, q, newsize);

	put_read_ptr(newsize);
	return newsize;
}

int rbuf::__get_size()
{
	int ret = idx_write - idx_read;

	if (ret < 0)
		ret += capacity;

	return ret;
}

void rbuf::__reset()
{
	idx_read = idx_write = 0;
}

int rbuf::__get_write_ptr(void** p)
{
	int available = (idx_read <= idx_write) ? capacity - idx_write : idx_read - idx_write;

	if (available <= 0) {
		pthread_mutex_unlock(&mutex);
		return available;
	}
	*p = &p_data[idx_write];

	return available;
}

void rbuf::__put_write_ptr(int size)
{
	if (idx_write + size >= capacity) { // == should be enough FIXME!
		idx_write = 0;
	} else {
		idx_write += size;
	}
}

int rbuf::__get_read_ptr(void**p, int size)
{
	int max_size = __get_size();

	if (max_size == 0)
		return 0;

	if (size > max_size)
		size = max_size;

	if (idx_read + size >= capacity) {
		size = capacity - idx_read;
		*p = p_data + idx_read;
	} else {
		*p = p_data + idx_read;
	}
	return size;
}

void rbuf::__put_read_ptr(int size)
{
	if (idx_read + size >= capacity) {
		idx_read = 0;
	} else {
		idx_read += size;
	}
}
<|endoftext|>


<commit_before>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This program 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 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "FileManagement.h"
#include <iostream>

namespace sofa
{
namespace gui
{
namespace qt
{

#ifndef SOFA_QT4
typedef QFileDialog Q3FileDialog;
#include <qdir.h>
#include <qfileinfo.h>
#else
#include <QDir>
#endif

QString getExistingDirectory ( QWidget* parent, const QString & dir, const char * name, const QString & caption)
{
#ifdef SOFA_QT4
    QFileDialog::Options options = QFileDialog::ShowDirsOnly;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::QFileDialog::DontUseSheet;
    return QFileDialog::getExistingDirectory ( parent, name?QString(name):caption, dir, options );
#else
    return Q3FileDialog::getExistingDirectory( dir, parent, name, caption );
#endif
};

QString getOpenFileName ( QWidget* parent, const QString & startWith, const QString & filter, const char * name, const QString & caption, QString * selectedFilter )
{
#ifdef SOFA_QT4
    QFileDialog::Options options = 0;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::DontUseSheet;
    return QFileDialog::getOpenFileName ( parent, name?QString(name):caption, startWith, filter, selectedFilter, options );
#else
    return Q3FileDialog::getOpenFileName ( startWith, filter, parent, name, caption, selectedFilter );
#endif
};

QString getSaveFileName ( QWidget* parent, const QString & startWith, const QString & filter, const char * name, const QString & caption, QString * selectedFilter )
{
#ifdef SOFA_QT4
    QFileDialog::Options options = 0;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::DontUseSheet;
    return QFileDialog::getSaveFileName ( parent, name?QString(name):caption, startWith, filter, selectedFilter, options );
#else
    return Q3FileDialog::getSaveFileName ( startWith, filter, parent, name, caption, selectedFilter );
#endif
};

void getFilesInDirectory( const QString &p, std::vector< QString > &files, bool recursive, const std::vector< QString > &filter )
{
    QString path=p;
    if (path.endsWith("/"))
    {
        int slash=path.find('/',-1);
        path.truncate(slash);
    }
    else if (path.endsWith("\\"))
    {
        int slash=path.find('\\',-1);
        path.truncate(slash);
    }

    QDir d(path);

    d.setFilter( QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > subDir;

    const QFileInfoList &listDirectories =
#ifdef SOFA_QT4
        d.entryInfoList();
    QStringList filters;
    for (unsigned int i=0; i<filter.size(); ++i)
        filters << filter[i];

    d.setNameFilters(filters);
    for (int j = 0; j < listDirectories.size(); ++j)
    {
        QFileInfo fileInfo=listDirectories.at(j);
#else
        *(d.entryInfoList());
    QString filters;
    for (unsigned int i=0; i<filter.size(); ++i)
        filters+=  filter[i] + QString(" ");

    d.setNameFilter(filters);
    QFileInfoListIterator itDir( listDirectories );
    while ( (itDir.current()) != 0 )
    {

        QFileInfo fileInfo=*(itDir.current());
#endif
        subDir.push_back(fileInfo.fileName());
#ifndef SOFA_QT4
        ++itDir;
#endif
    }

    d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );

    const QFileInfoList &listFiles =
#ifdef SOFA_QT4
        d.entryInfoList();
    for (int j = 0; j < listFiles.size(); ++j)
    {
        QFileInfo fileInfo=listFiles.at(j);
#else
        *(d.entryInfoList());
    QFileInfoListIterator itFile( listFiles );
    while ( (itFile.current()) != 0 )
    {
        QFileInfo fileInfo=*(itFile.current());
#endif
        files.push_back(path+QString("/")+fileInfo.fileName());
#ifndef SOFA_QT4
        ++itFile;
#endif
    }

    if (recursive)
    {
        for (unsigned int i=0; i<subDir.size(); ++i)
        {
            if (subDir[i].left(1) == QString(".")) continue;
            if (subDir[i] == QString("OBJ"))       continue;

            QString nextDir=path+QString("/")+subDir[i];
            getFilesInDirectory(nextDir, files, recursive, filter);
        }
    }
}

} // namespace qt

} // namespace gui

} // namespace sofa

<commit_msg>r4822/sofa-dev : FIX: small namespace mistake for sofa_QT4.<commit_after>/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 4      *
*                (c) 2006-2009 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This program 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 2 of the License, or (at your option)   *
* any later version.                                                          *
*                                                                             *
* This program is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for    *
* more details.                                                               *
*                                                                             *
* You should have received a copy of the GNU General Public License along     *
* with this program; if not, write to the Free Software Foundation, Inc., 51  *
* Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.                   *
*******************************************************************************
*                            SOFA :: Applications                             *
*                                                                             *
* Authors: M. Adam, J. Allard, B. Andre, P-J. Bensoussan, S. Cotin, C. Duriez,*
* H. Delingette, F. Falipou, F. Faure, S. Fonteneau, L. Heigeas, C. Mendoza,  *
* M. Nesme, P. Neumann, J-P. de la Plata Alcade, F. Poyer and F. Roy          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "FileManagement.h"
#include <iostream>

namespace sofa
{
namespace gui
{
namespace qt
{

#ifndef SOFA_QT4
typedef QFileDialog Q3FileDialog;
#include <qdir.h>
#include <qfileinfo.h>
#else
#include <QDir>
#endif

QString getExistingDirectory ( QWidget* parent, const QString & dir, const char * name, const QString & caption)
{
#ifdef SOFA_QT4
    QFileDialog::Options options = QFileDialog::ShowDirsOnly;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::DontUseSheet;
    return QFileDialog::getExistingDirectory ( parent, name?QString(name):caption, dir, options );
#else
    return Q3FileDialog::getExistingDirectory( dir, parent, name, caption );
#endif
};

QString getOpenFileName ( QWidget* parent, const QString & startWith, const QString & filter, const char * name, const QString & caption, QString * selectedFilter )
{
#ifdef SOFA_QT4
    QFileDialog::Options options = 0;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::DontUseSheet;
    return QFileDialog::getOpenFileName ( parent, name?QString(name):caption, startWith, filter, selectedFilter, options );
#else
    return Q3FileDialog::getOpenFileName ( startWith, filter, parent, name, caption, selectedFilter );
#endif
};

QString getSaveFileName ( QWidget* parent, const QString & startWith, const QString & filter, const char * name, const QString & caption, QString * selectedFilter )
{
#ifdef SOFA_QT4
    QFileDialog::Options options = 0;
    //	options |= QFileDialog::DontUseNativeDialog;
    options |= QFileDialog::DontUseSheet;
    return QFileDialog::getSaveFileName ( parent, name?QString(name):caption, startWith, filter, selectedFilter, options );
#else
    return Q3FileDialog::getSaveFileName ( startWith, filter, parent, name, caption, selectedFilter );
#endif
};

void getFilesInDirectory( const QString &p, std::vector< QString > &files, bool recursive, const std::vector< QString > &filter )
{
    QString path=p;
    if (path.endsWith("/"))
    {
        int slash=path.find('/',-1);
        path.truncate(slash);
    }
    else if (path.endsWith("\\"))
    {
        int slash=path.find('\\',-1);
        path.truncate(slash);
    }

    QDir d(path);

    d.setFilter( QDir::Dirs | QDir::Hidden | QDir::NoSymLinks );

    std::vector< QString > subDir;

    const QFileInfoList &listDirectories =
#ifdef SOFA_QT4
        d.entryInfoList();
    QStringList filters;
    for (unsigned int i=0; i<filter.size(); ++i)
        filters << filter[i];

    d.setNameFilters(filters);
    for (int j = 0; j < listDirectories.size(); ++j)
    {
        QFileInfo fileInfo=listDirectories.at(j);
#else
        *(d.entryInfoList());
    QString filters;
    for (unsigned int i=0; i<filter.size(); ++i)
        filters+=  filter[i] + QString(" ");

    d.setNameFilter(filters);
    QFileInfoListIterator itDir( listDirectories );
    while ( (itDir.current()) != 0 )
    {

        QFileInfo fileInfo=*(itDir.current());
#endif
        subDir.push_back(fileInfo.fileName());
#ifndef SOFA_QT4
        ++itDir;
#endif
    }

    d.setFilter( QDir::Files | QDir::Hidden | QDir::NoSymLinks );

    const QFileInfoList &listFiles =
#ifdef SOFA_QT4
        d.entryInfoList();
    for (int j = 0; j < listFiles.size(); ++j)
    {
        QFileInfo fileInfo=listFiles.at(j);
#else
        *(d.entryInfoList());
    QFileInfoListIterator itFile( listFiles );
    while ( (itFile.current()) != 0 )
    {
        QFileInfo fileInfo=*(itFile.current());
#endif
        files.push_back(path+QString("/")+fileInfo.fileName());
#ifndef SOFA_QT4
        ++itFile;
#endif
    }

    if (recursive)
    {
        for (unsigned int i=0; i<subDir.size(); ++i)
        {
            if (subDir[i].left(1) == QString(".")) continue;
            if (subDir[i] == QString("OBJ"))       continue;

            QString nextDir=path+QString("/")+subDir[i];
            getFilesInDirectory(nextDir, files, recursive, filter);
        }
    }
}

} // namespace qt

} // namespace gui

} // namespace sofa

<|endoftext|>


<commit_before>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "Physics/Capsule.h"
#include "Physics/Point.h"
#include "Physics/Sphere.h"

#include "ShapeTestBase.h"

namespace Magnum { namespace Physics { namespace Test {

class CapsuleTest: public Corrade::TestSuite::Tester, ShapeTestBase {
    public:
        CapsuleTest();

        void applyTransformation();
        void collisionPoint();
        void collisionSphere();
};

CapsuleTest::CapsuleTest() {
    addTests({&CapsuleTest::applyTransformation,
              &CapsuleTest::collisionPoint});
}

void CapsuleTest::applyTransformation() {
    Physics::Capsule3D capsule({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}, 7.0f);

    capsule.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::zAxis()));
    CORRADE_COMPARE(capsule.transformedA(), Vector3(-2.0f, 1.0f, 3.0f));
    CORRADE_COMPARE(capsule.transformedB(), Vector3(2.0f, -1.0f, -3.0f));
    CORRADE_COMPARE(capsule.radius(), 7.0f);

    /* Apply average scaling to radius */
    capsule.applyTransformationMatrix(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f}));
    CORRADE_COMPARE(capsule.transformedRadius(), Constants::sqrt3()*7.0f);
}

void CapsuleTest::collisionPoint() {
    Physics::Capsule3D capsule({-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, 2.0f);
    Physics::Point3D point({2.0f, 0.0f, 0.0f});
    Physics::Point3D point1({2.9f, 1.0f, 0.0f});
    Physics::Point3D point2({1.0f, 3.1f, 0.0f});

    randomTransformation(capsule);
    randomTransformation(point);
    randomTransformation(point1);
    randomTransformation(point2);

    VERIFY_COLLIDES(capsule, point);
    VERIFY_COLLIDES(capsule, point1);
    VERIFY_NOT_COLLIDES(capsule, point2);
}

void CapsuleTest::collisionSphere() {
    Physics::Capsule3D capsule({-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, 2.0f);
    Physics::Sphere3D sphere({3.0f, 0.0f, 0.0f}, 0.9f);
    Physics::Sphere3D sphere1({3.5f, 1.0f, 0.0f}, 0.6f);
    Physics::Sphere3D sphere2({1.0f, 4.1f, 0.0f}, 1.0f);

    randomTransformation(capsule);
    randomTransformation(sphere);
    randomTransformation(sphere1);
    randomTransformation(sphere2);

    VERIFY_COLLIDES(capsule, sphere);
    VERIFY_COLLIDES(capsule, sphere1);
    VERIFY_NOT_COLLIDES(capsule, sphere2);
}

}}}

CORRADE_TEST_MAIN(Magnum::Physics::Test::CapsuleTest)
<commit_msg>Physics: forgot to add test case to the list.<commit_after>/*
    This file is part of Magnum.

    Copyright © 2010, 2011, 2012, 2013 Vladimír Vondruš <mosra@centrum.cz>

    Permission is hereby granted, free of charge, to any person obtaining a
    copy of this software and associated documentation files (the "Software"),
    to deal in the Software without restriction, including without limitation
    the rights to use, copy, modify, merge, publish, distribute, sublicense,
    and/or sell copies of the Software, and to permit persons to whom the
    Software is furnished to do so, subject to the following conditions:

    The above copyright notice and this permission notice shall be included
    in all copies or substantial portions of the Software.

    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
    THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    DEALINGS IN THE SOFTWARE.
*/

#include "Physics/Capsule.h"
#include "Physics/Point.h"
#include "Physics/Sphere.h"

#include "ShapeTestBase.h"

namespace Magnum { namespace Physics { namespace Test {

class CapsuleTest: public Corrade::TestSuite::Tester, ShapeTestBase {
    public:
        CapsuleTest();

        void applyTransformation();
        void collisionPoint();
        void collisionSphere();
};

CapsuleTest::CapsuleTest() {
    addTests({&CapsuleTest::applyTransformation,
              &CapsuleTest::collisionPoint,
              &CapsuleTest::collisionSphere});
}

void CapsuleTest::applyTransformation() {
    Physics::Capsule3D capsule({1.0f, 2.0f, 3.0f}, {-1.0f, -2.0f, -3.0f}, 7.0f);

    capsule.applyTransformationMatrix(Matrix4::rotation(Deg(90.0f), Vector3::zAxis()));
    CORRADE_COMPARE(capsule.transformedA(), Vector3(-2.0f, 1.0f, 3.0f));
    CORRADE_COMPARE(capsule.transformedB(), Vector3(2.0f, -1.0f, -3.0f));
    CORRADE_COMPARE(capsule.radius(), 7.0f);

    /* Apply average scaling to radius */
    capsule.applyTransformationMatrix(Matrix4::scaling({Constants::sqrt3(), -Constants::sqrt2(), 2.0f}));
    CORRADE_COMPARE(capsule.transformedRadius(), Constants::sqrt3()*7.0f);
}

void CapsuleTest::collisionPoint() {
    Physics::Capsule3D capsule({-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, 2.0f);
    Physics::Point3D point({2.0f, 0.0f, 0.0f});
    Physics::Point3D point1({2.9f, 1.0f, 0.0f});
    Physics::Point3D point2({1.0f, 3.1f, 0.0f});

    randomTransformation(capsule);
    randomTransformation(point);
    randomTransformation(point1);
    randomTransformation(point2);

    VERIFY_COLLIDES(capsule, point);
    VERIFY_COLLIDES(capsule, point1);
    VERIFY_NOT_COLLIDES(capsule, point2);
}

void CapsuleTest::collisionSphere() {
    Physics::Capsule3D capsule({-1.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 0.0f}, 2.0f);
    Physics::Sphere3D sphere({3.0f, 0.0f, 0.0f}, 0.9f);
    Physics::Sphere3D sphere1({3.5f, 1.0f, 0.0f}, 0.6f);
    Physics::Sphere3D sphere2({1.0f, 4.1f, 0.0f}, 1.0f);

    randomTransformation(capsule);
    randomTransformation(sphere);
    randomTransformation(sphere1);
    randomTransformation(sphere2);

    VERIFY_COLLIDES(capsule, sphere);
    VERIFY_COLLIDES(capsule, sphere1);
    VERIFY_NOT_COLLIDES(capsule, sphere2);
}

}}}

CORRADE_TEST_MAIN(Magnum::Physics::Test::CapsuleTest)
<|endoftext|>


<commit_before>//===-- RegisterScavenging.cpp - Machine register scavenging --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine register scavenger. It can provide
// information, such as unused registers, at any point in a machine basic block.
// It also provides a mechanism to make registers available by evicting them to
// spill slots.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reg-scavenging"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

/// setUsed - Set the register and its sub-registers as being used.
void RegScavenger::setUsed(unsigned Reg) {
  RegsAvailable.reset(Reg);

  for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
       unsigned SubReg = *SubRegs; ++SubRegs)
    RegsAvailable.reset(SubReg);
}

bool RegScavenger::isAliasUsed(unsigned Reg) const {
  if (isUsed(Reg))
    return true;
  for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R)
    if (isUsed(*R))
      return true;
  return false;
}

void RegScavenger::initRegState() {
  ScavengedReg = 0;
  ScavengedRC = NULL;
  ScavengeRestore = NULL;

  // All registers started out unused.
  RegsAvailable.set();

  // Reserved registers are always used.
  RegsAvailable ^= ReservedRegs;

  if (!MBB)
    return;

  // Live-in registers are in use.
  for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(),
         E = MBB->livein_end(); I != E; ++I)
    setUsed(*I);

  // Pristine CSRs are also unavailable.
  BitVector PR = MBB->getParent()->getFrameInfo()->getPristineRegs(MBB);
  for (int I = PR.find_first(); I>0; I = PR.find_next(I))
    setUsed(I);
}

void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
  MachineFunction &MF = *mbb->getParent();
  const TargetMachine &TM = MF.getTarget();
  TII = TM.getInstrInfo();
  TRI = TM.getRegisterInfo();
  MRI = &MF.getRegInfo();

  assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) &&
         "Target changed?");

  // Self-initialize.
  if (!MBB) {
    NumPhysRegs = TRI->getNumRegs();
    RegsAvailable.resize(NumPhysRegs);

    // Create reserved registers bitvector.
    ReservedRegs = TRI->getReservedRegs(MF);

    // Create callee-saved registers bitvector.
    CalleeSavedRegs.resize(NumPhysRegs);
    const unsigned *CSRegs = TRI->getCalleeSavedRegs(&MF);
    if (CSRegs != NULL)
      for (unsigned i = 0; CSRegs[i]; ++i)
        CalleeSavedRegs.set(CSRegs[i]);
  }

  MBB = mbb;
  initRegState();

  Tracking = false;
}

void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
  BV.set(Reg);
  for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++)
    BV.set(*R);
}

void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) {
  BV.set(Reg);
  for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++)
    BV.set(*R);
}

void RegScavenger::forward() {
  // Move ptr forward.
  if (!Tracking) {
    MBBI = MBB->begin();
    Tracking = true;
  } else {
    assert(MBBI != MBB->end() && "Already past the end of the basic block!");
    MBBI = llvm::next(MBBI);
  }
  assert(MBBI != MBB->end() && "Already at the end of the basic block!");

  MachineInstr *MI = MBBI;

  if (MI == ScavengeRestore) {
    ScavengedReg = 0;
    ScavengedRC = NULL;
    ScavengeRestore = NULL;
  }

  if (MI->isDebugValue())
    return;

  // Find out which registers are early clobbered, killed, defined, and marked
  // def-dead in this instruction.
  // FIXME: The scavenger is not predication aware. If the instruction is
  // predicated, conservatively assume "kill" markers do not actually kill the
  // register. Similarly ignores "dead" markers.
  bool isPred = TII->isPredicated(MI);
  BitVector EarlyClobberRegs(NumPhysRegs);
  BitVector KillRegs(NumPhysRegs);
  BitVector DefRegs(NumPhysRegs);
  BitVector DeadRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg())
      continue;
    unsigned Reg = MO.getReg();
    if (!Reg || isReserved(Reg))
      continue;

    if (MO.isUse()) {
      // Ignore undef uses.
      if (MO.isUndef())
        continue;
      // Two-address operands implicitly kill.
      if (!isPred && (MO.isKill() || MI->isRegTiedToDefOperand(i)))
        addRegWithSubRegs(KillRegs, Reg);
    } else {
      assert(MO.isDef());
      if (!isPred && MO.isDead())
        addRegWithSubRegs(DeadRegs, Reg);
      else
        addRegWithSubRegs(DefRegs, Reg);
      if (MO.isEarlyClobber())
        addRegWithAliases(EarlyClobberRegs, Reg);
    }
  }

  // Verify uses and defs.
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg())
      continue;
    unsigned Reg = MO.getReg();
    if (!Reg || isReserved(Reg))
      continue;
    if (MO.isUse()) {
      if (MO.isUndef())
        continue;
      if (!isUsed(Reg)) {
        // Check if it's partial live: e.g.
        // D0 = insert_subreg D0<undef>, S0
        // ... D0
        // The problem is the insert_subreg could be eliminated. The use of
        // D0 is using a partially undef value. This is not *incorrect* since
        // S1 is can be freely clobbered.
        // Ideally we would like a way to model this, but leaving the
        // insert_subreg around causes both correctness and performance issues.
        bool SubUsed = false;
        for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
             unsigned SubReg = *SubRegs; ++SubRegs)
          if (isUsed(SubReg)) {
            SubUsed = true;
            break;
          }
#ifndef NDEBUG
        if (!SubUsed) {
          MBB->getParent()->verify(NULL, "In Register Scavenger");
          llvm_unreachable("Using an undefined register!");
        }
#endif
        (void)SubUsed;
      }
      assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) &&
             "Using an early clobbered register!");
    } else {
      assert(MO.isDef());
#if 0
      // FIXME: Enable this once we've figured out how to correctly transfer
      // implicit kills during codegen passes like the coalescer.
      assert((KillRegs.test(Reg) || isUnused(Reg) ||
              isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
             "Re-defining a live register!");
#endif
    }
  }

  // Commit the changes.
  setUnused(KillRegs);
  setUnused(DeadRegs);
  setUsed(DefRegs);
}

void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
  if (includeReserved)
    used = ~RegsAvailable;
  else
    used = ~RegsAvailable & ~ReservedRegs;
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const {
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
       I != E; ++I)
    if (!isAliasUsed(*I)) {
      DEBUG(dbgs() << "Scavenger found unused reg: " << TRI->getName(*I) <<
            "\n");
      return *I;
    }
  return 0;
}

/// getRegsAvailable - Return all available registers in the register class
/// in Mask.
BitVector RegScavenger::getRegsAvailable(const TargetRegisterClass *RC) {
  BitVector Mask(TRI->getNumRegs());
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
       I != E; ++I)
    if (!isAliasUsed(*I))
      Mask.set(*I);
  return Mask;
}

/// findSurvivorReg - Return the candidate register that is unused for the
/// longest after StargMII. UseMI is set to the instruction where the search
/// stopped.
///
/// No more than InstrLimit instructions are inspected.
///
unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator StartMI,
                                       BitVector &Candidates,
                                       unsigned InstrLimit,
                                       MachineBasicBlock::iterator &UseMI) {
  int Survivor = Candidates.find_first();
  assert(Survivor > 0 && "No candidates for scavenging");

  MachineBasicBlock::iterator ME = MBB->getFirstTerminator();
  assert(StartMI != ME && "MI already at terminator");
  MachineBasicBlock::iterator RestorePointMI = StartMI;
  MachineBasicBlock::iterator MI = StartMI;

  bool inVirtLiveRange = false;
  for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) {
    if (MI->isDebugValue()) {
      ++InstrLimit; // Don't count debug instructions
      continue;
    }
    bool isVirtKillInsn = false;
    bool isVirtDefInsn = false;
    // Remove any candidates touched by instruction.
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      const MachineOperand &MO = MI->getOperand(i);
      if (!MO.isReg() || MO.isUndef() || !MO.getReg())
        continue;
      if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
        if (MO.isDef())
          isVirtDefInsn = true;
        else if (MO.isKill())
          isVirtKillInsn = true;
        continue;
      }
      Candidates.reset(MO.getReg());
      for (const unsigned *R = TRI->getAliasSet(MO.getReg()); *R; R++)
        Candidates.reset(*R);
    }
    // If we're not in a virtual reg's live range, this is a valid
    // restore point.
    if (!inVirtLiveRange) RestorePointMI = MI;

    // Update whether we're in the live range of a virtual register
    if (isVirtKillInsn) inVirtLiveRange = false;
    if (isVirtDefInsn) inVirtLiveRange = true;

    // Was our survivor untouched by this instruction?
    if (Candidates.test(Survivor))
      continue;

    // All candidates gone?
    if (Candidates.none())
      break;

    Survivor = Candidates.find_first();
  }
  // If we ran off the end, that's where we want to restore.
  if (MI == ME) RestorePointMI = ME;
  assert (RestorePointMI != StartMI &&
          "No available scavenger restore location!");

  // We ran out of candidates, so stop the search.
  UseMI = RestorePointMI;
  return Survivor;
}

unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
                                        MachineBasicBlock::iterator I,
                                        int SPAdj) {
  // Consider all allocatable registers in the register class initially
  BitVector Candidates =
    TRI->getAllocatableSet(*I->getParent()->getParent(), RC);

  // Exclude all the registers being used by the instruction.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    MachineOperand &MO = I->getOperand(i);
    if (MO.isReg() && MO.getReg() != 0 &&
        !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
      Candidates.reset(MO.getReg());
  }

  // Try to find a register that's unused if there is one, as then we won't
  // have to spill. Search explicitly rather than masking out based on
  // RegsAvailable, as RegsAvailable does not take aliases into account.
  // That's what getRegsAvailable() is for.
  BitVector Available = getRegsAvailable(RC);

  if ((Candidates & Available).any())
     Candidates &= Available;

  // Find the register whose use is furthest away.
  MachineBasicBlock::iterator UseMI;
  unsigned SReg = findSurvivorReg(I, Candidates, 25, UseMI);

  // If we found an unused register there is no reason to spill it.
  if (!isAliasUsed(SReg)) {
    DEBUG(dbgs() << "Scavenged register: " << TRI->getName(SReg) << "\n");
    return SReg;
  }

  assert(ScavengedReg == 0 &&
         "Scavenger slot is live, unable to scavenge another register!");

  // Avoid infinite regress
  ScavengedReg = SReg;

  // If the target knows how to save/restore the register, let it do so;
  // otherwise, use the emergency stack spill slot.
  if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) {
    // Spill the scavenged register before I.
    assert(ScavengingFrameIndex >= 0 &&
           "Cannot scavenge register without an emergency spill slot!");
    TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC,TRI);
    MachineBasicBlock::iterator II = prior(I);
    TRI->eliminateFrameIndex(II, SPAdj, this);

    // Restore the scavenged register before its use (or first terminator).
    TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC, TRI);
    II = prior(UseMI);
    TRI->eliminateFrameIndex(II, SPAdj, this);
  }

  ScavengeRestore = prior(UseMI);

  // Doing this here leads to infinite regress.
  // ScavengedReg = SReg;
  ScavengedRC = RC;

  DEBUG(dbgs() << "Scavenged register (with spill): " << TRI->getName(SReg) <<
        "\n");

  return SReg;
}
<commit_msg>Avoid creating BitVector temporaries.<commit_after>//===-- RegisterScavenging.cpp - Machine register scavenging --------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the machine register scavenger. It can provide
// information, such as unused registers, at any point in a machine basic block.
// It also provides a mechanism to make registers available by evicting them to
// spill slots.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "reg-scavenging"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include "llvm/CodeGen/MachineInstr.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetRegisterInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/STLExtras.h"
using namespace llvm;

/// setUsed - Set the register and its sub-registers as being used.
void RegScavenger::setUsed(unsigned Reg) {
  RegsAvailable.reset(Reg);

  for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
       unsigned SubReg = *SubRegs; ++SubRegs)
    RegsAvailable.reset(SubReg);
}

bool RegScavenger::isAliasUsed(unsigned Reg) const {
  if (isUsed(Reg))
    return true;
  for (const unsigned *R = TRI->getAliasSet(Reg); *R; ++R)
    if (isUsed(*R))
      return true;
  return false;
}

void RegScavenger::initRegState() {
  ScavengedReg = 0;
  ScavengedRC = NULL;
  ScavengeRestore = NULL;

  // All registers started out unused.
  RegsAvailable.set();

  // Reserved registers are always used.
  RegsAvailable ^= ReservedRegs;

  if (!MBB)
    return;

  // Live-in registers are in use.
  for (MachineBasicBlock::livein_iterator I = MBB->livein_begin(),
         E = MBB->livein_end(); I != E; ++I)
    setUsed(*I);

  // Pristine CSRs are also unavailable.
  BitVector PR = MBB->getParent()->getFrameInfo()->getPristineRegs(MBB);
  for (int I = PR.find_first(); I>0; I = PR.find_next(I))
    setUsed(I);
}

void RegScavenger::enterBasicBlock(MachineBasicBlock *mbb) {
  MachineFunction &MF = *mbb->getParent();
  const TargetMachine &TM = MF.getTarget();
  TII = TM.getInstrInfo();
  TRI = TM.getRegisterInfo();
  MRI = &MF.getRegInfo();

  assert((NumPhysRegs == 0 || NumPhysRegs == TRI->getNumRegs()) &&
         "Target changed?");

  // Self-initialize.
  if (!MBB) {
    NumPhysRegs = TRI->getNumRegs();
    RegsAvailable.resize(NumPhysRegs);

    // Create reserved registers bitvector.
    ReservedRegs = TRI->getReservedRegs(MF);

    // Create callee-saved registers bitvector.
    CalleeSavedRegs.resize(NumPhysRegs);
    const unsigned *CSRegs = TRI->getCalleeSavedRegs(&MF);
    if (CSRegs != NULL)
      for (unsigned i = 0; CSRegs[i]; ++i)
        CalleeSavedRegs.set(CSRegs[i]);
  }

  MBB = mbb;
  initRegState();

  Tracking = false;
}

void RegScavenger::addRegWithSubRegs(BitVector &BV, unsigned Reg) {
  BV.set(Reg);
  for (const unsigned *R = TRI->getSubRegisters(Reg); *R; R++)
    BV.set(*R);
}

void RegScavenger::addRegWithAliases(BitVector &BV, unsigned Reg) {
  BV.set(Reg);
  for (const unsigned *R = TRI->getAliasSet(Reg); *R; R++)
    BV.set(*R);
}

void RegScavenger::forward() {
  // Move ptr forward.
  if (!Tracking) {
    MBBI = MBB->begin();
    Tracking = true;
  } else {
    assert(MBBI != MBB->end() && "Already past the end of the basic block!");
    MBBI = llvm::next(MBBI);
  }
  assert(MBBI != MBB->end() && "Already at the end of the basic block!");

  MachineInstr *MI = MBBI;

  if (MI == ScavengeRestore) {
    ScavengedReg = 0;
    ScavengedRC = NULL;
    ScavengeRestore = NULL;
  }

  if (MI->isDebugValue())
    return;

  // Find out which registers are early clobbered, killed, defined, and marked
  // def-dead in this instruction.
  // FIXME: The scavenger is not predication aware. If the instruction is
  // predicated, conservatively assume "kill" markers do not actually kill the
  // register. Similarly ignores "dead" markers.
  bool isPred = TII->isPredicated(MI);
  BitVector EarlyClobberRegs(NumPhysRegs);
  BitVector KillRegs(NumPhysRegs);
  BitVector DefRegs(NumPhysRegs);
  BitVector DeadRegs(NumPhysRegs);
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg())
      continue;
    unsigned Reg = MO.getReg();
    if (!Reg || isReserved(Reg))
      continue;

    if (MO.isUse()) {
      // Ignore undef uses.
      if (MO.isUndef())
        continue;
      // Two-address operands implicitly kill.
      if (!isPred && (MO.isKill() || MI->isRegTiedToDefOperand(i)))
        addRegWithSubRegs(KillRegs, Reg);
    } else {
      assert(MO.isDef());
      if (!isPred && MO.isDead())
        addRegWithSubRegs(DeadRegs, Reg);
      else
        addRegWithSubRegs(DefRegs, Reg);
      if (MO.isEarlyClobber())
        addRegWithAliases(EarlyClobberRegs, Reg);
    }
  }

  // Verify uses and defs.
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (!MO.isReg())
      continue;
    unsigned Reg = MO.getReg();
    if (!Reg || isReserved(Reg))
      continue;
    if (MO.isUse()) {
      if (MO.isUndef())
        continue;
      if (!isUsed(Reg)) {
        // Check if it's partial live: e.g.
        // D0 = insert_subreg D0<undef>, S0
        // ... D0
        // The problem is the insert_subreg could be eliminated. The use of
        // D0 is using a partially undef value. This is not *incorrect* since
        // S1 is can be freely clobbered.
        // Ideally we would like a way to model this, but leaving the
        // insert_subreg around causes both correctness and performance issues.
        bool SubUsed = false;
        for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
             unsigned SubReg = *SubRegs; ++SubRegs)
          if (isUsed(SubReg)) {
            SubUsed = true;
            break;
          }
#ifndef NDEBUG
        if (!SubUsed) {
          MBB->getParent()->verify(NULL, "In Register Scavenger");
          llvm_unreachable("Using an undefined register!");
        }
#endif
        (void)SubUsed;
      }
      assert((!EarlyClobberRegs.test(Reg) || MI->isRegTiedToDefOperand(i)) &&
             "Using an early clobbered register!");
    } else {
      assert(MO.isDef());
#if 0
      // FIXME: Enable this once we've figured out how to correctly transfer
      // implicit kills during codegen passes like the coalescer.
      assert((KillRegs.test(Reg) || isUnused(Reg) ||
              isLiveInButUnusedBefore(Reg, MI, MBB, TRI, MRI)) &&
             "Re-defining a live register!");
#endif
    }
  }

  // Commit the changes.
  setUnused(KillRegs);
  setUnused(DeadRegs);
  setUsed(DefRegs);
}

void RegScavenger::getRegsUsed(BitVector &used, bool includeReserved) {
  used = RegsAvailable;
  if (!includeReserved)
    used |= ReservedRegs;
  used.flip();
}

unsigned RegScavenger::FindUnusedReg(const TargetRegisterClass *RC) const {
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
       I != E; ++I)
    if (!isAliasUsed(*I)) {
      DEBUG(dbgs() << "Scavenger found unused reg: " << TRI->getName(*I) <<
            "\n");
      return *I;
    }
  return 0;
}

/// getRegsAvailable - Return all available registers in the register class
/// in Mask.
BitVector RegScavenger::getRegsAvailable(const TargetRegisterClass *RC) {
  BitVector Mask(TRI->getNumRegs());
  for (TargetRegisterClass::iterator I = RC->begin(), E = RC->end();
       I != E; ++I)
    if (!isAliasUsed(*I))
      Mask.set(*I);
  return Mask;
}

/// findSurvivorReg - Return the candidate register that is unused for the
/// longest after StargMII. UseMI is set to the instruction where the search
/// stopped.
///
/// No more than InstrLimit instructions are inspected.
///
unsigned RegScavenger::findSurvivorReg(MachineBasicBlock::iterator StartMI,
                                       BitVector &Candidates,
                                       unsigned InstrLimit,
                                       MachineBasicBlock::iterator &UseMI) {
  int Survivor = Candidates.find_first();
  assert(Survivor > 0 && "No candidates for scavenging");

  MachineBasicBlock::iterator ME = MBB->getFirstTerminator();
  assert(StartMI != ME && "MI already at terminator");
  MachineBasicBlock::iterator RestorePointMI = StartMI;
  MachineBasicBlock::iterator MI = StartMI;

  bool inVirtLiveRange = false;
  for (++MI; InstrLimit > 0 && MI != ME; ++MI, --InstrLimit) {
    if (MI->isDebugValue()) {
      ++InstrLimit; // Don't count debug instructions
      continue;
    }
    bool isVirtKillInsn = false;
    bool isVirtDefInsn = false;
    // Remove any candidates touched by instruction.
    for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
      const MachineOperand &MO = MI->getOperand(i);
      if (!MO.isReg() || MO.isUndef() || !MO.getReg())
        continue;
      if (TargetRegisterInfo::isVirtualRegister(MO.getReg())) {
        if (MO.isDef())
          isVirtDefInsn = true;
        else if (MO.isKill())
          isVirtKillInsn = true;
        continue;
      }
      Candidates.reset(MO.getReg());
      for (const unsigned *R = TRI->getAliasSet(MO.getReg()); *R; R++)
        Candidates.reset(*R);
    }
    // If we're not in a virtual reg's live range, this is a valid
    // restore point.
    if (!inVirtLiveRange) RestorePointMI = MI;

    // Update whether we're in the live range of a virtual register
    if (isVirtKillInsn) inVirtLiveRange = false;
    if (isVirtDefInsn) inVirtLiveRange = true;

    // Was our survivor untouched by this instruction?
    if (Candidates.test(Survivor))
      continue;

    // All candidates gone?
    if (Candidates.none())
      break;

    Survivor = Candidates.find_first();
  }
  // If we ran off the end, that's where we want to restore.
  if (MI == ME) RestorePointMI = ME;
  assert (RestorePointMI != StartMI &&
          "No available scavenger restore location!");

  // We ran out of candidates, so stop the search.
  UseMI = RestorePointMI;
  return Survivor;
}

unsigned RegScavenger::scavengeRegister(const TargetRegisterClass *RC,
                                        MachineBasicBlock::iterator I,
                                        int SPAdj) {
  // Consider all allocatable registers in the register class initially
  BitVector Candidates =
    TRI->getAllocatableSet(*I->getParent()->getParent(), RC);

  // Exclude all the registers being used by the instruction.
  for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i) {
    MachineOperand &MO = I->getOperand(i);
    if (MO.isReg() && MO.getReg() != 0 &&
        !TargetRegisterInfo::isVirtualRegister(MO.getReg()))
      Candidates.reset(MO.getReg());
  }

  // Try to find a register that's unused if there is one, as then we won't
  // have to spill. Search explicitly rather than masking out based on
  // RegsAvailable, as RegsAvailable does not take aliases into account.
  // That's what getRegsAvailable() is for.
  BitVector Available = getRegsAvailable(RC);
  Available &= Candidates;
  if (Available.any())
    Candidates = Available;

  // Find the register whose use is furthest away.
  MachineBasicBlock::iterator UseMI;
  unsigned SReg = findSurvivorReg(I, Candidates, 25, UseMI);

  // If we found an unused register there is no reason to spill it.
  if (!isAliasUsed(SReg)) {
    DEBUG(dbgs() << "Scavenged register: " << TRI->getName(SReg) << "\n");
    return SReg;
  }

  assert(ScavengedReg == 0 &&
         "Scavenger slot is live, unable to scavenge another register!");

  // Avoid infinite regress
  ScavengedReg = SReg;

  // If the target knows how to save/restore the register, let it do so;
  // otherwise, use the emergency stack spill slot.
  if (!TRI->saveScavengerRegister(*MBB, I, UseMI, RC, SReg)) {
    // Spill the scavenged register before I.
    assert(ScavengingFrameIndex >= 0 &&
           "Cannot scavenge register without an emergency spill slot!");
    TII->storeRegToStackSlot(*MBB, I, SReg, true, ScavengingFrameIndex, RC,TRI);
    MachineBasicBlock::iterator II = prior(I);
    TRI->eliminateFrameIndex(II, SPAdj, this);

    // Restore the scavenged register before its use (or first terminator).
    TII->loadRegFromStackSlot(*MBB, UseMI, SReg, ScavengingFrameIndex, RC, TRI);
    II = prior(UseMI);
    TRI->eliminateFrameIndex(II, SPAdj, this);
  }

  ScavengeRestore = prior(UseMI);

  // Doing this here leads to infinite regress.
  // ScavengedReg = SReg;
  ScavengedRC = RC;

  DEBUG(dbgs() << "Scavenged register (with spill): " << TRI->getName(SReg) <<
        "\n");

  return SReg;
}
<|endoftext|>


<commit_before>/*
 * Boost.Foreach support for pugixml classes.
 * This file is provided to the public domain.
 * Written by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
 */

#ifndef HEADER_PUGIXML_FOREACH_HPP
#define HEADER_PUGIXML_FOREACH_HPP

#include "pugixml.hpp"

/*
 * These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child iteration only).
 * Example usage:
 * BOOST_FOREACH(xml_node n, doc) {}
 */

namespace boost
{
	template <typename> struct range_mutable_iterator;
	template <typename> struct range_const_iterator;

	template<> struct range_mutable_iterator<pugi::xml_node>
	{
		typedef pugi::xml_node::iterator type;
	};

	template<> struct range_const_iterator<pugi::xml_node>
	{
		typedef pugi::xml_node::iterator type;
	};

	template<> struct range_mutable_iterator<pugi::xml_document>
	{
		typedef pugi::xml_document::iterator type;
	};

	template<> struct range_const_iterator<pugi::xml_document>
	{
		typedef pugi::xml_document::iterator type;
	};
}

/*
 * These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child/attribute iteration).
 * Example usage:
 * BOOST_FOREACH(xml_node n, children(doc)) {}
 * BOOST_FOREACH(xml_node n, attributes(doc)) {}
 */

namespace pugi
{
	struct xml_node_children_adapter
	{
		typedef pugi::xml_node::iterator iterator;
		typedef pugi::xml_node::iterator const_iterator;

		xml_node node;

		const_iterator begin() const
		{
			return node.begin();
		}

		const_iterator end() const
		{
			return node.end();
		}
	};

	inline xml_node_children_adapter children(const pugi::xml_node& node)
	{
		xml_node_children_adapter result = {node};
		return result;
	}

	struct xml_node_attribute_adapter
	{
		typedef pugi::xml_node::attribute_iterator iterator;
		typedef pugi::xml_node::attribute_iterator const_iterator;

		xml_node node;

		const_iterator begin() const
		{
			return node.attributes_begin();
		}

		const_iterator end() const
		{
			return node.attributes_end();
		}
	};

	inline xml_node_attribute_adapter attributes(const pugi::xml_node& node)
	{
		xml_node_attribute_adapter result = {node};
		return result;
	}
}

#endif
<commit_msg>contrib: Foreach contrib file is not really needed any more; left for compatibility, + removed node/attribute adapters since we now have object range support in pugixml.hpp<commit_after>/*
 * Boost.Foreach support for pugixml classes.
 * This file is provided to the public domain.
 * Written by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
 */

#ifndef HEADER_PUGIXML_FOREACH_HPP
#define HEADER_PUGIXML_FOREACH_HPP

#include "pugixml.hpp"

/*
 * These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child iteration only).
 * Example usage:
 * BOOST_FOREACH(xml_node n, doc) {}
 */

namespace boost
{
	template <typename> struct range_mutable_iterator;
	template <typename> struct range_const_iterator;

	template<> struct range_mutable_iterator<pugi::xml_node>
	{
		typedef pugi::xml_node::iterator type;
	};

	template<> struct range_const_iterator<pugi::xml_node>
	{
		typedef pugi::xml_node::iterator type;
	};

	template<> struct range_mutable_iterator<pugi::xml_document>
	{
		typedef pugi::xml_document::iterator type;
	};

	template<> struct range_const_iterator<pugi::xml_document>
	{
		typedef pugi::xml_document::iterator type;
	};
}

/*
 * These types add support for BOOST_FOREACH macro to xml_node and xml_document classes (child/attribute iteration).
 * Example usage:
 * BOOST_FOREACH(xml_node n, children(doc)) {}
 * BOOST_FOREACH(xml_node n, attributes(doc)) {}
 */

namespace pugi
{
	inline xml_object_range<xml_node_iterator> children(const pugi::xml_node& node)
	{
        return node.children();
	}

	inline xml_object_range<xml_attribute_iterator> attributes(const pugi::xml_node& node)
	{
        return node.attributes();
	}
}

#endif
<|endoftext|>


<commit_before>#pragma once

namespace DO {

    //! \defgroup ColorTypes Color typedefs
  //! @{

  // ======================================================================== //
  //! self-explanatory.
  typedef unsigned char gray8;
  //! self-explanatory.
  typedef char gray8s;
  //! self-explanatory.
  typedef unsigned short gray16;
  //! self-explanatory.
  typedef short gray16s;
  //! self-explanatory.
  typedef unsigned int gray32;
  //! self-explanatory.
  typedef int gray32s;
  //! self-explanatory.
  typedef float gray32f;
  //! self-explanatory.
  typedef double gray64f;

  // ======================================================================== //
  //! Macro for generic color typedefs
#define DEFINE_GENERIC_COLOR_TYPEDEFS(N)            \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<unsigned char, N, 1> Color##N##ub; \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<char, N, 1> Color##N##b;           \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<unsigned short, N, 1> Color##N##us;\
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<short, N, 1> Color##N##s;          \
  /*! \brief Color{NumChannels}{ChannelType}. */    \
  typedef Matrix<unsigned int, N, 1> Color##N##ui;  \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<int, N, 1> Color##N##i;            \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<float, N, 1> Color##N##f;          \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<double, N, 1> Color##N##d;

  DEFINE_GENERIC_COLOR_TYPEDEFS(3)
  DEFINE_GENERIC_COLOR_TYPEDEFS(4)
#undef DEFINE_GENERIC_COLOR_TYPEDEFS

  // ======================================================================== //
  //! Macro for color typedefs.
#define DEFINE_COLOR_TYPES(colorspace)                      \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned char, colorspace> colorspace##8;   \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned short, colorspace> colorspace##16; \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned int, colorspace> colorspace##32;   \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<char, colorspace> colorspace##8s;           \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<short, colorspace> colorspace##16s;         \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<int, colorspace> colorspace##32s;           \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<float, colorspace> colorspace##32f;         \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<double, colorspace> colorspace##64f;

  DEFINE_COLOR_TYPES(Rgb)
  DEFINE_COLOR_TYPES(Rgba)
  DEFINE_COLOR_TYPES(Cmyk)
  DEFINE_COLOR_TYPES(Yuv)
#undef DEFINE_COLOR_TYPES
  //! @} ColorTypes

  // ======================================================================== //
  //! \defgroup PrimaryColors Primary Colors in RGB.
  //! @{

  //! White color function.
  template <typename T> inline Matrix<T, 3, 1> white()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max() );
  }
  //! Black color function.
  template <typename T> inline Matrix<T, 3, 1> black()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min() );
  }
  //! Red color function.
  template <typename T> inline Matrix<T, 3, 1> red()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min() );
  }
  //! Green color function.
  template <typename T> inline Matrix<T, 3, 1> green()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min() );
  }
  //! Blue color function.
  template <typename T> inline Matrix<T, 3, 1> blue()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max() );
  }
  //! Cyan color function.
  template <typename T> inline Matrix<T, 3, 1> cyan()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max() );
  }
  //! Yellow color function.
  template <typename T> inline Matrix<T, 3, 1> yellow()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min() );
  }
  //! Magenta color function.
  template <typename T> inline Matrix<T, 3, 1> magenta()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max() );
  }

  //! Primary color definition.
#define DEFINE_COLOR_CONSTANT(Name, function)       \
  /*! \brief Return primary color of type Rgb8. */  \
  const Rgb8 Name##8(function<unsigned char>());    \
  /*! \brief Return primary color of type Rgb8s. */ \
  const Rgb8s Name##8s(function<char>());           \
  /*! \brief Return primary color of type Rgb16. */ \
  const Rgb16 Name##16(function<unsigned short>()); \
  /*! \brief Return primary color of type Rgb16s. */\
  const Rgb16s Name##16s(function<short>());        \
  /*! \brief Return primary color of type Rgb32. */ \
  const Rgb32 Name##32(function<unsigned int>());   \
  /*! \brief Return primary color of type Rgb32s. */\
  const Rgb32s Name##32s(function<int>());          \
  /*! \brief Return primary color of type Rgb32f. */\
  const Rgb32f Name##32f(function<float>());        \
  /*! \brief Return primary color of type Rgb64f. */\
  const Rgb64f Name##64f(function<double>());

  DEFINE_COLOR_CONSTANT(Red, red)
  DEFINE_COLOR_CONSTANT(Green, green)
  DEFINE_COLOR_CONSTANT(Blue, blue)
  DEFINE_COLOR_CONSTANT(Cyan, cyan)
  DEFINE_COLOR_CONSTANT(Magenta, magenta)
  DEFINE_COLOR_CONSTANT(Yellow, yellow)
  DEFINE_COLOR_CONSTANT(Black, black)
  DEFINE_COLOR_CONSTANT(White, white)
#undef DEFINE_COLOR_CONSTANT
  //! @}

  //! @}

} /* namespace DO */<commit_msg>Remove unused typedefs.<commit_after>#pragma once

namespace DO {

  //! \defgroup ColorTypes Color typedefs
  //! @{

  // ======================================================================== //
  //! Macro for generic color typedefs
#define DEFINE_GENERIC_COLOR_TYPEDEFS(N)            \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<unsigned char, N, 1> Color##N##ub; \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<char, N, 1> Color##N##b;           \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<unsigned short, N, 1> Color##N##us;\
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<short, N, 1> Color##N##s;          \
  /*! \brief Color{NumChannels}{ChannelType}. */    \
  typedef Matrix<unsigned int, N, 1> Color##N##ui;  \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<int, N, 1> Color##N##i;            \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<float, N, 1> Color##N##f;          \
  /*! \brief Color{NumChannels}{ChannelType} */     \
  typedef Matrix<double, N, 1> Color##N##d;

  DEFINE_GENERIC_COLOR_TYPEDEFS(3)
  DEFINE_GENERIC_COLOR_TYPEDEFS(4)
#undef DEFINE_GENERIC_COLOR_TYPEDEFS

  // ======================================================================== //
  //! Macro for color typedefs.
#define DEFINE_COLOR_TYPES(colorspace)                      \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned char, colorspace> colorspace##8;   \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned short, colorspace> colorspace##16; \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<unsigned int, colorspace> colorspace##32;   \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<char, colorspace> colorspace##8s;           \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<short, colorspace> colorspace##16s;         \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<int, colorspace> colorspace##32s;           \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<float, colorspace> colorspace##32f;         \
  /*! \brief {ColorSpace}{BitDepthPerChannel} */            \
  typedef Color<double, colorspace> colorspace##64f;

  DEFINE_COLOR_TYPES(Rgb)
  DEFINE_COLOR_TYPES(Rgba)
  DEFINE_COLOR_TYPES(Cmyk)
  DEFINE_COLOR_TYPES(Yuv)
#undef DEFINE_COLOR_TYPES
  //! @} ColorTypes

  // ======================================================================== //
  //! \defgroup PrimaryColors Primary Colors in RGB.
  //! @{

  //! White color function.
  template <typename T> inline Matrix<T, 3, 1> white()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max() );
  }
  //! Black color function.
  template <typename T> inline Matrix<T, 3, 1> black()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min() );
  }
  //! Red color function.
  template <typename T> inline Matrix<T, 3, 1> red()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min() );
  }
  //! Green color function.
  template <typename T> inline Matrix<T, 3, 1> green()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min() );
  }
  //! Blue color function.
  template <typename T> inline Matrix<T, 3, 1> blue()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max() );
  }
  //! Cyan color function.
  template <typename T> inline Matrix<T, 3, 1> cyan()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max() );
  }
  //! Yellow color function.
  template <typename T> inline Matrix<T, 3, 1> yellow()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min() );
  }
  //! Magenta color function.
  template <typename T> inline Matrix<T, 3, 1> magenta()
  {
    return Matrix<T,3,1>(
      ChannelTraits<T>::max(),
      ChannelTraits<T>::min(),
      ChannelTraits<T>::max() );
  }

  //! Primary color definition.
#define DEFINE_COLOR_CONSTANT(Name, function)       \
  /*! \brief Return primary color of type Rgb8. */  \
  const Rgb8 Name##8(function<unsigned char>());    \
  /*! \brief Return primary color of type Rgb8s. */ \
  const Rgb8s Name##8s(function<char>());           \
  /*! \brief Return primary color of type Rgb16. */ \
  const Rgb16 Name##16(function<unsigned short>()); \
  /*! \brief Return primary color of type Rgb16s. */\
  const Rgb16s Name##16s(function<short>());        \
  /*! \brief Return primary color of type Rgb32. */ \
  const Rgb32 Name##32(function<unsigned int>());   \
  /*! \brief Return primary color of type Rgb32s. */\
  const Rgb32s Name##32s(function<int>());          \
  /*! \brief Return primary color of type Rgb32f. */\
  const Rgb32f Name##32f(function<float>());        \
  /*! \brief Return primary color of type Rgb64f. */\
  const Rgb64f Name##64f(function<double>());

  DEFINE_COLOR_CONSTANT(Red, red)
  DEFINE_COLOR_CONSTANT(Green, green)
  DEFINE_COLOR_CONSTANT(Blue, blue)
  DEFINE_COLOR_CONSTANT(Cyan, cyan)
  DEFINE_COLOR_CONSTANT(Magenta, magenta)
  DEFINE_COLOR_CONSTANT(Yellow, yellow)
  DEFINE_COLOR_CONSTANT(Black, black)
  DEFINE_COLOR_CONSTANT(White, white)
#undef DEFINE_COLOR_CONSTANT
  //! @}

  //! @}

} /* namespace DO */<|endoftext|>


<commit_before>#pragma once

#include <algorithm>
#include <cassert>
#include <cstring>

namespace {
	template <typename T>
	void swapEndian (T* p) {
		uint8_t* q = reinterpret_cast<uint8_t*>(p);

		std::reverse(q, q + sizeof(T));
	}
}

struct Slice {
	uint8_t* begin;
	uint8_t* end;

	Slice() : begin(nullptr), end(nullptr) {}
	Slice(uint8_t* begin, uint8_t* end) : begin(begin), end(end) {
		assert(begin);
		assert(end);
	}

	void popFrontN (size_t n) {
		assert(this->length() >= n);
		begin += n;
	}

	void popFront () {
		this->popFrontN(1);
	}

	auto drop (size_t n) const {
		assert(this->length() >= n);
		return Slice(this->begin + n, this->end);
	}

	auto take (size_t n) const {
		assert(this->length() >= n);
		return Slice(this->begin, this->begin + n);
	}

	size_t length () const {
		return static_cast<size_t>(this->end - this->begin);
	}

	template <typename Y = uint8_t>
	Y peek (size_t offset = 0) const {
		return *(reinterpret_cast<Y*>(this->begin + offset));
	}

	template <typename Y, bool swap = false>
	void put (Y value, size_t offset = 0) {
		assert(this->length() >= offset + sizeof(Y));
		auto ptr = reinterpret_cast<Y*>(this->begin + offset);
		*ptr = value;

		if (swap) swapEndian(ptr);
	}

	void put (uint8_t* value, size_t n, size_t offset = 0) {
		assert(this->length() >= offset + n);
		memcpy(this->begin + offset, value, n);
	}

	void put (Slice value, size_t offset = 0) {
		this->put(value.begin, value.length(), offset);
	}

	template <typename Y = uint8_t>
	Y read () {
		const Y value = this->peek<Y>();
		this->popFrontN(sizeof(Y));
		return value;
	}

	template <typename Y, bool swap = false>
	void write (Y value) {
		this->put<Y, swap>(value);
		this->popFrontN(sizeof(Y));
	}

	void write (Slice value) {
		this->put(value);
		this->popFrontN(value.length());
	}

	void write (uint8_t* value, size_t n) {
		this->put(value, n);
		this->popFrontN(n);
	}

	uint8_t& operator[](const size_t i) {
		assert(this->length() >= i);
		return this->begin[i];
	}

	const uint8_t& operator[](const size_t i) const {
		assert(this->length() >= i);
		return this->begin[i];
	}
};
<commit_msg>slice: use < over >=<commit_after>#pragma once

#include <algorithm>
#include <cassert>
#include <cstring>

namespace {
	template <typename T>
	void swapEndian (T* p) {
		uint8_t* q = reinterpret_cast<uint8_t*>(p);

		std::reverse(q, q + sizeof(T));
	}
}

struct Slice {
	uint8_t* begin;
	uint8_t* end;

	Slice(uint8_t* begin, uint8_t* end) : begin(begin), end(end) {
		assert(begin);
		assert(end);
	}

	void popFrontN (size_t n) {
		assert(n < this->length());
		begin += n;
	}

	void popFront () {
		this->popFrontN(1);
	}

	auto drop (size_t n) const {
		assert(n < this->length());
		return Slice(this->begin + n, this->end);
	}

	auto take (size_t n) const {
		assert(n < this->length());
		return Slice(this->begin, this->begin + n);
	}

	size_t length () const {
		return static_cast<size_t>(this->end - this->begin);
	}

	template <typename Y = uint8_t>
	Y peek (size_t offset = 0) const {
		return *(reinterpret_cast<Y*>(this->begin + offset));
	}

	template <typename Y, bool swap = false>
	void put (Y value, size_t offset = 0) {
		assert(offset + sizeof(Y) < this->length());
		auto ptr = reinterpret_cast<Y*>(this->begin + offset);
		*ptr = value;

		if (swap) swapEndian(ptr);
	}

	void put (uint8_t* value, size_t n, size_t offset = 0) {
		assert(offset + n < this->length());
		memcpy(this->begin + offset, value, n);
	}

	void put (Slice value, size_t offset = 0) {
		this->put(value.begin, value.length(), offset);
	}

	template <typename Y = uint8_t>
	Y read () {
		const Y value = this->peek<Y>();
		this->popFrontN(sizeof(Y));
		return value;
	}

	template <typename Y, bool swap = false>
	void write (Y value) {
		this->put<Y, swap>(value);
		this->popFrontN(sizeof(Y));
	}

	void write (Slice value) {
		this->put(value);
		this->popFrontN(value.length());
	}

	void write (uint8_t* value, size_t n) {
		this->put(value, n);
		this->popFrontN(n);
	}

	uint8_t& operator[](const size_t i) {
		assert(i < this->length());
		return this->begin[i];
	}

	const uint8_t& operator[](const size_t i) const {
		assert(i < this->length());
		return this->begin[i];
	}
};
<|endoftext|>


<commit_before>#include <iostream>
#include <algorithm>

template <typename T>
class stack
{
public:
	stack();
	size_t count() const;
	size_t array_size() const;
	T * operator[](unsigned int index) const;
	void push(T const &);
	void pop();
	T top();
	T last()const;
	void print();
	void swap();
	bool empty();
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack()
{
	array_ = nullptr;
	array_size_ = 0;
	count_ = 0;
}
template <typename T>
size_t stack<T>::array_size() const
{
	return array_size_;
}
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
T * stack<T>::operator[](unsigned int index) const
{
	return array_[index];
}
template <typename T>
void stack<T>::push(T const & value)
{
	if (array_size_ == 0)
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		array_size_ *= 2;
		swap();
	}
	array_[count_++] = value;
}
template <typename T>
void stack<T>::pop()
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else
	{
		if (count_ - 1 == array_size_ / 2)
			array_size_ /= 2;
		swap();
	}
}
T stack<T>::top()
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else return array_[count - 1];
}
template <typename T>
T stack<T>::last()const
{
	if (count_ == 0)
		throw std::logic_error("Stack is empty");
	else return array_[count_ - 1];
}
template <typename T>
void stack<T>::print()
{
	for (unsigned int i = 0; i < count_; ++i)
		std::cout << array_[i] << " ";
	std::cout << std::endl;
}
template <typename T>
void stack<T>::swap()
{
	T * new_array = new T[array_size_]();
	std::copy(array_, array_ + count_, new_array);
	delete[] array_;
	array_ = new_array;
}
template <typename T>
bool stack<T>::empty()
{
	return (count_ == 0) ? true : false;
}
<commit_msg>Update stack.hpp<commit_after>#include <iostream>
#include <algorithm>
#include <stdexcept>

template <typename T>
class stack
{
public:
	stack();
	size_t count() const;
	size_t array_size() const;
	T * operator[](unsigned int index) const;
	void push(T const &);
	void pop();
	T top();
	T last()const;
	void print();
	void swap();
	bool empty();
private:
	T * array_;
	size_t array_size_;
	size_t count_;
};

template <typename T>
stack<T>::stack()
{
	array_ = nullptr;
	array_size_ = 0;
	count_ = 0;
}
template <typename T>
size_t stack<T>::array_size() const
{
	return array_size_;
}
template <typename T>
size_t stack<T>::count() const
{
	return count_;
}
template <typename T>
T * stack<T>::operator[](unsigned int index) const
{
	return array_[index];
}
template <typename T>
void stack<T>::push(T const & value)
{
	if (array_size_ == 0)
	{
		array_size_ = 1;
		array_ = new T[array_size_]();
	}
	else if (array_size_ == count_)
	{
		array_size_ *= 2;
		swap();
	}
	array_[count_++] = value;
}
template <typename T>
void stack<T>::pop()
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else
	{
		if (count_ - 1 == array_size_ / 2)
			array_size_ /= 2;
		swap();
	}
}
T stack<T>::top()
{
	if (empty())
		throw std::logic_error("Stack is empty");
	else return array_[count - 1];
}
template <typename T>
T stack<T>::last()const
{
	if (count_ == 0)
		throw std::logic_error("Stack is empty");
	else return array_[count_ - 1];
}
template <typename T>
void stack<T>::print()
{
	for (unsigned int i = 0; i < count_; ++i)
		std::cout << array_[i] << " ";
	std::cout << std::endl;
}
template <typename T>
void stack<T>::swap()
{
	T * new_array = new T[array_size_]();
	std::copy(array_, array_ + count_, new_array);
	delete[] array_;
	array_ = new_array;
}
template <typename T>
bool stack<T>::empty()
{
	return (count_ == 0) ? true : false;
}
<|endoftext|>