<commit_before>#include "Rectify.h"
using namespace std;
using namespace cv;
Rectify::Rectify(matPair inputPair)
{
    RectPair.left = inputPair.left;
    RectPair.right = inputPair.right;
    qDebug()<<"finding local maxima";
    RectPair = LocalMaxima(RectPair);
    qDebug()<<"removing borders";
    RectPair = BorderRemoveal(RectPair);
    qDebug()<<"gradiant frame";
    RectPair = GradiantFrame(RectPair);
    int top = 0;
    int bottom = 0;
    int left = 0;
    int right = 0;
    qDebug()<<"contour crop diff";
    contourCropDiff(RectPair,left,top,right,bottom);
    top = 0;
    bottom = 0;
    left = 0;
    right = 0;
    qDebug()<<"contour crop gray";
    contourCropGray(RectPair,left,top,right,bottom);
}

matPair Rectify::getCroppedPair()
{
    return RectPair;
}

matPair Rectify::GradiantFrame(matPair images)
{
    matPair grayImages;
    // convert image to grayscale
    cvtColor(images.left, grayImages.left, CV_BGR2GRAY);
    cvtColor(images.right, grayImages.right, CV_BGR2GRAY);
    int heightSize = 350;
    float heightScale = images.left.size().height/(float)heightSize;

    if(images.left.size().height>heightSize)
    {
          qDebug()<<"------------------------------------------\n\n\n\n\n"<<"image height was"<<images.left.size().height<<"so we scaled it and"<<"the scale factor is"<<heightScale;
          grayImages.left = ScaleImage(grayImages.left,heightSize, true);
          grayImages.right = ScaleImage(grayImages.right,heightSize, true);
    }
    else
    {
            qDebug()<<"--------------------------------------\n\n\n\n\ndidnt scale the image since it was too smal\n\n\n\n--------------------------------------";
            heightScale = 1;
    }
    shiftInfo info = gradiantShiftAndDistortion(grayImages);

    int finalDx = 0;
    int finalDy = info.dy*heightScale;
    images.left = cropImage(images.left,finalDx,finalDy);
    images.right = cropImage(images.right,finalDx,finalDy);
    return images;
}

matPair Rectify::LocalMaxima(matPair images)
{
    int histogramSize = 121; //Keep this an odd number or stuff might fail.
    double histogramScaleX;
    double histogramScaleY;

    Vec4i facesROI = findROI(images.left);
    qDebug()<<"\n\n\n\n\n\n\n----------------------------------------------------------------\n"<<"Image size is "<<images.left.size().width<<"x"<<images.left.size().height<<"\n"<<"Found faces in the box with corners ("<<facesROI[0]<<","<<facesROI[1]<<") and ("<<facesROI[2]<<","<<facesROI[3]<<")"<<"\n\n\n\n\n\n\n----------------------------------------------------------------\n";

    int numberOfSquares;//Note that this is really the squareroot of the number of squares.
                              //Also since we dont want to select the squares in the border
                              //numberOfSquares need to be greater than 2.
                              //we will gather our data in a histogram object to see where the maxima are.
    //These 2 are really the number of squares our big square is composed of.
    int maxX;
    int maxY;
    int squareWidth;
    int squareHeight;
    //the faces roi has width or height 0 so its empty
    if (facesROI[2] == 0 || facesROI[3] == 0)
    {
            numberOfSquares = 10;
            maxX = 1;
            maxY = 2;
            squareWidth = 7;
            squareHeight = 6;
    }
    else
    {
            numberOfSquares = 100;
            maxX = (facesROI[0]*numberOfSquares)/images.left.size().width;
            maxY = (facesROI[1]*numberOfSquares)/images.left.size().height;
            squareWidth = (facesROI[2]*numberOfSquares)/images.left.size().width;
            squareHeight = (facesROI[3]*numberOfSquares)/images.left.size().height;
    }
    //creates a blank histogram that is 121X121 big
    histogram *hist = new histogram(histogramSize, histogramSize);

    qDebug()<<"We are useing (x,y): ("<<maxX<<","<<maxY<<")";
    for(int res = 50; res < 60; res++)
    {
         // Now we search for the local maxima of the image scaled to a resolution of res.
         matPair scaledImages;
         //scale left and right images
         scaledImages.left = ScaleImage(images.left,res, true);
         scaledImages.right = ScaleImage(images.right,res, true);

         //returns a vector with the local maxima (peaks) of the input images.
         //A local peak is a data sample that is either larger than
         //its two neighboring samples or is equal to Inf.
         //Non-Inf signal endpoints are excluded. If a peak is flat,
         //the function returns only the point with the lowest index.
         vector<Vec2i> pointsVector = findLocalMaxima(scaledImages.left,scaledImages.right,-scaledImages.left.size().width/10,(scaledImages.left.size().width*2)/3,-scaledImages.left.size().height/5,scaledImages.left.size().height/5,
                                      0.75,0.125,0,(maxY*scaledImages.right.size().height)/numberOfSquares,scaledImages.left.size().width-1,((maxX+squareWidth)*scaledImages.right.size().width)/numberOfSquares,
                                      scaledImages.left.size().height-1,((maxY+squareHeight)*scaledImages.right.size().height)/numberOfSquares,0,(maxX*scaledImages.right.size().width)/numberOfSquares,15);
         histogramScaleX = histogramSize/(double)((2*scaledImages.left.size().width)-1);
         histogramScaleY = histogramSize/(double)((2*scaledImages.right.size().height)-1);

         //adds points from pointsVector into the histogram
         while(pointsVector.size() != 0)
         {
               hist->add(pointsVector.back()[0]*histogramScaleX+(histogramSize/2), pointsVector.back()[1]*histogramScaleY+(histogramSize/2));
               pointsVector.pop_back();
         }
    }
    if(hist->numberOfElements() == 0)
    {
          return images;
    }
    histogramScaleX = histogramSize/(double)((2*images.left.size().width)-1);
    histogramScaleY = histogramSize/(double)((2*images.left.size().height)-1);

    int dy = hist->getHighestColumn();

    //get the middle value of the collum dy
    int dx = hist->getMedianOfColumn(dy);
    //get the middle value of the row dx
    dy = hist->getMedianOfRow(dx);
    qDebug()<<"Median value:(x,y): ("<<dx<<","<<dy<<")";
    dx = (dx-(histogramSize/2))/histogramScaleX;
    dy = (dy-(histogramSize/2))/histogramScaleY;

    qDebug()<<"Shift by"<<dx<<dy;
    qDebug()<<hist->toString();

    //crops the images based on dx and dy
    images.left = cropImage(images.left,dx,-dy);
    images.right = cropImage(images.right,-dx,dy);

    return images;
}

void Rectify::contourCropDiff(matPair images, int &left, int &top, int &right, int &bottom)
{
        top = 0;
        bottom = 0;
        left = 0;
        right = 0;
        Mat diff = getThresholdedDiff(images);
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        findContours(diff, contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
        for (int i = 0; i< contours.size();i++)
        {
                if(contourArea(contours[i]) > diff.cols*diff.rows*0.02)
                {
                        Mat mask = Mat::zeros(diff.size(), CV_8UC1);
                        drawContours(mask,contours,i,Scalar(255),CV_FILLED);
                        int contourLeft = 0;
                        int contourRight = 0;
                        if(isVerticalRectangle(contours[i], mask, &contourLeft, &contourRight))
                        {
                                left = max(left, contourLeft);
                                right = max(right, contourRight);
                        }
                }
        }
        return;
}

//left, top, right and bottom contain the cropping info for the images.
void Rectify::contourCropGray(matPair images, int &left, int &top, int &right, int &bottom)
{
        top = 0;
        bottom = 0;
        left = 0;
        right = 0;

        vector<vector<Point> > contoursL;
        vector<vector<Point> > contoursR;
        vector<Vec4i> hierarchyL;
        vector<Vec4i> hierarchyR;
        Mat grayThresholdL = thresholdGrayToWhite(images.left);
        Mat grayThresholdR = thresholdGrayToWhite(images.right);
        findContours(grayThresholdL, contoursL,hierarchyL, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
        findContours(grayThresholdR, contoursR,hierarchyR, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));

                for (int i = 0; i< contoursL.size();i++)
                {
                        int areaL = contourArea(contoursL[i]);
                        if (contourArea(contoursL[i]) > 0.02*images.left.cols*images.left.rows)
                        {
                                vector<Point> convex_hull;
                                convexHull(contoursL[i], convex_hull);
                                int convexHullArea = contourArea(convex_hull);
                                Rect contourRect = boundingRect(contoursL[i]);
                                bool isConvex = areaL/(double)convexHullArea > 0.75;
                                bool isAtTop = contourRect.y < 0.05*images.left.rows;
                                bool isAtBottom = contourRect.y+contourRect.height > 0.95*images.left.rows;
                                bool isShortAndWide = contourRect.width > 2*contourRect.height;
                                if(isConvex && (isAtTop || isAtBottom) && isShortAndWide)
                                {
                                        if(isAtTop)
                                        {
                                                top = max(top, contourRect.y+contourRect.height);
                                        }
                                        else
                                        {
                                                bottom = max(bottom, images.left.rows-contourRect.y);
                                        }
                                }
                        }
                }
                for (int i = 0; i< contoursR.size();i++)
                {
                        int areaR = contourArea(contoursR[i]);
                        if (contourArea(contoursR[i]) > 0.02*images.right.cols*images.right.rows)
                        {
                                vector<Point> convex_hull;
                                convexHull(contoursR[i], convex_hull);
                                int convexHullArea = contourArea(convex_hull);
                                Rect contourRect = boundingRect(contoursR[i]);
                                bool isConvex = areaR/(double)convexHullArea > 0.75;
                                bool isAtTop = contourRect.y < 0.05*images.right.rows;
                                bool isAtBottom = contourRect.y+contourRect.height > 0.95*images.right.rows;
                                bool isShortAndWide = contourRect.width > 2*contourRect.height;
                                if(isConvex && (isAtTop || isAtBottom) && isShortAndWide)
                                {
                                        if(isAtTop)
                                        {
                                                top = max(top, contourRect.y+contourRect.height);
                                        }
                                        else
                                        {
                                                bottom = max(bottom, images.right.rows-contourRect.y);
                                        }
                                }
                        }

                }
    RectPair.left = cropImageBorders(images.left,0,right,0,left);
    RectPair.right = cropImageBorders(images.right,0,right,0,left);

}
<commit_msg>even more commenting<commit_after>#include "Rectify.h"
using namespace std;
using namespace cv;
Rectify::Rectify(matPair inputPair)
{
    RectPair.left = inputPair.left;
    RectPair.right = inputPair.right;
    qDebug()<<"finding local maxima";
    RectPair = LocalMaxima(RectPair);
    qDebug()<<"removing borders";
    RectPair = BorderRemoveal(RectPair);
    qDebug()<<"gradiant frame";
    RectPair = GradiantFrame(RectPair);
    int top = 0;
    int bottom = 0;
    int left = 0;
    int right = 0;
    qDebug()<<"contour crop diff";
    contourCropDiff(RectPair,left,top,right,bottom);
    top = 0;
    bottom = 0;
    left = 0;
    right = 0;
    qDebug()<<"contour crop gray";
    contourCropGray(RectPair,left,top,right,bottom);
}

matPair Rectify::getCroppedPair()
{
    return RectPair;
}

matPair Rectify::GradiantFrame(matPair images)
{
    matPair grayImages;
    // convert image to grayscale
    cvtColor(images.left, grayImages.left, CV_BGR2GRAY);
    cvtColor(images.right, grayImages.right, CV_BGR2GRAY);
    int heightSize = 350;
    float heightScale = images.left.size().height/(float)heightSize;

    if(images.left.size().height>heightSize)
    {
          qDebug()<<"------------------------------------------\n\n\n\n\n"<<"image height was"<<images.left.size().height<<"so we scaled it and"<<"the scale factor is"<<heightScale;
          grayImages.left = ScaleImage(grayImages.left,heightSize, true);
          grayImages.right = ScaleImage(grayImages.right,heightSize, true);
    }
    else
    {
            qDebug()<<"--------------------------------------\n\n\n\n\ndidnt scale the image since it was too smal\n\n\n\n--------------------------------------";
            heightScale = 1;
    }
    shiftInfo info = gradiantShiftAndDistortion(grayImages);

    int finalDx = 0;
    int finalDy = info.dy*heightScale;
    images.left = cropImage(images.left,finalDx,finalDy);
    images.right = cropImage(images.right,finalDx,finalDy);
    return images;
}

matPair Rectify::LocalMaxima(matPair images)
{
    int histogramSize = 121; //Keep this an odd number or stuff might fail.
    double histogramScaleX;
    double histogramScaleY;

    Vec4i facesROI = findROI(images.left);
    qDebug()<<"\n\n\n\n\n\n\n----------------------------------------------------------------\n"<<"Image size is "<<images.left.size().width<<"x"<<images.left.size().height<<"\n"<<"Found faces in the box with corners ("<<facesROI[0]<<","<<facesROI[1]<<") and ("<<facesROI[2]<<","<<facesROI[3]<<")"<<"\n\n\n\n\n\n\n----------------------------------------------------------------\n";

    int numberOfSquares;//Note that this is really the squareroot of the number of squares.
                              //Also since we dont want to select the squares in the border
                              //numberOfSquares need to be greater than 2.
                              //we will gather our data in a histogram object to see where the maxima are.
    //These 2 are really the number of squares our big square is composed of.
    int maxX;
    int maxY;
    int squareWidth;
    int squareHeight;
    //the faces roi has width or height 0 so its empty
    if (facesROI[2] == 0 || facesROI[3] == 0)
    {
            numberOfSquares = 10;
            maxX = 1;
            maxY = 2;
            squareWidth = 7;
            squareHeight = 6;
    }
    else
    {
            numberOfSquares = 100;
            maxX = (facesROI[0]*numberOfSquares)/images.left.size().width;
            maxY = (facesROI[1]*numberOfSquares)/images.left.size().height;
            squareWidth = (facesROI[2]*numberOfSquares)/images.left.size().width;
            squareHeight = (facesROI[3]*numberOfSquares)/images.left.size().height;
    }
    //creates a blank histogram that is 121X121 big
    histogram *hist = new histogram(histogramSize, histogramSize);

    qDebug()<<"We are useing (x,y): ("<<maxX<<","<<maxY<<")";
    for(int res = 50; res < 60; res++)
    {
         // Now we search for the local maxima of the image scaled to a resolution of res.
         matPair scaledImages;
         //scale left and right images
         scaledImages.left = ScaleImage(images.left,res, true);
         scaledImages.right = ScaleImage(images.right,res, true);

         //returns a vector with the local maxima (peaks) of the input images.
         //A local peak is a data sample that is either larger than
         //its two neighboring samples or is equal to Inf.
         //Non-Inf signal endpoints are excluded. If a peak is flat,
         //the function returns only the point with the lowest index.
         vector<Vec2i> pointsVector = findLocalMaxima(scaledImages.left,scaledImages.right,-scaledImages.left.size().width/10,(scaledImages.left.size().width*2)/3,-scaledImages.left.size().height/5,scaledImages.left.size().height/5,
                                      0.75,0.125,0,(maxY*scaledImages.right.size().height)/numberOfSquares,scaledImages.left.size().width-1,((maxX+squareWidth)*scaledImages.right.size().width)/numberOfSquares,
                                      scaledImages.left.size().height-1,((maxY+squareHeight)*scaledImages.right.size().height)/numberOfSquares,0,(maxX*scaledImages.right.size().width)/numberOfSquares,15);
         histogramScaleX = histogramSize/(double)((2*scaledImages.left.size().width)-1);
         histogramScaleY = histogramSize/(double)((2*scaledImages.right.size().height)-1);

         //adds points from pointsVector into the histogram
         while(pointsVector.size() != 0)
         {
               hist->add(pointsVector.back()[0]*histogramScaleX+(histogramSize/2), pointsVector.back()[1]*histogramScaleY+(histogramSize/2));
               pointsVector.pop_back();
         }
    }
    //if there are no elements in the histogram it returns the image as it is
    if(hist->numberOfElements() == 0)
    {
          return images;
    }
    histogramScaleX = histogramSize/(double)((2*images.left.size().width)-1);
    histogramScaleY = histogramSize/(double)((2*images.left.size().height)-1);

    //get the highest column
    int dy = hist->getHighestColumn();

    //get the middle value of the column dy
    int dx = hist->getMedianOfColumn(dy);
    //get the middle value of the row dx
    dy = hist->getMedianOfRow(dx);
    qDebug()<<"Median value:(x,y): ("<<dx<<","<<dy<<")";
    dx = (dx-(histogramSize/2))/histogramScaleX;
    dy = (dy-(histogramSize/2))/histogramScaleY;

    qDebug()<<"Shift by"<<dx<<dy;
    qDebug()<<hist->toString();

    //crops the images based on dx and dy
    images.left = cropImage(images.left,dx,-dy);
    images.right = cropImage(images.right,-dx,dy);

    return images;
}

void Rectify::contourCropDiff(matPair images, int &left, int &top, int &right, int &bottom)
{
        top = 0;
        bottom = 0;
        left = 0;
        right = 0;
        Mat diff = getThresholdedDiff(images);
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        //finds shapes in the image

        //CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships.
        //CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments
        //and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.
        //CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours.
        findContours(diff, contours,hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));

        for (int i = 0; i< contours.size();i++)
        {
                //checks if the calculateed contour area is bigger than diff.cols*diff.rows*0.02
                if(contourArea(contours[i]) > diff.cols*diff.rows*0.02)
                {
                        Mat mask = Mat::zeros(diff.size(), CV_8UC1);
                        //Draws contours outlines or filled contours.
                        drawContours(mask,contours,i,Scalar(255),CV_FILLED);
                        int contourLeft = 0;
                        int contourRight = 0;
                        if(isVerticalRectangle(contours[i], mask, &contourLeft, &contourRight))
                        {
                                left = max(left, contourLeft);
                                right = max(right, contourRight);
                        }
                }
        }
        return;
}

//left, top, right and bottom contain the cropping info for the images.
void Rectify::contourCropGray(matPair images, int &left, int &top, int &right, int &bottom)
{
        top = 0;
        bottom = 0;
        left = 0;
        right = 0;
        //shapes and seperate areas in left image
        vector<vector<Point> > contoursL;
        //shapes and seperate areas in right image
        vector<vector<Point> > contoursR;

        //vectors, containing information about the left amd right image topology.
        //It has as many elements as the number of contours.
        //For each i-th contour contours[i] , the elements hierarchy[i][0] ,
        //hiearchy[i][1] , hiearchy[i][2] , and hiearchy[i][3] are set to
        //0-based indices in contours of the next and previous contours
        //at the same hierarchical level, the first child contour and the parent
        //contour, respectively. If for the contour i there are no next,
        //previous, parent, or nested contours, the corresponding elements of
        //hierarchy[i] will be negative
        vector<Vec4i> hierarchyL;
        vector<Vec4i> hierarchyR;

        //replaces all pixels in the input image with luminance greater than set threshold with the value for white (white)
        Mat grayThresholdL = thresholdGrayToWhite(images.left);
        Mat grayThresholdR = thresholdGrayToWhite(images.right);
        //finds shapes in the image

        //CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships.
        //CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments
        //and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.
        //CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours.
        findContours(grayThresholdL, contoursL,hierarchyL, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));
        //finds shapes in the image

        //CV_RETR_LIST retrieves all of the contours without establishing any hierarchical relationships.
        //CV_CHAIN_APPROX_SIMPLE compresses horizontal, vertical, and diagonal segments
        //and leaves only their end points. For example, an up-right rectangular contour is encoded with 4 points.
        //CV_RETR_TREE retrieves all of the contours and reconstructs a full hierarchy of nested contours.
        findContours(grayThresholdR, contoursR,hierarchyR, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0,0));

                for (int i = 0; i< contoursL.size();i++)
                {
                        int areaL = contourArea(contoursL[i]);
                        if (contourArea(contoursL[i]) > 0.02*images.left.cols*images.left.rows)
                        {
                                vector<Point> convex_hull;
                                convexHull(contoursL[i], convex_hull);
                                int convexHullArea = contourArea(convex_hull);
                                Rect contourRect = boundingRect(contoursL[i]);
                                bool isConvex = areaL/(double)convexHullArea > 0.75;
                                bool isAtTop = contourRect.y < 0.05*images.left.rows;
                                bool isAtBottom = contourRect.y+contourRect.height > 0.95*images.left.rows;
                                bool isShortAndWide = contourRect.width > 2*contourRect.height;
                                if(isConvex && (isAtTop || isAtBottom) && isShortAndWide)
                                {
                                        if(isAtTop)
                                        {
                                                top = max(top, contourRect.y+contourRect.height);
                                        }
                                        else
                                        {
                                                bottom = max(bottom, images.left.rows-contourRect.y);
                                        }
                                }
                        }
                }
                for (int i = 0; i< contoursR.size();i++)
                {
                        //Calculates a contour area.
                        int areaR = contourArea(contoursR[i]);
                        if (contourArea(contoursR[i]) > 0.02*images.right.cols*images.right.rows)
                        {
                                vector<Point> convex_hull;
                                //The functions find the convex hull of a 2D point set
                                //using the Sklansky’s algorithm that has O(N logN)
                                //complexity in the current implementation.
                                convexHull(contoursR[i], convex_hull);
                                //Calculates a contour area.
                                int convexHullArea = contourArea(convex_hull);
                                //Calculates the up-right bounding rectangle of a point set.
                                Rect contourRect = boundingRect(contoursR[i]);
                                bool isConvex = areaR/(double)convexHullArea > 0.75;
                                bool isAtTop = contourRect.y < 0.05*images.right.rows;
                                bool isAtBottom = contourRect.y+contourRect.height > 0.95*images.right.rows;
                                bool isShortAndWide = contourRect.width > 2*contourRect.height;
                                if(isConvex && (isAtTop || isAtBottom) && isShortAndWide)
                                {
                                        if(isAtTop)
                                        {
                                                top = max(top, contourRect.y+contourRect.height);
                                        }
                                        else
                                        {
                                                bottom = max(bottom, images.right.rows-contourRect.y);
                                        }
                                }
                        }

                }
    //crops image pair
    RectPair.left = cropImageBorders(images.left,0,right,0,left);
    RectPair.right = cropImageBorders(images.right,0,right,0,left);

}
<|endoftext|>


<commit_before>#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QStringBuilder>
#include <QVector>
#include <functional>

#include "request.hpp"
#include "response.hpp"
#include "context.hpp"

//!
//! \brief The HttpServer class
//! Http (unsecure) server class
//!
class HttpServer : public QObject
{
    Q_OBJECT

public:
    HttpServer(QObject *parent = NULL);
    ~HttpServer();

    bool compose(quint64 port, QHostAddress address = QHostAddress::Any);

private:
    QTcpServer m_tcp_server;
    quint64 m_port;
    QHostAddress m_address;
    QObject *m_parent;
};

inline HttpServer::HttpServer(QObject *parent)
{
    m_parent = parent;
};

inline HttpServer::~HttpServer()
{

};

inline bool HttpServer::compose(quint64 port, QHostAddress address)
{
    m_port = port;
    m_address = address;

    if (!m_tcp_server.listen(address, port)) {
        qDebug() << "failed to start listening";
        return false;
    }

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        // TODO: create ctx (need parent's ref here?)
    });

    return true;
};

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
    Q_OBJECT

    using void_f = std::function<void()>;
    using void_ff = std::function<void(void_f prev)>;
    using next_prev_f = std::function<void(Context &ctx, void_ff next, void_f prev)>;
    using next_f = std::function<void(Context &ctx, void_f next)>;
    using final_f =  std::function<void(Context &ctx)>;

public:
    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    bool listen(HttpServer *server);
    void tester();

private:
    QCoreApplication app;
    HttpServer *http;
};

inline Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

inline Recurse::~Recurse()
{
    delete http;
};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
inline bool Recurse::listen(quint64 port, QHostAddress address)
{
    http = new HttpServer(this);
    http->compose(port, address);

    return app.exec();
};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! overloaded function
//!
//! \param server pointer to the HttpServer instance
//!
//! \return true on success
//!
inline bool Recurse::listen(HttpServer *server)
{
    http = server;

    return app.exec();
};

inline void Recurse::tester()
{
    qDebug() << "test function";
};
<commit_msg>add signal 'createContext' and its corresponding slot and connect Recurse to it<commit_after>#include <QCoreApplication>
#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QStringBuilder>
#include <QVector>
#include <functional>

#include "request.hpp"
#include "response.hpp"
#include "context.hpp"

//!
//! \brief The HttpServer class
//! Http (unsecure) server class
//!
class HttpServer : public QObject
{
    Q_OBJECT

public:
    HttpServer(QObject *parent = NULL);
    ~HttpServer();

    bool compose(quint64 port, QHostAddress address = QHostAddress::Any);

private:
    QTcpServer m_tcp_server;
    quint64 m_port;
    QHostAddress m_address;
    QObject *m_parent;

signals:
    void createContext();
};

inline HttpServer::HttpServer(QObject *parent)
{
    m_parent = parent;
};

inline HttpServer::~HttpServer()
{

};

inline bool HttpServer::compose(quint64 port, QHostAddress address)
{
    m_port = port;
    m_address = address;

    if (!m_tcp_server.listen(address, port)) {
        qDebug() << "failed to start listening";
        return false;
    }

    connect(&m_tcp_server, &QTcpServer::newConnection, [this] {
        qDebug() << "client connected";

        emit createContext();
        // TODO: create ctx (need parent's ref here?)
    });

    return true;
};

//!
//! \brief The Recurse class
//! main class of the app
//!
class Recurse : public QObject
{
    Q_OBJECT

    using void_f = std::function<void()>;
    using void_ff = std::function<void(void_f prev)>;
    using next_prev_f = std::function<void(Context &ctx, void_ff next, void_f prev)>;
    using next_f = std::function<void(Context &ctx, void_f next)>;
    using final_f =  std::function<void(Context &ctx)>;

public:
    Recurse(int & argc, char ** argv, QObject *parent = NULL);
    ~Recurse();

    bool listen(quint64 port, QHostAddress address = QHostAddress::Any);
    bool listen(HttpServer *server);

public slots:
    bool createContext();

private:
    QCoreApplication app;
    HttpServer *http;
};

inline Recurse::Recurse(int & argc, char ** argv, QObject *parent) : app(argc, argv)
{
    Q_UNUSED(parent);
};

inline Recurse::~Recurse()
{
    delete http;
};

//!
//! \brief Recurse::createContext
//! creates new recurse context for a tcp session
//!
//! \return true on success
//!
inline bool Recurse::createContext()
{
    qDebug() << "creating new context";
    return true;
};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! \param port tcp server port
//! \param address tcp server listening address
//!
//! \return true on success
//!
inline bool Recurse::listen(quint64 port, QHostAddress address)
{
    // set HttpServer instance, send reference to this object and prepare http connection
    http = new HttpServer(this);
    http->compose(port, address);

    // connect HttpServer signal 'createContext' to this class' 'createContext' slot
    connect(http, &HttpServer::createContext, this, &Recurse::createContext);
    return app.exec();
};

//!
//! \brief Recurse::listen
//! listen for tcp requests
//!
//! overloaded function
//!
//! \param server pointer to the HttpServer instance
//!
//! \return true on success
//!
inline bool Recurse::listen(HttpServer *server)
{
    http = server;

    // connect HttpServer signal 'createContext' to this class' 'createContext' slot
    connect(http, &HttpServer::createContext, this, &Recurse::createContext);
    return app.exec();
};

<|endoftext|>


<commit_before>// Copyright (c) 2012, Cloudera, inc.

#include <utility>

#include "tablet/deltafile.h"
#include "tablet/deltamemstore.h"
#include "util/hexdump.h"
#include "util/status.h"

namespace kudu { namespace tablet {

struct EncodedKeySlice : public Slice {
public:
  explicit EncodedKeySlice(uint32_t row_idx) :
    Slice(reinterpret_cast<const char *>(&buf_int_),
          sizeof(uint32_t)),
    buf_int_(htonl(row_idx))
  {
  }

private:
  uint32_t buf_int_;
};

////////////////////////////////////////////////////////////
// DeltaMemStore implementation
////////////////////////////////////////////////////////////

DeltaMemStore::DeltaMemStore(const Schema &schema) :
  schema_(schema),
  arena_(8*1024, 1*1024*1024)
{
}

void DeltaMemStore::Update(uint32_t row_idx,
                           const RowDelta &update) {
  EncodedKeySlice key(row_idx);

  btree::PreparedMutation<btree::BTreeTraits> mutation(key);
  mutation.Prepare(&tree_);
  if (mutation.exists()) {
    // This row was already updated - just merge the new updates
    // in with the old.
    Slice cur_val = mutation.current_mutable_value();

    RowDelta cur_delta = DecodeDelta(&cur_val);
    cur_delta.MergeUpdatesFrom(schema_, update, &arena_);
  } else {
    // This row hasn't been updated. Create a new delta for it.
    // Copy the update into the arena.
    // TODO: no need to copy the update - just need to copy the
    // referred-to data!
    RowDelta copied = update.CopyToArena(schema_, &arena_);
    Slice new_val(reinterpret_cast<char *>(&copied), sizeof(copied));
    CHECK(mutation.Insert(new_val));
  }
}

Status DeltaMemStore::ApplyUpdates(
  size_t col_idx, uint32_t start_row,
  ColumnBlock *dst) const
{
  DCHECK_EQ(schema_.column(col_idx).type_info().type(),
            dst->type_info().type());

  scoped_ptr<DMSTreeIter> iter(tree_.NewIterator());

  EncodedKeySlice start_key(start_row);

  bool exact;
  if (!iter->SeekAtOrAfter(start_key, &exact)) {
    // No updates matching this row or higher
    return Status::OK();
  }

  while (iter->IsValid()) {
    Slice key, val;
    iter->GetCurrentEntry(&key, &val);
    uint32_t decoded_key = DecodeKey(key);
    DCHECK_GE(decoded_key, start_row);
    if (decoded_key > start_row + dst->size()) {
      break;
    }

    uint32_t rel_idx = decoded_key - start_row;

    RowDelta delta = DecodeDelta(&val);
    delta.ApplyColumnUpdate(schema_, col_idx,
                            dst->cell_ptr(rel_idx));
    iter->Next();
  }

  return Status::OK();
}

Status DeltaMemStore::FlushToFile(DeltaFileWriter *dfw) const {
  scoped_ptr<DMSTreeIter> iter(tree_.NewIterator());
  iter->SeekToStart();
  while (iter->IsValid()) {
    Slice key, val;
    iter->GetCurrentEntry(&key, &val);
    uint32_t row_idx = DecodeKey(key);
    RowDelta delta = DecodeDelta(&val);
    dfw->AppendDelta(row_idx, delta);
    iter->Next();
  }
  return Status::OK();
}

uint32_t DeltaMemStore::DecodeKey(const Slice &key) const {
  DCHECK_EQ(sizeof(uint32_t), key.size());
  return ntohl(*reinterpret_cast<const uint32_t *>(key.data()));
}

RowDelta DeltaMemStore::DecodeDelta(Slice *val) const {
  DCHECK_EQ(sizeof(RowDelta), val->size());
  return *reinterpret_cast<RowDelta *>(val->mutable_data());
}

} // namespace tablet
} // namespace kudu
<commit_msg>deltamemstore: fix an off-by-one in calculating application of deltas<commit_after>// Copyright (c) 2012, Cloudera, inc.

#include <utility>

#include "tablet/deltafile.h"
#include "tablet/deltamemstore.h"
#include "util/hexdump.h"
#include "util/status.h"

namespace kudu { namespace tablet {

struct EncodedKeySlice : public Slice {
public:
  explicit EncodedKeySlice(uint32_t row_idx) :
    Slice(reinterpret_cast<const char *>(&buf_int_),
          sizeof(uint32_t)),
    buf_int_(htonl(row_idx))
  {
  }

private:
  uint32_t buf_int_;
};

////////////////////////////////////////////////////////////
// DeltaMemStore implementation
////////////////////////////////////////////////////////////

DeltaMemStore::DeltaMemStore(const Schema &schema) :
  schema_(schema),
  arena_(8*1024, 1*1024*1024)
{
}

void DeltaMemStore::Update(uint32_t row_idx,
                           const RowDelta &update) {
  EncodedKeySlice key(row_idx);

  btree::PreparedMutation<btree::BTreeTraits> mutation(key);
  mutation.Prepare(&tree_);
  if (mutation.exists()) {
    // This row was already updated - just merge the new updates
    // in with the old.
    Slice cur_val = mutation.current_mutable_value();

    RowDelta cur_delta = DecodeDelta(&cur_val);
    cur_delta.MergeUpdatesFrom(schema_, update, &arena_);
  } else {
    // This row hasn't been updated. Create a new delta for it.
    // Copy the update into the arena.
    // TODO: no need to copy the update - just need to copy the
    // referred-to data!
    RowDelta copied = update.CopyToArena(schema_, &arena_);
    Slice new_val(reinterpret_cast<char *>(&copied), sizeof(copied));
    CHECK(mutation.Insert(new_val));
  }
}

Status DeltaMemStore::ApplyUpdates(
  size_t col_idx, uint32_t start_row,
  ColumnBlock *dst) const
{
  DCHECK_EQ(schema_.column(col_idx).type_info().type(),
            dst->type_info().type());

  scoped_ptr<DMSTreeIter> iter(tree_.NewIterator());

  EncodedKeySlice start_key(start_row);

  bool exact;
  if (!iter->SeekAtOrAfter(start_key, &exact)) {
    // No updates matching this row or higher
    return Status::OK();
  }

  while (iter->IsValid()) {
    Slice key, val;
    iter->GetCurrentEntry(&key, &val);
    uint32_t decoded_key = DecodeKey(key);
    DCHECK_GE(decoded_key, start_row);
    if (decoded_key >= start_row + dst->size()) {
      break;
    }

    uint32_t rel_idx = decoded_key - start_row;

    RowDelta delta = DecodeDelta(&val);
    delta.ApplyColumnUpdate(schema_, col_idx,
                            dst->cell_ptr(rel_idx));
    iter->Next();
  }

  return Status::OK();
}

Status DeltaMemStore::FlushToFile(DeltaFileWriter *dfw) const {
  scoped_ptr<DMSTreeIter> iter(tree_.NewIterator());
  iter->SeekToStart();
  while (iter->IsValid()) {
    Slice key, val;
    iter->GetCurrentEntry(&key, &val);
    uint32_t row_idx = DecodeKey(key);
    RowDelta delta = DecodeDelta(&val);
    dfw->AppendDelta(row_idx, delta);
    iter->Next();
  }
  return Status::OK();
}

uint32_t DeltaMemStore::DecodeKey(const Slice &key) const {
  DCHECK_EQ(sizeof(uint32_t), key.size());
  return ntohl(*reinterpret_cast<const uint32_t *>(key.data()));
}

RowDelta DeltaMemStore::DecodeDelta(Slice *val) const {
  DCHECK_EQ(sizeof(RowDelta), val->size());
  return *reinterpret_cast<RowDelta *>(val->mutable_data());
}

} // namespace tablet
} // namespace kudu
<|endoftext|>


<commit_before>// This is core/vnl/algo/vnl_lsqr.cxx
#ifdef VCL_NEEDS_PRAGMA_INTERFACE
#pragma implementation
#endif
//
// vnl_lsqr
// Author: David Capel
// Created: July 2000
//
//-----------------------------------------------------------------------------

#include "vnl_lsqr.h"
#include <vcl_vector.h>
#include <vcl_iostream.h>
#include <vnl/vnl_vector_ref.h>

#include <vnl/algo/vnl_netlib.h> // lsqr_()

#include "lsqrBase.h"

class lsqrVNL : public lsqrBase
{
public:

  lsqrVNL()
    {
    this->ls_ = NULL;
    }

  virtual ~lsqrVNL()
    {
    }

  /**
   * computes y = y + A*x without altering x,
   * where A is a matrix of dimensions A[m][n].
   * The size of the vector x is n.
   * The size of the vector y is m.
   */
  void Aprod1(unsigned int m, unsigned int n, const double * x, double * y ) const
    {
    vnl_vector_ref<double> x_ref(n, const_cast<double*>(x) );
    vnl_vector_ref<double> y_ref(m,y);

    vnl_vector_ref<double> tmp(m,rw);
    this->ls_->multiply(x_ref, tmp);
    y_ref += tmp;
    }

  /**
   * computes x = x + A'*y without altering y,
   * where A is a matrix of dimensions A[m][n].
   * The size of the vector x is n.
   * The size of the vector y is m.
   */
  void Aprod2(unsigned int m, unsigned int n, double * x, const double * y ) const
    {
    vnl_vector_ref<double> x_ref(n,x);
    vnl_vector_ref<double> y_ref(m, const_cast<double*>( y ) );

    vnl_vector_ref<double> tmp(n,rw);
    this->ls_->transpose_multiply(y_ref, tmp);
    x_ref += tmp;
    }

  /** Set the linear system to be solved A*x = b. */
  void SetLinearSystem( vnl_linear_system * inls )
    {
    this->ls_ = inls;
    }

  void SetWorkingSpace( double * inrw )
    {
    this->rw = inrw;
    }

private:

  vnl_linear_system * ls_;

  double * rw;
};

vnl_lsqr::~vnl_lsqr()
{
}

// Requires number_of_residuals() of workspace in rw.
int vnl_lsqr::aprod_(long* mode, long* m, long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata)
{
  //
  // THIS CODE IS DEPRECATED
  // THE FUNCTIONALITY HAS BEEN MOVED TO THE lsqrVNL class above.
  // THE FUNCTIONS IS CONSERVED HERE ONLY FOR BACKWARD COMPATIBILITY.
  //
  vnl_lsqr* self = static_cast<vnl_lsqr*>(userdata);

  //  If MODE = 1, compute  y = y + A*x.
  //  If MODE = 2, compute  x = x + A(transpose)*y.

  vnl_vector_ref<double> x_ref(*n,x);
  vnl_vector_ref<double> y_ref(*m,y);

  if (*mode == 1) {
    vnl_vector_ref<double> tmp(*m,rw);
    self->ls_->multiply(x_ref, tmp);
    y_ref += tmp;
  }
  else {
    vnl_vector_ref<double> tmp(*n,rw);
    self->ls_->transpose_multiply(y_ref, tmp);
    x_ref += tmp;
  }

  return 0;
}

int vnl_lsqr::minimize(vnl_vector<double>& result)
{
  long m = ls_->get_number_of_residuals();
  long n = ls_->get_number_of_unknowns();
  double damp = 0;
  long leniw = 1;
  long* iw = 0;
  long lenrw = m;
#ifdef __GNUC__
  double rw[m];
  double v[n];
  double w[n];
  double se[n];
#else
  vcl_vector<double> rw(m);
  vcl_vector<double> v(n);
  vcl_vector<double> w(n);
  vcl_vector<double> se(n);
#endif
  double atol = 0;
  double btol = 0;
  double conlim = 0;
  long nout = -1;
  double anorm, acond, rnorm, arnorm, xnorm;

  vnl_vector<double> rhs(m);
  ls_->get_rhs(rhs);

  lsqrVNL solver;

  solver.SetDamp( damp );
  solver.SetLinearSystem( this->ls_ );
  solver.SetWorkingSpace( &rw[0] );
  solver.SetMaximumNumberOfIterations( max_iter_ );
  solver.SetStandardErrorEstimates( &se[0] );
  solver.SetToleranceA( atol );
  solver.SetToleranceB( btol );

  solver.Solve( m, n, rhs.data_block(), result.data_block() );

#ifdef THIS_CODE_IS_DISABLED_BECAUSE_THE_LSQR_CODE_FROM_NETLIB_WAS_COPYRIGHTED_BY_ACM
  v3p_netlib_lsqr_(
        &m, &n, aprod_, &damp, &leniw, &lenrw, iw, &rw[0],
        rhs.data_block(), &v[0], &w[0], result.data_block(), &se[0],
        &atol, &btol, &conlim, &max_iter_, &nout, &return_code_,
        &num_iter_, &anorm, &acond, &rnorm, &arnorm, &xnorm,
        this);
#endif

  resid_norm_estimate_ = solver.GetFinalEstimateOfNormRbar();
  result_norm_estimate_ = solver.GetFinalEstimateOfNormOfX();
  A_condition_estimate_ = solver.GetConditionNumberEstimateOfAbar();
  return_code_ = solver.GetStoppingReason();
  num_iter_ = solver.GetNumberOfIterationsPerformed();
  anorm = solver.GetFrobeniusNormEstimateOfAbar();
  arnorm = solver.GetFinalEstimateOfNormOfResiduals();

#if 0
  vcl_cerr << "A Fro norm estimate      = " << anorm << vcl_endl
           << "A condition estimate     = " << acond << vcl_endl
           << "Residual norm estimate   = " << rnorm << vcl_endl
           << "A'(Ax - b) norm estimate = " << arnorm << vcl_endl
           << "x norm estimate          = " << xnorm << vcl_endl;
#endif

  // We should return the return code, as translate_return_code is public and
  // it is very misleading that the return code from this function can't be fed
  // into translate_return_code. (Brian Amberg)
  return return_code_;
}

void vnl_lsqr::diagnose_outcome(vcl_ostream& os) const
{
  translate_return_code(os, return_code_);
  os << __FILE__ " : residual norm estimate = " << resid_norm_estimate_ << vcl_endl
     << __FILE__ " : result norm estimate   = " << result_norm_estimate_ << vcl_endl
     << __FILE__ " : condition no. estimate = " << A_condition_estimate_ << vcl_endl
     << __FILE__ " : iterations             = " << num_iter_ << vcl_endl;
}

void vnl_lsqr::translate_return_code(vcl_ostream& os, int rc)
{
  const char* vnl_lsqr_reasons[] = {
   "x = 0  is the exact solution. No iterations were performed.",
   "The equations A*x = b are probably compatible.  "
       "Norm(A*x - b) is sufficiently small, given the "
       "values of ATOL and BTOL.",
   "The system A*x = b is probably not compatible.  "
       "A least-squares solution has been obtained that is "
       "sufficiently accurate, given the value of ATOL.",
   "An estimate of cond(Abar) has exceeded CONLIM.  "
       "The system A*x = b appears to be ill-conditioned.  "
       "Otherwise, there could be an error in subroutine APROD.",
   "The equations A*x = b are probably compatible.  "
       "Norm(A*x - b) is as small as seems reasonable on this machine.",
   "The system A*x = b is probably not compatible.  A least-squares "
       "solution has been obtained that is as accurate as seems "
       "reasonable on this machine.",
   "Cond(Abar) seems to be so large that there is no point in doing further "
       "iterations, given the precision of this machine. "
       "There could be an error in subroutine APROD.",
   "The iteration limit ITNLIM was reached."
  };

  if
    (rc < 0 || rc > 7) os << __FILE__ " : Illegal return code : " << rc << vcl_endl;
  else
    os << __FILE__ " : " << vnl_lsqr_reasons[rc] << vcl_endl;
}
<commit_msg>COMP: Moving unused variables inside #ifdef that disables the call to lsqr       function.<commit_after>// This is core/vnl/algo/vnl_lsqr.cxx
#ifdef VCL_NEEDS_PRAGMA_INTERFACE
#pragma implementation
#endif
//
// vnl_lsqr
// Author: David Capel
// Created: July 2000
//
//-----------------------------------------------------------------------------

#include "vnl_lsqr.h"
#include <vcl_vector.h>
#include <vcl_iostream.h>
#include <vnl/vnl_vector_ref.h>

#include <vnl/algo/vnl_netlib.h> // lsqr_()

#include "lsqrBase.h"

class lsqrVNL : public lsqrBase
{
public:

  lsqrVNL()
    {
    this->ls_ = NULL;
    }

  virtual ~lsqrVNL()
    {
    }

  /**
   * computes y = y + A*x without altering x,
   * where A is a matrix of dimensions A[m][n].
   * The size of the vector x is n.
   * The size of the vector y is m.
   */
  void Aprod1(unsigned int m, unsigned int n, const double * x, double * y ) const
    {
    vnl_vector_ref<double> x_ref(n, const_cast<double*>(x) );
    vnl_vector_ref<double> y_ref(m,y);

    vnl_vector_ref<double> tmp(m,rw);
    this->ls_->multiply(x_ref, tmp);
    y_ref += tmp;
    }

  /**
   * computes x = x + A'*y without altering y,
   * where A is a matrix of dimensions A[m][n].
   * The size of the vector x is n.
   * The size of the vector y is m.
   */
  void Aprod2(unsigned int m, unsigned int n, double * x, const double * y ) const
    {
    vnl_vector_ref<double> x_ref(n,x);
    vnl_vector_ref<double> y_ref(m, const_cast<double*>( y ) );

    vnl_vector_ref<double> tmp(n,rw);
    this->ls_->transpose_multiply(y_ref, tmp);
    x_ref += tmp;
    }

  /** Set the linear system to be solved A*x = b. */
  void SetLinearSystem( vnl_linear_system * inls )
    {
    this->ls_ = inls;
    }

  void SetWorkingSpace( double * inrw )
    {
    this->rw = inrw;
    }

private:

  vnl_linear_system * ls_;

  double * rw;
};

vnl_lsqr::~vnl_lsqr()
{
}

// Requires number_of_residuals() of workspace in rw.
int vnl_lsqr::aprod_(long* mode, long* m, long* n, double* x, double* y, long* /*leniw*/, long* /*lenrw*/, long* /*iw*/, double* rw, void* userdata)
{
  //
  // THIS CODE IS DEPRECATED
  // THE FUNCTIONALITY HAS BEEN MOVED TO THE lsqrVNL class above.
  // THE FUNCTIONS IS CONSERVED HERE ONLY FOR BACKWARD COMPATIBILITY.
  //
  vnl_lsqr* self = static_cast<vnl_lsqr*>(userdata);

  //  If MODE = 1, compute  y = y + A*x.
  //  If MODE = 2, compute  x = x + A(transpose)*y.

  vnl_vector_ref<double> x_ref(*n,x);
  vnl_vector_ref<double> y_ref(*m,y);

  if (*mode == 1) {
    vnl_vector_ref<double> tmp(*m,rw);
    self->ls_->multiply(x_ref, tmp);
    y_ref += tmp;
  }
  else {
    vnl_vector_ref<double> tmp(*n,rw);
    self->ls_->transpose_multiply(y_ref, tmp);
    x_ref += tmp;
  }

  return 0;
}

int vnl_lsqr::minimize(vnl_vector<double>& result)
{
  long m = ls_->get_number_of_residuals();
  long n = ls_->get_number_of_unknowns();
  double damp = 0;
  long leniw = 1;
  long* iw = 0;
  long lenrw = m;
#ifdef __GNUC__
  double rw[m];
  double v[n];
  double w[n];
  double se[n];
#else
  vcl_vector<double> rw(m);
  vcl_vector<double> v(n);
  vcl_vector<double> w(n);
  vcl_vector<double> se(n);
#endif
  double atol = 0;
  double btol = 0;
  double conlim = 0;
  long nout = -1;
  double anorm, arnorm;

  vnl_vector<double> rhs(m);
  ls_->get_rhs(rhs);

  lsqrVNL solver;

  solver.SetDamp( damp );
  solver.SetLinearSystem( this->ls_ );
  solver.SetWorkingSpace( &rw[0] );
  solver.SetMaximumNumberOfIterations( max_iter_ );
  solver.SetStandardErrorEstimates( &se[0] );
  solver.SetToleranceA( atol );
  solver.SetToleranceB( btol );

  solver.Solve( m, n, rhs.data_block(), result.data_block() );

#ifdef THIS_CODE_IS_DISABLED_BECAUSE_THE_LSQR_CODE_FROM_NETLIB_WAS_COPYRIGHTED_BY_ACM
  double acond, rnorm, xnorm;
  v3p_netlib_lsqr_(
        &m, &n, aprod_, &damp, &leniw, &lenrw, iw, &rw[0],
        rhs.data_block(), &v[0], &w[0], result.data_block(), &se[0],
        &atol, &btol, &conlim, &max_iter_, &nout, &return_code_,
        &num_iter_, &anorm, &acond, &rnorm, &arnorm, &xnorm,
        this);
#endif

  resid_norm_estimate_ = solver.GetFinalEstimateOfNormRbar();
  result_norm_estimate_ = solver.GetFinalEstimateOfNormOfX();
  A_condition_estimate_ = solver.GetConditionNumberEstimateOfAbar();
  return_code_ = solver.GetStoppingReason();
  num_iter_ = solver.GetNumberOfIterationsPerformed();
  anorm = solver.GetFrobeniusNormEstimateOfAbar();
  arnorm = solver.GetFinalEstimateOfNormOfResiduals();

#if 0
  vcl_cerr << "A Fro norm estimate      = " << anorm << vcl_endl
           << "A condition estimate     = " << acond << vcl_endl
           << "Residual norm estimate   = " << rnorm << vcl_endl
           << "A'(Ax - b) norm estimate = " << arnorm << vcl_endl
           << "x norm estimate          = " << xnorm << vcl_endl;
#endif

  // We should return the return code, as translate_return_code is public and
  // it is very misleading that the return code from this function can't be fed
  // into translate_return_code. (Brian Amberg)
  return return_code_;
}

void vnl_lsqr::diagnose_outcome(vcl_ostream& os) const
{
  translate_return_code(os, return_code_);
  os << __FILE__ " : residual norm estimate = " << resid_norm_estimate_ << vcl_endl
     << __FILE__ " : result norm estimate   = " << result_norm_estimate_ << vcl_endl
     << __FILE__ " : condition no. estimate = " << A_condition_estimate_ << vcl_endl
     << __FILE__ " : iterations             = " << num_iter_ << vcl_endl;
}

void vnl_lsqr::translate_return_code(vcl_ostream& os, int rc)
{
  const char* vnl_lsqr_reasons[] = {
   "x = 0  is the exact solution. No iterations were performed.",
   "The equations A*x = b are probably compatible.  "
       "Norm(A*x - b) is sufficiently small, given the "
       "values of ATOL and BTOL.",
   "The system A*x = b is probably not compatible.  "
       "A least-squares solution has been obtained that is "
       "sufficiently accurate, given the value of ATOL.",
   "An estimate of cond(Abar) has exceeded CONLIM.  "
       "The system A*x = b appears to be ill-conditioned.  "
       "Otherwise, there could be an error in subroutine APROD.",
   "The equations A*x = b are probably compatible.  "
       "Norm(A*x - b) is as small as seems reasonable on this machine.",
   "The system A*x = b is probably not compatible.  A least-squares "
       "solution has been obtained that is as accurate as seems "
       "reasonable on this machine.",
   "Cond(Abar) seems to be so large that there is no point in doing further "
       "iterations, given the precision of this machine. "
       "There could be an error in subroutine APROD.",
   "The iteration limit ITNLIM was reached."
  };

  if
    (rc < 0 || rc > 7) os << __FILE__ " : Illegal return code : " << rc << vcl_endl;
  else
    os << __FILE__ " : " << vnl_lsqr_reasons[rc] << vcl_endl;
}
<|endoftext|>


<commit_before>// Dogee.cpp : ̨Ӧóڵ㡣
//
#ifdef _WIN32
#include "stdafx.h"
#endif

#include <stdio.h>
#include <iostream>

#include "DogeeMacro.h"
#include <stdint.h>
#include <assert.h>
#include "Dogee.h"
namespace Dogee
{
	//test code

	uint64_t data[4096 * 32];

	template <class Dest, class Source>
	inline Dest bit_cast(const Source& source) {
		static_assert(sizeof(Dest) <= sizeof(Source), "Error: sizeof(Dest) > sizeof(Source)");
		Dest dest;
		memcpy(&dest, &source, sizeof(dest));
		return dest;
	}

	typedef uint32_t ObjectKey;
	typedef uint32_t FieldKey;
	typedef uint64_t LongKey;
	class DObject
	{
	protected:
		static const int _LAST_ = 0;
	private:
		ObjectKey object_id;
	public:
		//test code
		ObjectKey GetObjectId()
		{
			return object_id;
		}

		DObject(ObjectKey obj_id)
		{
			object_id = obj_id;
			//last_field_id = ((LongKey)obj_id)<<32;
			//last_field_id = (LongKey)(data + obj_id * 10);
		}

		/*		DObject(DObject& x)
				{
				object_id=x.object_id;
				}*/

	};
	thread_local DObject* lastobject = nullptr;

	template<class T> class Reference;
	template<typename T> class Array;

	template <typename T>
	class DSMInterface
	{
	public:
		static T get_value(ObjectKey obj_id, FieldKey field_id)
		{
			T ret = *(T*)(data + obj_id * 10 + field_id);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, T val)
		{
			*(T*)(data + obj_id * 10 + field_id) = val;
		}

	};

	template <typename T>
	class DSMInterface < Reference<T> >
	{
	public:
		static Reference<T> get_value(ObjectKey obj_id, FieldKey field_id)
		{
			ObjectKey key = *(ObjectKey*)(data + obj_id * 10 + field_id);
			Reference<T> ret(key);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, Reference<T> val)
		{
			*(ObjectKey*)(data + obj_id * 10 + field_id) = val->GetObjectId();
		}

	};

	template <typename T>
	class DSMInterface < Array<T> >
	{
	public:
		static Array<T> get_value(ObjectKey obj_id, FieldKey field_id)
		{
			ObjectKey key = *(ObjectKey*)(data + obj_id * 10 + field_id);
			Array<T> ret(key);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, Array<T> val)
		{
			*(ObjectKey*)(data + obj_id * 10 + field_id) = val.GetObjectId();
		}

	};

	template<typename T> class ArrayElement
	{
		ObjectKey ok;
		FieldKey fk;
	public:

		//copy
		ArrayElement<T>& operator=(ArrayElement<T>& x)
		{
			set(x.get());
			return *this;
		}

		T get()
		{
			return DSMInterface<T>::get_value(ok, fk);
		}

		void set(T& x)
		{
			DSMInterface<T>::set_value(ok, fk, x);
		}
		//read
		operator T()
		{
			return get();
		}

		T operator->()
		{
			return get();
		}

		//write
		T operator=(T x)
		{
			set(x);
			return x;
		}

		ArrayElement(ObjectKey o_key, FieldKey f_key) : ok(o_key), fk(f_key)
		{
		}

	};

	template<typename T, FieldKey FieldId> class Value
	{

	private:
		//copy functions are forbidden, you should copy the value like "a->val = b->val +0"
		template<typename T2, FieldKey FieldId2>Value<T, FieldId>& operator=(Value<T2, FieldId2>& x);
		Value<T, FieldId>& operator=(Value<T, FieldId>& x);
	public:
		int GetFieldId()
		{
			return FieldId;
		}

		//read
		operator T() const
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			T ret = DSMInterface<T>::get_value(lastobject->GetObjectId(), FieldId);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return ret;
		}

		T operator->()
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			T ret = DSMInterface<T>::get_value(lastobject->GetObjectId(), FieldId);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return ret;
		}

/*		<T> operator[](int k)
		{
			return *(T*)nullptr;
		}*/

		//write
		Value<T, FieldId>& operator=(T x)
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			DSMInterface<T>::set_value(lastobject->GetObjectId(), FieldId, x);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return *this;
		}
		//operator const   T() { return this->b_; }
		//operator T&() { return this->b_; }
		/*		Value(T x)
				{
				this->operator=(x);
				}*/

		Value()
		{
		}

	};

/*	template<typename T, FieldKey FieldId>
	ArrayElement<T> Value<Array<T>, FieldId>::operator[](int k)
	{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			T ret = DSMInterface<T>::get_value(lastobject->GetObjectId(), FieldId);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return ret.ArrayAccess(k);
	}*/

	template<typename T> class Array
	{
	private:
		ObjectKey object_id;
	public:
		//test code
		ObjectKey GetObjectId()
		{
			return object_id;
		}
		Array(ObjectKey obj_id)
		{
			object_id = obj_id;
		}

		ArrayElement<T> ArrayAccess(int k)
		{
			FieldKey key = k;
			return ArrayElement<T>(object_id, key);
		}

		ArrayElement<T> operator[](int k)
		{
			return ArrayAccess(k);
		}
	};

	template<class T> class Reference
	{
	private:
		T obj;
	public:
		T* operator->()
		{
			lastobject = (DObject*)&obj;
			return &obj;
		}

		Reference(ObjectKey key) :obj(key){}

		Reference(T& k) :obj(k){}
	};

	//test code
	ObjectKey objid;
	template<class T> class Alloc
	{
	private:
		//test code

		static ObjectKey AllocObjectId()
		{
			return objid++;
		}
	public:
		static Array<T>  newarray()
		{
			return Array<T>(AllocObjectId());
		}

		static Reference<T>  tnew()
		{
			T ret(AllocObjectId());
			return Reference<T>(ret);
		}

		template<typename P1>
		static Reference<T>  tnew(P1 p1)
		{
			T ret(AllocObjectId(), p1);
			return Reference<T>(ret);
		}

		template<typename P1, typename P2>
		static Reference<T>  tnew(P1 p1, P2 p2)
		{
			T ret(AllocObjectId(), p1, p2);
			return Reference<T>(ret);
		}
		/*
		template<typename P1, typename P2, typename P3>
		T*  tnew(P1 p1, P2 p2, P3 p3)
		{
		return new (alloc()) T(p1, p2, p3);
		}

		template<typename P1, typename P2, typename P3, typename P4>
		T*  tnew(P1 p1, P2 p2, P3 p3, P4 p4)
		{
		return new (alloc()) T(p1, p2, p3, p4);
		}

		template<typename P1, typename P2, typename P3, typename P4, typename P5>
		T*  tnew(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
		{
		return new (alloc()) T(p1, p2, p3, p4, p5);
		}*/
	};

	template <class T> inline T* ReferenceObject(T* obj)
	{
		lastobject = (DObject*)obj;
		return obj;
	}
}
using namespace Dogee;

class clsa : public DObject
{
	DefBegin(DObject);
public:
	Def(int, i);
	Def(Array<float>, arr);
	Def(Reference<clsa>, next);
	DefEnd();
	clsa(ObjectKey obj_id) : DObject(obj_id)
	{}

};

template<typename T> void aaa(T* dummy)
{
	std::cout << "Normal" << std::endl;
}
template<> void aaa(int * dummy)
{
	std::cout << "Int" << std::endl;
}
int main(int argc, char* argv[])
{
/*	Dogee::DInt i = 10;
	int b = 0;
	i = i + 1;
	Dogee::DInt j = 220;
	i = j;
	Reference<clsa> aaa(123);
	std::cout<<*aaa;
	clsa obj(0);
	obj.i = 1;
	obj.j = 2.3;
	obj.k = 4.5;
	std::cout << sizeof(clsa) << std::endl << sizeof(DObject) << std::endl << sizeof(Value<int>) << std::endl;*/
	auto ptr = Dogee::Alloc<clsa>::tnew();
	ptr->arr = Dogee::Alloc<float>::newarray();
	Array<float> arr = ptr->arr;
	arr[0] = arr[0] + 1;
	//std::cout << ptr->i << std::endl << ptr->j << std::endl << ptr->k << std::endl;
	//ptr->next = ptr;
	//ptr->next->next->i = 1;
	//Reference<clsa> ptr2=ptr->next;
	std::cout << arr[0] << std::endl;

	return 0;
}

<commit_msg>add operator [] for Value<Array><commit_after>// Dogee.cpp : ̨Ӧóڵ㡣
//
#ifdef _WIN32
#include "stdafx.h"
#endif

#include <stdio.h>
#include <iostream>

#include "DogeeMacro.h"
#include <stdint.h>
#include <assert.h>
#include "Dogee.h"

namespace Dogee
{
	//test code

	uint64_t data[4096 * 32];

	template <class Dest, class Source>
	inline Dest bit_cast(const Source& source) {
		static_assert(sizeof(Dest) <= sizeof(Source), "Error: sizeof(Dest) > sizeof(Source)");
		Dest dest;
		memcpy(&dest, &source, sizeof(dest));
		return dest;
	}

	typedef uint32_t ObjectKey;
	typedef uint32_t FieldKey;
	typedef uint64_t LongKey;
	class DObject
	{
	protected:
		static const int _LAST_ = 0;
	private:
		ObjectKey object_id;
	public:
		//test code
		ObjectKey GetObjectId()
		{
			return object_id;
		}

		DObject(ObjectKey obj_id)
		{
			object_id = obj_id;
			//last_field_id = ((LongKey)obj_id)<<32;
			//last_field_id = (LongKey)(data + obj_id * 10);
		}

		/*		DObject(DObject& x)
				{
				object_id=x.object_id;
				}*/

	};
	thread_local DObject* lastobject = nullptr;

	template<class T> class Reference;
	template<typename T> class Array;

	template <typename T>
	class DSMInterface
	{
	public:
		static T get_value(ObjectKey obj_id, FieldKey field_id)
		{
			T ret = *(T*)(data + obj_id * 10 + field_id);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, T val)
		{
			*(T*)(data + obj_id * 10 + field_id) = val;
		}

	};

	template <typename T>
	class DSMInterface < Reference<T> >
	{
	public:
		static Reference<T> get_value(ObjectKey obj_id, FieldKey field_id)
		{
			ObjectKey key = *(ObjectKey*)(data + obj_id * 10 + field_id);
			Reference<T> ret(key);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, Reference<T> val)
		{
			*(ObjectKey*)(data + obj_id * 10 + field_id) = val->GetObjectId();
		}

	};

	template <typename T>
	class DSMInterface < Array<T> >
	{
	public:
		static Array<T> get_value(ObjectKey obj_id, FieldKey field_id)
		{
			ObjectKey key = *(ObjectKey*)(data + obj_id * 10 + field_id);
			Array<T> ret(key);
			return ret;
		}

		static void set_value(ObjectKey obj_id, FieldKey field_id, Array<T> val)
		{
			*(ObjectKey*)(data + obj_id * 10 + field_id) = val.GetObjectId();
		}

	};

	template<typename T> class ArrayElement
	{
		ObjectKey ok;
		FieldKey fk;
	public:

		//copy
		ArrayElement<T>& operator=(ArrayElement<T>& x)
		{
			set(x.get());
			return *this;
		}

		T get()
		{
			return DSMInterface<T>::get_value(ok, fk);
		}

		void set(T& x)
		{
			DSMInterface<T>::set_value(ok, fk, x);
		}
		//read
		operator T()
		{
			return get();
		}

		T operator->()
		{
			return get();
		}

		//write
		T operator=(T x)
		{
			set(x);
			return x;
		}

		ArrayElement(ObjectKey o_key, FieldKey f_key) : ok(o_key), fk(f_key)
		{
		}

	};

	//template<typename T> T dummy(T);
	//template<typename T> ArrayElement<T> dummy(Array<T>);
	template<typename T, FieldKey FieldId> class Value
	{
	private:

		//copy functions are forbidden, you should copy the value like "a->val = b->val +0"
		template<typename T2, FieldKey FieldId2>Value<T, FieldId>& operator=(Value<T2, FieldId2>& x);
		Value<T, FieldId>& operator=(Value<T, FieldId>& x);
	public:
		int GetFieldId()
		{
			return FieldId;
		}

		T get()
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			T ret = DSMInterface<T>::get_value(lastobject->GetObjectId(), FieldId);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return ret;
		}
		//read
		operator T()
		{
			return get();
		}

		T operator->()
		{
			return get();
		}

		//write
		Value<T, FieldId>& operator=(T x)
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			DSMInterface<T>::set_value(lastobject->GetObjectId(), FieldId, x);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return *this;
		}
		Value()
		{
		}

	};

	//a dirty bypass for Value<Array<T>, FieldId>, just to add "operator[]"
	template<typename T, FieldKey FieldId> class Value<Array<T>, FieldId>
	{
	private:

		//copy functions are forbidden, you should copy the value like "a->val = b->val +0"
		template<typename T2, FieldKey FieldId2>Value<Array<T>, FieldId>& operator=(Value<T2, FieldId2>& x);
		Value<Array<T>, FieldId>& operator=(Value<Array<T>, FieldId>& x);
	public:
		int GetFieldId()
		{
			return FieldId;
		}

		Array<T> get()
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			Array<T> ret = DSMInterface<Array<T>>::get_value(lastobject->GetObjectId(), FieldId);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return ret;
		}
		//read
		operator Array<T>()
		{
			return get();
		}
		ArrayElement<T> operator[](int k)
		{
			Array<T> ret = get();
			return ret.ArrayAccess(k);
		}
		//write
		Value<Array<T>, FieldId>& operator=(Array<T> x)
		{
			assert(lastobject != nullptr);// "You should use a Reference<T> to access the member"
			DSMInterface<Array<T>>::set_value(lastobject->GetObjectId(), FieldId, x);
#ifdef DOGEE_DBG
			lastobject = nullptr;
#endif
			return *this;
		}
		Value()
		{
		}

	};

	template<typename T> class Array
	{
	private:
		ObjectKey object_id;
	public:
		//test code
		ObjectKey GetObjectId()
		{
			return object_id;
		}
		Array(ObjectKey obj_id)
		{
			object_id = obj_id;
		}

		ArrayElement<T> ArrayAccess(int k)
		{
			FieldKey key = k;
			return ArrayElement<T>(object_id, key);
		}

		ArrayElement<T> operator[](int k)
		{
			return ArrayAccess(k);
		}
	};

	template<class T> class Reference
	{
	private:
		T obj;
	public:
		T* operator->()
		{
			lastobject = (DObject*)&obj;
			return &obj;
		}

		Reference(ObjectKey key) :obj(key){}

		Reference(T& k) :obj(k){}
	};

	//test code
	ObjectKey objid;
	template<class T> class Alloc
	{
	private:
		//test code

		static ObjectKey AllocObjectId()
		{
			return objid++;
		}
	public:
		static Array<T>  newarray()
		{
			return Array<T>(AllocObjectId());
		}

		static Reference<T>  tnew()
		{
			T ret(AllocObjectId());
			return Reference<T>(ret);
		}

		template<typename P1>
		static Reference<T>  tnew(P1 p1)
		{
			T ret(AllocObjectId(), p1);
			return Reference<T>(ret);
		}

		template<typename P1, typename P2>
		static Reference<T>  tnew(P1 p1, P2 p2)
		{
			T ret(AllocObjectId(), p1, p2);
			return Reference<T>(ret);
		}
		/*
		template<typename P1, typename P2, typename P3>
		T*  tnew(P1 p1, P2 p2, P3 p3)
		{
		return new (alloc()) T(p1, p2, p3);
		}

		template<typename P1, typename P2, typename P3, typename P4>
		T*  tnew(P1 p1, P2 p2, P3 p3, P4 p4)
		{
		return new (alloc()) T(p1, p2, p3, p4);
		}

		template<typename P1, typename P2, typename P3, typename P4, typename P5>
		T*  tnew(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5)
		{
		return new (alloc()) T(p1, p2, p3, p4, p5);
		}*/
	};

	template <class T> inline T* ReferenceObject(T* obj)
	{
		lastobject = (DObject*)obj;
		return obj;
	}
}
using namespace Dogee;

class clsa : public DObject
{
	DefBegin(DObject);
public:
	Def(int, i);
	Def(Array<float>, arr);
	Def(Array<Reference<clsa>>, next);
	DefEnd();
	clsa(ObjectKey obj_id) : DObject(obj_id)
	{}

};

template<typename T> void aaa(T* dummy)
{
	std::cout << "Normal" << std::endl;
}
template<> void aaa(int * dummy)
{
	std::cout << "Int" << std::endl;
}
int main(int argc, char* argv[])
{
/*	Dogee::DInt i = 10;
	int b = 0;
	i = i + 1;
	Dogee::DInt j = 220;
	i = j;
	Reference<clsa> aaa(123);
	std::cout<<*aaa;
	clsa obj(0);
	obj.i = 1;
	obj.j = 2.3;
	obj.k = 4.5;
	std::cout << sizeof(clsa) << std::endl << sizeof(DObject) << std::endl << sizeof(Value<int>) << std::endl;*/
	auto ptr = Dogee::Alloc<clsa>::tnew();
	ptr->arr = Dogee::Alloc<float>::newarray();
	ptr->next = Dogee::Alloc<Reference<clsa>>::newarray();
	ptr->next[0] = ptr;
	ptr->next[0]->i = 123;
	ptr->arr[0] = 133;
	ptr->arr[0]=ptr->arr[0] + 1;
	std::cout << ptr->arr[0] << std::endl << ptr->i;
	//std::cout << ptr->i << std::endl << ptr->j << std::endl << ptr->k << std::endl;
	//ptr->next = ptr;
	//ptr->next->next->i = 1;
	//Reference<clsa> ptr2=ptr->next;
	return 0;
}

<|endoftext|>


<commit_before>/****************************************************************************
 *
 *   Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file spektrum_rc.cpp
 *
 * This is a driver for a Spektrum satellite receiver connected to a Snapdragon
 * on the serial port. By default port J15 (next to USB) is used.
 */

#include <px4_tasks.h>
#include <px4_posix.h>

#include <lib/rc/dsm.h>
#include <drivers/drv_rc_input.h>
#include <drivers/drv_hrt.h>

#include <uORB/uORB.h>
#include <uORB/topics/input_rc.h>

// Snapdraogon: use J15 (next to USB)
#define SPEKTRUM_UART_DEVICE_PATH "/dev/tty-1"

#define UNUSED(x) (void)(x)

extern "C" { __EXPORT int spektrum_rc_main(int argc, char *argv[]); }

namespace spektrum_rc
{

volatile bool _task_should_exit = false;
static bool _is_running = false;
static px4_task_t _task_handle = -1;

int start();
int stop();
int info();
void usage();
void task_main(int argc, char *argv[]);

void fill_input_rc(uint16_t raw_rc_count, uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS],
		   hrt_abstime now, bool frame_drop, bool failsafe, unsigned frame_drops, int rssi,
		   input_rc_s &input_rc);

void task_main(int argc, char *argv[])
{
	int uart_fd = dsm_init(SPEKTRUM_UART_DEVICE_PATH);

	if (uart_fd < 1) {
		PX4_ERR("dsm init failed");
		return;
	}

	orb_advert_t rc_pub = nullptr;

	// Use a buffer size of the double of the minimum, just to be safe.
	uint8_t rx_buf[2 * DSM_BUFFER_SIZE];

	// Set up poll topic
	px4_pollfd_struct_t fds[1];
	fds[0].fd     = uart_fd;
	fds[0].events = POLLIN;

	_is_running = true;

	// Main loop
	while (!_task_should_exit) {

		int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 10);

		/* Timed out, do a periodic check for _task_should_exit. */
		if (pret == 0) {
			continue;
		}

		if (pret < 0) {
			PX4_WARN("poll error %d, %d", pret, errno);
			/* sleep a bit before next try */
			usleep(100000);
			continue;
		}

		if (!(fds[0].revents & POLLIN)) {
			// There is only one fd in poll, so this should be impossible.
			PX4_WARN("poll bit not set");
			continue;
		}

		int newbytes = ::read(uart_fd, &rx_buf[0], sizeof(rx_buf));

		if (newbytes < 0) {
			PX4_WARN("read failed");
			continue;
		}

		if (newbytes == 0) {
			PX4_WARN("read nothing");
			continue;
		}

		const hrt_abstime now = hrt_absolute_time();

		bool dsm_11_bit;
		unsigned frame_drops;
		uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS];
		uint16_t raw_rc_count;

		// parse new data
		bool rc_updated = dsm_parse(now, rx_buf, newbytes, &raw_rc_values[0], &raw_rc_count,
					    &dsm_11_bit, &frame_drops, input_rc_s::RC_INPUT_MAX_CHANNELS);
		UNUSED(dsm_11_bit);

		if (rc_updated) {

			input_rc_s input_rc = {};

			// We don't know RSSI.
			const int rssi = -1;

			fill_input_rc(raw_rc_count, raw_rc_values, now, false, false, frame_drops, rssi,
				      input_rc);

			if (rc_pub == nullptr) {
				rc_pub = orb_advertise(ORB_ID(input_rc), &input_rc);

			} else {
				orb_publish(ORB_ID(input_rc), rc_pub, &input_rc);
			}
		}
	}

	orb_unadvertise(rc_pub);
	dsm_deinit();

	_is_running = false;
}

void fill_input_rc(uint16_t raw_rc_count, uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS],
		   hrt_abstime now, bool frame_drop, bool failsafe, unsigned frame_drops, int rssi,
		   input_rc_s &input_rc)
{
	input_rc.input_source = input_rc_s::RC_INPUT_SOURCE_QURT;

	input_rc.channel_count = raw_rc_count;

	if (input_rc.channel_count > input_rc_s::RC_INPUT_MAX_CHANNELS) {
		input_rc.channel_count = input_rc_s::RC_INPUT_MAX_CHANNELS;
	}

	unsigned valid_chans = 0;

	for (unsigned i = 0; i < input_rc.channel_count; ++i) {
		input_rc.values[i] = raw_rc_values[i];

		if (raw_rc_values[i] != UINT16_MAX) {
			valid_chans++;
		}
	}

	input_rc.timestamp = now;
	input_rc.timestamp_last_signal = input_rc.timestamp;
	input_rc.rc_ppm_frame_length = 0;

	/* fake rssi if no value was provided */
	if (rssi == -1) {

		input_rc.rssi = 255;

	} else {
		input_rc.rssi = rssi;
	}

	if (valid_chans == 0) {
		input_rc.rssi = 0;
	}

	input_rc.rc_failsafe = failsafe;
	input_rc.rc_lost = (valid_chans == 0);
	input_rc.rc_lost_frame_count = frame_drops;
	input_rc.rc_total_frame_count = 0;
}

int start()
{
	if (_is_running) {
		PX4_WARN("already running");
		return -1;
	}

	ASSERT(_task_handle == -1);

	_task_should_exit = false;

	_task_handle = px4_task_spawn_cmd("spektrum_rc_main",
					  SCHED_DEFAULT,
					  SCHED_PRIORITY_DEFAULT,
					  2000,
					  (px4_main_t)&task_main,
					  nullptr);

	if (_task_handle < 0) {
		PX4_ERR("task start failed");
		return -1;
	}

	return 0;
}

int stop()
{
	if (!_is_running) {
		PX4_WARN("not running");
		return -1;
	}

	_task_should_exit = true;

	while (_is_running) {
		usleep(200000);
		PX4_INFO(".");
	}

	_task_handle = -1;
	return 0;
}

int info()
{
	PX4_INFO("running: %s", _is_running ? "yes" : "no");

	return 0;
}

void
usage()
{
	PX4_INFO("Usage: spektrum_rc {start|info|stop}");
}

} // namespace spektrum_rc

int spektrum_rc_main(int argc, char *argv[])
{
	int myoptind = 1;

	if (argc <= 1) {
		spektrum_rc::usage();
		return 1;
	}

	const char *verb = argv[myoptind];

	if (!strcmp(verb, "start")) {
		return spektrum_rc::start();
	}

	else if (!strcmp(verb, "stop")) {
		return spektrum_rc::stop();
	}

	else if (!strcmp(verb, "info")) {
		return spektrum_rc::info();
	}

	else {
		spektrum_rc::usage();
		return 1;
	}
}
<commit_msg>spektrum_rc: raise poll timeout to 50ms/20Hz<commit_after>/****************************************************************************
 *
 *   Copyright (c) 2016 PX4 Development Team. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 * 3. Neither the name PX4 nor the names of its contributors may be
 *    used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 *
 ****************************************************************************/

/**
 * @file spektrum_rc.cpp
 *
 * This is a driver for a Spektrum satellite receiver connected to a Snapdragon
 * on the serial port. By default port J15 (next to USB) is used.
 */

#include <px4_tasks.h>
#include <px4_posix.h>

#include <lib/rc/dsm.h>
#include <drivers/drv_rc_input.h>
#include <drivers/drv_hrt.h>

#include <uORB/uORB.h>
#include <uORB/topics/input_rc.h>

// Snapdraogon: use J15 (next to USB)
#define SPEKTRUM_UART_DEVICE_PATH "/dev/tty-1"

#define UNUSED(x) (void)(x)

extern "C" { __EXPORT int spektrum_rc_main(int argc, char *argv[]); }

namespace spektrum_rc
{

volatile bool _task_should_exit = false;
static bool _is_running = false;
static px4_task_t _task_handle = -1;

int start();
int stop();
int info();
void usage();
void task_main(int argc, char *argv[]);

void fill_input_rc(uint16_t raw_rc_count, uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS],
		   hrt_abstime now, bool frame_drop, bool failsafe, unsigned frame_drops, int rssi,
		   input_rc_s &input_rc);

void task_main(int argc, char *argv[])
{
	int uart_fd = dsm_init(SPEKTRUM_UART_DEVICE_PATH);

	if (uart_fd < 1) {
		PX4_ERR("dsm init failed");
		return;
	}

	orb_advert_t rc_pub = nullptr;

	// Use a buffer size of the double of the minimum, just to be safe.
	uint8_t rx_buf[2 * DSM_BUFFER_SIZE];

	// Set up poll topic
	px4_pollfd_struct_t fds[1];
	fds[0].fd     = uart_fd;
	fds[0].events = POLLIN;

	_is_running = true;

	// Main loop
	while (!_task_should_exit) {

		int pret = px4_poll(&fds[0], (sizeof(fds) / sizeof(fds[0])), 50);

		/* Timed out, do a periodic check for _task_should_exit. */
		if (pret == 0) {
			continue;
		}

		if (pret < 0) {
			PX4_WARN("poll error %d, %d", pret, errno);
			/* sleep a bit before next try */
			usleep(100000);
			continue;
		}

		if (!(fds[0].revents & POLLIN)) {
			// There is only one fd in poll, so this should be impossible.
			PX4_WARN("poll bit not set");
			continue;
		}

		int newbytes = ::read(uart_fd, &rx_buf[0], sizeof(rx_buf));

		if (newbytes < 0) {
			PX4_WARN("read failed");
			continue;
		}

		if (newbytes == 0) {
			PX4_WARN("read nothing");
			continue;
		}

		const hrt_abstime now = hrt_absolute_time();

		bool dsm_11_bit;
		unsigned frame_drops;
		uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS];
		uint16_t raw_rc_count;

		// parse new data
		bool rc_updated = dsm_parse(now, rx_buf, newbytes, &raw_rc_values[0], &raw_rc_count,
					    &dsm_11_bit, &frame_drops, input_rc_s::RC_INPUT_MAX_CHANNELS);
		UNUSED(dsm_11_bit);

		if (rc_updated) {

			input_rc_s input_rc = {};

			// We don't know RSSI.
			const int rssi = -1;

			fill_input_rc(raw_rc_count, raw_rc_values, now, false, false, frame_drops, rssi,
				      input_rc);

			if (rc_pub == nullptr) {
				rc_pub = orb_advertise(ORB_ID(input_rc), &input_rc);

			} else {
				orb_publish(ORB_ID(input_rc), rc_pub, &input_rc);
			}
		}
	}

	orb_unadvertise(rc_pub);
	dsm_deinit();

	_is_running = false;
}

void fill_input_rc(uint16_t raw_rc_count, uint16_t raw_rc_values[input_rc_s::RC_INPUT_MAX_CHANNELS],
		   hrt_abstime now, bool frame_drop, bool failsafe, unsigned frame_drops, int rssi,
		   input_rc_s &input_rc)
{
	input_rc.input_source = input_rc_s::RC_INPUT_SOURCE_QURT;

	input_rc.channel_count = raw_rc_count;

	if (input_rc.channel_count > input_rc_s::RC_INPUT_MAX_CHANNELS) {
		input_rc.channel_count = input_rc_s::RC_INPUT_MAX_CHANNELS;
	}

	unsigned valid_chans = 0;

	for (unsigned i = 0; i < input_rc.channel_count; ++i) {
		input_rc.values[i] = raw_rc_values[i];

		if (raw_rc_values[i] != UINT16_MAX) {
			valid_chans++;
		}
	}

	input_rc.timestamp = now;
	input_rc.timestamp_last_signal = input_rc.timestamp;
	input_rc.rc_ppm_frame_length = 0;

	/* fake rssi if no value was provided */
	if (rssi == -1) {

		input_rc.rssi = 255;

	} else {
		input_rc.rssi = rssi;
	}

	if (valid_chans == 0) {
		input_rc.rssi = 0;
	}

	input_rc.rc_failsafe = failsafe;
	input_rc.rc_lost = (valid_chans == 0);
	input_rc.rc_lost_frame_count = frame_drops;
	input_rc.rc_total_frame_count = 0;
}

int start()
{
	if (_is_running) {
		PX4_WARN("already running");
		return -1;
	}

	ASSERT(_task_handle == -1);

	_task_should_exit = false;

	_task_handle = px4_task_spawn_cmd("spektrum_rc_main",
					  SCHED_DEFAULT,
					  SCHED_PRIORITY_DEFAULT,
					  2000,
					  (px4_main_t)&task_main,
					  nullptr);

	if (_task_handle < 0) {
		PX4_ERR("task start failed");
		return -1;
	}

	return 0;
}

int stop()
{
	if (!_is_running) {
		PX4_WARN("not running");
		return -1;
	}

	_task_should_exit = true;

	while (_is_running) {
		usleep(200000);
		PX4_INFO(".");
	}

	_task_handle = -1;
	return 0;
}

int info()
{
	PX4_INFO("running: %s", _is_running ? "yes" : "no");

	return 0;
}

void
usage()
{
	PX4_INFO("Usage: spektrum_rc {start|info|stop}");
}

} // namespace spektrum_rc

int spektrum_rc_main(int argc, char *argv[])
{
	int myoptind = 1;

	if (argc <= 1) {
		spektrum_rc::usage();
		return 1;
	}

	const char *verb = argv[myoptind];

	if (!strcmp(verb, "start")) {
		return spektrum_rc::start();
	}

	else if (!strcmp(verb, "stop")) {
		return spektrum_rc::stop();
	}

	else if (!strcmp(verb, "info")) {
		return spektrum_rc::info();
	}

	else {
		spektrum_rc::usage();
		return 1;
	}
}
<|endoftext|>


<commit_before>#define WIN32_LEAN_AND_MEAN
#define STRICT
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _CRTDBG_MAP_ALLOC
#include <windows.h>
#include <atlbase.h>
#include <pathcch.h>
#include <shlwapi.h>
#include <winioctl.h>
#include <algorithm>
#include <clocale>
#include <cstdio>
#include <memory>
#include <crtdbg.h>
#pragma comment(lib, "pathcch")
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "user32")

#pragma region
static_assert( FIELD_OFFSET( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, ChecksumAlgorithm )
			== FIELD_OFFSET( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, ChecksumAlgorithm ), "" );
static_assert( RTL_SIZEOF_THROUGH_FIELD( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, ChecksumAlgorithm )
			== RTL_SIZEOF_THROUGH_FIELD( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, ChecksumAlgorithm ), "" );
static_assert( FIELD_OFFSET( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, Reserved )
			== FIELD_OFFSET( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, Reserved ), "" );
static_assert( RTL_SIZEOF_THROUGH_FIELD( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, Reserved )
			== RTL_SIZEOF_THROUGH_FIELD( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, Reserved ), "" );
static_assert( FIELD_OFFSET( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, Flags )
			== FIELD_OFFSET( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, Flags ), "" );
static_assert( RTL_SIZEOF_THROUGH_FIELD( FSCTL_GET_INTEGRITY_INFORMATION_BUFFER, Flags )
			== RTL_SIZEOF_THROUGH_FIELD( FSCTL_SET_INTEGRITY_INFORMATION_BUFFER, Flags ), "" );
#pragma endregion

std::unique_ptr<WCHAR[]> GetWindowsError( ULONG error_code = GetLastError() )
{
	auto msg = std::make_unique<WCHAR[]>( USHRT_MAX );
	if( FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, 0, msg.get(), USHRT_MAX, nullptr ) )
	{
		return msg;
	}
	return nullptr;
}
void PrintWindowsError( ULONG error_code = GetLastError() )
{
	if( auto error_msg = GetWindowsError( error_code ) )
	{
		fprintf( stderr, "%ls\n", error_msg.get() );
	}
}
_Success_( return == true )
bool reflink( _In_z_ PCWSTR oldpath, _In_z_ PCWSTR newpath )
{
	_ASSERTE( oldpath != nullptr && newpath != nullptr );
	ATL::CHandle source{ CreateFileW( oldpath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr ) };
	if( source == INVALID_HANDLE_VALUE )
	{
		source.Detach();
		return false;
	}

	ULONG fs_flags;
	if( !GetVolumeInformationByHandleW( source, nullptr, 0, nullptr, nullptr, &fs_flags, nullptr, 0 ) )
	{
		return false;
	}
	if( !( fs_flags & FILE_SUPPORTS_BLOCK_REFCOUNTING ) )
	{
		SetLastError( ERROR_NOT_CAPABLE );
		return false;
	}

	FILE_STANDARD_INFO file_standard;
	if( !GetFileInformationByHandleEx( source, FileStandardInfo, &file_standard, sizeof file_standard ) )
	{
		return false;
	}
	FILE_BASIC_INFO file_basic;
	if( !GetFileInformationByHandleEx( source, FileBasicInfo, &file_basic, sizeof file_basic ) )
	{
		return false;
	}
	ULONG dummy;
	union{
		FSCTL_GET_INTEGRITY_INFORMATION_BUFFER get_integrity;
		FSCTL_SET_INTEGRITY_INFORMATION_BUFFER set_integrity;
	};
	if( !DeviceIoControl( source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &get_integrity, sizeof get_integrity, &dummy, nullptr ) )
	{
		return false;
	}

#ifdef _DEBUG
	ATL::CHandle destination{ CreateFileW( newpath, GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, source ) };
#else
	ATL::CHandle destination{ CreateFileW( newpath, GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source ) };
#endif
	if( destination == INVALID_HANDLE_VALUE )
	{
		destination.Detach();
		return false;
	}
	FILE_DISPOSITION_INFO dispose = { TRUE };
	if( !SetFileInformationByHandle( destination, FileDispositionInfo, &dispose, sizeof dispose ) )
	{
		return false;
	}

	if( file_basic.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE )
	{
		if( !DeviceIoControl( destination, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &dummy, nullptr ) )
		{
			return false;
		}
	}
	if( !DeviceIoControl( destination, FSCTL_SET_INTEGRITY_INFORMATION, &set_integrity, sizeof set_integrity, nullptr, 0, nullptr, nullptr ) )
	{
		return false;
	}
	FILE_END_OF_FILE_INFO end_of_file = { file_standard.EndOfFile };
	if( !SetFileInformationByHandle( destination, FileEndOfFileInfo, &end_of_file, sizeof end_of_file ) )
	{
		return false;
	}

	const ULONG split_threshold = 0UL - get_integrity.ClusterSizeInBytes;

	DUPLICATE_EXTENTS_DATA dup_extent = { source };
	for( LONG64 offset = 0, remain = file_standard.AllocationSize.QuadPart; remain > 0; offset += split_threshold, remain -= split_threshold )
	{
		dup_extent.SourceFileOffset.QuadPart = dup_extent.TargetFileOffset.QuadPart = offset;
		dup_extent.ByteCount.QuadPart = std::min<LONG64>( split_threshold, remain );
		_ASSERTE( dup_extent.ByteCount.HighPart == 0 );
		_RPT3( _CRT_WARN, "r=%llx\no=%llx\nb=%llx\n\n", remain, dup_extent.SourceFileOffset.QuadPart, dup_extent.ByteCount.QuadPart );
		if( !DeviceIoControl( destination, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &dup_extent, sizeof dup_extent, nullptr, 0, &dummy, nullptr ) )
		{
			_CrtDbgBreak();
			return false;
		}
	}

	FILETIME atime = { file_basic.LastAccessTime.LowPart, ULONG( file_basic.LastAccessTime.HighPart ) };
	FILETIME mtime = { file_basic.LastWriteTime.LowPart, ULONG( file_basic.LastWriteTime.HighPart ) };
	SetFileTime( destination, nullptr, &atime, &mtime );
	dispose.DeleteFile = FALSE;
	return SetFileInformationByHandle( destination, FileDispositionInfo, &dispose, sizeof dispose ) != 0;
}
int __cdecl wmain( int argc, PWSTR argv[] )
{
	_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
	_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE );
	setlocale( LC_ALL, "" );

	if( argc != 3 )
	{
		fprintf(
			stderr,
			"Copy file without actual data write.\n"
			"\n"
			"%ls source destination\n"
			"\n"
			"source       Specifies a file to copy.\n"
			"             source must have placed on the ReFS volume.\n"
			"destination  Specifies new file name.\n"
			"             destination must have placed on the same volume as source.\n",
			PathFindFileNameW( argv[0] )
			);
		return EXIT_FAILURE;
	}
	auto source = std::make_unique<WCHAR[]>( PATHCCH_MAX_CCH );
	auto destination = std::make_unique<WCHAR[]>( PATHCCH_MAX_CCH );
	if( FAILED( PathCchCanonicalizeEx( source.get(), PATHCCH_MAX_CCH, argv[1], PATHCCH_ALLOW_LONG_PATHS ) )
		|| FAILED( PathCchCanonicalizeEx( destination.get(), PATHCCH_MAX_CCH, argv[2], PATHCCH_ALLOW_LONG_PATHS ) ) )
	{
		PrintWindowsError();
		return EXIT_FAILURE;
	}
	if( !reflink( source.get(), destination.get() ) )
	{
		PrintWindowsError();
		return EXIT_FAILURE;
	}
}<commit_msg>Minor change<commit_after>#define WIN32_LEAN_AND_MEAN
#define STRICT
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _CRTDBG_MAP_ALLOC
#include <windows.h>
#include <atlbase.h>
#include <pathcch.h>
#include <shlwapi.h>
#include <winioctl.h>
#include <algorithm>
#include <clocale>
#include <cstdio>
#include <memory>
#include <crtdbg.h>
#pragma comment(lib, "pathcch")
#pragma comment(lib, "shlwapi")
#pragma comment(lib, "user32")

std::unique_ptr<WCHAR[]> GetWindowsError( ULONG error_code = GetLastError() )
{
	auto msg = std::make_unique<WCHAR[]>( USHRT_MAX );
	if( FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM, nullptr, error_code, 0, msg.get(), USHRT_MAX, nullptr ) )
	{
		return msg;
	}
	return nullptr;
}
void PrintWindowsError( ULONG error_code = GetLastError() )
{
	if( auto error_msg = GetWindowsError( error_code ) )
	{
		fprintf( stderr, "%ls\n", error_msg.get() );
	}
}
_Success_( return == true )
bool reflink( _In_z_ PCWSTR oldpath, _In_z_ PCWSTR newpath )
{
	_ASSERTE( oldpath != nullptr && newpath != nullptr );
	ATL::CHandle source{ CreateFileW( oldpath, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr ) };
	if( source == INVALID_HANDLE_VALUE )
	{
		source.Detach();
		return false;
	}

	ULONG fs_flags;
	if( !GetVolumeInformationByHandleW( source, nullptr, 0, nullptr, nullptr, &fs_flags, nullptr, 0 ) )
	{
		return false;
	}
	if( !( fs_flags & FILE_SUPPORTS_BLOCK_REFCOUNTING ) )
	{
		SetLastError( ERROR_NOT_CAPABLE );
		return false;
	}

	FILE_STANDARD_INFO file_standard;
	if( !GetFileInformationByHandleEx( source, FileStandardInfo, &file_standard, sizeof file_standard ) )
	{
		return false;
	}
	FILE_BASIC_INFO file_basic;
	if( !GetFileInformationByHandleEx( source, FileBasicInfo, &file_basic, sizeof file_basic ) )
	{
		return false;
	}
	ULONG dummy;
	FSCTL_GET_INTEGRITY_INFORMATION_BUFFER get_integrity;
	if( !DeviceIoControl( source, FSCTL_GET_INTEGRITY_INFORMATION, nullptr, 0, &get_integrity, sizeof get_integrity, &dummy, nullptr ) )
	{
		return false;
	}

#ifdef _DEBUG
	ATL::CHandle destination{ CreateFileW( newpath, GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, source ) };
#else
	ATL::CHandle destination{ CreateFileW( newpath, GENERIC_READ | GENERIC_WRITE | DELETE, 0, nullptr, CREATE_NEW, 0, source ) };
#endif
	if( destination == INVALID_HANDLE_VALUE )
	{
		destination.Detach();
		return false;
	}
	FILE_DISPOSITION_INFO dispose = { TRUE };
	if( !SetFileInformationByHandle( destination, FileDispositionInfo, &dispose, sizeof dispose ) )
	{
		return false;
	}

	if( file_basic.FileAttributes & FILE_ATTRIBUTE_SPARSE_FILE )
	{
		if( !DeviceIoControl( destination, FSCTL_SET_SPARSE, nullptr, 0, nullptr, 0, &dummy, nullptr ) )
		{
			return false;
		}
	}
	FSCTL_SET_INTEGRITY_INFORMATION_BUFFER set_integrity = { get_integrity.ChecksumAlgorithm, get_integrity.Reserved, get_integrity.Flags };
	if( !DeviceIoControl( destination, FSCTL_SET_INTEGRITY_INFORMATION, &set_integrity, sizeof set_integrity, nullptr, 0, nullptr, nullptr ) )
	{
		return false;
	}
	FILE_END_OF_FILE_INFO end_of_file = { file_standard.EndOfFile };
	if( !SetFileInformationByHandle( destination, FileEndOfFileInfo, &end_of_file, sizeof end_of_file ) )
	{
		return false;
	}

	const ULONG split_threshold = 0UL - get_integrity.ClusterSizeInBytes;

	DUPLICATE_EXTENTS_DATA dup_extent = { source };
	for( LONG64 offset = 0, remain = file_standard.AllocationSize.QuadPart; remain > 0; offset += split_threshold, remain -= split_threshold )
	{
		dup_extent.SourceFileOffset.QuadPart = dup_extent.TargetFileOffset.QuadPart = offset;
		dup_extent.ByteCount.QuadPart = std::min<LONG64>( split_threshold, remain );
		_ASSERTE( dup_extent.ByteCount.HighPart == 0 );
		_RPT3( _CRT_WARN, "r=%llx\no=%llx\nb=%llx\n\n", remain, dup_extent.SourceFileOffset.QuadPart, dup_extent.ByteCount.QuadPart );
		if( !DeviceIoControl( destination, FSCTL_DUPLICATE_EXTENTS_TO_FILE, &dup_extent, sizeof dup_extent, nullptr, 0, &dummy, nullptr ) )
		{
			_CrtDbgBreak();
			return false;
		}
	}

	FILETIME atime = { file_basic.LastAccessTime.LowPart, ULONG( file_basic.LastAccessTime.HighPart ) };
	FILETIME mtime = { file_basic.LastWriteTime.LowPart, ULONG( file_basic.LastWriteTime.HighPart ) };
	SetFileTime( destination, nullptr, &atime, &mtime );
	dispose.DeleteFile = FALSE;
	return SetFileInformationByHandle( destination, FileDispositionInfo, &dispose, sizeof dispose ) != 0;
}
int __cdecl wmain( int argc, PWSTR argv[] )
{
	_CrtSetDbgFlag( _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG ) | _CRTDBG_LEAK_CHECK_DF );
	_CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR );
	_CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_DEBUG | _CRTDBG_MODE_FILE );
	setlocale( LC_ALL, "" );

	if( argc != 3 )
	{
		fprintf(
			stderr,
			"Copy file without actual data write.\n"
			"\n"
			"%ls source destination\n"
			"\n"
			"source       Specifies a file to copy.\n"
			"             source must have placed on the ReFS volume.\n"
			"destination  Specifies new file name.\n"
			"             destination must have placed on the same volume as source.\n",
			PathFindFileNameW( argv[0] )
			);
		return EXIT_FAILURE;
	}
	auto source = std::make_unique<WCHAR[]>( PATHCCH_MAX_CCH );
	auto destination = std::make_unique<WCHAR[]>( PATHCCH_MAX_CCH );
	if( FAILED( PathCchCanonicalizeEx( source.get(), PATHCCH_MAX_CCH, argv[1], PATHCCH_ALLOW_LONG_PATHS ) )
		|| FAILED( PathCchCanonicalizeEx( destination.get(), PATHCCH_MAX_CCH, argv[2], PATHCCH_ALLOW_LONG_PATHS ) ) )
	{
		PrintWindowsError();
		return EXIT_FAILURE;
	}
	if( !reflink( source.get(), destination.get() ) )
	{
		PrintWindowsError();
		return EXIT_FAILURE;
	}
}<|endoftext|>