text:
#include <fstream>
#include <sstream>
#include <vector>
#include <string>

#include <Eigen/Geometry>
#include <ConciseArgs>

struct Scan {
  int64_t mTimestamp;
  double mThetaInit;
  double mThetaStep;
  std::vector<double> mRanges;
};

struct Pose {
  int64_t mTimestamp;
  Eigen::Isometry3d mTransform;
  Eigen::Vector3d mTrans;
  Eigen::Quaterniond mQuat;
};

std::vector<Pose> readPoses(const std::string& iFileName) {
  std::ifstream ifs(iFileName);
  std::vector<Pose> poses;
  std::string line;
  while (std::getline(ifs,line)) {
    std::istringstream iss(line);
    Pose pose;
    auto matx = Eigen::Isometry3d::Identity();
    iss >> pose.mTimestamp >>
      matx(0,0) >> matx(0,1) >> matx(0,2) >> matx(0,3) >>
      matx(1,0) >> matx(1,1) >> matx(1,2) >> matx(1,3) >>
      matx(2,0) >> matx(2,1) >> matx(2,2) >> matx(2,3);
    pose.mTransform = matx;
    pose.mTrans = matx.translation();
    pose.mQuat = matx.rotation();
    poses.push_back(pose);
  }
  ifs.close();
  return poses;
}

void writePoints(const std::vector<Eigen::Vector3d>& iPoints,
                 const std::string& iFileName) {
  std::ofstream ofs(iFileName);
  for (auto p : iPoints) {
    ofs << p[0] << " " << p[1] << " " << p[2] << std::endl;
  }
  ofs.close();
}

Eigen::Vector3d applyInterpolated(const Eigen::Vector3d& iPoint,
                                  const Eigen::Isometry3d& iPose1,
                                  const Eigen::Isometry3d& iPose2,
                                  const Eigen::Isometry3d& iScanPose,
                                  const double iAlpha) {
  Eigen::Isometry3d scanToWorld1 = iPose1*iScanPose;
  Eigen::Isometry3d scanToWorld2 = iPose2*iScanPose;
  Eigen::Vector3d pos1 = scanToWorld1.translation();
  Eigen::Vector3d pos2 = scanToWorld2.translation();
  Eigen::Quaterniond q1(scanToWorld1.rotation());
  Eigen::Quaterniond q2(scanToWorld2.rotation());
  Eigen::Vector3d pos = pos1*(1-iAlpha) + pos2*iAlpha;
  Eigen::Quaterniond q = q1.slerp(iAlpha, q2);
  return q*iPoint + pos;
}

int main(const int iArgc, const char** iArgv) {
  std::string rootDir;
  ConciseArgs opt(iArgc, (char**)iArgv);
  opt.add(rootDir, "r", "root_dir", "input root directory");
  opt.parse();

  std::string fileName;

  // read lidar scans
  fileName = rootDir + "/scans.txt";
  std::ifstream ifs(fileName);
  std::string line;
  std::vector<Scan> scans;
  int totalPoints = 0;
  while (std::getline(ifs,line)) {
    std::istringstream iss(line);
    Scan scan;
    iss >> scan.mTimestamp >> scan.mThetaInit >> scan.mThetaStep;
    double val;
    while (iss >> val) {
      scan.mRanges.push_back(val);
    }
    scans.push_back(scan);
    totalPoints += scan.mRanges.size();
  }
  ifs.close();

  // read vo camera poses
  std::vector<Pose> voPoses = readPoses(rootDir + "/fovis_poses.txt");
  std::cout << "read " << voPoses.size() << " vo camera poses" << std::endl;

  // read original camera poses
  std::vector<Pose> camPoses = readPoses(rootDir + "/cam_poses.txt");
  std::cout << "read " << camPoses.size() << " camera poses" << std::endl;

  // read lidar spindle poses
  std::vector<Pose> spindlePoses = readPoses(rootDir + "/spindle_poses.txt");
  std::cout << "read " << spindlePoses.size() << " spindle poses" << std::endl;

  // interpolate camera for every lidar point
  std::cout << "interpolating " << totalPoints << " points..." << std::flush;
  std::vector<Eigen::Vector3d> pointsBefore, pointsAfter;
  pointsAfter.reserve(totalPoints);
  int poseIdx = 0;
  const double kPi = acos(-1);
  const double kScanFrequency = 1.0/40;
  const double kMaxRange = 20;
  for (int i = 0; i < scans.size(); ++i) {
    auto& scan = scans[i];
    int n = scan.mRanges.size();
    double dt = kScanFrequency*(scan.mThetaStep/(2*kPi));
    int64_t time2 = scans[i].mTimestamp;
    int64_t time1 = time2 - int64_t(dt*(n-1)*1e6 + 0.5);
    for (int j = 0; j < n; ++j) {

      // check whether lidar return is valid
      double r = scan.mRanges[j];
      if (r > kMaxRange) continue;

      // find pose for this time
      int64_t t = time1 + int64_t(dt*j*1e6 + 0.5);
      double alpha = (double)j/(n-1);
      if (t < voPoses[poseIdx].mTimestamp) continue;
      while (t > voPoses[poseIdx+1].mTimestamp) {
        ++poseIdx;
        if (poseIdx >= voPoses.size()) break;
      }

      // interpolate between two camera poses
      double theta = scan.mThetaInit + j*scan.mThetaStep;
      Eigen::Vector3d p(r*cos(theta), r*sin(theta), 0);
      Eigen::Vector3d pt;
      pt = applyInterpolated
        (p, camPoses[poseIdx].mTransform, camPoses[poseIdx+1].mTransform,
         spindlePoses[i].mTransform, alpha);
      pointsBefore.push_back(pt);
      pt = applyInterpolated
        (p, voPoses[poseIdx].mTransform, voPoses[poseIdx+1].mTransform,
         spindlePoses[i].mTransform, alpha);
      pointsAfter.push_back(pt);
    }
  }
  std::cout << "done." << std::endl;

  // dump points to files
  writePoints(pointsBefore, rootDir + "/cloud_before.txt");
  writePoints(pointsAfter, rootDir + "/cloud_after.txt");

  return 1;
}

max_stars_repo_name: liangfok/oh-distro

max_issues_repo_name: liangfok/oh-distro

max_forks_repo_name: liangfok/oh-distro


text:
// Boost test program for next() and prior() utilities.

// Copyright 2003 Daniel Walker.  Use, modification, and distribution
// are subject to the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or a copy at
// http://www.boost.org/LICENSE_1_0.txt.)

// See http://www.boost.org/libs/utility for documentation.

// Revision History 13 Dec 2003 Initial Version (Daniel Walker)

// next() and prior() are replacements for operator+ and operator- for
// non-random-access iterators. The semantics of these operators are
// such that after executing j = i + n, std::distance(i, j) equals
// n. Tests are provided to ensure next() has the same
// result. Parallel tests are provided for prior(). The tests call
// next() and prior() several times. next() and prior() are very
// simple functions, though, and it would be very strange if these
// tests were to fail.

#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>

#include <list>
#include <vector>

#include <boost/next_prior.hpp>

template<class RandomAccessIterator, class ForwardIterator>
bool plus_one_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2)
{
    RandomAccessIterator i = first;
    ForwardIterator j = first2;
    while(i != last)
        i = i + 1, j = boost::next(j);
    return std::distance(first, i) == std::distance(first2, j);
}

template<class RandomAccessIterator, class ForwardIterator>
bool plus_n_test(RandomAccessIterator first, RandomAccessIterator last, ForwardIterator first2)
{
    RandomAccessIterator i = first;
    ForwardIterator j = first2;
    for(int n = 0; i != last; ++n)
        i = first + n, j = boost::next(first2, n);
    return std::distance(first, i) == std::distance(first2, j);
}

template<class RandomAccessIterator, class BidirectionalIterator>
bool minus_one_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2)
{
    RandomAccessIterator i = last;
    BidirectionalIterator j = last2;
    while(i != first)
        i = i - 1, j = boost::prior(j);
    return std::distance(i, last) == std::distance(j, last2);
}

template<class RandomAccessIterator, class BidirectionalIterator>
bool minus_n_test(RandomAccessIterator first, RandomAccessIterator last, BidirectionalIterator last2)
{
    RandomAccessIterator i = last;
    BidirectionalIterator j = last2;
    for(int n = 0; i != first; ++n)
        i = last - n, j = boost::prior(last2, n);
    return std::distance(i, last) == std::distance(j, last2);
}

template<class Iterator, class Distance>
bool minus_n_unsigned_test(Iterator first, Iterator last, Distance size)
{
    Iterator i = boost::prior(last, size);
    return i == first;
}

int test_main(int, char*[])
{
    std::vector<int> x(8);
    std::list<int> y(x.begin(), x.end());

    // Tests with iterators
    BOOST_REQUIRE(plus_one_test(x.begin(), x.end(), y.begin()));
    BOOST_REQUIRE(plus_n_test(x.begin(), x.end(), y.begin()));
    BOOST_REQUIRE(minus_one_test(x.begin(), x.end(), y.end()));
    BOOST_REQUIRE(minus_n_test(x.begin(), x.end(), y.end()));
    BOOST_REQUIRE(minus_n_unsigned_test(x.begin(), x.end(), x.size()));
    BOOST_REQUIRE(minus_n_unsigned_test(y.begin(), y.end(), y.size()));

    // Tests with integers
    BOOST_REQUIRE(boost::next(5) == 6);
    BOOST_REQUIRE(boost::next(5, 7) == 12);
    BOOST_REQUIRE(boost::prior(5) == 4);
    BOOST_REQUIRE(boost::prior(5, 7) == -2);
    BOOST_REQUIRE(boost::prior(5, 7u) == -2);

    return 0;
}

ext: cpp


text:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>

#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/common/common.h>

#include <pcl/octree/octree.h>
#include <pcl/octree/octree_search.h>
#include <pcl/filters/extract_indices.h>

#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>

typedef pcl::PointXYZRGB PointT;
namespace po = boost::program_options;

// extract sub cloud from cloud
pcl::PointCloud<PointT>::Ptr extractSubCloud(PointT min, PointT max, pcl::PointCloud<PointT>::Ptr cloud, pcl::octree::OctreePointCloudSearch<PointT> &octree)
{

    pcl::PointCloud<PointT>::Ptr sub_cloud(new pcl::PointCloud<PointT>);
    std::vector<int> pointIdxBoxSearch;
    Eigen::Vector3f min_pt(min.x, min.y, min.z);
    Eigen::Vector3f max_pt(max.x, max.y, max.z);
    octree.boxSearch(min_pt, max_pt, pointIdxBoxSearch);

    pcl::ExtractIndices<PointT> extract;
    pcl::PointIndices::Ptr inliers(new pcl::PointIndices());
    inliers->indices = pointIdxBoxSearch;
    extract.setInputCloud(cloud);
    extract.setIndices(inliers);
    extract.setNegative(false);
    extract.filter(*sub_cloud);

    return sub_cloud;
}

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

    // boost po: variables that will store parsed command line values
    std::string input_file;
    std::string output_format;
    double resolution;
    float x_dim_sub_cloud;
    float y_dim_sub_cloud;
    float z_dim_sub_cloud;

    // boost po: setup options
    po::options_description desc("Inputs and options");
    desc.add_options()("help", "List of input arguments. Default values will be used if there is no input for an argument.")                                              // clang format
        ("input", po::value<std::string>(&input_file), "Set path to input file (.ply or .pcd). Use quotation marks (--input \"/path to file\") if file path has spaces.") // clang format
        ("output", po::value<std::string>(&output_format)->default_value("ply"), "Set output file format (--output ply or --output pcd) for sub clouds [default: ply].")  // clang format
        ("res", po::value<double>(&resolution)->default_value(0.01), "Set resolution for octree box search [default: 0.01].")                                             // clang format
        ("x-dim", po::value<float>(&x_dim_sub_cloud)->default_value(1.0), "Set sub cloud dimension in x direction [default: 1.0].")                                       // clang format
        ("y-dim", po::value<float>(&y_dim_sub_cloud)->default_value(1.0), "Set sub cloud dimension in y direction [default: 1.0].")                                       // clang format
        ("z-dim", po::value<float>(&z_dim_sub_cloud)->default_value(1.0), "Set sub cloud dimension in z direction [default: 1.0].")                                       // clang format
        ;

    // boost po: parse input
    po::variables_map vm;
    po::store(po::parse_command_line(argc, argv, desc), vm);
    po::notify(vm);

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

    else if (vm.count("input") == 0)
    {
        std::cout << "\nError: No input file was set. Set an input file.\n";
        return 1;
    }

    else if (output_format != "ply" && output_format != "pcd")
    {
        std::cout << "\nError: Unexpected output file format. Allowed inputs are \"ply\" and \"pcd\".\n";
        return 1;
    }

    // input file path, name, extension
    boost::filesystem::path file_path(input_file);
    std::string file_name_no_ext = file_path.stem().string();
    std::string file_extension = file_path.extension().string();
    std::string file_name_with_ext = file_path.filename().string();

    // cloud object input cloud
    pcl::PointCloud<PointT>::Ptr cloud(new pcl::PointCloud<PointT>);

    // load input cloud
    if (file_extension == ".ply")
    {
        std::cout << "\nLoading point cloud...\n";
        pcl::io::loadPLYFile<PointT>(input_file, *cloud);
    }

    else if (file_extension == ".pcd")
    {
        std::cout << "\nLoading point cloud...\n";
        pcl::io::loadPCDFile<PointT>(input_file, *cloud);
    }

    else if (file_extension != ".ply" && file_extension != ".pcd")
    {
        std::cout << "\nError: Input is no point cloud or has unexpected file format. Allowed input formats are \"ply\" and \"pcd\".\n";
        return 1;
    }

    // create timestamp for directories where point clouds will be saved
    time_t rawtime;
    struct tm *timeinfo;
    char buffer[64];
    time(&rawtime);
    timeinfo = localtime(&rawtime);
    strftime(buffer, 64, "%Y-%m-%d-%H-%M", timeinfo); // Year, Month, Day, Hour, Minute

    // create main output dump directory
    std::string str_output_files;
    str_output_files = "../output_files";
    boost::filesystem::path output_files_path(str_output_files);

    if (boost::filesystem::is_directory(output_files_path))
    {
        std::cout << "\nOutput directory already exists. Output will be saved in \"/output_files\"\n";
    }

    else
    {
        boost::filesystem::create_directory(str_output_files);
        std::cout << "\nOutput directory was created. Output will be saved in \"/output_files\"\n";
    }

    // create save dir where sub clouds will be saved
    std::stringstream ss_dir_path_sub_cloud;
    ss_dir_path_sub_cloud << str_output_files << "/" << buffer << "_sub_clouds_" << file_name_no_ext;
    boost::filesystem::create_directory(ss_dir_path_sub_cloud.str());

    std::stringstream ss_sub_cloud_save;
    std::string str_sub_cloud_save;
    int i = 0;

    pcl::octree::OctreePointCloudSearch<PointT> octree(resolution);
    octree.setInputCloud(cloud);
    octree.addPointsFromInputCloud();
    PointT p1;
    PointT p2;
    pcl::getMinMax3D<PointT>(*cloud, p1, p2);

    float x_min_cloud = p1.x;
    float x_max_cloud = p2.x;

    float y_min_cloud = p1.y;
    float y_max_cloud = p2.y;

    float z_min_cloud = p1.z;
    float z_max_cloud = p2.z;

    // create and write some information to log file
    std::ofstream logfile("./" + ss_dir_path_sub_cloud.str() + "/" + buffer + "_" + file_name_no_ext + "_subdivide_log.csv");
    logfile << "date," << buffer << "\n";
    logfile << "cloud name," << file_name_with_ext << "\n";
    logfile << "total points cloud," << cloud->size() << "\n";
    logfile << "total size cloud x," << std::fabs(x_max_cloud - x_min_cloud) << "\n";
    logfile << "total size cloud y," << std::fabs(y_max_cloud - y_min_cloud) << "\n";
    logfile << "total size cloud z," << std::fabs(z_max_cloud - z_min_cloud) << "\n";
    logfile << "\n";
    logfile << "octree resolution," << resolution << "\n";
    logfile << "set dim x," << x_dim_sub_cloud << "\n";
    logfile << "set dim y," << y_dim_sub_cloud << "\n";
    logfile << "set dim z," << z_dim_sub_cloud << "\n";
    logfile << "\n";
    logfile << "sub cloud, n points, size x, size y, size z" << std::endl;

    // subdivide input cloud to set size sub clouds
    float x_current = x_min_cloud;

    while (x_current < x_max_cloud)
    {
        float y_current = y_min_cloud;

        while (y_current < y_max_cloud)
        {
            float z_current = z_min_cloud;

            while (z_current < z_max_cloud)
            {
                PointT min;
                PointT max;
                min.x = x_current;
                min.y = y_current;
                min.z = z_current;
                max.x = x_current + x_dim_sub_cloud;
                max.y = y_current + y_dim_sub_cloud;
                max.z = z_current + z_dim_sub_cloud;
                pcl::PointCloud<PointT>::Ptr sub_cloud = extractSubCloud(min, max, cloud, octree);

                // save sub clouds
                if (sub_cloud->size() > 0)
                {
                    // size sub clouds for logfile
                    PointT sub_p1;
                    PointT sub_p2;
                    pcl::getMinMax3D<PointT>(*sub_cloud, sub_p1, sub_p2);

                    // create save path for sub cloud
                    ss_sub_cloud_save << "./" << ss_dir_path_sub_cloud.str() << "/" << file_name_no_ext << "_sub_cloud_" << i << "." << output_format;
                    str_sub_cloud_save = ss_sub_cloud_save.str();
                    ss_sub_cloud_save.str(std::string()); // clear contents std::stringstream
                    ss_sub_cloud_save.clear();            // clear any fail and eof flags std::stringstream

                    if (output_format == "ply")
                    {
                        pcl::io::savePLYFileASCII(str_sub_cloud_save, *sub_cloud);
                    }
                    else if (output_format == "pcd")
                    {
                        pcl::io::savePCDFileASCII(str_sub_cloud_save, *sub_cloud);
                    }

                    logfile << i << "," << sub_cloud->size() << "," << std::fabs(sub_p2.x - sub_p1.x) << "," << std::fabs(sub_p2.y - sub_p1.y) << "," << std::fabs(sub_p2.z - sub_p1.z) << std::endl;
                    std::cout << "Saving sub cloud " << i << std::endl;
                    i++;
                }

                z_current += z_dim_sub_cloud;
            }

            y_current += y_dim_sub_cloud;
        }

        x_current += x_dim_sub_cloud;
    }

    logfile.close();
    std::cout << "All sub clouds were saved in /output_files." << std::endl;

    return 0;
}

max_stars_repo_name: romankraemer/cloud-subdivide

max_issues_repo_name: romankraemer/cloud-subdivide

max_forks_repo_name: romankraemer/cloud-subdivide


text:
/*
Copyright 2013-2015 Rogier van Dalen.

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

/**
Helper to test the behaviour of a range with respect to all operations.
*/

#ifndef RANGE_TEST_CHECK_EQUAL_BEHAVIOUR_HPP_INCLUDED
#define RANGE_TEST_CHECK_EQUAL_BEHAVIOUR_HPP_INCLUDED

#include <type_traits>

#include <boost/utility/enable_if.hpp>

#include "rime/core.hpp"
#include "rime/call_if.hpp"

#include "range/core.hpp"

/**
Check whether values are equal in the applicable sense.
If the reference is a constant, then value should be a constant of the same
type and same value.
If the reference is a run-time value, then value should be of the same type
and compare equal.
*/
template <class Value, class Reference>
    typename boost::enable_if <rime::is_constant <Reference>>::type
    check_equal_value (Value const & value, Reference const & reference)
{
    static_assert (rime::is_rime_constant <Value>::value,
        "Value must be a Rime constant");
    static_assert (rime::same_constant <Value, Reference>::value,
        "Value must be of same type and have the same value as Reference");
}

template <class Value, class Reference>
    typename boost::disable_if <rime::is_constant <Reference>>::type
    check_equal_value (Value const & value, Reference const & reference)
{
    static_assert (std::is_same <Value, Reference>::value,
        "value and reference must be of the same type");
    BOOST_CHECK_EQUAL (value, reference);
}

// Specialise for pairs, because BOOST_CHECK_EQUAL does not deal with those.
template <class Value1, class Value2, class Reference1, class Reference2>
    void check_equal_value (std::pair <Value1, Value2> const & value,
        std::pair <Reference1, Reference2> const & reference)
{
    static_assert (std::is_same <Value1, Reference1>::value,
        "value and reference must be of the same type");
    static_assert (std::is_same <Value2, Reference2>::value,
        "value and reference must be of the same type");
    BOOST_CHECK_EQUAL (value.first, reference.first);
    BOOST_CHECK_EQUAL (value.second, reference.second);
}

namespace detail {

// Do nothing.
namespace callable {
    struct nothing {
        template <class ... Arguments>
            void operator() (Arguments const & ...) const {}
    };
} // namespace callable

static const auto nothing = callable::nothing();

/* Helpers. */

// empty.
// HasBack is not used: empty (back, range) is provided automatically even if
// back is not a valid direction.
template <class Range, class Reference>
    void check_empty (Range const & range, Reference const & reference)
{
    static_assert (range::has <range::callable::empty (Range)>::value, "");
    static_assert (range::has <range::callable::empty (
        Range, direction::front)>::value, "");
    static_assert (range::has <range::callable::empty (
        Range, direction::back)>::value, "");
    check_equal_value (range::empty (range), range::empty (reference));
    check_equal_value (range::empty (range, range::front),
        range::empty (reference, range::front));
    check_equal_value (range::empty (range, range::back),
        range::empty (range, range::front));
}

// Check size.
template <class HasSize, class Range, class Reference>
    typename boost::enable_if <HasSize>::type
    check_size (Range const & range, Reference const & reference)
{
    static_assert (range::has <range::callable::size (
        Range, direction::front)>::value, "");
    static_assert (range::has <range::callable::size (
        Range, direction::back)>::value, "");
    check_equal_value (range::size (range, range::front),
        range::size (reference, range::front));
    check_equal_value (range::size (range, range::back),
        range::size (range, range::front));
}
template <class HasSize, class Range, class Reference>
    typename boost::disable_if <HasSize>::type
    check_size (Range const & range, Reference const & reference, void * = 0)
{
    static_assert (!range::has <range::callable::size (
        Range, direction::front)>::value, "");
}

/* Main loop. */

template <class HasSize, class HasBack, class InitialDirection>
struct check_equal_behaviour_recursive_from;

template <class HasSize, class HasBack, class Range, class Reference>
void check_equal_behaviour_recursive (bool use_chop,
    Range const & range, Reference const & reference)
{
    detail::check_empty (range, reference);
    detail::check_size <HasSize> (range, reference);

    // Stop if either range or reference is empty, to prevent further errors.
    // If they are different, this will have been detected above.
    rime::call_if (
        rime::and_ (!range::empty (range), !range::empty (reference)),
        check_equal_behaviour_recursive_from <
            HasSize, HasBack, direction::front>(),
        nothing,
        use_chop, range, reference);

    rime::call_if (rime::and_ (!range::empty (range), !range::empty (reference),
            HasBack()),
        check_equal_behaviour_recursive_from <
            HasSize, HasBack, direction::back>(),
        nothing,
        use_chop, range, reference);
}

/**
Check first and drop, or chop.
On one recursion depth, first and drop are used; on the next, chop.
(It would be possible to use both recursively at both depths but that seems
rather silly and would lead to exponential complexity in the length of the
sequence.)
*/
template <class HasSize, class HasBack, class InitialDirection>
struct check_equal_behaviour_recursive_from {
    template <class Range, class Reference>
        void operator() (bool use_chop,
            Range const & range, Reference const & reference) const
    {
        assert (!range::empty (range));

        InitialDirection d;

        check_equal_value (
            ::range::first (range, d), ::range::first (reference, d));
        auto first_and_rest = ::range::chop (range, d);
        check_equal_value (
            first_and_rest.forward_first(), ::range::first (reference, d));

        if (!use_chop) {
            check_equal_behaviour_recursive <HasSize, HasBack> (!use_chop,
                ::range::drop (range, d), ::range::drop (reference, d));
        } else {
            check_equal_behaviour_recursive <HasSize, HasBack> (!use_chop,
                first_and_rest.forward_rest(), ::range::drop (reference, d));
        }
    }
};

// Check that drop (n, range) is internally consistent.
/*template <class Direction> struct check_drop_n_runtime {
    template <class Range> void operator() (Range const & range) const {
        Direction d;
        auto current = range::view (range);
        std::size_t size = range::size (range, d);
        for (std::size_t i = 0; i != size; ++ i) {
            auto r = range::drop (range, i, d);
            static_assert (std::is_same <
                decltype (r), decltype (current)>::value, "");
            check_equal_value (range::empty (r, d),
                range::empty (current, d));
            check_equal_value (range::size (r, d),
                range::size (current, d));
            check_equal_value (range::first (r, d),
                range::first (current, d));

            current = range::drop (d, current);
        }

        assert (range::empty (current));
        auto r = range::drop (range, range::size (range, d), d);
        check_equal_value (range::empty (current), range::empty (r));
    }
};
*/

template <class HasSize, class HasBack, class Zero>
    struct check_drop_n
{
    Zero zero;
    check_drop_n() : zero() {}

    /**
    Check equality of two ranges under drop with increment.
    This means that after drop, empty, size, and first function the same as a
    reference range.
    This works with empty and non-empty ranges.
    */
    class step {
    private:
        Zero zero;
        rime::size_t <1> one;

        /* check_first_equal */
        // Not known at compile time that the range is empty.
        // (It may be known to be non-empty, in which case this happily
        // compiles.)
        template <class Range, class Direction>
            typename boost::disable_if <range::always_empty <Range, Direction>
            >::type check_first_equal (
                Range const & range1, Range const & range2,
                Direction const & direction) const
        {
            if (!range::empty (range1, direction))
                check_equal_value (range::first (range1, direction),
                    range::first (range2, direction));
        }
        // Known only at compile time that the range is empty.
        template <class Range, class Direction>
            typename boost::enable_if <range::always_empty <Range, Direction>
            >::type check_first_equal (
                Range const & range1, Range const & range2,
                Direction const & direction) const {}

        template <class Range1, class Direction, class Range2>
            void check_equal (Range1 const & range1, Range2 const & range2,
                Direction const & direction) const;
        // Not defined.

        /**
        Check that range1 and range2 are equal under empty, size, and first.
        */
        template <class Range, class Direction>
            void check_equal (Range const & range1, Range const & range2,
                Direction const & direction) const
        {
            check_equal_value (range::empty (range1, direction),
                range::empty (range2, direction));
            check_size <HasSize> (range1, range2);
            check_first_equal (range1, range2, direction);
        }

        /**
        Check that range1 and range2 are equal under \c at with increment.
        \c reference must have already had \c increment elements dropped.
        */
        struct check_at {
            template <class Range1, class Range2,
                class Increment, class Direction>
            void operator() (
                Range1 const & current, Range2 const & reference, Increment gap,
                    Direction const & direction) const
            {
                check_equal_value (range::at (current, gap, direction),
                    range::first (reference, direction));
            }
        };

    public:
        step() : zero() {}

        /**
        \param direction The direction to be checked.
        \param current The current range to be checked.
        \param reference The reference range, with \c gap elements already
            dropped.
        \param gap The amount of elements to be dropped from reference.
        */
        template <class Range1, class Range2, class Increment, class Direction>
        void operator() (Range1 const & current, Range2 const & reference,
            Increment gap, Direction const & direction) const
        {
            auto new_gap = gap + one;
            auto new_current = range::drop (current, new_gap, direction);
            auto new_reference = range::drop (reference, direction);

            // Check current position: empty, size, first, and then at.
            check_equal (new_current, new_reference, direction);

            rime::call_if (!range::empty (new_current), check_at(), nothing,
                current, reference, gap, direction);

            // Recursively check combinations of drop with increment.
            // Recurse with drop (n + 1).
            rime::call_if (!range::empty (new_current), *this, nothing,
                current, new_reference, new_gap, direction);

            // Recurse starting at this point.
            rime::call_if (!range::empty (new_current), *this, nothing,
                new_current, new_reference, zero, range::front);
            rime::call_if (rime::and_ (!range::empty (new_current), HasBack()),
                *this, nothing,
                new_current, new_reference, zero, range::back);
        }
    };

    template <class Range, class Direction> void operator() (
        Range const & range, Direction const & direction) const
    {
        rime::call_if (range::empty (range, Direction()),
            nothing, step(), range, range, zero, direction);
    }
};

} // namespace detail

template <class HasSize, class HasBack,
    class HasDropConstantN, class HasDropRuntimeN,
    class Range, class Reference>
void check_equal_behaviour (Range const & range, Reference const & reference)
{
    BOOST_MPL_ASSERT ((range::is_range <Reference>));
    BOOST_MPL_ASSERT ((range::is_range <Range>));

    // Start off with first and drop.
    detail::check_equal_behaviour_recursive <HasSize, HasBack> (
        false, range, reference);
    // Start off with chop.
    detail::check_equal_behaviour_recursive <HasSize, HasBack> (
        true, range, reference);

    rime::call_if (HasDropRuntimeN(),
        detail::check_drop_n <HasSize, HasBack, std::size_t>(), detail::nothing,
        range, range::front);
    rime::call_if (rime::and_ (HasDropRuntimeN(), HasBack()),
        detail::check_drop_n <HasSize, HasBack, std::size_t>(), detail::nothing,
        range, range::back);

    rime::call_if (HasDropConstantN(),
        detail::check_drop_n <HasSize, HasBack, rime::size_t <0>>(),
        detail::nothing,
        range, range::front);
    rime::call_if (rime::and_ (HasDropConstantN(), HasBack()),
        detail::check_drop_n <HasSize, HasBack, rime::size_t <0>>(),
        detail::nothing,
        range, range::back);
}

#endif  // RANGE_TEST_CHECK_EQUAL_BEHAVIOUR_HPP_INCLUDED

ext: hpp

max_stars_repo_name: rogiervd/range

max_issues_repo_name: rogiervd/range

max_forks_repo_name: rogiervd/range


text:
//==================================================================================================
/*!
  @file

  @copyright 2016 NumScale SAS
  @copyright 2016 J.T. Lapreste

  Distributed under the Boost Software License, Version 1.0.
  (See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
//==================================================================================================
#ifndef BOOST_SIMD_FUNCTION_COSPI_HPP_INCLUDED
#define BOOST_SIMD_FUNCTION_COSPI_HPP_INCLUDED

#if defined(DOXYGEN_ONLY)
namespace boost { namespace simd
{

 /*!

    @ingroup group-trigonometric
    Function object implementing cospi capabilities

    cosine of angle in \f$\pi\f$ multiples.

    @par Semantic:

    For every parameter of floating or integral type T

    @code
    T r = cospi(x);
    @endcode

    is similar to:

    @code
    T r = cos(Pi<T>()*x);
    @endcode

    @par Note

    As other cosine functions cospi can be used with two parameters as
    @code
    T r = cos(x, range_);
    @endcode

    see @ref cos for further details

    As it conveys a peculiar meaning,  unlike the orher cosine, cospi is defined
    for integral types and the result of cospi(n) coincides with \f$(-1)^n\f$.

    Take care that large floating entries are always integral and even !

    @see sincospi, cos, cosd

  **/
  const boost::dispatch::functor<tag::cospi_> cospi = {};
} }
#endif

#include <boost/simd/function/scalar/cospi.hpp>
#include <boost/simd/function/simd/cospi.hpp>

#endif


text:
#pragma once

#include <cstdint>
#include <string>
#include <vector>

#include <nlohmann/json.hpp>
#include <pre/json/from_json.hpp>
#include <boost/fusion/include/adapt_struct.hpp>

#include <xxhr/xxhr.hpp>

#include <gh/auth.hxx>
#include <gh/owner.hxx>
#include <gh/branches.hxx>

namespace gh::repos {

  struct permissions_t {
    bool admin;
    bool push;
    bool pull;
  };
}

BOOST_FUSION_ADAPT_STRUCT(gh::repos::permissions_t,
  admin, push, pull);

namespace gh::repos {

  struct license_t {
    std::string key;
    std::string name;
    std::optional<std::string> spdx_id;
    std::optional<std::string> url;
  };
}

BOOST_FUSION_ADAPT_STRUCT(gh::repos::license_t,
  key, name, spdx_id, url);

namespace gh::repos {

  struct organization_t {
    std::string login;
    size_t id;
    std::string avatar_url;
    std::string gravatar_id;
    std::string url;
    std::string html_url;
    std::string followers_url;
    std::string following_url;
    std::string gists_url;
    std::string starred_url;
    std::string subscriptions_url;
    std::string organizations_url;
    std::string repos_url;
    std::string events_url;
    std::string received_events_url;
    std::string type;
    bool site_admin;
  };

}

BOOST_FUSION_ADAPT_STRUCT(gh::repos::organization_t,
  login, id, avatar_url, gravatar_id, url, html_url,
  followers_url, following_url, gists_url, starred_url,
  subscriptions_url, organizations_url, repos_url, events_url,
  received_events_url, type, site_admin);

namespace gh::repos {

  /**
   * \brief repository as found in repos api.
   */
  struct basic_repository_t {
    uint64_t id;

    //! name of the form org/repo or owner/repo
    std::string full_name;
    //! name inside the organization/owner
    std::string name;
    //bool private{}; // TODO: support keyword mapping for member names in pre::json because private is a c++ keyword.
    bool fork{};
    owner_t owner;

    std::string archive_url;
    std::string assignees_url;
    std::string blobs_url;
    std::string branches_url;
    std::string collaborators_url;
    std::string comments_url;
    std::string commits_url;
    std::string compare_url;
    std::string contents_url;
    std::string contributors_url;
    std::string deployments_url;
    std::optional<std::string> description;
    std::string downloads_url;
    std::string events_url;
    std::string forks_url;
    std::string git_commits_url;
    std::string git_refs_url;
    std::string git_tags_url;
    std::string hooks_url;
    std::string html_url;
    std::string issue_comment_url;
    std::string issue_events_url;
    std::string issues_url;
    std::string keys_url;
    std::string labels_url;
    std::string languages_url;
    std::string merges_url;
    std::string milestones_url;
    std::string notifications_url;

    std::string pulls_url;
    std::string releases_url;
    std::string stargazers_url;
    std::string statuses_url;
    std::string subscribers_url;
    std::string subscription_url;
    std::string tags_url;
    std::string teams_url;
    std::string trees_url;
    std::string url;

    std::optional<std::string> homepage;
    std::optional<std::string> language;
    size_t forks_count;
    size_t stargazers_count;
    size_t watchers_count;
    size_t size;

    std::string default_branch;

    size_t open_issues_count;
    std::optional<std::vector<std::string>> topics;

    bool has_issues;
    bool has_projects;
    bool has_wiki;
    bool has_pages;
    bool has_downloads;
    std::optional<bool> archived;
    std::string pushed_at;
    std::string created_at;
    std::string updated_at;

    std::optional<permissions_t> permissions;
    std::optional<bool> allow_rebase_merge;
    std::optional<bool> allow_squash_merge;
    std::optional<bool> allow_merge_commit;
    std::optional<size_t> subscribers_count;
    std::optional<size_t> network_count;
    std::optional<license_t> license;

    std::optional<organization_t> organization;

  };

  struct repository_t : public basic_repository_t {
    std::optional<basic_repository_t> parent;
    std::optional<basic_repository_t> source;
  };
}

BOOST_FUSION_ADAPT_STRUCT(gh::repos::basic_repository_t,
  (auto, id) (auto, full_name) (auto, name)
  /*(auto, private_)*/ (auto, fork) (auto, owner)
  (auto, description)

  (auto, archive_url) (auto, assignees_url) (auto, blobs_url)
  (auto, collaborators_url) (auto, comments_url) (auto, commits_url)
  (auto, compare_url) (auto, contents_url) (auto, contributors_url)
  (auto, deployments_url)
  (auto, downloads_url) (auto, events_url) (auto, forks_url)
  (auto, git_commits_url) (auto, git_refs_url) (auto, git_tags_url)
  (auto, hooks_url) (auto, html_url) (auto, issue_comment_url)
  (auto, issue_events_url) (auto, issues_url) (auto, keys_url)
  (auto, labels_url) (auto, languages_url) (auto, merges_url)
  (auto, milestones_url) (auto, notifications_url) (auto, pulls_url)
  (auto, releases_url) (auto ,stargazers_url) (auto,statuses_url)
  (auto, subscribers_url) (auto, subscription_url) (auto,tags_url)
  (auto, teams_url) (auto, trees_url) (auto, url)

  (auto, homepage) (auto, language) (auto, forks_count) (auto, stargazers_count)
  (auto, watchers_count) (auto, size) (auto, default_branch) (auto, open_issues_count)
  (auto, topics) (auto, has_issues) (auto, has_projects)
  (auto, has_wiki) (auto, has_pages) (auto, has_downloads)
  (auto, archived) (auto, pushed_at) (auto, created_at) (auto, updated_at)

  (auto, permissions) (auto, allow_rebase_merge) (auto, allow_squash_merge)
  (auto, allow_merge_commit) (auto, subscribers_count) (auto, network_count)
  (auto, license) (auto, organization)
);

BOOST_FUSION_ADAPT_STRUCT(gh::repos::repository_t,
  (auto, id) (auto, full_name) (auto, name)
  /*(auto, private_)*/ (auto, fork) (auto, owner)
  (auto, description)

  (auto, archive_url) (auto, assignees_url) (auto, blobs_url)
  (auto, collaborators_url) (auto, comments_url) (auto, commits_url)
  (auto, compare_url) (auto, contents_url) (auto, contributors_url)
  (auto, deployments_url)
  (auto, downloads_url) (auto, events_url) (auto, forks_url)
  (auto, git_commits_url) (auto, git_refs_url) (auto, git_tags_url)
  (auto, hooks_url) (auto, html_url) (auto, issue_comment_url)
  (auto, issue_events_url) (auto, issues_url) (auto, keys_url)
  (auto, labels_url) (auto, languages_url) (auto, merges_url)
  (auto, milestones_url) (auto, notifications_url) (auto, pulls_url)
  (auto, releases_url) (auto ,stargazers_url) (auto,statuses_url)
  (auto, subscribers_url) (auto, subscription_url) (auto,tags_url)
  (auto, teams_url) (auto, trees_url) (auto, url)

  (auto, homepage) (auto, language) (auto, forks_count) (auto, stargazers_count)
  (auto, watchers_count) (auto, size) (auto, default_branch) (auto, open_issues_count)
  (auto, topics) (auto, has_issues) (auto, has_projects)
  (auto, has_wiki) (auto, has_pages) (auto, has_downloads)
  (auto, archived) (auto, pushed_at) (auto, created_at) (auto, updated_at)

  (auto, permissions) (auto, allow_rebase_merge) (auto, allow_squash_merge)
  (auto, allow_merge_commit) (auto, subscribers_count) (auto, network_count)
  (auto, license) (auto, organization)

  (auto, parent) (auto, source));

namespace gh {

  using namespace std::string_literals;

  /**
   * \brief gets the provided repo and pass it to result_handler otherwise throws.
   * \param auth credentials
   * \param owner
   * \param repository
   * \param result_handler taking a gh::repos::repository_t
   */
  inline void repos_get(std::string owner, std::string repository,
    std::function<void(repos::repository_t&&)>&& result_handler,
    std::optional<auth> auth = std::nullopt,
    const std::string& api_endpoint = "https://api.github.com"s ) {

    using namespace xxhr;
    auto url = api_endpoint + "/repos/"s + owner + "/" + repository;

    auto response_handler = [&](auto&& resp) {
      if ( (!resp.error) && (resp.status_code == 200) ) {
        result_handler(pre::json::from_json<repos::repository_t>(resp.text));
      } else {
        throw std::runtime_error( "err : "s + std::string(resp.error) + "status: "s
            + std::to_string(resp.status_code) + " accessing : "s + url );
      }
    };

    if (auth) {
      GET(url,
        Authentication{auth->user, auth->pass},
        on_response = response_handler);
    } else {
      GET(url,
        on_response = response_handler);
    }
  }

}

ext: hxx

max_stars_repo_name: nxxm/gh

max_issues_repo_name: nxxm/gh

max_forks_repo_name: nxxm/gh


text:
/*******************************************************************************
 *         Copyright 2003 & onward LASMEA UMR 6602 CNRS/Univ. Clermont II
 *         Copyright 2009 & onward LRI    UMR 8623 CNRS/Univ Paris Sud XI
 *
 *          Distributed under the Boost Software License, Version 1.0.
 *                 See accompanying file LICENSE.txt or copy at
 *                     http://www.boost.org/LICENSE_1_0.txt
 ******************************************************************************/
#define NT2_UNIT_MODULE "nt2::meta::make_real"

#include <boost/mpl/placeholders.hpp>
#include <nt2/sdk/config/types.hpp>
#include <nt2/sdk/meta/make_real.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/add_pointer.hpp>
#include <nt2/sdk/unit/module.hpp>
#include <nt2/sdk/unit/tests/basic.hpp>

////////////////////////////////////////////////////////////////////////////////
// Test make_real output
////////////////////////////////////////////////////////////////////////////////
NT2_TEST_CASE(make_real)
{
  using nt2::meta::make_real;
  using boost::is_same;
  using namespace nt2;

  NT2_TEST( (is_same<float  , make_real<4>::type >::value)  );
  NT2_TEST( (is_same<double , make_real<8>::type >::value)  );
}

////////////////////////////////////////////////////////////////////////////////
// Test make_real transformed output
////////////////////////////////////////////////////////////////////////////////
NT2_TEST_CASE(make_real_transform)
{
  using nt2::meta::make_real;
  using boost::add_pointer;
  using boost::is_same;
  using boost::mpl::_;
  using namespace nt2;

  NT2_TEST( (is_same<float*  , make_real<4, add_pointer<_> >::type >::value)  );
  NT2_TEST( (is_same<double* , make_real<8, add_pointer<_> >::type >::value)  );
}


text:
#include "SparseCMPC/SparseCMPC.h"
#include <Eigen/Dense>
#include <unsupported/Eigen/MatrixFunctions>

void SparseCMPC::c2d(u32 trajIdx, u32 bBlockStartIdx, u32 block_count) {

  Eigen::Matrix<double, 24, 24> AB, expmm;
  AB.setZero();
  AB.block(0,0,12,12) = _aMat[trajIdx];

  for(u32 i = bBlockStartIdx; i < bBlockStartIdx + block_count; i++) {
    BblockID id = _bBlockIds[i];
    if(id.timestep != trajIdx) throw std::runtime_error("c2d timestep error");
    AB.block(0,12 + 3 * id.foot, 12, 3) = _bBlocks[i];
  }

  AB *= _dtTrajectory[trajIdx];

  expmm = AB.exp();
  _aMat[trajIdx] = expmm.block(0,0,12,12);

  for(u32 i = bBlockStartIdx; i < bBlockStartIdx + block_count; i++) {
    //BblockID id = _bBlockIds[i];
    //_bBlocks[i] = expmm.block(0,12 + 3 * id.foot, 12, 3);
    _bBlocks[i] *= _dtTrajectory[trajIdx];
  }
}

max_stars_repo_name: zbwu/Cheetah-Software

max_issues_repo_name: zbwu/Cheetah-Software

max_forks_repo_name: zbwu/Cheetah-Software


text:
//
// Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//

#ifndef BEAST_HTTP_IMPL_WRITE_IPP
#define BEAST_HTTP_IMPL_WRITE_IPP

#include <beast/http/concepts.hpp>
#include <beast/http/chunk_encode.hpp>
#include <beast/core/buffer_cat.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/buffer_concepts.hpp>
#include <beast/core/handler_helpers.hpp>
#include <beast/core/handler_ptr.hpp>
#include <beast/core/stream_concepts.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/core/write_dynabuf.hpp>
#include <beast/core/detail/sync_ostream.hpp>
#include <boost/asio/write.hpp>
#include <condition_variable>
#include <mutex>
#include <ostream>
#include <sstream>
#include <type_traits>

namespace beast {
namespace http {

namespace detail {

template<class DynamicBuffer, class Fields>
void
write_start_line(DynamicBuffer& dynabuf,
    header<true, Fields> const& msg)
{
    BOOST_ASSERT(msg.version == 10 || msg.version == 11);
    write(dynabuf, msg.method);
    write(dynabuf, " ");
    write(dynabuf, msg.url);
    switch(msg.version)
    {
    case 10:
        write(dynabuf, " HTTP/1.0\r\n");
        break;
    case 11:
        write(dynabuf, " HTTP/1.1\r\n");
        break;
    }
}

template<class DynamicBuffer, class Fields>
void
write_start_line(DynamicBuffer& dynabuf,
    header<false, Fields> const& msg)
{
    BOOST_ASSERT(msg.version == 10 || msg.version == 11);
    switch(msg.version)
    {
    case 10:
        write(dynabuf, "HTTP/1.0 ");
        break;
    case 11:
        write(dynabuf, "HTTP/1.1 ");
        break;
    }
    write(dynabuf, msg.status);
    write(dynabuf, " ");
    write(dynabuf, msg.reason);
    write(dynabuf, "\r\n");
}

template<class DynamicBuffer, class FieldSequence>
void
write_fields(DynamicBuffer& dynabuf, FieldSequence const& fields)
{
    static_assert(is_DynamicBuffer<DynamicBuffer>::value,
        "DynamicBuffer requirements not met");
    //static_assert(is_FieldSequence<FieldSequence>::value,
    //    "FieldSequence requirements not met");
    for(auto const& field : fields)
    {
        write(dynabuf, field.name());
        write(dynabuf, ": ");
        write(dynabuf, field.value());
        write(dynabuf, "\r\n");
    }
}

} // detail

//------------------------------------------------------------------------------

namespace detail {

template<class Stream, class Handler>
class write_streambuf_op
{
    struct data
    {
        bool cont;
        Stream& s;
        streambuf sb;
        int state = 0;

        data(Handler& handler, Stream& s_,
                streambuf&& sb_)
            : cont(beast_asio_helpers::
                is_continuation(handler))
            , s(s_)
            , sb(std::move(sb_))
        {
        }
    };

    handler_ptr<data, Handler> d_;

public:
    write_streambuf_op(write_streambuf_op&&) = default;
    write_streambuf_op(write_streambuf_op const&) = default;

    template<class DeducedHandler, class... Args>
    write_streambuf_op(DeducedHandler&& h, Stream& s,
            Args&&... args)
        : d_(std::forward<DeducedHandler>(h),
            s, std::forward<Args>(args)...)
    {
        (*this)(error_code{}, 0, false);
    }

    void
    operator()(error_code ec,
        std::size_t bytes_transferred, bool again = true);

    friend
    void* asio_handler_allocate(
        std::size_t size, write_streambuf_op* op)
    {
        return beast_asio_helpers::
            allocate(size, op->d_.handler());
    }

    friend
    void asio_handler_deallocate(
        void* p, std::size_t size, write_streambuf_op* op)
    {
        return beast_asio_helpers::
            deallocate(p, size, op->d_.handler());
    }

    friend
    bool asio_handler_is_continuation(write_streambuf_op* op)
    {
        return op->d_->cont;
    }

    template<class Function>
    friend
    void asio_handler_invoke(Function&& f, write_streambuf_op* op)
    {
        return beast_asio_helpers::
            invoke(f, op->d_.handler());
    }
};

template<class Stream, class Handler>
void
write_streambuf_op<Stream, Handler>::
operator()(error_code ec, std::size_t, bool again)
{
    auto& d = *d_;
    d.cont = d.cont || again;
    while(! ec && d.state != 99)
    {
        switch(d.state)
        {
        case 0:
        {
            d.state = 99;
            boost::asio::async_write(d.s,
                d.sb.data(), std::move(*this));
            return;
        }
        }
    }
    d_.invoke(ec);
}

} // detail

template<class SyncWriteStream,
    bool isRequest, class Fields>
void
write(SyncWriteStream& stream,
    header<isRequest, Fields> const& msg)
{
    static_assert(is_SyncWriteStream<SyncWriteStream>::value,
        "SyncWriteStream requirements not met");
    error_code ec;
    write(stream, msg, ec);
    if(ec)
        throw system_error{ec};
}

template<class SyncWriteStream,
    bool isRequest, class Fields>
void
write(SyncWriteStream& stream,
    header<isRequest, Fields> const& msg,
        error_code& ec)
{
    static_assert(is_SyncWriteStream<SyncWriteStream>::value,
        "SyncWriteStream requirements not met");
    streambuf sb;
    detail::write_start_line(sb, msg);
    detail::write_fields(sb, msg.fields);
    beast::write(sb, "\r\n");
    boost::asio::write(stream, sb.data(), ec);
}

template<class AsyncWriteStream,
    bool isRequest, class Fields,
        class WriteHandler>
typename async_completion<
    WriteHandler, void(error_code)>::result_type
async_write(AsyncWriteStream& stream,
    header<isRequest, Fields> const& msg,
        WriteHandler&& handler)
{
    static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
        "AsyncWriteStream requirements not met");
    beast::async_completion<WriteHandler,
        void(error_code)> completion{handler};
    streambuf sb;
    detail::write_start_line(sb, msg);
    detail::write_fields(sb, msg.fields);
    beast::write(sb, "\r\n");
    detail::write_streambuf_op<AsyncWriteStream,
        decltype(completion.handler)>{
            completion.handler, stream, std::move(sb)};
    return completion.result.get();
}

//------------------------------------------------------------------------------

namespace detail {

template<bool isRequest, class Body, class Fields>
struct write_preparation
{
    message<isRequest, Body, Fields> const& msg;
    typename Body::writer w;
    streambuf sb;
    bool chunked;
    bool close;

    explicit
    write_preparation(
            message<isRequest, Body, Fields> const& msg_)
        : msg(msg_)
        , w(msg)
        , chunked(token_list{
            msg.fields["Transfer-Encoding"]}.exists("chunked"))
        , close(token_list{
            msg.fields["Connection"]}.exists("close") ||
                (msg.version < 11 && ! msg.fields.exists(
                    "Content-Length")))
    {
    }

    void
    init(error_code& ec)
    {
        w.init(ec);
        if(ec)
            return;

        write_start_line(sb, msg);
        write_fields(sb, msg.fields);
        beast::write(sb, "\r\n");
    }
};

template<class Stream, class Handler,
    bool isRequest, class Body, class Fields>
class write_op
{
    struct data
    {
        bool cont;
        Stream& s;
        // VFALCO How do we use handler_alloc in write_preparation?
        write_preparation<
            isRequest, Body, Fields> wp;
        int state = 0;

        data(Handler& handler, Stream& s_,
                message<isRequest, Body, Fields> const& m_)
            : cont(beast_asio_helpers::
                is_continuation(handler))
            , s(s_)
            , wp(m_)
        {
        }
    };

    class writef0_lambda
    {
        write_op& self_;

    public:
        explicit
        writef0_lambda(write_op& self)
            : self_(self)
        {
        }

        template<class ConstBufferSequence>
        void operator()(ConstBufferSequence const& buffers) const
        {
            auto& d = *self_.d_;
            // write header and body
            if(d.wp.chunked)
                boost::asio::async_write(d.s,
                    buffer_cat(d.wp.sb.data(),
                        chunk_encode(false, buffers)),
                            std::move(self_));
            else
                boost::asio::async_write(d.s,
                    buffer_cat(d.wp.sb.data(),
                        buffers), std::move(self_));
        }
    };

    class writef_lambda
    {
        write_op& self_;

    public:
        explicit
        writef_lambda(write_op& self)
            : self_(self)
        {
        }

        template<class ConstBufferSequence>
        void operator()(ConstBufferSequence const& buffers) const
        {
            auto& d = *self_.d_;
            // write body
            if(d.wp.chunked)
                boost::asio::async_write(d.s,
                    chunk_encode(false, buffers),
                        std::move(self_));
            else
                boost::asio::async_write(d.s,
                    buffers, std::move(self_));
        }
    };

    handler_ptr<data, Handler> d_;

public:
    write_op(write_op&&) = default;
    write_op(write_op const&) = default;

    template<class DeducedHandler, class... Args>
    write_op(DeducedHandler&& h, Stream& s, Args&&... args)
        : d_(std::forward<DeducedHandler>(h),
            s, std::forward<Args>(args)...)
    {
        (*this)(error_code{}, 0, false);
    }

    void
    operator()(error_code ec,
        std::size_t bytes_transferred, bool again = true);

    friend
    void* asio_handler_allocate(
        std::size_t size, write_op* op)
    {
        return beast_asio_helpers::
            allocate(size, op->d_.handler());
    }

    friend
    void asio_handler_deallocate(
        void* p, std::size_t size, write_op* op)
    {
        return beast_asio_helpers::
            deallocate(p, size, op->d_.handler());
    }

    friend
    bool asio_handler_is_continuation(write_op* op)
    {
        return op->d_->cont;
    }

    template<class Function>
    friend
    void asio_handler_invoke(Function&& f, write_op* op)
    {
        return beast_asio_helpers::
            invoke(f, op->d_.handler());
    }
};

template<class Stream, class Handler,
    bool isRequest, class Body, class Fields>
void
write_op<Stream, Handler, isRequest, Body, Fields>::
operator()(error_code ec, std::size_t, bool again)
{
    auto& d = *d_;
    d.cont = d.cont || again;
    while(! ec && d.state != 99)
    {
        switch(d.state)
        {
        case 0:
        {
            d.wp.init(ec);
            if(ec)
            {
                // call handler
                d.state = 99;
                d.s.get_io_service().post(bind_handler(
                    std::move(*this), ec, 0, false));
                return;
            }
            d.state = 1;
            break;
        }

        case 1:
        {
            auto const result =
                d.wp.w.write(ec,
                    writef0_lambda{*this});
            if(ec)
            {
                // call handler
                d.state = 99;
                d.s.get_io_service().post(bind_handler(
                    std::move(*this), ec, false));
                return;
            }
            if(result)
                d.state = d.wp.chunked ? 4 : 5;
            else
                d.state = 2;
            return;
        }

        // sent header and body
        case 2:
            d.wp.sb.consume(d.wp.sb.size());
            d.state = 3;
            break;

        case 3:
        {
            auto const result =
                d.wp.w.write(ec,
                    writef_lambda{*this});
            if(ec)
            {
                // call handler
                d.state = 99;
                break;
            }
            if(result)
                d.state = d.wp.chunked ? 4 : 5;
            else
                d.state = 2;
            return;
        }

        case 4:
            // VFALCO Unfortunately the current interface to the
            //        Writer concept prevents us from coalescing the
            //        final body chunk with the final chunk delimiter.
            //
            // write final chunk
            d.state = 5;
            boost::asio::async_write(d.s,
                chunk_encode_final(), std::move(*this));
            return;

        case 5:
            if(d.wp.close)
            {
                // VFALCO TODO Decide on an error code
                ec = boost::asio::error::eof;
            }
            d.state = 99;
            break;
        }
    }
    d_.invoke(ec);
}

template<class SyncWriteStream, class DynamicBuffer>
class writef0_lambda
{
    DynamicBuffer const& sb_;
    SyncWriteStream& stream_;
    bool chunked_;
    error_code& ec_;

public:
    writef0_lambda(SyncWriteStream& stream,
            DynamicBuffer const& sb, bool chunked, error_code& ec)
        : sb_(sb)
        , stream_(stream)
        , chunked_(chunked)
        , ec_(ec)
    {
    }

    template<class ConstBufferSequence>
    void operator()(ConstBufferSequence const& buffers) const
    {
        // write header and body
        if(chunked_)
            boost::asio::write(stream_, buffer_cat(
                sb_.data(), chunk_encode(false, buffers)), ec_);
        else
            boost::asio::write(stream_, buffer_cat(
                sb_.data(), buffers), ec_);
    }
};

template<class SyncWriteStream>
class writef_lambda
{
    SyncWriteStream& stream_;
    bool chunked_;
    error_code& ec_;

public:
    writef_lambda(SyncWriteStream& stream,
            bool chunked, error_code& ec)
        : stream_(stream)
        , chunked_(chunked)
        , ec_(ec)
    {
    }

    template<class ConstBufferSequence>
    void operator()(ConstBufferSequence const& buffers) const
    {
        // write body
        if(chunked_)
            boost::asio::write(stream_,
                chunk_encode(false, buffers), ec_);
        else
            boost::asio::write(stream_, buffers, ec_);
    }
};

} // detail

template<class SyncWriteStream,
    bool isRequest, class Body, class Fields>
void
write(SyncWriteStream& stream,
    message<isRequest, Body, Fields> const& msg)
{
    static_assert(is_SyncWriteStream<SyncWriteStream>::value,
        "SyncWriteStream requirements not met");
    static_assert(is_Body<Body>::value,
        "Body requirements not met");
    static_assert(has_writer<Body>::value,
        "Body has no writer");
    static_assert(is_Writer<typename Body::writer,
        message<isRequest, Body, Fields>>::value,
            "Writer requirements not met");
    error_code ec;
    write(stream, msg, ec);
    if(ec)
        throw system_error{ec};
}

template<class SyncWriteStream,
    bool isRequest, class Body, class Fields>
void
write(SyncWriteStream& stream,
    message<isRequest, Body, Fields> const& msg,
        error_code& ec)
{
    static_assert(is_SyncWriteStream<SyncWriteStream>::value,
        "SyncWriteStream requirements not met");
    static_assert(is_Body<Body>::value,
        "Body requirements not met");
    static_assert(has_writer<Body>::value,
        "Body has no writer");
    static_assert(is_Writer<typename Body::writer,
        message<isRequest, Body, Fields>>::value,
            "Writer requirements not met");
    detail::write_preparation<isRequest, Body, Fields> wp(msg);
    wp.init(ec);
    if(ec)
        return;
    auto result = wp.w.write(
        ec, detail::writef0_lambda<
            SyncWriteStream, decltype(wp.sb)>{
                stream, wp.sb, wp.chunked, ec});
    if(ec)
        return;
    wp.sb.consume(wp.sb.size());
    if(! result)
    {
        detail::writef_lambda<SyncWriteStream> wf{
            stream, wp.chunked, ec};
        for(;;)
        {
            result = wp.w.write(ec, wf);
            if(ec)
                return;
            if(result)
                break;
        }
    }
    if(wp.chunked)
    {
        // VFALCO Unfortunately the current interface to the
        //        Writer concept prevents us from using coalescing the
        //        final body chunk with the final chunk delimiter.
        //
        // write final chunk
        boost::asio::write(stream, chunk_encode_final(), ec);
        if(ec)
            return;
    }
    if(wp.close)
    {
        // VFALCO TODO Decide on an error code
        ec = boost::asio::error::eof;
    }
}

template<class AsyncWriteStream,
    bool isRequest, class Body, class Fields,
        class WriteHandler>
typename async_completion<
    WriteHandler, void(error_code)>::result_type
async_write(AsyncWriteStream& stream,
    message<isRequest, Body, Fields> const& msg,
        WriteHandler&& handler)
{
    static_assert(is_AsyncWriteStream<AsyncWriteStream>::value,
        "AsyncWriteStream requirements not met");
    static_assert(is_Body<Body>::value,
        "Body requirements not met");
    static_assert(has_writer<Body>::value,
        "Body has no writer");
    static_assert(is_Writer<typename Body::writer,
        message<isRequest, Body, Fields>>::value,
            "Writer requirements not met");
    beast::async_completion<WriteHandler,
        void(error_code)> completion{handler};
    detail::write_op<AsyncWriteStream, decltype(completion.handler),
        isRequest, Body, Fields>{completion.handler, stream, msg};
    return completion.result.get();
}

//------------------------------------------------------------------------------

template<bool isRequest, class Fields>
std::ostream&
operator<<(std::ostream& os,
    header<isRequest, Fields> const& msg)
{
    beast::detail::sync_ostream oss{os};
    error_code ec;
    write(oss, msg, ec);
    if(ec)
        throw system_error{ec};
    return os;
}

template<bool isRequest, class Body, class Fields>
std::ostream&
operator<<(std::ostream& os,
    message<isRequest, Body, Fields> const& msg)
{
    static_assert(is_Body<Body>::value,
        "Body requirements not met");
    static_assert(has_writer<Body>::value,
        "Body has no writer");
    static_assert(is_Writer<typename Body::writer,
        message<isRequest, Body, Fields>>::value,
            "Writer requirements not met");
    beast::detail::sync_ostream oss{os};
    error_code ec;
    write(oss, msg, ec);
    if(ec && ec != boost::asio::error::eof)
        throw system_error{ec};
    return os;
}

} // http
} // beast

#endif

ext: ipp

max_stars_repo_name: MassICTBV/casinocoind

max_issues_repo_name: MassICTBV/casinocoind

max_forks_repo_name: MassICTBV/casinocoind