<commit_before>#include <vector>
#include <iterator>
#include <algorithm>
#include <values.h>
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <assert.h>
#include <utility>
#include <cmath>
using namespace std;

ostream & operator <<(ostream &os, const vector<double> &d)
{
  os << "V(";
  for (int i = 0; i < d.size(); i++) {
    if (i > 0) os << ",";
    os << d[i];
  }
  return os << ")";
}

#include "dataset.h"
#include "tuple.h"
#include "random.h"
#include "extra.h"
#include "regressor.h"
#include "policy.h"
#include "domain.h"
#include "fqi.h"

/** Calculate the mean squared error of the output for a data set,
 * given a tree.
 */
double mse(const dataset &ts, const ExtraTree &rf)
{
  double mse;
  for (int i = 0; i < ts.size(); i++) {
    double tmp = rf.output(ts.data[i].attributes) - ts.data[i].output;
    mse += tmp * tmp;
  }
  return mse / ts.size();
}

/* Read the Parkinson's disease data (classification)
 */
void readparkinsons(dataset &ts) {
  ifstream src("testing/parkinsons.data");
  string line;

  while (getline(src, line)) {
    double tmp[24];
    int i = 0;
    int p1 = 0;
    int p2 = 0;
    while ((p2 = line.find(',', p1)) != string::npos) {
      tmp[i++] = strtod(line.substr(p1, p2 - p1).c_str(), NULL);
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output = tmp[17] > 0.0 ? 1.0 : -1.0;
    for (int j = 1; j < 17; j++) {
      d.attributes.push_back(tmp[j]);
    }
    for (int j = 18; j < 24; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

void readwdbc(dataset &ts) {
  ifstream src("testing/wdbc.data");
  string line;

  while (getline(src, line)) {
    double tmp[100];
    int i = 0;
    int n = 0;
    int p1 = 0;
    int p2 = 0;
    while ((p2 = line.find(',', p1)) != string::npos) {
      string subs = line.substr(p1, p2 - p1);

      /* index 0 is ignored, index 1 is either 'M' or 'B', the rest are
       * features.
       */
      if (n == 1) {
        tmp[i++] = (subs.compare("M") == 0) ? 1.0 : -1.0;
      }
      else if (n >= 2) {
        tmp[i++] = strtod(subs.c_str(), NULL);
      }
      n++;
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output =  tmp[0];
    for (int j = 1; j < i; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

/* Read the yacht hydrodynamics data (regression)
 */
void readhydro(dataset &ts) {
  ifstream src("testing/yacht_hydrodynamics.data");
  string line;

  while (getline(src, line)) {
    double tmp[7];
    int i = 0;
    int p1 = 0;
    int p2 = 0;
    while ((p2 = line.find(' ', p1)) != string::npos) {
      tmp[i++] = strtod(line.substr(p1, p2 - p1).c_str(), NULL);
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output = tmp[6];
    for (int j = 0; j < 6; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

double checkRegression(const dataset &ts, int ntrain, ExtraTree &rf) {
  dataset trainset, testset;
  ts.randomFold(ntrain, trainset, testset);

  rf.train(trainset, false);

  return mse(testset, rf);     // Calculate mean squared error
}

void testRegression(int nfolds, const dataset &ts) {
  int ntrain = ts.size() * (nfolds - 1) / nfolds;

  for (int i = 1; i <= nfolds; i++) {
    cout << "Fold " << i;
    ExtraTree rf(ts.nd(), 30, 2);
    double mse = checkRegression(ts, ntrain, rf);
    cout << " mse " << mse << endl;
    assert(mse < 3.5);
  }
}

class ConfusionMatrix {
private:
  int tp, tn, fp, fn;

public:
  ConfusionMatrix(int i_tp = 0, int i_tn = 0, int i_fp = 0, int i_fn = 0) {
    tp = i_tp;
    tn = i_tn;
    fp = i_fp;
    fn = i_fn;
  }

  ConfusionMatrix operator +(const ConfusionMatrix &cm) {
    ConfusionMatrix r(tp + cm.tp,
                      tn + cm.tn,
                      fp + cm.fp,
                      fn + cm.fn);
    return r;
  }

  int total() const { return (tp + tn + fp + fn); }
  double accuracy() const { return (tp + tn) / (double) total(); }
  double precision() const { return (double) tp / (tp + fp); }
  double recall() { return (double) tp / (tp + fn); }
  double specificity() { return (double) tn / (tn + fp); }

  void record(double nPred, double nTrue) {
    if (nPred == nTrue) {
      if (nPred > 0) {
        tp += 1;
      }
      else {
        tn += 1;
      }
    }
    else {
      if (nPred > 0) {
        fp += 1;
      }
      else {
        fn += 1;
      }
    }
  }
  friend ostream & operator <<(ostream &os, const ConfusionMatrix &d);
};

ostream & operator <<(ostream &os, const ConfusionMatrix &d) {
  return os << "tp " << d.tp << " tn " << d.tn << " fp " << d.fp << " fn " << d.fn;
}

ConfusionMatrix checkClassification(const dataset &ts, int ntrain, ExtraTree &rf) {
  dataset trainset, testset;
  ts.randomFold(ntrain, trainset, testset);
  ConfusionMatrix cm;

  rf.train(trainset, false);

  for (int i = 0; i < testset.size(); i++) {
    datum item = testset.data[i];
    double pred = rf.output(item.attributes);
    cm.record(pred, item.output);
  }
  return cm;
}

void testClassification(int nfolds, const dataset &ts) {
  int ntrain = ts.size() * (nfolds - 1) / nfolds;
  ConfusionMatrix cmTotal;

  for (int i = 1; i <= nfolds; i++) {
    cout << "Fold " << i << " ";
    ExtraTreeClassification rf(ts.nd(), 100, 2);
    ConfusionMatrix cm = checkClassification(ts, ntrain, rf);
    cout << cm << endl;
    cmTotal = cmTotal + cm;
  }

  cout << "Totals: " << cmTotal << endl;
  cout << "Overall precision: " << cmTotal.precision() << endl;
  cout << "Overall recall: " << cmTotal.recall() << endl;
  cout << "Accuracy: " << cmTotal.accuracy() << endl;
}

#include "getopt.h"

int main(int argc, char **argv) {
  const char *domain = "mc";

  Domain *pd;
  Regressor *pr;
  FQI *fqi;
  int c;
  int tflag = 0;
  int sflag = 0;
  while ((c = getopt(argc, argv, "tsd:")) != -1) {
    switch (c) {
    case 't':
      tflag++;
      break;
    case 's':
      sflag++;
      break;
    case 'd':
      domain = optarg;
      break;
    case '?':
      return 1;
    default:
      break;
    }
  }

  if (tflag) {
    dataset ts1, ts2, ts3;

    cout << "Testing classification with parkinsons.data." << endl;
    readparkinsons(ts1);
    testClassification(10, ts1);

    cout << "Testing classification with wdbc.data." << endl;
    readwdbc(ts2);
    testClassification(10, ts2);

    cout << "Testing regression with yacht_hydrodynamics.data." << endl;
    readhydro(ts3);
    testRegression(10, ts3);
    return 0;
  }
  else {
    pd = CreateDomain(domain);
    if (sflag) {
      pr = new SingleETRegressor(pd->numActions, pd->numDimensions);
    }
    else {
      pr = new ExtraTreeRegressor(pd->numActions, pd->numDimensions);
    }
    fqi = new FQI(pd, pr, 0.98, 400, 10, 30);
    fqi->run();
  }
  cout << "done!" << endl;
}
<commit_msg>Improve documentation and testing, remove warnings.<commit_after>/** \file
 * \brief Main program and testing harness for the FQI and ExtraTree
 * algorithms.
 *
 * Copyright (c) 2008-2014 Robert D. Vincent.
 */
#include <vector>
#include <iterator>
#include <algorithm>
#include <values.h>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <assert.h>
#include <utility>
#include <cmath>
using namespace std;

/**
 * Helper function to print a vector of doubles to a stream.
 */
ostream & operator <<(ostream &os, const vector<double> &d)
{
  os << "V(";
  for (size_t i = 0; i < d.size(); i++) {
    if (i > 0) os << ",";
    os << d[i];
  }
  return os << ")";
}

#include "dataset.h"
#include "tuple.h"
#include "random.h"
#include "extra.h"
#include "regressor.h"
#include "policy.h"
#include "domain.h"
#include "fqi.h"

/**
 * Calculate the mean squared error of the output for a data set,
 * given a tree. Used for testing.
 * \param ts The dataset to test against.
 * \param rf The ExtraTree to test.
 * \return The average mean squared error over the entire \c dataset.
 */
double mse(const dataset &ts, const ExtraTree &rf)
{
  double mse = 0.0;
  for (size_t i = 0; i < ts.size(); i++) {
    double tmp = rf.output(ts.data[i].attributes) - ts.data[i].output;
    mse += tmp * tmp;
  }
  return mse / ts.size();
}

/**
 * Read the Parkinson's disease classification data (Little et al. 2007)
 * from the UCI repository. Used for testing.
 * \param ts The returned dataset.
 */
void readparkinsons(dataset &ts) {
  ifstream src("testing/parkinsons.data");
  string line;

  while (getline(src, line)) {
    double tmp[24];
    int i = 0;
    size_t p1 = 0;
    size_t p2 = 0;
    while ((p2 = line.find(',', p1)) != string::npos) {
      tmp[i++] = strtod(line.substr(p1, p2 - p1).c_str(), NULL);
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output = tmp[17] > 0.0 ? 1.0 : -1.0;
    for (int j = 1; j < 17; j++) {
      d.attributes.push_back(tmp[j]);
    }
    for (int j = 18; j < 24; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

/**
 * Read WDBC (Wisconsin diagnostic breast cancer) data (classification).
 * Used for testing.
 * \param ts The returned dataset.
 */
void readwdbc(dataset &ts) {
  ifstream src("testing/wdbc.data");
  string line;

  while (getline(src, line)) {
    double tmp[100];
    int i = 0;
    int n = 0;
    size_t p1 = 0;
    size_t p2 = 0;
    while ((p2 = line.find(',', p1)) != string::npos) {
      string subs = line.substr(p1, p2 - p1);

      /* index 0 is ignored, index 1 is either 'M' or 'B', the rest are
       * features.
       */
      if (n == 1) {
        tmp[i++] = (subs.compare("M") == 0) ? 1.0 : -1.0;
      }
      else if (n >= 2) {
        tmp[i++] = strtod(subs.c_str(), NULL);
      }
      n++;
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output =  tmp[0];
    for (int j = 1; j < i; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

/**
 * Read the yacht hydrodynamics data (regression). Used for testing.
 * \param ts The returned dataset.
 */
void readhydro(dataset &ts) {
  ifstream src("testing/yacht_hydrodynamics.data");
  string line;

  while (getline(src, line)) {
    double tmp[7];
    int i = 0;
    size_t p1 = 0;
    size_t p2 = 0;
    while ((p2 = line.find(' ', p1)) != string::npos) {
      tmp[i++] = strtod(line.substr(p1, p2 - p1).c_str(), NULL);
      p1 = p2 + 1;
    }
    tmp[i++] = strtod(line.substr(p1).c_str(), NULL);
    datum d;
    d.output = tmp[6];
    for (int j = 0; j < 6; j++) {
      d.attributes.push_back(tmp[j]);
    }
    ts.data.push_back(d);
  }
}

/**
 * Calculate regression results for an ExtraTree. Generates a random fold
 * of the dataset \c ts with \c ntrain elements and a test set containing the
 * remainder of the elements. Used for testing.
 *
 * \param ts The dataset to test against.
 * \param ntrain The number of training examples to use.
 * \param rf The ExtraTree to test.
 * \return The average mean-square error of the regression.
 */
double checkRegression(const dataset &ts, int ntrain, ExtraTree &rf) {
  dataset trainset, testset;
  ts.randomFold(ntrain, trainset, testset);

  rf.train(trainset, false);

  return mse(testset, rf);     // Calculate mean squared error
}

/**
 * Perform an n-fold test using a particular \c dataset. Used for testing.
 * \param nfolds The number of test folds.
 * \param ts The training \c dataset.
 * \return The average mean-squared error over all of the folds.
 */
double testRegression(int nfolds, const dataset &ts) {
  int ntrain = ts.size() * (nfolds - 1) / nfolds;
  double sum = 0.0;

  for (int i = 0; i < nfolds; i++) {
    cout << "Fold: " << i+1 << " ";
    ExtraTree rf(ts.nd(), 100, 5);
    double mse = checkRegression(ts, ntrain, rf);
    cout << "MSE: " << mse << endl;
    sum += mse;
  }
  return (sum / nfolds);
}

/**
 * Represents a standard binary confusion matrix.
 */
class ConfusionMatrix {
private:
  int tp;                       /**< Number of true positives */
  int tn;                       /**< Number of true negatives */
  int fp;                       /**< Number of false positives */
  int fn;                       /**< Number of false negatives */

public:
  /** Constructor for a confusion matrix.
   *
   * \param i_tp Initial number of true positives.
   * \param i_tn Initial number of true negatives.
   * \param i_fp Initial number of false positives.
   * \param i_fn Initial number of false negatives.
   */
  ConfusionMatrix(int i_tp = 0, int i_tn = 0, int i_fp = 0, int i_fn = 0) {
    tp = i_tp;
    tn = i_tn;
    fp = i_fp;
    fn = i_fn;
  }

  /**
   * Add two confusion matrices elementwise.
   * \param cm The right-hand operand of the addition.
   */
  ConfusionMatrix operator +(const ConfusionMatrix &cm) {
    ConfusionMatrix r(tp + cm.tp,
                      tn + cm.tn,
                      fp + cm.fp,
                      fn + cm.fn);
    return r;
  }

  /**
   * Calculate the total number of results.
   */
  int total() const { return (tp + tn + fp + fn); }

  /**
   * Calculate the overall accuracy, which is the percentage of
   * correct results overall.
   */
  double accuracy() const { return (tp + tn) / (double) total(); }

  /**
   * Calculate the overall precision, or the ratio of true positives to
   * all positives.
   */
  double precision() const { return (double) tp / (tp + fp); }

  /**
   * Calculate the recall, or the ratio of true positives to
   * true positives and false negatives.
   */
  double recall() { return (double) tp / (tp + fn); }

  /**
   * Calculate the specificity, or the ratio of true negatives to
   * true negatives plus false positives.
   */
  double specificity() { return (double) tn / (tn + fp); }

  /**
   * Record the result of a classification event.
   * \param nPred The predicted label.
   * \param nTrue The actual label.
   */
  void record(double nPred, double nTrue) {
    if (nPred == nTrue) {
      if (nPred > 0) {
        tp += 1;
      }
      else {
        tn += 1;
      }
    }
    else {
      if (nPred > 0) {
        fp += 1;
      }
      else {
        fn += 1;
      }
    }
  }

  friend ostream & operator <<(ostream &os, const ConfusionMatrix &d);
};

/**
 * Print a ConfusionMatrix in a human-readable manner.
 * \param os The output stream.
 * \param d The ConfusionMatrix to print.
 */
ostream & operator <<(ostream &os, const ConfusionMatrix &d) {
  return os << "tp " << d.tp << " tn " << d.tn << " fp " << d.fp << " fn " << d.fn;
}

/**
 * Calculate classification results.
 * \param ts The entire training set.
 * \param ntrain The number of training examples to use.
 * \param rf The ExtraTree to use.
 * \return A summary of the classification results.
 */
ConfusionMatrix checkClassification(const dataset &ts, int ntrain, ExtraTree &rf) {
  dataset trainset, testset;
  ts.randomFold(ntrain, trainset, testset);
  ConfusionMatrix cm;

  rf.train(trainset, false);

  for (size_t i = 0; i < testset.size(); i++) {
    datum item = testset.data[i];
    double pred = rf.output(item.attributes);
    cm.record(pred, item.output);
  }
  return cm;
}

/**
 * Perform n-fold validation with a \c dataset.
 * \param nfolds The number of cross-validation folds to perform.
 * \param ts The training dataset.
 * \return The overall accuracy.
 */
double testClassification(int nfolds, const dataset &ts) {
  int ntrain = ts.size() * (nfolds - 1) / nfolds;
  ConfusionMatrix cmTotal;
  cout << "Performing " << nfolds << " folds with ";
  cout << ntrain << " training examples out of " << ts.size() << "." << endl;

  for (int i = 0; i < nfolds; i++) {
    cout << "Fold: " << i+1 << " ";
    ExtraTreeClassification rf(ts.nd(), 51, 2);
    ConfusionMatrix cm = checkClassification(ts, ntrain, rf);
    cout << "Accuracy: " << cm.accuracy() << endl;
    cmTotal = cmTotal + cm;
  }
  cout << "Totals: " << cmTotal << endl;
  cout << "Accuracy: " << setprecision(5) << cmTotal.accuracy() << endl;
  return cmTotal.accuracy();
}

#include "getopt.h"

/**
 * Our main program. Performs simple command-line processing and sets
 * up for either testing the ExtraTree implementations or running the FQI
 * algorithm on the selected domain.
 */
int main(int argc, char **argv) {
  const char *domain = "mc";

  Domain *pd;
  Regressor *pr;
  FQI *fqi;
  int c;
  int tflag = 0;
  int sflag = 0;
  while ((c = getopt(argc, argv, "tsd:")) != -1) {
    switch (c) {
    case 't':
      tflag++;
      break;
    case 's':
      sflag++;
      break;
    case 'd':
      domain = optarg;
      break;
    case '?':
      return 1;
    default:
      break;
    }
  }

  if (tflag) {
    dataset ts1, ts2, ts3;

    cout << "*** Testing classification with parkinsons.data." << endl;
    readparkinsons(ts1);

    double acc = testClassification(40, ts1);
    /* Original paper reports 91.8% mean accuracy */
    assert(acc > 0.918);

    cout << "*** Testing classification with wdbc.data." << endl;
    readwdbc(ts2);
    assert(testClassification(20, ts2) > 0.94);

    cout << "*** Testing regression with yacht_hydrodynamics.data." << endl;
    readhydro(ts3);
    double mse = testRegression(20, ts3);
    assert(mse < 2.0);
    cout << "MSE: " << setprecision(5) << mse << endl;
    assert(mse < 1.1);

    return 0;
  }
  else {
    pd = CreateDomain(domain);
    if (sflag) {
      pr = new SingleETRegressor(pd->numActions, pd->numDimensions);
    }
    else {
      pr = new ExtraTreeRegressor(pd->numActions, pd->numDimensions);
    }
    fqi = new FQI(pd, pr, 0.98, 400, 10, 30);
    fqi->run();
  }
  cout << "done!" << endl;
}
<|endoftext|>


<commit_before>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() {}

    Vec3(const float x, const float y, const float z)
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3& operator+=(Vec3& left, Vec3::InParam right) {
    left.x += right.x;
    left.y += right.y;
    left.z += right.z;
    return left;
}

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) {
    return Vec3 {
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

Vec3& operator*=(Vec3& v, const float scale) {
    v.x *= scale;
    v.y *= scale;
    v.z *= scale;
    return v;
}

float dot(Vec3::InParam left, Vec3::InParam right) {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

float length_squared(const float x, const float y, const float z) {
    return x*x + y*y + z*z;
}

float length_squared(Vec3::InParam in) {
    return length_squared(in.x, in.y, in.z);
}

float length(const float x, const float y) {
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) {
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) {
    return (from * (1.0f - t) + (to * t));
}

Vec3 reflected(Vec3::InParam direction, Vec3::InParam normal) {
    const float scale = -2.0f * dot(direction, normal);
    return direction + normal * scale;
}

Vec3 sample_sky(const Vec3::InParam direction) {
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3 {red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction,
        const Vec3::InParam sphere_point_on_ground,
        const float sphere_magnitude_squared)
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_down {0.0f, -1.0f, 0.0f};
    const float dot_down {dot(direction, world_down)};

    Vec3 colour;

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    }

    const Vec3 to_sphere_on_ground = sphere_point_on_ground - position;
    if (length_squared(to_sphere_on_ground) < sphere_magnitude_squared) {
        colour *= 0.5f;
    }

    return colour;
}

Vec3 sample_sphere(
        const Vec3::InParam position,
        const Vec3::InParam normal,
        const Vec3::InParam direction)
{
    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(normal, world_up)};

    const Vec3 half {0.5f, 0.5f, 0.5f};
    const Vec3 color {(normal * 0.5f + half) * 255.0f};
    const Vec3 half_color {color * 0.5f};
    return lerp(half_color, color, dot_up);
}

Vec3 sample(Vec3 position, Vec3 direction) {

    Vec3 colour {0.0f, 0.0f, 0.0f};
    float colour_blend = 1.0f;

    // check for collision against sphere
    const Vec3 sphere_point {0.0f, 15.0f, 40.0f};
    const Vec3 sphere_point_on_ground {0.0f, 0.0f, 40.0f};
    const float sphere_magnitude = 11.0f;
    const float sphere_magnitude_squared = sphere_magnitude * sphere_magnitude;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            - length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        position = intersection;
        direction = reflected(direction, normal);
        colour = lerp(
            colour,
            sample_sphere(intersection, normal, direction),
            colour_blend);
        colour_blend = 0.5f;
    }

    // check for collision against ground
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    if (dot(ground_inverse_normal, direction) > 0.0f) {
        // hit the ground, figure out where
        const Vec3 ground_point(0.0f, 0.0f, 0.0f);
        const Vec3 to_ground {ground_point - position};
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        colour = lerp(
            colour,
            sample_ground(
                ground_intersection,
                direction,
                sphere_point_on_ground,
                sphere_magnitude_squared),
            colour_blend);
    } else {
        colour = lerp(
            colour,
            // TODO: remove position parameter
            sample_sky(direction),
            colour_blend);
    }

    return colour;
}

void draw_scene(const int image_width, const int image_height) {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3 {
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}

// Copyright 2014 Angelos Evripiotis
//
// 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.
<commit_msg>Refactor, lerp() - clearer bracketization<commit_after>#include <math.h>
#include <stdio.h>

struct Vec3
{
    typedef const Vec3& InParam;

    Vec3() {}

    Vec3(const float x, const float y, const float z)
        : x(x)
        , y(y)
        , z(z)
    {
    }

    float x, y, z;
};

Vec3& operator+=(Vec3& left, Vec3::InParam right) {
    left.x += right.x;
    left.y += right.y;
    left.z += right.z;
    return left;
}

Vec3 operator+(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x + right.x,
        left.y + right.y,
        left.z + right.z
    };
}

Vec3 operator-(Vec3::InParam left, Vec3::InParam right) {
    return Vec3{
        left.x - right.x,
        left.y - right.y,
        left.z - right.z
    };
}

Vec3 operator*(Vec3::InParam v, const float scale) {
    return Vec3 {
        v.x * scale,
        v.y * scale,
        v.z * scale
    };
}

Vec3& operator*=(Vec3& v, const float scale) {
    v.x *= scale;
    v.y *= scale;
    v.z *= scale;
    return v;
}

float dot(Vec3::InParam left, Vec3::InParam right) {
    return left.x*right.x + left.y*right.y + left.z*right.z;
}

float length_squared(const float x, const float y, const float z) {
    return x*x + y*y + z*z;
}

float length_squared(Vec3::InParam in) {
    return length_squared(in.x, in.y, in.z);
}

float length(const float x, const float y) {
    return sqrt(x*x + y*y);
}

float length(const float x, const float y, const float z) {
    return sqrt(x*x + y*y + z*z);
}

float length(Vec3::InParam in) {
    return length(in.x, in.y, in.z);
}

Vec3 normalised(Vec3::InParam in) {
    const float scale = 1.0f / length(in);
    return in * scale;
}

Vec3 lerp(Vec3::InParam from, Vec3::InParam to, const float t) {
    return (from * (1.0f - t)) + (to * t);
}

Vec3 reflected(Vec3::InParam direction, Vec3::InParam normal) {
    const float scale = -2.0f * dot(direction, normal);
    return direction + normal * scale;
}

Vec3 sample_sky(const Vec3::InParam direction) {
    const Vec3 up{0.0f, 1.0f, 0.0f};

    const float red = 32.0f;
    const float green = 128.0f;
    const float blue = 180.0f + 64.0f * dot(direction, up);

    return Vec3 {red, green, blue};
}

Vec3 sample_ground(
        const Vec3::InParam position,
        const Vec3::InParam direction,
        const Vec3::InParam sphere_point_on_ground,
        const float sphere_magnitude_squared)
{
    const float inverse_square_scale = 0.1f;
    const int x = fabs(position.x * inverse_square_scale);
    const int y = fabs(position.z * inverse_square_scale);

    const Vec3 world_down {0.0f, -1.0f, 0.0f};
    const float dot_down {dot(direction, world_down)};

    Vec3 colour;

    if ((x%2) ^ (y%2)) {
        const Vec3 green {32.0f, 128.0f, 32.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    } else {
        const Vec3 green {64.0f, 128.0f, 64.0f};
        const Vec3 light_green {green * 2.0f};
        colour = lerp(green, light_green, dot_down);
    }

    const Vec3 to_sphere_on_ground = sphere_point_on_ground - position;
    if (length_squared(to_sphere_on_ground) < sphere_magnitude_squared) {
        colour *= 0.5f;
    }

    return colour;
}

Vec3 sample_sphere(
        const Vec3::InParam position,
        const Vec3::InParam normal,
        const Vec3::InParam direction)
{
    const Vec3 world_up {0.0f, 1.0f, 0.0f};
    const float dot_up {dot(normal, world_up)};

    const Vec3 half {0.5f, 0.5f, 0.5f};
    const Vec3 color {(normal * 0.5f + half) * 255.0f};
    const Vec3 half_color {color * 0.5f};
    return lerp(half_color, color, dot_up);
}

Vec3 sample(Vec3 position, Vec3 direction) {

    Vec3 colour {0.0f, 0.0f, 0.0f};
    float colour_blend = 1.0f;

    // check for collision against sphere
    const Vec3 sphere_point {0.0f, 15.0f, 40.0f};
    const Vec3 sphere_point_on_ground {0.0f, 0.0f, 40.0f};
    const float sphere_magnitude = 11.0f;
    const float sphere_magnitude_squared = sphere_magnitude * sphere_magnitude;
    const Vec3 to_sphere {sphere_point - position};
    const float closest_to_sphere {dot(direction, to_sphere)};
    const Vec3 point_nearest_sphere {position + direction * closest_to_sphere};
    const float length_to_sphere {length(sphere_point - point_nearest_sphere)};
    // TODO: use squared magnitude
    if (length_to_sphere < sphere_magnitude) {
        // calc intersection point
        const float adjacent_length = sqrt(
            sphere_magnitude * sphere_magnitude
            - length_to_sphere * length_to_sphere);
        const Vec3 intersection {
            point_nearest_sphere - (direction * adjacent_length)};

        // sample the sphere
        const Vec3 normal {normalised(intersection - sphere_point)};
        position = intersection;
        direction = reflected(direction, normal);
        colour = lerp(
            colour,
            sample_sphere(intersection, normal, direction),
            colour_blend);
        colour_blend = 0.5f;
    }

    // check for collision against ground
    const Vec3 ground_inverse_normal(0.0f, -1.0f, 0.0f);
    if (dot(ground_inverse_normal, direction) > 0.0f) {
        // hit the ground, figure out where
        const Vec3 ground_point(0.0f, 0.0f, 0.0f);
        const Vec3 to_ground {ground_point - position};
        const float distance_to_ground {dot(to_ground, ground_inverse_normal)};
        const float dot_to_ground {dot(direction, ground_inverse_normal)};
        const float distance {distance_to_ground / dot_to_ground};
        const Vec3 ground_intersection {position + direction * distance};
        colour = lerp(
            colour,
            sample_ground(
                ground_intersection,
                direction,
                sphere_point_on_ground,
                sphere_magnitude_squared),
            colour_blend);
    } else {
        colour = lerp(
            colour,
            // TODO: remove position parameter
            sample_sky(direction),
            colour_blend);
    }

    return colour;
}

void draw_scene(const int image_width, const int image_height) {
    const Vec3 camera_forward{0.0f, 0.0f, 1.0f};
    const Vec3 camera_right{1.0f, 0.0f, 0.0f};
    const Vec3 camera_up{0.0f, 1.0f, 0.0f};
    const Vec3 camera_pos{0.0f, 10.0f, 0.0f};

    const int half_image_width = image_width / 2;
    const int half_image_height = image_height / 2;

    for (int y=image_height-1; y>=0; --y) {
        for (int x=0; x<image_width; ++x) {
            const Vec3 pixel_offset = Vec3 {
                float(x-half_image_width),
                float(y-half_image_height),
                0.0f};

            const Vec3 pixel_direction = normalised(
                camera_forward*image_height + pixel_offset);

            const Vec3 colour = sample(camera_pos, pixel_direction);

            printf("%c%c%c", int(colour.x), int(colour.y), int(colour.z));
        }
    }
}

int main() {
    printf("P6 512 512 255 ");
    draw_scene(512, 512);
}

// Copyright 2014 Angelos Evripiotis
//
// 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.
<|endoftext|>


<commit_before>#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <cstring>
#include <string>
using namespace std;

void lsCom() {

}
bool isDependant = 0;
int main(int argc, char *argv[]) {
char *arg[argc];
if(argc < 1) {
    cout << "No arguements passed in" << endl;
    exit(1);
}
else {
    int currArg = 1;
    string ArgStr;
    cout << argv[1] << endl;
    cout << *(argv[1] + 1) << endl;
    char* test = argv[1];
    while(currArg+1 < argc) {
        arg[0] = argv[currArg];
        int n = 0;
        for(int i = 0; i < strlen(argv[currArg]); ++i) {
            if(*(argv[currArg+1]+i) == ';' && i == (strlen(argv[currArg])-1)){
                *(argv[currArg+1]+i) = '\0';
                isDependant = 0;
            }
        }
        arg[1] = argv[currArg+1];
        ++currArg;
    }
    arg[2] = NULL;
    /*
    while(currArg < argc){
        if(*(argv[currArg]).at(0) = '-') {
            if(*(argv[currArg]).at(*(argv[currArg]).size() - 1) == ';') {
                *argv[currArg].pop_back();
                endCommand = 1;
            }
            ArgStr += argv[currArg];
        }
        ++currArg;

    }*/
    execvp(arg[0], arg);
    //cout << get_current_dir_name() << endl;
    /*DIR *dirp;
    if( NULL == (dirp = opendir(get_current_dir_name()))) {
      perror("The directory could not be opened or does not exist. ");
      exit(1);
    }
    struct dirent *file;
    errno = 0;
    while(NULL != (file = readdir(dirp))) {
      cout << file->d_name << " ";
    }
    cout << endl;*/
  }
return 0;
}
<commit_msg>commands with no arguements work now<commit_after>#include <iostream>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <cstring>
#include <string>
using namespace std;

void lsCom() {

}
bool isDependant = 0;
int main(int argc, char *argv[]) {
char *arg[argc];
if(argc < 1) {
    cout << "No arguements passed in" << endl;
    exit(1);
}
else {
    int currArg = 1;
    int SAP = 0; // Sub-Array Position
    string ArgStr;
    char* test = argv[1];
    while(currArg+1 <= argc) {
        SAP = 0;
        arg[SAP] = argv[currArg];
        ++SAP;
        int n = 0;
        for(int i = 0; i < strlen(argv[currArg]); ++i) {
            if(*(argv[currArg]+i) == ';' && i == (strlen(argv[currArg])-1)){
                *(argv[currArg]+i) = '\0';
                isDependant = 0;
            }
        }
        ++currArg;
        if((currArg) < argc && (argv[currArg]) != "||" && (argv[currArg]) != "&&") {
            arg[SAP] = argv[currArg];
            ++SAP;
        }
        else {
            arg[SAP] = NULL;
            ++SAP;
        }
        arg[SAP] = NULL;
        char *testa[3] = { NULL};
        if(execvp(arg[0], arg) == -1) {
            perror("The command could not be executed!");
            errno = 0;
        }
        /*else {
            execvp(arg[0], arg);
        }*/
        ++currArg;
    }
  }
return 0;
}
<|endoftext|>


<commit_before>d2cd7447-ad5c-11e7-9a5d-ac87a332f658<commit_msg>Tuesday, turns out it was tuesday<commit_after>d338545c-ad5c-11e7-b442-ac87a332f658<|endoftext|>


<commit_before>e167f6c0-2747-11e6-99cb-e0f84713e7b8<commit_msg>My Backup<commit_after>e172dffd-2747-11e6-84b0-e0f84713e7b8<|endoftext|>


<commit_before>836f9bf5-ad59-11e7-842e-ac87a332f658<commit_msg>I hope I am done<commit_after>8428c335-ad59-11e7-8da2-ac87a332f658<|endoftext|>


<commit_before>73c4977d-4b02-11e5-950f-28cfe9171a43<commit_msg>add file<commit_after>73d1cebd-4b02-11e5-b082-28cfe9171a43<|endoftext|>


<commit_before>caeb8738-4b02-11e5-b315-28cfe9171a43<commit_msg>update testing<commit_after>caf730eb-4b02-11e5-a544-28cfe9171a43<|endoftext|>


<commit_before>bb87afa1-2747-11e6-a3dd-e0f84713e7b8<commit_msg>Deal with it<commit_after>bb996bca-2747-11e6-afc0-e0f84713e7b8<|endoftext|>


<commit_before>c5d0c719-4b02-11e5-af83-28cfe9171a43<commit_msg>Backup, rebase this later<commit_after>c5de6be8-4b02-11e5-a9bb-28cfe9171a43<|endoftext|>


<commit_before>
#include "src/CmdLineOptions.h"
#include "src/MicroCore.h"
#include "src/page.h"

#include "ext/crow/crow.h"
#include "ext/member_checker.h"

#include <fstream>

using boost::filesystem::path;

using namespace std;

// needed for log system of momero
namespace epee {
    unsigned int g_test_dbg_lock_sleep = 0;
}

int main(int ac, const char* av[]) {

    // get command line options
    xmreg::CmdLineOptions opts {ac, av};

    auto help_opt = opts.get_option<bool>("help");

    // if help was chosen, display help text and finish
    if (*help_opt)
    {
        return EXIT_SUCCESS;
    }

    auto port_opt           = opts.get_option<string>("port");
    auto bc_path_opt        = opts.get_option<string>("bc-path");
    auto custom_db_path_opt = opts.get_option<string>("custom-db-path");
    auto deamon_url_opt     = opts.get_option<string>("deamon-url");

    //cast port number in string to uint16
    uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);

    // get blockchain path
    path blockchain_path;

    if (!xmreg::get_blockchain_path(bc_path_opt, blockchain_path))
    {
        cerr << "Error getting blockchain path." << endl;
        return EXIT_FAILURE;
    }

     // enable basic monero log output
    xmreg::enable_monero_log();

    // create instance of our MicroCore
    // and make pointer to the Blockchain
    xmreg::MicroCore mcore;
    cryptonote::Blockchain* core_storage;

    // initialize mcore and core_storage
    if (!xmreg::init_blockchain(blockchain_path.string(),
                               mcore, core_storage))
    {
        cerr << "Error accessing blockchain." << endl;
        return EXIT_FAILURE;
    }

    // check if we have path to lmdb2 (i.e., custom db)
    // and if it exists

    string custom_db_path_str;

    if (custom_db_path_opt)
    {
        if (boost::filesystem::exists(boost::filesystem::path(*custom_db_path_opt)))
        {
            custom_db_path_str = *custom_db_path_opt;
        }
        else
        {
            cerr << "Custom db path: " << *custom_db_path_opt
                 << "does not exist" << endl;

            return EXIT_FAILURE;
        }
    }
    else
    {
        // if not given assume it is located in ~./bitmonero/lmdb2 folder
        custom_db_path_str = blockchain_path.parent_path().string()
                             + string("/lmdb2");
    }

    custom_db_path_str = xmreg::remove_trailing_path_separator(custom_db_path_str);

    // create instance of page class which
    // contains logic for the website
    xmreg::page xmrblocks(&mcore, core_storage,
                          *deamon_url_opt, custom_db_path_str);

    // crow instance
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")
    ([&](const crow::request& req) {

        //for (const auto& m : req.headers)
        //    cout << m.first << ": " << m.second << endl;

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return xmrblocks.index2();
    });

    CROW_ROUTE(app, "/page/<uint>")
    ([&](size_t page_no) {
        return xmrblocks.index2(page_no);
    });

    CROW_ROUTE(app, "/block/<uint>")
    ([&](const crow::request& req, size_t block_height) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_height));
    });

    CROW_ROUTE(app, "/block/<string>")
    ([&](const crow::request& req, string block_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_hash));
    });

    CROW_ROUTE(app, "/tx/<string>")
    ([&](const crow::request& req, string tx_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_tx(tx_hash));
    });

    CROW_ROUTE(app, "/tx/<string>/<uint>")
    ([&](string tx_hash, uint with_ring_signatures) {
        return xmrblocks.show_tx(tx_hash, with_ring_signatures);
    });

    CROW_ROUTE(app, "/myoutputs").methods("GET"_method)
    ([&](const crow::request& req) {

        string tx_hash     = string(req.url_params.get("tx_hash"));
        string xmr_address = string(req.url_params.get("xmr_address"));
        string viewkey     = string(req.url_params.get("viewkey"));

        return xmrblocks.show_my_outputs(tx_hash, xmr_address, viewkey);
    });

    CROW_ROUTE(app, "/search").methods("GET"_method)
    ([&](const crow::request& req) {
        return xmrblocks.search(string(req.url_params.get("value")));
    });

    CROW_ROUTE(app, "/robots.txt")
    ([&]() {
        string text = "User-agent: *\n"
                      "Disallow: ";
        return text;
    });

    CROW_ROUTE(app, "/autorefresh")
    ([&]() {
        uint64_t page_no {0};
        bool refresh_page {true};
        return xmrblocks.index2(page_no, refresh_page);
    });

    // run the crow http server
    app.port(app_port).multithreaded().run();

    return EXIT_SUCCESS;
}
<commit_msg>crowler blocking added to home page<commit_after>
#include "src/CmdLineOptions.h"
#include "src/MicroCore.h"
#include "src/page.h"

#include "ext/crow/crow.h"
#include "ext/member_checker.h"

#include <fstream>

using boost::filesystem::path;

using namespace std;

// needed for log system of momero
namespace epee {
    unsigned int g_test_dbg_lock_sleep = 0;
}

int main(int ac, const char* av[]) {

    // get command line options
    xmreg::CmdLineOptions opts {ac, av};

    auto help_opt = opts.get_option<bool>("help");

    // if help was chosen, display help text and finish
    if (*help_opt)
    {
        return EXIT_SUCCESS;
    }

    auto port_opt           = opts.get_option<string>("port");
    auto bc_path_opt        = opts.get_option<string>("bc-path");
    auto custom_db_path_opt = opts.get_option<string>("custom-db-path");
    auto deamon_url_opt     = opts.get_option<string>("deamon-url");

    //cast port number in string to uint16
    uint16_t app_port = boost::lexical_cast<uint16_t>(*port_opt);

    // get blockchain path
    path blockchain_path;

    if (!xmreg::get_blockchain_path(bc_path_opt, blockchain_path))
    {
        cerr << "Error getting blockchain path." << endl;
        return EXIT_FAILURE;
    }

     // enable basic monero log output
    xmreg::enable_monero_log();

    // create instance of our MicroCore
    // and make pointer to the Blockchain
    xmreg::MicroCore mcore;
    cryptonote::Blockchain* core_storage;

    // initialize mcore and core_storage
    if (!xmreg::init_blockchain(blockchain_path.string(),
                               mcore, core_storage))
    {
        cerr << "Error accessing blockchain." << endl;
        return EXIT_FAILURE;
    }

    // check if we have path to lmdb2 (i.e., custom db)
    // and if it exists

    string custom_db_path_str;

    if (custom_db_path_opt)
    {
        if (boost::filesystem::exists(boost::filesystem::path(*custom_db_path_opt)))
        {
            custom_db_path_str = *custom_db_path_opt;
        }
        else
        {
            cerr << "Custom db path: " << *custom_db_path_opt
                 << "does not exist" << endl;

            return EXIT_FAILURE;
        }
    }
    else
    {
        // if not given assume it is located in ~./bitmonero/lmdb2 folder
        custom_db_path_str = blockchain_path.parent_path().string()
                             + string("/lmdb2");
    }

    custom_db_path_str = xmreg::remove_trailing_path_separator(custom_db_path_str);

    // create instance of page class which
    // contains logic for the website
    xmreg::page xmrblocks(&mcore, core_storage,
                          *deamon_url_opt, custom_db_path_str);

    // crow instance
    crow::SimpleApp app;

    CROW_ROUTE(app, "/")
    ([&](const crow::request& req) {

        //for (const auto& m : req.headers)
        //    cout << m.first << ": " << m.second << endl;

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.index2());
    });

    CROW_ROUTE(app, "/page/<uint>")
    ([&](size_t page_no) {
        return xmrblocks.index2(page_no);
    });

    CROW_ROUTE(app, "/block/<uint>")
    ([&](const crow::request& req, size_t block_height) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_height));
    });

    CROW_ROUTE(app, "/block/<string>")
    ([&](const crow::request& req, string block_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_block(block_hash));
    });

    CROW_ROUTE(app, "/tx/<string>")
    ([&](const crow::request& req, string tx_hash) {

        // there is some robot scanning everything
        // on the explorer. I block it with this
        if (!xmreg::does_header_has(req, "Accept", "q=.2, */*; q=.2").empty())
        {
            cout << "Scanner with q=.2, */*; q=.2 blocked!" << endl;
            return crow::response(400);
        }

        return crow::response(xmrblocks.show_tx(tx_hash));
    });

    CROW_ROUTE(app, "/tx/<string>/<uint>")
    ([&](string tx_hash, uint with_ring_signatures) {
        return xmrblocks.show_tx(tx_hash, with_ring_signatures);
    });

    CROW_ROUTE(app, "/myoutputs").methods("GET"_method)
    ([&](const crow::request& req) {

        string tx_hash     = string(req.url_params.get("tx_hash"));
        string xmr_address = string(req.url_params.get("xmr_address"));
        string viewkey     = string(req.url_params.get("viewkey"));

        return xmrblocks.show_my_outputs(tx_hash, xmr_address, viewkey);
    });

    CROW_ROUTE(app, "/search").methods("GET"_method)
    ([&](const crow::request& req) {
        return xmrblocks.search(string(req.url_params.get("value")));
    });

    CROW_ROUTE(app, "/robots.txt")
    ([&]() {
        string text = "User-agent: *\n"
                      "Disallow: ";
        return text;
    });

    CROW_ROUTE(app, "/autorefresh")
    ([&]() {
        uint64_t page_no {0};
        bool refresh_page {true};
        return xmrblocks.index2(page_no, refresh_page);
    });

    // run the crow http server
    app.port(app_port).multithreaded().run();

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/* Copyright (c) 2016, Pollard Banknote Limited
   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 of the copyright holder 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 HOLDER 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.
 */
#include "chrono.h"

#ifndef CPP11

#include <ctime>
#include "./cstdint.h"

namespace cpp11
{
namespace chrono
{
time_point< system_clock > system_clock::now()
{
	timespec ts;

	if ( ::clock_gettime(CLOCK_REALTIME, &ts) == 0 )
	{
		#if 0
		seconds     s(ts.tv_sec);
		nanoseconds ns(ts.tv_nsec);

		return time_point( duration(s + ms) );

		#else

		return time_point( duration( ts.tv_sec * 1000 + ( ts.tv_nsec / 1000000L ) ) );

		#endif
	}

	return time_point();
}

std::time_t system_clock::to_time_t(const time_point& t)
{
	return static_cast< std::time_t >( t.time_since_epoch().count() / 1000 );
}

time_point< system_clock > system_clock::from_time_t(std::time_t t)
{
	return time_point( duration(t * 1000) );
}

time_point< steady_clock > steady_clock::now()
{
	timespec ts;

	if ( ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0 )
	{
		return time_point( duration(ts.tv_sec * INT32_C(1000000000) + ts.tv_nsec) );
	}

	return time_point();
}

}
}
#endif // ifndef CPP11
<commit_msg>Fix include<commit_after>/* Copyright (c) 2016, Pollard Banknote Limited
   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 of the copyright holder 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 HOLDER 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.
 */
#include "chrono.h"

#ifndef CPP11

#include <ctime>
#include "cstdint.h"

namespace cpp11
{
namespace chrono
{
time_point< system_clock > system_clock::now()
{
	timespec ts;

	if ( ::clock_gettime(CLOCK_REALTIME, &ts) == 0 )
	{
		#if 0
		seconds     s(ts.tv_sec);
		nanoseconds ns(ts.tv_nsec);

		return time_point( duration(s + ms) );

		#else

		return time_point( duration( ts.tv_sec * 1000 + ( ts.tv_nsec / 1000000L ) ) );

		#endif
	}

	return time_point();
}

std::time_t system_clock::to_time_t(const time_point& t)
{
	return static_cast< std::time_t >( t.time_since_epoch().count() / 1000 );
}

time_point< system_clock > system_clock::from_time_t(std::time_t t)
{
	return time_point( duration(t * 1000) );
}

time_point< steady_clock > steady_clock::now()
{
	timespec ts;

	if ( ::clock_gettime(CLOCK_MONOTONIC, &ts) == 0 )
	{
		return time_point( duration(ts.tv_sec * INT32_C(1000000000) + ts.tv_nsec) );
	}

	return time_point();
}

}
}
#endif // ifndef CPP11
<|endoftext|>


<commit_before>#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif

#include <QWidget>
#include <QApplication>
#include <QDebug>
#include <QGamepadManager>
#include <QGamepad>
#include <QtEndian>
#include <QUdpSocket>
#include <QTimer>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QDialog>
#include <QMouseEvent>
#include <QCloseEvent>
#include <QSettings>

#include <algorithm>
#include <cmath>

#define CPAD_BOUND          0x5d0
#define CPP_BOUND           0x7f

#define TOUCH_SCREEN_WIDTH  320
#define TOUCH_SCREEN_HEIGHT 240

typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

double lx = 0.0, ly = 0.0;
double rx = 0.0, ry = 0.0;
QGamepadManager::GamepadButtons buttons = 0;
u32 interfaceButtons = 0;
QString ipAddress;
int yAxisMultiplier = 1;
bool abInverse = false;
bool xyInverse = false;

bool touchScreenPressed;
QPoint touchScreenPosition;

QSettings settings("TuxSH", "InputRedirectionClient-Qt");

void sendFrame(void)
{
    static const QGamepadManager::GamepadButton hidButtonsAB[] = {
        QGamepadManager::ButtonA,
        QGamepadManager::ButtonB,
    };

    static const QGamepadManager::GamepadButton hidButtonsMiddle[] = {
        QGamepadManager::ButtonSelect,
        QGamepadManager::ButtonStart,
        QGamepadManager::ButtonRight,
        QGamepadManager::ButtonLeft,
        QGamepadManager::ButtonUp,
        QGamepadManager::ButtonDown,
        QGamepadManager::ButtonR1,
        QGamepadManager::ButtonL1,
    };

    static const QGamepadManager::GamepadButton hidButtonsXY[] = {
        QGamepadManager::ButtonX,
        QGamepadManager::ButtonY,
    };

    static const QGamepadManager::GamepadButton irButtons[] = {
        QGamepadManager::ButtonR2,
        QGamepadManager::ButtonL2,
    };

    static const QGamepadManager::GamepadButton speButtons[] = {
        QGamepadManager::ButtonR3,
        QGamepadManager::ButtonL3,
        QGamepadManager::ButtonGuide,
    };

    u32 hidPad = 0xfff;
    if(!abInverse)
    {
        for(u32 i = 0; i < 2; i++)
        {
            if(buttons & (1 << hidButtonsAB[i]))
                hidPad &= ~(1 << i);
        }
    }
    else
    {
        for(u32 i = 0; i < 2; i++)
        {
            if(buttons & (1 << hidButtonsAB[1-i]))
                hidPad &= ~(1 << i);
        }
    }

    for(u32 i = 2; i < 10; i++)
    {
        if(buttons & (1 << hidButtonsMiddle[i-2]))
            hidPad &= ~(1 << i);
    }

    if(!xyInverse)
    {
        for(u32 i = 10; i < 12; i++)
        {
            if(buttons & (1 << hidButtonsXY[i-10]))
                hidPad &= ~(1 << i);
        }
    }
    else
    {
        for(u32 i = 10; i < 12; i++)
        {
            if(buttons & (1 << hidButtonsXY[1-(i-10)]))
                hidPad &= ~(1 << i);
        }
    }

    u32 irButtonsState = 0;
    for(u32 i = 0; i < 2; i++)
    {
        if(buttons & (1 << irButtons[i]))
            irButtonsState |= 1 << (i + 1);
    }

    u32 specialButtonsState = 0;
    for(u32 i = 0; i < 3; i++)
    {

        if(buttons & (1 << speButtons[i]))
            specialButtonsState |= 1 << i;
    }
    specialButtonsState |= interfaceButtons;

    u32 touchScreenState = 0x2000000;
    u32 circlePadState = 0x7ff7ff;
    u32 cppState = 0x80800081;

    if(lx != 0.0 || ly != 0.0)
    {
        u32 x = (u32)(lx * CPAD_BOUND + 0x800);
        u32 y = (u32)(ly * CPAD_BOUND + 0x800);
        x = x >= 0xfff ? (lx < 0.0 ? 0x000 : 0xfff) : x;
        y = y >= 0xfff ? (ly < 0.0 ? 0x000 : 0xfff) : y;

        circlePadState = (y << 12) | x;
    }

    if(rx != 0.0 || ry != 0.0 || irButtonsState != 0)
    {
        // We have to rotate the c-stick position 45°. Thanks, Nintendo.
        u32 x = (u32)(M_SQRT1_2 * (rx + ry) * CPP_BOUND + 0x80);
        u32 y = (u32)(M_SQRT1_2 * (ry - rx) * CPP_BOUND + 0x80);
        x = x >= 0xff ? (rx < 0.0 ? 0x00 : 0xff) : x;
        y = y >= 0xff ? (ry < 0.0 ? 0x00 : 0xff) : y;

        cppState = (y << 24) | (x << 16) | (irButtonsState << 8) | 0x81;
    }

    if(touchScreenPressed)
    {
        u32 x = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.x()), TOUCH_SCREEN_WIDTH)) / TOUCH_SCREEN_WIDTH;
        u32 y = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.y()), TOUCH_SCREEN_HEIGHT)) / TOUCH_SCREEN_HEIGHT;
        touchScreenState = (1 << 24) | (y << 12) | x;
    }

    QByteArray ba(20, 0);
    qToLittleEndian(hidPad, (uchar *)ba.data());
    qToLittleEndian(touchScreenState, (uchar *)ba.data() + 4);
    qToLittleEndian(circlePadState, (uchar *)ba.data() + 8);
    qToLittleEndian(cppState, (uchar *)ba.data() + 12);
    qToLittleEndian(specialButtonsState, (uchar *)ba.data() + 16);
    QUdpSocket().writeDatagram(ba, QHostAddress(ipAddress), 4950);
}

struct GamepadMonitor : public QObject {

    GamepadMonitor(QObject *parent = nullptr) : QObject(parent)
    {
        connect(QGamepadManager::instance(), &QGamepadManager::gamepadButtonPressEvent, this,
            [](int deviceId, QGamepadManager::GamepadButton button, double value)
        {
            (void)deviceId;
            (void)value;
            buttons |= QGamepadManager::GamepadButtons(1 << button);
            sendFrame();
        });

        connect(QGamepadManager::instance(), &QGamepadManager::gamepadButtonReleaseEvent, this,
            [](int deviceId, QGamepadManager::GamepadButton button)
        {
            (void)deviceId;
            buttons &= QGamepadManager::GamepadButtons(~(1 << button));
            sendFrame();
        });
        connect(QGamepadManager::instance(), &QGamepadManager::gamepadAxisEvent, this,
            [](int deviceId, QGamepadManager::GamepadAxis axis, double value)
        {
            (void)deviceId;
            (void)value;
            switch(axis)
            {
                case QGamepadManager::AxisLeftX:
                    lx = value;
                    break;
                case QGamepadManager::AxisLeftY:
                    ly = yAxisMultiplier * -value; // for some reason qt inverts this
                    break;

                case QGamepadManager::AxisRightX:
                    rx = value;
                    break;
                case QGamepadManager::AxisRightY:
                    ry = yAxisMultiplier * -value; // for some reason qt inverts this
                    break;
                default: break;
            }
            sendFrame();
        });
    }
};

struct TouchScreen : public QDialog {
    TouchScreen(QWidget *parent = nullptr) : QDialog(parent)
    {
        this->setFixedSize(TOUCH_SCREEN_WIDTH, TOUCH_SCREEN_HEIGHT);
        this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
        this->setWindowTitle(tr("InputRedirectionClient-Qt - Touch screen"));
    }

    void mousePressEvent(QMouseEvent *ev)
    {
        if(ev->button() == Qt::LeftButton)
        {
            touchScreenPressed = true;
            touchScreenPosition = ev->pos();
            sendFrame();
        }
    }

    void mouseMoveEvent(QMouseEvent *ev)
    {
        if(touchScreenPressed && (ev->buttons() & Qt::LeftButton))
        {
            touchScreenPosition = ev->pos();
            sendFrame();
        }
    }

    void mouseReleaseEvent(QMouseEvent *ev)
    {
        if(ev->button() == Qt::LeftButton)
        {
            touchScreenPressed = false;
            sendFrame();
        }
    }

    void closeEvent(QCloseEvent *ev)
    {
        touchScreenPressed = false;
        sendFrame();
        ev->accept();
    }
};

struct FrameTimer : public QTimer {
    FrameTimer(QObject *parent = nullptr) : QTimer(parent)
    {
        connect(this, &QTimer::timeout, this,
                [](void)
        {
            sendFrame();
        });
    }
};

class Widget : public QWidget
{
private:
    QVBoxLayout *layout;
    QFormLayout *formLayout;
    QLineEdit *addrLineEdit;
    QCheckBox *invertYCheckbox, *invertABCheckbox, *invertXYCheckbox;
    QPushButton *homeButton, *powerButton, *longPowerButton;
    TouchScreen *touchScreen;
public:
    Widget(QWidget *parent = nullptr) : QWidget(parent)
    {
        setWindowFlags(Qt::MSWindowsFixedSizeDialogHint);

        layout = new QVBoxLayout(this);

        addrLineEdit = new QLineEdit(this);
        addrLineEdit->setClearButtonEnabled(true);

        invertYCheckbox = new QCheckBox(this);
        invertABCheckbox = new QCheckBox(this);
        invertXYCheckbox = new QCheckBox(this);
        formLayout = new QFormLayout;

        formLayout->addRow(tr("IP &address"), addrLineEdit);
        formLayout->addRow(tr("&Invert Y axis"), invertYCheckbox);
        formLayout->addRow(tr("Invert A<->&B"), invertABCheckbox);
        formLayout->addRow(tr("Invert X<->&Y"), invertXYCheckbox);

        homeButton = new QPushButton(tr("&HOME"), this);
        powerButton = new QPushButton(tr("&POWER"), this);
        longPowerButton = new QPushButton(tr("POWER (&long)"), this);

        layout->addLayout(formLayout);
        layout->addWidget(homeButton);
        layout->addWidget(powerButton);
        layout->addWidget(longPowerButton);

        connect(addrLineEdit, &QLineEdit::textChanged, this,
                [](const QString &text)
        {
            ipAddress = text;
            settings.setValue("ipAddress", text);
        });

        connect(invertYCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    yAxisMultiplier = 1;
                    settings.setValue("invertY", false);
                    break;
                case Qt::Checked:
                    yAxisMultiplier = -1;
                    settings.setValue("invertY", true);
                    break;
                default: break;
            }
        });

        connect(invertABCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    abInverse = false;
                    settings.setValue("invertAB", false);
                    break;
                case Qt::Checked:
                    abInverse = true;
                    settings.setValue("invertAB", true);
                    break;
                default: break;
            }
        });

        connect(invertXYCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    xyInverse = false;
                    settings.setValue("invertXY", false);
                    break;
                case Qt::Checked:
                    xyInverse = true;
                    settings.setValue("invertXY", true);
                    break;
                default: break;
            }
        });

        connect(homeButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 1;
           sendFrame();
        });

        connect(homeButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~1;
           sendFrame();
        });

        connect(powerButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 2;
           sendFrame();
        });

        connect(powerButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~2;
           sendFrame();
        });

        connect(longPowerButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 4;
           sendFrame();
        });

        connect(longPowerButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~4;
           sendFrame();
        });

        touchScreen = new TouchScreen(nullptr);
        this->setWindowTitle(tr("InputRedirectionClient-Qt"));

        addrLineEdit->setText(settings.value("ipAddress", "").toString());
        invertYCheckbox->setChecked(settings.value("invertY", false).toBool());
        invertABCheckbox->setChecked(settings.value("invertAB", false).toBool());
        invertXYCheckbox->setChecked(settings.value("invertXY", false).toBool());
    }

    void show(void)
    {
        QWidget::show();
        touchScreen->show();
    }

    void closeEvent(QCloseEvent *ev)
    {
        touchScreen->close();
        ev->accept();
    }

    virtual ~Widget(void)
    {
        lx = ly = rx = ry = 0.0;
        buttons = 0;
        interfaceButtons = 0;
        touchScreenPressed = false;
        sendFrame();
        delete touchScreen;
    }

};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    GamepadMonitor m(&w);
    FrameTimer t(&w);
    TouchScreen ts;
    t.start(50);
    w.show();

    return a.exec();
}
<commit_msg>Remove MSWindowsFixedSizeDialogHint<commit_after>#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif

#include <QWidget>
#include <QApplication>
#include <QDebug>
#include <QGamepadManager>
#include <QGamepad>
#include <QtEndian>
#include <QUdpSocket>
#include <QTimer>
#include <QFormLayout>
#include <QVBoxLayout>
#include <QLineEdit>
#include <QPushButton>
#include <QCheckBox>
#include <QDialog>
#include <QMouseEvent>
#include <QCloseEvent>
#include <QSettings>

#include <algorithm>
#include <cmath>

#define CPAD_BOUND          0x5d0
#define CPP_BOUND           0x7f

#define TOUCH_SCREEN_WIDTH  320
#define TOUCH_SCREEN_HEIGHT 240

typedef uint32_t u32;
typedef uint16_t u16;
typedef uint8_t u8;

double lx = 0.0, ly = 0.0;
double rx = 0.0, ry = 0.0;
QGamepadManager::GamepadButtons buttons = 0;
u32 interfaceButtons = 0;
QString ipAddress;
int yAxisMultiplier = 1;
bool abInverse = false;
bool xyInverse = false;

bool touchScreenPressed;
QPoint touchScreenPosition;

QSettings settings("TuxSH", "InputRedirectionClient-Qt");

void sendFrame(void)
{
    static const QGamepadManager::GamepadButton hidButtonsAB[] = {
        QGamepadManager::ButtonA,
        QGamepadManager::ButtonB,
    };

    static const QGamepadManager::GamepadButton hidButtonsMiddle[] = {
        QGamepadManager::ButtonSelect,
        QGamepadManager::ButtonStart,
        QGamepadManager::ButtonRight,
        QGamepadManager::ButtonLeft,
        QGamepadManager::ButtonUp,
        QGamepadManager::ButtonDown,
        QGamepadManager::ButtonR1,
        QGamepadManager::ButtonL1,
    };

    static const QGamepadManager::GamepadButton hidButtonsXY[] = {
        QGamepadManager::ButtonX,
        QGamepadManager::ButtonY,
    };

    static const QGamepadManager::GamepadButton irButtons[] = {
        QGamepadManager::ButtonR2,
        QGamepadManager::ButtonL2,
    };

    static const QGamepadManager::GamepadButton speButtons[] = {
        QGamepadManager::ButtonR3,
        QGamepadManager::ButtonL3,
        QGamepadManager::ButtonGuide,
    };

    u32 hidPad = 0xfff;
    if(!abInverse)
    {
        for(u32 i = 0; i < 2; i++)
        {
            if(buttons & (1 << hidButtonsAB[i]))
                hidPad &= ~(1 << i);
        }
    }
    else
    {
        for(u32 i = 0; i < 2; i++)
        {
            if(buttons & (1 << hidButtonsAB[1-i]))
                hidPad &= ~(1 << i);
        }
    }

    for(u32 i = 2; i < 10; i++)
    {
        if(buttons & (1 << hidButtonsMiddle[i-2]))
            hidPad &= ~(1 << i);
    }

    if(!xyInverse)
    {
        for(u32 i = 10; i < 12; i++)
        {
            if(buttons & (1 << hidButtonsXY[i-10]))
                hidPad &= ~(1 << i);
        }
    }
    else
    {
        for(u32 i = 10; i < 12; i++)
        {
            if(buttons & (1 << hidButtonsXY[1-(i-10)]))
                hidPad &= ~(1 << i);
        }
    }

    u32 irButtonsState = 0;
    for(u32 i = 0; i < 2; i++)
    {
        if(buttons & (1 << irButtons[i]))
            irButtonsState |= 1 << (i + 1);
    }

    u32 specialButtonsState = 0;
    for(u32 i = 0; i < 3; i++)
    {

        if(buttons & (1 << speButtons[i]))
            specialButtonsState |= 1 << i;
    }
    specialButtonsState |= interfaceButtons;

    u32 touchScreenState = 0x2000000;
    u32 circlePadState = 0x7ff7ff;
    u32 cppState = 0x80800081;

    if(lx != 0.0 || ly != 0.0)
    {
        u32 x = (u32)(lx * CPAD_BOUND + 0x800);
        u32 y = (u32)(ly * CPAD_BOUND + 0x800);
        x = x >= 0xfff ? (lx < 0.0 ? 0x000 : 0xfff) : x;
        y = y >= 0xfff ? (ly < 0.0 ? 0x000 : 0xfff) : y;

        circlePadState = (y << 12) | x;
    }

    if(rx != 0.0 || ry != 0.0 || irButtonsState != 0)
    {
        // We have to rotate the c-stick position 45°. Thanks, Nintendo.
        u32 x = (u32)(M_SQRT1_2 * (rx + ry) * CPP_BOUND + 0x80);
        u32 y = (u32)(M_SQRT1_2 * (ry - rx) * CPP_BOUND + 0x80);
        x = x >= 0xff ? (rx < 0.0 ? 0x00 : 0xff) : x;
        y = y >= 0xff ? (ry < 0.0 ? 0x00 : 0xff) : y;

        cppState = (y << 24) | (x << 16) | (irButtonsState << 8) | 0x81;
    }

    if(touchScreenPressed)
    {
        u32 x = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.x()), TOUCH_SCREEN_WIDTH)) / TOUCH_SCREEN_WIDTH;
        u32 y = (u32)(0xfff * std::min(std::max(0, touchScreenPosition.y()), TOUCH_SCREEN_HEIGHT)) / TOUCH_SCREEN_HEIGHT;
        touchScreenState = (1 << 24) | (y << 12) | x;
    }

    QByteArray ba(20, 0);
    qToLittleEndian(hidPad, (uchar *)ba.data());
    qToLittleEndian(touchScreenState, (uchar *)ba.data() + 4);
    qToLittleEndian(circlePadState, (uchar *)ba.data() + 8);
    qToLittleEndian(cppState, (uchar *)ba.data() + 12);
    qToLittleEndian(specialButtonsState, (uchar *)ba.data() + 16);
    QUdpSocket().writeDatagram(ba, QHostAddress(ipAddress), 4950);
}

struct GamepadMonitor : public QObject {

    GamepadMonitor(QObject *parent = nullptr) : QObject(parent)
    {
        connect(QGamepadManager::instance(), &QGamepadManager::gamepadButtonPressEvent, this,
            [](int deviceId, QGamepadManager::GamepadButton button, double value)
        {
            (void)deviceId;
            (void)value;
            buttons |= QGamepadManager::GamepadButtons(1 << button);
            sendFrame();
        });

        connect(QGamepadManager::instance(), &QGamepadManager::gamepadButtonReleaseEvent, this,
            [](int deviceId, QGamepadManager::GamepadButton button)
        {
            (void)deviceId;
            buttons &= QGamepadManager::GamepadButtons(~(1 << button));
            sendFrame();
        });
        connect(QGamepadManager::instance(), &QGamepadManager::gamepadAxisEvent, this,
            [](int deviceId, QGamepadManager::GamepadAxis axis, double value)
        {
            (void)deviceId;
            (void)value;
            switch(axis)
            {
                case QGamepadManager::AxisLeftX:
                    lx = value;
                    break;
                case QGamepadManager::AxisLeftY:
                    ly = yAxisMultiplier * -value; // for some reason qt inverts this
                    break;

                case QGamepadManager::AxisRightX:
                    rx = value;
                    break;
                case QGamepadManager::AxisRightY:
                    ry = yAxisMultiplier * -value; // for some reason qt inverts this
                    break;
                default: break;
            }
            sendFrame();
        });
    }
};

struct TouchScreen : public QDialog {
    TouchScreen(QWidget *parent = nullptr) : QDialog(parent)
    {
        this->setFixedSize(TOUCH_SCREEN_WIDTH, TOUCH_SCREEN_HEIGHT);
        this->setWindowFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint);
        this->setWindowTitle(tr("InputRedirectionClient-Qt - Touch screen"));
    }

    void mousePressEvent(QMouseEvent *ev)
    {
        if(ev->button() == Qt::LeftButton)
        {
            touchScreenPressed = true;
            touchScreenPosition = ev->pos();
            sendFrame();
        }
    }

    void mouseMoveEvent(QMouseEvent *ev)
    {
        if(touchScreenPressed && (ev->buttons() & Qt::LeftButton))
        {
            touchScreenPosition = ev->pos();
            sendFrame();
        }
    }

    void mouseReleaseEvent(QMouseEvent *ev)
    {
        if(ev->button() == Qt::LeftButton)
        {
            touchScreenPressed = false;
            sendFrame();
        }
    }

    void closeEvent(QCloseEvent *ev)
    {
        touchScreenPressed = false;
        sendFrame();
        ev->accept();
    }
};

struct FrameTimer : public QTimer {
    FrameTimer(QObject *parent = nullptr) : QTimer(parent)
    {
        connect(this, &QTimer::timeout, this,
                [](void)
        {
            sendFrame();
        });
    }
};

class Widget : public QWidget
{
private:
    QVBoxLayout *layout;
    QFormLayout *formLayout;
    QLineEdit *addrLineEdit;
    QCheckBox *invertYCheckbox, *invertABCheckbox, *invertXYCheckbox;
    QPushButton *homeButton, *powerButton, *longPowerButton;
    TouchScreen *touchScreen;
public:
    Widget(QWidget *parent = nullptr) : QWidget(parent)
    {
        layout = new QVBoxLayout(this);

        addrLineEdit = new QLineEdit(this);
        addrLineEdit->setClearButtonEnabled(true);

        invertYCheckbox = new QCheckBox(this);
        invertABCheckbox = new QCheckBox(this);
        invertXYCheckbox = new QCheckBox(this);
        formLayout = new QFormLayout;

        formLayout->addRow(tr("IP &address"), addrLineEdit);
        formLayout->addRow(tr("&Invert Y axis"), invertYCheckbox);
        formLayout->addRow(tr("Invert A<->&B"), invertABCheckbox);
        formLayout->addRow(tr("Invert X<->&Y"), invertXYCheckbox);

        homeButton = new QPushButton(tr("&HOME"), this);
        powerButton = new QPushButton(tr("&POWER"), this);
        longPowerButton = new QPushButton(tr("POWER (&long)"), this);

        layout->addLayout(formLayout);
        layout->addWidget(homeButton);
        layout->addWidget(powerButton);
        layout->addWidget(longPowerButton);

        connect(addrLineEdit, &QLineEdit::textChanged, this,
                [](const QString &text)
        {
            ipAddress = text;
            settings.setValue("ipAddress", text);
        });

        connect(invertYCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    yAxisMultiplier = 1;
                    settings.setValue("invertY", false);
                    break;
                case Qt::Checked:
                    yAxisMultiplier = -1;
                    settings.setValue("invertY", true);
                    break;
                default: break;
            }
        });

        connect(invertABCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    abInverse = false;
                    settings.setValue("invertAB", false);
                    break;
                case Qt::Checked:
                    abInverse = true;
                    settings.setValue("invertAB", true);
                    break;
                default: break;
            }
        });

        connect(invertXYCheckbox, &QCheckBox::stateChanged, this,
                [](int state)
        {
            switch(state)
            {
                case Qt::Unchecked:
                    xyInverse = false;
                    settings.setValue("invertXY", false);
                    break;
                case Qt::Checked:
                    xyInverse = true;
                    settings.setValue("invertXY", true);
                    break;
                default: break;
            }
        });

        connect(homeButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 1;
           sendFrame();
        });

        connect(homeButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~1;
           sendFrame();
        });

        connect(powerButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 2;
           sendFrame();
        });

        connect(powerButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~2;
           sendFrame();
        });

        connect(longPowerButton, &QPushButton::pressed, this,
                [](void)
        {
           interfaceButtons |= 4;
           sendFrame();
        });

        connect(longPowerButton, &QPushButton::released, this,
                [](void)
        {
           interfaceButtons &= ~4;
           sendFrame();
        });

        touchScreen = new TouchScreen(nullptr);
        this->setWindowTitle(tr("InputRedirectionClient-Qt"));

        addrLineEdit->setText(settings.value("ipAddress", "").toString());
        invertYCheckbox->setChecked(settings.value("invertY", false).toBool());
        invertABCheckbox->setChecked(settings.value("invertAB", false).toBool());
        invertXYCheckbox->setChecked(settings.value("invertXY", false).toBool());
    }

    void show(void)
    {
        QWidget::show();
        touchScreen->show();
    }

    void closeEvent(QCloseEvent *ev)
    {
        touchScreen->close();
        ev->accept();
    }

    virtual ~Widget(void)
    {
        lx = ly = rx = ry = 0.0;
        buttons = 0;
        interfaceButtons = 0;
        touchScreenPressed = false;
        sendFrame();
        delete touchScreen;
    }

};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Widget w;
    GamepadMonitor m(&w);
    FrameTimer t(&w);
    TouchScreen ts;
    t.start(50);
    w.show();

    return a.exec();
}
<|endoftext|>


<commit_before>9b32e53d-2747-11e6-b483-e0f84713e7b8<commit_msg>Fix that bug where things didn't work but now they should<commit_after>9b44f628-2747-11e6-8105-e0f84713e7b8<|endoftext|>


<commit_before>1878eb91-ad5a-11e7-8e48-ac87a332f658<commit_msg>add file<commit_after>190160e3-ad5a-11e7-a3f9-ac87a332f658<|endoftext|>


<commit_before>72f59680-2749-11e6-a444-e0f84713e7b8<commit_msg>bug fix<commit_after>7303b635-2749-11e6-98f2-e0f84713e7b8<|endoftext|>


<commit_before>#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "player.hpp"

#include "Game.h"
#include "GameStateStart.h"

/*
 * Mainly following this guide
 * https://www.binpress.com/tutorial/creating-a-city-building-game-with-sfml/137
 */
int main()
{ //TODO classes to make.  Floor?  Maybe floor is a 2d array of Tiles that all have a texture?  idk dudes.
    //BEGIN STARTUP CODE
    sf::RenderWindow window(sf::VideoMode(600, 400), "SFML works!");
    sf::CircleShape shape(60.f);
    shape.setFillColor(sf::Color::Green);
	Player *player = new Player(true, 1, 1, 0.0);//solid, starting at (1,1) facing right.
    // while (window.isOpen())
    {
		//BEGIN MAIN GAME LOOP
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::W))
		{
			player->up();
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::A))
		{
			player->left();
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::S))
		{
			player->down();
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::D))
		{
			player->right();
		}
		if (sf::Keyboard::isKeyPressed(sf::Keyboard::Space))
		{
			player->attack();
		}

        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed){
                window.close();//SHUTDOWN CODE
            }
        }

        window.clear();
        window.draw(shape);
        window.display();
    }

    return 0;
}
<commit_msg>undo merge mess up<commit_after>#include <SFML/Graphics.hpp>
#include <memory>

#include "Game.h"
#include "GameStateStart.h"

/*
 * Mainly following this guide
 * https://www.binpress.com/tutorial/creating-a-city-building-game-with-sfml/137
 */
int main()
{
    Game game;

    game.pushState(std::make_unique<GameStateStart>(&game));
    game.run();

    return 0;
}
<|endoftext|>


<commit_before>#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include "sniffer.h"

static void signal_handler(int nsignal);
static void handle_alarm(int nsignal);
static void handle_sigusr1(int nsignal);

sniffer sniffer;

int main(int argc, char** argv)
{
	if (argc != 2) {
		fprintf(stderr, "Usage: %s <interface>\n");
		return -1;
	}

	if (!sniffer.create(argv[1], 32 * 1024 * 1024)) {
		fprintf(stderr, "Couldn't create sniffer.\n");
		return -1;
	}

	struct sigaction act;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = signal_handler;
	sigaction(SIGTERM, &act, NULL);
	sigaction(SIGINT, &act, NULL);

	act.sa_handler = handle_alarm;
	sigaction(SIGALRM, &act, NULL);

	act.sa_handler = handle_sigusr1;
	sigaction(SIGUSR1, &act, NULL);

	struct itimerval value;
	value.it_interval.tv_sec = 5;
	value.it_interval.tv_usec = 0;
	value.it_value.tv_sec = 5;
	value.it_value.tv_usec = 0;
	if (setitimer(ITIMER_REAL, &value, NULL) < 0) {
		fprintf(stderr, "Couldn't set real-time alarm.\n");
		return -1;
	}

	sniffer.start();

	return 0;
}

void signal_handler(int nsignal)
{
	fprintf(stderr, "Signal received...\n");

	sniffer.stop();
}

void handle_alarm(int nsignal)
{
	sniffer.on_alarm();
}

void handle_sigusr1(int nsignal)
{
	sniffer.on_dump_connections();
}
<commit_msg>In the usage, argv[0] was missing.<commit_after>#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#include <signal.h>
#include "sniffer.h"

static void signal_handler(int nsignal);
static void handle_alarm(int nsignal);
static void handle_sigusr1(int nsignal);

sniffer sniffer;

int main(int argc, char** argv)
{
	if (argc != 2) {
		fprintf(stderr, "Usage: %s <interface>\n", argv[0]);
		return -1;
	}

	if (!sniffer.create(argv[1], 32 * 1024 * 1024)) {
		fprintf(stderr, "Couldn't create sniffer.\n");
		return -1;
	}

	struct sigaction act;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	act.sa_handler = signal_handler;
	sigaction(SIGTERM, &act, NULL);
	sigaction(SIGINT, &act, NULL);

	act.sa_handler = handle_alarm;
	sigaction(SIGALRM, &act, NULL);

	act.sa_handler = handle_sigusr1;
	sigaction(SIGUSR1, &act, NULL);

	struct itimerval value;
	value.it_interval.tv_sec = 5;
	value.it_interval.tv_usec = 0;
	value.it_value.tv_sec = 5;
	value.it_value.tv_usec = 0;
	if (setitimer(ITIMER_REAL, &value, NULL) < 0) {
		fprintf(stderr, "Couldn't set real-time alarm.\n");
		return -1;
	}

	sniffer.start();

	return 0;
}

void signal_handler(int nsignal)
{
	fprintf(stderr, "Signal received...\n");

	sniffer.stop();
}

void handle_alarm(int nsignal)
{
	sniffer.on_alarm();
}

void handle_sigusr1(int nsignal)
{
	sniffer.on_dump_connections();
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2001-2003 Peter J Jones (pjones@pmade.org)
 * 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 of the Author 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 AUTHOR 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 AUTHOR
 * 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.
 */

// xmlwrapp includes
#include "xmlwrapp/errors.h"

#include "node_manip.h"

// standard includes
#include <stdexcept>
#include <string>

// libxml includes
#include <libxml/tree.h>

xmlNodePtr
xml::impl::node_insert(xmlNodePtr parent, xmlNodePtr before, xmlNodePtr to_add)
{
    xmlNodePtr new_xml_node = xmlCopyNode(to_add, 1);
    if ( !new_xml_node )
        throw std::bad_alloc();

    if ( before == 0 )
    {
        // insert at the end of the child list
        if ( xmlAddChild(parent, new_xml_node) == 0 )
        {
            xmlFreeNode(new_xml_node);
            throw xml::exception("failed to insert xml::node; xmlAddChild failed");
        }
    }
    else
    {
        if ( xmlAddPrevSibling(before, new_xml_node) == 0 )
        {
            xmlFreeNode(new_xml_node);
            throw xml::exception("failed to insert xml::node; xmlAddPrevSibling failed");
        }
    }

    return new_xml_node;
}

xmlNodePtr
xml::impl::node_replace(xmlNodePtr old_node, xmlNodePtr new_node)
{
    xmlNodePtr copied_node = xmlCopyNode(new_node, 1);
    if ( !copied_node )
        throw std::bad_alloc();

    // hack to see if xmlReplaceNode was successful
    copied_node->doc = reinterpret_cast<xmlDocPtr>(old_node);
    xmlReplaceNode(old_node, copied_node);

    if ( copied_node->doc == reinterpret_cast<xmlDocPtr>(old_node) )
    {
        xmlFreeNode(copied_node);
        throw xml::exception("failed to replace xml::node; xmlReplaceNode() failed");
    }

    xmlFreeNode(old_node);
    return copied_node;
}

xmlNodePtr xml::impl::node_erase(xmlNodePtr to_erase)
{
    xmlNodePtr after = to_erase->next;

    xmlUnlinkNode(to_erase);
    xmlFreeNode(to_erase);

    return after;
}
<commit_msg>Use parent namespace by default for the new nodes.<commit_after>/*
 * Copyright (C) 2001-2003 Peter J Jones (pjones@pmade.org)
 * 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 of the Author 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 AUTHOR 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 AUTHOR
 * 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.
 */

// xmlwrapp includes
#include "xmlwrapp/errors.h"

#include "node_manip.h"

// standard includes
#include <stdexcept>
#include <string>

// libxml includes
#include <libxml/tree.h>

namespace
{

// Make a copy of the given node with its contents and children which is meant
// to be added under the specified parent.
//
// The returned pointer is never null (but this function may throw) and must be
// freed with xmlFreeNode().
xmlNodePtr copy_node_under_parent(xmlNodePtr parent, xmlNodePtr orig_node)
{
    xmlNodePtr new_xml_node = xmlCopyNode(orig_node, 1);
    if ( !new_xml_node )
        throw std::bad_alloc();

    // The new node should inherit the namespace of its parent, unless it
    // already has a custom namespace, for consistency with how tree
    // construction works in libxml2.
    if ( !new_xml_node->ns )
    {
        // Check that we really have a parent as this could also be xmlDoc
        // masquerading as xmlNode when inserting the root element itself.
        if ( parent->type != XML_DOCUMENT_NODE )
            new_xml_node->ns = parent->ns;
    }

    return new_xml_node;
}

} // anonymous namespace

xmlNodePtr
xml::impl::node_insert(xmlNodePtr parent, xmlNodePtr before, xmlNodePtr to_add)
{
    xmlNodePtr const new_xml_node = copy_node_under_parent(parent, to_add);

    if ( before == 0 )
    {
        // insert at the end of the child list
        if ( xmlAddChild(parent, new_xml_node) == 0 )
        {
            xmlFreeNode(new_xml_node);
            throw xml::exception("failed to insert xml::node; xmlAddChild failed");
        }
    }
    else
    {
        if ( xmlAddPrevSibling(before, new_xml_node) == 0 )
        {
            xmlFreeNode(new_xml_node);
            throw xml::exception("failed to insert xml::node; xmlAddPrevSibling failed");
        }
    }

    return new_xml_node;
}

xmlNodePtr
xml::impl::node_replace(xmlNodePtr old_node, xmlNodePtr new_node)
{
    xmlNodePtr const copied_node = copy_node_under_parent(old_node->parent, new_node);

    // hack to see if xmlReplaceNode was successful
    copied_node->doc = reinterpret_cast<xmlDocPtr>(old_node);
    xmlReplaceNode(old_node, copied_node);

    if ( copied_node->doc == reinterpret_cast<xmlDocPtr>(old_node) )
    {
        xmlFreeNode(copied_node);
        throw xml::exception("failed to replace xml::node; xmlReplaceNode() failed");
    }

    xmlFreeNode(old_node);
    return copied_node;
}

xmlNodePtr xml::impl::node_erase(xmlNodePtr to_erase)
{
    xmlNodePtr after = to_erase->next;

    xmlUnlinkNode(to_erase);
    xmlFreeNode(to_erase);

    return after;
}
<|endoftext|>