<commit_before>#include <nan.h>
#include <node.h>

#include <cstring>
#include <string>

#include "../argon2/src/argon2.h"

namespace {

using uint = unsigned int;

const auto ENCODED_LEN = 108u;
const auto HASH_LEN = 32u;
const auto SALT_LEN = 16u;

class HashAsyncWorker : public Nan::AsyncWorker {
public:
    HashAsyncWorker(Nan::Callback* callback, const std::string& plain,
            const std::string& salt, uint time_cost, uint memory_cost,
            uint parallelism, argon2_type type);

    void Execute();

    void HandleOKCallback();

private:
    std::string plain;
    std::string salt;
    uint time_cost;
    uint memory_cost;
    uint parallelism;
    std::string error;
    Argon2_type type;
    std::string output;
};

HashAsyncWorker::HashAsyncWorker(Nan::Callback* callback,
        const std::string& plain, const std::string& salt, uint time_cost,
        uint memory_cost, uint parallelism, Argon2_type type):
    Nan::AsyncWorker(callback), plain{plain}, salt{salt}, time_cost{time_cost},
    memory_cost{memory_cost}, parallelism{parallelism}, error{}, type{type},
    output{}
{ }

void HashAsyncWorker::Execute()
{
    char encoded[ENCODED_LEN];

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, encoded, ENCODED_LEN, type);
    if (result != ARGON2_OK) {
        SetErrorMessage(error_message(result));
        return;
    }

    output = std::string{encoded};
}

void HashAsyncWorker::HandleOKCallback()
{
    using v8::Local;
    using v8::Value;

    Nan::HandleScope scope;

    Local <Value> argv[] = {
        Nan::Undefined(), Nan::Encode(output.c_str(), output.size(), Nan::BINARY)
    };

    callback->Call(2, argv);
}

NAN_METHOD(Hash) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 7) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("7 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String raw_salt{info[1]->ToString()};
    auto time_cost = info[2]->Uint32Value();
    auto memory_cost = info[3]->Uint32Value();
    auto parallelism = info[4]->Uint32Value();
    argon2_type type = info[5]->BooleanValue() ? Argon2_d : Argon2_i;
    Local<Function> callback = Local<Function>::Cast(info[6]);

    auto salt = std::string{*raw_salt};
    salt.resize(SALT_LEN, 0x0);

    auto worker = new HashAsyncWorker(new Nan::Callback(callback), *plain, salt,
            time_cost, 1 << memory_cost, parallelism, type);

    Nan::AsyncQueueWorker(worker);
}

NAN_METHOD(HashSync) {
    Nan::HandleScope scope;

    if (info.Length() < 6) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("6 arguments expected");
        info.GetReturnValue().Set(Nan::Undefined());
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String raw_salt{info[1]->ToString()};
    auto time_cost = info[2]->Uint32Value();
    auto memory_cost = info[3]->Uint32Value();
    auto parallelism = info[4]->Uint32Value();
    argon2_type type = info[5]->BooleanValue() ? Argon2_d : Argon2_i;

    char encoded[ENCODED_LEN];

    auto salt = std::string{*raw_salt};
    salt.resize(SALT_LEN, 0x0);

    auto result = argon2_hash(time_cost, 1 << memory_cost, parallelism, *plain,
            strlen(*plain), salt.c_str(), salt.size(), nullptr, HASH_LEN,
            encoded, ENCODED_LEN, type);

    if (result != ARGON2_OK) {
        Nan::ThrowError(error_message(result));
        info.GetReturnValue().Set(Nan::Undefined());
        return;
    }

    info.GetReturnValue().Set(Nan::Encode(encoded, std::strlen(encoded),
            Nan::BINARY));
}

class VerifyAsyncWorker : public Nan::AsyncWorker {
public:
    VerifyAsyncWorker(Nan::Callback* callback, const std::string& hash,
            const std::string& plain, argon2_type type);

    void Execute();

private:
    std::string hash;
    std::string plain;
    std::string error;
    argon2_type type;
    bool output;
};

VerifyAsyncWorker::VerifyAsyncWorker(Nan::Callback* callback,
        const std::string& hash, const std::string& plain, argon2_type type):
    Nan::AsyncWorker(callback), hash{hash}, plain{plain}, error{}, type{type},
    output{}
{ }

void VerifyAsyncWorker::Execute()
{
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    if (result != ARGON2_OK) {
        SetErrorMessage("The password did not match.");
    }
}

NAN_METHOD(Verify) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("3 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String hash{info[0]->ToString()};
    Nan::Utf8String plain{info[1]->ToString()};
    argon2_type type = info[2]->BooleanValue() ? Argon2_d : Argon2_i;
    Local<Function> callback = Local<Function>::Cast(info[3]);

    auto worker = new VerifyAsyncWorker(new Nan::Callback(callback), *hash,
            *plain, type);

    Nan::AsyncQueueWorker(worker);
}

NAN_METHOD(VerifySync) {
    using std::strlen;

    Nan::HandleScope scope;

    if (info.Length() < 2) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("2 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String hash{info[0]->ToString()};
    Nan::Utf8String plain{info[1]->ToString()};
    argon2_type type = info[2]->BooleanValue() ? Argon2_d : Argon2_i;

    auto result = argon2_verify(*hash, *plain, strlen(*plain), type);

    info.GetReturnValue().Set(result == ARGON2_OK);
}

}

NAN_MODULE_INIT(init) {
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "hashSync", HashSync);
    Nan::Export(target, "verify", Verify);
    Nan::Export(target, "verifySync", VerifySync);
};

NODE_MODULE(argon2_lib, init);
<commit_msg>Use constant-sized integers for storing parameters<commit_after>#include <nan.h>
#include <node.h>

#include <cstdint>
#include <cstring>
#include <string>

#include "../argon2/src/argon2.h"

namespace {

using std::uint32_t;

const auto ENCODED_LEN = 108u;
const auto HASH_LEN = 32u;
const auto SALT_LEN = 16u;

class HashAsyncWorker : public Nan::AsyncWorker {
public:
    HashAsyncWorker(Nan::Callback* callback, const std::string& plain,
            const std::string& salt, uint32_t time_cost, uint32_t memory_cost,
            uint32_t parallelism, argon2_type type);

    void Execute();

    void HandleOKCallback();

private:
    std::string plain;
    std::string salt;
    uint32_t time_cost;
    uint32_t memory_cost;
    uint32_t parallelism;
    std::string error;
    Argon2_type type;
    std::string output;
};

HashAsyncWorker::HashAsyncWorker(Nan::Callback* callback,
        const std::string& plain, const std::string& salt, uint32_t time_cost,
        uint32_t memory_cost, uint32_t parallelism, Argon2_type type):
    Nan::AsyncWorker(callback), plain{plain}, salt{salt}, time_cost{time_cost},
    memory_cost{memory_cost}, parallelism{parallelism}, error{}, type{type},
    output{}
{ }

void HashAsyncWorker::Execute()
{
    char encoded[ENCODED_LEN];

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, encoded, ENCODED_LEN, type);
    if (result != ARGON2_OK) {
        SetErrorMessage(error_message(result));
        return;
    }

    output = std::string{encoded};
}

void HashAsyncWorker::HandleOKCallback()
{
    using v8::Local;
    using v8::Value;

    Nan::HandleScope scope;

    Local <Value> argv[] = {
        Nan::Undefined(), Nan::Encode(output.c_str(), output.size(), Nan::BINARY)
    };

    callback->Call(2, argv);
}

NAN_METHOD(Hash) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 7) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("7 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String raw_salt{info[1]->ToString()};
    auto time_cost = info[2]->Uint32Value();
    auto memory_cost = info[3]->Uint32Value();
    auto parallelism = info[4]->Uint32Value();
    argon2_type type = info[5]->BooleanValue() ? Argon2_d : Argon2_i;
    Local<Function> callback = Local<Function>::Cast(info[6]);

    auto salt = std::string{*raw_salt};
    salt.resize(SALT_LEN, 0x0);

    auto worker = new HashAsyncWorker(new Nan::Callback(callback), *plain, salt,
            time_cost, 1 << memory_cost, parallelism, type);

    Nan::AsyncQueueWorker(worker);
}

NAN_METHOD(HashSync) {
    Nan::HandleScope scope;

    if (info.Length() < 6) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("6 arguments expected");
        info.GetReturnValue().Set(Nan::Undefined());
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String plain{info[0]->ToString()};
    Nan::Utf8String raw_salt{info[1]->ToString()};
    auto time_cost = info[2]->Uint32Value();
    auto memory_cost = info[3]->Uint32Value();
    auto parallelism = info[4]->Uint32Value();
    argon2_type type = info[5]->BooleanValue() ? Argon2_d : Argon2_i;

    char encoded[ENCODED_LEN];

    auto salt = std::string{*raw_salt};
    salt.resize(SALT_LEN, 0x0);

    auto result = argon2_hash(time_cost, 1 << memory_cost, parallelism, *plain,
            strlen(*plain), salt.c_str(), salt.size(), nullptr, HASH_LEN,
            encoded, ENCODED_LEN, type);

    if (result != ARGON2_OK) {
        Nan::ThrowError(error_message(result));
        info.GetReturnValue().Set(Nan::Undefined());
        return;
    }

    info.GetReturnValue().Set(Nan::Encode(encoded, std::strlen(encoded),
            Nan::BINARY));
}

class VerifyAsyncWorker : public Nan::AsyncWorker {
public:
    VerifyAsyncWorker(Nan::Callback* callback, const std::string& hash,
            const std::string& plain, argon2_type type);

    void Execute();

private:
    std::string hash;
    std::string plain;
    std::string error;
    argon2_type type;
    bool output;
};

VerifyAsyncWorker::VerifyAsyncWorker(Nan::Callback* callback,
        const std::string& hash, const std::string& plain, argon2_type type):
    Nan::AsyncWorker(callback), hash{hash}, plain{plain}, error{}, type{type},
    output{}
{ }

void VerifyAsyncWorker::Execute()
{
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    if (result != ARGON2_OK) {
        SetErrorMessage("The password did not match.");
    }
}

NAN_METHOD(Verify) {
    using v8::Function;
    using v8::Local;

    Nan::HandleScope scope;

    if (info.Length() < 3) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("3 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String hash{info[0]->ToString()};
    Nan::Utf8String plain{info[1]->ToString()};
    argon2_type type = info[2]->BooleanValue() ? Argon2_d : Argon2_i;
    Local<Function> callback = Local<Function>::Cast(info[3]);

    auto worker = new VerifyAsyncWorker(new Nan::Callback(callback), *hash,
            *plain, type);

    Nan::AsyncQueueWorker(worker);
}

NAN_METHOD(VerifySync) {
    using std::strlen;

    Nan::HandleScope scope;

    if (info.Length() < 2) {
        /* LCOV_EXCL_START */
        Nan::ThrowTypeError("2 arguments expected");
        return;
        /* LCOV_EXCL_STOP */
    }

    Nan::Utf8String hash{info[0]->ToString()};
    Nan::Utf8String plain{info[1]->ToString()};
    argon2_type type = info[2]->BooleanValue() ? Argon2_d : Argon2_i;

    auto result = argon2_verify(*hash, *plain, strlen(*plain), type);

    info.GetReturnValue().Set(result == ARGON2_OK);
}

}

NAN_MODULE_INIT(init) {
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "hashSync", HashSync);
    Nan::Export(target, "verify", Verify);
    Nan::Export(target, "verifySync", VerifySync);
};

NODE_MODULE(argon2_lib, init);
<|endoftext|>


<commit_before>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>
#include <tuple>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;
const auto HASH_LEN = 32u;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr auto log(uint64_t number, uint64_t base = 2u) -> decltype(number)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr auto base64Length(size_type length) -> decltype(length)
{
    return ((length + 2u) / 3u) * 4u;
}

auto encodedLength(size_type saltLength) -> decltype(saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(ARGON2_MAX_MEMORY + 1u, 10u) + log(ARGON2_MAX_TIME + 1u, 10u) +
        log(ARGON2_MAX_LANES + 1u, 10u) + base64Length(HASH_LEN);

    return extraLength + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        std::tuple<uint32_t, uint32_t, uint32_t, argon2_type>&& params):
    Nan::AsyncWorker{nullptr}, plain{plain}, salt{salt},
    time_cost{std::get<0>(params)}, memory_cost{std::get<1>(params)},
    parallelism{std::get<2>(params)}, type{std::get<3>(params)}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */
        SetErrorMessage(argon2_error_message(result));
        /* LCOV_EXCL_STOP */
    }
}

void HashWorker::HandleOKCallback()
{
    using namespace v8;
    using std::strlen;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::Encode(output.get(), strlen(output.get()))};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void HashWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Hash) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 8);

    const auto plain = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto salt = Nan::To<Object>(info[1]).ToLocalChecked();
    const auto options = Nan::To<Object>(info[2]).ToLocalChecked();

    const auto getArg = [&](const char* key) {
        auto localKey = Nan::New(key).ToLocalChecked();
        return Nan::Get(options, localKey).ToLocalChecked();
    };

    auto worker = new HashWorker{
            {Buffer::Data(plain), Buffer::Length(plain)},
            {Buffer::Data(salt), Buffer::Length(salt)},
            std::make_tuple(fromJust<uint32_t>(getArg("timeCost")),
                    1u << fromJust<uint32_t>(getArg("memoryCost")),
                    fromJust<uint32_t>(getArg("parallelism")),
                    fromJust<bool>(getArg("argon2d")) ? Argon2_d : Argon2_i)};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[3]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[4]));

    Nan::AsyncQueueWorker(worker);
}

VerifyWorker::VerifyWorker(std::string&& hash, std::string&& plain):
    Nan::AsyncWorker{nullptr}, hash{hash}, plain{plain}
{ }

void VerifyWorker::Execute()
{
    auto type = (hash.at(7) == 'd') ? Argon2_d : Argon2_i;
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    switch (result) {
        case ARGON2_OK:
        case ARGON2_VERIFY_MISMATCH:
            output = result == ARGON2_OK;
            break;
        default:
            /* LCOV_EXCL_START */
            SetErrorMessage(argon2_error_message(result));
            break;
            /* LCOV_EXCL_STOP */
    }
}

void VerifyWorker::HandleOKCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(output)};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void VerifyWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Verify) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 5);

    const auto hash = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto plain = Nan::To<Object>(info[1]).ToLocalChecked();

    auto worker = new VerifyWorker{{Buffer::Data(hash), Buffer::Length(hash)},
            {Buffer::Data(plain), Buffer::Length(plain)}};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[2]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[3]));

    Nan::AsyncQueueWorker(worker);
}

NAN_MODULE_INIT(init) {
    using namespace v8;

    auto limits = Nan::New<Object>();

    const auto setMaxMin = [&](const char* name, uint32_t max, uint32_t min) {
        auto obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New("max").ToLocalChecked(), Nan::New<Number>(max));
        Nan::Set(obj, Nan::New("min").ToLocalChecked(), Nan::New<Number>(min));
        Nan::Set(limits, Nan::New(name).ToLocalChecked(), obj);
    };

    setMaxMin("memoryCost", log(ARGON2_MAX_MEMORY), log(ARGON2_MIN_MEMORY));
    setMaxMin("timeCost", ARGON2_MAX_TIME, ARGON2_MIN_TIME);
    setMaxMin("parallelism", ARGON2_MAX_LANES, ARGON2_MIN_LANES);

    Nan::Set(target, Nan::New("limits").ToLocalChecked(), limits);
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "verify", Verify);
}

}

NODE_MODULE(argon2_lib, NodeArgon2::init);
<commit_msg>Properly implement move construction of parameters<commit_after>#include <node.h>

#include <stdint.h>
#include <cstring>
#include <string>
#include <tuple>

#include "../argon2/include/argon2.h"
#include "argon2_node.h"

namespace NodeArgon2 {

template<class T>
T fromJust(v8::Local<v8::Value> info) {
    return Nan::To<T>(info).FromJust();
}

using size_type = std::string::size_type;
const auto HASH_LEN = 32u;

enum OBJECTS {
    RESERVED = 0,
    THIS_OBJ,
    RESOLVE,
    REJECT,
};

constexpr auto log(uint64_t number, uint64_t base = 2u) -> decltype(number)
{
    return (number > 1) ? 1u + log(number / base, base) : 0u;
}

constexpr auto base64Length(size_type length) -> decltype(length)
{
    return ((length + 2u) / 3u) * 4u;
}

auto encodedLength(size_type saltLength) -> decltype(saltLength)
{
    /* statically calculate maximum encoded hash length */
    constexpr size_type extraLength = sizeof "$argon2x$m=,t=,p=$$" +
        log(ARGON2_MAX_MEMORY + 1u, 10u) + log(ARGON2_MAX_TIME + 1u, 10u) +
        log(ARGON2_MAX_LANES + 1u, 10u) + base64Length(HASH_LEN);

    return extraLength + base64Length(saltLength);
}

HashWorker::HashWorker(std::string&& plain, std::string&& salt,
        std::tuple<uint32_t, uint32_t, uint32_t, argon2_type>&& params):
    Nan::AsyncWorker{nullptr}, plain{std::move(plain)}, salt{std::move(salt)},
    time_cost{std::get<0>(params)}, memory_cost{std::get<1>(params)},
    parallelism{std::get<2>(params)}, type{std::get<3>(params)}
{ }

void HashWorker::Execute()
{
    const auto ENCODED_LEN = encodedLength(salt.size());
    output.reset(new char[ENCODED_LEN]);

    auto result = argon2_hash(time_cost, memory_cost, parallelism,
            plain.c_str(), plain.size(), salt.c_str(), salt.size(), nullptr,
            HASH_LEN, output.get(), ENCODED_LEN, type, ARGON2_VERSION_NUMBER);

    if (result != ARGON2_OK) {
        /* LCOV_EXCL_START */
        SetErrorMessage(argon2_error_message(result));
        /* LCOV_EXCL_STOP */
    }
}

void HashWorker::HandleOKCallback()
{
    using namespace v8;
    using std::strlen;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::Encode(output.get(), strlen(output.get()))};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void HashWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Hash) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 8);

    const auto plain = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto salt = Nan::To<Object>(info[1]).ToLocalChecked();
    const auto options = Nan::To<Object>(info[2]).ToLocalChecked();

    const auto getArg = [&](const char* key) {
        auto localKey = Nan::New(key).ToLocalChecked();
        return Nan::Get(options, localKey).ToLocalChecked();
    };

    auto worker = new HashWorker{
            {Buffer::Data(plain), Buffer::Length(plain)},
            {Buffer::Data(salt), Buffer::Length(salt)},
            std::make_tuple(fromJust<uint32_t>(getArg("timeCost")),
                    1u << fromJust<uint32_t>(getArg("memoryCost")),
                    fromJust<uint32_t>(getArg("parallelism")),
                    fromJust<bool>(getArg("argon2d")) ? Argon2_d : Argon2_i)};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[3]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[4]));

    Nan::AsyncQueueWorker(worker);
}

VerifyWorker::VerifyWorker(std::string&& hash, std::string&& plain):
    Nan::AsyncWorker{nullptr}, hash{std::move(hash)}, plain{std::move(plain)}
{ }

void VerifyWorker::Execute()
{
    auto type = (hash.at(7) == 'd') ? Argon2_d : Argon2_i;
    auto result = argon2_verify(hash.c_str(), plain.c_str(), plain.size(), type);

    switch (result) {
        case ARGON2_OK:
        case ARGON2_VERIFY_MISMATCH:
            output = result == ARGON2_OK;
            break;
        default:
            /* LCOV_EXCL_START */
            SetErrorMessage(argon2_error_message(result));
            break;
            /* LCOV_EXCL_STOP */
    }
}

void VerifyWorker::HandleOKCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(output)};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(RESOLVE).As<Function>(), 1, argv);
}

/* LCOV_EXCL_START */
void VerifyWorker::HandleErrorCallback()
{
    using namespace v8;

    Nan::HandleScope scope;

    Local<Value> argv[] = {Nan::New(ErrorMessage()).ToLocalChecked()};
    Nan::MakeCallback(GetFromPersistent(THIS_OBJ).As<Object>(),
            GetFromPersistent(REJECT).As<Function>(), 1, argv);
}
/* LCOV_EXCL_STOP */

NAN_METHOD(Verify) {
    using namespace node;
    using namespace v8;

    assert(info.Length() >= 5);

    const auto hash = Nan::To<Object>(info[0]).ToLocalChecked();
    const auto plain = Nan::To<Object>(info[1]).ToLocalChecked();

    auto worker = new VerifyWorker{{Buffer::Data(hash), Buffer::Length(hash)},
            {Buffer::Data(plain), Buffer::Length(plain)}};

    worker->SaveToPersistent(THIS_OBJ, info.This());
    worker->SaveToPersistent(RESOLVE, Local<Function>::Cast(info[2]));
    worker->SaveToPersistent(REJECT, Local<Function>::Cast(info[3]));

    Nan::AsyncQueueWorker(worker);
}

NAN_MODULE_INIT(init) {
    using namespace v8;

    auto limits = Nan::New<Object>();

    const auto setMaxMin = [&](const char* name, uint32_t max, uint32_t min) {
        auto obj = Nan::New<Object>();
        Nan::Set(obj, Nan::New("max").ToLocalChecked(), Nan::New<Number>(max));
        Nan::Set(obj, Nan::New("min").ToLocalChecked(), Nan::New<Number>(min));
        Nan::Set(limits, Nan::New(name).ToLocalChecked(), obj);
    };

    setMaxMin("memoryCost", log(ARGON2_MAX_MEMORY), log(ARGON2_MIN_MEMORY));
    setMaxMin("timeCost", ARGON2_MAX_TIME, ARGON2_MIN_TIME);
    setMaxMin("parallelism", ARGON2_MAX_LANES, ARGON2_MIN_LANES);

    Nan::Set(target, Nan::New("limits").ToLocalChecked(), limits);
    Nan::Export(target, "hash", Hash);
    Nan::Export(target, "verify", Verify);
}

}

NODE_MODULE(argon2_lib, NodeArgon2::init);
<|endoftext|>


<commit_before>#include <assert.h>
#include <math.h>
#include "commonmodel.h"
#include "common/clutil.h"
#include "common/mat.h"
#include "common/timing.h"

void frame_init(ModelFrame* frame, int width, int height,
                      cl_device_id device_id, cl_context context) {
  transform_init(&frame->transform, context, device_id);
  frame->width = width;
  frame->height = height;

  frame->y_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)width*height, NULL, &err));
  frame->u_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)(width/2)*(height/2), NULL, &err));
  frame->v_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)(width/2)*(height/2), NULL, &err));
  frame->net_input_size = ((width*height*3)/2)*sizeof(float);
  frame->net_input = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE,
                                frame->net_input_size, (void*)NULL, &err));
  loadyuv_init(&frame->loadyuv, context, device_id, width, height);
}

float *frame_prepare(ModelFrame* frame, cl_command_queue q,
                           cl_mem yuv_cl, int width, int height,
                           const mat3 &transform) {
  transform_queue(&frame->transform, q,
                  yuv_cl, width, height,
                  frame->y_cl, frame->u_cl, frame->v_cl,
                  frame->width, frame->height,
                  transform);
  loadyuv_queue(&frame->loadyuv, q,
                frame->y_cl, frame->u_cl, frame->v_cl,
                frame->net_input);
  float *net_input_buf = (float *)CL_CHECK_ERR(clEnqueueMapBuffer(q, frame->net_input, CL_TRUE,
                                            CL_MAP_READ, 0, frame->net_input_size,
                                            0, NULL, NULL, &err));
  clFinish(q);
  return net_input_buf;
}

void frame_free(ModelFrame* frame) {
  transform_destroy(&frame->transform);
  loadyuv_destroy(&frame->loadyuv);
  CL_CHECK(clReleaseMemObject(frame->net_input));
  CL_CHECK(clReleaseMemObject(frame->v_cl));
  CL_CHECK(clReleaseMemObject(frame->u_cl));
  CL_CHECK(clReleaseMemObject(frame->y_cl));
}

void softmax(const float* input, float* output, size_t len) {
  float max_val = -FLT_MAX;
  for(int i = 0; i < len; i++) {
    const float v = input[i];
    if( v > max_val ) {
      max_val = v;
    }
  }

  float denominator = 0;
  for(int i = 0; i < len; i++) {
    float const v = input[i];
    float const v_exp = expf(v - max_val);
    denominator += v_exp;
    output[i] = v_exp;
  }

  const float inv_denominator = 1. / denominator;
  for(int i = 0; i < len; i++) {
    output[i] *= inv_denominator;
  }

}

float sigmoid(float input) {
  return 1 / (1 + expf(-input));
}

float softplus(float input) {
  return log1p(expf(input));
}
<commit_msg>softmax(): use std::max_element (#20306)<commit_after>#include <assert.h>
#include <math.h>
#include <algorithm>
#include "commonmodel.h"
#include "common/clutil.h"
#include "common/mat.h"
#include "common/timing.h"

void frame_init(ModelFrame* frame, int width, int height,
                      cl_device_id device_id, cl_context context) {
  transform_init(&frame->transform, context, device_id);
  frame->width = width;
  frame->height = height;

  frame->y_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)width*height, NULL, &err));
  frame->u_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)(width/2)*(height/2), NULL, &err));
  frame->v_cl = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE, (size_t)(width/2)*(height/2), NULL, &err));
  frame->net_input_size = ((width*height*3)/2)*sizeof(float);
  frame->net_input = CL_CHECK_ERR(clCreateBuffer(context, CL_MEM_READ_WRITE,
                                frame->net_input_size, (void*)NULL, &err));
  loadyuv_init(&frame->loadyuv, context, device_id, width, height);
}

float *frame_prepare(ModelFrame* frame, cl_command_queue q,
                           cl_mem yuv_cl, int width, int height,
                           const mat3 &transform) {
  transform_queue(&frame->transform, q,
                  yuv_cl, width, height,
                  frame->y_cl, frame->u_cl, frame->v_cl,
                  frame->width, frame->height,
                  transform);
  loadyuv_queue(&frame->loadyuv, q,
                frame->y_cl, frame->u_cl, frame->v_cl,
                frame->net_input);
  float *net_input_buf = (float *)CL_CHECK_ERR(clEnqueueMapBuffer(q, frame->net_input, CL_TRUE,
                                            CL_MAP_READ, 0, frame->net_input_size,
                                            0, NULL, NULL, &err));
  clFinish(q);
  return net_input_buf;
}

void frame_free(ModelFrame* frame) {
  transform_destroy(&frame->transform);
  loadyuv_destroy(&frame->loadyuv);
  CL_CHECK(clReleaseMemObject(frame->net_input));
  CL_CHECK(clReleaseMemObject(frame->v_cl));
  CL_CHECK(clReleaseMemObject(frame->u_cl));
  CL_CHECK(clReleaseMemObject(frame->y_cl));
}

void softmax(const float* input, float* output, size_t len) {
  const float max_val = *std::max_element(input, input + len);
  float denominator = 0;
  for(int i = 0; i < len; i++) {
    float const v_exp = expf(input[i] - max_val);
    denominator += v_exp;
    output[i] = v_exp;
  }

  const float inv_denominator = 1. / denominator;
  for(int i = 0; i < len; i++) {
    output[i] *= inv_denominator;
  }
}

float sigmoid(float input) {
  return 1 / (1 + expf(-input));
}

float softplus(float input) {
  return log1p(expf(input));
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the $MODULE$ of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used 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.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qglobal.h> // for Q_WS_WIN define (non-PCH)

#include <QtGui/qpaintdevice.h>
#include <private/qwidget_p.h>
#include "qwindowsurface_s60_p.h"
#include "qt_s60_p.h"
#include "private/qdrawhelper_p.h"

QT_BEGIN_NAMESPACE

struct QS60WindowSurfacePrivate
{
    QImage device;
    CFbsBitmap *bitmap;
    uchar* bytes;

    // Since only one CFbsBitmap is allowed to be locked at a time, this is static.
    static QS60WindowSurface* lockedSurface;
};
QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL;

QS60WindowSurface::QS60WindowSurface(QWidget* widget)
    : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
{
    d_ptr->bytes = 0;
    d_ptr->bitmap = 0;

    TDisplayMode mode = S60->screenDevice()->DisplayMode();
    bool isOpaque = qt_widget_private(widget)->isOpaque;
    if (mode == EColor16MA && isOpaque)
        mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated
    else if (mode == EColor16MU && !isOpaque)
        mode = EColor16MA; // Try for transparency anyway

    // We create empty CFbsBitmap here -> it will be resized in setGeometry
    d_ptr->bitmap = q_check_ptr(new CFbsBitmap);	// CBase derived object needs check on new
    qt_throwIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) );

    updatePaintDeviceOnBitmap();

    setStaticContentsSupport(true);
}

QS60WindowSurface::~QS60WindowSurface()
{
    // Ensure that locking and unlocking of this surface were symmetrical
    Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface != this);

    delete d_ptr->bitmap;
    delete d_ptr;
}

void QS60WindowSurface::beginPaint(const QRegion &rgn)
{
    if(!d_ptr->bitmap)
        return;

    Q_ASSERT(!QS60WindowSurfacePrivate::lockedSurface);
    QS60WindowSurfacePrivate::lockedSurface = this;
    lockBitmapHeap();

    if (!qt_widget_private(window())->isOpaque) {
        QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits());
        const int row_stride = d_ptr->device.bytesPerLine() / 4;

        const QVector<QRect> rects = rgn.rects();
        for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
            const int x_start = it->x();
            const int width = it->width();

            const int y_start = it->y();
            const int height = it->height();

            QRgb *row = data + row_stride * y_start;
            for (int y = 0; y < height; ++y) {
                qt_memfill(row + x_start, 0U, width);
                row += row_stride;
            }
        }
    }
}

void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
{
    const QVector<QRect> subRects = region.rects();
    for (int i = 0; i < subRects.count(); ++i) {
        TRect tr = qt_QRect2TRect(subRects[i]);
        widget->winId()->DrawNow(tr);
    }
}

bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy)
{
    QRect rect = area.boundingRect();

    if (dx == 0 && dy == 0)
        return false;

    if (d_ptr->device.isNull())
        return false;

    CFbsBitmapDevice *bitmapDevice = 0;
    QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap));
    CBitmapContext *bitmapContext;
    TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
    if (err != KErrNone) {
        CBase::Delete(bitmapDevice);
        return false;
    }
    bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
    CBase::Delete(bitmapContext);
    CBase::Delete(bitmapDevice);
    return true;
}

void QS60WindowSurface::endPaint(const QRegion & /* rgn */)
{
    if(!d_ptr->bitmap)
        return;

    Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface);
    unlockBitmapHeap();
    QS60WindowSurfacePrivate::lockedSurface = NULL;
}

QPaintDevice* QS60WindowSurface::paintDevice()
{
    return &d_ptr->device;
}

void QS60WindowSurface::setGeometry(const QRect& rect)
{
    if (rect == geometry())
        return;

    QWindowSurface::setGeometry(rect);

    TRect nativeRect(qt_QRect2TRect(rect));
    qt_throwIfError(d_ptr->bitmap->Resize(nativeRect.Size()));

    if (!rect.isNull())
        updatePaintDeviceOnBitmap();
}

void QS60WindowSurface::lockBitmapHeap()
{
    if (!QS60WindowSurfacePrivate::lockedSurface)
        return;

    // Get some local variables to make later code lines more clear to read
    CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap;
    QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device;
    uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes;

    bitmap->LockHeap();
    uchar *newBytes = (uchar*)bitmap->DataAddress();
    if (newBytes != bytes) {
        bytes = newBytes;

        // Get some values for QImage creation
        TDisplayMode mode  = bitmap->DisplayMode();
        if (mode == EColor16MA
            && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque)
            mode = EColor16MU;
        QImage::Format format = qt_TDisplayMode2Format( mode );
        TSize bitmapSize = bitmap->SizeInPixels();
        int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode);

        device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format );
    }
}

void QS60WindowSurface::unlockBitmapHeap()
{
    if (!QS60WindowSurfacePrivate::lockedSurface)
        return;

    QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap();
}

void QS60WindowSurface::updatePaintDeviceOnBitmap()
{
    // This forces the actual device to be updated based on CFbsBitmap
    beginPaint(QRegion());
    endPaint(QRegion());
}

CFbsBitmap *QS60WindowSurface::symbianBitmap() const
{
    return d_ptr->bitmap;
}

QT_END_NAMESPACE
<commit_msg>replacing assert with recovery for begin/end paint lock for exception compatability<commit_after>/****************************************************************************
**
** Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
** This file is part of the $MODULE$ of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the either Technology Preview License Agreement or the
** Beta Release License Agreement.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used 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.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain
** additional rights. These rights are described in the Nokia Qt LGPL
** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
** package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <qglobal.h> // for Q_WS_WIN define (non-PCH)

#include <QtGui/qpaintdevice.h>
#include <private/qwidget_p.h>
#include "qwindowsurface_s60_p.h"
#include "qt_s60_p.h"
#include "private/qdrawhelper_p.h"

QT_BEGIN_NAMESPACE

struct QS60WindowSurfacePrivate
{
    QImage device;
    CFbsBitmap *bitmap;
    uchar* bytes;

    // Since only one CFbsBitmap is allowed to be locked at a time, this is static.
    static QS60WindowSurface* lockedSurface;
};
QS60WindowSurface* QS60WindowSurfacePrivate::lockedSurface = NULL;

QS60WindowSurface::QS60WindowSurface(QWidget* widget)
    : QWindowSurface(widget), d_ptr(new QS60WindowSurfacePrivate)
{
    d_ptr->bytes = 0;
    d_ptr->bitmap = 0;

    TDisplayMode mode = S60->screenDevice()->DisplayMode();
    bool isOpaque = qt_widget_private(widget)->isOpaque;
    if (mode == EColor16MA && isOpaque)
        mode = EColor16MU; // Faster since 16MU -> 16MA is typically accelerated
    else if (mode == EColor16MU && !isOpaque)
        mode = EColor16MA; // Try for transparency anyway

    // We create empty CFbsBitmap here -> it will be resized in setGeometry
    d_ptr->bitmap = q_check_ptr(new CFbsBitmap);	// CBase derived object needs check on new
    qt_throwIfError( d_ptr->bitmap->Create(TSize(0, 0), mode ) );

    updatePaintDeviceOnBitmap();

    setStaticContentsSupport(true);
}

QS60WindowSurface::~QS60WindowSurface()
{
    if (QS60WindowSurfacePrivate::lockedSurface == this)
        unlockBitmapHeap();

    delete d_ptr->bitmap;
    delete d_ptr;
}

void QS60WindowSurface::beginPaint(const QRegion &rgn)
{
    if(!d_ptr->bitmap)
        return;

    if (QS60WindowSurfacePrivate::lockedSurface)
        unlockBitmapHeap();

    QS60WindowSurfacePrivate::lockedSurface = this;
    lockBitmapHeap();

    if (!qt_widget_private(window())->isOpaque) {
        QRgb *data = reinterpret_cast<QRgb *>(d_ptr->device.bits());
        const int row_stride = d_ptr->device.bytesPerLine() / 4;

        const QVector<QRect> rects = rgn.rects();
        for (QVector<QRect>::const_iterator it = rects.begin(); it != rects.end(); ++it) {
            const int x_start = it->x();
            const int width = it->width();

            const int y_start = it->y();
            const int height = it->height();

            QRgb *row = data + row_stride * y_start;
            for (int y = 0; y < height; ++y) {
                qt_memfill(row + x_start, 0U, width);
                row += row_stride;
            }
        }
    }
}

void QS60WindowSurface::flush(QWidget *widget, const QRegion &region, const QPoint &)
{
    const QVector<QRect> subRects = region.rects();
    for (int i = 0; i < subRects.count(); ++i) {
        TRect tr = qt_QRect2TRect(subRects[i]);
        widget->winId()->DrawNow(tr);
    }
}

bool QS60WindowSurface::scroll(const QRegion &area, int dx, int dy)
{
    QRect rect = area.boundingRect();

    if (dx == 0 && dy == 0)
        return false;

    if (d_ptr->device.isNull())
        return false;

    CFbsBitmapDevice *bitmapDevice = 0;
    QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(d_ptr->bitmap));
    CBitmapContext *bitmapContext;
    TInt err = bitmapDevice->CreateBitmapContext(bitmapContext);
    if (err != KErrNone) {
        CBase::Delete(bitmapDevice);
        return false;
    }
    bitmapContext->CopyRect(TPoint(dx, dy), qt_QRect2TRect(rect));
    CBase::Delete(bitmapContext);
    CBase::Delete(bitmapDevice);
    return true;
}

void QS60WindowSurface::endPaint(const QRegion & /* rgn */)
{
    if(!d_ptr->bitmap)
        return;

    Q_ASSERT(QS60WindowSurfacePrivate::lockedSurface);
    unlockBitmapHeap();
    QS60WindowSurfacePrivate::lockedSurface = NULL;
}

QPaintDevice* QS60WindowSurface::paintDevice()
{
    return &d_ptr->device;
}

void QS60WindowSurface::setGeometry(const QRect& rect)
{
    if (rect == geometry())
        return;

    QWindowSurface::setGeometry(rect);

    TRect nativeRect(qt_QRect2TRect(rect));
    qt_throwIfError(d_ptr->bitmap->Resize(nativeRect.Size()));

    if (!rect.isNull())
        updatePaintDeviceOnBitmap();
}

void QS60WindowSurface::lockBitmapHeap()
{
    if (!QS60WindowSurfacePrivate::lockedSurface)
        return;

    // Get some local variables to make later code lines more clear to read
    CFbsBitmap*& bitmap = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap;
    QImage& device = QS60WindowSurfacePrivate::lockedSurface->d_ptr->device;
    uchar*& bytes = QS60WindowSurfacePrivate::lockedSurface->d_ptr->bytes;

    bitmap->LockHeap();
    uchar *newBytes = (uchar*)bitmap->DataAddress();
    if (newBytes != bytes) {
        bytes = newBytes;

        // Get some values for QImage creation
        TDisplayMode mode  = bitmap->DisplayMode();
        if (mode == EColor16MA
            && qt_widget_private(QS60WindowSurfacePrivate::lockedSurface->window())->isOpaque)
            mode = EColor16MU;
        QImage::Format format = qt_TDisplayMode2Format( mode );
        TSize bitmapSize = bitmap->SizeInPixels();
        int bytesPerLine = CFbsBitmap::ScanLineLength( bitmapSize.iWidth, mode);

        device = QImage( bytes, bitmapSize.iWidth, bitmapSize.iHeight, bytesPerLine, format );
    }
}

void QS60WindowSurface::unlockBitmapHeap()
{
    if (!QS60WindowSurfacePrivate::lockedSurface)
        return;

    QS60WindowSurfacePrivate::lockedSurface->d_ptr->bitmap->UnlockHeap();
}

void QS60WindowSurface::updatePaintDeviceOnBitmap()
{
    // This forces the actual device to be updated based on CFbsBitmap
    beginPaint(QRegion());
    endPaint(QRegion());
}

CFbsBitmap *QS60WindowSurface::symbianBitmap() const
{
    return d_ptr->bitmap;
}

QT_END_NAMESPACE
<|endoftext|>


<commit_before>/*
 =====================================================================================
        Filename:  fork_lock.cpp
     	Description:  fork导致的死锁，并通过pthread_atfork来解决
        Version:  1.0
        Created:  05/15/2015 06:33:16 AM
        Revision:  none
        Compiler:  gcc
        Author:  Jeff (), zyfforlinux@163.com
    	Organization:  Linux
 =====================================================================================
 */

//因为fork复制了锁的状态，导致子进程死锁了
#include <iostream>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* doit(void *data)
{
    printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));
    pthread_mutex_lock(&mutex);
    struct timespec sp = {2,0};
    nanosleep(&sp,NULL);
    pthread_mutex_unlock(&mutex);
    printf("pid = %d end doit ...\n",static_cast<int>(getpid()));
}

int main()
{
    printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));
    pthread_t p;
    pthread_create(&p,NULL,doit,NULL);
    struct timespec ts = {1,0};
    nanosleep(&ts,NULL);
    if (fork() == 0) {
        doit(NULL);
    }
    pthread_join(p,NULL);
    printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));
}
<commit_msg>fork后死锁的解释<commit_after>/*
 =====================================================================================
        Filename:  fork_lock.cpp
     	Description:  fork导致的死锁，并通过pthread_atfork来解决
        Version:  1.0
        Created:  05/15/2015 06:33:16 AM
        Revision:  none
        Compiler:  gcc
        Author:  Jeff (), zyfforlinux@163.com
    	Organization:  Linux
 =====================================================================================
 */

//因为fork复制了锁的状态，导致子进程死锁了
#include <iostream>
#include <pthread.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void* doit(void *data)
{
    printf("pid = %d begin doit ...\n",static_cast<int>(getpid()));
    pthread_mutex_lock(&mutex);
    struct timespec sp = {2,0};
    nanosleep(&sp,NULL);
    pthread_mutex_unlock(&mutex);
    printf("pid = %d end doit ...\n",static_cast<int>(getpid()));
}

int main()
{
    printf("pid = %d Entering main ...\n", static_cast<int>(getpid()));
    pthread_t p;
    pthread_create(&p,NULL,doit,NULL);
    struct timespec ts = {1,0};
    nanosleep(&ts,NULL);
    if (fork() == 0) {
        doit(NULL);//线程中已经加锁了，导致子进程执行的时候锁的状态是锁定的，
                   //所以导致子进程再次加锁出现死锁。
    }
    pthread_join(p,NULL);
    printf("pid = %d Exiting main ...\n",static_cast<int>(getpid()));
}
<|endoftext|>


<commit_before>// 18 november 2015
#include "uipriv_haiku.hpp"

class libuiBWindow : public BWindow {
public:
	// C++11! Inherit constructors.
	using BWindow::BWindow;

	uiWindow *w;
	virtual bool QuitRequested();
};

struct uiWindow {
	uiHaikuControl c;

	libuiBWindow *window;

	struct child *child;
	int margined;

	int (*onClosing)(uiWindow *, void *);
	void *onClosingData;
};

uiHaikuDefineControlWithOnDestroy(
	uiWindow,							// type name
	uiWindowType,							// type function
	window,								// handle
	complain("attempt to use default CommitDestroy() code for uiWindow on Haiku");			// on destroy
)

// TODO is this correct?
bool libuiBWindow::QuitRequested()
{
	// manually destroy the window ourselves; don't let the default BWindow code do it directly
	if ((*(this->w->onClosing))(this->w, this->w->onClosingData))
		uiControlDestroy(uiControl(this->w));
	// don't continue to the default BWindow code; we destroyed the window by now
	return false;
}

static int defaultOnClosing(uiWindow *w, void *data)
{
	return 0;
}

static void windowCommitDestroy(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	// first hide ourselves
	w->window->Hide();
	// now destroy the child
//TODO	if (w->child != NULL)
//TODO		childDestroy(w->child);
	// and finally destroy ourselves
	// this is why we don't use the libui-provided CommitDestroy() implementation
	w->window->Lock();
	w->window->Quit();
	// w->window is now destroyed for us
}

// The default implementations assume a BView, which a uiWindow is not.
static void windowCommitShow(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	// This is documented as behaving how we want with regards to presentation.
	w->window->Show();
}

static void windowCommitHide(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	w->window->Hide();
}

static void windowContainerUpdateState(uiControl *c)
{
/*TODO
	uiWindow *w = uiWindow(c);

	if (w->child != NULL)
		childUpdateState(w->child);
*/
}

char *uiWindowTitle(uiWindow *w)
{
	return uiHaikuStrdupText(w->window->Title());
}

void uiWindowSetTitle(uiWindow *w, const char *title)
{
	w->window->SetTitle(title);
	// don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long)
}

void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
	w->onClosing = f;
	w->onClosingData = data;
}

void uiWindowSetChild(uiWindow *w, uiControl *child)
{
/*TODO
	if (w->child != NULL)
		childDestroy(w->child);
	w->child = newChildWithBox(child, uiControl(w), w->vboxContainer, w->margined);
	if (w->child != NULL) {
		gtk_widget_set_hexpand(childBox(w->child), TRUE);
		gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL);
		gtk_widget_set_vexpand(childBox(w->child), TRUE);
		gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL);
	}
*/
}

int uiWindowMargined(uiWindow *w)
{
	return w->margined;
}

void uiWindowSetMargined(uiWindow *w, int margined)
{
	w->margined = margined;
//TODO	if (w->child != NULL)
//TODO		childSetMargined(w->child, w->margined);
}

uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
	uiWindow *w;

	w = (uiWindow *) uiNewControl(uiWindowType());

	// TODO find out how to make it ignore position
	// The given rect is the size of the inside of the window, just as we want.
	w->window = new libuiBWindow(
		BRect(100, 100, width, height),
		title,
		B_TITLED_WINDOW,
		B_ASYNCHRONOUS_CONTROLS);
	w->window->w = w;

	uiWindowOnClosing(w, defaultOnClosing, NULL);

	uiHaikuFinishNewControl(w, uiWindow);
	uiControl(w)->CommitDestroy = windowCommitDestroy;
	uiControl(w)->CommitShow = windowCommitShow;
	uiControl(w)->CommitHide = windowCommitHide;
	uiControl(w)->ContainerUpdateState = windowContainerUpdateState;

	return w;
}
<commit_msg>More TODOs.<commit_after>// 18 november 2015
#include "uipriv_haiku.hpp"

class libuiBWindow : public BWindow {
public:
	// C++11! Inherit constructors.
	using BWindow::BWindow;

	uiWindow *w;
	virtual bool QuitRequested();
};

struct uiWindow {
	uiHaikuControl c;

	libuiBWindow *window;

	struct child *child;
	int margined;

	int (*onClosing)(uiWindow *, void *);
	void *onClosingData;
};

uiHaikuDefineControlWithOnDestroy(
	uiWindow,							// type name
	uiWindowType,							// type function
	window,								// handle
	complain("attempt to use default CommitDestroy() code for uiWindow on Haiku");			// on destroy
)

// TODO is this correct?
bool libuiBWindow::QuitRequested()
{
	// manually destroy the window ourselves; don't let the default BWindow code do it directly
	if ((*(this->w->onClosing))(this->w, this->w->onClosingData))
		uiControlDestroy(uiControl(this->w));
	// don't continue to the default BWindow code; we destroyed the window by now
	return false;
}

static int defaultOnClosing(uiWindow *w, void *data)
{
	return 0;
}

static void windowCommitDestroy(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	// first hide ourselves
	w->window->Hide();
	// now destroy the child
//TODO	if (w->child != NULL)
//TODO		childDestroy(w->child);
	// and finally destroy ourselves
	// this is why we don't use the libui-provided CommitDestroy() implementation
	// TODO check this for errors?
	w->window->Lock();
	w->window->Quit();
	// w->window is now destroyed for us
}

// The default implementations assume a BView, which a uiWindow is not.
static void windowCommitShow(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	// This is documented as behaving how we want with regards to presentation.
	w->window->Show();
}

static void windowCommitHide(uiControl *c)
{
	uiWindow *w = uiWindow(c);

	w->window->Hide();
}

static void windowContainerUpdateState(uiControl *c)
{
/*TODO
	uiWindow *w = uiWindow(c);

	if (w->child != NULL)
		childUpdateState(w->child);
*/
}

char *uiWindowTitle(uiWindow *w)
{
	return uiHaikuStrdupText(w->window->Title());
}

void uiWindowSetTitle(uiWindow *w, const char *title)
{
	w->window->SetTitle(title);
	// don't queue resize; the caption isn't part of what affects layout and sizing of the client area (it'll be ellipsized if too long)
}

void uiWindowOnClosing(uiWindow *w, int (*f)(uiWindow *, void *), void *data)
{
	w->onClosing = f;
	w->onClosingData = data;
}

void uiWindowSetChild(uiWindow *w, uiControl *child)
{
/*TODO
	if (w->child != NULL)
		childDestroy(w->child);
	w->child = newChildWithBox(child, uiControl(w), w->vboxContainer, w->margined);
	if (w->child != NULL) {
		gtk_widget_set_hexpand(childBox(w->child), TRUE);
		gtk_widget_set_halign(childBox(w->child), GTK_ALIGN_FILL);
		gtk_widget_set_vexpand(childBox(w->child), TRUE);
		gtk_widget_set_valign(childBox(w->child), GTK_ALIGN_FILL);
	}
*/
}

int uiWindowMargined(uiWindow *w)
{
	return w->margined;
}

void uiWindowSetMargined(uiWindow *w, int margined)
{
	w->margined = margined;
//TODO	if (w->child != NULL)
//TODO		childSetMargined(w->child, w->margined);
}

uiWindow *uiNewWindow(const char *title, int width, int height, int hasMenubar)
{
	uiWindow *w;

	w = (uiWindow *) uiNewControl(uiWindowType());

	// TODO find out how to make it ignore position
	// The given rect is the size of the inside of the window, just as we want.
	w->window = new libuiBWindow(
		BRect(100, 100, width, height),
		title,
		B_TITLED_WINDOW,
		B_ASYNCHRONOUS_CONTROLS);
	w->window->w = w;

	uiWindowOnClosing(w, defaultOnClosing, NULL);

	uiHaikuFinishNewControl(w, uiWindow);
	uiControl(w)->CommitDestroy = windowCommitDestroy;
	uiControl(w)->CommitShow = windowCommitShow;
	uiControl(w)->CommitHide = windowCommitHide;
	uiControl(w)->ContainerUpdateState = windowContainerUpdateState;

	return w;
}
<|endoftext|>


<commit_before>#include "ingameelements/heroes/reinhardt.h"
#include "datastructures.h"
#include "spriteloader.h"
#include "animation.h"
#include "gamestate.h"
#include "engine.h"

#include <memory>
#include <cmath>
#include <allegro5/allegro_primitives.h>

void Reinhardt::init(uint64_t id_, Gamestate *state, EntityPtr owner_)
{
    Character::init(id_, state, owner_);

    chargeanim.init(herofolder()+"charge/", std::bind(&Reinhardt::endcharge, this));
    chargeanim.active(false);
    preparechargeanim.init(herofolder()+"preparecharge/", std::bind(&Reinhardt::begincharge, this));
    preparechargeanim.active(false);
    endchargeanim.init(herofolder()+"endcharge/");
    endchargeanim.active(false);
    earthshatteranim.init(herofolder()+"ult/");
    earthshatteranim.active(false);
    shieldrunanim.init(herofolder()+"shieldrun/");
}

void Reinhardt::render(Renderer *renderer, Gamestate *state)
{
    Character::render(renderer, state);
    al_set_target_bitmap(renderer->midground);

    // Render weapon back first
    state->get<Hammer>(weapon)->renderbehind(renderer, state);

    std::string mainsprite;
    ALLEGRO_BITMAP *sprite;
    double spriteoffset_x, spriteoffset_y;
    double rel_x, rel_y;

    mainsprite = getsprite(state, false);
    sprite = renderer->spriteloader.requestsprite(mainsprite);
    spriteoffset_x = renderer->spriteloader.get_spriteoffset_x(mainsprite)*renderer->zoom;
    spriteoffset_y = renderer->spriteloader.get_spriteoffset_y(mainsprite)*renderer->zoom;
    rel_x = (x-renderer->cam_x)*renderer->zoom;
    rel_y = (y-renderer->cam_y)*renderer->zoom;

    ALLEGRO_BITMAP *outline = renderer->spriteloader.requestspriteoutline(mainsprite);
    ALLEGRO_COLOR outlinecolor = al_map_rgb(225, 17, 17);

    if (isflipped)
    {
        // Flip horizontally
        al_draw_scaled_rotated_bitmap(sprite, spriteoffset_x, spriteoffset_y, rel_x, rel_y, -1, 1, 0, 0);
        if (state->get<Player>(renderer->myself)->team != team)
        {
            // Draw enemy outline
            al_draw_tinted_scaled_rotated_bitmap(outline, outlinecolor, spriteoffset_x, spriteoffset_y, rel_x, rel_y, -1, 1, 0, 0);
        }
    }
    else
    {
        al_draw_bitmap(sprite, rel_x-spriteoffset_x, rel_y-spriteoffset_y, 0);
        if (state->get<Player>(renderer->myself)->team != team)
        {
            // Draw enemy outline
            al_draw_tinted_bitmap(outline, outlinecolor, rel_x-spriteoffset_x, rel_y-spriteoffset_y, 0);
        }
    }

    state->get<Weapon>(weapon)->render(renderer, state);
}

void Reinhardt::drawhud(Renderer *renderer, Gamestate *state)
{
    Character::drawhud(renderer, state);
}

void Reinhardt::midstep(Gamestate *state, double frametime)
{
    Character::midstep(state, frametime);

    if (chargeanim.active())
    {
        if (xblocked)
        {
            endcharge();
        }
        if (isflipped)
        {
            hspeed = -500;
        }
        else
        {
            hspeed = 500;
        }
    }
    chargeanim.update(state, frametime);
    preparechargeanim.update(state, frametime);
    endchargeanim.update(state, frametime);
    earthshatteranim.update(state, frametime);
    if (onground(state))
    {
        if (isflipped)
        {
            shieldrunanim.update(state, -hspeed*frametime);
        }
        else
        {
            shieldrunanim.update(state, hspeed*frametime);
        }
    }

    if (canuseabilities(state))
    {
        if (heldkeys.ABILITY_1 and state->engine->isserver)
        {
            useability1(state);
            state->engine->sendbuffer->write<uint8_t>(ABILITY1_USED);
            state->engine->sendbuffer->write<uint8_t>(state->findplayerid(owner));
        }
        if (heldkeys.ABILITY_2 and state->engine->isserver)
        {
            useability2(state);
            state->engine->sendbuffer->write<uint8_t>(ABILITY2_USED);
            state->engine->sendbuffer->write<uint8_t>(state->findplayerid(owner));
        }
    }
}

void Reinhardt::interpolate(Entity *prev_entity, Entity *next_entity, double alpha)
{
    Character::interpolate(prev_entity, next_entity, alpha);

    Reinhardt *p = static_cast<Reinhardt*>(prev_entity);
    Reinhardt *n = static_cast<Reinhardt*>(next_entity);

    preparechargeanim.interpolate(&(p->preparechargeanim), &(n->preparechargeanim), alpha);
    chargeanim.interpolate(&(p->chargeanim), &(n->chargeanim), alpha);
    endchargeanim.interpolate(&(p->endchargeanim), &(n->endchargeanim), alpha);
    earthshatteranim.interpolate(&(p->earthshatteranim), &(n->earthshatteranim), alpha);
    shieldrunanim.interpolate(&(p->shieldrunanim), &(n->shieldrunanim), alpha);
}

bool Reinhardt::cangetinput(Gamestate *state)
{
    return  not chargeanim.active() and not preparechargeanim.active() and not endchargeanim.active()
        and not earthshatteranim.active() and Character::cangetinput(state);
}

bool Reinhardt::weaponvisible(Gamestate *state)
{
    return  not stunanim.active() and not preparechargeanim.active() and not chargeanim.active()
        and not endchargeanim.active() and not earthshatteranim.active();
}

void Reinhardt::useability1(Gamestate *state)
{
    preparechargeanim.reset();
}

void Reinhardt::useability2(Gamestate *state)
{

}

void Reinhardt::useultimate(Gamestate *state)
{
    earthshatteranim.reset();
    Player *ownerplayer = state->get<Player>(owner);
    ownerplayer->ultcharge.reset();
}

void Reinhardt::interrupt(Gamestate *state)
{
    chargeanim.active(false);
    earthshatteranim.active(false);
}

Rect Reinhardt::getcollisionrect(Gamestate *state)
{
    if (crouchanim.active())
    {
        return state->engine->maskloader.get_rect_from_json(herofolder()+"crouch/").offset(x, y);
    }
    return getstandingcollisionrect(state);
}

Rect Reinhardt::getstandingcollisionrect(Gamestate *state)
{
    return state->engine->maskloader.get_rect_from_json(herofolder()).offset(x, y);
}

std::string Reinhardt::getsprite(Gamestate *state, bool mask)
{
    if (stunanim.active())
    {
        return stunanim.getframepath();
    }
    if (earthshatteranim.active())
    {
        return earthshatteranim.getframepath();
    }
    if (preparechargeanim.active())
    {
        return preparechargeanim.getframepath();
    }
    if (chargeanim.active())
    {
        return chargeanim.getframepath();
    }
    if (endchargeanim.active())
    {
        return endchargeanim.getframepath();
    }
    if (crouchanim.active())
    {
        return crouchanim.getframepath();
    }
    /*if (not ongroundsmooth.active)
    {
        if (vspeed > 100)
        {
            return herofolder()+"falling/1";
        }
        else
        {
            return herofolder()+"jump/1";
        }
    }*/
    if (std::fabs(hspeed) < 11.0 and not heldkeys.LEFT and not heldkeys.RIGHT)
    {
        return herofolder()+"idle/1";
    }
    Hammer *hammer = state->get<Hammer>(weapon);
    if (hammer->barrier.active)
    {
        return shieldrunanim.getframepath();
    }
    return runanim.getframepath();
}
<commit_msg>Made earthshatter pause until you hit the floor.<commit_after>#include "ingameelements/heroes/reinhardt.h"
#include "datastructures.h"
#include "spriteloader.h"
#include "animation.h"
#include "gamestate.h"
#include "engine.h"

#include <memory>
#include <cmath>
#include <allegro5/allegro_primitives.h>

void Reinhardt::init(uint64_t id_, Gamestate *state, EntityPtr owner_)
{
    Character::init(id_, state, owner_);

    chargeanim.init(herofolder()+"charge/", std::bind(&Reinhardt::endcharge, this));
    chargeanim.active(false);
    preparechargeanim.init(herofolder()+"preparecharge/", std::bind(&Reinhardt::begincharge, this));
    preparechargeanim.active(false);
    endchargeanim.init(herofolder()+"endcharge/");
    endchargeanim.active(false);
    earthshatteranim.init(herofolder()+"ult/");
    earthshatteranim.active(false);
    shieldrunanim.init(herofolder()+"shieldrun/");
}

void Reinhardt::render(Renderer *renderer, Gamestate *state)
{
    Character::render(renderer, state);
    al_set_target_bitmap(renderer->midground);

    // Render weapon back first
    state->get<Hammer>(weapon)->renderbehind(renderer, state);

    std::string mainsprite;
    ALLEGRO_BITMAP *sprite;
    double spriteoffset_x, spriteoffset_y;
    double rel_x, rel_y;

    mainsprite = getsprite(state, false);
    sprite = renderer->spriteloader.requestsprite(mainsprite);
    spriteoffset_x = renderer->spriteloader.get_spriteoffset_x(mainsprite)*renderer->zoom;
    spriteoffset_y = renderer->spriteloader.get_spriteoffset_y(mainsprite)*renderer->zoom;
    rel_x = (x-renderer->cam_x)*renderer->zoom;
    rel_y = (y-renderer->cam_y)*renderer->zoom;

    ALLEGRO_BITMAP *outline = renderer->spriteloader.requestspriteoutline(mainsprite);
    ALLEGRO_COLOR outlinecolor = al_map_rgb(225, 17, 17);

    if (isflipped)
    {
        // Flip horizontally
        al_draw_scaled_rotated_bitmap(sprite, spriteoffset_x, spriteoffset_y, rel_x, rel_y, -1, 1, 0, 0);
        if (state->get<Player>(renderer->myself)->team != team)
        {
            // Draw enemy outline
            al_draw_tinted_scaled_rotated_bitmap(outline, outlinecolor, spriteoffset_x, spriteoffset_y, rel_x, rel_y, -1, 1, 0, 0);
        }
    }
    else
    {
        al_draw_bitmap(sprite, rel_x-spriteoffset_x, rel_y-spriteoffset_y, 0);
        if (state->get<Player>(renderer->myself)->team != team)
        {
            // Draw enemy outline
            al_draw_tinted_bitmap(outline, outlinecolor, rel_x-spriteoffset_x, rel_y-spriteoffset_y, 0);
        }
    }

    state->get<Weapon>(weapon)->render(renderer, state);
}

void Reinhardt::drawhud(Renderer *renderer, Gamestate *state)
{
    Character::drawhud(renderer, state);
}

void Reinhardt::midstep(Gamestate *state, double frametime)
{
    Character::midstep(state, frametime);

    if (chargeanim.active())
    {
        if (xblocked)
        {
            endcharge();
        }
        if (isflipped)
        {
            hspeed = -500;
        }
        else
        {
            hspeed = 500;
        }
    }
    chargeanim.update(state, frametime);
    preparechargeanim.update(state, frametime);
    endchargeanim.update(state, frametime);
    if (earthshatteranim.active() and not (earthshatteranim.getframe() == 9 and not onground(state)))
    {
        earthshatteranim.update(state, frametime);
    }
    if (onground(state))
    {
        if (isflipped)
        {
            shieldrunanim.update(state, -hspeed*frametime);
        }
        else
        {
            shieldrunanim.update(state, hspeed*frametime);
        }
    }

    if (canuseabilities(state))
    {
        if (heldkeys.ABILITY_1 and state->engine->isserver)
        {
            useability1(state);
            state->engine->sendbuffer->write<uint8_t>(ABILITY1_USED);
            state->engine->sendbuffer->write<uint8_t>(state->findplayerid(owner));
        }
        if (heldkeys.ABILITY_2 and state->engine->isserver)
        {
            useability2(state);
            state->engine->sendbuffer->write<uint8_t>(ABILITY2_USED);
            state->engine->sendbuffer->write<uint8_t>(state->findplayerid(owner));
        }
    }
}

void Reinhardt::interpolate(Entity *prev_entity, Entity *next_entity, double alpha)
{
    Character::interpolate(prev_entity, next_entity, alpha);

    Reinhardt *p = static_cast<Reinhardt*>(prev_entity);
    Reinhardt *n = static_cast<Reinhardt*>(next_entity);

    preparechargeanim.interpolate(&(p->preparechargeanim), &(n->preparechargeanim), alpha);
    chargeanim.interpolate(&(p->chargeanim), &(n->chargeanim), alpha);
    endchargeanim.interpolate(&(p->endchargeanim), &(n->endchargeanim), alpha);
    earthshatteranim.interpolate(&(p->earthshatteranim), &(n->earthshatteranim), alpha);
    shieldrunanim.interpolate(&(p->shieldrunanim), &(n->shieldrunanim), alpha);
}

bool Reinhardt::cangetinput(Gamestate *state)
{
    return  not chargeanim.active() and not preparechargeanim.active() and not endchargeanim.active()
        and not earthshatteranim.active() and Character::cangetinput(state);
}

bool Reinhardt::weaponvisible(Gamestate *state)
{
    return  not stunanim.active() and not preparechargeanim.active() and not chargeanim.active()
        and not endchargeanim.active() and not earthshatteranim.active();
}

void Reinhardt::useability1(Gamestate *state)
{
    preparechargeanim.reset();
}

void Reinhardt::useability2(Gamestate *state)
{

}

void Reinhardt::useultimate(Gamestate *state)
{
    earthshatteranim.reset();
    Player *ownerplayer = state->get<Player>(owner);
    ownerplayer->ultcharge.reset();
}

void Reinhardt::interrupt(Gamestate *state)
{
    chargeanim.active(false);
    earthshatteranim.active(false);
}

Rect Reinhardt::getcollisionrect(Gamestate *state)
{
    if (crouchanim.active())
    {
        return state->engine->maskloader.get_rect_from_json(herofolder()+"crouch/").offset(x, y);
    }
    return getstandingcollisionrect(state);
}

Rect Reinhardt::getstandingcollisionrect(Gamestate *state)
{
    return state->engine->maskloader.get_rect_from_json(herofolder()).offset(x, y);
}

std::string Reinhardt::getsprite(Gamestate *state, bool mask)
{
    if (stunanim.active())
    {
        return stunanim.getframepath();
    }
    if (earthshatteranim.active())
    {
        return earthshatteranim.getframepath();
    }
    if (preparechargeanim.active())
    {
        return preparechargeanim.getframepath();
    }
    if (chargeanim.active())
    {
        return chargeanim.getframepath();
    }
    if (endchargeanim.active())
    {
        return endchargeanim.getframepath();
    }
    if (crouchanim.active())
    {
        return crouchanim.getframepath();
    }
    /*if (not ongroundsmooth.active)
    {
        if (vspeed > 100)
        {
            return herofolder()+"falling/1";
        }
        else
        {
            return herofolder()+"jump/1";
        }
    }*/
    if (std::fabs(hspeed) < 11.0 and not heldkeys.LEFT and not heldkeys.RIGHT)
    {
        return herofolder()+"idle/1";
    }
    Hammer *hammer = state->get<Hammer>(weapon);
    if (hammer->barrier.active)
    {
        return shieldrunanim.getframepath();
    }
    return runanim.getframepath();
}
<|endoftext|>


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

// Included first as it collides with the X11 headers.
#include "gtest/gtest.h"

#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"

// Checks sending window metrics events works.
TEST(FlEngineTest, WindowMetrics) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendWindowMetricsEvent = MOCK_ENGINE_PROC(
      SendWindowMetricsEvent,
      ([&called](auto engine, const FlutterWindowMetricsEvent* event) {
        called = true;
        EXPECT_EQ(event->width, static_cast<size_t>(3840));
        EXPECT_EQ(event->height, static_cast<size_t>(2160));
        EXPECT_EQ(event->pixel_ratio, 2.0);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  fl_engine_send_window_metrics_event(engine, 3840, 2160, 2.0);

  EXPECT_TRUE(called);
}

// Checks sending mouse pointer events works.
TEST(FlEngineTest, MousePointer) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPointerEvent = MOCK_ENGINE_PROC(
      SendPointerEvent,
      ([&called](auto engine, const FlutterPointerEvent* events,
                 size_t events_count) {
        called = true;
        EXPECT_EQ(events_count, static_cast<size_t>(1));
        EXPECT_EQ(events[0].phase, kDown);
        EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
        EXPECT_EQ(events[0].x, 800);
        EXPECT_EQ(events[0].y, 600);
        EXPECT_EQ(events[0].device, static_cast<int32_t>(0));
        EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
        EXPECT_EQ(events[0].scroll_delta_x, 1.2);
        EXPECT_EQ(events[0].scroll_delta_y, -3.4);
        EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
        EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  fl_engine_send_mouse_pointer_event(engine, kDown, 1234567890, 800, 600, 1.2,
                                     -3.4, kFlutterPointerButtonMouseSecondary);

  EXPECT_TRUE(called);
}

// Checks sending platform messages works.
TEST(FlEngineTest, PlatformMessage) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  FlutterEngineSendPlatformMessageFnPtr old_handler =
      embedder_api->SendPlatformMessage;
  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
      SendPlatformMessage,
      ([&called, old_handler](auto engine,
                              const FlutterPlatformMessage* message) {
        if (strcmp(message->channel, "test") != 0) {
          return old_handler(engine, message);
        }

        called = true;

        EXPECT_EQ(message->message_size, static_cast<size_t>(4));
        EXPECT_EQ(message->message[0], 't');
        EXPECT_EQ(message->message[1], 'e');
        EXPECT_EQ(message->message[2], 's');
        EXPECT_EQ(message->message[3], 't');

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  g_autoptr(GBytes) message = g_bytes_new_static("test", 4);
  fl_engine_send_platform_message(engine, "test", message, nullptr, nullptr,
                                  nullptr);

  EXPECT_TRUE(called);
}

// Checks sending platform message responses works.
TEST(FlEngineTest, PlatformMessageResponse) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPlatformMessageResponse = MOCK_ENGINE_PROC(
      SendPlatformMessageResponse,
      ([&called](auto engine,
                 const FlutterPlatformMessageResponseHandle* handle,
                 const uint8_t* data, size_t data_length) {
        called = true;

        EXPECT_EQ(
            handle,
            reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42));
        EXPECT_EQ(data_length, static_cast<size_t>(4));
        EXPECT_EQ(data[0], 't');
        EXPECT_EQ(data[1], 'e');
        EXPECT_EQ(data[2], 's');
        EXPECT_EQ(data[3], 't');

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  g_autoptr(GBytes) response = g_bytes_new_static("test", 4);
  EXPECT_TRUE(fl_engine_send_platform_message_response(
      engine, reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42),
      response, &error));
  EXPECT_EQ(error, nullptr);

  EXPECT_TRUE(called);
}

// Checks settings plugin sends settings on startup.
TEST(FlEngineTest, SettingsPlugin) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
      SendPlatformMessage,
      ([&called](auto engine, const FlutterPlatformMessage* message) {
        called = true;

        EXPECT_STREQ(message->channel, "flutter/settings");

        g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
        g_autoptr(GBytes) data =
            g_bytes_new(message->message, message->message_size);
        g_autoptr(GError) error = nullptr;
        g_autoptr(FlValue) settings = fl_message_codec_decode_message(
            FL_MESSAGE_CODEC(codec), data, &error);
        EXPECT_NE(settings, nullptr);
        EXPECT_EQ(error, nullptr);
        g_printerr("%s\n", fl_value_to_string(settings));

        g_autoptr(FlValue) text_scale_factor =
            fl_value_lookup_string(settings, "textScaleFactor");
        EXPECT_NE(text_scale_factor, nullptr);
        EXPECT_EQ(fl_value_get_type(text_scale_factor), FL_VALUE_TYPE_FLOAT);

        g_autoptr(FlValue) always_use_24hr_format =
            fl_value_lookup_string(settings, "alwaysUse24HourFormat");
        EXPECT_NE(always_use_24hr_format, nullptr);
        EXPECT_EQ(fl_value_get_type(always_use_24hr_format),
                  FL_VALUE_TYPE_BOOL);

        g_autoptr(FlValue) platform_brightness =
            fl_value_lookup_string(settings, "platformBrightness");
        EXPECT_NE(platform_brightness, nullptr);
        EXPECT_EQ(fl_value_get_type(platform_brightness), FL_VALUE_TYPE_STRING);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);

  EXPECT_TRUE(called);
}
<commit_msg>Skip the FlEngineTest.SettingsPlugin test (#23516)<commit_after>// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Included first as it collides with the X11 headers.
#include "gtest/gtest.h"

#include "flutter/shell/platform/embedder/test_utils/proc_table_replacement.h"
#include "flutter/shell/platform/linux/fl_engine_private.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_engine.h"
#include "flutter/shell/platform/linux/public/flutter_linux/fl_json_message_codec.h"
#include "flutter/shell/platform/linux/testing/fl_test.h"

// Checks sending window metrics events works.
TEST(FlEngineTest, WindowMetrics) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendWindowMetricsEvent = MOCK_ENGINE_PROC(
      SendWindowMetricsEvent,
      ([&called](auto engine, const FlutterWindowMetricsEvent* event) {
        called = true;
        EXPECT_EQ(event->width, static_cast<size_t>(3840));
        EXPECT_EQ(event->height, static_cast<size_t>(2160));
        EXPECT_EQ(event->pixel_ratio, 2.0);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  fl_engine_send_window_metrics_event(engine, 3840, 2160, 2.0);

  EXPECT_TRUE(called);
}

// Checks sending mouse pointer events works.
TEST(FlEngineTest, MousePointer) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPointerEvent = MOCK_ENGINE_PROC(
      SendPointerEvent,
      ([&called](auto engine, const FlutterPointerEvent* events,
                 size_t events_count) {
        called = true;
        EXPECT_EQ(events_count, static_cast<size_t>(1));
        EXPECT_EQ(events[0].phase, kDown);
        EXPECT_EQ(events[0].timestamp, static_cast<size_t>(1234567890));
        EXPECT_EQ(events[0].x, 800);
        EXPECT_EQ(events[0].y, 600);
        EXPECT_EQ(events[0].device, static_cast<int32_t>(0));
        EXPECT_EQ(events[0].signal_kind, kFlutterPointerSignalKindScroll);
        EXPECT_EQ(events[0].scroll_delta_x, 1.2);
        EXPECT_EQ(events[0].scroll_delta_y, -3.4);
        EXPECT_EQ(events[0].device_kind, kFlutterPointerDeviceKindMouse);
        EXPECT_EQ(events[0].buttons, kFlutterPointerButtonMouseSecondary);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  fl_engine_send_mouse_pointer_event(engine, kDown, 1234567890, 800, 600, 1.2,
                                     -3.4, kFlutterPointerButtonMouseSecondary);

  EXPECT_TRUE(called);
}

// Checks sending platform messages works.
TEST(FlEngineTest, PlatformMessage) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  FlutterEngineSendPlatformMessageFnPtr old_handler =
      embedder_api->SendPlatformMessage;
  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
      SendPlatformMessage,
      ([&called, old_handler](auto engine,
                              const FlutterPlatformMessage* message) {
        if (strcmp(message->channel, "test") != 0) {
          return old_handler(engine, message);
        }

        called = true;

        EXPECT_EQ(message->message_size, static_cast<size_t>(4));
        EXPECT_EQ(message->message[0], 't');
        EXPECT_EQ(message->message[1], 'e');
        EXPECT_EQ(message->message[2], 's');
        EXPECT_EQ(message->message[3], 't');

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  g_autoptr(GBytes) message = g_bytes_new_static("test", 4);
  fl_engine_send_platform_message(engine, "test", message, nullptr, nullptr,
                                  nullptr);

  EXPECT_TRUE(called);
}

// Checks sending platform message responses works.
TEST(FlEngineTest, PlatformMessageResponse) {
  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPlatformMessageResponse = MOCK_ENGINE_PROC(
      SendPlatformMessageResponse,
      ([&called](auto engine,
                 const FlutterPlatformMessageResponseHandle* handle,
                 const uint8_t* data, size_t data_length) {
        called = true;

        EXPECT_EQ(
            handle,
            reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42));
        EXPECT_EQ(data_length, static_cast<size_t>(4));
        EXPECT_EQ(data[0], 't');
        EXPECT_EQ(data[1], 'e');
        EXPECT_EQ(data[2], 's');
        EXPECT_EQ(data[3], 't');

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);
  g_autoptr(GBytes) response = g_bytes_new_static("test", 4);
  EXPECT_TRUE(fl_engine_send_platform_message_response(
      engine, reinterpret_cast<const FlutterPlatformMessageResponseHandle*>(42),
      response, &error));
  EXPECT_EQ(error, nullptr);

  EXPECT_TRUE(called);
}

// Checks settings plugin sends settings on startup.
TEST(FlEngineTest, SettingsPlugin) {
  GTEST_SKIP()
      << "disabled: see https://github.com/flutter/flutter/issues/73517";

  g_autoptr(FlEngine) engine = make_mock_engine();
  FlutterEngineProcTable* embedder_api = fl_engine_get_embedder_api(engine);

  bool called = false;
  embedder_api->SendPlatformMessage = MOCK_ENGINE_PROC(
      SendPlatformMessage,
      ([&called](auto engine, const FlutterPlatformMessage* message) {
        called = true;

        EXPECT_STREQ(message->channel, "flutter/settings");

        g_autoptr(FlJsonMessageCodec) codec = fl_json_message_codec_new();
        g_autoptr(GBytes) data =
            g_bytes_new(message->message, message->message_size);
        g_autoptr(GError) error = nullptr;
        g_autoptr(FlValue) settings = fl_message_codec_decode_message(
            FL_MESSAGE_CODEC(codec), data, &error);
        EXPECT_NE(settings, nullptr);
        EXPECT_EQ(error, nullptr);
        g_printerr("%s\n", fl_value_to_string(settings));

        g_autoptr(FlValue) text_scale_factor =
            fl_value_lookup_string(settings, "textScaleFactor");
        EXPECT_NE(text_scale_factor, nullptr);
        EXPECT_EQ(fl_value_get_type(text_scale_factor), FL_VALUE_TYPE_FLOAT);

        g_autoptr(FlValue) always_use_24hr_format =
            fl_value_lookup_string(settings, "alwaysUse24HourFormat");
        EXPECT_NE(always_use_24hr_format, nullptr);
        EXPECT_EQ(fl_value_get_type(always_use_24hr_format),
                  FL_VALUE_TYPE_BOOL);

        g_autoptr(FlValue) platform_brightness =
            fl_value_lookup_string(settings, "platformBrightness");
        EXPECT_NE(platform_brightness, nullptr);
        EXPECT_EQ(fl_value_get_type(platform_brightness), FL_VALUE_TYPE_STRING);

        return kSuccess;
      }));

  g_autoptr(GError) error = nullptr;
  EXPECT_TRUE(fl_engine_start(engine, &error));
  EXPECT_EQ(error, nullptr);

  EXPECT_TRUE(called);
}
<|endoftext|>


<commit_before>#include "manipulator/details/post_event_to_virtual_devices.hpp"
#include "thread_utility.hpp"
#include "time_utility.hpp"
#include "virtual_hid_device_client.hpp"

namespace {
class logger final {
public:
  static spdlog::logger& get_logger(void) {
    static std::shared_ptr<spdlog::logger> logger;
    if (!logger) {
      logger = spdlog::stdout_color_mt("virtual_device_client");
    }
    return *logger;
  }
};
} // namespace

int main(int argc, const char* argv[]) {
  krbn::thread_utility::register_main_thread();

  if (getuid() != 0) {
    logger::get_logger().error("virtual_device_client requires root privilege.");
  }

  auto virtual_hid_device_client_ptr = std::make_unique<krbn::virtual_hid_device_client>(logger::get_logger());
  krbn::manipulator::details::post_event_to_virtual_devices::queue queue;

  virtual_hid_device_client_ptr->client_connected.connect([&]() {
    std::cout << "connected" << std::endl;

    pqrs::karabiner_virtual_hid_device::properties::keyboard_initialization properties;
    virtual_hid_device_client_ptr->initialize_virtual_hid_keyboard(properties);
  });

  virtual_hid_device_client_ptr->virtual_hid_keyboard_ready.connect([&]() {
    std::cout << "virtual_hid_keyboard_ready" << std::endl;

    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardSpacebar);
      event.value = 1;
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardSpacebar);
      event.value = 0;
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }

    {
      auto time_stamp = mach_absolute_time();

      {
        pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
        event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardLeftShift);
        event.value = 1;
        queue.emplace_back_event(event, time_stamp);
        queue.post_events(*virtual_hid_device_client_ptr);
      }

      time_stamp += krbn::time_utility::nano_to_absolute(NSEC_PER_MSEC);

      {
        pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
        event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardB);
        event.value = 1;
        queue.emplace_back_event(event, time_stamp);
        queue.post_events(*virtual_hid_device_client_ptr);
      }
      {
        pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
        event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardB);
        event.value = 0;
        queue.emplace_back_event(event, time_stamp);
        queue.post_events(*virtual_hid_device_client_ptr);
      }
      {
        pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
        event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardLeftShift);
        event.value = 0;
        queue.emplace_back_event(event, time_stamp);
        queue.post_events(*virtual_hid_device_client_ptr);
      }
    }

    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardA);
      event.value = 1;
      auto time_stamp = mach_absolute_time() + krbn::time_utility::nano_to_absolute(NSEC_PER_SEC);
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardA);
      event.value = 0;
      auto time_stamp = mach_absolute_time() + krbn::time_utility::nano_to_absolute(3 * NSEC_PER_SEC);
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }

    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardB);
      event.value = 1;
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      pqrs::karabiner_virtual_hid_device::hid_event_service::keyboard_event event;
      event.usage = pqrs::karabiner_virtual_hid_device::usage(kHIDUsage_KeyboardB);
      event.value = 0;
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(event, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
  });

  virtual_hid_device_client_ptr->connect();

  CFRunLoopRun();
  return 0;
}
<commit_msg>update for post_event_to_virtual_devices updates<commit_after>#include "manipulator/details/post_event_to_virtual_devices.hpp"
#include "thread_utility.hpp"
#include "time_utility.hpp"
#include "virtual_hid_device_client.hpp"

namespace {
class logger final {
public:
  static spdlog::logger& get_logger(void) {
    static std::shared_ptr<spdlog::logger> logger;
    if (!logger) {
      logger = spdlog::stdout_color_mt("virtual_device_client");
    }
    return *logger;
  }
};
} // namespace

int main(int argc, const char* argv[]) {
  krbn::thread_utility::register_main_thread();

  if (getuid() != 0) {
    logger::get_logger().error("virtual_device_client requires root privilege.");
  }

  auto virtual_hid_device_client_ptr = std::make_unique<krbn::virtual_hid_device_client>(logger::get_logger());
  krbn::manipulator::details::post_event_to_virtual_devices::queue queue;

  virtual_hid_device_client_ptr->client_connected.connect([&]() {
    std::cout << "connected" << std::endl;

    pqrs::karabiner_virtual_hid_device::properties::keyboard_initialization properties;
    virtual_hid_device_client_ptr->initialize_virtual_hid_keyboard(properties);
  });

  virtual_hid_device_client_ptr->virtual_hid_keyboard_ready.connect([&]() {
    std::cout << "virtual_hid_keyboard_ready" << std::endl;

    {
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(krbn::key_code::spacebar, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(krbn::key_code::spacebar, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }

    {
      auto time_stamp = mach_absolute_time();

      // Put `Bc`.

      queue.emplace_back_event(krbn::key_code::left_shift, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::b, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::b, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::left_shift, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::c, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::left_shift, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::c, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);

      queue.emplace_back_event(krbn::key_code::left_shift, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }

    {
      auto time_stamp = mach_absolute_time() + krbn::time_utility::nano_to_absolute(NSEC_PER_SEC);
      queue.emplace_back_event(krbn::key_code::a, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      auto time_stamp = mach_absolute_time() + krbn::time_utility::nano_to_absolute(2 * NSEC_PER_SEC);
      queue.emplace_back_event(krbn::key_code::a, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }

    {
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(krbn::key_code::b, krbn::event_type::key_down, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
    {
      auto time_stamp = mach_absolute_time();
      queue.emplace_back_event(krbn::key_code::b, krbn::event_type::key_up, time_stamp);
      queue.post_events(*virtual_hid_device_client_ptr);
    }
  });

  virtual_hid_device_client_ptr->connect();

  CFRunLoopRun();
  return 0;
}
<|endoftext|>