<commit_before>/// @file
/// @author  Boris Mikic
/// @version 2.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#if HAVE_OGG
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>

#include "AudioManager.h"
#include "OGG_Source.h"
#include "xal.h"

namespace xal
{
	OGG_Source::OGG_Source(chstr filename) : Source(filename)
	{
	}

	OGG_Source::~OGG_Source()
	{
	}

	bool OGG_Source::open()
	{
		bool result = Source::open();
		if (result)
		{
			if (ov_fopen((char*)this->filename.c_str(), &this->oggStream) == 0)
			{
				vorbis_info* info = ov_info(&oggStream, -1);
				this->channels = info->channels;
				this->samplingRate = info->rate;
				this->bitsPerSample = 16; // always 16 bit data
				int bytes = this->bitsPerSample / 8;
				this->size = (int)ov_pcm_total(&this->oggStream, -1) * this->channels * bytes;
				this->duration = ((float)this->size) / (this->samplingRate * this->channels * bytes);
			}
			else
			{
				xal::log("ogg: error opening file!");
				result = false;
			}
		}
		return result;
	}

	bool OGG_Source::close()
	{
		bool result = Source::close();
		if (result)
		{
			ov_clear(&this->oggStream);
		}
		return result;
	}

	bool OGG_Source::rewind()
	{
		bool result = Source::rewind();
		if (result)
		{
			ov_raw_seek(&this->oggStream, 0);
		}
		return result;
	}

	bool OGG_Source::load(unsigned char* output)
	{
		if (!Source::load(output))
		{
			return false;
		}
		int section;
		unsigned long remaining = this->size;
		unsigned char* buffer = output;
		int read;
		while (remaining > 0)
		{
			read = ov_read(&this->oggStream, (char*)buffer, remaining, 0, 2, 1, &section);
			if (read == 0)
			{
				break;
			}
			remaining -= read;
			buffer += read;
		}
#ifdef __BIG_ENDIAN__ // TODO - this should be tested properly
		for (int i = 0; i < this->size; i += 2)
		{
			XAL_NORMALIZE_ENDIAN((uint16_t)output[i]); // always 16 bit data
		}
#endif
		return true;
	}

	int OGG_Source::loadChunk(unsigned char* output, int size)
	{
		if (Source::loadChunk(output, size) == 0)
		{
			return 0;
		}
		int remaining = size;
		int section;
		unsigned char* buffer = output;
		int read;
		while (remaining > 0)
		{
			read = ov_read(&this->oggStream, (char*)buffer, remaining, 0, 2, 1, &section);
			if (read == 0)
			{
				break;
			}
			remaining -= read;
			buffer += read;
		}
#ifdef __BIG_ENDIAN__ // TODO - this should be tested properly
		for (int i = 0; i < this->size; i += 2)
		{
			XAL_NORMALIZE_ENDIAN((uint16_t)output[i]); // always 16 bit data
		}
#endif
		return (size - remaining);
	}

}
#endif
<commit_msg>XAL PowerPC code fixed<commit_after>/// @file
/// @author  Boris Mikic
/// @version 2.0
///
/// @section LICENSE
///
/// This program is free software; you can redistribute it and/or modify it under
/// the terms of the BSD license: http://www.opensource.org/licenses/bsd-license.php

#if HAVE_OGG
#include <ogg/ogg.h>
#include <vorbis/codec.h>
#include <vorbis/vorbisfile.h>

#include "Endianess.h"
#include "AudioManager.h"
#include "OGG_Source.h"
#include "xal.h"

namespace xal
{
	OGG_Source::OGG_Source(chstr filename) : Source(filename)
	{
	}

	OGG_Source::~OGG_Source()
	{
	}

	bool OGG_Source::open()
	{
		bool result = Source::open();
		if (result)
		{
			if (ov_fopen((char*)this->filename.c_str(), &this->oggStream) == 0)
			{
				vorbis_info* info = ov_info(&oggStream, -1);
				this->channels = info->channels;
				this->samplingRate = info->rate;
				this->bitsPerSample = 16; // always 16 bit data
				int bytes = this->bitsPerSample / 8;
				this->size = (int)ov_pcm_total(&this->oggStream, -1) * this->channels * bytes;
				this->duration = ((float)this->size) / (this->samplingRate * this->channels * bytes);
			}
			else
			{
				xal::log("ogg: error opening file!");
				result = false;
			}
		}
		return result;
	}

	bool OGG_Source::close()
	{
		bool result = Source::close();
		if (result)
		{
			ov_clear(&this->oggStream);
		}
		return result;
	}

	bool OGG_Source::rewind()
	{
		bool result = Source::rewind();
		if (result)
		{
			ov_raw_seek(&this->oggStream, 0);
		}
		return result;
	}

	bool OGG_Source::load(unsigned char* output)
	{
		if (!Source::load(output))
		{
			return false;
		}
		int section;
		unsigned long remaining = this->size;
		unsigned char* buffer = output;
		int read;
		while (remaining > 0)
		{
			read = ov_read(&this->oggStream, (char*)buffer, remaining, 0, 2, 1, &section);
			if (read == 0)
			{
				break;
			}
			remaining -= read;
			buffer += read;
		}
#ifdef __BIG_ENDIAN__ // TODO - this should be tested properly
		for (int i = 0; i < this->size; i += 2)
		{
			XAL_NORMALIZE_ENDIAN(*(uint16_t*)(output + i)); // always 16 bit data
		}
#endif
		return true;
	}

	int OGG_Source::loadChunk(unsigned char* output, int size)
	{
		if (Source::loadChunk(output, size) == 0)
		{
			return 0;
		}
		int remaining = size;
		int section;
		unsigned char* buffer = output;
		int read;
		while (remaining > 0)
		{
			read = ov_read(&this->oggStream, (char*)buffer, remaining, 0, 2, 1, &section);
			if (read == 0)
			{
				break;
			}
			remaining -= read;
			buffer += read;
		}
#ifdef __BIG_ENDIAN__ // TODO - this should be tested properly
		for (int i = 0; i < this->size; i += 2)
		{
			XAL_NORMALIZE_ENDIAN(*(uint16_t*)(output + i)); // always 16 bit data
		}
#endif
		return (size - remaining);
	}

}
#endif
<|endoftext|>


<commit_before>/*===========================================================================*\
 *                                                                           *
 *                               OpenMesh                                    *
 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openmesh.org                                *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenMesh.                                           *
 *                                                                           *
 *  OpenMesh 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 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenMesh 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 LesserGeneral Public          *
 *  License along with OpenMesh.  If not,                                    *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
 \*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                   *
 *                                                                           *
 \*===========================================================================*/

/** \file DecimaterT.cc
 */

//=============================================================================
//
//  CLASS DecimaterT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_DECIMATER_DECIMATERT_CC

//== INCLUDES =================================================================

#include <OpenMesh/Tools/Decimater/DecimaterT.hh>

#include <vector>
#if defined(OM_CC_MIPS)
#  include <float.h>
#else
#  include <cfloat>
#endif

//== NAMESPACE ===============================================================

namespace OpenMesh {
namespace Decimater {

//== IMPLEMENTATION ==========================================================

template<class Mesh>
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
  BaseDecimaterT<Mesh>(_mesh),
    mesh_(_mesh), heap_(NULL) {

  // private vertex properties
  mesh_.add_property(collapse_target_);
  mesh_.add_property(priority_);
  mesh_.add_property(heap_position_);
}

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

template<class Mesh>
DecimaterT<Mesh>::~DecimaterT() {

  // private vertex properties
  mesh_.remove_property(collapse_target_);
  mesh_.remove_property(priority_);
  mesh_.remove_property(heap_position_);

}

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

template<class Mesh>
void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
  //   std::clog << "heap_vertex: " << _vh << std::endl;

  float prio, best_prio(FLT_MAX);
  typename Mesh::HalfedgeHandle heh, collapse_target;

  // find best target in one ring
  typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
  for (; voh_it; ++voh_it) {
    heh = voh_it.handle();
    CollapseInfo ci(mesh_, heh);

    if (this->is_collapse_legal(ci)) {
      prio = this->collapse_priority(ci);
      if (prio >= 0.0 && prio < best_prio) {
        best_prio = prio;
        collapse_target = heh;
      }
    }
  }

  // target found -> put vertex on heap
  if (collapse_target.is_valid()) {
    //     std::clog << "  added|updated" << std::endl;
    mesh_.property(collapse_target_, _vh) = collapse_target;
    mesh_.property(priority_, _vh) = best_prio;

    if (heap_->is_stored(_vh))
      heap_->update(_vh);
    else
      heap_->insert(_vh);
  }

  // not valid -> remove from heap
  else {
    //     std::clog << "  n/a|removed" << std::endl;
    if (heap_->is_stored(_vh))
      heap_->remove(_vh);

    mesh_.property(collapse_target_, _vh) = collapse_target;
    mesh_.property(priority_, _vh) = -1;
  }
}

//-----------------------------------------------------------------------------
template<class Mesh>
size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
  if (!this->is_initialized())
    return 0;

  typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
  typename Mesh::VertexHandle vp;
  typename Mesh::HalfedgeHandle v0v1;
  typename Mesh::VertexVertexIter vv_it;
  typename Mesh::VertexFaceIter vf_it;
  unsigned int n_collapses(0);

  typedef std::vector<typename Mesh::VertexHandle> Support;
  typedef typename Support::iterator SupportIterator;

  Support support(15);
  SupportIterator s_it, s_end;

  // check _n_collapses
  if (!_n_collapses)
    _n_collapses = mesh_.n_vertices();

  // initialize heap
  HeapInterface HI(mesh_, priority_, heap_position_);
  heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
  heap_->reserve(mesh_.n_vertices());

  for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
    heap_->reset_heap_position(v_it.handle());
    if (!mesh_.status(v_it).deleted())
      heap_vertex(v_it.handle());
  }

  // process heap
  while ((!heap_->empty()) && (n_collapses < _n_collapses)) {
    // get 1st heap entry
    vp = heap_->front();
    v0v1 = mesh_.property(collapse_target_, vp);
    heap_->pop_front();

    // setup collapse info
    CollapseInfo ci(mesh_, v0v1);

    // check topological correctness AGAIN !
    if (!this->is_collapse_legal(ci))
      continue;

    // store support (= one ring of *vp)
    vv_it = mesh_.vv_iter(ci.v0);
    support.clear();
    for (; vv_it; ++vv_it)
      support.push_back(vv_it.handle());

    // perform collapse
    mesh_.collapse(v0v1);
    ++n_collapses;

    // update triangle normals
    vf_it = mesh_.vf_iter(ci.v1);
    for (; vf_it; ++vf_it)
      if (!mesh_.status(vf_it).deleted())
        mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));

    // post-process collapse
    this->postprocess_collapse(ci);

    // update heap (former one ring of decimated vertex)
    for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
      assert(!mesh_.status(*s_it).deleted());
      heap_vertex(*s_it);
    }
  }

  // delete heap
  heap_.reset();

  // DON'T do garbage collection here! It's up to the application.
  return n_collapses;
}

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

template<class Mesh>
size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
  if (!this->is_initialized())
    return 0;

  if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
    return 0;

  typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
  typename Mesh::VertexHandle vp;
  typename Mesh::HalfedgeHandle v0v1;
  typename Mesh::VertexVertexIter vv_it;
  typename Mesh::VertexFaceIter vf_it;
  unsigned int nv = mesh_.n_vertices();
  unsigned int nf = mesh_.n_faces();
  unsigned int n_collapses = 0;

  typedef std::vector<typename Mesh::VertexHandle> Support;
  typedef typename Support::iterator SupportIterator;

  Support support(15);
  SupportIterator s_it, s_end;

  // initialize heap
  HeapInterface HI(mesh_, priority_, heap_position_);
  heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
  heap_->reserve(mesh_.n_vertices());

  for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
    heap_->reset_heap_position(v_it.handle());
    if (!mesh_.status(v_it).deleted())
      heap_vertex(v_it.handle());
  }

  // process heap
  while ((!heap_->empty()) && (_nv < nv) && (_nf < nf)) {
    // get 1st heap entry
    vp = heap_->front();
    v0v1 = mesh_.property(collapse_target_, vp);
    heap_->pop_front();

    // setup collapse info
    CollapseInfo ci(mesh_, v0v1);

    // check topological correctness AGAIN !
    if (!is_collapse_legal(ci))
      continue;

    // store support (= one ring of *vp)
    vv_it = mesh_.vv_iter(ci.v0);
    support.clear();
    for (; vv_it; ++vv_it)
      support.push_back(vv_it.handle());

    // adjust complexity in advance (need boundary status)
    ++n_collapses;
    --nv;
    if (mesh_.is_boundary(ci.v0v1) || mesh_.is_boundary(ci.v1v0))
      --nf;
    else
      nf -= 2;

    // pre-processing
    preprocess_collapse(ci);

    // perform collapse
    mesh_.collapse(v0v1);

    // update triangle normals
    vf_it = mesh_.vf_iter(ci.v1);
    for (; vf_it; ++vf_it)
      if (!mesh_.status(vf_it).deleted())
        mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));

    // post-process collapse
    postprocess_collapse(ci);

    // update heap (former one ring of decimated vertex)
    for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
      assert(!mesh_.status(*s_it).deleted());
      heap_vertex(*s_it);
    }
  }

  // delete heap
  heap_.reset();

  // DON'T do garbage collection here! It's up to the application.
  return n_collapses;
}

//=============================================================================
}// END_NS_DECIMATER
} // END_NS_OPENMESH
//=============================================================================

<commit_msg>Missing this pointers<commit_after>/*===========================================================================*\
 *                                                                           *
 *                               OpenMesh                                    *
 *      Copyright (C) 2001-2011 by Computer Graphics Group, RWTH Aachen      *
 *                           www.openmesh.org                                *
 *                                                                           *
 *---------------------------------------------------------------------------*
 *  This file is part of OpenMesh.                                           *
 *                                                                           *
 *  OpenMesh 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 3 of           *
 *  the License, or (at your option) any later version with the              *
 *  following exceptions:                                                    *
 *                                                                           *
 *  If other files instantiate templates or use macros                       *
 *  or inline functions from this file, or you compile this file and         *
 *  link it with other files to produce an executable, this file does        *
 *  not by itself cause the resulting executable to be covered by the        *
 *  GNU Lesser General Public License. This exception does not however       *
 *  invalidate any other reasons why the executable file might be            *
 *  covered by the GNU Lesser General Public License.                        *
 *                                                                           *
 *  OpenMesh 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 LesserGeneral Public          *
 *  License along with OpenMesh.  If not,                                    *
 *  see <http://www.gnu.org/licenses/>.                                      *
 *                                                                           *
 \*===========================================================================*/

/*===========================================================================*\
 *                                                                           *
 *   $Revision$                                                         *
 *   $Date$                   *
 *                                                                           *
 \*===========================================================================*/

/** \file DecimaterT.cc
 */

//=============================================================================
//
//  CLASS DecimaterT - IMPLEMENTATION
//
//=============================================================================
#define OPENMESH_DECIMATER_DECIMATERT_CC

//== INCLUDES =================================================================

#include <OpenMesh/Tools/Decimater/DecimaterT.hh>

#include <vector>
#if defined(OM_CC_MIPS)
#  include <float.h>
#else
#  include <cfloat>
#endif

//== NAMESPACE ===============================================================

namespace OpenMesh {
namespace Decimater {

//== IMPLEMENTATION ==========================================================

template<class Mesh>
DecimaterT<Mesh>::DecimaterT(Mesh& _mesh) :
  BaseDecimaterT<Mesh>(_mesh),
    mesh_(_mesh), heap_(NULL) {

  // private vertex properties
  mesh_.add_property(collapse_target_);
  mesh_.add_property(priority_);
  mesh_.add_property(heap_position_);
}

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

template<class Mesh>
DecimaterT<Mesh>::~DecimaterT() {

  // private vertex properties
  mesh_.remove_property(collapse_target_);
  mesh_.remove_property(priority_);
  mesh_.remove_property(heap_position_);

}

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

template<class Mesh>
void DecimaterT<Mesh>::heap_vertex(VertexHandle _vh) {
  //   std::clog << "heap_vertex: " << _vh << std::endl;

  float prio, best_prio(FLT_MAX);
  typename Mesh::HalfedgeHandle heh, collapse_target;

  // find best target in one ring
  typename Mesh::VertexOHalfedgeIter voh_it(mesh_, _vh);
  for (; voh_it; ++voh_it) {
    heh = voh_it.handle();
    CollapseInfo ci(mesh_, heh);

    if (this->is_collapse_legal(ci)) {
      prio = this->collapse_priority(ci);
      if (prio >= 0.0 && prio < best_prio) {
        best_prio = prio;
        collapse_target = heh;
      }
    }
  }

  // target found -> put vertex on heap
  if (collapse_target.is_valid()) {
    //     std::clog << "  added|updated" << std::endl;
    mesh_.property(collapse_target_, _vh) = collapse_target;
    mesh_.property(priority_, _vh) = best_prio;

    if (heap_->is_stored(_vh))
      heap_->update(_vh);
    else
      heap_->insert(_vh);
  }

  // not valid -> remove from heap
  else {
    //     std::clog << "  n/a|removed" << std::endl;
    if (heap_->is_stored(_vh))
      heap_->remove(_vh);

    mesh_.property(collapse_target_, _vh) = collapse_target;
    mesh_.property(priority_, _vh) = -1;
  }
}

//-----------------------------------------------------------------------------
template<class Mesh>
size_t DecimaterT<Mesh>::decimate(size_t _n_collapses) {
  if (!this->is_initialized())
    return 0;

  typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
  typename Mesh::VertexHandle vp;
  typename Mesh::HalfedgeHandle v0v1;
  typename Mesh::VertexVertexIter vv_it;
  typename Mesh::VertexFaceIter vf_it;
  unsigned int n_collapses(0);

  typedef std::vector<typename Mesh::VertexHandle> Support;
  typedef typename Support::iterator SupportIterator;

  Support support(15);
  SupportIterator s_it, s_end;

  // check _n_collapses
  if (!_n_collapses)
    _n_collapses = mesh_.n_vertices();

  // initialize heap
  HeapInterface HI(mesh_, priority_, heap_position_);
  heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
  heap_->reserve(mesh_.n_vertices());

  for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
    heap_->reset_heap_position(v_it.handle());
    if (!mesh_.status(v_it).deleted())
      heap_vertex(v_it.handle());
  }

  // process heap
  while ((!heap_->empty()) && (n_collapses < _n_collapses)) {
    // get 1st heap entry
    vp = heap_->front();
    v0v1 = mesh_.property(collapse_target_, vp);
    heap_->pop_front();

    // setup collapse info
    CollapseInfo ci(mesh_, v0v1);

    // check topological correctness AGAIN !
    if (!this->is_collapse_legal(ci))
      continue;

    // store support (= one ring of *vp)
    vv_it = mesh_.vv_iter(ci.v0);
    support.clear();
    for (; vv_it; ++vv_it)
      support.push_back(vv_it.handle());

    // perform collapse
    mesh_.collapse(v0v1);
    ++n_collapses;

    // update triangle normals
    vf_it = mesh_.vf_iter(ci.v1);
    for (; vf_it; ++vf_it)
      if (!mesh_.status(vf_it).deleted())
        mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));

    // post-process collapse
    this->postprocess_collapse(ci);

    // update heap (former one ring of decimated vertex)
    for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
      assert(!mesh_.status(*s_it).deleted());
      heap_vertex(*s_it);
    }
  }

  // delete heap
  heap_.reset();

  // DON'T do garbage collection here! It's up to the application.
  return n_collapses;
}

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

template<class Mesh>
size_t DecimaterT<Mesh>::decimate_to_faces(size_t _nv, size_t _nf) {
  if (!this->is_initialized())
    return 0;

  if (_nv >= mesh_.n_vertices() || _nf >= mesh_.n_faces())
    return 0;

  typename Mesh::VertexIter v_it, v_end(mesh_.vertices_end());
  typename Mesh::VertexHandle vp;
  typename Mesh::HalfedgeHandle v0v1;
  typename Mesh::VertexVertexIter vv_it;
  typename Mesh::VertexFaceIter vf_it;
  unsigned int nv = mesh_.n_vertices();
  unsigned int nf = mesh_.n_faces();
  unsigned int n_collapses = 0;

  typedef std::vector<typename Mesh::VertexHandle> Support;
  typedef typename Support::iterator SupportIterator;

  Support support(15);
  SupportIterator s_it, s_end;

  // initialize heap
  HeapInterface HI(mesh_, priority_, heap_position_);
  heap_ = std::auto_ptr<DeciHeap>(new DeciHeap(HI));
  heap_->reserve(mesh_.n_vertices());

  for (v_it = mesh_.vertices_begin(); v_it != v_end; ++v_it) {
    heap_->reset_heap_position(v_it.handle());
    if (!mesh_.status(v_it).deleted())
      heap_vertex(v_it.handle());
  }

  // process heap
  while ((!heap_->empty()) && (_nv < nv) && (_nf < nf)) {
    // get 1st heap entry
    vp = heap_->front();
    v0v1 = mesh_.property(collapse_target_, vp);
    heap_->pop_front();

    // setup collapse info
    CollapseInfo ci(mesh_, v0v1);

    // check topological correctness AGAIN !
    if (!this->is_collapse_legal(ci))
      continue;

    // store support (= one ring of *vp)
    vv_it = mesh_.vv_iter(ci.v0);
    support.clear();
    for (; vv_it; ++vv_it)
      support.push_back(vv_it.handle());

    // adjust complexity in advance (need boundary status)
    ++n_collapses;
    --nv;
    if (mesh_.is_boundary(ci.v0v1) || mesh_.is_boundary(ci.v1v0))
      --nf;
    else
      nf -= 2;

    // pre-processing
    this->preprocess_collapse(ci);

    // perform collapse
    mesh_.collapse(v0v1);

    // update triangle normals
    vf_it = mesh_.vf_iter(ci.v1);
    for (; vf_it; ++vf_it)
      if (!mesh_.status(vf_it).deleted())
        mesh_.set_normal(vf_it, mesh_.calc_face_normal(vf_it.handle()));

    // post-process collapse
    this->postprocess_collapse(ci);

    // update heap (former one ring of decimated vertex)
    for (s_it = support.begin(), s_end = support.end(); s_it != s_end; ++s_it) {
      assert(!mesh_.status(*s_it).deleted());
      heap_vertex(*s_it);
    }
  }

  // delete heap
  heap_.reset();

  // DON'T do garbage collection here! It's up to the application.
  return n_collapses;
}

//=============================================================================
}// END_NS_DECIMATER
} // END_NS_OPENMESH
//=============================================================================

<|endoftext|>


<commit_before>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * 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 <organization> 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 EARLIER MENTIONED AUTHORS ``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 <copyright holder> 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 "MemoryLeakWarning.h"

#include <stdlib.h>
#include <stdio.h>

/* Static since we REALLY can have only one of these! */
static int allocatedBlocks = 0;
static int allocatedArrays = 0;
static int firstInitialBlocks = 0;
static int firstInitialArrays = 0;
static bool reporterRegistered = false;

class MemoryLeakWarningData
{
	public:
		MemoryLeakWarningData();

		int initialBlocksUsed;
		int initialArraysUsed;

		int blockUsageCheckPoint;
		int arrayUsageCheckPoint;
		int expectCount;
		char message[100];
};

void MemoryLeakWarning::CreateData()
{
	_impl = (MemoryLeakWarningData*) malloc(sizeof(MemoryLeakWarningData));
	_impl->initialBlocksUsed = 0;
	_impl->initialArraysUsed = 0;

	_impl->blockUsageCheckPoint = 0;
	_impl->arrayUsageCheckPoint = 0;
	_impl->expectCount = 0;
	_impl->message[0] = '\0';
}

void MemoryLeakWarning::DestroyData()
{
	free(_impl);
}

extern "C" {
void reportMemoryBallance();
}

void reportMemoryBallance()
{
  int blockBalance = allocatedBlocks - firstInitialBlocks;
  int arrayBalance = allocatedArrays - firstInitialArrays;
  if (blockBalance == 0 && arrayBalance == 0)
    ;
  else if (blockBalance + arrayBalance == 0)
    printf("No leaks but some arrays were deleted without []\n");
  else
    {
      if (blockBalance > 0)
        printf("Memory leak! %d blocks not deleted\n", blockBalance);
      if (arrayBalance > 0)
        printf("Memory leak! %d arrays not deleted\n", arrayBalance);
      if (blockBalance < 0)
        printf("More blocks deleted than newed! %d extra deletes\n", blockBalance);
      if (arrayBalance < 0)
        printf("More arrays deleted than newed! %d extra deletes\n", arrayBalance);

      printf("NOTE - some memory leaks appear to be allocated statics that are not released\n"
             "     - by the standard library\n"
             "     - Use the -r switch on your unit tests to repeat the test sequence\n"
             "     - If no leaks are reported on the second pass, it is likely a static\n"
             "     - that is not released\n");
    }
}

MemoryLeakWarning* MemoryLeakWarning::_latest = NULL;

void MemoryLeakWarning::Enable()
{
  _impl->initialBlocksUsed = allocatedBlocks;
  _impl->initialArraysUsed = allocatedArrays;

	if (!reporterRegistered) {
		firstInitialBlocks = allocatedBlocks;
		firstInitialArrays = allocatedArrays;
		reporterRegistered = true;
		atexit(reportMemoryBallance);
	}

}

const char*  MemoryLeakWarning::FinalReport(int toBeDeletedLeaks)
{
  if (_impl->initialBlocksUsed != (allocatedBlocks-toBeDeletedLeaks) || _impl->initialArraysUsed != allocatedArrays )
    {
      printf("initial blocks=%d, allocated blocks=%d\ninitial arrays=%d, allocated arrays=%d\n",
             _impl->initialBlocksUsed, allocatedBlocks, _impl->initialArraysUsed, allocatedArrays);

      return "Memory new/delete imbalance after running tests\n";
    }
  else
    return "";
}

void MemoryLeakWarning::CheckPointUsage()
{
  _impl->blockUsageCheckPoint = allocatedBlocks;
  _impl->arrayUsageCheckPoint = allocatedArrays;
}

bool MemoryLeakWarning::UsageIsNotBalanced()
{
  int arrayBalance = allocatedArrays - _impl->arrayUsageCheckPoint;
  int blockBalance = allocatedBlocks - _impl->blockUsageCheckPoint;

  if (_impl->expectCount != 0 && blockBalance + arrayBalance == _impl->expectCount)
    return false;
  if (blockBalance == 0 && arrayBalance == 0)
    return false;
  else if (blockBalance + arrayBalance == 0)
    sprintf(_impl->message, "No leaks but some arrays were deleted without []\n");
  else
    {
      int nchars = 0;
      if (_impl->blockUsageCheckPoint != allocatedBlocks)
        nchars = sprintf(_impl->message, "this test leaks %d blocks",
                         allocatedBlocks - _impl->blockUsageCheckPoint);

      if (_impl->arrayUsageCheckPoint != allocatedArrays)
        sprintf(_impl->message + nchars, "this test leaks %d arrays",
                allocatedArrays - _impl->arrayUsageCheckPoint);
    }
  return true;
}

const char* MemoryLeakWarning::Message()
{
  return _impl->message;
}

void MemoryLeakWarning::ExpectLeaks(int n)
{
	_impl->expectCount = n;
}

/* Global overloaded operators */

void* operator new(size_t size)
{
	allocatedBlocks++;
  	return malloc(size);
}

void operator delete(void* mem)
{
  	allocatedBlocks--;
  	free(mem);
}

void* operator new[](size_t size)
{
	allocatedArrays++;
  	return malloc(size);
}

void operator delete[](void* mem)
{
 	allocatedArrays--;
  	free(mem);
}

<commit_msg>Added some methods because of symbian port<commit_after>/*
 * Copyright (c) 2007, Michael Feathers, James Grenning and Bas Vodde
 * 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 <organization> 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 EARLIER MENTIONED AUTHORS ``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 <copyright holder> 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 "MemoryLeakWarning.h"

#include <stdlib.h>
#include <stdio.h>

/* Static since we REALLY can have only one of these! */
static int allocatedBlocks = 0;
static int allocatedArrays = 0;
static int firstInitialBlocks = 0;
static int firstInitialArrays = 0;
static bool reporterRegistered = false;

class MemoryLeakWarningData
{
	public:
		MemoryLeakWarningData();

		int initialBlocksUsed;
		int initialArraysUsed;

		int blockUsageCheckPoint;
		int arrayUsageCheckPoint;
		int expectCount;
		char message[100];
};

void MemoryLeakWarning::CreateData()
{
	_impl = (MemoryLeakWarningData*) malloc(sizeof(MemoryLeakWarningData));
	_impl->initialBlocksUsed = 0;
	_impl->initialArraysUsed = 0;

	_impl->blockUsageCheckPoint = 0;
	_impl->arrayUsageCheckPoint = 0;
	_impl->expectCount = 0;
	_impl->message[0] = '\0';
}

void MemoryLeakWarning::DestroyData()
{
	free(_impl);
}

extern "C" {
void reportMemoryBallance();
}

void reportMemoryBallance()
{
  int blockBalance = allocatedBlocks - firstInitialBlocks;
  int arrayBalance = allocatedArrays - firstInitialArrays;
  if (blockBalance == 0 && arrayBalance == 0)
    ;
  else if (blockBalance + arrayBalance == 0)
    printf("No leaks but some arrays were deleted without []\n");
  else
    {
      if (blockBalance > 0)
        printf("Memory leak! %d blocks not deleted\n", blockBalance);
      if (arrayBalance > 0)
        printf("Memory leak! %d arrays not deleted\n", arrayBalance);
      if (blockBalance < 0)
        printf("More blocks deleted than newed! %d extra deletes\n", blockBalance);
      if (arrayBalance < 0)
        printf("More arrays deleted than newed! %d extra deletes\n", arrayBalance);

      printf("NOTE - some memory leaks appear to be allocated statics that are not released\n"
             "     - by the standard library\n"
             "     - Use the -r switch on your unit tests to repeat the test sequence\n"
             "     - If no leaks are reported on the second pass, it is likely a static\n"
             "     - that is not released\n");
    }
}

MemoryLeakWarning* MemoryLeakWarning::_latest = NULL;

MemoryLeakWarning::MemoryLeakWarning()
{
	_latest = this;
	CreateData();
}

MemoryLeakWarning::~MemoryLeakWarning()
{
	DestroyData();
}

MemoryLeakWarning* MemoryLeakWarning::GetLatest()
{
	return _latest;
}

void MemoryLeakWarning::SetLatest(MemoryLeakWarning* latest)
{
	_latest = latest;
}

void MemoryLeakWarning::Enable()
{
  _impl->initialBlocksUsed = allocatedBlocks;
  _impl->initialArraysUsed = allocatedArrays;

	if (!reporterRegistered) {
		firstInitialBlocks = allocatedBlocks;
		firstInitialArrays = allocatedArrays;
		reporterRegistered = true;
		atexit(reportMemoryBallance);
	}

}

const char*  MemoryLeakWarning::FinalReport(int toBeDeletedLeaks)
{
  if (_impl->initialBlocksUsed != (allocatedBlocks-toBeDeletedLeaks) || _impl->initialArraysUsed != allocatedArrays )
    {
      printf("initial blocks=%d, allocated blocks=%d\ninitial arrays=%d, allocated arrays=%d\n",
             _impl->initialBlocksUsed, allocatedBlocks, _impl->initialArraysUsed, allocatedArrays);

      return "Memory new/delete imbalance after running tests\n";
    }
  else
    return "";
}

void MemoryLeakWarning::CheckPointUsage()
{
  _impl->blockUsageCheckPoint = allocatedBlocks;
  _impl->arrayUsageCheckPoint = allocatedArrays;
}

bool MemoryLeakWarning::UsageIsNotBalanced()
{
  int arrayBalance = allocatedArrays - _impl->arrayUsageCheckPoint;
  int blockBalance = allocatedBlocks - _impl->blockUsageCheckPoint;

  if (_impl->expectCount != 0 && blockBalance + arrayBalance == _impl->expectCount)
    return false;
  if (blockBalance == 0 && arrayBalance == 0)
    return false;
  else if (blockBalance + arrayBalance == 0)
    sprintf(_impl->message, "No leaks but some arrays were deleted without []\n");
  else
    {
      int nchars = 0;
      if (_impl->blockUsageCheckPoint != allocatedBlocks)
        nchars = sprintf(_impl->message, "this test leaks %d blocks",
                         allocatedBlocks - _impl->blockUsageCheckPoint);

      if (_impl->arrayUsageCheckPoint != allocatedArrays)
        sprintf(_impl->message + nchars, "this test leaks %d arrays",
                allocatedArrays - _impl->arrayUsageCheckPoint);
    }
  return true;
}

const char* MemoryLeakWarning::Message()
{
  return _impl->message;
}

void MemoryLeakWarning::ExpectLeaks(int n)
{
	_impl->expectCount = n;
}

/* Global overloaded operators */

void* operator new(size_t size)
{
	allocatedBlocks++;
  	return malloc(size);
}

void operator delete(void* mem)
{
  	allocatedBlocks--;
  	free(mem);
}

void* operator new[](size_t size)
{
	allocatedArrays++;
  	return malloc(size);
}

void operator delete[](void* mem)
{
 	allocatedArrays--;
  	free(mem);
}

<|endoftext|>


<commit_before>#include <algorithm>
#include <cassert>
#include <cstdlib>

#include "RDMap.h"
#include "ReachingDefinitions.h"

namespace dg {
namespace analysis {
namespace rd {

class RDNode;

RDMap::RDMap(const RDMap& o)
{
    merge(&o);
}

static bool comp_ds(const DefSite& a, const DefSite& b)
{
    return a.target < b.target;
}

///
// merge @oth map to this map. If given @no_update set,
// take those definitions as 'overwrites'. That is -
// if some definition in @no_update set overwrites definition
// in @oth set, don't merge it to our map. The exception are
// definitions with UNKNOWN_OFFSET, since we don't know what
// places can these overwrite, these are always added (weak update).
// If @merge_unknown flag is set to true, all definitions
// with concrete offset are merge to the definition with UNKNOWN offset
// once this definition is found (this is because to a def-use
// relation the concrete OFFSET and UNKNOWN offset act the same, that is:
//
//   def(A, 0, 4) at NODE1
//   def(A, UNKNOWN) at NODE2
//   use(A, 2)
//
// The use has reaching definitions NODE1 and NODE2, thus we can
// just have that merged to UNKNOWN, since UNKNOWN may be 0-4:
//
//   def(A, UNKNOWN) at NODE1, NODE2
//   use(A, 2)
//
// That may introduce some unprecision, though:
//
//   def(A, 0, 4) at NODE1
//   def(A, 4, 8) at NODE3
//   def(A, UNKNOWN) at NODE2
//   use(A, 2) -- reaching is just NODE1 and NODE2
//   ---
//   def(A, UNKNOWN) at NODE1, NODE2, NODE2
//                      -- reaching are all thre
//
// This is useful when we have a lot of concrete and unknown definitions
// in the map
bool RDMap::merge(const RDMap *oth,
                  DefSiteSetT *no_update,
                  bool field_insensitive,
                  uint32_t max_set_size,
                  bool merge_unknown)
{
    if (this == oth)
        return false;

    bool changed = false;
    for (auto it : oth->defs) {
        const DefSite& ds = it.first;
        bool is_unknown = ds.offset.isUnknown();

        // STRONG UPDATE
        // --------------------
        // should we update this def-site (strong update)?
        // but only if the offset is concrete, because if
        // it is not concrete, we want to do weak update
        // Also, we don't want to do strong updates for
        // heap allocated objects, since they are all represented
        // by the call site
        if (!field_insensitive && !is_unknown && no_update
            && ds.target->getType() != DYN_ALLOC) {
            bool skip = false;

            auto range = std::equal_range(no_update->begin(),
                                          no_update->end(),
                                          ds, comp_ds);
            for (auto I = range.first; I!= range.second; ++I) {
                const DefSite& ds2 = *I;
                assert(ds.target == ds2.target);
                // if the 'no_update' set contains target with unknown
                // pointer, we should always keep that value
                // and the value being merged (just all possible definitions)
                if (ds2.offset.isUnknown()) {
                    // break no_update skip = true, thus adding
                    // the values for UNKOWN to our map
                    is_unknown = true;
                    break;
                }

                // targets are the same, check if the what we have
                // in 'no_update' set overwrites the values that are in
                // the other map
                if ((*ds.offset >= *ds2.offset)
                    && (*ds.offset + *ds.len <= *ds2.offset + *ds2.len)) {
                    skip = true;
                    break;
                }
            }

            // if values in 'no_update' map overwrite the coresponding values
            // in the other map, don't update our map
            if (skip)
                continue;
        }

        if (field_insensitive)
            merge_unknown = true;

        // MERGE CONCRETE OFFSETS (if desired)
        // ------------------------------------
        RDNodesSet *our_vals = nullptr;
        if (merge_unknown && is_unknown) {
            // this loop finds all concrete offsets and merges them into one
            // defsite with UNKNOWN_OFFSET. This defsite is set in 'our_vals'
            // after the loop exit
            our_vals = &defs[DefSite(ds.target, UNKNOWN_OFFSET, UNKNOWN_OFFSET)];

            auto range = getObjectRange(ds);
            for (auto I = range.first; I != range.second;) {
                auto cur = I++;

                // this must hold (getObjectRange)
                assert(cur->first.target == ds.target);

                // don't remove the one with UNKNOWN_OFFSET
                if (&cur->second == our_vals)
                    continue;

                // merge values with concrete offset to
                // this unknown offset
                for (RDNode *defnode : cur->second)
                    changed |= our_vals->insert(defnode);

                // erase the def-site with concrete offset
                defs.erase(cur);
            }

            // fall-through to add the new definitions from the other map
        } else {
            // our values that we have for this definition-site
            our_vals = &defs[ds];
        }

        assert(our_vals && "BUG");

        // copy values that have the map 'oth' for the defsite 'ds' to our map
        for (RDNode *defnode : it.second)
            changed |= our_vals->insert(defnode);

        // crop the set to UNKNOWN_MEMORY if it is too big.
        // But only in the case that the  DefSite is not also UNKNOWN,
        // because then we would be 'unknown memory defined @ unknown place'
        if (!ds.target->isUnknown() && our_vals->size() > max_set_size)
            our_vals->makeUnknown();
    }

    return changed;
}

bool RDMap::add(const DefSite& p, RDNode *n)
{
    return defs[p].insert(n);
}

bool RDMap::update(const DefSite& p, RDNode *n)
{
    bool ret;
    RDNodesSet& dfs = defs[p];

    ret = dfs.count(n) == 0 || dfs.size() > 1;
    dfs.clear();
    dfs.insert(n);

    return ret;
}

bool RDMap::definesWithAnyOffset(const DefSite& ds)
{
    // FIXME do it via binary search
    for (auto it : defs)
        if (it.first.target == ds.target)
            return true;

    return false;
}

static inline bool comp(const std::pair<const DefSite, RDNodesSet>& a,
                        const std::pair<const DefSite, RDNodesSet>& b)
{
    return a.first.target < b.first.target;
}

std::pair<RDMap::iterator, RDMap::iterator>
RDMap::getObjectRange(const DefSite& ds)
{
    std::pair<const DefSite, RDNodesSet> what(ds, RDNodesSet());
    return std::equal_range(defs.begin(), defs.end(), what, comp);
}

} // rd
} // analysis
} // dg
<commit_msg>RD: fix field insensitiveness<commit_after>#include <algorithm>
#include <cassert>
#include <cstdlib>

#include "RDMap.h"
#include "ReachingDefinitions.h"

namespace dg {
namespace analysis {
namespace rd {

class RDNode;

RDMap::RDMap(const RDMap& o)
{
    merge(&o);
}

static bool comp_ds(const DefSite& a, const DefSite& b)
{
    return a.target < b.target;
}

///
// merge @oth map to this map. If given @no_update set,
// take those definitions as 'overwrites'. That is -
// if some definition in @no_update set overwrites definition
// in @oth set, don't merge it to our map. The exception are
// definitions with UNKNOWN_OFFSET, since we don't know what
// places can these overwrite, these are always added (weak update).
// If @merge_unknown flag is set to true, all definitions
// with concrete offset are merge to the definition with UNKNOWN offset
// once this definition is found (this is because to a def-use
// relation the concrete OFFSET and UNKNOWN offset act the same, that is:
//
//   def(A, 0, 4) at NODE1
//   def(A, UNKNOWN) at NODE2
//   use(A, 2)
//
// The use has reaching definitions NODE1 and NODE2, thus we can
// just have that merged to UNKNOWN, since UNKNOWN may be 0-4:
//
//   def(A, UNKNOWN) at NODE1, NODE2
//   use(A, 2)
//
// That may introduce some unprecision, though:
//
//   def(A, 0, 4) at NODE1
//   def(A, 4, 8) at NODE3
//   def(A, UNKNOWN) at NODE2
//   use(A, 2) -- reaching is just NODE1 and NODE2
//   ---
//   def(A, UNKNOWN) at NODE1, NODE2, NODE2
//                      -- reaching are all thre
//
// This is useful when we have a lot of concrete and unknown definitions
// in the map
bool RDMap::merge(const RDMap *oth,
                  DefSiteSetT *no_update,
                  bool field_insensitive,
                  uint32_t max_set_size,
                  bool merge_unknown)
{
    if (this == oth)
        return false;

    bool changed = false;
    for (auto it : oth->defs) {
        const DefSite& ds = it.first;
        bool is_unknown = ds.offset.isUnknown();

        // STRONG UPDATE
        // --------------------
        // should we update this def-site (strong update)?
        // but only if the offset is concrete, because if
        // it is not concrete, we want to do weak update
        // Also, we don't want to do strong updates for
        // heap allocated objects, since they are all represented
        // by the call site
        if (!field_insensitive && !is_unknown && no_update
            && ds.target->getType() != DYN_ALLOC) {
            bool skip = false;

            auto range = std::equal_range(no_update->begin(),
                                          no_update->end(),
                                          ds, comp_ds);
            for (auto I = range.first; I!= range.second; ++I) {
                const DefSite& ds2 = *I;
                assert(ds.target == ds2.target);
                // if the 'no_update' set contains target with unknown
                // pointer, we should always keep that value
                // and the value being merged (just all possible definitions)
                if (ds2.offset.isUnknown()) {
                    // break no_update skip = true, thus adding
                    // the values for UNKOWN to our map
                    is_unknown = true;
                    break;
                }

                // targets are the same, check if the what we have
                // in 'no_update' set overwrites the values that are in
                // the other map
                if ((*ds.offset >= *ds2.offset)
                    && (*ds.offset + *ds.len <= *ds2.offset + *ds2.len)) {
                    skip = true;
                    break;
                }
            }

            // if values in 'no_update' map overwrite the coresponding values
            // in the other map, don't update our map
            if (skip)
                continue;
        }

        // MERGE CONCRETE OFFSETS (if desired)
        // ------------------------------------
        RDNodesSet *our_vals = nullptr;
        if (field_insensitive || (merge_unknown && is_unknown)) {
            // this loop finds all concrete offsets and merges them into one
            // defsite with UNKNOWN_OFFSET. This defsite is set in 'our_vals'
            // after the loop exit
            our_vals = &defs[DefSite(ds.target, UNKNOWN_OFFSET, UNKNOWN_OFFSET)];

            auto range = getObjectRange(ds);
            for (auto I = range.first; I != range.second;) {
                auto cur = I++;

                // this must hold (getObjectRange)
                assert(cur->first.target == ds.target);

                // don't remove the one with UNKNOWN_OFFSET
                if (&cur->second == our_vals)
                    continue;

                // merge values with concrete offset to
                // this unknown offset
                for (RDNode *defnode : cur->second)
                    changed |= our_vals->insert(defnode);

                // erase the def-site with concrete offset
                defs.erase(cur);
            }

            // fall-through to add the new definitions from the other map
        } else {
            // our values that we have for this definition-site
            our_vals = &defs[ds];
        }

        assert(our_vals && "BUG");

        // copy values that have the map 'oth' for the defsite 'ds' to our map
        for (RDNode *defnode : it.second)
            changed |= our_vals->insert(defnode);

        // crop the set to UNKNOWN_MEMORY if it is too big.
        // But only in the case that the  DefSite is not also UNKNOWN,
        // because then we would be 'unknown memory defined @ unknown place'
        if (!ds.target->isUnknown() && our_vals->size() > max_set_size)
            our_vals->makeUnknown();
    }

    return changed;
}

bool RDMap::add(const DefSite& p, RDNode *n)
{
    return defs[p].insert(n);
}

bool RDMap::update(const DefSite& p, RDNode *n)
{
    bool ret;
    RDNodesSet& dfs = defs[p];

    ret = dfs.count(n) == 0 || dfs.size() > 1;
    dfs.clear();
    dfs.insert(n);

    return ret;
}

bool RDMap::definesWithAnyOffset(const DefSite& ds)
{
    // FIXME do it via binary search
    for (auto it : defs)
        if (it.first.target == ds.target)
            return true;

    return false;
}

static inline bool comp(const std::pair<const DefSite, RDNodesSet>& a,
                        const std::pair<const DefSite, RDNodesSet>& b)
{
    return a.first.target < b.first.target;
}

std::pair<RDMap::iterator, RDMap::iterator>
RDMap::getObjectRange(const DefSite& ds)
{
    std::pair<const DefSite, RDNodesSet> what(ds, RDNodesSet());
    return std::equal_range(defs.begin(), defs.end(), what, comp);
}

} // rd
} // analysis
} // dg
<|endoftext|>


<commit_before>#include "config.h"
#include "common/dir.h"
#include "common/common.h"
#include "common/file.h"
#include "utils/utils.h"

#define MAX_BUFFER_LEN 1024

Config::Config()
: m_file(Dir::GetConfigDir() + "/twainet.conf")
{
	m_file.Load();
}

Config::~Config()
{
	m_file.Save();
}

std::string Config::GetTrustedFileName()
{
	return m_file.getString("common", "trustedFileName", "twainet.trusted");
}

std::string Config::GetPluginsFileName()
{
    return m_file.getString("common", "pluginsFileName", "twainet.plugins");
}

int Config::GetLocalServerPort()
{
	return m_file.getLong("common", "localPort", g_localServerPort);
}

void Config::SetLocalServerPort(int port)
{
	m_file.setLong("common", "localPort", port);
}

FileConfig::FileConfig(const std::string& filePath)
: m_filePath(filePath){}

FileConfig::~FileConfig(){}

std::vector<std::string> FileConfig::Read()
{
    std::vector<std::string> dataContainer;
    File configFile(m_filePath);
    int filesize = configFile.GetFileSize(), filepos = 0;
    char* data = new char[MAX_BUFFER_LEN];
    char* dataPos = data;
    while(filepos < filesize)
    {
        unsigned int size = MAX_BUFFER_LEN - (unsigned int)(dataPos - data) ;
        memset(dataPos, 0, size);
        if(!configFile.Read(dataPos, &size))
        {
            break;
        }
        filepos += size;

        std::vector<std::string> lines = CommonUtils::DelimitString(data, "\n");
        int pos = 0;
        for(int i = 0; i < (int)lines.size() - 1; i++)
        {
            pos += lines[i].size() + 1;
            std::string line = lines[i];
            if(line[line.size() - 1] == '\r')
                line.erase(line.size() - 1, 1);
            if(line[0] == '#' || line.empty())
                continue;

            dataContainer.push_back(line);
        }

        int templen = filepos - pos;
        char* tempData = new char[templen];
        memcpy(tempData, data + pos, templen);
        memcpy(data, tempData, templen);
        delete tempData;
        dataPos = data + templen;
    }

    if(dataPos - data)
    {
        dataContainer.push_back(std::string(data, dataPos - data));
    }
    delete data;
    return dataContainer;
}

void FileConfig::Write(const std::string& description, const std::vector<std::string>& data)
{
    File configFile(m_filePath);
    configFile.Open("wt");
    configFile.Write("# ", 2);
    configFile.Write(description.c_str(), description.size());
    configFile.Write("\r\n", 2);
    for(std::vector<std::string>::const_iterator it = data.begin();
        it != data.end(); it++)
    {
        configFile.Write(it->c_str(), it->size());
        configFile.Write("\r\n", 1);
    }
}<commit_msg>fix config<commit_after>#include "config.h"
#include "common/dir.h"
#include "common/common.h"
#include "common/file.h"
#include "utils/utils.h"

#define MAX_BUFFER_LEN 1024

Config::Config()
: m_file(Dir::GetConfigDir() + "/twainet.conf")
{
	m_file.Load();
}

Config::~Config()
{
	m_file.Save();
}

std::string Config::GetTrustedFileName()
{
	return m_file.getString("common", "trustedFileName", "twainet.trusted");
}

std::string Config::GetPluginsFileName()
{
    return m_file.getString("common", "pluginsFileName", "twainet.plugins");
}

int Config::GetLocalServerPort()
{
	return m_file.getLong("common", "localPort", g_localServerPort);
}

void Config::SetLocalServerPort(int port)
{
	m_file.setLong("common", "localPort", port);
}

FileConfig::FileConfig(const std::string& filePath)
: m_filePath(filePath){}

FileConfig::~FileConfig(){}

std::vector<std::string> FileConfig::Read()
{
    std::vector<std::string> dataContainer;
    File configFile(m_filePath);
    int filesize = configFile.GetFileSize(), filepos = 0;
    char* data = new char[MAX_BUFFER_LEN];
    char* dataPos = data;
    while(filepos < filesize)
    {
        unsigned int size = MAX_BUFFER_LEN - (unsigned int)(dataPos - data) ;
        memset(dataPos, 0, size);
        if(!configFile.Read(dataPos, &size))
        {
            break;
        }
        filepos += size;

        std::vector<std::string> lines = CommonUtils::DelimitString(data, "\n");
        int pos = 0;
        for(int i = 0; i < (int)lines.size(); i++)
        {
            pos += lines[i].size();
            std::string line = lines[i];
            if(line[line.size() - 1] == '\r')
                line.erase(line.size() - 1, 1);
            if(line[0] == '#' || line.empty())
                continue;

            dataContainer.push_back(line);
        }
    }

    delete data;
    return dataContainer;
}

void FileConfig::Write(const std::string& description, const std::vector<std::string>& data)
{
    File configFile(m_filePath);
    configFile.Open("wt");
    configFile.Write("# ", 2);
    configFile.Write(description.c_str(), description.size());
    configFile.Write("\r\n", 2);
    for(std::vector<std::string>::const_iterator it = data.begin();
        it != data.end(); it++)
    {
        configFile.Write(it->c_str(), it->size());
        configFile.Write("\r\n", 1);
    }
}<|endoftext|>


<commit_before>/*
 * SessionPackrat.cpp
 *
 * Copyright (C) 2009-14 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionPackrat.hpp"

#include <core/Exec.hpp>
#include <core/FileSerializer.hpp>
#include <core/Hash.hpp>
#include <core/system/FileMonitor.hpp>

#include <r/RExec.hpp>
#include <r/session/RClientState.hpp>

#include <session/projects/SessionProjects.hpp>
#include <session/SessionModuleContext.hpp>

#include "SessionPackages.hpp"

using namespace core;

namespace session {
namespace modules {
namespace packrat {

namespace {

enum PackratHashType
{
   HASH_TYPE_LOCKFILE = 0,
   HASH_TYPE_LIBRARY = 1
};

std::string keyOfHashType(PackratHashType hashType)
{
   return hashType == HASH_TYPE_LOCKFILE ?
      "packratLockfileHash" :
      "packratLibraryHash";
}

std::string getStoredHash(PackratHashType hashType)
{
   json::Value hash =
      r::session::clientState().getProjectPersistent("packrat",
                                                     keyOfHashType(hashType));
   if (hash.type() == json::StringType)
      return hash.get_str();
   else
      return "";
}

void setStoredHash(PackratHashType hashType, const std::string& hash)
{
   r::session::clientState().putProjectPersistent(
         "packrat",
         keyOfHashType(hashType),
         hash);
}

// adds content from the given file to the given file if it's a
// DESCRIPTION file (used to summarize library content for hashing)
void addDescContent(int level, const FilePath& path, std::string* pDescContent)
{
   std::string newDescContent;
   if (path.filename() == "DESCRIPTION")
   {
      Error error = readStringFromFile(path, &newDescContent);
      pDescContent->append(newDescContent);
   }
}

// computes a hash of the content of all DESCRIPTION files in the Packrat
// private library
std::string computeLibraryHash()
{
   FilePath libraryPath =
      projects::projectContext().directory().complete("packrat/lib");

   // find all DESCRIPTION files in the library and concatenate them to form
   // a hashable state
   std::string descFileContent;
   libraryPath.childrenRecursive(
         boost::bind(addDescContent, _1, _2, &descFileContent));

   if (descFileContent.empty())
      return "";

   return hash::crc32HexHash(descFileContent);
}

// computes the hash of the current project's lockfile
std::string computeLockfileHash()
{
   FilePath lockFilePath =
      projects::projectContext().directory().complete("packrat/packrat.lock");

   if (!lockFilePath.exists())
      return "";

   std::string lockFileContent;
   Error error = readStringFromFile(lockFilePath, &lockFileContent);
   if (error)
   {
      LOG_ERROR(error);
      return "";
   }

   return hash::crc32HexHash(lockFileContent);
}

std::string getComputedHash(PackratHashType hashType)
{
   if (hashType == HASH_TYPE_LOCKFILE)
      return computeLockfileHash();
   else
      return computeLibraryHash();
}

void checkHashes(
      PackratHashType primary,
      PackratHashType secondary,
      boost::function<void(const std::string&, const std::string&)> onPrimaryMismatch)
{
   std::string oldHash = getStoredHash(primary);
   std::string newHash = getComputedHash(primary);

   // hashes match, no work needed
   if (oldHash == newHash)
      return;

   // primary hashes mismatch, secondary hashes match
   else if (getStoredHash(secondary) == getComputedHash(secondary))
   {
      onPrimaryMismatch(oldHash, newHash);
   }

   // primary and secondary hashes mismatch
   else
   {
      // TODO: invoke status() to see if we're in a consistent state.
      // yes -> update both hashes
      // no -> prompt user
   }
}

void onLockfileUpdate(const std::string& oldHash, const std::string& newHash)
{
   std::cerr << "detected lockfile change ("
      << oldHash << " -> " << newHash << ")" << std::endl;
   setStoredHash(HASH_TYPE_LOCKFILE, newHash);
}

void onLibraryUpdate(const std::string& oldHash, const std::string& newHash)
{
   std::cerr << "detected library change ("
      << oldHash << " -> " << newHash << ")" << std::endl;
   setStoredHash(HASH_TYPE_LIBRARY, newHash);
}

void onFileChanged(FilePath sourceFilePath)
{
   FilePath libraryPath =
      projects::projectContext().directory().complete("packrat/lib");

   if (sourceFilePath.filename() == "packrat.lock")
   {
      checkHashes(HASH_TYPE_LOCKFILE, HASH_TYPE_LIBRARY, onLockfileUpdate);
   }
   else if (sourceFilePath.isWithin(libraryPath))
   {
      checkHashes(HASH_TYPE_LIBRARY, HASH_TYPE_LOCKFILE, onLibraryUpdate);
   }
}

void onFilesChanged(const std::vector<core::system::FileChangeEvent>& changes)
{
   BOOST_FOREACH(const core::system::FileChangeEvent& fileChange, changes)
   {
      FilePath changedFilePath(fileChange.fileInfo().absolutePath());
      onFileChanged(changedFilePath);
   }
}
} // anonymous namespace

bool isPackratAvailable()
{
    return module_context::isPackageVersionInstalled("packrat", "0.2.0");
}

// returns true if we're in a project and packrat is installed
bool isPackratEligibleProject()
{
   if (!projects::projectContext().hasProject())
      return false;

   if (!isPackratAvailable())
       return false;

   return true;
}

bool isPackratModeOn()
{
   if (!isPackratEligibleProject())
      return false;

   // if we are in a project, attempt to ascertain whether Packrat mode is on
   // for the project (it's OK if this fails; by default we presume packrat
   // mode to be off)
   bool packratMode = false;
   FilePath dir = projects::projectContext().directory();
   r::exec::RFunction("packrat:::isPackratModeOn",
                      dir.absolutePath()).call(&packratMode);
   return packratMode;
}

bool isPackratManagedRPackage()
{
   if (!isPackratEligibleProject())
      return false;

   // get the current working directory
   FilePath dir = projects::projectContext().directory();

   // bail if this isn't a package
   if (!core::r_util::isPackageDirectory(dir))
      return false;

   // check if the project is packified
   bool isPackratProject;
   r::exec::RFunction("packrat:::checkPackified",
                      /* project = */ dir.absolutePath(),
                      /* silent = */ true).call(&isPackratProject);
   return isPackratProject;
}

Error initialize()
{
   using boost::bind;
   using namespace module_context;

   // listen for changes to the project files
   session::projects::FileMonitorCallbacks cb;
   cb.onFilesChanged = onFilesChanged;
   projects::projectContext().subscribeToFileMonitor("Packrat", cb);
   module_context::events().onSourceEditorFileSaved.connect(onFileChanged);

   ExecBlock initBlock;

   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionPackrat.R"));

   return initBlock.execute();
}

} // namespace packrat
} // namespace modules
} // namespace session

<commit_msg>fix build (recursive dir iteration function now returns bool)<commit_after>/*
 * SessionPackrat.cpp
 *
 * Copyright (C) 2009-14 by RStudio, Inc.
 *
 * Unless you have received this program directly from RStudio pursuant
 * to the terms of a commercial license agreement with RStudio, then
 * this program is licensed to you under the terms of version 3 of the
 * GNU Affero General Public License. This program is distributed WITHOUT
 * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
 * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
 *
 */

#include "SessionPackrat.hpp"

#include <core/Exec.hpp>
#include <core/FileSerializer.hpp>
#include <core/Hash.hpp>
#include <core/system/FileMonitor.hpp>

#include <r/RExec.hpp>
#include <r/session/RClientState.hpp>

#include <session/projects/SessionProjects.hpp>
#include <session/SessionModuleContext.hpp>

#include "SessionPackages.hpp"

using namespace core;

namespace session {
namespace modules {
namespace packrat {

namespace {

enum PackratHashType
{
   HASH_TYPE_LOCKFILE = 0,
   HASH_TYPE_LIBRARY = 1
};

std::string keyOfHashType(PackratHashType hashType)
{
   return hashType == HASH_TYPE_LOCKFILE ?
      "packratLockfileHash" :
      "packratLibraryHash";
}

std::string getStoredHash(PackratHashType hashType)
{
   json::Value hash =
      r::session::clientState().getProjectPersistent("packrat",
                                                     keyOfHashType(hashType));
   if (hash.type() == json::StringType)
      return hash.get_str();
   else
      return "";
}

void setStoredHash(PackratHashType hashType, const std::string& hash)
{
   r::session::clientState().putProjectPersistent(
         "packrat",
         keyOfHashType(hashType),
         hash);
}

// adds content from the given file to the given file if it's a
// DESCRIPTION file (used to summarize library content for hashing)
bool addDescContent(int level, const FilePath& path, std::string* pDescContent)
{
   std::string newDescContent;
   if (path.filename() == "DESCRIPTION")
   {
      Error error = readStringFromFile(path, &newDescContent);
      pDescContent->append(newDescContent);
   }
   return true;
}

// computes a hash of the content of all DESCRIPTION files in the Packrat
// private library
std::string computeLibraryHash()
{
   FilePath libraryPath =
      projects::projectContext().directory().complete("packrat/lib");

   // find all DESCRIPTION files in the library and concatenate them to form
   // a hashable state
   std::string descFileContent;
   libraryPath.childrenRecursive(
         boost::bind(addDescContent, _1, _2, &descFileContent));

   if (descFileContent.empty())
      return "";

   return hash::crc32HexHash(descFileContent);
}

// computes the hash of the current project's lockfile
std::string computeLockfileHash()
{
   FilePath lockFilePath =
      projects::projectContext().directory().complete("packrat/packrat.lock");

   if (!lockFilePath.exists())
      return "";

   std::string lockFileContent;
   Error error = readStringFromFile(lockFilePath, &lockFileContent);
   if (error)
   {
      LOG_ERROR(error);
      return "";
   }

   return hash::crc32HexHash(lockFileContent);
}

std::string getComputedHash(PackratHashType hashType)
{
   if (hashType == HASH_TYPE_LOCKFILE)
      return computeLockfileHash();
   else
      return computeLibraryHash();
}

void checkHashes(
      PackratHashType primary,
      PackratHashType secondary,
      boost::function<void(const std::string&, const std::string&)> onPrimaryMismatch)
{
   std::string oldHash = getStoredHash(primary);
   std::string newHash = getComputedHash(primary);

   // hashes match, no work needed
   if (oldHash == newHash)
      return;

   // primary hashes mismatch, secondary hashes match
   else if (getStoredHash(secondary) == getComputedHash(secondary))
   {
      onPrimaryMismatch(oldHash, newHash);
   }

   // primary and secondary hashes mismatch
   else
   {
      // TODO: invoke status() to see if we're in a consistent state.
      // yes -> update both hashes
      // no -> prompt user
   }
}

void onLockfileUpdate(const std::string& oldHash, const std::string& newHash)
{
   std::cerr << "detected lockfile change ("
      << oldHash << " -> " << newHash << ")" << std::endl;
   setStoredHash(HASH_TYPE_LOCKFILE, newHash);
}

void onLibraryUpdate(const std::string& oldHash, const std::string& newHash)
{
   std::cerr << "detected library change ("
      << oldHash << " -> " << newHash << ")" << std::endl;
   setStoredHash(HASH_TYPE_LIBRARY, newHash);
}

void onFileChanged(FilePath sourceFilePath)
{
   FilePath libraryPath =
      projects::projectContext().directory().complete("packrat/lib");

   if (sourceFilePath.filename() == "packrat.lock")
   {
      checkHashes(HASH_TYPE_LOCKFILE, HASH_TYPE_LIBRARY, onLockfileUpdate);
   }
   else if (sourceFilePath.isWithin(libraryPath))
   {
      checkHashes(HASH_TYPE_LIBRARY, HASH_TYPE_LOCKFILE, onLibraryUpdate);
   }
}

void onFilesChanged(const std::vector<core::system::FileChangeEvent>& changes)
{
   BOOST_FOREACH(const core::system::FileChangeEvent& fileChange, changes)
   {
      FilePath changedFilePath(fileChange.fileInfo().absolutePath());
      onFileChanged(changedFilePath);
   }
}
} // anonymous namespace

bool isPackratAvailable()
{
    return module_context::isPackageVersionInstalled("packrat", "0.2.0");
}

// returns true if we're in a project and packrat is installed
bool isPackratEligibleProject()
{
   if (!projects::projectContext().hasProject())
      return false;

   if (!isPackratAvailable())
       return false;

   return true;
}

bool isPackratModeOn()
{
   if (!isPackratEligibleProject())
      return false;

   // if we are in a project, attempt to ascertain whether Packrat mode is on
   // for the project (it's OK if this fails; by default we presume packrat
   // mode to be off)
   bool packratMode = false;
   FilePath dir = projects::projectContext().directory();
   r::exec::RFunction("packrat:::isPackratModeOn",
                      dir.absolutePath()).call(&packratMode);
   return packratMode;
}

bool isPackratManagedRPackage()
{
   if (!isPackratEligibleProject())
      return false;

   // get the current working directory
   FilePath dir = projects::projectContext().directory();

   // bail if this isn't a package
   if (!core::r_util::isPackageDirectory(dir))
      return false;

   // check if the project is packified
   bool isPackratProject;
   r::exec::RFunction("packrat:::checkPackified",
                      /* project = */ dir.absolutePath(),
                      /* silent = */ true).call(&isPackratProject);
   return isPackratProject;
}

Error initialize()
{
   using boost::bind;
   using namespace module_context;

   // listen for changes to the project files
   session::projects::FileMonitorCallbacks cb;
   cb.onFilesChanged = onFilesChanged;
   projects::projectContext().subscribeToFileMonitor("Packrat", cb);
   module_context::events().onSourceEditorFileSaved.connect(onFileChanged);

   ExecBlock initBlock;

   initBlock.addFunctions()
      (bind(sourceModuleRFile, "SessionPackrat.R"));

   return initBlock.execute();
}

} // namespace packrat
} // namespace modules
} // namespace session

<|endoftext|>


<commit_before>// Copyright (c) 2014-2015, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
//
// 2. 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.
//
// 3. Neither the name of the copyright holder 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 HOLDER 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers

#include "checkpoints_create.h"
#include "common/dns_utils.h"
#include "include_base_utils.h"
#include <sstream>
#include <random>
#include "storages/portable_storage_template_helper.h" // epee json include

namespace
{
  bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
  {
    if (a.size() != b.size()) return false;

    for (const auto& record_in_a : a)
    {
      bool ok = false;
      for (const auto& record_in_b : b)
      {
	if (record_in_a == record_in_b)
	{
	  ok = true;
	  break;
	}
      }
      if (!ok) return false;
    }

    return true;
  }
} // anonymous namespace

namespace cryptonote
{

struct t_hashline
{
	uint64_t height;
	std::string hash;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(height)
        KV_SERIALIZE(hash)
      END_KV_SERIALIZE_MAP()
};

struct t_hash_json {
 	std::vector<t_hashline> hashlines;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(hashlines)
      END_KV_SERIALIZE_MAP()
};

bool create_checkpoints(cryptonote::checkpoints& checkpoints)
{
  ADD_CHECKPOINT(1,     "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
  ADD_CHECKPOINT(10,    "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
  ADD_CHECKPOINT(100,   "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
  ADD_CHECKPOINT(1000,  "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876");
  ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2");
  ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
  ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
  ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
  ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
  ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
  ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2");
  ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb");
  ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063");
  ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553");
  ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61");
  ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf");
  ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131");
  ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8");
  ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d");
  ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831");

  return true;
}

bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  boost::system::error_code errcode;
  if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
  {
    LOG_PRINT_L1("Blockchain checkpoints file not found");
    return true;
  }

  LOG_PRINT_L1("Adding checkpoints from blockchain hashfile");

  uint64_t prev_max_height = checkpoints.get_max_height();
  LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
  t_hash_json hashes;
  epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
  for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
  {
      uint64_t height;
      height = it->height;
      if (height <= prev_max_height) {
	LOG_PRINT_L1("ignoring checkpoint height " << height);
      } else {
	std::string blockhash = it->hash;
	LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
	ADD_CHECKPOINT(height, blockhash);
      }
      ++it;
  }

  return true;
}

bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testnet)
{
  // All four MoneroPulse domains have DNSSEC on and valid
  static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
						   , "checkpoints.moneropulse.org"
						   , "checkpoints.moneropulse.net"
						   , "checkpoints.moneropulse.co"
  };

  static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se"
							   , "testpoints.moneropulse.org"
							   , "testpoints.moneropulse.net"
							   , "testpoints.moneropulse.co"
  };

  std::vector<std::vector<std::string> > records;
  records.resize(dns_urls.size());

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
  size_t first_index = dis(gen);

  bool avail, valid;
  size_t cur_index = first_index;
  do
  {
    std::string url;
    if (testnet)
    {
      url = testnet_dns_urls[cur_index];
    }
    else
    {
      url = dns_urls[cur_index];
    }

    records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
    if (!avail)
    {
      LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
    }
    if (!valid)
    {
      LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
    }

    if (records[cur_index].size() == 0 || !avail || !valid)
    {
      cur_index++;
      if (cur_index == dns_urls.size())
      {
	cur_index = 0;
      }
      records[cur_index].clear();
      continue;
    }
    break;
  } while (cur_index != first_index);

  size_t num_valid_records = 0;

  for( const auto& record_set : records)
  {
    if (record_set.size() != 0)
    {
      num_valid_records++;
    }
  }

  if (num_valid_records < 2)
  {
    LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
    return true;
  }

  int good_records_index = -1;
  for (size_t i = 0; i < records.size() - 1; ++i)
  {
    if (records[i].size() == 0) continue;

    for (size_t j = i + 1; j < records.size(); ++j)
    {
      if (dns_records_match(records[i], records[j]))
      {
	good_records_index = i;
	break;
      }
    }
    if (good_records_index >= 0) break;
  }

  if (good_records_index < 0)
  {
    LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
    return true;
  }

  for (auto& record : records[good_records_index])
  {
    auto pos = record.find(":");
    if (pos != std::string::npos)
    {
      uint64_t height;
      crypto::hash hash;

      // parse the first part as uint64_t,
      // if this fails move on to the next record
      std::stringstream ss(record.substr(0, pos));
      if (!(ss >> height))
      {
	continue;
      }

      // parse the second part as crypto::hash,
      // if this fails move on to the next record
      std::string hashStr = record.substr(pos + 1);
      if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
      {
	continue;
      }

      ADD_CHECKPOINT(height, hashStr);
    }
  }
  return true;
}

bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  // TODO: replace hard-coded url with const string or #define
  return (load_checkpoints_from_json(checkpoints, json_hashfile_fullpath) && load_checkpoints_from_dns(checkpoints));
}

}  // namespace cryptonote
<commit_msg>Fix DNS checkpoint consensus code<commit_after>// Copyright (c) 2014-2015, The Monero Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
//    conditions and the following disclaimer.
//
// 2. 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.
//
// 3. Neither the name of the copyright holder 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 HOLDER 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.
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers

#include "checkpoints_create.h"
#include "common/dns_utils.h"
#include "include_base_utils.h"
#include <sstream>
#include <random>
#include "storages/portable_storage_template_helper.h" // epee json include

namespace
{
  bool dns_records_match(const std::vector<std::string>& a, const std::vector<std::string>& b)
  {
    if (a.size() != b.size()) return false;

    for (const auto& record_in_a : a)
    {
      bool ok = false;
      for (const auto& record_in_b : b)
      {
	if (record_in_a == record_in_b)
	{
	  ok = true;
	  break;
	}
      }
      if (!ok) return false;
    }

    return true;
  }
} // anonymous namespace

namespace cryptonote
{

struct t_hashline
{
	uint64_t height;
	std::string hash;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(height)
        KV_SERIALIZE(hash)
      END_KV_SERIALIZE_MAP()
};

struct t_hash_json {
 	std::vector<t_hashline> hashlines;
      BEGIN_KV_SERIALIZE_MAP()
        KV_SERIALIZE(hashlines)
      END_KV_SERIALIZE_MAP()
};

bool create_checkpoints(cryptonote::checkpoints& checkpoints)
{
  ADD_CHECKPOINT(1,     "771fbcd656ec1464d3a02ead5e18644030007a0fc664c0a964d30922821a8148");
  ADD_CHECKPOINT(10,    "c0e3b387e47042f72d8ccdca88071ff96bff1ac7cde09ae113dbb7ad3fe92381");
  ADD_CHECKPOINT(100,   "ac3e11ca545e57c49fca2b4e8c48c03c23be047c43e471e1394528b1f9f80b2d");
  ADD_CHECKPOINT(1000,  "5acfc45acffd2b2e7345caf42fa02308c5793f15ec33946e969e829f40b03876");
  ADD_CHECKPOINT(10000, "c758b7c81f928be3295d45e230646de8b852ec96a821eac3fea4daf3fcac0ca2");
  ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
  ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
  ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
  ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
  ADD_CHECKPOINT(202612, "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698");
  ADD_CHECKPOINT(202613, "e2aa337e78df1f98f462b3b1e560c6b914dec47b610698b7b7d1e3e86b6197c2");
  ADD_CHECKPOINT(202614, "c29e3dc37d8da3e72e506e31a213a58771b24450144305bcba9e70fa4d6ea6fb");
  ADD_CHECKPOINT(205000, "5d3d7a26e6dc7535e34f03def711daa8c263785f73ec1fadef8a45880fde8063");
  ADD_CHECKPOINT(220000, "9613f455933c00e3e33ac315cc6b455ee8aa0c567163836858c2d9caff111553");
  ADD_CHECKPOINT(230300, "bae7a80c46859db355556e3a9204a337ae8f24309926a1312323fdecf1920e61");
  ADD_CHECKPOINT(230700, "93e631240ceac831da1aebfc5dac8f722c430463024763ebafa888796ceaeedf");
  ADD_CHECKPOINT(231350, "b5add137199b820e1ea26640e5c3e121fd85faa86a1e39cf7e6cc097bdeb1131");
  ADD_CHECKPOINT(232150, "955de8e6b6508af2c24f7334f97beeea651d78e9ade3ab18fec3763be3201aa8");
  ADD_CHECKPOINT(249380, "654fb0a81ce3e5caf7e3264a70f447d4bd07586c08fa50f6638cc54da0a52b2d");
  ADD_CHECKPOINT(460000, "75037a7aed3e765db96c75bcf908f59d690a5f3390baebb9edeafd336a1c4831");

  return true;
}

bool load_checkpoints_from_json(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  boost::system::error_code errcode;
  if (! (boost::filesystem::exists(json_hashfile_fullpath, errcode)))
  {
    LOG_PRINT_L1("Blockchain checkpoints file not found");
    return true;
  }

  LOG_PRINT_L1("Adding checkpoints from blockchain hashfile");

  uint64_t prev_max_height = checkpoints.get_max_height();
  LOG_PRINT_L1("Hard-coded max checkpoint height is " << prev_max_height);
  t_hash_json hashes;
  epee::serialization::load_t_from_json_file(hashes, json_hashfile_fullpath);
  for (std::vector<t_hashline>::const_iterator it = hashes.hashlines.begin(); it != hashes.hashlines.end(); )
  {
      uint64_t height;
      height = it->height;
      if (height <= prev_max_height) {
	LOG_PRINT_L1("ignoring checkpoint height " << height);
      } else {
	std::string blockhash = it->hash;
	LOG_PRINT_L1("Adding checkpoint height " << height << ", hash=" << blockhash);
	ADD_CHECKPOINT(height, blockhash);
      }
      ++it;
  }

  return true;
}

bool load_checkpoints_from_dns(cryptonote::checkpoints& checkpoints, bool testnet)
{
  // All four MoneroPulse domains have DNSSEC on and valid
  static const std::vector<std::string> dns_urls = { "checkpoints.moneropulse.se"
						   , "checkpoints.moneropulse.org"
						   , "checkpoints.moneropulse.net"
						   , "checkpoints.moneropulse.co"
  };

  static const std::vector<std::string> testnet_dns_urls = { "testpoints.moneropulse.se"
							   , "testpoints.moneropulse.org"
							   , "testpoints.moneropulse.net"
							   , "testpoints.moneropulse.co"
  };

  std::vector<std::vector<std::string> > records;
  records.resize(dns_urls.size());

  std::random_device rd;
  std::mt19937 gen(rd());
  std::uniform_int_distribution<int> dis(0, dns_urls.size() - 1);
  size_t first_index = dis(gen);

  bool avail, valid;
  size_t cur_index = first_index;
  do
  {
    std::string url;
    if (testnet)
    {
      url = testnet_dns_urls[cur_index];
    }
    else
    {
      url = dns_urls[cur_index];
    }

    records[cur_index] = tools::DNSResolver::instance().get_txt_record(url, avail, valid);
    if (!avail)
    {
      records[cur_index].clear();
      LOG_PRINT_L2("DNSSEC not available for checkpoint update at URL: " << url << ", skipping.");
    }
    if (!valid)
    {
      records[cur_index].clear();
      LOG_PRINT_L2("DNSSEC validation failed for checkpoint update at URL: " << url << ", skipping.");
    }

    cur_index++;
    if (cur_index == dns_urls.size())
    {
      cur_index = 0;
    }
    records[cur_index].clear();
  } while (cur_index != first_index);

  size_t num_valid_records = 0;

  for( const auto& record_set : records)
  {
    if (record_set.size() != 0)
    {
      num_valid_records++;
    }
  }

  if (num_valid_records < 2)
  {
    LOG_PRINT_L0("WARNING: no two valid MoneroPulse DNS checkpoint records were received");
    return true;
  }

  int good_records_index = -1;
  for (size_t i = 0; i < records.size() - 1; ++i)
  {
    if (records[i].size() == 0) continue;

    for (size_t j = i + 1; j < records.size(); ++j)
    {
      if (dns_records_match(records[i], records[j]))
      {
	good_records_index = i;
	break;
      }
    }
    if (good_records_index >= 0) break;
  }

  if (good_records_index < 0)
  {
    LOG_PRINT_L0("WARNING: no two MoneroPulse DNS checkpoint records matched");
    return true;
  }

  for (auto& record : records[good_records_index])
  {
    auto pos = record.find(":");
    if (pos != std::string::npos)
    {
      uint64_t height;
      crypto::hash hash;

      // parse the first part as uint64_t,
      // if this fails move on to the next record
      std::stringstream ss(record.substr(0, pos));
      if (!(ss >> height))
      {
	continue;
      }

      // parse the second part as crypto::hash,
      // if this fails move on to the next record
      std::string hashStr = record.substr(pos + 1);
      if (!epee::string_tools::parse_tpod_from_hex_string(hashStr, hash))
      {
	continue;
      }

      ADD_CHECKPOINT(height, hashStr);
    }
  }
  return true;
}

bool load_new_checkpoints(cryptonote::checkpoints& checkpoints, std::string json_hashfile_fullpath)
{
  // TODO: replace hard-coded url with const string or #define
  return (load_checkpoints_from_json(checkpoints, json_hashfile_fullpath) && load_checkpoints_from_dns(checkpoints));
}

}  // namespace cryptonote
<|endoftext|>


<commit_before>/// \file AddTaskNucleiYield.C
/// \brief Simple macro to add the task to a grid job
///
/// The task is here added several times to analyse different particle species and to investigate
/// different set of cuts in only one run.
///
/// \author Maximiliano Puccio <maximiliano.puccio@cern.ch>, University and INFN Torino
/// \date Feb 19th, 2015

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <Rtypes.h>
#include <TString.h>
#include "AliAnalysisTaskNucleiYield.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliPID.h"
#endif

AliAnalysisTaskNucleiYield* AddTaskNucleiYield_LHC15o(Bool_t isMC = kFALSE,
    AliPID::EParticleType part = AliPID::kDeuteron,
    Int_t pdgCode = 1000010020,
    TString tskname = "deuteron",
    TString suffix = "") {

  // Get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskNucleiYield", "No analysis manager found.");
    return 0x0;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskNucleiYield", "This task requires an input event handler");
    return 0x0;
  }

  tskname.Append(Form("%s",suffix.Data()));

  AliAnalysisTaskNucleiYield *deu = new AliAnalysisTaskNucleiYield(tskname);

  deu->SetParticleType(part);
  deu->SetPDG(pdgCode);
  deu->SetIsMC(isMC);
  deu->SetDCABins(80,-0.5,0.5);

  deu->SetRequireTPCpidSigmas(3.f);
  float cent[14] = {-1000.f,0.f,5.f,10.f,20.f,30.f,40.f,50.f,60.f,70.f,80.f,90.f,100.f,1000.f};
  deu->SetCentBins(13, cent);
  deu->SetUseFlattening(false);
  float pt[20] = {
    0.5f,0.6f,0.7f,0.8f,0.9f,1.0f,1.1f,1.2f,1.4f,1.6f,
    1.8f,2.0f,2.2f,2.6f,3.0f,3.4f,3.6f,4.0f,5.0f,6.0f
  };
  deu->SetPtBins(19,pt);

  float dcabins[53] = {
    -1.30,-1.20,-1.10,-1.00,-0.90,-0.80,-0.70,-0.60,-0.50,-0.40,
    -0.35,-0.30,-0.25,-0.20,-0.15,-0.12,-0.10,-0.09,-0.08,-0.07,
    -0.06,-0.05,-0.04,-0.03,-0.02,-0.01, 0.00, 0.01, 0.02, 0.03,
     0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.12, 0.15, 0.20,
     0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00,
     1.10, 1.20, 1.30
  };
  deu->SetDCABins(52,dcabins);

  deu->fEventCut.fCentralityFramework = 1;

  mgr->AddTask(deu);

  TString output = "AnalysisResults.root";
  AliAnalysisDataContainer *deuCont = mgr->CreateContainer(Form("mpuccio_%s",tskname.Data()),
      TList::Class(),
      AliAnalysisManager::kOutputContainer,
      output.Data());
  mgr->ConnectInput  (deu,  0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput (deu,  1, deuCont);
  return deu;
}

<commit_msg>Fixed function name<commit_after>/// \file AddTaskNucleiYield.C
/// \brief Simple macro to add the task to a grid job
///
/// The task is here added several times to analyse different particle species and to investigate
/// different set of cuts in only one run.
///
/// \author Maximiliano Puccio <maximiliano.puccio@cern.ch>, University and INFN Torino
/// \date Feb 19th, 2015

#if !defined(__CINT__) || defined(__MAKECINT__)
#include <Rtypes.h>
#include <TString.h>
#include "AliAnalysisTaskNucleiYield.h"
#include "AliAnalysisManager.h"
#include "AliAnalysisDataContainer.h"
#include "AliPID.h"
#endif

AliAnalysisTaskNucleiYield* AddTaskNucleiYield(Bool_t isMC = kFALSE,
    AliPID::EParticleType part = AliPID::kDeuteron,
    Int_t pdgCode = 1000010020,
    TString tskname = "deuteron",
    TString suffix = "") {

  // Get the current analysis manager
  AliAnalysisManager *mgr = AliAnalysisManager::GetAnalysisManager();
  if (!mgr) {
    Error("AddTaskNucleiYield", "No analysis manager found.");
    return 0x0;
  }

  // Check the analysis type using the event handlers connected to the analysis manager.
  if (!mgr->GetInputEventHandler()) {
    ::Error("AddTaskNucleiYield", "This task requires an input event handler");
    return 0x0;
  }

  tskname.Append(Form("%s",suffix.Data()));

  AliAnalysisTaskNucleiYield *deu = new AliAnalysisTaskNucleiYield(tskname);

  deu->SetParticleType(part);
  deu->SetPDG(pdgCode);
  deu->SetIsMC(isMC);
  deu->SetDCABins(80,-0.5,0.5);

  deu->SetRequireTPCpidSigmas(3.f);
  float cent[14] = {-1000.f,0.f,5.f,10.f,20.f,30.f,40.f,50.f,60.f,70.f,80.f,90.f,100.f,1000.f};
  deu->SetCentBins(13, cent);
  deu->SetUseFlattening(false);
  float pt[20] = {
    0.5f,0.6f,0.7f,0.8f,0.9f,1.0f,1.1f,1.2f,1.4f,1.6f,
    1.8f,2.0f,2.2f,2.6f,3.0f,3.4f,3.6f,4.0f,5.0f,6.0f
  };
  deu->SetPtBins(19,pt);

  float dcabins[53] = {
    -1.30,-1.20,-1.10,-1.00,-0.90,-0.80,-0.70,-0.60,-0.50,-0.40,
    -0.35,-0.30,-0.25,-0.20,-0.15,-0.12,-0.10,-0.09,-0.08,-0.07,
    -0.06,-0.05,-0.04,-0.03,-0.02,-0.01, 0.00, 0.01, 0.02, 0.03,
     0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.10, 0.12, 0.15, 0.20,
     0.25, 0.30, 0.35, 0.40, 0.50, 0.60, 0.70, 0.80, 0.90, 1.00,
     1.10, 1.20, 1.30
  };
  deu->SetDCABins(52,dcabins);

  deu->fEventCut.fCentralityFramework = 1;

  mgr->AddTask(deu);

  TString output = "AnalysisResults.root";
  AliAnalysisDataContainer *deuCont = mgr->CreateContainer(Form("mpuccio_%s",tskname.Data()),
      TList::Class(),
      AliAnalysisManager::kOutputContainer,
      output.Data());
  mgr->ConnectInput  (deu,  0, mgr->GetCommonInputContainer());
  mgr->ConnectOutput (deu,  1, deuCont);
  return deu;
}

<|endoftext|>