<commit_before>#ifndef IMPLSTORE_HPP
# define IMPLSTORE_HPP
# pragma once

#include <cstddef>

#include <new>

#include <type_traits>

#include <utility>

namespace generic
{

template <class U, ::std::size_t N = 64>
class implstore
{
public:
  static constexpr ::std::size_t buffer_size = N;

  using value_type = U;

  template <typename ...A, typename =
    typename ::std::enable_if<::std::is_constructible<U, A...>{}>::type>
  implstore(A&& ...args)
  {
    static_assert(sizeof(U) <= sizeof(store_),
      "impl too large");
    new (static_cast<void*>(&store_)) U(::std::forward<A>(args)...);

    deleter_ = deleter_stub;
  }

  ~implstore() { if (deleter_) deleter_(*this); }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_copy_constructible<K>{}>::type>
  implstore(implstore<U, M> const& other)
  {
    new (static_cast<void*>(&store_)) U(*other);

    deleter_ = other.deleter_;
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_move_constructible<K>{}>::type>
  implstore(implstore<U, M>&& other)
  {
    new (static_cast<void*>(&store_)) U(::std::move(*other));

    deleter_ = other.deleter_;
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_copy_assignable<K>{}>::type>
  implstore& operator=(implstore<U, M> const& other)
  {
    **this = *other;

    return *this;
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_move_assignable<K>{}>::type>
  implstore& operator=(implstore<U, M>&& other)
  {
    **this = ::std::move(*other);

    return *this;
  }

  U const* operator->() const noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U* operator->() noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U const* get() const noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U* get() noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U const& operator*() const noexcept
  {
    return *reinterpret_cast<U*>(&store_);
  }

  U& operator*() noexcept
  {
    return *reinterpret_cast<U*>(&store_);
  }

  explicit operator bool() const noexcept { return deleter_; }

private:
  static void deleter_stub(implstore& is) { is->~U(); }

private:
  using deleter_type = void(*)(implstore&);
  deleter_type deleter_;

  typename ::std::aligned_storage<N>::type store_;
};

}

#endif // IMPLSTORE_HPP
<commit_msg>some fixes<commit_after>#ifndef IMPLSTORE_HPP
# define IMPLSTORE_HPP
# pragma once

#include <cstddef>

#include <new>

#include <type_traits>

#include <utility>

namespace generic
{

template <class U, ::std::size_t N = 64>
class implstore
{
public:
  static constexpr ::std::size_t buffer_size = N;

  using value_type = U;

  template <typename ...A, typename =
    typename ::std::enable_if<::std::is_constructible<U, A...>{}>::type>
  implstore(A&& ...args)
  {
    static_assert(sizeof(U) <= sizeof(store_),
      "impl too large");
    new (static_cast<void*>(&store_)) U(::std::forward<A>(args)...);
  }

  ~implstore() { get()->~U(); }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_copy_constructible<K>{}>::type>
  implstore(implstore<U, M> const& other)
  {
    new (static_cast<void*>(&store_)) U(*other);
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_move_constructible<K>{}>::type>
  implstore(implstore<U, M>&& other)
  {
    new (static_cast<void*>(&store_)) U(::std::move(*other));
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_copy_assignable<K>{}>::type>
  implstore& operator=(implstore<U, M> const& other)
  {
    **this = *other;

    return *this;
  }

  template <::std::size_t M, typename K = U, typename =
    typename ::std::enable_if<::std::is_move_assignable<K>{}>::type>
  implstore& operator=(implstore<U, M>&& other)
  {
    **this = ::std::move(*other);

    return *this;
  }

  U const* operator->() const noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U* operator->() noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U const* get() const noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U* get() noexcept
  {
    return reinterpret_cast<U*>(&store_);
  }

  U const& operator*() const noexcept
  {
    return *reinterpret_cast<U*>(&store_);
  }

  U& operator*() noexcept
  {
    return *reinterpret_cast<U*>(&store_);
  }

private:
  typename ::std::aligned_storage<N>::type store_;
};

}

#endif // IMPLSTORE_HPP
<|endoftext|>


<commit_before>#include "atomic.h"
#include "rmc.h"
#include <unistd.h>

// Testing with some different lock implementations.

typedef struct bslock_peterson_t {
    int turn;
    int flag[2];
} bslock_peterson_t;
#define BSLOCK_INIT { 0, {0, 0} }

void bslock_lock_peterson(bslock_peterson_t *lock, int me) {
    int rt, rf;
    int other = 1-me;
    ACCESS_ONCE(lock->turn) = other;
    ACCESS_ONCE(lock->flag[me]) = 1;
    smp_mb();
    while (ACCESS_ONCE(lock->flag[other]) && ACCESS_ONCE(lock->turn) == other) {
        continue;
    }
}

void bslock_unlock_peterson(bslock_peterson_t *lock, int me) {
    ACCESS_ONCE(lock->flag[me]) = 0;
}

//
#define bslock_dekker_t bslock_peterson_t

void bslock_lock_dekker(bslock_dekker_t *lock, int me) {
    int other = 1-me;
    ACCESS_ONCE(lock->flag[me]) = 1;
    smp_mb();
    while (ACCESS_ONCE(lock->flag[other])) {
        if (ACCESS_ONCE(lock->turn) != me) {
            ACCESS_ONCE(lock->flag[me]) = 0;
            while (ACCESS_ONCE(lock->turn) != me) {
                continue;
            }
            ACCESS_ONCE(lock->flag[me]) = 1;
            smp_mb();
        }
    }
}

void bslock_unlock_dekker(bslock_dekker_t *lock, int me) {
    int other = 1-me;
    ACCESS_ONCE(lock->turn) = other;
    ACCESS_ONCE(lock->flag[me]) = 0;
}

//
#ifdef INCLUDE_CPP
#include <atomic>

typedef struct bslock_dekker11_t {
    std::atomic<int> turn;
    std::atomic<int> flag[2];
} bslock_dekker11_t;

void bslock_lock_dekker11(bslock_dekker11_t *lock, int me) {
    int other = 1-me;
    lock->flag[me] = 1;
    while (lock->flag[other]) {
        if (lock->turn != me) {
            lock->flag[me] = 0;
            while (lock->turn != me) {
                continue;
            }
            lock->flag[me] = 1;
        }
    }
}

void bslock_unlock_dekker11(bslock_dekker11_t *lock, int me) {
    int other = 1-me;
    lock->turn = other;
    lock->flag[me] = 0;
}
#endif

#ifndef NO_TEST
/*************************** Testing ***************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define INT_TO_PTR(n) ((void *)(long)n)
#define PTR_TO_INT(n) ((int)(long)n)

#ifndef TEST_NAME
#define TEST_NAME peterson
#endif

/* C. */
#define CAT(x,y)      x ## y
#define XCAT(x,y)     CAT(x,y)

#define bslock_lock XCAT(bslock_lock_, TEST_NAME)
#define bslock_unlock XCAT(bslock_unlock_, TEST_NAME)
#define bslock_t XCAT(XCAT(bslock_, TEST_NAME), _t)

#define ITERATIONS 10000000

int PADDED num_in_section;
int PADDED collision_count[2];

bslock_t lock/* = BSLOCK_INIT*/;

long iterations;

void *tester(void *p)
{
    int me = (int)(long)p;
    int i = 0;

    while (i < iterations) {
        bslock_lock(&lock, me);
        if (__sync_fetch_and_add(&num_in_section, 1) == 1) {
            collision_count[me]++;
        }
        __sync_fetch_and_add(&num_in_section, -1);
        bslock_unlock(&lock, me);

        i++;
    }

    return NULL;
}

int main(int argc, char **argv)
{
    iterations = (argc == 2) ? strtol(argv[1], NULL, 0) : ITERATIONS;
    void *arg = (void *)(long)iterations;

    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, tester, INT_TO_PTR(0));
    pthread_create(&thread2, NULL, tester, INT_TO_PTR(1));

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("collisions: 0 = %d, 1 = %d\n",
           collision_count[0], collision_count[1]);

    return 0;
}

#endif
<commit_msg>Drop the pointless include of rmc.h in the locks experiment<commit_after>#include "atomic.h"
#include <unistd.h>

// Testing with some different lock implementations.

typedef struct bslock_peterson_t {
    int turn;
    int flag[2];
} bslock_peterson_t;
#define BSLOCK_INIT { 0, {0, 0} }

void bslock_lock_peterson(bslock_peterson_t *lock, int me) {
    int rt, rf;
    int other = 1-me;
    ACCESS_ONCE(lock->turn) = other;
    ACCESS_ONCE(lock->flag[me]) = 1;
    smp_mb();
    while (ACCESS_ONCE(lock->flag[other]) && ACCESS_ONCE(lock->turn) == other) {
        continue;
    }
}

void bslock_unlock_peterson(bslock_peterson_t *lock, int me) {
    ACCESS_ONCE(lock->flag[me]) = 0;
}

//
#define bslock_dekker_t bslock_peterson_t

void bslock_lock_dekker(bslock_dekker_t *lock, int me) {
    int other = 1-me;
    ACCESS_ONCE(lock->flag[me]) = 1;
    smp_mb();
    while (ACCESS_ONCE(lock->flag[other])) {
        if (ACCESS_ONCE(lock->turn) != me) {
            ACCESS_ONCE(lock->flag[me]) = 0;
            while (ACCESS_ONCE(lock->turn) != me) {
                continue;
            }
            ACCESS_ONCE(lock->flag[me]) = 1;
            smp_mb();
        }
    }
}

void bslock_unlock_dekker(bslock_dekker_t *lock, int me) {
    int other = 1-me;
    ACCESS_ONCE(lock->turn) = other;
    ACCESS_ONCE(lock->flag[me]) = 0;
}

//
#ifdef INCLUDE_CPP
#include <atomic>

typedef struct bslock_dekker11_t {
    std::atomic<int> turn;
    std::atomic<int> flag[2];
} bslock_dekker11_t;

void bslock_lock_dekker11(bslock_dekker11_t *lock, int me) {
    int other = 1-me;
    lock->flag[me] = 1;
    while (lock->flag[other]) {
        if (lock->turn != me) {
            lock->flag[me] = 0;
            while (lock->turn != me) {
                continue;
            }
            lock->flag[me] = 1;
        }
    }
}

void bslock_unlock_dekker11(bslock_dekker11_t *lock, int me) {
    int other = 1-me;
    lock->turn = other;
    lock->flag[me] = 0;
}
#endif

#ifndef NO_TEST
/*************************** Testing ***************************************/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>

#define INT_TO_PTR(n) ((void *)(long)n)
#define PTR_TO_INT(n) ((int)(long)n)

#ifndef TEST_NAME
#define TEST_NAME peterson
#endif

/* C. */
#define CAT(x,y)      x ## y
#define XCAT(x,y)     CAT(x,y)

#define bslock_lock XCAT(bslock_lock_, TEST_NAME)
#define bslock_unlock XCAT(bslock_unlock_, TEST_NAME)
#define bslock_t XCAT(XCAT(bslock_, TEST_NAME), _t)

#define ITERATIONS 10000000

int PADDED num_in_section;
int PADDED collision_count[2];

bslock_t lock/* = BSLOCK_INIT*/;

long iterations;

void *tester(void *p)
{
    int me = (int)(long)p;
    int i = 0;

    while (i < iterations) {
        bslock_lock(&lock, me);
        if (__sync_fetch_and_add(&num_in_section, 1) == 1) {
            collision_count[me]++;
        }
        __sync_fetch_and_add(&num_in_section, -1);
        bslock_unlock(&lock, me);

        i++;
    }

    return NULL;
}

int main(int argc, char **argv)
{
    iterations = (argc == 2) ? strtol(argv[1], NULL, 0) : ITERATIONS;
    void *arg = (void *)(long)iterations;

    pthread_t thread1, thread2;
    pthread_create(&thread1, NULL, tester, INT_TO_PTR(0));
    pthread_create(&thread2, NULL, tester, INT_TO_PTR(1));

    pthread_join(thread1, NULL);
    pthread_join(thread2, NULL);

    printf("collisions: 0 = %d, 1 = %d\n",
           collision_count[0], collision_count[1]);

    return 0;
}

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "itkImageRegionConstIterator.h"
//  Software Guide : BeginLatex
//
//  Usually, the streaming process is hidden within the pipeline. This
//  allows the user to get rid of the annoying task of splitting the
//  images into tiles, end so on. However, for some kinds of
//  processing, we do not really need a pipeline: no writer is needed,
//  only read access to pixel values is wanted. In these cases, one
//  has to explicitly set up the streaming procedure. Fortunately, OTB
//  offers a high level of abstraction for this task. We will need to
//  include the following header files:
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkImageRegionSplitter.h"
#include "otbStreamingTraits.h"
// Software Guide : EndCodeSnippet

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

  if( argc != 3 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile nbLinesForStreaming " << std::endl;
    return EXIT_FAILURE;
    }

  const char * infname = argv[1];
  const unsigned int nbLinesForStreaming = atoi(argv[2]);

  typedef float PixelType;

  typedef otb::VectorImage<PixelType,2> ImageType;
  typedef otb::ImageFileReader<ImageType> ImageReaderType;

//  Software Guide : BeginLatex
//
//  The \doxygen{otb}{StreamingTraits} class manages the streaming
//  approaches which are possible with the image type over which it is
//  templated. The class \doxygen{itk}{ImageRegionSplitter} is
//  templated over the number of dimensions of the image and will
//  perform the actual image splitting.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef otb::StreamingTraits<ImageType> StreamingTraitsType;
  typedef itk::ImageRegionSplitter<2>  SplitterType;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  Once a region of the image is available, we will use classical
//  region iterators to get the pixels.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef ImageType::RegionType RegionType;

  typedef itk::ImageRegionConstIterator<ImageType> IteratorType;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We instantiate the image file reader, but in order to avoid
//  reading the whole image, we call the
//  \code{GenerateOutputInformation()} method instead of the
//  \code{Update()} one. \code{GenerateOutputInformation()} will make
//  available the information about sizes, band, resolutions,
//  etc. After that, we can access the largest possible region of the
//  input image.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ImageReaderType::Pointer reader = ImageReaderType::New();

  reader->SetFileName(infname);

  reader->GenerateOutputInformation();

  RegionType largestRegion = reader->GetOutput()->GetLargestPossibleRegion();
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We set up now the local streaming capabilities by asking the
//  streaming traits to compute the number of regions to split the
//  image into given the splitter, the user defined number of lines,
//  and the input image information.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  SplitterType::Pointer splitter = SplitterType::New();
  unsigned int numberOfStreamDivisions =
    StreamingTraitsType::CalculateNumberOfStreamDivisions(
      reader->GetOutput(),
      largestRegion,
      splitter,
      otb::SET_BUFFER_NUMBER_OF_LINES,
      0,0,nbLinesForStreaming);
// Software Guide : EndCodeSnippet
  std::cout<<"The images will be streamed into "<<numberOfStreamDivisions<<" parts."<<std::endl;

//  Software Guide : BeginLatex
//
//  We can now get the split regions and iterate through them.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

  unsigned int piece = 0;
  RegionType streamingRegion;

  for (piece = 0;
       piece < numberOfStreamDivisions;
       piece++)
  {
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We get the region
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
    streamingRegion =
      splitter->GetSplit(piece,numberOfStreamDivisions,largestRegion);

    std::cout<<"Processing region: "<<streamingRegion<<std::endl;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We ask the reader to provide the region.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

    reader->GetOutput()->SetRequestedRegion(streamingRegion);
    reader->GetOutput()->PropagateRequestedRegion();
    reader->GetOutput()->UpdateOutputData();
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We declare an iterator and walk through the region.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

    IteratorType it(reader->GetOutput(),streamingRegion);
    it.GoToBegin();

    while(!it.IsAtEnd())
    {
    std::cout << it.Get() << std::endl;
    ++it;
    }

// Software Guide : EndCodeSnippet
  }
    return EXIT_SUCCESS;
}
<commit_msg>Exemple streaming explicite<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif

#ifdef __BORLANDC__
#define ITK_LEAN_AND_MEAN
#endif

#include "otbVectorImage.h"
#include "otbImageFileReader.h"
#include "itkImageRegionConstIterator.h"
//  Software Guide : BeginLatex
//
//  Usually, the streaming process is hidden within the pipeline. This
//  allows the user to get rid of the annoying task of splitting the
//  images into tiles, and so on. However, for some kinds of
//  processing, we do not really need a pipeline: no writer is needed,
//  only read access to pixel values is wanted. In these cases, one
//  has to explicitly set up the streaming procedure. Fortunately, OTB
//  offers a high level of abstraction for this task. We will need to
//  include the following header files:
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
#include "itkImageRegionSplitter.h"
#include "otbStreamingTraits.h"
// Software Guide : EndCodeSnippet

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

  if( argc != 3 )
    {
    std::cerr << "Usage: " << std::endl;
    std::cerr << argv[0] << " inputImageFile nbLinesForStreaming " << std::endl;
    return EXIT_FAILURE;
    }

  const char * infname = argv[1];
  const unsigned int nbLinesForStreaming = atoi(argv[2]);

  typedef float PixelType;

  typedef otb::VectorImage<PixelType,2> ImageType;
  typedef otb::ImageFileReader<ImageType> ImageReaderType;

//  Software Guide : BeginLatex
//
//  The \doxygen{otb}{StreamingTraits} class manages the streaming
//  approaches which are possible with the image type over which it is
//  templated. The class \doxygen{itk}{ImageRegionSplitter} is
//  templated over the number of dimensions of the image and will
//  perform the actual image splitting.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef otb::StreamingTraits<ImageType> StreamingTraitsType;
  typedef itk::ImageRegionSplitter<2>  SplitterType;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  Once a region of the image is available, we will use classical
//  region iterators to get the pixels.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  typedef ImageType::RegionType RegionType;

  typedef itk::ImageRegionConstIterator<ImageType> IteratorType;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We instantiate the image file reader, but in order to avoid
//  reading the whole image, we call the
//  \code{GenerateOutputInformation()} method instead of the
//  \code{Update()} one. \code{GenerateOutputInformation()} will make
//  available the information about sizes, band, resolutions,
//  etc. After that, we can access the largest possible region of the
//  input image.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  ImageReaderType::Pointer reader = ImageReaderType::New();

  reader->SetFileName(infname);

  reader->GenerateOutputInformation();

  RegionType largestRegion = reader->GetOutput()->GetLargestPossibleRegion();
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We set up now the local streaming capabilities by asking the
//  streaming traits to compute the number of regions to split the
//  image into given the splitter, the user defined number of lines,
//  and the input image information.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
  SplitterType::Pointer splitter = SplitterType::New();
  unsigned int numberOfStreamDivisions =
    StreamingTraitsType::CalculateNumberOfStreamDivisions(
      reader->GetOutput(),
      largestRegion,
      splitter,
      otb::SET_BUFFER_NUMBER_OF_LINES,
      0,0,nbLinesForStreaming);
// Software Guide : EndCodeSnippet
  std::cout<<"The images will be streamed into "<<numberOfStreamDivisions<<" parts."<<std::endl;

//  Software Guide : BeginLatex
//
//  We can now get the split regions and iterate through them.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

  unsigned int piece = 0;
  RegionType streamingRegion;

  for (piece = 0;
       piece < numberOfStreamDivisions;
       piece++)
  {
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We get the region
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet
    streamingRegion =
      splitter->GetSplit(piece,numberOfStreamDivisions,largestRegion);

    std::cout<<"Processing region: "<<streamingRegion<<std::endl;
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We ask the reader to provide the region.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

    reader->GetOutput()->SetRequestedRegion(streamingRegion);
    reader->GetOutput()->PropagateRequestedRegion();
    reader->GetOutput()->UpdateOutputData();
// Software Guide : EndCodeSnippet
//  Software Guide : BeginLatex
//
//  We declare an iterator and walk through the region.
//
//  Software Guide : EndLatex

// Software Guide : BeginCodeSnippet

    IteratorType it(reader->GetOutput(),streamingRegion);
    it.GoToBegin();

    while(!it.IsAtEnd())
    {
    std::cout << it.Get() << std::endl;
    ++it;
    }

// Software Guide : EndCodeSnippet
  }
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#if defined(__APPLE__)

#include "apple_fsnotifier.h"

using namespace std;

WatchPoint::WatchPoint(Server* server, CFRunLoopRef runLoop, const u16string& path, long latencyInMillis) {
    CFStringRef cfPath = CFStringCreateWithCharacters(NULL, (UniChar*) path.c_str(), path.length());
    if (cfPath == nullptr) {
        throw FileWatcherException("Could not allocate CFString for path", path);
    }
    CFMutableArrayRef pathArray = CFArrayCreateMutable(NULL, 1, NULL);
    if (pathArray == NULL) {
        throw FileWatcherException("Could not allocate array to store root to watch", path);
    }
    CFArrayAppendValue(pathArray, cfPath);

    FSEventStreamContext context = {
        0,                 // version, must be 0
        (void*) server,    // info
        NULL,              // retain
        NULL,              // release
        NULL               // copyDescription
    };
    FSEventStreamRef watcherStream = FSEventStreamCreate(
        NULL,
        &handleEventsCallback,
        &context,
        pathArray,
        kFSEventStreamEventIdSinceNow,
        latencyInMillis / 1000.0,
        kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagWatchRoot);
    CFRelease(pathArray);
    CFRelease(cfPath);
    if (watcherStream == NULL) {
        throw FileWatcherException("Couldn't add watch", path);
    }
    FSEventStreamScheduleWithRunLoop(watcherStream, runLoop, kCFRunLoopDefaultMode);
    FSEventStreamStart(watcherStream);
    this->watcherStream = watcherStream;
}

WatchPoint::~WatchPoint() {
    // Reading the Apple docs it seems we should call FSEventStreamFlushSync() here.
    // But doing so produces this log:
    //
    //     2020-02-17 23:02 java[50430] (FSEvents.framework) FSEventStreamFlushSync(): failed assertion '(SInt64)last_id > 0LL'
    //
    // According to this comment we should not use flush at all, and it's probably broken:
    // https://github.com/nodejs/node/issues/854#issuecomment-294892950
    // As the comment mentions, even Watchman doesn't flush:
    // https://github.com/facebook/watchman/blob/b397e00cf566f361282a456122eef4e909f26182/watcher/fsevents.cpp#L276-L285
    // FSEventStreamFlushSync(watcherStream);
    FSEventStreamStop(watcherStream);
    FSEventStreamInvalidate(watcherStream);
    FSEventStreamRelease(watcherStream);
}

//
// Server
//

void processCommandsCallback(void* info) {
    Server* server = (Server*) info;
    server->processCommands();
}

Server::Server(JNIEnv* env, jobject watcherCallback, long latencyInMillis)
    : AbstractServer(env, watcherCallback)
    , latencyInMillis(latencyInMillis) {
    CFRunLoopSourceContext context = {
        0,                         // version;
        (void*) this,              // info;
        NULL,                      // retain()
        NULL,                      // release()
        NULL,                      // copyDescription()
        NULL,                      // equal()
        NULL,                      // hash()
        NULL,                      // schedule()
        NULL,                      // cancel()
        processCommandsCallback    // perform()
    };
    messageSource = CFRunLoopSourceCreate(
        kCFAllocatorDefault,    // allocator
        0,                      // index
        &context                // context
    );
    startThread();
}

Server::~Server() {
    vector<u16string> paths(watchPoints.size());
    for (auto& watchPoint : watchPoints) {
        paths.push_back(watchPoint.first);
    }
    executeOnThread(shared_ptr<Command>(new UnregisterPathsCommand(paths)));
    executeOnThread(shared_ptr<Command>(new TerminateCommand()));

    if (watcherThread.joinable()) {
        watcherThread.join();
    }
    CFRelease(messageSource);
}

void Server::runLoop(function<void(exception_ptr)> notifyStarted) {
    try {
        CFRunLoopRef threadLoop = CFRunLoopGetCurrent();
        this->threadLoop = threadLoop;

        CFRunLoopAddSource(threadLoop, messageSource, kCFRunLoopDefaultMode);

        notifyStarted(nullptr);
    } catch (...) {
        notifyStarted(current_exception());
    }

    CFRunLoopRun();
}

void Server::processCommandsOnThread() {
    CFRunLoopSourceSignal(messageSource);
    CFRunLoopWakeUp(threadLoop);
}

void Server::terminate() {
    CFRunLoopStop(threadLoop);
}

static void handleEventsCallback(
    ConstFSEventStreamRef,
    void* clientCallBackInfo,
    size_t numEvents,
    void* eventPaths,
    const FSEventStreamEventFlags eventFlags[],
    const FSEventStreamEventId*) {
    Server* server = (Server*) clientCallBackInfo;
    server->handleEvents(numEvents, (char**) eventPaths, eventFlags);
}

void Server::handleEvents(
    size_t numEvents,
    char** eventPaths,
    const FSEventStreamEventFlags eventFlags[]) {
    JNIEnv* env = getThreadEnv();

    try {
        for (size_t i = 0; i < numEvents; i++) {
            handleEvent(env, eventPaths[i], eventFlags[i]);
        }
    } catch (const exception& ex) {
        reportError(env, ex);
    }
}

void Server::handleEvent(JNIEnv* env, char* path, FSEventStreamEventFlags flags) {
    logToJava(FINE, "Event flags: 0x%x for %s", flags, path);

    jint type;
    if (IS_SET(flags, kFSEventStreamEventFlagHistoryDone)) {
        return;
    } else if (IS_ANY_SET(flags,
                   kFSEventStreamEventFlagRootChanged
                       | kFSEventStreamEventFlagMount
                       | kFSEventStreamEventFlagUnmount
                       | kFSEventStreamEventFlagMustScanSubDirs)) {
        type = FILE_EVENT_INVALIDATE;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemRenamed)) {
        if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
            type = FILE_EVENT_REMOVED;
        } else {
            type = FILE_EVENT_CREATED;
        }
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemModified)) {
        type = FILE_EVENT_MODIFIED;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemRemoved)) {
        type = FILE_EVENT_REMOVED;
    } else if (IS_ANY_SET(flags,
                   kFSEventStreamEventFlagItemInodeMetaMod    // file locked
                       | kFSEventStreamEventFlagItemFinderInfoMod
                       | kFSEventStreamEventFlagItemChangeOwner
                       | kFSEventStreamEventFlagItemXattrMod)) {
        type = FILE_EVENT_MODIFIED;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
        type = FILE_EVENT_CREATED;
    } else {
        logToJava(WARNING, "Unknown event 0x%x for %s", flags, path);
        type = FILE_EVENT_UNKNOWN;
    }

    logToJava(FINE, "Changed: %s %d", path, type);
    u16string pathStr = utf8ToUtf16String(path);
    reportChange(env, type, pathStr);
}

void Server::registerPath(const u16string& path) {
    if (watchPoints.find(path) != watchPoints.end()) {
        throw FileWatcherException("Already watching path", path);
    }
    watchPoints.emplace(piecewise_construct,
        forward_as_tuple(path),
        forward_as_tuple(this, threadLoop, path, latencyInMillis));
}

void Server::unregisterPath(const u16string& path) {
    if (watchPoints.erase(path) == 0) {
        logToJava(FINE, "Path is not watched: %s", utf16ToUtf8String(path).c_str());
    }
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_startWatcher0(JNIEnv* env, jclass, long latencyInMillis, jobject javaCallback) {
    return wrapServer(env, [env, javaCallback, latencyInMillis]() {
        return new Server(env, javaCallback, latencyInMillis);
    });
}

#endif
<commit_msg>Correctly allocate vector with reserved size<commit_after>#if defined(__APPLE__)

#include "apple_fsnotifier.h"

using namespace std;

WatchPoint::WatchPoint(Server* server, CFRunLoopRef runLoop, const u16string& path, long latencyInMillis) {
    CFStringRef cfPath = CFStringCreateWithCharacters(NULL, (UniChar*) path.c_str(), path.length());
    if (cfPath == nullptr) {
        throw FileWatcherException("Could not allocate CFString for path", path);
    }
    CFMutableArrayRef pathArray = CFArrayCreateMutable(NULL, 1, NULL);
    if (pathArray == NULL) {
        throw FileWatcherException("Could not allocate array to store root to watch", path);
    }
    CFArrayAppendValue(pathArray, cfPath);

    FSEventStreamContext context = {
        0,                 // version, must be 0
        (void*) server,    // info
        NULL,              // retain
        NULL,              // release
        NULL               // copyDescription
    };
    FSEventStreamRef watcherStream = FSEventStreamCreate(
        NULL,
        &handleEventsCallback,
        &context,
        pathArray,
        kFSEventStreamEventIdSinceNow,
        latencyInMillis / 1000.0,
        kFSEventStreamCreateFlagNoDefer | kFSEventStreamCreateFlagFileEvents | kFSEventStreamCreateFlagWatchRoot);
    CFRelease(pathArray);
    CFRelease(cfPath);
    if (watcherStream == NULL) {
        throw FileWatcherException("Couldn't add watch", path);
    }
    FSEventStreamScheduleWithRunLoop(watcherStream, runLoop, kCFRunLoopDefaultMode);
    FSEventStreamStart(watcherStream);
    this->watcherStream = watcherStream;
}

WatchPoint::~WatchPoint() {
    // Reading the Apple docs it seems we should call FSEventStreamFlushSync() here.
    // But doing so produces this log:
    //
    //     2020-02-17 23:02 java[50430] (FSEvents.framework) FSEventStreamFlushSync(): failed assertion '(SInt64)last_id > 0LL'
    //
    // According to this comment we should not use flush at all, and it's probably broken:
    // https://github.com/nodejs/node/issues/854#issuecomment-294892950
    // As the comment mentions, even Watchman doesn't flush:
    // https://github.com/facebook/watchman/blob/b397e00cf566f361282a456122eef4e909f26182/watcher/fsevents.cpp#L276-L285
    // FSEventStreamFlushSync(watcherStream);
    FSEventStreamStop(watcherStream);
    FSEventStreamInvalidate(watcherStream);
    FSEventStreamRelease(watcherStream);
}

//
// Server
//

void processCommandsCallback(void* info) {
    Server* server = (Server*) info;
    server->processCommands();
}

Server::Server(JNIEnv* env, jobject watcherCallback, long latencyInMillis)
    : AbstractServer(env, watcherCallback)
    , latencyInMillis(latencyInMillis) {
    CFRunLoopSourceContext context = {
        0,                         // version;
        (void*) this,              // info;
        NULL,                      // retain()
        NULL,                      // release()
        NULL,                      // copyDescription()
        NULL,                      // equal()
        NULL,                      // hash()
        NULL,                      // schedule()
        NULL,                      // cancel()
        processCommandsCallback    // perform()
    };
    messageSource = CFRunLoopSourceCreate(
        kCFAllocatorDefault,    // allocator
        0,                      // index
        &context                // context
    );
    startThread();
}

Server::~Server() {
    vector<u16string> paths;
    paths.reserve(watchPoints.size());
    for (auto& it : watchPoints) {
        auto& path = it.first;
        paths.push_back(path);
    }
    executeOnThread(shared_ptr<Command>(new UnregisterPathsCommand(paths)));
    executeOnThread(shared_ptr<Command>(new TerminateCommand()));

    if (watcherThread.joinable()) {
        watcherThread.join();
    }
    CFRelease(messageSource);
}

void Server::runLoop(function<void(exception_ptr)> notifyStarted) {
    try {
        CFRunLoopRef threadLoop = CFRunLoopGetCurrent();
        this->threadLoop = threadLoop;

        CFRunLoopAddSource(threadLoop, messageSource, kCFRunLoopDefaultMode);

        notifyStarted(nullptr);
    } catch (...) {
        notifyStarted(current_exception());
    }

    CFRunLoopRun();
}

void Server::processCommandsOnThread() {
    CFRunLoopSourceSignal(messageSource);
    CFRunLoopWakeUp(threadLoop);
}

void Server::terminate() {
    CFRunLoopStop(threadLoop);
}

static void handleEventsCallback(
    ConstFSEventStreamRef,
    void* clientCallBackInfo,
    size_t numEvents,
    void* eventPaths,
    const FSEventStreamEventFlags eventFlags[],
    const FSEventStreamEventId*) {
    Server* server = (Server*) clientCallBackInfo;
    server->handleEvents(numEvents, (char**) eventPaths, eventFlags);
}

void Server::handleEvents(
    size_t numEvents,
    char** eventPaths,
    const FSEventStreamEventFlags eventFlags[]) {
    JNIEnv* env = getThreadEnv();

    try {
        for (size_t i = 0; i < numEvents; i++) {
            handleEvent(env, eventPaths[i], eventFlags[i]);
        }
    } catch (const exception& ex) {
        reportError(env, ex);
    }
}

void Server::handleEvent(JNIEnv* env, char* path, FSEventStreamEventFlags flags) {
    logToJava(FINE, "Event flags: 0x%x for %s", flags, path);

    jint type;
    if (IS_SET(flags, kFSEventStreamEventFlagHistoryDone)) {
        return;
    } else if (IS_ANY_SET(flags,
                   kFSEventStreamEventFlagRootChanged
                       | kFSEventStreamEventFlagMount
                       | kFSEventStreamEventFlagUnmount
                       | kFSEventStreamEventFlagMustScanSubDirs)) {
        type = FILE_EVENT_INVALIDATE;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemRenamed)) {
        if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
            type = FILE_EVENT_REMOVED;
        } else {
            type = FILE_EVENT_CREATED;
        }
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemModified)) {
        type = FILE_EVENT_MODIFIED;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemRemoved)) {
        type = FILE_EVENT_REMOVED;
    } else if (IS_ANY_SET(flags,
                   kFSEventStreamEventFlagItemInodeMetaMod    // file locked
                       | kFSEventStreamEventFlagItemFinderInfoMod
                       | kFSEventStreamEventFlagItemChangeOwner
                       | kFSEventStreamEventFlagItemXattrMod)) {
        type = FILE_EVENT_MODIFIED;
    } else if (IS_SET(flags, kFSEventStreamEventFlagItemCreated)) {
        type = FILE_EVENT_CREATED;
    } else {
        logToJava(WARNING, "Unknown event 0x%x for %s", flags, path);
        type = FILE_EVENT_UNKNOWN;
    }

    logToJava(FINE, "Changed: %s %d", path, type);
    u16string pathStr = utf8ToUtf16String(path);
    reportChange(env, type, pathStr);
}

void Server::registerPath(const u16string& path) {
    if (watchPoints.find(path) != watchPoints.end()) {
        throw FileWatcherException("Already watching path", path);
    }
    watchPoints.emplace(piecewise_construct,
        forward_as_tuple(path),
        forward_as_tuple(this, threadLoop, path, latencyInMillis));
}

void Server::unregisterPath(const u16string& path) {
    if (watchPoints.erase(path) == 0) {
        logToJava(FINE, "Path is not watched: %s", utf16ToUtf8String(path).c_str());
    }
}

JNIEXPORT jobject JNICALL
Java_net_rubygrapefruit_platform_internal_jni_OsxFileEventFunctions_startWatcher0(JNIEnv* env, jclass, long latencyInMillis, jobject javaCallback) {
    return wrapServer(env, [env, javaCallback, latencyInMillis]() {
        return new Server(env, javaCallback, latencyInMillis);
    });
}

#endif
<|endoftext|>


<commit_before>#ifndef FASTIO_HH
#define	FASTIO_HH

#include "utilities.hh"
#include "Board_traits.hh"
#include <fastarduino/iocommons.hh>

// This class maps to a PORT pin
// SRAM size is 0
template<Board::Port PORT_, uint8_t BIT_>
class FastPin
{
private:
	using TRAIT = Board::Port_trait<PORT_>;

public:
	static const Board::Port PORT = PORT_;
	static const uint8_t BIT = BIT_;

	FastPin() INLINE
	{
		static_assert(TRAIT::DPIN_MASK & _BV(BIT), "BIT must be compatible with PORT available pins");
	}
	FastPin(PinMode mode, bool value = false) INLINE
	{
		static_assert(TRAIT::DPIN_MASK & _BV(BIT), "BIT must be compatible with PORT available pins");
		set_mode(mode, value);
	}
	void set_mode(PinMode mode, bool value = false) INLINE
	{
		if (mode == PinMode::OUTPUT)
			set_ioreg_bit(TRAIT::DDR, BIT);
		else
			clear_ioreg_bit(TRAIT::DDR, BIT);
		if (value || mode == PinMode::INPUT_PULLUP)
			set_ioreg_bit(TRAIT::PORT, BIT);
		else
			clear_ioreg_bit(TRAIT::PORT, BIT);
	}
	void set() INLINE
	{
		set_ioreg_bit(TRAIT::PORT, BIT);
	}
	void clear() INLINE
	{
		clear_ioreg_bit(TRAIT::PORT, BIT);
	}
	void toggle() INLINE
	{
		set_ioreg_bit(TRAIT::PIN, BIT);
	}
	bool value() INLINE
	{
		return ioreg_bit_value(TRAIT::PIN, BIT);
	}
};

// This class maps to a PORT and handles it all 8 bits at a time
// SRAM size is 0
template<Board::Port PORT_>
class FastPort
{
private:
	using TRAIT = Board::Port_trait<PORT_>;

public:
	static const Board::Port PORT = PORT_;

	FastPort() {}
	FastPort(uint8_t ddr, uint8_t port = 0) INLINE
	{
		set_DDR(ddr);
		set_PORT(port);
	}

	template<uint8_t BIT>
	FastPin<PORT, BIT> get_pin(PinMode mode, bool value = false)
	{
		return FastPin<PORT, BIT>{mode, value};
	}

	template<uint8_t BIT>
	FastPin<PORT, BIT> get_pin()
	{
		return FastPin<PORT, BIT>{};
	}

	void set_PORT(uint8_t port) INLINE
	{
		set_ioreg_byte(TRAIT::PORT, port);
	}
	uint8_t get_PORT() INLINE
	{
		return get_ioreg_byte(TRAIT::PORT);
	}
	void set_DDR(uint8_t ddr) INLINE
	{
		set_ioreg_byte(TRAIT::DDR, ddr);
	}
	uint8_t get_DDR() INLINE
	{
		return get_ioreg_byte(TRAIT::DDR);
	}
	void set_PIN(uint8_t pin) INLINE
	{
		set_ioreg_byte(TRAIT::PIN, pin);
	}
	uint8_t get_PIN() INLINE
	{
		return get_ioreg_byte(TRAIT::PIN);
	}
};

template<Board::DigitalPin DPIN>
struct FastPinType
{
	static const Board::Port PORT = Board::DigitalPin_trait<DPIN>::PORT;
	static const uint8_t BIT = Board::DigitalPin_trait<DPIN>::BIT;
	static const uint8_t MASK = _BV(BIT);
	using TYPE = FastPin<PORT, BIT>;
	using PORT_TYPE = FastPort<PORT>;
};

template<>
class FastPin<Board::Port::NONE, 0>
{
public:
	FastPin(PinMode mode UNUSED, bool value UNUSED = false) INLINE {}
	void set() INLINE {}
	void clear() INLINE {}
	void toggle() INLINE {}
	bool value() INLINE
	{
		return false;
	}
};

#endif	/* FASTIO_HH */
<commit_msg>Add MaskedPort to FastIO<commit_after>#ifndef FASTIO_HH
#define	FASTIO_HH

#include "utilities.hh"
#include "Board_traits.hh"
#include <fastarduino/iocommons.hh>

// This class maps to a PORT pin
// SRAM size is 0
template<Board::Port PORT_, uint8_t BIT_>
class FastPin
{
private:
	using TRAIT = Board::Port_trait<PORT_>;

public:
	static const Board::Port PORT = PORT_;
	static const uint8_t BIT = BIT_;

	FastPin() INLINE
	{
		static_assert(TRAIT::DPIN_MASK & _BV(BIT), "BIT must be compatible with PORT available pins");
	}
	FastPin(PinMode mode, bool value = false) INLINE
	{
		static_assert(TRAIT::DPIN_MASK & _BV(BIT), "BIT must be compatible with PORT available pins");
		set_mode(mode, value);
	}
	void set_mode(PinMode mode, bool value = false) INLINE
	{
		if (mode == PinMode::OUTPUT)
			set_ioreg_bit(TRAIT::DDR, BIT);
		else
			clear_ioreg_bit(TRAIT::DDR, BIT);
		if (value || mode == PinMode::INPUT_PULLUP)
			set_ioreg_bit(TRAIT::PORT, BIT);
		else
			clear_ioreg_bit(TRAIT::PORT, BIT);
	}
	void set() INLINE
	{
		set_ioreg_bit(TRAIT::PORT, BIT);
	}
	void clear() INLINE
	{
		clear_ioreg_bit(TRAIT::PORT, BIT);
	}
	void toggle() INLINE
	{
		set_ioreg_bit(TRAIT::PIN, BIT);
	}
	bool value() INLINE
	{
		return ioreg_bit_value(TRAIT::PIN, BIT);
	}
};

// This class maps to a PORT and handles it all 8 bits at a time
// SRAM size is 0
template<Board::Port PORT_>
class FastPort
{
private:
	using TRAIT = Board::Port_trait<PORT_>;

public:
	static const Board::Port PORT = PORT_;

	FastPort() {}
	FastPort(uint8_t ddr, uint8_t port = 0) INLINE
	{
		set_DDR(ddr);
		set_PORT(port);
	}

	template<uint8_t BIT>
	FastPin<PORT, BIT> get_pin(PinMode mode, bool value = false)
	{
		return FastPin<PORT, BIT>{mode, value};
	}

	template<uint8_t BIT>
	FastPin<PORT, BIT> get_pin()
	{
		return FastPin<PORT, BIT>{};
	}

	void set_PORT(uint8_t port) INLINE
	{
		set_ioreg_byte(TRAIT::PORT, port);
	}
	uint8_t get_PORT() INLINE
	{
		return get_ioreg_byte(TRAIT::PORT);
	}
	void set_DDR(uint8_t ddr) INLINE
	{
		set_ioreg_byte(TRAIT::DDR, ddr);
	}
	uint8_t get_DDR() INLINE
	{
		return get_ioreg_byte(TRAIT::DDR);
	}
	void set_PIN(uint8_t pin) INLINE
	{
		set_ioreg_byte(TRAIT::PIN, pin);
	}
	uint8_t get_PIN() INLINE
	{
		return get_ioreg_byte(TRAIT::PIN);
	}
};

// This class maps to a PORT and handles it all 8 bits at a time
// SRAM size is 0
template<Board::Port PORT_>
class FastMaskedPort
{
private:
	using TRAIT = Board::Port_trait<PORT_>;

public:
	static const Board::Port PORT = PORT_;

	FastMaskedPort() {}
	FastMaskedPort(uint8_t mask, uint8_t ddr, uint8_t port = 0) INLINE
	:_mask{mask}
	{
		set_DDR(ddr);
		set_PORT(port);
	}

	void set_PORT(uint8_t port) INLINE
	{
		MASK_VALUE(TRAIT::PORT, port);
	}
	uint8_t get_PORT() INLINE
	{
		return TRAIT::PORT.get() & _mask;
	}
	void set_DDR(uint8_t ddr) INLINE
	{
		MASK_VALUE(TRAIT::DDR, ddr);
	}
	uint8_t get_DDR() INLINE
	{
		return TRAIT::DDR.get() & _mask;
	}
	void set_PIN(uint8_t pin) INLINE
	{
		TRAIT::PIN.set(pin & _mask);
	}
	uint8_t get_PIN() INLINE
	{
		return TRAIT::PIN.get() & _mask;
	}

private:
	void MASK_VALUE(volatile uint8_t& reg, uint8_t value) INLINE
	{
		reg = (reg & ~_mask) | (value & _mask);
	}

	uint8_t _mask;
};

template<Board::DigitalPin DPIN>
struct FastPinType
{
	static const Board::Port PORT = Board::DigitalPin_trait<DPIN>::PORT;
	static const uint8_t BIT = Board::DigitalPin_trait<DPIN>::BIT;
	static const uint8_t MASK = _BV(BIT);
	using TYPE = FastPin<PORT, BIT>;
	using PORT_TYPE = FastPort<PORT>;
};

template<>
class FastPin<Board::Port::NONE, 0>
{
public:
	FastPin(PinMode mode UNUSED, bool value UNUSED = false) INLINE {}
	void set() INLINE {}
	void clear() INLINE {}
	void toggle() INLINE {}
	bool value() INLINE
	{
		return false;
	}
};

#endif	/* FASTIO_HH */
<|endoftext|>


<commit_before>// Copyright 2011 Software Freedom Conservancy
// Licensed 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.

#include "HtmlDialog.h"
#include "logging.h"

namespace webdriver {

HtmlDialog::HtmlDialog(IHTMLWindow2* window, HWND hwnd, HWND session_handle) : DocumentHost(hwnd, session_handle) {
  this->is_navigating_ = false;
  this->window_ = window;
  this->AttachEvents();
}

HtmlDialog::~HtmlDialog(void) {
}

void HtmlDialog::AttachEvents() {
  CComPtr<IUnknown> unknown;
  this->window_->QueryInterface<IUnknown>(&unknown);
  HRESULT hr = this->DispEventAdvise(unknown);
}

void HtmlDialog::DetachEvents() {
  CComPtr<IUnknown> unknown;
  this->window_->QueryInterface<IUnknown>(&unknown);
  HRESULT hr = this->DispEventUnadvise(unknown);
}

void __stdcall HtmlDialog::OnBeforeUnload(IHTMLEventObj *pEvtObj) {
  this->is_navigating_ = true;
}

void __stdcall HtmlDialog::OnLoad(IHTMLEventObj *pEvtObj) {
  this->is_navigating_ = false;
}

void HtmlDialog::GetDocument(IHTMLDocument2** doc) {
  HRESULT hr = S_OK;
  if (this->focused_frame_window() == NULL) {
    hr = this->window_->get_document(doc);
  } else {
    hr = this->focused_frame_window()->get_document(doc);
  }

  if (FAILED(hr)) {
    LOGHR(DEBUG, hr) << "Unable to get document";
  }
}

void HtmlDialog::Close() {
  if (!this->is_closing()) {
    this->is_navigating_ = false;
    // Closing the browser, so having focus on a frame doesn't
    // make any sense.
    this->SetFocusedFrameByElement(NULL);
    this->DetachEvents();
    this->window_->close();

    // Must manually release the CComPtr<IHTMLWindow> so that the
    // destructor will not try to release a no-longer-valid object.
    this->window_.Release();
    this->window_ = NULL;

    this->PostQuitMessage();
  }
}

bool HtmlDialog::IsBusy() {
  return false;
}

bool HtmlDialog::Wait() {
  // If the window handle is no longer valid, the window is closing,
  // the wait is completed, and we must post the quit message.
  if (!this->is_closing() && !::IsWindow(this->GetTopLevelWindowHandle())) {
    this->is_navigating_ = false;
    this->DetachEvents();
    this->PostQuitMessage();
    return true;
  }

  // If we're not navigating to a new location, we should check to see if
  // a new modal dialog or alert has been opened. If one has, the wait is complete,
  // so we must set the flag indicating to the message loop not to call wait
  // anymore.
  if (!this->is_navigating_) {
    HWND child_dialog_handle = this->GetActiveDialogWindowHandle();
    if (child_dialog_handle != NULL) {
      // Check to see if the dialog opened is another HTML dialog. If so,
      // notify the IECommandExecutor that a new window exists.
      std::vector<char> window_class_name(34);
      if (::GetClassNameA(child_dialog_handle, &window_class_name[0], 34)) {
        if (strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) == 0) {
          HWND content_window_handle = this->FindContentWindowHandle(child_dialog_handle);
          if (content_window_handle != NULL) {
            // Must have a sleep here to give IE a chance to draw the window.
            ::Sleep(250);
            ::PostMessage(this->executor_handle(),
                          WD_NEW_HTML_DIALOG,
                          NULL,
                          reinterpret_cast<LPARAM>(content_window_handle));
          }
        }
      }
      this->set_wait_required(false);
      return true;
    }
  }

  // Otherwise, we wait until navigation is complete.
  ::Sleep(250);
  return !this->is_navigating_;
}

HWND HtmlDialog::GetWindowHandle() {
  return this->window_handle();
}

std::string HtmlDialog::GetWindowName() {
  return "";
}

std::string HtmlDialog::GetBrowserUrl() {
  return "";
}

std::string HtmlDialog::GetTitle() {
  CComPtr<IHTMLDocument2> doc;
  this->GetDocument(&doc);
  CComBSTR title;
  HRESULT hr = doc->get_title(&title);
  if (FAILED(hr)) {
    LOGHR(WARN, hr) << "Unable to get document title";
    return "";
  }

  std::wstring converted_title = title;
  std::string title_string = StringUtilities::ToString(converted_title);
  return title_string;
}

HWND HtmlDialog::GetTopLevelWindowHandle(void) {
  return ::GetParent(this->window_handle());
}

HWND HtmlDialog::GetActiveDialogWindowHandle() {
  DialogWindowInfo info;
  info.hwndOwner = this->GetTopLevelWindowHandle();
  info.hwndDialog = NULL;
  if (info.hwndOwner != NULL) {
    ::EnumWindows(&HtmlDialog::FindChildDialogWindow, reinterpret_cast<LPARAM>(&info));
  }
  return info.hwndDialog;
}

long HtmlDialog::GetWidth() {
  // TODO: calculate width
  return 0L;
}

long HtmlDialog::GetHeight() {
  // TODO: calculate height
  return 0L;
}

void HtmlDialog::SetWidth(long width) {
}

void HtmlDialog::SetHeight(long height) {
}

int HtmlDialog::NavigateToUrl(const std::string& url) {
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::NavigateBack() {
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::NavigateForward() {
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::Refresh() {
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

BOOL CALLBACK HtmlDialog::FindChildDialogWindow(HWND hwnd, LPARAM arg) {
  DialogWindowInfo* window_info = reinterpret_cast<DialogWindowInfo*>(arg);
  if (::GetWindow(hwnd, GW_OWNER) != window_info->hwndOwner) {
    return TRUE;
  }
  std::vector<char> window_class_name(34);
  if (::GetClassNameA(hwnd, &window_class_name[0], 34) == 0) {
    // No match found. Skip
    return TRUE;
  }
  if (strcmp(ALERT_WINDOW_CLASS, &window_class_name[0]) != 0 &&
      strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) != 0) {
    return TRUE;
  } else {
    // If the window style has the WS_DISABLED bit set or the
    // WS_VISIBLE bit unset, it can't  be handled via the UI,
    // and must not be a visible dialog.
    if ((::GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED) != 0 ||
        (::GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) == 0) {
      return TRUE;
    }
  }
  window_info->hwndDialog = hwnd;
  return FALSE;
}

} // namespace webdriver
<commit_msg>Implementing logging for IE driver HtmlDialog class<commit_after>// Copyright 2011 Software Freedom Conservancy
// Licensed 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.

#include "HtmlDialog.h"
#include "logging.h"

namespace webdriver {

HtmlDialog::HtmlDialog(IHTMLWindow2* window, HWND hwnd, HWND session_handle) : DocumentHost(hwnd, session_handle) {
  LOG(TRACE) << "Entering HtmlDialog::HtmlDialog";
  this->is_navigating_ = false;
  this->window_ = window;
  this->AttachEvents();
}

HtmlDialog::~HtmlDialog(void) {
}

void HtmlDialog::AttachEvents() {
  CComPtr<IUnknown> unknown;
  this->window_->QueryInterface<IUnknown>(&unknown);
  HRESULT hr = this->DispEventAdvise(unknown);
}

void HtmlDialog::DetachEvents() {
  LOG(TRACE) << "Entering HtmlDialog::DetachEvents";
  CComPtr<IUnknown> unknown;
  this->window_->QueryInterface<IUnknown>(&unknown);
  HRESULT hr = this->DispEventUnadvise(unknown);
}

void __stdcall HtmlDialog::OnBeforeUnload(IHTMLEventObj *pEvtObj) {
  LOG(TRACE) << "Entering HtmlDialog::OnBeforeUnload";
  this->is_navigating_ = true;
}

void __stdcall HtmlDialog::OnLoad(IHTMLEventObj *pEvtObj) {
  LOG(TRACE) << "Entering HtmlDialog::OnLoad";
  this->is_navigating_ = false;
}

void HtmlDialog::GetDocument(IHTMLDocument2** doc) {
  LOG(TRACE) << "Entering HtmlDialog::GetDocument";
  HRESULT hr = S_OK;
  if (this->focused_frame_window() == NULL) {
    hr = this->window_->get_document(doc);
  } else {
    hr = this->focused_frame_window()->get_document(doc);
  }

  if (FAILED(hr)) {
    LOGHR(DEBUG, hr) << "Unable to get document";
  }
}

void HtmlDialog::Close() {
  LOG(TRACE) << "Entering HtmlDialog::Close";
  if (!this->is_closing()) {
    this->is_navigating_ = false;
    // Closing the browser, so having focus on a frame doesn't
    // make any sense.
    this->SetFocusedFrameByElement(NULL);
    this->DetachEvents();
    this->window_->close();

    // Must manually release the CComPtr<IHTMLWindow> so that the
    // destructor will not try to release a no-longer-valid object.
    this->window_.Release();
    this->window_ = NULL;

    this->PostQuitMessage();
  }
}

bool HtmlDialog::IsBusy() {
  LOG(TRACE) << "Entering HtmlDialog::IsBusy";
  return false;
}

bool HtmlDialog::Wait() {
  LOG(TRACE) << "Entering HtmlDialog::Wait";
  // If the window handle is no longer valid, the window is closing,
  // the wait is completed, and we must post the quit message.
  if (!this->is_closing() && !::IsWindow(this->GetTopLevelWindowHandle())) {
    this->is_navigating_ = false;
    this->DetachEvents();
    this->PostQuitMessage();
    return true;
  }

  // If we're not navigating to a new location, we should check to see if
  // a new modal dialog or alert has been opened. If one has, the wait is complete,
  // so we must set the flag indicating to the message loop not to call wait
  // anymore.
  if (!this->is_navigating_) {
    HWND child_dialog_handle = this->GetActiveDialogWindowHandle();
    if (child_dialog_handle != NULL) {
      // Check to see if the dialog opened is another HTML dialog. If so,
      // notify the IECommandExecutor that a new window exists.
      std::vector<char> window_class_name(34);
      if (::GetClassNameA(child_dialog_handle, &window_class_name[0], 34)) {
        if (strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) == 0) {
          HWND content_window_handle = this->FindContentWindowHandle(child_dialog_handle);
          if (content_window_handle != NULL) {
            // Must have a sleep here to give IE a chance to draw the window.
            ::Sleep(250);
            ::PostMessage(this->executor_handle(),
                          WD_NEW_HTML_DIALOG,
                          NULL,
                          reinterpret_cast<LPARAM>(content_window_handle));
          }
        }
      }
      this->set_wait_required(false);
      return true;
    }
  }

  // Otherwise, we wait until navigation is complete.
  ::Sleep(250);
  return !this->is_navigating_;
}

HWND HtmlDialog::GetWindowHandle() {
  LOG(TRACE) << "Entering HtmlDialog::GetWindowHandle";
  return this->window_handle();
}

std::string HtmlDialog::GetWindowName() {
  LOG(TRACE) << "Entering HtmlDialog::GetWindowName";
  return "";
}

std::string HtmlDialog::GetBrowserUrl() {
  LOG(TRACE) << "Entering HtmlDialog::GetBrowserUrl";
  return "";
}

std::string HtmlDialog::GetTitle() {
  LOG(TRACE) << "Entering HtmlDialog::GetTitle";
  CComPtr<IHTMLDocument2> doc;
  this->GetDocument(&doc);
  CComBSTR title;
  HRESULT hr = doc->get_title(&title);
  if (FAILED(hr)) {
    LOGHR(WARN, hr) << "Unable to get document title";
    return "";
  }

  std::wstring converted_title = title;
  std::string title_string = StringUtilities::ToString(converted_title);
  return title_string;
}

HWND HtmlDialog::GetTopLevelWindowHandle(void) {
  LOG(TRACE) << "Entering HtmlDialog::GetTopLevelWindowHandle";
  return ::GetParent(this->window_handle());
}

HWND HtmlDialog::GetActiveDialogWindowHandle() {
  LOG(TRACE) << "Entering HtmlDialog::GetActiveDialogWindowHandle";
  DialogWindowInfo info;
  info.hwndOwner = this->GetTopLevelWindowHandle();
  info.hwndDialog = NULL;
  if (info.hwndOwner != NULL) {
    ::EnumWindows(&HtmlDialog::FindChildDialogWindow, reinterpret_cast<LPARAM>(&info));
  }
  return info.hwndDialog;
}

long HtmlDialog::GetWidth() {
  LOG(TRACE) << "Entering HtmlDialog::GetWidth";
  // TODO: calculate width
  return 0L;
}

long HtmlDialog::GetHeight() {
  LOG(TRACE) << "Entering HtmlDialog::GetHeight";
  // TODO: calculate height
  return 0L;
}

void HtmlDialog::SetWidth(long width) {
  LOG(TRACE) << "Entering HtmlDialog::SetWidth";
}

void HtmlDialog::SetHeight(long height) {
  LOG(TRACE) << "Entering HtmlDialog::SetHeight";
}

int HtmlDialog::NavigateToUrl(const std::string& url) {
  LOG(TRACE) << "Entering HtmlDialog::NavigateToUrl";
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::NavigateBack() {
  LOG(TRACE) << "Entering HtmlDialog::NavigateBack";
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::NavigateForward() {
  LOG(TRACE) << "Entering HtmlDialog::NavigateForward";
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

int HtmlDialog::Refresh() {
  LOG(TRACE) << "Entering HtmlDialog::Refresh";
  // Cannot force navigation on windows opened with showModalDialog();
  return ENOTIMPLEMENTED;
}

BOOL CALLBACK HtmlDialog::FindChildDialogWindow(HWND hwnd, LPARAM arg) {
  DialogWindowInfo* window_info = reinterpret_cast<DialogWindowInfo*>(arg);
  if (::GetWindow(hwnd, GW_OWNER) != window_info->hwndOwner) {
    return TRUE;
  }
  std::vector<char> window_class_name(34);
  if (::GetClassNameA(hwnd, &window_class_name[0], 34) == 0) {
    // No match found. Skip
    return TRUE;
  }
  if (strcmp(ALERT_WINDOW_CLASS, &window_class_name[0]) != 0 &&
      strcmp(HTML_DIALOG_WINDOW_CLASS, &window_class_name[0]) != 0) {
    return TRUE;
  } else {
    // If the window style has the WS_DISABLED bit set or the
    // WS_VISIBLE bit unset, it can't  be handled via the UI,
    // and must not be a visible dialog.
    if ((::GetWindowLong(hwnd, GWL_STYLE) & WS_DISABLED) != 0 ||
        (::GetWindowLong(hwnd, GWL_STYLE) & WS_VISIBLE) == 0) {
      return TRUE;
    }
  }
  window_info->hwndDialog = hwnd;
  return FALSE;
}

} // namespace webdriver
<|endoftext|>


<commit_before>#include <algorithm>
#include <array>
#include <cstdio>
#include <cwchar>
#include <unordered_map>
#include <vector>

#include "core/armor_set.h"
#include "dataset.h"

namespace monster_avengers {

namespace dataset {

void Data::PrintSkill(int id, int verbose, Language language) {
  const SkillSystem &skill = skills_[id];
  const SkillSystemAddon &addon = skill_addons_[id];
  wprintf(L"[SKILL %03d] %ls", id, addon.name[language].c_str());
  if (verbose >= 1) {
    wprintf(L":");
    for (int i = 0; i < skill.skills.size(); ++i) {
      wprintf(L"  [%d %ls]", skill.skills[i].points,
              addon.skill_names[i][language].c_str());
    }
  }
  wprintf(L"\n");
}

void Data::PrintJewel(int id, int verbose, Language language) {
  const Jewel &jewel = jewels_[id];
  const JewelAddon &addon = jewel_addons_[id];
  wprintf(L"[JEWEL %03d] %ls", id, addon.name[language].c_str());
  if (verbose >= 1) {
    wprintf(L":");
    for (const Effect &effect : jewel.effects) {
      wprintf(L"   [%03d]%ls %d", effect.id,
              skill_addons_[effect.id].name[language].c_str(),
              effect.points);
    }
  }
  wprintf(L"\n");
}

void Data::PrintArmor(const Armor &armor, int id,
                      int verbose, Language language) {
  char slots[4] = "---";
  for (int i = 0; i < armor.slots; ++i) slots[i] = 'O';
  if (id >= armors_.size()) {
    wprintf(L"[ARMOR %04d] [%s] RARE-%02d  Custom %s\n",
            id, slots, armor.rare,
            StringifyEnum(armor.part).c_str());
  } else {
    const ArmorAddon &addon = armor_addons_[id];
    wprintf(L"[ARMOR %04d] [%s] RARE-%02d  %ls\n",
            id, slots, armor.rare,
            addon.name[language].c_str());
  }
  if (verbose >= 1) {
    wprintf(L"             [Part: %s]\n", StringifyEnum(armor.part).c_str());
    wprintf(L"             [Type: %s]\n",
            StringifyEnum(armor.weapon_type).c_str());
    wprintf(L"             [Gender: %s]\n",
            StringifyEnum(armor.gender).c_str());
    wprintf(L"             [Def(Min): %d]\n", armor.min_defense);
    wprintf(L"             [Def(Max): %d]\n", armor.max_defense);
    wprintf(L"             [Resist: F(%d) | T(%d) | D(%d) | W(%d) | I(%d)]\n",
            armor.resistance.fire,
            armor.resistance.thunder,
            armor.resistance.dragon,
            armor.resistance.water,
            armor.resistance.ice);
    for (const Effect &effect : armor.effects) {
      wprintf(L"             [%03d]%ls %d\n",
              effect.id,
              skill_addons_[effect.id].name[language].c_str(),
              effect.points);
    }
  }
}

void Data::PrintArmor(int id, int verbose, Language language) {
  const Armor &armor = armors_[id];
  PrintArmor(armor, id, verbose, language);
}

int Data::GetMultiplier(const ArmorSet &armor_set, const Arsenal &arsenal) {
  int multiplier = 1;
  for (int i = 0; i < PART_NUM; ++i) {
    if (arsenal.IsTorsoUp(armor_set.ids[i])) {
      multiplier++;
    }
  }
  return multiplier;
}

std::vector<Effect> Data::GetSkillStats(
    const ArmorSet &armor_set, const Arsenal &arsenal) {
  std::unordered_map<int, int> stats_map;

  int multiplier = GetMultiplier(armor_set, arsenal);

  for (int i = 0; i < PART_NUM; ++i) {
    int armor_id = armor_set.ids[i];
    for (const Effect &effect : arsenal[armor_id].effects) {
      auto iter = stats_map.find(effect.id);
      int points = (BODY == i) ? effect.points * multiplier
          : effect.points;
      if (stats_map.end() != iter) {
        iter->second += points;
      } else {
        stats_map[effect.id] = points;
      }
    }

    // Jewels
    for (int jewel_id : armor_set.jewels[i]) {
      for (const Effect &effect : jewels_[jewel_id].effects) {
        auto iter = stats_map.find(effect.id);
        int points = (BODY == i) ? effect.points * multiplier
            : effect.points;
        if (stats_map.end() != iter) {
          iter->second += points;
        } else {
          stats_map[effect.id] = points;
        }
      }
    }
  }

  std::vector<Effect> stats;
  for (const auto& pair : stats_map) {
    stats.emplace_back();
    stats.back().id = pair.first;
    stats.back().points = pair.second;
  }

  return stats;
}

void Data::PrintArmorSet(const ArmorSet &armor_set,
                         const Arsenal &arsenal,
                         int verbose,
                         Language language) {
  static std::array<ArmorPart, PART_NUM> ordered_part {
    {GEAR, HEAD, BODY, HANDS, WAIST, FEET, AMULET}};

  wprintf(L"__________ Armor Set __________\n");
  for (ArmorPart part : ordered_part) {
    const Armor &armor = arsenal[armor_set.ids[part]];

    // Print ID
    wprintf(L"[%04d] ", armor_set.ids[part]);

    // Print Slots
    wchar_t slots_text[4] = L"\u2013\u2013\u2013";
    int occupied = std::accumulate(
        armor_set.jewels[part].begin(),
        armor_set.jewels[part].end(),
        0, [](int sum, int id) {
          return sum + Data::jewel(id).slots;
        });
    for (int i = 0; i < 3; ++i) {
      if (i < occupied) {
        slots_text[i] = L'\u25CF';
      } else if (i < armor.slots) {
        slots_text[i] = L'\u25CB';
      }
    }
    wprintf(L"%ls ", slots_text);

    // Print Name
    if (armor_set.ids[part] < armors_.size()) {
      wprintf(L"%ls\n",
              armor_addons_[armor_set.ids[part]].name[language].c_str());
    } else {
      wprintf(L"%s\n", StringifyEnum(part).c_str());
    }

    if (verbose > 0 ) {
      wprintf(L"%16s", "\u2559\u2500\u2500 ");
      // Print Rarity
      wprintf(L"Rare-%02d ", armor.rare);
      for (int jewel_id : armor_set.jewels[part]) {
        wprintf(L"   %ls", jewel_addons_[jewel_id].name[language].c_str());
      }
      wprintf(L"\n");
    }
  }
  std::vector<Effect> stats = std::move(GetSkillStats(armor_set, arsenal));
  std::sort(stats.begin(), stats.end(),
            [](const Effect &a, const Effect &b) {
              return a.points > b.points;
            });
  for (const Effect &effect : stats) {
    wprintf(L"%ls(%+d)  ", skill_addons_[effect.id].name[language].c_str(),
            effect.points);
  }
  wprintf(L"\n");
  wprintf(L"\n");
}

}  // namespace dataset

}  // namespace monster_avengers
<commit_msg>pretty print result<commit_after>#include <algorithm>
#include <array>
#include <cstdio>
#include <cwchar>
#include <unordered_map>
#include <vector>

#include "core/armor_set.h"
#include "dataset.h"

namespace monster_avengers {

namespace dataset {

void Data::PrintSkill(int id, int verbose, Language language) {
  const SkillSystem &skill = skills_[id];
  const SkillSystemAddon &addon = skill_addons_[id];
  wprintf(L"[SKILL %03d] %ls", id, addon.name[language].c_str());
  if (verbose >= 1) {
    wprintf(L":");
    for (int i = 0; i < skill.skills.size(); ++i) {
      wprintf(L"  [%d %ls]", skill.skills[i].points,
              addon.skill_names[i][language].c_str());
    }
  }
  wprintf(L"\n");
}

void Data::PrintJewel(int id, int verbose, Language language) {
  const Jewel &jewel = jewels_[id];
  const JewelAddon &addon = jewel_addons_[id];
  wprintf(L"[JEWEL %03d] %ls", id, addon.name[language].c_str());
  if (verbose >= 1) {
    wprintf(L":");
    for (const Effect &effect : jewel.effects) {
      wprintf(L"   [%03d]%ls %d", effect.id,
              skill_addons_[effect.id].name[language].c_str(),
              effect.points);
    }
  }
  wprintf(L"\n");
}

void Data::PrintArmor(const Armor &armor, int id,
                      int verbose, Language language) {
  char slots[4] = "---";
  for (int i = 0; i < armor.slots; ++i) slots[i] = 'O';
  if (id >= armors_.size()) {
    wprintf(L"[ARMOR %04d] [%s] RARE-%02d  Custom %s\n",
            id, slots, armor.rare,
            StringifyEnum(armor.part).c_str());
  } else {
    const ArmorAddon &addon = armor_addons_[id];
    wprintf(L"[ARMOR %04d] [%s] RARE-%02d  %ls\n",
            id, slots, armor.rare,
            addon.name[language].c_str());
  }
  if (verbose >= 1) {
    wprintf(L"             [Part: %s]\n", StringifyEnum(armor.part).c_str());
    wprintf(L"             [Type: %s]\n",
            StringifyEnum(armor.weapon_type).c_str());
    wprintf(L"             [Gender: %s]\n",
            StringifyEnum(armor.gender).c_str());
    wprintf(L"             [Def(Min): %d]\n", armor.min_defense);
    wprintf(L"             [Def(Max): %d]\n", armor.max_defense);
    wprintf(L"             [Resist: F(%d) | T(%d) | D(%d) | W(%d) | I(%d)]\n",
            armor.resistance.fire,
            armor.resistance.thunder,
            armor.resistance.dragon,
            armor.resistance.water,
            armor.resistance.ice);
    for (const Effect &effect : armor.effects) {
      wprintf(L"             [%03d]%ls %d\n",
              effect.id,
              skill_addons_[effect.id].name[language].c_str(),
              effect.points);
    }
  }
}

void Data::PrintArmor(int id, int verbose, Language language) {
  const Armor &armor = armors_[id];
  PrintArmor(armor, id, verbose, language);
}

int Data::GetMultiplier(const ArmorSet &armor_set, const Arsenal &arsenal) {
  int multiplier = 1;
  for (int i = 0; i < PART_NUM; ++i) {
    if (arsenal.IsTorsoUp(armor_set.ids[i])) {
      multiplier++;
    }
  }
  return multiplier;
}

std::vector<Effect> Data::GetSkillStats(
    const ArmorSet &armor_set, const Arsenal &arsenal) {
  std::unordered_map<int, int> stats_map;

  int multiplier = GetMultiplier(armor_set, arsenal);

  for (int i = 0; i < PART_NUM; ++i) {
    int armor_id = armor_set.ids[i];
    for (const Effect &effect : arsenal[armor_id].effects) {
      auto iter = stats_map.find(effect.id);
      int points = (BODY == i) ? effect.points * multiplier
          : effect.points;
      if (stats_map.end() != iter) {
        iter->second += points;
      } else {
        stats_map[effect.id] = points;
      }
    }

    // Jewels
    for (int jewel_id : armor_set.jewels[i]) {
      for (const Effect &effect : jewels_[jewel_id].effects) {
        auto iter = stats_map.find(effect.id);
        int points = (BODY == i) ? effect.points * multiplier
            : effect.points;
        if (stats_map.end() != iter) {
          iter->second += points;
        } else {
          stats_map[effect.id] = points;
        }
      }
    }
  }

  std::vector<Effect> stats;
  for (const auto& pair : stats_map) {
    stats.emplace_back();
    stats.back().id = pair.first;
    stats.back().points = pair.second;
  }

  return stats;
}

void Data::PrintArmorSet(const ArmorSet &armor_set,
                         const Arsenal &arsenal,
                         int verbose,
                         Language language) {
  static std::array<ArmorPart, PART_NUM> ordered_part {
    {GEAR, HEAD, BODY, HANDS, WAIST, FEET, AMULET}};

  wprintf(L"__________ Armor Set __________\n");
  for (ArmorPart part : ordered_part) {
    const Armor &armor = arsenal[armor_set.ids[part]];

    // Print ID
    wprintf(L"[%04d] ", armor_set.ids[part]);

    // Print Slots
    wchar_t slots_text[4] = L"\u2013\u2013\u2013";
    int occupied = std::accumulate(
        armor_set.jewels[part].begin(),
        armor_set.jewels[part].end(),
        0, [](int sum, int id) {
          return sum + Data::jewel(id).slots;
        });
    for (int i = 0; i < 3; ++i) {
      if (i < occupied) {
        slots_text[i] = L'\u25CF';
      } else if (i < armor.slots) {
        slots_text[i] = L'\u25CB';
      }
    }
    wprintf(L"%ls ", slots_text);

    // Print Name
    if (armor_set.ids[part] < armors_.size()) {
      wprintf(L"\u2500\u2565\u2500\u2500 \u23e3 %ls\n",
              armor_addons_[armor_set.ids[part]].name[language].c_str());
    } else {
      wprintf(L"\u2500\u2565\u2500\u2500 \u23e3 %s\n",
              StringifyEnum(part).c_str());
    }

    // Print TorsoUps
    if (arsenal.IsTorsoUp(armor_set.ids[part])) {
      wprintf(L"%15s (Torso-Up)\n", "\u255f\u2500\u2500");
    }

    // Print Jewels
    if (verbose > 0 ) {
      wprintf(L"%16s", "\u2559\u2500\u2500 ");
      // Print Rarity
      wprintf(L"Rare-%02d ", armor.rare);
      for (int jewel_id : armor_set.jewels[part]) {
        wprintf(L"   %ls", jewel_addons_[jewel_id].name[language].c_str());
      }
      wprintf(L"\n");
    }
  }

  // Print Skill Stats
  std::vector<Effect> stats = std::move(GetSkillStats(armor_set, arsenal));
  std::sort(stats.begin(), stats.end(),
            [](const Effect &a, const Effect &b) {
              return a.points > b.points;
            });
  for (const Effect &effect : stats) {
    wprintf(L"%ls(%+d)  ", skill_addons_[effect.id].name[language].c_str(),
            effect.points);
  }
  wprintf(L"\n");
  wprintf(L"\n");
}

}  // namespace dataset

}  // namespace monster_avengers
<|endoftext|>


<commit_before>#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include "mongodb_store/SetParam.h"

ros::ServiceClient client;

bool is_inlier(const Eigen::Vector3f& point, const Eigen::Vector4f plane, double threshold)
{
    return fabs(point.dot(plane.segment<3>(0)) + plane(3)) < threshold;
}

void plot_best_plane(const pcl::PointCloud<pcl::PointXYZ>& points, const Eigen::Vector4f plane, double threshold)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr inlier_cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PointCloud<pcl::PointXYZ>::Ptr outlier_cloud(new pcl::PointCloud<pcl::PointXYZ>());

    for (int i = 0; i < points.size(); ++i) {
        if (is_inlier(points[i].getVector3fMap(), plane, threshold)) {
            inlier_cloud->push_back(points[i]);
        }
        else {
            outlier_cloud->push_back(points[i]);
        }
    }

    pcl::visualization::PCLVisualizer viewer("3D Viewer");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addCoordinateSystem(1.0, "reference", 0);
    viewer.initCameraParameters();

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> inlier_color_handler(inlier_cloud, 255, 0, 0);
    viewer.addPointCloud(inlier_cloud, inlier_color_handler, "inliers");

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> outlier_color_handler(outlier_cloud, 0, 0, 255);
    viewer.addPointCloud(outlier_cloud, outlier_color_handler, "outliers");

    while (!viewer.wasStopped())
    {
        viewer.spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

}

void compute_plane(Eigen::Vector4f& plane, const pcl::PointCloud<pcl::PointXYZ>& points, int* inds)
{
    Eigen::Vector3f first = points[inds[1]].getVector3fMap() - points[inds[0]].getVector3fMap();
    Eigen::Vector3f second = points[inds[2]].getVector3fMap() - points[inds[0]].getVector3fMap();
    Eigen::Vector3f normal = first.cross(second);
    normal.normalize();
    plane.segment<3>(0) = normal;
    plane(3) = -normal.dot(points[inds[0]].getVector3fMap());
}

void extract_height_and_angle(const Eigen::Vector4f& plane)
{
    ROS_INFO("Ground plane: %f, %f, %f, %f", plane(0), plane(1), plane(2), plane(3));
    double dist = fabs(plane(3)/plane(2)); // distance along z axis
    double height = fabs(plane(3)/plane.segment<3>(0).squaredNorm()); // height
    ROS_INFO("Distance to plane along camera axis: %f", dist);
    ROS_INFO("Height above ground: %f", height);
    double angle = asin(height/dist);
    ROS_INFO("Angle radians: %f", angle);
    ROS_INFO("Angle degrees: %f", 180.0f*angle/M_PI);

    mongodb_store::SetParam srv;
    char buffer[250];

    // store height above ground in datacentre
    ros::param::set("/chest_xtion_height", height);
    sprintf(buffer, "{\"path\":\"/chest_xtion_height\",\"value\":%f}", height);
    srv.request.param = buffer;
    if (!client.call(srv)) {
        ROS_ERROR("Failed to call set height, is config manager running?");
    }

    // store angle between camera and horizontal plane
    ros::param::set("/chest_xtion_angle", angle);
    sprintf(buffer, "{\"path\":\"/chest_xtion_angle\",\"value\":%f}", angle);
    srv.request.param = buffer;
    if (!client.call(srv)) {
        ROS_ERROR("Failed to call set angle, is config manager running?");
    }
}

void callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
{
    ROS_INFO("Got a pointcloud, calibrating...");
    pcl::PointCloud<pcl::PointXYZ> cloud;
    pcl::fromROSMsg(*msg, cloud);

    int nbr = cloud.size();

    int max = 1000; // ransac iterations
    double threshold = 0.02; // threshold for plane inliers

    Eigen::Vector4f best_plane; // best plane parameters found
    int best_inliers = -1; // best number of inliers

    int inds[3];

    Eigen::Vector4f plane;
    int inliers;
    for (int i = 0; i < max; ++i) {

        for (int j = 0; j < 3; ++j) {
            inds[j] = rand() % nbr; // get a random point
        }

        // check that the points aren't the same
        if (inds[0] == inds[1] || inds[0] == inds[2] || inds[1] == inds[2]) {
            continue;
        }

        compute_plane(plane, cloud, inds);
        inliers = 0;
        for (int j = 0; j < nbr; j += 30) { // count number of inliers
            if (is_inlier(cloud[j].getVector3fMap(), plane, threshold)) {
                ++inliers;
            }
        }

        if (inliers > best_inliers) {
            best_plane = plane;
            best_inliers = inliers;
        }
    }

    extract_height_and_angle(best_plane); // find parameters and feed them to datacentre
    plot_best_plane(cloud, best_plane, threshold); // visually evaluate plane fit

    exit(0);
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "calibrate_chest");
	ros::NodeHandle n;

    std::string camera_topic = "chest_xtion";
    client = n.serviceClient<mongodb_store::SetParam>("/config_manager/set_param");
	ros::Subscriber sub = n.subscribe(camera_topic + "/depth/points", 1, callback);

    ros::spin();

	return 0;
}
<commit_msg>Removed my error.<commit_after>#include <ros/ros.h>
#include <sensor_msgs/PointCloud2.h>
#include <pcl_ros/point_cloud.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include "mongodb_store/SetParam.h"

ros::ServiceClient client;

bool is_inlier(const Eigen::Vector3f& point, const Eigen::Vector4f plane, double threshold)
{
    return fabs(point.dot(plane.segment<3>(0)) + plane(3)) < threshold;
}

void plot_best_plane(const pcl::PointCloud<pcl::PointXYZ>& points, const Eigen::Vector4f plane, double threshold)
{
    pcl::PointCloud<pcl::PointXYZ>::Ptr inlier_cloud(new pcl::PointCloud<pcl::PointXYZ>());
    pcl::PointCloud<pcl::PointXYZ>::Ptr outlier_cloud(new pcl::PointCloud<pcl::PointXYZ>());

    for (int i = 0; i < points.size(); ++i) {
        if (is_inlier(points[i].getVector3fMap(), plane, threshold)) {
            inlier_cloud->push_back(points[i]);
        }
        else {
            outlier_cloud->push_back(points[i]);
        }
    }

    pcl::visualization::PCLVisualizer viewer("3D Viewer");
    viewer.setBackgroundColor(0, 0, 0);
    viewer.addCoordinateSystem(1.0);
    viewer.initCameraParameters();

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> inlier_color_handler(inlier_cloud, 255, 0, 0);
    viewer.addPointCloud(inlier_cloud, inlier_color_handler, "inliers");

    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> outlier_color_handler(outlier_cloud, 0, 0, 255);
    viewer.addPointCloud(outlier_cloud, outlier_color_handler, "outliers");

    while (!viewer.wasStopped())
    {
        viewer.spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

}

void compute_plane(Eigen::Vector4f& plane, const pcl::PointCloud<pcl::PointXYZ>& points, int* inds)
{
    Eigen::Vector3f first = points[inds[1]].getVector3fMap() - points[inds[0]].getVector3fMap();
    Eigen::Vector3f second = points[inds[2]].getVector3fMap() - points[inds[0]].getVector3fMap();
    Eigen::Vector3f normal = first.cross(second);
    normal.normalize();
    plane.segment<3>(0) = normal;
    plane(3) = -normal.dot(points[inds[0]].getVector3fMap());
}

void extract_height_and_angle(const Eigen::Vector4f& plane)
{
    ROS_INFO("Ground plane: %f, %f, %f, %f", plane(0), plane(1), plane(2), plane(3));
    double dist = fabs(plane(3)/plane(2)); // distance along z axis
    double height = fabs(plane(3)/plane.segment<3>(0).squaredNorm()); // height
    ROS_INFO("Distance to plane along camera axis: %f", dist);
    ROS_INFO("Height above ground: %f", height);
    double angle = asin(height/dist);
    ROS_INFO("Angle radians: %f", angle);
    ROS_INFO("Angle degrees: %f", 180.0f*angle/M_PI);

    mongodb_store::SetParam srv;
    char buffer[250];

    // store height above ground in datacentre
    ros::param::set("/chest_xtion_height", height);
    sprintf(buffer, "{\"path\":\"/chest_xtion_height\",\"value\":%f}", height);
    srv.request.param = buffer;
    if (!client.call(srv)) {
        ROS_ERROR("Failed to call set height, is config manager running?");
    }

    // store angle between camera and horizontal plane
    ros::param::set("/chest_xtion_angle", angle);
    sprintf(buffer, "{\"path\":\"/chest_xtion_angle\",\"value\":%f}", angle);
    srv.request.param = buffer;
    if (!client.call(srv)) {
        ROS_ERROR("Failed to call set angle, is config manager running?");
    }
}

void callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
{
    ROS_INFO("Got a pointcloud, calibrating...");
    pcl::PointCloud<pcl::PointXYZ> cloud;
    pcl::fromROSMsg(*msg, cloud);

    int nbr = cloud.size();

    int max = 1000; // ransac iterations
    double threshold = 0.02; // threshold for plane inliers

    Eigen::Vector4f best_plane; // best plane parameters found
    int best_inliers = -1; // best number of inliers

    int inds[3];

    Eigen::Vector4f plane;
    int inliers;
    for (int i = 0; i < max; ++i) {

        for (int j = 0; j < 3; ++j) {
            inds[j] = rand() % nbr; // get a random point
        }

        // check that the points aren't the same
        if (inds[0] == inds[1] || inds[0] == inds[2] || inds[1] == inds[2]) {
            continue;
        }

        compute_plane(plane, cloud, inds);
        inliers = 0;
        for (int j = 0; j < nbr; j += 30) { // count number of inliers
            if (is_inlier(cloud[j].getVector3fMap(), plane, threshold)) {
                ++inliers;
            }
        }

        if (inliers > best_inliers) {
            best_plane = plane;
            best_inliers = inliers;
        }
    }

    extract_height_and_angle(best_plane); // find parameters and feed them to datacentre
    plot_best_plane(cloud, best_plane, threshold); // visually evaluate plane fit

    exit(0);
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "calibrate_chest");
	ros::NodeHandle n;

    std::string camera_topic = "chest_xtion";
    client = n.serviceClient<mongodb_store::SetParam>("/config_manager/set_param");
	ros::Subscriber sub = n.subscribe(camera_topic + "/depth/points", 1, callback);

    ros::spin();

	return 0;
}
<|endoftext|>


<commit_before>#include "rb_Nef_polyhedron_3.h"

template <class HDS>
class Polyhedron_builder : public CGAL::Modifier_base<HDS> {
public:
	Array points;
	Array faces;

	Polyhedron_builder(Array points, Array faces) {
		this->points = points;
		this->faces = faces;
	}

  void operator()( HDS& hds) {
    // Postcondition: `hds' is a valid polyhedral surface.
    CGAL::Polyhedron_incremental_builder_3<HDS> B( hds, true);
    typedef typename HDS::Vertex   Vertex;
    typedef typename Vertex::Point PointHDS;
    B.begin_surface( points.size(), faces.size());
    // Add vertices
		for (unsigned int i = 0; i < points.size(); i++) {
			Array point = Array(points[i]);
			PointHDS pt = PointHDS(
				from_ruby<double>(point[0]),
				from_ruby<double>(point[1]),
				from_ruby<double>(point[2]));
			B.add_vertex(pt);
		}
		// Add faces
		for (unsigned int i = 0; i < faces.size(); i++) {
			Array indices = Array(faces[i]);
			B.begin_facet();
			for (unsigned int j = 0; j < indices.size(); j++) {
				B.add_vertex_to_facet(from_ruby<int>(indices[j]));
			}
			B.end_facet();
		}
    B.end_surface();
  }
};

/*-----------MAIN METHODS------------*/

Nef_polyhedron_3 build(Array points, Array faces){
	Polyhedron_builder<HalfedgeDS> pb(points, faces);
	Polyhedron_3 P;
	P.delegate(pb);
	Nef_polyhedron_3 N(P);
	return N;
}

Nef_polyhedron_3 build_polyline(Array points){
	typedef Point_3* 																		point_iterator;
	typedef std::pair<point_iterator,point_iterator> 		point_range;
	typedef std::list<point_range> 											polyline_list;
	Point_3 polyline[points.size()];
	for (unsigned int i = 0; i < points.size(); ++i){
		polyline[i] = from_ruby<Point_3>(points[i]);
	}
	polyline_list polylines;
	polylines.push_back(point_range(polyline,polyline+points.size()));
	Nef_polyhedron_3 N( polylines.begin(),
											polylines.end(),
											Nef_polyhedron_3::Polylines_tag());
	return N;
}

Array split(Nef_polyhedron_3 N){
	vector<Nef_polyhedron_3> nefs;
	Nef_polyhedron_3::Volume_const_iterator vi = ++N.volumes_begin();
	Nef_polyhedron_3::Shell_entry_const_iterator si;
  CGAL_forall_volumes(vi,N) {
		if(vi->mark()) {
			Nef_polyhedron_3::Shell_entry_const_iterator si;
			CGAL_forall_shells_of(si, vi) {
				Nef_polyhedron_3::SFace_const_handle sfch(si);
				Nef_polyhedron_3 O(N,sfch);
				nefs.push_back(O);
			}
		}
	}
	Array out(nefs.begin(), nefs.end());
	return out;
}

String to_off(Nef_polyhedron_3 N){
	stringstream ss;
	if (N.is_valid() && N.is_simple()) {
		Polyhedron_3 P;
		N.convert_to_polyhedron(P);
		ss << P;
	}
	return String(ss.str());
}

Array vertices(Nef_polyhedron_3 N){
	vector<Vertex> vertices;
	Nef_polyhedron_3::Vertex_const_iterator vci;
	CGAL_forall_vertices(vci,N){
		vertices.push_back(*vci);
  }
	Array out(vertices.begin(), vertices.end());
	return out;
}

Array halffacets(Nef_polyhedron_3 N){
	vector<Halffacet> halffacets;
	Nef_polyhedron_3::Halffacet_const_iterator hfci;
	CGAL_forall_halffacets(hfci,N){
		halffacets.push_back(*hfci);
  }
	Array out(halffacets.begin(), halffacets.end());
	return out;
}

Iso_cuboid_3 bounding_box(Nef_polyhedron_3 N){
	vector<Point_3> points;
	Nef_polyhedron_3::Vertex_const_iterator vci;
	CGAL_forall_vertices(vci,N){
		points.push_back(vci->point());
  }
	return CGAL::bounding_box(points.begin(),points.end());
}
/*
String to_s(Nef_polyhedron_3 N){
	stringstream ss;
	ss << N;
	return String(ss.str());
}

Nef_polyhedron_3 load(String s){
	stringstream ss;
	ss << s.c_str();
	Nef_polyhedron_3 N;
	ss >> N;
	return N;
}

bool is_bounded(Nef_polyhedron_3 N){
	return N.is_bounded();
}
*/

Data_Type<Nef_polyhedron_3> define_Nef_polyhedron_3(Rice::Module rb_mCGAL ) {

	typedef bool (Nef_polyhedron_3::*np3_is_valid)();
	Data_Type<Nef_polyhedron_3> rb_cNef_polyhedron_3 =
		define_class_under<Nef_polyhedron_3>(rb_mCGAL, "Nef_polyhedron_3")
		.define_constructor(Constructor<Nef_polyhedron_3>())
		.define_singleton_method("build", &build)
		.define_singleton_method("build_polyline", &build_polyline)
//		.define_singleton_method("load", &load)
		.define_method("simple?", &Nef_polyhedron_3::is_simple)
		.define_method("valid?", np3_is_valid(&Nef_polyhedron_3::is_valid))
		.define_method("empty?", &Nef_polyhedron_3::is_empty)
		.define_method("space?", &Nef_polyhedron_3::is_space)
//		.define_method("bounded?", &is_bounded)
		.define_method("+", &Nef_polyhedron_3::operator+)
		.define_method("-", &Nef_polyhedron_3::operator-)
		.define_method("*", &Nef_polyhedron_3::operator*)
		.define_method("vertices", &vertices)
		.define_method("halffacets", &halffacets)
		.define_method("to_off", &to_off)
		.define_method("split", &split)
		.define_method("bounding_box", &bounding_box)
//		.define_method("to_s", &to_s)
	;

	return rb_cNef_polyhedron_3;
}

<commit_msg>Add comment to try this thing out<commit_after>#include "rb_Nef_polyhedron_3.h"

// Comment to try git, by Rodrigo

template <class HDS>
class Polyhedron_builder : public CGAL::Modifier_base<HDS> {
public:
	Array points;
	Array faces;

	Polyhedron_builder(Array points, Array faces) {
		this->points = points;
		this->faces = faces;
	}

  void operator()( HDS& hds) {
    // Postcondition: `hds' is a valid polyhedral surface.
    CGAL::Polyhedron_incremental_builder_3<HDS> B( hds, true);
    typedef typename HDS::Vertex   Vertex;
    typedef typename Vertex::Point PointHDS;
    B.begin_surface( points.size(), faces.size());
    // Add vertices
		for (unsigned int i = 0; i < points.size(); i++) {
			Array point = Array(points[i]);
			PointHDS pt = PointHDS(
				from_ruby<double>(point[0]),
				from_ruby<double>(point[1]),
				from_ruby<double>(point[2]));
			B.add_vertex(pt);
		}
		// Add faces
		for (unsigned int i = 0; i < faces.size(); i++) {
			Array indices = Array(faces[i]);
			B.begin_facet();
			for (unsigned int j = 0; j < indices.size(); j++) {
				B.add_vertex_to_facet(from_ruby<int>(indices[j]));
			}
			B.end_facet();
		}
    B.end_surface();
  }
};

/*-----------MAIN METHODS------------*/

Nef_polyhedron_3 build(Array points, Array faces){
	Polyhedron_builder<HalfedgeDS> pb(points, faces);
	Polyhedron_3 P;
	P.delegate(pb);
	Nef_polyhedron_3 N(P);
	return N;
}

Nef_polyhedron_3 build_polyline(Array points){
	typedef Point_3* 																		point_iterator;
	typedef std::pair<point_iterator,point_iterator> 		point_range;
	typedef std::list<point_range> 											polyline_list;
	Point_3 polyline[points.size()];
	for (unsigned int i = 0; i < points.size(); ++i){
		polyline[i] = from_ruby<Point_3>(points[i]);
	}
	polyline_list polylines;
	polylines.push_back(point_range(polyline,polyline+points.size()));
	Nef_polyhedron_3 N( polylines.begin(),
											polylines.end(),
											Nef_polyhedron_3::Polylines_tag());
	return N;
}

Array split(Nef_polyhedron_3 N){
	vector<Nef_polyhedron_3> nefs;
	Nef_polyhedron_3::Volume_const_iterator vi = ++N.volumes_begin();
	Nef_polyhedron_3::Shell_entry_const_iterator si;
  CGAL_forall_volumes(vi,N) {
		if(vi->mark()) {
			Nef_polyhedron_3::Shell_entry_const_iterator si;
			CGAL_forall_shells_of(si, vi) {
				Nef_polyhedron_3::SFace_const_handle sfch(si);
				Nef_polyhedron_3 O(N,sfch);
				nefs.push_back(O);
			}
		}
	}
	Array out(nefs.begin(), nefs.end());
	return out;
}

String to_off(Nef_polyhedron_3 N){
	stringstream ss;
	if (N.is_valid() && N.is_simple()) {
		Polyhedron_3 P;
		N.convert_to_polyhedron(P);
		ss << P;
	}
	return String(ss.str());
}

Array vertices(Nef_polyhedron_3 N){
	vector<Vertex> vertices;
	Nef_polyhedron_3::Vertex_const_iterator vci;
	CGAL_forall_vertices(vci,N){
		vertices.push_back(*vci);
  }
	Array out(vertices.begin(), vertices.end());
	return out;
}

Array halffacets(Nef_polyhedron_3 N){
	vector<Halffacet> halffacets;
	Nef_polyhedron_3::Halffacet_const_iterator hfci;
	CGAL_forall_halffacets(hfci,N){
		halffacets.push_back(*hfci);
  }
	Array out(halffacets.begin(), halffacets.end());
	return out;
}

Iso_cuboid_3 bounding_box(Nef_polyhedron_3 N){
	vector<Point_3> points;
	Nef_polyhedron_3::Vertex_const_iterator vci;
	CGAL_forall_vertices(vci,N){
		points.push_back(vci->point());
  }
	return CGAL::bounding_box(points.begin(),points.end());
}
/*
String to_s(Nef_polyhedron_3 N){
	stringstream ss;
	ss << N;
	return String(ss.str());
}

Nef_polyhedron_3 load(String s){
	stringstream ss;
	ss << s.c_str();
	Nef_polyhedron_3 N;
	ss >> N;
	return N;
}

bool is_bounded(Nef_polyhedron_3 N){
	return N.is_bounded();
}
*/

Data_Type<Nef_polyhedron_3> define_Nef_polyhedron_3(Rice::Module rb_mCGAL ) {

	typedef bool (Nef_polyhedron_3::*np3_is_valid)();
	Data_Type<Nef_polyhedron_3> rb_cNef_polyhedron_3 =
		define_class_under<Nef_polyhedron_3>(rb_mCGAL, "Nef_polyhedron_3")
		.define_constructor(Constructor<Nef_polyhedron_3>())
		.define_singleton_method("build", &build)
		.define_singleton_method("build_polyline", &build_polyline)
//		.define_singleton_method("load", &load)
		.define_method("simple?", &Nef_polyhedron_3::is_simple)
		.define_method("valid?", np3_is_valid(&Nef_polyhedron_3::is_valid))
		.define_method("empty?", &Nef_polyhedron_3::is_empty)
		.define_method("space?", &Nef_polyhedron_3::is_space)
//		.define_method("bounded?", &is_bounded)
		.define_method("+", &Nef_polyhedron_3::operator+)
		.define_method("-", &Nef_polyhedron_3::operator-)
		.define_method("*", &Nef_polyhedron_3::operator*)
		.define_method("vertices", &vertices)
		.define_method("halffacets", &halffacets)
		.define_method("to_off", &to_off)
		.define_method("split", &split)
		.define_method("bounding_box", &bounding_box)
//		.define_method("to_s", &to_s)
	;

	return rb_cNef_polyhedron_3;
}

<|endoftext|>