text:
/*
 * Software License Agreement (BSD License)
 *
 * Point Cloud Library (PCL) - www.pointclouds.org
 * Copyright (c) 2009-2012, Willow Garage, Inc.
 * Copyright (c) 2012-, Open Perception, Inc.
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above
 *    copyright notice, this list of conditions and the following
 *    disclaimer in the documentation and/or other materials provided
 *    with the distribution.
 *  * Neither the name of the copyright holder(s) nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 * $Id: mesh_base.hpp 7156 2012-09-17 15:59:12Z rusu $
 *
 */

#ifndef PCL_GEOMETRY_MESH_BASE_HPP
#define PCL_GEOMETRY_MESH_BASE_HPP

#include <assert.h>
#include <utility>

#include <boost/type_traits/conditional.hpp>

#include <pcl/geometry/eigen.h>
#include <pcl/geometry/mesh_element_index.h>
#include <pcl/geometry/impl/vertex.hpp>
#include <pcl/geometry/impl/half_edge.hpp>
#include <pcl/geometry/impl/face.hpp>
#include <pcl/geometry/impl/mesh_circulators.hpp>

namespace pcl
{

  // TODO: This could be put in pcl/common
  // http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
  template <class T>
  class HasEigenAlignedOperatorNew
  {
    private:

      typedef char Yes [1];
      typedef char No  [2];

      template <class U> static Yes&
      test (typename U::eigen_aligned_operator_new_marker_type*);

      template <class> static No&
      test (...);

    public:

      static const bool value = sizeof (test <T> (0)) == sizeof (Yes);
  };

} // End namespace pcl

namespace pcl
{

  struct EmptyVertexData   {bool operator == (const EmptyVertexData&  ) const {return (true);}};
  struct EmptyHalfEdgeData {bool operator == (const EmptyHalfEdgeData&) const {return (true);}};
  struct EmptyFaceData     {bool operator == (const EmptyFaceData&    ) const {return (true);}};

  template <class VertexDataT, class FaceDataT, class HalfEdgeDataT>
  class MeshBase
  {
    public:

      typedef pcl::MeshBase <VertexDataT, FaceDataT, HalfEdgeDataT> Self;

      typedef VertexDataT   VertexData;
      typedef HalfEdgeDataT HalfEdgeData;
      typedef FaceDataT     FaceData;

      typedef pcl::VertexIndex   VertexIndex;
      typedef pcl::HalfEdgeIndex HalfEdgeIndex;
      typedef pcl::FaceIndex     FaceIndex;

      typedef pcl::Vertex   <VertexData,   Self> Vertex;
      typedef pcl::HalfEdge <HalfEdgeData, Self> HalfEdge;
      typedef pcl::Face     <FaceData,     Self> Face;

      // TODO: Compare vector with deque
      typedef typename boost::conditional <pcl::HasEigenAlignedOperatorNew <Vertex>::value,   std::vector <Vertex,   Eigen::aligned_allocator <Vertex> >,   std::vector <Vertex> >::type   Vertexes;
      typedef typename boost::conditional <pcl::HasEigenAlignedOperatorNew <HalfEdge>::value, std::vector <HalfEdge, Eigen::aligned_allocator <HalfEdge> >, std::vector <HalfEdge> >::type HalfEdges;
      typedef typename boost::conditional <pcl::HasEigenAlignedOperatorNew <Face>::value,     std::vector <Face,     Eigen::aligned_allocator <Face> >,     std::vector <Face> >::type     Faces;

      typedef std::vector <VertexIndex>   VertexIndexes;
      typedef std::vector <HalfEdgeIndex> HalfEdgeIndexes;
      typedef std::vector <FaceIndex>     FaceIndexes;

      typedef typename Vertexes::size_type SizeType;

      // Iterators
      typedef typename Vertexes::iterator  VertexIterator;
      typedef typename HalfEdges::iterator HalfEdgeIterator;
      typedef typename Faces::iterator     FaceIterator;

      typedef typename Vertexes::const_iterator  VertexConstIterator;
      typedef typename HalfEdges::const_iterator HalfEdgeConstIterator;
      typedef typename Faces::const_iterator     FaceConstIterator;

      // Const iterators
      typedef typename VertexIndexes::iterator   VertexIndexIterator;
      typedef typename HalfEdgeIndexes::iterator HalfEdgeIndexIterator;
      typedef typename FaceIndexes::iterator     FaceIndexIterator;

      typedef typename VertexIndexes::const_iterator   VertexIndexConstIterator;
      typedef typename HalfEdgeIndexes::const_iterator HalfEdgeIndexConstIterator;
      typedef typename FaceIndexes::const_iterator     FaceIndexConstIterator;

      // Circulators
      typedef pcl::VertexAroundVertexCirculator           <Self> VertexAroundVertexCirculator;
      typedef pcl::OutgoingHalfEdgeAroundVertexCirculator <Self> OutgoingHalfEdgeAroundVertexCirculator;
      typedef pcl::IncomingHalfEdgeAroundVertexCirculator <Self> IncomingHalfEdgeAroundVertexCirculator;
      typedef pcl::FaceAroundVertexCirculator             <Self> FaceAroundVertexCirculator;
      typedef pcl::VertexAroundFaceCirculator             <Self> VertexAroundFaceCirculator;
      typedef pcl::InnerHalfEdgeAroundFaceCirculator      <Self> InnerHalfEdgeAroundFaceCirculator;
      typedef pcl::OuterHalfEdgeAroundFaceCirculator      <Self> OuterHalfEdgeAroundFaceCirculator;
      typedef pcl::FaceAroundFaceCirculator               <Self> FaceAroundFaceCirculator;
      typedef InnerHalfEdgeAroundFaceCirculator                  HalfEdgeAroundBoundaryCirculator;

      // Const circulators
      typedef pcl::VertexAroundVertexCirculator           <const Self> VertexAroundVertexConstCirculator;
      typedef pcl::OutgoingHalfEdgeAroundVertexCirculator <const Self> OutgoingHalfEdgeAroundVertexConstCirculator;
      typedef pcl::IncomingHalfEdgeAroundVertexCirculator <const Self> IncomingHalfEdgeAroundVertexConstCirculator;
      typedef pcl::FaceAroundVertexCirculator             <const Self> FaceAroundVertexConstCirculator;
      typedef pcl::VertexAroundFaceCirculator             <const Self> VertexAroundFaceConstCirculator;
      typedef pcl::InnerHalfEdgeAroundFaceCirculator      <const Self> InnerHalfEdgeAroundFaceConstCirculator;
      typedef pcl::OuterHalfEdgeAroundFaceCirculator      <const Self> OuterHalfEdgeAroundFaceConstCirculator;
      typedef pcl::FaceAroundFaceCirculator               <const Self> FaceAroundFaceConstCirculator;
      typedef InnerHalfEdgeAroundFaceConstCirculator                   HalfEdgeAroundBoundaryConstCirculator;

    public:

      MeshBase ()
        : vertexes_ (),
          half_edges_ (),
          faces_ ()
      {
      }

    public:

      //////////////////////////////////////////////////////////////////////////
      // Begin / End
      //////////////////////////////////////////////////////////////////////////

      VertexIterator        beginVertexes ()        {return (vertexes_.begin ());}
      VertexConstIterator   beginVertexes () const  {return (vertexes_.begin ());}

      VertexIterator        endVertexes ()          {return (vertexes_.end ());}
      VertexConstIterator   endVertexes () const    {return (vertexes_.end ());}

      HalfEdgeIterator      beginHalfEdges ()       {return (half_edges_.begin ());}
      HalfEdgeConstIterator beginHalfEdges () const {return (half_edges_.begin ());}

      HalfEdgeIterator      endHalfEdges ()         {return (half_edges_.end ());}
      HalfEdgeConstIterator endHalfEdges () const   {return (half_edges_.end ());}

      FaceIterator          beginFaces ()           {return (faces_.begin ());}
      FaceConstIterator     beginFaces () const     {return (faces_.begin ());}

      FaceIterator          endFaces ()             {return (faces_.end ());}
      FaceConstIterator     endFaces () const       {return (faces_.end ());}

      //////////////////////////////////////////////////////////////////////////
      // Front / Back
      //////////////////////////////////////////////////////////////////////////

      Vertex&         frontVertexes ()        {return (vertexes_.front ());}
      const Vertex&   frontVertexes () const  {return (vertexes_.front ());}

      Vertex&         backVertexes ()         {return (vertexes_.back ());}
      const Vertex&   backVertexes () const   {return (vertexes_.back ());}

      HalfEdge&       frontHalfEdges ()       {return (half_edges_.front ());}
      const HalfEdge& frontHalfEdges () const {return (half_edges_.front ());}

      HalfEdge&       backHalfEdges ()        {return (half_edges_.back ());}
      const HalfEdge& backHalfEdges () const  {return (half_edges_.back ());}

      Face&           frontFaces ()           {return (faces_.front ());}
      const Face&     frontFaces () const     {return (faces_.front ());}

      Face&           backFaces ()            {return (faces_.back ());}
      const Face&     backFaces () const      {return (faces_.back ());}

      //////////////////////////////////////////////////////////////////////////
      // Size
      //////////////////////////////////////////////////////////////////////////

      SizeType sizeVertexes () const  {return (vertexes_.size ());}
      SizeType sizeHalfEdges () const {return (half_edges_.size ());}
      SizeType sizeFaces () const     {return (faces_.size ());}

      //////////////////////////////////////////////////////////////////////////
      // empty
      //////////////////////////////////////////////////////////////////////////

      bool empty () {return (vertexes_.empty () && half_edges_.empty () && faces_.empty ());}

      //////////////////////////////////////////////////////////////////////////
      // Reserve
      //////////////////////////////////////////////////////////////////////////

      void reserveVertexes (const SizeType n)  {vertexes_.reserve (n);}
      void reserveHalfEdges (const SizeType n) {half_edges_.reserve (n);}
      void reserveFaces (const SizeType n)     {faces_.reserve (n);}

      //////////////////////////////////////////////////////////////////////////
      // Clear
      //////////////////////////////////////////////////////////////////////////

      void clear ()
      {
        vertexes_.clear ();
        half_edges_.clear ();
        faces_.clear ();
      }

      //////////////////////////////////////////////////////////////////////////
      // Get the mesh elements
      //////////////////////////////////////////////////////////////////////////

      const Vertex&
      getElement (const VertexIndex& idx_vertex) const
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        return (vertexes_ [idx_vertex.getIndex ()]);
      }

      Vertex&
      getElement (const VertexIndex& idx_vertex)
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        return (vertexes_ [idx_vertex.getIndex ()]);
      }

      const HalfEdge&
      getElement (const HalfEdgeIndex& idx_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_half_edge));
        return (half_edges_ [idx_half_edge.getIndex ()]);
      }

      HalfEdge&
      getElement (const HalfEdgeIndex& idx_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_half_edge));
        return (half_edges_ [idx_half_edge.getIndex ()]);
      }

      const Face&
      getElement (const FaceIndex& idx_face) const
      {
        assert (this->validateMeshElementIndex (idx_face));
        return (faces_ [idx_face.getIndex ()]);
      }

      Face&
      getElement (const FaceIndex& idx_face)
      {
        assert (this->validateMeshElementIndex (idx_face));
        return (faces_ [idx_face.getIndex ()]);
      }

      //////////////////////////////////////////////////////////////////////////
      // VertexAroundVertexCirculator
      //////////////////////////////////////////////////////////////////////////

      VertexAroundVertexCirculator
      getVertexAroundVertexCirculator (const Vertex& vertex)
      {
        assert (this->validateMeshElement (vertex));
        return (VertexAroundVertexCirculator (vertex, this));
      }

      VertexAroundVertexConstCirculator
      getVertexAroundVertexConstCirculator (const Vertex& vertex) const
      {
        assert (this->validateMeshElement (vertex));
        return (VertexAroundVertexConstCirculator (vertex, this));
      }

      VertexAroundVertexCirculator
      getVertexAroundVertexCirculator (const VertexIndex& idx_vertex)
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (VertexAroundVertexCirculator (idx_vertex, this));
      }

      VertexAroundVertexConstCirculator
      getVertexAroundVertexConstCirculator (const VertexIndex& idx_vertex) const
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (VertexAroundVertexConstCirculator (idx_vertex, this));
      }

      VertexAroundVertexCirculator
      getVertexAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (VertexAroundVertexCirculator (idx_outgoing_half_edge, this));
      }

      VertexAroundVertexConstCirculator
      getVertexAroundVertexConstCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (VertexAroundVertexConstCirculator (idx_outgoing_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // OutgoingHalfEdgeAroundVertexCirculator
      //////////////////////////////////////////////////////////////////////////

      OutgoingHalfEdgeAroundVertexCirculator
      getOutgoingHalfEdgeAroundVertexCirculator (const Vertex& vertex)
      {
        assert (this->validateMeshElement (vertex));
        return (OutgoingHalfEdgeAroundVertexCirculator (vertex, this));
      }

      OutgoingHalfEdgeAroundVertexConstCirculator
      getOutgoingHalfEdgeAroundVertexConstCirculator (const Vertex& vertex) const
      {
        assert (this->validateMeshElement (vertex));
        return (OutgoingHalfEdgeAroundVertexConstCirculator (vertex, this));
      }

      OutgoingHalfEdgeAroundVertexCirculator
      getOutgoingHalfEdgeAroundVertexCirculator (const VertexIndex& idx_vertex)
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (OutgoingHalfEdgeAroundVertexCirculator (idx_vertex, this));
      }

      OutgoingHalfEdgeAroundVertexConstCirculator
      getOutgoingHalfEdgeAroundVertexConstCirculator (const VertexIndex& idx_vertex) const
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (OutgoingHalfEdgeAroundVertexConstCirculator (idx_vertex, this));
      }

      OutgoingHalfEdgeAroundVertexCirculator
      getOutgoingHalfEdgeAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (OutgoingHalfEdgeAroundVertexCirculator (idx_outgoing_half_edge, this));
      }

      OutgoingHalfEdgeAroundVertexConstCirculator
      getOutgoingHalfEdgeAroundVertexConstCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (OutgoingHalfEdgeAroundVertexConstCirculator (idx_outgoing_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // IncomingHalfEdgeAroundVertexCirculator
      //////////////////////////////////////////////////////////////////////////

      IncomingHalfEdgeAroundVertexCirculator
      getIncomingHalfEdgeAroundVertexCirculator (const Vertex& vertex)
      {
        assert (this->validateMeshElement (vertex));
        return (IncomingHalfEdgeAroundVertexCirculator (vertex, this));
      }

      IncomingHalfEdgeAroundVertexConstCirculator
      getIncomingHalfEdgeAroundVertexConstCirculator (const Vertex& vertex) const
      {
        assert (this->validateMeshElement (vertex));
        return (IncomingHalfEdgeAroundVertexConstCirculator (vertex, this));
      }

      IncomingHalfEdgeAroundVertexCirculator
      getIncomingHalfEdgeAroundVertexCirculator (const VertexIndex& idx_vertex)
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (IncomingHalfEdgeAroundVertexCirculator (idx_vertex, this));
      }

      IncomingHalfEdgeAroundVertexConstCirculator
      getIncomingHalfEdgeAroundVertexConstCirculator (const VertexIndex& idx_vertex) const
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (IncomingHalfEdgeAroundVertexConstCirculator (idx_vertex, this));
      }

      IncomingHalfEdgeAroundVertexCirculator
      getIncomingHalfEdgeAroundVertexCirculator (const HalfEdgeIndex& idx_incoming_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_incoming_half_edge));
        return (IncomingHalfEdgeAroundVertexCirculator (idx_incoming_half_edge, this));
      }

      IncomingHalfEdgeAroundVertexConstCirculator
      getIncomingHalfEdgeAroundVertexConstCirculator (const HalfEdgeIndex& idx_incoming_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_incoming_half_edge));
        return (IncomingHalfEdgeAroundVertexConstCirculator (idx_incoming_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // FaceAroundVertexCirculator
      //////////////////////////////////////////////////////////////////////////

      FaceAroundVertexCirculator
      getFaceAroundVertexCirculator (const Vertex& vertex)
      {
        assert (this->validateMeshElement (vertex));
        return (FaceAroundVertexCirculator (vertex, this));
      }

      FaceAroundVertexConstCirculator
      getFaceAroundVertexConstCirculator (const Vertex& vertex) const
      {
        assert (this->validateMeshElement (vertex));
        return (FaceAroundVertexConstCirculator (vertex, this));
      }

      FaceAroundVertexCirculator
      getFaceAroundVertexCirculator (const VertexIndex& idx_vertex)
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (FaceAroundVertexCirculator (idx_vertex, this));
      }

      FaceAroundVertexConstCirculator
      getFaceAroundVertexConstCirculator (const VertexIndex& idx_vertex) const
      {
        assert (this->validateMeshElementIndex (idx_vertex));
        assert (this->validateMeshElement (this->getElement (idx_vertex)));
        return (FaceAroundVertexConstCirculator (idx_vertex, this));
      }

      FaceAroundVertexCirculator
      getFaceAroundVertexCirculator (const HalfEdgeIndex& idx_outgoing_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (FaceAroundVertexCirculator (idx_outgoing_half_edge, this));
      }

      FaceAroundVertexConstCirculator
      getFaceAroundVertexConstCirculator (const HalfEdgeIndex& idx_outgoing_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_outgoing_half_edge));
        return (FaceAroundVertexConstCirculator (idx_outgoing_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // VertexAroundFaceCirculator
      //////////////////////////////////////////////////////////////////////////

      VertexAroundFaceCirculator
      getVertexAroundFaceCirculator (const Face& face)
      {
        assert (this->validateMeshElement (face));
        return (VertexAroundFaceCirculator (face, this));
      }

      VertexAroundFaceConstCirculator
      getVertexAroundFaceConstCirculator (const Face& face) const
      {
        assert (this->validateMeshElement (face));
        return (VertexAroundFaceConstCirculator (face, this));
      }

      VertexAroundFaceCirculator
      getVertexAroundFaceCirculator (const FaceIndex& idx_face)
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (VertexAroundFaceCirculator (idx_face, this));
      }

      VertexAroundFaceConstCirculator
      getVertexAroundFaceConstCirculator (const FaceIndex& idx_face) const
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (VertexAroundFaceConstCirculator (idx_face, this));
      }

      VertexAroundFaceCirculator
      getVertexAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (VertexAroundFaceCirculator (idx_inner_half_edge, this));
      }

      VertexAroundFaceConstCirculator
      getVertexAroundFaceConstCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (VertexAroundFaceConstCirculator (idx_inner_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // InnerHalfEdgeAroundFaceCirculator
      //////////////////////////////////////////////////////////////////////////

      InnerHalfEdgeAroundFaceCirculator
      getInnerHalfEdgeAroundFaceCirculator (const Face& face)
      {
        assert (this->validateMeshElement (face));
        return (InnerHalfEdgeAroundFaceCirculator (face, this));
      }

      InnerHalfEdgeAroundFaceConstCirculator
      getInnerHalfEdgeAroundFaceConstCirculator (const Face& face) const
      {
        assert (this->validateMeshElement (face));
        return (InnerHalfEdgeAroundFaceConstCirculator (face, this));
      }

      InnerHalfEdgeAroundFaceCirculator
      getInnerHalfEdgeAroundFaceCirculator (const FaceIndex& idx_face)
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (InnerHalfEdgeAroundFaceCirculator (idx_face, this));
      }

      InnerHalfEdgeAroundFaceConstCirculator
      getInnerHalfEdgeAroundFaceConstCirculator (const FaceIndex& idx_face) const
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (InnerHalfEdgeAroundFaceConstCirculator (idx_face, this));
      }

      InnerHalfEdgeAroundFaceCirculator
      getInnerHalfEdgeAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (InnerHalfEdgeAroundFaceCirculator (idx_inner_half_edge, this));
      }

      InnerHalfEdgeAroundFaceConstCirculator
      getInnerHalfEdgeAroundFaceConstCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (InnerHalfEdgeAroundFaceConstCirculator (idx_inner_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // OuterHalfEdgeAroundFaceCirculator
      //////////////////////////////////////////////////////////////////////////

      OuterHalfEdgeAroundFaceCirculator
      getOuterHalfEdgeAroundFaceCirculator (const Face& face)
      {
        assert (this->validateMeshElement (face));
        return (OuterHalfEdgeAroundFaceCirculator (face, this));
      }

      OuterHalfEdgeAroundFaceConstCirculator
      getOuterHalfEdgeAroundFaceConstCirculator (const Face& face) const
      {
        assert (this->validateMeshElement (face));
        return (OuterHalfEdgeAroundFaceConstCirculator (face, this));
      }

      OuterHalfEdgeAroundFaceCirculator
      getOuterHalfEdgeAroundFaceCirculator (const FaceIndex& idx_face)
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (OuterHalfEdgeAroundFaceCirculator (idx_face, this));
      }

      OuterHalfEdgeAroundFaceConstCirculator
      getOuterHalfEdgeAroundFaceConstCirculator (const FaceIndex& idx_face) const
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (OuterHalfEdgeAroundFaceConstCirculator (idx_face, this));
      }

      OuterHalfEdgeAroundFaceCirculator
      getOuterHalfEdgeAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (OuterHalfEdgeAroundFaceCirculator (idx_inner_half_edge, this));
      }

      OuterHalfEdgeAroundFaceConstCirculator
      getOuterHalfEdgeAroundFaceConstCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (OuterHalfEdgeAroundFaceConstCirculator (idx_inner_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // FaceAroundFaceCirculator
      //////////////////////////////////////////////////////////////////////////

      FaceAroundFaceCirculator
      getFaceAroundFaceCirculator (const Face& face)
      {
        assert (this->validateMeshElement (face));
        return (FaceAroundFaceCirculator (face, this));
      }

      FaceAroundFaceConstCirculator
      getFaceAroundFaceConstCirculator (const Face& face) const
      {
        assert (this->validateMeshElement (face));
        return (FaceAroundFaceConstCirculator (face, this));
      }

      FaceAroundFaceCirculator
      getFaceAroundFaceCirculator (const FaceIndex& idx_face)
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (FaceAroundFaceCirculator (idx_face, this));
      }

      FaceAroundFaceConstCirculator
      getFaceAroundFaceConstCirculator (const FaceIndex& idx_face) const
      {
        assert (this->validateMeshElementIndex (idx_face));
        assert (this->validateMeshElement (this->getElement (idx_face)));
        return (FaceAroundFaceConstCirculator (idx_face, this));
      }

      FaceAroundFaceCirculator
      getFaceAroundFaceCirculator (const HalfEdgeIndex& idx_inner_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (FaceAroundFaceCirculator (idx_inner_half_edge, this));
      }

      FaceAroundFaceConstCirculator
      getFaceAroundFaceConstCirculator (const HalfEdgeIndex& idx_inner_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_inner_half_edge));
        return (FaceAroundFaceConstCirculator (idx_inner_half_edge, this));
      }

      //////////////////////////////////////////////////////////////////////////
      // HalfEdgeAroundBoundaryCirculator
      //////////////////////////////////////////////////////////////////////////

      HalfEdgeAroundBoundaryCirculator
      getHalfEdgeAroundBoundaryCirculator (const HalfEdgeIndex& idx_boundary_half_edge)
      {
        assert (this->validateMeshElementIndex (idx_boundary_half_edge));
        return (this->getInnerHalfEdgeAroundFaceCirculator (idx_boundary_half_edge));
      }

      HalfEdgeAroundBoundaryConstCirculator
      getHalfEdgeAroundBoundaryConstCirculator (const HalfEdgeIndex& idx_boundary_half_edge) const
      {
        assert (this->validateMeshElementIndex (idx_boundary_half_edge));
        return (this->getInnerHalfEdgeAroundFaceConstCirculator (idx_boundary_half_edge));
      }

    protected:

      //////////////////////////////////////////////////////////////////////////
      // Push back
      //////////////////////////////////////////////////////////////////////////

      VertexIndex
      pushBackVertex (const Vertex& vertex)
      {
        vertexes_.push_back (vertex);
        return (VertexIndex (static_cast<int> (this->sizeVertexes ()) - 1));
      }

      VertexIndex
      pushBackVertex (const VertexData&    vertex_data             = VertexData (),
                      const HalfEdgeIndex& idx_outgoing_half_edge_ = HalfEdgeIndex ())
      {
        vertexes_.push_back (Vertex (vertex_data, idx_outgoing_half_edge_));
        return (VertexIndex (static_cast<int> (this->sizeVertexes ()) - 1));
      }

      HalfEdgeIndex
      pushBackHalfEdge (const HalfEdge& half_edge)
      {
        half_edges_.push_back (half_edge);
        return (HalfEdgeIndex (static_cast<int> (this->sizeHalfEdges ()) - 1));
      }

      HalfEdgeIndex
      pushBackHalfEdge (const HalfEdgeData&  half_edge_data         = HalfEdgeData  (),
                        const VertexIndex&   idx_terminating_vertex = VertexIndex   (),
                        const HalfEdgeIndex& idx_opposite_half_edge = HalfEdgeIndex (),
                        const HalfEdgeIndex& idx_next_half_edge     = HalfEdgeIndex (),
                        const HalfEdgeIndex& idx_prev_half_edge     = HalfEdgeIndex (),
                        const FaceIndex&     idx_face               = FaceIndex     ())
      {
        half_edges_.push_back (HalfEdge (half_edge_data, idx_terminating_vertex, idx_opposite_half_edge, idx_next_half_edge, idx_prev_half_edge, idx_face));
        return (HalfEdgeIndex (static_cast<int> (this->sizeHalfEdges ()) - 1));
      }

      FaceIndex
      pushBackFace (const Face& face)
      {
        faces_.push_back (face);
        return (FaceIndex (static_cast<int> (this->sizeFaces ()) - 1));
      }

      FaceIndex
      pushBackFace (const FaceData&          face_data           = FaceData (),
                    const HalfEdgeIndex& idx_inner_half_edge = HalfEdgeIndex ())
      {
        faces_.push_back (Face (face_data, idx_inner_half_edge));
        return (FaceIndex (static_cast<int> (this->sizeFaces ()) - 1));
      }

      //////////////////////////////////////////////////////////////////////////
      // For the assertions
      //////////////////////////////////////////////////////////////////////////

      bool
      validateMeshElement (const Vertex& vertex) const
      {
        return (this->validateMeshElementIndex (vertex.getOutgoingHalfEdgeIndex ()));
      }

      bool
      validateMeshElementIndex (const VertexIndex& idx_vertex) const
      {
        if (!idx_vertex.isValid ())                    return (false);
        if (idx_vertex >= int (this->sizeVertexes ())) return (false);
        return (true);
      }

      bool
      validateMeshElementIndex (const HalfEdgeIndex& idx_half_edge) const
      {
        if (!idx_half_edge.isValid ())                     return (false);
        if (idx_half_edge >= int (this->sizeHalfEdges ())) return (false);
        return (true);
      }

      bool
      validateMeshElement (const Face& face) const
      {
        return (this->validateMeshElementIndex (face.getInnerHalfEdgeIndex ()));
      }

      bool
      validateMeshElementIndex (const FaceIndex& idx_face) const
      {
        if (!idx_face.isValid ())                 return (false);
        if (idx_face >= int (this->sizeFaces ())) return (false);
        return (true);
      }

    protected:

      Vertexes  vertexes_;
      HalfEdges half_edges_;
      Faces     faces_;
  };

} // End namespace pcl

#endif // PCL_GEOMETRY_MESH_BASE_HPP

max_stars_repo_name: zhangxaochen/CuFusion

max_issues_repo_name: GucciPrada/CuFusion

max_forks_repo_name: GucciPrada/CuFusion


text:
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifdef _WIN32
#   include <windows.h>
#endif

#include <sql.h>
#include <sqlext.h>

#include <vector>
#include <string>
#include <algorithm>

#include <boost/test/unit_test.hpp>

#include "ignite/ignite.h"
#include "test_type.h"
#include "test_utils.h"
#include "odbc_test_suite.h"

using namespace ignite;
using namespace ignite_test;

using namespace boost::unit_test;

/**
 * Test setup fixture.
 */
struct TypesTestSuiteFixture : odbc::OdbcTestSuite
{
    /**
     * Constructor.
     */
    TypesTestSuiteFixture() :
        cache1(0)
    {
        node = StartPlatformNode("queries-test.xml", "NodeMain");

        cache1 = node.GetCache<int64_t, TestType>("cache");
    }

    /**
     * Destructor.
     */
    virtual ~TypesTestSuiteFixture()
    {
        // No-op.
    }

    /** Node started during the test. */
    Ignite node;

    /** Cache instance. */
    cache::Cache<int64_t, TestType> cache1;
};

BOOST_FIXTURE_TEST_SUITE(TypesTestSuite, TypesTestSuiteFixture)

BOOST_AUTO_TEST_CASE(TestZeroDecimal)
{
    Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=PUBLIC");

    SQLCHAR ddl[] = "CREATE TABLE IF NOT EXISTS TestTable "
        "(RecId varchar PRIMARY KEY, RecValue DECIMAL(4,2))"
        "WITH \"template=replicated, cache_name=TestTable_Cache\";";

    SQLRETURN ret = SQLExecDirect(stmt, ddl, SQL_NTS);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    SQLCHAR dml[] = "INSERT INTO TestTable (RecId, RecValue) VALUES ('1', ?)";

    ret = SQLPrepare(stmt, dml, SQL_NTS);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    SQL_NUMERIC_STRUCT num;

    memset(&num, 0, sizeof(num));

    num.sign = 1;
    num.precision = 1;

    ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_NUMERIC, SQL_DECIMAL, 0, 0, &num, 0, 0);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    ret = SQLExecute(stmt);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    SQL_NUMERIC_STRUCT num0;
    SQLLEN num0Len = static_cast<SQLLEN>(sizeof(num0));

    // Filling data to avoid acidental equality
    memset(&num0, 0xFF, sizeof(num0));

    ret = SQLBindCol(stmt, 1, SQL_C_NUMERIC, &num0, sizeof(num0), &num0Len);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    SQLCHAR qry[] = "SELECT RecValue FROM TestTable WHERE RecId = '1'";

    ret = SQLExecDirect(stmt, qry, SQL_NTS);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    ret = SQLFetch(stmt);

    if (!SQL_SUCCEEDED(ret))
        BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));

    BOOST_CHECK_EQUAL(num.precision, num0.precision);
    BOOST_CHECK_EQUAL(num.scale, num0.scale);
    BOOST_CHECK_EQUAL(num.sign, num0.sign);

    BOOST_CHECK_EQUAL(num.val[0], num0.val[0]);
    BOOST_CHECK_EQUAL(num.val[1], num0.val[1]);
    BOOST_CHECK_EQUAL(num.val[2], num0.val[2]);
    BOOST_CHECK_EQUAL(num.val[3], num0.val[3]);
    BOOST_CHECK_EQUAL(num.val[4], num0.val[4]);
    BOOST_CHECK_EQUAL(num.val[5], num0.val[5]);
    BOOST_CHECK_EQUAL(num.val[6], num0.val[6]);
    BOOST_CHECK_EQUAL(num.val[7], num0.val[7]);
    BOOST_CHECK_EQUAL(num.val[8], num0.val[8]);
    BOOST_CHECK_EQUAL(num.val[9], num0.val[9]);
    BOOST_CHECK_EQUAL(num.val[10], num0.val[10]);
    BOOST_CHECK_EQUAL(num.val[11], num0.val[11]);
    BOOST_CHECK_EQUAL(num.val[12], num0.val[12]);
    BOOST_CHECK_EQUAL(num.val[13], num0.val[13]);
    BOOST_CHECK_EQUAL(num.val[14], num0.val[14]);
    BOOST_CHECK_EQUAL(num.val[15], num0.val[15]);
}

BOOST_AUTO_TEST_SUITE_END()

ext: cpp

max_stars_repo_name: geertjanw/ignite

max_issues_repo_name: geertjanw/ignite

max_forks_repo_name: geertjanw/ignite


text:
#pragma once

#include "network_messages.hpp"
#include "round.hpp"
#include "randpa_logger.hpp"

#include <fc/exception/exception.hpp>
#include <fc/io/json.hpp>

#include <boost/blank.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/compute/detail/lru_cache.hpp>

#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>

namespace randpa_finality {

using ::fc::static_variant;

using mutex_guard = std::lock_guard<std::mutex>;

//---------- types ----------//

template <typename message_type>
class message_queue {
public:
    using message_ptr = std::shared_ptr<message_type>;

public:
    /// Add message to the queue.
    template <typename T>
    void push_message(const T& msg) {
        mutex_guard lock(_message_queue_mutex);

        auto randpa_msg = std::make_shared<message_type>(msg);
        _message_queue.push(randpa_msg);

        if (_need_notify) {
            _new_msg_cond.notify_one();
        }
    }

    /// Extract next message, or return nullptr (if empty).
    message_ptr get_next_msg() {
        mutex_guard lock(_message_queue_mutex);

        if (_message_queue.empty()) {
            _need_notify = true;
            return nullptr;
        } else {
            _need_notify = false;
        }

        const auto msg = _message_queue.front();
        _message_queue.pop();
        return msg;
    }

    /// Extract next message (if there is no one, wait until it appears in the queue).
    message_ptr get_next_msg_wait() {
        while (true) {
            if (_need_notify) {
                std::unique_lock<std::mutex> lk(_message_queue_mutex);

                _new_msg_cond.wait(lk, [this](){
                    return !_message_queue.empty() || _done;
                });
            }

            if (_done) {
                return nullptr;
            }

            auto msg = get_next_msg();
            if (msg) {
                return msg;
            }
        }
    }

    /// Finish working with queue.
    void terminate() {
        _done = true;
        _new_msg_cond.notify_one();
    }

    /// Get queue size.
    size_t size() const {
        mutex_guard lock(_message_queue_mutex);
        return _message_queue.size();
    }

private:
    std::atomic<bool> _need_notify { true };
    std::queue<message_ptr> _message_queue;
    std::atomic<bool> _done { false };

    mutable std::mutex _message_queue_mutex;
    std::condition_variable _new_msg_cond;
};

template <typename ...Args>
class channel {
public:
    using cb_type = std::function<void(Args...)>;

    void subscribe(cb_type && cb) {
        cbs.emplace_back(cb);
    }

    void send(Args... args) {
        for (auto && cb: cbs) {
            cb(std::forward<Args>(args)...);
        }
    }

protected:
    std::vector<cb_type> cbs;
};

/// RANDPA-specific network messages.
struct randpa_net_msg {
    uint32_t ses_id;
    randpa_net_msg_data data;
    fc::time_point_sec receive_time;
};

struct on_accepted_block_event {
    block_id_type block_id;
    block_id_type prev_block_id;
    public_key_type creator_key;              ///< block creator's key
    std::set<public_key_type> active_bp_keys; ///< keys of BPs, that signed this block
    bool sync;
};

struct on_irreversible_event {
    block_id_type block_id;
};

struct on_new_peer_event {
    uint32_t ses_id;
};

using randpa_event_data = static_variant<on_accepted_block_event, on_irreversible_event, on_new_peer_event>;

/// External events.
struct randpa_event {
    randpa_event_data data;
};

using randpa_message = static_variant<randpa_net_msg, randpa_event>;
using randpa_message_ptr = std::shared_ptr<randpa_message>;

using net_channel = channel<const randpa_net_msg&>;
using net_channel_ptr = std::shared_ptr<net_channel>;

using event_channel = channel<const randpa_event&>;
using event_channel_ptr = std::shared_ptr<event_channel>;

using finality_channel = channel<const block_id_type&>;
using finality_channel_ptr = std::shared_ptr<finality_channel>;
using lru_cache_type = boost::compute::detail::lru_cache<digest_type, boost::blank>;

class randpa {
public:
    static constexpr uint32_t round_width = 2;
    static constexpr uint32_t prevote_width = 1;
    static constexpr uint32_t msg_expiration_ms = 1000;

public:
    randpa()
            : _peer_messages{_messages_cache_size}
            , _self_messages{_messages_cache_size}
            , _last_proofs{_proofs_cache_size} {
        // 2 cases:
        //   full node:
        //     * sig provider with random-generated private key,
        //     * 0-initialized public key (will not be used for full nodes);
        //   block producer:
        //     * one or more user-defined sig providers,
        //     * corresponding public keys (to private keys stored in sig providers).
        //
        // A node considered to be a full-one, unless at least one signature provider defined.

        const auto default_priv_key = private_key_type::generate();

        _signature_providers.push_back(
            [default_priv_key](const digest_type& digest) {
                return default_priv_key.sign(digest);
            }
        );
        _public_keys.push_back(public_key_type{});
    }

    randpa& set_in_net_channel(const net_channel_ptr& ptr) {
        _in_net_channel = ptr;
        return *this;
    }

    randpa& set_out_net_channel(const net_channel_ptr& ptr) {
        _out_net_channel = ptr;
        return *this;
    }

    randpa& set_event_channel(const event_channel_ptr& ptr) {
        _in_event_channel = ptr;
        return *this;
    }

    randpa& set_finality_channel(const finality_channel_ptr& ptr) {
        _finality_channel = ptr;
        return *this;
    }

    /// Set signature providers.
    randpa& set_signature_providers(const std::vector<signature_provider_type>& signature_providers,
                                    const std::vector<public_key_type>& public_keys) {
        FC_ASSERT(_is_block_producer, "failed adding signature provider to the full node; use --producer-name option");
        FC_ASSERT(signature_providers.size() == public_keys.size(), "number of signature providers and number of public keys differ");

        _signature_providers = signature_providers;
        _public_keys = public_keys;

        _sig_provs_by_key.clear();
        for (size_t i = 0; i < _public_keys.size(); i++) {
            _sig_provs_by_key[_public_keys[i]] = _signature_providers[i];
        }

        randpa_dlog("set signature providers for producers ${p}", ("p", public_keys));
        return *this;
    }

    /// Add signature provider.
    // XXX: don't use!
    // TODO: remove after fixing simulator (CYB-573)
    randpa& add_signature_provider(const signature_provider_type& signature_provider, const public_key_type& public_key) {
        FC_ASSERT(_is_block_producer, "failed adding signature provider to the full node; use --producer-name option");

        //~if (!_is_bp_key_provided) {
        //~    FC_ASSERT(_signature_providers.size() == 1 && _public_keys.size() == 1, "changing from full-node case was expected");
        //~    // remove default values, stored for full-node case
        //~    _signature_providers.clear();
        //~    _public_keys.clear();
        //~    _sig_provs_by_key.clear();
        //~    _is_bp_key_provided = true;
        //~}

        _signature_providers.push_back(signature_provider);
        _public_keys.push_back(public_key);

        _sig_provs_by_key[public_key] = signature_provider;

        randpa_dlog("set signature provider for producer ${p}", ("p", public_key));
        return *this;
    }

    void start(prefix_tree_ptr tree) {
        FC_ASSERT(_in_net_channel && _in_event_channel, "input channels should be initialized");
        FC_ASSERT(_out_net_channel, "output channel should be initialized");
        FC_ASSERT(_finality_channel, "finality channel should be initialized");
        if (_is_block_producer) {
            FC_ASSERT(!_signature_providers.empty());
        }

        _prefix_tree = tree;
        _lib = tree->get_root()->block_id;

#ifndef SYNC_RANDPA
        _thread_ptr.reset(new std::thread([this]() {
            randpa_wlog("Randpa thread started");
            loop();
            randpa_wlog("Randpa thread terminated");
        }));
#endif

        subscribe();
    }

    void stop() {
#ifndef SYNC_RANDPA
        _done = true;
        _message_queue.terminate();
        _thread_ptr->join();
#endif
    }

#ifndef SYNC_RANDPA
    const message_queue<randpa_message>& get_message_queue() const {
        return _message_queue;
    }
#endif

    prefix_tree_ptr get_prefix_tree() const {
        return _prefix_tree;
    }

    bool is_syncing() const {
        return _is_syncing;
    }

    bool is_frozen() const {
        return _is_frozen;
    }

    void set_type_block_producer() {
        _is_block_producer = true;
    }

private:
    static constexpr size_t _proofs_cache_size = 2; ///< how much last proofs to keep; @see _last_proofs
    static constexpr size_t _messages_cache_size = 100 * 100 * 100; // network msg cache size
    // See https://bit.ly/2Wp3Nsf
    // 2 / 3 * 102 * 12 (blocks per slot) * 2 rounds * 2 (additional)
    static constexpr int32_t _max_finality_lag_blocks = 69 * 12 * 2 * 2;

    std::unique_ptr<std::thread> _thread_ptr;
    std::atomic<bool> _done = false;
    std::vector<signature_provider_type> _signature_providers;
    std::vector<public_key_type> _public_keys;
    /// this hash map allows effectively filter only active BPs among all listed in configuration file
    /// XXX: cannot use unordered_map until fc::crypto::public_key is hashable
    std::map<public_key_type, signature_provider_type> _sig_provs_by_key;
    // TODO: remove after fixing simulator (CYB-573)
    //~bool _is_bp_key_provided = false;       ///< true if user explicitly set at least one sig provider
    bool _is_block_producer = false;        ///< node is a block producer if run with at least one --producer-name option
    prefix_tree_ptr _prefix_tree;
    randpa_round_ptr _round;
    block_id_type _lib;                     ///< last irreversible block
    uint32_t _last_prooved_block_num = 0;
    std::map<public_key_type, uint32_t> _peers;
    lru_cache_type _peer_messages;
    lru_cache_type _self_messages;
    /// Proof data is invalidated after each round is finished, but other nodes will want to request
    /// proofs for that round; this cache holds some proofs to reply such requests.
    boost::circular_buffer<proof_type> _last_proofs;
    bool _is_syncing = false;               ///< syncing blocks from peers
    bool _is_frozen = false;                ///< freeze if dpos finality stops working

#ifndef SYNC_RANDPA
    message_queue<randpa_message> _message_queue;
#endif

    net_channel_ptr _in_net_channel;
    net_channel_ptr _out_net_channel;
    event_channel_ptr _in_event_channel;
    finality_channel_ptr _finality_channel;

    //

    void subscribe() {
        _in_net_channel->subscribe([&](const randpa_net_msg& msg) {
#ifdef SYNC_RANDPA
            process_msg(std::make_shared<randpa_message>(msg));
#else
            _message_queue.push_message(msg);
#endif
        });

        _in_event_channel->subscribe([&](const randpa_event& event) {
            randpa_dlog("Randpa received event, type: ${type}", ("type", event.data.which()));
#ifdef SYNC_RANDPA
            process_msg(std::make_shared<randpa_message>(event));
#else
            _message_queue.push_message(event);
#endif
        });
    }

    template <typename T>
    void send(uint32_t ses_id, const T & msg) {
        auto net_msg = randpa_net_msg { ses_id, msg };
        _out_net_channel->send(net_msg);
    }

    template <typename T>
    void bcast(const T & msg) {
        auto msg_hash = digest_type::hash(msg);
        if (_peer_messages.contains(msg_hash)) {
            return;
        }
        for (const auto& peer : _peers) {
            send(peer.second, msg);
        }
        _peer_messages.insert(msg_hash, {});
    }

#ifndef SYNC_RANDPA
    void loop() {
        while (true) {
            auto msg = _message_queue.get_next_msg_wait();

            if (_done) {
                break;
            }

            process_msg(msg);
        }
    }
#endif

    template <typename T>
    bool check_is_valid_msg(const T& msg) const {
        try {
            msg.public_keys();
        } catch (const fc::exception&) {
            return false;
        }
        return true;
    }

    /// Get intersection of two sets: _signature_providers and active_bp_keys.
    std::vector<signature_provider_type> get_active_signature_providers(const std::set<public_key_type>& active_bp_keys) const {
        std::vector<signature_provider_type> active_sig_provs;
        active_sig_provs.reserve(_signature_providers.size());
        for (const auto& key : active_bp_keys) {
            const auto it = _sig_provs_by_key.find(key);
            if (it != _sig_provs_by_key.end()) {
                active_sig_provs.push_back(it->second);
            }
        }
        return active_sig_provs;
    }

    // need handle all messages
    void process_msg(randpa_message_ptr msg_ptr) {
        const auto msg = *msg_ptr;
        switch (msg.which()) {
        case randpa_message::tag<randpa_net_msg>::value:
            process_net_msg(msg.get<randpa_net_msg>());
            break;
        case randpa_message::tag<randpa_event>::value:
            process_event(msg.get<randpa_event>());
            break;
        default:
            randpa_wlog("Randpa received unknown message, type: ${type}", ("type", msg.which()));
            break;
        }
    }

    /// Visitor for RANDPA various message types.
    class net_msg_handler: public fc::visitor<void> {
    public:
        net_msg_handler(randpa& randpa_ref, uint32_t ses_id)
            : _randpa(randpa_ref)
            , _ses_id(ses_id)
        {}

        template <typename T>
        void operator() (const T& msg) {
            if (_randpa.check_is_valid_msg(msg)) {
                _randpa.on(_ses_id, msg);
            }
        }

    private:
        randpa& _randpa;
        uint32_t _ses_id;
    };

    void process_net_msg(const randpa_net_msg& msg) {
        if (fc::time_point::now() - msg.receive_time > fc::milliseconds(msg_expiration_ms)) {
            randpa_dlog("Network message dropped, msg age: ${age}", ("age", fc::time_point::now() - msg.receive_time));
            return;
        }

        auto visitor = net_msg_handler(*this, msg.ses_id);
        msg.data.visit(visitor);
    }

    void process_event(const randpa_event& event) {
        const auto& data = event.data;
        switch (data.which()) {
        case randpa_event_data::tag<on_accepted_block_event>::value:
            on(data.get<on_accepted_block_event>());
            break;
        case randpa_event_data::tag<on_irreversible_event>::value:
            on(data.get<on_irreversible_event>());
            break;
        case randpa_event_data::tag<on_new_peer_event>::value:
            on(data.get<on_new_peer_event>());
            break;
        default:
            randpa_wlog("Randpa event received, but handler not found, type: ${type}", ("type", data.which()));
            break;
        }
    }

    bool validate_prevote(const prevote_type& prevote,
                          const public_key_type& prevoter_key,
                          const block_id_type& best_block,
                          const std::set<public_key_type>& bp_keys) const {
        if (prevote.base_block != best_block
            && std::find(prevote.blocks.begin(), prevote.blocks.end(), best_block) == prevote.blocks.end()) {
            randpa_dlog("Best block: ${id} was not found in prevote blocks", ("id", best_block));
        } else if (!bp_keys.count(prevoter_key)) {
            randpa_dlog("Prevoter public key is not in active bp keys: ${pub_key}", ("pub_key", prevoter_key));
        } else {
            return true;
        }

        return false;
    }

    bool validate_precommit(const precommit_type& precommit,
                            const public_key_type& precommiter_key,
                            const block_id_type& best_block,
                            const std::set<public_key_type>& bp_keys) const {
        if (precommit.block_id != best_block) {
            randpa_dlog("Precommit block ${pbid}, best block: ${bbid}",
                ("pbid", precommit.block_id)
                ("bbid", best_block));
        } else if (!bp_keys.count(precommiter_key)) {
            randpa_dlog("Precommitter public key is not in active bp keys: ${pub_key}", ("pub_key", precommiter_key));
        } else {
            return true;
        }

        return false;
    }

    bool validate_proof(const proof_type& proof) const {
        const auto best_block = proof.best_block;
        const auto node = _prefix_tree->find(best_block);

        if (!node) {
            randpa_dlog("Received proof for unknown block: ${block_id}", ("block_id", best_block));
            return false;
        }

        std::set<public_key_type> prevoted_keys, precommited_keys;
        const auto& bp_keys = node->active_bp_keys;

        for (const auto& prevote : proof.prevotes) {
            for (const auto& prevoter_pub_key : prevote.public_keys()) {
                if (!validate_prevote(prevote.data, prevoter_pub_key, best_block, bp_keys)) {
                    randpa_dlog("Prevote validation failed, base_block: ${id}, blocks: ${blocks}",
                        ("id", prevote.data.base_block)
                        ("blocks", prevote.data.blocks));
                    return false;
                }
                prevoted_keys.insert(prevoter_pub_key);
            }
        }

        for (const auto& precommit : proof.precommits) {
            for (const auto& precommiter_pub_key : precommit.public_keys()) {
                if (!prevoted_keys.count(precommiter_pub_key)) {
                    randpa_dlog("Precommiter has not prevoted, pub_key: ${pub_key}", ("pub_key", precommiter_pub_key));
                    return false;
                }

                if (!validate_precommit(precommit.data, precommiter_pub_key, best_block, bp_keys)) {
                    randpa_dlog("Precommit validation failed for ${id}", ("id", precommit.data.block_id));
                    return false;
                }
                precommited_keys.insert(precommiter_pub_key);
            }
        }
        bool is_enough_keys = precommited_keys.size() > node->active_bp_keys.size() * 2 / 3;
        if (!is_enough_keys) {
            randpa_dlog("Precommit validation failed: not enough keys: have ${have}, need ${need}",
                ("have", precommited_keys.size())("need", node->active_bp_keys.size() * 2 / 3 + 1));
        }
        return is_enough_keys;
    }

    void on(uint32_t ses_id, const prevote_msg& msg) {
        process_round_msg(ses_id, msg);
    }

    void on(uint32_t ses_id, const precommit_msg& msg) {
        process_round_msg(ses_id, msg);
    }

    void on(uint32_t ses_id, const finality_notice_msg& msg) {
        const auto& data = msg.data;
        randpa_dlog("Randpa finality_notice_msg received for block ${bid}", ("bid", data.best_block));
        if (is_active_bp(data.best_block) && get_block_num(data.best_block) <= _last_prooved_block_num) {
            randpa_dlog("no need to get finality proof for block producer node");
            return;
        }
        send(ses_id, finality_req_proof_msg{{data.round_num}, _signature_providers}); // TODO: filter _signature_providers???
    }

    void on(uint32_t ses_id, const finality_req_proof_msg& msg) {
        const auto& data = msg.data;
        randpa_dlog("Randpa finality_req_proof_msg received for round ${r}", ("r", data.round_num));
        for (const auto& proof : _last_proofs) {
            if (proof.round_num == data.round_num) {
                randpa_dlog("proof found; sending it");
                send(ses_id, proof_msg{proof, _signature_providers}); // TODO: see above
                break;
            }
        }
    }

    void on(uint32_t ses_id, const proof_msg& msg) {
        const auto& proof = msg.data;
        randpa_dlog("Received proof for round ${num}", ("num", proof.round_num));

        if (_is_syncing || _is_frozen) {
            randpa_dlog("Skipping proof while syncing or frozen");
            return;
        }

        if (_last_prooved_block_num >= get_block_num(proof.best_block)) {
            randpa_dlog("Skipping proof for ${id} cause last prooved block ${lpb} is higher",
                ("id", proof.best_block)
                ("lpb", _last_prooved_block_num));
            return;
        }

        if (get_block_num(_lib) >= get_block_num(proof.best_block)) {
            randpa_dlog("Skipping proof for ${id} cause lib ${lib} is higher",
                ("id", proof.best_block)
                ("lib", _lib));
            return;
        }

        if (_round && _round->get_state() == randpa_round::state_type::done) {
            randpa_dlog("Skipping proof for ${id} cause round ${num} is finished",
                ("id", proof.best_block)
                ("num", _round->get_num()));
            return;
        }

        if (!validate_proof(proof)) {
            for (const auto& public_key : msg.public_keys()) {
                randpa_ilog("Invalid proof among ${peer}", ("peer", public_key));
            }
            randpa_dlog("Proof msg: ${msg}", ("msg", msg));
            return;
        }

        randpa_ilog("Successfully validated proof for block ${id}", ("id", proof.best_block));

        if (_round && _round->get_num() == proof.round_num) {
            randpa_dlog("Gotta proof for round ${num}", ("num", _round->get_num()));
            _round->set_state(randpa_round::state_type::done);
        }
        on_proof_gained(proof);
    }

    void on(uint32_t ses_id, const handshake_msg& msg) {
        for (const auto& public_key : msg.public_keys()) {
            randpa_ilog("Randpa handshake_msg received, ses_id: ${ses_id}, from: ${pk}", ("ses_id", ses_id)("pk", public_key));
            try {
                _peers[public_key] = ses_id;
                send(ses_id, handshake_ans_msg(handshake_ans_type { _lib }, _signature_providers));
            } catch (const fc::exception& e) {
                randpa_elog("Randpa handshake_msg handler error, reason: ${e}", ("e", e.what()));
            }
        }
    }

    void on(uint32_t ses_id, const handshake_ans_msg& msg) {
        for (const auto& public_key : msg.public_keys()) {
            randpa_ilog("Randpa handshake_ans_msg received, ses_id: ${ses_id}, from: ${pk}", ("ses_id", ses_id)("pk", public_key));
            try {
                _peers[public_key] = ses_id;
            } catch (const fc::exception& e) {
                randpa_elog("Randpa handshake_ans_msg handler error, reason: ${e}", ("e", e.what()));
            }
        }
    }

    void on(const on_accepted_block_event& event) {
        randpa_dlog("Randpa on_accepted_block_event event handled, block_id: ${id}, num: ${num}, creator: ${c}, bp_keys: ${bpk}",
            ("id", event.block_id)
            ("num", get_block_num(event.block_id))
            ("c", event.creator_key)
            ("bpk", event.active_bp_keys)
        );

        try {
            _prefix_tree->insert({event.prev_block_id, {event.block_id}},
                                event.creator_key, event.active_bp_keys);
        } catch (const NodeNotFoundError& e) {
            randpa_elog("Randpa cannot insert block into tree, base_block: ${base_id}, block: ${id}",
                ("base_id", event.prev_block_id)
                ("id", event.block_id)
            );
            return;
        }

        // when node in syncing or frozen state it's useless to creating new rounds
        _is_syncing = event.sync;
        _is_frozen = get_block_num(event.block_id) - get_block_num(_lib) > _max_finality_lag_blocks;
        if (_is_syncing) {
            randpa_ilog("Randpa omit block while syncing, block id: ${id}", ("id", event.block_id));
            return;
        }
        if (_is_frozen) {
            randpa_ilog("Randpa omit block while frozen, block id: ${id}", ("id", event.block_id));
            return;
        }

        if (should_start_round(event.block_id)) {
            randpa_dlog("removing current round ${r}", ("r", (_round ? _round->get_num() : 0)));
            remove_round();

            randpa_dlog("starting new round");
            if (is_active_bp(event.block_id)) {
                new_round(round_num(event.block_id), event.creator_key, event.active_bp_keys);
                randpa_dlog("new round (${n}) started", ("n", _round->get_num()));
            }
        }

        if (should_end_prevote(event.block_id)) {
            _round->end_prevote();
        }
    }

    void on(const on_irreversible_event& event) {
        randpa_dlog("Randpa on_irreversible_event event handled, block_id: ${bid}, num: ${num}",
            ("bid", event.block_id)
            ("num", get_block_num(event.block_id))
        );

        if (get_block_num(event.block_id) <= get_block_num(_prefix_tree->get_root()->block_id)) {
            randpa_dlog("Randpa handled on_irreversible for old block: block_num: ${blk_num}",
                       ("blk_num", get_block_num(event.block_id))
            );
            return;
        }

        update_lib(event.block_id);
    }

    void on(const on_new_peer_event& event) {
        randpa_dlog("Randpa on_new_peer_event event handled, ses_id: ${ses_id}", ("ses_id", event.ses_id));
        auto msg = handshake_msg(handshake_type{_lib}, _signature_providers);
        send(event.ses_id, msg);
    }

    void on_proof_gained(const proof_type& proof) {
        _last_proofs.push_front(proof);
        randpa_dlog("cached proof for block ${b}", ("b", proof.best_block));

        _last_prooved_block_num = get_block_num(proof.best_block);
        _finality_channel->send(proof.best_block);
        bcast(finality_notice_msg{{proof.round_num, proof.best_block}, _signature_providers});
    }

    template <typename T>
    void process_round_msg(uint32_t ses_id, const T& msg) {
        if (_is_syncing || _is_frozen) {
            randpa_dlog("Randpa syncing or frozen");
            return;
        }

        const auto msg_hash = digest_type::hash(msg);
        if (_self_messages.contains(msg_hash)) {
            return;
        }

        _self_messages.insert(msg_hash, {});

        const auto last_round_num = round_num(_prefix_tree->get_head()->block_id);
        if (last_round_num == msg.data.round_num) {
            bcast(msg);
        }

        if (!_round) {
            randpa_dlog("Randpa round does not exist");
            return;
        }

        _round->on(msg);
    }

    uint32_t round_num(const block_id_type& block_id) const {
        return (get_block_num(block_id) - 1) / round_width;
    }

    uint32_t num_in_round(const block_id_type& block_id) const {
        return (get_block_num(block_id) - 1) % round_width;
    }

    bool should_start_round(const block_id_type& block_id) const {
        if (get_block_num(block_id) < 1) {
            return false;
        }

        if (!_round) {
            return true;
        }

        return round_num(block_id) > _round->get_num();
    }

    bool should_end_prevote(const block_id_type& block_id) const {
        if (!_round) {
            randpa_dlog("No active round; no need to finish prevote phase.");
            return false;
        }

        bool should_end = round_num(block_id) == _round->get_num() && num_in_round(block_id) == prevote_width;
        if (!should_end) {
            randpa_dlog("Cannot end prevote phase for block ${b} on round ${r}",
                ("b", get_block_num(block_id))("r", _round->get_num()));
        }
        return should_end;
    }

    bool is_active_bp(const block_id_type& block_id) const {
        if (!_is_block_producer) {
            return false;
        }

        randpa_dlog("bp key provided");

        auto node_ptr = _prefix_tree->find(block_id);

        if (!node_ptr) {
            randpa_dlog("block not found");
            return false;
        }

        for (const auto& public_key : _public_keys) {
            if (node_ptr->active_bp_keys.count(public_key)) {
                return true;
            }
        }
        return false;
    }

    void finish_round() {
        if (!_round) {
            return;
        }

        if (!_round->finish()) {
            return;
        }

        const auto& proof = _round->get_proof();
        randpa_ilog("Randpa round reached supermajority, round num: ${n}, best block id: ${b}, best block num: ${bn}",
            ("n", proof.round_num)
            ("b", proof.best_block)
            ("bn", get_block_num(proof.best_block))
        );

        if (get_block_num(_lib) < get_block_num(proof.best_block)) {
            on_proof_gained(proof);
            update_lib(proof.best_block);
        }
        randpa_dlog("round ${r} finished", ("r", _round->get_num()));
    }

    void new_round(uint32_t round_num, const public_key_type& primary, const std::set<public_key_type>& active_bp_keys) {
        _round.reset(new randpa_round(
            round_num,
            primary,
            _prefix_tree,
            get_active_signature_providers(active_bp_keys),
            [this](const prevote_msg& msg) { bcast(msg); },
            [this](const precommit_msg& msg) { bcast(msg); },
            [this]() { finish_round(); }
        ));
    }

    void remove_round() {
        _peer_messages.clear();
        _self_messages.clear();
        _prefix_tree->remove_confirmations();
        _round.reset();
    }

    void update_lib(const block_id_type& lib_id) {
        auto node_ptr = _prefix_tree->find(lib_id);

        if (node_ptr) {
            _prefix_tree->set_root(node_ptr);
        } else {
            auto new_irb = std::make_shared<tree_node>(tree_node { lib_id });
            _prefix_tree->set_root(new_irb);
        }

        _lib = lib_id;
    }
};

} //namespace randpa_finality

ext: hpp

max_stars_repo_name: DaoCasino/dc-blockchain

max_issues_repo_name: DaoCasino/dc-blockchain

max_forks_repo_name: DaoCasino/dc-blockchain


text:
/**
MIT License

This file is part of the Granite project which is based on Basalt.
https://github.com/DLR-RM/granite

Copyright (c) Martin Wudenka, Deutsches Zentrum für Luft- und Raumfahrt

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.
*/

/**
Original license of Basalt:
BSD 3-Clause License

This file is part of the Basalt project.
https://gitlab.com/VladyslavUsenko/granite-headers.git

Copyright (c) 2019, Vladyslav Usenko and Nikolaus Demmel.
All rights reserved.

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

* Redistributions of source code must retain the above copyright notice, this
  list of conditions and the following disclaimer.

* Redistributions in binary form must reproduce the above copyright notice,
  this list of conditions and the following disclaimer in the documentation
  and/or other materials provided with the distribution.

* Neither the name of the copyright holder nor the names of its
  contributors may be used to endorse or promote products derived from
  this software without specific prior written permission.

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

@file
@brief Definition of the standard containers with Eigen allocator.
*/

#pragma once

#include <deque>
#include <map>
#include <unordered_map>
#include <vector>

#include <Eigen/Dense>

namespace Eigen {

template <typename T>
using aligned_vector = std::vector<T, Eigen::aligned_allocator<T>>;

template <typename T>
using aligned_deque = std::deque<T, Eigen::aligned_allocator<T>>;

template <typename K, typename V>
using aligned_map = std::map<K, V, std::less<K>,
                             Eigen::aligned_allocator<std::pair<K const, V>>>;

template <typename K, typename V>
using aligned_unordered_map =
    std::unordered_map<K, V, std::hash<K>, std::equal_to<K>,
                       Eigen::aligned_allocator<std::pair<K const, V>>>;

}  // namespace Eigen

max_stars_repo_name: wstuerzl/granite

max_issues_repo_name: wstuerzl/granite

max_forks_repo_name: wstuerzl/granite


text:
#include <climits>
#include <iostream>
#include <boost/scoped_ptr.hpp>

#include "BRChainParams.h"

#include "Wrapper/ChainParams.h"
#include "MasterWalletManager.h"
#include "Log.h"

#include "TestConnectPeer.h"

using namespace Elastos::ElaWallet;

static int BRMainNetVerifyDifficulty(const BRMerkleBlock *block, const BRSet *blockSet) {
	const BRMerkleBlock *previous, *b = NULL;
	uint32_t i;

	assert(block != NULL);
	assert(blockSet != NULL);

	// check if we hit a difficulty transition, and find previous transition block
	if ((block->height % BLOCK_DIFFICULTY_INTERVAL) == 0) {
		for (i = 0, b = block; b && i < BLOCK_DIFFICULTY_INTERVAL; i++) {
			b = (const BRMerkleBlock *) BRSetGet(blockSet, &b->prevBlock);
		}
	}

	previous = (const BRMerkleBlock *) BRSetGet(blockSet, &block->prevBlock);
	return BRMerkleBlockVerifyDifficulty(block, previous, (b) ? b->timestamp : 0);
}

void TestConnectPeer::runPeerConnectTest_WalletFactory() {

	boost::scoped_ptr<MasterWalletManager> walletFactory(new MasterWalletManager("Data"));

	std::string mnemonic = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
	std::string phrasePassword = "";
	std::string payPassword = "payPassword";
	IMasterWallet *masterWallet = walletFactory->ImportWalletWithMnemonic("ELA", mnemonic, phrasePassword, payPassword);

	ISubWallet *subWallet = masterWallet->CreateSubWallet("IdChain", payPassword, false);
	ISubWallet *elaWallet = masterWallet->CreateSubWallet("ELA", payPassword, false);
	nlohmann::json addresses = subWallet->GetAllAddress(0, INT_MAX);
	std::cout << "IdChain wallet addrs: " << addresses << std::endl;
	std::cout << "ELA wallet addrs: " << elaWallet->GetAllAddress(0, INT_MAX);
	sleep(4);

	bool hasSentTransaction = false;

	while (true) {
		sleep(10);
		subWallet->GetAllTransaction(0, 20, "");
		elaWallet->GetAllTransaction(0, 20, "");
		Log::getLogger()->info("IdChain wallet balance = {}", subWallet->GetBalance());
		Log::getLogger()->info("ELA wallet balance = {}", elaWallet->GetBalance());

#if 0
		if (balance > 1000000 && !hasSentTransaction) {
			try {
				nlohmann::json tx = subWallet->CreateTransaction("EZ3PoRzcr95ADMrDLCDb8DQAMRs7j8DkB2", "ERcEon7MC8fUBZSadvCUTVYmdHyRK1Jork", balance / 2, 100000, "", "");
				nlohmann::json result = subWallet->SendRawTransaction(tx, 100000, payPassword);
				Log::getLogger()->info("send tx result = {}", result.dump());
			} catch (std::exception e) {
				Log::getLogger()->error("send transaction from EZ3PoRzcr95ADMrDLCDb8DQAMRs7j8DkB2 to ERcEon7MC8fUBZSadvCUTVYmdHyRK1Jork error: {}", e.what());
			}
			hasSentTransaction = true;
		}
#endif
	}

	masterWallet->DestroyWallet(subWallet);
	walletFactory->DestroyWallet(masterWallet->GetId());
}


text:
// Copyright András Vukics 2006–2020. Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE.txt)
#include "ElementAveraged.h"

#include "FormDouble.h"

#include <boost/range/algorithm/for_each.hpp>

using namespace std;

std::ostream& structure::details::streamCommon(const AveragedCommon::Averages& averages, std::ostream& os, int precision)
{
  using namespace formdouble;

  os<<'\t';
  {
    const FormDouble fd(precision);
    boost::for_each(averages,[&](double v){os<<fd(v);});
  }
  return os;
}

ext: cc

max_stars_repo_name: bartoszek/cppqed

max_issues_repo_name: bartoszek/cppqed

max_forks_repo_name: bartoszek/cppqed


text:
// Copyright (c) 2012 by Raytheon BBN Technologies Corp.
// All Rights Reserved.

#include "Generic/common/leak_detection.h" // This must be the first #include

#include "Generic/edt/MentionGroups/extractors/EditDistanceExtractor.h"
#include "Generic/edt/MentionGroups/LinkInfoCache.h"
#include "Generic/theories/DocTheory.h"
#include "Generic/edt/CorefUtilities.h"

#include <limits>
#include <boost/foreach.hpp>

EditDistanceExtractor::EditDistanceExtractor() :
	AttributeValuePairExtractor<MentionPair>(Symbol(L"MentionPair"), Symbol(L"edit-distance"))
{
	validateRequiredParameters();
}

std::vector<AttributeValuePair_ptr> EditDistanceExtractor::extractFeatures(const MentionPair& context,
                                                                           LinkInfoCache& cache,
                                                                           const DocTheory *docTheory)
{
	std::vector<AttributeValuePair_ptr> results;

	if ((context.first->getMentionType() != Mention::NAME && context.first->getMentionType() != Mention::NEST) ||
		(context.second->getMentionType() != Mention::NAME && context.second->getMentionType() != Mention::NEST))
		return results;

	std::vector<AttributeValuePair_ptr> m1Features = cache.getMentionFeaturesByName(context.first, Symbol(L"Mention-normalized-name"), Symbol(L"name"));
	std::vector<AttributeValuePair_ptr> m2Features = cache.getMentionFeaturesByName(context.second, Symbol(L"Mention-normalized-name"), Symbol(L"name"));

	float min_distance =  std::numeric_limits<float>::max();
	BOOST_FOREACH(AttributeValuePair_ptr feature1, m1Features) {
		boost::shared_ptr< AttributeValuePair<Symbol> > f1 = boost::dynamic_pointer_cast< AttributeValuePair<Symbol> >(feature1);
		std::wstring m1 = f1->getValue().to_string();
		BOOST_FOREACH(AttributeValuePair_ptr feature2, m2Features) {
			boost::shared_ptr< AttributeValuePair<Symbol> > f2 = boost::dynamic_pointer_cast< AttributeValuePair<Symbol> >(feature2);
			std::wstring m2 = f2->getValue().to_string();
			int e = CorefUtilities::editDistance(m1, m2);
			float d = (float)e/std::min(m1.length(), m2.length());
			if (d < min_distance)
				min_distance = d;
		}
	}

	results.push_back(AttributeValuePair<float>::create(Symbol(L"edit-distance"), min_distance, getFullName()));
	return results;
}

max_stars_repo_name: BBN-E/serif

max_issues_repo_name: BBN-E/serif

max_forks_repo_name: BBN-E/serif


text:
/*!
@file
Adapts `std::array` for use with Hana.

@copyright Louis Dionne 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
 */

#ifndef BOOST_HANA_EXT_STD_ARRAY_HPP
#define BOOST_HANA_EXT_STD_ARRAY_HPP

#include <boost/hana/bool.hpp>
#include <boost/hana/detail/algorithm.hpp>
#include <boost/hana/fwd/at.hpp>
#include <boost/hana/fwd/core/tag_of.hpp>
#include <boost/hana/fwd/equal.hpp>
#include <boost/hana/fwd/is_empty.hpp>
#include <boost/hana/fwd/length.hpp>
#include <boost/hana/fwd/less.hpp>
#include <boost/hana/fwd/tail.hpp>
#include <boost/hana/integral_constant.hpp>

#include <array>
#include <cstddef>
#include <type_traits>
#include <utility>

namespace boost { namespace hana {
    namespace ext { namespace std { struct array_tag; }}

    template <typename T, std::size_t N>
    struct tag_of<std::array<T, N>> {
        using type = ext::std::array_tag;
    };

    //////////////////////////////////////////////////////////////////////////
    // Foldable
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct length_impl<ext::std::array_tag> {
        template <typename Xs>
        static constexpr auto apply(Xs const&) {
            return hana::size_c< ::std::tuple_size<Xs>::type::value>;
        }
    };

    //////////////////////////////////////////////////////////////////////////
    // Iterable
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct at_impl<ext::std::array_tag> {
        template <typename Xs, typename N>
        static constexpr decltype(auto) apply(Xs&& xs, N const&) {
            constexpr std::size_t n = N::value;
            return static_cast<Xs&&>(xs)[n];
        }
    };

    template <>
    struct tail_impl<ext::std::array_tag> {
        template <typename T, std::size_t N, typename Xs, std::size_t ...index>
        static constexpr auto tail_helper(Xs&& xs, std::index_sequence<index...>) {
            return std::array<T, N - 1>{{
                static_cast<Xs&&>(xs)[index + 1]...
            }};
        }

        template <typename Xs>
        static constexpr decltype(auto) apply(Xs&& xs) {
            using RawArray = typename std::remove_cv<
                typename std::remove_reference<Xs>::type
            >::type;
            constexpr auto N = std::tuple_size<RawArray>::value;
            using T = typename RawArray::value_type;
            return tail_helper<T, N>(
                static_cast<Xs&&>(xs),
                std::make_index_sequence<N - 1>{}
            );
        }
    };

    template <>
    struct is_empty_impl<ext::std::array_tag> {
        template <typename T, std::size_t N>
        static constexpr auto apply(std::array<T, N> const&) {
            return hana::bool_c<N == 0>;
        }
    };

    //////////////////////////////////////////////////////////////////////////
    // Comparable
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct equal_impl<ext::std::array_tag, ext::std::array_tag> {
        template <typename T, std::size_t n, typename U>
        static constexpr bool apply(std::array<T, n> const& xs, std::array<U, n> const& ys)
        { return xs == ys; }

        template <typename T, typename U>
        static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
        { return hana::true_c; }

        template <typename T, std::size_t n, typename U, std::size_t m>
        static constexpr auto apply(std::array<T, n> const&, std::array<U, m> const&)
        { return hana::false_c; }
    };

    //////////////////////////////////////////////////////////////////////////
    // Orderable
    //////////////////////////////////////////////////////////////////////////
    template <>
    struct less_impl<ext::std::array_tag, ext::std::array_tag> {
        template <typename T, std::size_t n, typename U>
        static constexpr bool apply(std::array<T, n> const& xs, std::array<U, n> const& ys)
        { return xs < ys; }

        template <typename T, typename U>
        static constexpr auto apply(std::array<T, 0> const&, std::array<U, 0> const&)
        { return hana::false_c; }

        template <typename T, std::size_t n, typename U, std::size_t m>
        static constexpr auto apply(std::array<T, n> const& xs, std::array<U, m> const& ys) {
            return detail::lexicographical_compare(
                xs.begin(), xs.end(), ys.begin(), ys.end()
            );
        }
    };
}} // end namespace boost::hana

#endif // !BOOST_HANA_EXT_STD_ARRAY_HPP

max_stars_repo_name: qicosmos/hana

max_issues_repo_name: qicosmos/hana

max_forks_repo_name: qicosmos/hana


text:
/* thanks to Valient Gough for this example program! */

#include <mtl/matrix.h>
#include <mtl/mtl.h>
#include <mtl/utils.h>
#include <mtl/lu.h>

using namespace mtl;

// don't print out the matrices once they get to this size...
#define MAX_PRINT_SIZE 5

typedef matrix<double, rectangle<>, dense<>, row_major>::type Matrix;
typedef dense1D<double> Vector;

double testMatrixError(const Matrix &A, const Matrix &AInv)
{
  int size = A.nrows();

  // test it
  Matrix AInvA(size,size);

  // AInvA = AInv * A
  mult(AInv, A, AInvA);

  // I = identity
  typedef matrix<double, diagonal<>, packed<>, row_major>::type IdentMat;
  IdentMat I(size, size, 0, 0);
  mtl::set_value(I, 1.0);

  // AInvA += -I
  add(scaled(I, -1.0), AInvA);

  if (size < MAX_PRINT_SIZE) {
    std::cout << "Ainv * A - I = " << std::endl;
    print_all_matrix(AInvA);
  }

  // find max error
  double max_error = 0.0;
  for(Matrix::iterator i = AInvA.begin(); i != AInvA.end(); ++i)
    for(Matrix::Row::iterator j = (*i).begin(); j != (*i).end(); ++j)
      if(fabs(*j) > fabs(max_error))
	max_error = *j;

  std::cout << "max error = " << max_error << std::endl;

  return max_error;
}

void testLUSoln(const Matrix &A, const Vector &b, Vector &x)
{
  // create LU decomposition
  Matrix LU(A.nrows(), A.ncols());
  dense1D<int> pvector(A.nrows());

  copy(A, LU);
  lu_factorize(LU, pvector);

  // solve
  lu_solve(LU, pvector, b, x);
}

void testLUInv(const Matrix &A, int size)
{
  // invert it
  Matrix AInv(size,size);

  // create LU decomposition
  Matrix LU(A.nrows(), A.ncols());
  dense1D<int> pvector(A.nrows());

  copy(A, LU);
  lu_factor(LU, pvector);

  // solve
  lu_inverse(LU, pvector, AInv);

  if(size < MAX_PRINT_SIZE) {
    std::cout << "Ainv = " << std::endl;
    print_all_matrix(AInv);
  }

  // test it
  testMatrixError(A, AInv);

}

int main(int argc, char **argv)
{
  typedef Matrix::size_type sizeT;

  sizeT size = 3;

  if(argc > 1)
    size = atoi(argv[1]);

  std::cout << "inverting matrix of size " << size << std::endl;

  // create a random matrix and invert it.  Then see how close it comes to
  // identity.

  Matrix A(size,size);
  Vector b(size);
  Vector x(size);

  // initialize
  for (sizeT i=0; i<A.nrows(); i++) {
    for (sizeT j=0; j<A.nrows(); j++)
      A(i,j) = (double)(rand() % 200 - 100) / 50.0;
    b[i] = (double)(rand() % 200 - 100) / 50.0;
  }

  if (size < MAX_PRINT_SIZE) {
    std::cout << "A = " << std::endl;
    print_all_matrix(A);
  }

  // time LU inv
  std::cout << std::endl
       << " ----------- testing inversion using LU decomposition"
       << std::endl;
  testLUInv(A, size);

  if (size < MAX_PRINT_SIZE) {
    std::cout << "solution = ";
    print_vector(x);
  }

  // test LU solution
  mtl::set_value(x, 0.0);
  testLUSoln(A, b, x);

  if(size < MAX_PRINT_SIZE) {
    std::cout << "solution = ";
    print_vector(x);
  }

  if(argc == 1)
    std::cout << std::endl
	 << "pass size argument to program to time larger matrices."
	 << std::endl;

  return 0;
}


text:
#include <boost/filesystem.hpp>
#include <fstream>
#include <queue>
#include "../string_tools.hpp"

class DirReader
   {
    boost::filesystem::recursive_directory_iterator dir,initial;
    std::wifstream file_in;
    wchar_t buffer[MAX_STR_SIZE];
    std::string line_current;
    const std::locale locale;
public:
    DirReader(std::string _dir);
    void reset();
    bool check_simlink_and_advance();
    int check_eof_and_advance();
    bool is_separator(wchar_t c);
    wchar_t * get_word_raw();
    wchar_t * get_word();
    std::queue<std::wstring> myqueue;
    //bool getline(std::string & line);
};


text:
#pragma once

#include <xul/xio/io_server.hpp>
#include <xul/net/io_factory.hpp>
#include <xul/net/tcp_acceptor.hpp>
#include <xul/xio/net/tcp_session.hpp>
#include <xul/util/listenable_mixin.hpp>
#include <xul/util/log.hpp>
#include <xul/data/tuple.hpp>
#include <boost/noncopyable.hpp>
#include <map>
#include <set>
#include <stdint.h>
#include <assert.h>

namespace xul {

class tcp_server
    : public listenable_mixin<object_impl<io_server>, io_server_listener, detail::dummy_io_server_listener>
    , public tcp_acceptor_listener
{
public:
    class tcp_server_session : public tcp_session
    {
    public:
        explicit tcp_server_session(tcp_server& owner, tcp_socket* sock)
            : tcp_session(sock)
            , m_owner(owner)
        {
        }
        virtual ~tcp_server_session()
        {
        }

    protected:
        virtual void on_session_error(int errcode)
        {
            do_get_listener()->on_session_error(this, errcode);
            m_owner.on_session_error(this, errcode);
        }

    private:
        tcp_server& m_owner;
    };

    typedef boost::intrusive_ptr<tcp_server_session> tcp_server_session_ptr;
    typedef std::map<tcp_server_session*, tcp_server_session_ptr> tcp_server_session_collection;
    typedef std::set<tcp_server_session_ptr> tcp_server_session_set;

    explicit tcp_server(io_service* ioFactory) : m_io_factory(ioFactory)
    {
        m_acceptor = m_io_factory->create_tcp_acceptor();
        m_acceptor->set_listener(this);
    }
    virtual ~tcp_server()
    {
        destroy();
    }

    bool start(uint16_t port, bool enableReuseAddress)
    {
        stop();
        return m_acceptor->open(port, enableReuseAddress);
    }

    void stop()
    {
        m_sessions.clear();
        m_acceptor->close();
    }
    void destroy()
    {
        m_acceptor->reset_listener();
        stop();
    }

    tcp_acceptor* get_acceptor() { return m_acceptor.get(); }

    virtual void on_acceptor_client(tcp_acceptor* acceptor, tcp_socket* newClient, const inet_socket_address& sockAddr)
    {
        assert(m_acceptor.get() == acceptor);
        tcp_server_session_ptr session = create_session(newClient, sockAddr);
        if (do_get_listener()->on_session_create(this, session.get()))
        {
            session->attach_listener();
            session->open_session();
            m_sessions[session.get()] = session;
        }
    }

    virtual void on_acceptor_error(tcp_acceptor* acceptor, int errcode) { }

    void on_session_error(tcp_server_session* session, int errcode)
    {
        tcp_server_session_collection::iterator iter = m_sessions.find(session);
        if (iter == m_sessions.end())
            return;
        tcp_server_session_ptr p = iter->second;
        p->destroy();
        m_sessions.erase(iter);
        do_get_listener()->on_session_destroy(this, p.get(), errcode);
        XUL_APP_DEBUG("tcp_server::on_session_error " << session->get_remote_address() << " " << xul::make_tuple(session, errcode));
    }

    const tcp_server_session_collection& get_sessions() const { return m_sessions; }

protected:
    virtual tcp_server_session* create_session(tcp_socket* sock, const inet_socket_address& sockaddr)
    {
        return new tcp_server_session(*this, sock);
    }

protected:
    boost::intrusive_ptr<io_service> m_io_factory;

    /// tcp acceptor object
    boost::intrusive_ptr<tcp_acceptor> m_acceptor;

    /// client session collection
    tcp_server_session_collection m_sessions;
};

}

max_stars_repo_name: hindsights/xul

max_issues_repo_name: hindsights/xul

max_forks_repo_name: hindsights/xul


text: #include <boost/numeric/conversion/is_subranged.hpp>

max_stars_repo_name: miathedev/BoostForArduino

max_issues_repo_name: miathedev/BoostForArduino

max_forks_repo_name: miathedev/BoostForArduino


text:
#include <iostream>
#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

int main()
{
  boost::asio::io_service ios;

  boost::asio::deadline_timer t(ios, boost::posix_time::seconds(1));
  t.wait();

  std::cout << "Hello, world!" << std::endl;

  return 0;
}

max_stars_repo_name: nolmeunion/learn

max_issues_repo_name: nolmeunion/learn

max_forks_repo_name: nolmeunion/learn


text:
#include "tune_derivatives.hh"

#include "tune_instances.hh"
#include "tune_matrix.hh"
#include "../../util/stream/chain.hh"
#include "../../util/stream/typed_stream.hh"

#include <Eigen/Core>

namespace lm { namespace interpolate {

Accum Derivatives(Instances &in, const Vector &weights, Vector &gradient, Matrix &hessian) {
  gradient = in.CorrectGradientTerm();
  hessian = Matrix::Zero(weights.rows(), weights.rows());

  // TODO: loop instead to force low-memory evaluation?
  // Compute p_I(x)*Z_{\epsilon} i.e. the unnormalized probabilities
  Vector weighted_uni((in.LNUnigrams() * weights).array().exp());
  // Even -inf doesn't work for <s> because weights can be negative.  Manually set it to zero.
  weighted_uni(in.BOS()) = 0.0;
  Accum Z_epsilon = weighted_uni.sum();
  // unigram_cross(i) = \sum_{all x} p_I(x) ln p_i(x)
  Vector unigram_cross(in.LNUnigrams().transpose() * weighted_uni / Z_epsilon);

  Accum sum_B_I = 0.0;
  Accum sum_ln_Z_context = 0.0;

  // Temporaries used each cycle of the loop.
  Matrix convolve;
  Vector full_cross;
  Matrix hessian_missing_Z_context;
  // Backed off ln p_i(x)B_i(context)
  Vector ln_p_i_backed;
  // Full ln p_i(x | context)
  Vector ln_p_i_full;

  // TODO make configurable memory size.
  util::stream::Chain chain(util::stream::ChainConfig(in.ReadExtensionsEntrySize(), 2, 64 << 20));
  chain.ActivateProgress();
  in.ReadExtensions(chain);
  util::stream::TypedStream<Extension> extensions(chain.Add());
  chain >> util::stream::kRecycle;

  // Loop over instances (words in the tuning data).
  for (InstanceIndex n = 0; n < in.NumInstances(); ++n) {
    assert(extensions);
    Accum weighted_backoffs = exp(in.LNBackoffs(n).dot(weights));

    // Compute \sum_{x: model does not back off to unigram} p_I(x)Z(epsilon)
    Accum unnormalized_sum_x_p_I = 0.0;
    // Compute \sum_{x: model does not back off to unigram} p_I(x | context)Z(context)
    Accum unnormalized_sum_x_p_I_full = 0.0;

    // This should be divided by Z_context then added to the Hessian.
    hessian_missing_Z_context = Matrix::Zero(weights.rows(), weights.rows());

    full_cross = Vector::Zero(weights.rows());

    // Loop over words within an instance for which extension exists.  An extension happens when any model matches more than a unigram in the tuning instance.
    while (extensions && extensions->instance == n) {
      const WordIndex word = extensions->word;
      unnormalized_sum_x_p_I += weighted_uni(word);

      ln_p_i_backed = in.LNUnigrams().row(word) + in.LNBackoffs(n);

      // Calculate ln_p_i_full(i) = ln p_i(word | context) by filling in unigrams then overwriting with extensions.
      ln_p_i_full = ln_p_i_backed;
      // Loop over all models that have an extension for the same word namely p_i(word | context) matches at least a bigram.
      for (; extensions && extensions->word == word && extensions->instance == n; ++extensions) {
        ln_p_i_full(extensions->model) = extensions->ln_prob;
      }

      // This is the weighted product of probabilities.  In other words, p_I(word | context) * Z(context) = exp(\sum_i w_i * p_i(word | context)).
      Accum weighted = exp(ln_p_i_full.dot(weights));
      unnormalized_sum_x_p_I_full += weighted;

      // These aren't normalized by Z_context (happens later)
      full_cross.noalias() +=
        weighted * ln_p_i_full
        - weighted_uni(word) * weighted_backoffs /* we'll divide by Z_context later to form B_I */ * in.LNUnigrams().row(word).transpose();

      // This will get multiplied by Z_context then added to the Hessian.
      hessian_missing_Z_context.noalias() +=
        // Replacement terms.
        weighted * ln_p_i_full * ln_p_i_full.transpose()
        // Presumed unigrams.  Z_epsilon * weighted_backoffs will turn into B_I once all of this is divided by Z_context.
        - weighted_uni(word) * weighted_backoffs * ln_p_i_backed * ln_p_i_backed.transpose();
    }

    Accum Z_context =
      weighted_backoffs * (Z_epsilon - unnormalized_sum_x_p_I) // Back off and unnormalize the unigrams for which there is no extension.
      + unnormalized_sum_x_p_I_full; // Add the extensions.
    sum_ln_Z_context += log(Z_context);
    Accum B_I = Z_epsilon / Z_context * weighted_backoffs;
    sum_B_I += B_I;

    // This is the gradient term for this instance except for -log p_i(w_n | w_1^{n-1}) which was accounted for as part of neg_correct_sum_.
    // full_cross(i) is \sum_{all x} p_I(x | context) log p_i(x | context)
    // Prior terms excluded dividing by Z_context because it wasn't known at the time.
    full_cross /= Z_context;
    full_cross +=
      // Uncorrected term
      B_I * (in.LNBackoffs(n).transpose() + unigram_cross)
      // Subtract values that should not have been charged.
      - unnormalized_sum_x_p_I / Z_epsilon * B_I * in.LNBackoffs(n).transpose();
    gradient += full_cross;

    convolve = unigram_cross * in.LNBackoffs(n);
    // There's one missing term here, which is independent of context and done at the end.
    hessian.noalias() +=
      // First term of Hessian, assuming all models back off to unigram.
      B_I * (convolve + convolve.transpose() + in.LNBackoffs(n).transpose() * in.LNBackoffs(n))
      // Error in the first term, correcting from unigram to full probabilities.
      + hessian_missing_Z_context / Z_context
      // Second term of Hessian, with correct full probabilities.
      - full_cross * full_cross.transpose();
  }

  for (Matrix::Index x = 0; x < weighted_uni.rows(); ++x) {
    // \sum_{contexts} B_I(context) \sum_x p_I(x) log p_i(x) log p_j(x)
    // TODO can this be optimized?  It's summing over the entire vocab which should be a matrix operation.
    hessian.noalias() += sum_B_I * weighted_uni(x) / Z_epsilon * in.LNUnigrams().row(x).transpose() * in.LNUnigrams().row(x);
  }
  return exp((in.CorrectGradientTerm().dot(weights) + sum_ln_Z_context) / static_cast<double>(in.NumInstances()));
}

}} // namespaces


text:
/**************************************************************
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 *************************************************************/

#ifndef _CPPCANVAS_SPRITECANVAS_HXX
#define _CPPCANVAS_SPRITECANVAS_HXX

#include <sal/types.h>
#include <osl/diagnose.h>
#include <basegfx/vector/b2dsize.hxx>

#include <boost/shared_ptr.hpp>

#include <cppcanvas/bitmapcanvas.hxx>
#include <cppcanvas/sprite.hxx>
#include <cppcanvas/customsprite.hxx>

namespace com { namespace sun { namespace star { namespace rendering
{
    class  XSpriteCanvas;
} } } }

/* Definition of SpriteCanvas */

namespace cppcanvas
{
    class SpriteCanvas;

    // forward declaration, since cloneSpriteCanvas() also references SpriteCanvas
    typedef ::boost::shared_ptr< ::cppcanvas::SpriteCanvas > SpriteCanvasSharedPtr;

    /** SpriteCanvas interface
     */
    class SpriteCanvas : public virtual BitmapCanvas
    {
    public:
        virtual bool					updateScreen( bool bUpdateAll ) const = 0;

        virtual CustomSpriteSharedPtr 	createCustomSprite( const ::basegfx::B2DSize& ) const = 0;
        virtual SpriteSharedPtr 		createClonedSprite( const SpriteSharedPtr& ) const = 0;

        // shared_ptr does not allow for covariant return types
        SpriteCanvasSharedPtr			cloneSpriteCanvas() const
        {
            SpriteCanvasSharedPtr p( ::boost::dynamic_pointer_cast< SpriteCanvas >(this->clone()) );
            OSL_ENSURE(p.get(), "SpriteCanvas::cloneSpriteCanvas(): dynamic cast failed");
            return p;
        }

        virtual ::com::sun::star::uno::Reference<
            ::com::sun::star::rendering::XSpriteCanvas > 	getUNOSpriteCanvas() const = 0;
    };

}

#endif /* _CPPCANVAS_SPRITECANVAS_HXX */

ext: hxx

max_stars_repo_name: Grosskopf/openoffice

max_issues_repo_name: Grosskopf/openoffice

max_forks_repo_name: Grosskopf/openoffice