<commit_before>#include "linedetector.h"
#include <opencv2/video/video.hpp>
#include <opencv2/opencv.hpp>
#include <sensor_msgs/image_encodings.h>
#include <pcl_ros/point_cloud.h>
#include <queue>
#include <chrono>
#include <ctime>

using namespace std;
using namespace cv;
using namespace pcl;

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

constexpr double radians(double degrees)
{
    return degrees / 180.0 * M_PI;
}

void LineDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    // chrono::time_point<chrono::system_clock> start, end; // instantiate time to use
    // start = chrono::system_clock::now();

    cv_ptr = cv_bridge::toCvCopy(msg, "");
    src_img = cv_ptr->image;
    dst_img = Mat::zeros(src_img.size(), src_img.type());
    fin_img = Mat::zeros(src_img.size(), src_img.type());

    // What separates lines from other objects?
    // 1. Lines are whiter than their surroundings
    // 2. Lines are on the ground
    // 3. A section of a line has two other line sections adjascent to it
    // 4. We know roughly how wide a line is going to be

    DetectLines(lineThickness);

    EnforceLength(working, lineLengthThreshold);

    resize(working, fin_img, Size(src_img.cols, src_img.rows), 0, 0, INTER_LANCZOS4);

    cloud = toPointCloud(fin_img);
    _line_cloud.publish(cloud);

    cvtColor(fin_img, fin_img, CV_GRAY2BGR);
    cv_ptr->image = fin_img;
    _filt_img.publish(cv_ptr->toImageMsg());

    // end = chrono::system_clock::now();
    // chrono::duration<double> elapsedTime = end - start;

    // cerr<<elapsedTime.count();
}

LineDetector::LineDetector(ros::NodeHandle &handle)
      : _it(handle)
      , tf_listener(handle)
{
     cout<<"Running"<<endl;
    _src_img = _it.subscribe("/left/image_rect_color", 1, &LineDetector::img_callback, this);
	  _filt_img = _it.advertise("/filt_img", 1);
    _line_cloud = handle.advertise<PCLCloud>("/line_cloud", 100);
    initLineDetection();
}

PointCloud<PointXYZ>::Ptr LineDetector::toPointCloud(Mat src){
    PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
    tf::StampedTransform transform;
    tf_listener.lookupTransform("/base_footprint", "/camera_left", ros::Time(0), transform);
    double roll, pitch, yaw;
    tf::Matrix3x3(transform.getRotation()).getRPY(roll, pitch, yaw);
    auto origin_z = transform.getOrigin().getZ();
    auto origin_y = transform.getOrigin().getY();
    auto HFOV = radians(66.0);
    auto VFOV = radians(47.6);
    pitch = -roll; // Because conventions are different and I'm in the middle of comp, and give me a break.
    for(int r = src.rows/2; r < src.rows; r++)
    {
        uchar *row = src.ptr<uchar>(r);
        for(int c = 0; c < src.cols; c++)
        {
            if(row[c] > 0)
            {
                auto pitch_offset = ((float)(r-src.rows/2) / src.rows) * VFOV;
                auto y = origin_z /tan(pitch + pitch_offset) + origin_y;

                auto theta = ((float)(c-src.cols/2) / src.cols) * HFOV;
                auto x = y * tan(theta);

                cloud->points.push_back(PointXYZ(x, y, 0));
            }
        }
    }
    cloud->header.frame_id = "base_footprint";
    return cloud;
}

void LineDetector::initLineDetection() {
    cerr << "DetectLines::Initing" << endl;
    lineThickness = 20;
    lineLengthThreshold = 40;

    float karray[3][9][9] = {
            {
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0}
            },
            {
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,     0,     1},
                    {-1,   -1,    -1,    -1,    -1,     0,     1,     1,     1},
                    {-1,   -1,    -1,     0,     1,     1,     1,     1,     1},
                    {-1,    0,     1,     1,     1,     1,     1,    .5,     0},
                    {1,     1,     1,     1,     1,    .5,     0,     0,     0},
                    {1,     1,     1,    .5,     0,     0,     0,     0,     0},
                    {1,    .5,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0}
            },
            {
                    {-.89,-.89, -.89,  -.89,  -.89,  -.89,  -.89,     1,     1},
                    {-.89,-.89, -.89,  -.89,  -.89,  -.89,     1,     1,     1},
                    {-.89,-.89, -.89,  -.89,  -.89,     1,     1,     1,     0},
                    {-.89,-.89, -.89,  -.89,     1,     1,     1,     0,     0},
                    {-.89,-.89, -.89,     1,     1,     1,     0,     0,     0},
                    {-.89,-.89,    1,     1,     1,     0,     0,     0,     0},
                    {-.89,  1,     1,     1,     0,     0,     0,     0,     0},
                    {1,     1,     1,     0,     0,     0,     0,     0,     0},
                    {1,     1,     0,     0,     0,     0,     0,     0,     0}
            }
    };

    Mat kernel1(9, 9, CV_32FC1, karray[0]);
    kernel1 /= 27;
    Mat kernel2(9, 9, CV_32FC1, karray[1]);
    kernel2 /= 25;
    Mat kernel3(9, 9, CV_32FC1, karray[2]);
    kernel3 /= 25;

    Mat kernel4 = kernel2.t();
    Mat kernel5 = kernel1.t();

    Mat kernel6;
    Mat kernel7;
    Mat kernel8;

    flip(kernel4, kernel6, 0);
    flip(kernel3, kernel7, 0);
    flip(kernel2, kernel8, 0);

    kernels[0] = kernel1.clone();
    kernels[1] = kernel2.clone();
    kernels[2] = kernel3.clone();
    kernels[3] = kernel4.clone();
    kernels[4] = kernel5.clone();
    kernels[5] = kernel6.clone();
    kernels[6] = kernel7.clone();
    kernels[7] = kernel8.clone();

    for (int i = 0; i < KERNAL_COUNT; i++) {
        Mat kernelComplement;
        flip(kernels[i], kernelComplement, -1);
        kernelComplements[i] = kernelComplement.clone();
    }
}

void LineDetector::DetectLines(int lineThickness) {

    // Resize the image such that the lines are approximately 3 pixels wide
    //cerr << "DetectLines::Reducing Image" << endl;
    lineThickness = max(1, lineThickness); // 0 thickness doesn't make sense
    resize(src_img, working, Size(3*src_img.cols/lineThickness, 3*src_img.rows/lineThickness), 0, 0, INTER_LANCZOS4);

    // Convert the image into HSV space to make processing white lines easier
    //cerr << "DetectLines::Converting to HSV" << endl;
    cvtColor(working, working, CV_BGR2HSV);

    // Calculate each pixel's "whiteness" defined as value*(255-saturation);
    //cerr << "DetectLines::Filtering Whiteness" << endl;
    WhitenessFilter(working, working);

    // Pass directional kernels over image
    //cerr << "DetectLines::Filtering kernels" << endl;
    for(size_t i = 0; i < KERNAL_COUNT; i++)
        filter2D(working, kernelResults[i], -1, kernels[i]);

    // Pass directional kernel complements over image (same edge, rotated 180 degrees, 3 pixels between edge and complement)
    //cerr << "DetectLines::Filtering complements" << endl;
    for(size_t i = 0; i < KERNAL_COUNT; i++)
        filter2D(working, complementResults[i], -1, kernelComplements[i]);

    // Multiply the results of kernel filter by its complement
    //cerr << "DetectLines::Multiplying Results" << endl;
    MultiplyByComplements(kernelResults, complementResults, kernelResults);

    working = Mat::zeros(kernelResults[0].size(), kernelResults[0].type());
    //cerr << "DetectLines::Thresholding Results" << endl;
    for(int i = 0; i < KERNAL_COUNT; i++) {
        // threshold(kernelResults[i], kernelResults[i], ((float)lineContinue*lineContinue)/255, 255, CV_THRESH_BINARY);
        adaptiveThreshold(kernelResults[i], kernelResults[i], 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 9, -1.85);
        bitwise_or(working, kernelResults[i], working);
    }
}

void LineDetector::WhitenessFilter(Mat& hsv_image, Mat& fin_img) {
    Mat result = 255 * Mat::ones(hsv_image.size(), CV_16UC1);
    Mat tmp;
    hsv_image.convertTo(tmp, CV_16UC3, 1.0);
    Mat channel[3];
    split(tmp, channel);
    result = result - channel[1];
    result = result.mul(channel[2]);
    result.convertTo(fin_img, CV_8UC1, 1.0/255);
}

void LineDetector::MultiplyByComplements(Mat* images, Mat* complements, Mat* results) {
    for(size_t i = 0; i < KERNAL_COUNT; i++) {
        Mat image;
        Mat complement;
        Mat result = Mat::zeros(images[0].size(), CV_16UC1);
        images[i].convertTo(image, CV_16UC1, 1.0);
        complements[i].convertTo(complement, CV_16UC1, 1.0);
        result = image.mul(complement);
        result.convertTo(results[i], CV_8UC1, 1.0/255); // TODO figure this const out
    }
}

void LineDetector::EnforceLength(Mat& img, int length) {
    // Thresholding the line length using the area of the contours
    vector<vector<Point>> contours;
    vector<vector<Point>> contoursThreshold;
    vector<Vec4i> hierarchy;

    Mat copy = img.clone();
    findContours(copy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

    for (unsigned int i = 0; i < contours.size(); ++i) {
        if ((int) contours[i].size() < length) {
            contoursThreshold.push_back(contours[i]);
        }
    }

    Scalar color(0, 0, 0);
    drawContours(img, contoursThreshold, -1, color, -1);
}
<commit_msg>Blacked out the outsize border before finding contours to enforce line length, this prevents weird tiny contours on image edges from being detected as large contours<commit_after>#include "linedetector.h"
#include <opencv2/video/video.hpp>
#include <opencv2/opencv.hpp>
#include <sensor_msgs/image_encodings.h>
#include <pcl_ros/point_cloud.h>
#include <queue>
#include <chrono>
#include <ctime>

using namespace std;
using namespace cv;
using namespace pcl;

cv_bridge::CvImagePtr cv_ptr;
typedef pcl::PointCloud<pcl::PointXYZ> PCLCloud;

constexpr double radians(double degrees)
{
    return degrees / 180.0 * M_PI;
}

void LineDetector::img_callback(const sensor_msgs::ImageConstPtr& msg) {
    // chrono::time_point<chrono::system_clock> start, end; // instantiate time to use
    // start = chrono::system_clock::now();

    cv_ptr = cv_bridge::toCvCopy(msg, "");
    src_img = cv_ptr->image;
    dst_img = Mat::zeros(src_img.size(), src_img.type());
    fin_img = Mat::zeros(src_img.size(), src_img.type());

    // What separates lines from other objects?
    // 1. Lines are whiter than their surroundings
    // 2. Lines are on the ground
    // 3. A section of a line has two other line sections adjascent to it
    // 4. We know roughly how wide a line is going to be

    DetectLines(lineThickness);

    EnforceLength(working, lineLengthThreshold);

    resize(working, fin_img, Size(src_img.cols, src_img.rows), 0, 0, INTER_LANCZOS4);

    cloud = toPointCloud(fin_img);
    _line_cloud.publish(cloud);

    cvtColor(fin_img, fin_img, CV_GRAY2BGR);
    cv_ptr->image = fin_img;
    _filt_img.publish(cv_ptr->toImageMsg());

    // end = chrono::system_clock::now();
    // chrono::duration<double> elapsedTime = end - start;

    // cerr<<elapsedTime.count();
}

LineDetector::LineDetector(ros::NodeHandle &handle)
      : _it(handle)
      , tf_listener(handle)
{
     cout<<"Running"<<endl;
    _src_img = _it.subscribe("/left/image_rect_color", 1, &LineDetector::img_callback, this);
	  _filt_img = _it.advertise("/filt_img", 1);
    _line_cloud = handle.advertise<PCLCloud>("/line_cloud", 100);
    initLineDetection();
}

PointCloud<PointXYZ>::Ptr LineDetector::toPointCloud(Mat src){
    PointCloud<PointXYZ>::Ptr cloud(new PointCloud<PointXYZ>);
    tf::StampedTransform transform;
    tf_listener.lookupTransform("/base_footprint", "/camera_left", ros::Time(0), transform);
    double roll, pitch, yaw;
    tf::Matrix3x3(transform.getRotation()).getRPY(roll, pitch, yaw);
    auto origin_z = transform.getOrigin().getZ();
    auto origin_y = transform.getOrigin().getY();
    auto HFOV = radians(66.0);
    auto VFOV = radians(47.6);
    pitch = -roll; // Because conventions are different and I'm in the middle of comp, and give me a break.
    for(int r = src.rows/2; r < src.rows; r++)
    {
        uchar *row = src.ptr<uchar>(r);
        for(int c = 0; c < src.cols; c++)
        {
            if(row[c] > 0)
            {
                auto pitch_offset = ((float)(r-src.rows/2) / src.rows) * VFOV;
                auto y = origin_z /tan(pitch + pitch_offset) + origin_y;

                auto theta = ((float)(c-src.cols/2) / src.cols) * HFOV;
                auto x = y * tan(theta);

                cloud->points.push_back(PointXYZ(x, y, 0));
            }
        }
    }
    cloud->header.frame_id = "base_footprint";
    return cloud;
}

void LineDetector::initLineDetection() {
    cerr << "DetectLines::Initing" << endl;
    lineThickness = 20;
    lineLengthThreshold = 40;

    float karray[3][9][9] = {
            {
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {1,     1,     1,     1,     1,     1,     1,     1,     1},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0}
            },
            {
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,    -1,    -1},
                    {-1,   -1,    -1,    -1,    -1,    -1,    -1,     0,     1},
                    {-1,   -1,    -1,    -1,    -1,     0,     1,     1,     1},
                    {-1,   -1,    -1,     0,     1,     1,     1,     1,     1},
                    {-1,    0,     1,     1,     1,     1,     1,    .5,     0},
                    {1,     1,     1,     1,     1,    .5,     0,     0,     0},
                    {1,     1,     1,    .5,     0,     0,     0,     0,     0},
                    {1,    .5,     0,     0,     0,     0,     0,     0,     0},
                    {0,     0,     0,     0,     0,     0,     0,     0,     0}
            },
            {
                    {-.89,-.89, -.89,  -.89,  -.89,  -.89,  -.89,     1,     1},
                    {-.89,-.89, -.89,  -.89,  -.89,  -.89,     1,     1,     1},
                    {-.89,-.89, -.89,  -.89,  -.89,     1,     1,     1,     0},
                    {-.89,-.89, -.89,  -.89,     1,     1,     1,     0,     0},
                    {-.89,-.89, -.89,     1,     1,     1,     0,     0,     0},
                    {-.89,-.89,    1,     1,     1,     0,     0,     0,     0},
                    {-.89,  1,     1,     1,     0,     0,     0,     0,     0},
                    {1,     1,     1,     0,     0,     0,     0,     0,     0},
                    {1,     1,     0,     0,     0,     0,     0,     0,     0}
            }
    };

    Mat kernel1(9, 9, CV_32FC1, karray[0]);
    kernel1 /= 27;
    Mat kernel2(9, 9, CV_32FC1, karray[1]);
    kernel2 /= 25;
    Mat kernel3(9, 9, CV_32FC1, karray[2]);
    kernel3 /= 25;

    Mat kernel4 = kernel2.t();
    Mat kernel5 = kernel1.t();

    Mat kernel6;
    Mat kernel7;
    Mat kernel8;

    flip(kernel4, kernel6, 0);
    flip(kernel3, kernel7, 0);
    flip(kernel2, kernel8, 0);

    kernels[0] = kernel1.clone();
    kernels[1] = kernel2.clone();
    kernels[2] = kernel3.clone();
    kernels[3] = kernel4.clone();
    kernels[4] = kernel5.clone();
    kernels[5] = kernel6.clone();
    kernels[6] = kernel7.clone();
    kernels[7] = kernel8.clone();

    for (int i = 0; i < KERNAL_COUNT; i++) {
        Mat kernelComplement;
        flip(kernels[i], kernelComplement, -1);
        kernelComplements[i] = kernelComplement.clone();
    }
}

void LineDetector::DetectLines(int lineThickness) {

    // Resize the image such that the lines are approximately 3 pixels wide
    //cerr << "DetectLines::Reducing Image" << endl;
    lineThickness = max(1, lineThickness); // 0 thickness doesn't make sense
    resize(src_img, working, Size(3*src_img.cols/lineThickness, 3*src_img.rows/lineThickness), 0, 0, CV_INTER_AREA);

    // Convert the image into HSV space to make processing white lines easier
    //cerr << "DetectLines::Converting to HSV" << endl;
    cvtColor(working, working, CV_BGR2HSV);

    // Calculate each pixel's "whiteness" defined as value*(255-saturation);
    //cerr << "DetectLines::Filtering Whiteness" << endl;
    WhitenessFilter(working, working);

    // Pass directional kernels over image
    //cerr << "DetectLines::Filtering kernels" << endl;
    for(size_t i = 0; i < KERNAL_COUNT; i++)
        filter2D(working, kernelResults[i], -1, kernels[i]);

    // Pass directional kernel complements over image (same edge, rotated 180 degrees, 3 pixels between edge and complement)
    //cerr << "DetectLines::Filtering complements" << endl;
    for(size_t i = 0; i < KERNAL_COUNT; i++)
        filter2D(working, complementResults[i], -1, kernelComplements[i]);

    // Multiply the results of kernel filter by its complement
    //cerr << "DetectLines::Multiplying Results" << endl;
    MultiplyByComplements(kernelResults, complementResults, kernelResults);

    working = Mat::zeros(kernelResults[0].size(), kernelResults[0].type());
    //cerr << "DetectLines::Thresholding Results" << endl;
    for(int i = 0; i < KERNAL_COUNT; i++) {
        // threshold(kernelResults[i], kernelResults[i], ((float)lineContinue*lineContinue)/255, 255, CV_THRESH_BINARY);
        adaptiveThreshold(kernelResults[i], kernelResults[i], 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 9, -1.85);
        bitwise_or(working, kernelResults[i], working);
    }
}

void LineDetector::WhitenessFilter(Mat& hsv_image, Mat& fin_img) {
    Mat result = 255 * Mat::ones(hsv_image.size(), CV_16UC1);
    Mat tmp;
    hsv_image.convertTo(tmp, CV_16UC3, 1.0);
    Mat channel[3];
    split(tmp, channel);
    result = result - channel[1];
    result = result.mul(channel[2]);
    result.convertTo(fin_img, CV_8UC1, 1.0/255);
}

void LineDetector::MultiplyByComplements(Mat* images, Mat* complements, Mat* results) {
    for(size_t i = 0; i < KERNAL_COUNT; i++) {
        Mat image;
        Mat complement;
        Mat result = Mat::zeros(images[0].size(), CV_16UC1);
        images[i].convertTo(image, CV_16UC1, 1.0);
        complements[i].convertTo(complement, CV_16UC1, 1.0);
        result = image.mul(complement);
        result.convertTo(results[i], CV_8UC1, 1.0/255); // TODO figure this const out
    }
}

void LineDetector::EnforceLength(Mat& img, int length) {
    // Thresholding the line length using the area of the contours
    vector<vector<Point>> contours;
    vector<vector<Point>> contoursThreshold;
    vector<Vec4i> hierarchy;

    rectangle(img, Point(0, 0), Point(copy.cols - 1, copy.rows - 1), Scalar(0, 0, 0));
    Mat copy = img.clone();
    findContours(copy, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);

    for (unsigned int i = 0; i < contours.size(); ++i) {
        if ((int) contours[i].size() < length) {
            contoursThreshold.push_back(contours[i]);
        }
    }

    Scalar color(0, 0, 0);
    drawContours(img, contoursThreshold, -1, color, -1);
}
<|endoftext|>


<commit_before>/*!
 * \file static_resource.hpp
 * \brief file static_resource.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/c_array.hpp>

namespace fastuidraw
{
/*!\addtogroup Utility
  @{
 */

  /*!
    Generate and store a string resource for use. Once a string resource
    is added it cannot be removed.
    \param resource_label "name" of resource, the string is copied
    \param value "value" of resource, the data behind value is copied
   */
  void
  generate_static_resource(const char *resource_label, const_c_array<uint8_t> value);

  /*!
    Returns the string behind a string resource. If no
    resource is found, returns 0.
    \param resource_label label of resource as specified
                          by generate_static_resource().
   */
  const_c_array<uint8_t>
  fetch_static_resource(const char *resource_label);

  /*!
    Provided as a conveniance. The ctor calls
    generate_static_resource().
   */
  class static_resource
  {
  public:
    /*!
      Ctor.
      On construction, calls generate_static_resource().
      \param resource_label resource label to pass to generate_static_resource()
      \param value value of resource to pass to generate_static_resource()
     */
    static_resource(const char *resource_label, const_c_array<uint8_t> value);
  };
/*! @} */
}
<commit_msg>fastuidraw/util: doxytg fix for static_resource<commit_after>/*!
 * \file static_resource.hpp
 * \brief file static_resource.hpp
 *
 * Copyright 2016 by Intel.
 *
 * Contact: kevin.rogovin@intel.com
 *
 * This Source Code Form is subject to the
 * terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with
 * this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * \author Kevin Rogovin <kevin.rogovin@intel.com>
 *
 */

#pragma once

#include <fastuidraw/util/c_array.hpp>

namespace fastuidraw
{
/*!\addtogroup Utility
  @{
 */

  /*!
    Generate and store a resource for use. Once a resource is added it
    cannot be removed.
    \param resource_label "name" of resource, the string is copied
    \param value "value" of resource, the data behind value is copied
   */
  void
  generate_static_resource(const char *resource_label, const_c_array<uint8_t> value);

  /*!
    Returns the data behind a resource. If no resource is found,
    returns an empty const_c_array.
    \param resource_label label of resource as specified
                          by generate_static_resource().
   */
  const_c_array<uint8_t>
  fetch_static_resource(const char *resource_label);

  /*!
    Provided as a conveniance. The ctor calls
    generate_static_resource().
   */
  class static_resource
  {
  public:
    /*!
      Ctor.
      On construction, calls generate_static_resource().
      \param resource_label resource label to pass to generate_static_resource()
      \param value value of resource to pass to generate_static_resource()
     */
    static_resource(const char *resource_label, const_c_array<uint8_t> value);
  };
/*! @} */
}
<|endoftext|>


<commit_before><commit_msg>Create 095_UniqueBinarySearchTrees.cc<commit_after><|endoftext|>


<commit_before>extern "C"
{
#include "libavformat/avformat.h"//ͷļֻڱʱ⣬ҵ
}

#include <iostream>
using namespace std;

//ӿļҵĶ
#pragma comment(lib,"avformat.lib")
#pragma comment(lib, "avutil.lib")

int XError(int errNum){
	char buf[1024] = { 0 };
	av_strerror(errNum, buf, sizeof(buf));
	cout << buf << endl;
	return -1;
}

int main(int argc, char *argv[])
{
	const char *inUrl = "FMLive.mp4";
	const char *outUrl = "rtmp://106.14.33.215:1935/live/fmlive";

	//ʼзװװ flv mp4 mov mp3
	av_register_all();

	//ʼ
	avformat_network_init();

	//1.ļװ
	//װ
	AVFormatContext *ifmt_ctx = NULL;

	//ļļͷ
	//ifmt_ctxĵַ˵ifmt_ctxǽз䣬Ҫעͷš
	int ret = avformat_open_input(&ifmt_ctx,inUrl, NULL, NULL);
	if (ret < 0){
		return XError(ret);
	}
	cout << "Open file '" << inUrl << "' success." << endl;

	//ȡƵƵϢ, h264 flv
	ret = avformat_find_stream_info(ifmt_ctx, NULL);
	if (ret < 0){
		return XError(ret);
	}

	av_dump_format(ifmt_ctx, 0, inUrl, 0);

	///////////////////////////////////////////////////
	//

	//
	AVFormatContext *ofmt_ctx = NULL;
	ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, "mp4", outUrl);
	if (!ofmt_ctx){
		return XError(ret);
	}
	cout << "ofmt_ctx create success!" << endl;

	//
	//AVStream
	for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++){
		AVStream *out_stream = avformat_new_stream(ofmt_ctx, ifmt_ctx->streams[i]->codec->codec);
		if (!out_stream){
			return XError(0);
		}

		//Ϣ,mp4
		ret = avcodec_copy_context(out_stream->codec, ifmt_ctx->streams[i]->codec);

		//Ϣ,°汾
		//ret = avcodec_parameters_copy(out_stream->codecpar, ifmt_ctx->streams[i]->codecpar);
		out_stream->codec->codec_tag = 0;

	}

	av_dump_format(ofmt_ctx, 0, outUrl, 1);

	///////////////////////////////////////////////////
	//rtmp
	//дͷϢ

	getchar();
	return 0;
}<commit_msg>Update main.cpp<commit_after>extern "C"
{
#include "libavformat/avformat.h"//头文件只是在编译时，用来语法检测，能找到函数的声明
#include "libavutil/time.h"
}

#include <iostream>
using namespace std;

//添加库文件，已找到函数的定义
#pragma comment(lib,"avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avcodec.lib")

int XError(int errNum){
	char buf[1024] = { 0 };
	av_strerror(errNum, buf, sizeof(buf));
	cout << buf << endl;
	return -1;
}

static double r2d(AVRational r){
    return r.num == 0 || r.den == 0?0. : (double)r.num/(double)r.den;
}

int main(int argc, char *argv[])
{
	const char *inUrl = "FMLive.mp4";
	const char *outUrl = "rtmp://106.14.33.215:1935/live/fmlive";

	//初始化所有封装解封装 flv mp4 mov mp3
	av_register_all();

	//初始化网络库
	avformat_network_init();

	//1.打开文件解封装
	//输入封装上下文
	AVFormatContext *ifmt_ctx = NULL;

	//打开文件，解封文件头
	//传的是ifmt_ctx的地址，说明ifmt_ctx由我们进行分配，这样，就要注意进行释放。
	int ret = avformat_open_input(&ifmt_ctx,inUrl, NULL, NULL);
	if (ret < 0){
		return XError(ret);
	}
	cout << "Open file '" << inUrl << "' success." << endl;

	//获取音频视频流信息, h264 flv
	ret = avformat_find_stream_info(ifmt_ctx, NULL);
	if (ret < 0){
		return XError(ret);
	}

	av_dump_format(ifmt_ctx, 0, inUrl, 0);

	///////////////////////////////////////////////////
	//输出流

	//创建输出流上下文
	AVFormatContext *ofmt_ctx = NULL;
	ret = avformat_alloc_output_context2(&ofmt_ctx, NULL, "mp4", outUrl);
	if (!ofmt_ctx){
		return XError(ret);
	}
	cout << "ofmt_ctx create success!" << endl;

	//配置输出流
	//遍历输入的AVStream
	for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++){
		AVStream *out_stream = avformat_new_stream(ofmt_ctx, ifmt_ctx->streams[i]->codec->codec);
		if (!out_stream){
			return XError(0);
		}

		//复制配置信息,用于mp4
		ret = avcodec_copy_context(out_stream->codec, ifmt_ctx->streams[i]->codec);

		//复制配置信息,新版本
		//ret = avcodec_parameters_copy(out_stream->codecpar, ifmt_ctx->streams[i]->codecpar);
		out_stream->codec->codec_tag = 0;

	}

	av_dump_format(ofmt_ctx, 0, outUrl, 1);

	///////////////////////////////////////////////////
	//rtmp推流

	//打开IO
    ret = avio_open(&ofmt_ctx->pb, outUrl, AVIO_FLAG_WRITE);
    if(!ofmt_ctx->pb){
        return XError(ret);
    }

	//写入头信息
ret = avformat_write_header(ofmt_ctx, NULL);
    if(ret < 0){
        return XError(ret);
    }

	cout<< "avformat_write_header"<< endl;

    //推流每一帧数据
    AVPacket pkt;
    long long startTime = av_gettime();//获取微妙时间戳

    while(true){
        ret = av_read_frame(ifmt_ctx, &pkt);
        if(ret != 0){
            break;
        }

        cout<< pkt.pts << " "<<flush;
        //计算转换pts dts
        AVRational itime = ifmt_ctx->streams[pkt.stream_index]->time_base;
        AVRational otime = ofmt_ctx->streams[pkt.stream_index]->time_base;

        pkt.pts = av_rescale_q_rnd(pkt.pts, itime, otime, (AVRational)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt.dts = av_rescale_q_rnd(pkt.pts, itime, otime, (AVRational)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt.duration = av_rescalse_q_rnd(pkt.duration, itime, otime, (AVRational)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX));
        pkt.position = -1;

        //视频帧推送速度
        if(ifmt_ctx->streams[pkt.stream_index]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO){
            AVRational tb = ifmt_ctx->streams[pkt.stream_index]->time_base;
            //已经过去的时间
            long long now = av_gettime() - startTime;
            long long dts = 0;
            dts = pkt.dts * (1000*1000*r2d(tb));
            if(dts > now){
                av_usleep(dts - now);
            }

        }
        if(ret < 0){
            return XError(ret);
        }

        ret = av_interleaved_write_frame(ofmt_ctx, &pkt);

        av_packet_unref(&pkt);
    }

	getchar();
	return 0;
}
<|endoftext|>


<commit_before>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CSSSelector.h"

#include <assert.h>

#include <org/w3c/dom/Element.h>

#include "CSSStyleDeclarationImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace
{

inline bool find(const std::u16string& s, const std::u16string& t)
{
    return s.find(t) != std::u16string::npos;
}

// s is a whitespace-separated list of words
inline bool contains(const std::u16string& s, const std::u16string& t)
{
    size_t pos = 0;
    for (;;) {
        pos = s.find(t, pos);
        if (pos == std::u16string::npos)
            return false;
        if ((pos == 0 || isSpace(s[pos - 1])) && (pos + t.length() == s.length() || isSpace(s[pos + t.length()])))
            return true;
        ++pos;
    }
}

inline bool startsWith(const std::u16string& s, const std::u16string& t)
{
    return !s.compare(0, t.length(), t);
}

inline bool endsWith(const std::u16string& s, const std::u16string& t)
{
    if (s.length() < t.length())
        return false;
    return !s.compare(s.length() - t.length(), t.length(), t);
}

}

void CSSSelectorsGroup::serialize(std::u16string& result)
{
    for (auto i = selectors.begin(); i != selectors.end(); ++i) {
        if (i != selectors.begin())
            result += u", ";
        (*i)->serialize(result);

        if (CSSSerializeControl.serializeSpecificity) {
            result += u" /* specificity = ";
            result += CSSSerializeHex((*i)->getSpecificity());
            result += u" */ ";
        }
    }
}

void CSSSelector::serialize(std::u16string& result)
{
    for (auto i = simpleSelectors.begin(); i != simpleSelectors.end(); ++i)
        (*i)->serialize(result);
}

void CSSPrimarySelector::serialize(std::u16string& result)
{
    if (combinator) {
        if (combinator != u' ') {
            result += u' ';
            result += static_cast<char16_t>(combinator);
        }
        result += u' ';
    }
    if (name == u"*")
        result += name;
    else
        result += CSSSerializeIdentifier(name);
    for (auto i = chain.begin(); i != chain.end(); ++i)
        (*i)->serialize(result);
}

void CSSAttributeSelector::serialize(std::u16string& result)
{
    result += u'[';
    result += CSSSerializeIdentifier(name);
    if (op) {
        result += static_cast<char16_t>(op);
        if (op != u'=')
            result += u'=';
        result += CSSSerializeString(value);
    }
    result += u']';
}

void CSSNthPseudoClassSelector::serialize(std::u16string& text)
{
    text += u':' + CSSSerializeIdentifier(name) + u'(';
    if (!a)
        text += CSSSerializeInteger(b);
    else {
        if (a == -1)  // TODO: Ask Anne about this.
            text += '-';
        else if (a != 1 && a != -1)
            text += CSSSerializeInteger(a);
        text += u'n';
        if (b) {
            if (0 < b)
                text += u'+';
            text += CSSSerializeInteger(b);
        }
    }
    text += u')';
}

CSSSpecificity CSSPrimarySelector::getSpecificity() {
    CSSSpecificity specificity;
    if (name != u"*")
        specificity += CSSSpecificity(0, 0, 0, 1);
    for (auto i = chain.begin(); i != chain.end(); ++i)
        specificity += (*i)->getSpecificity();
    return specificity;
}

CSSSpecificity CSSSelector::getSpecificity()
{
    CSSSpecificity specificity;
    for (auto i = simpleSelectors.begin(); i != simpleSelectors.end(); ++i)
        specificity += (*i)->getSpecificity();
    return specificity;
}

bool CSSPrimarySelector::match(Element e)
{
    if (name != u"*") {
        if (e.getLocalName() != name)
            return false;
        if (namespacePrefix != u"*") {
            if (!e.getNamespaceURI().hasValue() || e.getNamespaceURI().value() != namespacePrefix)
                return false;
        }
    }
    for (auto i = chain.begin(); i != chain.end(); ++i) {
        if (!(*i)->match(e))
            return false;
    }
    return true;
}

bool CSSIDSelector::match(Element e)
{
    Nullable<std::u16string> id = e.getAttribute(u"id");
    if (!id.hasValue())
        return false;
    return id.value() == name;  // TODO: ignore case
}

bool CSSClassSelector::match(Element e)
{
    Nullable<std::u16string> classes = e.getAttribute(u"class");
    if (!classes.hasValue())
        return false;
    return contains(classes.value(), name);  // TODO: ignore case
}

bool CSSAttributeSelector::match(Element e)
{
    Nullable<std::u16string> attr = e.getAttribute(name);
    if (!attr.hasValue())
        return false;
    switch (op) {
    case None:
        return true;
    case Equals:
        return attr.value() == value;
    case Includes:
        if (attr.value().length() == 0 || contains(attr.value(), u" "))
            return false;
        return contains(attr.value(), value);
    case DashMatch:
        if (!startsWith(attr.value(), value))
            return false;
        return attr.value().length() == value.length() || attr.value()[value.length()] == u'-';
    case PrefixMatch:
        if (attr.value().length() == 0)
            return false;
        return startsWith(attr.value(), value);
    case SuffixMatch:
        if (attr.value().length() == 0)
            return false;
        return endsWith(attr.value(), value);
    case SubstringMatch:
        if (attr.value().length() == 0)
            return false;
        return find(attr.value(), value);
    default:
        return false;
    }
}

bool CSSSelector::match(Element e)
{
    if (!e || simpleSelectors.size() == 0)
        return false;

    auto i = simpleSelectors.rbegin();
    if (!(*i)->match(e))
        return false;
    int combinator = (*i)->getCombinator();
    ++i;
    while (i != simpleSelectors.rend()) {
        switch (combinator) {
        case CSSPrimarySelector::Descendant:
            while (e = e.getParentElement()) {  // TODO: do we need to retry from here upon failure?
                if ((*i)->match(e))
                    break;
            }
            if (!e)
                return false;
            break;
        case CSSPrimarySelector::Child:
            e = e.getParentElement();
            if (!(*i)->match(e))
                return false;
            break;
        case CSSPrimarySelector::AdjacentSibling:
            e = e.getPreviousElementSibling();
            if (!(*i)->match(e))
                return false;
            break;
        case CSSPrimarySelector::GeneralSibling:
            while (e = e.getPreviousElementSibling()) {
                if ((*i)->match(e))
                    break;
            }
            if (!e)
                return false;
        default:
            return false;
        }
        combinator = (*i)->getCombinator();
        ++i;
    }
    if (combinator != CSSPrimarySelector::None)
        return false;
    return true;
}

CSSSelector* CSSSelectorsGroup::match(Element e)
{
    specificity = CSSSpecificity();
    for (auto i = selectors.begin(); i != selectors.end(); ++i) {
        if ((*i)->match(e)) {
            specificity = (*i)->getSpecificity();
            return *i;
        }
    }
    return 0;
}

CSSPseudoElementSelector* CSSPrimarySelector::getPseudoElement() const {
    if (chain.empty())
        return 0;
    if (CSSPseudoElementSelector* pseudo = dynamic_cast<CSSPseudoElementSelector*>(chain.back()))
        return pseudo;
    return 0;
}

CSSPseudoElementSelector* CSSSelector::getPseudoElement() const {
    if (simpleSelectors.empty())
        return 0;
    simpleSelectors.back()->getPseudoElement();
}

CSSPseudoElementSelector::CSSPseudoElementSelector(int id) :
    CSSPseudoSelector(CSSStyleDeclarationImp::getPseudoElementName(id)),
    id(id)
{
}

CSSPseudoSelector* CSSPseudoSelector::createPseudoSelector(int type, const std::u16string& ident)
{
    if (type == PseudoClass) {
        /* Exceptions: :first-line, :first-letter, :before and :after. */
        if (ident == u"first-line" || ident == u"first-letter" || ident == u"before" || ident == u"after")
            type = PseudoElement;
    }
    int id = -1;
    switch (type) {
    case PseudoClass:
        return new(std::nothrow) CSSPseudoClassSelector(ident);
        break;
    case PseudoElement:
        id = CSSStyleDeclarationImp::getPseudoElementID(ident);
        if (0 <= id)
            return new(std::nothrow) CSSPseudoElementSelector(id);
        break;
    default:
        break;
    }
    return 0;
}

CSSPseudoSelector* CSSPseudoSelector::createPseudoSelector(int type, const CSSParserTerm& function)
{
    switch (type) {
    case PseudoClass:
        return new(std::nothrow) CSSPseudoClassSelector(function);
        break;
    case PseudoElement:
        // No functional pseudo element is defined in CSS 2.1
        break;
    default:
        break;
    }
    return 0;
}

}}}}  // org::w3c::dom::bootstrap<commit_msg>(CSSSelector::getPseudoElement) : Fix a bug.<commit_after>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "CSSSelector.h"

#include <assert.h>

#include <org/w3c/dom/Element.h>

#include "CSSStyleDeclarationImp.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace
{

inline bool find(const std::u16string& s, const std::u16string& t)
{
    return s.find(t) != std::u16string::npos;
}

// s is a whitespace-separated list of words
inline bool contains(const std::u16string& s, const std::u16string& t)
{
    size_t pos = 0;
    for (;;) {
        pos = s.find(t, pos);
        if (pos == std::u16string::npos)
            return false;
        if ((pos == 0 || isSpace(s[pos - 1])) && (pos + t.length() == s.length() || isSpace(s[pos + t.length()])))
            return true;
        ++pos;
    }
}

inline bool startsWith(const std::u16string& s, const std::u16string& t)
{
    return !s.compare(0, t.length(), t);
}

inline bool endsWith(const std::u16string& s, const std::u16string& t)
{
    if (s.length() < t.length())
        return false;
    return !s.compare(s.length() - t.length(), t.length(), t);
}

}

void CSSSelectorsGroup::serialize(std::u16string& result)
{
    for (auto i = selectors.begin(); i != selectors.end(); ++i) {
        if (i != selectors.begin())
            result += u", ";
        (*i)->serialize(result);

        if (CSSSerializeControl.serializeSpecificity) {
            result += u" /* specificity = ";
            result += CSSSerializeHex((*i)->getSpecificity());
            result += u" */ ";
        }
    }
}

void CSSSelector::serialize(std::u16string& result)
{
    for (auto i = simpleSelectors.begin(); i != simpleSelectors.end(); ++i)
        (*i)->serialize(result);
}

void CSSPrimarySelector::serialize(std::u16string& result)
{
    if (combinator) {
        if (combinator != u' ') {
            result += u' ';
            result += static_cast<char16_t>(combinator);
        }
        result += u' ';
    }
    if (name == u"*")
        result += name;
    else
        result += CSSSerializeIdentifier(name);
    for (auto i = chain.begin(); i != chain.end(); ++i)
        (*i)->serialize(result);
}

void CSSAttributeSelector::serialize(std::u16string& result)
{
    result += u'[';
    result += CSSSerializeIdentifier(name);
    if (op) {
        result += static_cast<char16_t>(op);
        if (op != u'=')
            result += u'=';
        result += CSSSerializeString(value);
    }
    result += u']';
}

void CSSNthPseudoClassSelector::serialize(std::u16string& text)
{
    text += u':' + CSSSerializeIdentifier(name) + u'(';
    if (!a)
        text += CSSSerializeInteger(b);
    else {
        if (a == -1)  // TODO: Ask Anne about this.
            text += '-';
        else if (a != 1 && a != -1)
            text += CSSSerializeInteger(a);
        text += u'n';
        if (b) {
            if (0 < b)
                text += u'+';
            text += CSSSerializeInteger(b);
        }
    }
    text += u')';
}

CSSSpecificity CSSPrimarySelector::getSpecificity() {
    CSSSpecificity specificity;
    if (name != u"*")
        specificity += CSSSpecificity(0, 0, 0, 1);
    for (auto i = chain.begin(); i != chain.end(); ++i)
        specificity += (*i)->getSpecificity();
    return specificity;
}

CSSSpecificity CSSSelector::getSpecificity()
{
    CSSSpecificity specificity;
    for (auto i = simpleSelectors.begin(); i != simpleSelectors.end(); ++i)
        specificity += (*i)->getSpecificity();
    return specificity;
}

bool CSSPrimarySelector::match(Element e)
{
    if (name != u"*") {
        if (e.getLocalName() != name)
            return false;
        if (namespacePrefix != u"*") {
            if (!e.getNamespaceURI().hasValue() || e.getNamespaceURI().value() != namespacePrefix)
                return false;
        }
    }
    for (auto i = chain.begin(); i != chain.end(); ++i) {
        if (!(*i)->match(e))
            return false;
    }
    return true;
}

bool CSSIDSelector::match(Element e)
{
    Nullable<std::u16string> id = e.getAttribute(u"id");
    if (!id.hasValue())
        return false;
    return id.value() == name;  // TODO: ignore case
}

bool CSSClassSelector::match(Element e)
{
    Nullable<std::u16string> classes = e.getAttribute(u"class");
    if (!classes.hasValue())
        return false;
    return contains(classes.value(), name);  // TODO: ignore case
}

bool CSSAttributeSelector::match(Element e)
{
    Nullable<std::u16string> attr = e.getAttribute(name);
    if (!attr.hasValue())
        return false;
    switch (op) {
    case None:
        return true;
    case Equals:
        return attr.value() == value;
    case Includes:
        if (attr.value().length() == 0 || contains(attr.value(), u" "))
            return false;
        return contains(attr.value(), value);
    case DashMatch:
        if (!startsWith(attr.value(), value))
            return false;
        return attr.value().length() == value.length() || attr.value()[value.length()] == u'-';
    case PrefixMatch:
        if (attr.value().length() == 0)
            return false;
        return startsWith(attr.value(), value);
    case SuffixMatch:
        if (attr.value().length() == 0)
            return false;
        return endsWith(attr.value(), value);
    case SubstringMatch:
        if (attr.value().length() == 0)
            return false;
        return find(attr.value(), value);
    default:
        return false;
    }
}

bool CSSSelector::match(Element e)
{
    if (!e || simpleSelectors.size() == 0)
        return false;

    auto i = simpleSelectors.rbegin();
    if (!(*i)->match(e))
        return false;
    int combinator = (*i)->getCombinator();
    ++i;
    while (i != simpleSelectors.rend()) {
        switch (combinator) {
        case CSSPrimarySelector::Descendant:
            while (e = e.getParentElement()) {  // TODO: do we need to retry from here upon failure?
                if ((*i)->match(e))
                    break;
            }
            if (!e)
                return false;
            break;
        case CSSPrimarySelector::Child:
            e = e.getParentElement();
            if (!(*i)->match(e))
                return false;
            break;
        case CSSPrimarySelector::AdjacentSibling:
            e = e.getPreviousElementSibling();
            if (!(*i)->match(e))
                return false;
            break;
        case CSSPrimarySelector::GeneralSibling:
            while (e = e.getPreviousElementSibling()) {
                if ((*i)->match(e))
                    break;
            }
            if (!e)
                return false;
        default:
            return false;
        }
        combinator = (*i)->getCombinator();
        ++i;
    }
    if (combinator != CSSPrimarySelector::None)
        return false;
    return true;
}

CSSSelector* CSSSelectorsGroup::match(Element e)
{
    specificity = CSSSpecificity();
    for (auto i = selectors.begin(); i != selectors.end(); ++i) {
        if ((*i)->match(e)) {
            specificity = (*i)->getSpecificity();
            return *i;
        }
    }
    return 0;
}

CSSPseudoElementSelector* CSSPrimarySelector::getPseudoElement() const {
    if (chain.empty())
        return 0;
    if (CSSPseudoElementSelector* pseudo = dynamic_cast<CSSPseudoElementSelector*>(chain.back()))
        return pseudo;
    return 0;
}

CSSPseudoElementSelector* CSSSelector::getPseudoElement() const {
    if (simpleSelectors.empty())
        return 0;
    return simpleSelectors.back()->getPseudoElement();
}

CSSPseudoElementSelector::CSSPseudoElementSelector(int id) :
    CSSPseudoSelector(CSSStyleDeclarationImp::getPseudoElementName(id)),
    id(id)
{
}

CSSPseudoSelector* CSSPseudoSelector::createPseudoSelector(int type, const std::u16string& ident)
{
    if (type == PseudoClass) {
        /* Exceptions: :first-line, :first-letter, :before and :after. */
        if (ident == u"first-line" || ident == u"first-letter" || ident == u"before" || ident == u"after")
            type = PseudoElement;
    }
    int id = -1;
    switch (type) {
    case PseudoClass:
        return new(std::nothrow) CSSPseudoClassSelector(ident);
        break;
    case PseudoElement:
        id = CSSStyleDeclarationImp::getPseudoElementID(ident);
        if (0 <= id)
            return new(std::nothrow) CSSPseudoElementSelector(id);
        break;
    default:
        break;
    }
    return 0;
}

CSSPseudoSelector* CSSPseudoSelector::createPseudoSelector(int type, const CSSParserTerm& function)
{
    switch (type) {
    case PseudoClass:
        return new(std::nothrow) CSSPseudoClassSelector(function);
        break;
    case PseudoElement:
        // No functional pseudo element is defined in CSS 2.1
        break;
    default:
        break;
    }
    return 0;
}

}}}}  // org::w3c::dom::bootstrap<|endoftext|>


<commit_before>/*
 * Copyright 2011 Esrille Inc.
 *
 * 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.
 */

// A test harness for the implementation report of
//       the CSS2.1 Conformance Test Suite
// http://test.csswg.org/suites/css2.1/20110323/

#include <unistd.h>
#include <sys/wait.h>

#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

int processOutput(std::istream& stream, std::string& result)
{
    std::string output;
    bool completed = false;
    while (std::getline(stream, output)) {
        if (!completed) {
            if (output == "## complete")
                completed = true;
            continue;
        }
        if (output == "##")
            break;
        result += output + '\n';
    }
    return 0;
}

int main(int argc, char* argv[])
{
    bool headless = true;

    int argi = 1;
    while (*argv[argi] == '-') {
        switch (argv[argi][1]) {
        case 'i':
            headless = false;
            break;
        default:
            break;
        }
        ++argi;
    }

    if (argc < argi + 2) {
        std::cout << "usage: " << argv[0] << " [-i] report.data command [argument ...]\n";
        return EXIT_FAILURE;
    }

    std::ifstream data(argv[argi]);
    if (!data) {
        std::cerr << "error: " << argv[argi] << ": no such file\n";
        return EXIT_FAILURE;
    }

    std::ofstream result("report.data", std::ios_base::out | std::ios_base::trunc);
    if (!result) {
        std::cerr << "error: failed to open the report file\n";
        return EXIT_FAILURE;
    }

    char* args[argc - argi + 1];
    for (int i = 2; i < argc; ++i)
        args[i - 2] = argv[i + argi - 1];
    args[argc - argi] = 0;

    while (data) {
        std::string line;
        std::getline(data, line);
        if (line.empty() || line[0] == '#' || line == "testname    result  comment") {
            result << line << '\n';
            continue;
        }

        std::stringstream s(line, std::stringstream::in);
        std::string url;
        s >> url;
        if (url.empty())
            continue;

        int pipefd[2];
        pipe(pipefd);

        pid_t pid = fork();
        if (pid == -1) {
            std::cerr << "error: no more process to create\n";
            break;
        }
        if (pid == 0) {
            close(1);
            dup(pipefd[1]);
            close(pipefd[0]);

            url = "http://localhost:8000/" + url;
            args[argc - argi - 1] = strdup(url.c_str());
            execvp(args[0], args);
            exit(EXIT_FAILURE);
        }
        close(pipefd[1]);

        std::string output;

#if 104400 <= BOOST_VERSION
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], boost::iostreams::close_handle);
#else
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], true);
#endif
        processOutput(stream, output);

        if (headless)
            kill(pid, SIGTERM);

        int status;
        if (wait(&status) == -1) {
            std::cerr << "error: failed to wait for a test process to complete\n";
            break;
        }

        std::string path(url);
        size_t pos = path.rfind('.');
        if (pos != std::string::npos) {
            path.erase(pos);
            path += ".log";
        }
        std::string evaluation;

        if (output.empty())
            evaluation = "fatal";
        else if (!headless) {
            std::cout << "## complete\n" << output;
            std::cout << '[' << url << "]? ";
            std::getline(std::cin, evaluation);
            if (evaluation.empty() || evaluation == "p" || evaluation == "\x1b")
                evaluation = "pass";
            else if (evaluation == "f")
                evaluation = "fail";
            else if (evaluation == "i")
                evaluation = "invalid";
            else if (evaluation == "n")
                evaluation = "na";
            else if (evaluation == "s")
                evaluation = "skip";
            else if (evaluation == "u")
                evaluation = "uncertain";
            else if (evaluation == "q" || evaluation == "quit")
                break;

            std::ofstream dump(path.c_str(), std::ios_base::out | std::ios_base::trunc);
            if (!dump) {
                std::cerr << "error: failed to open the report file\n";
                return EXIT_FAILURE;
            }
            dump << "# " << url.c_str() << '\t' << evaluation << '\n' << output;
            dump.flush();
            dump.close();
        } else {
            std::ifstream dump(path.c_str());
            if (!dump)
                evaluation = "uncertain";
            else {
                std::string head;
                std::getline(dump, line);
                std::stringstream s(line, std::stringstream::in);
                s >> evaluation;
                s >> evaluation;
                s >> evaluation;
                std::string comp;
                while (std::getline(dump, line))
                    comp += line + '\n';
                if (output != comp) {
                    if (evaluation == "pass")
                        evaluation = "fail";
                    else
                        evaluation = "uncertain";
                }
            }
        }

        result << url << '\t' << evaluation << '\n';
    }
    result.close();
}
<commit_msg>(harness) : Kill each test process automatically even in the interactive mode.<commit_after>/*
 * Copyright 2011 Esrille Inc.
 *
 * 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.
 */

// A test harness for the implementation report of
//       the CSS2.1 Conformance Test Suite
// http://test.csswg.org/suites/css2.1/20110323/

#include <unistd.h>
#include <sys/wait.h>

#include <cstring>
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

#include <boost/version.hpp>
#include <boost/iostreams/stream.hpp>
#include <boost/iostreams/device/file_descriptor.hpp>

int processOutput(std::istream& stream, std::string& result)
{
    std::string output;
    bool completed = false;
    while (std::getline(stream, output)) {
        if (!completed) {
            if (output == "## complete")
                completed = true;
            continue;
        }
        if (output == "##")
            break;
        result += output + '\n';
    }
    return 0;
}

bool loadLog(const std::string& path, std::string& result, std::string& log)
{
    std::ifstream file(path.c_str());
    if (!file) {
        result = "?";
        return false;
    }
    std::string line;
    std::getline(file, line);
    size_t pos = line.find('\t');
    if (pos != std::string::npos)
        result = line.substr(pos + 1);
    else {
        result = "?";
        return false;
    }
    log.clear();
    while (std::getline(file, line))
        log += line + '\n';
    return true;
}

bool saveLog(const std::string& path, const std::string& url, const std::string& result, const std::string& log)
{
    std::ofstream file(path.c_str(), std::ios_base::out | std::ios_base::trunc);
    if (!file) {
        std::cerr << "error: failed to open the report file\n";
        return false;
    }
    file << "# " << url.c_str() << '\t' << result << '\n' << log;
    file.flush();
    file.close();
    return true;
}

int main(int argc, char* argv[])
{
    bool headless = true;

    int argi = 1;
    while (*argv[argi] == '-') {
        switch (argv[argi][1]) {
        case 'i':
            headless = false;
            break;
        default:
            break;
        }
        ++argi;
    }

    if (argc < argi + 2) {
        std::cout << "usage: " << argv[0] << " [-i] report.data command [argument ...]\n";
        return EXIT_FAILURE;
    }

    std::ifstream data(argv[argi]);
    if (!data) {
        std::cerr << "error: " << argv[argi] << ": no such file\n";
        return EXIT_FAILURE;
    }

    std::ofstream report("report.data", std::ios_base::out | std::ios_base::trunc);
    if (!report) {
        std::cerr << "error: failed to open the report file\n";
        return EXIT_FAILURE;
    }

    char* args[argc - argi + 1];
    for (int i = 2; i < argc; ++i)
        args[i - 2] = argv[i + argi - 1];
    args[argc - argi] = 0;

    while (data) {
        std::string line;
        std::getline(data, line);
        if (line.empty() || line[0] == '#' || line == "testname    result  comment") {
            report << line << '\n';
            continue;
        }

        std::stringstream s(line, std::stringstream::in);
        std::string url;
        s >> url;
        if (url.empty())
            continue;

        int pipefd[2];
        pipe(pipefd);

        pid_t pid = fork();
        if (pid == -1) {
            std::cerr << "error: no more process to create\n";
            break;
        }
        if (pid == 0) {
            close(1);
            dup(pipefd[1]);
            close(pipefd[0]);

            url = "http://localhost:8000/" + url;
            args[argc - argi - 1] = strdup(url.c_str());
            execvp(args[0], args);
            exit(EXIT_FAILURE);
        }
        close(pipefd[1]);

        std::string output;
#if 104400 <= BOOST_VERSION
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], boost::iostreams::close_handle);
#else
        boost::iostreams::stream<boost::iostreams::file_descriptor_source> stream(pipefd[0], true);
#endif
        processOutput(stream, output);

        std::string path(url);
        size_t pos = path.rfind('.');
        if (pos != std::string::npos) {
            path.erase(pos);
            path += ".log";
        }

        std::string evaluation;
        std::string log;
        loadLog(path, evaluation, log);

        std::string result;
        if (output.empty())
            result = "fatal";
        else if (!headless) {
            std::cout << "## complete\n" << output;
            std::cout << '[' << url << " : " << evaluation << "]? ";
            std::getline(std::cin, result);
            if (result.empty() || result == "p" || result == "\x1b")
                result = "pass";
            else if (result == "f")
                result = "fail";
            else if (result == "i")
                result = "invalid";
            else if (result == "k") // keep
                result = evaluation;
            else if (result == "n")
                result = "na";
            else if (result == "s")
                result = "skip";
            else if (result == "u")
                result = "uncertain";
            else if (result == "q" || result == "quit")
                break;
            if (!saveLog(path, url, result, output)) {
                std::cerr << "error: failed to open the report file\n";
                return EXIT_FAILURE;
            }
        } else {
            if (evaluation != "?" && output != log)
                result = "uncertain";
            else
                result = evaluation;
            std::cout << url << '\t' << result << '\n';
        }

        int status;
        kill(pid, SIGTERM);
        if (wait(&status) == -1) {
            std::cerr << "error: failed to wait for a test process to complete\n";
            break;
        }

        report << url << '\t' << result << '\n';
    }
    report.close();
}
<|endoftext|>


<commit_before>#include "info.hpp"

namespace z
{
	namespace file
	{
		info::info(const zpath& path) noexcept
		{
			does_exist = _stat((char*)path.cstring(), &fileStat);
		}

		bool info::exists() const noexcept
		{
			return does_exist;
		}

		time_t info::accessed() const noexcept
		{
			return does_exist ? fileStat.st_atime : 0;
		}

		time_t info::modified() const noexcept
		{
			return does_exist ? fileStat.st_mtime : 0;
		}

		time_t info::changed() const noexcept
		{
			return does_exist ? fileStat.st_ctime : 0;
		}

		size_t info::size() const noexcept
		{
			return does_exist ? fileStat.st_size : 0;
		}

		int info::device() const noexcept
		{
			return does_exist ? fileStat.st_dev : 0;
		}

		mode_t info::mode() const noexcept
		{
			return does_exist ? fileStat.st_mode : 0;
		}

		bool info::directory() const noexcept
		{
			return does_exist ? S_ISDIR(fileStat.st_mode) : false;
		}

		bool info::symlink() const noexcept
		{
			return does_exist ? S_ISLNK(fileStat.st_mode) : false;
		}

		bool info::regular() const noexcept
		{
			return does_exist ? S_ISREG(fileStat.st_mode) : false;
		}
	}
}
<commit_msg>info::symlink() should always return false if windows.<commit_after>#include "info.hpp"

namespace z
{
	namespace file
	{
		info::info(const zpath& path) noexcept
		{
			does_exist = _stat((char*)path.cstring(), &fileStat);
		}

		bool info::exists() const noexcept
		{
			return does_exist;
		}

		time_t info::accessed() const noexcept
		{
			return does_exist ? fileStat.st_atime : 0;
		}

		time_t info::modified() const noexcept
		{
			return does_exist ? fileStat.st_mtime : 0;
		}

		time_t info::changed() const noexcept
		{
			return does_exist ? fileStat.st_ctime : 0;
		}

		size_t info::size() const noexcept
		{
			return does_exist ? fileStat.st_size : 0;
		}

		int info::device() const noexcept
		{
			return does_exist ? fileStat.st_dev : 0;
		}

		mode_t info::mode() const noexcept
		{
			return does_exist ? fileStat.st_mode : 0;
		}

		bool info::directory() const noexcept
		{
			return does_exist ? S_ISDIR(fileStat.st_mode) : false;
		}

		bool info::symlink() const noexcept
		{
#			ifdef _WIN32
			return false;
#			else
			return does_exist ? S_ISLNK(fileStat.st_mode) : false;
#			endif
		}

		bool info::regular() const noexcept
		{
			return does_exist ? S_ISREG(fileStat.st_mode) : false;
		}
	}
}
<|endoftext|>


<commit_before>#ifndef pRNG_impl
#define pRNG_impl
namespace pRNG{
	template<class result_type>
	struct pRNG{
		void*data_region;
		typedef result_type(*function_type)(void*);
		function_type iterate_function;
		pRNG(void*data_region,function_type iterate_function):
			data_region(data_region),
			iterate_function(iterate_function){}
		inline result_type operator()(){
			return iterate_function(data_region);
		}
		template<typename T,typename...vv>
		void seed(vv...args){
			((T*)data_region)->seed(args...);
		}
	};
	template<typename T>
	typename T::result_type pRNG_next(
		void*T_Ptr
	){
		return ((T*)T_Ptr)->operator()();
	}
	template<class T>
	pRNG<typename T::result_type>pRNG_adapt(T&prng_instance){
		return pRNG<typename T::result_type>((void*)(&prng_instance),pRNG_next<T>);
	}
	template<typename T,typename...args>
	pRNG<typename T::result_type>pRNG_create(args...vv){
		return pRNG_adapt(*(new T(vv...)));
	}
	template<typename T>
	void pRNG_free(pRNG<typename T::result_type>gg){
		delete (T*)(gg.data_region);
	}
}
#endif
<commit_msg>Update pRNG.cpp<commit_after>#ifndef pRNG_impl
#define pRNG_impl
namespace pRNG{
	template<class result_type>
	struct pRNG{
		void*data_region;
		typedef result_type(*function_type)(void*);
		function_type iterate_function;
		pRNG(void*data_region,function_type iterate_function):
			data_region(data_region),
			iterate_function(iterate_function){}
		inline result_type operator()(){
			return iterate_function(data_region);
		}
		template<typename T,typename...vv>
		void seed(vv...args){
			((T*)data_region)->seed(args...);
		}
		template<typename T>
		inline T&instance(){return *(T*)data_region;}
	};
	template<typename T>
	typename T::result_type pRNG_next(
		void*T_Ptr
	){
		return ((T*)T_Ptr)->operator()();
	}
	template<class T>
	pRNG<typename T::result_type>pRNG_adapt(T&prng_instance){
		return pRNG<typename T::result_type>((void*)(&prng_instance),pRNG_next<T>);
	}
	template<typename T,typename...args>
	pRNG<typename T::result_type>pRNG_create(args...vv){
		return pRNG_adapt(*(new T(vv...)));
	}
	template<typename T>
	pRNG<typename T::result_type>pRNG_duplicate(T gg){
		return pRNG_adapt(*(new T(gg)));
	}
	template<typename T>
	void pRNG_free(pRNG<typename T::result_type>gg){
		delete (T*)(gg.data_region);
	}
}
#endif
<|endoftext|>


<commit_before><commit_msg>aim on catch<commit_after><|endoftext|>


<commit_before>#include <igvc/SerialPort.h>
#include <igvc_msgs/velocity_pair.h>
#include <std_msgs/Bool.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <ros/subscriber.h>
#include <std_msgs/Float64.h>
#include <string>
#include <vector>
#include <igvc/StringUtils.hpp>
#include <iomanip>
#include <sstream>

igvc_msgs::velocity_pair current_motor_command;

bool enabled = false;
int precision;

void cmdCallback(const igvc_msgs::velocity_pair::ConstPtr& msg)
{
  current_motor_command = *msg;
}

std::string toBoundedString(double input) {
  std::stringstream stream;
  stream << std::fixed << std::setprecision(precision) << input;
  return stream.str();
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "motor_controller");
  ros::NodeHandle nh;
  ros::NodeHandle nhp("~");

  ros::Subscriber cmd_sub = nh.subscribe("/motors", 1, cmdCallback);

  ros::Publisher enc_pub = nh.advertise<igvc_msgs::velocity_pair>("/encoders", 1000);

  ros::Publisher enabled_pub = nh.advertise<std_msgs::Bool>("/robot_enabled", 1);

  ros::Publisher battery_pub = nh.advertise<std_msgs::Float64>("/battery", 1);

  std::string device_path;
  nhp.param(std::string("device"), device_path, std::string("/dev/igvc_motor_board"));

  int baud_rate;
  nhp.param(std::string("baud_rate"), baud_rate, 9600);

  int messages_to_read;
  nhp.param(std::string("messages_to_read"), messages_to_read, 3);

  nhp.param("precision", precision, 1);

  double p_l, p_r, d_l, d_r, i_l, i_r;
  nhp.param("p_l", p_l, 3.0);
  nhp.param("p_r", p_r, 3.0);
  nhp.param("d_l", d_l, 0.0);
  nhp.param("d_r", d_r, 0.0);
  nhp.param("i_r", i_r, 0.0);
  nhp.param("i_l", i_l, 0.0);

  SerialPort port(device_path, baud_rate);

  if (!port.isOpen())
  {
    ROS_ERROR_STREAM("Motor Board serial port failed to open.");
    return -1;
  }
  port.flush();
  ROS_INFO_STREAM("Motor Board ready.");

  ros::Rate rate(10);

  std::string p_values = "#P" + toBoundedString(p_l) + "," + toBoundedString(p_r) + "\n";
  std::string d_values = "#D" + toBoundedString(d_l) + "," + toBoundedString(d_r) + "\n";
  std::string i_values = "#I" + toBoundedString(i_l) + "," + toBoundedString(i_r) + "\n";

  bool valid_values_p = false;
  bool valid_values_d = false;
  bool valid_values_i = false;

  while(ros::ok() && (!valid_values_p || !valid_values_d || !valid_values_i)) {
    ros::spinOnce();
    if(!valid_values_p) {
      port.write(p_values);
    }
    if(!valid_values_d) {
      port.write(d_values);
    }
    if(!valid_values_i) {
      port.write(i_values);
    }
    for(int i = 0; i < 3; i++) {
      std::string ret = port.readln();
      if(!ret.empty() && ret.at(0) == '#' && ret.at(1) != 'E') {
        size_t p_loc = ret.find('P');
        size_t d_loc = ret.find('D');
        size_t i_loc = ret.find('I');
        size_t end = ret.find('\n');
        if(p_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(p_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set p values");
          if(vals.size() == 2) {
            valid_values_p = true;
            valid_values_p = (stod(vals.at(0)) == p_l) && valid_values_p;
            valid_values_p = (stod(vals.at(1)) == p_r) && valid_values_p;
          }
        } else if(d_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(d_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set d values");
          if(vals.size() == 2) {
            valid_values_d = true;
            valid_values_d = (stod(vals.at(0)) == d_l) && valid_values_d;
            valid_values_d = (stod(vals.at(1)) == d_r) && valid_values_d;
          }
        } else if(i_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(i_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set i values");
          if(vals.size() == 2) {
            valid_values_i = true;
            valid_values_i = (stod(vals.at(0)) == i_l) && valid_values_i;
            valid_values_i = (stod(vals.at(1)) == i_r) && valid_values_i;
          }
        } else {
          ROS_ERROR_STREAM("Recieved unknown string while setting PID values " << ret);
        }
      } else if(ret.empty()) {
        ROS_ERROR_STREAM("Empty return from motor board while sending PID values.\t" << ret);
      }
    }
    rate.sleep();
  }
  ROS_INFO_STREAM("Sucessfully set all PID values");

  while (ros::ok() && port.isOpen()) {
    ros::spinOnce();
    std::string msg = "$" + (enabled ? toBoundedString(current_motor_command.left_velocity) : toBoundedString(0.0)) + "," +
      (enabled ? toBoundedString(current_motor_command.right_velocity) : toBoundedString(0.0)) + "\n";

    port.write(msg);

    std::string ret = port.readln();
    size_t dollar = ret.find('$');
    size_t pound = ret.find('#');
    int count = 0;
    while ((dollar != std::string::npos || pound != std::string::npos) && count <= messages_to_read) {
      count++;
      size_t end = ret.find('\n');
      std::vector<std::string> tokens;
      if(dollar != std::string::npos) {
        tokens = split(ret.substr(dollar + 1, end), ',');
      }
      if(pound != std::string::npos) {
        tokens = split(ret.substr(pound + 2, end), ',');
      }

      if(tokens.size() <= 0) {
        ROS_INFO_STREAM("Invalid number of tokens from motor board");
      } else {
        if(pound != std::string::npos) {
          if(ret.at(1) == 'I') {
            // imu message
          } else if(ret.at(1) == 'V') {
            std_msgs::Float64 battery_msg;
            double voltage = atof(tokens.at(0).c_str());
            battery_msg.data = voltage;
            battery_pub.publish(battery_msg);
            if(voltage < 24) {
              ROS_ERROR_STREAM("Battery voltage dangerously low");
            }
            std_msgs::Bool enabled_msg;
            enabled_msg.data = tokens.at(1) == "1";
            enabled = enabled_msg.data;
            enabled_pub.publish(enabled_msg);
          } else if(ret.at(1) == 'E') {
            ROS_ERROR_STREAM(ret);
            count--;
          }
        } else if(dollar != std::string::npos) {
          igvc_msgs::velocity_pair enc_msg;
          enc_msg.left_velocity = atof(tokens.at(0).c_str());
          enc_msg.right_velocity = atof(tokens.at(1).c_str());
          enc_msg.duration = atof(tokens.at(2).c_str());
          enc_msg.header.stamp = ros::Time::now();
          enc_pub.publish(enc_msg);
        } else {
          ROS_ERROR_STREAM("Unknown message from motor board " << ret);
        }
      }
      ret = port.readln();
      dollar = ret.find('$');
      pound = ret.find('#');
    }
    rate.sleep();
  }

}
<commit_msg>graceful error handling for motor controller parsing<commit_after>#include <igvc/SerialPort.h>
#include <igvc_msgs/velocity_pair.h>
#include <std_msgs/Bool.h>
#include <ros/publisher.h>
#include <ros/ros.h>
#include <ros/subscriber.h>
#include <std_msgs/Float64.h>
#include <string>
#include <vector>
#include <igvc/StringUtils.hpp>
#include <iomanip>
#include <sstream>

igvc_msgs::velocity_pair current_motor_command;

bool enabled = false;
int precision;

void cmdCallback(const igvc_msgs::velocity_pair::ConstPtr& msg)
{
  current_motor_command = *msg;
}

std::string toBoundedString(double input) {
  std::stringstream stream;
  stream << std::fixed << std::setprecision(precision) << input;
  return stream.str();
}

int main(int argc, char** argv)
{
  ros::init(argc, argv, "motor_controller");
  ros::NodeHandle nh;
  ros::NodeHandle nhp("~");

  ros::Subscriber cmd_sub = nh.subscribe("/motors", 1, cmdCallback);

  ros::Publisher enc_pub = nh.advertise<igvc_msgs::velocity_pair>("/encoders", 1000);

  ros::Publisher enabled_pub = nh.advertise<std_msgs::Bool>("/robot_enabled", 1);

  ros::Publisher battery_pub = nh.advertise<std_msgs::Float64>("/battery", 1);

  std::string device_path;
  nhp.param(std::string("device"), device_path, std::string("/dev/igvc_motor_board"));

  int baud_rate;
  nhp.param(std::string("baud_rate"), baud_rate, 9600);

  int messages_to_read;
  nhp.param(std::string("messages_to_read"), messages_to_read, 3);

  nhp.param("precision", precision, 1);

  double p_l, p_r, d_l, d_r, i_l, i_r;
  nhp.param("p_l", p_l, 3.0);
  nhp.param("p_r", p_r, 3.0);
  nhp.param("d_l", d_l, 0.0);
  nhp.param("d_r", d_r, 0.0);
  nhp.param("i_r", i_r, 0.0);
  nhp.param("i_l", i_l, 0.0);

  SerialPort port(device_path, baud_rate);

  if (!port.isOpen())
  {
    ROS_ERROR_STREAM("Motor Board serial port failed to open.");
    return -1;
  }
  port.flush();
  ROS_INFO_STREAM("Motor Board ready.");

  ros::Rate rate(10);

  std::string p_values = "#P" + toBoundedString(p_l) + "," + toBoundedString(p_r) + "\n";
  std::string d_values = "#D" + toBoundedString(d_l) + "," + toBoundedString(d_r) + "\n";
  std::string i_values = "#I" + toBoundedString(i_l) + "," + toBoundedString(i_r) + "\n";

  bool valid_values_p = false;
  bool valid_values_d = false;
  bool valid_values_i = false;

  while(ros::ok() && (!valid_values_p || !valid_values_d || !valid_values_i)) {
    ros::spinOnce();
    if(!valid_values_p) {
      port.write(p_values);
    }
    if(!valid_values_d) {
      port.write(d_values);
    }
    if(!valid_values_i) {
      port.write(i_values);
    }
    for(int i = 0; i < 3; i++) {
      std::string ret = port.readln();
      if(!ret.empty() && ret.at(0) == '#' && ret.at(1) != 'E') {
        size_t p_loc = ret.find('P');
        size_t d_loc = ret.find('D');
        size_t i_loc = ret.find('I');
        size_t end = ret.find('\n');
        if(p_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(p_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set p values");
          if(vals.size() == 2) {
            valid_values_p = true;
            valid_values_p = (stod(vals.at(0)) == p_l) && valid_values_p;
            valid_values_p = (stod(vals.at(1)) == p_r) && valid_values_p;
          }
        } else if(d_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(d_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set d values");
          if(vals.size() == 2) {
            valid_values_d = true;
            valid_values_d = (stod(vals.at(0)) == d_l) && valid_values_d;
            valid_values_d = (stod(vals.at(1)) == d_r) && valid_values_d;
          }
        } else if(i_loc != std::string::npos) {
          std::vector<std::string> vals = split(ret.substr(i_loc + 1, end), ',');
          ROS_INFO_STREAM("Successfully set i values");
          if(vals.size() == 2) {
            valid_values_i = true;
            valid_values_i = (stod(vals.at(0)) == i_l) && valid_values_i;
            valid_values_i = (stod(vals.at(1)) == i_r) && valid_values_i;
          }
        } else if(ret.at(1) != 'V') {
          ROS_ERROR_STREAM("Recieved unknown string while setting PID values " << ret);
        }
      } else if(ret.empty()) {
        ROS_ERROR_STREAM("Empty return from motor board while sending PID values.\t" << ret);
      }
    }
    rate.sleep();
  }
  ROS_INFO_STREAM("Sucessfully set all PID values");

  while (ros::ok() && port.isOpen()) {
    ros::spinOnce();
    std::string msg = "$" + (enabled ? toBoundedString(current_motor_command.left_velocity) : toBoundedString(0.0)) + "," +
      (enabled ? toBoundedString(current_motor_command.right_velocity) : toBoundedString(0.0)) + "\n";

    port.write(msg);

    std::string ret = port.readln();
    size_t dollar = ret.find('$');
    size_t pound = ret.find('#');
    int count = 0;
    while ((dollar != std::string::npos || pound != std::string::npos) && count <= messages_to_read) {
      count++;
      size_t end = ret.find('\n');
      std::vector<std::string> tokens;
      if(dollar != std::string::npos) {
        tokens = split(ret.substr(dollar + 1, end), ',');
      }
      if(pound != std::string::npos) {
        tokens = split(ret.substr(pound + 2, end), ',');
      }

      if(tokens.size() <= 0) {
        ROS_INFO_STREAM("Invalid number of tokens from motor board");
      } else {
        if(pound != std::string::npos) {
          if(ret.at(1) == 'I') {
            // imu message
          } else if(ret.at(1) == 'V') {
            std_msgs::Float64 battery_msg;
            double voltage = atof(tokens.at(0).c_str());
            battery_msg.data = voltage;
            battery_pub.publish(battery_msg);
            if(voltage < 24) {
              ROS_ERROR_STREAM("Battery voltage dangerously low");
            }
            std_msgs::Bool enabled_msg;
            enabled_msg.data = tokens.at(1) == "1";
            enabled = enabled_msg.data;
            enabled_pub.publish(enabled_msg);
          } else if(ret.at(1) == 'E') {
            ROS_ERROR_STREAM(ret);
            count--;
          }
        } else if(dollar != std::string::npos) {
          igvc_msgs::velocity_pair enc_msg;
          enc_msg.left_velocity = atof(tokens.at(0).c_str());
          enc_msg.right_velocity = atof(tokens.at(1).c_str());
          enc_msg.duration = atof(tokens.at(2).c_str());
          enc_msg.header.stamp = ros::Time::now();
          enc_pub.publish(enc_msg);
        } else {
          ROS_ERROR_STREAM("Unknown message from motor board " << ret);
        }
      }
      ret = port.readln();
      dollar = ret.find('$');
      pound = ret.find('#');
    }
    rate.sleep();
  }

}
<|endoftext|>


<commit_before><commit_msg>Whitespace change to trigger the bots.<commit_after><|endoftext|>


<commit_before>#ifndef TEXTURE2D_HPP
#define TEXTURE2D_HPP

#include <iostream>
#include <memory>

#include <VBE/graphics/Texture.hpp>

///
/// \brief Texture2D represents a GL 2D Texture
///
class Texture2D : public Texture {
	public:
		///
		/// \brief Loads a new texture from a stream.
		///
		/// The input stream may be an open file or a user-implemented stream.
		///
		/// \see Storage
		///
		static Texture2D load(
				std::unique_ptr<std::istream> in,
				TextureFormat::Format format = TextureFormat::AUTO);

		///
		/// \brief Default constructor. Generates invalid texture (0x0)
		///
		/// This constructor will generate a texture of size (0,0). This texture is not
		/// meant for use in rendering.
		///
		Texture2D();

		///
		/// \brief Size and Format constructor.
		///
		/// Will create an empty texture with the specified size and format.
		/// The initial contents of the texture are undefined.
		///
		/// \param format Can be sized or not.
		///
		/// \see TextureFormat::Format
		///
		Texture2D(vec2ui size,
				  TextureFormat::Format format = TextureFormat::RGBA);

		///
		/// \brief Sets the content of the texture
		///
		/// The pixels must be hold enough data to fill the texture, otherwise the behaviour is undefined
		///
		/// \param sourceFormat The format of the pixels pointer
		/// \param sourceType The data type of the pixels pointer
		///
		/// \see TextureFormat::Format
		/// \see TextureFormat::SourceType
		///
		void setData(const void* pixels,
					 TextureFormat::Format sourceFormat = TextureFormat::RGBA,
					 TextureFormat::SourceType sourceType = TextureFormat::UNSIGNED_BYTE);

		///
		/// \brief Generate mipmap levels
		///
		/// This function should be called every time the texture data changes to keep mipmapping working
		/// In order to make use of mipmapping, the texture min/mag filters should be
		/// appropiately set to a filter that supports mipmap.
		///
		/// \see Texture::setFilter
		///
		void generateMipmap();

		///
		/// \brief Returns the texture size
		///
		vec2ui getSize() const;

		///
		/// \brief Bind a texture to any given slot
		///
		/// Binding this texture will replace whatever texture was previously assigned for this slot
		///
		static void bind(const Texture2D* tex, unsigned int slot) {
			Texture::bind(Texture::Type2D, tex, slot);
		}

		///
		/// \brief Move constructor
		///
		Texture2D(Texture2D&& rhs);

		///
		/// \brief Move operator=
		///
		Texture2D& operator=(Texture2D&& rhs);

		///
		/// \brief Swap operator for the Texture2D class
		///
		friend void swap(Texture2D& a, Texture2D& b);

	private:
		vec2ui size = vec2ui(0);
};
///
/// \class Window Window.hpp <VBE/system/Window.hpp>
/// \ingroup System
///

#endif // TEXTURE2D_HPP
<commit_msg>Update Texture2D.hpp<commit_after>#ifndef TEXTURE2D_HPP
#define TEXTURE2D_HPP

#include <iostream>
#include <memory>

#include <VBE/graphics/Texture.hpp>

///
/// \brief Texture2D represents a GL 2D Texture
///
class Texture2D : public Texture {
	public:
		///
		/// \brief Loads a new texture from a stream.
		///
		/// The input stream may be an open file or a user-implemented stream.
		///
		/// \see Storage
		///
		static Texture2D load(
				std::unique_ptr<std::istream> in,
				TextureFormat::Format format = TextureFormat::AUTO);

		///
		/// \brief Default constructor. Generates an invalid texture with no pixels.
		///
		/// This constructor will generate a texture of size 0. This texture is not
		/// meant for use in rendering.
		///
		Texture2D();

		///
		/// \brief Size and Format constructor.
		///
		/// Will create an empty texture with the specified size and format.
		/// The initial contents of the texture are undefined.
		///
		/// \param format Can be sized or not.
		///
		/// \see TextureFormat::Format
		///
		Texture2D(vec2ui size,
				  TextureFormat::Format format = TextureFormat::RGBA);

		///
		/// \brief Sets the content of the texture
		///
		/// The pixels must be hold enough data to fill the texture, otherwise the behaviour is undefined
		///
		/// \param sourceFormat The format of the pixels pointer
		/// \param sourceType The data type of the pixels pointer
		///
		/// \see TextureFormat::Format
		/// \see TextureFormat::SourceType
		///
		void setData(const void* pixels,
					 TextureFormat::Format sourceFormat = TextureFormat::RGBA,
					 TextureFormat::SourceType sourceType = TextureFormat::UNSIGNED_BYTE);

		///
		/// \brief Generate mipmap levels
		///
		/// This function should be called every time the texture data changes to keep mipmapping working
		/// In order to make use of mipmapping, the texture min/mag filters should be
		/// appropiately set to a filter that supports mipmap.
		///
		/// \see Texture::setFilter
		///
		void generateMipmap();

		///
		/// \brief Returns the texture size
		///
		vec2ui getSize() const;

		///
		/// \brief Bind a texture to any given slot
		///
		/// Binding this texture will replace whatever texture was previously assigned for this slot
		///
		static void bind(const Texture2D* tex, unsigned int slot) {
			Texture::bind(Texture::Type2D, tex, slot);
		}

		///
		/// \brief Move constructor
		///
		Texture2D(Texture2D&& rhs);

		///
		/// \brief Move operator=
		///
		Texture2D& operator=(Texture2D&& rhs);

		///
		/// \brief Swap operator for the Texture2D class
		///
		friend void swap(Texture2D& a, Texture2D& b);

	private:
		vec2ui size = vec2ui(0);
};
///
/// \class Texture2D Texture2D.hpp <VBE/graphics/Texture2D.hpp>
/// \ingroup Graphics
///

#endif // TEXTURE2D_HPP
<|endoftext|>


<commit_before>#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <math.h>
#include <GL/glut.h>

#define GL_GLEXT_PROTOTYPES
#define PI 3.141592654
#define SHARPNESS_FACTOR 500

double floor_x = -30, world_y = 0, wing_z = 0, z_factor = 100.0, r_step = 5.0, scale = 1.0, world_y_trans = 0.0 , wing_speed = 0.0;
double wind_y = 0, wind_x = 0, wind_acc_factor = .8, turbine_factor = 0.005;
double progoffset = 0.0, progstep = 0.000, progstep_acc = .0005;
double torqueFact = 0.00002;
#include "shapes.h"
#include "user.h"

int w=1000,h=1000;

void print_bitmap_string(void* font, char* s)
{
	if(s&&strlen(s))
	{
		while(*s)
		{
			glutBitmapCharacter(font, *s);
			s++;
		}
	}
}

void drawWindMill()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);	// Clear color and depth buffers

	glLoadIdentity();
  	glTranslatef(0.0,world_y_trans,0.0);
  	glScalef(scale,scale,scale);	// Reset the model-view matrix

	// rotate the cube according to rx world_y and wing_z parameters , controlled via arrow keys
	glRotatef(world_y+90, 0.0, 1.0, 0.0);
	glRotatef(90, 1.0, 0.0, 0.0);
	Shaft(.03,.02,.75);

	GLUquadricObj *quadObj = gluNewQuadric();

	glLoadIdentity();
  	glTranslatef(0.0,world_y_trans,0.0);
  	glScalef(scale,scale,scale);
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.03,-.07);
	gluCylinder(quadObj, .03, .03, .05, 100, 100);

	glLoadIdentity();
  	glTranslatef(0.0,world_y_trans,0.0);
  	glScalef(scale,scale,scale);
	glRotatef(world_y, 0.0, 1.0, 0.0);
	glTranslatef(0,-0.03,-.07);
	Cone(.03,.0,.6,.6);

	GLdouble size;
	GLdouble aspect;
	glLoadIdentity();
	size = (GLdouble)((w >= h) ? w : h) / 2.0;
	if (w <= h) {
	  aspect = (GLdouble)h/(GLdouble)w;
	  glOrtho(-size, size, -size*aspect, size*aspect, -100000.0, 100000.0);
	}
	else {
	  aspect = (GLdouble)w/(GLdouble)h;
	  glOrtho(-size*aspect, size*aspect, -size, size, -100000.0, 100000.0);
	}

	glColor4f(0.20, 0.20, 0.20, 0.0);
	glRasterPos2f(200, 280.0);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, "DASHBOARD");

	//Wing speed
	glColor4f(0.0, .7, 0.7, 0.0);
	glRasterPos2f(200, 240.0);
	char* st = new char[100];
	ftoa(fabs(wing_speed),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, "Wing Speed(deg/frame): ");
	if(wing_speed<0.0)	print_bitmap_string(GLUT_BITMAP_HELVETICA_12, "-");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	//Wind speed
	glColor4f(.7, 0.0, 0.0, 0.0);
	glRasterPos2f(200, 210.0);
	ftoa(1000*fabs(progstep),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, "Wind Speed(km/hr):         ");
	if(progstep<0.0)	print_bitmap_string(GLUT_BITMAP_HELVETICA_12, "-");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	glColor4f(.7, 0.0, .7, 0.0);
	glRasterPos2f(200, 180.0);
	ftoa(1000*fabs(progstep*cos(wind_y/180*PI)*cos(wind_x/180*PI)),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, "Wind Speed z(km/hr):      ");
	if(progstep*cos(wind_y/180*PI)*cos(wind_x/180*PI)<0.0)	print_bitmap_string(GLUT_BITMAP_HELVETICA_12, "-");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	glColor4f(.7, .7, .7, 0.0);
	glRasterPos2f(200, 150.0);
	ftoa(1000*fabs(torqueFact*wing_speed*wing_speed),st,4);
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, "Power (MW):                    ");
	print_bitmap_string(GLUT_BITMAP_HELVETICA_18, st);

	Arrow(0.005,0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,0.2,-0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,0.2,-.98,-0.78,0.2,1.0);
	Arrow(0.005,-0.2,-0.2,-.98,-0.78,0.2,1.0);

	TriangularWing(0.055,0.05,0.4,0.025,30);
	TriangularWing(0.055,0.05,0.4,0.025,150);
	TriangularWing(0.055,0.05,0.4,0.025,270);

	glLoadIdentity();
  	glTranslatef(0.0,world_y_trans,0.0);
  	glScalef(scale,scale,scale);
	glRotatef(-10, 1.0, 0.0, 0.0);
	glRotatef(world_y+45, 0.0, 1.0, 0.0);
	for(int i=0;i<1000;++i)
	{
		glBegin (GL_LINES);
			glColor3f  (0,.1+.3*i/1000.0,0);
			glVertex3f  (-.5+i/1000.0,-.75, .5);
			glColor3f  (0,.7+.3*i/1000.0,0);
			glVertex3f  (-.5+i/1000.0,-.75, -.5);
		glEnd();
	}

	dashboard_arrow(0.005,.6,-.55,(progstep>0 ? .2 : -.2),.2,0.7);

	glLoadIdentity();
	glTranslatef(.6,-.55,0);
	glRotatef(floor_x/2,1,0,0);
	for(int i=0;i<1000;i++)
	{
		double th = (2*PI/1000)*i;
		glBegin (GL_LINES);
			glColor3f  (.6,.6,.6);
			glVertex3f  (.28*cos(th),0, .28*sin(th));
			glVertex3f  (.29*cos(th),0, .29*sin(th));
		glEnd();
	}
	glFlush();
  	glutSwapBuffers();
}

int main(int argc, char* argv[])
{
	// Initialize GLUT and process user parameters
	glutInit(&argc, argv);
	// Request double buffered true color window with Z-buffer
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
	// Set Window Size
	glutInitWindowSize(1000, 1000);
	// Set Window Position
	glutInitWindowPosition(100,100);
	// Create Window
	glutCreateWindow("WindMill");
	// Enable Z-buffer depth test
	glEnable(GL_DEPTH_TEST);

	// Callback Functions
	glutDisplayFunc(drawWindMill);
	glutIdleFunc(rotate);
	glutSpecialFunc(specialKeys);
	glutKeyboardFunc(rotateWind);
	glutMouseFunc(mouseWheel);
	glutMainLoop();
}<commit_msg>Deleted windmill_xyz & moved code to windmill.cpp<commit_after><|endoftext|>


<commit_before><commit_msg>Ignore chat messages, because they should be handled differently<commit_after><|endoftext|>


<commit_before><commit_msg>#68 tested on LE BE bytes order<commit_after><|endoftext|>


<commit_before>#ifndef ITER_ZIP_LONGEST_HPP_
#define ITER_ZIP_LONGEST_HPP_

#include "iterbase.hpp"

#include <boost/optional.hpp>
#include <iterator>
#include <tuple>
#include <utility>

namespace iter {

  template <typename Container>
  using OptIterDeref = boost::optional<iterator_deref<Container>>;

  template <typename... RestContainers>
  class ZippedLongest;

  template <typename... Containers>
  ZippedLongest<Containers...> zip_longest(Containers&&...);

  template <typename Container, typename... RestContainers>
  class ZippedLongest<Container, RestContainers...> {
    static_assert(!std::is_rvalue_reference<Container>::value,
        "Itertools cannot be templated with rvalue references");

    friend ZippedLongest zip_longest<Container, RestContainers...>(
        Container&&, RestContainers&&...);

    template <typename...>
    friend class ZippedLongest;

   private:
    using OptType = OptIterDeref<Container>;
    using ZipIterDeref = std::tuple<OptType, OptIterDeref<RestContainers>...>;

    Container container;
    ZippedLongest<RestContainers...> rest_zipped;
    ZippedLongest(Container&& in_container, RestContainers&&... rest)
        : container(std::forward<Container>(in_container)),
          rest_zipped{std::forward<RestContainers>(rest)...} {}

   public:
    class Iterator
        : public std::iterator<std::input_iterator_tag, ZipIterDeref> {
     private:
      using RestIter = typename ZippedLongest<RestContainers...>::Iterator;

      iterator_type<Container> iter;
      iterator_type<Container> end;
      RestIter rest_iter;

     public:
      Iterator(iterator_type<Container>&& it, iterator_type<Container>&& in_end,
          RestIter&& rest)
          : iter{std::move(it)},
            end{std::move(in_end)},
            rest_iter{std::move(rest)} {}

      Iterator& operator++() {
        if (this->iter != this->end) {
          ++this->iter;
        }
        ++this->rest_iter;
        return *this;
      }

      Iterator operator++(int) {
        auto ret = *this;
        ++*this;
        return ret;
      }

      bool operator!=(const Iterator& other) const {
        return this->iter != other.iter || this->rest_iter != other.rest_iter;
      }

      bool operator==(const Iterator& other) const {
        return !(*this != other);
      }

      ZipIterDeref operator*() {
        if (this->iter != this->end) {
          return std::tuple_cat(
              std::tuple<OptType>{{*this->iter}}, *this->rest_iter);
        } else {
          return std::tuple_cat(std::tuple<OptType>{{}}, *this->rest_iter);
        }
      }

      ArrowProxy<ZipIterDeref> operator->() {
        return {**this};
      }
    };

    Iterator begin() {
      return {std::begin(this->container), std::end(this->container),
          std::begin(this->rest_zipped)};
    }

    Iterator end() {
      return {std::end(this->container), std::end(this->container),
          std::end(this->rest_zipped)};
    }
  };

  template <>
  class ZippedLongest<> {
   public:
    class Iterator
        : public std::iterator<std::input_iterator_tag, std::tuple<>> {
     public:
      Iterator& operator++() {
        return *this;
      }

      constexpr Iterator operator++(int) const {
        return *this;
      }

      constexpr bool operator!=(const Iterator&) const {
        return false;
      }

      constexpr bool operator==(const Iterator&) const {
        return true;
      }

      constexpr std::tuple<> operator*() const {
        return {};
      }

      constexpr ArrowProxy<std::tuple<>> operator->() const {
        return {{}};
      }
    };

    constexpr Iterator begin() const {
      return {};
    }

    constexpr Iterator end() const {
      return {};
    }
  };

  template <typename... Containers>
  ZippedLongest<Containers...> zip_longest(Containers&&... containers) {
    return {std::forward<Containers>(containers)...};
  }
}

#endif
<commit_msg>moves ZippedLongest into impl { }<commit_after>#ifndef ITER_ZIP_LONGEST_HPP_
#define ITER_ZIP_LONGEST_HPP_

#include "iterbase.hpp"

#include <boost/optional.hpp>
#include <iterator>
#include <tuple>
#include <utility>

namespace iter {
  namespace impl {
    template <typename... RestContainers>
    class ZippedLongest;

    template <typename Container, typename... RestContainers>
    class ZippedLongest<Container, RestContainers...>;

    template <>
    class ZippedLongest<>;
  }

  template <typename... Containers>
  impl::ZippedLongest<Containers...> zip_longest(Containers&&...);
}

template <typename Container, typename... RestContainers>
class iter::impl::ZippedLongest<Container, RestContainers...> {
  static_assert(!std::is_rvalue_reference<Container>::value,
      "Itertools cannot be templated with rvalue references");

  friend ZippedLongest zip_longest<Container, RestContainers...>(
      Container&&, RestContainers&&...);

  template <typename...>
  friend class ZippedLongest;

 private:
  template <typename C>
  using OptIterDeref = boost::optional<iterator_deref<C>>;

  using OptType = OptIterDeref<Container>;
  using ZipIterDeref = std::tuple<OptType, OptIterDeref<RestContainers>...>;

  Container container;
  ZippedLongest<RestContainers...> rest_zipped;
  ZippedLongest(Container&& in_container, RestContainers&&... rest)
      : container(std::forward<Container>(in_container)),
        rest_zipped{std::forward<RestContainers>(rest)...} {}

 public:
  class Iterator : public std::iterator<std::input_iterator_tag, ZipIterDeref> {
   private:
    using RestIter = typename ZippedLongest<RestContainers...>::Iterator;

    iterator_type<Container> iter;
    iterator_type<Container> end;
    RestIter rest_iter;

   public:
    Iterator(iterator_type<Container>&& it, iterator_type<Container>&& in_end,
        RestIter&& rest)
        : iter{std::move(it)},
          end{std::move(in_end)},
          rest_iter{std::move(rest)} {}

    Iterator& operator++() {
      if (this->iter != this->end) {
        ++this->iter;
      }
      ++this->rest_iter;
      return *this;
    }

    Iterator operator++(int) {
      auto ret = *this;
      ++*this;
      return ret;
    }

    bool operator!=(const Iterator& other) const {
      return this->iter != other.iter || this->rest_iter != other.rest_iter;
    }

    bool operator==(const Iterator& other) const {
      return !(*this != other);
    }

    ZipIterDeref operator*() {
      if (this->iter != this->end) {
        return std::tuple_cat(
            std::tuple<OptType>{{*this->iter}}, *this->rest_iter);
      } else {
        return std::tuple_cat(std::tuple<OptType>{{}}, *this->rest_iter);
      }
    }

    ArrowProxy<ZipIterDeref> operator->() {
      return {**this};
    }
  };

  Iterator begin() {
    return {std::begin(this->container), std::end(this->container),
        std::begin(this->rest_zipped)};
  }

  Iterator end() {
    return {std::end(this->container), std::end(this->container),
        std::end(this->rest_zipped)};
  }
};

template <>
class iter::impl::ZippedLongest<> {
 public:
  class Iterator : public std::iterator<std::input_iterator_tag, std::tuple<>> {
   public:
    Iterator& operator++() {
      return *this;
    }

    constexpr Iterator operator++(int) const {
      return *this;
    }

    constexpr bool operator!=(const Iterator&) const {
      return false;
    }

    constexpr bool operator==(const Iterator&) const {
      return true;
    }

    constexpr std::tuple<> operator*() const {
      return {};
    }

    constexpr ArrowProxy<std::tuple<>> operator->() const {
      return {{}};
    }
  };

  constexpr Iterator begin() const {
    return {};
  }

  constexpr Iterator end() const {
    return {};
  }
};

template <typename... Containers>
iter::impl::ZippedLongest<Containers...> iter::zip_longest(
    Containers&&... containers) {
  return {std::forward<Containers>(containers)...};
}

#endif
<|endoftext|>


<commit_before>#pragma once
#include "string_util.hpp"
#include "stream_exception.hpp"

namespace kumori
{

	class chunked_encoder
	{
	public:

		typedef char char_type;

		struct category
			: boost::iostreams::output_filter_tag
			, boost::iostreams::closable_tag
			, boost::iostreams::multichar_tag
		{
		};

		template <class Synk>
		std::streamsize write(Synk& synk, const char_type* s, std::streamsize n)
		{
			std::string size_str = to_hex(static_cast<boost::make_unsigned<std::streamsize>::type>(n));
			if (boost::iostreams::write(synk, size_str.c_str(), size_str.size()) != static_cast<std::streamsize>(size_str.size()))
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, "\r\n", 2) != 2)
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, s, n) != n)
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, "\r\n", 2) != 2)
				BOOST_THROW_EXCEPTION(stream_exception());
			return n;
		}

		template <class Synk>
		void close(Synk& synk)
		{
			if (boost::iostreams::write(synk, "0\r\n\r\n", 5) != 5)
				BOOST_THROW_EXCEPTION(stream_exception());
		}

	};

}
<commit_msg>Replace boost::make_unsigned -> std::make_unsigned<commit_after>#pragma once
#include "string_util.hpp"
#include "stream_exception.hpp"

namespace kumori
{

	class chunked_encoder
	{
	public:

		typedef char char_type;

		struct category
			: boost::iostreams::output_filter_tag
			, boost::iostreams::closable_tag
			, boost::iostreams::multichar_tag
		{
		};

		template <class Synk>
		std::streamsize write(Synk& synk, const char_type* s, std::streamsize n)
		{
			std::string size_str = to_hex(static_cast<std::make_unsigned<std::streamsize>::type>(n));
			if (boost::iostreams::write(synk, size_str.c_str(), size_str.size()) != static_cast<std::streamsize>(size_str.size()))
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, "\r\n", 2) != 2)
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, s, n) != n)
				BOOST_THROW_EXCEPTION(stream_exception());
			if (boost::iostreams::write(synk, "\r\n", 2) != 2)
				BOOST_THROW_EXCEPTION(stream_exception());
			return n;
		}

		template <class Synk>
		void close(Synk& synk)
		{
			if (boost::iostreams::write(synk, "0\r\n\r\n", 5) != 5)
				BOOST_THROW_EXCEPTION(stream_exception());
		}

	};

}
<|endoftext|>