<commit_before>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#pragma once
#include <unordered_map>
#include <queue>
#include "id_gen.hpp"
#include "cache.h"

namespace redc
{
  template <typename T, typename Id = uint16_t>
  struct ID_Map
  {
    using id_type = Id;

    using map_type = std::unordered_map<id_type, T>;

    using iterator = typename map_type::iterator;
    using const_iterator = typename map_type::const_iterator;
    using value_type = typename map_type::value_type;
    using key_type = typename map_type::key_type;
    using size_type = typename map_type::size_type;

    inline ID_Map() noexcept
    {
      this->ids_cache_.gen_func([this](auto)
      {
        auto ids = std::make_unique<std::vector<id_type> >();
        for(auto&& pair : *this)
        {
          ids->push_back(std::get<0>(pair));
        }
        return ids;
      });
    }
    inline id_type insert(T const& obj) noexcept;

    template <class... Args>
    inline id_type emplace(Args&&... args) noexcept;

    inline T const& at(id_type) const;
    inline T& at(id_type);

    inline const_iterator find(id_type) const;
    inline iterator find(id_type);
    inline void set(id_type, T const&);

    inline iterator erase(const_iterator pos);
    inline iterator erase(const_iterator first, const_iterator last);
    inline size_type erase(key_type id);

    inline iterator begin() { return objs_.begin(); }
    inline const_iterator begin() const { return objs_.begin(); }
    inline const_iterator cbegin() const { return objs_.cbegin(); }

    inline iterator end() { return objs_.end(); }
    inline const_iterator end() const { return objs_.end(); }
    inline const_iterator cend() const { return objs_.cend(); }

    inline size_type size() const { return objs_.size(); }

    inline std::vector<id_type> ids() const noexcept;
  private:
    map_type objs_;
    ID_Gen<id_type> id_counter_;

    mutable Cache<std::vector<id_type> > ids_cache_;
  };

  template <class T, class Id>
  inline auto ID_Map<T, Id>::insert(T const& obj) noexcept -> id_type
  {
    id_type id = this->id_counter_.get();
    if(!id) return 0;

    this->objs_.emplace(id, obj);
    this->ids_cache_.invalidate();
    return id;
  }

  template <class T, class Id>
  template <class... Args>
  inline auto ID_Map<T, Id>::emplace(Args&&... args) noexcept -> id_type
  {
    id_type id = this->id_counter_.get();
    if(!id) return 0;

    this->objs_.emplace(id, T{std::forward<Args>(args)...});
    this->ids_cache_.invalidate();
    return id;
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(const_iterator pos) -> iterator
  {
    using std::end;
    if(pos != end(this->objs_)) this->id_counter_.remove(pos->first);

    this->ids_cache_.invalidate();
    return this->objs_.erase(pos);
  }
  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(const_iterator first,
                                   const_iterator last) -> iterator
  {
    const_iterator orig_first = first;
    for(; first != last; ++first) this->id_counter_.remove(first->first);

    this->ids_cache_.invalidate();
    return this->objs_.erase(orig_first, last);
  }
  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(key_type id) -> size_type
  {
    using std::end;
    if(this->objs_.find(id) != end(this->objs_))
      this->id_counter_.remove(id);

    this->ids_cache_.invalidate();
    return this->objs_.erase(id);
  }

  template <class T, class Id>
  inline T const& ID_Map<T, Id>::at(id_type id) const
  {
    return objs_.at(id);
  }
  template <class T, class Id>
  inline T& ID_Map<T, Id>::at(id_type id)
  {
    return objs_.at(id);
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::find(id_type id) const -> const_iterator
  {
    return objs_.find(id);
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::find(id_type id) -> iterator
  {
    return objs_.find(id);
  }

  template <class T, class Id>
  inline void ID_Map<T, Id>::set(id_type id, T const& obj)
  {
    this->objs_.at(id) = obj;
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::ids() const noexcept -> std::vector<id_type>
  {
    return *this->ids_cache_.cache();
  }
}
<commit_msg>Add callback mechanism to ID_Map<commit_after>/*
 * Copyright (C) 2015 Luke San Antonio
 * All rights reserved.
 */
#pragma once
#include <unordered_map>
#include <queue>
#include "id_gen.hpp"
#include "cache.h"

namespace redc
{
  template <typename T, typename Id = uint16_t>
  struct ID_Map
  {
    using id_type = Id;

    using map_type = std::unordered_map<id_type, T>;

    using iterator = typename map_type::iterator;
    using const_iterator = typename map_type::const_iterator;
    using value_type = typename map_type::value_type;
    using key_type = typename map_type::key_type;
    using size_type = typename map_type::size_type;

    inline ID_Map() noexcept
    {
      this->ids_cache_.gen_func([this](auto)
      {
        auto ids = std::make_unique<std::vector<id_type> >();
        for(auto&& pair : *this)
        {
          ids->push_back(std::get<0>(pair));
        }
        return ids;
      });
    }
    inline id_type insert(T const& obj) noexcept;

    template <class... Args>
    inline id_type emplace(Args&&... args) noexcept;

    inline T const& at(id_type) const;
    inline T& at(id_type);

    inline const_iterator find(id_type) const;
    inline iterator find(id_type);
    inline void set(id_type, T const&);

    inline iterator erase(const_iterator pos);
    inline iterator erase(const_iterator first, const_iterator last);
    inline size_type erase(key_type id);

    inline iterator begin() { return objs_.begin(); }
    inline const_iterator begin() const { return objs_.begin(); }
    inline const_iterator cbegin() const { return objs_.cbegin(); }

    inline iterator end() { return objs_.end(); }
    inline const_iterator end() const { return objs_.end(); }
    inline const_iterator cend() const { return objs_.cend(); }

    inline size_type size() const { return objs_.size(); }

    inline std::vector<id_type> ids() const noexcept;
  private:
    map_type objs_;
    ID_Gen<id_type> id_counter_;

    mutable Cache<std::vector<id_type> > ids_cache_;

    // Overall this is a pretty limited mechanism but it really is all we need
    // to implement Active_Map.
    virtual void on_insert(id_type id) {}
    virtual void on_erase(id_type id) {}
  };

  template <class T, class Id>
  inline auto ID_Map<T, Id>::insert(T const& obj) noexcept -> id_type
  {
    id_type id = this->id_counter_.get();
    if(!id) return 0;

    this->objs_.emplace(id, obj);
    this->ids_cache_.invalidate();

    // Do the callback
    on_insert(id);

    return id;
  }

  template <class T, class Id>
  template <class... Args>
  inline auto ID_Map<T, Id>::emplace(Args&&... args) noexcept -> id_type
  {
    id_type id = this->id_counter_.get();
    if(!id) return 0;

    this->objs_.emplace(id, T{std::forward<Args>(args)...});
    this->ids_cache_.invalidate();

    on_insert(id);

    return id;
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(const_iterator pos) -> iterator
  {
    using std::end;
    if(pos != end(this->objs_)) this->id_counter_.remove(pos->first);

    this->ids_cache_.invalidate();

    auto ret = this->objs_.erase(pos);

    // We need to do this only after doing the removal
    on_erase(pos->first);

    return ret;
  }
  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(const_iterator first,
                                   const_iterator last) -> iterator
  {
    const_iterator orig_first = first;
    for(; first != last; ++first) this->id_counter_.remove(first->first);

    this->ids_cache_.invalidate();
    auto ret = this->objs_.erase(orig_first, last);

    // Remove each id
    for(first = orig_first; first != last; ++first) on_erase(orig_first->first);

    return ret;
  }
  template <class T, class Id>
  inline auto ID_Map<T, Id>::erase(key_type id) -> size_type
  {
    using std::end;
    if(this->objs_.find(id) != end(this->objs_))
      this->id_counter_.remove(id);

    this->ids_cache_.invalidate();
    auto ret = this->objs_.erase(id);

    on_erase(id);

    return ret;
  }

  template <class T, class Id>
  inline T const& ID_Map<T, Id>::at(id_type id) const
  {
    return objs_.at(id);
  }
  template <class T, class Id>
  inline T& ID_Map<T, Id>::at(id_type id)
  {
    return objs_.at(id);
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::find(id_type id) const -> const_iterator
  {
    return objs_.find(id);
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::find(id_type id) -> iterator
  {
    return objs_.find(id);
  }

  template <class T, class Id>
  inline void ID_Map<T, Id>::set(id_type id, T const& obj)
  {
    this->objs_.at(id) = obj;
  }

  template <class T, class Id>
  inline auto ID_Map<T, Id>::ids() const noexcept -> std::vector<id_type>
  {
    return *this->ids_cache_.cache();
  }
}
<|endoftext|>


<commit_before><commit_msg>Update config.cpp<commit_after><|endoftext|>


<commit_before>//----------------------------  grid_refinement.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  grid_refinement.cc  ---------------------------

#include <lac/vector.h>
#include <grid/grid_refinement.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/tria.h>

#include <numeric>
#include <algorithm>

template <int dim, typename number>
void GridRefinement::refine (Triangulation<dim>   &tria,
			     const Vector<number> &criteria,
			     const double         threshold)
{
  Assert (criteria.size() == tria.n_active_cells(),
	  ExcInvalidVectorSize(criteria.size(), tria.n_active_cells()));

				   // nothing to do; especially we
				   // do not want to flag with zero
				   // error since then we may get
				   // into conflict with coarsening
				   // in some cases
  if (threshold==0)
    return;

  Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
  const unsigned int n_cells = criteria.size();

  for (unsigned int index=0; index<n_cells; ++cell, ++index)
    if (fabs(criteria(index)) >= threshold)
      cell->set_refine_flag();
};

template <int dim, typename number>
void GridRefinement::coarsen (Triangulation<dim>   &tria,
			      const Vector<number> &criteria,
			      const double         threshold)
{
  Assert (criteria.size() == tria.n_active_cells(),
	  ExcInvalidVectorSize(criteria.size(), tria.n_active_cells()));

  Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
  const unsigned int n_cells = criteria.size();

  for (unsigned int index=0; index<n_cells; ++cell, ++index)
    if (fabs(criteria(index)) <= threshold)
      cell->set_coarsen_flag();
};

template <int dim, typename number>
void
GridRefinement::refine_and_coarsen_fixed_number (Triangulation<dim>   &tria,
						 const Vector<number> &criteria,
						 const double         top_fraction,
						 const double         bottom_fraction)
{
				   // correct number of cells is
				   // checked in @p{refine}
  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());

  const int refine_cells=static_cast<int>(top_fraction*criteria.size());
  const int coarsen_cells=static_cast<int>(bottom_fraction*criteria.size());

  if (refine_cells || coarsen_cells)
    {
      Vector<number> tmp(criteria);
      if (refine_cells)
	{
	  nth_element (tmp.begin(), tmp.begin()+refine_cells,
		       tmp.end(),
		       greater<double>());
	  refine (tria, criteria, *(tmp.begin() + refine_cells));
	};

      if (coarsen_cells)
	{
	  nth_element (tmp.begin(), tmp.begin()+tmp.size()-coarsen_cells,
		       tmp.end(),
		       greater<double>());
	  coarsen (tria, criteria, *(tmp.begin() + tmp.size() - coarsen_cells));
	};
    };
};

template <int dim, typename number>
void
GridRefinement::refine_and_coarsen_fixed_fraction (Triangulation<dim>   &tria,
						   const Vector<number> &criteria,
						   const double         top_fraction,
						   const double         bottom_fraction)
{
				   // correct number of cells is
				   // checked in @p{refine}
  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());

				   // let tmp be the cellwise square of the
				   // error, which is what we have to sum
				   // up and compare with
				   // @p{fraction_of_error*total_error}.
  Vector<number> tmp(criteria);
  const double total_error = tmp.l1_norm();

  Vector<number> partial_sums(criteria.size());

				   // sort the largest criteria to the
				   // beginning of the vector
  sort (tmp.begin(), tmp.end(), greater<double>());
  partial_sum (tmp.begin(), tmp.end(), partial_sums.begin());

				   // compute thresholds
  const typename Vector<number>::const_iterator
    q = lower_bound (partial_sums.begin(), partial_sums.end(),
		     top_fraction*total_error),
    p = upper_bound (partial_sums.begin(), partial_sums.end(),
		     total_error*(1-bottom_fraction));

  double bottom_threshold = tmp(p != partial_sums.end() ?
				p-partial_sums.begin() :
				criteria.size()-1),
	 top_threshold    = tmp(q-partial_sums.begin());

				   // in some rare cases it may happen that
				   // both thresholds are the same (e.g. if
				   // there are many cells with the same
				   // error indicator). That would mean that
				   // all cells will be flagged for
				   // refinement or coarsening, but some will
				   // be flagged for both, namely those for
				   // which the indicator equals the
				   // thresholds. This is forbidden, however.
				   //
				   // In some rare cases with very few cells
				   // we also could get integer round off
				   // errors and get problems with
				   // the top and bottom fractions.
				   //
				   // In these case we arbitrarily reduce the
				   // bottom threshold by one permille below
				   // the top threshold
				   //
				   // Finally, in some cases
				   // (especially involving symmetric
				   // solutions) there are many cells
				   // with the same error indicator
				   // values. if there are many with
				   // indicator equal to the top
				   // threshold, no refinement will
				   // take place below; to avoid this
				   // case, we also lower the top
				   // threshold if it equals the
				   // largest indicator and the
				   // top_fraction!=1
  if ((top_threshold == *max_element(criteria.begin(), criteria.end())) &&
      (top_fraction != 1))
    top_threshold *= 0.999;

  if (bottom_threshold>=top_threshold)
    bottom_threshold = 0.999*top_threshold;

				   // actually flag cells
  if (top_threshold < *max_element(criteria.begin(), criteria.end()))
    refine (tria, criteria, top_threshold);
  if (bottom_threshold > *min_element(criteria.begin(), criteria.end()))
    coarsen (tria, criteria, bottom_threshold);
};

// explicit instantiations
template void GridRefinement
::refine (Triangulation<deal_II_dimension> &, const Vector<float> &, const double);

template void GridRefinement
::refine (Triangulation<deal_II_dimension> &, const Vector<double> &, const double);

template void GridRefinement
::coarsen (Triangulation<deal_II_dimension> &, const Vector<float> &, const double);

template void GridRefinement
::coarsen (Triangulation<deal_II_dimension> &, const Vector<double> &, const double);

template void GridRefinement
::refine_and_coarsen_fixed_number (Triangulation<deal_II_dimension> &,
				   const Vector<double> &,
				   const double         top_fraction,
				   const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_number (Triangulation<deal_II_dimension> &,
				   const Vector<float> &criteria,
				   const double         top_fraction,
				   const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_fraction (Triangulation<deal_II_dimension> &,
				     const Vector<double> &criteria,
				     const double         top_fraction,
				     const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_fraction (Triangulation<deal_II_dimension> &,
				     const Vector<float> &criteria,
				     const double         top_fraction,
				     const double         bottom_fraction);

<commit_msg>Avoid error with undefined fabs with gcc2.97<commit_after>//----------------------------  grid_refinement.cc  ---------------------------
//    $Id$
//    Version: $Name$
//
//    Copyright (C) 1998, 1999, 2000 by the deal.II authors
//
//    This file is subject to QPL and may not be  distributed
//    without copyright and license information. Please refer
//    to the file deal.II/doc/license.html for the  text  and
//    further information on this license.
//
//----------------------------  grid_refinement.cc  ---------------------------

#include <lac/vector.h>
#include <grid/grid_refinement.h>
#include <grid/tria_accessor.h>
#include <grid/tria_iterator.h>
#include <grid/tria.h>

#include <numeric>
#include <algorithm>
#include <cmath>

template <int dim, typename number>
void GridRefinement::refine (Triangulation<dim>   &tria,
			     const Vector<number> &criteria,
			     const double         threshold)
{
  Assert (criteria.size() == tria.n_active_cells(),
	  ExcInvalidVectorSize(criteria.size(), tria.n_active_cells()));

				   // nothing to do; especially we
				   // do not want to flag with zero
				   // error since then we may get
				   // into conflict with coarsening
				   // in some cases
  if (threshold==0)
    return;

  Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
  const unsigned int n_cells = criteria.size();

  for (unsigned int index=0; index<n_cells; ++cell, ++index)
    if (fabs(criteria(index)) >= threshold)
      cell->set_refine_flag();
};

template <int dim, typename number>
void GridRefinement::coarsen (Triangulation<dim>   &tria,
			      const Vector<number> &criteria,
			      const double         threshold)
{
  Assert (criteria.size() == tria.n_active_cells(),
	  ExcInvalidVectorSize(criteria.size(), tria.n_active_cells()));

  Triangulation<dim>::active_cell_iterator cell = tria.begin_active();
  const unsigned int n_cells = criteria.size();

  for (unsigned int index=0; index<n_cells; ++cell, ++index)
    if (fabs(criteria(index)) <= threshold)
      cell->set_coarsen_flag();
};

template <int dim, typename number>
void
GridRefinement::refine_and_coarsen_fixed_number (Triangulation<dim>   &tria,
						 const Vector<number> &criteria,
						 const double         top_fraction,
						 const double         bottom_fraction)
{
				   // correct number of cells is
				   // checked in @p{refine}
  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());

  const int refine_cells=static_cast<int>(top_fraction*criteria.size());
  const int coarsen_cells=static_cast<int>(bottom_fraction*criteria.size());

  if (refine_cells || coarsen_cells)
    {
      Vector<number> tmp(criteria);
      if (refine_cells)
	{
	  nth_element (tmp.begin(), tmp.begin()+refine_cells,
		       tmp.end(),
		       greater<double>());
	  refine (tria, criteria, *(tmp.begin() + refine_cells));
	};

      if (coarsen_cells)
	{
	  nth_element (tmp.begin(), tmp.begin()+tmp.size()-coarsen_cells,
		       tmp.end(),
		       greater<double>());
	  coarsen (tria, criteria, *(tmp.begin() + tmp.size() - coarsen_cells));
	};
    };
};

template <int dim, typename number>
void
GridRefinement::refine_and_coarsen_fixed_fraction (Triangulation<dim>   &tria,
						   const Vector<number> &criteria,
						   const double         top_fraction,
						   const double         bottom_fraction)
{
				   // correct number of cells is
				   // checked in @p{refine}
  Assert ((top_fraction>=0) && (top_fraction<=1), ExcInvalidParameterValue());
  Assert ((bottom_fraction>=0) && (bottom_fraction<=1), ExcInvalidParameterValue());
  Assert (top_fraction+bottom_fraction <= 1, ExcInvalidParameterValue());

				   // let tmp be the cellwise square of the
				   // error, which is what we have to sum
				   // up and compare with
				   // @p{fraction_of_error*total_error}.
  Vector<number> tmp(criteria);
  const double total_error = tmp.l1_norm();

  Vector<number> partial_sums(criteria.size());

				   // sort the largest criteria to the
				   // beginning of the vector
  sort (tmp.begin(), tmp.end(), greater<double>());
  partial_sum (tmp.begin(), tmp.end(), partial_sums.begin());

				   // compute thresholds
  const typename Vector<number>::const_iterator
    q = lower_bound (partial_sums.begin(), partial_sums.end(),
		     top_fraction*total_error),
    p = upper_bound (partial_sums.begin(), partial_sums.end(),
		     total_error*(1-bottom_fraction));

  double bottom_threshold = tmp(p != partial_sums.end() ?
				p-partial_sums.begin() :
				criteria.size()-1),
	 top_threshold    = tmp(q-partial_sums.begin());

				   // in some rare cases it may happen that
				   // both thresholds are the same (e.g. if
				   // there are many cells with the same
				   // error indicator). That would mean that
				   // all cells will be flagged for
				   // refinement or coarsening, but some will
				   // be flagged for both, namely those for
				   // which the indicator equals the
				   // thresholds. This is forbidden, however.
				   //
				   // In some rare cases with very few cells
				   // we also could get integer round off
				   // errors and get problems with
				   // the top and bottom fractions.
				   //
				   // In these case we arbitrarily reduce the
				   // bottom threshold by one permille below
				   // the top threshold
				   //
				   // Finally, in some cases
				   // (especially involving symmetric
				   // solutions) there are many cells
				   // with the same error indicator
				   // values. if there are many with
				   // indicator equal to the top
				   // threshold, no refinement will
				   // take place below; to avoid this
				   // case, we also lower the top
				   // threshold if it equals the
				   // largest indicator and the
				   // top_fraction!=1
  if ((top_threshold == *max_element(criteria.begin(), criteria.end())) &&
      (top_fraction != 1))
    top_threshold *= 0.999;

  if (bottom_threshold>=top_threshold)
    bottom_threshold = 0.999*top_threshold;

				   // actually flag cells
  if (top_threshold < *max_element(criteria.begin(), criteria.end()))
    refine (tria, criteria, top_threshold);
  if (bottom_threshold > *min_element(criteria.begin(), criteria.end()))
    coarsen (tria, criteria, bottom_threshold);
};

// explicit instantiations
template void GridRefinement
::refine (Triangulation<deal_II_dimension> &, const Vector<float> &, const double);

template void GridRefinement
::refine (Triangulation<deal_II_dimension> &, const Vector<double> &, const double);

template void GridRefinement
::coarsen (Triangulation<deal_II_dimension> &, const Vector<float> &, const double);

template void GridRefinement
::coarsen (Triangulation<deal_II_dimension> &, const Vector<double> &, const double);

template void GridRefinement
::refine_and_coarsen_fixed_number (Triangulation<deal_II_dimension> &,
				   const Vector<double> &,
				   const double         top_fraction,
				   const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_number (Triangulation<deal_II_dimension> &,
				   const Vector<float> &criteria,
				   const double         top_fraction,
				   const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_fraction (Triangulation<deal_II_dimension> &,
				     const Vector<double> &criteria,
				     const double         top_fraction,
				     const double         bottom_fraction);

template void GridRefinement
::refine_and_coarsen_fixed_fraction (Triangulation<deal_II_dimension> &,
				     const Vector<float> &criteria,
				     const double         top_fraction,
				     const double         bottom_fraction);

<|endoftext|>


<commit_before><commit_msg>608 - Counterfeit Dollar<commit_after><|endoftext|>


<commit_before><commit_msg>faster printing for witness and report + simplified analyze<commit_after><|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "passthroughfs.hpp"

#if defined(OX_HAS_PASSTHROUGHFS)

#include <fstream>

namespace ox {

PassThroughFS::PassThroughFS(const char *dirPath) {
	m_path = dirPath;
}

PassThroughFS::~PassThroughFS() {
}

std::string PassThroughFS::basePath() {
	return m_path.string();
}

Error PassThroughFS::mkdir(const char *path, bool recursive) {
	bool success = false;
	const auto p = m_path / stripSlash(path);
	const auto u8p = p.u8string();
	oxTrace("ox::fs::PassThroughFS::mkdir") << u8p.c_str();
	if (recursive) {
		success = std::filesystem::create_directories(p);
	} else {
		success = std::filesystem::create_directory(p);
	}
	return OxError(success ? 0 : 1);
}

Error PassThroughFS::move(const char *src, const char *dest) {
	std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest));
	return OxError(0);
}

Error PassThroughFS::read(const char *path, void *buffer, std::size_t buffSize) {
	try {
		std::ifstream file((m_path / stripSlash(path)), std::ios::binary | std::ios::ate);
		const std::size_t size = file.tellg();
		file.seekg(0, std::ios::beg);
		if (size > buffSize) {
			oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed: Buffer too small:" << path;
			return OxError(1);
		}
		file.read(static_cast<char*>(buffer), buffSize);
	} catch (const std::fstream::failure&) {
		oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed:" << path;
		throw OxError(2);
	}
	return OxError(0);
}

ValErr<uint8_t*> PassThroughFS::read(const char*) {
	return OxError(1);
}

Error PassThroughFS::read(uint64_t, void*, std::size_t) {
	// unsupported
	return OxError(1);
}

Error PassThroughFS::read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) {
	// unsupported
	return OxError(1);
}

ValErr<uint8_t*> PassThroughFS::read(uint64_t) {
	return OxError(1);
}

Error PassThroughFS::remove(const char *path, bool recursive) {
	if (recursive) {
		return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
	} else {
		return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0);
	}
}

ox::Error PassThroughFS::resize(uint64_t, void*) {
	// unsupported
	return OxError(1);
}

Error PassThroughFS::write(const char *path, void *buffer, uint64_t size, uint8_t) {
	auto p = (m_path / stripSlash(path));
	try {
		std::ofstream f(p, std::ios::binary);
		f.write(static_cast<char*>(buffer), size);
	} catch (const std::fstream::failure&) {
		oxTrace("ox::fs::PassThroughFS::write::error") << "Write failed:" << path;
		throw OxError(1);
	}
	return OxError(0);
}

Error PassThroughFS::write(uint64_t, void*, uint64_t, uint8_t) {
	// unsupported
	return OxError(1);
}

ValErr<FileStat> PassThroughFS::stat(uint64_t) {
	// unsupported
	return {{}, OxError(1)};
}

ValErr<FileStat> PassThroughFS::stat(const char *path) {
	std::error_code ec;
	const auto p = m_path / stripSlash(path);
	uint8_t type = std::filesystem::is_directory(p, ec) ?
		FileType_Directory : FileType_NormalFile;
	oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
	uint64_t size = type == FileType_Directory ? 0 : std::filesystem::file_size(p, ec);
	oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
	oxTrace("PassThroughFS::stat::size") << path << size;
	return {{0, 0, size, type}, OxError(ec.value())};
}

uint64_t PassThroughFS::spaceNeeded(uint64_t size) {
	return size;
}

uint64_t PassThroughFS::available() {
	std::error_code ec;
	auto s = std::filesystem::space(m_path, ec);
	return s.available;
}

uint64_t PassThroughFS::size() const {
	std::error_code ec;
	auto s = std::filesystem::space(m_path, ec);
	return s.capacity;
}

char *PassThroughFS::buff() {
	return nullptr;
}

Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) {
	return OxError(1);
}

bool PassThroughFS::valid() const {
	return std::filesystem::is_directory(m_path);
}

const char *PassThroughFS::stripSlash(const char *path) {
	auto pathLen = ox_strlen(path);
	for (decltype(pathLen) i = 0; i < pathLen && path[0] == '/'; i++) {
		path++;
	}
	return path;
}

}

#endif
<commit_msg>[ox/fs] Make PassthroughFS mkdir pass mkdir -p on existing directory<commit_after>/*
 * Copyright 2015 - 2018 gtalent2@gmail.com
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "passthroughfs.hpp"
#include <filesystem>

#if defined(OX_HAS_PASSTHROUGHFS)

#include <fstream>

namespace ox {

PassThroughFS::PassThroughFS(const char *dirPath) {
	m_path = dirPath;
}

PassThroughFS::~PassThroughFS() {
}

std::string PassThroughFS::basePath() {
	return m_path.string();
}

Error PassThroughFS::mkdir(const char *path, bool recursive) {
	bool success = false;
	const auto p = m_path / stripSlash(path);
	const auto u8p = p.u8string();
	oxTrace("ox::fs::PassThroughFS::mkdir") << u8p.c_str();
	if (recursive) {
		if (std::filesystem::is_directory(p)) {
			success = true;
		} else {
			success = std::filesystem::create_directories(p);
		}
	} else {
		success = std::filesystem::create_directory(p);
	}
	return OxError(success ? 0 : 1);
}

Error PassThroughFS::move(const char *src, const char *dest) {
	std::filesystem::rename(m_path / stripSlash(src), m_path / stripSlash(dest));
	return OxError(0);
}

Error PassThroughFS::read(const char *path, void *buffer, std::size_t buffSize) {
	try {
		std::ifstream file((m_path / stripSlash(path)), std::ios::binary | std::ios::ate);
		const std::size_t size = file.tellg();
		file.seekg(0, std::ios::beg);
		if (size > buffSize) {
			oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed: Buffer too small:" << path;
			return OxError(1);
		}
		file.read(static_cast<char*>(buffer), buffSize);
	} catch (const std::fstream::failure&) {
		oxTrace("ox::fs::PassThroughFS::read::error") << "Read failed:" << path;
		throw OxError(2);
	}
	return OxError(0);
}

ValErr<uint8_t*> PassThroughFS::read(const char*) {
	return OxError(1);
}

Error PassThroughFS::read(uint64_t, void*, std::size_t) {
	// unsupported
	return OxError(1);
}

Error PassThroughFS::read(uint64_t, std::size_t, std::size_t, void*, std::size_t*) {
	// unsupported
	return OxError(1);
}

ValErr<uint8_t*> PassThroughFS::read(uint64_t) {
	return OxError(1);
}

Error PassThroughFS::remove(const char *path, bool recursive) {
	if (recursive) {
		return OxError(std::filesystem::remove_all(m_path / stripSlash(path)) != 0);
	} else {
		return OxError(std::filesystem::remove(m_path / stripSlash(path)) != 0);
	}
}

ox::Error PassThroughFS::resize(uint64_t, void*) {
	// unsupported
	return OxError(1);
}

Error PassThroughFS::write(const char *path, void *buffer, uint64_t size, uint8_t) {
	auto p = (m_path / stripSlash(path));
	try {
		std::ofstream f(p, std::ios::binary);
		f.write(static_cast<char*>(buffer), size);
	} catch (const std::fstream::failure&) {
		oxTrace("ox::fs::PassThroughFS::write::error") << "Write failed:" << path;
		throw OxError(1);
	}
	return OxError(0);
}

Error PassThroughFS::write(uint64_t, void*, uint64_t, uint8_t) {
	// unsupported
	return OxError(1);
}

ValErr<FileStat> PassThroughFS::stat(uint64_t) {
	// unsupported
	return {{}, OxError(1)};
}

ValErr<FileStat> PassThroughFS::stat(const char *path) {
	std::error_code ec;
	const auto p = m_path / stripSlash(path);
	uint8_t type = std::filesystem::is_directory(p, ec) ?
		FileType_Directory : FileType_NormalFile;
	oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
	uint64_t size = type == FileType_Directory ? 0 : std::filesystem::file_size(p, ec);
	oxTrace("PassThroughFS::stat") << ec.message().c_str() << path;
	oxTrace("PassThroughFS::stat::size") << path << size;
	return {{0, 0, size, type}, OxError(ec.value())};
}

uint64_t PassThroughFS::spaceNeeded(uint64_t size) {
	return size;
}

uint64_t PassThroughFS::available() {
	std::error_code ec;
	auto s = std::filesystem::space(m_path, ec);
	return s.available;
}

uint64_t PassThroughFS::size() const {
	std::error_code ec;
	auto s = std::filesystem::space(m_path, ec);
	return s.capacity;
}

char *PassThroughFS::buff() {
	return nullptr;
}

Error PassThroughFS::walk(Error(*)(uint8_t, uint64_t, uint64_t)) {
	return OxError(1);
}

bool PassThroughFS::valid() const {
	return std::filesystem::is_directory(m_path);
}

const char *PassThroughFS::stripSlash(const char *path) {
	auto pathLen = ox_strlen(path);
	for (decltype(pathLen) i = 0; i < pathLen && path[0] == '/'; i++) {
		path++;
	}
	return path;
}

}

#endif
<|endoftext|>


<commit_before>#include "AppConfig.hpp"

#include "common/PlayerRuntimeError.hpp"
#include "common/fs/FileSystem.hpp"
#include "common/logger/Logging.hpp"

#if !defined(SNAP_ENABLED)
#include "GitHash.hpp"
#endif

#include <filesystem>
#include <linux/limits.h>
#include <unistd.h>

FilePath AppConfig::resourceDirectory_;

std::string AppConfig::version()
{
    return releaseVersion() + "-" + codeVersion();
}

std::string AppConfig::releaseVersion()
{
#if defined(SNAP_ENABLED)
    return getenv("SNAP_VERSION");
#else
    // Update this with each release.
    return std::string{"1.8 R"} + codeVersion() + GIT_HASH;
#endif
}

std::string AppConfig::codeVersion()
{
#if defined(SNAP_ENABLED)
    return getenv("SNAP_REVISION");
#else
    // Update this with each release
    return "6";
#endif
}

FilePath AppConfig::resourceDirectory()
{
    return resourceDirectory_;
}

void AppConfig::resourceDirectory(const FilePath& directory)
{
    if (!FileSystem::exists(directory))
        throw PlayerRuntimeError{
            "AppConfig", "Resource directory doesn't exist. Create or use exsiting one in the player options app."};

    resourceDirectory_ = directory;
}

FilePath AppConfig::configDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP_USER_COMMON")};
#else
    return execDirectory();
#endif
}

FilePath AppConfig::publicKeyPath()
{
    return configDirectory() / "id_rsa.pub";
}

FilePath AppConfig::privateKeyPath()
{
    return configDirectory() / "id_rsa";
}

FilePath AppConfig::cmsSettingsPath()
{
    return configDirectory() / "cmsSettings.xml";
}

FilePath AppConfig::playerSettingsPath()
{
    return configDirectory() / "playerSettings.xml";
}

FilePath AppConfig::schedulePath()
{
    return configDirectory() / "schedule.xml";
}

FilePath AppConfig::cachePath()
{
    return configDirectory() / "cacheFile.xml";
}

FilePath AppConfig::statsCache()
{
    return configDirectory() / "stats.sqlite";
}

FilePath AppConfig::additionalResourcesDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP")} / "share" / "xibo-player";
#else
    return execDirectory();
#endif
}

FilePath AppConfig::splashScreenPath()
{
    return additionalResourcesDirectory() / "splash.jpg";
}

FilePath AppConfig::uiFile()
{
    return additionalResourcesDirectory() / "ui.glade";
}

FilePath AppConfig::execDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP")} / "bin";
#else
    // workaround for those who starts the player out of snap
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    assert(count != -1);
    return FilePath{std::filesystem::path(std::string(result, static_cast<size_t>(count))).parent_path()};
#endif
}

std::string AppConfig::playerBinary()
{
    return (execDirectory() / "xibo-player").string();
}

std::string AppConfig::optionsBinary()
{
    return (execDirectory() / "xibo-options").string();
}
<commit_msg>Fix #243 when running a manual snap<commit_after>#include "AppConfig.hpp"

#include <boost/algorithm/string/predicate.hpp>

#include "common/PlayerRuntimeError.hpp"
#include "common/fs/FileSystem.hpp"
#include "common/logger/Logging.hpp"

#if !defined(SNAP_ENABLED)
#include "GitHash.hpp"
#endif

#include <filesystem>
#include <linux/limits.h>
#include <unistd.h>

FilePath AppConfig::resourceDirectory_;

std::string AppConfig::version()
{
    return releaseVersion() + "-" + codeVersion();
}

std::string AppConfig::releaseVersion()
{
#if defined(SNAP_ENABLED)
    return getenv("SNAP_VERSION");
#else
    // Update this with each release.
    return std::string{"1.8 R"} + codeVersion() + GIT_HASH;
#endif
}

std::string AppConfig::codeVersion()
{
#if defined(SNAP_ENABLED)
    if (boost::starts_with(getenv("SNAP_REVISION"), "x")) {
        return "6";
    }
    return getenv("SNAP_REVISION");
#else
    // Update this with each release
    return "6";
#endif
}

FilePath AppConfig::resourceDirectory()
{
    return resourceDirectory_;
}

void AppConfig::resourceDirectory(const FilePath& directory)
{
    if (!FileSystem::exists(directory))
        throw PlayerRuntimeError{
            "AppConfig", "Resource directory doesn't exist. Create or use exsiting one in the player options app."};

    resourceDirectory_ = directory;
}

FilePath AppConfig::configDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP_USER_COMMON")};
#else
    return execDirectory();
#endif
}

FilePath AppConfig::publicKeyPath()
{
    return configDirectory() / "id_rsa.pub";
}

FilePath AppConfig::privateKeyPath()
{
    return configDirectory() / "id_rsa";
}

FilePath AppConfig::cmsSettingsPath()
{
    return configDirectory() / "cmsSettings.xml";
}

FilePath AppConfig::playerSettingsPath()
{
    return configDirectory() / "playerSettings.xml";
}

FilePath AppConfig::schedulePath()
{
    return configDirectory() / "schedule.xml";
}

FilePath AppConfig::cachePath()
{
    return configDirectory() / "cacheFile.xml";
}

FilePath AppConfig::statsCache()
{
    return configDirectory() / "stats.sqlite";
}

FilePath AppConfig::additionalResourcesDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP")} / "share" / "xibo-player";
#else
    return execDirectory();
#endif
}

FilePath AppConfig::splashScreenPath()
{
    return additionalResourcesDirectory() / "splash.jpg";
}

FilePath AppConfig::uiFile()
{
    return additionalResourcesDirectory() / "ui.glade";
}

FilePath AppConfig::execDirectory()
{
#if defined(SNAP_ENABLED)
    return FilePath{getenv("SNAP")} / "bin";
#else
    // workaround for those who starts the player out of snap
    char result[PATH_MAX];
    ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
    assert(count != -1);
    return FilePath{std::filesystem::path(std::string(result, static_cast<size_t>(count))).parent_path()};
#endif
}

std::string AppConfig::playerBinary()
{
    return (execDirectory() / "xibo-player").string();
}

std::string AppConfig::optionsBinary()
{
    return (execDirectory() / "xibo-options").string();
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: cexports.cxx,v $
 * $Revision: 1.8 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_desktop.hxx"

#include "cppuhelper/implementationentry.hxx"
#include "jvmfwk.hxx"
#include "basicmigration.hxx"
#include "autocorrmigration.hxx"

extern "C"
{

::cppu::ImplementationEntry entries [] =
{
    {
        migration::jvmfwk_create, migration::jvmfwk_getImplementationName,
        migration::jvmfwk_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    {
        migration::BasicMigration_create, migration::BasicMigration_getImplementationName,
        migration::BasicMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    {
        migration::AutocorrectionMigration_create, migration::AutocorrectionMigration_getImplementationName,
        migration::AutocorrectionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
        pServiceManager, pRegistryKey, entries );
}

void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey, entries );
}

}
<commit_msg>INTEGRATION: CWS userdatamigration (1.8.90); FILE MERGED 2008/07/08 06:58:01 mba 1.8.90.1: #i88426#: migration of extensions and wordbooks<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: cexports.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_desktop.hxx"

#include "cppuhelper/implementationentry.hxx"
#include "basicmigration.hxx"
#include "wordbookmigration.hxx"
#include "extensionmigration.hxx"

extern "C"
{

::cppu::ImplementationEntry entries [] =
{
    {
        migration::BasicMigration_create, migration::BasicMigration_getImplementationName,
        migration::BasicMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    {
        migration::WordbookMigration_create, migration::WordbookMigration_getImplementationName,
        migration::WordbookMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    {
        migration::ExtensionMigration_create, migration::ExtensionMigration_getImplementationName,
        migration::ExtensionMigration_getSupportedServiceNames, ::cppu::createSingleComponentFactory,
        0, 0
    },
    { 0, 0, 0, 0, 0, 0 }
};

void SAL_CALL component_getImplementationEnvironment(
    const sal_Char ** ppEnvTypeName, uno_Environment ** )
{
    *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
}

sal_Bool SAL_CALL component_writeInfo(
    void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_writeInfoHelper(
        pServiceManager, pRegistryKey, entries );
}

void * SAL_CALL component_getFactory(
    const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
{
    return ::cppu::component_getFactoryHelper(
        pImplName, pServiceManager, pRegistryKey, entries );
}

}
<|endoftext|>


<commit_before>/*
 * Handle cookies sent by the HTTP client.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_COOKIE_SERVER_HXX
#define BENG_PROXY_COOKIE_SERVER_HXX

struct pool;
struct strmap;

#ifdef __cplusplus
extern "C" {
#endif

/**
 * Parse a Cookie request header and store all cookies in the
 * specified strmap.
 */
void
cookie_map_parse(struct strmap *cookies, const char *p, struct pool *pool);

#ifdef __cplusplus
}
#endif

#endif
<commit_msg>cookie_server: remove C++ check<commit_after>/*
 * Handle cookies sent by the HTTP client.
 *
 * author: Max Kellermann <mk@cm4all.com>
 */

#ifndef BENG_PROXY_COOKIE_SERVER_HXX
#define BENG_PROXY_COOKIE_SERVER_HXX

struct pool;
struct strmap;

/**
 * Parse a Cookie request header and store all cookies in the
 * specified strmap.
 */
void
cookie_map_parse(struct strmap *cookies, const char *p, struct pool *pool);

#endif
<|endoftext|>


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

   Copyright (C) 2012, Oak Ridge National Laboratory

   This product includes software produced by UT-Battelle, LLC under Contract No.
   DE-AC05-00OR22725 with the Department of Energy.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the New BSD 3-clause software license (LICENSE).

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   LICENSE for more details.

   For more information please contact the INDDGO developers at:
   inddgo-info@googlegroups.com

 */

#include "GraphWriter.h"
#include "Util.h"

using namespace std;

namespace Graph {
    GraphWriter::GraphWriter(){
        this->shuffle = false;
        this->shuffle_seed = 42;
    }

    GraphWriter::~GraphWriter(){
    }

    /**
     * \param[in] shuf bool, shuffle graphs out from this GraphWriter
     */
    void GraphWriter::set_shuffle(bool shuf){
        this->shuffle = shuf;
    }

    /**
     * \param[in] shuf bool, shuffle graphs out from this GraphWriter
     */
    void GraphWriter::set_shuffle_seed(int seed){
        this->shuffle_seed = seed;
    }

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     * \param[in] type format of the file to write
     * \param[in] write_vertex_weights whether to write vertex weights to the output file
     */
    int GraphWriter::write_graph(Graph *g, const string filename, const string type, bool write_vertex_weights, bool shuffle){
        string t = str_to_up(type);
        if("ADJMATRIX" == t){
            write_adjmatrix(g, filename);
        }
        else if("DIMACS" == t){
            write_dimacs(g, filename, write_vertex_weights);
        }
        else if("METIS" == t){
            write_metis(g, filename);
        }
        else if("GRAPHVIZ" == t){
            write_graphviz(g, filename);
        }
        else if("ADJLIST" == t){
            write_adjlist(g, filename);
        }
        else {
            cerr << "unknown type: " << type << endl;
        }
        return 0;
    } // write_graph

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_adjmatrix(Graph *g, const string filename){
        FILE *fout = fopen(filename.c_str(), "w");
        if(!fout){
            fatal_error("can not open %s for write", filename.c_str());
        }

        int n = g->get_num_nodes();
        int i = 0;
        int j = 0;
        int val = 0;

        fprintf(fout, "%d \n", n);

        for(i = 0; i < n; i++){
            for(j = 0; j <  n; j++){
                val = 0;
                if(g->is_edge(i, j)){
                    val = 1;
                }
                fprintf(fout, "%d ", val);
            }
            fprintf(fout, "\n");
        }

        fclose(fout);

        return 0;
    } // write_adjmatrix

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_adjlist(Graph *g, const string filename){
        FILE *fout = fopen(filename.c_str(), "w");
        if(!fout){
            fatal_error("can not open %s for write", filename.c_str());
        }

        int n = g->get_num_nodes();
        int i = 0;
        int j = 0;
        int val = 0;

        for(i = 0; i < n; i++){
            const list<int> &nbrs = g->get_node(i)->get_nbrs_ref();
            fprintf(fout, "%d", i);
            for(list<int>::const_iterator it = nbrs.begin(); it != nbrs.end(); ++it){
                if(*it > i){
                    fprintf(fout, " %d", *it);
                }
                else if(*it == i){
                    fprintf(stderr, "Found self loop on node %d\n", i);
                }
            }
            fprintf(fout, "\n");
        }

        fclose(fout);

        return 0;
    } // write_adjmatrix

    /**
     * Expects to output to a 1-based METIS file
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     * \param[in] write_vertex_weights whether to write vertex weights to the output file
     * \return 0 on success, nonzero on failure
     */
    int GraphWriter::write_metis(Graph *g, const string filename){
        int capacity = g->get_capacity();
        int num_nodes = g->get_num_nodes();
        int num_edges = g->get_num_edges();
        // FIXME: there should be a better way than copying our entire node vector here
        vector<Node> nodes = g->get_nodes();

        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error("%s:  Couldn't open %s for writing\n", __FUNCTION__,
                        filename.c_str());
        }

        if(capacity != num_nodes){
            fprintf(stderr, "%s:  Warning! Metis file may have holes.\n",
                    __FUNCTION__);
            // Print a comment warning in the file
            fprintf(
                out,
                "c Warning: capacity=%d, num_nodes=%d. Resulting graph may have holes\n",
                capacity, num_nodes);
        }

        fprintf(out, "%d %d\n", num_nodes, num_edges);
        list<int>::iterator ii;
        list<int> *nbrs;
        for(int i = 0; i < num_nodes; i++){
            nbrs = nodes[i].get_nbrs_ptr();
            for(ii = nbrs->begin(); ii != nbrs->end(); ++ii){
                fprintf(out, "%d ", (*ii) + 1);
            }
            fprintf(out, "\n");
        }

        fflush(out);
        fclose(out);
        return 0;
    } // write_metis

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_dimacs(Graph *g, const string filename, bool write_vertex_weights){
        //FIXME: figure out if this is actually necessary
        vector<int> perm;
        int capacity = g->get_capacity();
        int num_nodes = g->get_num_nodes();
        int num_edges = g->get_num_edges();
        //vector<Node> nodes = g->get_nodes();
        Node *n;

        for(int i = 0; i < capacity; i++){
            perm.push_back(i);
        }

        if(this->shuffle){
            int s = this->shuffle_seed % 97;
            for(int i = 0; i < s; i++){
                random_shuffle(perm.begin(), perm.end());
            }
        }

        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error("%s:  Couldn't open %s for writing\n", __FUNCTION__,
                        filename.c_str());
        }

        // Print out a comment line
        //fprintf(out,"c Graph has %d connected components\n",g->num_connected_components);

        // Will write out non-canonical - note that we may have "holes" in the numbering
        // Print a warning to stderr and the file in this case
        if(capacity != num_nodes){
            fprintf(stderr, "%s:  Warning! DIMACS file may have holes.\n",
                    __FUNCTION__);
            // Print a comment warning in the file
            fprintf(
                out,
                "c Warning: capacity=%d, num_nodes=%d. Resulting graph may have holes\n",
                capacity, num_nodes);
        }

        //EDITED TO PRINT p edge instead of p e for compatibility with Koster.
        fprintf(out, "p edge %d %d\n", num_nodes, num_edges);
        // Write edges out using the label field from the nodes
        // Only write out edges u-v with u<=v - so file is at least simple
        list<int>::iterator ii;
        int edges_written = 0;
        list<int> nbrs;
        for(int i = 0; i < num_nodes; i++){
            // CSG- could add sort here although that won't work for the randomized labels
            // g->nodes[perm[i]].nbrs.sort();
            nbrs = g->get_node(i)->get_nbrs();
            for(ii = nbrs.begin(); ii != nbrs.end(); ++ii){
                //if(i<=*ii)
                // CSG - we want the edges in the file to be u-v with u<=v
                if(g->get_node(perm[i])->get_label() <= g->get_node(perm[*ii])->get_label()){
                    // Changing june 21 for testing - not using labels
                    //if(i<=*ii)
                    edges_written++;
                    fprintf(out, "e %d %d\n", g->get_node(perm[i])->get_label(),
                            g->get_node(perm[*ii])->get_label());
                    //,i+1,*ii+1);//
                }
            }
        }
        if(edges_written != num_edges){
            fatal_error("%s:  Didn't write the correct number of edges! (%d!=%d)\n",
                        __FUNCTION__, edges_written, num_edges);
        }

        fflush(out);
        fclose(out);

        return 0;
    } // write_dimacs

    int GraphWriter::write_graphviz(Graph *g, const string filename){
        int i, j;
        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error( "%s:  Error opening file %s for writing graphviz output\n", __FUNCTION__, filename.c_str());
        }

        fprintf(out, "Graph G{\n");
        fprintf(out, "overlap=false;\n");
        list<int>::iterator it;
        //FIXME: really shouldn't be copying our vector around
        vector<Node> nodes = g->get_nodes();
        list<int> nbrs;

        for(i = 0; i < g->get_num_nodes(); i++){
            nbrs = nodes[i].get_nbrs();
            it = nbrs.begin();
            while(it != nbrs.end()){
                j = *it;
                if(i < j){
                    // Make this 1-based in true DIMACS spirit
                    fprintf(out, "%d -- %d;\n", i + 1, j + 1);
                }
                ++it;
            }
        }
        fprintf(out, "}\n");
        fflush(out);
        fclose(out);

        return(0);
    } // write_graphviz
}
<commit_msg>For now, don't have the adjacencly list writer check for self-loops<commit_after>/*
   This file is part of INDDGO.

   Copyright (C) 2012, Oak Ridge National Laboratory

   This product includes software produced by UT-Battelle, LLC under Contract No.
   DE-AC05-00OR22725 with the Department of Energy.

   This program is free software; you can redistribute it and/or modify
   it under the terms of the New BSD 3-clause software license (LICENSE).

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   LICENSE for more details.

   For more information please contact the INDDGO developers at:
   inddgo-info@googlegroups.com

 */

#include "GraphWriter.h"
#include "Util.h"

using namespace std;

namespace Graph {
    GraphWriter::GraphWriter(){
        this->shuffle = false;
        this->shuffle_seed = 42;
    }

    GraphWriter::~GraphWriter(){
    }

    /**
     * \param[in] shuf bool, shuffle graphs out from this GraphWriter
     */
    void GraphWriter::set_shuffle(bool shuf){
        this->shuffle = shuf;
    }

    /**
     * \param[in] shuf bool, shuffle graphs out from this GraphWriter
     */
    void GraphWriter::set_shuffle_seed(int seed){
        this->shuffle_seed = seed;
    }

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     * \param[in] type format of the file to write
     * \param[in] write_vertex_weights whether to write vertex weights to the output file
     */
    int GraphWriter::write_graph(Graph *g, const string filename, const string type, bool write_vertex_weights, bool shuffle){
        string t = str_to_up(type);
        if("ADJMATRIX" == t){
            write_adjmatrix(g, filename);
        }
        else if("DIMACS" == t){
            write_dimacs(g, filename, write_vertex_weights);
        }
        else if("METIS" == t){
            write_metis(g, filename);
        }
        else if("GRAPHVIZ" == t){
            write_graphviz(g, filename);
        }
        else if("ADJLIST" == t){
            write_adjlist(g, filename);
        }
        else {
            cerr << "unknown type: " << type << endl;
        }
        return 0;
    } // write_graph

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_adjmatrix(Graph *g, const string filename){
        FILE *fout = fopen(filename.c_str(), "w");
        if(!fout){
            fatal_error("can not open %s for write", filename.c_str());
        }

        int n = g->get_num_nodes();
        int i = 0;
        int j = 0;
        int val = 0;

        fprintf(fout, "%d \n", n);

        for(i = 0; i < n; i++){
            for(j = 0; j <  n; j++){
                val = 0;
                if(g->is_edge(i, j)){
                    val = 1;
                }
                fprintf(fout, "%d ", val);
            }
            fprintf(fout, "\n");
        }

        fclose(fout);

        return 0;
    } // write_adjmatrix

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_adjlist(Graph *g, const string filename){
        FILE *fout = fopen(filename.c_str(), "w");
        if(!fout){
            fatal_error("can not open %s for write", filename.c_str());
        }

        int n = g->get_num_nodes();
        int i = 0;
        int j = 0;
        int val = 0;

        for(i = 0; i < n; i++){
            const list<int> &nbrs = g->get_node(i)->get_nbrs_ref();
            fprintf(fout, "%d", i);
            for(list<int>::const_iterator it = nbrs.begin(); it != nbrs.end(); ++it){
                fprintf(fout, " %d", *it);
            }
            fprintf(fout, "\n");
        }

        fclose(fout);

        return 0;
    } // write_adjmatrix

    /**
     * Expects to output to a 1-based METIS file
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     * \param[in] write_vertex_weights whether to write vertex weights to the output file
     * \return 0 on success, nonzero on failure
     */
    int GraphWriter::write_metis(Graph *g, const string filename){
        int capacity = g->get_capacity();
        int num_nodes = g->get_num_nodes();
        int num_edges = g->get_num_edges();
        // FIXME: there should be a better way than copying our entire node vector here
        vector<Node> nodes = g->get_nodes();

        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error("%s:  Couldn't open %s for writing\n", __FUNCTION__,
                        filename.c_str());
        }

        if(capacity != num_nodes){
            fprintf(stderr, "%s:  Warning! Metis file may have holes.\n",
                    __FUNCTION__);
            // Print a comment warning in the file
            fprintf(
                out,
                "c Warning: capacity=%d, num_nodes=%d. Resulting graph may have holes\n",
                capacity, num_nodes);
        }

        fprintf(out, "%d %d\n", num_nodes, num_edges);
        list<int>::iterator ii;
        list<int> *nbrs;
        for(int i = 0; i < num_nodes; i++){
            nbrs = nodes[i].get_nbrs_ptr();
            for(ii = nbrs->begin(); ii != nbrs->end(); ++ii){
                fprintf(out, "%d ", (*ii) + 1);
            }
            fprintf(out, "\n");
        }

        fflush(out);
        fclose(out);
        return 0;
    } // write_metis

    /**
     * \return 0 on success, nonzero on failure
     * \param[in] g Pointer to the graph to be written
     * \param[in] filename full path of the file to be written to
     */
    int GraphWriter::write_dimacs(Graph *g, const string filename, bool write_vertex_weights){
        //FIXME: figure out if this is actually necessary
        vector<int> perm;
        int capacity = g->get_capacity();
        int num_nodes = g->get_num_nodes();
        int num_edges = g->get_num_edges();
        //vector<Node> nodes = g->get_nodes();
        Node *n;

        for(int i = 0; i < capacity; i++){
            perm.push_back(i);
        }

        if(this->shuffle){
            int s = this->shuffle_seed % 97;
            for(int i = 0; i < s; i++){
                random_shuffle(perm.begin(), perm.end());
            }
        }

        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error("%s:  Couldn't open %s for writing\n", __FUNCTION__,
                        filename.c_str());
        }

        // Print out a comment line
        //fprintf(out,"c Graph has %d connected components\n",g->num_connected_components);

        // Will write out non-canonical - note that we may have "holes" in the numbering
        // Print a warning to stderr and the file in this case
        if(capacity != num_nodes){
            fprintf(stderr, "%s:  Warning! DIMACS file may have holes.\n",
                    __FUNCTION__);
            // Print a comment warning in the file
            fprintf(
                out,
                "c Warning: capacity=%d, num_nodes=%d. Resulting graph may have holes\n",
                capacity, num_nodes);
        }

        //EDITED TO PRINT p edge instead of p e for compatibility with Koster.
        fprintf(out, "p edge %d %d\n", num_nodes, num_edges);
        // Write edges out using the label field from the nodes
        // Only write out edges u-v with u<=v - so file is at least simple
        list<int>::iterator ii;
        int edges_written = 0;
        list<int> nbrs;
        for(int i = 0; i < num_nodes; i++){
            // CSG- could add sort here although that won't work for the randomized labels
            // g->nodes[perm[i]].nbrs.sort();
            nbrs = g->get_node(i)->get_nbrs();
            for(ii = nbrs.begin(); ii != nbrs.end(); ++ii){
                //if(i<=*ii)
                // CSG - we want the edges in the file to be u-v with u<=v
                if(g->get_node(perm[i])->get_label() <= g->get_node(perm[*ii])->get_label()){
                    // Changing june 21 for testing - not using labels
                    //if(i<=*ii)
                    edges_written++;
                    fprintf(out, "e %d %d\n", g->get_node(perm[i])->get_label(),
                            g->get_node(perm[*ii])->get_label());
                    //,i+1,*ii+1);//
                }
            }
        }
        if(edges_written != num_edges){
            fatal_error("%s:  Didn't write the correct number of edges! (%d!=%d)\n",
                        __FUNCTION__, edges_written, num_edges);
        }

        fflush(out);
        fclose(out);

        return 0;
    } // write_dimacs

    int GraphWriter::write_graphviz(Graph *g, const string filename){
        int i, j;
        FILE *out;
        if((out = fopen(filename.c_str(), "w")) == NULL){
            fatal_error( "%s:  Error opening file %s for writing graphviz output\n", __FUNCTION__, filename.c_str());
        }

        fprintf(out, "Graph G{\n");
        fprintf(out, "overlap=false;\n");
        list<int>::iterator it;
        //FIXME: really shouldn't be copying our vector around
        vector<Node> nodes = g->get_nodes();
        list<int> nbrs;

        for(i = 0; i < g->get_num_nodes(); i++){
            nbrs = nodes[i].get_nbrs();
            it = nbrs.begin();
            while(it != nbrs.end()){
                j = *it;
                if(i < j){
                    // Make this 1-based in true DIMACS spirit
                    fprintf(out, "%d -- %d;\n", i + 1, j + 1);
                }
                ++it;
            }
        }
        fprintf(out, "}\n");
        fflush(out);
        fclose(out);

        return(0);
    } // write_graphviz
}
<|endoftext|>


<commit_before>#include "compiler.h"

#include <cstring>
#include <string>
#include <sstream>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Frontend/LangStandard.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Support/Host.h>
#include <llvm/Module.h>
#include <llvm/LLVMContext.h>

using namespace Coal;

Compiler::Compiler(const std::string &options)
: p_valid(false), p_log_stream(p_log), p_log_printer(0)
{
    // Set codegen options
    clang::CodeGenOptions &codegen_opts = p_compiler.getCodeGenOpts();
    codegen_opts.DebugInfo = false;
    codegen_opts.AsmVerbose = true;

    // Set diagnostic options
    clang::DiagnosticOptions &diag_opts = p_compiler.getDiagnosticOpts();
    diag_opts.Pedantic = true;
    diag_opts.ShowColumn = true;
    diag_opts.ShowLocation = true;
    diag_opts.ShowCarets = false;
    diag_opts.ShowFixits = true;
    diag_opts.ShowColors = false;
    diag_opts.ErrorLimit = 19;
    diag_opts.MessageLength = 0;
    diag_opts.DumpBuildInformation = std::string();
    diag_opts.DiagnosticLogFile = std::string();

    // Set frontend options
    clang::FrontendOptions &frontend_opts = p_compiler.getFrontendOpts();
    frontend_opts.ProgramAction = clang::frontend::EmitLLVMOnly;
    frontend_opts.DisableFree = true;
    frontend_opts.Inputs.push_back(std::make_pair(clang::IK_OpenCL, "program.cl"));

    // Set header search options
    clang::HeaderSearchOptions &header_opts = p_compiler.getHeaderSearchOpts();
    header_opts.Verbose = false;
    header_opts.UseBuiltinIncludes = false;
    header_opts.UseStandardIncludes = false;
    header_opts.UseStandardCXXIncludes = false;

    // Set lang options
    clang::LangOptions &lang_opts = p_compiler.getLangOpts();
    lang_opts.NoBuiltin = true;
    lang_opts.OpenCL = true;

    // Set target options
    clang::TargetOptions &target_opts = p_compiler.getTargetOpts();
    target_opts.Triple = llvm::sys::getHostTriple();

    // Set preprocessor options
    clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
    //prep_opts.Includes.push_back("stdlib.h");
    //prep_opts.addRemappedFile("stdlib.h", ...);

    clang::CompilerInvocation &invocation = p_compiler.getInvocation();
    invocation.setLangDefaults(clang::IK_OpenCL);

    // Parse the user options
    std::istringstream options_stream(options);
    std::string token;

    while (options_stream >> token)
    {

    }

    // Create the diagnostics engine
    p_log_printer = new clang::TextDiagnosticPrinter(p_log_stream, diag_opts);
    p_compiler.createDiagnostics(0, NULL, p_log_printer);

    if (!p_compiler.hasDiagnostics())
        return;

    p_valid = true;
}

Compiler::~Compiler()
{

}

bool Compiler::valid() const
{
    return p_valid;
}

llvm::Module *Compiler::compile(llvm::MemoryBuffer *source)
{
    // Feed the compiler with source
    clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
    prep_opts.addRemappedFile("program.cl", source);
    prep_opts.RetainRemappedFileBuffers = true;

    // Compile
    llvm::Module *module = 0;

    llvm::OwningPtr<clang::CodeGenAction> act(
        new clang::EmitLLVMOnlyAction(new llvm::LLVMContext)
    );

    if (!p_compiler.ExecuteAction(*act))
    {
        return 0;
    }

    p_log_stream.flush();
    module = act->takeModule();

    // Cleanup
    prep_opts.eraseRemappedFile(prep_opts.remapped_file_buffer_end());

    return module;
}

std::string Compiler::log() const
{
    return p_log;
}
<commit_msg>Implement OpenCL C compiler's options.<commit_after>#include "compiler.h"

#include <cstring>
#include <string>
#include <sstream>
#include <clang/Frontend/CompilerInvocation.h>
#include <clang/Frontend/TextDiagnosticPrinter.h>
#include <clang/Frontend/LangStandard.h>
#include <clang/Basic/Diagnostic.h>
#include <clang/CodeGen/CodeGenAction.h>
#include <llvm/ADT/SmallVector.h>
#include <llvm/Support/Host.h>
#include <llvm/Module.h>
#include <llvm/LLVMContext.h>

using namespace Coal;

Compiler::Compiler(const std::string &options)
: p_valid(false), p_log_stream(p_log), p_log_printer(0)
{
    // Set codegen options
    clang::CodeGenOptions &codegen_opts = p_compiler.getCodeGenOpts();
    codegen_opts.DebugInfo = false;
    codegen_opts.AsmVerbose = true;
    codegen_opts.OptimizationLevel = 2;

    // Set diagnostic options
    clang::DiagnosticOptions &diag_opts = p_compiler.getDiagnosticOpts();
    diag_opts.Pedantic = true;
    diag_opts.ShowColumn = true;
    diag_opts.ShowLocation = true;
    diag_opts.ShowCarets = false;
    diag_opts.ShowFixits = true;
    diag_opts.ShowColors = false;
    diag_opts.ErrorLimit = 19;
    diag_opts.MessageLength = 0;
    diag_opts.DumpBuildInformation = std::string();
    diag_opts.DiagnosticLogFile = std::string();

    // Set frontend options
    clang::FrontendOptions &frontend_opts = p_compiler.getFrontendOpts();
    frontend_opts.ProgramAction = clang::frontend::EmitLLVMOnly;
    frontend_opts.DisableFree = true;
    frontend_opts.Inputs.push_back(std::make_pair(clang::IK_OpenCL, "program.cl"));

    // Set header search options
    clang::HeaderSearchOptions &header_opts = p_compiler.getHeaderSearchOpts();
    header_opts.Verbose = false;
    header_opts.UseBuiltinIncludes = false;
    header_opts.UseStandardIncludes = false;
    header_opts.UseStandardCXXIncludes = false;

    // Set lang options
    clang::LangOptions &lang_opts = p_compiler.getLangOpts();
    lang_opts.NoBuiltin = true;
    lang_opts.OpenCL = true;

    // Set target options
    clang::TargetOptions &target_opts = p_compiler.getTargetOpts();
    target_opts.Triple = llvm::sys::getHostTriple();

    // Set preprocessor options
    clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
    //prep_opts.Includes.push_back("stdlib.h");
    //prep_opts.addRemappedFile("stdlib.h", ...);

    clang::CompilerInvocation &invocation = p_compiler.getInvocation();
    invocation.setLangDefaults(clang::IK_OpenCL);

    // Parse the user options
    std::istringstream options_stream(options);
    std::string token;
    bool Werror = false, inI = false, inD = false;

    while (options_stream >> token)
    {
        if (inI)
        {
            // token is an include path
            header_opts.AddPath(token, clang::frontend::Angled, true, false, false);
            inI = false;
            continue;
        }
        else if (inD)
        {
            // token is name or name=value
            prep_opts.addMacroDef(token);
        }

        if (token == "-I")
        {
            inI = true;
        }
        else if (token == "-D")
        {
            inD = true;
        }
        else if (token == "-cl-single-precision-constant")
        {
            lang_opts.SinglePrecisionConstants = true;
        }
        else if (token == "-cl-opt-disable")
        {
            codegen_opts.OptimizationLevel = 0;
        }
        else if (token == "-cl-mad-enable")
        {
            codegen_opts.LessPreciseFPMAD = true;
        }
        else if (token == "-cl-unsafe-math-optimizations")
        {
            codegen_opts.UnsafeFPMath = true;
        }
        else if (token == "-cl-finite-math-only")
        {
            codegen_opts.NoInfsFPMath = true;
            codegen_opts.NoNaNsFPMath = true;
        }
        else if (token == "-cl-fast-relaxed-math")
        {
            codegen_opts.UnsafeFPMath = true;
            codegen_opts.NoInfsFPMath = true;
            codegen_opts.NoNaNsFPMath = true;
            lang_opts.FastRelaxedMath = true;
        }
        else if (token == "-w")
        {
            diag_opts.IgnoreWarnings = true;
        }
        else if (token == "-Werror")
        {
            Werror = true;
        }
    }

    // Create the diagnostics engine
    p_log_printer = new clang::TextDiagnosticPrinter(p_log_stream, diag_opts);
    p_compiler.createDiagnostics(0, NULL, p_log_printer);

    if (!p_compiler.hasDiagnostics())
        return;

    p_compiler.getDiagnostics().setWarningsAsErrors(Werror);

    p_valid = true;
}

Compiler::~Compiler()
{

}

bool Compiler::valid() const
{
    return p_valid;
}

llvm::Module *Compiler::compile(llvm::MemoryBuffer *source)
{
    // Feed the compiler with source
    clang::PreprocessorOptions &prep_opts = p_compiler.getPreprocessorOpts();
    prep_opts.addRemappedFile("program.cl", source);
    prep_opts.RetainRemappedFileBuffers = true;

    // Compile
    llvm::Module *module = 0;

    llvm::OwningPtr<clang::CodeGenAction> act(
        new clang::EmitLLVMOnlyAction(new llvm::LLVMContext)
    );

    if (!p_compiler.ExecuteAction(*act))
    {
        return 0;
    }

    p_log_stream.flush();
    module = act->takeModule();

    // Cleanup
    prep_opts.eraseRemappedFile(prep_opts.remapped_file_buffer_end());

    return module;
}

std::string Compiler::log() const
{
    return p_log;
}
<|endoftext|>


<commit_before>#ifndef VEXCL_DEVLIST_HPP
#define VEXCL_DEVLIST_HPP

/*
The MIT License

Copyright (c) 2012-2014 Denis Demidov <dennis.demidov@gmail.com>

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

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

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

/**
 * \file   devlist.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  OpenCL device enumeration and context initialization.
 */

#include <vector>
#include <functional>
#include <string>
#include <cstdlib>

#include <vexcl/backend.hpp>
#include <vexcl/util.hpp>

#ifdef __GNUC__
#  ifndef _GLIBCXX_USE_NANOSLEEP
#    define _GLIBCXX_USE_NANOSLEEP
#  endif
#endif

namespace vex {

/// Device filters.
namespace Filter {
    /// \cond INTERNAL
    struct AnyFilter {
        bool operator()(const backend::device&) const {
            return true;
        }
    };
    /// \endcond

    /// Selects any device. \deprecated
    const AnyFilter All = {};

    /// Selects any device.
    const AnyFilter Any = {};

    /// Selects no more than given number of devices.
    /**
     * \note This filter should be the last in filter expression. In this case,
     * it will be applied only to devices which passed all other filters.
     * Otherwise, you could get less devices than planned (every time this
     * filter is applied, internal counter is decremented).
     */
    struct Count {
        explicit Count(int c) : count(c) {}

        bool operator()(const backend::device&) const {
            return --count >= 0;
        }

        private:
            mutable int count;
    };

    /// Selects one device at the given position.
    /**
     * Select one device at the given position in the list of devices
     * satisfying previously applied filters.
     */
    struct Position {
        explicit Position(int p) : pos(p) {}

        bool operator()(const backend::device&) const {
            return 0 == pos--;
        }

        private:
            mutable int pos;
    };

    /// \cond INTERNAL

    /// Negation of a filter.
    struct NegateFilter {
        template <class Filter>
        NegateFilter(Filter&& filter)
          : filter(std::forward<Filter>(filter)) {}

        bool operator()(const backend::device &d) const {
            return !filter(d);
        }

        private:
            std::function<bool(const backend::device&)> filter;
    };

    /// Filter join operators.
    enum FilterOp {
        FilterAnd, FilterOr
    };

    /// Filter join expression template.
    template <FilterOp op>
    struct FilterBinaryOp {
        template <class LHS, class RHS>
        FilterBinaryOp(LHS&& lhs, RHS&& rhs)
            : lhs(std::forward<LHS>(lhs)), rhs(std::forward<RHS>(rhs)) {}

        bool operator()(const backend::device &d) const {
            // This could be hidden into FilterOp::apply() call (with FilterOp
            // being a struct instead of enum), but this form allows to rely on
            // short-circuit evaluation (important for mutable filters as Count
            // or Position).
            switch (op) {
                case FilterOr:
                    return lhs(d) || rhs(d);
                case FilterAnd:
                default:
                    return lhs(d) && rhs(d);
            }
        }

        private:
            std::function<bool(const backend::device&)> lhs;
            std::function<bool(const backend::device&)> rhs;
    };

    /// \endcond

    /// Join two filters with AND operator.
    template <class LHS, class RHS>
    FilterBinaryOp<FilterAnd> operator&&(LHS&& lhs, RHS&& rhs)
    {
        return FilterBinaryOp<FilterAnd>(std::forward<LHS>(lhs), std::forward<RHS>(rhs));
    }

    /// Join two filters with OR operator.
    template <class LHS, class RHS>
    FilterBinaryOp<FilterOr> operator||(LHS&& lhs, RHS&& rhs)
    {
        return FilterBinaryOp<FilterOr>(std::forward<LHS>(lhs), std::forward<RHS>(rhs));
    }

    /// Negate a filter.
    template <class Filter>
    NegateFilter operator!(Filter&& filter) {
        return NegateFilter(std::forward<Filter>(filter));
    }

    /// Runtime filter holder.
    /**
     * The filter can be changed at runtime as in:
     \code
     vex::Filter::General f = vex::Filter::Env;
     if (need_double) f = f && vex::Filter::DoublePrecision;
     \endcode
     */
    struct General {
        template<class Filter>
        General(Filter filter) : filter(filter) { }

        bool operator()(const backend::device &d) const {
            return filter(d);
        }

        private:
            std::function<bool(const backend::device&)> filter;
    };

    /// \cond INTERNAL
    struct EnvFilter {
        EnvFilter()
            : filter( backend_env_filters() )
        {
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable: 4996)
#endif
            const char *maxdev   = getenv("OCL_MAX_DEVICES");
            const char *position = getenv("OCL_POSITION");
#ifdef _MSC_VER
#  pragma warning(pop)
#endif

            if (maxdev)   filter.push_back(Count(std::stoi(maxdev)));
            if (position) filter.push_back(Position(std::stoi(position)));
        }

        bool operator()(const backend::device &d) const {
            if (filter.empty()) return true;

            return std::all_of(
                    filter.begin(), filter.end(),
                    [d](const std::function<bool(const backend::device)> &f) {
                        return f(d);
                    });
        }

        private:
            std::vector< std::function<bool(const backend::device&)> > filter;
    };
    /// \endcond

    /// Environment filter
    /**
     * Selects devices with respect to environment variables. Recognized
     * variables are:
     *
     * \li OCL_PLATFORM -- platform name;
     * \li OCL_VENDOR   -- device vendor;
     * \li OCL_DEVICE   -- device name;
     * \li OCL_TYPE     -- device type (CPU, GPU, ACCELERATOR);
     * \li OCL_MAX_DEVICES -- maximum number of devices to use.
     * \li OCL_POSITION -- devices position in the device list.
     *
     * \note Since this filter possibly counts passed devices, it should be the
     * last in filter expression. Same reasoning applies as in case of
     * Filter::Count.
     */
    const EnvFilter Env;

} // namespace Filter

class Context;

template <bool dummy = true>
class StaticContext {
    static_assert(dummy, "dummy parameter should be true");

    public:
        static void set(Context &ctx) {
            instance = &ctx;
        }

        static const Context& get() {
            precondition(instance, "Uninitialized static context");
            return *instance;
        }
    private:
        static Context *instance;
};

template <bool dummy>
Context* StaticContext<dummy>::instance = 0;

/// Returns reference to the latest instance of vex::Context.
inline const Context& current_context() {
    return StaticContext<>::get();
}

/// Check if type is a device filter.
template <class T, class Enable = void>
struct is_device_filter : std::false_type {};

template <class T>
struct is_device_filter<T,
    typename std::enable_if<
            std::is_same<
                bool, typename std::result_of<T(const backend::device&)>::type
            >::value
        >::type
    > : std::true_type
{};

/// VexCL context holder.
/**
 * Holds vectors of backend::contexts and backend::command_queues returned by queue_list.
 */
class Context {
    public:
        /// Initialize context from a device filter.
        template <class DevFilter>
        explicit Context(DevFilter&& filter,
                backend::command_queue_properties properties = 0)
        {
            std::tie(c, q) = backend::queue_list(std::forward<DevFilter>(filter), properties);

#ifdef VEXCL_THROW_ON_EMPTY_CONTEXT
            precondition(!q.empty(), "No compute devices found");
#endif

            StaticContext<>::set(*this);
        }

        /// Initializes context from user-supplied list of backend::contexts and backend::command_queues.
        Context(const std::vector<std::pair<backend::context, backend::command_queue>> &user_ctx) {
            c.reserve(user_ctx.size());
            q.reserve(user_ctx.size());
            for(auto u = user_ctx.begin(); u != user_ctx.end(); u++) {
                c.push_back(u->first);
                q.push_back(u->second);
            }

            StaticContext<>::set(*this);
        }

        /// Initializes context from user-supplied list of backend::contexts and backend::command_queues.
        Context(std::vector<backend::context> c, std::vector<backend::command_queue> q)
            : c(std::move(c)), q(std::move(q))
        {
            StaticContext<>::set(*this);
        }

        const std::vector<backend::context>& context() const {
            return c;
        }

        const backend::context& context(unsigned d) const {
            return c[d];
        }

        const std::vector<backend::command_queue>& queue() const {
            return q;
        }

        operator const std::vector<backend::command_queue>&() const {
            return q;
        }

        const backend::command_queue& queue(unsigned d) const {
            return q[d];
        }

        const backend::device device(unsigned d) const {
            return backend::device( backend::get_device_id(q[d]) );
        }

        size_t size() const {
            return q.size();
        }

        bool empty() const {
            return q.empty();
        }

        operator bool() const {
            return !empty();
        }

        void finish() const {
            for(auto queue = q.begin(); queue != q.end(); ++queue)
                queue->finish();
        }
    private:
        std::vector<backend::context>       c;
        std::vector<backend::command_queue> q;
};

} // namespace vex

namespace std {

/// Output list of devices to stream.
inline std::ostream& operator<<(std::ostream &os,
        const std::vector<vex::backend::command_queue> &queue)
{
    unsigned p = 0;

    for(auto q = queue.begin(); q != queue.end(); q++)
        os << ++p << ". " << *q << std::endl;

    return os;
}

/// Output list of devices to stream.
inline std::ostream& operator<<(std::ostream &os, const vex::Context &ctx) {
    return os << ctx.queue();
}

}

#endif
<commit_msg>Remove ambiguous version of vex::Context constructor<commit_after>#ifndef VEXCL_DEVLIST_HPP
#define VEXCL_DEVLIST_HPP

/*
The MIT License

Copyright (c) 2012-2014 Denis Demidov <dennis.demidov@gmail.com>

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

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

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

/**
 * \file   devlist.hpp
 * \author Denis Demidov <dennis.demidov@gmail.com>
 * \brief  OpenCL device enumeration and context initialization.
 */

#include <vector>
#include <functional>
#include <string>
#include <cstdlib>

#include <vexcl/backend.hpp>
#include <vexcl/util.hpp>

#ifdef __GNUC__
#  ifndef _GLIBCXX_USE_NANOSLEEP
#    define _GLIBCXX_USE_NANOSLEEP
#  endif
#endif

namespace vex {

/// Device filters.
namespace Filter {
    /// \cond INTERNAL
    struct AnyFilter {
        bool operator()(const backend::device&) const {
            return true;
        }
    };
    /// \endcond

    /// Selects any device. \deprecated
    const AnyFilter All = {};

    /// Selects any device.
    const AnyFilter Any = {};

    /// Selects no more than given number of devices.
    /**
     * \note This filter should be the last in filter expression. In this case,
     * it will be applied only to devices which passed all other filters.
     * Otherwise, you could get less devices than planned (every time this
     * filter is applied, internal counter is decremented).
     */
    struct Count {
        explicit Count(int c) : count(c) {}

        bool operator()(const backend::device&) const {
            return --count >= 0;
        }

        private:
            mutable int count;
    };

    /// Selects one device at the given position.
    /**
     * Select one device at the given position in the list of devices
     * satisfying previously applied filters.
     */
    struct Position {
        explicit Position(int p) : pos(p) {}

        bool operator()(const backend::device&) const {
            return 0 == pos--;
        }

        private:
            mutable int pos;
    };

    /// \cond INTERNAL

    /// Negation of a filter.
    struct NegateFilter {
        template <class Filter>
        NegateFilter(Filter&& filter)
          : filter(std::forward<Filter>(filter)) {}

        bool operator()(const backend::device &d) const {
            return !filter(d);
        }

        private:
            std::function<bool(const backend::device&)> filter;
    };

    /// Filter join operators.
    enum FilterOp {
        FilterAnd, FilterOr
    };

    /// Filter join expression template.
    template <FilterOp op>
    struct FilterBinaryOp {
        template <class LHS, class RHS>
        FilterBinaryOp(LHS&& lhs, RHS&& rhs)
            : lhs(std::forward<LHS>(lhs)), rhs(std::forward<RHS>(rhs)) {}

        bool operator()(const backend::device &d) const {
            // This could be hidden into FilterOp::apply() call (with FilterOp
            // being a struct instead of enum), but this form allows to rely on
            // short-circuit evaluation (important for mutable filters as Count
            // or Position).
            switch (op) {
                case FilterOr:
                    return lhs(d) || rhs(d);
                case FilterAnd:
                default:
                    return lhs(d) && rhs(d);
            }
        }

        private:
            std::function<bool(const backend::device&)> lhs;
            std::function<bool(const backend::device&)> rhs;
    };

    /// \endcond

    /// Join two filters with AND operator.
    template <class LHS, class RHS>
    FilterBinaryOp<FilterAnd> operator&&(LHS&& lhs, RHS&& rhs)
    {
        return FilterBinaryOp<FilterAnd>(std::forward<LHS>(lhs), std::forward<RHS>(rhs));
    }

    /// Join two filters with OR operator.
    template <class LHS, class RHS>
    FilterBinaryOp<FilterOr> operator||(LHS&& lhs, RHS&& rhs)
    {
        return FilterBinaryOp<FilterOr>(std::forward<LHS>(lhs), std::forward<RHS>(rhs));
    }

    /// Negate a filter.
    template <class Filter>
    NegateFilter operator!(Filter&& filter) {
        return NegateFilter(std::forward<Filter>(filter));
    }

    /// Runtime filter holder.
    /**
     * The filter can be changed at runtime as in:
     \code
     vex::Filter::General f = vex::Filter::Env;
     if (need_double) f = f && vex::Filter::DoublePrecision;
     \endcode
     */
    struct General {
        template<class Filter>
        General(Filter filter) : filter(filter) { }

        bool operator()(const backend::device &d) const {
            return filter(d);
        }

        private:
            std::function<bool(const backend::device&)> filter;
    };

    /// \cond INTERNAL
    struct EnvFilter {
        EnvFilter()
            : filter( backend_env_filters() )
        {
#ifdef _MSC_VER
#  pragma warning(push)
#  pragma warning(disable: 4996)
#endif
            const char *maxdev   = getenv("OCL_MAX_DEVICES");
            const char *position = getenv("OCL_POSITION");
#ifdef _MSC_VER
#  pragma warning(pop)
#endif

            if (maxdev)   filter.push_back(Count(std::stoi(maxdev)));
            if (position) filter.push_back(Position(std::stoi(position)));
        }

        bool operator()(const backend::device &d) const {
            if (filter.empty()) return true;

            return std::all_of(
                    filter.begin(), filter.end(),
                    [d](const std::function<bool(const backend::device)> &f) {
                        return f(d);
                    });
        }

        private:
            std::vector< std::function<bool(const backend::device&)> > filter;
    };
    /// \endcond

    /// Environment filter
    /**
     * Selects devices with respect to environment variables. Recognized
     * variables are:
     *
     * \li OCL_PLATFORM -- platform name;
     * \li OCL_VENDOR   -- device vendor;
     * \li OCL_DEVICE   -- device name;
     * \li OCL_TYPE     -- device type (CPU, GPU, ACCELERATOR);
     * \li OCL_MAX_DEVICES -- maximum number of devices to use.
     * \li OCL_POSITION -- devices position in the device list.
     *
     * \note Since this filter possibly counts passed devices, it should be the
     * last in filter expression. Same reasoning applies as in case of
     * Filter::Count.
     */
    const EnvFilter Env;

} // namespace Filter

class Context;

template <bool dummy = true>
class StaticContext {
    static_assert(dummy, "dummy parameter should be true");

    public:
        static void set(Context &ctx) {
            instance = &ctx;
        }

        static const Context& get() {
            precondition(instance, "Uninitialized static context");
            return *instance;
        }
    private:
        static Context *instance;
};

template <bool dummy>
Context* StaticContext<dummy>::instance = 0;

/// Returns reference to the latest instance of vex::Context.
inline const Context& current_context() {
    return StaticContext<>::get();
}

/// Check if type is a device filter.
template <class T, class Enable = void>
struct is_device_filter : std::false_type {};

template <class T>
struct is_device_filter<T,
    typename std::enable_if<
            std::is_same<
                bool, typename std::result_of<T(const backend::device&)>::type
            >::value
        >::type
    > : std::true_type
{};

/// VexCL context holder.
/**
 * Holds vectors of backend::contexts and backend::command_queues returned by queue_list.
 */
class Context {
    public:
        /// Initialize context from a device filter.
        template <class DevFilter>
        explicit Context(DevFilter&& filter,
                backend::command_queue_properties properties = 0)
        {
            std::tie(c, q) = backend::queue_list(std::forward<DevFilter>(filter), properties);

#ifdef VEXCL_THROW_ON_EMPTY_CONTEXT
            precondition(!q.empty(), "No compute devices found");
#endif

            StaticContext<>::set(*this);
        }

        /// Initializes context from user-supplied list of backend::contexts and backend::command_queues.
        Context(std::vector<backend::context> c, std::vector<backend::command_queue> q)
            : c(std::move(c)), q(std::move(q))
        {
            StaticContext<>::set(*this);
        }

        const std::vector<backend::context>& context() const {
            return c;
        }

        const backend::context& context(unsigned d) const {
            return c[d];
        }

        const std::vector<backend::command_queue>& queue() const {
            return q;
        }

        operator const std::vector<backend::command_queue>&() const {
            return q;
        }

        const backend::command_queue& queue(unsigned d) const {
            return q[d];
        }

        const backend::device device(unsigned d) const {
            return backend::device( backend::get_device_id(q[d]) );
        }

        size_t size() const {
            return q.size();
        }

        bool empty() const {
            return q.empty();
        }

        operator bool() const {
            return !empty();
        }

        void finish() const {
            for(auto queue = q.begin(); queue != q.end(); ++queue)
                queue->finish();
        }
    private:
        std::vector<backend::context>       c;
        std::vector<backend::command_queue> q;
};

} // namespace vex

namespace std {

/// Output list of devices to stream.
inline std::ostream& operator<<(std::ostream &os,
        const std::vector<vex::backend::command_queue> &queue)
{
    unsigned p = 0;

    for(auto q = queue.begin(); q != queue.end(); q++)
        os << ++p << ". " << *q << std::endl;

    return os;
}

/// Output list of devices to stream.
inline std::ostream& operator<<(std::ostream &os, const vex::Context &ctx) {
    return os << ctx.queue();
}

}

#endif
<|endoftext|>