<commit_before>/***************************************************************************
  This is a library for the Adafruit 10DOF Breakout

  Designed specifically to work with the Adafruit 10DOF Breakout

  These displays use I2C to communicate, 2 pins are required to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/
#if ARDUINO >= 100
 #include "Arduino.h"
#else
 #include "WProgram.h"
#endif

#include <Wire.h>
#include <limits.h>
#include <math.h>

#include "Adafruit_10DOF.h"

#define PI  (3.14159265F);

/***************************************************************************
 PRIVATE FUNCTIONS
 ***************************************************************************/

/***************************************************************************
 CONSTRUCTOR
 ***************************************************************************/

/**************************************************************************/
/*!
    @brief  Instantiates a new Adafruit_10DOF class
*/
/**************************************************************************/
Adafruit_10DOF::Adafruit_10DOF(void)
{
}

/***************************************************************************
 PUBLIC FUNCTIONS
 ***************************************************************************/

/**************************************************************************/
/*!
    @brief  Setups the HW
*/
/**************************************************************************/
bool Adafruit_10DOF::begin()
{
  // Enable I2C
  Wire.begin();

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .pitch/.roll fields in the sensors_vec_t struct
            with the right angular data (in degree)

    @param  event         The sensors_event_t variable containing the
                          data from the accelerometer
    @param  orientation   The sensors_vec_t object that will have it's
                          .pitch and .roll fields populated
    @return Returns true if the operation was successful, false if there
            was an error

    @code

    bool error;
    sensors_event_t event;
    sensors_vec_t orientation;
    ...
    lsm303accelGetSensorEvent(&event);
    error = accelGetOrientation(&event, &orientation);

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::accelGetOrientation(sensors_event_t *event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if (event == NULL) return false;
  if (orientation == NULL) return false;

  float t_pitch;
  float t_roll;
  float t_heading;
  float signOfZ = event->acceleration.z >= 0 ? 1.0F : -1.0F;

  /* roll: Rotation around the longitudinal axis (the plane body, 'X axis'). -90<=roll<=90    */
  /* roll is positive and increasing when moving downward                                     */
  /*                                                                                */
  /*                                 y                                                        */
  /*             roll = atan(-----------------)                                               */
  /*                          sqrt(x^2 + z^2)                                                 */
  /* where:  x, y, z are returned value from accelerometer sensor                             */

  t_roll = event->acceleration.x * event->acceleration.x + event->acceleration.z * event->acceleration.z;
  orientation->roll = (float)atan2(event->acceleration.y, sqrt(t_roll)) * 180 / PI;

  /* pitch: Rotation around the lateral axis (the wing span, 'Y axis'). -180<=pitch<=180)     */
  /* pitch is positive and increasing when moving upwards                                     */
  /*                                                                                */
  /*                                 x                                                        */
  /*            pitch = atan(-----------------)                                               */
  /*                          sqrt(y^2 + z^2)                                                 */
  /* where:  x, y, z are returned value from accelerometer sensor                             */

  t_pitch = event->acceleration.y * event->acceleration.y + event->acceleration.z * event->acceleration.z;
  orientation->pitch = (float)atan2(event->acceleration.x, signOfZ * sqrt(t_pitch)) * 180 / PI;

  return true;
}

/**************************************************************************/
/*!
    @brief  Utilize the sensor data from an accelerometer to compensate
            the magnetic sensor measurements when the sensor is tilted
            (the pitch and roll angles are not equal 0°)

    @param  axis          The given axis (SENSOR_AXIS_X/Y/Z) that is
                          parallel to the gravity of the Earth

    @param  mag_event     The raw magnetometer data to adjust for tilt

    @param  accel_event   The accelerometer event data to use to determine
                          the tilt when compensating the mag_event values

    @code

    // Perform tilt compensation with matching accelerometer data
    sensors_event_t accel_event;
    error = lsm303accelGetSensorEvent(&accel_event);
    if (!error)
    {
      magTiltCompensation(SENSOR_AXIS_Z, &mag_event, &accel_event);
    }

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magTiltCompensation(sensors_axis_t axis, sensors_event_t *mag_event, sensors_event_t *accel_event)
{
  /* Make sure the input is valid, not null, etc. */
  if (mag_event == NULL) return false;
  if (accel_event == NULL) return false;

  float accel_X, accel_Y, accel_Z;
  float *mag_X, *mag_Y, *mag_Z;

  switch (axis)
  {
    case SENSOR_AXIS_X:
      /* The X-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.y;
      accel_Y = accel_event->acceleration.z;
      accel_Z = accel_event->acceleration.x;
      mag_X = &(mag_event->magnetic.y);
      mag_Y = &(mag_event->magnetic.z);
      mag_Z = &(mag_event->magnetic.x);
      break;

    case SENSOR_AXIS_Y:
      /* The Y-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.z;
      accel_Y = accel_event->acceleration.x;
      accel_Z = accel_event->acceleration.y;
      mag_X = &(mag_event->magnetic.z);
      mag_Y = &(mag_event->magnetic.x);
      mag_Z = &(mag_event->magnetic.y);
      break;

    case SENSOR_AXIS_Z:
      /* The Z-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.x;
      accel_Y = accel_event->acceleration.y;
      accel_Z = accel_event->acceleration.z;
      mag_X = &(mag_event->magnetic.x);
      mag_Y = &(mag_event->magnetic.y);
      mag_Z = &(mag_event->magnetic.z);
      break;

    default:
      return false;
  }

  float t_roll = accel_X * accel_X + accel_Z * accel_Z;
  float rollRadians = (float)atan2(accel_Y, sqrt(t_roll));

  float t_pitch = accel_Y * accel_Y + accel_Z * accel_Z;
  float pitchRadians = (float)atan2(accel_X, sqrt(t_pitch));

  float cosRoll = (float)cos(rollRadians);
  float sinRoll = (float)sin(rollRadians);
  float cosPitch = (float)cos(-1*pitchRadians);
  float sinPitch = (float)sin(-1*pitchRadians);

  /* The tilt compensation algorithm                            */
  /* Xh = X.cosPitch + Z.sinPitch                               */
  /* Yh = X.sinRoll.sinPitch + Y.cosRoll - Z.sinRoll.cosPitch   */
  *mag_X = (*mag_X) * cosPitch + (*mag_Z) * sinPitch;
  *mag_Y = (*mag_X) * sinRoll * sinPitch + (*mag_Y) * cosRoll - (*mag_Z) * sinRoll * cosPitch;

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .heading fields in the sensors_vec_t
            struct with the right angular data (0-359°)

            Heading increases when measuring clockwise

    @param  axis          The given axis (SENSOR_AXIS_X/Y/Z)

    @param  event         The raw magnetometer sensor data to use when
                          calculating out heading

    @param  orientation   The sensors_vec_t object where we will
                          assign an 'orientation.heading' value

    @code

    magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation);

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magGetOrientation(sensors_axis_t axis, sensors_event_t *event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if (event == NULL) return false;
  if (orientation == NULL) return false;

  switch (axis)
  {
    case SENSOR_AXIS_X:
      /* Sensor rotates around X-axis                                                                 */
      /* "heading" is the angle between the 'Y axis' and magnetic north on the horizontal plane (Oyz) */
      /* heading = atan(Mz / My)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.z, event->magnetic.y) * 180 / PI;
      break;

    case SENSOR_AXIS_Y:
      /* Sensor rotates around Y-axis                                                                 */
      /* "heading" is the angle between the 'Z axis' and magnetic north on the horizontal plane (Ozx) */
      /* heading = atan(Mx / Mz)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.x, event->magnetic.z) * 180 / PI;
      break;

    case SENSOR_AXIS_Z:
      /* Sensor rotates around Z-axis                                                                 */
      /* "heading" is the angle between the 'X axis' and magnetic north on the horizontal plane (Oxy) */
      /* heading = atan(My / Mx)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.y, event->magnetic.x) * 180 / PI;
      break;

    default:
      return false;
  }

  /* Normalize to 0-359° */
  if (orientation->heading < 0)
  {
    orientation->heading = 360 + orientation->heading;
  }

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .roll/.pitch/.heading fields in the sensors_vec_t
            struct with the right angular data (in degree).

            The starting position is set by placing the object flat and
            pointing northwards (Z-axis pointing upward and X-axis pointing
            northwards).

            The orientation of the object can be modeled as resulting from
            3 consecutive rotations in turn: heading (Z-axis), pitch (Y-axis),
            and roll (X-axis) applied to the starting position.

    @param  accel_event   The sensors_event_t variable containing the
                          data from the accelerometer

    @param  mag_event     The sensors_event_t variable containing the
                          data from the magnetometer

    @param  orientation   The sensors_vec_t object that will have it's
                          .roll, .pitch and .heading fields populated
*/
/**************************************************************************/
bool Adafruit_10DOF::fusionGetOrientation(sensors_event_t *accel_event, sensors_event_t *mag_event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if ( accel_event  == NULL) return false;
  if ( mag_event    == NULL) return false;
  if ( orientation  == NULL) return false;

  float const PI_F = 3.14159265F;

  /* roll: Rotation around the X-axis. -180 <= roll <= 180                                          */
  /* a positive roll angle is defined to be a clockwise rotation about the positive X-axis          */
  /*                                                                                */
  /*                    y                                                                           */
  /*      roll = atan2(---)                                                                         */
  /*                    z                                                                           */
  /*                                                                                */
  /* where:  y, z are returned value from accelerometer sensor                                      */
  orientation->roll = (float)atan2(accel_event->acceleration.y, accel_event->acceleration.z);

  /* pitch: Rotation around the Y-axis. -180 <= roll <= 180                                         */
  /* a positive pitch angle is defined to be a clockwise rotation about the positive Y-axis         */
  /*                                                                                */
  /*                                 -x                                                             */
  /*      pitch = atan(-------------------------------)                                             */
  /*                    y * sin(roll) + z * cos(roll)                                               */
  /*                                                                                */
  /* where:  x, y, z are returned value from accelerometer sensor                                   */
  if (accel_event->acceleration.y * sin(orientation->roll) + accel_event->acceleration.z * cos(orientation->roll) == 0)
    orientation->pitch = accel_event->acceleration.x > 0 ? (PI_F / 2) : (-PI_F / 2);
  else
    orientation->pitch = (float)atan(-accel_event->acceleration.x / (accel_event->acceleration.y * sin(orientation->roll) + \
                                                                     accel_event->acceleration.z * cos(orientation->roll)));

  /* heading: Rotation around the Z-axis. -180 <= roll <= 180                                       */
  /* a positive heading angle is defined to be a clockwise rotation about the positive Z-axis       */
  /*                                                                                */
  /*                                       z * sin(roll) - y * cos(roll)                            */
  /*   heading = atan2(--------------------------------------------------------------------------)  */
  /*                    x * cos(pitch) + y * sin(pitch) * sin(roll) + z * sin(pitch) * cos(roll))   */
  /*                                                                                */
  /* where:  x, y, z are returned value from magnetometer sensor                                    */
  orientation->heading = (float)atan2(mag_event->magnetic.z * sin(orientation->roll) - mag_event->magnetic.y * cos(orientation->roll), \
                                      mag_event->magnetic.x * cos(orientation->pitch) + \
                                      mag_event->magnetic.y * sin(orientation->pitch) * sin(orientation->roll) + \
                                      mag_event->magnetic.z * sin(orientation->pitch) * cos(orientation->roll));

  /* Convert angular data to degree */
  orientation->roll = orientation->roll * 180 / PI_F;
  orientation->pitch = orientation->pitch * 180 / PI_F;
  orientation->heading = orientation->heading * 180 / PI_F;

  return true;
}
<commit_msg>Update Adafruit_10DOF.cpp<commit_after>/***************************************************************************
  This is a library for the Adafruit 10DOF Breakout

  Designed specifically to work with the Adafruit 10DOF Breakout

  These displays use I2C to communicate, 2 pins are required to interface.

  Adafruit invests time and resources providing this open source code,
  please support Adafruit andopen-source hardware by purchasing products
  from Adafruit!

  Written by Kevin Townsend for Adafruit Industries.
  BSD license, all text above must be included in any redistribution
 ***************************************************************************/

#include <Wire.h>
#include <limits.h>
#include <math.h>

#include "Adafruit_10DOF.h"

#define PI  (3.14159265F);

/***************************************************************************
 PRIVATE FUNCTIONS
 ***************************************************************************/

/***************************************************************************
 CONSTRUCTOR
 ***************************************************************************/

/**************************************************************************/
/*!
    @brief  Instantiates a new Adafruit_10DOF class
*/
/**************************************************************************/
Adafruit_10DOF::Adafruit_10DOF(void)
{
}

/***************************************************************************
 PUBLIC FUNCTIONS
 ***************************************************************************/

/**************************************************************************/
/*!
    @brief  Setups the HW
*/
/**************************************************************************/
bool Adafruit_10DOF::begin()
{
  // Enable I2C
  Wire.begin();

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .pitch/.roll fields in the sensors_vec_t struct
            with the right angular data (in degree)

    @param  event         The sensors_event_t variable containing the
                          data from the accelerometer
    @param  orientation   The sensors_vec_t object that will have it's
                          .pitch and .roll fields populated
    @return Returns true if the operation was successful, false if there
            was an error

    @code

    bool error;
    sensors_event_t event;
    sensors_vec_t orientation;
    ...
    lsm303accelGetSensorEvent(&event);
    error = accelGetOrientation(&event, &orientation);

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::accelGetOrientation(sensors_event_t *event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if (event == NULL) return false;
  if (orientation == NULL) return false;

  float t_pitch;
  float t_roll;
  float t_heading;
  float signOfZ = event->acceleration.z >= 0 ? 1.0F : -1.0F;

  /* roll: Rotation around the longitudinal axis (the plane body, 'X axis'). -90<=roll<=90    */
  /* roll is positive and increasing when moving downward                                     */
  /*                                                                                */
  /*                                 y                                                        */
  /*             roll = atan(-----------------)                                               */
  /*                          sqrt(x^2 + z^2)                                                 */
  /* where:  x, y, z are returned value from accelerometer sensor                             */

  t_roll = event->acceleration.x * event->acceleration.x + event->acceleration.z * event->acceleration.z;
  orientation->roll = (float)atan2(event->acceleration.y, sqrt(t_roll)) * 180 / PI;

  /* pitch: Rotation around the lateral axis (the wing span, 'Y axis'). -180<=pitch<=180)     */
  /* pitch is positive and increasing when moving upwards                                     */
  /*                                                                                */
  /*                                 x                                                        */
  /*            pitch = atan(-----------------)                                               */
  /*                          sqrt(y^2 + z^2)                                                 */
  /* where:  x, y, z are returned value from accelerometer sensor                             */

  t_pitch = event->acceleration.y * event->acceleration.y + event->acceleration.z * event->acceleration.z;
  orientation->pitch = (float)atan2(event->acceleration.x, signOfZ * sqrt(t_pitch)) * 180 / PI;

  return true;
}

/**************************************************************************/
/*!
    @brief  Utilize the sensor data from an accelerometer to compensate
            the magnetic sensor measurements when the sensor is tilted
            (the pitch and roll angles are not equal 0°)

    @param  axis          The given axis (SENSOR_AXIS_X/Y/Z) that is
                          parallel to the gravity of the Earth

    @param  mag_event     The raw magnetometer data to adjust for tilt

    @param  accel_event   The accelerometer event data to use to determine
                          the tilt when compensating the mag_event values

    @code

    // Perform tilt compensation with matching accelerometer data
    sensors_event_t accel_event;
    error = lsm303accelGetSensorEvent(&accel_event);
    if (!error)
    {
      magTiltCompensation(SENSOR_AXIS_Z, &mag_event, &accel_event);
    }

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magTiltCompensation(sensors_axis_t axis, sensors_event_t *mag_event, sensors_event_t *accel_event)
{
  /* Make sure the input is valid, not null, etc. */
  if (mag_event == NULL) return false;
  if (accel_event == NULL) return false;

  float accel_X, accel_Y, accel_Z;
  float *mag_X, *mag_Y, *mag_Z;

  switch (axis)
  {
    case SENSOR_AXIS_X:
      /* The X-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.y;
      accel_Y = accel_event->acceleration.z;
      accel_Z = accel_event->acceleration.x;
      mag_X = &(mag_event->magnetic.y);
      mag_Y = &(mag_event->magnetic.z);
      mag_Z = &(mag_event->magnetic.x);
      break;

    case SENSOR_AXIS_Y:
      /* The Y-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.z;
      accel_Y = accel_event->acceleration.x;
      accel_Z = accel_event->acceleration.y;
      mag_X = &(mag_event->magnetic.z);
      mag_Y = &(mag_event->magnetic.x);
      mag_Z = &(mag_event->magnetic.y);
      break;

    case SENSOR_AXIS_Z:
      /* The Z-axis is parallel to the gravity */
      accel_X = accel_event->acceleration.x;
      accel_Y = accel_event->acceleration.y;
      accel_Z = accel_event->acceleration.z;
      mag_X = &(mag_event->magnetic.x);
      mag_Y = &(mag_event->magnetic.y);
      mag_Z = &(mag_event->magnetic.z);
      break;

    default:
      return false;
  }

  float t_roll = accel_X * accel_X + accel_Z * accel_Z;
  float rollRadians = (float)atan2(accel_Y, sqrt(t_roll));

  float t_pitch = accel_Y * accel_Y + accel_Z * accel_Z;
  float pitchRadians = (float)atan2(accel_X, sqrt(t_pitch));

  float cosRoll = (float)cos(rollRadians);
  float sinRoll = (float)sin(rollRadians);
  float cosPitch = (float)cos(-1*pitchRadians);
  float sinPitch = (float)sin(-1*pitchRadians);

  /* The tilt compensation algorithm                            */
  /* Xh = X.cosPitch + Z.sinPitch                               */
  /* Yh = X.sinRoll.sinPitch + Y.cosRoll - Z.sinRoll.cosPitch   */
  *mag_X = (*mag_X) * cosPitch + (*mag_Z) * sinPitch;
  *mag_Y = (*mag_X) * sinRoll * sinPitch + (*mag_Y) * cosRoll - (*mag_Z) * sinRoll * cosPitch;

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .heading fields in the sensors_vec_t
            struct with the right angular data (0-359°)

            Heading increases when measuring clockwise

    @param  axis          The given axis (SENSOR_AXIS_X/Y/Z)

    @param  event         The raw magnetometer sensor data to use when
                          calculating out heading

    @param  orientation   The sensors_vec_t object where we will
                          assign an 'orientation.heading' value

    @code

    magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation);

    @endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magGetOrientation(sensors_axis_t axis, sensors_event_t *event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if (event == NULL) return false;
  if (orientation == NULL) return false;

  switch (axis)
  {
    case SENSOR_AXIS_X:
      /* Sensor rotates around X-axis                                                                 */
      /* "heading" is the angle between the 'Y axis' and magnetic north on the horizontal plane (Oyz) */
      /* heading = atan(Mz / My)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.z, event->magnetic.y) * 180 / PI;
      break;

    case SENSOR_AXIS_Y:
      /* Sensor rotates around Y-axis                                                                 */
      /* "heading" is the angle between the 'Z axis' and magnetic north on the horizontal plane (Ozx) */
      /* heading = atan(Mx / Mz)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.x, event->magnetic.z) * 180 / PI;
      break;

    case SENSOR_AXIS_Z:
      /* Sensor rotates around Z-axis                                                                 */
      /* "heading" is the angle between the 'X axis' and magnetic north on the horizontal plane (Oxy) */
      /* heading = atan(My / Mx)                                                                      */
      orientation->heading = (float)atan2(event->magnetic.y, event->magnetic.x) * 180 / PI;
      break;

    default:
      return false;
  }

  /* Normalize to 0-359° */
  if (orientation->heading < 0)
  {
    orientation->heading = 360 + orientation->heading;
  }

  return true;
}

/**************************************************************************/
/*!
    @brief  Populates the .roll/.pitch/.heading fields in the sensors_vec_t
            struct with the right angular data (in degree).

            The starting position is set by placing the object flat and
            pointing northwards (Z-axis pointing upward and X-axis pointing
            northwards).

            The orientation of the object can be modeled as resulting from
            3 consecutive rotations in turn: heading (Z-axis), pitch (Y-axis),
            and roll (X-axis) applied to the starting position.

    @param  accel_event   The sensors_event_t variable containing the
                          data from the accelerometer

    @param  mag_event     The sensors_event_t variable containing the
                          data from the magnetometer

    @param  orientation   The sensors_vec_t object that will have it's
                          .roll, .pitch and .heading fields populated
*/
/**************************************************************************/
bool Adafruit_10DOF::fusionGetOrientation(sensors_event_t *accel_event, sensors_event_t *mag_event, sensors_vec_t *orientation)
{
  /* Make sure the input is valid, not null, etc. */
  if ( accel_event  == NULL) return false;
  if ( mag_event    == NULL) return false;
  if ( orientation  == NULL) return false;

  float const PI_F = 3.14159265F;

  /* roll: Rotation around the X-axis. -180 <= roll <= 180                                          */
  /* a positive roll angle is defined to be a clockwise rotation about the positive X-axis          */
  /*                                                                                */
  /*                    y                                                                           */
  /*      roll = atan2(---)                                                                         */
  /*                    z                                                                           */
  /*                                                                                */
  /* where:  y, z are returned value from accelerometer sensor                                      */
  orientation->roll = (float)atan2(accel_event->acceleration.y, accel_event->acceleration.z);

  /* pitch: Rotation around the Y-axis. -180 <= roll <= 180                                         */
  /* a positive pitch angle is defined to be a clockwise rotation about the positive Y-axis         */
  /*                                                                                */
  /*                                 -x                                                             */
  /*      pitch = atan(-------------------------------)                                             */
  /*                    y * sin(roll) + z * cos(roll)                                               */
  /*                                                                                */
  /* where:  x, y, z are returned value from accelerometer sensor                                   */
  if (accel_event->acceleration.y * sin(orientation->roll) + accel_event->acceleration.z * cos(orientation->roll) == 0)
    orientation->pitch = accel_event->acceleration.x > 0 ? (PI_F / 2) : (-PI_F / 2);
  else
    orientation->pitch = (float)atan(-accel_event->acceleration.x / (accel_event->acceleration.y * sin(orientation->roll) + \
                                                                     accel_event->acceleration.z * cos(orientation->roll)));

  /* heading: Rotation around the Z-axis. -180 <= roll <= 180                                       */
  /* a positive heading angle is defined to be a clockwise rotation about the positive Z-axis       */
  /*                                                                                */
  /*                                       z * sin(roll) - y * cos(roll)                            */
  /*   heading = atan2(--------------------------------------------------------------------------)  */
  /*                    x * cos(pitch) + y * sin(pitch) * sin(roll) + z * sin(pitch) * cos(roll))   */
  /*                                                                                */
  /* where:  x, y, z are returned value from magnetometer sensor                                    */
  orientation->heading = (float)atan2(mag_event->magnetic.z * sin(orientation->roll) - mag_event->magnetic.y * cos(orientation->roll), \
                                      mag_event->magnetic.x * cos(orientation->pitch) + \
                                      mag_event->magnetic.y * sin(orientation->pitch) * sin(orientation->roll) + \
                                      mag_event->magnetic.z * sin(orientation->pitch) * cos(orientation->roll));

  /* Convert angular data to degree */
  orientation->roll = orientation->roll * 180 / PI_F;
  orientation->pitch = orientation->pitch * 180 / PI_F;
  orientation->heading = orientation->heading * 180 / PI_F;

  return true;
}
<|endoftext|>


<commit_before>
#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <set>
#include <algorithm>
#include <bitset>
#include <math.h>

/*
An interesting problem:

There are n particles in a chamber of m locations (n<=m). Each particle is marked L or R based on whether it moves left or right. Empty locations are marked as dot(.). If the initial state of the chamber is denoted as S, then given a speed w which measures number of steps a particle moves left/right every unit of time, list all states of the chamber starting from S until it is empty.

Particles can move through each other so each position in steps subsequent to S is marked as X if there is at least one particle in that postion. Otherwise it marked as dot(.)

Input: w=2, S="R....L"
Output: {
          "X....X"
          "..XX..",
          ".X..X.",
          "......"
        }

*/

using namespace std;

int num2bits(int n) {
    return (1 << n) - 1;
}

void printSeq(unsigned long s, unsigned long length = 0, int iter = 0) {
    static int len = 0;
    if (length) {
        len = length;
        cout << "{  ";
    }
    cout << "\"";
    for (unsigned long i = 0; i < len; i++) {
        if ((1 << (len - 1 - i)) & s) {
            cout << "X";
        } else {
            cout << ".";
        }
    }
    if (iter) {
        cout << "\"," << "\n";
    } else {
        cout << "\"" << "\n";
    }
}

void animate(int speed, const char *init) {
    unsigned long resultL = 0;
    unsigned long resultR = 0;
    unsigned long resultAll = 0;

    const char *i = init;
    char c;
    unsigned long index = 0;
    while ((c = *i)) {
        resultL <<= 1;
        resultR <<= 1;
        if (c == 'L') {
            resultL = resultL | 1 ;
        }
        if (c == 'R') {
            resultR = resultR | 1 ;
        }
        i++;
        index++;
    }

    cout << "{ " << "\n";
    int mask = num2bits(index);
    resultL &= mask;
    resultR &= mask;
    resultAll = (resultL | resultR);
    int iter = 0;
    printSeq(resultAll, index, iter);

    while (resultAll != 0) {
       resultL = (resultL << speed) & mask;
       resultR = (resultR >> speed) & mask;
       resultAll = (resultL | resultR);
       iter++;
       printSeq(resultAll, 0L, iter);
    }
    cout << " }\n";
}

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

animate(2,"..R....");
animate(3,"RR..LRL");
animate(2,  "LRLR.LRLR");
animate(10,  "RLRLRLRLRL");
animate(1,  "...");
animate(1,  "LRRL.LR.LRR.R.LRRL.");

}

<commit_msg>remove<commit_after><|endoftext|>


<commit_before>/*
 *  qi_mtsat.cpp
 *
 *  Copyright (c) 2019 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <Eigen/Core>

#include "Args.h"
#include "ImageIO.h"
#include "SequenceBase.h"
#include "Util.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"

struct MTSatSequence : QI::SequenceBase {
    double TR, al_t1, al_pd, al_mt;

    QI_SEQUENCE_DECLARE(MTSat);
    Eigen::Index size() const override { return 1; };
};
void from_json(const json &j, MTSatSequence &s) {
    j.at("TR").get_to(s.TR);
    s.al_pd = j.at("FA_PD").get<double>() * M_PI / 180;
    s.al_t1 = j.at("FA_T1").get<double>() * M_PI / 180;
    s.al_mt = j.at("FA_MT").get<double>() * M_PI / 180;
}

void to_json(json &j, const MTSatSequence &s) {
    j = json{
        {"TR", s.TR},
        {"FA_PD", s.al_pd * 180 / M_PI},
        {"FA_T1", s.al_t1 * 180 / M_PI},
        {"FA_MT", s.al_mt * 180 / M_PI},
    };
}

/*
 * Main
 */
int main(int argc, char **argv) {
    Eigen::initParallel();
    args::ArgumentParser parser(
        "Calculates MTsat from PDw, T1w, MTw data.\nhttp://github.com/spinicist/QUIT");
    args::Positional<std::string> pdw_path(parser, "PDw", "Input PD-weighted file");
    args::Positional<std::string> t1w_path(parser, "T1w", "Input T1-weighted file");
    args::Positional<std::string> mtw_path(parser, "MTw", "Input MT-weighted file");

    args::HelpFlag       help(parser, "HELP", "Show this help message", {'h', "help"});
    args::Flag           verbose(parser, "VERBOSE", "Print more information", {'v', "verbose"});
    args::ValueFlag<int> threads(parser,
                                 "THREADS",
                                 "Use N threads (default=4, 0=hardware limit)",
                                 {'T', "threads"},
                                 QI::GetDefaultThreads());
    args::ValueFlag<std::string> outarg(
        parser, "OUTPREFIX", "Add a prefix to output filename", {'o', "out"});
    args::ValueFlag<std::string> mask_path(
        parser, "MASK", "Only process voxels within the mask", {'m', "mask"});
    args::ValueFlag<std::string> json_file(
        parser, "JSON", "Read JSON from file instead of stdin", {"json"});
    args::ValueFlag<std::string> b1_path(parser, "B1", "Path to B1 map", {'b', "B1"});
    QI::ParseArgs(parser, argc, argv, verbose, threads);

    auto pdw_img = QI::ReadImage(QI::CheckPos(pdw_path), verbose);
    auto t1w_img = QI::ReadImage(QI::CheckPos(t1w_path), verbose);
    auto mtw_img = QI::ReadImage(QI::CheckPos(mtw_path), verbose);
    QI::Log(verbose, "Reading sequence parameters");
    json          doc = json_file ? QI::ReadJSON(json_file.Get()) : QI::ReadJSON(std::cin);
    MTSatSequence s(doc["MTSat"]);

    QI::VolumeF::Pointer b1_img = nullptr, mask_img = nullptr;
    if (b1_path) {
        b1_img = QI::ReadImage(b1_path.Get(), verbose);
    }
    if (mask_path) {
        mask_img = QI::ReadImage(mask_path.Get(), verbose);
    }

    QI::Info(verbose, "Allocating output memory");
    auto R1_img = QI::NewImageLike<QI::VolumeF>(pdw_img);
    auto A_img  = QI::NewImageLike<QI::VolumeF>(pdw_img);
    auto d_img  = QI::NewImageLike<QI::VolumeF>(pdw_img);

    QI::Info(verbose, "Processing");
    auto mt = itk::MultiThreaderBase::New();
    mt->SetNumberOfWorkUnits(threads.Get());
    mt->ParallelizeImageRegion<3>(
        R1_img->GetBufferedRegion(),
        [&](const QI::VolumeF::RegionType &region) {
            itk::ImageRegionConstIterator<QI::VolumeF> pdw_it(pdw_img, region),
                t1w_it(t1w_img, region), mtw_it(mtw_img, region);
            itk::ImageRegionIterator<QI::VolumeF> R1_it(R1_img, region), A_it(A_img, region),
                d_it(d_img, region);
            itk::ImageRegionConstIterator<QI::VolumeF> B1_it, mask_it;
            if (b1_img) {
                B1_it = itk::ImageRegionConstIterator<QI::VolumeF>(b1_img, region);
            }
            if (mask_img) {
                mask_it = itk::ImageRegionConstIterator<QI::VolumeF>(mask_img, region);
            }

            for (R1_it.GoToBegin(); !R1_it.IsAtEnd(); ++R1_it) {
                if (!mask_img || mask_it.Get()) {
                    auto S_pd = pdw_it.Get();
                    auto S_t1 = t1w_it.Get();
                    auto S_mt = mtw_it.Get();
                    auto B1   = b1_img ? B1_it.Get() : 1.0f;

                    auto R1 = (B1 * B1 / (2. * s.TR)) * (S_t1 * s.al_t1 - S_pd * s.al_pd) /
                              (S_pd / s.al_pd - S_t1 / s.al_t1);
                    auto A = (S_pd * S_t1 / B1) * (s.al_t1 / s.al_pd - s.al_pd / s.al_t1) /
                             (S_t1 * s.al_t1 - S_pd * s.al_pd);
                    auto d = (A * B1 * s.al_mt / S_mt - 1) * R1 * s.TR -
                             (B1 * B1 * s.al_mt * s.al_mt / 2);
                    R1_it.Set(R1);
                    A_it.Set(A);
                    d_it.Set(d * 100);
                } else {
                    R1_it.Set(0.0);
                    A_it.Set(0.0);
                    d_it.Set(0.0);
                }

                ++t1w_it;
                ++pdw_it;
                ++mtw_it;
                // ++R1_it;
                ++A_it;
                ++d_it;
                if (b1_img) {
                    ++B1_it;
                }
                if (mask_img) {
                    ++mask_it;
                }
            }
        },
        nullptr);
    QI::Info(verbose, "Finished");
    QI::WriteImage(R1_img, outarg.Get() + "MTSat_R1" + QI::OutExt(), verbose);
    QI::WriteImage(A_img, outarg.Get() + "MTSat_A" + QI::OutExt(), verbose);
    QI::WriteImage(d_img, outarg.Get() + "MTSat_delta" + QI::OutExt(), verbose);
    return EXIT_SUCCESS;
}
<commit_msg>BUG Allow different TRs for MTsat<commit_after>/*
 *  qi_mtsat.cpp
 *
 *  Copyright (c) 2019 Tobias Wood.
 *
 *  This Source Code Form is subject to the terms of the Mozilla Public
 *  License, v. 2.0. If a copy of the MPL was not distributed with this
 *  file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 */

#include <Eigen/Core>

#include "Args.h"
#include "ImageIO.h"
#include "SequenceBase.h"
#include "Util.h"
#include "itkImageRegionConstIterator.h"
#include "itkImageRegionIterator.h"

struct MTSatSequence : QI::SequenceBase {
    double TR_pd, al_pd, TR_t1, al_t1, TR_mt, al_mt;

    QI_SEQUENCE_DECLARE(MTSat);
    Eigen::Index size() const override { return 1; };
};
void from_json(const json &j, MTSatSequence &s) {
    j.at("TR_PDw").get_to(s.TR_pd);
    j.at("TR_T1w").get_to(s.TR_t1);
    j.at("TR_MTw").get_to(s.TR_mt);
    s.al_pd = j.at("FA_PDw").get<double>() * M_PI / 180;
    s.al_t1 = j.at("FA_T1w").get<double>() * M_PI / 180;
    s.al_mt = j.at("FA_MTw").get<double>() * M_PI / 180;
}

void to_json(json &j, const MTSatSequence &s) {
    j = json{
        {"TR_PDw", s.TR_pd},
        {"TR_T1w", s.TR_t1},
        {"TR_MTw", s.TR_mt},
        {"FA_PDw", s.al_pd * 180 / M_PI},
        {"FA_T1w", s.al_t1 * 180 / M_PI},
        {"FA_MTw", s.al_mt * 180 / M_PI},
    };
}

/*
 * Main
 */
int main(int argc, char **argv) {
    Eigen::initParallel();
    args::ArgumentParser parser(
        "Calculates MTsat from PDw, T1w, MTw data.\nhttp://github.com/spinicist/QUIT");
    args::Positional<std::string> pdw_path(parser, "PDw", "Input PD-weighted file");
    args::Positional<std::string> t1w_path(parser, "T1w", "Input T1-weighted file");
    args::Positional<std::string> mtw_path(parser, "MTw", "Input MT-weighted file");

    args::HelpFlag       help(parser, "HELP", "Show this help message", {'h', "help"});
    args::Flag           verbose(parser, "VERBOSE", "Print more information", {'v', "verbose"});
    args::ValueFlag<int> threads(parser,
                                 "THREADS",
                                 "Use N threads (default=4, 0=hardware limit)",
                                 {'T', "threads"},
                                 QI::GetDefaultThreads());
    args::ValueFlag<std::string> outarg(
        parser, "OUTPREFIX", "Add a prefix to output filename", {'o', "out"});
    args::ValueFlag<std::string> mask_path(
        parser, "MASK", "Only process voxels within the mask", {'m', "mask"});
    args::ValueFlag<std::string> json_file(
        parser, "JSON", "Read JSON from file instead of stdin", {"json"});
    args::ValueFlag<std::string> b1_path(parser, "B1", "Path to B1 map", {'b', "B1"});
    QI::ParseArgs(parser, argc, argv, verbose, threads);

    auto pdw_img = QI::ReadImage(QI::CheckPos(pdw_path), verbose);
    auto t1w_img = QI::ReadImage(QI::CheckPos(t1w_path), verbose);
    auto mtw_img = QI::ReadImage(QI::CheckPos(mtw_path), verbose);
    QI::Log(verbose, "Reading sequence parameters");
    json          doc = json_file ? QI::ReadJSON(json_file.Get()) : QI::ReadJSON(std::cin);
    MTSatSequence s(doc["MTSat"]);

    QI::VolumeF::Pointer b1_img = nullptr, mask_img = nullptr;
    if (b1_path) {
        b1_img = QI::ReadImage(b1_path.Get(), verbose);
    }
    if (mask_path) {
        mask_img = QI::ReadImage(mask_path.Get(), verbose);
    }

    QI::Info(verbose, "Allocating output memory");
    auto R1_img = QI::NewImageLike<QI::VolumeF>(pdw_img);
    auto A_img  = QI::NewImageLike<QI::VolumeF>(pdw_img);
    auto d_img  = QI::NewImageLike<QI::VolumeF>(pdw_img);

    QI::Info(verbose, "Processing");
    auto mt = itk::MultiThreaderBase::New();
    mt->SetNumberOfWorkUnits(threads.Get());
    mt->ParallelizeImageRegion<3>(
        R1_img->GetBufferedRegion(),
        [&](const QI::VolumeF::RegionType &region) {
            itk::ImageRegionConstIterator<QI::VolumeF> pdw_it(pdw_img, region),
                t1w_it(t1w_img, region), mtw_it(mtw_img, region);
            itk::ImageRegionIterator<QI::VolumeF> R1_it(R1_img, region), A_it(A_img, region),
                d_it(d_img, region);
            itk::ImageRegionConstIterator<QI::VolumeF> B1_it, mask_it;
            if (b1_img) {
                B1_it = itk::ImageRegionConstIterator<QI::VolumeF>(b1_img, region);
            }
            if (mask_img) {
                mask_it = itk::ImageRegionConstIterator<QI::VolumeF>(mask_img, region);
            }

            for (R1_it.GoToBegin(); !R1_it.IsAtEnd(); ++R1_it) {
                if (!mask_img || mask_it.Get()) {
                    auto S_pd = pdw_it.Get();
                    auto S_t1 = t1w_it.Get();
                    auto S_mt = mtw_it.Get();
                    auto B1   = b1_img ? B1_it.Get() : 1.0f;

                    auto R1 = (B1 * B1 / 2.) *
                              (S_t1 * s.al_t1 / s.TR_t1 - S_pd * s.al_pd / s.TR_pd) /
                              (S_pd / s.al_pd - S_t1 / s.al_t1);
                    auto A = (S_pd * S_t1 / B1) *
                             (s.TR_pd * s.al_t1 / s.al_pd - s.TR_t1 * s.al_pd / s.al_t1) /
                             (S_t1 * s.TR_pd * s.al_t1 - S_pd * s.TR_t1 * s.al_pd);
                    auto d = (A * B1 * s.al_mt / S_mt - 1) * R1 * s.TR_mt -
                             (B1 * B1 * s.al_mt * s.al_mt / 2);
                    R1_it.Set(R1);
                    A_it.Set(A);
                    d_it.Set(d * 100);
                } else {
                    R1_it.Set(0.0);
                    A_it.Set(0.0);
                    d_it.Set(0.0);
                }

                ++t1w_it;
                ++pdw_it;
                ++mtw_it;
                // ++R1_it;
                ++A_it;
                ++d_it;
                if (b1_img) {
                    ++B1_it;
                }
                if (mask_img) {
                    ++mask_it;
                }
            }
        },
        nullptr);
    QI::Info(verbose, "Finished");
    QI::WriteImage(R1_img, outarg.Get() + "MTSat_R1" + QI::OutExt(), verbose);
    QI::WriteImage(A_img, outarg.Get() + "MTSat_A" + QI::OutExt(), verbose);
    QI::WriteImage(d_img, outarg.Get() + "MTSat_delta" + QI::OutExt(), verbose);
    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>// =========================================================
// (C) The Linbox Group 1999   Examples for using fields
// Fri Feb  8 14:10:35 MET 2002 / Gilles Villard
// =========================================================

// ---------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
// ---------------------------------------------

#include "LinBox/gmp-rational-field.C"
#include "LinBox/unparam_field.h"
#include "LinBox/param_modular.h"

using namespace LinBox;

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

int main() {

  /*  Use of LinBox basic field capabilities.
   *  A concrete field will be a domain (an object)
   *  with a given type that one may choose between
      LinBox kernel capabilities :
   */

  typedef GMP_Rational_Field  Field;     // Rational numbers based on Gmp
  //typedef unparam_field<double> Field;   // Or the doubles via the LinBox interface

  //typedef param_modular Field;             // Or the % on the integers for a mod p field

  /* Once this type "Field" is chosen, a domain K is declared */

  Field K;
  //Field K(7);  /* If choice of the modular field, modulo 7 */

  /* The element of "K" are addressed using the type "Field::element" */

  Field::element a,b,r;

  /* "a" and "b" elements of K, initialized, read from
   * std input, divided, written on std output
   */

  K.init(a); K.init(b); K.init(r);
  K.read(cin,a);  K.read(cin,b);

  K.div(r,a,b);
  K.write(cout,r) << "\n";

  return 0;
};
<commit_msg>*** empty log message ***<commit_after>// =========================================================
// (C) The Linbox Group 1999   Examples for using fields
// Fri Feb  8 14:10:35 MET 2002 / Gilles Villard
// =========================================================

// ---------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
// ---------------------------------------------

#include "LinBox/gmp-rational-field.C"
#include "LinBox/unparam_field.h"
#include "LinBox/param_modular.h"

using namespace LinBox;

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

int main() {

  /*  Use of LinBox basic field capabilities.
   *  A concrete field will be a domain (an object)
   *  with a given type that one may choose between
      LinBox kernel capabilities :
   */

  //typedef GMP_Rational_Field  Field;     // Rational numbers based on Gmp
  //typedef unparam_field<double> Field;   // Or the doubles via the LinBox interface

  typedef param_modular Field;             // Or the % on the integers for a mod p field

  /* Once this type "Field" is chosen, a domain K is declared */

  //Field K;
  Field K(7);  /* If choice of the modular field, modulo 7 */

  /* The element of "K" are addressed using the type "Field::element" */

  Field::element a,b,r;

  /* "a" and "b" elements of K, initialized, read from
   * std input, divided, written on std output
   */

  K.init(a); K.init(b); K.init(r);
  K.read(cin,a);  K.read(cin,b);

  K.div(r,a,b);
  K.write(cout,r) << "\n";

  return 0;
};
<|endoftext|>


<commit_before>#include <stdio.h>
void main()
{

}<commit_msg>#include 삭제.<commit_after>void main()
{

}<|endoftext|>


<commit_before>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

// SDL2 Bitmap implementation

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"

#include "PLT/Bitmap.h"

namespace PLT {

//! Memory image buffer
class Bitmap::Impl : public Image
{
public:
   Impl(unsigned width, unsigned height)
   {
      surface = SDL_CreateRGBSurface(0, width, height, 32,
                                     0x00FF0000,
                                     0x0000FF00,
                                     0x000000FF,
                                     0xFF000000);
   }

   Impl(const char* filename)
   {
      surface = IMG_Load(filename);
      if (surface == nullptr)
      {
         fprintf(stderr, "Failed to open file '%s'\n", filename);
      }
   }

   ~Impl()
   {
      SDL_FreeSurface(surface);
   }

   void getSize(unsigned& width, unsigned& height)
   {
      if (surface != nullptr)
      {
         width  = surface->w;
         height = surface->h;
      }
      else
      {
         width  = 0;
         height = 0;
      }
   }

   uint8_t* getStorage(unsigned& pitch)
   {
      if(surface == nullptr) return nullptr;

      pitch = surface->pitch;
      return (uint8_t*)surface->pixels;
   }

   virtual void* getHandle() const override
   {
      return surface;
   }

private:
   SDL_Surface*   surface{nullptr};
};

Bitmap::Bitmap(unsigned width_, unsigned height_)
   : Image(width_, height_)
{
   pimpl = new Impl(width_, height_);

   buffer = pimpl->getStorage(pitch);
}

Bitmap::Bitmap(const char* filename_)
{
   pimpl  = new Impl(filename_);

   pimpl->getSize(width, height);
   buffer = pimpl->getStorage(pitch);
}

Bitmap::~Bitmap()
{
   delete pimpl;
}

void* Bitmap::getHandle() const
{
   return pimpl->getHandle();
}

} // namespace PLT
<commit_msg>Fix SDL2 image load RGB format issues<commit_after>//------------------------------------------------------------------------------
// Copyright (c) 2016 John D. Haughton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//------------------------------------------------------------------------------

// SDL2 Bitmap implementation

#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"

#include "PLT/Bitmap.h"

namespace PLT {

//! Memory image buffer
class Bitmap::Impl : public Image
{
public:
   Impl(unsigned width, unsigned height)
   {
      surface = SDL_CreateRGBSurface(0, width, height, 32,
                                     0x00FF0000,
                                     0x0000FF00,
                                     0x000000FF,
                                     0xFF000000);
   }

   Impl(const char* filename)
   {
      SDL_Surface* image_surface = IMG_Load(filename);
      if (image_surface == nullptr)
      {
         fprintf(stderr, "Failed to open file '%s'\n", filename);
      }
      else
      {
         surface = SDL_ConvertSurfaceFormat(image_surface,
                                            SDL_PIXELFORMAT_BGRA32,
                                            /* not used */ 0);

         SDL_FreeSurface(image_surface);
      }
   }

   ~Impl()
   {
      SDL_FreeSurface(surface);
   }

   void getSize(unsigned& width, unsigned& height)
   {
      if (surface != nullptr)
      {
         width  = surface->w;
         height = surface->h;
      }
      else
      {
         width  = 0;
         height = 0;
      }
   }

   uint8_t* getStorage(unsigned& pitch)
   {
      if(surface == nullptr) return nullptr;

      pitch = surface->pitch;
      return (uint8_t*)surface->pixels;
   }

   virtual void* getHandle() const override
   {
      return surface;
   }

private:
   SDL_Surface*   surface{nullptr};
};

Bitmap::Bitmap(unsigned width_, unsigned height_)
   : Image(width_, height_)
{
   pimpl = new Impl(width_, height_);

   buffer = pimpl->getStorage(pitch);
}

Bitmap::Bitmap(const char* filename_)
{
   pimpl  = new Impl(filename_);

   pimpl->getSize(width, height);
   buffer = pimpl->getStorage(pitch);
}

Bitmap::~Bitmap()
{
   delete pimpl;
}

void* Bitmap::getHandle() const
{
   return pimpl->getHandle();
}

} // namespace PLT
<|endoftext|>


<commit_before>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>

#include "fnord-base/exception.h"
#include "fnord-base/inspect.h"
#include "fnord-base/net/tcpserver.h"

namespace fnord {
namespace net {

TCPServer::TCPServer(
    TaskScheduler* scheduler) :
    scheduler_(scheduler),
    on_connection_cb_(nullptr) {}

void TCPServer::onConnection(
    std::function<void (std::unique_ptr<TCPConnection>)> callback) {
  on_connection_cb_ = callback;
}

void TCPServer::accept() {
  int conn_fd = ::accept(ssock_, NULL, NULL);

  if (conn_fd < 0) {
    RAISE_ERRNO(kIOError, "accept() failed");
  }

  if (on_connection_cb_) {
    scheduler_->run([this, conn_fd] () {
      on_connection_cb_(
          std::unique_ptr<TCPConnection>(new TCPConnection(conn_fd)));
    });
  }

  scheduler_->runOnReadable(std::bind(&TCPServer::accept, this), ssock_);
}

void TCPServer::listen(int port) {
  ssock_ = socket(AF_INET, SOCK_STREAM, 0);
  if (ssock_ == 0) {
    RAISE_ERRNO(kIOError, "create socket() failed");
  }

  int opt = 1;
  if (setsockopt(ssock_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
    RAISE_ERRNO(kIOError, "setsockopt(SO_REUSEADDR) failed");
    return;
  }

  int flags = fcntl(ssock_, F_GETFL, 0);
  flags = flags | O_NONBLOCK;

  if (fcntl(ssock_, F_SETFL, flags) != 0) {
    RAISE_ERRNO(kIOError, "fnctl(%i) failed", ssock_);
  }

  struct sockaddr_in addr;
  memset((char *) &addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(port);
  if (::bind(ssock_, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    RAISE_ERRNO(kIOError, "bind() failed");
  }

  if (::listen(ssock_, 1024) == -1) {
    RAISE_ERRNO(kIOError, "listen() failed");
  }

  scheduler_->runOnReadable(std::bind(&TCPServer::accept, this), ssock_);
}

}
}
<commit_msg>allow SO_REUSEPORT<commit_after>/**
 * This file is part of the "FnordMetric" project
 *   Copyright (c) 2014 Paul Asmuth, Google Inc.
 *
 * FnordMetric is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <unistd.h>

#include "fnord-base/exception.h"
#include "fnord-base/inspect.h"
#include "fnord-base/net/tcpserver.h"

namespace fnord {
namespace net {

TCPServer::TCPServer(
    TaskScheduler* scheduler) :
    scheduler_(scheduler),
    on_connection_cb_(nullptr) {}

void TCPServer::onConnection(
    std::function<void (std::unique_ptr<TCPConnection>)> callback) {
  on_connection_cb_ = callback;
}

void TCPServer::accept() {
  int conn_fd = ::accept(ssock_, NULL, NULL);

  if (conn_fd < 0) {
    RAISE_ERRNO(kIOError, "accept() failed");
  }

  if (on_connection_cb_) {
    scheduler_->run([this, conn_fd] () {
      on_connection_cb_(
          std::unique_ptr<TCPConnection>(new TCPConnection(conn_fd)));
    });
  }

  scheduler_->runOnReadable(std::bind(&TCPServer::accept, this), ssock_);
}

void TCPServer::listen(int port) {
  ssock_ = socket(AF_INET, SOCK_STREAM, 0);
  if (ssock_ == 0) {
    RAISE_ERRNO(kIOError, "create socket() failed");
  }

  int opt = 1;
  if (setsockopt(ssock_, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0) {
    RAISE_ERRNO(kIOError, "setsockopt(SO_REUSEADDR) failed");
    return;
  }

  opt = 1;
  if (setsockopt(ssock_, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)) < 0) {
    RAISE_ERRNO(kIOError, "setsockopt(SO_REUSEPORT) failed");
    return;
  }

  int flags = fcntl(ssock_, F_GETFL, 0);
  flags = flags | O_NONBLOCK;

  if (fcntl(ssock_, F_SETFL, flags) != 0) {
    RAISE_ERRNO(kIOError, "fnctl(%i) failed", ssock_);
  }

  struct sockaddr_in addr;
  memset((char *) &addr, 0, sizeof(addr));
  addr.sin_family = AF_INET;
  addr.sin_addr.s_addr = htonl(INADDR_ANY);
  addr.sin_port = htons(port);
  if (::bind(ssock_, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
    RAISE_ERRNO(kIOError, "bind() failed");
  }

  if (::listen(ssock_, 1024) == -1) {
    RAISE_ERRNO(kIOError, "listen() failed");
  }

  scheduler_->runOnReadable(std::bind(&TCPServer::accept, this), ssock_);
}

}
}
<|endoftext|>


<commit_before>#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QMessageAuthenticationCode>
#include <QCryptographicHash>
#include <QTimer>

#include "userstream.h"
#include "update_name_oauth.h"

UserStream::UserStream(QObject *parent) :
    QThread(parent)
{
    isStopped = true;
}

UserStream::~UserStream()
{
    //reply->deleteLater();
}

void UserStream::run()
{
    const QByteArray signatureKey = settings.consumerSecret().toUtf8()
            .append("&")
            .append(settings.accessTokenSecret().toUtf8());

    QVariantMap oauthParams;
    QUrlQuery   oauthQuery;
    QByteArray  signatureBaseString;
    QByteArray  oauthHeader;
    QNetworkRequest request;
    QNetworkAccessManager manager;
    QByteArray response;
    QByteArray buffer;
    QNetworkReply *reply;
    QEventLoop  loop;
    QTimer timer;
    bool connected = false;
    int failedCount = 0;

    isStopped = false;

    while(!isStopped && failedCount <= 5) {
        emit stateChanged(Connecting);

        oauthParams.clear();
        oauthParams["oauth_consumer_key"]     = settings.consumerKey();
        oauthParams["oauth_token"]            = settings.accessToken();
        oauthParams["oauth_signature_method"] = OAUTH_SIGNATURE_METHOD;
        oauthParams["oauth_timestamp"]        = OAUTH_TIMESTAMP;
        oauthParams["oauth_nonce"]            = OAUTH_NONCE;
        oauthParams["oauth_version"]          = OAUTH_VERSION;

        oauthQuery.clear();
        for(int i = 0; i < oauthParams.size(); i++) {
            oauthQuery.addQueryItem(oauthParams.keys()[i], oauthParams.values()[i].toString());
        }

        signatureBaseString.clear();
        signatureBaseString.append("GET&")
                .append(USERSTREAM_URL.toUtf8().toPercentEncoding())
                .append("&")
                .append(oauthQuery.toString().toUtf8().toPercentEncoding());

        oauthParams["oauth_signature"] =
                QMessageAuthenticationCode::hash(signatureBaseString,
                                                 signatureKey,
                                                 QCryptographicHash::Sha1).toBase64().toPercentEncoding();

        oauthHeader.clear();
        oauthHeader.append("OAuth ");
        for(int i = 0; i < oauthParams.size(); i++) {
            oauthHeader.append(oauthParams.keys()[i])
                    .append("=\"")
                    .append(oauthParams.values()[i].toByteArray())
                    .append("\", ");
        }
        oauthHeader.chop(2);

        request.setUrl(QUrl(USERSTREAM_URL));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        request.setRawHeader("Authorization", oauthHeader);

        reply = manager.get(request);

        connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit()));
        connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
        connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

        timer.setSingleShot(true);

        buffer.clear();

        while(!reply->isFinished() && !isStopped && reply->error() == QNetworkReply::NoError) {
            timer.start(60000);
            loop.exec();

            if(reply->error() == QNetworkReply::NoError && timer.isActive()) {
                if(!connected) {
                    emit stateChanged(Running);
                    connected = true;
                    failedCount = 0;
                }
                response = reply->readAll();

                qDebug() << "response" << response;

                if(response.indexOf("\r") > 0) {
                    if(!buffer.isEmpty()) {
                        response.prepend(QString::fromUtf8(buffer).split("\r").first().toUtf8());
                    buffer.replace(QString::fromUtf8(buffer).split("\r").first().toUtf8(), "");
                    }
                    emit receivedData(response);
                } else if(response.indexOf("\r") == -1) {
                    buffer.append(response);
                }
            } else {
                emit stateChanged(ConnectionFailed);
                qCritical() << reply->errorString();
                failedCount++;
                break;
            }
        }
        emit stateChanged(DisConnected);
        connected = false;

        if(failedCount <= 5) {
            qWarning() << "再接続まで5秒待機します。";
            sleep(5);
        } else {
            break;
        }
    }

    reply->deleteLater();

    emit finished();
}

void UserStream::stop()
{
    isStopped = true;
}
<commit_msg>デバッグメッセージ無効化<commit_after>#include <QUrlQuery>
#include <QNetworkRequest>
#include <QNetworkAccessManager>
#include <QMessageAuthenticationCode>
#include <QCryptographicHash>
#include <QTimer>

#include "userstream.h"
#include "update_name_oauth.h"

UserStream::UserStream(QObject *parent) :
    QThread(parent)
{
    isStopped = true;
}

UserStream::~UserStream()
{
    //reply->deleteLater();
}

void UserStream::run()
{
    const QByteArray signatureKey = settings.consumerSecret().toUtf8()
            .append("&")
            .append(settings.accessTokenSecret().toUtf8());

    QVariantMap oauthParams;
    QUrlQuery   oauthQuery;
    QByteArray  signatureBaseString;
    QByteArray  oauthHeader;
    QNetworkRequest request;
    QNetworkAccessManager manager;
    QByteArray response;
    QByteArray buffer;
    QNetworkReply *reply;
    QEventLoop  loop;
    QTimer timer;
    bool connected = false;
    int failedCount = 0;

    isStopped = false;

    while(!isStopped && failedCount <= 5) {
        emit stateChanged(Connecting);

        oauthParams.clear();
        oauthParams["oauth_consumer_key"]     = settings.consumerKey();
        oauthParams["oauth_token"]            = settings.accessToken();
        oauthParams["oauth_signature_method"] = OAUTH_SIGNATURE_METHOD;
        oauthParams["oauth_timestamp"]        = OAUTH_TIMESTAMP;
        oauthParams["oauth_nonce"]            = OAUTH_NONCE;
        oauthParams["oauth_version"]          = OAUTH_VERSION;

        oauthQuery.clear();
        for(int i = 0; i < oauthParams.size(); i++) {
            oauthQuery.addQueryItem(oauthParams.keys()[i], oauthParams.values()[i].toString());
        }

        signatureBaseString.clear();
        signatureBaseString.append("GET&")
                .append(USERSTREAM_URL.toUtf8().toPercentEncoding())
                .append("&")
                .append(oauthQuery.toString().toUtf8().toPercentEncoding());

        oauthParams["oauth_signature"] =
                QMessageAuthenticationCode::hash(signatureBaseString,
                                                 signatureKey,
                                                 QCryptographicHash::Sha1).toBase64().toPercentEncoding();

        oauthHeader.clear();
        oauthHeader.append("OAuth ");
        for(int i = 0; i < oauthParams.size(); i++) {
            oauthHeader.append(oauthParams.keys()[i])
                    .append("=\"")
                    .append(oauthParams.values()[i].toByteArray())
                    .append("\", ");
        }
        oauthHeader.chop(2);

        request.setUrl(QUrl(USERSTREAM_URL));
        request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
        request.setRawHeader("Authorization", oauthHeader);

        reply = manager.get(request);

        connect(reply, SIGNAL(readyRead()), &loop, SLOT(quit()));
        connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
        connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
        connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));

        timer.setSingleShot(true);

        buffer.clear();

        while(!reply->isFinished() && !isStopped && reply->error() == QNetworkReply::NoError) {
            timer.start(60000);
            loop.exec();

            if(reply->error() == QNetworkReply::NoError && timer.isActive()) {
                if(!connected) {
                    emit stateChanged(Running);
                    connected = true;
                    failedCount = 0;
                }
                response = reply->readAll();

                //qDebug() << "response" << response;

                if(response.indexOf("\r") > 0) {
                    if(!buffer.isEmpty()) {
                        response.prepend(QString::fromUtf8(buffer).split("\r").first().toUtf8());
                    buffer.replace(QString::fromUtf8(buffer).split("\r").first().toUtf8(), "");
                    }
                    emit receivedData(response);
                } else if(response.indexOf("\r") == -1) {
                    buffer.append(response);
                }
            } else {
                emit stateChanged(ConnectionFailed);
                //qCritical() << reply->errorString();
                failedCount++;
                break;
            }
        }
        emit stateChanged(DisConnected);
        connected = false;

        if(failedCount <= 5) {
            qWarning() << "再接続まで5秒待機します。";
            sleep(5);
        } else {
            break;
        }
    }

    reply->deleteLater();

    emit finished();
}

void UserStream::stop()
{
    isStopped = true;
}
<|endoftext|>


<commit_before>#include <Share.h>

#include <bps/event.h>
#include <bps/navigator.h>
#include <bps/navigator_invoke.h>
#include <screen/screen.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>

using namespace std;

namespace openflShareExtension {

	void log(const char *msg) {
		/*
		FILE *logFile = fopen("logs/log.txt", "a");
		fprintf(logFile, "%s\n", msg);
		fclose(logFile);
		*/
	}

	void doShare(const char *method, const char *text) {

		navigator_invoke_invocation_t *invoke = NULL;
		navigator_invoke_invocation_create(&invoke);

		navigator_invoke_invocation_set_action(invoke, "bb.action.SHARE");
		navigator_invoke_invocation_set_data(invoke, text, strlen(text));
		navigator_invoke_invocation_set_target(invoke, method);
		navigator_invoke_invocation_set_type(invoke, "text/plain");

		navigator_invoke_invocation_send(invoke);
		navigator_invoke_invocation_destroy(invoke);

	}

	vector<ShareQueryResult> query() {

		/*
		FILE *logFile = fopen("logs/log.txt", "w");
		fclose(logFile);
		char msg[64];
		*/

		/*
		snprintf(msg, 64, "pid %d\n", getpid());
		log(msg);
		*/

		vector<ShareQueryResult> results;

		navigator_invoke_query_t *query = NULL;
		navigator_invoke_query_create(&query);

		navigator_invoke_query_set_id(query, "12345");
		navigator_invoke_query_set_action(query, "bb.action.SHARE");
		navigator_invoke_query_set_type(query, "text/plain");

		if (navigator_invoke_query_send(query)!=BPS_SUCCESS) {
			log("navigator_invoke_query_send Failed");
		}

		bps_event_t *event = NULL;

		do {

			bps_get_event(&event, -1);
			/*
			snprintf(msg, 64, "query result %#04x\n", bps_event_get_code(event));
			log(msg);
			*/
		} while (

			navigator_get_domain()!=bps_event_get_domain(event) ||
			bps_event_get_code(event)!=NAVIGATOR_INVOKE_QUERY_RESULT

		);

		// create integer holding the number of actions returned by the query
		int action_count =
			navigator_invoke_event_get_query_result_action_count(event);

		// loop listing all actions returned by the query
		for (int i=0; i<action_count; i++) {

			const navigator_invoke_query_result_action_t *action =
				navigator_invoke_event_get_query_result_action(event, i);

			// retrieve action attributes
			const char *name =
				navigator_invoke_query_result_action_get_name(action);
			const char *icon =
				navigator_invoke_query_result_action_get_icon(action);
			const char *label =
				navigator_invoke_query_result_action_get_label(action);

			// create integer holding the number of targets in the action
			int target_count =
				navigator_invoke_query_result_action_get_target_count(action);

			// loop listing all targets in the action
			for (int j=0; j < target_count; j++) {

				const navigator_invoke_query_result_target_t *target =
					navigator_invoke_query_result_action_get_target(action, j);

				if (target==NULL) {
					log("target is null!");
				}

				// retrieve target attributes
				ShareQueryResult result;

				const char *key =
					navigator_invoke_query_result_target_get_key(target);
				const char *icon =
					navigator_invoke_query_result_target_get_icon(target);
				const char *label =
					navigator_invoke_query_result_target_get_label(target);

				strcpy(result.key, key);
				strcpy(result.icon, icon);
				strcpy(result.label, label);

				results.push_back(result);

			}

		}

		navigator_invoke_query_destroy(query);

		return results;

	}

}
<commit_msg>Update Share.cpp<commit_after>#include <Share.h>

#include <bps/event.h>
#include <bps/navigator.h>
//#include <bps/navigator_invoke.h>
#include <screen/screen.h>
#include <string.h>
#include <string>
#include <unistd.h>
#include <vector>

using namespace std;

namespace openflShareExtension {

	void log(const char *msg) {
		/*
		FILE *logFile = fopen("logs/log.txt", "a");
		fprintf(logFile, "%s\n", msg);
		fclose(logFile);
		*/
	}

	void doShare(const char *method, const char *text) {

		navigator_invoke_invocation_t *invoke = NULL;
		navigator_invoke_invocation_create(&invoke);

		navigator_invoke_invocation_set_action(invoke, "bb.action.SHARE");
		navigator_invoke_invocation_set_data(invoke, text, strlen(text));
		navigator_invoke_invocation_set_target(invoke, method);
		navigator_invoke_invocation_set_type(invoke, "text/plain");

		navigator_invoke_invocation_send(invoke);
		navigator_invoke_invocation_destroy(invoke);

	}

	vector<ShareQueryResult> query() {

		/*
		FILE *logFile = fopen("logs/log.txt", "w");
		fclose(logFile);
		char msg[64];
		*/

		/*
		snprintf(msg, 64, "pid %d\n", getpid());
		log(msg);
		*/

		vector<ShareQueryResult> results;

		navigator_invoke_query_t *query = NULL;
		navigator_invoke_query_create(&query);

		navigator_invoke_query_set_id(query, "12345");
		navigator_invoke_query_set_action(query, "bb.action.SHARE");
		navigator_invoke_query_set_type(query, "text/plain");

		if (navigator_invoke_query_send(query)!=BPS_SUCCESS) {
			log("navigator_invoke_query_send Failed");
		}

		bps_event_t *event = NULL;

		do {

			bps_get_event(&event, -1);
			/*
			snprintf(msg, 64, "query result %#04x\n", bps_event_get_code(event));
			log(msg);
			*/
		} while (

			navigator_get_domain()!=bps_event_get_domain(event) ||
			bps_event_get_code(event)!=NAVIGATOR_INVOKE_QUERY_RESULT

		);

		// create integer holding the number of actions returned by the query
		int action_count =
			navigator_invoke_event_get_query_result_action_count(event);

		// loop listing all actions returned by the query
		for (int i=0; i<action_count; i++) {

			const navigator_invoke_query_result_action_t *action =
				navigator_invoke_event_get_query_result_action(event, i);

			// retrieve action attributes
			const char *name =
				navigator_invoke_query_result_action_get_name(action);
			const char *icon =
				navigator_invoke_query_result_action_get_icon(action);
			const char *label =
				navigator_invoke_query_result_action_get_label(action);

			// create integer holding the number of targets in the action
			int target_count =
				navigator_invoke_query_result_action_get_target_count(action);

			// loop listing all targets in the action
			for (int j=0; j < target_count; j++) {

				const navigator_invoke_query_result_target_t *target =
					navigator_invoke_query_result_action_get_target(action, j);

				if (target==NULL) {
					log("target is null!");
				}

				// retrieve target attributes
				ShareQueryResult result;

				const char *key =
					navigator_invoke_query_result_target_get_key(target);
				const char *icon =
					navigator_invoke_query_result_target_get_icon(target);
				const char *label =
					navigator_invoke_query_result_target_get_label(target);

				strcpy(result.key, key);
				strcpy(result.icon, icon);
				strcpy(result.label, label);

				results.push_back(result);

			}

		}

		navigator_invoke_query_destroy(query);

		return results;

	}

}
<|endoftext|>


<commit_before>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "serializer/merger.hpp"

#include "errors.hpp"

#include "serializer/types.hpp"
#include "arch/runtime/coroutines.hpp"
#include "config/args.hpp"

merger_serializer_t::merger_serializer_t(serializer_t *_inner, int _max_active_writes) :
    inner(_inner),
    index_writes_io_account(make_io_account(MERGED_INDEX_WRITE_IO_PRIORITY)),
    num_active_writes(0),
    max_active_writes(_max_active_writes) {
}

merger_serializer_t::~merger_serializer_t() {
    assert_thread();
    rassert(num_active_writes == 0);
    rassert(outstanding_index_writes.empty());

    delete index_writes_io_account;
    delete inner;
}

void merger_serializer_t::index_write(const std::vector<index_write_op_t>& write_ops, file_account_t *) {
    rassert(coro_t::self() != NULL);
    assert_thread();

    std::shared_ptr<cond_t> write_complete;
    {
        // Our set of write ops must be processed atomically...
        ASSERT_NO_CORO_WAITING;
        for (auto op = write_ops.begin(); op != write_ops.end(); ++op) {
            push_index_write(*op);
        }
        // ... and we also take a copy of the on_index_writes_complete signal
        // so we get notified exactly when all of our write ops have
        // been completed.
        write_complete = on_index_writes_complete;
    }

    // Check if we can initiate a new index write
    if (num_active_writes < max_active_writes) {
        do_index_write();
    }

    // Wait for the write to complete
    write_complete->wait_lazily_unordered();
}

void merger_serializer_t::do_index_write() {
    assert_thread();
    rassert(num_active_writes < max_active_writes);

    ++num_active_writes;

    // Assemble the currently outstanding index writes into
    // a vector of index_write_op_t-s.
    std::shared_ptr<cond_t> write_complete;
    std::vector<index_write_op_t> write_ops;
    write_ops.reserve(outstanding_index_writes.size());
    {
        ASSERT_NO_CORO_WAITING;
        for (auto op_pair = outstanding_index_writes.begin(); op_pair != outstanding_index_writes.end(); ++op_pair) {
            write_ops.push_back(op_pair->second);
        }
        outstanding_index_writes.clear();

        // Swap out the on_index_writes_complete signal so subsequent index
        // writes can be captured by the next round of do_index_write().
        write_complete = on_index_writes_complete;
        on_index_writes_complete.reset(new cond_t());
    }

    inner->index_write(write_ops, index_writes_io_account);

    write_complete->pulse();

    --num_active_writes;

    // Check if we should start another index write
    if (num_active_writes < max_active_writes && !outstanding_index_writes.empty()) {
        coro_t::spawn_sometime(std::bind(&merger_serializer_t::do_index_write, this));
    }
}

void merger_serializer_t::merge_index_write(const index_write_op_t &to_be_merged, index_write_op_t *into_out) const {
    rassert(to_be_merged.block_id == into_out->block_id);
    if (to_be_merged.token.is_initialized()) {
        into_out->token = to_be_merged.token;
    }
    if (to_be_merged.recency.is_initialized()) {
        into_out->recency = to_be_merged.recency;
    }
}

void merger_serializer_t::push_index_write(const index_write_op_t &op) {
    auto existing_it = outstanding_index_writes.find(op.block_id);
    if (existing_it != outstanding_index_writes.end()) {
        merge_index_write(op, &existing_it->second);
    } else {
        outstanding_index_writes.insert(std::pair<block_id_t, index_write_op_t>(op.block_id, op));
    }
}

<commit_msg>Missing initialization<commit_after>// Copyright 2010-2013 RethinkDB, all rights reserved.
#include "serializer/merger.hpp"

#include "errors.hpp"

#include "serializer/types.hpp"
#include "arch/runtime/coroutines.hpp"
#include "config/args.hpp"

merger_serializer_t::merger_serializer_t(serializer_t *_inner, int _max_active_writes) :
    inner(_inner),
    index_writes_io_account(make_io_account(MERGED_INDEX_WRITE_IO_PRIORITY)),
    on_index_writes_complete(new cond_t()),
    num_active_writes(0),
    max_active_writes(_max_active_writes) {
}

merger_serializer_t::~merger_serializer_t() {
    assert_thread();
    rassert(num_active_writes == 0);
    rassert(outstanding_index_writes.empty());

    delete index_writes_io_account;
    delete inner;
}

void merger_serializer_t::index_write(const std::vector<index_write_op_t>& write_ops, file_account_t *) {
    rassert(coro_t::self() != NULL);
    assert_thread();

    std::shared_ptr<cond_t> write_complete;
    {
        // Our set of write ops must be processed atomically...
        ASSERT_NO_CORO_WAITING;
        for (auto op = write_ops.begin(); op != write_ops.end(); ++op) {
            push_index_write(*op);
        }
        // ... and we also take a copy of the on_index_writes_complete signal
        // so we get notified exactly when all of our write ops have
        // been completed.
        write_complete = on_index_writes_complete;
    }

    // Check if we can initiate a new index write
    if (num_active_writes < max_active_writes) {
        do_index_write();
    }

    // Wait for the write to complete
    write_complete->wait_lazily_unordered();
}

void merger_serializer_t::do_index_write() {
    assert_thread();
    rassert(num_active_writes < max_active_writes);

    ++num_active_writes;

    // Assemble the currently outstanding index writes into
    // a vector of index_write_op_t-s.
    std::shared_ptr<cond_t> write_complete;
    std::vector<index_write_op_t> write_ops;
    write_ops.reserve(outstanding_index_writes.size());
    {
        ASSERT_NO_CORO_WAITING;
        for (auto op_pair = outstanding_index_writes.begin(); op_pair != outstanding_index_writes.end(); ++op_pair) {
            write_ops.push_back(op_pair->second);
        }
        outstanding_index_writes.clear();

        // Swap out the on_index_writes_complete signal so subsequent index
        // writes can be captured by the next round of do_index_write().
        write_complete = on_index_writes_complete;
        on_index_writes_complete.reset(new cond_t());
    }

    inner->index_write(write_ops, index_writes_io_account);

    write_complete->pulse();

    --num_active_writes;

    // Check if we should start another index write
    if (num_active_writes < max_active_writes && !outstanding_index_writes.empty()) {
        coro_t::spawn_sometime(std::bind(&merger_serializer_t::do_index_write, this));
    }
}

void merger_serializer_t::merge_index_write(const index_write_op_t &to_be_merged, index_write_op_t *into_out) const {
    rassert(to_be_merged.block_id == into_out->block_id);
    if (to_be_merged.token.is_initialized()) {
        into_out->token = to_be_merged.token;
    }
    if (to_be_merged.recency.is_initialized()) {
        into_out->recency = to_be_merged.recency;
    }
}

void merger_serializer_t::push_index_write(const index_write_op_t &op) {
    auto existing_it = outstanding_index_writes.find(op.block_id);
    if (existing_it != outstanding_index_writes.end()) {
        merge_index_write(op, &existing_it->second);
    } else {
        outstanding_index_writes.insert(std::pair<block_id_t, index_write_op_t>(op.block_id, op));
    }
}

<|endoftext|>