<commit_before>#include <iostream>
#include <ctime>
#include <string>
#include <opencv2/opencv.hpp>
#include <raspicam/raspicam_cv.h>
#include <stdio.h>

#include "objectTracking/Vec3.h"
#include "objectTracking/ColorTracker.h"
#include "objectTracking/ImgFunc.h"

#define END_LOOP_BUTTON 24

int frameWidth = 320;
int frameHeight = 240;

Vec3 objectColor;
Vec3 minColor;
Vec3 maxColor;
Vec3 threshold(20, 40, 40);

void clear()
{
    // CSI[2J clears screen, CSI[H moves the cursor to top-left corner
    std::cout << "\x1B[2J\x1B[H";
}

int main()
{
    //Setting up the camera
    raspicam::RaspiCam_Cv camera;

    camera.set(CV_CAP_PROP_FRAME_WIDTH, frameWidth);
    camera.set(CV_CAP_PROP_FRAME_HEIGHT, frameHeight);

    std::cout << "Opening camera" << std::endl;
    if(!camera.open())
    {
        std::cout << "Error opening camera" << std::endl;
        return -1;
    }

    //Capturing a few frames to adjust the exposure of the camera
    std::cout << "Precapturing" << std::endl;
    cv::Mat testImg;
    for(unsigned int i = 0; i < 10; i++)
    {
        camera.grab();

        camera.retrieve(testImg);
    }
    std::cout << "Writing test img" << std::endl;
    cv::imwrite("/home/frans/public_html/test2.jpg", testImg);

    //Main menu
    bool running = true;
    while(running == true)
    {
        std::string input;

        std::cout << "1: select object" << std::endl;
        std::cout << "2: search once" << std::endl;
        std::cout << "3: search" << std::endl;
        std::cout << "0: exit" << std::endl;

        //Getting commands from the user
        std::cout << "Command: " << std::endl;
        std::cin >> input;

        //Checking the input
        if(input.compare("1") == 0)
        {
            //Grabbing an image
            cv::Mat image;

            camera.grab();

            std::cout << "Grabed image "<<std::endl;
            camera.retrieve(image);
            std::cout << "Retrieved image" << std::endl;

            //Processing the image
            ColorTracker ct;
            ct.setImage(image);
            ct.saveImage("/home/frans/public_html/cvRefRaw.jpg");

            objectColor = ct.getObjectColor();

            for(int i = 0; i < 3; i++)
            {
                minColor.val[i] = objectColor.val[i] - threshold.val[i];
                maxColor.val[i] = objectColor.val[i] + threshold.val[i];
            }

            //Print the color of the image
            std::cout << "Selected color: " << objectColor.getString() << std::endl;
        }
        else if(input.compare("2") == 0)
        {
            cv::Mat image;

            camera.grab();
            camera.retrieve(image);

            ColorTracker ct;
            ct.setImage(image);
            ct.generateBinary(minColor, maxColor, true);

            ct.saveBinary("/home/frans/public_html/cvThr.jpg");

            //Print the result of the search
            std::cout << "Found object in: " << ct.getMiddlePos().getString() << std::endl;

        }
        else if(input.compare("3") == 0)
        {
            //Color tracker object for tracking objects
            ColorTracker ct;
            cv::Mat image;
            cv::Mat pathImg(cv::Size(frameWidth, frameHeight), CV_8UC1,  cv::Scalar(0));

            bool capturing = true;

            std::clock_t searchStart = std::clock();
            while(capturing == true)
            {
                clear();

                //Grabbing an image
                camera.grab();
                camera.retrieve(image);

                ct.setImage(image);
                ct.generateBinary(minColor, maxColor, true);

                cv::imshow("", image);

                std::cout << "Found object in: " << ct.getMiddlePos().getString() << std::endl;
                //storing the result in an image
                uint8_t* pathData = pathImg.data;

                int pixelPos = ImgFunc::getPixelStart(ct.getMiddlePos().val[0], ct.getMiddlePos().val[1], frameWidth, frameHeight, 1);

                if(pixelPos > 0 && pixelPos < frameWidth*frameHeight)
                {
                    pathData[pixelPos] = 255;
                    std::cout << "Writing pixel" << std::endl;
                }

                if((std::clock() - searchStart) / CLOCKS_PER_SEC >  3)
                {
                    capturing = false;

                    imwrite("/home/frans/public_html/path.jpg", pathImg);
                }
            }
        }
        else if(input.compare("0") == 0)
        {
           running = false;
        }
    }
    return 0;
}

<commit_msg>Fix image drawing on raspi<commit_after>#include <iostream>
#include <ctime>
#include <string>
#include <opencv2/opencv.hpp>
#include <raspicam/raspicam_cv.h>
#include <stdio.h>

#include "objectTracking/Vec3.h"
#include "objectTracking/ColorTracker.h"
#include "objectTracking/ImgFunc.h"

#define END_LOOP_BUTTON 24

int frameWidth = 320;
int frameHeight = 240;

Vec3 objectColor;
Vec3 minColor;
Vec3 maxColor;
Vec3 threshold(20, 40, 40);

void clear()
{
    // CSI[2J clears screen, CSI[H moves the cursor to top-left corner
    std::cout << "\x1B[2J\x1B[H";
}

int main()
{
    //cv::namedWindow("abc", CV_WINDOW_OPENGL);

    //Setting up the camera
    raspicam::RaspiCam_Cv camera;

    camera.set(CV_CAP_PROP_FRAME_WIDTH, frameWidth);
    camera.set(CV_CAP_PROP_FRAME_HEIGHT, frameHeight);

    std::cout << "Opening camera" << std::endl;
    if(!camera.open())
    {
        std::cout << "Error opening camera" << std::endl;
        return -1;
    }

    //Capturing a few frames to adjust the exposure of the camera
    std::cout << "Precapturing" << std::endl;
    cv::Mat testImg;
    for(unsigned int i = 0; i < 10; i++)
    {
        camera.grab();

        camera.retrieve(testImg);
    }
    std::cout << "Writing test img" << std::endl;
    cv::imwrite("/home/frans/public_html/test2.jpg", testImg);

    //Main menu
    bool running = true;
    while(running == true)
    {
        std::string input;

        std::cout << "1: select object" << std::endl;
        std::cout << "2: search once" << std::endl;
        std::cout << "3: search" << std::endl;
        std::cout << "0: exit" << std::endl;

        //Getting commands from the user
        std::cout << "Command: " << std::endl;
        std::cin >> input;

        //Checking the input
        if(input.compare("1") == 0)
        {
            //Grabbing an image
            cv::Mat image;

            camera.grab();

            std::cout << "Grabed image "<<std::endl;
            camera.retrieve(image);
            std::cout << "Retrieved image" << std::endl;

            //Processing the image
            ColorTracker ct;
            ct.setImage(image);
            ct.saveImage("/home/frans/public_html/cvRefRaw.jpg");

            objectColor = ct.getObjectColor();

            for(int i = 0; i < 3; i++)
            {
                minColor.val[i] = objectColor.val[i] - threshold.val[i];
                maxColor.val[i] = objectColor.val[i] + threshold.val[i];
            }

            //Print the color of the image
            std::cout << "Selected color: " << objectColor.getString() << std::endl;
        }
        else if(input.compare("2") == 0)
        {
            cv::Mat image;

            camera.grab();
            camera.retrieve(image);

            ColorTracker ct;
            ct.setImage(image);
            ct.generateBinary(minColor, maxColor, true);

            ct.saveBinary("/home/frans/public_html/cvThr.jpg");

            //Print the result of the search
            std::cout << "Found object in: " << ct.getMiddlePos().getString() << std::endl;

        }
        else if(input.compare("3") == 0)
        {
            //Color tracker object for tracking objects
            ColorTracker ct;
            cv::Mat image;
            cv::Mat pathImg(cv::Size(frameWidth, frameHeight), CV_8UC1,  cv::Scalar(0));

            bool capturing = true;

            std::clock_t searchStart = std::clock();
            while(capturing == true)
            {
                clear();

                //Grabbing an image
                camera.grab();
                camera.retrieve(image);

                ct.setImage(image);
                ct.generateBinary(minColor, maxColor, true);

                cv::imshow("abc", ct.getBinary());
                cv::waitKey(10);

                std::cout << "Found object in: " << ct.getMiddlePos().getString() << std::endl;
                std::cout <<  "Showing image" << std::endl;
                //storing the result in an image
                uint8_t* pathData = pathImg.data;

                int pixelPos = ImgFunc::getPixelStart(ct.getMiddlePos().val[0], ct.getMiddlePos().val[1], frameWidth, frameHeight, 1);

                if(pixelPos > 0 && pixelPos < frameWidth*frameHeight)
                {
                    pathData[pixelPos] = 255;
                    std::cout << "Writing pixel" << std::endl;
                }

                if((std::clock() - searchStart) / CLOCKS_PER_SEC >  3)
                {
                    capturing = false;

                    imwrite("/home/frans/public_html/path.jpg", pathImg);
                }
            }
        }
        else if(input.compare("0") == 0)
        {
           running = false;
        }
    }
    return 0;
}

<|endoftext|>


<commit_before>//
// detail/mockup_serial_port_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

#ifndef BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP
#define BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP

#include <boost/asio/detail/config.hpp>

#include <string>
#include <deque>
#include <memory>
#include <boost/chrono.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/serial_port_base.hpp>
#include <boost/asio/streambuf.hpp>

#include <boost/asio/buffer.hpp>
#include <boost/asio/buffers_iterator.hpp>

#include <boost/asio/detail/buffer_sequence_adapter.hpp>

#include <boost/thread/condition_variable.hpp>
#include <boost/thread/recursive_mutex.hpp>

namespace boost {
namespace asio {
namespace detail {

// Extend mockup_descriptor_service to provide serial port support.
class mockup_serial_port_service
{
public:
  // The dummy native type of a serial port.
  typedef int native_handle_type;

  // The dummy implementation type of the serial port.
  struct implementation_type {

    // Each read handler that get registered, get's a work object associated,
    // to avoid io_service.run() from returning until the handler can effectively
    // be called
    typedef std::pair<boost::function<void ()>, io_service::work> read_handler_entry;

    // Thread specific values
    native_handle_type handle_ = -1;
    bool open_ = false;
    bool cancelled_ = false;

    // The buffer, it's mutex and condition_variable is shared by
    // multiple thread opening the same device name.
    std::shared_ptr<std::string> serial_line_simulation_buffer_in_
      = std::make_shared<std::string>();

    // io_service associated stack of handler to call in case a write occurs.
    std::shared_ptr<std::map<
      io_service*,
      std::shared_ptr<std::deque< read_handler_entry >>
    >> pending_read_handlers_
      = std::make_shared<std::map<
          io_service*,
          std::shared_ptr<std::deque< read_handler_entry >>
        >>();

    // Mutex to protect access the shared(_ptr) values
    std::shared_ptr<boost::recursive_mutex> mutex_
      = std::make_shared<boost::recursive_mutex>();

    // Condition variable to come back from a blocking read or a cancel faster.
    std::shared_ptr<boost::condition_variable> ready_read_
      = std::make_shared<boost::condition_variable>();
  };

  BOOST_ASIO_DECL mockup_serial_port_service(
      boost::asio::io_service& io_service);

  // Destroy all user-defined handler objects owned by the service.
  BOOST_ASIO_DECL void shutdown_service();

  // Construct a new serial port implementation.
  void construct(implementation_type& impl)
  {
  }

  // Move-construct a new serial port implementation.
  void move_construct(implementation_type& impl,
      implementation_type& other_impl)
  {
    impl.serial_line_simulation_buffer_in_ = other_impl.serial_line_simulation_buffer_in_;
  }

//  // Move-assign from another serial port implementation.
//  void move_assign(implementation_type& impl,
//      mockup_serial_port_service& other_service,
//      implementation_type& other_impl)
//  {
//    impl = other_service.fake_serial_;
//  }

  // Destroy a serial port implementation.
  void destroy(implementation_type& impl)
  {
  }

  // Open the serial port using the specified device name.
  BOOST_ASIO_DECL boost::system::error_code open(implementation_type& impl,
      const std::string& device, boost::system::error_code& ec);

  // Assign a native descriptor to a serial port implementation.
  boost::system::error_code assign(implementation_type& impl,
      const native_handle_type& native_descriptor,
      boost::system::error_code& ec)
  {
    throw std::runtime_error("Assigning from native handle is unsupported in mockup.");
  }

  // Determine whether the serial port is open.
  bool is_open(const implementation_type& impl) const
  {
    return impl.open_;
  }

  // Destroy a serial port implementation.
  boost::system::error_code close(implementation_type& impl,
      boost::system::error_code& ec)
  {
    cancel(impl, ec);
    impl.open_ = false;
    ec = boost::system::error_code();
    return ec;
  }

  // Get the native serial port representation.
  native_handle_type native_handle(implementation_type& impl)
  {
    return impl.handle_;
  }

  // Cancel all operations associated with the serial port.
  boost::system::error_code cancel(implementation_type& impl,
      boost::system::error_code& ec)
  {
    if (!is_open(impl))
    {
      ec = boost::asio::error::bad_descriptor;
      return ec;
    }

    impl.cancelled_ = true;

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

      auto pending_handlers = impl.pending_read_handlers_
        ->at(std::addressof(io_service_));

      while (!pending_handlers->empty()) {
        // operation_aborted will be passed as they
        // will notice all was cancelled
        io_service_.post(pending_handlers->back().first);
        pending_handlers->pop_back();
      }
    }

    impl.ready_read_->notify_all();

    ec = boost::system::error_code();
    return ec;
  }

  // Set an option on the serial port.
  template <typename SettableSerialPortOption>
  boost::system::error_code set_option(implementation_type& impl,
      const SettableSerialPortOption& option, boost::system::error_code& ec)
  {
    return do_set_option(impl,
        &mockup_serial_port_service::store_option<SettableSerialPortOption>,
        &option, ec);
  }

  // Get an option from the serial port.
  template <typename GettableSerialPortOption>
  boost::system::error_code get_option(const implementation_type& impl,
      GettableSerialPortOption& option, boost::system::error_code& ec) const
  {
    return do_get_option(impl,
        &mockup_serial_port_service::load_option<GettableSerialPortOption>,
        &option, ec);
  }

  // Send a break sequence to the serial port.
  boost::system::error_code send_break(implementation_type& impl,
      boost::system::error_code& ec)
  {
    ec = boost::asio::error::operation_not_supported;
    return ec;
  }

  // Write the given data. Returns the number of bytes sent.
  template <typename ConstBufferSequence>
  size_t write_some(implementation_type& impl,
      const ConstBufferSequence& buffers, boost::system::error_code& ec)
  {
    boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

    if (impl.cancelled_) {
      ec = boost::asio::error::operation_aborted;
      return 0;
    }

    auto begin_bytes = boost::asio::buffers_iterator<ConstBufferSequence>::begin(buffers);
    auto end_bytes = boost::asio::buffers_iterator<ConstBufferSequence>::end(buffers);

    std::copy(begin_bytes, end_bytes, std::back_inserter(*impl.serial_line_simulation_buffer_in_));
    size_t bytes_transferred = std::distance(begin_bytes, end_bytes);

    for (auto& pending_handler : *impl.pending_read_handlers_) {
      while (!pending_handler.second->empty()) {
        pending_handler.first->post(pending_handler.second->back().first);
        pending_handler.second->pop_back();
      }
    }

    impl.ready_read_->notify_all();
    ec = boost::system::error_code();
    return bytes_transferred;
  }

  // Start an asynchronous write. The data being written must be valid for the
  // lifetime of the asynchronous operation.
  template <typename ConstBufferSequence, typename Handler>
  void async_write_some(implementation_type& impl,
      const ConstBufferSequence& buffers, Handler& handler)
  {

    auto perform_write = [&impl, buffers, handler, this]() mutable {
      boost::system::error_code ec{};
      auto bytes_written = write_some(impl, buffers, ec);
      handler(ec, bytes_written);
    };

    io_service_.post(perform_write);
  }

  // Read some data. Returns the number of bytes received.
  template <typename MutableBufferSequence>
  size_t read_some(implementation_type& impl,
      const MutableBufferSequence& buffers, boost::system::error_code& ec)
  {
    // empy out buffer is a no-op.
    buffer_sequence_adapter<boost::asio::mutable_buffer,
        MutableBufferSequence> bufs_adapted(buffers);
    if (bufs_adapted.all_empty()) {
      ec = boost::system::error_code();
      return 0;
    }

    bool bytes_available = false;
    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
      bytes_available = !impl.serial_line_simulation_buffer_in_->empty();
    }

    while ( (!bytes_available) && (!impl.cancelled_) ) {
      // Wait for bytes to be available
      boost::mutex mutex_wait{};
      boost::mutex::scoped_lock wait_lock{mutex_wait};
      impl.ready_read_->wait_for(wait_lock, boost::chrono::milliseconds(5));

      { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
        bytes_available = !impl.serial_line_simulation_buffer_in_->empty();
      }

    }

    if (impl.cancelled_) {
      ec = boost::asio::error::operation_aborted;
      return 0;
    }

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

      size_t read_count = 0;

      for (auto buf : buffers) {
        char* bytes = boost::asio::buffer_cast<char*>(buf);
        auto bytes_to_read =  std::min(boost::asio::buffer_size(buf), impl.serial_line_simulation_buffer_in_->size());
        memcpy(bytes, impl.serial_line_simulation_buffer_in_->data(), bytes_to_read);
        impl.serial_line_simulation_buffer_in_->erase(0, bytes_to_read);

        read_count += bytes_to_read;
      }

      ec = boost::system::error_code();
      return read_count;
    }
  }

  // Start an asynchronous read. The buffer for the data being received must be
  // valid for the lifetime of the asynchronous operation.
  template <typename MutableBufferSequence, typename Handler>
  void async_read_some(implementation_type& impl,
      const MutableBufferSequence& buffers, Handler& handler)
  {

    boost::function<void ()> perform_read = [&impl, buffers, handler, this]() mutable {
      boost::system::error_code ec{};
      auto bytes_read = read_some(impl, buffers, ec);
      handler(ec, bytes_read);
    };

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
      impl.pending_read_handlers_
        ->at(std::addressof(io_service_))
        ->push_front(std::make_pair(perform_read, io_service::work(io_service_)));
    }
  }

private:

#ifdef _WIN32
	struct termios {};
#endif

  // Function pointer type for storing a serial port option.
  typedef boost::system::error_code (*store_function_type)(
      const void*, termios&, boost::system::error_code&);

  // Helper function template to store a serial port option.
  template <typename SettableSerialPortOption>
  static boost::system::error_code store_option(const void* option,
      termios& storage, boost::system::error_code& ec)
  {
    return static_cast<const SettableSerialPortOption*>(option)->store(
        storage, ec);
  }

  // Helper function to set a serial port option.
  BOOST_ASIO_DECL boost::system::error_code do_set_option(
      implementation_type& impl, store_function_type store,
      const void* option, boost::system::error_code& ec);

  // Function pointer type for loading a serial port option.
  typedef boost::system::error_code (*load_function_type)(
      void*, const termios&, boost::system::error_code&);

  // Helper function template to load a serial port option.
  template <typename GettableSerialPortOption>
  static boost::system::error_code load_option(void* option,
      const termios& storage, boost::system::error_code& ec)
  {
    return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
  }

  // Helper function to get a serial port option.
  BOOST_ASIO_DECL boost::system::error_code do_get_option(
      const implementation_type& impl, load_function_type load,
      void* option, boost::system::error_code& ec) const;

  io_service& io_service_;
  termios termios_storage;
};

} // namespace detail
} // namespace asio
} // namespace boost

#include <pre/boost/asio/detail/impl/mockup_serial_port_service.ipp>

#endif // BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP
<commit_msg>BUGFIX: Windows build did no more work with Boost 1.59 and needs to have the BOOST_ASIO_OPTION_STORAGE defined.<commit_after>//
// detail/mockup_serial_port_service.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

#ifndef BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP
#define BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP

#include <boost/asio/detail/config.hpp>

#include <string>
#include <deque>
#include <memory>
#include <boost/chrono.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/serial_port_base.hpp>
#include <boost/asio/streambuf.hpp>

#include <boost/asio/buffer.hpp>
#include <boost/asio/buffers_iterator.hpp>

#include <boost/asio/detail/buffer_sequence_adapter.hpp>

#include <boost/thread/condition_variable.hpp>
#include <boost/thread/recursive_mutex.hpp>

#if defined(GENERATING_DOCUMENTATION)
# define BOOST_ASIO_OPTION_STORAGE implementation_defined
#elif defined(BOOST_ASIO_WINDOWS) || defined(__CYGWIN__)
# define BOOST_ASIO_OPTION_STORAGE DCB
#else
# define BOOST_ASIO_OPTION_STORAGE termios
#endif

namespace boost {
namespace asio {
namespace detail {

// Extend mockup_descriptor_service to provide serial port support.
class mockup_serial_port_service
{
public:
  // The dummy native type of a serial port.
  typedef int native_handle_type;

  // The dummy implementation type of the serial port.
  struct implementation_type {

    // Each read handler that get registered, get's a work object associated,
    // to avoid io_service.run() from returning until the handler can effectively
    // be called
    typedef std::pair<boost::function<void ()>, io_service::work> read_handler_entry;

    // Thread specific values
    native_handle_type handle_ = -1;
    bool open_ = false;
    bool cancelled_ = false;

    // The buffer, it's mutex and condition_variable is shared by
    // multiple thread opening the same device name.
    std::shared_ptr<std::string> serial_line_simulation_buffer_in_
      = std::make_shared<std::string>();

    // io_service associated stack of handler to call in case a write occurs.
    std::shared_ptr<std::map<
      io_service*,
      std::shared_ptr<std::deque< read_handler_entry >>
    >> pending_read_handlers_
      = std::make_shared<std::map<
          io_service*,
          std::shared_ptr<std::deque< read_handler_entry >>
        >>();

    // Mutex to protect access the shared(_ptr) values
    std::shared_ptr<boost::recursive_mutex> mutex_
      = std::make_shared<boost::recursive_mutex>();

    // Condition variable to come back from a blocking read or a cancel faster.
    std::shared_ptr<boost::condition_variable> ready_read_
      = std::make_shared<boost::condition_variable>();
  };

  BOOST_ASIO_DECL mockup_serial_port_service(
      boost::asio::io_service& io_service);

  // Destroy all user-defined handler objects owned by the service.
  BOOST_ASIO_DECL void shutdown_service();

  // Construct a new serial port implementation.
  void construct(implementation_type& impl)
  {
  }

  // Move-construct a new serial port implementation.
  void move_construct(implementation_type& impl,
      implementation_type& other_impl)
  {
    impl.serial_line_simulation_buffer_in_ = other_impl.serial_line_simulation_buffer_in_;
  }

//  // Move-assign from another serial port implementation.
//  void move_assign(implementation_type& impl,
//      mockup_serial_port_service& other_service,
//      implementation_type& other_impl)
//  {
//    impl = other_service.fake_serial_;
//  }

  // Destroy a serial port implementation.
  void destroy(implementation_type& impl)
  {
  }

  // Open the serial port using the specified device name.
  BOOST_ASIO_DECL boost::system::error_code open(implementation_type& impl,
      const std::string& device, boost::system::error_code& ec);

  // Assign a native descriptor to a serial port implementation.
  boost::system::error_code assign(implementation_type& impl,
      const native_handle_type& native_descriptor,
      boost::system::error_code& ec)
  {
    throw std::runtime_error("Assigning from native handle is unsupported in mockup.");
  }

  // Determine whether the serial port is open.
  bool is_open(const implementation_type& impl) const
  {
    return impl.open_;
  }

  // Destroy a serial port implementation.
  boost::system::error_code close(implementation_type& impl,
      boost::system::error_code& ec)
  {
    cancel(impl, ec);
    impl.open_ = false;
    ec = boost::system::error_code();
    return ec;
  }

  // Get the native serial port representation.
  native_handle_type native_handle(implementation_type& impl)
  {
    return impl.handle_;
  }

  // Cancel all operations associated with the serial port.
  boost::system::error_code cancel(implementation_type& impl,
      boost::system::error_code& ec)
  {
    if (!is_open(impl))
    {
      ec = boost::asio::error::bad_descriptor;
      return ec;
    }

    impl.cancelled_ = true;

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

      auto pending_handlers = impl.pending_read_handlers_
        ->at(std::addressof(io_service_));

      while (!pending_handlers->empty()) {
        // operation_aborted will be passed as they
        // will notice all was cancelled
        io_service_.post(pending_handlers->back().first);
        pending_handlers->pop_back();
      }
    }

    impl.ready_read_->notify_all();

    ec = boost::system::error_code();
    return ec;
  }

  // Set an option on the serial port.
  template <typename SettableSerialPortOption>
  boost::system::error_code set_option(implementation_type& impl,
      const SettableSerialPortOption& option, boost::system::error_code& ec)
  {
    return do_set_option(impl,
        &mockup_serial_port_service::store_option<SettableSerialPortOption>,
        &option, ec);
  }

  // Get an option from the serial port.
  template <typename GettableSerialPortOption>
  boost::system::error_code get_option(const implementation_type& impl,
      GettableSerialPortOption& option, boost::system::error_code& ec) const
  {
    return do_get_option(impl,
        &mockup_serial_port_service::load_option<GettableSerialPortOption>,
        &option, ec);
  }

  // Send a break sequence to the serial port.
  boost::system::error_code send_break(implementation_type& impl,
      boost::system::error_code& ec)
  {
    ec = boost::asio::error::operation_not_supported;
    return ec;
  }

  // Write the given data. Returns the number of bytes sent.
  template <typename ConstBufferSequence>
  size_t write_some(implementation_type& impl,
      const ConstBufferSequence& buffers, boost::system::error_code& ec)
  {
    boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

    if (impl.cancelled_) {
      ec = boost::asio::error::operation_aborted;
      return 0;
    }

    auto begin_bytes = boost::asio::buffers_iterator<ConstBufferSequence>::begin(buffers);
    auto end_bytes = boost::asio::buffers_iterator<ConstBufferSequence>::end(buffers);

    std::copy(begin_bytes, end_bytes, std::back_inserter(*impl.serial_line_simulation_buffer_in_));
    size_t bytes_transferred = std::distance(begin_bytes, end_bytes);

    for (auto& pending_handler : *impl.pending_read_handlers_) {
      while (!pending_handler.second->empty()) {
        pending_handler.first->post(pending_handler.second->back().first);
        pending_handler.second->pop_back();
      }
    }

    impl.ready_read_->notify_all();
    ec = boost::system::error_code();
    return bytes_transferred;
  }

  // Start an asynchronous write. The data being written must be valid for the
  // lifetime of the asynchronous operation.
  template <typename ConstBufferSequence, typename Handler>
  void async_write_some(implementation_type& impl,
      const ConstBufferSequence& buffers, Handler& handler)
  {

    auto perform_write = [&impl, buffers, handler, this]() mutable {
      boost::system::error_code ec{};
      auto bytes_written = write_some(impl, buffers, ec);
      handler(ec, bytes_written);
    };

    io_service_.post(perform_write);
  }

  // Read some data. Returns the number of bytes received.
  template <typename MutableBufferSequence>
  size_t read_some(implementation_type& impl,
      const MutableBufferSequence& buffers, boost::system::error_code& ec)
  {
    // empy out buffer is a no-op.
    buffer_sequence_adapter<boost::asio::mutable_buffer,
        MutableBufferSequence> bufs_adapted(buffers);
    if (bufs_adapted.all_empty()) {
      ec = boost::system::error_code();
      return 0;
    }

    bool bytes_available = false;
    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
      bytes_available = !impl.serial_line_simulation_buffer_in_->empty();
    }

    while ( (!bytes_available) && (!impl.cancelled_) ) {
      // Wait for bytes to be available
      boost::mutex mutex_wait{};
      boost::mutex::scoped_lock wait_lock{mutex_wait};
      impl.ready_read_->wait_for(wait_lock, boost::chrono::milliseconds(5));

      { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
        bytes_available = !impl.serial_line_simulation_buffer_in_->empty();
      }

    }

    if (impl.cancelled_) {
      ec = boost::asio::error::operation_aborted;
      return 0;
    }

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};

      size_t read_count = 0;

      for (auto buf : buffers) {
        char* bytes = boost::asio::buffer_cast<char*>(buf);
        auto bytes_to_read =  std::min(boost::asio::buffer_size(buf), impl.serial_line_simulation_buffer_in_->size());
        memcpy(bytes, impl.serial_line_simulation_buffer_in_->data(), bytes_to_read);
        impl.serial_line_simulation_buffer_in_->erase(0, bytes_to_read);

        read_count += bytes_to_read;
      }

      ec = boost::system::error_code();
      return read_count;
    }
  }

  // Start an asynchronous read. The buffer for the data being received must be
  // valid for the lifetime of the asynchronous operation.
  template <typename MutableBufferSequence, typename Handler>
  void async_read_some(implementation_type& impl,
      const MutableBufferSequence& buffers, Handler& handler)
  {

    boost::function<void ()> perform_read = [&impl, buffers, handler, this]() mutable {
      boost::system::error_code ec{};
      auto bytes_read = read_some(impl, buffers, ec);
      handler(ec, bytes_read);
    };

    { boost::recursive_mutex::scoped_lock lock{*impl.mutex_};
      impl.pending_read_handlers_
        ->at(std::addressof(io_service_))
        ->push_front(std::make_pair(perform_read, io_service::work(io_service_)));
    }
  }

private:

  // Function pointer type for storing a serial port option.
  typedef boost::system::error_code (*store_function_type)(
      const void*, BOOST_ASIO_OPTION_STORAGE&, boost::system::error_code&);

  // Helper function template to store a serial port option.
  template <typename SettableSerialPortOption>
  static boost::system::error_code store_option(const void* option,
      BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
  {
    return static_cast<const SettableSerialPortOption*>(option)->store(
        storage, ec);
  }

  // Helper function to set a serial port option.
  BOOST_ASIO_DECL boost::system::error_code do_set_option(
      implementation_type& impl, store_function_type store,
      const void* option, boost::system::error_code& ec);

  // Function pointer type for loading a serial port option.
  typedef boost::system::error_code (*load_function_type)(
      void*, const BOOST_ASIO_OPTION_STORAGE&, boost::system::error_code&);

  // Helper function template to load a serial port option.
  template <typename GettableSerialPortOption>
  static boost::system::error_code load_option(void* option,
      const BOOST_ASIO_OPTION_STORAGE& storage, boost::system::error_code& ec)
  {
    return static_cast<GettableSerialPortOption*>(option)->load(storage, ec);
  }

  // Helper function to get a serial port option.
  BOOST_ASIO_DECL boost::system::error_code do_get_option(
      const implementation_type& impl, load_function_type load,
      void* option, boost::system::error_code& ec) const;

  io_service& io_service_;
  BOOST_ASIO_OPTION_STORAGE termios_storage;
};

} // namespace detail
} // namespace asio
} // namespace boost

#include <pre/boost/asio/detail/impl/mockup_serial_port_service.ipp>

#endif // BOOST_ASIO_DETAIL_MOCKUP_SERIAL_PORT_SERVICE_HPP
<|endoftext|>


<commit_before>/*
 * File:   MathSet.hpp
 * Original Author: Ryan Richard <ryanmrichard1@gmail.com>
 *
 * Created on January 22, 2016, 11:11 AM
 */

#ifndef BPMODULE_GUARD_MATH__MATHSET_HPP_
#define BPMODULE_GUARD_MATH__MATHSET_HPP_

#include <vector> //For default set container
#include <algorithm> //For set operations
#include "bpmodule/exception/Assert.hpp"
#include "bpmodule/exception/Exceptions.hpp"
#include "bpmodule/math/Universe.hpp"

namespace bpmodule {
    namespace math {

        /** \brief A class for performing set manipulations efficiently relative to
         *   some universe.
         *
         *   With the universe class all of the operations are deep copies or involve
         *   copying the actual elements over.  Now that we know what our universe is,
         *   we can do these operations much more efficiently by mapping each element
         *   to an integer in the range 0 to the size of our universe and performing
         *   the operations on those integers.  That's what this class does.  Thus
         *   by default operations with this class are shallow copies.  It is entirely
         *   possible to simply use the Universe class for set manipulations (barring
         *   complement), it will just not be as efficient.
         *
         *   Because a MathSet derives from Universe it is perfectly capable of being
         *   itself used as a universe.  Note that the privateness of the Universe
         *   base class means you can't pass this class by it's base class to anything
         *   other than this class.  All classes that intend to use MathSet should
         *   derive from it.
         *
         *   Developer note:  I originally thought we could get away without the
         *   shared_ptr to the Universe_.  When we link to a Universe, we just set
         *   the Storage_ in the base class to that of the one in Universe we are
         *   linking to.  Then we can use the base class's interface to do everything.
         *   This works fine if we don't ever intend to use a MathSet as a universe, but
         *   we do.  Imagine we have:
         *   \code
         *    Universe U;
         *    MathSet A(U);
         *    MathSet B(A);
         *   \endcode
         *   where we assume the objects are actually declared and setup correctly,
         *   additionally we assume A is a proper subset of U. Now how do we know if an
         *   element is in B's Universe?  For A we just had to check if it was in
         *   Storage_, but for B this won't work because Storage_ hasn't changed to
         *   represent the reduced subspace (we could do this, but then we'd have to
         *   copy and the point of this class is to avoid that (the Universe class
         *   would have taken that route)).  However, by storing a pointer to A, we
         *   need only compare against A's Elems_.
         *
         */
        template<typename T, typename U = std::vector<T>>
        class MathSet : private Universe<T, U> {
        private:
            ///Base class's type
            typedef Universe<T, U> Base_t;
            ///This class's type
            typedef MathSet<T, U> My_t;

            std::shared_ptr<const Base_t> Universe_;

            ///Checks if Elem (either as type T or as size_t) is in the universe
            template<typename V>
            void InUniverse(const V& Elem)const {
                exception::Assert<exception::ValueOutOfRange>(
                        Universe_->Contains(Elem),
                        "Requested element is not in the universe for this set"
                        );
            }

            MathSet(std::shared_ptr<const Base_t> Universe, const std::set<size_t> & Elems)
                : Universe_(Universe)
            {
                this->Elems_ = Elems;
            }

        public:
            typedef ConstSetItr<T, U> const_iterator;
            typedef T value_type;
            typedef U store_type;
            typedef std::function<bool(const T &)> SelectorFunc;
            typedef std::function<T(const T &)> TransformerFunc;

            ///Makes a set that is part of the given universe
            // fill = Make this set a set of all elements in the universe
            MathSet(std::shared_ptr<const Base_t> AUniverse, bool fill) : Universe_(AUniverse)
            {
                //!\todo replace with getting a set of indicies from the universe? Would probably be safer
                if(fill)
                {
                    for(size_t i = 0; i < AUniverse->size(); i++) this->Elems_.insert(i);
                }
            }

            ///Deep copies elements, shallow copies Universe_ and Storage_
            MathSet(const My_t&) = default;
            MathSet(My_t&&) = default;
            MathSet & operator=(My_t&&) = default;

            ///Returns a deep copy of everything
            virtual My_t Clone()const {
                return My_t(std::shared_ptr<Base_t>(new Base_t(*Universe_)), this->Elems_);
                //                                         ^^ Deep copy universe, copy elements
            }

            size_t size(void)const noexcept {
                return this->Elems_.size();
            }

            virtual size_t Idx(const T& Elem)const {
                return Universe_->Idx(Elem);
            }

            ///Same as copy constructor, but for assignment
            My_t& operator=(const My_t &) = default;

            ///For adding an element, if you know its index in the universe
            My_t& operator<<(size_t Idx) {
                InUniverse(Idx);
                this->Elems_.insert(Idx);
                return *this;
            }

            ///Unlike the base class, we just add the index
            virtual My_t& operator<<(const T& Elem) {
                InUniverse(Elem);
                return (*this) << Universe_->Idx(Elem);
            }

            ///Makes this the union of this and other
            const My_t& operator+=(const My_t& RHS) {
                for (const size_t& EI : RHS.Elems_)
                    this->Elems_.insert(EI);
                return *this;
            }

            ///Returns the union of this and other (result shares same resources)
            My_t operator+(const My_t& RHS)const {
                return My_t(*this) += RHS;
            }

            ///Makes this the intersection of this and other
            const My_t& operator/=(const My_t& RHS) {
                std::set<size_t> Temp(std::move(this->Elems_));
                this->Elems_ = std::set<size_t>();
                std::set_intersection(Temp.begin(), Temp.end(),
                        RHS.Elems_.begin(), RHS.Elems_.end(),
                        std::inserter<std::set < size_t >> (
                        this->Elems_, this->Elems_.begin()));
                return *this;
            }

            ///Returns the intersection of this and other
            My_t operator/(const My_t& RHS)const {
                return My_t(*this) /= RHS;
            }

            ///Makes this the set-difference of this and other
            const My_t operator-=(const My_t& RHS) {
                std::set<size_t> Temp(std::move(this->Elems_));
                this->Elems_ = std::set<size_t>();
                std::set_difference(Temp.begin(), Temp.end(),
                        RHS.Elems_.begin(), RHS.Elems_.end(),
                        std::inserter<std::set < size_t >> (
                        this->Elems_, this->Elems_.begin()));
                return *this;
            }

            ///Returns the set-difference of this and other
            My_t operator-(const My_t& RHS)const {
                return My_t(*this) -= RHS;
            }

            ///Returns the complement of this
            My_t Complement()const {
                My_t Temp(Universe_, {});
                for (const T& EI : *Universe_) {
                    if (!this->Contains(EI))Temp << EI;
                }
                return Temp;
            }

            virtual std::string ToString()const {
                std::stringstream ss;
                for (const size_t& EI : this->Elems_)
                    ss << (*Universe_)[EI] << " ";
                return ss.str();
            }

            My_t Transform(TransformerFunc transformer)const
            {
                //! \todo better way to do this function?
                //  This makes some assumptions about the ordering of elements
                std::shared_ptr<Base_t> newuniverse(new Base_t);

                for(size_t i = 0; i < Universe_->size(); ++i)
                {
                    const auto & it = (*Universe_)[i];

                    if(this->Elems_.count(i) > 0)
                        (*newuniverse) << transformer(it);
                    else
                        (*newuniverse) << it;
                }

                return My_t(newuniverse, this->Elems_);
            }

            My_t Partition(SelectorFunc selector) const
            {
                std::set<size_t> newelems;
                for(const auto & idx : this->Elems_)
                {
                    const auto & el = (*Universe_)[idx];
                    if(selector(el))
                        newelems.insert(idx);
                }

                return My_t(Universe_, newelems);
            }

            ///@{

            const_iterator begin() const {
                return const_iterator(Universe_->MakeIterator(this->Elems_.begin()));
            }

            const_iterator end() const {
                return const_iterator(Universe_->MakeIterator(this->Elems_.end()));
            }

            ///@}
        };

    }
}//End namespaces

#endif /* BPMODULE_GUARD_MATHSET_HPP_ */

<commit_msg>InUniverse should always throw exception, rather than only if debugging enabled<commit_after>/*
 * File:   MathSet.hpp
 * Original Author: Ryan Richard <ryanmrichard1@gmail.com>
 *
 * Created on January 22, 2016, 11:11 AM
 */

#ifndef BPMODULE_GUARD_MATH__MATHSET_HPP_
#define BPMODULE_GUARD_MATH__MATHSET_HPP_

#include <vector> //For default set container
#include <algorithm> //For set operations
#include "bpmodule/exception/Assert.hpp"
#include "bpmodule/exception/Exceptions.hpp"
#include "bpmodule/math/Universe.hpp"

namespace bpmodule {
    namespace math {

        /** \brief A class for performing set manipulations efficiently relative to
         *   some universe.
         *
         *   With the universe class all of the operations are deep copies or involve
         *   copying the actual elements over.  Now that we know what our universe is,
         *   we can do these operations much more efficiently by mapping each element
         *   to an integer in the range 0 to the size of our universe and performing
         *   the operations on those integers.  That's what this class does.  Thus
         *   by default operations with this class are shallow copies.  It is entirely
         *   possible to simply use the Universe class for set manipulations (barring
         *   complement), it will just not be as efficient.
         *
         *   Because a MathSet derives from Universe it is perfectly capable of being
         *   itself used as a universe.  Note that the privateness of the Universe
         *   base class means you can't pass this class by it's base class to anything
         *   other than this class.  All classes that intend to use MathSet should
         *   derive from it.
         *
         *   Developer note:  I originally thought we could get away without the
         *   shared_ptr to the Universe_.  When we link to a Universe, we just set
         *   the Storage_ in the base class to that of the one in Universe we are
         *   linking to.  Then we can use the base class's interface to do everything.
         *   This works fine if we don't ever intend to use a MathSet as a universe, but
         *   we do.  Imagine we have:
         *   \code
         *    Universe U;
         *    MathSet A(U);
         *    MathSet B(A);
         *   \endcode
         *   where we assume the objects are actually declared and setup correctly,
         *   additionally we assume A is a proper subset of U. Now how do we know if an
         *   element is in B's Universe?  For A we just had to check if it was in
         *   Storage_, but for B this won't work because Storage_ hasn't changed to
         *   represent the reduced subspace (we could do this, but then we'd have to
         *   copy and the point of this class is to avoid that (the Universe class
         *   would have taken that route)).  However, by storing a pointer to A, we
         *   need only compare against A's Elems_.
         *
         */
        template<typename T, typename U = std::vector<T>>
        class MathSet : private Universe<T, U> {
        private:
            ///Base class's type
            typedef Universe<T, U> Base_t;
            ///This class's type
            typedef MathSet<T, U> My_t;

            std::shared_ptr<const Base_t> Universe_;

            ///Checks if Elem (either as type T or as size_t) is in the universe
            template<typename V>
            void InUniverse(const V& Elem)const {
                if(!Universe_->Contains(Elem))
                    throw exception::ValueOutOfRange("Requested element is not in the universe for this set");
            }

            MathSet(std::shared_ptr<const Base_t> Universe, const std::set<size_t> & Elems)
                : Universe_(Universe)
            {
                this->Elems_ = Elems;
            }

        public:
            typedef ConstSetItr<T, U> const_iterator;
            typedef T value_type;
            typedef U store_type;
            typedef std::function<bool(const T &)> SelectorFunc;
            typedef std::function<T(const T &)> TransformerFunc;

            ///Makes a set that is part of the given universe
            // fill = Make this set a set of all elements in the universe
            MathSet(std::shared_ptr<const Base_t> AUniverse, bool fill) : Universe_(AUniverse)
            {
                //!\todo replace with getting a set of indicies from the universe? Would probably be safer
                if(fill)
                {
                    for(size_t i = 0; i < AUniverse->size(); i++) this->Elems_.insert(i);
                }
            }

            ///Deep copies elements, shallow copies Universe_ and Storage_
            MathSet(const My_t&) = default;
            MathSet(My_t&&) = default;
            MathSet & operator=(My_t&&) = default;

            ///Returns a deep copy of everything
            virtual My_t Clone()const {
                return My_t(std::shared_ptr<Base_t>(new Base_t(*Universe_)), this->Elems_);
                //                                         ^^ Deep copy universe, copy elements
            }

            size_t size(void)const noexcept {
                return this->Elems_.size();
            }

            virtual size_t Idx(const T& Elem)const {
                return Universe_->Idx(Elem);
            }

            ///Same as copy constructor, but for assignment
            My_t& operator=(const My_t &) = default;

            ///For adding an element, if you know its index in the universe
            My_t& operator<<(size_t Idx) {
                InUniverse(Idx);
                this->Elems_.insert(Idx);
                return *this;
            }

            ///Unlike the base class, we just add the index
            virtual My_t& operator<<(const T& Elem) {
                InUniverse(Elem);
                return (*this) << Universe_->Idx(Elem);
            }

            ///Makes this the union of this and other
            const My_t& operator+=(const My_t& RHS) {
                for (const size_t& EI : RHS.Elems_)
                    this->Elems_.insert(EI);
                return *this;
            }

            ///Returns the union of this and other (result shares same resources)
            My_t operator+(const My_t& RHS)const {
                return My_t(*this) += RHS;
            }

            ///Makes this the intersection of this and other
            const My_t& operator/=(const My_t& RHS) {
                std::set<size_t> Temp(std::move(this->Elems_));
                this->Elems_ = std::set<size_t>();
                std::set_intersection(Temp.begin(), Temp.end(),
                        RHS.Elems_.begin(), RHS.Elems_.end(),
                        std::inserter<std::set < size_t >> (
                        this->Elems_, this->Elems_.begin()));
                return *this;
            }

            ///Returns the intersection of this and other
            My_t operator/(const My_t& RHS)const {
                return My_t(*this) /= RHS;
            }

            ///Makes this the set-difference of this and other
            const My_t operator-=(const My_t& RHS) {
                std::set<size_t> Temp(std::move(this->Elems_));
                this->Elems_ = std::set<size_t>();
                std::set_difference(Temp.begin(), Temp.end(),
                        RHS.Elems_.begin(), RHS.Elems_.end(),
                        std::inserter<std::set < size_t >> (
                        this->Elems_, this->Elems_.begin()));
                return *this;
            }

            ///Returns the set-difference of this and other
            My_t operator-(const My_t& RHS)const {
                return My_t(*this) -= RHS;
            }

            ///Returns the complement of this
            My_t Complement()const {
                My_t Temp(Universe_, {});
                for (const T& EI : *Universe_) {
                    if (!this->Contains(EI))Temp << EI;
                }
                return Temp;
            }

            virtual std::string ToString()const {
                std::stringstream ss;
                for (const size_t& EI : this->Elems_)
                    ss << (*Universe_)[EI] << " ";
                return ss.str();
            }

            My_t Transform(TransformerFunc transformer)const
            {
                //! \todo better way to do this function?
                //  This makes some assumptions about the ordering of elements
                std::shared_ptr<Base_t> newuniverse(new Base_t);

                for(size_t i = 0; i < Universe_->size(); ++i)
                {
                    const auto & it = (*Universe_)[i];

                    if(this->Elems_.count(i) > 0)
                        (*newuniverse) << transformer(it);
                    else
                        (*newuniverse) << it;
                }

                return My_t(newuniverse, this->Elems_);
            }

            My_t Partition(SelectorFunc selector) const
            {
                std::set<size_t> newelems;
                for(const auto & idx : this->Elems_)
                {
                    const auto & el = (*Universe_)[idx];
                    if(selector(el))
                        newelems.insert(idx);
                }

                return My_t(Universe_, newelems);
            }

            ///@{

            const_iterator begin() const {
                return const_iterator(Universe_->MakeIterator(this->Elems_.begin()));
            }

            const_iterator end() const {
                return const_iterator(Universe_->MakeIterator(this->Elems_.end()));
            }

            ///@}
        };

    }
}//End namespaces

#endif /* BPMODULE_GUARD_MATHSET_HPP_ */

<|endoftext|>


<commit_before>#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include <omp.h>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "alignment.h"
#include "data_array.h"
#include "features/count_source_target.h"
#include "features/feature.h"
#include "features/is_source_singleton.h"
#include "features/is_source_target_singleton.h"
#include "features/max_lex_source_given_target.h"
#include "features/max_lex_target_given_source.h"
#include "features/sample_source_count.h"
#include "features/target_given_source_coherent.h"
#include "grammar.h"
#include "grammar_extractor.h"
#include "precomputation.h"
#include "rule.h"
#include "scorer.h"
#include "suffix_array.h"
#include "time_util.h"
#include "translation_table.h"

namespace fs = boost::filesystem;
namespace po = boost::program_options;
using namespace std;
using namespace extractor;
using namespace features;

int main(int argc, char** argv) {
  int num_threads_default = 1;
  #pragma omp parallel
  num_threads_default = omp_get_num_threads();

  po::options_description desc("Command line options");
  desc.add_options()
    ("help,h", "Show available options")
    ("source,f", po::value<string>(), "Source language corpus")
    ("target,e", po::value<string>(), "Target language corpus")
    ("bitext,b", po::value<string>(), "Parallel text (source ||| target)")
    ("alignment,a", po::value<string>()->required(), "Bitext word alignment")
    ("grammars,g", po::value<string>()->required(), "Grammars output path")
    ("threads,t", po::value<int>()->default_value(num_threads_default),
        "Number of parallel extractors")
    ("frequent", po::value<int>()->default_value(100),
        "Number of precomputed frequent patterns")
    ("super_frequent", po::value<int>()->default_value(10),
        "Number of precomputed super frequent patterns")
    ("max_rule_span", po::value<int>()->default_value(15),
        "Maximum rule span")
    ("max_rule_symbols", po::value<int>()->default_value(5),
        "Maximum number of symbols (terminals + nontermals) in a rule")
    ("min_gap_size", po::value<int>()->default_value(1), "Minimum gap size")
    ("max_phrase_len", po::value<int>()->default_value(4),
        "Maximum frequent phrase length")
    ("max_nonterminals", po::value<int>()->default_value(2),
        "Maximum number of nonterminals in a rule")
    ("min_frequency", po::value<int>()->default_value(1000),
        "Minimum number of occurences for a pharse to be considered frequent")
    ("max_samples", po::value<int>()->default_value(300),
        "Maximum number of samples")
    ("tight_phrases", po::value<bool>()->default_value(true),
        "False if phrases may be loose (better, but slower)");

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

  // Check for help argument before notify, so we don't need to pass in the
  // required parameters.
  if (vm.count("help")) {
    cout << desc << endl;
    return 0;
  }

  po::notify(vm);

  if (!((vm.count("source") && vm.count("target")) || vm.count("bitext"))) {
    cerr << "A paralel corpus is required. "
         << "Use -f (source) with -e (target) or -b (bitext)."
         << endl;
    return 1;
  }

  Clock::time_point preprocess_start_time = Clock::now();
  cerr << "Reading source and target data..." << endl;
  Clock::time_point start_time = Clock::now();
  shared_ptr<DataArray> source_data_array, target_data_array;
  if (vm.count("bitext")) {
    source_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), SOURCE);
    target_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), TARGET);
  } else {
    source_data_array = make_shared<DataArray>(vm["source"].as<string>());
    target_data_array = make_shared<DataArray>(vm["target"].as<string>());
  }
  Clock::time_point stop_time = Clock::now();
  cerr << "Reading data took " << GetDuration(start_time, stop_time)
       << " seconds" << endl;

  cerr << "Creating source suffix array..." << endl;
  start_time = Clock::now();
  shared_ptr<SuffixArray> source_suffix_array =
      make_shared<SuffixArray>(source_data_array);
  stop_time = Clock::now();
  cerr << "Creating suffix array took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Reading alignment..." << endl;
  start_time = Clock::now();
  shared_ptr<Alignment> alignment =
      make_shared<Alignment>(vm["alignment"].as<string>());
  stop_time = Clock::now();
  cerr << "Reading alignment took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Precomputing collocations..." << endl;
  start_time = Clock::now();
  shared_ptr<Precomputation> precomputation = make_shared<Precomputation>(
      source_suffix_array,
      vm["frequent"].as<int>(),
      vm["super_frequent"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["min_gap_size"].as<int>(),
      vm["max_phrase_len"].as<int>(),
      vm["min_frequency"].as<int>());
  stop_time = Clock::now();
  cerr << "Precomputing collocations took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Precomputing conditional probabilities..." << endl;
  start_time = Clock::now();
  shared_ptr<TranslationTable> table = make_shared<TranslationTable>(
      source_data_array, target_data_array, alignment);
  stop_time = Clock::now();
  cerr << "Precomputing conditional probabilities took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  Clock::time_point preprocess_stop_time = Clock::now();
  cerr << "Overall preprocessing step took "
       << GetDuration(preprocess_start_time, preprocess_stop_time)
       << " seconds" << endl;

  Clock::time_point extraction_start_time = Clock::now();
  vector<shared_ptr<Feature> > features = {
      make_shared<TargetGivenSourceCoherent>(),
      make_shared<SampleSourceCount>(),
      make_shared<CountSourceTarget>(),
      make_shared<MaxLexSourceGivenTarget>(table),
      make_shared<MaxLexTargetGivenSource>(table),
      make_shared<IsSourceSingleton>(),
      make_shared<IsSourceTargetSingleton>()
  };
  shared_ptr<Scorer> scorer = make_shared<Scorer>(features);

  GrammarExtractor extractor(
      source_suffix_array,
      target_data_array,
      alignment,
      precomputation,
      scorer,
      vm["min_gap_size"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_nonterminals"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["max_samples"].as<int>(),
      vm["tight_phrases"].as<bool>());

  // Release extra memory used by the initial precomputation.
  precomputation.reset();

  fs::path grammar_path = vm["grammars"].as<string>();
  if (!fs::is_directory(grammar_path)) {
    fs::create_directory(grammar_path);
  }

  string sentence;
  vector<string> sentences;
  while (getline(cin, sentence)) {
    sentences.push_back(sentence);
  }

  #pragma omp parallel for schedule(dynamic) \
      num_threads(vm["threads"].as<int>()) ordered
  for (size_t i = 0; i < sentences.size(); ++i) {
    string delimiter = "|||";
    string suffix = "";
    int position = sentences[i].find(delimiter);
    if (position != sentences[i].npos) {
      suffix = sentences[i].substr(position);
      sentences[i] = sentences[i].substr(0, position);
    }

    Grammar grammar = extractor.GetGrammar(sentences[i]);
    string file_name = "grammar." + to_string(i);
    fs::path grammar_file = grammar_path / file_name;
    ofstream output(grammar_file.c_str());
    output << grammar;

    #pragma omp critical (stdout_write)
    {
      cout << "<seg grammar=\"" << grammar_file << "\" id=\"" << i << "\"> "
           << sentences[i] << " </seg> " << suffix << endl;
    }
  }
  Clock::time_point extraction_stop_time = Clock::now();
  cerr << "Overall extraction step took "
       << GetDuration(extraction_start_time, extraction_stop_time)
       << " seconds" << endl;

  return 0;
}
<commit_msg>Fixed stdout output order.<commit_after>#include <chrono>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>

#include <omp.h>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <boost/program_options/variables_map.hpp>

#include "alignment.h"
#include "data_array.h"
#include "features/count_source_target.h"
#include "features/feature.h"
#include "features/is_source_singleton.h"
#include "features/is_source_target_singleton.h"
#include "features/max_lex_source_given_target.h"
#include "features/max_lex_target_given_source.h"
#include "features/sample_source_count.h"
#include "features/target_given_source_coherent.h"
#include "grammar.h"
#include "grammar_extractor.h"
#include "precomputation.h"
#include "rule.h"
#include "scorer.h"
#include "suffix_array.h"
#include "time_util.h"
#include "translation_table.h"

namespace fs = boost::filesystem;
namespace po = boost::program_options;
using namespace std;
using namespace extractor;
using namespace features;

fs::path GetGrammarFilePath(const fs::path& grammar_path, int file_number) {
  string file_name = "grammar." + to_string(file_number);
  return grammar_path / file_name;
}

int main(int argc, char** argv) {
  int num_threads_default = 1;
  #pragma omp parallel
  num_threads_default = omp_get_num_threads();

  po::options_description desc("Command line options");
  desc.add_options()
    ("help,h", "Show available options")
    ("source,f", po::value<string>(), "Source language corpus")
    ("target,e", po::value<string>(), "Target language corpus")
    ("bitext,b", po::value<string>(), "Parallel text (source ||| target)")
    ("alignment,a", po::value<string>()->required(), "Bitext word alignment")
    ("grammars,g", po::value<string>()->required(), "Grammars output path")
    ("threads,t", po::value<int>()->default_value(num_threads_default),
        "Number of parallel extractors")
    ("frequent", po::value<int>()->default_value(100),
        "Number of precomputed frequent patterns")
    ("super_frequent", po::value<int>()->default_value(10),
        "Number of precomputed super frequent patterns")
    ("max_rule_span", po::value<int>()->default_value(15),
        "Maximum rule span")
    ("max_rule_symbols", po::value<int>()->default_value(5),
        "Maximum number of symbols (terminals + nontermals) in a rule")
    ("min_gap_size", po::value<int>()->default_value(1), "Minimum gap size")
    ("max_phrase_len", po::value<int>()->default_value(4),
        "Maximum frequent phrase length")
    ("max_nonterminals", po::value<int>()->default_value(2),
        "Maximum number of nonterminals in a rule")
    ("min_frequency", po::value<int>()->default_value(1000),
        "Minimum number of occurences for a pharse to be considered frequent")
    ("max_samples", po::value<int>()->default_value(300),
        "Maximum number of samples")
    ("tight_phrases", po::value<bool>()->default_value(true),
        "False if phrases may be loose (better, but slower)");

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

  // Check for help argument before notify, so we don't need to pass in the
  // required parameters.
  if (vm.count("help")) {
    cout << desc << endl;
    return 0;
  }

  po::notify(vm);

  if (!((vm.count("source") && vm.count("target")) || vm.count("bitext"))) {
    cerr << "A paralel corpus is required. "
         << "Use -f (source) with -e (target) or -b (bitext)."
         << endl;
    return 1;
  }

  Clock::time_point preprocess_start_time = Clock::now();
  cerr << "Reading source and target data..." << endl;
  Clock::time_point start_time = Clock::now();
  shared_ptr<DataArray> source_data_array, target_data_array;
  if (vm.count("bitext")) {
    source_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), SOURCE);
    target_data_array = make_shared<DataArray>(
        vm["bitext"].as<string>(), TARGET);
  } else {
    source_data_array = make_shared<DataArray>(vm["source"].as<string>());
    target_data_array = make_shared<DataArray>(vm["target"].as<string>());
  }
  Clock::time_point stop_time = Clock::now();
  cerr << "Reading data took " << GetDuration(start_time, stop_time)
       << " seconds" << endl;

  cerr << "Creating source suffix array..." << endl;
  start_time = Clock::now();
  shared_ptr<SuffixArray> source_suffix_array =
      make_shared<SuffixArray>(source_data_array);
  stop_time = Clock::now();
  cerr << "Creating suffix array took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Reading alignment..." << endl;
  start_time = Clock::now();
  shared_ptr<Alignment> alignment =
      make_shared<Alignment>(vm["alignment"].as<string>());
  stop_time = Clock::now();
  cerr << "Reading alignment took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Precomputing collocations..." << endl;
  start_time = Clock::now();
  shared_ptr<Precomputation> precomputation = make_shared<Precomputation>(
      source_suffix_array,
      vm["frequent"].as<int>(),
      vm["super_frequent"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["min_gap_size"].as<int>(),
      vm["max_phrase_len"].as<int>(),
      vm["min_frequency"].as<int>());
  stop_time = Clock::now();
  cerr << "Precomputing collocations took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  cerr << "Precomputing conditional probabilities..." << endl;
  start_time = Clock::now();
  shared_ptr<TranslationTable> table = make_shared<TranslationTable>(
      source_data_array, target_data_array, alignment);
  stop_time = Clock::now();
  cerr << "Precomputing conditional probabilities took "
       << GetDuration(start_time, stop_time) << " seconds" << endl;

  Clock::time_point preprocess_stop_time = Clock::now();
  cerr << "Overall preprocessing step took "
       << GetDuration(preprocess_start_time, preprocess_stop_time)
       << " seconds" << endl;

  Clock::time_point extraction_start_time = Clock::now();
  vector<shared_ptr<Feature> > features = {
      make_shared<TargetGivenSourceCoherent>(),
      make_shared<SampleSourceCount>(),
      make_shared<CountSourceTarget>(),
      make_shared<MaxLexSourceGivenTarget>(table),
      make_shared<MaxLexTargetGivenSource>(table),
      make_shared<IsSourceSingleton>(),
      make_shared<IsSourceTargetSingleton>()
  };
  shared_ptr<Scorer> scorer = make_shared<Scorer>(features);

  GrammarExtractor extractor(
      source_suffix_array,
      target_data_array,
      alignment,
      precomputation,
      scorer,
      vm["min_gap_size"].as<int>(),
      vm["max_rule_span"].as<int>(),
      vm["max_nonterminals"].as<int>(),
      vm["max_rule_symbols"].as<int>(),
      vm["max_samples"].as<int>(),
      vm["tight_phrases"].as<bool>());

  // Release extra memory used by the initial precomputation.
  precomputation.reset();

  fs::path grammar_path = vm["grammars"].as<string>();
  if (!fs::is_directory(grammar_path)) {
    fs::create_directory(grammar_path);
  }

  string sentence;
  vector<string> sentences, suffixes;
  while (getline(cin, sentence)) {
    sentences.push_back(sentence);
  }

  #pragma omp parallel for schedule(dynamic) \
      num_threads(vm["threads"].as<int>())
  for (size_t i = 0; i < sentences.size(); ++i) {
    string delimiter = "|||", suffix;
    int position = sentences[i].find(delimiter);
    if (position != sentences[i].npos) {
      suffix = sentences[i].substr(position);
      sentences[i] = sentences[i].substr(0, position);
    }
    suffixes.push_back(suffix);

    Grammar grammar = extractor.GetGrammar(sentences[i]);
    ofstream output(GetGrammarFilePath(grammar_path, i).c_str());
    output << grammar;
  }

  for (size_t i = 0; i < sentences.size(); ++i) {
    cout << "<seg grammar=\"" << GetGrammarFilePath(grammar_path, i) << "\" id=\""
         << i << "\"> " << sentences[i] << " </seg> " << suffixes[i] << endl;
  }

  Clock::time_point extraction_stop_time = Clock::now();
  cerr << "Overall extraction step took "
       << GetDuration(extraction_start_time, extraction_stop_time)
       << " seconds" << endl;

  return 0;
}
<|endoftext|>


<commit_before>#include "ase.hpp"

#include <stdint.h>
#include <fstream>

#if defined(_MSC_VER)

#include <intrin.h>
#define SWAP32(x) _byteswap_ulong(x)
#define SWAP16(x) _byteswap_ushort(x)

#elif defined(__GNUC__) || defined(__clang__)

#define SWAP32(x) __builtin_bswap32(x)
#define SWAP16(x) __builtin_bswap16(x)
#else

inline uint16_t SWAP16(uint16_t x)
{
	return (
		((x & 0x00FF) << 8) |
		((x & 0xFF00) >> 8)
		);
}

inline uint32_t SWAP32(uint32_t x)
{
	return(
		((x & 0x000000FF) << 24) |
		((x & 0x0000FF00) << 8) |
		((x & 0x00FF0000) >> 8) |
		((x & 0xFF000000) >> 24)
		);
}

#endif

namespace ase
{
enum BlockClass : uint16_t
{
	ColorEntry = 0x0001,
	GroupBegin = 0xC001,
	GroupEnd = 0xC002
};

enum ColorModel : uint32_t
{
	// Big Endian
	CMYK = 'CMYK',
	RGB = 'RGB ',
	LAB = 'LAB ',
	GRAY = 'Gray'
};

enum ColorCategory : uint16_t
{
	Global = 0,
	Spot = 1,
	Normal = 2
};

bool LoadFromFile(
	ColorCallback& Callback,
	const char* FileName
)
{
	std::ifstream SwatchFile;

	SwatchFile.open(
		FileName,
		std::ios::binary
	);

	return LoadFromStream(Callback, SwatchFile);
}

bool LoadFromStream(
	ColorCallback& Callback,
	std::istream &Stream
)
{
	if( !Stream )
	{
		return false;
	}

	uint32_t Magic;
	Stream.read(
		reinterpret_cast<char*>(&Magic),
		sizeof(uint32_t)
	);

	Magic = SWAP32(Magic);

	if( Magic != 'ASEF' )
	{
		return false;
	}

	uint16_t Version[2];
	uint32_t BlockCount;

	Stream.read(
		reinterpret_cast<char*>(&Version[0]),
		sizeof(uint16_t)
	);
	Stream.read(
		reinterpret_cast<char*>(&Version[1]),
		sizeof(uint16_t)
	);
	Stream.read(
		reinterpret_cast<char*>(&BlockCount),
		sizeof(uint32_t)
	);

	Version[0] = SWAP16(Version[0]);
	Version[1] = SWAP16(Version[1]);
	BlockCount = SWAP32(BlockCount);

	uint16_t CurBlockClass;
	uint32_t CurBlockSize;
	// Process stream
	while( BlockCount-- )
	{
		Stream.read(
			reinterpret_cast<char*>(&CurBlockClass),
			sizeof(uint16_t)
		);
		CurBlockClass = SWAP16(CurBlockClass);

		switch( CurBlockClass )
		{
		case BlockClass::ColorEntry:
		case BlockClass::GroupBegin:
		{
			Stream.read(
				reinterpret_cast<char*>(&CurBlockSize),
				sizeof(uint32_t)
			);
			CurBlockSize = SWAP32(CurBlockSize);

			std::u16string EntryName;
			uint16_t EntryNameLength;

			Stream.read(
				reinterpret_cast<char*>(&EntryNameLength),
				sizeof(uint16_t)
			);
			EntryNameLength = SWAP16(EntryNameLength);

			EntryName.clear();
			EntryName.resize(EntryNameLength);

			Stream.read(
				reinterpret_cast<char*>(&EntryName[0]),
				EntryNameLength * 2
			);

			// Endian swap each character
			for( size_t i = 0; i < EntryNameLength; i++ )
			{
				EntryName[i] = SWAP16(EntryName[i]);
			}

			if( CurBlockClass == BlockClass::GroupBegin )
			{
				Callback.GroupBegin(
					EntryName
				);
			}
			else if( CurBlockClass == BlockClass::ColorEntry )
			{
				uint32_t ColorModel;

				Stream.read(
					reinterpret_cast<char*>(&ColorModel),
					sizeof(uint32_t)
				);
				ColorModel = SWAP32(ColorModel);

				switch( ColorModel )
				{
				case ColorModel::CMYK:
				{
					ColorType::CMYK CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::CMYK)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					*reinterpret_cast<uint32_t*>(&CurColor[3]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[3]));
					Callback.ColorCMYK(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::RGB:
				{
					ColorType::RGB CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::RGB)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					Callback.ColorRGB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::LAB:
				{
					ColorType::LAB CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::LAB)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					Callback.ColorLAB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::GRAY:
				{
					ColorType::Gray CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::CMYK)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					Callback.ColorGray(
						EntryName,
						CurColor
					);
					break;
				}
				}

				uint16_t ColorCategory;

				Stream.read(
					reinterpret_cast<char*>(&ColorCategory),
					sizeof(uint16_t)
				);
				ColorCategory = SWAP16(ColorCategory);
			}

			break;
		}
		case BlockClass::GroupEnd:
		{
			Callback.GroupEnd();
			break;
		}
		}
	}

	return true;
}

template< typename T >
inline T ReadType(const void* &Pointer)
{
	const T *Temp = static_cast<const T*>(Pointer);
	Pointer = static_cast<const T*>(Pointer) + static_cast<ptrdiff_t>(1);
	return *Temp;
}

template<>
inline uint32_t ReadType<uint32_t>(const void* &Pointer)
{
	const uint32_t *Temp = static_cast<const uint32_t*>(Pointer);
	Pointer = static_cast<const uint32_t*>(Pointer) + static_cast<ptrdiff_t>(1);

	return SWAP32(*Temp);
}

template<>
inline uint16_t ReadType<uint16_t>(const void* &Pointer)
{
	const uint16_t *Temp = static_cast<const uint16_t*>(Pointer);
	Pointer = static_cast<const uint16_t*>(Pointer) + static_cast<ptrdiff_t>(1);

	return SWAP16(*Temp);
}

template<>
inline float ReadType<float>(const void* &Pointer)
{
	uint32_t Temp = SWAP32(*static_cast<const uint32_t*>(Pointer));
	Pointer = static_cast<const float*>(Pointer) + static_cast<ptrdiff_t>(1);
	return *reinterpret_cast<float*>(&Temp);
}

inline void Read(const void* &Pointer, void* Dest, size_t Count)
{
	Dest = memcpy(Dest, Pointer, Count);
	Pointer = static_cast<const uint8_t*>(Pointer) + Count;
}

bool LoadFromMemory(
	ColorCallback& Callback,
	const void* Buffer,
	size_t Size
)
{
	if( Buffer == nullptr )
	{
		return false;
	}

	const void* ReadPoint = Buffer;

	uint32_t Magic = ReadType<uint32_t>(ReadPoint);

	if( Magic != 'ASEF' )
	{
		return false;
	}

	uint16_t Version[2];
	uint32_t BlockCount;

	Version[0] = ReadType<uint16_t>(ReadPoint);
	Version[1] = ReadType<uint16_t>(ReadPoint);
	BlockCount = ReadType<uint32_t>(ReadPoint);

	uint16_t CurBlockClass;
	uint32_t CurBlockSize;
	// Process stream
	while( BlockCount-- )
	{
		CurBlockClass = ReadType<uint16_t>(ReadPoint);

		switch( CurBlockClass )
		{
		case BlockClass::ColorEntry:
		case BlockClass::GroupBegin:
		{
			CurBlockSize = ReadType<uint32_t>(ReadPoint);

			uint16_t EntryNameLength;

			EntryNameLength = ReadType<uint16_t>(ReadPoint);

			std::u16string EntryName;
			EntryName.resize(EntryNameLength);

			// Endian swap each character
			for( size_t i = 0; i < EntryNameLength; i++ )
			{
				EntryName[i] = ReadType<uint16_t>(ReadPoint);
			}

			if( CurBlockClass == BlockClass::GroupBegin )
			{
				Callback.GroupBegin(
					EntryName
				);
			}
			else if( CurBlockClass == BlockClass::ColorEntry )
			{
				uint32_t ColorModel;

				ColorModel = ReadType<uint32_t>(ReadPoint);

				switch( ColorModel )
				{
				case ColorModel::CMYK:
				{
					ColorType::CMYK CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					CurColor[3] = ReadType<float>(ReadPoint);
					Callback.ColorCMYK(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::RGB:
				{
					ColorType::RGB CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					Callback.ColorRGB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::LAB:
				{
					ColorType::LAB CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					Callback.ColorLAB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::GRAY:
				{
					ColorType::Gray CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					Callback.ColorGray(
						EntryName,
						CurColor
					);
					break;
				}
				}

				uint16_t ColorCategory;
				ColorCategory = ReadType<uint16_t>(ReadPoint);
			}

			break;
		}
		case BlockClass::GroupEnd:
		{
			Callback.GroupEnd();
			break;
		}
		}
	}

	return true;
}
}<commit_msg>Fix Gray loading CMYK size<commit_after>#include "ase.hpp"

#include <stdint.h>
#include <fstream>

#if defined(_MSC_VER)

#include <intrin.h>
#define SWAP32(x) _byteswap_ulong(x)
#define SWAP16(x) _byteswap_ushort(x)

#elif defined(__GNUC__) || defined(__clang__)

#define SWAP32(x) __builtin_bswap32(x)
#define SWAP16(x) __builtin_bswap16(x)
#else

inline uint16_t SWAP16(uint16_t x)
{
	return (
		((x & 0x00FF) << 8) |
		((x & 0xFF00) >> 8)
		);
}

inline uint32_t SWAP32(uint32_t x)
{
	return(
		((x & 0x000000FF) << 24) |
		((x & 0x0000FF00) << 8) |
		((x & 0x00FF0000) >> 8) |
		((x & 0xFF000000) >> 24)
		);
}

#endif

namespace ase
{
enum BlockClass : uint16_t
{
	ColorEntry = 0x0001,
	GroupBegin = 0xC001,
	GroupEnd = 0xC002
};

enum ColorModel : uint32_t
{
	// Big Endian
	CMYK = 'CMYK',
	RGB = 'RGB ',
	LAB = 'LAB ',
	GRAY = 'Gray'
};

enum ColorCategory : uint16_t
{
	Global = 0,
	Spot = 1,
	Normal = 2
};

bool LoadFromFile(
	ColorCallback& Callback,
	const char* FileName
)
{
	std::ifstream SwatchFile;

	SwatchFile.open(
		FileName,
		std::ios::binary
	);

	return LoadFromStream(Callback, SwatchFile);
}

bool LoadFromStream(
	ColorCallback& Callback,
	std::istream &Stream
)
{
	if( !Stream )
	{
		return false;
	}

	uint32_t Magic;
	Stream.read(
		reinterpret_cast<char*>(&Magic),
		sizeof(uint32_t)
	);

	Magic = SWAP32(Magic);

	if( Magic != 'ASEF' )
	{
		return false;
	}

	uint16_t Version[2];
	uint32_t BlockCount;

	Stream.read(
		reinterpret_cast<char*>(&Version[0]),
		sizeof(uint16_t)
	);
	Stream.read(
		reinterpret_cast<char*>(&Version[1]),
		sizeof(uint16_t)
	);
	Stream.read(
		reinterpret_cast<char*>(&BlockCount),
		sizeof(uint32_t)
	);

	Version[0] = SWAP16(Version[0]);
	Version[1] = SWAP16(Version[1]);
	BlockCount = SWAP32(BlockCount);

	uint16_t CurBlockClass;
	uint32_t CurBlockSize;
	// Process stream
	while( BlockCount-- )
	{
		Stream.read(
			reinterpret_cast<char*>(&CurBlockClass),
			sizeof(uint16_t)
		);
		CurBlockClass = SWAP16(CurBlockClass);

		switch( CurBlockClass )
		{
		case BlockClass::ColorEntry:
		case BlockClass::GroupBegin:
		{
			Stream.read(
				reinterpret_cast<char*>(&CurBlockSize),
				sizeof(uint32_t)
			);
			CurBlockSize = SWAP32(CurBlockSize);

			std::u16string EntryName;
			uint16_t EntryNameLength;

			Stream.read(
				reinterpret_cast<char*>(&EntryNameLength),
				sizeof(uint16_t)
			);
			EntryNameLength = SWAP16(EntryNameLength);

			EntryName.clear();
			EntryName.resize(EntryNameLength);

			Stream.read(
				reinterpret_cast<char*>(&EntryName[0]),
				EntryNameLength * 2
			);

			// Endian swap each character
			for( size_t i = 0; i < EntryNameLength; i++ )
			{
				EntryName[i] = SWAP16(EntryName[i]);
			}

			if( CurBlockClass == BlockClass::GroupBegin )
			{
				Callback.GroupBegin(
					EntryName
				);
			}
			else if( CurBlockClass == BlockClass::ColorEntry )
			{
				uint32_t ColorModel;

				Stream.read(
					reinterpret_cast<char*>(&ColorModel),
					sizeof(uint32_t)
				);
				ColorModel = SWAP32(ColorModel);

				switch( ColorModel )
				{
				case ColorModel::CMYK:
				{
					ColorType::CMYK CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::CMYK)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					*reinterpret_cast<uint32_t*>(&CurColor[3]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[3]));
					Callback.ColorCMYK(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::RGB:
				{
					ColorType::RGB CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::RGB)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					Callback.ColorRGB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::LAB:
				{
					ColorType::LAB CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::LAB)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					*reinterpret_cast<uint32_t*>(&CurColor[1]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[1]));
					*reinterpret_cast<uint32_t*>(&CurColor[2]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[2]));
					Callback.ColorLAB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::GRAY:
				{
					ColorType::Gray CurColor;
					Stream.read(
						reinterpret_cast<char*>(&CurColor),
						sizeof(ColorType::Gray)
					);
					*reinterpret_cast<uint32_t*>(&CurColor[0]) = SWAP32(*reinterpret_cast<uint32_t*>(&CurColor[0]));
					Callback.ColorGray(
						EntryName,
						CurColor
					);
					break;
				}
				}

				uint16_t ColorCategory;

				Stream.read(
					reinterpret_cast<char*>(&ColorCategory),
					sizeof(uint16_t)
				);
				ColorCategory = SWAP16(ColorCategory);
			}

			break;
		}
		case BlockClass::GroupEnd:
		{
			Callback.GroupEnd();
			break;
		}
		}
	}

	return true;
}

template< typename T >
inline T ReadType(const void* &Pointer)
{
	const T *Temp = static_cast<const T*>(Pointer);
	Pointer = static_cast<const T*>(Pointer) + static_cast<ptrdiff_t>(1);
	return *Temp;
}

template<>
inline uint32_t ReadType<uint32_t>(const void* &Pointer)
{
	const uint32_t *Temp = static_cast<const uint32_t*>(Pointer);
	Pointer = static_cast<const uint32_t*>(Pointer) + static_cast<ptrdiff_t>(1);

	return SWAP32(*Temp);
}

template<>
inline uint16_t ReadType<uint16_t>(const void* &Pointer)
{
	const uint16_t *Temp = static_cast<const uint16_t*>(Pointer);
	Pointer = static_cast<const uint16_t*>(Pointer) + static_cast<ptrdiff_t>(1);

	return SWAP16(*Temp);
}

template<>
inline float ReadType<float>(const void* &Pointer)
{
	uint32_t Temp = SWAP32(*static_cast<const uint32_t*>(Pointer));
	Pointer = static_cast<const float*>(Pointer) + static_cast<ptrdiff_t>(1);
	return *reinterpret_cast<float*>(&Temp);
}

inline void Read(const void* &Pointer, void* Dest, size_t Count)
{
	Dest = memcpy(Dest, Pointer, Count);
	Pointer = static_cast<const uint8_t*>(Pointer) + Count;
}

bool LoadFromMemory(
	ColorCallback& Callback,
	const void* Buffer,
	size_t Size
)
{
	if( Buffer == nullptr )
	{
		return false;
	}

	const void* ReadPoint = Buffer;

	uint32_t Magic = ReadType<uint32_t>(ReadPoint);

	if( Magic != 'ASEF' )
	{
		return false;
	}

	uint16_t Version[2];
	uint32_t BlockCount;

	Version[0] = ReadType<uint16_t>(ReadPoint);
	Version[1] = ReadType<uint16_t>(ReadPoint);
	BlockCount = ReadType<uint32_t>(ReadPoint);

	uint16_t CurBlockClass;
	uint32_t CurBlockSize;
	// Process stream
	while( BlockCount-- )
	{
		CurBlockClass = ReadType<uint16_t>(ReadPoint);

		switch( CurBlockClass )
		{
		case BlockClass::ColorEntry:
		case BlockClass::GroupBegin:
		{
			CurBlockSize = ReadType<uint32_t>(ReadPoint);

			uint16_t EntryNameLength;

			EntryNameLength = ReadType<uint16_t>(ReadPoint);

			std::u16string EntryName;
			EntryName.resize(EntryNameLength);

			// Endian swap each character
			for( size_t i = 0; i < EntryNameLength; i++ )
			{
				EntryName[i] = ReadType<uint16_t>(ReadPoint);
			}

			if( CurBlockClass == BlockClass::GroupBegin )
			{
				Callback.GroupBegin(
					EntryName
				);
			}
			else if( CurBlockClass == BlockClass::ColorEntry )
			{
				uint32_t ColorModel;

				ColorModel = ReadType<uint32_t>(ReadPoint);

				switch( ColorModel )
				{
				case ColorModel::CMYK:
				{
					ColorType::CMYK CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					CurColor[3] = ReadType<float>(ReadPoint);
					Callback.ColorCMYK(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::RGB:
				{
					ColorType::RGB CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					Callback.ColorRGB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::LAB:
				{
					ColorType::LAB CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					CurColor[1] = ReadType<float>(ReadPoint);
					CurColor[2] = ReadType<float>(ReadPoint);
					Callback.ColorLAB(
						EntryName,
						CurColor
					);
					break;
				}
				case ColorModel::GRAY:
				{
					ColorType::Gray CurColor;
					CurColor[0] = ReadType<float>(ReadPoint);
					Callback.ColorGray(
						EntryName,
						CurColor
					);
					break;
				}
				}

				uint16_t ColorCategory;
				ColorCategory = ReadType<uint16_t>(ReadPoint);
			}

			break;
		}
		case BlockClass::GroupEnd:
		{
			Callback.GroupEnd();
			break;
		}
		}
	}

	return true;
}
}<|endoftext|>