<commit_before>/* FILE: CarbonDioxide.cpp
 * DESCRIPTION:
 *  representation of substance Carbon Dioxide
 *  values and functions are from
 *  "Thermodynamic Properties in SI" bu W.C. Reynolds
 * AUTHOR: me@rebeccahhunt.com: GCEP, Stanford University
 *
 */

#include "CarbonDioxide.h"
#include <math.h>
#include <string.h>

namespace tpx
{

/*
 * Carbon Dioxide constants
 */
static const double Tmn = 216.54;   // [K] minimum temperature for which calculations are valid
static const double Tmx = 1500.0;   // [K] maximum temperature for which calculations are valid
static const double Tc=304.21;      // [K] critical temperature
static const double Roc=464.00;        // [kg/m^3] critical density
static const double To=216.54;        // [K] reference Temperature
static const double R=188.918;        // [] gas constant for CO2 J/kg/K
static const double Gamma=5.0E-6;    // [??]
static const double u0=3.217405E5;    // [] internal energy at To
static const double s0=2.1396056E3;    // [] entropy at To
static const double Tp=250;            // [K] ??
//static const double Pc=7.38350E6;    // [Pa] critical pressure
static const double Pc=7.3817589E6;   // Adjusted to fit the actual functional form
static const double M=44.01;        // [kg/kmol] molar density

/*
 * array Acarbdi is used by the function named Pp
 */
static const double Acarbdi[]= {
    2.2488558E-1,
    -1.3717965E2,
    -1.4430214E4,
    -2.9630491E6,
    -2.0606039E8,
    4.5554393E-5,
    7.7042840E-2,
    4.0602371E1,
    4.0029509E-7,
    -3.9436077E-4,
    1.2115286E-10,
    1.0783386E-7,
    4.3962336E-11,
    -3.6505545E4,
    1.9490511E7,
    -2.9186718E9,
    2.4358627E-2,
    -3.7546530E1,
    1.1898141E4
};

/*
 * array F is used by the function named Psat
 */
static const double F[]= {
    -6.5412610,
    -2.7914636E-1,
    -3.4716202,
    -3.4989637,
    -1.9770948E1,
    1.3922839E2,
    -2.7670389E2,
    -7.0510251E3
};

/*
 * array D is used by the function ldens
 */
static const double D[]= {
    4.6400009E2,
    6.7938129E2,
    1.4776836E3,
    -3.1267676E3,
    3.6397656E3,
    -1.3437098E3
};

/*
 * array G is used by the function sp
 */
static const double G[]= {
    8.726361E3,
    1.840040E2,
    1.914025,
    -1.667825E-3,
    7.305950E-7,
    -1.255290E-10,
    3.2174105E5,
    2.1396056E3

};

/*
 * C returns a multiplier in each term of the sum
 * in P-3, used in conjunction with C in the function Pp
 * j is used to represent which of the values in the summation to calculate
 * j=0 is the second additive in the formula in reynolds
 * j=1 is the third...
 * (this part does not include the multiplier rho^n)
 */
double CarbonDioxide::C(int j,double Tinverse, double T2inverse, double T3inverse, double T4inverse)
{
    switch (j) {
    case 0 :
        return    Acarbdi[0]*T            +
                  Acarbdi[1]                +
                  Acarbdi[2] * Tinverse    +
                  Acarbdi[3] * T2inverse    +
                  Acarbdi[4] * T3inverse ;
    case 1 :
        return    Acarbdi[5] *T            +
                  Acarbdi[6]                +
                  Acarbdi[7] * Tinverse ;
    case 2 :
        return Acarbdi[8]*T + Acarbdi[9];
    case 3 :
        return Acarbdi[10]*T  + Acarbdi[11];
    case 4 :
        return Acarbdi[12];
    case 5 :
        return    Acarbdi[13] *T2inverse    +
                  Acarbdi[14] *T3inverse    +
                  Acarbdi[15] *T4inverse;
    case 6 :
        return    Acarbdi[16] *T2inverse    +
                  Acarbdi[17] *T3inverse    +
                  Acarbdi[18] *T4inverse;
    default :
        return 0.0;
    }
}

/* cprime
 * derivative of C(i)
 */
inline double CarbonDioxide::Cprime(int j, double T2inverse, double T3inverse, double T4inverse)
{

    switch (j) {
    case 0 :
        return    Acarbdi[0]     +
                  - Acarbdi[2] * T2inverse    +
                  -2 * Acarbdi[3] * T3inverse    +
                  -3 * Acarbdi[4] * T4inverse ;
    case 1 :
        return    Acarbdi[5]     -
                  Acarbdi[7] * T2inverse;
    case 2 :
        return  Acarbdi[8] ;
    case 3 :
        return    Acarbdi[10] ;
    case 4 :
        return    0;
    case 5 :
        return
            -2 *Acarbdi[13] *T3inverse    +
            -3 *Acarbdi[14] *T4inverse    +
            -4 *Acarbdi[15]* pow(T,-5);
    case 6 :
        return
            -2 *Acarbdi[16] *T3inverse    +
            -3 *Acarbdi[17] *T4inverse    +
            -4 *Acarbdi[18] *pow(T,-5);
    default :
        return 0.0;
    }
}

/*
 * I = integral from o-rho { 1/(rho^2) * H(i, rho) d rho }
 * ( see section 2 of Reynolds TPSI )
 */
inline double CarbonDioxide::I(int j, double ergho, double Gamma)
{
    switch (j) {

    case 0:
        return Rho;
    case 1:
        return pow(Rho, 2)/2;
    case 2:
        return pow(Rho, 3)/ 3;
    case 3:
        return pow(Rho, 4)/ 4;
    case 4:
        return pow(Rho, 5)/ 5;
    case 5:
        return (1 - ergho) / double(2 * Gamma);
    case 6:
        return (1 - ergho * double(Gamma * pow(Rho,2) + double(1)))/ double(2 * Gamma * Gamma);
    default:
        return 0.0;
    }
}

/* H returns a multiplier in each term of the sum
 * in P-3
 * this is used in conjunction with C in the function Pp
 * this represents the product rho^n
 * i=0 is the second additive in the formula in reynolds
 * i=1 is the third ...
 */
double CarbonDioxide::H(int i, double egrho)
{
    if (i < 5) {
        return pow(Rho,i+2);
    } else if (i == 5) {
        return pow(Rho,3)*egrho;
    } else if (i == 6) {
        return pow(Rho,5)*egrho;
    } else {
        return 0;
    }
}

/*
 * internal energy
 *  see Reynolds eqn (15) section 2
 *  u = (the integral from T to To of co(T)dT) +
 *         sum from i to N ([C(i) - T*Cprime(i)] + uo
 */
double CarbonDioxide::up()
{

    double Tinverse = 1.0/T;
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double sum = 0.0;

    // Equation C-6 integrated
    sum += G[0]*log(T/To);
    int i;
    for (i=1; i<=5; i++) {
        sum += G[i]*(pow(T,i) - pow(To,i))/double(i);
    }

    for (i=0; i<=6; i++) {
        sum += I(i,egrho, Gamma) *
               (C(i, Tinverse, T2inverse, T3inverse, T4inverse) - T*Cprime(i,T2inverse, T3inverse, T4inverse));
    }

    sum += u0;
    return sum + m_energy_offset;

}

/*
*  entropy
 *  see Reynolds eqn (16) section 2
*/

double CarbonDioxide::sp()
{
    //double Tinverse = 1.0/T;
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double sum = 0.0;

    for (int i=2; i<=5; i++) {
        sum += G[i]*(pow(T,i-1) - pow(To,i-1))/double(i-1);
    }

    sum += G[1]*log(T/To);
    sum -= G[0]*(1.0/To - 1.0/T);

    for (int i=0; i<=6; i++) {
        sum -= Cprime(i,T2inverse, T3inverse, T4inverse)*I(i,egrho,Gamma);
    }

    sum += s0 - R*log(Rho);

    return sum + m_entropy_offset;
}

/*
 * Equation P-3 in Reynolds
 * P - rho - T
 * returns P (pressure)
 */
double CarbonDioxide::Pp()
{
    double Tinverse = pow(T,-1);
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double P = Rho*R*T;

    // when i=0 we are on second sum of equation (where rho^2)
    for (int i=0; i<=6; i++) {
        P += C(i,Tinverse, T2inverse, T3inverse, T4inverse)*H(i,egrho);
    }
    return P;
}

/*
 * Equation S-2 in Reynolds
 * Pressure at Saturation
 */
double CarbonDioxide::Psat()
{

    double log, sum=0,P;
    if ((T < Tmn) || (T > Tc)) {
        std::cout << " error in Psat " << TempError << std::endl;
        set_Err(TempError); // Error("CarbonDioxide::Psat",TempError,T);
    }
    for (int i=1; i<=8; i++) {
        sum += F[i-1] * pow((T/Tp -1),double(i-1));
    }

    log = ((Tc/T)-1)*sum;
    P=exp(log)*Pc;

    //cout << "Psat is returning " << P << " at T " << T << " and Pc " << Pc << " and Tp " << Tp << endl;
    return P;

}

/*
 * Equation D2 in Reynolds
 * liquid density, of rho_f
 */
double CarbonDioxide::ldens()
{
    double xx=1-(T/Tc), sum=0;
    if ((T < Tmn) || (T > Tc)) {
        std::cout << " error in ldens " << TempError << std::endl;
        set_Err(TempError);
    }
    for (int i=1; i<=6; i++) {
        sum+=D[i-1]*pow(xx,double(i-1)/3.0);
    }

    return sum;
}

/*
 * the following functions allow users
 * to get the properties of CarbonDioxide
 * that are not dependent on the state
 */
double CarbonDioxide::Tcrit()
{
    return Tc;
}
double CarbonDioxide::Pcrit()
{
    return Pc;
}
double CarbonDioxide::Vcrit()
{
    return 1.0/Roc;
}
double CarbonDioxide::Tmin()
{
    return Tmn;
}
double CarbonDioxide::Tmax()
{
    return Tmx;
}
char* CarbonDioxide::name()
{
    return (char*) m_name.c_str() ;
}
char* CarbonDioxide::formula()
{
    return (char*) m_formula.c_str();
}
double CarbonDioxide::MolWt()
{
    return M;
}

}

<commit_msg>Fixed errors in implementation of carbon dioxide equation of state<commit_after>/* FILE: CarbonDioxide.cpp
 * DESCRIPTION:
 *  representation of substance Carbon Dioxide
 *  values and functions are from
 *  "Thermodynamic Properties in SI" bu W.C. Reynolds
 * AUTHOR: me@rebeccahhunt.com: GCEP, Stanford University
 *
 */

#include "CarbonDioxide.h"
#include <math.h>
#include <string.h>

namespace tpx
{

/*
 * Carbon Dioxide constants
 */
static const double Tmn = 216.54;   // [K] minimum temperature for which calculations are valid
static const double Tmx = 1500.0;   // [K] maximum temperature for which calculations are valid
static const double Tc=304.21;      // [K] critical temperature
static const double Roc=464.00;        // [kg/m^3] critical density
static const double To=216.54;        // [K] reference Temperature
static const double R=188.918;        // [] gas constant for CO2 J/kg/K
static const double Gamma=5.0E-6;    // [??]
static const double u0=3.2174105E5;    // [] internal energy at To
static const double s0=2.1396056E3;    // [] entropy at To
static const double Tp=250;            // [K] ??
static const double Pc=7.38350E6;    // [Pa] critical pressure
static const double M=44.01;        // [kg/kmol] molar density

/*
 * array Acarbdi is used by the function named Pp
 */
static const double Acarbdi[]= {
    2.2488558E-1,
    -1.3717965E2,
    -1.4430214E4,
    -2.9630491E6,
    -2.0606039E8,
    4.5554393E-5,
    7.7042840E-2,
    4.0602371E1,
    4.0029509E-7,
    -3.9436077E-4,
    1.2115286E-10,
    1.0783386E-7,
    4.3962336E-11,
    -3.6505545E4,
    1.9490511E7,
    -2.9186718E9,
    2.4358627E-2,
    -3.7546530E1,
    1.1898141E4
};

/*
 * array F is used by the function named Psat
 */
static const double F[]= {
    -6.5412610,
    -2.7914636E-1,
    -3.4716202,
    -3.4989637,
    -1.9770948E1,
    1.3922839E2,
    -2.7670389E2,
    -7.0510251E3
};

/*
 * array D is used by the function ldens
 */
static const double D[]= {
    4.6400009E2,
    6.7938129E2,
    1.4776836E3,
    -3.1267676E3,
    3.6397656E3,
    -1.3437098E3
};

/*
 * array G is used by the function sp
 */
static const double G[]= {
    8.726361E3,
    1.840040E2,
    1.914025,
    -1.667825E-3,
    7.305950E-7,
    -1.255290E-10,
};

/*
 * C returns a multiplier in each term of the sum
 * in P-3, used in conjunction with C in the function Pp
 * j is used to represent which of the values in the summation to calculate
 * j=0 is the second additive in the formula in reynolds
 * j=1 is the third...
 * (this part does not include the multiplier rho^n)
 */
double CarbonDioxide::C(int j,double Tinverse, double T2inverse, double T3inverse, double T4inverse)
{
    switch (j) {
    case 0 :
        return    Acarbdi[0]*T            +
                  Acarbdi[1]                +
                  Acarbdi[2] * Tinverse    +
                  Acarbdi[3] * T2inverse    +
                  Acarbdi[4] * T3inverse ;
    case 1 :
        return    Acarbdi[5] *T            +
                  Acarbdi[6]                +
                  Acarbdi[7] * Tinverse ;
    case 2 :
        return Acarbdi[8]*T + Acarbdi[9];
    case 3 :
        return Acarbdi[10]*T  + Acarbdi[11];
    case 4 :
        return Acarbdi[12];
    case 5 :
        return    Acarbdi[13] *T2inverse    +
                  Acarbdi[14] *T3inverse    +
                  Acarbdi[15] *T4inverse;
    case 6 :
        return    Acarbdi[16] *T2inverse    +
                  Acarbdi[17] *T3inverse    +
                  Acarbdi[18] *T4inverse;
    default :
        return 0.0;
    }
}

/* cprime
 * derivative of C(i)
 */
inline double CarbonDioxide::Cprime(int j, double T2inverse, double T3inverse, double T4inverse)
{

    switch (j) {
    case 0 :
        return    Acarbdi[0]     +
                  - Acarbdi[2] * T2inverse    +
                  -2 * Acarbdi[3] * T3inverse    +
                  -3 * Acarbdi[4] * T4inverse ;
    case 1 :
        return    Acarbdi[5]     -
                  Acarbdi[7] * T2inverse;
    case 2 :
        return  Acarbdi[8] ;
    case 3 :
        return    Acarbdi[10] ;
    case 4 :
        return    0;
    case 5 :
        return
            -2 *Acarbdi[13] *T3inverse    +
            -3 *Acarbdi[14] *T4inverse    +
            -4 *Acarbdi[15]* pow(T,-5);
    case 6 :
        return
            -2 *Acarbdi[16] *T3inverse    +
            -3 *Acarbdi[17] *T4inverse    +
            -4 *Acarbdi[18] *pow(T,-5);
    default :
        return 0.0;
    }
}

/*
 * I = integral from o-rho { 1/(rho^2) * H(i, rho) d rho }
 * ( see section 2 of Reynolds TPSI )
 */
inline double CarbonDioxide::I(int j, double ergho, double Gamma)
{
    switch (j) {

    case 0:
        return Rho;
    case 1:
        return pow(Rho, 2)/2;
    case 2:
        return pow(Rho, 3)/ 3;
    case 3:
        return pow(Rho, 4)/ 4;
    case 4:
        return pow(Rho, 5)/ 5;
    case 5:
        return (1 - ergho) / double(2 * Gamma);
    case 6:
        return (1 - ergho * double(Gamma * pow(Rho,2) + double(1)))/ double(2 * Gamma * Gamma);
    default:
        return 0.0;
    }
}

/* H returns a multiplier in each term of the sum
 * in P-3
 * this is used in conjunction with C in the function Pp
 * this represents the product rho^n
 * i=0 is the second additive in the formula in reynolds
 * i=1 is the third ...
 */
double CarbonDioxide::H(int i, double egrho)
{
    if (i < 5) {
        return pow(Rho,i+2);
    } else if (i == 5) {
        return pow(Rho,3)*egrho;
    } else if (i == 6) {
        return pow(Rho,5)*egrho;
    } else {
        return 0;
    }
}

/*
 * internal energy
 *  see Reynolds eqn (15) section 2
 *  u = (the integral from T to To of co(T)dT) +
 *         sum from i to N ([C(i) - T*Cprime(i)] + uo
 */
double CarbonDioxide::up()
{

    double Tinverse = 1.0/T;
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double sum = 0.0;

    // Equation C-6 integrated
    sum += G[0]*log(T/To);
    int i;
    for (i=1; i<=5; i++) {
        sum += G[i]*(pow(T,i) - pow(To,i))/double(i);
    }

    for (i=0; i<=6; i++) {
        sum += I(i,egrho, Gamma) *
               (C(i, Tinverse, T2inverse, T3inverse, T4inverse) - T*Cprime(i,T2inverse, T3inverse, T4inverse));
    }

    sum += u0;
    return sum + m_energy_offset;

}

/*
*  entropy
 *  see Reynolds eqn (16) section 2
*/

double CarbonDioxide::sp()
{
    //double Tinverse = 1.0/T;
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double sum = 0.0;

    for (int i=2; i<=5; i++) {
        sum += G[i]*(pow(T,i-1) - pow(To,i-1))/double(i-1);
    }

    sum += G[1]*log(T/To);
    sum -= G[0]*(1.0/T - 1.0/To);

    for (int i=0; i<=6; i++) {
        sum -= Cprime(i,T2inverse, T3inverse, T4inverse)*I(i,egrho,Gamma);
    }

    sum += s0 - R*log(Rho);

    return sum + m_entropy_offset;
}

/*
 * Equation P-3 in Reynolds
 * P - rho - T
 * returns P (pressure)
 */
double CarbonDioxide::Pp()
{
    double Tinverse = pow(T,-1);
    double T2inverse = pow(T, -2);
    double T3inverse = pow(T, -3);
    double T4inverse = pow(T, -4);
    double egrho = exp(-Gamma*Rho*Rho);

    double P = Rho*R*T;

    // when i=0 we are on second sum of equation (where rho^2)
    for (int i=0; i<=6; i++) {
        P += C(i,Tinverse, T2inverse, T3inverse, T4inverse)*H(i,egrho);
    }
    return P;
}

/*
 * Equation S-2 in Reynolds
 * Pressure at Saturation
 */
double CarbonDioxide::Psat()
{

    double log, sum=0,P;
    if ((T < Tmn) || (T > Tc)) {
        std::cout << " error in Psat " << TempError << std::endl;
        set_Err(TempError); // Error("CarbonDioxide::Psat",TempError,T);
    }
    for (int i=1; i<=8; i++) {
        sum += F[i-1] * pow((T/Tp -1),double(i-1));
    }

    log = ((Tc/T)-1)*sum;
    P=exp(log)*Pc;

    //cout << "Psat is returning " << P << " at T " << T << " and Pc " << Pc << " and Tp " << Tp << endl;
    return P;

}

/*
 * Equation D2 in Reynolds
 * liquid density, of rho_f
 */
double CarbonDioxide::ldens()
{
    double xx=1-(T/Tc), sum=0;
    if ((T < Tmn) || (T > Tc)) {
        std::cout << " error in ldens " << TempError << std::endl;
        set_Err(TempError);
    }
    for (int i=1; i<=6; i++) {
        sum+=D[i-1]*pow(xx,double(i-1)/3.0);
    }

    return sum;
}

/*
 * the following functions allow users
 * to get the properties of CarbonDioxide
 * that are not dependent on the state
 */
double CarbonDioxide::Tcrit()
{
    return Tc;
}
double CarbonDioxide::Pcrit()
{
    return Pc;
}
double CarbonDioxide::Vcrit()
{
    return 1.0/Roc;
}
double CarbonDioxide::Tmin()
{
    return Tmn;
}
double CarbonDioxide::Tmax()
{
    return Tmx;
}
char* CarbonDioxide::name()
{
    return (char*) m_name.c_str() ;
}
char* CarbonDioxide::formula()
{
    return (char*) m_formula.c_str();
}
double CarbonDioxide::MolWt()
{
    return M;
}

}

<|endoftext|>


<commit_before>#include "unittest/gtest.hpp"
#include "unittest/server_test_helper.hpp"
#include "unittest/unittest_utils.hpp"
#include "buffer_cache/blob.hpp"

namespace unittest {

class blob_tracker_t {
public:
    blob_tracker_t(block_size_t block_size, size_t maxreflen)
        : expected_("\0"), blob_(block_size, expected_.c_str(), maxreflen) {
        // That's a bit of a hack, because blob_ will only read the
        // first byte or first two bytes if they are zero.
        expected_.clear();
    }

    void check_region(transaction_t *txn, int64_t offset, int64_t size) {
        ASSERT_LE(0, offset);
        ASSERT_LE(offset, expected_.size());
        ASSERT_LE(0, size);
        ASSERT_LE(offset + size, expected_.size());

        ASSERT_EQ(expected_.size(), blob_.valuesize());

        buffer_group_t bg;
        blob_acq_t bacq;
        blob_.expose_region(txn, rwi_read, offset, size, &bg, &bacq);

        ASSERT_EQ(size, bg.get_size());

        std::string::iterator p_orig = expected_.begin() + offset, p = p_orig, e = p + size;
        for (size_t i = 0, n = bg.num_buffers(); i < n; ++i) {
            buffer_group_t::buffer_t buffer = bg.get_buffer(i);
            ASSERT_LE(buffer.size, e - p);
            char *data = reinterpret_cast<char *>(buffer.data);
            ASSERT_TRUE(std::equal(data, data + buffer.size, p));
            p += buffer.size;
        }

        ASSERT_EQ(e - p_orig, p - p_orig);
    }

    void check(transaction_t *txn) {
        check_region(txn, 0, expected_.size());
    }

    void append(transaction_t *txn, const std::string& x) {
        int64_t n = x.size();

        blob_.append_region(txn, n);

        ASSERT_EQ(expected_.size() + n, blob_.valuesize());

        {
            buffer_group_t bg;
            blob_acq_t bacq;
            blob_.expose_region(txn, rwi_write, expected_.size(), n, &bg, &bacq);

            ASSERT_EQ(n, bg.get_size());

            const_buffer_group_t copyee;
            copyee.add_buffer(x.size(), x.data());

            buffer_group_copy_data(&bg, &copyee);

            expected_ += x;
        }

        check(txn);
    }

    void prepend(transaction_t *txn, const std::string& x) {
        int64_t n = x.size();

        blob_.prepend_region(txn, n);

        ASSERT_EQ(n + expected_.size(), blob_.valuesize());

        {
            buffer_group_t bg;
            blob_acq_t bacq;
            blob_.expose_region(txn, rwi_write, expected_.size(), n, &bg, &bacq);

            ASSERT_EQ(n, bg.get_size());

            const_buffer_group_t copyee;
            copyee.add_buffer(x.size(), x.data());

            buffer_group_copy_data(&bg, &copyee);

            expected_ = x + expected_;
        }

        check(txn);
    }

    void unprepend(transaction_t *txn, int64_t n) {
        ASSERT_LE(n, expected_.size());

        blob_.unprepend_region(txn, n);
        expected_.erase(0, n);

        check(txn);
    }

    void unappend(transaction_t *txn, int64_t n) {
        ASSERT_LE(n, expected_.size());

        blob_.unappend_region(txn, n);
        expected_.erase(expected_.size() - n);

        check(txn);
    }

private:
    std::string expected_;
    blob_t blob_;
};

struct blob_tester_t : public server_test_helper_t {
protected:
    void run_tests(cache_t *cache) {
        small_value_test(cache);
    }

private:
    void small_value_test(cache_t *cache) {
        block_size_t block_size = cache->get_block_size();

        transaction_t txn(cache, rwi_write, 0, repli_timestamp_t::distant_past);

        blob_tracker_t tk(block_size, 251);

        tk.append(&txn, "a");
        tk.append(&txn, "b");
        tk.prepend(&txn, "c");
    }
};

TEST(BlobTest, all_tests) {
    blob_tester_t().run();
}

}  // namespace unittest
<commit_msg>Fixed bug in blob_tracker_t::prepend.<commit_after>#include "unittest/gtest.hpp"
#include "unittest/server_test_helper.hpp"
#include "unittest/unittest_utils.hpp"
#include "buffer_cache/blob.hpp"

namespace unittest {

class blob_tracker_t {
public:
    blob_tracker_t(block_size_t block_size, size_t maxreflen)
        : expected_("\0"), blob_(block_size, expected_.c_str(), maxreflen) {
        // That's a bit of a hack, because blob_ will only read the
        // first byte or first two bytes if they are zero.
        expected_.clear();
    }

    void check_region(transaction_t *txn, int64_t offset, int64_t size) {
        ASSERT_LE(0, offset);
        ASSERT_LE(offset, expected_.size());
        ASSERT_LE(0, size);
        ASSERT_LE(offset + size, expected_.size());

        ASSERT_EQ(expected_.size(), blob_.valuesize());

        buffer_group_t bg;
        blob_acq_t bacq;
        blob_.expose_region(txn, rwi_read, offset, size, &bg, &bacq);

        ASSERT_EQ(size, bg.get_size());

        std::string::iterator p_orig = expected_.begin() + offset, p = p_orig, e = p + size;
        for (size_t i = 0, n = bg.num_buffers(); i < n; ++i) {
            buffer_group_t::buffer_t buffer = bg.get_buffer(i);
            ASSERT_LE(buffer.size, e - p);
            char *data = reinterpret_cast<char *>(buffer.data);
            ASSERT_TRUE(std::equal(data, data + buffer.size, p));
            p += buffer.size;
        }

        ASSERT_EQ(e - p_orig, p - p_orig);
    }

    void check(transaction_t *txn) {
        check_region(txn, 0, expected_.size());
    }

    void append(transaction_t *txn, const std::string& x) {
        int64_t n = x.size();

        blob_.append_region(txn, n);

        ASSERT_EQ(expected_.size() + n, blob_.valuesize());

        {
            buffer_group_t bg;
            blob_acq_t bacq;
            blob_.expose_region(txn, rwi_write, expected_.size(), n, &bg, &bacq);

            ASSERT_EQ(n, bg.get_size());

            const_buffer_group_t copyee;
            copyee.add_buffer(x.size(), x.data());

            buffer_group_copy_data(&bg, &copyee);

            expected_ += x;
        }

        check(txn);
    }

    void prepend(transaction_t *txn, const std::string& x) {
        int64_t n = x.size();

        blob_.prepend_region(txn, n);

        ASSERT_EQ(n + expected_.size(), blob_.valuesize());

        {
            buffer_group_t bg;
            blob_acq_t bacq;
            blob_.expose_region(txn, rwi_write, 0, n, &bg, &bacq);

            ASSERT_EQ(n, bg.get_size());

            const_buffer_group_t copyee;
            copyee.add_buffer(x.size(), x.data());

            buffer_group_copy_data(&bg, &copyee);

            expected_ = x + expected_;
        }

        check(txn);
    }

    void unprepend(transaction_t *txn, int64_t n) {
        ASSERT_LE(n, expected_.size());

        blob_.unprepend_region(txn, n);
        expected_.erase(0, n);

        check(txn);
    }

    void unappend(transaction_t *txn, int64_t n) {
        ASSERT_LE(n, expected_.size());

        blob_.unappend_region(txn, n);
        expected_.erase(expected_.size() - n);

        check(txn);
    }

private:
    std::string expected_;
    blob_t blob_;
};

struct blob_tester_t : public server_test_helper_t {
protected:
    void run_tests(cache_t *cache) {
        small_value_test(cache);
    }

private:
    void small_value_test(cache_t *cache) {
        block_size_t block_size = cache->get_block_size();

        transaction_t txn(cache, rwi_write, 0, repli_timestamp_t::distant_past);

        blob_tracker_t tk(block_size, 251);

        tk.append(&txn, "a");
        tk.append(&txn, "b");
        tk.prepend(&txn, "c");
    }
};

TEST(BlobTest, all_tests) {
    blob_tester_t().run();
}

}  // namespace unittest
<|endoftext|>


<commit_before>#include <map>
#include "unittest/gtest.hpp"

#include "btree/loof_node.hpp"

struct short_value_t;

template <>
class value_sizer_t<short_value_t> {
public:
    value_sizer_t<short_value_t>(block_size_t bs) : block_size_(bs) { }

    int size(const short_value_t *value) const {
        int x = *reinterpret_cast<const uint8_t *>(value);
        return 1 + x;
    }

    bool fits(const short_value_t *value, int length_available) const {
        return length_available > 0 && size(value) <= length_available;
    }

    int max_possible_size() const {
        return 256;
    }

    static block_magic_t btree_leaf_magic() {
        block_magic_t magic = { { 's', 'h', 'L', 'F' } };
        return magic;
    }

    block_size_t block_size() const { return block_size_; }

private:
    block_size_t block_size_;

    DISABLE_COPYING(value_sizer_t<short_value_t>);
};

using loof::loof_t;

namespace unittest {

class short_value_buffer_t {
public:
    short_value_buffer_t(const std::string& v) {
        rassert(v.size() < 255);
        data_[0] = v.size();
        memcpy(data_ + 1, v.data(), v.size());
    }

    short_value_t *data() {
        return reinterpret_cast<short_value_t *>(data_);
    }

private:
    uint8_t data_[256];
};

class LoofTracker {
public:
    LoofTracker() : bs_(block_size_t::unsafe_make(4096)), sizer_(bs_), node_(reinterpret_cast<loof_t *>(new char[bs_.value()])),
                    tstamp_counter_(0) {
        loof::init(&sizer_, node_);
        Print();
    }
    ~LoofTracker() { delete[] node_; }

    bool Insert(const std::string& key, const std::string& value) {
        btree_key_buffer_t k(key.begin(), key.end());
        short_value_buffer_t v(value);

        if (loof::is_full(&sizer_, node_, k.key(), v.data())) {
            Print();
            return false;
        }

        repli_timestamp_t tstamp;
        loof::insert(&sizer_, node_, k.key(), v.data(), tstamp);

        kv_[key] = value;

        Print();
        return true;

        Verify();
    }

    repli_timestamp_t NextTimestamp() {
        tstamp_counter_ ++;
        repli_timestamp_t ret;
        ret.time = tstamp_counter_;
        return ret;
    }

    void Print() {
        // loof::print(stdout, &sizer_, node_);
    }

    void Verify() {
        if (!kv_.empty()) {
            ASSERT_EQ(tstamp_counter_, reinterpret_cast<repli_timestamp_t *>(loof::get_at_offset(node_, node_->frontmost))->time);
        }

        loof::validate(&sizer_, node_);
    }

private:
    block_size_t bs_;
    value_sizer_t<short_value_t> sizer_;
    loof_t *node_;

    int tstamp_counter_;

    std::map<std::string, std::string> kv_;

    DISABLE_COPYING(LoofTracker);
};

TEST(LoofTest, Offsets) {
    ASSERT_EQ(0, offsetof(loof_t, magic));
    ASSERT_EQ(4, offsetof(loof_t, num_pairs));
    ASSERT_EQ(6, offsetof(loof_t, live_size));
    ASSERT_EQ(8, offsetof(loof_t, frontmost));
    ASSERT_EQ(10, offsetof(loof_t, tstamp_cutpoint));
    ASSERT_EQ(12, offsetof(loof_t, pair_offsets));
    ASSERT_EQ(12, sizeof(loof_t));
}

TEST(LoofTest, Reinserts) {
    LoofTracker tracker;
    std::string v = "aa";
    std::string k = "key";
    for (; v[0] <= 'z'; ++v[0]) {
        v[1] = 'a';
        for (; v[1] <= 'z'; ++v[1]) {
            // printf("inserting %s\n", v.c_str());
            tracker.Insert(k, v);
        }
    }
}

TEST(LoofTest, FiveInserts) {
    LoofTracker tracker;

    std::string ks[5] = { "the_relatively_long_key_that_is_relatively_long,_eh?",
                          "some_other_relatively_long_key_that_...whatever.",
                          "another relatively long key",
                          "a short key",
                          "n" /* not an empty key */ };

    for (int i = 0; i < 26 * 26; ++i) {
        std::string v;
        v += ('a' + (i / 26));
        v += ('a' + (i % 26));

        for (int j = 0; j < 5; ++j) {
            tracker.Insert(ks[j], v);
        }
    }

}

}  // namespace unittest
<commit_msg>Moved Verify() to an actual reachable part of LoofTracker::Insert, which checks the timestamps, resulting in failed Reinserts test.<commit_after>#include <map>
#include "unittest/gtest.hpp"

#include "btree/loof_node.hpp"

struct short_value_t;

template <>
class value_sizer_t<short_value_t> {
public:
    value_sizer_t<short_value_t>(block_size_t bs) : block_size_(bs) { }

    int size(const short_value_t *value) const {
        int x = *reinterpret_cast<const uint8_t *>(value);
        return 1 + x;
    }

    bool fits(const short_value_t *value, int length_available) const {
        return length_available > 0 && size(value) <= length_available;
    }

    int max_possible_size() const {
        return 256;
    }

    static block_magic_t btree_leaf_magic() {
        block_magic_t magic = { { 's', 'h', 'L', 'F' } };
        return magic;
    }

    block_size_t block_size() const { return block_size_; }

private:
    block_size_t block_size_;

    DISABLE_COPYING(value_sizer_t<short_value_t>);
};

using loof::loof_t;

namespace unittest {

class short_value_buffer_t {
public:
    short_value_buffer_t(const std::string& v) {
        rassert(v.size() < 255);
        data_[0] = v.size();
        memcpy(data_ + 1, v.data(), v.size());
    }

    short_value_t *data() {
        return reinterpret_cast<short_value_t *>(data_);
    }

private:
    uint8_t data_[256];
};

class LoofTracker {
public:
    LoofTracker() : bs_(block_size_t::unsafe_make(4096)), sizer_(bs_), node_(reinterpret_cast<loof_t *>(new char[bs_.value()])),
                    tstamp_counter_(0) {
        loof::init(&sizer_, node_);
        Print();
    }
    ~LoofTracker() { delete[] node_; }

    bool Insert(const std::string& key, const std::string& value) {
        btree_key_buffer_t k(key.begin(), key.end());
        short_value_buffer_t v(value);

        if (loof::is_full(&sizer_, node_, k.key(), v.data())) {
            Print();

            Verify();
            return false;
        }

        repli_timestamp_t tstamp;
        loof::insert(&sizer_, node_, k.key(), v.data(), tstamp);

        kv_[key] = value;

        Print();

        Verify();
        return true;
    }

    void Remove(const std::string& key) {
        btree_key_buffer_t k(key.begin(), key.end());

        ASSERT_TRUE(kv_.end() != kv_.find(key));

        kv_.erase(key);

        repli_timestamp_t tstamp;
        loof::remove(&sizer_, node_, k.key(), tstamp);

        Verify();

        Print();
    }

    repli_timestamp_t NextTimestamp() {
        tstamp_counter_ ++;
        repli_timestamp_t ret;
        ret.time = tstamp_counter_;
        return ret;
    }

    void Print() {
        // loof::print(stdout, &sizer_, node_);
    }

    void Verify() {
        if (!kv_.empty()) {
            ASSERT_EQ(tstamp_counter_, reinterpret_cast<repli_timestamp_t *>(loof::get_at_offset(node_, node_->frontmost))->time);
        }

        // Of course, this will fail with rassert, not a gtest assertion.
        loof::validate(&sizer_, node_);
    }

private:
    block_size_t bs_;
    value_sizer_t<short_value_t> sizer_;
    loof_t *node_;

    int tstamp_counter_;

    std::map<std::string, std::string> kv_;

    DISABLE_COPYING(LoofTracker);
};

TEST(LoofTest, Offsets) {
    ASSERT_EQ(0, offsetof(loof_t, magic));
    ASSERT_EQ(4, offsetof(loof_t, num_pairs));
    ASSERT_EQ(6, offsetof(loof_t, live_size));
    ASSERT_EQ(8, offsetof(loof_t, frontmost));
    ASSERT_EQ(10, offsetof(loof_t, tstamp_cutpoint));
    ASSERT_EQ(12, offsetof(loof_t, pair_offsets));
    ASSERT_EQ(12, sizeof(loof_t));
}

TEST(LoofTest, Reinserts) {
    LoofTracker tracker;
    std::string v = "aa";
    std::string k = "key";
    for (; v[0] <= 'z'; ++v[0]) {
        v[1] = 'a';
        for (; v[1] <= 'z'; ++v[1]) {
            // printf("inserting %s\n", v.c_str());
            tracker.Insert(k, v);
        }
    }
}

TEST(LoofTest, FiveInserts) {
    LoofTracker tracker;

    std::string ks[5] = { "the_relatively_long_key_that_is_relatively_long,_eh?",
                          "some_other_relatively_long_key_that_...whatever.",
                          "another relatively long key",
                          "a short key",
                          "n" /* not an empty key */ };

    for (int i = 0; i < 26 * 26; ++i) {
        std::string v;
        v += ('a' + (i / 26));
        v += ('a' + (i % 26));

        for (int j = 0; j < 5; ++j) {
            tracker.Insert(ks[j], v);
        }
    }
}

TEST(LoofTest, InsertRemove) {
    LoofTracker tracker;

    srand(12345);

    std::string ks[5] = { "the_relatively_long_key_that_is_relatively_long,_eh?",
                          "some_other_relatively_long_key_that_...whatever.",
                          "another relatively long key",
                          "a short key",
                          "n" /* not an empty key */ };

    for (int i = 0; i < 26 * 26; ++i) {
        std::string v;
        v += ('a' + (i / 26));
        v += ('a' + (i % 26));

        for (int j = 0; j < 5; ++j) {
            if (rand() % 2 == 1) {
                tracker.Insert(ks[j], v);
            } else {
                tracker.Remove(ks[j]);
            }
        }
    }

}

}  // namespace unittest
<|endoftext|>


<commit_before>/**
 * @file		engined.cpp
 * @brief		COSSB Engine Daemon
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 7. 28
 * @details	COSSB Engine for Daemon, Daemon is meant to run in the background with no user interaction.
 */

#include <iostream>
#include <csignal>
#include <cstdlib>
#include <unistd.h>
#include <popt.h>
#include <memory>
#include <syslog.h>
#include <fcntl.h>

#include "cossb.hpp"

using namespace std;
using namespace cossb;

/**
 * @brief	destroy main instance
 * @details	It will be called by SIGINT signal
 */
void destroy()
{
	manager::component_manager::get()->destroy();
	broker::component_broker::get()->destroy();
}

/**
 * @brief	SIGTERM signal callback function
 * @details	Stop all services and destroy all instances
 */
void sigc_terminate(int param) { destroy();	exit(0); }

/**
 * @brief	Main routine
 * @param	command
 * @details	Execute as daemon
 */

int main(int argc, char* argv[])
{
	signal(SIGTERM, sigc_terminate);

	pid_t pid;

	if(daemon(1,1)==-1)
	  return EXIT_FAILURE;

	if((pid=fork())<0)
	  return EXIT_FAILURE;
	else if(pid>0)
	  _exit(0);	//terminate parent

	char* config_file = nullptr;
	struct poptOption optionTable[] = {
			{"run", 'r', POPT_ARG_NONE, 0, 'r', "Run Engine with default configuration", ""},
			{"version", 'v', POPT_ARG_NONE, 0, 'v', "Version", "version"},
			{"config", 'c', POPT_ARG_STRING, (void*)config_file, 'c', "Open configuration file", "XML Configuration file"},
			{"debug", 'd', POPT_ARG_NONE, 0, 'd', "DEBUG mode", ""},
			{"reset", 'e', POPT_ARG_NONE, 0, 'e', "Reset All system", "Clear and initialize the configurations"},
			POPT_AUTOHELP
			POPT_TABLEEND
	};
	poptContext optionCon = poptGetContext(NULL, argc, (const char**)argv, optionTable, 0);
	poptSetOtherOptionHelp(optionCon, "<option>");

	if(argc<2)
	{
		std::cout << poptStrerror(POPT_ERROR_NOARG) << endl;
		destroy();
		_exit(0);
	}

	int opt = 0;
	while((opt = poptGetNextOpt(optionCon))>=0)
	{
		switch(opt)
		{
		// install components
		case 'v':
		{
			std::cout << COSSB_NAME << COSSB_VERSION << " (Released " << __DATE__ << " " <<__TIME__ << ")" << std::endl;
			destroy();
			_exit(0);

		} break;

		//load configuration file
		case 'c':
		{
			string config_file = (const char*)poptGetOptArg(optionCon);
			manager::component_manager::get()->load_config(new config(config_file.c_str()));
		}
			break;

		//run in debug mode
		case 'd':
		{
		}
			break;

		case 'r':
		{
			manager::component_manager::get()->load_config(new config("manifest.xml"));
		}
		break;

		}
	}

	if (opt<-1)
	{
		cout << poptBadOption(optionCon, POPT_BADOPTION_NOALIAS) << ":" << poptStrerror(opt) << endl;
		destroy();
		_exit(0);
	}

	pause();

	//notice, this function affects the checking memory leak, especially when you are using valgrind.
	poptFreeContext(optionCon);

	destroy();
	_exit(0);

	return 0;

}
<commit_msg>edit comment<commit_after>/**
 * @file		engined.cpp
 * @brief		COSSB Engine Daemon
 * @author		Byunghun Hwang<bhhwang@nsynapse.com>
 * @date 		2015. 7. 28
 * @details	COSSB Engine Daemon
 */

#include <iostream>
#include <csignal>
#include <cstdlib>
#include <unistd.h>
#include <popt.h>
#include <memory>
#include <syslog.h>
#include <fcntl.h>

#include "cossb.hpp"

using namespace std;
using namespace cossb;

/**
 * @brief	destroy main instance
 * @details	It will be called by SIGINT signal
 */
void destroy()
{
	manager::component_manager::get()->destroy();
	broker::component_broker::get()->destroy();
}

/**
 * @brief	SIGTERM signal callback function
 * @details	Stop all services and destroy all instances
 */
void sigc_terminate(int param) { destroy();	exit(0); }

/**
 * @brief	Main routine
 * @param	command
 * @details	Execute as daemon
 */

int main(int argc, char* argv[])
{
	signal(SIGTERM, sigc_terminate);

	pid_t pid;

	if(daemon(1,1)==-1)
	  return EXIT_FAILURE;

	if((pid=fork())<0)
	  return EXIT_FAILURE;
	else if(pid>0)
	  _exit(0);	//terminate parent

	char* config_file = nullptr;
	struct poptOption optionTable[] = {
			{"run", 'r', POPT_ARG_NONE, 0, 'r', "Run Engine with default configuration", ""},
			{"version", 'v', POPT_ARG_NONE, 0, 'v', "Version", "version"},
			{"config", 'c', POPT_ARG_STRING, (void*)config_file, 'c', "Open configuration file", "XML Configuration file"},
			{"debug", 'd', POPT_ARG_NONE, 0, 'd', "DEBUG mode", ""},
			{"reset", 'e', POPT_ARG_NONE, 0, 'e', "Reset All system", "Clear and initialize the configurations"},
			POPT_AUTOHELP
			POPT_TABLEEND
	};
	poptContext optionCon = poptGetContext(NULL, argc, (const char**)argv, optionTable, 0);
	poptSetOtherOptionHelp(optionCon, "<option>");

	if(argc<2)
	{
		std::cout << poptStrerror(POPT_ERROR_NOARG) << endl;
		destroy();
		_exit(0);
	}

	int opt = 0;
	while((opt = poptGetNextOpt(optionCon))>=0)
	{
		switch(opt)
		{
		// install components
		case 'v':
		{
			std::cout << COSSB_NAME << COSSB_VERSION << " (Released " << __DATE__ << " " <<__TIME__ << ")" << std::endl;
			destroy();
			_exit(0);

		} break;

		//load configuration file
		case 'c':
		{
			string config_file = (const char*)poptGetOptArg(optionCon);
			manager::component_manager::get()->load_config(new config(config_file.c_str()));
		}
			break;

		//run in debug mode
		case 'd':
		{
		}
			break;

		case 'r':
		{
			manager::component_manager::get()->load_config(new config("manifest.xml"));
		}
		break;

		}
	}

	if (opt<-1)
	{
		cout << poptBadOption(optionCon, POPT_BADOPTION_NOALIAS) << ":" << poptStrerror(opt) << endl;
		destroy();
		_exit(0);
	}

	pause();

	//notice, this function affects the checking memory leak, especially when you are using valgrind.
	poptFreeContext(optionCon);

	destroy();
	_exit(0);

	return 0;

}
<|endoftext|>


<commit_before>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//

#include "stdafx.h"
#include "unwinder.h"

EXTERN_C void GetRuntimeStackWalkInfo(IN  ULONG64   ControlPc,
                                      OUT UINT_PTR* pModuleBase,
                                      OUT UINT_PTR* pFuncEntry);

//---------------------------------------------------------------------------------------
//
// Given a control PC, return the base of the module it is in.  For jitted managed code, this is the
// start of the code heap.
//
// Arguments:
//    address - the specified address
//    pdwBase - out parameter; returns the module base
//
// Return Value:
//    S_OK if we retrieve the module base successfully;
//    E_FAIL otherwise
//

HRESULT OOPStackUnwinder::GetModuleBase(      DWORD64  address,
                                          __out PDWORD64 pdwBase)
{
    GetRuntimeStackWalkInfo(address, reinterpret_cast<UINT_PTR *>(pdwBase), NULL);
    return ((*pdwBase == NULL) ? E_FAIL : S_OK);
}

//---------------------------------------------------------------------------------------
//
// Given a control PC, return the function entry of the functoin it is in.
//
// Arguments:
//    address  - the specified IP
//    pBuffer  - the buffer to store the retrieved function entry
//    cbBuffer - the size of the buffer
//
// Return Value:
//    S_OK          if we retrieve the function entry successfully;
//    E_INVALIDARG  if the buffer is too small;
//    E_FAIL        otherwise
//

HRESULT OOPStackUnwinder::GetFunctionEntry(                       DWORD64 address,
                                           __out_ecount(cbBuffer) PVOID   pBuffer,
                                                                  DWORD   cbBuffer)
{
    if (cbBuffer < sizeof(T_RUNTIME_FUNCTION))
    {
        return E_INVALIDARG;
    }

    PVOID pFuncEntry = NULL;
    GetRuntimeStackWalkInfo(address, NULL, reinterpret_cast<UINT_PTR *>(&pFuncEntry));
    if (pFuncEntry == NULL)
    {
        return E_FAIL;
    }

    memcpy(pBuffer, pFuncEntry, cbBuffer);
    return S_OK;
}
<commit_msg>typo (#13026)<commit_after>// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

//

#include "stdafx.h"
#include "unwinder.h"

EXTERN_C void GetRuntimeStackWalkInfo(IN  ULONG64   ControlPc,
                                      OUT UINT_PTR* pModuleBase,
                                      OUT UINT_PTR* pFuncEntry);

//---------------------------------------------------------------------------------------
//
// Given a control PC, return the base of the module it is in.  For jitted managed code, this is the
// start of the code heap.
//
// Arguments:
//    address - the specified address
//    pdwBase - out parameter; returns the module base
//
// Return Value:
//    S_OK if we retrieve the module base successfully;
//    E_FAIL otherwise
//

HRESULT OOPStackUnwinder::GetModuleBase(      DWORD64  address,
                                          __out PDWORD64 pdwBase)
{
    GetRuntimeStackWalkInfo(address, reinterpret_cast<UINT_PTR *>(pdwBase), NULL);
    return ((*pdwBase == NULL) ? E_FAIL : S_OK);
}

//---------------------------------------------------------------------------------------
//
// Given a control PC, return the function entry of the function it is in.
//
// Arguments:
//    address  - the specified IP
//    pBuffer  - the buffer to store the retrieved function entry
//    cbBuffer - the size of the buffer
//
// Return Value:
//    S_OK          if we retrieve the function entry successfully;
//    E_INVALIDARG  if the buffer is too small;
//    E_FAIL        otherwise
//

HRESULT OOPStackUnwinder::GetFunctionEntry(                       DWORD64 address,
                                           __out_ecount(cbBuffer) PVOID   pBuffer,
                                                                  DWORD   cbBuffer)
{
    if (cbBuffer < sizeof(T_RUNTIME_FUNCTION))
    {
        return E_INVALIDARG;
    }

    PVOID pFuncEntry = NULL;
    GetRuntimeStackWalkInfo(address, NULL, reinterpret_cast<UINT_PTR *>(&pFuncEntry));
    if (pFuncEntry == NULL)
    {
        return E_FAIL;
    }

    memcpy(pBuffer, pFuncEntry, cbBuffer);
    return S_OK;
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelapplets.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "usbview.h"

#include <MLabel>
#include <MLayout>
#include <QGraphicsLinearLayout>
#include <MLinearLayoutPolicy>
#include <MComboBox>
#include <MInfoBanner>
#include <MApplication>
#include <MImageWidget>
#include <MWidgetController>

#include <QTimer>

#undef DEBUG
#define WARNING
#include "../debug.h"

#ifdef HAVE_QMSYSTEM
using namespace MeeGo;

static QmUSBMode::Mode usbModes[3] =
       { QmUSBMode::Ask,
         QmUSBMode::MassStorage,
         QmUSBMode::OviSuite };

inline int
usbModeIndex (QmUSBMode::Mode mode)
{
    int ret = 0;
    for (int i = 0; i < 3; i++)
        if (usbModes[i] == mode)
        {
            ret = i;
            break;
        }
    return ret;
}

UsbView::UsbView (MeeGo::QmUSBMode *logic) :
    DcpStylableWidget (0),
    m_logic (logic),
    m_policy (0),
    m_infoLabel (0)
{
    setObjectName ("UsbView");

    initWidget ();

    connect (m_logic, SIGNAL (modeChanged (MeeGo::QmUSBMode::Mode)),
             SLOT (updateInfoLabel ()));
}
#else
/*
 * FIXME: to implement a variant that does not use the QmSystem library.
 */
UsbView::UsbView (void *logic) :
    DcpStylableWidget (0),
    m_policy (0),
    m_infoLabel (0)
{
    setObjectName ("UsbView");
    initWidget ();
}
#endif

UsbView::~UsbView ()
{
}

void
UsbView::initWidget ()
{
    SYS_DEBUG ("");
    MLayout                 *mainLayout;

    m_infoOrder = 0;
    setStyleName ("CommonPanelInverted");

// Creating the main layout
    mainLayout = new MLayout;
    m_policy = new MLinearLayoutPolicy (mainLayout, Qt::Vertical);

    mainLayout->setContentsMargins (0,0,0,0);
    m_policy->setContentsMargins (0,0,0,0);
    m_policy->setSpacing (0);

#ifndef MEEGO
// Create the title-bar
    MLabel *title = addTitleLabel (
            this, m_policy, "CommonApplicationHeaderInverted");
    //% "USB"
    title->setText (qtTrId ("qtn_usb_title"));
    m_infoOrder++;
#endif

    MWidgetController *spacer = new MWidgetController;
    spacer->setStyleName ("CommonSpacer");
    m_policy->addItem (spacer);
    m_infoOrder++;

    m_UsbModeCombo = new MComboBox;
    //% "Default USB device mode"
    m_UsbModeCombo->setTitle (qtTrId ("qtn_usb_default_info"));
    m_UsbModeCombo->setStyleName ("CommonComboBoxInverted");
    m_UsbModeCombo->setObjectName ("UsbModeCombo");

    //% "Always ask"
    m_UsbModeCombo->insertItem (0, qtTrId ("qtn_usb_always_ask"));
    //% "Mass storage mode"
    m_UsbModeCombo->insertItem (1, qtTrId("qtn_usb_mass_storage"));
    //% "Ovi suite mode"
    m_UsbModeCombo->insertItem (2, qtTrId("qtn_usb_ovi_suite"));

#ifdef HAVE_QMSYSTEM
    m_UsbModeCombo->setCurrentIndex (usbModeIndex (m_logic->getDefaultMode ()));
#endif

    connect (m_UsbModeCombo, SIGNAL (activated (int)),
             SLOT (usbModeActivated (int)), Qt::QueuedConnection);

    m_policy->addItem (m_UsbModeCombo);
    m_policy->addStretch ();

    setLayout (mainLayout);

    updateInfoLabel ();
}

void
UsbView::usbModeActivated (int idx)
{
    SYS_DEBUG ("idx = %d", idx);
#ifdef HAVE_QMSYSTEM
    /*
     * Do nothing if we just tapped on the
     * currently selected one...
     */
    if (m_logic->getDefaultMode() == usbModes[idx])
        return;

    QmUSBMode::Mode active = m_logic->getMode ();

    /*
     * If we are connected and some mode active, then
     * show an error message and set the mode back
     * to original
     */
    if ((active == QmUSBMode::MassStorage) ||
        (active == QmUSBMode::OviSuite))
    {
        /*
         * Set checked on the previously active button
         */
        m_UsbModeCombo->setCurrentIndex (usbModeIndex (m_logic->getDefaultMode ()));

        MInfoBanner *infoBanner = new MInfoBanner (MInfoBanner::Information);
        infoBanner->setIconID ("icon-m-common-usb");
        //% "Cannot change the USB mode when it is connected"
        infoBanner->setBodyText (
            QString ("
") + qtTrId ("qtn_usb_change_incorrect") + "
");

        infoBanner->appear (MApplication::instance ()->activeWindow (),
                            MSceneWindow::DestroyWhenDone);
        return;
    }

    QmUSBMode::Mode newmode = usbModes[idx];
    m_logic->setDefaultMode (newmode);

    /*
     * If we are connected, and we've changed the default
     * mode lets activate the selected mode...
     */
    if (active == QmUSBMode::ChargingOnly)
        m_logic->setMode (newmode);
#endif
}

MLabel *
UsbView::addTitleLabel (
        QGraphicsWidget     *parent,
        MLinearLayoutPolicy *targetPolicy,
        const char          *labelStyleName)
{
    Q_UNUSED (parent);
    MLabel                  *label;

    label = new MLabel;
    label->setStyleName (labelStyleName);

    targetPolicy->addItem (label);
    return label;
}

QString
UsbView::currentText () const
{
    SYS_DEBUG ("");
#ifdef HAVE_QMSYSTEM
    QmUSBMode::Mode active = m_logic->getMode ();

    switch (active)
    {
        case QmUSBMode::MassStorage:
            //% "%1 active"
            return qtTrId ("qtn_usb_active_mode").arg (
            //% "Mass storage mode"
                   qtTrId ("qtn_usb_mass_storage"));
            break;
        case QmUSBMode::OviSuite:
            //% "%1 active"
            return qtTrId ("qtn_usb_active_mode").arg (
            //% "Mass storage mode"
                   qtTrId ("qtn_usb_ovi_suite"));
            break;
        case QmUSBMode::ChargingOnly:
            //% "Current state: Charging only"
            return qtTrId ("qtn_usb_charging");
            break;
        default:
            return "";
            break;
    }
#endif
    return "";
}

void
UsbView::updateInfoLabel ()
{
    if (! m_policy)
        return;

    QString infoText = currentText ();

    if ((! infoText.isEmpty ()) && m_infoLabel)
    {
        /*
         * Label is already there, lets update the text
         */
        m_infoLabel->setText (infoText);
        return;
    }

    if (infoText.isEmpty ())
    {
        /*
         * Label needs to be removed if it is there...
         */
        if (! m_infoLabel)
            return;

        /*
         * Delete the infoWidget
         */
        delete m_policy->itemAt (m_infoOrder);
        m_infoLabel = 0;
        return;
    }

    SYS_DEBUG ("creating the info-widget");
    /*
     * Create the info label widget, and
     * initialize its contents...
     */
    MWidgetController *infoWidget = new MWidgetController;
    infoWidget->setStyleName ("CommonTextFrameInverted");
    infoWidget->setContentsMargins (0,0,0,0);

    QGraphicsLinearLayout *iwLayout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    iwLayout->setContentsMargins (0,0,0,0);
    iwLayout->setSpacing (0);

    MImageWidget *iwIcon = new MImageWidget ("icon-m-common-usb");
    iwIcon->setStyleName ("CommonMainIcon");
    iwLayout->addItem (iwIcon);

    m_infoLabel = new MLabel;
    m_infoLabel->setStyleName ("CommonSingleTitleInverted");
    m_infoLabel->setText (infoText);
    iwLayout->addItem (m_infoLabel);

    infoWidget->setLayout (iwLayout);

    /*
     * Insert it to the proper place...
     */
    m_policy->insertItem (m_infoOrder, infoWidget);
}

<commit_msg>using the short version of the UI string.<commit_after>/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (directui@nokia.com)
**
** This file is part of meegotouch-controlpanelapplets.
**
** If you have questions regarding the use of this file, please contact
** Nokia at directui@nokia.com.
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/
#include "usbview.h"

#include <MLabel>
#include <MLayout>
#include <QGraphicsLinearLayout>
#include <MLinearLayoutPolicy>
#include <MComboBox>
#include <MInfoBanner>
#include <MApplication>
#include <MImageWidget>
#include <MWidgetController>

#include <QTimer>
#include <QStringList>

#undef DEBUG
#define WARNING
#include "../debug.h"

#ifdef HAVE_QMSYSTEM
using namespace MeeGo;

#define qtTrIdShort(id) qtTrId(id).split(QChar(0x9c)).last()

static QmUSBMode::Mode usbModes[3] =
       { QmUSBMode::Ask,
         QmUSBMode::MassStorage,
         QmUSBMode::OviSuite };

inline int
usbModeIndex (QmUSBMode::Mode mode)
{
    int ret = 0;
    for (int i = 0; i < 3; i++)
        if (usbModes[i] == mode)
        {
            ret = i;
            break;
        }
    return ret;
}

UsbView::UsbView (MeeGo::QmUSBMode *logic) :
    DcpStylableWidget (0),
    m_logic (logic),
    m_policy (0),
    m_infoLabel (0)
{
    setObjectName ("UsbView");

    initWidget ();

    connect (m_logic, SIGNAL (modeChanged (MeeGo::QmUSBMode::Mode)),
             SLOT (updateInfoLabel ()));
}
#else
/*
 * FIXME: to implement a variant that does not use the QmSystem library.
 */
UsbView::UsbView (void *logic) :
    DcpStylableWidget (0),
    m_policy (0),
    m_infoLabel (0)
{
    setObjectName ("UsbView");
    initWidget ();
}
#endif

UsbView::~UsbView ()
{
}

void
UsbView::initWidget ()
{
    SYS_DEBUG ("");
    MLayout                 *mainLayout;

    m_infoOrder = 0;
    setStyleName ("CommonPanelInverted");

// Creating the main layout
    mainLayout = new MLayout;
    m_policy = new MLinearLayoutPolicy (mainLayout, Qt::Vertical);

    mainLayout->setContentsMargins (0,0,0,0);
    m_policy->setContentsMargins (0,0,0,0);
    m_policy->setSpacing (0);

#ifndef MEEGO
// Create the title-bar
    MLabel *title = addTitleLabel (
            this, m_policy, "CommonApplicationHeaderInverted");
    //% "USB"
    title->setText (qtTrId ("qtn_usb_title"));
    m_infoOrder++;
#endif

    MWidgetController *spacer = new MWidgetController;
    spacer->setStyleName ("CommonSpacer");
    m_policy->addItem (spacer);
    m_infoOrder++;

    m_UsbModeCombo = new MComboBox;
    //% "Default USB device mode"
    m_UsbModeCombo->setTitle (qtTrId ("qtn_usb_default_info"));
    m_UsbModeCombo->setStyleName ("CommonComboBoxInverted");
    m_UsbModeCombo->setObjectName ("UsbModeCombo");

    //% "Always ask"
    m_UsbModeCombo->insertItem (0, qtTrId ("qtn_usb_always_ask"));
    //% "Mass storage mode"
    m_UsbModeCombo->insertItem (1, qtTrId("qtn_usb_mass_storage"));
    //% "Ovi suite mode"
    m_UsbModeCombo->insertItem (2, qtTrId("qtn_usb_ovi_suite"));

#ifdef HAVE_QMSYSTEM
    m_UsbModeCombo->setCurrentIndex (usbModeIndex (m_logic->getDefaultMode ()));
#endif

    connect (m_UsbModeCombo, SIGNAL (activated (int)),
             SLOT (usbModeActivated (int)), Qt::QueuedConnection);

    m_policy->addItem (m_UsbModeCombo);
    m_policy->addStretch ();

    setLayout (mainLayout);

    updateInfoLabel ();
}

void
UsbView::usbModeActivated (int idx)
{
    SYS_DEBUG ("idx = %d", idx);
#ifdef HAVE_QMSYSTEM
    /*
     * Do nothing if we just tapped on the
     * currently selected one...
     */
    if (m_logic->getDefaultMode() == usbModes[idx])
        return;

    QmUSBMode::Mode active = m_logic->getMode ();

    /*
     * If we are connected and some mode active, then
     * show an error message and set the mode back
     * to original
     */
    if ((active == QmUSBMode::MassStorage) ||
        (active == QmUSBMode::OviSuite))
    {
        /*
         * Set checked on the previously active button
         */
        m_UsbModeCombo->setCurrentIndex (usbModeIndex (m_logic->getDefaultMode ()));

        MInfoBanner *infoBanner = new MInfoBanner (MInfoBanner::Information);
        infoBanner->setIconID ("icon-m-common-usb");
        //% "Cannot change the USB mode when it is connected"
        infoBanner->setBodyText (
            QString ("
") + qtTrIdShort ("qtn_usb_change_incorrect") + "
");

        infoBanner->appear (MApplication::instance ()->activeWindow (),
                            MSceneWindow::DestroyWhenDone);
        return;
    }

    QmUSBMode::Mode newmode = usbModes[idx];
    m_logic->setDefaultMode (newmode);

    /*
     * If we are connected, and we've changed the default
     * mode lets activate the selected mode...
     */
    if (active == QmUSBMode::ChargingOnly)
        m_logic->setMode (newmode);
#endif
}

MLabel *
UsbView::addTitleLabel (
        QGraphicsWidget     *parent,
        MLinearLayoutPolicy *targetPolicy,
        const char          *labelStyleName)
{
    Q_UNUSED (parent);
    MLabel                  *label;

    label = new MLabel;
    label->setStyleName (labelStyleName);

    targetPolicy->addItem (label);
    return label;
}

QString
UsbView::currentText () const
{
    SYS_DEBUG ("");
#ifdef HAVE_QMSYSTEM
    QmUSBMode::Mode active = m_logic->getMode ();

    switch (active)
    {
        case QmUSBMode::MassStorage:
            //% "%1 active"
            return qtTrId ("qtn_usb_active_mode").arg (
            //% "Mass storage mode"
                   qtTrId ("qtn_usb_mass_storage"));
            break;
        case QmUSBMode::OviSuite:
            //% "%1 active"
            return qtTrId ("qtn_usb_active_mode").arg (
            //% "Mass storage mode"
                   qtTrId ("qtn_usb_ovi_suite"));
            break;
        case QmUSBMode::ChargingOnly:
            //% "Current state: Charging only"
            return qtTrId ("qtn_usb_charging");
            break;
        default:
            return "";
            break;
    }
#endif
    return "";
}

void
UsbView::updateInfoLabel ()
{
    if (! m_policy)
        return;

    QString infoText = currentText ();

    if ((! infoText.isEmpty ()) && m_infoLabel)
    {
        /*
         * Label is already there, lets update the text
         */
        m_infoLabel->setText (infoText);
        return;
    }

    if (infoText.isEmpty ())
    {
        /*
         * Label needs to be removed if it is there...
         */
        if (! m_infoLabel)
            return;

        /*
         * Delete the infoWidget
         */
        delete m_policy->itemAt (m_infoOrder);
        m_infoLabel = 0;
        return;
    }

    SYS_DEBUG ("creating the info-widget");
    /*
     * Create the info label widget, and
     * initialize its contents...
     */
    MWidgetController *infoWidget = new MWidgetController;
    infoWidget->setStyleName ("CommonTextFrameInverted");
    infoWidget->setContentsMargins (0,0,0,0);

    QGraphicsLinearLayout *iwLayout =
        new QGraphicsLinearLayout (Qt::Horizontal);
    iwLayout->setContentsMargins (0,0,0,0);
    iwLayout->setSpacing (0);

    MImageWidget *iwIcon = new MImageWidget ("icon-m-common-usb");
    iwIcon->setStyleName ("CommonMainIcon");
    iwLayout->addItem (iwIcon);

    m_infoLabel = new MLabel;
    m_infoLabel->setStyleName ("CommonSingleTitleInverted");
    m_infoLabel->setText (infoText);
    iwLayout->addItem (m_infoLabel);

    infoWidget->setLayout (iwLayout);

    /*
     * Insert it to the proper place...
     */
    m_policy->insertItem (m_infoOrder, infoWidget);
}

<|endoftext|>


<commit_before>#pragma once

#include <string>
#include <algorithm>

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

namespace string_match
{
    namespace _internal {
        typedef std::string::const_iterator iter_t;
        typedef decltype(iter_t()-iter_t()) score_t;

        inline score_t match_len_at(iter_t master_b, iter_t master_e, iter_t input_b, iter_t input_e)
        {
            const auto beg = master_b;
            while (master_b != master_e && input_b != input_e && *master_b == *input_b) {
                ++master_b;
                ++input_b;
            }
            return master_b - beg;
        }

        inline score_t substring_match(iter_t master_b, iter_t master_e, iter_t input_b, iter_t input_e, size_t level_k = 0)
        {
            score_t max_score = 0;
            while (input_b != input_e) {
                auto found = std::find(master_b, master_e, *input_b);
                while (found != master_e) {
                    const score_t len = match_len_at(found, master_e, input_b, input_e);
                    const score_t score = len * len + substring_match(found + len, master_e, input_b + len, input_e, level_k + 1);
                    if (score > max_score)
                        max_score = score;
                    found  = std::find(found + 1, master_e, *input_b);
                }
                ++input_b;
            }
            return max_score;
        }
    }

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

    typedef _internal::score_t score_t;

    inline score_t match(std::string master, std::string input)
    {
        return _internal::substring_match(master.begin(), master.end(), input.begin(), input.end(), input.size());

    } // string_match
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<commit_msg>minor fix<commit_after>#pragma once

#include <string_view>
#include <algorithm>

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

namespace string_match
{
    namespace _internal {
        typedef std::string_view::const_iterator iter_t;
        typedef decltype(iter_t()-iter_t()) score_t;

        inline score_t match_len_at(iter_t master_b, iter_t master_e, iter_t input_b, iter_t input_e)
        {
            const auto beg = master_b;
            while (master_b != master_e && input_b != input_e && *master_b == *input_b) {
                ++master_b;
                ++input_b;
            }
            return master_b - beg;
        }

        inline score_t substring_match(iter_t master_b, iter_t master_e, iter_t input_b, iter_t input_e, size_t level_k = 0)
        {
            score_t max_score = 0;
            while (input_b != input_e) {
                auto found = std::find(master_b, master_e, *input_b);
                while (found != master_e) {
                    const score_t len = match_len_at(found, master_e, input_b, input_e);
                    const score_t score = len * len + substring_match(found + len, master_e, input_b + len, input_e, level_k + 1);
                    if (score > max_score)
                        max_score = score;
                    found  = std::find(found + 1, master_e, *input_b);
                }
                ++input_b;
            }
            return max_score;
        }
    }

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

    typedef _internal::score_t score_t;

    inline score_t match(std::string_view master, std::string_view input)
    {
        return _internal::substring_match(master.begin(), master.end(), input.begin(), input.end(), input.size());

    } // string_match
}

// ----------------------------------------------------------------------
/// Local Variables:
/// eval: (if (fboundp 'eu-rename-buffer) (eu-rename-buffer))
/// End:
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/event_executor_win.h"

#include <windows.h>
#include "app/keyboard_codes.h"
#include "base/stl_util-inl.h"
#include "remoting/host/capturer.h"

namespace remoting {

// TODO(hclam): Move this method to base.
// TODO(hclam): Using values look ugly, change it to something else.
static app::KeyboardCode WindowsKeyCodeForPosixKeyCode(int keycode) {
  switch (keycode) {
    case 0x08:
      return app::VKEY_BACK;
    case 0x09:
      return app::VKEY_TAB;
    case 0x0C:
      return app::VKEY_CLEAR;
    case 0x0D:
      return app::VKEY_RETURN;
    case 0x10:
      return app::VKEY_SHIFT;
    case 0x11:
      return app::VKEY_CONTROL;
    case 0x12:
      return app::VKEY_MENU;
    case 0x13:
      return app::VKEY_PAUSE;
    case 0x14:
      return app::VKEY_CAPITAL;
    case 0x15:
      return app::VKEY_KANA;
    case 0x17:
      return app::VKEY_JUNJA;
    case 0x18:
      return app::VKEY_FINAL;
    case 0x19:
      return app::VKEY_KANJI;
    case 0x1B:
      return app::VKEY_ESCAPE;
    case 0x1C:
      return app::VKEY_CONVERT;
    case 0x1D:
      return app::VKEY_NONCONVERT;
    case 0x1E:
      return app::VKEY_ACCEPT;
    case 0x1F:
      return app::VKEY_MODECHANGE;
    case 0x20:
      return app::VKEY_SPACE;
    case 0x21:
      return app::VKEY_PRIOR;
    case 0x22:
      return app::VKEY_NEXT;
    case 0x23:
      return app::VKEY_END;
    case 0x24:
      return app::VKEY_HOME;
    case 0x25:
      return app::VKEY_LEFT;
    case 0x26:
      return app::VKEY_UP;
    case 0x27:
      return app::VKEY_RIGHT;
    case 0x28:
      return app::VKEY_DOWN;
    case 0x29:
      return app::VKEY_SELECT;
    case 0x2A:
      return app::VKEY_PRINT;
    case 0x2B:
      return app::VKEY_EXECUTE;
    case 0x2C:
      return app::VKEY_SNAPSHOT;
    case 0x2D:
      return app::VKEY_INSERT;
    case 0x2E:
      return app::VKEY_DELETE;
    case 0x2F:
      return app::VKEY_HELP;
    case 0x30:
      return app::VKEY_0;
    case 0x31:
      return app::VKEY_1;
    case 0x32:
      return app::VKEY_2;
    case 0x33:
      return app::VKEY_3;
    case 0x34:
      return app::VKEY_4;
    case 0x35:
      return app::VKEY_5;
    case 0x36:
      return app::VKEY_6;
    case 0x37:
      return app::VKEY_7;
    case 0x38:
      return app::VKEY_8;
    case 0x39:
      return app::VKEY_9;
    case 0x41:
      return app::VKEY_A;
    case 0x42:
      return app::VKEY_B;
    case 0x43:
      return app::VKEY_C;
    case 0x44:
      return app::VKEY_D;
    case 0x45:
      return app::VKEY_E;
    case 0x46:
      return app::VKEY_F;
    case 0x47:
      return app::VKEY_G;
    case 0x48:
      return app::VKEY_H;
    case 0x49:
      return app::VKEY_I;
    case 0x4A:
      return app::VKEY_J;
    case 0x4B:
      return app::VKEY_K;
    case 0x4C:
      return app::VKEY_L;
    case 0x4D:
      return app::VKEY_M;
    case 0x4E:
      return app::VKEY_N;
    case 0x4F:
      return app::VKEY_O;
    case 0x50:
      return app::VKEY_P;
    case 0x51:
      return app::VKEY_Q;
    case 0x52:
      return app::VKEY_R;
    case 0x53:
      return app::VKEY_S;
    case 0x54:
      return app::VKEY_T;
    case 0x55:
      return app::VKEY_U;
    case 0x56:
      return app::VKEY_V;
    case 0x57:
      return app::VKEY_W;
    case 0x58:
      return app::VKEY_X;
    case 0x59:
      return app::VKEY_Y;
    case 0x5A:
      return app::VKEY_Z;
    case 0x5B:
      return app::VKEY_LWIN;
    case 0x5C:
      return app::VKEY_RWIN;
    case 0x5D:
      return app::VKEY_APPS;
    case 0x5F:
      return app::VKEY_SLEEP;
    case 0x60:
      return app::VKEY_NUMPAD0;
    case 0x61:
      return app::VKEY_NUMPAD1;
    case 0x62:
      return app::VKEY_NUMPAD2;
    case 0x63:
      return app::VKEY_NUMPAD3;
    case 0x64:
      return app::VKEY_NUMPAD4;
    case 0x65:
      return app::VKEY_NUMPAD5;
    case 0x66:
      return app::VKEY_NUMPAD6;
    case 0x67:
      return app::VKEY_NUMPAD7;
    case 0x68:
      return app::VKEY_NUMPAD8;
    case 0x69:
      return app::VKEY_NUMPAD9;
    case 0x6A:
      return app::VKEY_MULTIPLY;
    case 0x6B:
      return app::VKEY_ADD;
    case 0x6C:
      return app::VKEY_SEPARATOR;
    case 0x6D:
      return app::VKEY_SUBTRACT;
    case 0x6E:
      return app::VKEY_DECIMAL;
    case 0x6F:
      return app::VKEY_DIVIDE;
    case 0x70:
      return app::VKEY_F1;
    case 0x71:
      return app::VKEY_F2;
    case 0x72:
      return app::VKEY_F3;
    case 0x73:
      return app::VKEY_F4;
    case 0x74:
      return app::VKEY_F5;
    case 0x75:
      return app::VKEY_F6;
    case 0x76:
      return app::VKEY_F7;
    case 0x77:
      return app::VKEY_F8;
    case 0x78:
      return app::VKEY_F9;
    case 0x79:
      return app::VKEY_F10;
    case 0x7A:
      return app::VKEY_F11;
    case 0x7B:
      return app::VKEY_F12;
    case 0x7C:
      return app::VKEY_F13;
    case 0x7D:
      return app::VKEY_F14;
    case 0x7E:
      return app::VKEY_F15;
    case 0x7F:
      return app::VKEY_F16;
    case 0x80:
      return app::VKEY_F17;
    case 0x81:
      return app::VKEY_F18;
    case 0x82:
      return app::VKEY_F19;
    case 0x83:
      return app::VKEY_F20;
    case 0x84:
      return app::VKEY_F21;
    case 0x85:
      return app::VKEY_F22;
    case 0x86:
      return app::VKEY_F23;
    case 0x87:
      return app::VKEY_F24;
    case 0x90:
      return app::VKEY_NUMLOCK;
    case 0x91:
      return app::VKEY_SCROLL;
    case 0xA0:
      return app::VKEY_LSHIFT;
    case 0xA1:
      return app::VKEY_RSHIFT;
    case 0xA2:
      return app::VKEY_LCONTROL;
    case 0xA3:
      return app::VKEY_RCONTROL;
    case 0xA4:
      return app::VKEY_LMENU;
    case 0xA5:
      return app::VKEY_RMENU;
    case 0xA6:
      return app::VKEY_BROWSER_BACK;
    case 0xA7:
      return app::VKEY_BROWSER_FORWARD;
    case 0xA8:
      return app::VKEY_BROWSER_REFRESH;
    case 0xA9:
      return app::VKEY_BROWSER_STOP;
    case 0xAA:
      return app::VKEY_BROWSER_SEARCH;
    case 0xAB:
      return app::VKEY_BROWSER_FAVORITES;
    case 0xAC:
      return app::VKEY_BROWSER_HOME;
    case 0xAD:
      return app::VKEY_VOLUME_MUTE;
    case 0xAE:
      return app::VKEY_VOLUME_DOWN;
    case 0xAF:
      return app::VKEY_VOLUME_UP;
    case 0xB0:
      return app::VKEY_MEDIA_NEXT_TRACK;
    case 0xB1:
      return app::VKEY_MEDIA_PREV_TRACK;
    case 0xB2:
      return app::VKEY_MEDIA_STOP;
    case 0xB3:
      return app::VKEY_MEDIA_PLAY_PAUSE;
    case 0xB4:
      return app::VKEY_MEDIA_LAUNCH_MAIL;
    case 0xB5:
      return app::VKEY_MEDIA_LAUNCH_MEDIA_SELECT;
    case 0xB6:
      return app::VKEY_MEDIA_LAUNCH_APP1;
    case 0xB7:
      return app::VKEY_MEDIA_LAUNCH_APP2;
    case 0xBA:
      return app::VKEY_OEM_1;
    case 0xBB:
      return app::VKEY_OEM_PLUS;
    case 0xBC:
      return app::VKEY_OEM_COMMA;
    case 0xBD:
      return app::VKEY_OEM_MINUS;
    case 0xBE:
      return app::VKEY_OEM_PERIOD;
    case 0xBF:
      return app::VKEY_OEM_2;
    case 0xC0:
      return app::VKEY_OEM_3;
    case 0xDB:
      return app::VKEY_OEM_4;
    case 0xDC:
      return app::VKEY_OEM_5;
    case 0xDD:
      return app::VKEY_OEM_6;
    case 0xDE:
      return app::VKEY_OEM_7;
    case 0xDF:
      return app::VKEY_OEM_8;
    case 0xE2:
      return app::VKEY_OEM_102;
    case 0xE5:
      return app::VKEY_PROCESSKEY;
    case 0xE7:
      return app::VKEY_PACKET;
    case 0xF6:
      return app::VKEY_ATTN;
    case 0xF7:
      return app::VKEY_CRSEL;
    case 0xF8:
      return app::VKEY_EXSEL;
    case 0xF9:
      return app::VKEY_EREOF;
    case 0xFA:
      return app::VKEY_PLAY;
    case 0xFB:
      return app::VKEY_ZOOM;
    case 0xFC:
      return app::VKEY_NONAME;
    case 0xFD:
      return app::VKEY_PA1;
    case 0xFE:
      return app::VKEY_OEM_CLEAR;
    default:
      return app::VKEY_UNKNOWN;
  }
}

EventExecutorWin::EventExecutorWin(Capturer* capturer)
  : EventExecutor(capturer) {
}

EventExecutorWin::~EventExecutorWin() {
}

void EventExecutorWin::HandleInputEvent(ChromotingClientMessage* msg) {
  if (msg->has_mouse_set_position_event()) {
    HandleMouseSetPosition(msg);
  } else if (msg->has_mouse_move_event()) {
    HandleMouseMove(msg);
  } else if (msg->has_mouse_wheel_event()) {
    HandleMouseWheel(msg);
  } else if (msg->has_mouse_down_event()) {
    HandleMouseButtonDown(msg);
  } else if (msg->has_mouse_up_event()) {
    HandleMouseButtonUp(msg);
  } else if (msg->has_key_event()) {
    HandleKey(msg);
  }
  delete msg;
}

void EventExecutorWin::HandleMouseSetPosition(ChromotingClientMessage* msg) {
  int x = msg->mouse_set_position_event().x();
  int y = msg->mouse_set_position_event().y();
  int width = msg->mouse_set_position_event().width();
  int height = msg->mouse_set_position_event().height();

  // Get width and height from the capturer if they are missing from the
  // message.
  if (width == 0 || height == 0) {
    width = capturer_->width();
    height = capturer_->height();
  }
  if (width == 0 || height == 0) {
    return;
  }

  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = static_cast<int>((x * 65535) / width);
  input.mi.dy = static_cast<int>((y * 65535) / height);
  input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseMove(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = msg->mouse_move_event().offset_x();
  input.mi.dy = msg->mouse_move_event().offset_y();
  input.mi.dwFlags = MOUSEEVENTF_MOVE;
  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseWheel(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;

  int dx = msg->mouse_wheel_event().offset_x();
  int dy = msg->mouse_wheel_event().offset_y();

  if (dx != 0) {
    input.mi.mouseData = dx;
    input.mi.dwFlags = MOUSEEVENTF_HWHEEL;
    SendInput(1, &input, sizeof(INPUT));
  }
  if (dy != 0) {
    input.mi.mouseData = dy;
    input.mi.dwFlags = MOUSEEVENTF_WHEEL;
    SendInput(1, &input, sizeof(INPUT));
  }
}

void EventExecutorWin::HandleMouseButtonDown(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = 0;
  input.mi.dy = 0;

  MouseButton button = msg->mouse_down_event().button();
  if (button == MouseButtonLeft) {
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
  } else if (button == MouseButtonMiddle) {
    input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
  } else if (button == MouseButtonRight) {
    input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
  } else {
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
  }

  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseButtonUp(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = 0;
  input.mi.dy = 0;

  MouseButton button = msg->mouse_down_event().button();
  if (button == MouseButtonLeft) {
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
  } else if (button == MouseButtonMiddle) {
    input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
  } else if (button == MouseButtonRight) {
    input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
  } else {
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleKey(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = 0;
  input.ki.wScan = msg->key_event().key();
  input.ki.dwFlags = KEYEVENTF_UNICODE;
  if (!msg->key_event().pressed()) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

}  // namespace remoting
<commit_msg>Basic client-host key (+ dead key) support for Chromoting (Windows).<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/event_executor_win.h"

#include <windows.h>
#include "app/keyboard_codes.h"
#include "base/stl_util-inl.h"
#include "remoting/host/capturer.h"

namespace remoting {

EventExecutorWin::EventExecutorWin(Capturer* capturer)
  : EventExecutor(capturer) {
}

EventExecutorWin::~EventExecutorWin() {
}

void EventExecutorWin::HandleInputEvent(ChromotingClientMessage* msg) {
  if (msg->has_mouse_set_position_event()) {
    HandleMouseSetPosition(msg);
  } else if (msg->has_mouse_move_event()) {
    HandleMouseMove(msg);
  } else if (msg->has_mouse_wheel_event()) {
    HandleMouseWheel(msg);
  } else if (msg->has_mouse_down_event()) {
    HandleMouseButtonDown(msg);
  } else if (msg->has_mouse_up_event()) {
    HandleMouseButtonUp(msg);
  } else if (msg->has_key_event()) {
    HandleKey(msg);
  }
  delete msg;
}

void EventExecutorWin::HandleMouseSetPosition(ChromotingClientMessage* msg) {
  int x = msg->mouse_set_position_event().x();
  int y = msg->mouse_set_position_event().y();
  int width = msg->mouse_set_position_event().width();
  int height = msg->mouse_set_position_event().height();

  // Get width and height from the capturer if they are missing from the
  // message.
  if (width == 0 || height == 0) {
    width = capturer_->width();
    height = capturer_->height();
  }
  if (width == 0 || height == 0) {
    return;
  }

  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = static_cast<int>((x * 65535) / width);
  input.mi.dy = static_cast<int>((y * 65535) / height);
  input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseMove(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = msg->mouse_move_event().offset_x();
  input.mi.dy = msg->mouse_move_event().offset_y();
  input.mi.dwFlags = MOUSEEVENTF_MOVE;
  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseWheel(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;

  int dx = msg->mouse_wheel_event().offset_x();
  int dy = msg->mouse_wheel_event().offset_y();

  if (dx != 0) {
    input.mi.mouseData = dx;
    input.mi.dwFlags = MOUSEEVENTF_HWHEEL;
    SendInput(1, &input, sizeof(INPUT));
  }
  if (dy != 0) {
    input.mi.mouseData = dy;
    input.mi.dwFlags = MOUSEEVENTF_WHEEL;
    SendInput(1, &input, sizeof(INPUT));
  }
}

void EventExecutorWin::HandleMouseButtonDown(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = 0;
  input.mi.dy = 0;

  MouseButton button = msg->mouse_down_event().button();
  if (button == MouseButtonLeft) {
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
  } else if (button == MouseButtonMiddle) {
    input.mi.dwFlags = MOUSEEVENTF_MIDDLEDOWN;
  } else if (button == MouseButtonRight) {
    input.mi.dwFlags = MOUSEEVENTF_RIGHTDOWN;
  } else {
    input.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
  }

  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleMouseButtonUp(ChromotingClientMessage* msg) {
  INPUT input;
  input.type = INPUT_MOUSE;
  input.mi.time = 0;
  input.mi.dx = 0;
  input.mi.dy = 0;

  MouseButton button = msg->mouse_down_event().button();
  if (button == MouseButtonLeft) {
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
  } else if (button == MouseButtonMiddle) {
    input.mi.dwFlags = MOUSEEVENTF_MIDDLEUP;
  } else if (button == MouseButtonRight) {
    input.mi.dwFlags = MOUSEEVENTF_RIGHTUP;
  } else {
    input.mi.dwFlags = MOUSEEVENTF_LEFTUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

void EventExecutorWin::HandleKey(ChromotingClientMessage* msg) {
  int key = msg->key_event().key();
  bool down = msg->key_event().pressed();

  // Calculate scan code from virtual key.
  HKL hkl = GetKeyboardLayout(0);
  int scan_code = MapVirtualKeyEx(key, MAPVK_VK_TO_VSC_EX, hkl);

  INPUT input;
  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = key;
  input.ki.wScan = scan_code;

  // Flag to mark extended 'e0' key scancodes. Without this, the left and
  // right windows keys will not be handled properly (on US keyboard).
  if ((scan_code & 0xFF00) == 0xE000) {
    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
  }

  // Flag to mark keyup events. Default is keydown.
  if (!down) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

}  // namespace remoting
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/event_executor_win.h"

#include <windows.h>

#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "remoting/host/capturer.h"
#include "remoting/proto/event.pb.h"
#include "ui/base/keycodes/keyboard_codes.h"

namespace remoting {

using protocol::MouseEvent;
using protocol::KeyEvent;

EventExecutorWin::EventExecutorWin(
    MessageLoop* message_loop, Capturer* capturer)
    : message_loop_(message_loop),
      capturer_(capturer) {
}

EventExecutorWin::~EventExecutorWin() {
}

void EventExecutorWin::InjectKeyEvent(const KeyEvent* event, Task* done) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        NewRunnableMethod(this, &EventExecutorWin::InjectKeyEvent,
                          event, done));
    return;
  }
  HandleKey(event);
  done->Run();
  delete done;
}

void EventExecutorWin::InjectMouseEvent(const MouseEvent* event, Task* done) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        NewRunnableMethod(this, &EventExecutorWin::InjectMouseEvent,
                          event, done));
    return;
  }
  HandleMouse(event);
  done->Run();
  delete done;
}

void EventExecutorWin::HandleKey(const KeyEvent* event) {
  int key = event->keycode();
  bool down = event->pressed();

  // Calculate scan code from virtual key.
  HKL hkl = GetKeyboardLayout(0);
  int scan_code = MapVirtualKeyEx(key, MAPVK_VK_TO_VSC_EX, hkl);

  INPUT input;
  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = key;
  input.ki.wScan = scan_code;

  // Flag to mark extended 'e0' key scancodes. Without this, the left and
  // right windows keys will not be handled properly (on US keyboard).
  if ((scan_code & 0xFF00) == 0xE000) {
    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
  }

  // Flag to mark keyup events. Default is keydown.
  if (!down) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

protocol::InputStub* CreateEventExecutor(MessageLoop* message_loop,
                                         Capturer* capturer) {
  return new EventExecutorWin(message_loop, capturer);
}

void EventExecutorWin::HandleMouse(const MouseEvent* event) {
  // TODO(garykac) Collapse mouse (x,y) and button events into a single
  // input event when possible.
  if (event->has_x() && event->has_y()) {
    int x = event->x();
    int y = event->y();

    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.time = 0;
    input.mi.dx = static_cast<int>((x * 65535) / capturer_->width());
    input.mi.dy = static_cast<int>((y * 65535) / capturer_->height());
    input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
    SendInput(1, &input, sizeof(INPUT));
  }

  if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) {
    INPUT wheel;
    wheel.type = INPUT_MOUSE;
    wheel.mi.time = 0;

    int dx = event->wheel_offset_x();
    int dy = event->wheel_offset_y();

    if (dx != 0) {
      wheel.mi.mouseData = dx;
      wheel.mi.dwFlags = MOUSEEVENTF_HWHEEL;
      SendInput(1, &wheel, sizeof(INPUT));
    }
    if (dy != 0) {
      wheel.mi.mouseData = dy;
      wheel.mi.dwFlags = MOUSEEVENTF_WHEEL;
      SendInput(1, &wheel, sizeof(INPUT));
    }
  }

  if (event->has_button() && event->has_button_down()) {
    INPUT button_event;
    button_event.type = INPUT_MOUSE;
    button_event.mi.time = 0;
    button_event.mi.dx = 0;
    button_event.mi.dy = 0;

    MouseEvent::MouseButton button = event->button();
    bool down = event->button_down();
    if (button == MouseEvent::BUTTON_LEFT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    } else if (button == MouseEvent::BUTTON_MIDDLE) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
    } else if (button == MouseEvent::BUTTON_RIGHT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
    } else {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    }

    SendInput(1, &button_event, sizeof(INPUT));
  }
}

}  // namespace remoting
<commit_msg>Fix key missing problem on windows<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "remoting/host/event_executor_win.h"

#include <windows.h>

#include "base/message_loop.h"
#include "base/stl_util-inl.h"
#include "remoting/host/capturer.h"
#include "remoting/proto/event.pb.h"
#include "ui/base/keycodes/keyboard_codes.h"

namespace remoting {

using protocol::MouseEvent;
using protocol::KeyEvent;

EventExecutorWin::EventExecutorWin(
    MessageLoop* message_loop, Capturer* capturer)
    : message_loop_(message_loop),
      capturer_(capturer) {
}

EventExecutorWin::~EventExecutorWin() {
}

void EventExecutorWin::InjectKeyEvent(const KeyEvent* event, Task* done) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        NewRunnableMethod(this, &EventExecutorWin::InjectKeyEvent,
                          event, done));
    return;
  }
  HandleKey(event);
  done->Run();
  delete done;
}

void EventExecutorWin::InjectMouseEvent(const MouseEvent* event, Task* done) {
  if (MessageLoop::current() != message_loop_) {
    message_loop_->PostTask(
        FROM_HERE,
        NewRunnableMethod(this, &EventExecutorWin::InjectMouseEvent,
                          event, done));
    return;
  }
  HandleMouse(event);
  done->Run();
  delete done;
}

void EventExecutorWin::HandleKey(const KeyEvent* event) {
  int key = event->keycode();
  bool down = event->pressed();

  // Calculate scan code from virtual key.
  HKL hkl = GetKeyboardLayout(0);
  int scan_code = MapVirtualKeyEx(key, MAPVK_VK_TO_VSC_EX, hkl);

  INPUT input;
  memset(&input, 0, sizeof(input));

  input.type = INPUT_KEYBOARD;
  input.ki.time = 0;
  input.ki.wVk = key;
  input.ki.wScan = scan_code;

  // Flag to mark extended 'e0' key scancodes. Without this, the left and
  // right windows keys will not be handled properly (on US keyboard).
  if ((scan_code & 0xFF00) == 0xE000) {
    input.ki.dwFlags |= KEYEVENTF_EXTENDEDKEY;
  }

  // Flag to mark keyup events. Default is keydown.
  if (!down) {
    input.ki.dwFlags |= KEYEVENTF_KEYUP;
  }

  SendInput(1, &input, sizeof(INPUT));
}

protocol::InputStub* CreateEventExecutor(MessageLoop* message_loop,
                                         Capturer* capturer) {
  return new EventExecutorWin(message_loop, capturer);
}

void EventExecutorWin::HandleMouse(const MouseEvent* event) {
  // TODO(garykac) Collapse mouse (x,y) and button events into a single
  // input event when possible.
  if (event->has_x() && event->has_y()) {
    int x = event->x();
    int y = event->y();

    INPUT input;
    input.type = INPUT_MOUSE;
    input.mi.time = 0;
    input.mi.dx = static_cast<int>((x * 65535) / capturer_->width());
    input.mi.dy = static_cast<int>((y * 65535) / capturer_->height());
    input.mi.dwFlags = MOUSEEVENTF_MOVE | MOUSEEVENTF_ABSOLUTE;
    SendInput(1, &input, sizeof(INPUT));
  }

  if (event->has_wheel_offset_x() && event->has_wheel_offset_y()) {
    INPUT wheel;
    wheel.type = INPUT_MOUSE;
    wheel.mi.time = 0;

    int dx = event->wheel_offset_x();
    int dy = event->wheel_offset_y();

    if (dx != 0) {
      wheel.mi.mouseData = dx;
      wheel.mi.dwFlags = MOUSEEVENTF_HWHEEL;
      SendInput(1, &wheel, sizeof(INPUT));
    }
    if (dy != 0) {
      wheel.mi.mouseData = dy;
      wheel.mi.dwFlags = MOUSEEVENTF_WHEEL;
      SendInput(1, &wheel, sizeof(INPUT));
    }
  }

  if (event->has_button() && event->has_button_down()) {
    INPUT button_event;
    button_event.type = INPUT_MOUSE;
    button_event.mi.time = 0;
    button_event.mi.dx = 0;
    button_event.mi.dy = 0;

    MouseEvent::MouseButton button = event->button();
    bool down = event->button_down();
    if (button == MouseEvent::BUTTON_LEFT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    } else if (button == MouseEvent::BUTTON_MIDDLE) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_MIDDLEDOWN : MOUSEEVENTF_MIDDLEUP;
    } else if (button == MouseEvent::BUTTON_RIGHT) {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_RIGHTDOWN : MOUSEEVENTF_RIGHTUP;
    } else {
      button_event.mi.dwFlags =
          down ? MOUSEEVENTF_LEFTDOWN : MOUSEEVENTF_LEFTUP;
    }

    SendInput(1, &button_event, sizeof(INPUT));
  }
}

}  // namespace remoting
<|endoftext|>