<commit_before>#ifndef selection_hh_INCLUDED
#define selection_hh_INCLUDED

#include "buffer.hh"

namespace Kakoune
{

using CaptureList = Vector<String, MemoryDomain::Selections>;

// A selection is a Selection, associated with a CaptureList
struct Selection
{
    static constexpr MemoryDomain Domain = MemoryDomain::Selections;

    Selection() = default;
    Selection(BufferCoord pos) : Selection(pos,pos) {}
    Selection(BufferCoord anchor, BufferCoord cursor,
              CaptureList captures = {})
        : m_anchor{anchor}, m_cursor{cursor},
          m_captures(std::move(captures)) {}

    void merge_with(const Selection& range);

    BufferCoord& anchor() { return m_anchor; }
    BufferCoordAndTarget& cursor() { return m_cursor; }

    const BufferCoord& anchor() const { return m_anchor; }
    const BufferCoordAndTarget& cursor() const { return m_cursor; }

    CaptureList& captures() { return m_captures; }
    const CaptureList& captures() const { return m_captures; }

    bool operator== (const Selection& other) const
    {
        return m_anchor == other.m_anchor and m_cursor == other.m_cursor;
    }

    const BufferCoord& min() const { return m_anchor < m_cursor ? m_anchor : m_cursor; }
    const BufferCoord& max() const { return m_anchor < m_cursor ? m_cursor : m_anchor; }

    BufferCoord& min() { return m_anchor < m_cursor ? m_anchor : m_cursor; }
    BufferCoord& max() { return m_anchor < m_cursor ? m_cursor : m_anchor; }

private:
    BufferCoord m_anchor;
    BufferCoordAndTarget m_cursor;

    CaptureList m_captures;
};

inline bool overlaps(const Selection& lhs, const Selection& rhs)
{
    return lhs.min() <= rhs.min() ? lhs.max() >= rhs.min()
                                  : lhs.min() <= rhs.max();
}

void update_selections(Vector<Selection>& selections, size_t& main,
                       Buffer& buffer, size_t timestamp);

enum class InsertMode : unsigned
{
    Insert,
    InsertCursor,
    Append,
    Replace,
    InsertAtLineBegin,
    InsertAtNextLineBegin,
    AppendAtLineEnd,
    OpenLineBelow,
    OpenLineAbove
};

struct SelectionList
{
    static constexpr MemoryDomain Domain = MemoryDomain::Selections;

    SelectionList(Buffer& buffer, Selection s);
    SelectionList(Buffer& buffer, Selection s, size_t timestamp);
    SelectionList(Buffer& buffer, Vector<Selection> s);
    SelectionList(Buffer& buffer, Vector<Selection> s, size_t timestamp);

    void update();

    void check_invariant() const;

    const Selection& main() const { return (*this)[m_main]; }
    Selection& main() { return (*this)[m_main]; }
    size_t main_index() const { return m_main; }
    void set_main_index(size_t main) { kak_assert(main < size()); m_main = main; }

    void rotate_main(int count) { m_main = (m_main + count) % size(); }

    void avoid_eol();

    void push_back(const Selection& sel) { m_selections.push_back(sel); }
    void push_back(Selection&& sel) { m_selections.push_back(std::move(sel)); }

    Selection& operator[](size_t i) { return m_selections[i]; }
    const Selection& operator[](size_t i) const { return m_selections[i]; }

    SelectionList& operator=(Vector<Selection> list)
    {
        set(std::move(list), list.size()-1);
        return *this;
    }

    void set(Vector<Selection> list, size_t main)
    {
        kak_assert(main < list.size());
        m_selections = std::move(list);
        m_main = main;
        sort_and_merge_overlapping();
        update_timestamp();
        check_invariant();
    }

    using iterator = Vector<Selection>::iterator;
    iterator begin() { return m_selections.begin(); }
    iterator end() { return m_selections.end(); }

    using const_iterator = Vector<Selection>::const_iterator;
    const_iterator begin() const { return m_selections.begin(); }
    const_iterator end() const { return m_selections.end(); }

    void remove(size_t index) { m_selections.erase(begin() + index); }

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

    bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; }
    bool operator!=(const SelectionList& other) const { return not ((*this) == other); }

    void sort();
    void merge_overlapping();
    void merge_consecutive();
    void sort_and_merge_overlapping();

    Buffer& buffer() const { return *m_buffer; }

    size_t timestamp() const { return m_timestamp; }
    void update_timestamp() { m_timestamp = m_buffer->timestamp(); }

    void insert(ConstArrayView<String> strings, InsertMode mode,
                Vector<BufferCoord>* out_insert_pos = nullptr);
    void erase();

private:
    size_t m_main = 0;
    Vector<Selection> m_selections;

    SafePtr<Buffer> m_buffer;
    size_t m_timestamp;
};

Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp);

String selection_to_string(const Selection& selection);
String selection_list_to_string(const SelectionList& selection);
Selection selection_from_string(StringView desc);
SelectionList selection_list_from_string(Buffer& buffer, StringView desc);

}

#endif // selection_hh_INCLUDED
<commit_msg>Fix bug relying on undefined arg evaluation order.<commit_after>#ifndef selection_hh_INCLUDED
#define selection_hh_INCLUDED

#include "buffer.hh"

namespace Kakoune
{

using CaptureList = Vector<String, MemoryDomain::Selections>;

// A selection is a Selection, associated with a CaptureList
struct Selection
{
    static constexpr MemoryDomain Domain = MemoryDomain::Selections;

    Selection() = default;
    Selection(BufferCoord pos) : Selection(pos,pos) {}
    Selection(BufferCoord anchor, BufferCoord cursor,
              CaptureList captures = {})
        : m_anchor{anchor}, m_cursor{cursor},
          m_captures(std::move(captures)) {}

    void merge_with(const Selection& range);

    BufferCoord& anchor() { return m_anchor; }
    BufferCoordAndTarget& cursor() { return m_cursor; }

    const BufferCoord& anchor() const { return m_anchor; }
    const BufferCoordAndTarget& cursor() const { return m_cursor; }

    CaptureList& captures() { return m_captures; }
    const CaptureList& captures() const { return m_captures; }

    bool operator== (const Selection& other) const
    {
        return m_anchor == other.m_anchor and m_cursor == other.m_cursor;
    }

    const BufferCoord& min() const { return m_anchor < m_cursor ? m_anchor : m_cursor; }
    const BufferCoord& max() const { return m_anchor < m_cursor ? m_cursor : m_anchor; }

    BufferCoord& min() { return m_anchor < m_cursor ? m_anchor : m_cursor; }
    BufferCoord& max() { return m_anchor < m_cursor ? m_cursor : m_anchor; }

private:
    BufferCoord m_anchor;
    BufferCoordAndTarget m_cursor;

    CaptureList m_captures;
};

inline bool overlaps(const Selection& lhs, const Selection& rhs)
{
    return lhs.min() <= rhs.min() ? lhs.max() >= rhs.min()
                                  : lhs.min() <= rhs.max();
}

void update_selections(Vector<Selection>& selections, size_t& main,
                       Buffer& buffer, size_t timestamp);

enum class InsertMode : unsigned
{
    Insert,
    InsertCursor,
    Append,
    Replace,
    InsertAtLineBegin,
    InsertAtNextLineBegin,
    AppendAtLineEnd,
    OpenLineBelow,
    OpenLineAbove
};

struct SelectionList
{
    static constexpr MemoryDomain Domain = MemoryDomain::Selections;

    SelectionList(Buffer& buffer, Selection s);
    SelectionList(Buffer& buffer, Selection s, size_t timestamp);
    SelectionList(Buffer& buffer, Vector<Selection> s);
    SelectionList(Buffer& buffer, Vector<Selection> s, size_t timestamp);

    void update();

    void check_invariant() const;

    const Selection& main() const { return (*this)[m_main]; }
    Selection& main() { return (*this)[m_main]; }
    size_t main_index() const { return m_main; }
    void set_main_index(size_t main) { kak_assert(main < size()); m_main = main; }

    void rotate_main(int count) { m_main = (m_main + count) % size(); }

    void avoid_eol();

    void push_back(const Selection& sel) { m_selections.push_back(sel); }
    void push_back(Selection&& sel) { m_selections.push_back(std::move(sel)); }

    Selection& operator[](size_t i) { return m_selections[i]; }
    const Selection& operator[](size_t i) const { return m_selections[i]; }

    SelectionList& operator=(Vector<Selection> list)
    {
        const size_t main_index = list.size()-1;
        set(std::move(list), main_index);
        return *this;
    }

    void set(Vector<Selection> list, size_t main)
    {
        kak_assert(main < list.size());
        m_selections = std::move(list);
        m_main = main;
        sort_and_merge_overlapping();
        update_timestamp();
        check_invariant();
    }

    using iterator = Vector<Selection>::iterator;
    iterator begin() { return m_selections.begin(); }
    iterator end() { return m_selections.end(); }

    using const_iterator = Vector<Selection>::const_iterator;
    const_iterator begin() const { return m_selections.begin(); }
    const_iterator end() const { return m_selections.end(); }

    void remove(size_t index) { m_selections.erase(begin() + index); }

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

    bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; }
    bool operator!=(const SelectionList& other) const { return not ((*this) == other); }

    void sort();
    void merge_overlapping();
    void merge_consecutive();
    void sort_and_merge_overlapping();

    Buffer& buffer() const { return *m_buffer; }

    size_t timestamp() const { return m_timestamp; }
    void update_timestamp() { m_timestamp = m_buffer->timestamp(); }

    void insert(ConstArrayView<String> strings, InsertMode mode,
                Vector<BufferCoord>* out_insert_pos = nullptr);
    void erase();

private:
    size_t m_main = 0;
    Vector<Selection> m_selections;

    SafePtr<Buffer> m_buffer;
    size_t m_timestamp;
};

Vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp);

String selection_to_string(const Selection& selection);
String selection_list_to_string(const SelectionList& selection);
Selection selection_from_string(StringView desc);
SelectionList selection_list_from_string(Buffer& buffer, StringView desc);

}

#endif // selection_hh_INCLUDED
<|endoftext|>


<commit_before>#ifndef _SDD_DD_NARY_HH_
#define _SDD_DD_NARY_HH_

#include <algorithm> // copy, equal
#include <cassert>
#include <initializer_list>
#include <iosfwd>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/context_fwd.hh"
#include "sdd/dd/definition.hh"
#include "sdd/dd/top.hh"

namespace sdd { namespace dd {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Check that all operands are compatible and determine the nodes' type (hierarchical
/// or flat).
template<typename C>
struct check_visitor
{
  typedef node_tag result_type;

  node_tag
  operator()( const flat_node<C>& lhs, const flat_node<C>& rhs
            , const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    if (not (lhs.variable() == rhs.variable()))
    {
      throw top<C>(sdd_lhs, sdd_rhs);
    }
    return node_tag::flat;
  }

  node_tag
  operator()( const hierarchical_node<C>& lhs, const hierarchical_node<C>& rhs
            , const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    if (not (lhs.variable() == rhs.variable()))
    {
      throw top<C>(sdd_lhs, sdd_rhs);
    }
    return node_tag::hierarchical;
  }

  node_tag
  operator()(const one_terminal<C>&, const one_terminal<C>&, const SDD<C>&, const SDD<C>&)
  const noexcept
  {
    assert(false && "More than one |1| in operands.");
    __builtin_unreachable();
  }

  template <typename T, typename U>
  __attribute__((noreturn))
  node_tag
  operator()(const T&, const U&, const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    throw top<C>(sdd_lhs, sdd_rhs);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base class for sum and intersection operations, used by the cache.
///
/// It manages the allocation and deallocation of operands, as well as the dispatch on the
/// correct type (flat or hierarchical node). Use CRTP.
/// As it's an internally used structure, we don't bother with private and public sections.
template <typename C, typename Operation>
struct LIBSDD_ATTRIBUTE_PACKED nary_base
{
  // Can't copy a nary_base.
  nary_base(const nary_base&) = delete;
  nary_base& operator=(const nary_base&) = delete;

  /// Used by the cache to know the type of the result.
  typedef SDD<C> result_type;

  /// To iterate on operands.
  typedef const SDD<C>* const_iterator;

  /// The dynamically allocated array of operands.
  char* operands;

  /// The number of operands.
  const typename C::operands_size_type size;

  template <typename Builder>
  nary_base(Builder& builder)
    : operands(new char[builder.size_to_allocate()])
    , size(static_cast<typename C::operands_size_type>(builder.size()))
  {
    builder.consolidate(operands);
  }

  nary_base(nary_base&& other)
  noexcept
    : operands(other.operands)
    , size(other.size)
  {
    other.operands = nullptr;
  }

  ~nary_base()
  {
    if (operands != nullptr)
    {
      for (auto& operand : *this)
      {
        operand.~SDD<C>();
      }
      delete[] operands;
    }
  }

  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands);
  }

  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands) + size;
  }

  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    // Check compatibility of operands, size is necessarily at least 2.
    auto cit = begin();
    auto last = end() - 1;
    node_tag tag = node_tag::flat;
    for (; cit != last; ++cit)
    {
      tag = apply_binary_visitor( check_visitor<C>()
                                , (*cit)->data(), (*(cit + 1))->data()
                                , *cit, *(cit + 1));
    }
    // Dispatch on the function that does the real work with the deduced type.
    const Operation* impl = static_cast<const Operation*>(this);
    if (tag == node_tag::flat)
    {
      return impl->template work<node_tag::flat>(cxt);
    }
    else
    {
      return impl->template work<node_tag::hierarchical>(cxt);
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Equality of two operations based on nary_base.
/// @related nary_base
template <typename C, typename Operation>
inline
bool
operator==(const nary_base<C, Operation>& lhs, const nary_base<C, Operation>& rhs)
noexcept
{
  return lhs.size == rhs.size and std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

/// @internal
/// @related nary_base
template <typename C, typename Operation>
std::ostream&
operator<<(std::ostream& os, const nary_base<C, Operation>& x)
{
  os << Operation::symbol() << " (";
  std::copy(x.begin(), std::prev(x.end()), std::ostream_iterator<SDD<C>>(os, ", "));
  return os << *std::prev(x.end()) << ")";
}

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base type for builders of sum and intersection operations.
///
/// The goal of a this builder is ensure that operands are always stored in the same order
/// (to improve cache hits); and to know the exact number of operands in order to allocate the
/// smallest possible memory to store all of them (this allocation is performed in the
/// construction of operations in nary_base).
template <typename Valuation, typename Builder>
struct LIBSDD_ATTRIBUTE_PACKED nary_builder
{
  typedef boost::container::flat_set<Valuation> set_type;
  typedef typename set_type::const_iterator const_iterator;

  /// @brief The policy to add new operands.
  Builder builder_;

  /// @brief Sorted container of operands.
  set_type set_;

  /// @brief Default constructor.
  nary_builder()
    : builder_()
    , set_()
  {
  }

  /// @brief Construction with a reserve request.
  nary_builder(std::size_t size)
    : builder_()
    , set_()
  {
    set_.reserve(size);
  }

  /// @brief Construction from a list of operands.
  nary_builder(std::initializer_list<Valuation> operands)
    : nary_builder(operands.size())
  {
    for (const auto& op : operands)
    {
      add(op);
    }
  }

  /// @brief Add a new operand.
  void
  add(Valuation&& operand)
  {
    builder_.add(set_, std::move(operand));
  }

  /// @brief Add a new operand.
  void
  add(const Valuation& operand)
  {
    builder_.add(set_, operand);
  }

  /// @brief Request for allocation of additional memory.
  void
  reserve(std::size_t size)
  noexcept
  {
    set_.reserve(size);
  }

  const_iterator
  begin()
  const noexcept
  {
    return set_.begin();
  }

  const_iterator
  end()
  const noexcept
  {
    return set_.end();
  }

  /// @brief Tell if this build doesn't contain any node.
  bool
  empty()
  const noexcept
  {
    return set_.empty();
  }

  std::size_t
  size()
  const noexcept
  {
    return set_.size();
  }

  /// @brief Compute the size needed to store all the operands contained by this builder.
  std::size_t
  size_to_allocate()
  const noexcept
  {
    return set_.size() * sizeof(Valuation);
  }

  /// @brief Move operands of this builder to a given memory location.
  /// @param addr shall point to an allocated memory location of the size returned by
  /// size_to_allocate().
  ///
  /// Once performed, all subsequent calls to this instance are invalid.
  void
  consolidate(void* addr)
  noexcept
  {
    Valuation* base = reinterpret_cast<Valuation*>(addr);
    std::size_t i = 0;
    for (auto it = set_.begin(); it != set_.end(); ++it, ++i)
    {
      new (base + i) Valuation(std::move(*it));
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::dd

#endif // _SDD_DD_NARY_HH_
<commit_msg>Documentation.<commit_after>#ifndef _SDD_DD_NARY_HH_
#define _SDD_DD_NARY_HH_

#include <algorithm> // copy, equal
#include <cassert>
#include <initializer_list>
#include <iosfwd>

#include <boost/container/flat_set.hpp>

#include "sdd/dd/context_fwd.hh"
#include "sdd/dd/definition.hh"
#include "sdd/dd/top.hh"

namespace sdd { namespace dd {

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Check that all operands are compatible and determine the nodes' type (hierarchical
/// or flat).
template<typename C>
struct check_visitor
{
  typedef node_tag result_type;

  node_tag
  operator()( const flat_node<C>& lhs, const flat_node<C>& rhs
            , const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    if (not (lhs.variable() == rhs.variable()))
    {
      throw top<C>(sdd_lhs, sdd_rhs);
    }
    return node_tag::flat;
  }

  node_tag
  operator()( const hierarchical_node<C>& lhs, const hierarchical_node<C>& rhs
            , const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    if (not (lhs.variable() == rhs.variable()))
    {
      throw top<C>(sdd_lhs, sdd_rhs);
    }
    return node_tag::hierarchical;
  }

  node_tag
  operator()(const one_terminal<C>&, const one_terminal<C>&, const SDD<C>&, const SDD<C>&)
  const noexcept
  {
    assert(false && "More than one |1| in operands.");
    __builtin_unreachable();
  }

  template <typename T, typename U>
  __attribute__((noreturn))
  node_tag
  operator()(const T&, const U&, const SDD<C>& sdd_lhs, const SDD<C>& sdd_rhs)
  const
  {
    throw top<C>(sdd_lhs, sdd_rhs);
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base class for sum and intersection operations, used by the cache.
///
/// It manages the allocation and deallocation of operands, as well as the dispatch on the
/// correct type (flat or hierarchical node). Use CRTP.
/// As it's an internally used structure, we don't bother with private and public sections.
template <typename C, typename Operation>
struct LIBSDD_ATTRIBUTE_PACKED nary_base
{
  // Can't copy a nary_base.
  nary_base(const nary_base&) = delete;
  nary_base& operator=(const nary_base&) = delete;

  /// Used by the cache to know the type of the result.
  typedef SDD<C> result_type;

  /// To iterate on operands.
  typedef const SDD<C>* const_iterator;

  /// The dynamically allocated array of operands.
  char* operands;

  /// The number of operands.
  const typename C::operands_size_type size;

  template <typename Builder>
  nary_base(Builder& builder)
    : operands(new char[builder.size_to_allocate()])
    , size(static_cast<typename C::operands_size_type>(builder.size()))
  {
    builder.consolidate(operands);
  }

  nary_base(nary_base&& other)
  noexcept
    : operands(other.operands)
    , size(other.size)
  {
    other.operands = nullptr;
  }

  ~nary_base()
  {
    if (operands != nullptr)
    {
      for (auto& operand : *this)
      {
        operand.~SDD<C>();
      }
      delete[] operands;
    }
  }

  const_iterator
  begin()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands);
  }

  const_iterator
  end()
  const noexcept
  {
    return reinterpret_cast<const SDD<C>*>(operands) + size;
  }

  SDD<C>
  operator()(context<C>& cxt)
  const
  {
    // Check compatibility of operands, size is necessarily at least 2.
    auto cit = begin();
    auto last = end() - 1;
    node_tag tag = node_tag::flat;
    for (; cit != last; ++cit)
    {
      tag = apply_binary_visitor( check_visitor<C>()
                                , (*cit)->data(), (*(cit + 1))->data()
                                , *cit, *(cit + 1));
    }
    // Dispatch on the function that does the real work with the deduced type.
    const Operation* impl = static_cast<const Operation*>(this);
    if (tag == node_tag::flat)
    {
      return impl->template work<node_tag::flat>(cxt);
    }
    else
    {
      return impl->template work<node_tag::hierarchical>(cxt);
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Equality of two operations based on nary_base.
/// @related nary_base
template <typename C, typename Operation>
inline
bool
operator==(const nary_base<C, Operation>& lhs, const nary_base<C, Operation>& rhs)
noexcept
{
  return lhs.size == rhs.size and std::equal(lhs.begin(), lhs.end(), rhs.begin());
}

/// @internal
/// @related nary_base
template <typename C, typename Operation>
std::ostream&
operator<<(std::ostream& os, const nary_base<C, Operation>& x)
{
  os << Operation::symbol() << " (";
  std::copy(x.begin(), std::prev(x.end()), std::ostream_iterator<SDD<C>>(os, ", "));
  return os << *std::prev(x.end()) << ")";
}

/*------------------------------------------------------------------------------------------------*/

/// @internal
/// @brief Base type for builders of sum and intersection operations.
///
/// The goal of a this builder is ensure that operands are always stored in the same order
/// (to improve cache hits); and to know the exact number of operands in order to allocate the
/// smallest possible memory to store all of them (this allocation is performed in the
/// construction of operations in nary_base).
template <typename Valuation, typename Builder>
struct LIBSDD_ATTRIBUTE_PACKED nary_builder
{
  typedef boost::container::flat_set<Valuation> set_type;
  typedef typename set_type::const_iterator const_iterator;

  /// @brief The policy to add new operands.
  ///
  /// An instance is needed for builders with a state (intersection).
  Builder builder_;

  /// @brief Sorted container of operands.
  set_type set_;

  /// @brief Default constructor.
  nary_builder()
    : builder_()
    , set_()
  {
  }

  /// @brief Construction with a reserve request.
  nary_builder(std::size_t size)
    : builder_()
    , set_()
  {
    set_.reserve(size);
  }

  /// @brief Construction from a list of operands.
  nary_builder(std::initializer_list<Valuation> operands)
    : nary_builder(operands.size())
  {
    for (const auto& op : operands)
    {
      add(op);
    }
  }

  /// @brief Add a new operand.
  void
  add(Valuation&& operand)
  {
    builder_.add(set_, std::move(operand));
  }

  /// @brief Add a new operand.
  void
  add(const Valuation& operand)
  {
    builder_.add(set_, operand);
  }

  /// @brief Request for allocation of additional memory.
  void
  reserve(std::size_t size)
  noexcept
  {
    set_.reserve(size);
  }

  const_iterator
  begin()
  const noexcept
  {
    return set_.begin();
  }

  const_iterator
  end()
  const noexcept
  {
    return set_.end();
  }

  /// @brief Tell if this build doesn't contain any node.
  bool
  empty()
  const noexcept
  {
    return set_.empty();
  }

  std::size_t
  size()
  const noexcept
  {
    return set_.size();
  }

  /// @brief Compute the size needed to store all the operands contained by this builder.
  std::size_t
  size_to_allocate()
  const noexcept
  {
    return set_.size() * sizeof(Valuation);
  }

  /// @brief Move operands of this builder to a given memory location.
  /// @param addr shall point to an allocated memory location of the size returned by
  /// size_to_allocate().
  ///
  /// Once performed, all subsequent calls to this instance are invalid.
  void
  consolidate(void* addr)
  noexcept
  {
    Valuation* base = reinterpret_cast<Valuation*>(addr);
    std::size_t i = 0;
    for (auto it = set_.begin(); it != set_.end(); ++it, ++i)
    {
      new (base + i) Valuation(std::move(*it));
    }
  }
};

/*------------------------------------------------------------------------------------------------*/

}} // namespace sdd::dd

#endif // _SDD_DD_NARY_HH_
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <assert.h>

#include "../vowpalwabbit/vw.h"

using namespace std;

int pairs = 0;
int users = 0;
int items = 0;
int recs = 0;
int skipped = 0;
int banned = 0;
int show = 1;
void progress()
{
        fprintf(stderr, "%12d %8d %8d %8d %8d\n", pairs, users, items, recs, skipped);
}

void usage(char *prog) {
        fprintf(stderr, "usage: %s [-b <2|4|8|...|32>] [-v] <blacklist> <users> <items> <topN> <vwparams>\n", prog);
        exit(EXIT_FAILURE);
}

int b=16;
int topn=10;
int verbose=0;
char * blacklistfilename = NULL;
char * itemfilename = NULL;
char * userfilename = NULL;
char * vwparams = NULL;

unsigned hash_ber(char *in, size_t len) {
        unsigned hashv = 0;
        while (len--)  hashv = ((hashv) * 33) + *in++;
        return hashv;
}
unsigned hash_fnv(char *in, size_t len) {
        unsigned hashv = 2166136261UL;
        while(len--) hashv = (hashv * 16777619) ^ *in++;
        return hashv;
}
#define MASK(u,b) ( u & ((1UL << b) - 1))
#define NUM_HASHES 2
void get_hashv(char *in, size_t len, unsigned *out) {
        assert(NUM_HASHES==2);
        out[0] = MASK(hash_ber(in,len),b);
        out[1] = MASK(hash_fnv(in,len),b);
}

#define BIT_TEST(c,i) (c[i/8] & (1 << (i % 8)))
#define BIT_SET(c,i) (c[i/8] |= (1 << (i % 8)))
#define byte_len(b) (((1UL << b) / 8) + (((1UL << b) % 8) ? 1 : 0))
#define num_bits(b) (1UL << b)
char *bf_new(unsigned b) {
        char *bf = (char*)calloc(1,byte_len(b));
        return bf;
}
void bf_add(char *bf, char *line) {
        unsigned i, hashv[NUM_HASHES];
        get_hashv(line,strlen(line),hashv);
        for(i=0;i<NUM_HASHES;i++) BIT_SET(bf,hashv[i]);
}
void bf_info(char *bf, FILE *f) {
        unsigned i, on=0;
        for(i=0; i<num_bits(b); i++)
                if (BIT_TEST(bf,i)) on++;

        fprintf(f, "%.2f%% saturation\n%lu bf bit size\n", on*100.0/num_bits(b), num_bits(b));
}
int bf_hit(char *bf, char *line) {
        unsigned i, hashv[NUM_HASHES];
        get_hashv(line,strlen(line),hashv);
        for(i=0;i<NUM_HASHES;i++) {
                if (BIT_TEST(bf,hashv[i])==0) return 0;
        }
        return 1;
}

typedef pair<float, string> scored_example;
vector<scored_example> scored_examples;

struct compare_scored_examples
{
    bool operator()(scored_example const& a, scored_example const& b) const
    {
        return a.first > b.first;
    }
};

priority_queue<scored_example, vector<scored_example>, compare_scored_examples > pr_queue;

int main(int argc, char *argv[])
{
        int opt;

        while ( (opt = getopt(argc, argv, "b:v+N:")) != -1) {
                switch (opt) {
                        case 'N':
                                topn = atoi(optarg);
                                break;
                        case 'b':
                                b = atoi(optarg);
                                break;
                        case 'v':
                                verbose++;
                                break;
                        default:
                                usage(argv[0]);
                                break;
                }
        }

        if (optind < argc) blacklistfilename=argv[optind++];
        if (optind < argc) userfilename=argv[optind++];
        if (optind < argc) itemfilename=argv[optind++];
        if (optind < argc) vwparams=argv[optind++];

        if (!blacklistfilename || !userfilename || !itemfilename || !vwparams) usage(argv[0]);

        FILE * fB;
        FILE * fU;
        FILE * fI;

        if((fB = fopen(blacklistfilename, "r")) == NULL)
        {
                fprintf(stderr,"can't open %s: %s\n", blacklistfilename, strerror(errno));
                usage(argv[0]);
        }
        if((fU = fopen(userfilename, "r")) == NULL )
        {
                fprintf(stderr,"can't open %s: %s\n", userfilename, strerror(errno));
                usage(argv[0]);
        }
        if((fI = fopen(itemfilename, "r")) == NULL )
        {
                fprintf(stderr,"can't open %s: %s\n", itemfilename, strerror(errno));
                usage(argv[0]);
        }

        char * buf = NULL;
        char * u = NULL;
        char * i = NULL;
        size_t len = 0;
        ssize_t read;

        /* make the bloom filter */
        if(verbose>0)
                fprintf(stderr, "loading blacklist into bloom filter...\n");
        char *bf= bf_new(b);

        /* loop over the source file */
        while ((read = getline(&buf,&len,fB)) != -1)
        {
                bf_add(bf,buf);
                banned++;
        }

        /* print saturation etc */
        if (verbose)
        {
                bf_info(bf,stderr);
                fprintf(stderr, "%d banned pairs\n", banned);
        }

        // INITIALIZE WITH WHATEVER YOU WOULD PUT ON THE VW COMMAND LINE
        if(verbose>0)
                fprintf(stderr, "initializing vw...\n");
        vw* model = VW::initialize(vwparams);

        char * estr = NULL;

        if(verbose>0)
        {
                fprintf(stderr, "predicting...\n");
                fprintf(stderr, "%12s %8s %8s %8s %8s\n", "pair", "user", "item", "rec", "skipped");
        }
        while ((read = getline(&u, &len, fU)) != -1)
        {
                users++;
                u[strlen(u)-1] = 0; // chop
                rewind(fI);
                items=0;
                while ((read = getline(&i, &len, fI)) != -1)
                {
                        items++;
                        pairs++;

                        if((verbose > 0) & (pairs % show == 0))
                        {
                                progress();
                                show *= 2;
                        }

                        free(estr);
                        estr = strdup((string(u)+string(i)).c_str());

                        if (!bf_hit(bf,estr))
                        {
                                example *ex = VW::read_example(*model, estr);
                                model->learn(ex);

                                const string str(estr);

                                if(pr_queue.size() < topn)
                                {
                                        pr_queue.push(make_pair(ex->final_prediction, str));
                                }
                                else if(pr_queue.top().first < ex->final_prediction)
                                {
                                        pr_queue.pop();
                                        pr_queue.push(make_pair(ex->final_prediction, str));
                                }

                                VW::finish_example(*model, ex);
                        }
                        else
                        {
                                skipped++;
                                if(verbose>=2)
                                        fprintf(stderr,"skipping:|%s|\n", estr);
                        }

                }

                while(!pr_queue.empty())
                {
                        cout << pr_queue.top().first << "\t" << pr_queue.top().second;
                        pr_queue.pop();
                        recs++;
                }
        }
        if(verbose>0)
        {
                progress();
        }

        VW::finish(*model);
        fclose(fI);
        fclose(fU);
        exit(EXIT_SUCCESS);
}

<commit_msg>use boost::program_options instead of getopt<commit_after>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <queue>
#include <utility>
#include <algorithm>
#include <iostream>
#include <fstream>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <boost/program_options.hpp>

#include "../vowpalwabbit/vw.h"

using namespace std;
namespace po = boost::program_options;

int pairs = 0;
int users = 0;
int items = 0;
int recs = 0;
int skipped = 0;
int banned = 0;
int show = 1;

int b=16;
int topk=10;
int verbose=0;
string blacklistfilename;
string itemfilename;
string userfilename;
string vwparams;

void progress()
{
        fprintf(stderr, "%12d %8d %8d %8d %12d %s %s\n", pairs, users, items, recs, skipped, userfilename.c_str(), itemfilename.c_str());
}

unsigned hash_ber(char *in, size_t len) {
        unsigned hashv = 0;
        while (len--)  hashv = ((hashv) * 33) + *in++;
        return hashv;
}
unsigned hash_fnv(char *in, size_t len) {
        unsigned hashv = 2166136261UL;
        while(len--) hashv = (hashv * 16777619) ^ *in++;
        return hashv;
}
#define MASK(u,b) ( u & ((1UL << b) - 1))
#define NUM_HASHES 2
void get_hashv(char *in, size_t len, unsigned *out) {
        assert(NUM_HASHES==2);
        out[0] = MASK(hash_ber(in,len),b);
        out[1] = MASK(hash_fnv(in,len),b);
}

#define BIT_TEST(c,i) (c[i/8] & (1 << (i % 8)))
#define BIT_SET(c,i) (c[i/8] |= (1 << (i % 8)))
#define byte_len(b) (((1UL << b) / 8) + (((1UL << b) % 8) ? 1 : 0))
#define num_bits(b) (1UL << b)
char *bf_new(unsigned b) {
        char *bf = (char*)calloc(1,byte_len(b));
        return bf;
}
void bf_add(char *bf, char *line) {
        unsigned i, hashv[NUM_HASHES];
        get_hashv(line,strlen(line),hashv);
        for(i=0;i<NUM_HASHES;i++) BIT_SET(bf,hashv[i]);
}
void bf_info(char *bf, FILE *f) {
        unsigned i, on=0;
        for(i=0; i<num_bits(b); i++)
                if (BIT_TEST(bf,i)) on++;

        fprintf(f, "%.2f%% saturation\n%lu bf bit size\n", on*100.0/num_bits(b), num_bits(b));
}
int bf_hit(char *bf, char *line) {
        unsigned i, hashv[NUM_HASHES];
        get_hashv(line,strlen(line),hashv);
        for(i=0;i<NUM_HASHES;i++) {
                if (BIT_TEST(bf,hashv[i])==0) return 0;
        }
        return 1;
}

typedef pair<float, string> scored_example;
vector<scored_example> scored_examples;

struct compare_scored_examples
{
    bool operator()(scored_example const& a, scored_example const& b) const
    {
        return a.first > b.first;
    }
};

priority_queue<scored_example, vector<scored_example>, compare_scored_examples > pr_queue;

int main(int argc, char *argv[])
{
        try {
        po::variables_map vm;
        po::options_description desc("Allowed options");
        desc.add_options()
                ("help,h", "produce help message")
                ("topk", po::value<int>(&topk), "number of items to recommend per user")
                ("verbose,v", po::value<int>(&verbose), "increase verbosity (can be repeated)")
                ("bf_bits,b", po::value<int>(&b), "number of items to recommend")
                ("blacklist,B", po::value<string>(&blacklistfilename), "user item pairs (in vw format) that we should not recommend (have been seen before)")
                ("users,U", po::value<string>(&userfilename), "users portion in vw format to make recs for")
                ("items,I", po::value<string>(&itemfilename), "items (in vw format) to recommend from")
                ("vwparams", po::value<string>(&vwparams), "vw parameters for model instantiation (-i model ...)")
                ;

        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);

        if (vm.count("help")) {
                cout << desc << "\n";
                return 1;
        }

        if (blacklistfilename.empty() || userfilename.empty() || itemfilename.empty() || vwparams.empty())
        {
                cout << desc << "\n";
                exit(2);
        }

        FILE * fB;
        FILE * fU;
        FILE * fI;

        if((fB = fopen(blacklistfilename.c_str(), "r")) == NULL)
        {
                fprintf(stderr,"can't open %s: %s\n", blacklistfilename.c_str(), strerror(errno));
                cerr << desc << endl;
                exit(2);
        }
        if((fU = fopen(userfilename.c_str(), "r")) == NULL )
        {
                fprintf(stderr,"can't open %s: %s\n", userfilename.c_str(), strerror(errno));
                cerr << desc << endl;
                exit(2);
        }
        if((fI = fopen(itemfilename.c_str(), "r")) == NULL )
        {
                fprintf(stderr,"can't open %s: %s\n", itemfilename.c_str(), strerror(errno));
                cerr << desc << endl;
                exit(2);
        }

        char * buf = NULL;
        char * u = NULL;
        char * i = NULL;
        size_t len = 0;
        ssize_t read;

        /* make the bloom filter */
        if(verbose>0)
                fprintf(stderr, "loading blacklist into bloom filter...\n");
        char *bf= bf_new(b);

        /* loop over the source file */
        while ((read = getline(&buf,&len,fB)) != -1)
        {
                bf_add(bf,buf);
                banned++;
        }

        /* print saturation etc */
        if (verbose)
        {
                bf_info(bf,stderr);
                fprintf(stderr, "%d banned pairs\n", banned);
        }

        // INITIALIZE WITH WHATEVER YOU WOULD PUT ON THE VW COMMAND LINE
        if(verbose>0)
                fprintf(stderr, "initializing vw...\n");
        vw* model = VW::initialize(vwparams);

        char * estr = NULL;

        if(verbose>0)
        {
                fprintf(stderr, "predicting...\n");
                fprintf(stderr, "%12s %8s %8s %8s %12s %s %s\n", "pair", "user", "item", "rec", "skipped", "userfile", "itemfile");
        }
        while ((read = getline(&u, &len, fU)) != -1)
        {
                users++;
                u[strlen(u)-1] = 0; // chop
                rewind(fI);
                items=0;
                while ((read = getline(&i, &len, fI)) != -1)
                {
                        items++;
                        pairs++;

                        if((verbose > 0) & (pairs % show == 0))
                        {
                                progress();
                                show *= 2;
                        }

                        free(estr);
                        estr = strdup((string(u)+string(i)).c_str());

                        if (!bf_hit(bf,estr))
                        {
                                example *ex = VW::read_example(*model, estr);
                                model->learn(ex);

                                const string str(estr);

                                if(pr_queue.size() < topk)
                                {
                                        pr_queue.push(make_pair(ex->final_prediction, str));
                                }
                                else if(pr_queue.top().first < ex->final_prediction)
                                {
                                        pr_queue.pop();
                                        pr_queue.push(make_pair(ex->final_prediction, str));
                                }

                                VW::finish_example(*model, ex);
                        }
                        else
                        {
                                skipped++;
                                if(verbose>=2)
                                        fprintf(stderr,"skipping:#%s#\n", estr);
                        }

                }

                while(!pr_queue.empty())
                {
                        cout << pr_queue.top().first << "\t" << pr_queue.top().second;
                        pr_queue.pop();
                        recs++;
                }
        }
        if(verbose>0)
        {
                progress();
        }

        VW::finish(*model);
        fclose(fI);
        fclose(fU);
        exit(EXIT_SUCCESS);
        }
        catch(exception & e)
        {
                cout << e.what();
                return 0;
        }

}

<|endoftext|>


<commit_before>#include "button.h"

#include "const.h"
#include "logger.h"
#include "bluetooth.h"

namespace button {
  namespace {
    //Stores the value of the button pressed or depressed
    const uint8_t BUTTON_NONE = 65;
    volatile uint8_t buttonPressed = BUTTON_NONE;

    //Method to call when the the interrupt pin is falling
    void isr() {

      buttonPressed = 0;

      for (int i = 0; i < 8; i++) {

        //Wait for clock to go high
        while (digitalRead(constants::P_BUTTON_CLOCK) == LOW);

        //If value is high add one
        buttonPressed = buttonPressed + digitalRead(constants::P_BUTTON_DATA);

        //If not last time in loop, shift bits
        if (i != 7) {
          buttonPressed = buttonPressed << 1;
        }

        //Wait for clock to go low
        while (digitalRead(constants::P_BUTTON_CLOCK) == HIGH);
      }

      buttonPressed -= 1;

      if (buttonPressed > 64) {
        buttonPressed -= 128;
        bluetooth::sendPacket(bluetooth::C_BUTTON_PRESS + String(buttonPressed));
        logger::log(logger::TYPE_INFO, "button", "Button pressed : " + String(buttonPressed));
      }
    }
  }

  //Checks whether the button got pressed
  bool isPressed(uint8_t buttonToCheck) {
    //If not button shield wait two seconds and return true
    if (not constants::IS_BUTTON_SHIELD_CONNECTED) {
      delay(2000);
      return true;
    }

    //If button pressed is the button to check return true
    if (buttonPressed == buttonToCheck) {
      return true;
    }
    return false;
  }

  void clearLast() {
    buttonPressed = BUTTON_NONE;
  }

  void setup() {
    attachInterrupt(digitalPinToInterrupt(constants::P_BUTTON_INTERRUPT), isr, FALLING); //Attach interrupt for 64 button shield
  }
}
<commit_msg>Fix bug where button is called twice - untested<commit_after>#include "button.h"

#include "const.h"
#include "logger.h"
#include "bluetooth.h"

namespace button {
  namespace {
    //Stores the value of the button pressed or depressed
    const int8_t BUTTON_NONE = -1;
    volatile int8_t buttonPressed = BUTTON_NONE;

    //Method to call when the the interrupt pin is falling
    void isr() {

      uint8_t button = 0;

      for (int i = 0; i < 8; i++) {

        while (digitalRead(constants::P_BUTTON_CLOCK) == LOW);  //Wait for clock to go high

        buttonPressed = buttonPressed + digitalRead(constants::P_BUTTON_DATA);  //If value is high add one

        //If not last time in loop, shift bits
        if (i != 7) {
          buttonPressed = buttonPressed << 1;
        }

        while (digitalRead(constants::P_BUTTON_CLOCK) == HIGH);  //Wait for clock to go low
      }

      if (button > 64) {  // If button pressed
        buttonPressed = button - 129 ;
        bluetooth::sendPacket(bluetooth::C_BUTTON_PRESS + String(buttonPressed));
      }
    }
  }

  //Checks whether the button got pressed
  bool isPressed(uint8_t buttonToCheck) {
    //If not button shield wait two seconds and return true
    if (not constants::IS_BUTTON_SHIELD_CONNECTED) {
      delay(2000);
      return true;
    }

    //If button pressed is the button to check return true
    if (buttonPressed == buttonToCheck) {
      return true;
    }
    return false;
  }

  void clearLast() {
    buttonPressed = BUTTON_NONE;
  }

  void setup() {
    attachInterrupt(digitalPinToInterrupt(constants::P_BUTTON_INTERRUPT), isr, FALLING); //Attach interrupt for 64 button shield
  }
}
<|endoftext|>


<commit_before>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("before read secretfile \n");
    init_time_at(time,"# read Secret file",t);

    Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
	print_time(time,"# ... took :");
    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    print_time(time,"# ... took :");
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
	print_time(time,"# ... took :");

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,0);
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
		redistribute_tf(M,P,pp,F,A,0);
	}
	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++)printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size()-2;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf(" before pass = %d  at %d  tiles  \n",i,starter);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        /*
        for (int jj=starter; jj<F.NUsedplate; jj++) {
            int js = A.suborder[jj];
            assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF
            assign_unused(js,M,P,pp,F,A);
        }
         */
        //update target information for interval i

        for (int jj=starter; jj<update_intervals[i+1]; jj++) {
            printf(" jj  %d \n",jj);
        }
    }

    /*
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A); else printf("\n no update\n");

        redistribute_tf(M,P,pp,F,A,starter);
        improve(M,P,pp,F,A,starter);
        redistribute_tf(M,P,pp,F,A,starter);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);

    // check on SS and SF
/*
    for(int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }

    }
     */

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<commit_msg>diagnostic<commit_after>#include	<cstdlib>
#include	<cmath>
#include	<fstream>
#include	<sstream>
#include	<iostream>
#include	<iomanip>
#include	<string>
#include	<vector>
#include	<algorithm>
#include	<exception>
#include	<sys/time.h>
#include	"modules/htmTree.h"
#include	"modules/kdTree.h"
#include        "misc.h"
#include        "feat.h"
#include        "structs.h"
#include        "collision.h"
#include        "global.h"
//reduce redistributes, updates  07/02/15 rnc
int main(int argc, char **argv) {
	//// Initializations ---------------------------------------------
	srand48(1234); // Make sure we have reproducability
	check_args(argc);
	Time t, time; // t for global, time for local
	init_time(t);
	Feat F;
    MTL M;

	// Read parameters file //
	F.readInputFile(argv[1]);
	printFile(argv[1]);
	// Read Secretfile
    // Secret contains the identity of each target: QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF
    Gals Secret;
    printf("before read secretfile \n");
    init_time_at(time,"# read Secret file",t);

    Secret=read_Secretfile(F.Secretfile,F);
    printf("# Read %d galaxies from %s \n",Secret.size(),F.Secretfile.c_str());
	print_time(time,"# ... took :");
    std::vector<int> count;
    count=count_galaxies(Secret);
    printf(" Number of galaxies by type, QSO-Ly-a, QSO-tracers, LRG, ELG, fake QSO, fake LRG, SS, SF\n");
    for(int i=0;i<8;i++){printf (" type %d number  %d  \n",i, count[i]);}
    //read the three input files
    init_time_at(time,"# read target, SS, SF files",t);
    MTL Targ=read_MTLfile(F.Targfile,F,0,0);
    MTL SStars=read_MTLfile(F.SStarsfile,F,1,0);
    MTL SkyF=read_MTLfile(F.SkyFfile,F,0,1);
    print_time(time,"# ... took :");
    //combine the three input files

    M=Targ;

    printf(" M size %d \n",M.size());
    M.insert(M.end(),SStars.begin(),SStars.end());
    printf(" M size %d \n",M.size());
    M.insert(M.end(),SkyF.begin(),SkyF.end());
    printf(" M size %d \n",M.size());
    F.Ngal=M.size();
    assign_priority_class(M);

    //establish priority classes
    init_time_at(time,"# establish priority clasess",t);
    std::vector <int> count_class(M.priority_list.size(),0);
    for(int i;i<M.size();++i){
        if(!M[i].SS&&!M[i].SF){
        count_class[M[i].priority_class]+=1;
        }
    }
	print_time(time,"# ... took :");

    for(int i;i<M.priority_list.size();++i){
        printf("  class  %d  number  %d\n",i,count_class[i]);
    }

    PP pp;
	pp.read_fiber_positions(F);
	F.Nfiber = pp.fp.size()/2;
	F.Npetal = max(pp.spectrom)+1;
    F.Nfbp = (int) (F.Nfiber/F.Npetal);// fibers per petal = 500
	pp.get_neighbors(F); pp.compute_fibsofsp(F);

    //P is original list of plates
	Plates P = read_plate_centers(F);

    printf(" future plates %d\n",P.size());
    F.Nplate=P.size();
	printf("# Read %s plate centers from %s and %d fibers from %s\n",f(F.Nplate).c_str(),F.tileFile.c_str(),F.Nfiber,F.fibFile.c_str());

	// Computes geometries of cb and fh: pieces of positioner - used to determine possible collisions
	F.cb = create_cb(); // cb=central body
	F.fh = create_fh(); // fh=fiber holder

	//// Collect available galaxies <-> tilefibers --------------------
	// HTM Tree of galaxies
	const double MinTreeSize = 0.01;
	init_time_at(time,"# Start building HTM tree",t);
	htmTree<struct target> T(M,MinTreeSize);
	print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect galaxies at ",t);

	// For plates/fibers, collect available galaxies; done in parallel
    collect_galaxies_for_all(M,T,P,pp,F);
    print_time(time,"# ... took :");//T.stats();
    init_time_at(time,"# collect available tile-fibers at",t);
	// For each galaxy, computes available tilefibers  G[i].av_tfs = [(j1,k1),(j2,k2),..]
	collect_available_tilefibers(M,P,F);

	//results_on_inputs("doc/figs/",G,P,F,true);

	//// Assignment |||||||||||||||||||||||||||||||||||||||||||||||||||
    printf(" Nplate %d  Ngal %d   Nfiber %d \n", F.Nplate, F.Ngal, F.Nfiber);
    Assignment A(M,F);

	print_time(t,"# Start assignment at : ");

	// Make a plan ----------------------------------------------------
    // Plans whole survey without sky fibers, standard stars
    // assumes maximum number of observations needed for QSOs, LRGs

    simple_assign(M,P,pp,F,A);

    //check to see if there are tiles with no galaxies
    //need to keep mapping of old tile list to new tile list
    //and inverse map
    A.inv_order=initList(F.Nplate,0);
    for (int j=0;j<F.Nplate ;++j){
        bool not_done=true;
        for(int k=0;k<F.Nfiber && not_done;++k){
            if(A.TF[j][k]!=-1){
                A.suborder.push_back(j);
                not_done=false;

            }
        }
    }
    F.NUsedplate=A.suborder.size();
    printf(" Plates after screening %d \n",F.NUsedplate);

    //if(F.diagnose)diagnostic(M,G,F,A);

    print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false); // Hist of unused fibs

	// Smooth out distribution of free fibers, and increase the number of assignments

	for (int i=0; i<1; i++) redistribute_tf(M,P,pp,F,A,0);// more iterations will improve performance slightly
	for (int i=0; i<1; i++) {
        improve(M,P,pp,F,A,0);
		redistribute_tf(M,P,pp,F,A,0);
	}
	print_hist("Unused fibers",5,histogram(A.unused_fbp(pp,F),5),false);
    //try assigning SF and SS before real time assignment
    for (int j=0;j<F.NUsedplate;++j){

        int js=A.suborder[j];
        assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF for each tile
        assign_unused(js,M,P,pp,F,A);
    }
    if(F.diagnose)diagnostic(M,Secret,F,A);
    init_time_at(time,"# Begin real time assignment",t);

	//Execute plan, updating targets at intervals
    for(int i=0;i<F.pass_intervals.size();i++)printf(" i=%d interval %d \n",i,F.pass_intervals[i]);
    std::vector <int> update_intervals=F.pass_intervals;
    update_intervals.push_back(F.NUsedplate);//to end intervals at last plate
    for(int i=0;i<update_intervals.size()-1;++i){//go plate by used plate
        int starter=update_intervals[i];
        printf(" before pass = %d  at %d  tiles  \n",i,starter);
        //display_results("doc/figs/",G,P,pp,F,A,true);
        //plan whole survey from this point out
        /*
        for (int jj=starter; jj<F.NUsedplate; jj++) {
            int js = A.suborder[jj];
            assign_sf_ss(js,M,P,pp,F,A); // Assign SS and SF
            assign_unused(js,M,P,pp,F,A);
        }
         */
        //update target information for interval i

        for (int jj=starter; jj<update_intervals[i+1]; jj++) {
            printf(" jj  %d \n",jj);
        }
    }

    /*
            // Update corrects all future occurrences of wrong QSOs etc and tries to observe something else
            if (0<=jj-F.Analysis) update_plan_from_one_obs(jj,Secret,M,P,pp,F,A); else printf("\n no update\n");

        redistribute_tf(M,P,pp,F,A,starter);
        improve(M,P,pp,F,A,starter);
        redistribute_tf(M,P,pp,F,A,starter);
        //}

        if(F.diagnose)diagnostic(M,Secret,F,A);

    // check on SS and SF
/*
    for(int j=0;j<F.NUsedplate;++j){
        int js=A.suborder[j];
        printf("\n js = %d\n",js);
        for (int p=0;p<F.Npetal;++p){
            int count_SS=0;
            int count_SF=0;
            for (int k=0;k<F.Nfbp;++k){
                int kk=pp.fibers_of_sp[p][k];
                int g=A.TF[js][kk];
                if(g!=-1 && M[g].SS)count_SS++;
                if(g!=-1 && M[g].SF)count_SF++;

            }
            printf("  %d  %d   ",count_SS,count_SF);
        }
        printf("\n");
    }

    }
     */

	// Results -------------------------------------------------------
    if (F.PrintAscii) for (int j=0; j<F.NUsedplate; j++){
        write_FAtile_ascii(A.suborder[j],F.outDir,M,P,pp,F,A);
    }

    if (F.PrintFits) for (int j=0; j<F.NUsedplate; j++){
        fa_write(A.suborder[j],F.outDir,M,P,pp,F,A); // Write output
    }

	display_results("doc/figs/",Secret,M,P,pp,F,A,true);
	if (F.Verif) A.verif(P,M,pp,F); // Verification that the assignment is sane

	print_time(t,"# Finished !... in");

	return(0);

}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2020 The Bitcoin Core developers
// Copyright (c) 2020 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "fs.h"

#ifndef WIN32
#include <fcntl.h>
#else
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <codecvt>
#include <windows.h>
#endif

namespace fsbridge {

FILE *fopen(const fs::path& p, const char *mode)
{
#ifndef WIN32
    return ::fopen(p.string().c_str(), mode);
#else
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
    return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
#endif
}

#ifndef WIN32

static std::string GetErrorReason() {
    return std::strerror(errno);
}

FileLock::FileLock(const fs::path& file)
{
    fd = open(file.string().c_str(), O_RDWR);
    if (fd == -1) {
        reason = GetErrorReason();
    }
}

FileLock::~FileLock()
{
    if (fd != -1) {
        close(fd);
    }
}

bool FileLock::TryLock()
{
    if (fd == -1) {
        return false;
    }
    struct flock lock;
    lock.l_type = F_WRLCK;
    lock.l_whence = SEEK_SET;
    lock.l_start = 0;
    lock.l_len = 0;
    if (fcntl(fd, F_SETLK, &lock) == -1) {
        reason = GetErrorReason();
        return false;
    }
    return true;
}
#else

static std::string GetErrorReason() {
    wchar_t* err;
    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<WCHAR*>(&err), 0, nullptr);
    std::wstring err_str(err);
    LocalFree(err);
    return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(err_str);
}

FileLock::FileLock(const fs::path& file)
{
    hFile = CreateFileW(file.wstring().c_str(),  GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
    if (hFile == INVALID_HANDLE_VALUE) {
        reason = GetErrorReason();
    }
}

FileLock::~FileLock()
{
    if (hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(hFile);
    }
}

bool FileLock::TryLock()
{
    if (hFile == INVALID_HANDLE_VALUE) {
        return false;
    }
    _OVERLAPPED overlapped = {0};
    if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
        reason = GetErrorReason();
        return false;
    }
    return true;
}
#endif

std::string get_filesystem_error_message(const fs::filesystem_error& e)
{
#ifndef WIN32
    return e.what();
#else
    // Convert from Multi Byte to utf-16
    std::string mb_string(e.what());
    int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);

    std::wstring utf16_string(size, L'\0');
    MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
    // Convert from utf-16 to utf-8
    return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
#endif
}

#ifdef WIN32
#ifdef __GLIBCXX__

// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270

static std::string openmodeToStr(std::ios_base::openmode mode)
{
    switch (mode & ~std::ios_base::ate) {
    case std::ios_base::out:
    case std::ios_base::out | std::ios_base::trunc:
        return "w";
    case std::ios_base::out | std::ios_base::app:
    case std::ios_base::app:
        return "a";
    case std::ios_base::in:
        return "r";
    case std::ios_base::in | std::ios_base::out:
        return "r+";
    case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
        return "w+";
    case std::ios_base::in | std::ios_base::out | std::ios_base::app:
    case std::ios_base::in | std::ios_base::app:
        return "a+";
    case std::ios_base::out | std::ios_base::binary:
    case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
        return "wb";
    case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
    case std::ios_base::app | std::ios_base::binary:
        return "ab";
    case std::ios_base::in | std::ios_base::binary:
        return "rb";
    case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
        return "r+b";
    case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
        return "w+b";
    case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
    case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
        return "a+b";
    default:
        return std::string();
    }
}

void ifstream::open(const fs::path& p, std::ios_base::openmode mode)
{
    close();
    m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
    if (m_file == nullptr) {
        return;
    }
    m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
    rdbuf(&m_filebuf);
    if (mode & std::ios_base::ate) {
        seekg(0, std::ios_base::end);
    }
}

void ifstream::close()
{
    if (m_file != nullptr) {
        m_filebuf.close();
        fclose(m_file);
    }
    m_file = nullptr;
}

void ofstream::open(const fs::path& p, std::ios_base::openmode mode)
{
    close();
    m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
    if (m_file == nullptr) {
        return;
    }
    m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
    rdbuf(&m_filebuf);
    if (mode & std::ios_base::ate) {
        seekp(0, std::ios_base::end);
    }
}

void ofstream::close()
{
    if (m_file != nullptr) {
        m_filebuf.close();
        fclose(m_file);
    }
    m_file = nullptr;
}
#else // __GLIBCXX__

static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
    "Warning: This build is using boost::filesystem ofstream and ifstream "
    "implementations which will fail to open paths containing multibyte "
    "characters. You should delete this static_assert to ignore this warning, "
    "or switch to a different C++ standard library like the Microsoft C++ "
    "Standard Library (where boost uses non-standard extensions to construct "
    "stream objects with wide filenames), or the GNU libstdc++ library (where "
    "a more complicated workaround has been implemented above).");

#endif // __GLIBCXX__
#endif // WIN32

} // fsbridge
<commit_msg>Fix WSL file locking by using flock instead of fcntl<commit_after>// Copyright (c) 2017-2020 The Bitcoin Core developers
// Copyright (c) 2020 The PIVX developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "fs.h"

#ifndef WIN32
#include <fcntl.h>
#include <string>
#include <sys/file.h>
#include <sys/utsname.h>
#else
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <codecvt>
#include <windows.h>
#endif

namespace fsbridge {

FILE *fopen(const fs::path& p, const char *mode)
{
#ifndef WIN32
    return ::fopen(p.string().c_str(), mode);
#else
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>,wchar_t> utf8_cvt;
    return ::_wfopen(p.wstring().c_str(), utf8_cvt.from_bytes(mode).c_str());
#endif
}

#ifndef WIN32

static std::string GetErrorReason() {
    return std::strerror(errno);
}

FileLock::FileLock(const fs::path& file)
{
    fd = open(file.string().c_str(), O_RDWR);
    if (fd == -1) {
        reason = GetErrorReason();
    }
}

FileLock::~FileLock()
{
    if (fd != -1) {
        close(fd);
    }
}

static bool IsWSL()
{
    struct utsname uname_data;
    return uname(&uname_data) == 0 && std::string(uname_data.version).find("Microsoft") != std::string::npos;
}

bool FileLock::TryLock()
{
    if (fd == -1) {
        return false;
    }

    // Exclusive file locking is broken on WSL using fcntl (issue #18622)
    // This workaround can be removed once the bug on WSL is fixed
    static const bool is_wsl = IsWSL();
    if (is_wsl) {
        if (flock(fd, LOCK_EX | LOCK_NB) == -1) {
            reason = GetErrorReason();
            return false;
        }
    } else {
        struct flock lock;
        lock.l_type = F_WRLCK;
        lock.l_whence = SEEK_SET;
        lock.l_start = 0;
        lock.l_len = 0;
        if (fcntl(fd, F_SETLK, &lock) == -1) {
            reason = GetErrorReason();
            return false;
        }
    }

    return true;
}
#else

static std::string GetErrorReason() {
    wchar_t* err;
    FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
        nullptr, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<WCHAR*>(&err), 0, nullptr);
    std::wstring err_str(err);
    LocalFree(err);
    return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>>().to_bytes(err_str);
}

FileLock::FileLock(const fs::path& file)
{
    hFile = CreateFileW(file.wstring().c_str(),  GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
    if (hFile == INVALID_HANDLE_VALUE) {
        reason = GetErrorReason();
    }
}

FileLock::~FileLock()
{
    if (hFile != INVALID_HANDLE_VALUE) {
        CloseHandle(hFile);
    }
}

bool FileLock::TryLock()
{
    if (hFile == INVALID_HANDLE_VALUE) {
        return false;
    }
    _OVERLAPPED overlapped = {0};
    if (!LockFileEx(hFile, LOCKFILE_EXCLUSIVE_LOCK | LOCKFILE_FAIL_IMMEDIATELY, 0, std::numeric_limits<DWORD>::max(), std::numeric_limits<DWORD>::max(), &overlapped)) {
        reason = GetErrorReason();
        return false;
    }
    return true;
}
#endif

std::string get_filesystem_error_message(const fs::filesystem_error& e)
{
#ifndef WIN32
    return e.what();
#else
    // Convert from Multi Byte to utf-16
    std::string mb_string(e.what());
    int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);

    std::wstring utf16_string(size, L'\0');
    MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
    // Convert from utf-16 to utf-8
    return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
#endif
}

#ifdef WIN32
#ifdef __GLIBCXX__

// reference: https://github.com/gcc-mirror/gcc/blob/gcc-7_3_0-release/libstdc%2B%2B-v3/include/std/fstream#L270

static std::string openmodeToStr(std::ios_base::openmode mode)
{
    switch (mode & ~std::ios_base::ate) {
    case std::ios_base::out:
    case std::ios_base::out | std::ios_base::trunc:
        return "w";
    case std::ios_base::out | std::ios_base::app:
    case std::ios_base::app:
        return "a";
    case std::ios_base::in:
        return "r";
    case std::ios_base::in | std::ios_base::out:
        return "r+";
    case std::ios_base::in | std::ios_base::out | std::ios_base::trunc:
        return "w+";
    case std::ios_base::in | std::ios_base::out | std::ios_base::app:
    case std::ios_base::in | std::ios_base::app:
        return "a+";
    case std::ios_base::out | std::ios_base::binary:
    case std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
        return "wb";
    case std::ios_base::out | std::ios_base::app | std::ios_base::binary:
    case std::ios_base::app | std::ios_base::binary:
        return "ab";
    case std::ios_base::in | std::ios_base::binary:
        return "rb";
    case std::ios_base::in | std::ios_base::out | std::ios_base::binary:
        return "r+b";
    case std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary:
        return "w+b";
    case std::ios_base::in | std::ios_base::out | std::ios_base::app | std::ios_base::binary:
    case std::ios_base::in | std::ios_base::app | std::ios_base::binary:
        return "a+b";
    default:
        return std::string();
    }
}

void ifstream::open(const fs::path& p, std::ios_base::openmode mode)
{
    close();
    m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
    if (m_file == nullptr) {
        return;
    }
    m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
    rdbuf(&m_filebuf);
    if (mode & std::ios_base::ate) {
        seekg(0, std::ios_base::end);
    }
}

void ifstream::close()
{
    if (m_file != nullptr) {
        m_filebuf.close();
        fclose(m_file);
    }
    m_file = nullptr;
}

void ofstream::open(const fs::path& p, std::ios_base::openmode mode)
{
    close();
    m_file = fsbridge::fopen(p, openmodeToStr(mode).c_str());
    if (m_file == nullptr) {
        return;
    }
    m_filebuf = __gnu_cxx::stdio_filebuf<char>(m_file, mode);
    rdbuf(&m_filebuf);
    if (mode & std::ios_base::ate) {
        seekp(0, std::ios_base::end);
    }
}

void ofstream::close()
{
    if (m_file != nullptr) {
        m_filebuf.close();
        fclose(m_file);
    }
    m_file = nullptr;
}
#else // __GLIBCXX__

static_assert(sizeof(*fs::path().BOOST_FILESYSTEM_C_STR) == sizeof(wchar_t),
    "Warning: This build is using boost::filesystem ofstream and ifstream "
    "implementations which will fail to open paths containing multibyte "
    "characters. You should delete this static_assert to ignore this warning, "
    "or switch to a different C++ standard library like the Microsoft C++ "
    "Standard Library (where boost uses non-standard extensions to construct "
    "stream objects with wide filenames), or the GNU libstdc++ library (where "
    "a more complicated workaround has been implemented above).");

#endif // __GLIBCXX__
#endif // WIN32

} // fsbridge
<|endoftext|>


<commit_before>//@ {"targets":[{"name":"serializer.hpp","type":"include"}]}

#ifndef TEMPLE_SERIALIZER_HPP
#define TEMPLE_SERIALIZER_HPP

#include "item.hpp"
#include "treenode.hpp"
#include <stack>

namespace Temple
	{
	namespace
		{
		template<class Callback>
		class VisitorBase
			{
			public:
				virtual bool atEnd() const noexcept=0;
				virtual void advance() noexcept=0;
				virtual void itemProcess(Callback& cb) const=0;
				virtual ~VisitorBase()=default;
				char terminator() const noexcept
					{return m_terminator;}
				size_t size() const noexcept
					{return m_size;}
			protected:
				explicit VisitorBase(char term,size_t size) noexcept:
					m_terminator(term),m_size(size)
					{}

			private:
				char m_terminator;
				size_t m_size;
			};

		template<class Callback,class Container>
		class Visitor:public VisitorBase<Callback>
			{
			public:
				explicit Visitor(Container&&)=delete;
				explicit Visitor(const Container& container,char term):
					 VisitorBase<Callback>(term,container.size())
					,m_begin(container.begin())
					,m_current(container.begin())
					,m_end(container.end())
					{}

				bool atEnd() const noexcept
					{return m_current==m_end;}

				bool atBegin() const noexcept
					{return m_current==m_begin;}

				void advance() noexcept
					{++m_current;}

				void itemProcess(Callback& cb) const
					{cb(*m_current,*this);}

				static auto create(const Container& cnt,char term)
					{return std::unique_ptr<VisitorBase<Callback>>(new Visitor(cnt,term));}

			private:
				typename Container::const_iterator m_begin;
				typename Container::const_iterator m_current;
				typename Container::const_iterator m_end;
			};

		template<class Sink>
		void indent(size_t level,Sink& sink)
			{
			assert(level!=0);
			--level;
			while(level!=0)
				{
				putc('\t',sink);
				--level;
				}
			}

		template<class CharType,class Sink>
		void write(const CharType* src,Sink& sink)
			{
			while(true)
				{
				auto ch_in=*src;
				if(ch_in=='\0')
					{return;}
				if(ch_in=='\\' || ch_in=='\"')
					{putc('\\',sink);}
				putc(ch_in,sink);
				++src;
				}
			}

		template<class StorageModel,class Sink>
		void write(const typename StorageModel::StringType& string,Sink& sink)
			{
			putc('"',sink);
			write(string.c_str(),sink);
			putc('"',sink);
			}

		template<class StorageModel,class T,class Sink,std::enable_if_t<std::is_arithmetic<T>::value,int> a=0>
		void write(T x,Sink& sink)
			{write(convert<std::string>(x).c_str(),sink);}

		template<class StorageModel,class T,class Sink>
		void write(const typename StorageModel::template ArrayType<T>& array,Sink& sink)
			{
			putc('[',sink);
			auto ptr=array.begin();
			auto ptr_end=array.end();
			if(ptr!=ptr_end)
				{
				write<StorageModel>(*ptr,sink);
				++ptr;
				}
			while(ptr!=ptr_end)
				{
				putc(',',sink);
				write<StorageModel>(*ptr,sink);
				++ptr;
				}

			putc(']',sink);
			}

		template<class StorageModel,class Sink>
		class Acceptor
			{
			public:
				using MapType=typename StorageModel::template MapType< std::unique_ptr< ItemBase<StorageModel> > > ;
				using CompoundArray=typename StorageModel::template ArrayType<MapType>;

				using VisitorArray=Visitor<Acceptor,CompoundArray>;
				using VisitorMap=Visitor<Acceptor,MapType>;

				explicit Acceptor(ItemBase<StorageModel>&&)=delete;

				explicit Acceptor(const ItemBase<StorageModel>& root,Sink& sink):r_sink(sink)
					{
					if(root.array())
						{m_stack.push(VisitorArray::create(root.template value<CompoundArray>(),']') );}
					else
						{m_stack.push(VisitorMap::create(root.template value<MapType>(),'}'));}
					}

				void run()
					{
					while(!m_stack.empty())
						{
						auto& visitor=m_stack.top();
						if(visitor->atEnd())
							{
							if(visitor->size()>1
								|| (visitor->terminator()==']' && visitor->size()!=0))
								{indent(m_stack.size(),r_sink);}
							putc(visitor->terminator(),r_sink);
							putc('\n',r_sink);
							m_stack.pop();
							}
						else
							{
							visitor->itemProcess(*this);
							visitor->advance();
							}
						}
					}

				void operator()(const MapType& node_current,const VisitorArray& visitor)
					{
					indent(m_stack.size(),r_sink);
					putc(visitor.atBegin()?'[':',',r_sink);
					putc('\n',r_sink);
					m_stack.push(VisitorMap::create(node_current,'}'));
					}

				void operator()(const typename MapType::value_type& node_current,const VisitorMap& visitor)
					{
					indent(m_stack.size(),r_sink);
					if(visitor.size()==1)
						{putc('{',r_sink);}
					else
						{
						fputs(visitor.atBegin()?"{\n":",",r_sink);
						if(visitor.atBegin())
							{
							indent(m_stack.size(),r_sink);
							putc(' ',r_sink);
							}
						}
					putc('"',r_sink);
					write(node_current.first.c_str(),r_sink);
					auto type_current=node_current.second->type();
					fprintf(r_sink,"\",%s:",type(type_current));
					if(type_current==Type::COMPOUND)
						{
						auto node=VisitorMap::create(node_current.second->template value<MapType>(),'}');
						putc('\n',r_sink);
						if(node->atEnd())
							{
							indent(m_stack.size()+1,r_sink);
							putc('{',r_sink);
							}
						m_stack.push(std::move(node));
						}
					else
					if(type_current==Type::COMPOUND_ARRAY)
						{
						auto node=VisitorArray::create(node_current.second->template value<CompoundArray>(),']');
						putc('\n',r_sink);
						if(node->atEnd())
							{
							indent(m_stack.size()+1,r_sink);
							putc('[',r_sink);
							}
						m_stack.push(std::move(node));
						}
					else
						{
						for_type<StorageModel,Type::I8,1,Type::STRING_ARRAY>(type_current,[&node_current,this,&visitor](auto tag)
							{
							using TypeCurrent=typename decltype(tag)::type;
							auto& object=node_current.second->template value<TypeCurrent>();
							write<StorageModel>(object,this->r_sink);
							if(visitor.size()!=1)
								{putc('\n',this->r_sink);}
							});
						}
					}

			private:
				Sink& r_sink;
				std::stack< std::unique_ptr< VisitorBase<Acceptor> > > m_stack;
			};
		}

	template<class StorageModel,class Sink>
	void temple_store(const ItemBase<StorageModel>& root,Sink& sink)
		{
		Locale loc;
		Acceptor<StorageModel,Sink>(root,sink).run();
		}
	}

#endif
<commit_msg>whitespace after comma when writing arrays<commit_after>//@ {"targets":[{"name":"serializer.hpp","type":"include"}]}

#ifndef TEMPLE_SERIALIZER_HPP
#define TEMPLE_SERIALIZER_HPP

#include "item.hpp"
#include "treenode.hpp"
#include <stack>

namespace Temple
	{
	namespace
		{
		template<class Callback>
		class VisitorBase
			{
			public:
				virtual bool atEnd() const noexcept=0;
				virtual void advance() noexcept=0;
				virtual void itemProcess(Callback& cb) const=0;
				virtual ~VisitorBase()=default;
				char terminator() const noexcept
					{return m_terminator;}
				size_t size() const noexcept
					{return m_size;}
			protected:
				explicit VisitorBase(char term,size_t size) noexcept:
					m_terminator(term),m_size(size)
					{}

			private:
				char m_terminator;
				size_t m_size;
			};

		template<class Callback,class Container>
		class Visitor:public VisitorBase<Callback>
			{
			public:
				explicit Visitor(Container&&)=delete;
				explicit Visitor(const Container& container,char term):
					 VisitorBase<Callback>(term,container.size())
					,m_begin(container.begin())
					,m_current(container.begin())
					,m_end(container.end())
					{}

				bool atEnd() const noexcept
					{return m_current==m_end;}

				bool atBegin() const noexcept
					{return m_current==m_begin;}

				void advance() noexcept
					{++m_current;}

				void itemProcess(Callback& cb) const
					{cb(*m_current,*this);}

				static auto create(const Container& cnt,char term)
					{return std::unique_ptr<VisitorBase<Callback>>(new Visitor(cnt,term));}

			private:
				typename Container::const_iterator m_begin;
				typename Container::const_iterator m_current;
				typename Container::const_iterator m_end;
			};

		template<class Sink>
		void indent(size_t level,Sink& sink)
			{
			assert(level!=0);
			--level;
			while(level!=0)
				{
				putc('\t',sink);
				--level;
				}
			}

		template<class CharType,class Sink>
		void write(const CharType* src,Sink& sink)
			{
			while(true)
				{
				auto ch_in=*src;
				if(ch_in=='\0')
					{return;}
				if(ch_in=='\\' || ch_in=='\"')
					{putc('\\',sink);}
				putc(ch_in,sink);
				++src;
				}
			}

		template<class StorageModel,class Sink>
		void write(const typename StorageModel::StringType& string,Sink& sink)
			{
			putc('"',sink);
			write(string.c_str(),sink);
			putc('"',sink);
			}

		template<class StorageModel,class T,class Sink,std::enable_if_t<std::is_arithmetic<T>::value,int> a=0>
		void write(T x,Sink& sink)
			{write(convert<std::string>(x).c_str(),sink);}

		template<class StorageModel,class T,class Sink>
		void write(const typename StorageModel::template ArrayType<T>& array,Sink& sink)
			{
			putc('[',sink);
			auto ptr=array.begin();
			auto ptr_end=array.end();
			if(ptr!=ptr_end)
				{
				write<StorageModel>(*ptr,sink);
				++ptr;
				}
			while(ptr!=ptr_end)
				{
				fputs(", ",sink);
				write<StorageModel>(*ptr,sink);
				++ptr;
				}

			putc(']',sink);
			}

		template<class StorageModel,class Sink>
		class Acceptor
			{
			public:
				using MapType=typename StorageModel::template MapType< std::unique_ptr< ItemBase<StorageModel> > > ;
				using CompoundArray=typename StorageModel::template ArrayType<MapType>;

				using VisitorArray=Visitor<Acceptor,CompoundArray>;
				using VisitorMap=Visitor<Acceptor,MapType>;

				explicit Acceptor(ItemBase<StorageModel>&&)=delete;

				explicit Acceptor(const ItemBase<StorageModel>& root,Sink& sink):r_sink(sink)
					{
					if(root.array())
						{m_stack.push(VisitorArray::create(root.template value<CompoundArray>(),']') );}
					else
						{m_stack.push(VisitorMap::create(root.template value<MapType>(),'}'));}
					}

				void run()
					{
					while(!m_stack.empty())
						{
						auto& visitor=m_stack.top();
						if(visitor->atEnd())
							{
							if(visitor->size()>1
								|| (visitor->terminator()==']' && visitor->size()!=0))
								{indent(m_stack.size(),r_sink);}
							putc(visitor->terminator(),r_sink);
							putc('\n',r_sink);
							m_stack.pop();
							}
						else
							{
							visitor->itemProcess(*this);
							visitor->advance();
							}
						}
					}

				void operator()(const MapType& node_current,const VisitorArray& visitor)
					{
					indent(m_stack.size(),r_sink);
					putc(visitor.atBegin()?'[':',',r_sink);
					putc('\n',r_sink);
					m_stack.push(VisitorMap::create(node_current,'}'));
					}

				void operator()(const typename MapType::value_type& node_current,const VisitorMap& visitor)
					{
					indent(m_stack.size(),r_sink);
					if(visitor.size()==1)
						{putc('{',r_sink);}
					else
						{
						fputs(visitor.atBegin()?"{\n":",",r_sink);
						if(visitor.atBegin())
							{
							indent(m_stack.size(),r_sink);
							putc(' ',r_sink);
							}
						}
					putc('"',r_sink);
					write(node_current.first.c_str(),r_sink);
					auto type_current=node_current.second->type();
					fprintf(r_sink,"\",%s:",type(type_current));
					if(type_current==Type::COMPOUND)
						{
						auto node=VisitorMap::create(node_current.second->template value<MapType>(),'}');
						putc('\n',r_sink);
						if(node->atEnd())
							{
							indent(m_stack.size()+1,r_sink);
							putc('{',r_sink);
							}
						m_stack.push(std::move(node));
						}
					else
					if(type_current==Type::COMPOUND_ARRAY)
						{
						auto node=VisitorArray::create(node_current.second->template value<CompoundArray>(),']');
						putc('\n',r_sink);
						if(node->atEnd())
							{
							indent(m_stack.size()+1,r_sink);
							putc('[',r_sink);
							}
						m_stack.push(std::move(node));
						}
					else
						{
						for_type<StorageModel,Type::I8,1,Type::STRING_ARRAY>(type_current,[&node_current,this,&visitor](auto tag)
							{
							using TypeCurrent=typename decltype(tag)::type;
							auto& object=node_current.second->template value<TypeCurrent>();
							write<StorageModel>(object,this->r_sink);
							if(visitor.size()!=1)
								{putc('\n',this->r_sink);}
							});
						}
					}

			private:
				Sink& r_sink;
				std::stack< std::unique_ptr< VisitorBase<Acceptor> > > m_stack;
			};
		}

	template<class StorageModel,class Sink>
	void temple_store(const ItemBase<StorageModel>& root,Sink& sink)
		{
		Locale loc;
		Acceptor<StorageModel,Sink>(root,sink).run();
		}
	}

#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

#include <vector>
#include <string>

using namespace std;

int main(int argc, char** argv)
{
	bool aFlag = false;
	bool lFlag = false;
	bool RFlag = false;
	vector<string> fileParam;

	// Loops through arguments looking for flags/files/directories
	for(int i = 1; i < argc; ++i)
	{
		// Is a flag if first char of c-string is '-'
		if(argv[i][0] == '-')
		{
			// Accounts for flags like -laR, -lR, etc.
			for(int j = 1; argv[i][j] != '\n'; ++j)
			{
				if(argv[i][j] == 'a')
				{
					aFlag = true;
				}
				else if(argv[i][j] == 'l')
				{
					lFlag = true;
				}
				else if(argv[i][j] == 'R')
				{
					RFlag = true;
				}
				else
				{
					// If flag is neither 'l', 'a', nor 'R'
					cerr << "Error: Invalid flag" << endl;
					exit(1);
				}
			}
		}
		else
		{
			// Adds directories/files to vector
			fileParam.push_back(argv[i]);
		}
	}
	if(fileParam.size() == 0)
	{
		fileParam.push_back("."); // Current directory, if no others specified
	}

	return 0;
}
<commit_msg>Updated ls<commit_after>#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>

#include <vector>
#include <string>

using namespace std;

int main(int argc, char** argv)
{
	bool aFlag = false;
	bool lFlag = false;
	bool RFlag = false;
	vector<string> fileParam;

	// Loops through arguments looking for flags/files/directories
	for(int i = 1; i < argc; ++i)
	{
		// Is a flag if first char of c-string is '-'
		if(argv[i][0] == '-')
		{
			// Accounts for flags like -laR, -lR, etc.
			for(int j = 1; argv[i][j] != '\n'; ++j)
			{
				if(argv[i][j] == 'a')
				{
					aFlag = true;
				}
				else if(argv[i][j] == 'l')
				{
					lFlag = true;
				}
				else if(argv[i][j] == 'R')
				{
					RFlag = true;
				}
				else
				{
					// If flag is neither 'l', 'a', nor 'R'
					cerr << "Error: Invalid flag" << endl;
					exit(1);
				}
			}
		}
		else
		{
			// Adds directories/files to vector
			fileParam.push_back(argv[i]);
		}
	}
	if(fileParam.size() == 0)
	{
		fileParam.push_back("."); // Current directory, if no others specified
	}

	for(auto str : fileParam)
	{
		DIR* dirp;
		if(-1 == (dirp = opendir(str.c_str())))
		{
			perror("Error in opening directory");
			exit(1);
		}
	}

	return 0;
}
<|endoftext|>


<commit_before><commit_msg>WaE: overriding virtual function declaration not marked 'override'<commit_after><|endoftext|>