<commit_before>#include "fluidsystem.h"
#include "camera.h"
#include "vertexrecorder.h"
#include <iostream>
#include <math.h>
#include <algorithm>    // std::max
#include "particle.h"
#include "wall.h"

using namespace std;

 // your system should at least contain 8x8 particles.
const int N = 5;

const float PARTICLE_RADIUS = .015;
const float PARTICLE_SPACING = .0225;

const float H = 0.03;//.0457;
const float Hsquared = H*H;
const float Hfouth = Hsquared*Hsquared;
const float mu = .35;//0.001;

const float SPRING_CONSTANT = 5; // N/m
const float PARTICLE_MASS = 0.02;//.03; // kg
const float GRAVITY = 9.8; // m/s
const float DRAG_CONSTANT = .05;

const float WALL_K = 100.0; // wall spring constant
const float WALL_DAMPING = -0.15; // wall damping constant

float WPoly6(Vector3f R);
Vector3f WSpiky(Vector3f R);
float WViscosity(Vector3f R);

FluidSystem::FluidSystem()
{
    // change box size - make sure this is the same as in main.cpp
    float len = 0.1;
    // back, front, left, right, bottom - respectively
    _walls.push_back(Wall(Vector3f(0,-len/2,-len), Vector3f(0,0,1)));
    _walls.push_back(Wall(Vector3f(0,-len/2,len), Vector3f(0,0,-1)));
    _walls.push_back(Wall(Vector3f(-len,-len/2,0), Vector3f(1,0,0)));
    _walls.push_back(Wall(Vector3f(len,-len/2,0), Vector3f(-1,0,0)));
    _walls.push_back(Wall(Vector3f(0,-len,0), Vector3f(0,1,0)));

    // Initialize m_vVecState with fluid particles.
    // You can again use rand_uniform(lo, hi) to make things a bit more interesting
    m_vVecState.clear();
    int particleCount = 0;
    for (unsigned i = 0; i < N; i++){
        for (unsigned j = 0; j< N; j++){
            for (unsigned l = 0; l < N; l++){
                float x = -len + i*PARTICLE_SPACING;
                float y = 0.2 + -len + j*PARTICLE_SPACING;
                float z = -len + l*PARTICLE_SPACING;
                // particles evenly spaced
                Vector3f position = Vector3f(x, y, z);
                // all particles stationary
                // Vector3f velocity = Vector3f( rand_uniform(-1,  1), 0, rand_uniform( -1, 1));
                Vector3f velocity = Vector3f(0);

                Particle particle = Particle(particleCount, position, velocity);
                m_vVecState.push_back(particle);
                particleCount += 1;
            }
        }
    }
}

std::vector<Particle> FluidSystem::evalF(std::vector<Particle> state)
{

    std::vector<Particle> f;
    // FLuid Particles undergo the following forces:
    // - gravity
    // - collision forces
    // - viscous drag
    // - pressure
    // ---Below Not Implemented---
    // - surface tension

    // F = mg  -> GRAVITY
    // ----------------------------------------
    float gForce = PARTICLE_MASS*GRAVITY;
    // only in the y-direction
    Vector3f gravityForce = Vector3f(0,-gForce, 0);
    // ----------------------------------------

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle& particle = state[i];
        Vector3f position = particle.getPosition();
        Vector3f velocity = particle.getVelocity();
        // compute density of every particle first
        double density_i = 0;
        for (unsigned j = 0; j < state.size(); j+=1) {
            if (j != i) {
                Particle particle_j = state[j];

                Vector3f delta = position - particle_j.getPosition();
                if (delta.absSquared() < H*H) {
                    density_i += WPoly6(delta);
                    // cout << WPoly6(delta) << endl;
                }
            }
        }
        particle.density() = PARTICLE_MASS*density_i;
        // cout << density_i << endl;

    }

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle particle = state[i];
        Vector3f position = particle.getPosition();
        Vector3f velocity = particle.getVelocity();
        double density = particle.density();
        float pressure = particle.getPressure();

        // compute updated density and gradient of pressure
        // based on all other particles
        Vector3f f_pressure;
        Vector3f f_viscosity;
        for (unsigned j = 0; j < state.size(); j+=1) {
            if (j != i) {
                Particle particle_j = state[j];

                Vector3f delta = position - particle_j.getPosition() + Vector3f(2 * PARTICLE_RADIUS);
                // cout << "delta" << delta.x() << ","<< delta.y() << ","<< delta.z() << endl;
                if (delta.absSquared() < H*H) {
                    //  ---------------gradient of pressure computation-----------------

                    // sample implementation value: pi/roi2 + pj/roj2
                    float p_factor = (pressure/(density*density)) + (particle_j.getPressure()/(particle_j.density()*particle_j.density()));

                    // Mueller value: (pi + pj) / 2roj
                    // float p_factor = (pressure+particle_j.getPressure()) / (2*particle_j.getDensity());

                    // Lecture video value: pi/roi + pj/roj
                    // float p_factor = pressure/density + particle_j.getPressure()/particle_j.getDensity();
                    // (WSpiky(delta)).print();
                    // delta.print();
                    f_pressure += p_factor*WSpiky(delta);
                    //  ---------------viscosity computation-----------------
                    float kernel_distance_viscosity = H-delta.abs();

                    Vector3f v_factor = (particle_j.getVelocity() - velocity) / particle_j.getDensity();

                    Vector3f viscosity_term = PARTICLE_MASS*WViscosity(delta)/ particle_j.getDensity()*v_factor;
                    // cout << "delta " << kernel_constant_pressure << endl;
                    // viscosity_term.print();
                    f_viscosity += viscosity_term;
                    // velocity.print();
                }
            }
        }

        f_pressure *= PARTICLE_MASS;
        f_viscosity *= mu * PARTICLE_MASS;

        // Total Force
        // Vector3f totalForce = (gravityForce +(mu*f_viscosity) + f_pressure)/density;
        // f_pressure.print();
        // cout << density << endl;
        Vector3f f_collision = collisionForce(particle);

        // Total Force
        Vector3f totalForce = gravityForce + f_collision + f_viscosity*mu*0.0000;
        // Vector3f totalForce = gravityForce + f_collision ;//+ f_pressure;
        cout << "f_collision: " << f_collision.x() << ","<< f_collision.y() << ","<< f_collision.z() << endl;
        // cout << "f_pressure: " << f_pressure.x() << ","<< f_pressure.y() << ","<< f_pressure.z() << endl;
        // cout << "gravityForce: " << gravityForce.x() << ","<< gravityForce.y() << ","<< gravityForce.z() << endl;
        // totalForce.print();

        Vector3f acceleration = totalForce / PARTICLE_MASS;

        Particle newParticle = Particle(i, velocity, acceleration, density);
        f.push_back(newParticle);
    }

    return f;
}

float WPoly6(Vector3f R){
    float constant_term = 315.0 / (64.0 * M_PI * Hfouth * Hfouth * H);
    float factor = Hsquared - R.absSquared();
    float kernel_distance_density = factor * factor * factor;
    return kernel_distance_density*constant_term;
}

Vector3f WSpiky(Vector3f R){
    if (R.abs() < .000001){
        return Vector3f(0,0,0);
    }
    float constant_term = -45.0 / (M_PI * Hfouth * Hsquared);
    float factor = H - R.abs();
    Vector3f kernel_distance_pressure = factor * factor * R.normalized();
    return constant_term * kernel_distance_pressure;
}

float WViscosity(Vector3f R){
    float constant_term = 45.0 / (M_PI * Hfouth * Hsquared);
    float kernel_distance_viscosity = H-R.abs();
    return constant_term * kernel_distance_viscosity;
}

Vector3f FluidSystem::collisionForce(Particle particle) {
    Vector3f f_collision;
    for (unsigned int i = 0; i < _walls.size(); i++) {

        Wall wall = _walls[i];
        Vector3f wallNormal = wall.getNormal();
        double d = Vector3f::dot(wallNormal, (wall.getPoint() - particle.getPosition())) +  0.015; // particle radius
        if (d > 0.0) {
            f_collision += WALL_DAMPING * Vector3f::dot(wallNormal, particle.getVelocity()) * wallNormal + WALL_K * wallNormal * d;
        }
    }
    return f_collision;
}

void FluidSystem::draw(GLProgram& gl)
{
    //TODO 5: render the system
    //         - ie draw the particles as little spheres
    //         - or draw the springs as little lines or cylinders
    //         - or draw wireframe mesh

    const Vector3f blue(0.0f, 0.0f, 1.0f);

    // EXAMPLE for how to render cloth particles.
    //  - you should replace this code.
    // EXAMPLE: This shows you how to render lines to debug the spring system.
    //
    //          You should replace this code.
    //
    //          Since lines don't have a clearly defined normal, we can't use
    //          a regular lighting model.
    //          GLprogram has a "color only" mode, where illumination
    //          is disabled, and you specify color directly as vertex attribute.
    //          Note: enableLighting/disableLighting invalidates uniforms,
    //          so you'll have to update the transformation/material parameters
    //          after a mode change.
    gl.disableLighting();
    gl.updateModelMatrix(Matrix4f::identity()); // update uniforms after mode change
    // drawBox(Vector3f(0,0,0), 1);

    // not working :(
    gl.updateMaterial(blue);

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle p = m_vVecState[i];
        Vector3f pos = p.getPosition();
        gl.updateModelMatrix(Matrix4f::translation(pos));
        drawSphere(PARTICLE_RADIUS, 10, 4);
    }

    gl.enableLighting(); // reset to default lighting model
}

<commit_msg>stabilized?<commit_after>#include "fluidsystem.h"
#include "camera.h"
#include "vertexrecorder.h"
#include <iostream>
#include <math.h>
#include <algorithm>    // std::max
#include "particle.h"
#include "wall.h"

using namespace std;

 // your system should at least contain 8x8 particles.
const int N = 5;

const float PARTICLE_RADIUS = .015;
const float PARTICLE_SPACING = .0225;

const float H = 0.03;//.0457;
const float Hsquared = H*H;
const float Hfouth = Hsquared*Hsquared;
const float mu = .35;//0.001;

const float SPRING_CONSTANT = 5; // N/m
const float PARTICLE_MASS = 0.02;//.03; // kg
const float GRAVITY = 9.8; // m/s
const float DRAG_CONSTANT = .05;

const float WALL_K = 75.0; // wall spring constant
const float WALL_DAMPING = -0.0001; // wall damping constant

float WPoly6(Vector3f R);
Vector3f WSpiky(Vector3f R);
float WViscosity(Vector3f R);

FluidSystem::FluidSystem()
{
    // change box size - make sure this is the same as in main.cpp
    float len = 0.1;
    // back, front, left, right, bottom - respectively
    _walls.push_back(Wall(Vector3f(0,-len/2,-len), Vector3f(0,0,1)));
    _walls.push_back(Wall(Vector3f(0,-len/2,len), Vector3f(0,0,-1)));
    _walls.push_back(Wall(Vector3f(-len,-len/2,0), Vector3f(1,0,0)));
    _walls.push_back(Wall(Vector3f(len,-len/2,0), Vector3f(-1,0,0)));
    _walls.push_back(Wall(Vector3f(0,-len,0), Vector3f(0,1,0)));

    // Initialize m_vVecState with fluid particles.
    // You can again use rand_uniform(lo, hi) to make things a bit more interesting
    m_vVecState.clear();
    int particleCount = 0;
    for (unsigned i = 0; i < N; i++){
        for (unsigned j = 0; j< N; j++){
            for (unsigned l = 0; l < N; l++){
                float x = -len + i*PARTICLE_SPACING;
                float y = 0.05 + -len + j*PARTICLE_SPACING;
                float z = -len + l*PARTICLE_SPACING;
                // particles evenly spaced
                Vector3f position = Vector3f(x, y, z);
                // all particles stationary
                // Vector3f velocity = Vector3f( rand_uniform(-1,  1), 0, rand_uniform( -1, 1));
                Vector3f velocity = Vector3f(0);

                Particle particle = Particle(particleCount, position, velocity);
                m_vVecState.push_back(particle);
                particleCount += 1;
            }
        }
    }
}

std::vector<Particle> FluidSystem::evalF(std::vector<Particle> state)
{

    std::vector<Particle> f;
    // FLuid Particles undergo the following forces:
    // - gravity
    // - collision forces
    // - viscous drag
    // - pressure
    // ---Below Not Implemented---
    // - surface tension

    // F = mg  -> GRAVITY
    // ----------------------------------------
    float gForce = PARTICLE_MASS*GRAVITY;
    // only in the y-direction
    Vector3f gravityForce = Vector3f(0,-gForce, 0);
    // ----------------------------------------

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle& particle = state[i];
        Vector3f position = particle.getPosition();
        Vector3f velocity = particle.getVelocity();
        // compute density of every particle first
        double density_i = 0;
        for (unsigned j = 0; j < state.size(); j+=1) {
            if (j != i) {
                Particle particle_j = state[j];

                Vector3f delta = position - particle_j.getPosition();
                if (delta.absSquared() < H*H) {
                    density_i += WPoly6(delta);
                    // cout << WPoly6(delta) << endl;
                }
            }
        }
        particle.density() = .001+PARTICLE_MASS*density_i;
        // cout <<particle.density() << endl;

        if (particle.density() < 50){
        particle.density() = 500;
        }
        // cout << density_i << endl;

    }

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle particle = state[i];
        Vector3f position = particle.getPosition();
        Vector3f velocity = particle.getVelocity();
        double density = particle.density();
        float pressure = particle.getPressure();

        // compute updated density and gradient of pressure
        // based on all other particles
        Vector3f f_pressure;
        Vector3f f_viscosity;
        for (unsigned j = 0; j < state.size(); j+=1) {
            if (j != i) {
                Particle particle_j = state[j];

                Vector3f delta = position - particle_j.getPosition() + Vector3f(2 * PARTICLE_RADIUS);
                // cout << "delta" << delta.x() << ","<< delta.y() << ","<< delta.z() << endl;
                if (delta.absSquared() < H*H) {
                    //  ---------------gradient of pressure computation-----------------

                    // sample implementation value: pi/roi2 + pj/roj2
                    float p_factor = (pressure/(density*density)) + (particle_j.getPressure()/(particle_j.density()*particle_j.density()));

                    // Mueller value: (pi + pj) / 2roj
                    // float p_factor = (pressure+particle_j.getPressure()) / (2*particle_j.getDensity());

                    // Lecture video value: pi/roi + pj/roj
                    // float p_factor = pressure/density + particle_j.getPressure()/particle_j.getDensity();
                    // (WSpiky(delta)).print();
                    // delta.print();
                    f_pressure += p_factor*WSpiky(delta);
                    //  ---------------viscosity computation-----------------
                    float kernel_distance_viscosity = H-delta.abs();

                    Vector3f v_factor = (particle_j.getVelocity() - velocity);// / particle_j.getDensity();
                    // cout << WViscosity(delta) << endl;

                    Vector3f viscosity_term = (WViscosity(delta)/ particle_j.getDensity())*v_factor;
                    // cout << "delta " << kernel_constant_pressure << endl;
                    // viscosity_term.print();
                    f_viscosity += viscosity_term;
                    // velocity.print();
                        float dd = WViscosity(delta);

                    // cout << dd << endl;
                    // cout << particle_j.getDensity() << endl;

                    // if ((viscosity_term * mu * PARTICLE_MASS).y() > 20){
                    //     cout << j << endl;
                    //     cout << "alert" << endl;
                    //     cout << particle_j.getDensity() << endl;
                    //     cout << dd <<endl;
                    //     v_factor.print();
                    //     viscosity_term.print();
                    // }
                }
            }
        }

        f_pressure *= PARTICLE_MASS;
        f_viscosity *= mu * PARTICLE_MASS;

        // Total Force
        // Vector3f totalForce = (gravityForce +(mu*f_viscosity) + f_pressure)/density;
        // f_pressure.print();
        // cout << density << endl;
        Vector3f f_collision = .9*collisionForce(particle);

        // (f_viscosity/PARTICLE_MASS).print();

        // Total Force
        f_collision = Vector3f(0, f_collision.y(), 0);
        // f_viscosity.print();
        Vector3f totalForce = gravityForce + f_collision + .001*f_viscosity;
        // if (f_viscosity.abs() > 15){
        //     cout << "wtf" << endl;
        //            f_viscosity.print();
        // f_collision.print();
        // }

        // Vector3f totalForce = gravityForce + f_collision ;//+ f_pressure;
        // cout << "f_collision: " << f_collision.x() << ","<< f_collision.y() << ","<< f_collision.z() << endl;
        // cout << "f_pressure: " << f_pressure.x() << ","<< f_pressure.y() << ","<< f_pressure.z() << endl;
        // cout << "gravityForce: " << gravityForce.x() << ","<< gravityForce.y() << ","<< gravityForce.z() << endl;
        // totalForce.print();

        Vector3f acceleration = totalForce / PARTICLE_MASS;

        Particle newParticle = Particle(i, velocity, acceleration, density);
        f.push_back(newParticle);
    }

    return f;
}

float WPoly6(Vector3f R){
    float constant_term = 315.0 / (64.0 * M_PI * Hfouth * Hfouth * H);
    float factor = Hsquared - R.absSquared();
    float kernel_distance_density = factor * factor * factor;
    return kernel_distance_density*constant_term;
}

Vector3f WSpiky(Vector3f R){
    if (R.abs() < .000001){
        return Vector3f(0,0,0);
    }
    float constant_term = -45.0 / (M_PI * Hfouth * Hsquared);
    float factor = H - R.abs();
    Vector3f kernel_distance_pressure = factor * factor * R.normalized();
    return constant_term * kernel_distance_pressure;
}

float WViscosity(Vector3f R){
    float constant_term = 45.0 / (M_PI * Hfouth * Hsquared);
    float kernel_distance_viscosity = H-R.abs();
    return constant_term * kernel_distance_viscosity /10.0;
}

Vector3f FluidSystem::collisionForce(Particle particle) {
    Vector3f f_collision;
    for (unsigned int i = 0; i < _walls.size(); i++) {

        Wall wall = _walls[i];
        Vector3f wallNormal = wall.getNormal();
        double d = Vector3f::dot(wallNormal, (wall.getPoint() - particle.getPosition())) +  0.008; // particle radius
        if (d > 0.0) {
            f_collision += WALL_DAMPING * Vector3f::dot(wallNormal, particle.getVelocity()) * wallNormal + WALL_K * wallNormal * d;
        }
    }
    return f_collision;
}

void FluidSystem::draw(GLProgram& gl)
{
    //TODO 5: render the system
    //         - ie draw the particles as little spheres
    //         - or draw the springs as little lines or cylinders
    //         - or draw wireframe mesh

    const Vector3f blue(0.0f, 0.0f, 1.0f);

    // EXAMPLE for how to render cloth particles.
    //  - you should replace this code.
    // EXAMPLE: This shows you how to render lines to debug the spring system.
    //
    //          You should replace this code.
    //
    //          Since lines don't have a clearly defined normal, we can't use
    //          a regular lighting model.
    //          GLprogram has a "color only" mode, where illumination
    //          is disabled, and you specify color directly as vertex attribute.
    //          Note: enableLighting/disableLighting invalidates uniforms,
    //          so you'll have to update the transformation/material parameters
    //          after a mode change.
    gl.disableLighting();
    gl.updateModelMatrix(Matrix4f::identity()); // update uniforms after mode change
    // drawBox(Vector3f(0,0,0), 1);

    // not working :(
    gl.updateMaterial(blue);

    for (unsigned i = 0; i < m_vVecState.size(); i+=1){
        Particle p = m_vVecState[i];
        Vector3f pos = p.getPosition();
        gl.updateModelMatrix(Matrix4f::translation(pos));
        drawSphere(.012, 10, 4);
    }

    gl.enableLighting(); // reset to default lighting model
}

<|endoftext|>


<commit_before>#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

#define MOD         1000000007

int * * cnt1;
int * * cnt2;

int main() {
    int l, n, m;
    long long c;

    scanf("%d %d %d %lld", &l, &n, &m, &c);

    // malloc
    cnt1 = (int * *)malloc((n + 1) * sizeof(int*));
    for (size_t i = 0; i <= n; i++) {
        cnt1[i] = (int *)malloc(m * sizeof(int));
        memset(cnt1[i], 0, m * sizeof(int));
    }

    cnt2 = (int * *)malloc((n + 1) * sizeof(int*));
    for (size_t i = 0; i <= n; i++) {
        cnt2[i] = (int *)malloc(m * sizeof(int));
        memset(cnt2[i], 0, m * sizeof(int));
    }

    long long sum = 0;

    cnt1[0][0] = (c - 2) % MOD;
    cnt1[0][1] = 1;
    cnt1[1][0] = 1;

    sum += ((long long)(c % MOD)) * (long long)n % MOD;

    printf("sum is %lld\n", sum);

    int * * now = cnt2;
    int * * pre = cnt1;

    for (size_t day = 2; day <= l; day++) {
        int max_n = (n < day) ? n : day;
        for (size_t in = 0; in <= max_n; in++) {
            long long tmp = 0;
            int max_m = ((m - 1) < (day - in)) ? (m - 1) : (day - in);
            for (size_t im = 0; im <= max_m; im++) {
                if (0 == im) {
                    for (size_t i = 0; i < m; i++) {
                        tmp += (c - 2) * pre[in][i] % MOD;
                        tmp %= MOD;
                    }

                    if (in > 0) {
                        for (size_t i = 0; i < m; i++) {
                            tmp += pre[in - 1][i];
                            tmp %= MOD;
                        }
                    }

                    now[in][im] = tmp;
                }
                else {
                    now[in][im] = pre[in][im - 1];
                }

                if (0 == in) {
                    sum += (long long)l * (long long)now[in][im];
                    sum %= MOD;
                }
                else {
                    sum += (long long)(l - in + 1) * (long long)now[in][im];
                    sum %= MOD;
                }
            }
        }

        if (now == cnt2) {
            now = cnt1;
            pre = cnt2;
        }
        else {
            now = cnt2;
            pre = cnt1;
        }
    }

    printf("%lld\n", sum);

    return 0;
}
<commit_msg>delete cpp file<commit_after><|endoftext|>


<commit_before>/*******************************************************************************
* Touch Controller
*
* Handles initializing the QTouch library and detecting touches.
******************************************************************************/

/*----------------------------------------------------------------------------
                                include files
----------------------------------------------------------------------------*/
#include <avr/io.h>
#include "touch_api.h"
#include "touch.h"
#include "touch_control.h"

/*----------------------------------------------------------------------------
                                extern variables
----------------------------------------------------------------------------*/

/* This configuration data structure parameters if needs to be changed will be
   changed in the qt_set_parameters function */
extern qt_touch_lib_config_data_t qt_config_data;

/* touch output - measurement data */
extern qt_touch_lib_measure_data_t qt_measure_data;

/*----------------------------------------------------------------------------
                                    macros
----------------------------------------------------------------------------*/
#define GET_SENSOR_STATE(SENSOR_NUMBER) qt_measure_data.qt_touch_status.sensor_states[(SENSOR_NUMBER/8)] & (1 << (SENSOR_NUMBER % 8))

/*============================================================================
 * Initialize the QTouch library
 *============================================================================*/
void touch_init( void ) {

  // Disable pull-ups
  MCUCR |= (1u << PUD);

  /* Configure the Sensors as keys or Keys With Rotor/Sliders in this function */
  config_sensors();

  /* initialise touch sensing */
  qt_init_sensing();

  /*  Set the parameters like recalibration threshold, Max_On_Duration etc in this function by the user */
  qt_set_parameters();
}

/*============================================================================
 * Measure a touch sensor.
 *   + sensor_num: The sensor to measure (zero indexed)
 *   + current_time: The current time, in milliseconds
 *   + max_measurements: If multiple measurements are needed, this is the maximum measurements to make.
 *
 * Returns 1 = touch detected, 0 = no touch
 *============================================================================*/
uint8_t touch_measure(uint8_t sensor_num, uint16_t current_time, uint8_t max_measurements) {

	/* status flags to indicate the re-burst for library */
  static uint16_t status_flag = 0u;
  static uint16_t burst_flag = 0u;
  uint8_t measure_count = 0;

  do {
    status_flag = qt_measure_sensors( current_time );
    burst_flag = status_flag & QTLIB_BURST_AGAIN;
    measure_count++;
  } while (burst_flag && measure_count < max_measurements);

  return GET_SENSOR_STATE(sensor_num);
}
uint8_t touch_measure(uint8_t sensor_num, uint16_t current_time) {
  return touch_measure(sensor_num, current_time, 100);
}

/*============================================================================
 * Set the QTouch detection parameters and threshold values.
 *===========================================================================*/
static void qt_set_parameters() {
  qt_config_data.qt_di              = 4;
  qt_config_data.qt_neg_drift_rate  = 20;
  qt_config_data.qt_pos_drift_rate  = 5;
  qt_config_data.qt_max_on_duration = 0;
  qt_config_data.qt_drift_hold_time = 20;
  qt_config_data.qt_recal_threshold = RECAL_50;
  qt_config_data.qt_pos_recal_delay = 10;
}

/*============================================================================
 * Setup all the sensors
 *============================================================================*/
static void config_sensors() {
	qt_enable_key( CHANNEL_0, NO_AKS_GROUP, 7u, HYST_25 );
  // qt_enable_key( CHANNEL_0, NO_AKS_GROUP, 7u, HYST_6_25 );
}

<commit_msg>Only disable pullups when we're testing for a touch<commit_after>/*******************************************************************************
* Touch Controller
*
* Handles initializing the QTouch library and detecting touches.
******************************************************************************/

/*----------------------------------------------------------------------------
                                include files
----------------------------------------------------------------------------*/
#include <avr/io.h>
#include "touch_api.h"
#include "touch.h"
#include "touch_control.h"

/*----------------------------------------------------------------------------
                                extern variables
----------------------------------------------------------------------------*/

/* This configuration data structure parameters if needs to be changed will be
   changed in the qt_set_parameters function */
extern qt_touch_lib_config_data_t qt_config_data;

/* touch output - measurement data */
extern qt_touch_lib_measure_data_t qt_measure_data;

/*----------------------------------------------------------------------------
                                    macros
----------------------------------------------------------------------------*/
#define GET_SENSOR_STATE(SENSOR_NUMBER) qt_measure_data.qt_touch_status.sensor_states[(SENSOR_NUMBER/8)] & (1 << (SENSOR_NUMBER % 8))

/*============================================================================
 * Initialize the QTouch library
 *============================================================================*/
void touch_init( void ) {

  /* Configure the Sensors as keys or Keys With Rotor/Sliders in this function */
  config_sensors();

  /* initialise touch sensing */
  qt_init_sensing();

  /*  Set the parameters like recalibration threshold, Max_On_Duration etc in this function by the user */
  qt_set_parameters();
}

/*============================================================================
 * Measure a touch sensor.
 *   + sensor_num: The sensor to measure (zero indexed)
 *   + current_time: The current time, in milliseconds
 *   + max_measurements: If multiple measurements are needed, this is the maximum measurements to make.
 *
 * Returns 1 = touch detected, 0 = no touch
 *============================================================================*/
uint8_t touch_measure(uint8_t sensor_num, uint16_t current_time, uint8_t max_measurements) {

  // Disable all pull-ups
  uint8_t mcuRegister = MCUCR;
  MCUCR |= (1 << PUD);

	// status flags to indicate the re-burst for library
  static uint16_t status_flag = 0u;
  static uint16_t burst_flag = 0u;
  uint8_t measure_count = 0;

  do {
    status_flag = qt_measure_sensors( current_time );
    burst_flag = status_flag & QTLIB_BURST_AGAIN;
    measure_count++;
  } while (burst_flag && measure_count < max_measurements);

  // Reset pull-ups
  MCUCR = mcuRegister;

  return GET_SENSOR_STATE(sensor_num);
}
uint8_t touch_measure(uint8_t sensor_num, uint16_t current_time) {
  return touch_measure(sensor_num, current_time, 100);
}

/*============================================================================
 * Set the QTouch detection parameters and threshold values.
 *===========================================================================*/
static void qt_set_parameters() {
  qt_config_data.qt_di              = 4;
  qt_config_data.qt_neg_drift_rate  = 20;
  qt_config_data.qt_pos_drift_rate  = 5;
  qt_config_data.qt_max_on_duration = 0;
  qt_config_data.qt_drift_hold_time = 20;
  qt_config_data.qt_recal_threshold = RECAL_50;
  qt_config_data.qt_pos_recal_delay = 10;
}

/*============================================================================
 * Setup all the sensors
 *============================================================================*/
static void config_sensors() {
	qt_enable_key( CHANNEL_0, NO_AKS_GROUP, 7u, HYST_25 );
  // qt_enable_key( CHANNEL_0, NO_AKS_GROUP, 7u, HYST_6_25 );
}

<|endoftext|>


<commit_before>/// @file Environment.cpp
/// @brief Manages environment-related reX-logic, e.g. world time and lightning.
/// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "RexLogicModule.h"
#include "Environment.h"
#include "Foundation.h"
#include "EC_OgreEnvironment.h"
#include "Entity.h"

namespace RexLogic
{

Environment::Environment(RexLogicModule *owner)
:owner_(owner)
{
}

Environment::~Environment()
{
}

bool Environment::HandleOSNE_SimulatorViewerTimeMessage(OpenSimProtocol::NetworkEventInboundData *data)
{
    NetInMessage &msg = *data->message;
    msg.ResetReading();

    usecSinceStart_ = (time_t)msg.ReadU64();
    secPerDay_ = msg.ReadU32(); // seems to be zero, at least with 0.4 server
    secPerYear_ = msg.ReadU32(); // seems to be zero, at least with 0.4 server
    sunDirection_ = msg.ReadVector3();
    sunPhase_ = msg.ReadF32(); // seems to be zero, at least with 0.4 server
    sunAngVelocity_ = msg.ReadVector3();

    if (!entity_)
        return false;

    // Update the sunlight direction and angle velocity.
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (entity_->GetComponent("EC_OgreEnvironment").get());

    env.SetSunDirection(sunDirection_);
    // Set somekind of ambient light, so that the lights are visible.
    ///\todo Find a good default value
    env.SetAmbientLightColor(Core::Color(0.75f, 0.75f, 0.75f, 0.1f));

    return false;
}

}
<commit_msg>Fixed headless mode crash.<commit_after>/// @file Environment.cpp
/// @brief Manages environment-related reX-logic, e.g. world time and lightning.
/// For conditions of distribution and use, see copyright notice in license.txt

#include "StableHeaders.h"
#include "RexLogicModule.h"
#include "Environment.h"
#include "Foundation.h"
#include "EC_OgreEnvironment.h"
#include "Entity.h"

namespace RexLogic
{

Environment::Environment(RexLogicModule *owner)
:owner_(owner)
{
}

Environment::~Environment()
{
}

bool Environment::HandleOSNE_SimulatorViewerTimeMessage(OpenSimProtocol::NetworkEventInboundData *data)
{
    NetInMessage &msg = *data->message;
    msg.ResetReading();

    usecSinceStart_ = (time_t)msg.ReadU64();
    secPerDay_ = msg.ReadU32(); // seems to be zero, at least with 0.4 server
    secPerYear_ = msg.ReadU32(); // seems to be zero, at least with 0.4 server
    sunDirection_ = msg.ReadVector3();
    sunPhase_ = msg.ReadF32(); // seems to be zero, at least with 0.4 server
    sunAngVelocity_ = msg.ReadVector3();

    if (!entity_)
        return false;

    Foundation::ComponentPtr component = entity_->GetComponent("EC_OgreEnvironment");
    if (!component)
        return false;

    // Update the sunlight direction and angle velocity.
    OgreRenderer::EC_OgreEnvironment &env = *checked_static_cast<OgreRenderer::EC_OgreEnvironment*>
        (component.get());

    env.SetSunDirection(sunDirection_);
    // Set somekind of ambient light, so that the lights are visible.
    ///\todo Find a good default value
    env.SetAmbientLightColor(Core::Color(0.75f, 0.75f, 0.75f, 0.1f));

    return false;
}

}
<|endoftext|>


<commit_before>#include "stdafx.h"
#include "ReentrantCounterTest.h"
#include "ReentrantCounter.h"
#include <boost/chrono.hpp>
#include <vector>

// Timeouts, in microseconds:
const size_t gc_timeouts[] = {500, 221, 3700, 1910, 21100, 442, 9281, 7201, 49102, 701, 222};

// Recovered timeouts:
PerformanceCounter g_timeouts[ARRAYCOUNT(gc_timeouts)];

// Current offset:
size_t g_curOffset = 0;

// Slack value--we allow 50us of slack
const boost::chrono::microseconds slack(50);

// Reentrant function proper:
void Reenter() {
  // Start our counter:
  ReentrantCounter ctr(g_timeouts[g_curOffset]);

  // Spin until time-up.  We want precision, so we spin rather than sleep
  auto finish = boost::chrono::high_resolution_clock::now() + boost::chrono::microseconds(gc_timeouts[g_curOffset]);
  while(boost::chrono::high_resolution_clock::now() < finish);

  // Reenter every second value:
  if(g_curOffset++ % 2)
    Reenter();
}

TEST_F(ReentrantCounterTest, VerifySimpleBenchmarking) {
  // Total time we will spin for, to test reentrancy:
  const boost::chrono::microseconds spinTime(1299);

  PerformanceCounter counter;

  // Wait for spin-time period:
  {
    ReentrantCounter ctr(counter);
    auto finish = boost::chrono::high_resolution_clock::now() + spinTime;
    while(boost::chrono::high_resolution_clock::now() < finish);
  }

  // Verify we hit exactly once:
  EXPECT_EQ(1UL, counter.hitCount) << "Performance counter incremented an incorrect number of times";

  // Verify we are in range:
  EXPECT_LT(spinTime - slack, counter.lingerTime) << "Reentrant counter underestimated the total spin time";
  EXPECT_GT(spinTime + slack, counter.lingerTime) << "Reentrant counter overestimated the total spin time";
}

TEST_F(ReentrantCounterTest, VerifyComplexReentrancy) {
  // Run our reentrant function:
  while(g_curOffset < ARRAYCOUNT(gc_timeouts)){
    Reenter();
  }
  // Validate timeouts:;
  for(size_t i = 0; i < ARRAYCOUNT(gc_timeouts); i++) {
    EXPECT_EQ(1UL, g_timeouts[i].hitCount) << "Performance counter hit too many times";
    EXPECT_LT(
      g_timeouts[i].lingerTime - slack,
      boost::chrono::microseconds(gc_timeouts[i])
    );
    EXPECT_GT(
      g_timeouts[i].lingerTime + slack,
      boost::chrono::microseconds(gc_timeouts[i])
    );
  }
}<commit_msg>Increased slack time in ReentrantCounterTest<commit_after>#include "stdafx.h"
#include "ReentrantCounterTest.h"
#include "ReentrantCounter.h"
#include <boost/chrono.hpp>
#include <vector>

// Timeouts, in microseconds:
const size_t gc_timeouts[] = {500, 221, 3700, 1910, 21100, 442, 9281, 7201, 49102, 701, 222};

// Recovered timeouts:
PerformanceCounter g_timeouts[ARRAYCOUNT(gc_timeouts)];

// Current offset:
size_t g_curOffset = 0;

// Slack value--we allow 1s of slack
const boost::chrono::seconds slack(1);

// Reentrant function proper:
void Reenter() {
  // Start our counter:
  ReentrantCounter ctr(g_timeouts[g_curOffset]);

  // Spin until time-up.  We want precision, so we spin rather than sleep
  auto finish = boost::chrono::high_resolution_clock::now() + boost::chrono::microseconds(gc_timeouts[g_curOffset]);
  while(boost::chrono::high_resolution_clock::now() < finish);

  // Reenter every second value:
  if(g_curOffset++ % 2)
    Reenter();
}

TEST_F(ReentrantCounterTest, VerifySimpleBenchmarking) {
  // Total time we will spin for, to test reentrancy:
  const boost::chrono::microseconds spinTime(1299);

  PerformanceCounter counter;

  // Wait for spin-time period:
  {
    ReentrantCounter ctr(counter);
    auto finish = boost::chrono::high_resolution_clock::now() + spinTime;
    while(boost::chrono::high_resolution_clock::now() < finish);
  }

  // Verify we hit exactly once:
  EXPECT_EQ(1UL, counter.hitCount) << "Performance counter incremented an incorrect number of times";

  // Verify we are in range:
  EXPECT_LT(spinTime - slack, counter.lingerTime) << "Reentrant counter underestimated the total spin time";
  EXPECT_GT(spinTime + slack, counter.lingerTime) << "Reentrant counter overestimated the total spin time";
}

TEST_F(ReentrantCounterTest, VerifyComplexReentrancy) {
  // Run our reentrant function:
  while(g_curOffset < ARRAYCOUNT(gc_timeouts)){
    Reenter();
  }
  // Validate timeouts:;
  for(size_t i = 0; i < ARRAYCOUNT(gc_timeouts); i++) {
    EXPECT_EQ(1UL, g_timeouts[i].hitCount) << "Performance counter hit too many times";
    EXPECT_LT(
      g_timeouts[i].lingerTime - slack,
      boost::chrono::microseconds(gc_timeouts[i])
    );
    EXPECT_GT(
      g_timeouts[i].lingerTime + slack,
      boost::chrono::microseconds(gc_timeouts[i])
    );
  }
}<|endoftext|>


<commit_before>#include "TStatusBitsChecker.h"

#include "TClass.h"
#include "TInterpreter.h"

#include "gtest/gtest.h"

const char* gCode = R"CODE(
   struct ClassWithOverlap : public TObject {
      enum EStatusBits {
         kOverlappingBit = BIT(13)
      };
   };
)CODE";

void MakeClassWithOverlap() {
   gInterpreter->Declare(gCode);
}

TEST(StatusBitsChecker,NoOverlap)
{
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TObject"));
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TNamed"));
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TStreamerElement"));
}

TEST(StatusBitsChecker,Overlap)
{
   MakeClassWithOverlap();
   EXPECT_NE(nullptr,TClass::GetClass("ClassWithOverlap"));
   EXPECT_FALSE(ROOT::Detail::TStatusBitsChecker::Check("ClassWithOverlap"));
}
<commit_msg>[core] Silence diagnostics in testStatusBitsChecker.<commit_after>#include "TStatusBitsChecker.h"

#include "TClass.h"
#include "TInterpreter.h"
#include "ROOTUnitTestSupport.h"

#include "gtest/gtest.h"

const char* gCode = R"CODE(
   struct ClassWithOverlap : public TObject {
      enum EStatusBits {
         kOverlappingBit = BIT(13)
      };
   };
)CODE";

void MakeClassWithOverlap() {
   gInterpreter->Declare(gCode);
}

TEST(StatusBitsChecker,NoOverlap)
{
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TObject"));
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TNamed"));
   EXPECT_TRUE(ROOT::Detail::TStatusBitsChecker::Check("TStreamerElement"));
}

TEST(StatusBitsChecker,Overlap)
{
   ROOTUnitTestSupport::CheckDiagsRAII diags;
   diags.requiredDiag(kError, "TStatusBitsChecker", "ClassWithOverlap", /*matchFullMessage=*/false);
   diags.requiredDiag(kError, "TStatusBitsChecker", "13 used in",       /*matchFullMessage=*/false);

   MakeClassWithOverlap();
   EXPECT_NE(nullptr,TClass::GetClass("ClassWithOverlap"));
   EXPECT_FALSE(ROOT::Detail::TStatusBitsChecker::Check("ClassWithOverlap"));
}
<|endoftext|>


<commit_before>/** @passthru.cc
 *
 *  Example protocol plugin.
 *
 *  @section license License
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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.
 */

/*
 * Passthru plugin.
 *
 * This plugin demonstrates:
 *
 *  - Using TSMgmtStringCreate() to add custom records into records.config.
 *  - Listening on a custom socket with TSPortDescriptorAccept().
 *  - Using TSHttpConnectWithPluginId() and the VConn API to proxy HTTP traffic.
 */

#include <ts/ts.h>
#include <cinttypes>
#include <cstring>

#define PLUGIN_NAME "passthru"

#define PassthruSessionDebug(sp, fmt, ...)                 \
  do {                                                     \
    TSDebug(PLUGIN_NAME, "sp=%p " fmt, sp, ##__VA_ARGS__); \
  } while (0)

static int PassthruSessionEvent(TSCont cont, TSEvent event, void *edata);

union EventArgument {
  void *edata;
  TSVConn vconn;
  TSVIO vio;

  EventArgument(void *_p) : edata(_p) {}
};

struct PassthruIO {
  TSVIO vio;
  TSIOBuffer iobuf;
  TSIOBufferReader reader;

  PassthruIO() : vio(nullptr), iobuf(nullptr), reader(nullptr) {}
  ~PassthruIO() { clear(); }
  void
  clear()
  {
    if (this->reader) {
      TSIOBufferReaderFree(this->reader);
    }

    if (this->iobuf) {
      TSIOBufferDestroy(this->iobuf);
    }

    this->reader = nullptr;
    this->iobuf  = nullptr;
    this->vio    = nullptr;
  }

  // Start a read operation.
  void
  read(TSVConn vconn, TSCont contp)
  {
    TSReleaseAssert(this->vio == nullptr);

    this->iobuf  = TSIOBufferCreate();
    this->reader = TSIOBufferReaderAlloc(this->iobuf);
    this->vio    = TSVConnRead(vconn, contp, this->iobuf, INT64_MAX);
  }

  // Start a write operation.
  void
  write(TSVConn vconn, TSCont contp)
  {
    TSReleaseAssert(this->vio == nullptr);

    this->iobuf  = TSIOBufferCreate();
    this->reader = TSIOBufferReaderAlloc(this->iobuf);
    this->vio    = TSVConnWrite(vconn, contp, this->reader, INT64_MAX);
  }

  // Transfer data from this IO object to the target IO object. We use
  // TSIOBufferCopy to move the data without actually duplicating it.
  int64_t
  transfer_to(PassthruIO &to)
  {
    int64_t consumed = 0;
    int64_t avail    = TSIOBufferReaderAvail(this->reader);

    if (avail) {
      consumed = TSIOBufferCopy(to.iobuf, this->reader, avail, 0 /* offset */);
      TSIOBufferReaderConsume(this->reader, consumed);
    }

    return consumed;
  }

private:
  PassthruIO(const PassthruIO &) = delete;
  PassthruIO &operator=(const PassthruIO &) = delete;
};

struct PassthruSession {
  // VC session to the client.
  struct {
    TSVConn vconn;
    PassthruIO readio;
    PassthruIO writeio;
  } client;

  // VC session to Traffic Server via TSHttpConnect.
  struct {
    TSVConn vconn;
    PassthruIO readio;
    PassthruIO writeio;
  } server;

  TSCont contp;

  PassthruSession() : contp(TSContCreate(PassthruSessionEvent, TSMutexCreate()))
  {
    this->client.vconn = this->server.vconn = nullptr;
    TSContDataSet(this->contp, this);
  }

  ~PassthruSession()
  {
    if (this->server.vconn) {
      TSVConnClose(this->server.vconn);
    }

    if (this->client.vconn) {
      TSVConnClose(this->client.vconn);
    }

    TSContDataSet(this->contp, nullptr);
    TSContDestroy(this->contp);

    PassthruSessionDebug(this, "destroyed session");
  }

private:
  PassthruSession(const PassthruSession &) = delete;
  PassthruSession &operator=(const PassthruSession &) = delete;
};

static bool
PassthruSessionIsFinished(PassthruSession *sp)
{
  int64_t avail = TSIOBufferReaderAvail(sp->client.writeio.reader);

  // We should shut down the session if we don't have a server vconn
  // (either it was never started, or it was closed), and we have drained
  // the client write buffer.
  if (sp->server.vconn == nullptr && avail == 0) {
    return true;
  }

  PassthruSessionDebug(sp, "continuing session with %" PRId64 " buffered client bytes", avail);
  return false;
}

static int
PassthruSessionEvent(TSCont cont, TSEvent event, void *edata)
{
  EventArgument arg(edata);
  PassthruSession *sp = (PassthruSession *)TSContDataGet(cont);

  PassthruSessionDebug(sp, "session event on vconn=%p event=%d (%s)", TSVIOVConnGet(arg.vio), event, TSHttpEventNameLookup(event));

  if (event == TS_EVENT_VCONN_READ_READY) {
    // On the first read, wire up the internal transfer to the server.
    if (sp->server.vconn == nullptr) {
      sp->server.vconn = TSHttpConnectWithPluginId(TSNetVConnRemoteAddrGet(sp->client.vconn), PLUGIN_NAME, 0);

      TSReleaseAssert(sp->server.vconn != nullptr);

      // Start the server end of the IO before we write any data.
      sp->server.readio.read(sp->server.vconn, sp->contp);
      sp->server.writeio.write(sp->server.vconn, sp->contp);
    }

    if (sp->server.vconn != nullptr) {
      int64_t nbytes;

      nbytes = sp->client.readio.transfer_to(sp->server.writeio);
      PassthruSessionDebug(sp, "proxied %" PRId64 " bytes from client vconn=%p to server vconn=%p", nbytes, sp->client.vconn,
                           sp->server.vconn);
      if (nbytes) {
        TSVIOReenable(sp->client.readio.vio);
        TSVIOReenable(sp->server.writeio.vio);
      }

      nbytes = sp->server.readio.transfer_to(sp->client.writeio);
      PassthruSessionDebug(sp, "proxied %" PRId64 " bytes from server vconn=%p to client vconn=%p", nbytes, sp->server.vconn,
                           sp->client.vconn);
      if (nbytes) {
        TSVIOReenable(sp->server.readio.vio);
        TSVIOReenable(sp->client.writeio.vio);
      }
    }

    if (PassthruSessionIsFinished(sp)) {
      delete sp;
      return TS_EVENT_NONE;
    }

    TSVIOReenable(arg.vio);
    return TS_EVENT_NONE;
  }

  if (event == TS_EVENT_VCONN_WRITE_READY) {
    if (PassthruSessionIsFinished(sp)) {
      delete sp;
      return TS_EVENT_NONE;
    }

    return TS_EVENT_NONE;
  }

  if (event == TS_EVENT_VCONN_EOS) {
    // If we get EOS from the client, just abort everything; we don't
    // care any more.
    if (TSVIOVConnGet(arg.vio) == sp->client.vconn) {
      PassthruSessionDebug(sp, "got EOS from client vconn=%p", sp->client.vconn);

      delete sp;
      return TS_EVENT_NONE;
    }

    // If we get EOS from the server, then we should make sure that we
    // drain any outstanding data before shutting down the client.
    if (TSVIOVConnGet(arg.vio) == sp->server.vconn) {
      PassthruSessionDebug(sp, "EOS from server vconn=%p", sp->server.vconn);

      TSReleaseAssert(sp->client.vconn != nullptr);

      if (TSIOBufferReaderAvail(sp->server.readio.reader) > 0) {
        sp->server.readio.transfer_to(sp->client.writeio);
        TSVIOReenable(sp->client.writeio.vio);
      }

      TSVConnClose(sp->server.vconn);
      sp->server.vconn = nullptr;
      sp->server.readio.clear();
      sp->server.writeio.clear();
    }

    return TS_EVENT_NONE;
  }

  TSError("[%s] unexpected event %s (%d) edata=%p", PLUGIN_NAME, TSHttpEventNameLookup(event), event, arg.edata);

  return TS_EVENT_ERROR;
}

static int
PassthruAccept(TSCont /* cont */, TSEvent event, void *edata)
{
  EventArgument arg(edata);
  PassthruSession *sp = new PassthruSession();

  PassthruSessionDebug(sp, "accepting connection on vconn=%p event=%d", arg.vconn, event);
  TSReleaseAssert(event == TS_EVENT_NET_ACCEPT);

  // Start the client end of the IO. We delay starting the server end until
  // we get the first read from the client end.
  sp->client.vconn = arg.vconn;
  sp->client.readio.read(arg.vconn, sp->contp);
  sp->client.writeio.write(arg.vconn, sp->contp);

  return TS_EVENT_NONE;
}

static TSReturnCode
PassthruListen()
{
  TSMgmtString ports          = nullptr;
  TSPortDescriptor descriptor = nullptr;
  TSCont cont                 = nullptr;

  if (TSMgmtStringGet("config.plugin.passthru.server_ports", &ports) == TS_ERROR) {
    TSError("[%s] missing config.plugin.passthru.server_ports configuration", PLUGIN_NAME);
    return TS_ERROR;
  }

  descriptor = TSPortDescriptorParse(ports);
  if (descriptor == nullptr) {
    TSError("[%s] failed to parse config.plugin.passthru.server_ports", PLUGIN_NAME);
    TSfree(ports);
    return TS_ERROR;
  }

  TSDebug(PLUGIN_NAME, "listening on port '%s'", ports);
  TSfree(ports);

  cont = TSContCreate(PassthruAccept, nullptr);
  return TSPortDescriptorAccept(descriptor, cont);
}

void
TSPluginInit(int /* argc */, const char * /* argv */ [])
{
  TSPluginRegistrationInfo info = {PLUGIN_NAME, "Apache Software Foundation", "dev@trafficserver.apache.org"};

  TSReturnCode status;

  TSMgmtStringCreate(TS_RECORDTYPE_CONFIG, "config.plugin.passthru.server_ports", const_cast<char *>(""),
                     TS_RECORDUPDATE_RESTART_TS, TS_RECORDCHECK_NULL, nullptr /* check_regex */, TS_RECORDACCESS_NULL);

  // Start listening on the configured port.
  status = PassthruListen();
  TSReleaseAssert(status == TS_SUCCESS);

  // Now that succeded, we can register.
  status = TSPluginRegister(&info);
  TSReleaseAssert(status == TS_SUCCESS);
}

// vim: set sw=2 ts=2 sts=2 et:
<commit_msg>Coverity 1363659: Dereference before null check<commit_after>/** @passthru.cc
 *
 *  Example protocol plugin.
 *
 *  @section license License
 *
 *  Licensed to the Apache Software Foundation (ASF) under one
 *  or more contributor license agreements.  See the NOTICE file
 *  distributed with this work for additional information
 *  regarding copyright ownership.  The ASF licenses this file
 *  to you 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.
 */

/*
 * Passthru plugin.
 *
 * This plugin demonstrates:
 *
 *  - Using TSMgmtStringCreate() to add custom records into records.config.
 *  - Listening on a custom socket with TSPortDescriptorAccept().
 *  - Using TSHttpConnectWithPluginId() and the VConn API to proxy HTTP traffic.
 */

#include <ts/ts.h>
#include <cinttypes>
#include <cstring>

#define PLUGIN_NAME "passthru"

#define PassthruSessionDebug(sp, fmt, ...)                 \
  do {                                                     \
    TSDebug(PLUGIN_NAME, "sp=%p " fmt, sp, ##__VA_ARGS__); \
  } while (0)

static int PassthruSessionEvent(TSCont cont, TSEvent event, void *edata);

union EventArgument {
  void *edata;
  TSVConn vconn;
  TSVIO vio;

  EventArgument(void *_p) : edata(_p) {}
};

struct PassthruIO {
  TSVIO vio;
  TSIOBuffer iobuf;
  TSIOBufferReader reader;

  PassthruIO() : vio(nullptr), iobuf(nullptr), reader(nullptr) {}
  ~PassthruIO() { clear(); }
  void
  clear()
  {
    if (this->reader) {
      TSIOBufferReaderFree(this->reader);
    }

    if (this->iobuf) {
      TSIOBufferDestroy(this->iobuf);
    }

    this->reader = nullptr;
    this->iobuf  = nullptr;
    this->vio    = nullptr;
  }

  // Start a read operation.
  void
  read(TSVConn vconn, TSCont contp)
  {
    TSReleaseAssert(this->vio == nullptr);

    this->iobuf  = TSIOBufferCreate();
    this->reader = TSIOBufferReaderAlloc(this->iobuf);
    this->vio    = TSVConnRead(vconn, contp, this->iobuf, INT64_MAX);
  }

  // Start a write operation.
  void
  write(TSVConn vconn, TSCont contp)
  {
    TSReleaseAssert(this->vio == nullptr);

    this->iobuf  = TSIOBufferCreate();
    this->reader = TSIOBufferReaderAlloc(this->iobuf);
    this->vio    = TSVConnWrite(vconn, contp, this->reader, INT64_MAX);
  }

  // Transfer data from this IO object to the target IO object. We use
  // TSIOBufferCopy to move the data without actually duplicating it.
  int64_t
  transfer_to(PassthruIO &to)
  {
    int64_t consumed = 0;
    int64_t avail    = TSIOBufferReaderAvail(this->reader);

    if (avail) {
      consumed = TSIOBufferCopy(to.iobuf, this->reader, avail, 0 /* offset */);
      TSIOBufferReaderConsume(this->reader, consumed);
    }

    return consumed;
  }

private:
  PassthruIO(const PassthruIO &) = delete;
  PassthruIO &operator=(const PassthruIO &) = delete;
};

struct PassthruSession {
  // VC session to the client.
  struct {
    TSVConn vconn;
    PassthruIO readio;
    PassthruIO writeio;
  } client;

  // VC session to Traffic Server via TSHttpConnect.
  struct {
    TSVConn vconn;
    PassthruIO readio;
    PassthruIO writeio;
  } server;

  TSCont contp;

  PassthruSession() : contp(TSContCreate(PassthruSessionEvent, TSMutexCreate()))
  {
    this->client.vconn = this->server.vconn = nullptr;
    TSContDataSet(this->contp, this);
  }

  ~PassthruSession()
  {
    if (this->server.vconn) {
      TSVConnClose(this->server.vconn);
    }

    if (this->client.vconn) {
      TSVConnClose(this->client.vconn);
    }

    TSContDataSet(this->contp, nullptr);
    TSContDestroy(this->contp);

    PassthruSessionDebug(this, "destroyed session");
  }

private:
  PassthruSession(const PassthruSession &) = delete;
  PassthruSession &operator=(const PassthruSession &) = delete;
};

static bool
PassthruSessionIsFinished(PassthruSession *sp)
{
  int64_t avail = TSIOBufferReaderAvail(sp->client.writeio.reader);

  // We should shut down the session if we don't have a server vconn
  // (either it was never started, or it was closed), and we have drained
  // the client write buffer.
  if (sp->server.vconn == nullptr && avail == 0) {
    return true;
  }

  PassthruSessionDebug(sp, "continuing session with %" PRId64 " buffered client bytes", avail);
  return false;
}

static int
PassthruSessionEvent(TSCont cont, TSEvent event, void *edata)
{
  EventArgument arg(edata);
  PassthruSession *sp = (PassthruSession *)TSContDataGet(cont);

  PassthruSessionDebug(sp, "session event on vconn=%p event=%d (%s)", TSVIOVConnGet(arg.vio), event, TSHttpEventNameLookup(event));

  if (event == TS_EVENT_VCONN_READ_READY) {
    // On the first read, wire up the internal transfer to the server.
    if (sp->server.vconn == nullptr) {
      sp->server.vconn = TSHttpConnectWithPluginId(TSNetVConnRemoteAddrGet(sp->client.vconn), PLUGIN_NAME, 0);

      TSReleaseAssert(sp->server.vconn != nullptr);

      // Start the server end of the IO before we write any data.
      sp->server.readio.read(sp->server.vconn, sp->contp);
      sp->server.writeio.write(sp->server.vconn, sp->contp);
    }

    int64_t nbytes;

    nbytes = sp->client.readio.transfer_to(sp->server.writeio);
    PassthruSessionDebug(sp, "proxied %" PRId64 " bytes from client vconn=%p to server vconn=%p", nbytes, sp->client.vconn,
                         sp->server.vconn);
    if (nbytes) {
      TSVIOReenable(sp->client.readio.vio);
      TSVIOReenable(sp->server.writeio.vio);
    }

    nbytes = sp->server.readio.transfer_to(sp->client.writeio);
    PassthruSessionDebug(sp, "proxied %" PRId64 " bytes from server vconn=%p to client vconn=%p", nbytes, sp->server.vconn,
                         sp->client.vconn);
    if (nbytes) {
      TSVIOReenable(sp->server.readio.vio);
      TSVIOReenable(sp->client.writeio.vio);
    }
  }

  if (PassthruSessionIsFinished(sp)) {
    delete sp;
    return TS_EVENT_NONE;
  }

  TSVIOReenable(arg.vio);
  return TS_EVENT_NONE;

  if (event == TS_EVENT_VCONN_WRITE_READY) {
    if (PassthruSessionIsFinished(sp)) {
      delete sp;
      return TS_EVENT_NONE;
    }

    return TS_EVENT_NONE;
  }

  if (event == TS_EVENT_VCONN_EOS) {
    // If we get EOS from the client, just abort everything; we don't
    // care any more.
    if (TSVIOVConnGet(arg.vio) == sp->client.vconn) {
      PassthruSessionDebug(sp, "got EOS from client vconn=%p", sp->client.vconn);

      delete sp;
      return TS_EVENT_NONE;
    }

    // If we get EOS from the server, then we should make sure that we
    // drain any outstanding data before shutting down the client.
    if (TSVIOVConnGet(arg.vio) == sp->server.vconn) {
      PassthruSessionDebug(sp, "EOS from server vconn=%p", sp->server.vconn);

      TSReleaseAssert(sp->client.vconn != nullptr);

      if (TSIOBufferReaderAvail(sp->server.readio.reader) > 0) {
        sp->server.readio.transfer_to(sp->client.writeio);
        TSVIOReenable(sp->client.writeio.vio);
      }

      TSVConnClose(sp->server.vconn);
      sp->server.vconn = nullptr;
      sp->server.readio.clear();
      sp->server.writeio.clear();
    }

    return TS_EVENT_NONE;
  }

  TSError("[%s] unexpected event %s (%d) edata=%p", PLUGIN_NAME, TSHttpEventNameLookup(event), event, arg.edata);

  return TS_EVENT_ERROR;
}

static int
PassthruAccept(TSCont /* cont */, TSEvent event, void *edata)
{
  EventArgument arg(edata);
  PassthruSession *sp = new PassthruSession();

  PassthruSessionDebug(sp, "accepting connection on vconn=%p event=%d", arg.vconn, event);
  TSReleaseAssert(event == TS_EVENT_NET_ACCEPT);

  // Start the client end of the IO. We delay starting the server end until
  // we get the first read from the client end.
  sp->client.vconn = arg.vconn;
  sp->client.readio.read(arg.vconn, sp->contp);
  sp->client.writeio.write(arg.vconn, sp->contp);

  return TS_EVENT_NONE;
}

static TSReturnCode
PassthruListen()
{
  TSMgmtString ports          = nullptr;
  TSPortDescriptor descriptor = nullptr;
  TSCont cont                 = nullptr;

  if (TSMgmtStringGet("config.plugin.passthru.server_ports", &ports) == TS_ERROR) {
    TSError("[%s] missing config.plugin.passthru.server_ports configuration", PLUGIN_NAME);
    return TS_ERROR;
  }

  descriptor = TSPortDescriptorParse(ports);
  if (descriptor == nullptr) {
    TSError("[%s] failed to parse config.plugin.passthru.server_ports", PLUGIN_NAME);
    TSfree(ports);
    return TS_ERROR;
  }

  TSDebug(PLUGIN_NAME, "listening on port '%s'", ports);
  TSfree(ports);

  cont = TSContCreate(PassthruAccept, nullptr);
  return TSPortDescriptorAccept(descriptor, cont);
}

void
TSPluginInit(int /* argc */, const char * /* argv */ [])
{
  TSPluginRegistrationInfo info = {PLUGIN_NAME, "Apache Software Foundation", "dev@trafficserver.apache.org"};

  TSReturnCode status;

  TSMgmtStringCreate(TS_RECORDTYPE_CONFIG, "config.plugin.passthru.server_ports", const_cast<char *>(""),
                     TS_RECORDUPDATE_RESTART_TS, TS_RECORDCHECK_NULL, nullptr /* check_regex */, TS_RECORDACCESS_NULL);

  // Start listening on the configured port.
  status = PassthruListen();
  TSReleaseAssert(status == TS_SUCCESS);

  // Now that succeded, we can register.
  status = TSPluginRegister(&info);
  TSReleaseAssert(status == TS_SUCCESS);
}

// vim: set sw=2 ts=2 sts=2 et:
<|endoftext|>


<commit_before>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/fmt/format.hpp"
#include "vendor/range/v3/view/transform.hpp"
#include "vendor/docopt/docopt.hpp"
#include "vendor/range/v3/view/filter.hpp"
#include "vendor/range/v3/to_container.hpp"
#include "vendor/json.hpp"
#include <thewizardplusplus/wizard_parser/lexer/lexeme.hpp>
#include <thewizardplusplus/wizard_parser/parser/rule_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/dummy_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/typing_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/match_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/concatenation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/lookahead_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/repetition_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/alternation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/ast_node.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/lexer/token.hpp>
#include <thewizardplusplus/wizard_parser/utilities/utilities.hpp>
#include <regex>
#include <cstdint>
#include <stdexcept>
#include <cstddef>
#include <iostream>
#include <string>
#include <cstdlib>
#include <functional>
#include <iterator>
#include <exception>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

const auto usage =
R"(Usage:
  ./example -h | --help
  ./example [-t TARGET | --target TARGET] [--] <expression>
  ./example [-t TARGET | --target TARGET] (-s | --stdin)

Options:
  -h, --help                  - show this message;
  -t TARGET, --target TARGET  - preliminary target of processing
                              (allowed: tokens, cst);
  -s, --stdin                 - read an expression from stdin.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{"-"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{"/"}, "slash"},
	{std::regex{"%"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{","}, "comma"},
	{std::regex{R"(\d+(?:\.\d+)?(?:e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};

BETTER_ENUM(entity_type, std::uint8_t, symbol, token, eoi)

template<entity_type::_integral type>
struct unexpected_entity_exception final: std::runtime_error {
	static_assert(entity_type::_is_valid(type));

	explicit unexpected_entity_exception(const std::size_t& offset);
};

template<entity_type::_integral type>
unexpected_entity_exception<type>::unexpected_entity_exception(
	const std::size_t& offset
):
	std::runtime_error{fmt::format(
		"unexpected {:s} (offset: {:d})",
		entity_type::_from_integral(type)._to_string(),
		offset
	)}
{}

void stop(const int& code, std::ostream& stream, const std::string& message) {
	stream << fmt::format("{:s}\n", message);
	std::exit(code);
}

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy >> *(&","_v >> expression_dummy))
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary >> *(("*"_v | "/"_v | "%"_v) >> unary);
	RULE(sum) = product >> *(("+"_v | "-"_v) >> product);
	expression_dummy->set_parser(sum);

	return sum;
}

parser::ast_node walk_ast(
	const parser::ast_node& ast,
	const std::function<parser::ast_node(const parser::ast_node&)>& handler
) {
	const auto new_ast = handler(ast);
	const auto new_children = new_ast.children
		| ranges::view::transform([&] (const auto& ast) {
			return walk_ast(ast, handler);
		});
	return {new_ast.type, new_ast.value, new_children, new_ast.offset};
}

int main(int argc, char* argv[]) try {
	const auto options = docopt::docopt(usage, {argv+1, argv+argc}, true);
	const auto code = options.at("--stdin").asBool()
		? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
		: options.at("<expression>").asString();
	const auto [tokens, rest_offset] = lexer::tokenize(lexemes, code);
	if (rest_offset != code.size()) {
		throw unexpected_entity_exception<entity_type::symbol>{rest_offset};
	}

	auto cleaned_tokens = tokens
		| ranges::view::filter([] (const auto& token) {
			return token.type != "whitespace";
		})
		| ranges::to_<lexer::token_group>();
	if (options.at("--target") == "tokens"s) {
		stop(EXIT_SUCCESS, std::cout, nlohmann::json(cleaned_tokens).dump());
	}

	const auto ast = make_parser()->parse(cleaned_tokens);
	if (!ast.rest_tokens.empty()) {
		throw unexpected_entity_exception<entity_type::token>{
			get_offset(ast.rest_tokens)
		};
	}
	if (!ast.node) {
		throw unexpected_entity_exception<entity_type::eoi>{code.size()};
	}

	auto transformed_ast = walk_ast(*ast.node, [&] (const auto& ast) {
		const auto offset = ast.offset == utilities::integral_infinity
			? code.size()
			: ast.offset;
		return parser::ast_node{ast.type, ast.value, ast.children, offset};
	});
	transformed_ast = walk_ast(transformed_ast, [] (const auto& ast) {
		const auto type = (+parser::ast_node_type::nothing)._to_string();
		const auto new_children = ast.children
			| ranges::view::filter([&] (const auto& ast) { return ast.type != type; })
			| ranges::to_<parser::ast_node_group>();
		return parser::ast_node{ast.type, ast.value, new_children, ast.offset};
	});
	if (options.at("--target") == "cst"s) {
		stop(EXIT_SUCCESS, std::cout, nlohmann::json(transformed_ast).dump());
	}

	throw std::runtime_error("not implemented yet");
} catch (const std::exception& exception) {
	stop(EXIT_FAILURE, std::cerr, fmt::format("error: {:s}", exception.what()));
}
<commit_msg>Simplify a result CST in the example: join nodes with the `sequence` type<commit_after>#define THEWIZARDPLUSPLUS_WIZARD_PARSER_PARSER_MACROSES

#include "vendor/better-enums/enum_strict.hpp"
#include "vendor/fmt/format.hpp"
#include "vendor/range/v3/view/transform.hpp"
#include "vendor/docopt/docopt.hpp"
#include "vendor/range/v3/view/filter.hpp"
#include "vendor/range/v3/to_container.hpp"
#include "vendor/json.hpp"
#include "vendor/range/v3/view/join.hpp"
#include <thewizardplusplus/wizard_parser/lexer/lexeme.hpp>
#include <thewizardplusplus/wizard_parser/parser/rule_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/dummy_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/typing_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/match_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/concatenation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/lookahead_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/repetition_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/alternation_parser.hpp>
#include <thewizardplusplus/wizard_parser/parser/ast_node.hpp>
#include <thewizardplusplus/wizard_parser/lexer/tokenize.hpp>
#include <thewizardplusplus/wizard_parser/lexer/token.hpp>
#include <thewizardplusplus/wizard_parser/utilities/utilities.hpp>
#include <regex>
#include <cstdint>
#include <stdexcept>
#include <cstddef>
#include <iostream>
#include <string>
#include <cstdlib>
#include <functional>
#include <iterator>
#include <vector>
#include <exception>

using namespace thewizardplusplus::wizard_parser;
using namespace thewizardplusplus::wizard_parser::parser::operators;
using namespace std::literals::string_literals;

const auto usage =
R"(Usage:
  ./example -h | --help
  ./example [-t TARGET | --target TARGET] [--] <expression>
  ./example [-t TARGET | --target TARGET] (-s | --stdin)

Options:
  -h, --help                  - show this message;
  -t TARGET, --target TARGET  - preliminary target of processing
                              (allowed: tokens, cst);
  -s, --stdin                 - read an expression from stdin.)";
const auto lexemes = lexer::lexeme_group{
	{std::regex{R"(\+)"}, "plus"},
	{std::regex{"-"}, "minus"},
	{std::regex{R"(\*)"}, "star"},
	{std::regex{"/"}, "slash"},
	{std::regex{"%"}, "percent"},
	{std::regex{R"(\()"}, "opening_parenthesis"},
	{std::regex{R"(\))"}, "closing_parenthesis"},
	{std::regex{","}, "comma"},
	{std::regex{R"(\d+(?:\.\d+)?(?:e-?\d+)?)"}, "number"},
	{std::regex{R"([A-Za-z_]\w*)"}, "identifier"},
	{std::regex{R"(\s+)"}, "whitespace"}
};

BETTER_ENUM(entity_type, std::uint8_t, symbol, token, eoi)

template<entity_type::_integral type>
struct unexpected_entity_exception final: std::runtime_error {
	static_assert(entity_type::_is_valid(type));

	explicit unexpected_entity_exception(const std::size_t& offset);
};

template<entity_type::_integral type>
unexpected_entity_exception<type>::unexpected_entity_exception(
	const std::size_t& offset
):
	std::runtime_error{fmt::format(
		"unexpected {:s} (offset: {:d})",
		entity_type::_from_integral(type)._to_string(),
		offset
	)}
{}

void stop(const int& code, std::ostream& stream, const std::string& message) {
	stream << fmt::format("{:s}\n", message);
	std::exit(code);
}

parser::rule_parser::pointer make_parser() {
	const auto expression_dummy = parser::dummy();
	RULE(function_call) = "identifier"_t >> &"("_v >>
		-(expression_dummy >> *(&","_v >> expression_dummy))
	>> &")"_v;
	RULE(atom) = "number"_t
		| function_call
		| "identifier"_t
		| (&"("_v >> expression_dummy >> &")"_v);
	RULE(unary) = *("-"_v) >> atom;
	RULE(product) = unary >> *(("*"_v | "/"_v | "%"_v) >> unary);
	RULE(sum) = product >> *(("+"_v | "-"_v) >> product);
	expression_dummy->set_parser(sum);

	return sum;
}

parser::ast_node walk_ast(
	const parser::ast_node& ast,
	const std::function<parser::ast_node(const parser::ast_node&)>& handler
) {
	const auto new_ast = handler(ast);
	const auto new_children = new_ast.children
		| ranges::view::transform([&] (const auto& ast) {
			return walk_ast(ast, handler);
		});
	return {new_ast.type, new_ast.value, new_children, new_ast.offset};
}

int main(int argc, char* argv[]) try {
	const auto options = docopt::docopt(usage, {argv+1, argv+argc}, true);
	const auto code = options.at("--stdin").asBool()
		? std::string{std::istreambuf_iterator<char>{std::cin}, {}}
		: options.at("<expression>").asString();
	const auto [tokens, rest_offset] = lexer::tokenize(lexemes, code);
	if (rest_offset != code.size()) {
		throw unexpected_entity_exception<entity_type::symbol>{rest_offset};
	}

	auto cleaned_tokens = tokens
		| ranges::view::filter([] (const auto& token) {
			return token.type != "whitespace";
		})
		| ranges::to_<lexer::token_group>();
	if (options.at("--target") == "tokens"s) {
		stop(EXIT_SUCCESS, std::cout, nlohmann::json(cleaned_tokens).dump());
	}

	const auto ast = make_parser()->parse(cleaned_tokens);
	if (!ast.rest_tokens.empty()) {
		throw unexpected_entity_exception<entity_type::token>{
			get_offset(ast.rest_tokens)
		};
	}
	if (!ast.node) {
		throw unexpected_entity_exception<entity_type::eoi>{code.size()};
	}

	auto transformed_ast = walk_ast(*ast.node, [&] (const auto& ast) {
		const auto offset = ast.offset == utilities::integral_infinity
			? code.size()
			: ast.offset;
		return parser::ast_node{ast.type, ast.value, ast.children, offset};
	});
	transformed_ast = walk_ast(transformed_ast, [] (const auto& ast) {
		const auto type = (+parser::ast_node_type::nothing)._to_string();
		const auto new_children = ast.children
			| ranges::view::filter([&] (const auto& ast) { return ast.type != type; })
			| ranges::to_<parser::ast_node_group>();
		return parser::ast_node{ast.type, ast.value, new_children, ast.offset};
	});
	transformed_ast = walk_ast(transformed_ast, [] (const auto& ast) {
		const auto type = (+parser::ast_node_type::sequence)._to_string();
		if (ast.type != type) {
			return ast;
		}

		const auto new_children_set = ast.children
			| ranges::view::transform([&] (const auto& ast) {
				return ast.type == type ? ast.children : parser::ast_node_group{ast};
			})
			| ranges::to_<std::vector<parser::ast_node_group>>();
		const auto new_children = new_children_set
			| ranges::view::join
			| ranges::to_<parser::ast_node_group>();
		return parser::ast_node{ast.type, ast.value, new_children, ast.offset};
	});
	if (options.at("--target") == "cst"s) {
		stop(EXIT_SUCCESS, std::cout, nlohmann::json(transformed_ast).dump());
	}

	throw std::runtime_error("not implemented yet");
} catch (const std::exception& exception) {
	stop(EXIT_FAILURE, std::cerr, fmt::format("error: {:s}", exception.what()));
}
<|endoftext|>


<commit_before><commit_msg>Remove TestPasswordManager from password_manager_unittest.cc<commit_after><|endoftext|>


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

#include "IECore/MeshPrimitive.h"

#include "IECoreAlembic/FromAlembicXFormConverter.h"

using namespace IECore;
using namespace IECoreAlembic;
using namespace Alembic::AbcGeom;

FromAlembicXFormConverter::ConverterDescription<FromAlembicXFormConverter> FromAlembicXFormConverter::g_description;

IE_CORE_DEFINERUNTIMETYPED( FromAlembicXFormConverter );

FromAlembicXFormConverter::FromAlembicXFormConverter( Alembic::Abc::IObject iXForm )
	:	FromAlembicConverter( "Converts AbcGeom::IXForm objects to IECore::M44f objects", iXForm )
{
}

IECore::ObjectPtr FromAlembicXFormConverter::doAlembicConversion( const Alembic::Abc::IObject &iObject, const Alembic::Abc::ISampleSelector &sampleSelector, const IECore::CompoundObject *operands ) const
{
	IXform iXForm( iObject, kWrapExisting );
	IXformSchema &iXFormSchema = iXForm.getSchema();
	XformSample sample;
	iXFormSchema.get( sample, sampleSelector );
	return new M44fData( M44f( sample.getMatrix() ) );
}
<commit_msg>Fixing to work with Imath versions which don't define an M44f( const M44d & ) constructor.<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2012, John Haddon. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//     * Redistributions of source code must retain the above copyright
//       notice, this list of conditions and the following disclaimer.
//
//     * 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.
//
//     * Neither the name of Image Engine Design nor the names of any
//       other contributors to this software may be used to endorse or
//       promote products derived from this software without specific prior
//       written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "IECore/MeshPrimitive.h"

#include "IECoreAlembic/FromAlembicXFormConverter.h"

using namespace IECore;
using namespace IECoreAlembic;
using namespace Alembic::AbcGeom;

FromAlembicXFormConverter::ConverterDescription<FromAlembicXFormConverter> FromAlembicXFormConverter::g_description;

IE_CORE_DEFINERUNTIMETYPED( FromAlembicXFormConverter );

FromAlembicXFormConverter::FromAlembicXFormConverter( Alembic::Abc::IObject iXForm )
	:	FromAlembicConverter( "Converts AbcGeom::IXForm objects to IECore::M44f objects", iXForm )
{
}

IECore::ObjectPtr FromAlembicXFormConverter::doAlembicConversion( const Alembic::Abc::IObject &iObject, const Alembic::Abc::ISampleSelector &sampleSelector, const IECore::CompoundObject *operands ) const
{
	IXform iXForm( iObject, kWrapExisting );
	IXformSchema &iXFormSchema = iXForm.getSchema();
	XformSample sample;
	iXFormSchema.get( sample, sampleSelector );
	M44d m = sample.getMatrix();
	return new M44fData(
		M44f(
			m[0][0], m[0][1], m[0][2], m[0][3],
			m[1][0], m[1][1], m[1][2], m[1][3],
			m[2][0], m[2][1], m[2][2], m[2][3],
			m[3][0], m[3][1], m[3][2], m[3][3]
		)
	);
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ObjectCounter.h"

#include <boost/thread/mutex.hpp>

#include <assert.h>
#include <iostream>
#include <sstream>

#ifdef WIN32
#include <windows.h>
#include <Dbghelp.h>
#else
#include <cxxabi.h>
#endif

#define DEBUG_ALLOC 1

namespace avg {

using namespace std;

ObjectCounter* ObjectCounter::m_pObjectCounter = 0;
boost::mutex * pCounterMutex;

ObjectCounter::ObjectCounter()
{
}

ObjectCounter::~ObjectCounter()
{
}

ObjectCounter * ObjectCounter::get()
{
    if (!m_pObjectCounter) {
        m_pObjectCounter = new ObjectCounter;
        pCounterMutex = new boost::mutex;
    }
    return m_pObjectCounter;
}

void ObjectCounter::incRef(const std::type_info* pType)
{
#ifdef DEBUG_ALLOC
    boost::mutex::scoped_lock Lock(*pCounterMutex);
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        m_TypeMap[pType] = 1;
    } else {
        (MapEntry->second)++;
    }
//    cerr << "incRef " << demangle(pType->name()) << ":" << m_TypeMap[pType] << endl;
#endif
}

void ObjectCounter::decRef(const std::type_info* pType)
{
#ifdef DEBUG_ALLOC
    boost::mutex::scoped_lock Lock(*pCounterMutex);
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        // Can't decref a type that hasn't been incref'd.
        assert (false);
    } else {
        (MapEntry->second)--;
        if (MapEntry->second < 0) {
            cerr << "ObjectCounter: refcount for " <<
                    demangle(MapEntry->first->name()) <<
                    " < 0" << endl;
            assert (false);
        }
    }
//    cerr << "decRef " << demangle(pType->name()) << ":" << MapEntry->second << endl;
#endif
}

int ObjectCounter::getCount(const std::type_info* pType)
{
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        return 0;
    } else {
        return MapEntry->second;
    }

}

std::string ObjectCounter::dump()
{
    stringstream ss;
    ss << "Object dump: " << endl;
    TypeMap::iterator it;
    for (it = m_TypeMap.begin(); it != m_TypeMap.end(); ++it) {
        if (it->second > 0) {
            ss << "  " << demangle(it->first->name()) << ": " << it->second << endl;
        }
    }
    return ss.str();
}

string ObjectCounter::demangle(string s)
{
    int rc;
    string sResult;
#ifdef _WIN32
    char szDemangledName[2048];
    rc = int(UnDecorateSymbolName(s.c_str(), szDemangledName, sizeof(szDemangledName),
            UNDNAME_COMPLETE));
    if (rc) {
        sResult = szDemangledName;
    } else {
        int error = GetLastError();
        printf("UnDecorateSymbolName returned error %d\n", error);
        sResult = s;
    }
#else
    char * pszDemangled = abi::__cxa_demangle(s.c_str(), 0, 0, &rc);
    if (rc) {
        sResult = s;
    } else {
        sResult = pszDemangled;
    }
    if (pszDemangled) {
        free(pszDemangled);
    }
#endif
    return sResult;
}

}
<commit_msg>ObjectCounter now outputs a sorted dump.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ObjectCounter.h"

#include <boost/thread/mutex.hpp>

#include <assert.h>
#include <iostream>
#include <sstream>
#include <vector>
#include <algorithm>

#ifdef WIN32
#include <windows.h>
#include <Dbghelp.h>
#else
#include <cxxabi.h>
#endif

#define DEBUG_ALLOC 1

namespace avg {

using namespace std;

ObjectCounter* ObjectCounter::m_pObjectCounter = 0;
boost::mutex * pCounterMutex;

ObjectCounter::ObjectCounter()
{
}

ObjectCounter::~ObjectCounter()
{
}

ObjectCounter * ObjectCounter::get()
{
    if (!m_pObjectCounter) {
        m_pObjectCounter = new ObjectCounter;
        pCounterMutex = new boost::mutex;
    }
    return m_pObjectCounter;
}

void ObjectCounter::incRef(const std::type_info* pType)
{
#ifdef DEBUG_ALLOC
    boost::mutex::scoped_lock Lock(*pCounterMutex);
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        m_TypeMap[pType] = 1;
    } else {
        (MapEntry->second)++;
    }
//    cerr << "incRef " << demangle(pType->name()) << ":" << m_TypeMap[pType] << endl;
#endif
}

void ObjectCounter::decRef(const std::type_info* pType)
{
#ifdef DEBUG_ALLOC
    boost::mutex::scoped_lock Lock(*pCounterMutex);
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        // Can't decref a type that hasn't been incref'd.
        assert (false);
    } else {
        (MapEntry->second)--;
        if (MapEntry->second < 0) {
            cerr << "ObjectCounter: refcount for " <<
                    demangle(MapEntry->first->name()) <<
                    " < 0" << endl;
            assert (false);
        }
    }
//    cerr << "decRef " << demangle(pType->name()) << ":" << MapEntry->second << endl;
#endif
}

int ObjectCounter::getCount(const std::type_info* pType)
{
    TypeMap::iterator MapEntry = m_TypeMap.find(pType);
    if (MapEntry == m_TypeMap.end()) {
        return 0;
    } else {
        return MapEntry->second;
    }

}

std::string ObjectCounter::dump()
{
    stringstream ss;
    ss << "Object dump: " << endl;
    TypeMap::iterator it;
    vector<string> strings;
    for (it = m_TypeMap.begin(); it != m_TypeMap.end(); ++it) {
        stringstream tempStream;
        if (it->second > 0) {
            tempStream << "  " << demangle(it->first->name()) << ": " << it->second;
            strings.push_back(tempStream.str());
        }
    }
    sort(strings.begin(), strings.end());
    for (vector<string>::iterator it=strings.begin(); it != strings.end(); ++it) {
        ss << *it << endl;
    }
    return ss.str();
}

string ObjectCounter::demangle(string s)
{
    int rc;
    string sResult;
#ifdef _WIN32
    char szDemangledName[2048];
    rc = int(UnDecorateSymbolName(s.c_str(), szDemangledName, sizeof(szDemangledName),
            UNDNAME_COMPLETE));
    if (rc) {
        sResult = szDemangledName;
    } else {
        int error = GetLastError();
        printf("UnDecorateSymbolName returned error %d\n", error);
        sResult = s;
    }
#else
    char * pszDemangled = abi::__cxa_demangle(s.c_str(), 0, 0, &rc);
    if (rc) {
        sResult = s;
    } else {
        sResult = pszDemangled;
    }
    if (pszDemangled) {
        free(pszDemangled);
    }
#endif
    return sResult;
}

}
<|endoftext|>