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

#include <votca/tools/spline.h>
#include <votca/tools/cubicspline.h>
#include <votca/tools/akimaspline.h>
#include <votca/tools/linspline.h>
#include <votca/tools/table.h>
#include <votca/tools/tokenizer.h>
#include <boost/program_options.hpp>
#include <iostream>
#include <votca/csg/version.h>

using namespace std;
namespace po = boost::program_options;
using namespace votca::csg;
using namespace votca::tools;

void help_text()
{
    votca::csg::HelpTextHeader("csg_resample");
    cout << "Change grid and interval of any sort of table files.\n"
            "Mainly called internally by inverse script, can also be\n"
            "used to manually prepare input files for coarse-grained\n"
            "simulations.\n\n";
}

void check_option(po::options_description &desc, po::variables_map &vm, const string &option)
{
    if(!vm.count(option)) {
        cout << "csg_resample \n\n";
        cout << desc << endl << "parameter " << option << " is not specified\n";
        exit(1);
    }
}

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

    string in_file, out_file, grid, fitgrid, comment, type, boundaries;
    Spline *spline=NULL;
    Table in, out, der;
    // program options
    po::options_description desc("Allowed options");

    desc.add_options()
      ("help", "produce this help message")
      ("in", po::value<string>(&in_file), "table to read")
      ("out", po::value<string>(&out_file), "table to write")
      ("derivative", po::value<string>(), "table to write")
      ("grid", po::value<string>(&grid), "new grid spacing (min:step:max). If 'grid' is specified only, interpolation is performed.")
      ("type", po::value<string>(&type)->default_value("akima"), "[cubic|akima|linear]. If option is not specified, the default type 'akima' is assumed.")
      ("fitgrid", po::value<string>(&fitgrid), "specify fit grid (min:step:max). If 'grid' and 'fitgrid' are specified, a fit is performed.")
      ("nocut", "Option for fitgrid: Normally, values out of fitgrid boundaries are cut off. If they shouldn't, choose --nocut.")
      ("comment", po::value<string>(&comment), "store a comment in the output table")
      ("boundaries", po::value<string>(&boundaries), "(natural|periodic|derivativezero) sets boundary conditions");

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch(po::error err) {
        cout << "error parsing command line: " << err.what() << endl;
        return -1;
    }

    try {
    // does the user want help?
    if (vm.count("help")) {
        help_text();
        cout << desc << endl;
        return 0;
    }

    check_option(desc, vm, "in");
    check_option(desc, vm, "out");

    if(!(vm.count("grid") || vm.count("fitgrid"))) {
            cout << "Need grid for interpolation or fitgrid for fit.\n";
            return 1;
    }

    if((!vm.count("grid")) && vm.count("fitgrid")) {
            cout << "Need a grid for fitting as well.\n";
            return 1;
    }

    double min, max, step;
    {
        Tokenizer tok(grid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format, use min:step:max\n";
            return 1;
        }
        min = boost::lexical_cast<double>(toks[0]);
        step = boost::lexical_cast<double>(toks[1]);
        max = boost::lexical_cast<double>(toks[2]);
    }

    in.Load(in_file);

    if (vm.count("type")) {
        if(type=="cubic") {
            spline = new CubicSpline();
        }
        else if(type=="akima") {
            spline = new AkimaSpline();
        }
        else if(type=="linear") {
            spline = new LinSpline();
        }
        else {
            throw std::runtime_error("unknown type");
        }
    }
    spline->setBC(Spline::splineNormal);

    if (vm.count("boundaries")) {
        if(boundaries=="periodic") {
            spline->setBC(Spline::splinePeriodic);
        }
        if(boundaries=="derivativezero") {
            spline->setBC(Spline::splineDerivativeZero);
        }
        //default: normal
    }

    // in case fit is specified
    if (vm.count("fitgrid")) {
        Tokenizer tok(fitgrid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format in fitgrid, use min:step:max\n";
            return 1;
        }
        double sp_min, sp_max, sp_step;
        sp_min = boost::lexical_cast<double>(toks[0]);
        sp_step = boost::lexical_cast<double>(toks[1]);
        sp_max = boost::lexical_cast<double>(toks[2]);
        cout << "doing " << type << " fit " << sp_min << ":" << sp_step << ":" << sp_max << endl;

        // cut off any values out of fitgrid boundaries (exception: do nothing in case of --nocut)
        ub::vector<double> x_copy;
        ub::vector<double> y_copy;
        if (!vm.count("nocut")) {
            // determine vector size
            int minindex=-1, maxindex;
            for (size_t i=0; i<in.x().size(); i++) {
                if(in.x(i)<sp_min) {
                    minindex = i;
                }
                if(in.x(i)<sp_max) {
                    maxindex = i;
                }
            }
            // copy data values in [sp_min,sp_max] into new vectors
            minindex++;
            x_copy = ub::zero_vector<double>(maxindex-minindex+1);
            y_copy = ub::zero_vector<double>(maxindex-minindex+1);
            for (int i=minindex; i<=maxindex; i++) {
                x_copy(i-minindex) = in.x(i);
                y_copy(i-minindex) = in.y(i);
            }
        }

        // fitting
        spline->GenerateGrid(sp_min, sp_max, sp_step);
        try {
            if (vm.count("nocut")) {
                spline->Fit(in.x(), in.y());
            } else {
                spline->Fit(x_copy, y_copy);
            }
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while fitting.");
        }
    } else {
        // otherwise do interpolation (default = cubic)
        try {
            spline->Interpolate(in.x(), in.y());
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while interpolating.");
        }
    }

    out.GenerateGridSpacing(min, max, step);
    spline->Calculate(out.x(), out.y());

    //store a comment line
    if (vm.count("comment")){
        out.set_comment(comment);
    }
    out.y() = out.y();
    out.flags() = ub::scalar_vector<double>(out.flags().size(), 'o');

    unsigned int i=0;
    for(i=0; out.x(i) < in.x(0) && i<out.size(); ++i);

    unsigned int j=0;
    for(;i < out.size(); ++i) {
        for(; j < in.size(); ++j)
            if(in.x(j) >= out.x(i)  || fabs(in.x(j)-out.x(i) ) < 1e-12) // fix for precison errors
                break;
        if(in.size() == j) break;
        out.flags(i) = in.flags(j);
    }

    out.Save(out_file);

    if (vm.count("derivative")) {
        der.GenerateGridSpacing(min, max, step);
        der.flags() = ub::scalar_vector<double>(der.flags().size(), 'o');

        spline->CalculateDerivative(der.x(), der.y());

        der.Save(vm["derivative"].as<string>());
    }

    delete spline;
	}
    catch(std::exception &error) {
         cerr << "an error occurred:\n" << error.what() << endl;
         return -1;
    }
    return 0;
}

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

#include <votca/tools/spline.h>
#include <votca/tools/cubicspline.h>
#include <votca/tools/akimaspline.h>
#include <votca/tools/linspline.h>
#include <votca/tools/table.h>
#include <votca/tools/tokenizer.h>
#include <boost/program_options.hpp>
#include <iostream>
#include <votca/csg/version.h>

using namespace std;
namespace po = boost::program_options;
using namespace votca::csg;
using namespace votca::tools;

void help_text()
{
    votca::csg::HelpTextHeader("csg_resample");
    cout << "Change grid and interval of any sort of table files.\n"
            "Mainly called internally by inverse script, can also be\n"
            "used to manually prepare input files for coarse-grained\n"
            "simulations.\n\n";
}

void check_option(po::options_description &desc, po::variables_map &vm, const string &option)
{
    if(!vm.count(option)) {
        cout << "csg_resample \n\n";
        cout << desc << endl << "parameter " << option << " is not specified\n";
        exit(1);
    }
}

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

    string in_file, out_file, grid, fitgrid, comment, type, boundaries;
    Spline *spline=NULL;
    Table in, out, der;
    // program options
    po::options_description desc("Allowed options");

    desc.add_options()
      ("help", "produce this help message")
      ("in", po::value<string>(&in_file), "table to read")
      ("out", po::value<string>(&out_file), "table to write")
      ("derivative", po::value<string>(), "table to write")
      ("grid", po::value<string>(&grid), "new grid spacing (min:step:max). If 'grid' is specified only, interpolation is performed.")
      ("type", po::value<string>(&type)->default_value("akima"), "[cubic|akima|linear]. If option is not specified, the default type 'akima' is assumed.")
      ("fitgrid", po::value<string>(&fitgrid), "specify fit grid (min:step:max). If 'grid' and 'fitgrid' are specified, a fit is performed.")
      ("nocut", "Option for fitgrid: Normally, values out of fitgrid boundaries are cut off. If they shouldn't, choose --nocut.")
      ("comment", po::value<string>(&comment), "store a comment in the output table")
      ("boundaries", po::value<string>(&boundaries), "(natural|periodic|derivativezero) sets boundary conditions");

    po::variables_map vm;
    try {
        po::store(po::parse_command_line(argc, argv, desc), vm);
        po::notify(vm);
    }
    catch(po::error err) {
        cout << "error parsing command line: " << err.what() << endl;
        return -1;
    }

    try {
    // does the user want help?
    if (vm.count("help")) {
        help_text();
        cout << desc << endl;
        return 0;
    }

    check_option(desc, vm, "in");
    check_option(desc, vm, "out");

    if(!(vm.count("grid") || vm.count("fitgrid"))) {
            cout << "Need grid for interpolation or fitgrid for fit.\n";
            return 1;
    }

    if((!vm.count("grid")) && vm.count("fitgrid")) {
            cout << "Need a grid for fitting as well.\n";
            return 1;
    }

    double min, max, step;
    {
        Tokenizer tok(grid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format, use min:step:max\n";
            return 1;
        }
        min = boost::lexical_cast<double>(toks[0]);
        step = boost::lexical_cast<double>(toks[1]);
        max = boost::lexical_cast<double>(toks[2]);
    }

    in.Load(in_file);

    if (vm.count("type")) {
        if(type=="cubic") {
            spline = new CubicSpline();
        }
        else if(type=="akima") {
            spline = new AkimaSpline();
        }
        else if(type=="linear") {
            spline = new LinSpline();
        }
        else {
            throw std::runtime_error("unknown type");
        }
    }
    spline->setBC(Spline::splineNormal);

    if (vm.count("boundaries")) {
        if(boundaries=="periodic") {
            spline->setBC(Spline::splinePeriodic);
        }
        if(boundaries=="derivativezero") {
            spline->setBC(Spline::splineDerivativeZero);
        }
        //default: normal
    }

    // in case fit is specified
    if (vm.count("fitgrid")) {
        Tokenizer tok(fitgrid, ":");
        vector<string> toks;
        tok.ToVector(toks);
        if(toks.size()!=3) {
            cout << "wrong range format in fitgrid, use min:step:max\n";
            return 1;
        }
        double sp_min, sp_max, sp_step;
        sp_min = boost::lexical_cast<double>(toks[0]);
        sp_step = boost::lexical_cast<double>(toks[1]);
        sp_max = boost::lexical_cast<double>(toks[2]);
        cout << "doing " << type << " fit " << sp_min << ":" << sp_step << ":" << sp_max << endl;

        // cut off any values out of fitgrid boundaries (exception: do nothing in case of --nocut)
        ub::vector<double> x_copy;
        ub::vector<double> y_copy;
        if (!vm.count("nocut")) {
            // determine vector size
            int minindex=-1, maxindex;
            for (size_t i=0; i<in.x().size(); i++) {
                if(in.x(i)<sp_min) {
                    minindex = i;
                }
                if(in.x(i)<sp_max) {
                    maxindex = i;
                }
            }
            // copy data values in [sp_min,sp_max] into new vectors
            minindex++;
            x_copy = ub::zero_vector<double>(maxindex-minindex+1);
            y_copy = ub::zero_vector<double>(maxindex-minindex+1);
            for (int i=minindex; i<=maxindex; i++) {
                x_copy(i-minindex) = in.x(i);
                y_copy(i-minindex) = in.y(i);
            }
        }

        // fitting
        spline->GenerateGrid(sp_min, sp_max, sp_step);
        try {
            if (vm.count("nocut")) {
                spline->Fit(in.x(), in.y());
            } else {
                spline->Fit(x_copy, y_copy);
            }
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data for fit, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while fitting.");
        }
    } else {
        // otherwise do interpolation (default = cubic)
        try {
            spline->Interpolate(in.x(), in.y());
        } catch (const char* message) {
            if(strcmp("qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else if(strcmp("constrained_qrsolve_zero_column_in_matrix",message)) {
                throw std::runtime_error("error in Linalg::linalg_constrained_qrsolve : Not enough data, please adjust grid (zero row in fit matrix)");
            }
            else throw std::runtime_error("Unknown error in csg_resample while interpolating.");
        }
    }

    out.GenerateGridSpacing(min, max, step);
    spline->Calculate(out.x(), out.y());

    //store a comment line
    if (vm.count("comment")){
        out.set_comment(comment);
    }
    out.y() = out.y();
    out.flags() = ub::scalar_vector<double>(out.flags().size(), 'o');

    der.GenerateGridSpacing(min, max, step);
    der.flags() = ub::scalar_vector<double>(der.flags().size(), 'o');

    unsigned int i=0;
    for(i=0; out.x(i) < in.x(0) && i<out.size(); ++i);

    unsigned int j=0;
    for(;i < out.size(); ++i) {
        for(; j < in.size(); ++j)
            if(in.x(j) >= out.x(i)  || fabs(in.x(j)-out.x(i) ) < 1e-12) // fix for precison errors
                break;
        if(in.size() == j) break;
        out.flags(i) = in.flags(j);
        der.flags(i) = in.flags(j);
    }

    out.Save(out_file);

    if (vm.count("derivative")) {
        spline->CalculateDerivative(der.x(), der.y());

        der.Save(vm["derivative"].as<string>());
    }

    delete spline;
	}
    catch(std::exception &error) {
         cerr << "an error occurred:\n" << error.what() << endl;
         return -1;
    }
    return 0;
}

<|endoftext|>


<commit_before>/*
 * Date Started: 8/09/18
 * Original Author: Sajid Ibne Anower
 * Editors:
 * Purpose: Widget to display voltage of the batteries
 * This code is released under the MIT License. Copyright BLUEsat UNSW, 2017, 2018
 */
#include "ros_video_components/ros_voltage_meter.hpp"

#define RECT_X 0
#define RECT_Y 0
#define RECT_WIDTH RECT_X*40
#define RECT_HEIGHT 150
#define MAXDATA 100
#define MAXNUM 5
#define NUMCOLOR 3
#define GREEN 4
#define YELLOW 2
#define RED 1
#define HASH MAXDATA/MAXNUM
#define TOO_WEAK MAXDATA/20

ROS_Voltage_Meter::ROS_Voltage_Meter(QQuickItem * parent) :
    QQuickPaintedItem(parent),
    topic_value("/rover/volt"),
    ros_ready(false),
    data(50) {}

void ROS_Voltage_Meter::setup(ros::NodeHandle * nh) {
    volt_sub = nh->subscribe(
        "/rover/volt",
        1,
        &ROS_Voltage_Meter::receive_volt_val,
        this);
    ros_ready = true;
}

void ROS_Voltage_Meter::paint(QPainter * painter) {
    int x = RECT_X;
    int y = RECT_Y;
    int widthV = width(); // RECT_WIDTH;
    int heightV = height(); // RECT_HEIGHT;

    QLinearGradient linearGradient(0, 0, 100, 100);
    int num = 0;
    float hash = HASH;
    if (data >= MAXDATA) {
        num = MAXNUM;
    } else if (data <= TOO_WEAK) {
        num = 0;
        linearGradient.setColorAt(0.0, Qt::white);
        painter->setBrush(linearGradient);
    } else {
        num = (data/hash) + 1;
    }
    // draw the outer main rectangle
    painter->drawRect(x, y, widthV - 1, heightV - 1);

    int i = 0;

    int barWidth = widthV/MAXNUM;
    int barHeight = heightV/MAXNUM;
    y += ((MAXNUM-1) * heightV) /MAXNUM;
    const int increment = heightV/MAXNUM;
    if (num == 0) {
        ROS_INFO("NO SIGNAL\n");
    } else {
        for (i = 1; i <= num; i++) {
            if (num >= GREEN) {
                linearGradient.setColorAt(0.2, Qt::green);
            } else if (num >= YELLOW) {
                linearGradient.setColorAt(0.2, Qt::yellow);
            } else {
                linearGradient.setColorAt(0.2, Qt::red);
            }
            painter->setBrush(linearGradient);
            painter->drawRect(x, y, barWidth, barHeight);
            x += barWidth; // move x along
            barHeight += increment; // increase height
            y -= increment; // decrease height
        }
    }
}

void ROS_Voltage_Meter::set_topic(const QString & new_value) {
    // ROS_INFO("set_topic");
    if (topic_value != new_value) {
        topic_value = new_value;
        if (ros_ready) {
            volt_sub.shutdown();
            volt_sub = nh->subscribe(
                topic_value.toStdString(),
                1,
                &ROS_Voltage_Meter::receive_volt_val,
                this);
        }
        emit topic_changed();
    }
}

QString ROS_Voltage_Meter::get_topic() const {
    return topic_value;
}

void ROS_Voltage_Meter :: receive_volt_val(const std_msgs::Float32::ConstPtr & msg) {
    data = msg->data;
    ROS_INFO("Received voltage update");
    update();
}
<commit_msg>Add stub for paint<commit_after>/*
 * Date Started: 8/09/18
 * Original Author: Sajid Ibne Anower
 * Editors:
 * Purpose: Widget to display voltage of the batteries
 * This code is released under the MIT License. Copyright BLUEsat UNSW, 2017, 2018
 */
#include "ros_video_components/ros_voltage_meter.hpp"

ROS_Voltage_Meter::ROS_Voltage_Meter(QQuickItem * parent) :
    QQuickPaintedItem(parent),
    topic_value("/rover/volt"),
    ros_ready(false),
    data(50) {}

void ROS_Voltage_Meter::setup(ros::NodeHandle * nh) {
    volt_sub = nh->subscribe(
        "/rover/volt",
        1,
        &ROS_Voltage_Meter::receive_volt_val,
        this);
    ros_ready = true;
}

void ROS_Voltage_Meter::paint(QPainter * painter) {
    // TODO(sajidanower23)
}

void ROS_Voltage_Meter::set_topic(const QString & new_value) {
    // ROS_INFO("set_topic");
    if (topic_value != new_value) {
        topic_value = new_value;
        if (ros_ready) {
            volt_sub.shutdown();
            volt_sub = nh->subscribe(
                topic_value.toStdString(),
                1,
                &ROS_Voltage_Meter::receive_volt_val,
                this);
        }
        emit topic_changed();
    }
}

QString ROS_Voltage_Meter::get_topic() const {
    return topic_value;
}

void ROS_Voltage_Meter :: receive_volt_val(const std_msgs::Float32::ConstPtr & msg) {
    data = msg->data;
    ROS_INFO("Received voltage update");
    update();
}
<|endoftext|>


<commit_before>#include "./shader_program.h"
#include <string>
#include <QFile>
#include <QUrl>
#include <QString>
#include <QRegularExpression>
#include <QTextStream>
#include <QDir>
#include "./gl.h"

ShaderProgram::ShaderProgram(Gl *gl, std::string vertexShaderPath,
                             std::string fragmentShaderPath)
  : gl(gl)
{
  if (!shaderProgram.addShaderFromSourceCode(
          QOpenGLShader::Vertex,
          readFileAndHandleIncludes(vertexShaderPath.c_str())))
  {
    qCritical() << "error";
  }
  if (!shaderProgram.addShaderFromSourceCode(
          QOpenGLShader::Fragment,
          readFileAndHandleIncludes(fragmentShaderPath.c_str())))
  {
    qCritical() << "error";
  }
  if (!shaderProgram.link())
  {
    qCritical() << "error";
  }
  glCheckError();
}

ShaderProgram::~ShaderProgram()
{
}

void ShaderProgram::bind()
{
  shaderProgram.bind();
}

void ShaderProgram::release()
{
  shaderProgram.release();
}

void ShaderProgram::enableAndSetAttributes(std::string usage,
                                           int perVertexElements)
{
  shaderProgram.enableAttributeArray(usage.c_str());
  shaderProgram.setAttributeBuffer(usage.c_str(), GL_FLOAT, 0,
                                   perVertexElements);
  glCheckError();
}

int ShaderProgram::getId()
{
  return shaderProgram.programId();
}

void ShaderProgram::setUniform(const char *name, Eigen::Matrix4f matrix)
{
  glAssert(gl->glProgramUniformMatrix4fv(getId(), getLocation(name), 1,
                                         GL_FALSE, matrix.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector4f vector)
{
  glAssert(
      gl->glProgramUniform4fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector3f vector)
{
  glAssert(
      gl->glProgramUniform3fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector2f vector)
{
  glAssert(
      gl->glProgramUniform2fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, float value)
{
  glAssert(gl->glProgramUniform1f(getId(), getLocation(name), value));
}

void ShaderProgram::setUniform(const char *name, int value)
{
  glAssert(gl->glProgramUniform1i(getId(), getLocation(name), value));
}

QString readFile(QString path)
{
  QFile file(path);

  if (!file.open(QFile::ReadOnly | QFile::Text))
    throw std::runtime_error("The file '" + path.toStdString() +
                             "' doesn't exist!");

  std::stringstream buffer;
  QTextStream in(&file);

  return in.readAll();
}

QString ShaderProgram::readFileAndHandleIncludes(QString path)
{
  auto directory = QFileInfo(path).absoluteDir().path() + "/";
  auto source = readFile(path);

  QRegularExpression regex("^[ ]*#include[ ]+[\"<](.*)[\">].*");
  regex.setPatternOptions(QRegularExpression::MultilineOption);

  auto match = regex.match(source);
  while (match.hasMatch())
  {
    auto filename = match.captured(1);
    auto includePath = directory + filename;
    auto includeSource = readFile(includePath);
    includeSource = includeSource.replace(
        QRegularExpression("^[ ]*#version \\d*.*$",
                           QRegularExpression::MultilineOption),
        "");
    source = source.replace(match.capturedStart(0), match.capturedLength(0),
                            includeSource);

    qDebug() << path << "includes" << includePath;

    match = regex.match(source, match.capturedEnd(0));
  }

  return source;
}

int ShaderProgram::getLocation(const char *name)
{
  return shaderProgram.uniformLocation(name);
}

<commit_msg>Fix linting errors.<commit_after>#include "./shader_program.h"
#include <QFile>
#include <QUrl>
#include <QString>
#include <QRegularExpression>
#include <QTextStream>
#include <QDir>
#include <string>
#include "./gl.h"

ShaderProgram::ShaderProgram(Gl *gl, std::string vertexShaderPath,
                             std::string fragmentShaderPath)
  : gl(gl)
{
  if (!shaderProgram.addShaderFromSourceCode(
          QOpenGLShader::Vertex,
          readFileAndHandleIncludes(vertexShaderPath.c_str())))
  {
    qCritical() << "error";
  }
  if (!shaderProgram.addShaderFromSourceCode(
          QOpenGLShader::Fragment,
          readFileAndHandleIncludes(fragmentShaderPath.c_str())))
  {
    qCritical() << "error";
  }
  if (!shaderProgram.link())
  {
    qCritical() << "error";
  }
  glCheckError();
}

ShaderProgram::~ShaderProgram()
{
}

void ShaderProgram::bind()
{
  shaderProgram.bind();
}

void ShaderProgram::release()
{
  shaderProgram.release();
}

void ShaderProgram::enableAndSetAttributes(std::string usage,
                                           int perVertexElements)
{
  shaderProgram.enableAttributeArray(usage.c_str());
  shaderProgram.setAttributeBuffer(usage.c_str(), GL_FLOAT, 0,
                                   perVertexElements);
  glCheckError();
}

int ShaderProgram::getId()
{
  return shaderProgram.programId();
}

void ShaderProgram::setUniform(const char *name, Eigen::Matrix4f matrix)
{
  glAssert(gl->glProgramUniformMatrix4fv(getId(), getLocation(name), 1,
                                         GL_FALSE, matrix.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector4f vector)
{
  glAssert(
      gl->glProgramUniform4fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector3f vector)
{
  glAssert(
      gl->glProgramUniform3fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, Eigen::Vector2f vector)
{
  glAssert(
      gl->glProgramUniform2fv(getId(), getLocation(name), 1, vector.data()));
}

void ShaderProgram::setUniform(const char *name, float value)
{
  glAssert(gl->glProgramUniform1f(getId(), getLocation(name), value));
}

void ShaderProgram::setUniform(const char *name, int value)
{
  glAssert(gl->glProgramUniform1i(getId(), getLocation(name), value));
}

QString readFile(QString path)
{
  QFile file(path);

  if (!file.open(QFile::ReadOnly | QFile::Text))
    throw std::runtime_error("The file '" + path.toStdString() +
                             "' doesn't exist!");

  std::stringstream buffer;
  QTextStream in(&file);

  return in.readAll();
}

QString ShaderProgram::readFileAndHandleIncludes(QString path)
{
  auto directory = QFileInfo(path).absoluteDir().path() + "/";
  auto source = readFile(path);

  QRegularExpression regex("^[ ]*#include[ ]+[\"<](.*)[\">].*");
  regex.setPatternOptions(QRegularExpression::MultilineOption);

  auto match = regex.match(source);
  while (match.hasMatch())
  {
    auto filename = match.captured(1);
    auto includePath = directory + filename;
    auto includeSource = readFile(includePath);
    includeSource = includeSource.replace(
        QRegularExpression("^[ ]*#version \\d*.*$",
                           QRegularExpression::MultilineOption),
        "");
    source = source.replace(match.capturedStart(0), match.capturedLength(0),
                            includeSource);

    qDebug() << path << "includes" << includePath;

    match = regex.match(source, match.capturedEnd(0));
  }

  return source;
}

int ShaderProgram::getLocation(const char *name)
{
  return shaderProgram.uniformLocation(name);
}

<|endoftext|>


<commit_before>#include <type_traits>
#include <af/array.h>
#include <af/dim4.hpp>
#include <Array.hpp>
#include <diff.hpp>

namespace cpu
{
    unsigned getIdx(af::dim4 strides, af::dim4 offs, int i, int j = 0, int k = 0, int l = 0)
    {
        return ((l + offs[3]) * strides[3] +
                (k + offs[2]) * strides[2] +
                (j + offs[1]) * strides[1] +
                (i + offs[0]));
    }

    template<typename T>
    Array<T>* diff1(const Array<T> &in, const int dim)
    {
        // Bool for dimension
        bool is_dim0 = dim == 0;
        bool is_dim1 = dim == 1;
        bool is_dim2 = dim == 2;
        bool is_dim3 = dim == 3;

        // Decrement dimension of select dimension
        af::dim4 dims = in.dims();
        dims[dim]--;

        // Create output placeholder
        Array<T> *outArray = createValueArray(dims, (T)0);

        // Get pointers to raw data
        const T *inPtr = in.get(false);
              T *outPtr = outArray->get();

        // TODO: Improve this
        for(dim_type l = 0; l < dims[3]; l++) {
            for(dim_type k = 0; k < dims[2]; k++) {
                for(dim_type j = 0; j < dims[1]; j++) {
                    for(dim_type i = 0; i < dims[0]; i++) {
                        // Operation: out[index] = in[index + 1 * dim_size] - in[index]
                        int idx = getIdx(in.strides(), in.offsets(), i, j, k, l);
                        int jdx = getIdx(in.strides(), in.offsets(),
                                         i + is_dim0, j + is_dim1,
                                         k + is_dim2, l + is_dim3);
                        int odx = getIdx(outArray->strides(), outArray->offsets(), i, j, k, l);
                        outPtr[odx] = inPtr[jdx] - inPtr[idx];
                    }
                }
            }
        }

        return outArray;
    }

    template<typename T>
    Array<T>* diff2(const Array<T> &in, const int dim)
    {
        // Bool for dimension
        bool is_dim0 = dim == 0;
        bool is_dim1 = dim == 1;
        bool is_dim2 = dim == 2;
        bool is_dim3 = dim == 3;

        // Decrement dimension of select dimension
        af::dim4 dims = in.dims();
        dims[dim] -= 2;

        // Create output placeholder
        Array<T> *outArray = createValueArray(dims, (T)0);

        // Get pointers to raw data
        const T *inPtr = in.get(false);
              T *outPtr = outArray->get();

        // TODO: Improve this
        for(dim_type l = 0; l < dims[3]; l++) {
            for(dim_type k = 0; k < dims[2]; k++) {
                for(dim_type j = 0; j < dims[1]; j++) {
                    for(dim_type i = 0; i < dims[0]; i++) {
                        // Operation: out[index] = in[index + 1 * dim_size] - in[index]
                        int idx = getIdx(in.strides(), in.offsets(), i, j, k, l);
                        int jdx = getIdx(in.strides(), in.offsets(),
                                         i + is_dim0, j + is_dim1,
                                         k + is_dim2, l + is_dim3);
                        int kdx = getIdx(in.strides(), in.offsets(),
                                         i + 2 * is_dim0, j + 2 * is_dim1,
                                         k + 2 * is_dim2, l + 2 * is_dim3);
                        int odx = getIdx(outArray->strides(), outArray->offsets(), i, j, k, l);
                        outPtr[odx] = inPtr[kdx] + inPtr[idx] - inPtr[jdx] - inPtr[jdx];
                    }
                }
            }
        }

        return outArray;
    }

#define INSTANTIATE(T)                                                  \
    template Array<T>* diff1<T>  (const Array<T> &in, const int dim);   \
    template Array<T>* diff2<T>  (const Array<T> &in, const int dim);   \

    INSTANTIATE(float)
    INSTANTIATE(double)
    INSTANTIATE(cfloat)
    INSTANTIATE(cdouble)
    INSTANTIATE(int)
    INSTANTIATE(uint)
    INSTANTIATE(uchar)
    INSTANTIATE(char)
}
<commit_msg>Updated diff CPU with offset changes<commit_after>#include <type_traits>
#include <af/array.h>
#include <af/dim4.hpp>
#include <Array.hpp>
#include <diff.hpp>

namespace cpu
{
    unsigned getIdx(af::dim4 strides, af::dim4 offs, int i, int j = 0, int k = 0, int l = 0)
    {
        return (l * strides[3] +
                k * strides[2] +
                j * strides[1] +
                i);
    }

    template<typename T>
    Array<T>* diff1(const Array<T> &in, const int dim)
    {
        // Bool for dimension
        bool is_dim0 = dim == 0;
        bool is_dim1 = dim == 1;
        bool is_dim2 = dim == 2;
        bool is_dim3 = dim == 3;

        // Decrement dimension of select dimension
        af::dim4 dims = in.dims();
        dims[dim]--;

        // Create output placeholder
        Array<T> *outArray = createValueArray(dims, (T)0);

        // Get pointers to raw data
        const T *inPtr = in.get();
              T *outPtr = outArray->get();

        // TODO: Improve this
        for(dim_type l = 0; l < dims[3]; l++) {
            for(dim_type k = 0; k < dims[2]; k++) {
                for(dim_type j = 0; j < dims[1]; j++) {
                    for(dim_type i = 0; i < dims[0]; i++) {
                        // Operation: out[index] = in[index + 1 * dim_size] - in[index]
                        int idx = getIdx(in.strides(), in.offsets(), i, j, k, l);
                        int jdx = getIdx(in.strides(), in.offsets(),
                                         i + is_dim0, j + is_dim1,
                                         k + is_dim2, l + is_dim3);
                        int odx = getIdx(outArray->strides(), outArray->offsets(), i, j, k, l);
                        outPtr[odx] = inPtr[jdx] - inPtr[idx];
                    }
                }
            }
        }

        return outArray;
    }

    template<typename T>
    Array<T>* diff2(const Array<T> &in, const int dim)
    {
        // Bool for dimension
        bool is_dim0 = dim == 0;
        bool is_dim1 = dim == 1;
        bool is_dim2 = dim == 2;
        bool is_dim3 = dim == 3;

        // Decrement dimension of select dimension
        af::dim4 dims = in.dims();
        dims[dim] -= 2;

        // Create output placeholder
        Array<T> *outArray = createValueArray(dims, (T)0);

        // Get pointers to raw data
        const T *inPtr = in.get();
              T *outPtr = outArray->get();

        // TODO: Improve this
        for(dim_type l = 0; l < dims[3]; l++) {
            for(dim_type k = 0; k < dims[2]; k++) {
                for(dim_type j = 0; j < dims[1]; j++) {
                    for(dim_type i = 0; i < dims[0]; i++) {
                        // Operation: out[index] = in[index + 1 * dim_size] - in[index]
                        int idx = getIdx(in.strides(), in.offsets(), i, j, k, l);
                        int jdx = getIdx(in.strides(), in.offsets(),
                                         i + is_dim0, j + is_dim1,
                                         k + is_dim2, l + is_dim3);
                        int kdx = getIdx(in.strides(), in.offsets(),
                                         i + 2 * is_dim0, j + 2 * is_dim1,
                                         k + 2 * is_dim2, l + 2 * is_dim3);
                        int odx = getIdx(outArray->strides(), outArray->offsets(), i, j, k, l);
                        outPtr[odx] = inPtr[kdx] + inPtr[idx] - inPtr[jdx] - inPtr[jdx];
                    }
                }
            }
        }

        return outArray;
    }

#define INSTANTIATE(T)                                                  \
    template Array<T>* diff1<T>  (const Array<T> &in, const int dim);   \
    template Array<T>* diff2<T>  (const Array<T> &in, const int dim);   \

    INSTANTIATE(float)
    INSTANTIATE(double)
    INSTANTIATE(cfloat)
    INSTANTIATE(cdouble)
    INSTANTIATE(int)
    INSTANTIATE(uint)
    INSTANTIATE(uchar)
    INSTANTIATE(char)
}
<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// bb_toposort_sccs LLVM sample. Demonstrates:
//
//
// Eli Bendersky (eliben@gmail.com)
// This code is in the public domain
//------------------------------------------------------------------------------
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"

using namespace llvm;

// Runs a topological sort on the basic blocks of the given function. Uses
// the simple recursive DFS from "Introduction to algorithms", with 3-coloring
// of vertices. The coloring enables detecting cycles in the graph with a simple
// test.
class TopoSorter {
public:
  void runToposort(const Function &F) {
    outs() << "Topological sort of function " << F.getName() << ":\n";
    // Initialize the color map by marking all the vertices white.
    for (Function::const_iterator I = F.begin(), IE = F.end(); I != IE; ++I) {
      ColorMap[I] = TopoSorter::WHITE;
    }

    // The BB graph has a single entry vertex from which the other BBs should
    // be discoverable - the function entry block.
    bool success = recursiveDFSToposort(&F.getEntryBlock());
    if (success) {
      // Now we have all the BBs inside SortedBBs in reverse topological order.
      for (BBVector::const_reverse_iterator RI = SortedBBs.rbegin(),
                                            RE = SortedBBs.rend();
                                            RI != RE; ++RI) {
        outs() << "  " << (*RI)->getName() << "\n";
      }
    } else {
      outs() << "  Sorting failed\n";
    }
  }
private:
  enum Color {WHITE, GREY, BLACK};
  // Color marks per vertex (BB).
  typedef DenseMap<const BasicBlock *, Color> BBColorMap;
  // Collects vertices (BBs) in "finish" order. The first finished vertex is
  // first, and so on.
  typedef SmallVector<const BasicBlock *, 32> BBVector;
  BBColorMap ColorMap;
  BBVector SortedBBs;

  // Helper function to recursively run topological sort from a given BB.
  // Returns true if the sort succeeded and false otherwise; topological sort
  // may fail if, for example, the graph is not a DAG (detected a cycle).
  bool recursiveDFSToposort(const BasicBlock *BB) {
    ColorMap[BB] = TopoSorter::GREY;
    // For demonstration, using the lowest-level APIs here. A BB's successors
    // are determined by looking at its terminator instruction.
    const TerminatorInst *TInst = BB->getTerminator();
    for (unsigned I = 0, NSucc = TInst->getNumSuccessors(); I < NSucc; ++I) {
      BasicBlock *Succ = TInst->getSuccessor(I);
      Color SuccColor = ColorMap[Succ];
      if (SuccColor == TopoSorter::WHITE) {
        if (!recursiveDFSToposort(Succ))
          return false;
      } else if (SuccColor == TopoSorter::GREY) {
        // This detects a cycle because grey vertices are all ancestors of the
        // currently explored vertex (in other words, they're "on the stack").
        outs() << "  Detected cycle: edge from " << BB->getName() <<
                  " to " << Succ->getName() << "\n";
        return false;
      }
    }
    // This BB is finished (fully explored), so we can add it to the vector.
    ColorMap[BB] = TopoSorter::BLACK;
    SortedBBs.push_back(BB);
    return true;
  }
};

class AnalyzeBBGraph : public FunctionPass {
public:
  AnalyzeBBGraph() : FunctionPass(ID) {}

  virtual bool runOnFunction(Function &F) {
    TopoSorter TS;
    TS.runToposort(F);
    return false;
  }

  // The address of this member is used to uniquely identify the class. This is
  // used by LLVM's own RTTI mechanism.
  static char ID;
};

char AnalyzeBBGraph::ID = 0;

int main(int argc, char **argv) {
  if (argc < 2) {
    errs() << "Usage: " << argv[0] << " <IR file>\n";
    return 1;
  }

  // Parse the input LLVM IR file into a module.
  SMDiagnostic Err;
  Module *Mod = ParseIRFile(argv[1], Err, getGlobalContext());
  if (!Mod) {
    Err.print(argv[0], errs());
    return 1;
  }

  // Create a pass manager and fill it with the passes we want to run.
  PassManager PM;
  PM.add(new AnalyzeBBGraph());
  PM.run(*Mod);

  return 0;
}
<commit_msg>Using po_iterator to produce a post-order iteration.<commit_after>//------------------------------------------------------------------------------
// bb_toposort_sccs LLVM sample. Demonstrates:
//
//
// Eli Bendersky (eliben@gmail.com)
// This code is in the public domain
//------------------------------------------------------------------------------
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Pass.h"
#include "llvm/PassManager.h"
#include "llvm/Support/CFG.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/SourceMgr.h"
#include <string>

using namespace llvm;

// Runs a topological sort on the basic blocks of the given function. Uses
// the simple recursive DFS from "Introduction to algorithms", with 3-coloring
// of vertices. The coloring enables detecting cycles in the graph with a simple
// test.
class TopoSorter {
public:
  void runToposort(const Function &F) {
    outs() << "Topological sort of function " << F.getName() << ":\n";
    // Initialize the color map by marking all the vertices white.
    for (Function::const_iterator I = F.begin(), IE = F.end(); I != IE; ++I) {
      ColorMap[I] = TopoSorter::WHITE;
    }

    // The BB graph has a single entry vertex from which the other BBs should
    // be discoverable - the function entry block.
    bool success = recursiveDFSToposort(&F.getEntryBlock());
    if (success) {
      // Now we have all the BBs inside SortedBBs in reverse topological order.
      for (BBVector::const_reverse_iterator RI = SortedBBs.rbegin(),
                                            RE = SortedBBs.rend();
                                            RI != RE; ++RI) {
        outs() << "  " << (*RI)->getName() << "\n";
      }
    } else {
      outs() << "  Sorting failed\n";
    }
  }
private:
  enum Color {WHITE, GREY, BLACK};
  // Color marks per vertex (BB).
  typedef DenseMap<const BasicBlock *, Color> BBColorMap;
  // Collects vertices (BBs) in "finish" order. The first finished vertex is
  // first, and so on.
  typedef SmallVector<const BasicBlock *, 32> BBVector;
  BBColorMap ColorMap;
  BBVector SortedBBs;

  // Helper function to recursively run topological sort from a given BB.
  // Returns true if the sort succeeded and false otherwise; topological sort
  // may fail if, for example, the graph is not a DAG (detected a cycle).
  bool recursiveDFSToposort(const BasicBlock *BB) {
    ColorMap[BB] = TopoSorter::GREY;
    // For demonstration, using the lowest-level APIs here. A BB's successors
    // are determined by looking at its terminator instruction.
    const TerminatorInst *TInst = BB->getTerminator();
    for (unsigned I = 0, NSucc = TInst->getNumSuccessors(); I < NSucc; ++I) {
      BasicBlock *Succ = TInst->getSuccessor(I);
      Color SuccColor = ColorMap[Succ];
      if (SuccColor == TopoSorter::WHITE) {
        if (!recursiveDFSToposort(Succ))
          return false;
      } else if (SuccColor == TopoSorter::GREY) {
        // This detects a cycle because grey vertices are all ancestors of the
        // currently explored vertex (in other words, they're "on the stack").
        outs() << "  Detected cycle: edge from " << BB->getName() <<
                  " to " << Succ->getName() << "\n";
        return false;
      }
    }
    // This BB is finished (fully explored), so we can add it to the vector.
    ColorMap[BB] = TopoSorter::BLACK;
    SortedBBs.push_back(BB);
    return true;
  }
};

class AnalyzeBBGraph : public FunctionPass {
public:
  AnalyzeBBGraph(const std::string &AnalysisKind)
    : FunctionPass(ID), AnalysisKind(AnalysisKind)
  {}

  virtual bool runOnFunction(Function &F) {
    if (AnalysisKind == "-topo") {
      TopoSorter TS;
      TS.runToposort(F);
    } else if (AnalysisKind == "-po") {
      // Use LLVM's post-order iterator to produce a reverse topological sort.
      // Note that this doesn't detect cycles so if the graph is not a DAG, the
      // result is not a true topological sort.
      outs() << "Basic blocks of " << F.getName() << " in post-order:\n";
      for (po_iterator<BasicBlock *> I = po_begin(&F.getEntryBlock()),
                                     IE = po_end(&F.getEntryBlock());
                                     I != IE; ++I) {
        outs() << "  " << (*I)->getName() << "\n";
      }
    } else {
      outs() << "Unknown analysis kind: " << AnalysisKind << "\n";
    }
    return false;
  }

  // The address of this member is used to uniquely identify the class. This is
  // used by LLVM's own RTTI mechanism.
  static char ID;
private:
  std::string AnalysisKind;
};

char AnalyzeBBGraph::ID = 0;

int main(int argc, char **argv) {
  if (argc < 3) {
    // Using very basic command-line argument parsing here...
    errs() << "Usage: " << argv[0] << " -[topo|po|scc] <IR file>\n";
    return 1;
  }

  // Parse the input LLVM IR file into a module.
  SMDiagnostic Err;
  Module *Mod = ParseIRFile(argv[2], Err, getGlobalContext());
  if (!Mod) {
    Err.print(argv[0], errs());
    return 1;
  }

  // Create a pass manager and fill it with the passes we want to run.
  PassManager PM;
  PM.add(new AnalyzeBBGraph(std::string(argv[1])));
  PM.run(*Mod);

  return 0;
}
<|endoftext|>


<commit_before>/* sim_connection.cpp
 *
 * libpsx
 *
 * Copyright (C) 2015, Christopher Collins
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
*/
#include "psx.h"
#include <iostream>
#include <cstdio>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#endif

using namespace std;
using namespace psx;

SimConnection::SimConnection(const std::string &hostname, int port)
  : hostname(hostname), port(port)
{
  msgMutex = SDL_CreateMutex();
}

SimConnection::~SimConnection()
{
  stopListener();
  if (NULL != msgMutex) {
    SDL_DestroyMutex(msgMutex);
    msgMutex = NULL;
  }
}

bool
SimConnection::connect()
{
  char    serviceName[16];
  snprintf(serviceName, 16, "%d", port);
  serviceName[15] = '\0';

  struct addrinfo addrHints = {
    ai_flags: AI_NUMERICSERV | AI_ADDRCONFIG,
    ai_family: AF_INET,
    ai_socktype: SOCK_STREAM,
  };

  struct addrinfo *results = NULL;
  if (getaddrinfo(hostname.c_str(), serviceName, &addrHints, &results)) {
    return false;
  }

  socket_fd = socket(results->ai_family, results->ai_socktype, 0);
  if (-1 == socket_fd) {
    perror("connect: socket");
    return false;
  }
  int nodelay = 1;
  setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
  int retry_delay = base_retry_interval;
  while (running) {
    if (!::connect(socket_fd, results->ai_addr, results->ai_addrlen)) {
      return true;
    }
    SDL_Delay(retry_delay);
    if ((retry_delay * 2) <= max_retry_interval) {
      retry_delay *= 2;
    }
  }
  close(socket_fd);
  return false;
}

void
SimConnection::stopListener()
{
  running = false;
  // force shtudown the socket - this should trip a 0 byte iop in the listener which will let it die.
  if (socket_fd >= 0) {
    shutdown(socket_fd, SHUT_RDWR);
  }
  if (rcvThread != NULL) {
    SDL_WaitThread(rcvThread, NULL);
    rcvThread = NULL;
  }
}

extern "C" {
  static int
  bootstrapListener(void *data)
  {
    SimConnection *sc = static_cast<SimConnection *>(data);

    return sc->listener();
  }
}

void
SimConnection::startListener()
{
  if (NULL != rcvThread) {
    return;
  }
  running = true;
  rcvThread = SDL_CreateThread(bootstrapListener, "PSXListener", static_cast<void*>(this));
}

int
SimConnection::listener()
{
  while (running) {
    if (!connect()) {
      cerr << "failed to connect" << endl;
      continue;
    }

    std::string   curMsg = "";
    while(running) {
      char cBuf;
      int len = recv(socket_fd, &cBuf, 1, 0);
      if (len > 0) {
        if (cBuf == '\n') {
          interpret(curMsg);
          curMsg = "";
        } else {
          curMsg += cBuf;
        }
      } else {
        if (len < 0 && errno == EINTR) {
          continue;
        }
        // some kind of error.  Reconnect.
        ::close(socket_fd);
        socket_fd = -1;
        break;
      }
    }
  }
  return 0;
}

void
SimConnection::send(const std::string &msg)
{
  ::send(socket_fd, msg.c_str(), msg.length(), 0);
}

void
SimConnection::send(const WirePair &pair)
{
  std::string wireString = pair.toWire();
  wireString += "\n";

  send(wireString);
}
<commit_msg>conform with ANSI syntax<commit_after>/* sim_connection.cpp
 *
 * libpsx
 *
 * Copyright (C) 2015, Christopher Collins
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License version 2.1 as published by the Free Software Foundation
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 * USA
*/
#include "psx.h"
#include <iostream>
#include <cstdio>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#else
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#endif

using namespace std;
using namespace psx;

SimConnection::SimConnection(const std::string &hostname, int port)
  : hostname(hostname), port(port)
{
  msgMutex = SDL_CreateMutex();
}

SimConnection::~SimConnection()
{
  stopListener();
  if (NULL != msgMutex) {
    SDL_DestroyMutex(msgMutex);
    msgMutex = NULL;
  }
}

bool
SimConnection::connect()
{
  char    serviceName[16];
  snprintf(serviceName, 16, "%d", port);
  serviceName[15] = '\0';

  struct addrinfo addrHints = {
    .ai_flags = AI_NUMERICSERV | AI_ADDRCONFIG,
    .ai_family = AF_INET,
    .ai_socktype = SOCK_STREAM,
  };

  struct addrinfo *results = NULL;
  if (getaddrinfo(hostname.c_str(), serviceName, &addrHints, &results)) {
    return false;
  }

  socket_fd = socket(results->ai_family, results->ai_socktype, 0);
  if (-1 == socket_fd) {
    perror("connect: socket");
    return false;
  }
  int nodelay = 1;
  setsockopt(socket_fd, IPPROTO_TCP, TCP_NODELAY, &nodelay, sizeof(nodelay));
  int retry_delay = base_retry_interval;
  while (running) {
    if (!::connect(socket_fd, results->ai_addr, results->ai_addrlen)) {
      return true;
    }
    SDL_Delay(retry_delay);
    if ((retry_delay * 2) <= max_retry_interval) {
      retry_delay *= 2;
    }
  }
  close(socket_fd);
  return false;
}

void
SimConnection::stopListener()
{
  running = false;
  // force shtudown the socket - this should trip a 0 byte iop in the listener which will let it die.
  if (socket_fd >= 0) {
    shutdown(socket_fd, SHUT_RDWR);
  }
  if (rcvThread != NULL) {
    SDL_WaitThread(rcvThread, NULL);
    rcvThread = NULL;
  }
}

extern "C" {
  static int
  bootstrapListener(void *data)
  {
    SimConnection *sc = static_cast<SimConnection *>(data);

    return sc->listener();
  }
}

void
SimConnection::startListener()
{
  if (NULL != rcvThread) {
    return;
  }
  running = true;
  rcvThread = SDL_CreateThread(bootstrapListener, "PSXListener", static_cast<void*>(this));
}

int
SimConnection::listener()
{
  while (running) {
    if (!connect()) {
      cerr << "failed to connect" << endl;
      continue;
    }

    std::string   curMsg = "";
    while(running) {
      char cBuf;
      int len = recv(socket_fd, &cBuf, 1, 0);
      if (len > 0) {
        if (cBuf == '\n') {
          interpret(curMsg);
          curMsg = "";
        } else {
          curMsg += cBuf;
        }
      } else {
        if (len < 0 && errno == EINTR) {
          continue;
        }
        // some kind of error.  Reconnect.
        ::close(socket_fd);
        socket_fd = -1;
        break;
      }
    }
  }
  return 0;
}

void
SimConnection::send(const std::string &msg)
{
  ::send(socket_fd, msg.c_str(), msg.length(), 0);
}

void
SimConnection::send(const WirePair &pair)
{
  std::string wireString = pair.toWire();
  wireString += "\n";

  send(wireString);
}
<|endoftext|>


<commit_before>#include "../Block_Diagonal_Matrix.hxx"

// Minimum eigenvalue of A.  A is assumed to be symmetric.

// Annoyingly, El::HermitianEig modifies 'block'.  It is OK, because
// it is only called from step_length(), which passes in a temporary.
// Still ugly.
El::BigFloat min_eigenvalue(Block_Diagonal_Matrix &A)
{
  El::BigFloat local_min(El::limits::Max<El::BigFloat>());

  for(auto &block : A.blocks)
    {
      El::DistMatrix<El::BigFloat, El::VR, El::STAR> eigenvalues(block.Grid());
      El::HermitianEig(El::UpperOrLowerNS::LOWER, block, eigenvalues);
      local_min = El::Min(local_min, El::Min(eigenvalues));
    }
  return El::mpi::AllReduce(local_min, El::mpi::MIN, El::mpi::COMM_WORLD);
}
<commit_msg>Work around a bug in Elemental eigenvalue computation<commit_after>#include "../Block_Diagonal_Matrix.hxx"

// Minimum eigenvalue of A.  A is assumed to be symmetric.

// Annoyingly, El::HermitianEig modifies 'block'.  It is OK, because
// it is only called from step_length(), which passes in a temporary.
// Still ugly.
El::BigFloat min_eigenvalue(Block_Diagonal_Matrix &A)
{
  El::BigFloat local_min(El::limits::Max<El::BigFloat>());

  for(auto &block : A.blocks)
    {
      El::DistMatrix<El::BigFloat, El::VR, El::STAR> eigenvalues(block.Grid());
      /// There is a bug in El::HermitianEig when there is more than
      /// one level of recursion when computing eigenvalues.  One fix
      /// is to increase the cutoff so that there is no more than one
      /// level of recursion.

      /// An alternate workaround is to compute both eigenvalues and
      /// eigenvectors, but that seems to be significantly slower.
      El::HermitianEigCtrl<El::BigFloat> hermitian_eig_ctrl;
      hermitian_eig_ctrl.tridiagEigCtrl.dcCtrl.cutoff=block.Height()/2+1;

      El::HermitianEig(El::UpperOrLowerNS::LOWER, block, eigenvalues);
      local_min = El::Min(local_min, El::Min(eigenvalues));
    }
  return El::mpi::AllReduce(local_min, El::mpi::MIN, El::mpi::COMM_WORLD);
}
<|endoftext|>


<commit_before>/*===================================================================
APM_PLANNER Open Source Ground Control Station

(c) 2014 APM_PLANNER PROJECT <http://www.ardupilot.com>

This file is part of the APM_PLANNER project

    APM_PLANNER is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    APM_PLANNER is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with APM_PLANNER. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/
/**
 * @file
 *   @brief Droneshare API Query Object
 *
 *   @author Bill Bonney <billbonney@communistech.com>
 */

#include "QsLog.h"
#include "AutoUpdateCheck.h"
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptValueIterator>
#include <QMessageBox>
#include <QSettings>
#include "QGC.h"

#define VERSION_REGEX "(\\d*\\.\\d+\\.?\\d+)-?(rc\\d)?"

AutoUpdateCheck::AutoUpdateCheck(QObject *parent) :
    QObject(parent),
    m_networkReply(NULL),
    m_httpRequestAborted(false),
    m_suppressNoUpdateSignal(false)
{
    loadSettings();
}

void AutoUpdateCheck::forcedAutoUpdateCheck()
{
    loadSettings();
    setSkipVersion("0.0.0");
    autoUpdateCheck();
}

void AutoUpdateCheck::autoUpdateCheck()
{
    autoUpdateCheck(QUrl(AUTOUPDATE_VERSION_OBJECT_LOCATION
                          + AUTOUPDATE_VERSION_OBJECT_NAME));
}

void AutoUpdateCheck::autoUpdateCheck(const QUrl &url)
{
    QLOG_DEBUG() << "retrieve versionobject from server: " + url.toString();

    m_url = QUrl(url);

    if (m_networkReply != NULL){
        delete m_networkReply;
        m_networkReply = NULL;
    }
    m_networkReply = m_networkAccessManager.get(QNetworkRequest(m_url));
    connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpFinished()));
    connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(updateDataReadProgress(qint64,qint64)));
}

void AutoUpdateCheck::cancelDownload()
{
     m_httpRequestAborted = true;
     m_networkReply->abort();
}

void AutoUpdateCheck::httpFinished()
{
    QLOG_DEBUG() << "AutoUpdateCheck::httpFinished()";
    if (m_httpRequestAborted) {
        m_networkReply->deleteLater();
        m_networkReply = NULL;
        return;
    }

    // Finished donwloading the version information
    if (m_networkReply->error()) {
        // [TODO] cleanup download failed
#ifdef QT_DEBUG
        QMessageBox::information(NULL, tr("HTTP"),
                                 tr("Download failed: %1.")
                                 .arg(m_networkReply->errorString()));
#endif
    } else {
        // Process downloadeed object
        processDownloadedVersionObject(QString(m_networkReply->readAll()));
    }

    m_networkReply->deleteLater();
    m_networkReply = NULL;
}

void AutoUpdateCheck::processDownloadedVersionObject(const QString &versionObject)
{
    QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(versionObject);
    QScriptEngine engine;
    QScriptValue result = engine.evaluate("("+versionObject+")");

    if (engine.hasUncaughtException()){
        QLOG_ERROR() << "Error evaluating version object";
        QLOG_ERROR() << "Error @line#" << engine.uncaughtExceptionLineNumber();
        QLOG_ERROR() << "Backtrace:" << engine.uncaughtExceptionBacktrace();
        QLOG_ERROR() << "Syntax Check:" << syntaxCheck.errorMessage();
        QLOG_ERROR() << "Syntax Check line:" << syntaxCheck.errorLineNumber()
                     << " col:" << syntaxCheck.errorColumnNumber();
        return;
    }

    QScriptValue entries = result.property("releases");
    QScriptValueIterator it(entries);
    while (it.hasNext()){
        it.next();
        QScriptValue entry = it.value();

        QString platform = entry.property("platform").toString();
        QString type = entry.property("type").toString();
        QString version = entry.property("version").toString();
        QString name = entry.property("name").toString();
        QString locationUrl = entry.property("url").toString();

        if ((platform == define2string(APP_PLATFORM)) && (type == m_releaseType)){
            if (compareVersionStrings(version,QGC_APPLICATION_VERSION)){
                QLOG_DEBUG() << "Found New Version: " << platform << " "
                            << type << " " << version << " " << locationUrl;
                if(m_skipVerison != version){
                    emit updateAvailable(version, type, locationUrl, name);
                } else {
                    QLOG_INFO() << "Version Skipped at user request";
                }
                break;
            } else {
                QLOG_INFO() << "no new update available";
                if (!m_suppressNoUpdateSignal){
                    emit noUpdateAvailable();
                }
                m_suppressNoUpdateSignal = false;
            }
        }
    }
}

void AutoUpdateCheck::httpReadyRead()
{

}

void AutoUpdateCheck::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
    if (m_httpRequestAborted)
        return;
    QLOG_DEBUG() << "Downloading:" << bytesRead << "/" << totalBytes;
}

bool AutoUpdateCheck::compareVersionStrings(const QString& newVersion, const QString& currentVersion)
{
    // [TODO] DRY this out by creating global function for use in APM Firmware as well
    int newMajor,newMinor,newBuild = 0;
    int currentMajor, currentMinor,currentBuild = 0;

    QString newBuildSubMoniker, oldBuildSubMoniker; // holds if the build is a rc or dev build

    QRegExp versionEx(VERSION_REGEX);
    QString versionstr = "";
    int pos = versionEx.indexIn(newVersion);
    if (pos > -1) {
        // Split first sub-element to get numercal major.minor.build version
        QLOG_DEBUG() << "Detected newVersion:" << versionEx.capturedTexts()<< " count:"
                     << versionEx.captureCount();
        versionstr = versionEx.cap(1);
        QStringList versionList = versionstr.split(".");
        newMajor = versionList[0].toInt();
        newMinor = versionList[1].toInt();
        if (versionList.size() > 2){
            newBuild = versionList[2].toInt();
        }
        // second subelement is either rcX candidate or developement build
        if (versionEx.captureCount() == 2)
            newBuildSubMoniker = versionEx.cap(2);
    }

    QRegExp versionEx2(VERSION_REGEX);
    versionstr = "";
    pos = versionEx2.indexIn(currentVersion);
    if (pos > -1) {
        QLOG_DEBUG() << "Detected currentVersion:" << versionEx2.capturedTexts() << " count:"
                     << versionEx2.captureCount();
        versionstr = versionEx2.cap(1);
        QStringList versionList = versionstr.split(".");
        currentMajor = versionList[0].toInt();
         currentMinor = versionList[1].toInt();
        if (versionList.size() > 2){
            currentBuild = versionList[2].toInt();
        }
        // second subelement is either rcX candidate or developement build
        if (versionEx2.captureCount() == 2)
            oldBuildSubMoniker = versionEx2.cap(2);
    }

    QLOG_DEBUG() << "Verison Compare:" <<QString().sprintf(" New Version %d.%d.%d compared to Old Version %d.%d.%d",
                                                 newMajor,newMinor,newBuild, currentMajor, currentMinor,currentBuild);
    if (newMajor>currentMajor){
        // A Major release
        return true;
    } else if (newMajor == currentMajor){
        if (newMinor >  currentMinor){
            // A minor release
            return true;
        } else if (newMinor ==  currentMinor){
            if (newBuild > currentBuild)
                // new build (or tiny release)
                return true;
            else if (newBuild == currentBuild) {
                // Check if RC is newer
                // If the version isn't newer, it might be a new release candidate
                int newRc = 0, oldRc = 0;

                if (newBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)
                        && oldBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)) {
                    QRegExp releaseNumber("\\d+");
                    pos = releaseNumber.indexIn(newBuildSubMoniker);
                    if (pos > -1) {
                        QLOG_DEBUG() << "Detected newRc:" << versionEx.capturedTexts();
                        newRc = releaseNumber.cap(0).toInt();
                    }

                    QRegExp releaseNumber2("\\d+");
                    pos = releaseNumber2.indexIn(oldBuildSubMoniker);
                    if (pos > -1) {
                        QLOG_DEBUG() << "Detected oldRc:" << versionEx2.capturedTexts();
                        oldRc = releaseNumber.cap(0).toInt();
                    }

                    if (newRc > oldRc)
                        return true;
                }

                if (newBuildSubMoniker.length() == 0
                        && oldBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)) {
                    QLOG_DEBUG() << "Stable build newer that last unstable release candidate ";
                    return true; // this means a new stable build of the unstable rc is available
                }
            }
        }
    }

    return false;
}

void AutoUpdateCheck::setSkipVersion(const QString& version)
{
    m_skipVerison = version;
    writeSettings();
}

void AutoUpdateCheck::setAutoUpdateEnabled(bool enabled)
{
    m_isAutoUpdateEnabled = enabled;
    writeSettings();
}

bool AutoUpdateCheck::isUpdateEnabled()
{
    return m_isAutoUpdateEnabled;
}

void AutoUpdateCheck::loadSettings()
{
    // Load defaults from settings
    QSettings settings;
    settings.beginGroup("AUTO_UPDATE");
    m_isAutoUpdateEnabled = settings.value("ENABLED", true).toBool();
    m_skipVerison = settings.value("SKIP_VERSION", "0.0.0").toString();
    m_releaseType = settings.value("RELEASE_TYPE", define2string(APP_TYPE)).toString();
    settings.endGroup();
}

void AutoUpdateCheck::writeSettings()
{
    // Store settings
    QSettings settings;
    settings.beginGroup("AUTO_UPDATE");
    settings.setValue("ENABLED", m_isAutoUpdateEnabled);
    settings.setValue("SKIP_VERSION", m_skipVerison);
    settings.setValue("RELEASE_TYPE", m_releaseType);
    settings.endGroup();
    settings.sync();
}

void AutoUpdateCheck::suppressNoUpdateSignal()
{
    m_suppressNoUpdateSignal = true;
}
<commit_msg>Autoupdate: Fixes RC version compare<commit_after>/*===================================================================
APM_PLANNER Open Source Ground Control Station

(c) 2014 APM_PLANNER PROJECT <http://www.ardupilot.com>

This file is part of the APM_PLANNER project

    APM_PLANNER is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    APM_PLANNER is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with APM_PLANNER. If not, see <http://www.gnu.org/licenses/>.

======================================================================*/
/**
 * @file
 *   @brief Droneshare API Query Object
 *
 *   @author Bill Bonney <billbonney@communistech.com>
 */

#include "QsLog.h"
#include "AutoUpdateCheck.h"
#include <QtScript/QScriptEngine>
#include <QtScript/QScriptValue>
#include <QtScript/QScriptValueIterator>
#include <QMessageBox>
#include <QSettings>
#include "QGC.h"

#define VERSION_REGEX "(\\d*\\.\\d+\\.?\\d+)-?(rc\\d)?"

AutoUpdateCheck::AutoUpdateCheck(QObject *parent) :
    QObject(parent),
    m_networkReply(NULL),
    m_httpRequestAborted(false),
    m_suppressNoUpdateSignal(false)
{
    loadSettings();
}

void AutoUpdateCheck::forcedAutoUpdateCheck()
{
    loadSettings();
    setSkipVersion("0.0.0");
    autoUpdateCheck();
}

void AutoUpdateCheck::autoUpdateCheck()
{
    autoUpdateCheck(QUrl(AUTOUPDATE_VERSION_OBJECT_LOCATION
                          + AUTOUPDATE_VERSION_OBJECT_NAME));
}

void AutoUpdateCheck::autoUpdateCheck(const QUrl &url)
{
    QLOG_DEBUG() << "retrieve versionobject from server: " + url.toString();

    m_url = QUrl(url);

    if (m_networkReply != NULL){
        delete m_networkReply;
        m_networkReply = NULL;
    }
    m_networkReply = m_networkAccessManager.get(QNetworkRequest(m_url));
    connect(m_networkReply, SIGNAL(finished()), this, SLOT(httpFinished()));
    connect(m_networkReply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(updateDataReadProgress(qint64,qint64)));
}

void AutoUpdateCheck::cancelDownload()
{
     m_httpRequestAborted = true;
     m_networkReply->abort();
}

void AutoUpdateCheck::httpFinished()
{
    QLOG_DEBUG() << "AutoUpdateCheck::httpFinished()";
    if (m_httpRequestAborted) {
        m_networkReply->deleteLater();
        m_networkReply = NULL;
        return;
    }

    // Finished donwloading the version information
    if (m_networkReply->error()) {
        // [TODO] cleanup download failed
#ifdef QT_DEBUG
        QMessageBox::information(NULL, tr("HTTP"),
                                 tr("Download failed: %1.")
                                 .arg(m_networkReply->errorString()));
#endif
    } else {
        // Process downloadeed object
        processDownloadedVersionObject(QString(m_networkReply->readAll()));
    }

    m_networkReply->deleteLater();
    m_networkReply = NULL;
}

void AutoUpdateCheck::processDownloadedVersionObject(const QString &versionObject)
{
    QScriptSyntaxCheckResult syntaxCheck = QScriptEngine::checkSyntax(versionObject);
    QScriptEngine engine;
    QScriptValue result = engine.evaluate("("+versionObject+")");

    if (engine.hasUncaughtException()){
        QLOG_ERROR() << "Error evaluating version object";
        QLOG_ERROR() << "Error @line#" << engine.uncaughtExceptionLineNumber();
        QLOG_ERROR() << "Backtrace:" << engine.uncaughtExceptionBacktrace();
        QLOG_ERROR() << "Syntax Check:" << syntaxCheck.errorMessage();
        QLOG_ERROR() << "Syntax Check line:" << syntaxCheck.errorLineNumber()
                     << " col:" << syntaxCheck.errorColumnNumber();
        return;
    }

    QScriptValue entries = result.property("releases");
    QScriptValueIterator it(entries);
    while (it.hasNext()){
        it.next();
        QScriptValue entry = it.value();

        QString platform = entry.property("platform").toString();
        QString type = entry.property("type").toString();
        QString version = entry.property("version").toString();
        QString name = entry.property("name").toString();
        QString locationUrl = entry.property("url").toString();

        if ((platform == define2string(APP_PLATFORM)) && (type == m_releaseType)){
            if (compareVersionStrings(version,QGC_APPLICATION_VERSION)){
                QLOG_DEBUG() << "Found New Version: " << platform << " "
                            << type << " " << version << " " << locationUrl;
                if(m_skipVerison != version){
                    emit updateAvailable(version, type, locationUrl, name);
                } else {
                    QLOG_INFO() << "Version Skipped at user request";
                }
                break;
            } else {
                QLOG_INFO() << "no new update available";
                if (!m_suppressNoUpdateSignal){
                    emit noUpdateAvailable();
                }
                m_suppressNoUpdateSignal = false;
            }
        }
    }
}

void AutoUpdateCheck::httpReadyRead()
{

}

void AutoUpdateCheck::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
    if (m_httpRequestAborted)
        return;
    QLOG_DEBUG() << "Downloading:" << bytesRead << "/" << totalBytes;
}

bool AutoUpdateCheck::compareVersionStrings(const QString& newVersion, const QString& currentVersion)
{
    // [TODO] DRY this out by creating global function for use in APM Firmware as well
    int newMajor,newMinor,newBuild = 0;
    int currentMajor, currentMinor,currentBuild = 0;

    QString newBuildSubMoniker, oldBuildSubMoniker; // holds if the build is a rc or dev build

    QRegExp versionEx(VERSION_REGEX);
    QString versionstr = "";
    int pos = versionEx.indexIn(newVersion);
    if (pos > -1) {
        // Split first sub-element to get numercal major.minor.build version
        QLOG_DEBUG() << "Detected newVersion:" << versionEx.capturedTexts()<< " count:"
                     << versionEx.captureCount();
        versionstr = versionEx.cap(1);
        QStringList versionList = versionstr.split(".");
        newMajor = versionList[0].toInt();
        newMinor = versionList[1].toInt();
        if (versionList.size() > 2){
            newBuild = versionList[2].toInt();
        }
        // second subelement is either rcX candidate or developement build
        if (versionEx.captureCount() == 2)
            newBuildSubMoniker = versionEx.cap(2);
    }

    QRegExp versionEx2(VERSION_REGEX);
    versionstr = "";
    pos = versionEx2.indexIn(currentVersion);
    if (pos > -1) {
        QLOG_DEBUG() << "Detected currentVersion:" << versionEx2.capturedTexts() << " count:"
                     << versionEx2.captureCount();
        versionstr = versionEx2.cap(1);
        QStringList versionList = versionstr.split(".");
        currentMajor = versionList[0].toInt();
         currentMinor = versionList[1].toInt();
        if (versionList.size() > 2){
            currentBuild = versionList[2].toInt();
        }
        // second subelement is either rcX candidate or developement build
        if (versionEx2.captureCount() == 2)
            oldBuildSubMoniker = versionEx2.cap(2);
    }

    QLOG_DEBUG() << "Verison Compare:" <<QString().sprintf(" New Version %d.%d.%d compared to Old Version %d.%d.%d",
                                                 newMajor,newMinor,newBuild, currentMajor, currentMinor,currentBuild);
    if (newMajor>currentMajor){
        // A Major release
        return true;
    } else if (newMajor == currentMajor){
        if (newMinor >  currentMinor){
            // A minor release
            return true;
        } else if (newMinor ==  currentMinor){
            if (newBuild > currentBuild)
                // new build (or tiny release)
                return true;
            else if (newBuild == currentBuild) {
                // Check if RC is newer
                // If the version isn't newer, it might be a new release candidate
                int newRc = 0, oldRc = 0;

                if (newBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)
                        && oldBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)) {
                    QRegExp releaseNumber("\\d+");
                    pos = releaseNumber.indexIn(newBuildSubMoniker);
                    if (pos > -1) {
                        QLOG_DEBUG() << "Detected newRc:" << versionEx.capturedTexts();
                        newRc = releaseNumber.cap(0).toInt();
                    }

                    QRegExp releaseNumber2("\\d+");
                    pos = releaseNumber2.indexIn(oldBuildSubMoniker);
                    if (pos > -1) {
                        QLOG_DEBUG() << "Detected oldRc:" << versionEx2.capturedTexts();
                        oldRc = releaseNumber2.cap(0).toInt();
                    }

                    if (newRc > oldRc)
                        return true;
                }

                if (newBuildSubMoniker.length() == 0
                        && oldBuildSubMoniker.startsWith("RC", Qt::CaseInsensitive)) {
                    QLOG_DEBUG() << "Stable build newer that last unstable release candidate ";
                    return true; // this means a new stable build of the unstable rc is available
                }
            }
        }
    }

    return false;
}

void AutoUpdateCheck::setSkipVersion(const QString& version)
{
    m_skipVerison = version;
    writeSettings();
}

void AutoUpdateCheck::setAutoUpdateEnabled(bool enabled)
{
    m_isAutoUpdateEnabled = enabled;
    writeSettings();
}

bool AutoUpdateCheck::isUpdateEnabled()
{
    return m_isAutoUpdateEnabled;
}

void AutoUpdateCheck::loadSettings()
{
    // Load defaults from settings
    QSettings settings;
    settings.beginGroup("AUTO_UPDATE");
    m_isAutoUpdateEnabled = settings.value("ENABLED", true).toBool();
    m_skipVerison = settings.value("SKIP_VERSION", "0.0.0").toString();
    m_releaseType = settings.value("RELEASE_TYPE", define2string(APP_TYPE)).toString();
    settings.endGroup();
}

void AutoUpdateCheck::writeSettings()
{
    // Store settings
    QSettings settings;
    settings.beginGroup("AUTO_UPDATE");
    settings.setValue("ENABLED", m_isAutoUpdateEnabled);
    settings.setValue("SKIP_VERSION", m_skipVerison);
    settings.setValue("RELEASE_TYPE", m_releaseType);
    settings.endGroup();
    settings.sync();
}

void AutoUpdateCheck::suppressNoUpdateSignal()
{
    m_suppressNoUpdateSignal = true;
}
<|endoftext|>